'**************************************************************** '* Name : IR_RX_TX.BAS * '* Author : Frank Mc Alinden * '* Notice : Copyright (c) 2003 * '* : All Rights Reserved * '* Date : 9/06/2003 * '* Version : 1.0 * '* Notes : * '* : * '**************************************************************** DEFINE LCD_EREG PORTB ' LCD ENABLE PORT DEFINE LCD_EBIT 4 ' LCD ENABLE BIT DEFINE LCD_LINES 4 ' 4 LINE LCD SETUP 'SET UP THE PWM FOR 38KHZ CMCON = 7 ' SET UP FOR DIGITAL VRCON = 0 ' DISABLE A/D REF TRISA = %00000000 ' TRISB = %11100000 ' B.3 =PWM,B.0,B.1 VOL UP + DOWN LEDS,B.5= IR RX PR2 = 25 ' SET PWM FOR APPROX 38KHZ CCPR1L = 13 ' SET PWM DUTY CYCLE TO 50% CCP1CON = %00001100 ' MODE SELECT = PWM T2CON = %00000100 ' TIMER2 ON + 1:1 PRESCALE OPTION_REG = %10000000'ASSIGN PRESCALER TO TIMER 0 IR_DEV VAR BYTE ' BUFFER FOR DEVICE CODE IR_BUT VAR BYTE ' BUFFER FOR BUTTON CODE _IR_BUT VAR BYTE ' BUFFER FOR BUTTON INVERTED NEC _IR_DEV VAR BYTE ' BUFFER FOR DEVICE INVERTED NEC HEADER VAR WORD ' IR HEADER PACKET VAR WORD ' IR DEVICE + DATA BUFFER SYNC VAR WORD 'PAUSE AFTER HEADER P_VAL VAR BYTE ' IR BIT BUFFER BITCNT VAR BYTE ' IR BIT COUNTER NOISE VAR BIT 'NOISE FLAG SONY12 VAR BIT 'IR SIGNAL SONY 12 BIT SONY15 VAR BIT 'IR SIGNAL SONY 15 BIT NEC VAR BIT 'IR SIGNAL NEC NEC_REPEAT VAR BIT 'NEC REPEAT FLAG RC5 VAR BIT 'IR SIGNAL PHILIPS RC5 START2 VAR BYTE '2ND START BYTE IN RC5 FORMAT RC5_OLD VAR BYTE 'PREVIOUSLY RECEIVED RC5 CODE TOG_BIT VAR BIT 'USED IN RC5 FORMAT TEMP VAR BYTE RX_LED_TIMER VAR BYTE'RECEIVED IR LED TIMER RX_TIM_EN VAR BIT 'RECEIVED IR TIMER ENABLE FLAG W_TEMP VAR BYTE $20 SYSTEM W_TEMP1 VAR BYTE $A0 SYSTEM W_TEMP2 VAR BYTE $120 SYSTEM STATUS_TEMP VAR BYTE BANK0 SYSTEM TEMP_FSR VAR BYTE MICRO_SEC_CNT VAR BYTE ' MILLI_SEC_CNT VAR BYTE ' ALIVE_LED VAR PORTB.0 ;HEART BEAT LED RED_LED VAR PORTB.1 'CHANNEL DOWN LED REC_IR VAR PORTB.2 'RECEIVED IR LED IR_RX VAR PORTB.5 'INFRA RED RECEIVER GOTO START DEFINE INTHAND myint ;************************************************************* ; INTERRUPT ROUTINE ;************************************************************* asm myint clrwdt ; MOVWF W_TEMP ;save w swapf STATUS,w ;swap status and save in w bcf STATUS,RP0 bcf STATUS,RP1 ;select bank 0 movwf STATUS_TEMP ;save status test_timer0 btfsc INTCON,T0IF ;was it timer 0 goto ser_timer0 ;yes goto exit_int ; ;************************************************************** ; TIMER 0 INTERRUPT ROUTINE ;************************************************************** ser_timer0 decfsz _MICRO_SEC_CNT ;dec micro second counter goto _ext_tim0_int ; movlw 004H ;reload micro second timer movwf _MICRO_SEC_CNT ; decfsz _MILLI_SEC_CNT,1 ;decrement milli seconds counter goto _ext_tim0_int ; movlw 78H ;reload milli second counter 120 DEC movwf _MILLI_SEC_CNT ;120 CHECK_IR_LED_TIMER BTFSS _RX_TIM_EN ;CHECK IF RX LED TIMER ENABLED GOTO UPDATE_ALIVE ; DECFSZ _RX_LED_TIMER ; CHECK IF TIMER DONE GOTO UPDATE_ALIVE ; MOVLW 020H ; TIMER DONE RELOAD TIMER MOVWF _RX_LED_TIMER ; BCF _RX_TIM_EN ;DISABLE TIMER BCF _REC_IR ;TURN OFF RX IR LED UPDATE_ALIVE btfss _ALIVE_LED ; test led status goto turn_led_on ;led is off bcf _ALIVE_LED ; TURN ALIVE LED OFF goto _ext_tim0_int ;exit turn_led_on bsf _ALIVE_LED ; TURN ALIVE LED ON _ext_tim0_int bcf INTCON,T0IF ;CLEAR INT FLAG ;*********************************************************************** ; ;************************************************************************ exit_int swapf STATUS_TEMP,w ;restore status movwf STATUS ; swapf W_TEMP ;restore w without swapf W_TEMP,w ;effecting the status reg retfie ;return from interrupt endasm START: CLEAR 'CLEAR ALL RAM LOCATIONS RX_LED_TIMER = 20 'INITILISE TIMER INTCON = %10100000 ' ENABLE GLOBAL AND TIMER0 INT HIGH ALIVE_LED HIGH RED_LED HIGH REC_IR PAUSE 1000 LOW ALIVE_LED LOW RED_LED LOW REC_IR LCDOUT $FE,1," HELLO WORLD" BEGIN: IF IR_RX = 0 THEN CAPTURE 'PIN LOW MAYBE IR SIGNAL GOTO BEGIN ' CAPTURE: INTCON = %00000000 'DISABLE GLOBAL AND TIMER 0 INT GOSUB IR_IN 'GET IR SIGNAL IF NOISE = 0 THEN DECODE_IR 'DECODE IR SIGNAL LOW NOISE 'CLEAR NOISE FLAG INTCON = %10100000 'RE ENABLE GLOBAL AND TIMER 0 INT GOTO BEGIN 'GOTO CAPTURE ' DECODE_IR: INTCON = %10100000 'RE ENABLE GLOBAL AND TIMER 0 INT IF SONY12=1 THEN SONY_12_BIT 'SONY 12 BIT FORMAT DETECTED IF SONY15=1 THEN SONY_15_BIT 'SONY 15 BIT FORMAT DETECTED IF NEC=1 THEN NEC_32 'NEC FORMAT DETECTED IF NEC_REPEAT= 1 THEN REPEAT_NEC'REPEAT COMMAND IF RC5 = 1 THEN RC5_14 'RC5 14 BIT FORMAT lcdout $FE,1,"FORMAT UNKNOWN" lcdout $FE,$C0,"START2 =",#START2,"0uS" LCDOUT $FE,$94,"SYNC = ", #SYNC,"0uS" LCDOUT $FE,$d4,"HEADER = ", #HEADER,"0uS" pause 200 GOTO BEGIN 'UNKNOWN '****************************************************************************** SONY_12_BIT: LOW SONY12 'CLEAR SONY FORMAT FLAG lcdout $FE,1," SONY 12 FORMAT" PAUSE 200 GOTO BEGIN 'DO IT ALL AGAIN '****************************************************************************** SONY_15_BIT: LOW SONY15 'CLEAR SONY FORMAT FLAG lcdout $FE,1," SONY 15 FORMAT" LCDOUT $FE,$C0,"DEVICE CODE =",#IR_DEV LCDOUT $FE,$94,"BUTTON CODE = ",#IR_BUT LCDOUT $FE,$d4,"HEADER =", #HEADER PAUSE 200 GOTO BEGIN 'DO IT ALL AGAIN '****************************************************************************** NEC_32: LOW NEC 'CLEAR NEC FORMAT FLAG lcdout $FE,1," NEC FORMAT" LCDOUT $FE,$C0,"DEVICE CODE =",#IR_DEV LCDOUT $FE,$94,"BUTTON CODE = ",#IR_BUT PAUSE 200 RX_LED_TIMER = 20 'RELOAD TIMER HIGH REC_IR 'TURN ON RX IR LED RX_TIM_EN = 1 'ENABLE RX LED TIMER GOTO BEGIN 'DO IT ALL AGAIN '****************************************************************************** REPEAT_NEC: LOW NEC_REPEAT 'CLEAR NEC REPEAT FLAG lcdout $FE,1," NEC REPEAT" ' LCDOUT $FE,$C0,"SYNC = ",#SYNC,"0uS" PAUSE 500 goto BEGIN ' '************************************************************************** RC5_14 LOW RC5 'CLEAR RC5 FORMAT FLAG lcdout $FE,1," TEMP =",#TEMP,"0uS" LCDOUT $FE,$C0,"START1 =",#HEADER,"0uS" LCDOUT $FE,$94,"SYNC = ",#SYNC,"0uS" LCDOUT $FE,$d4,"START2 =", #START2,"0uS" pause 200 GOTO BEGIN '*************************************************************************** ' GET IR HEADER '**************************************************************************** IR_IN: IR_DEV=255:IR_BUT=255 'PRESET RETURN VALUES RCTIME IR_RX,0,HEADER 'GET HEADER VALUE IF HEADER <15 THEN GLITCH 'GLITCH IGNORE IF HEADER >=200 AND HEADER <= 260 THEN SONY' IF HEADER >800 AND HEADER <= 1000 THEN NEC_FORMAT' IF HEADER >88 AND HEADER <= 105 THEN RC5_FORMAT RCTIME IR_RX,1,SYNC 'GET SYNC VALUE FOR VIEWING RETURN GLITCH: HIGH NOISE 'SET NOISE FLAG RETURN '****************************************************************************** 'RECEIVE SONY 12 OR 15 BIT AND CONVERT INTO A PACKET '****************************************************************************** SONY: DEFINE PULSIN_MAX 200 'DEFINE MAX EXPECTED DELAY FOR SIG FOR BITCNT=0 TO 14 'LOAD COUNTER = 15 PULSIN IR_RX,0,P_VAL ' if P_VAL =0 AND BITCNT = 12 THEN EXIT_SONY12'ONLY 12 BIT IF P_VAL>=90 THEN 'CHECK FOR HIGH PACKET.0[BITCNT]=1 'SET BIT ELSE PACKET.0[BITCNT]=0 'CLEAR BIT ENDIF ' NEXT ' SONY15BIT: IR_BUT=PACKET&%01111111 'MASK THE 7 BUTTON BITS IR_DEV=(PACKET>>7)&%11111111 'MASK THE 8 DEVICE BITS HIGH SONY15 'SET SONY 15 BIT FORMAT FLAG RETURN ' EXIT_SONY12: IR_BUT=PACKET&%01111111 'MASK THE 7 BUTTON BITS IR_DEV=(PACKET>>7)&%000111111 'MASK THE 5 DEVICE BITS HIGH SONY12 'SET SONY 12 BIT FORMAT FLAG RETURN ' '****************************************************************************** 'RECEIVE NEC 32 BIT AND CONVERT INTO A PACKET '****************************************************************************** NEC_FORMAT: DEFINE PULSIN_MAX 1200 'DEFINE MAX EXPECTED DELAY FOR SIG RCTIME IR_RX,1,SYNC 'GET SYNC VALUE IF SYNC >=390 AND SYNC <450 THEN NEC_DATA 'DATA SIGNAL if SYNC >190 and SYNC < 240 THEN NEC_RPT 'REPEAT SIGNAL RETURN NEC_RPT HIGH NEC_REPEAT 'MUST BE A REPEAT RETURN 'GET DEVICE '********** NEC_DATA: for BITCNT = 0 to 7 PULSIN IR_RX,1,P_VAL ' IF P_VAL>=90 THEN ' PACKET.0[BITCNT]=1 'SET BIT ELSE PACKET.0[BITCNT]=0 'CLEAR BIT ENDIF ' NEXT ' IR_DEV = PACKET ' 'GET INVERTED DEVICE '******************** for BITCNT= 0 TO 7 PULSIN IR_RX,1,P_VAL ' IF P_VAL>=90 THEN ' PACKET.0[BITCNT]=1 'SET BIT ELSE PACKET.0[BITCNT]=0 'CLEAR BIT ENDIF ' NEXT ' _IR_DEV = PACKET ' 'GET BUTTON '*********** FOR BITCNT = 0 TO 7 PULSIN IR_RX,1,P_VAL ' IF P_VAL>=90 THEN ' PACKET.0[BITCNT]=1 'SET BIT ELSE PACKET.0[BITCNT]=0 'CLEAR BIT ENDIF ' NEXT ' IR_BUT = PACKET 'GET INVERTED BUTTON '********************* FOR BITCNT = 0 TO 7 PULSIN IR_RX,1,P_VAL ' IF P_VAL>=90 THEN ' PACKET.0[BITCNT]=1 'SET BIT ELSE PACKET.0[BITCNT]=0 'CLEAR BIT ENDIF ' NEXT ' _IR_BUT = PACKET ' IF (IR_DEV ^ _IR_DEV)=$FF THEN CHEC_BUT'CHECK IR_DEV = 255 RETURN CHEC_BUT: IF (IR_BUT ^ _IR_BUT)=$FF THEN NEC_DONE IR_BUT = 255 RETURN NEC_DONE: HIGH NEC 'SET NEC FORMAT RETURN ' '***************************************************************************** 'RC5 FORMAT '***************************************************************************** RC5_FORMAT RCTIME IR_RX,1,SYNC 'GET SYNC VALUE IF SYNC >=42 AND SYNC<= 60 THEN CHEC_START2; RETURN 'NOT RC5 CHEC_START2: PULSIN IR_RX,0,START2 'GET START2 IF START2 >=88 AND START2 <= 100 THEN LO_TOG'TOGGLE CLEAR IF START2 >=178 AND START2<= 190 THEN HI_TOG'TOGGLE SET RETURN ' LO_TOG: TOG_BIT = 0 'CLEAR TOGGLE FLAG 'pauseus 1350 ' GOTO FORMAT_RC5 ' HI_TOG: TOG_BIT = 1 'SET TOGGLE BIT 'pauseus 900 FORMAT_RC5 RCTIME IR_RX,1,TEMP 'GET SYNC VALUE HIGH RC5 'SET RC5 FLAG RETURN