LIST p=16F628a include "P16F628a.inc" __CONFIG _CP_OFF & _BODEN_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF & _MCLRE_OFF & _HS_OSC ; The defines #DEFINE SCL PORTA, 0 ;output #DEFINE SDA PORTA, 1 ;bi-directional #DEFINE ir_out PORTA, 2 ;output #DEFINE row5 PORTA, 3 ;input #DEFINE row4 PORTA, 4 ;input ;#DEFINE mclr PORTA, 5 ; #DEFINE col2 PORTB, 7 ;output #DEFINE col1 PORTB, 6 ;output #DEFINE col0 PORTB, 5 ;output ;#DEFINE OPEN PORTB, 4 ;input #DEFINE row0 PORTB, 3 ;input #DEFINE row1 PORTB, 2 ;input #DEFINE row2 PORTB, 1 ;input #DEFINE row3 PORTB, 0 ;input CONSTANT I2C_C=0 CONSTANT I2C_D=1 #define TV_PHILLIPS 0x00 ;36kHz #define DVD_RCA 0x05 ;56kHz #define CMPT_RCA 0x03 ;56kHz #define ADDRESS_PCF8574 0x40 cblock 0x20 t0 ;Temps for delay routines t1 t2 t3 temp ;Holds value to be put on the SPI and 1-wire bytes flags ;flags to control control counter temp_ir temp_hi temp_lo remote_mode ;0=TV(Phillips), 1=Computer(RC5), 2=DVD(RCA) found ;Place value of pressed key here last_found ;Save off the last key that was pressed ir_address ir_command toggle ;This stores the value for the toggle bit in the Phillips RC-5 ;I2C variables loop IOBYTE endc ;Commands for the RCA DVD player Address = 5 ; Power 42 ; Eject 64 ; Skip-F 32 ; Skip-B 34 ; Play 21 ; Stop 31 ; Pause 25 ; Enter 244 ; Arrow-Up 89 ; Arrow-Dn 88 ; Arrow-L 86 ; Arrow-R 87 ; Mute 63 ;Define ram locations org 0x00 goto init RCA_command: addwf PCL,F retlw .255 ; 0 retlw .64 ; 1 retlw .87 ; 2 retlw .255 ; 3 retlw .32 ; 4 retlw .31 ; 5 retlw .255 ; 6 retlw .89 ; 7 retlw .244 ; 8 retlw .88 ; 9 retlw .8 ; 10 retlw .21 ; 11 retlw .42 ; 12 retlw .255 ; 13 retlw .86 ; 14 retlw .39 ; 15 retlw .34 ; 16 retlw .25 ; 17 Phillips_command_1: addwf PCL,F retlw .63 ; 0 retlw .3 ; 1 retlw .6 ; 2 retlw .9 ; 3 retlw .63 ; 4 retlw .63 ; 5 retlw .63 ; 6 retlw .2 ; 7 retlw .5 ; 8 retlw .8 ; 9 retlw .0 ; 10 retlw .63 ; 11 retlw .12 ; 12 retlw .1 ; 13 retlw .4 ; 14 retlw .7 ; 15 retlw .34 ; 16 retlw .63 ; 17 Phillips_command_2: addwf PCL,F retlw .63 ; 0 retlw .63 ; 1 retlw .16 ; 2 retlw .13 ; 3 retlw .63 ; 4 retlw .63 ; 5 retlw .63 ; 6 retlw .32 ; 7 retlw .15 ; 8 retlw .33 ; 9 retlw .63 ; 10 retlw .63 ; 11 retlw .12 ; 12 retlw .63 ; 13 retlw .17 ; 14 retlw .46 ; 15 retlw .34 ; 16 retlw .63 ; 17 CMPT_command: addwf PCL,F retlw .1 ; 0 retlw .2 ; 1 retlw .3 ; 2 retlw .4 ; 3 retlw .5 ; 4 retlw .6 ; 5 retlw .7 ; 6 retlw .8 ; 7 retlw .9 ; 8 retlw .10 ; 9 retlw .11 ; 10 retlw .12 ; 11 retlw .13 ; 12 retlw .14 ; 13 retlw .15 ; 14 retlw .16 ; 15 retlw .17 ; 16 retlw .18 ; 17 ;******************************************************************** ;*** I2C Communcation Subroutines ;******************************************************************** ;*** OUTPUT 1 ON I2C BUS (PIN = INPUT) I2C1: bsf STATUS, RP0 ;switch to page 1 bsf PORTA, I2C_D ;set data pin to input (high impedence 1) bcf STATUS, RP0 ;switch to page 0 return ;*** OUTPUT 0 ON I2CBUS I2C0: bcf PORTA, I2C_D ;set the data output to zero bsf STATUS, RP0 ;switch to page 1 bcf PORTA, I2C_D ;set data pin to output (low impedence 0) bcf STATUS, RP0 ;switch to page 0 bcf PORTA, I2C_D ;pull data line low again return ;*** SEND I2C START CONDITION I2CSTA: call I2C1 ;output a 1 on the bus call D60us ;wait 60us bsf PORTA,I2C_C ;set the clock high call D500us ;wait 500us call I2C0 ;output a 0 on the bus call D60us ;wait 60us bcf PORTA,I2C_C ;set the clock low return ;*** SEND I2C STOP CONDITION I2CSTO: call I2C0 ;output a 0 on the bus call D60us ;wait 60us bsf PORTA,I2C_C ;set the clock high call D60us ;wait 60us call I2C1 ;output a 1 on the bus return ;*** WRITE BYTE TO I2C BUS I2CWB: movwf IOBYTE movlw .8 movwf loop I2CWB1: rlf IOBYTE, F btfss STATUS, C goto I2CWB3 goto I2CWB4 I2CWB2: decfsz loop, F goto I2CWB1 call I2C1 ; read ACK bit... call D60us bsf PORTA,I2C_C call D60us bcf PORTA,I2C_C call D60us return I2CWB3: call I2C0 ; bring DATA_PIN low call D60us bsf PORTA,I2C_C call D60us bcf PORTA,I2C_C goto I2CWB2 I2CWB4: call I2C1 call D60us bsf PORTA,I2C_C call D60us bcf PORTA,I2C_C goto I2CWB2 ;*** READ BYTE FROM I2C BUS I2CRB: call I2C1 movlw .8 movwf loop clrf IOBYTE I2CRB1: bsf PORTA,I2C_C call D60us bsf STATUS,C btfss PORTA,I2C_D bcf STATUS,C RLF IOBYTE,F bcf PORTA,I2C_C call D60us decfsz loop, F goto I2CRB1 call I2C0 call D60us bsf PORTA,I2C_C ; ACK-bit call D60us bcf PORTA,I2C_C call D60us call I2C1 call D60us movfw IOBYTE ; return the result in W return ;*** READ LAST BYTE FROM I2C BUS (NO ACK) I2CRL: call I2C1 movlw .8 movwf loop clrf IOBYTE I2CRL1: bsf PORTA,I2C_C call D60us bsf STATUS,C btfss PORTA,I2C_D bcf STATUS,C RLF IOBYTE,F bcf PORTA,I2C_C call D60us decfsz loop, F goto I2CRL1 call I2C0 call D60us bsf PORTA,I2C_C ; ACK-bit call D60us call I2C1 movfw IOBYTE ; return the result in W return ;************************* end i2c routines ************************* ;*************************** Set Leds ******************************* set_leds: movwf temp bcf temp, 7 call I2CSTA movlw ADDRESS_PCF8574 ;Load/send device address call I2CWB movf temp, w ;Send Led data call I2CWB call I2CSTO ; stop address send return ;*************************** END Set Leds ******* ******************** ;-------------------------- Send TV Phillips RC5 for now (36kHz)-----------; Send_TV: ;Goods are stored in address and command ;First send first one call Send_TV_1 call Send_TV_1 toggle_bit: btfsc toggle, 0 call Send_TV_1 btfss toggle, 0 call Send_TV_0 TV_Address: btfsc ir_address, 4 call Send_TV_1 btfss ir_address, 4 call Send_TV_0 btfsc ir_address, 3 call Send_TV_1 btfss ir_address, 3 call Send_TV_0 btfsc ir_address, 2 call Send_TV_1 btfss ir_address, 2 call Send_TV_0 btfsc ir_address, 1 call Send_TV_1 btfss ir_address, 1 call Send_TV_0 btfsc ir_address, 0 call Send_TV_1 btfss ir_address, 0 call Send_TV_0 TV_Command: btfsc ir_command, 5 call Send_TV_1 btfss ir_command, 5 call Send_TV_0 btfsc ir_command, 4 call Send_TV_1 btfss ir_command, 4 call Send_TV_0 btfsc ir_command, 3 call Send_TV_1 btfss ir_command, 3 call Send_TV_0 btfsc ir_command, 2 call Send_TV_1 btfss ir_command, 2 call Send_TV_0 btfsc ir_command, 1 call Send_TV_1 btfss ir_command, 1 call Send_TV_0 btfsc ir_command, 0 call Send_TV_1 btfss ir_command, 0 call Send_TV_0 return Send_TV_0: movlw 0x20 ;Number of cycles to send movwf temp Burst_hi_tv_0: bsf ir_out ;Turn LED on call D70ins bcf ir_out ;Turn LED off call D70ins decfsz temp, f ;2us if false, 1us if true goto Burst_hi_tv_0 movlw 0x20 ;Number of cycles to send movwf temp Burst_lo_tv_0: bcf ir_out ;Turn LED off call D70ins bcf ir_out ;Turn LED off call D70ins decfsz temp, f ;2us if false, 1us if true goto Burst_lo_tv_0 return Send_TV_1: movlw 0x20 ;Number of cycles to send movwf temp Burst_hi_tv_1: bcf ir_out ;Turn LED off call D70ins bcf ir_out ;Turn LED off call D70ins decfsz temp, f ;2us if false, 1us if true goto Burst_hi_tv_1 movlw 0x20 ;Number of cycles to send movwf temp Burst_lo_tv_1: bsf ir_out ;Turn LED on call D70ins bcf ir_out ;Turn LED off call D70ins decfsz temp, f ;2us if false, 1us if true goto Burst_lo_tv_1 return ;------------------------- Send Comptuer RC5 wth differnt address (36kHz)--; Send_CMPT: return ;-------------------------- Send DVD RCA (56kHz)---------------------------; Send_DVD: ;Goods are stored in address and command ;First send the 4ms AGC Burst that is 224 56kHz cycles movlw 0xE0 ;Number of cycles to send movwf temp Burst_hi: bsf ir_out ;Turn LED on call D20ins bcf ir_out ;Turn LED off call D20ins decfsz temp, f ;2us if false, 1us if true goto Burst_hi ;Second send the 4ms Blank Burst that is 224 56kHz cycles movlw 0xE0 ;Number of cycles to send movwf temp Burst_lo: bcf ir_out ;Turn LED off call D20ins bcf ir_out ;Turn LED off call D20ins decfsz temp, f ;2us if false, 1us if true goto Burst_lo ;Third send the address and command movlw 0x04 movwf counter movf ir_address,w movwf temp_ir Send_address: btfsc temp_ir,3 call sendDVD_1 btfss temp_ir,3 call sendDVD_0 rlf temp_ir,f decfsz counter, f goto Send_address movlw 0x08 movwf counter movf ir_command,w movwf temp_ir Send_Command: btfsc temp_ir,7 call sendDVD_1 btfss temp_ir,7 call sendDVD_0 rlf temp_ir,f decfsz counter, f goto Send_Command ;Forth send inverted address and command movlw 0x04 movwf counter movf ir_address,w movwf temp_ir Send_address_inv: btfsc temp_ir,3 call sendDVD_0 btfss temp_ir,3 call sendDVD_1 rlf temp_ir,f decfsz counter, f goto Send_address_inv movlw 0x08 movwf counter movf ir_command,w movwf temp_ir Send_Command_inv: btfsc temp_ir,7 call sendDVD_0 btfss temp_ir,7 call sendDVD_1 rlf temp_ir,f decfsz counter, f goto Send_Command_inv call sendDVD_0 return sendDVD_1: movlw 0x1C ;Number of cycles to send movwf temp Burst_hi_1: ;Send 500us of 1's bsf ir_out ;Turn LED on call D20ins bcf ir_out ;Turn LED off call D20ins decfsz temp, f ;2us if false, 1us if true goto Burst_hi_1 movlw 0x70 ;Number of cycles to send movwf temp Burst_lo_1: ;Send 2ms of 0's bcf ir_out ;Turn LED off call D20ins bcf ir_out ;Turn LED off call D20ins decfsz temp, f ;2us if false, 1us if true goto Burst_lo_1 return sendDVD_0: movlw 0x1C ;Number of cycles to send movwf temp Burst_hi_0: ;Send 500us of 1's bsf ir_out ;Turn LED on call D20ins bcf ir_out ;Turn LED off call D20ins decfsz temp, f ;2us if false, 1us if true goto Burst_hi_0 movlw 0x34 ;Number of cycles to send movwf temp Burst_lo_0: ;Send 1ms of 0's bcf ir_out ;Turn LED off call D20ins bcf ir_out ;Turn LED off call D20ins decfsz temp, f ;2us if false, 1us if true goto Burst_lo_0 return ;-------------------------- Scan Keys ------------------------------; Scan_Keys: movlw 0xFF ;clear any pins that might be high bcf col0 bcf col1 bcf col2 ;Set first col high bsf col0 ;call D60us btfsc row0 movlw .0 btfsc row1 movlw .1 btfsc row2 movlw .2 btfsc row3 movlw .3 btfsc row4 movlw .4 btfsc row5 movlw .5 bcf col0 ;Set second col high bsf col1 btfsc row0 movlw .6 btfsc row1 movlw .7 btfsc row2 movlw .8 btfsc row3 movlw .9 btfsc row4 movlw .10 btfsc row5 movlw .11 bcf col1 ;Set third col high bsf col2 btfsc row0 movlw .12 btfsc row1 movlw .13 btfsc row2 movlw .14 btfsc row3 movlw .15 btfsc row4 movlw .16 btfsc row5 movlw .17 bcf col2 movwf found return ;***** Delay Routines ; 500 us delay @ 10MHz D500us: movlw 0xF9 ;1248 cycles movwf t0 movlw 0x01 movwf t1 D500u: decfsz t0, f goto $+2 decfsz t1, f goto D500u return ; 22 instructions delay @ 10=MHz D20ins: movlw 0x05 ;20 cycles movwf t0 D22: decfsz t0, f ;1 ins goto D22 ;2 ins return ; 140 instructions delay @ 10=MHz D70ins: movlw 0x09 ;20 cycles movwf t0 D70: decfsz t0, f ;1 ins goto D70 ;2 ins return ; 60 us delay @ 10MHz D60us: movlw 0x31 ;150 cycles movwf t0 D60: decfsz t0, f goto D60 return ;*** 100 ms delay @ 10MHz D100ms: movlw 0x4F ;250000 cycles movwf t0 movlw 0xC4 movwf t1 D100: decfsz t0, f goto $+2 decfsz t1, f goto D100 nop nop return ;*** 20 ms delay @ 10MHz D20ms: movlw 0x0F ;50000 cycles movwf t0 movlw 0x28 movwf t1 D20: decfsz t0, f goto $+2 decfsz t1, f goto D20 nop nop return ;;-------------------------------INIT-----------------------------------;; init movlw 0x07 ;Turn off the analog comparators movwf CMCON bsf STATUS, RP0 ;Goto page 1 movlw b'00011010' ; movwf TRISA movlw b'00011111' movwf TRISB ;Setup Port B bcf STATUS, RP0 ;Goto page 0 call I2CSTO ;send stop condition call D100ms ;wait 100ms for circuit to settle movlw 0x00 call set_leds clrf remote_mode ;Default to mode 0 clrf ir_address clrf ir_command ;********************* Begin the main Program HERE******************* ;This is the main program main movf found, w ;Save off last key press movwf last_found movf remote_mode, w xorlw 0xFF call set_leds call Scan_Keys ;Scans keys and places the first pressed key in "found" movwf found ;key pressed? sublw 0xFF skpnz goto main ;If nothing pressed... don't send anything... movf last_found, w subwf found, w skpz incf toggle, f ;Check to see if it is a mode button movf found, w sublw 0x06 skpz goto Process_Mode_1 movf last_found, w subwf found, w skpnz goto main ;ignore repeat command pulses movf remote_mode, w sublw 0x01 skpnz goto Next_mode_2 movlw 0x01 movwf remote_mode goto main Next_mode_2: movf last_found, w subwf found, w skpnz goto main ;ignore repeat command pulses movlw 0x02 movwf remote_mode goto main Process_Mode_1: movf found, w sublw 0x00 skpz goto Process_command movf remote_mode, w sublw 0x00 skpnz goto Next_mode_0 movf last_found, w subwf found, w skpnz goto main ;ignore repeat command pulses movlw 0x00 movwf remote_mode goto main Next_mode_0: movf last_found, w subwf found, w skpnz goto main ;ignore repeat command pulses movlw 0x03 movwf remote_mode goto main Process_command: movf remote_mode, w sublw 0 ;Is it mode zero? skpnz goto Mode_0 movf remote_mode, w sublw 1 ;Is it mode one? skpnz goto Mode_1 movf remote_mode, w sublw 2 ;Is it mode two? skpnz goto Mode_2 movf remote_mode, w sublw 3 ;Is it mode three? skpnz goto Mode_3 goto End_Mode ;We are in an unknow mode?????? Mode_0: movlw DVD_RCA movwf ir_address movf found, w call RCA_command movwf ir_command call Send_DVD call D100ms goto End_Mode Mode_1: movlw TV_PHILLIPS movwf ir_address movf found, w call Phillips_command_1 movwf ir_command call Send_TV call D100ms goto End_Mode Mode_2: movlw TV_PHILLIPS movwf ir_address movf found, w call Phillips_command_2 movwf ir_command call Send_TV call D100ms goto End_Mode Mode_3: movlw CMPT_RCA movwf ir_address movf found, w call CMPT_command movwf ir_command call Send_DVD call D20ms goto End_Mode End_Mode: goto main end