;*** Generic remote control program for PIC16F84 ; ; Processor running at 4MHz --> 1uS per instruction ; Output 9600b/s no parity, 1 start,1 or 2 stop bits. ; ; changes: ; Adapted from the original ecal source file for MPASM ; Adapted to be compatible with the UIR (added response to init string 'IR' ; changed baudrate 115600 -> 9600 ; changed output from 4 to 6 bytes ; Changed the port bits to be compatible with the incirquit programable UIR ; ; by Ruud v Gessel, june 2000 ; ; email dobbelbeker@hotmail.com (temporarily) ; ; How it works : ; The proggy simply waits for a pause of longer than 16mS on the remote ; control line. If the pause is found, the size of each negative pulse ; is compared with the previous negative pulse width, if the difference ; is larger than a certain amount (DIFLIM) a 1 is shifted into the output ; variable, else a 0 is shifted in... The same is done for the high pulses. ; The decoding is stopped when no edge is detected for 16mS after which ; the recorded data is send to the host. The recorded data is preceided ; by the edge count.. ; ; I haven't seen a remote control yet which doesn't give a unique output ; value for each key, though I am sure one will exist... Tested on 14 ; remote controls. list p=16F84 #include __CONFIG _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC ;*** Bit definitions vRSIN EQU 6 ;RS232 input bit number mRSIN EQU b'01000000' ;RS232 input bit mask vRSOUT EQU 7 ;RS232 output bit number mRSOUT EQU b'10000000' ;RS232 output bit mask vREMIN EQU 3 ;Remote control input bit number mREMIN EQU b'00001000' ;Remote control input bit mask vTrisB EQU (mRSIN+mREMIN) ;all inputs of PORTB DIFLIM EQU 3 ;Limit for diff to be detected ;*** Variable definitions bMask EQU 0x1D bTlow0 EQU 0x1E ;Keeps previous low pulse width bThigh0 EQU 0x1F ;Keeps previous high pulse width bRemDat EQU 0x20 ;6 Data bytes, must be at 20h bTemp1 EQU 0x26 bTemp2 EQU 0x27 bDelay EQU 0x28 ;Delay counter ORG 0x000 Main clrf INTCON ;No interrupts bsf STATUS,RP0 ;Select bank 1 movlw 0xff movwf TRISA ;All inputs movlw vTrisB movwf TRISB ;Set in/out PORTB movlw b'11000101' ; ³³³³³ÀÁÁÄ Prescaler /64 ; ³³³³ÀÄÄÄÄ Prescaler as TMR0. ; ³³³ÀÄÄÄÄÄ Timer edge Rising. ; ³³ÀÄÄÄÄÄÄ Timer source Internal. ; ³ÀÄÄÄÄÄÄÄ Int edge Rising. ; ÀÄÄÄÄÄÄÄÄ Pullups Off. movwf OPTION_REG ;Set option register bcf STATUS,RP0 ;Select bank 0 clrf PORTB ;All zero ;*** Initial reset... Scan for host call WaitRs232Byte ;Wait for init string xorlw 'I' ;Test for 'I' btfss STATUS,Z ;Skip if ok goto Main ;Reset, wrong init string call WaitRs232Byte ;Wait for second byte xorlw 'R' ;Test for 'R' btfss STATUS,Z ;Skip if ok goto Main ;Reset if wrong init string movlw 'O' call SendRsByte ;'O' to host movlw 'K' call SendRsByte ;'K' to host GetRemData clrf TMR0 ;Setup counter bcf INTCON,T0IF ;Reset time out Grd00 btfss PORTB,vREMIN ;Skip if line high goto GetRemData ;Loop, Try again btfss INTCON,T0IF ;Skip if found goto Grd00 ;Wait some more movlw bMask ;Start of data -1 movwf FSR ;Pointer to data movlw 9 movwf bDelay ;bDelay = 9 Stz0 clrf INDF ;Clear it incf FSR,F ;At next data byte decfsz bDelay,F ;Count down goto Stz0 incf bMask,F movlw bRemDat movwf FSR btfsc PORTB,vREMIN ;Is rem line low? goto $-1 ;Wait for low clrf TMR0 ;Reset counter bcf INTCON,T0IF ;No timeout ;*** Time out value = 16 mS, --> Prescaler = 64 ; 1 timer tick = 64 uS MeasTlow btfsc PORTB,vREMIN ;Skip if line low. goto HaveTlow ;>> Handle this bit btfss INTCON,T0IF ;Skip if time out goto MeasTlow ;>> Loop until line high goto HaveData ;>> Have data, now evaluate HaveTlow movf TMR0,W ;Get time subwf bTlow0,W ;W=Tlow0-Tlow1 subwf bTlow0,F ;bTlow0=bTlow1 call ShiftInBit ;Check difference, determine bit MeasThigh btfss PORTB,vREMIN ;Skip if line high. goto HaveThigh ;>> Handle this bit btfss INTCON,T0IF ;Skip if time out goto MeasThigh ;>> Loop until line high ;*** Have remote data, send it to PC HaveData movf bRemDat+5,W ;Edge counter addlw 0xf0 ;>=16? btfss STATUS,C ;Skip if more than 16 edges goto GetRemData ;Loop if not movf bMask,W xorwf INDF,F movlw bRemDat+5 movwf FSR ;*** RC5 fix movlw 0xe8 xorwf bRemDat,W movlw 0xca btfsc STATUS,Z movwf bRemDat movlw 0xd5 xorwf bRemDat,W movlw 0xc1 btfsc STATUS,Z movwf bRemDat SndDat0 movf INDF,W ;Get data byte call SendRsByte ;Send data decf FSR,F ;One down btfsc FSR,5 ;Skip if below data goto SndDat0 ;Loop until all data sent goto GetRemData ;Get next data HaveThigh movf TMR0,W ;Get time subwf bThigh0,W ;W=Thigh0-Thigh1 subwf bThigh0,F ;bThigh0=bThigh1 call ShiftInBit ;Check difference, determine bit goto MeasTlow ;Measure next low pulse ;*** Shift in 1 or 0 depending upon |W| ShiftInBit clrf TMR0 ;Setup for next measurement bcf INTCON,T0IF ;Reset timeout flag movwf bTemp1 ;Store diff btfsc bTemp1,7 ;Skip if positive sublw 0 ;Make it positive addlw (0xff-DIFLIM) ;Add limit for CY incf bRemDat+5,F ;1 more edge rlf bMask,F ;Shift in carry btfss STATUS,C ;Skip if not last bit return ;Done movf bMask,W ;Get value xorwf INDF,F ;Update data movlw 1 ;New value for shift movwf bMask ;Shift value incf FSR,F ;At next byte movlw bRemDat+5 ;Top of buffer xorwf FSR,W ;Test for top movlw bRemDat+1 ;Last byte unchanged btfsc STATUS,Z ;Skip if not start movwf FSR ;New buffer pointer return ;*** Wait for rs232 byte, 9600bps --> 104uS per bit ; ; TDEL01=(F-32*BR)/(12*BR) TDEL01 EQU d'32' WaitRs232Byte movlw 0x80 ;Only highest bit (counter) movwf bTemp1 ;Holds data btfss PORTB,vRSIN ;Skip if start detected goto $-1 ;Indefinite wait movlw (TDEL01*3)/2 ;Initial time to wait ScanRsBit movwf bDelay ;@7 Init delay counter decfsz bDelay,F ;@8 ++++ Count down goto $-1 ;@9 ++++ Loop until 0 bcf STATUS,C ;@103 Assume a 0 btfss PORTB,vRSIN ;@104-->0 Skip if 0 bsf STATUS,C ;@1 Must be 1 then rrf bTemp1,F ;@2 Rotate in the bit movlw TDEL01 ;@3 Delay value 1 bit btfss STATUS,C ;@4 Skip if last bit goto ScanRsBit ;@5 Get 8 bits of data movlw TDEL01 movwf bDelay decfsz bDelay,F goto $-1 movf bTemp1,W ;Get data in W return ;*** Send byte via rs232 line, 9600bps --> 104uS per bit ; ; TDEL02=(F-44*BR)/(12*BR) TDEL02 EQU d'31' SendRsByte movwf bTemp1 ;Put data here movlw d'11' ;1 start, 8 bits, 2 stop movwf bTemp2 ;Bit counter bcf STATUS,C ;Start bit is 0, (high) SendRsBit movf PORTB,W ;@99 iorlw mRSOUT ;@100 Assume 0 btfsc STATUS,C ;@101 Skip if 0 xorlw mRSOUT ;@102 Toggle bit to 1 movwf PORTB ;@103 Output bit movlw TDEL02 ;@104 --> 0 Delay value movwf bDelay ;@1 Delay counter decfsz bDelay,F ;@2 ++++ Count down goto $-1 ;@3 ++++ Loop until 0 bsf STATUS,C ;@94 Stop bits are 1 rrf bTemp1,F ;@95 Rotate out bit decfsz bTemp2,F ;@96 Bit count goto SendRsBit ;@97 Loop 11 bits return END