;************************************************************************ ; TaPRK IR-LINK-RECEIVER ;************************************************************************ LIST P = 16F84A, R = HEX ;Prosessortype, radix INCLUDE "p16f84A.inc" ;w,f,porta,portb etc. ERRORLEVEL -224, -302 ;prevents error from ;"tris"-command __CONFIG _PWRTE_ON & _HS_OSC & _WDT_OFF ;************************************************************************ ; SCHEMATIC DIAGRAM ;************************************************************************ ; +---+_+---+ ; N/C PORTA.2 ->|1 18|<- PORTA.1 N/C ; N/C PORTA.3 ->|2 17|<- PORTA.0 TSOP1738 act.lo ; PORTA.4 ->|3 16|-- XTAL ; Vdd --|4 15|-- XTAL ; Vss(GND)--|5 14|-- Vdd (+5V) ; Strobe_MUX PORTB.0 <-|6 13|-> PORTB.7 LED1 ; Strobe_Disp PORTB.1 <-|7 12|-> PORTB.6 N/C ; Comm.Ser.data PORTB.2 <-|8 11|-> PORTB.5 N/C ; Comm.Ser.clock PORTB.3 <-|9 10|-> PORTB.4 N/C ; +---------+ ;************************************************************************ ; MAIN IDEA ;************************************************************************ ; ; This is based on Holger Klabunde's design, but is completely ; rewritten in assembler. ; ; Timing ; ====== ; 26us cycle of IR-LED on/off gives 38,5kHz ; 16 cycles for 1/2 bit -> 16 x 26us= 416 us ; Prescaler of 1:8 makes TMR0 advance every 8us (@4MHz crystal) ; 1/2 bit needs 416/8 = 52 ticks of TMR0 ; 1/4 bit needs 52/2 = 26 ticks of TMR0 ; ; This is loosely following Philips RC5, exept: ; ; -- Bit length 2 X 416us! ; -- Only one start bit, and it is "0" ; -- Only 8 data bits ; -- Added parity bit ; -- Total of 10 bits ; ; This is presumably the same as Lorell Joiner's ; setup, done with hardwired UART some 10 years ago, but instead ; of using 250 kHz carrier and on/off bits, I use the ; Bit formation same as RC5 at 36...38 kHz carrier: ; ; +---+ +---+ ; | | =0 | | =1 ; + +---+ +---+ + ; ; TSOP1738 receiver module inverts the above ; ; Serial output to 7-segment display and C-MOS switches ; 4094 serial-in-parallel-out will be used. Two branches, one ; for controllers (PC-Joystick through C-MOS switches) and the ; other for speed step (hex-) display. Both branches may use ; common data and clock, strobe sent only to correct branch. ; ; I'll use 4066 to connect a set of trimmers to replace ; joystick pot. ; ; Functions (F0 and F1) will be added later! ; ; ============================================================== ; 5-PIN STEREO DIN DISP. UNIT ; -------------------------------------------------------------- ; 1 CK Orange [Biltema ; 4 GND Green keyboard ; 2 DATA Blue extension ; 5 +5V White cord ; 3 STROBE Black colours] ; ============================================================== ; 3.5mm STEREO IR-MODULE CONNECTOR ; -------------------------------------------------------------- ; Tip Data ; Ring + ; Sleeve GND ; ============================================================== ; RESISTOR NETWORK VALUES (eq.47K pot) ; -------------------------------------------------------------- ; 1 2K9 ; 2 6K ; 4 11K9 ; 8 23K5 ; -------------------------------------------------------------- ; 4094 switch on-resistance 250R/switch, so all cable throttles ; will be equipped with a 1K resistor in addition to pot to ; compensate as this will not go to 0 ohms. Will also change ; cable throttles to have max. speed at min resistance in case ; of power failure in this setup! [NB: resistance values above ; are thoise we used, our 47K pots were in fact approx 43K5 ; potentiometers, therefore the odd figures!] ; ; Throttle number 0 now has working functions! Single press ; of F0 or F1 will produce correct pattern and keeping the ; button down will keep the functions last dir-button press ; down. ; ; If speed is zero then speed will be advanced to step one ; and it will return to last used speed after function procedure ; (zero if speed was zero before pressing of F-button) ; This is still quick and dirty. We'll polish the code and ; make it operate other controllers as well ; ;************************************************************************ ; VARIABLES ;************************************************************************ CBLOCK H'0C' Data1 ;Data from IR-receiver Data2 ;waiting for conversion to 7-seg... Parity ;Parity Err ;error flag from ReadBit bitcount ;bit counter count_gp ;freewheeling counter blink ;blink on/off f_served ;number of cab whose f's are to be served last_0 ;cab 0 last received command speed_0 ;cab 0 speed (4 bits) func_0 ;cab 0 functions chann_0 ;cab 0 channel (msb hi: unfinished) last_1 ;cab 0 last received command speed_1 ;cab 0 speed (4 bits) func_1 ;cab 0 functions chann_1 ;cab 0 channel (msb hi: unfinished) last_2 ;cab 0 last received command speed_2 ;cab 0 speed (4 bits) func_2 ;cab 0 functions chann_2 ;cab 0 channel (msb hi: unfinished) last_3 ;cab 0 last received command speed_3 ;cab 0 speed (4 bits) func_3 ;cab 0 functions chann_3 ;cab 0 channel (msb hi: unfinished) ENDC ;************************************************************************ ; STATICS ;************************************************************************ #DEFINE TSOP PORTA, 0 ;IR receiver #DEFINE M_STROBE PORTB, 1 ;MUX Strobe #DEFINE S_STROBE PORTB, 0 ;7-SEG Strobe #DEFINE S_DATA PORTB, 2 ;7-SEG Data #DEFINE S_CLOCK PORTB, 3 ;7-SEG Clock #DEFINE LED1 PORTB, 7 ;Pilot light #DEFINE HALFBIT .203 ;= 255-52 #DEFINE QUADBIT .229 ;= 255-26 ;************************************************************************ ;RESTART/INT-START ;************************************************************************ ORG 0 ; Restart vector goto main ORG 4 ; INT vector retfie ;------------------------------------------------------------------------ ; Initialize I/O ports, Interrupts, Timers etc ;------------------------------------------------------------------------ init movlw b'00000000' ;RB0..7=out tris portb ; movlw b'00011111' ;RA0..4=in tris porta ; ;easy to recall: ;Input -> I -> 1 ;Output-> O -> 0 clrf porta ;clear Port A (Shift reg output) clrf portb ;Port B on (LED test) CLRWDT ; bsf STATUS, RP0 ; movlw b'00000010' ;Pullup=on, Prescaler= 1:8 movwf OPTION_REG ; bcf STATUS, RP0 ; ramc movlw 0x0c ; start of 16F84 ram movwf fsr ramc1 clrf indf ; clear indirect location incf fsr, f ; next location btfss fsr, 7 ; cleans up to 0x7f goto ramc1 ; [From J.Niinikoski] ramdone movfw DATA1 ;clear w call disp_speed ;Show speed w. 7-seg display call mux_speed ;Drive mux to operate speed network return ;------------------------------------------------------------------------ ; Increment cab's typematic counters ;------------------------------------------------------------------------ IncCounters tstf count_gp ;set zero flag from counter skpz ;skip if zero goto gpnz ;non-zero goto gpz ;zero gpnz bsf LED1 ;pilot off incf count_gp, f ;not yet -> increment return ;[21/4-2002] gpz bcf LED1 ;pilot on incf blink, f ;change blink (choose bit to follow ;for different rates!) call func ; return ; ;------------------------------------------------------------------------ ; Read whole bit, set/clear error reset TMR0, count parity ;------------------------------------------------------------------------ ReadBit movlw 0xFF ;Set error state, movwf ERR ;will be cleared if bit correctly read rb1 btfss INTCON, T0IF ;wait for timer to overflow goto rb1 ;not yet movlw HALFBIT ;new timer base addwf TMR0, f ;add to just overflowed timer bcf INTCON, T0IF ;clear overflow flag call IncCounters ;increment countgp at each INTCON T0IF btfsc TSOP ;test 1st halfbit state goto read1 ;was high -> beginning of "1" read0 btfss INTCON, T0IF ;wait for timer to overflow goto read0 ;not yet movlw HALFBIT ;new timer base addwf TMR0, f ;add to just overflowed timer bcf INTCON, T0IF ;clear overflow flag call IncCounters ;increment countgp at each INTCON T0IF btfss TSOP ;test 2nd halfbit, must be high (set) return ;was not, error, return bcf STATUS, C ;have read a "0" rlf DATA1, f ;move it into DATA1 clrf ERR ;clear error state return read1 btfss INTCON, T0IF ;wait for timer to overflow goto read1 ;not yet movlw HALFBIT ;new timer base addwf TMR0, f ;add to just overflowed timer bcf INTCON, T0IF ;clear overflow flag call IncCounters ;increment countgp at each INTCON T0IF btfsc TSOP ;test 2nd halfbit, must be low (clear) return ;was not, error, return bsf STATUS, C ;have read a "1" rlf DATA1, f ;move it into DATA1 incf Parity, f ;add 1 to parity clrf ERR ;clear error state return ;--------------------------------------------------------------- ;Lookup-table for 7-seg display, uses 4094 shift registers ;--------------------------------------------------------------- Lookup andlw 0x0F ;clear top to prevent going past addwf pcl,f ; retlw b'00011000' ; 0 retlw b'01111011' ; 1 retlw b'00101100' ; 2 retlw b'00101001' ; 3 77777 retlw b'01001011' ; 4 6 8 retlw b'10001001' ; 5 6 8 retlw b'10001000' ; 6 6 8 retlw b'00111011' ; 7 55555 retlw b'00001000' ; 8 1 3 retlw b'00001001' ; 9 1 3 retlw b'00001010' ; A 1 3 44 retlw b'11001000' ; b 22222 44 retlw b'10011100' ; C retlw b'01101000' ; d retlw b'10001100' ; E retlw b'10001110' ; F retlw b'11101111' ; - ;--------------------------------------------------------------- ;Lookup-table for cab to be served for functions ;--------------------------------------------------------------- lookup_last addwf pcl,f ; retlw last_0 ; point to cab 0's last cmd retlw last_1 ; point to cab 1's last cmd retlw last_2 ; point to cab 2's last cmd retlw last_3 ; point to cab 3's last cmd ;------------------------------------------------------------ ; MUX out SPEED ;------------------------------------------------------------ mux_speed movf speed_1, w ;speed_x to w btfsc chann_1, 7 ;Check for unfinished ch selection movlw .0 ;under construction: no output call so_byte ;and shift out byte movf speed_0, w ;speed_x to w btfsc chann_0, 7 ;Check for unfinished ch selection movlw .0 ;under construction: no output call so_byte ;and shift out byte bsf M_STROBE ;strobe out nop ;wait for slow C-MOS bcf M_STROBE ; return ;------------------------------------------------------------------------- ; DISPALY SPEED ;------------------------------------------------------------------------- ; New development at cab 0: ; if chann_0 = 0 then only dash is displayed as cab is ; effectively disconnected! ; While choosing a channel, the dp will be lit if the candidate ; channel equals the presently active one ; ; cab 1 has old ch routine, ; cabs 2 and 3 have yet nothing (well -- they have the 'dash')! ; ; Must make this also "modular" (through FSR, like functions) ;------------------------------------------------------------------------- Disp_speed d3 movlw b'11101111' ;light (clear) 'dash' only! call so_byte ;and shift out byte d2 movlw b'11101111' ;light (clear) 'dash' only! call so_byte ;and shift out byte d1 btfsc chann_1, 7 ;test if unfinished channel sel? goto d_ch1 ;yes, what's the score? movf speed_1, w ;no, speed_x to w andlw 0xF ;clear top nibble call lookup ;convert to 7-segment btfsc speed_1, 4 ;Check for direction button andlw b'11110111' ;light (clear) 'dp' if set! call so_byte ;and shift out byte goto d0 ;next d_ch1 movf chann_1, w ;channel: chann_x to w andlw 0xF ;clear top nibble btfss last_1, 5 ;ordinary speed packet received? movlw b'11101111' ;yes, dash out! btfsc blink, 2 ;Check for blink phase movlw 0xFF ;turn off in case call so_byte ;and shift out byte d0 btfsc chann_0, 7 ;test if unfinished channel sel? goto d_ch0 ;yes, what's the score? tstf chann_0 ;test channel skpnz ;is there a channel goto d0_null ;no, the throttle is disconnected! movf speed_0, w ;yes, speed_x to w andlw 0xF ;clear top nibble call lookup ;convert to 7-segment btfsc speed_0, 4 ;Check for direction button andlw b'11110111' ;light (clear) 'dp' if set! call so_byte ;and shift out byte goto ds ;strobe out d0_null movlw b'11101111' ;light (clear) 'dash'only! call so_byte ;and shift out byte goto ds ;strobe out d_ch0 movfw chann_0 ;load current channel to accumulator, andlw 0x0F ;clear the flag bit and xorwf last_0, w ;subtract last_0 to test equality skpnz ;well, was it equal? goto d_ch0_eq ;yes, show the dp movfw last_0 ;no, lets get the candidate call lookup ;convert to 7-segment btfsc blink, 2 ;Check for blink phase movlw 0xFF ;turn off in case call so_byte ;and shift out byte goto ds ;strobe out d_ch0_eq movfw last_0 ;equal, lets get the candidate call lookup ;convert to 7-segment andlw b'11110111' ;light (clear) 'dp'! btfsc blink, 2 ;Check for blink phase movlw 0xFF ;turn off in case call so_byte ;and shift out byte goto ds ;strobe out ds bsf S_STROBE ;strobe out nop ;wait for slow C-MOS bcf S_STROBE ; return ;----------------------------------------------------------------------- ;shift out one byte from w (uses DATA1 and BITCOUNT) ;----------------------------------------------------------------------- so_byte movwf DATA1 ;and put out for shifting movlw .8 ;all 8 bits movwf BITCOUNT ; sob1 rlf DATA1, F ;rotate through carry (MSB first) and btfsc STATUS, C ;in case of carry shift out 1 goto so1 ;carry=1 so0 ;carry=0 bcf S_DATA ;data lo bsf S_CLOCK ;clock hi nop ;wait for slow C-MOS bcf S_CLOCK ;clock lo goto sob2 so1 bsf S_DATA ;data hi bsf S_CLOCK ;clock hi nop ;wait for slow C-MOS bcf S_CLOCK ;clock lo sob2 decfsz BITCOUNT, F ;all bits sent? goto sob1 ;not yet, shift out more return ;yes, this byte shifted out ;----------------------------------------------------------------------- ;Function action (now works with all cabs!) ; ; This is rather complicated, but the idea is that ; FSR contains the address of last_x of the cab in question. ; To manipulate and test also speed_x and func_x FSR ; needs to be incremented and decremented. ; When jump to another spot is made the comment ; at label row will tell what register the FSR is pointing ; at the moment of entry ;----------------------------------------------------------------------- func incf count_gp, f ;count_gp to non-zero! ;--------------------------------------------------------------- ; Move the FSR to point next cabs particulars ;--------------------------------------------------------------- incf f_served, w ;point to next cabs particulars movwf f_served ;return updated valued btfsc f_served, 2 ;gone past 4? goto fdisp ;yes, display what we got call lookup_last ;no, get address of last_x of this cab movwf FSR ;and set this to indirect pointer f0 ;--- FSR: last_x ------------------- incf FSR, f ;FSR: last_x -> speed_x incf FSR, f ;FSR: speed_x-> func_x tstf INDF ;let's see cab x's func_x status? skpz ;Do we have fun? goto f0yes ;Yes, let's process the fun! ;no, let's sync last speed w. last cmd decf FSR, f ;FSR: func_x ->speed_x decf FSR, f ;FSR: speed_x->last_x movfw INDF ;move last command (non func!) to w andlw 0x1f ;clear 3 top bits incf FSR, f ;FSR: last_x -> speed_x movwf INDF ;move to speed_0 return ;and finish for now f0yes ;--- FSR: func_x ------------------- ;so, func_x was non zero! decf FSR, f ;FSR: func_x -> speed_x tstf INDF ;Let's see cab has speed? skpz ;Do we have speed? goto f0act ;yes, let's have some more activity incf INDF, f ;no, lets add some speed return ;and finish for now f0act ;--- FSR: speed_x ----------------- ;Now we have speed and fun is non-zero btfss INDF, 4 ;Is dir on? goto f0setdir ;no, go and put it on ;yes [speed<>0; func<>0; dir=1] incf FSR, f ;FSR: speed_x-> func_x decfsz INDF, w ;Test if func_x is one [1->0?] goto f0diroff ;No, proceed to put dir off etc.... ;yes [speed<>0; func=1; dir=1] decf FSR, f ;FSR: func_x ->speed_x decf FSR, f ;FSR: speed_x->last_x btfsc INDF, 5 ;Test if last_x has a F-command B5=1 return ;yes, lets keep the dir as "1" ;no, lets clear dir and dec. func incf FSR, f ;FSR: last_x -> speed_x incf FSR, f ;FSR: speed_x-> func_x f0diroff ;--- FSR: func_x ------------------- decf FSR, f ;FSR: func_x ->speed_x bcf INDF, 4 ;yes, put it off incf FSR, f ;FSR: speed_x-> func_x decf INDF, f ;and decrement fun contents return ;and go to to see if next has fun f0setdir ;--- FSR: speed_x ------------------ bsf INDF, 4 ;set the dir of this cab return ;and finnish for now fdisp ;--- FSR: whatever ;) -------------- call disp_speed ;Show speed w. 7-seg display call mux_speed ;Drive mux to operate speed network movlw 0xff ;lets make sure next entry to f gets zero movwf f_served ;as f_served goes over top return ;------------------------------------------------------------------------ ; MAIN PROGRAMME ;------------------------------------------------------------------------ main call init ;intialize ports m1 btfss TSOP ;wait for beginning of the broadcast goto m2 ;found, start interpreting btfss INTCON, T0IF ;has timer overflowed goto m1 ;not yet movlw HALFBIT ;new timer base addwf TMR0, f ;add to just overflowed timer bcf INTCON, T0IF ;clear overflow flag call IncCounters ;increment countgp at each INTCON T0IF ; tstf count_gp ;set zero flag from counter ; skpz ;skip if zero ; goto m1 ;wait for broadcast m2 movlw QUADBIT ;advance 1/4 bit to hit middle of movwf TMR0 ;1st half-bit of start-bit ("0") bcf INTCON, T0IF ;just in case: clear Timer overflow flag call ReadBit ;read whole start-bit btfsc ERR, 0 ;if error, return to square one goto m1 ; btfsc DATA1, 0 ;last read bit (LSB of DATA1) must goto m1 ;be "0" as it was the start bit movlw 8 ;read 8 bits movwf BITCOUNT clrf DATA1 ;clear read DATA1 clrf Parity ;clear parity m3 call ReadBit ;read whole DATA1 bit btfsc ERR, 0 ;if error, return to square one goto m1 ; decfsz BITCOUNT, f ;All DATA1 bits read? goto m3 ;not yet, read more movfw DATA1 ;all DATA1 read movwf DATA2 ;move to safety call ReadBit ;read parity bit btfsc ERR, 0 ;if error, return to square one goto m1 ; btfsc Parity, 0 ;Parity must now be clear goto m1 ;if not return to square one bcf PORTA, 2 ad ;----------------------------------------------------------------------- ;ADDRESS TESTING btfss DATA2, 7 ;test for address MSB goto adlo ;address=0/1 goto adhi ;address=2/3 adlo btfss DATA2, 6 ;test for address LSB goto ad0 ;address=0 goto ad1 ;address=1 adhi btfss DATA2, 6 ;test for address LSB goto ad2 ;address=2 goto ad3 ;address=3 ;---------------------------------------------------------------- ; Handling of incoming data packets ; --------------------------------- ; [not yet reality, but soon...] ; The handling of incoming data depends on present status ; of the receiver: ; ; - pending Functions handling and ; - pending Channel selection handling ; ; In case there are pending Functions handling (func_x <> 0) ; all incoming packets are just copied to last_x ; so that the speed of the loco after dir-flashing sequence ; may be received during flashing (does not adjust speed during ; flashing yet). The functions handler is called by the ; count_gp updating routine (flashes the dir button and ; decrements func_x. ; ; In case the channel selection is still pending (MSB of ; chann_x is high, no ordinary speed packets are taken in at all! ; The exception is if incoming speed packet has speed=0. That ; will cause copying of last channel commands channel from ; last_x to chann_x and terminates channel selection (MSB low). ; ; in case the received packet is a functions packet, the ; function number is extracted (lower nibble) and placed in ; func_x and the received byte as is goes to last_x ; (further speed packets will also go to last_x so that ; when the functions handilng nears completion the last_x ; is tested in case the transmitter still has the funtion button ; pressed, thus resulting contunued dir-button down. This ; is carried in "count_gp" triggered routine! ; ; In case the packet is a channel selection packet, the MSB ; of chann_x is taken high (as a flag) and packet copied to last_x. ; The channel of chann_x is kept as is, so that the display routine ; can display dp in case the previuous setting is selected ; (in case one got "accidentally" into channel selection this ; provides a way to undo -- yet one must find the channel that ; lights the dp first!). The speed_x will be kept cleared while ; MSB of chann_x is high! ; ; When the transmitter ceases sending channel packets, it will ; send speed packets, but the chann_x MSB will remain high! ; Incoming speed packets will be discarded as mentioned above ; (last_x contains the next channel number!) until a speed=0 packet ; is received, and then last_x info will be used to fill func_x. ; ; Presently it seems that starting a channel selection during ; pending functions will just extend the last dir-button. ; ; I'm wish, that in case a used channel is displayed while ; browsing the new candidate, the display should show "r" like ; reserved! ; ; So: only in case chann_x MSB is high and non-zero speed packet is ; received, it will be discarded, else it is copied to last_x ; ; ATTENTION: DEVELOPMENT ONLY AT cab 0! ; Cab 1 has previous version! ; Cabs 2 and 3 don't work at all! ; Must make this also "modular" (through FSR, like functions) ;-------------------------------------------------------------------------- ad0 tstf func_0 ;Test Functions: skpz ;Any functions pending? goto fun_on ;yes, go for it fun_off ;no, so fun is off btfsc chann_0, 7 ;Any channel selection pending? goto ch_on ;yes, go for it! all_off ;no, all are off! btfss data2, 5 ;Test if speed packet coming? goto all_off_sp_in ;yes, go for it! btfss data2, 4 ;no, lets see if func packet coming? goto all_off_fun_in ;yes, go for it! all_off_ch_in ;no, so this must be channel-stuff bsf chann_0, 7 ;set pending ch flag hi! movfw data2 ;Load incoming into accumulator, andlw 0x0F ;clear top nibble, movwf last_0 ;and move as next ch candidate goto m4 ;and quit! fun_on movfw DATA2 ;copy new packet to accumulator movwf last_0 ;and on to last command goto m4 ;and quit! ch_on btfss data2, 5 ;received a speed packet? goto ch_on_sp_in ;yes, go for it btfss data2, 4 ;no, is it a function packet? goto m4 ;yes, not interested due to pending... ch_on_ch_in ;Channel pending, got a new ch packet movfw data2 ;As it's another channel candidate, we'll andlw 0x0F ;clear top to expose proposed ch number movwf last_0 ;and make it available at last_0 goto m4 ;and quit! ch_on_sp_in ;Channel pending, received a speed packet movfw data2 ;no, lets see, if it's speed=0 packet andlw 0x0F ;by clearing top and skpz ;so, is it zero? goto m4 ;no, waste it! movfw last_0 ;yes, so channel candidate at last_0 movwf chann_0 ;is new channel (and ch-flag becomes cleared too!) goto m4 ;and quit! all_off_sp_in ;no pending stuff, got a speed packet movfw DATA2 ;Move DATA to w movwf last_0 ;new last command andlw 0x1f ;clear only 3 top bits movwf speed_0 ;move to speed_0 goto m4 ;and quit! all_off_fun_in ;no pending stuff, got a function packet movfw DATA2 ;Let's see which F-button pressed andlw b'00001111' ;by masking out top nibble movwf func_0 ;and make it to cab's next function, goto m4 ;and quit! ;----------------------------------------------------------------------; ; OLD ad0 ; movfw last_0 ;load last command to accumulator subwf DATA2, w ;subtract DATA2 from last command skpnz ;skip if non-zero goto m4 ;nothing new, goto m4 movfw DATA2 ;DATA2 to accumulator movwf last_0 ;accumulator to last command tstf func_0 ;Test if F-stuff pending, skpz ;and forget this packet goto m4 ;and pass btfsc DATA2, 5 ;test for Speed/Function bit goto ad0f ;set (1): cab1 F-stuff movfw DATA2 ;clear: move DATA to w andlw 0x1f ;clear 3 top bits movwf speed_0 ;move to speed_0 tstf speed_0 ;is speed 0 skpnz bcf chann_0, 7 ;yes no pending channel! goto m4 ad0f btfsc DATA2, 4 ;test if it's a channel select packet? goto ad0ch ;yes, let's save it movfw DATA2 ;no,let's see which F-button pressed andlw b'00001111' ;by masking out top nibble movwf func_0 ;and make it to cab x's function, goto m4 ;and so done here ad0ch movfw DATA2 ;no,let's see which channel proposed andlw b'00001111' ;by masking out top nibble iorlw b'10000000' ;this is pending stuff (msb=1) movwf chann_0 ;and make it to cab x's function, goto m4 ;and so done here ; ; ;---------------------------------------------------------------------; ad1 btfsc DATA2, 5 ;test for Speed/Function bit goto m4 ;set (1) no F-stuff handler yet, skip movfw DATA2 ;move DATA to w andlw 0x1f ;clear 3 top bits movwf speed_1 ;move to speed_1 goto m4 ;------------------------------------------------------------------- ad2 ;------------------------------------------------------------------- ad3 goto m4 m4 call disp_speed ;Show speed w. 7-seg display call mux_speed ;Drive mux to operate speed network goto m1 end