;************************************************************************ ; TaPRK IR-LINK-RECEIVER ;************************************************************************ LIST P = 16F84A, R = HEX ;Prosessortype, radix INCLUDE "p16f84A.inc" ;w,f,porta,portb etc. ERRORLEVEL -224 ;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! ; ;************************************************************************ ; 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 speed_0 ;cab 0 speed (4 bits) speed_1 ;cab 1 speed (4 bits) speed_2 ;cab 2 speed (4 bits) speed_3 ;cab 3 speed (4 bits) 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] ; clrf speed_0 ;set speed_x to zero ; clrf speed_1 ;set speed_x to zero ; clrf speed_2 ;set speed_x to zero ; clrf speed_3 ;set speed_x to zero ; clrf DATA1 ;set speed_x to zero ; clrf DATA2 ;set speed_x to zero 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 incf count_gp, f ;not yet -> increment return ;[21/4-2002] ;------------------------------------------------------------------------ ; 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 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 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 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 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 ;------------------------------------------------------------ ; MUX out SPEED ;------------------------------------------------------------ mux_speed movf speed_1, w ;speed_x to w btfsc speed_1, 4 ;Check for direction button iorlw b'00010000' ;operate c-mos switch if set! call so_byte ;and shift out byte movf speed_0, w ;speed_x to w btfsc speed_0, 4 ;Check for direction button iorlw b'00010000' ;operate c-mos switch if set! call so_byte ;and shift out byte bsf M_STROBE ;strobe out nop ;wait for slow C-MOS bcf M_STROBE ; return ;------------------------------------------------------------ ; DISPALY SPEED ;------------------------------------------------------------ Disp_speed movf speed_1, w ;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 movf speed_0, w ;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 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 ;------------------------------------------------------------------------ ; MAIN PROGRAMME ;------------------------------------------------------------------------ main call init ;intialize ports m1 bsf LED1 ;pilot off btfss TSOP ;wait for beginning of the broadcast ## goto m2 ;found, start interpreting incfsz count_gp, f ;set zero flag from counter_gp goto m1 ;not yet, wait for broadcast nop ;HERE F-section -> increment cab counters goto m1 ;wait for broadcast m2 bcf LED1 ;pilot on 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 ;---------------------------------------------------------------- ad0 ; btfss DATA2, 5 ;test for Speed/Function bit ; goto m4 ;set (1) no F-stuff yet, skip to m4 movfw DATA2 ;move DATA to w andlw 0x1f ;clear 3 top bits movwf speed_0 ;move to speed_0 goto m4 ;---------------------------------------------------------------- ad1 ; btfss DATA2, 5 ;test for Speed/Function bit ; goto m4 ;set (1) no F-stuff yet, skip to m4 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 ; ;----------------------------------------------------; ; ; LED DISPALY AT PORT B ; ; ; [This gets messed up if direction button pressed] ; ; ;----------------------------------------------------; ; swapf speed_1, w ;speed of cab1 to high nibble ; iorwf speed_0, w ;set cab 0 bits hi also ; movwf DATA2 ;move to ex. safety ; comf DATA2, w ;invert bits for output ; movwf PORTB ;move to display m5 call disp_speed ;Show speed w. 7-seg display call mux_speed ;Drive mux to operate speed network goto m1 end