📄 drivera.asm
字号:
movlw 8 ; First state = t1accel
lgoto raslewall ;
;
; dslowslew starts a slow slew on dec drive
; speedh, speedl, stepcmd, inccmd all set up previously
;
dslowslew
bsf dstatus, ST_STOP ; Signal that we need to stop
dslowslew2
btfss dstatus, ST_STOPPED ; Check for stopped
goto dslowslew2 ; Wait for a stop
dslowslew1
movfw speedh ; Set up compare regs for int level
movwf dspdhigh ;
movfw speedl ;
movwf dspdlow ;
movlw 0 ; Start in state 0
dslewall ; start up the engine... Enter here with initial state in w
movwf t2state ;
clrf dstatus ;
movfw inccmd ; Set up interrupt level vbls
movwf dinc ;
movfw stepcmd ;
movwf t2stepcmd ;
splh ; Disable ints while we get timer 1
movfw TMR1H ; Mark1 - Pick up high
addwf dspdhigh, w ; calc capture reg
movwf CCPR2H ;
movlw 5 ; Mark2-Mark1+1 timing
subwf TMR1L, w ; Mark2 - Pick up low
spl0 ; Reenable
addwf dspdlow, w ; Calc other reg
movwf CCPR2L ;
skpnc ;
incf CCPR2H, f ;
movlw B'00001010' ; CCP1X:CCP1Y=0 CCP1M3:CCP1M0=1010
movwf CCP2CON ; Set up for compare mode, int on match
bcf PIR2, 0 ; Be sure CCP2IF is clear
banksel PIE2 ;
bsf PIE2, 0 ; Enable the capture interrupt
banksel 0 ;
; dstep expanded here by hand to allow the lcall of gettraj
movfw t2stepcmd ; Step 1 of 8
addwf dtrajp, f ; see where to go next
movlw 0x1f ; Wrap pointer
andwf dtrajp, w ; w gets ptr for gettraj
movwf dtrajp ; Save new ptr
lcall gettraj ; Get the table value
dec_out ; Send to motor
mlretlw 0 ; Successful completion
;
; dfastslew starts a fast slew
; speedh, speedl, stepcmd, inccmd all set up previously
;
dfastslew
bsf dstatus, ST_STOP ; Signal that we need to stop
dfastslew2
btfss dstatus, ST_STOPPED ; Check for stopped
goto dfastslew ; Wait for a stop
dfastslew1
movlw 0 ; Start at 0
movwf dcuridx ; Set starting point
lcall dgetaccel ; Set up rac_cnt, rspdhigh, rspdlow
movfw speedh ; Pick up high index
movwf dhiacidx ; Set stopping point
movlw 8 ; First state = t2accel
lgoto dslewall ;
;
; Full step command
;
dofstep
mreturn
;
; Micro step command
;
domicrostep
mreturn
;
; Quit commands
; w = 0 means just quit, leave motors running
; w = 1 means quit, shut motors off (idle)
;
doquit
movwf temp ; Save parameter
incf FSR, f ; Advance to next in cmd
movfw INDF ; Get the cmd
sublw 0x0D ; CR?
skpz ;
goto doquit1 ;
; No parameter means both
movfw temp ;
mcall stopboth ;
goto doquitok ;
doquit1
movfw INDF ; Maybe it's an R?
sublw 'R' ;
skpz ;
goto doquit3 ;
bsf rstatus, ST_STOP ; Signal RA to stop
doquit2 btfss rstatus, ST_STOPPED ; Wait for RA to stop
goto doquit2 ;
movfw temp ; Idle too?
skpnz ;
goto doquitok ; Done, RA stopped
movlw 0 ;
ra_out ; Kill power to the motor
goto doquitok ;
doquit3
movfw INDF ; OK, got to be a D...
sublw 'D' ;
skpnz ; Return if not
goto doquit5 ;
mretlw 1 ; Error return
doquit5 bsf dstatus, ST_STOP ; Signal DEC to stop
doquit4 btfss dstatus, ST_STOPPED ;
goto doquit4 ;
movfw temp ; Idle too?
skpnz ;
goto doquitok ; Done, DEC stopped
movlw 0 ;
dec_out ; Kill power to the motor
doquitok mretlw 0 ;
;
; Subroutine used to stop both motors.
; w = 1 means kill the power too
;
stopboth
movwf temp
bsf rstatus, ST_STOP ; Stop RA motion
bsf dstatus, ST_STOP ; Stop Dec motion
stopboth1 btfss rstatus, ST_STOPPED ; Wait for both axes to stop
goto stopboth1 ;
btfss dstatus, ST_STOPPED ;
goto stopboth1 ;
movfw temp ; Idle?
skpnz ;
goto stopbothok ; Done - both are stopped
movlw 0 ;
ra_out ; Turn off both motors
movlw 0 ;
dec_out ;
stopbothok mreturn ;
;
; Get commands
;
doget
incf FSR, f ; Advance to C, hopefully
movfw INDF ;
sublw 'C' ; Get count?
skpz ;
goto doget1 ; Jump if not a C
mcall dogetsub ;
splh
movd rapos, d0 ; Convert rapos first
spl0
mcall dtoa ;
movlw ' ' ;
movwf INDF ; Put in a space
incf FSR, f ;
splh
movd dpos, d0 ; Now convert dec pos
spl0
mcall dtoa ;
mcall dogetwrap ; Wrap it up
mretlw 0 ; Successful completion
doget1
movfw INDF ;
sublw 'B' ; Get battery value?
skpnz ;
goto doget2 ;
mretlw 1 ; Error return if not "C" or "B"
doget2
mcall dogetsub ; Set up for return
mcall getbatt ; Get the battery voltage
movpwd d0 ; Put in d0
mcall dtoa ; Convert to ascii
movlw ' ' ;
movwf INDF ;
incf FSR, f ;
movfw avgbatt ; Get the average too
movpwd d0 ;
mcall dtoa ;
mcall dogetwrap ;
mretlw 0 ; And done
;
; Helper subroutine for doget - sets up cmdbuff for a return value
;
dogetsub
movlw cmdbuff ; Point to start of buffer
movwf FSR ;
movlw 0x0D ; CR
movwf INDF ;
incf FSR, f ;
movlw 0x0A ; LF
movwf INDF ;
incf FSR, f ;
mreturn
;
; Wrapup doget routines
;
dogetwrap
movlw 0x0D ; CR; LF supplied by docmd()
movwf INDF ;
incf FSR, F ;
movlw 0 ; Mark the end with a null
movwf INDF ;
movlw cmdbuff ; Set up to send buff
movwf FSR ;
mcall buffout ; Send the buffer
mreturn
;
; Set commands
; Call with FSR pointing into the buffer at the "S"
; Returns 0 for success, 1 for error
; SS<speed> Sets speed for next Slew command (both axes)
; SC<m> <count> Sets the saved count for an axis
; <speed> is "T" for Tracking speed
; "G" for Guide
; "L" for Lunar
; "S" for Solar
; "M" for Medium
; "F" for Fast
;
doset
incf FSR, f ; Advance to "S" or "C"
movfw INDF ;
sublw 'S' ; Speed?
skpz ;
goto doset1 ; Skip if not
; Set speed
incf FSR, f ; Advance to speed parameter
clrf temp ; Index starts at 0
dosetlp
call getspeed ; Get the speed name (F, M, etc)
andlw 0xff ; Is it zero?
skpnz ;
goto dosetbad ; Error return if end of speedtbl
subwf INDF, w ; Same as table entry?
skpnz ;
goto doset2 ;
movlw 4 ; Advance index
addwf temp, f ;
goto dosetlp ; Check next
doset2
incf temp, f ; Advance index
call getspeed ; Get flag
movwf slew ; Set slew
incf temp, f ;
call getspeed ;
movwf speedh ; set speedh
incf temp, f
call getspeed ;
movfw speedl ;
goto dosetok ; Successful return
doset1
movfw INDF ;
sublw 'C' ; Count?
skpz ;
goto dosetbad ; Nothing else to set
; Set Count
incf FSR, f ; Point to R/D
movfw INDF ;
sublw 'R' ; RA?
skpz ;
goto dosetc1 ;
incf FSR, f ; Advance past R
mcall atod ; Convert RA count to binary
splh ;
movd d0, rapos ; Set count
spl0 ;
goto dosetok ;
dosetc1 movfw INDF ;
sublw 'D' ; Dec?
skpz ;
goto dosetbad ; Error if neither R nor D
incf FSR, f ; Advance past D
mcall atod ; Convert DEC count to binary
splh ;
movd d0, dpos ; fall through to dosetok
spl0
dosetok mretlw 0 ; Good return
dosetbad mretlw 1 ; Bad return
;
;
; Check the limit switches
; No parameters passed
; Nothing returned
; Side effects are somewhat dramatic..
;
chklim
mreturn
;
; Check the battery voltage
; No parameters passed
; Nothing returned
; Implments a length 16 rolling average. Anything below 10V
; shuts things down.
;
chkbatt
movfw t0ticks ; Find out if we need to check
subwf timbatt, w ;
skpnz ;
goto chkbattdone ; Done if the same
incf timbatt, f ; Follow the timer
movfw avgbatt ; Pick up rolling average
movpwd d0 ; Save in d0
movlw 15 ; Multiply by 15
mulpwd d0, d1, temp, temp1, temp2
mcall getbatt ; Pick up the current battery value
addpwd d0 ; Add to it
clrf temp ; Assume no rounding
movfw d0+b3 ; Check for rounding error
andlw 0x0f ;
sublw 7 ;
andlw 0x80 ;
skpnz ;
goto chkbatt1 ;
movlw 1 ; add in 1 to rount it up
movwf temp ;
chkbatt1 rrd d0 ; Divide by 16
rrd d0 ;
rrd d0 ;
rrd d0 ;
movfw temp ;
addpwd d0 ; Round if needed
movfw d0+b3 ; Pick up the new average
movwf avgbatt ; And save
sublw MINBATT ; Is it still OK?
andlw 0x80 ;
ifndef SIM
skpz ;
endif
goto chkbattdone ;
; Shut it down...
movlw 1 ; Want to kill the power
mcall stopboth ;
; xxx need to do LED signals...
chkbattdone mreturn
;
; getbatt gets the value from the battery a-to-d converter
;
getbatt
movlw B'11000001' ; FRC, Channel 0, ADON (Turn on converter)
movwf ADCON0 ;
movlw 5 ; 16 clocks coming up
movwf temp ;
getbatt1 decfsz temp, f ; Spin it down
goto getbatt1 ;
bsf ADCON0, 2 ; Set GO/DONE
nop ; May not need this..
getbatt2 btfsc ADCON0, 2 ; Spin until conversion is done
goto getbatt2 ;
movfw ADRES ; Pick up result
bcf ADCON0, 0 ; Shut off unit
mreturn
;
; atod converts ascii to 32bit
; Call with fsr pointing at the number
; returns the result in d0
;
atod
movfw INDF ; Skip past zeros
sublw ' ' ;
skpz ;
goto atod1 ;
incf FSR, f ;
goto atod ;
atod1 clrf temp ; temp = 0 means the number is positive
movfw INDF ;
sublw '-' ; Is it negative?
skpz ;
goto atod2 ;
incf temp, f ; temp = 1 means the result is negative
incf FSR, f ;
atod2 ; Pointing at the the number, should be all digits from here on
clrd d0 ; start with zeros
atod3 movlw '0' ;
subwf INDF, f ; Pick up the number and convert to binary
movfw INDF ; Check for less than '0'
andlw 0x80 ;
skpz ;
goto atodend ; Negative means was less than ascii 0
movfw INDF ;
sublw 9 ; w = 9 - w
andlw 0x80 ;
skpz ;
goto atodend ; Must have been greater than ascii 9
movlw 10 ; Multiply previous results by 10
mulpwd d0, d1, temp1, temp2, temp3
movfw INDF ; Pick up the new digit
addwd d0 ; Add it in
incf FSR, f ; Advance to next char
goto atod3 ; Check next char
atodend
movf temp, f ; Pos?
skpnz ;
goto atodend1 ;
negd d0, d1, temp1 ; Negate if temp is set
atodend1
mreturn ; Done
;
; dtoa converts 32 bit binary numbers to ascii
; Pass start of buffer in FSR.
; Returns with FSR pointing at the next space past the number
; The number should be in d0
; uses pottbl to decompose the number
;
dtoa
movfw d0+b0 ; Is it negative?
andlw 0x80 ;
skpnz ;
goto dtoa1 ;
movlw '-' ; Put in a minus sign
movwf INDF ;
incf FSR, f ;
negd d0, d1, temp1 ; Negate d0
dtoa1
clrf temp ; Used as an argument to getpot
movlw '0' ;
movwf INDF ; Start with a zero
dtoa2 ; This loop looks for the first non-zero digit
; Surpresses leading zeros
mcall nxtpot ;
subd d0, d1, temp1 ; d0 = d0 - d1
movfw d0+b0 ;
andlw 0x80 ; Negative?
skpnz ;
goto dtoa3 ;
addd d0, d1, temp1 ; Put it back
movlw 40 ; At the end of pottbl?
subwf temp, w ;
skpz ;
goto dtoa2 ; Loop to next try
incf FSR, f ; Point to next digit
goto dtoadone ; It's zero if whole table finished
dtoa3 ; Got a positive result
movlw '1' ;
movwf INDF ;
dtoa4 ; Main conversion loop
subd d0, d1, temp1 ;
movfw d0+b0 ;
andlw 0x80 ;
skpz ; Continue if still pos
goto dtoa5 ;
incf INDF, f ; Increment the digit
goto dtoa4 ;
dtoa5 ; d0 went from d0 >= 0 to d0 < 0
incf FSR, f ; Advance to next output digit
movlw 40 ; End of table?
subwf temp, w ;
skpnz ;
goto dtoadone ; Done if end of table
movlw '9' ;
movwf INDF ; Start next digit
mcall nxtpot ; Get next power of 10
dtoa6 ; on negative side waiting to go positive
addd d0, d1, temp1 ; Add in power of 10
movfw d0+b0 ;
andlw 0x80 ;
skpnz ;
goto dtoa7 ;
decf INDF, f ;
goto dtoa6 ;
dtoa7 ; d0 went from d0 < 0 to d0 >= 0
incf FSR, f ;
movlw 40 ; Are we done yet?
subwf temp, w ;
skpnz ;
goto dtoadone ;
movlw '0' ;
movwf INDF ;
mcall nxtpot ;
goto dtoa4 ;
dtoadone mreturn ;
;
; nxtpot calls getpot repeatedly and stuffs the 32 bit number
; in d1. Increments temp (in getpot) as a side effect
nxtpot
call getpot ; Pick up current power of 10
movwf d1+b0 ;
call getpot ;
movwf d1+b1 ;
call getpot ;
movwf d1+b2 ;
call getpot ;
movwf d1+b3 ;
mreturn ;
END ; directive 'end of program'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -