;This code is written for the SX28 with a date code of AB9921AA (or later) ;and requires the SXKEY28L.exe software for assembly and programming. ; ; ; Step8 ; device SX28L,oscxt5,turbo,stackx_optionx id 'SX Demo' reset reset_entry freq 50_000_000 ; ; ; Equates ; rx_pin = ra.1 tx_pin = ra.2 dirup = rb.0 dirdn = rb.1 bitpinb = rb.2 bitpin = rb.3 red_pin = rb.5 grn_pin = rb.6 adc0_out_pin = rc.4 adc0_in_pin = rc.5 adc1_out_pin = rc.6 adc1_in_pin = rc.7 ; ; ; Variables ; org 8 temp ds 1 byte ds 1 cmd ds 1 number_low ds 1 number_high ds 1 hex ds 1 string ds 1 num ds 1 org 10h ;bank0 variables stats = $ tcountlo ds 1 ;timecounter tcounthi ds 1 tout ds 1 ;timeoutput toutacc ds 1 cn ds 1 ;current min cx ds 1 ;current max cv ds 1 ;current value cvo ds 1 ;current value old cvoo ds 1 ;current value old min ds 1 ;minumum max ds 1 ;maximum mid ds 1 ;midpoint ss ds 1 ;stepsize org 30h ;bank1 variables analog = $ port_buff ds 1 ;buffer - used by all adc0 ds 1 ;adc0 adc0_count ds 1 adc0_acc ds 1 adc1 ds 1 ;adc1 adc1_count ds 1 adc1_acc ds 1 org 50h ;bank2 variables serial = $ tx_high ds 1 ;tx tx_low ds 1 tx_count ds 1 tx_divide ds 1 rx_count ds 1 ;rx rx_divide ds 1 rx_byte ds 1 rx_flag ds 1 ; ; ; Interrupt routine ; interrupt org 0 bank analog ;1 clr port_buff ;1 mov w,>>rc ;1 ;adc0/adc1 not w ;1 ;complement inputs to outputs and w,#%01010000 ;1 or port_buff,w ;1 =4 mov rc,port_buff ;2 =2 ;update port pins sb port_buff.4 ;1 ;adc0 inc adc0_acc ;1 ;if was high, inc acc mov w,adc0_acc ;1 ;get acc into w inc adc0_count ;1 ;done? snz ;1 ;if so, update adc0 mov adc0,w ;1 snz ;1 ;if so, reset acc clr adc0_acc ;1 =8 sb port_buff.6 ;1 ;adc1 inc adc1_acc ;1 ;if was high, inc acc mov w,adc1_acc ;1 ;get acc into w inc adc1_count ;1 ;done? snz ;1 ;if so, update adc0 mov adc1,w ;1 snz ;1 ;if so, reset acc clr adc1_acc ;1 =8 ;------------------ bank stats clc ;1 ;do stuff every n x 256 x 3.26microsec add tcountlo,#1 ;2 addb tcounthi,c ;2 ; cjne tcounthi,#5,:cont0 ; mov cvoo,cv ; cjne tcounthi,#10,:cont0 ; mov cvo,cv :cont0 cjne tcounthi,#15,:cont7 ;n is the compare value mov cvoo,cvo mov cvo,cv mov tcounthi,#0 inc toutacc cjne toutacc,#$FF,:cont1 mov toutacc,#$FF :cont1 ;low pass filter adc inputs bank analog mov num,adc1 ;adc1 clc rr num movb bitpin,C bank stats ;2 clc rr cv movb bitpinb,C add cv, num ;2 jnb bitpin,:mmmr jnb bitpinb,:mmmr addb cv,bitpin ;mov cv,num :mmmr ;update max min and mid registers cjb cv,max,:mintst ;4,6 ;if cv>=max then max=cv mov max,cv ;2 :mintst cja cv,min,:cont ;4,6 ;if cv<=min then min=cv mov min,cv ;2 :cont mov mid,max ;2 add mid,min ;2 rr mid ;1 ;mid=(max+min)/2 cjae cv,cvo,:cont2 cjae cvo,cvoo,:cont2 ;goingdown setb red_pin clrb grn_pin setb dirdn jmp :cont4 :cont2 cjbe cv,cvo,:cont3 cjbe cvo,cvoo,:cont3 ;goingup clrb red_pin setb grn_pin setb dirup jmp :cont4 :cont3 ;within slop value clrb red_pin clrb grn_pin :cont4 ;inflection tests jnb dirdn,:cont7 jnb dirup,:cont7 jnb red_pin,:cont5 mov cx,cv mov tout,toutacc mov toutacc,#0 jmp :cont6 :cont5 jnb grn_pin,:cont7 mov tout,toutacc mov toutacc,#0 mov cn,cv :cont6 clrb dirdn clrb dirup :cont7 ;------------------ bank serial ;1 clrb tx_divide.4 ;1 ;serial transmit inc tx_divide ;1 ;only execute every 16th time mov w,tx_divide ;1 and w,#$10 ;1 sz ;1 test tx_count ;1 ;busy? clc ;1 ;ready stop bit sz ;1 ;if busy, shift bits rr tx_high ;1 sz ;1 rr tx_low ;1 sz ;1 ;if busy, dec counter dec tx_count ;1 movb tx_pin,/tx_low.6 ;4 =17 ;output next bit movb c,rx_pin ;4 ;serial receive test rx_count ;1 ;waiting for stop bit? jnz :rxbit ;3,2 ;if not, :bit mov w,#9 ;1 ;in case start, ready 9 bits sc ;1 ;if start, set rx_count mov rx_count,w ;1 mov rx_divide,#16+8+1 ;2 ;ready 1.5 bit periods :rxbit djnz rx_divide,:rxdone ;3,2 ;8th time through? setb rx_divide.4 ;1 ;yes, ready 1 bit period dec rx_count ;1 ;last bit? sz ;1 ;if not, save bit rr rx_byte ;1 snz ;1 ;if so, set flag setb rx_flag ;1 =20 :rxdone mov w,#-163 ;1 ;interrupt every 163 clocks retiw ;3 ; ; ; Reset entry ; reset_entry mov ra,#%11111111 ;init ra mov !ra,#%11111011 mov rb,#%11100000 ;init rb mov !rb,#%10000000 mov rc,#%00000000 ;init rc mov !rc,#%10101111 clr rc ;init rc mov !rc,#%10101010 mov m,#$D ;set cmos input levels mov !rc,#0 mov m,#$F clr fsr ;reset all ram banks :loop setb fsr.4 clr ind ijnz fsr,:loop mov !option,#%10011111 ;enable rtcc interrupt jmp @terminal ; ; ; Data ; _hello dw 13,10,13,10,'Stepr',13,10,0 _prompt dw 13,10,'>',0 _error dw 'Error!',13,10,0 _hex dw '0123456789ABCDEF' ; ; ;*************** ;* Subroutines * ;*************** ; org $200 ; ; Get byte via serial port ; get_byte jnb rx_flag,$ clrb rx_flag mov byte,rx_byte ;followed by send_byte ; ; ; Send byte via serial port ; send_byte bank serial :wait test tx_count ;wait for not busy jnz :wait not w ;ready bits mov tx_high,w setb tx_low.7 mov tx_count,#10 ;1 start + 8 data + 1 stop bit ret ; ; ; Get hex number ; get_hex clr number_low ;reset number clr number_high :loop call get_byte ;get digit cje byte,#' ',:loop ;ignore spaces mov w,<>byte ;get <>byte into hex mov hex,w cjb byte,#'0',:done ;if below '0', done cjbe byte,#'9',:got ;if '0'-'9', got hex digit call uppercase ;make byte uppercase cjb byte,#'A',:done ;if below 'A', done cja byte,#'F',:done ;if above 'F', done add hex,#$90 ;'A'-'F', adjust hex digit :got mov temp,#4 ;shift digit into number :shift rl hex rl number_low rl number_high djnz temp,:shift jmp :loop ;next digit :cr call get_byte ;wait for cr :done cjne byte,#13,:cr ret ; ; ; Send hex byte (2 digits) ; send_hex mov w,#13 ;send cr lf call send_byte mov w,#10 call send_byte mov w,<>number_low ;send first digit call :digit mov w,number_low ;send second digit :digit and w,#$F ;read hex chr mov temp,w mov w,#_hex clc add w,temp mov m,#0 iread mov m,#$F jmp send_byte ;send hex chr ; ; ; Send string at w ; send_string mov string,w ;send string at w :loop mov w,string ;read chr at w mov m,#0 iread mov m,#$F test w ;if 0, exit snz ret call send_byte ;not 0, send chr inc string ;next chr jmp :loop ; ; ; Make byte uppercase ; uppercase csae byte,#'a' ret sub byte,#'a'-'A' ret ; ; send bank stats mov ss,cx ;send stepsize=cx-cn sub ss,cn mov number_low,ss call send_hex clc bank stats mov ss,cx ;(cx+cn)/2 add ss,cn rr ss mov number_low,mid sub number_low,ss ;skew = mid-(cx+cn)/2 call send_hex bank stats mov number_low,tout ;send timer call send_hex bank analog mov number_low,adc0 ;send back call send_hex bank stats mov tout,#0 ;clear timer output reg ret ; ;******** ;* Main * ;******** ; ; ; Terminal - main loop ; terminal mov w,#_hello ;send hello string call send_string jmp :rstb ;reset stats :loop mov w,#_prompt ;send prompt string call send_string call get_byte ;get command call uppercase mov cmd,byte cje cmd,#'?',:howdy ;send hello cje cmd,#'B',:b ;send backposition value cje cmd,#'F',:f ;send foot position value cje cmd,#'R',:rst ;reset registers cje cmd,#'M',:mmm ;view min mid max registers cje cmd,#'D',:dirtr ;view direction & timer registers cje cmd,#'C',:cxvo ;view cn cx cv registers call send ;default is stepsize timer skew backpos jmp :loop ;try again :b bank analog ;adc0 read mov number_low,adc0 call send_hex jmp :loop :f bank stats ;adc1 read mov number_low,cv call send_hex jmp :loop :mmm bank stats ;min mid max regs mov number_low,min call send_hex bank stats mov number_low,mid call send_hex bank stats mov number_low,max call send_hex jmp :loop :dirtr bank stats ;direction & timer regs mov number_low,#00 movb number_low.0,dirup call send_hex bank stats mov number_low,#00 movb number_low.0,dirdn call send_hex bank stats mov number_low,tout call send_hex bank stats mov tout,#0 ;clear timer output reg jmp :loop :cxvo bank stats ;cn cx cv regs mov number_low,cn call send_hex bank stats mov number_low,cx call send_hex bank stats mov number_low,cv call send_hex bank stats mov number_low,tout ;send timer call send_hex ;bank stats ;mov tout,#0 ;clear timer output reg jmp :loop :howdy mov w,#_hello call send_string jmp :loop :rst setb red_pin setb grn_pin :rstb bank stats clrb dirup ;direction registers clrb dirdn mov tout,#$00 ;timer mov toutacc,#$00 mov tcountlo,#$00 mov tcounthi,#$00 mov cn,#$ff ;current min mov cx,#$00 ;current max mov cv,#$94 ;current value mov cvo,#$7f ;current value old mov cvoo,#$7f ;current value old mov min,#$ff ;minumum mov max,#$00 ;maximum mov mid,#$7f ;midpoint jmp :loop