; blink5.src ; ; Device ; device SX28L device turbo,stackx_optionx,oscxtmax id 'Blink5' reset reset_entry freq 50_000_000 ; ; ; Equates ; rx_pin = ra.2 tx_pin = ra.3 led_pin = rb.6 led2_pin = rb.5 in_pin = rb.4 ; ; ; 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 org 10h ;bank0 variables bankone = $ mscount_low ds 1 ;millisecond counter mscount_high ds 1 dur_low ds 1 ;accumulator window duration dur_high ds 1 durcount_low ds 1 ;accumulator window counter durcount_high ds 1 tx_high ds 1 ;tx serial tx_low ds 1 tx_count ds 1 tx_divide ds 1 rx_count ds 1 ;rx serial rx_divide ds 1 rx_byte ds 1 rx_flag ds 1 org 0 ; ; ; Interrupt routine - virtual peripherals ; interrupt bank bankone ;1 add mscount_low,#1 ;2 ;inc ms counter addb mscount_high,c ;2 cjne mscount_high,#$01,:sericont ;4,6 ;skip if ms <> 500 cjne mscount_low,#$f4,:sericont ;4,6 add durcount_low,#1 ;2 ;inc duration counter addb durcount_high,c ;2 clr mscount_low ;1 ;reset mscounter clr mscount_high ;1 :sericont inc tx_divide ;1 ;serial transmit cje tx_divide,#13,:is13 ;4,6 stz ;1 jmp :not13 ;3 :is13 clr tx_divide ;1 ;13 clear tx_divide test tx_count ;1 ;busy? :not13 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 ;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,#13+6+1 ;2 ;ready 1.5 bit periods (approx) :rxbit djnz rx_divide,:rxdone ;3,2 ;8th time through? mov rx_divide,#13 ;2 ;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 :rxdone ; 79cyc worst case + 6 isr in&out = 85 min rtcc adj value, so 100 ok mov w,#-100 ;1 ;interrupt every 100 clocks retiw ;3 ;leaves 15 cyc per 2microsec ; ; ; Data ; _hello dw 13,10,'Blink',13,10,0 _prompt dw 13,10,'>',0 _error dw 'Error!',13,10,0 _hex dw '0123456789ABCDEF' ; ; ;*************** ;* Subroutines * ;*************** ; ; ; 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 :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 cjne byte,#'?',:num ;if ? send hello setb led_pin ;wink awake mov w,#_hello ;send hello string call send_string clrb led_pin ;end wink ret ;exit after hello :num 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 hex word (4 digits) ; send_word mov w,#13 ;send cr lf call send_byte mov w,#10 call send_byte mov w,<>number_high ;send first (MSD) digit call :digi mov w,number_high ;send second digit call :digi mov w,<>number_low ;send third digit call :digi mov w,number_low ;send fourth (LSD) digit :digi and w,#$F ;read hex chr mov temp,w mov w,#_hex clc add w,temp mov m,#0 iread mov m,#$F call send_byte ;send hex chr ret ; ; ; 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 ; ; ;******** ;* Main * ;******** ; ; ; Reset entry ; reset_entry bank bankone mov m,#$0f ;data direction reg mode mov ra,#%1000 ;init ra mov !ra,#%0111 mov rb,#%00001111 ;init rb mov !rb,#%10010000 mode $0b ;wakeup mode=0 regular=1 mov !rb,#%11111111 ;dont want to generate interrupts mode $0a ;edge rising=0 falling=1 mov !rb,#%11111111 mode $09 ;clear latches mov !rb,#%00000000 mov m,#$D ;set ttl input levels mov !rb,#%11111111 mov m,#$0C ;set schmitt trigger input 4 mov !rb,#%11101111 mov m,#$0f clr fsr ;clear all ram banks :loop setb fsr.4 clr ind ijnz fsr,:loop ;set defaults mov dur_low,#$e8 ;accumulator window duration 1000 mov dur_high,#$03 mov !option,#%10011111 ;enable rtcc interrupt ; ; ; Terminal - main loop ; terminal bank bankone setb led_pin ;wink awake mov w,#_hello ;send hello string call send_string clrb led_pin ;end wink :loop mov w,#_prompt ;send prompt string call send_string clrb led2_pin ;be sure mirroring led is off call get_hex ;get hex number mov dur_low,number_low ;load accumulation duration mov dur_high,number_high mov mscount_low,#0 ;millisecond counter mov mscount_high,#0 mov durcount_low,#0 ;accumulator window counter mov durcount_high,#0 mode $09 mov !rb,#%00000000 ;move status to w and clear latches and w,#%00010000 setb led_pin ;accumulator window open indicator :edgetest movb led2_pin,in_pin ;mirror input on led2 ; detect edge on in_pin b4 clc mode $09 mov !rb,#%00000000 ;move status to w and clear latches and w,#%00010000 jz :durtest ;skip if no edge clrb led_pin ;accumulator window closed indicator mov number_low,durcount_low ;send duration counter value mov number_high,durcount_high call send_word jmp :loop :durtest cjne durcount_high,dur_high,:edgetest cjb durcount_low,dur_low,:edgetest clrb led_pin ;accumulator window closed indicator mov number_low,#$00 ;send null value mov number_high,#$00 call send_word jmp :loop