.include "tn28def.inc"
.DEF inport_save =R3;
.DEF loop1_store =R4;
.DEF loop2_store =R5;
.DEF loop3_store =R6;
.DEF clk_delay =R16; specifies the delay of each duty cycle
.DEF rat =R17; register active time
.DEF rit =R18; register inactive time.
.DEF rgen1 =R19; general register 1
.DEF rgen2 =R20; general register 2
.DEF loop1 =r21; loop delay counters
.DEF loop2 =r22
.DEF loop3 =r23
.DEF width =R24; width is the five bit input from motor controller
.DEF active_time =R26;
.DEF inact_time =R28;
;
; Constants
;
.EQU ActivePin =DDA0; Desired output pin
.EQU LoopLen =4; Magic num for the length loops are multiplied
;
; Code segment start
;
.CSEG
rjmp Start;
;
; Subroutines
;
; Get cycle
;
; Read the input and use first three bits to set the delay length. Use the
; last five bits to calculate the width of active and inactive times
; of the pulse. Calculate counter value for active time
; It may be wise to do some error checking, and maybe even create minimun
; and maximum limits to the lengths of times.
getcycle:
in inport_save, PIND
mov width, inport_save
; push the last five bits over three
lsr width
lsr width
lsr width ; the max that width can be is 32
lsl width ; I'm told this doubles the value, and the laser's max is 65
brne wasnt_zero
ldi width, 1; It was zero, and width has >= 1
wasnt_zero:
mov rat,width; rat will contain the active time
; rit will contain inactive time. which is almost there after its subtracted from 100
mov rit,width
ldi rgen1,100
sub rgen1,rit
mov rit,rgen1
ret
set_delays:
; this is going to be the multiplier that sets the length of the duty cycle
ldi rgen1,1
mov loop1_store,rgen1
mov loop2_store,rgen1
mov loop3_store,rgen1
mov clk_delay, inport_save
cbr clk_delay,0b11111000
ldi rgen1,LoopLen
bst clk_delay,2 ; load third bit into t-register
brtc j3 ; do some tests to see what will be stored in the loop registers...
mov loop3_store,rgen1
j3: bst clk_delay,1
brtc j2
mov loop2_store,rgen1
j2: bst clk_delay,0
brtc j1
mov loop1_store,rgen1
j1:
ret
;
; Delay
;
; A triple nested loop that chows cycles depending on what
; is loaded into the loop registers. This is set based on
; what came in from the first three bits of InPort
delay:
mov loop3,loop3_store
loop3: mov loop2,loop2_store
loop2: mov loop1,loop1_store
loop1: dec loop1
brne loop1
dec loop2
brne loop2
dec loop3
brne loop3
ret
;
; Start of program
;
Start:
;
; Initiate Ports
;
sbi PACR,ActivePin ; set portA to output signal
ldi rgen1,0b00000000 ; set portd as input
out DDRD,rgen1
out PORTD,rgen1
;
; Init cycle times
;
rcall getcycle; get new cycle time
mov active_time,rat; active_time, gets the active time
mov inact_time,rit; and inact_time gets the inactive time.
rcall set_delays
;
; Loop starts, continues indefinitely.
;
ctloop:
sbi PORTA,ActivePin
ActLoop:
rcall delay
subi active_time,1; 0.5 µs
brne ActLoop; 0.5 µs
cbi PORTA,ActivePin
InactLoop:
rcall delay
subi inact_time,1; 0.5 µs
brne InactLoop; 0.5 µs
; there is a value at PIND, go get it.
in rgen1, PIND
; how does it compare to what was saved earlier?
cpse rgen1,inport_save; if rgen1 and input_save are different...
rcall getcycle; get new cycle time
mov active_time,rat; get the active time
mov inact_time,rit; get the inactive time.
rjmp ctloop; start a new cycle