Getting numbers pressed via IR

105 views Asked by At

I am having a bit of trouble moving on with what I am trying to do here. I have an IR receiver set up to just check for incoming signals, which it does. I am using a simple remote control, 0 - 9 on it, which is obviously 10 numbers.

Here is my code so far that has it getting the incoming IR and noticing it. I want to decode what number it is. I know each number has a different signal and I can figure out what number is being pressed via the high and lows, 0 and 1's but how can I translate that into what number and put it somewhere to be display on the LCD I have.

Here is the code:

        list p=16f690,r=dec     ; set processor type, default to base 10

#include    <p16f690.inc>           ; chip definitions
        errorlevel  -302        ; bank warnings on +302 off -302
        __CONFIG    (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF 
        & _MCLRE_OFF &    _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

#define     IR_PORT PORTA           ; IR receiver
#define     IR      2               ; IR receiver on RA2
#define     SWITCH  3               ; switch on RA3
#define     LED_0   0               ; LED on RC0
#define     LED_1   1               ; LED on RC1
#define     LED_2   2               ; LED on RC2
#define     LED_3   3               ; LED on RC3
#define     READY   0               ; READY bit

BANK_0      UDATA   0x20            ; bank_0
BANK_0      RES     1               ; variable used for bank switching
state       RES     1               ; state bits
bitcount    RES     1               ; number of bits seen so far
buffer      RES     20              ; the bits

SHARED      UDATA_SHR               ; shared across all banks
w_temp      RES     1               ; variable used for context saving 
status_temp RES     1               ; variable used for context saving
pclath_temp RES     1               ; variable used for context saving

RESET_VECTOR    CODE    0x000       ; processor reset vector location
    goto    main                ; go to beginning of program

INT_VECTOR      CODE    0x004       ; interrupt vector location
    goto    interrupt           ; go to the interrupt service routine

MAIN            CODE    0x005       ; address after vectors
interrupt:                          ; interrupt service routine
    movwf   w_temp              ; save off current W register contents
    movf    STATUS,w            ; move status register into W register
    movwf   status_temp         ; save off contents of STATUS register
    movf    PCLATH,w            ; move pclath register into W register
    movwf   pclath_temp         ; save off contents of PCLATH register
lowedge:                            ; let's check RA2
    btfss   INTCON,INTF         ; check for type of interrupt = RA2
    goto    timercheck          ; not RA2
    bcf     INTCON,INTF         ; ack the interrupt
    movf    TMR0,w              ; get the value
    movwf   INDF                ; store in buffer
    incf    FSR,f               ; bump the pointer
    incf    bitcount,f          ; count the bit
    movf    bitcount,w          ; pick up the count
    sublw   18                  ; got all the bits?
    btfss   STATUS,Z            ; check
    goto    goon                ; continue
    bsf     state,READY         ; it is
    bcf     INTCON,INTE         ; turn off RA2 interrupts for now
    bcf     INTCON,GIE
goon:                               ; go on
    movlw   200                 ; prepare
    movwf   TMR0                ; timeout
    bcf     INTCON,T0IF         ; clear the interrupt flag
    bsf     INTCON,T0IE         ; enable timer 0 interrupts
    goto    eoi                 ; we're done
timercheck:
    btfss   INTCON,T0IF         ; check for type of interrupt = TMR0
    goto    eoi                 ; is it an alien attack?
    bcf     INTCON,T0IF         ; ack the interrupt
    clrf    bitcount            ; clear the bitcount
    bcf     state,READY         ; clear just in case
    movlw   buffer              ; point at
    movwf   FSR                 ; start of buffer
    bcf     INTCON,T0IE         ; disable timer 0 interrupts
    BANKSEL BANK_0              ; bank 0
    comf    PORTC,f             ; flip the leds
    bcf     INTCON,T0IF         ; ack the interrupt
eoi:                                ; end of interrupt
    BANKSEL BANK_0              ; bank 0
    movf    pclath_temp,w       ; retrieve copy of PCLATH register
    movwf   PCLATH              ; restore pre-isr PCLATH register contents
    movf    status_temp,w       ; retrieve copy of STATUS register
    movwf   STATUS              ; restore pre-isr STATUS register contents
    swapf   w_temp,f            ; restore pre-isr W register contents
    swapf   w_temp,w            ; (swapf doesn't affect the flags)
    retfie                      ; return from interrupt

main:                               ; main code
    BANKSEL OSCCON              ; bank 1
    movlw   0x10                ; system clock = 125 kHz
    movwf   OSCCON              ; instruction clock = 7750 Hz, 32uS/instruction
    BANKSEL PORTA               ; bank 0
    clrf    PORTA               ; init PORTA
    BANKSEL ANSEL               ; bank 2
    clrf    ANSEL               ; digital I/O
    clrf    ANSELH              ; digital I/O
    BANKSEL TRISA               ; bank 1
    movlw   0xff                ; init PORTA
    movwf   TRISA               ; as inputs
    BANKSEL PORTC               ; bank 0
    clrf    PORTC               ; init PORTC as outputs
    BANKSEL TRISC               ; bank 1
    movlw   0xf0                ; set RC<7:4> as inputs
    movwf   TRISC               ; set RC<3:0> as outputs
    BANKSEL PORTC               ; bank 0
    movlw   0x09                ; init the
    movwf   PORTC               ;   leds
    clrwdt                      ; clear WDT and prescaler
    BANKSEL OPTION_REG          ; bank 1
    movlw   b'11110000'         ; mask TMR0 select and
    andwf   OPTION_REG,W        ;   prescaler bits
    iorlw   b'00000010'         ; set prescale to
    movwf   OPTION_REG          ;   1:n
    bcf     OPTION_REG,T0CS     ; make it a timer
    bcf     OPTION_REG,INTEDG   ; select the falling edge of RA2
    BANKSEL TMR0                ; bank 0
    clrf    TMR0                ; clear the count
    BANKSEL INTCON              ; bank 0
    bcf     INTCON,T0IF         ; clear pending timer 0 interrupts
    bcf     INTCON,T0IE         ; disallow timer 0 interrupts for now
    bsf     INTCON,INTE         ; enable RA2 interrupts
    BANKSEL BANK_0              ; bank 0
    bcf     state,READY         ; clear the ready bit
    clrf    bitcount            ; we have seen no bits
    movlw   buffer              ; point at
    movwf   FSR                 ; start of buffer
    bsf     INTCON,GIE          ; enable global interrupts
    BANKSEL BANK_0              ; bank 0
forever:                            ; stay here forever
    btfss   state,READY         ; check for IR Code ready
    goto    forever             ; go check again
dobits:                             ; process ir code
    BANKSEL BANK_0              ; bank 0

    bcf     state,READY         ; clear the ready bit
    clrf    bitcount            ; we have seen no bits
    movlw   buffer              ; point at
    movwf   FSR                 ; start of buffer
    bsf     INTCON,INTE         ; enable RA2 interrupts
    bsf     INTCON,GIE          ; enable global interrupts
    goto    forever             ; keep doing it

EE              CODE    0x2100  ;   eeprom
    DE      'J', 'A', 'S', 'O', 'N', 0

    END
1

There are 1 answers

0
jolati On

As it is now written the interrupt handler is only called on high to low transitions. This measures only the frequency of the input. If, as you say, ones and zeros are encoded as specific lengths of high and low state you need to interrupt on change (on both falling and rising transitions). Measure the duration to the next change using the timer. Determine the number of bits of that state by dividing the duration by the bit length.