CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

IR Remote Code Grabber S/W

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
newguy



Joined: 24 Jun 2004
Posts: 1481
Location: Edmonton, Alberta

View user's profile Send private message

IR Remote Code Grabber S/W
PostPosted: Sat Dec 18, 2004 1:42 pm     Reply with quote

I just finished doing a little program that grabs the 32 bit code from an infra-red remote (i.e. a TV or stereo's remote) and displays it on an LCD. I thought that someone else may find it useful. For the schematic, refer to me labs' lab-x1 board found here: http://www.melabs.com/downloads/labx1sch.pdf

The IR remote receiver itself is the Sharp GP1UD262XK (part # 425-1117-ND from digikey: http://www.digikey.ca) The GP1UD is a 3 pin device - simple hookup: supply 5V to Vcc, ground the GND pin, and the signal out pin is hooked to the PIC's EXT0 pin (pin B0).

Here is a good link regarding IR remotes and their data format: http://www.tapspring.com/HATcker_AP_TV.htm Edit: I just tried this link, and it seems to be down for the moment. Anyway, a remote starts a packet with a lead-in sequence. In the absence of IR light, the output of the decoder is normally high. The lead-in sequence consists of a logic low lasting about 8 - 9 ms, followed by a high lasting about 4 ms. Data transfer starts immediately after that, MSbit first. A logic 0 consists of pulsetrain starting with a low level lasting about 0.5 - 0.6 ms, followed by a high level lasting about 0.4 ms. A logic 1 consists of a pulsetrain starting with a low level lasting about 0.5 - 0.6 ms, followed by a high level lasting about 1.4 ms.

I should point out that most remotes send a bare minimum of 64 bits, in two 32 bit "packets". For some functions, the two packets are identical. For others, the two packets are different - thus the reason why the code grabs two packets and displays them.

Here it is. Enjoy.

Code:
#include <18F452.h>
#device adc=8
#use delay(clock=20000000,RESTART_WDT)
#fuses HS, BROWNOUT, BORV20, PUT, STVREN, NOLVP

struct lcd_pin_map {
           boolean junk;
           boolean unused;
           boolean junk2;
           boolean junk3;
           int     data : 4;
           boolean rs;
           boolean enable;
           boolean rw;
        } lcd;

#byte lcd = 0xf83  // 18f452
//#byte lcd = 8 // 16f877

#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line

byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.

                             // The following are used for setting
                             // the I/O port direction register.

STRUCT lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
STRUCT lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in

byte lcd_read_byte() {
      byte low,high;
      set_tris_d(LCD_READ);
      lcd.rw = 1;
      delay_cycles(1);
      lcd.enable = 1;
      delay_cycles(1);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(1);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_d(LCD_WRITE);
      return( (high<<4) | low);
}

void lcd_send_nibble( byte n ) {
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}

void lcd_send_byte( byte address, byte n ) {

      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}

void lcd_init() {
    byte i;
    set_tris_d(LCD_WRITE);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}

void lcd_gotoxy( byte x, byte y) {
   byte address;

   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}

#define LEAD_IN_LOW 40000 // 8 ms
#define LEAD_IN_TOTAL 60000 // 12 ms
#define MIN_TIME 3000 // 0.6 ms
#define THRESHOLD 8000 // 1.6 ms
#define MAX_TIME 11500 // 2.3 ms

unsigned int8 overflow_count = 0, rx_state = 0xff;
unsigned int32 timer_at_start, timer_at_end, low_time, timer_at_mid, period, first_data = 0, second_data = 0;
unsigned int32 temp1, temp2, timer_at_mid_start;
int1 full_cycle = FALSE, got_first = FALSE, data_avail = FALSE, caught_rise = TRUE;

#int_TIMER1
void TIMER1_isr(void) {
   ++overflow_count; // increment when an overflow occurs
}

#int_EXT
void ext_isr(void) {
   if (caught_rise) { // this is a falling edge
      timer_at_end = get_timer1();
      period = (0x10000 * overflow_count) + timer_at_end - timer_at_start;
      overflow_count = 0;
      timer_at_start = timer_at_end;
      full_cycle = TRUE;
      caught_rise = FALSE;
      rx_state++;
      ext_int_edge(0,L_TO_H);
   }
   else { // this is a rising edge
      timer_at_mid = get_timer1();
      low_time = (0x10000 * overflow_count) + timer_at_mid - timer_at_start;
      if (rx_state == 33) {
         rx_state = 0xff;
         if (!got_first) {
            got_first = TRUE;
         }
         else {
            got_first = FALSE;
            data_avail = TRUE;
         }
      }
      caught_rise = TRUE;
      ext_int_edge(0,H_TO_L);
   }
}

void decode_info(void) {
   // each tick = 200 ns
   int i;
   if (rx_state == 1) { // end of first period - lead in
      if ((low_time < LEAD_IN_LOW) || (period < LEAD_IN_TOTAL)) {
         rx_state = 0xff; // reset
         caught_rise = TRUE;
         ext_int_edge(0,H_TO_L);
      }
   }
   else if ((rx_state > 1) && (rx_state < 34)) { // valid data
      i = 33 - rx_state;
      if (period < MIN_TIME) {
         rx_state = 0xff; // reset
         caught_rise = TRUE;
         ext_int_edge(0,H_TO_L);
      }
      if (period < THRESHOLD) { // logic zero
         if (!got_first) {
            bit_clear(first_data, i);
         }
         else {
            bit_clear(second_data, i);
         }
      }
      else if (period < MAX_TIME) { // logic one
         if (!got_first) {
            bit_set(first_data, i);
         }
         else {
            bit_set(second_data, i);
         }
      }
      else if (period >= MAX_TIME) { // reset
         rx_state = 0xff;
         caught_rise = TRUE;
         ext_int_edge(0,H_TO_L);
      }
   }
}

void main() {

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_ON);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   ext_int_edge(0,H_TO_L);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INT_EXT);
   enable_interrupts(global);

   set_tris_e(0x00);
   set_tris_c(0xff);
   port_b_pullups(TRUE);
   set_tris_b(0xff);
   lcd_init();
   lcd_putc("\fReady...");
   rx_state = 0xff;

   while (TRUE) {
      restart_wdt();
      if (full_cycle) {
         full_cycle = FALSE;
         decode_info();
      }
      if (data_avail) {
         data_avail = FALSE;
         printf(lcd_putc,"\fCMD1 = %lx\nCMD2 = %lx", first_data, second_data);
      }
   }
}
chai98a



Joined: 11 Mar 2006
Posts: 2

View user's profile Send private message

PostPosted: Sun Mar 19, 2006 3:29 am     Reply with quote

Pls help, If we need to change to pic16F877 and send data to rs232
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group