Jump to content
43oh

CIR - Infrared remote decoder for NEC protocol


Recommended Posts

A quick demo that can be converted to a library:

 

/* Consumer IR receiver demo for the NEC protocol for MSP430G2231 (Launchpad)
* Requires a 38kHz IR detector such as Vishay TSOP4838 on Pin 4 (P1.2/TA0.1)
* Toggles a LED when a particular IR remote button is pushed
* For more details on the NEC protocol, see http://www.sbprojects.com/knowledge/ir/nec.php 
*/ 

#include 

// IR pulse timing constants in microseconds

#define HP_MIN      8500    // Header pulse minimum duration
#define HP_MAX      9500    // Header pulse maximum duration
#define HPL_MIN     4100    // Header pulse low minimum duration
#define HPL_MAX     4800    // Header pulse low maximum duration
#define RPT_MIN     1900    // Repeat pulse minimum duration
#define RPT_MAX     2500    // Repeat pulse minimum duration
#define BP_MIN      450     // Bit pulse minimum duration
#define BP_MAX      650     // Bit pulse maximum duration
#define ONE_MIN     2000    // Logical one minumum duration
#define ONE_MAX     2500    // Logical one maxumum duration
#define ZERO_MIN    1000    // Logical zero minumum duration
#define ZERO_MAX    1300    // Logical zero maxumum duration

#define FALSE 0
#define TRUE (!FALSE)
#define IR_REPEAT 0xFF00    // Special repeat code
#define MAX_DATA_BITS 32    // NEC protocol provides for 32 bits of data

#define PIN_IR      BIT2    // This must be TA0.1
#define PIN_LED1    BIT0    // LED1 on the Launchpad

#define BUTTON_POWER    0x00FD00FF    // This is a code for the button to toggle the LED

static volatile unsigned long data;

void ir_init(void)
{
   _disable_interrupts();
   BCSCTL1 = CALBC1_1MHZ;                  // Set DCO to 1MHz to measure pulses in microseconds
   DCOCTL = CALDCO_1MHZ;
   P1DIR &= ~PIN_IR;                       // Set IR detector pin to input
   P1OUT |= PIN_IR;                        // Set resistor to pull-up
   P1REN |= PIN_IR;                        // Enable resistor
   P1SEL = PIN_IR;                         // set IR detector pin to peripheral function
   TACTL = TASSEL_2 | ID_0 | MC_2;         // SMCLK, Continuous mode, Input divider /1
   TACCTL1 = CM_3 |  CCIS_0 | CAP | CCIE;  // Capture on both edges, Capture Input Select CCI0A, Capture mode, Capture interrupt enable
   _enable_interrupts();
}

void main(void)
{
   WDTCTL = WDTPW | WDTHOLD;       // Stop the Watchdog timer
   P1DIR = PIN_LED1;               // LED1 to output
   ir_init();                      // Initialize IR detection 
   for (;                        // Loop forever
   {
       _low_power_mode_0();        // Wait in LPM0 until the IR remote code is received 
       // Set a breakpoint on the next line and add a watch for the data variable to see the IR code received 
       if (data == BUTTON_POWER)   // If remote power button is pressed
           P1OUT ^= PIN_LED1;      // Toggle LED1 
   }
}
#pragma vector=TIMERA1_VECTOR
__interrupt void timer_A_interrupt(void)
{
   static unsigned char hp, hr;                    //header pulse received, header received
   static unsigned char br;                        // bits received
   static unsigned char pulse=FALSE;               // pulse in progress
   static volatile unsigned char ready = FALSE;    // data ready
   static unsigned int pw=0, bw=0;                 // pulse width, bit width
   unsigned int i = TAIV;                          // Read TAIV to clear CCIFG

   // Is this the beginning or the end of the pulse?
   if (!pulse)
   // start of the pulse
   {
       bw=TACCR1;
       // reset Timer
       TACTL |= TACLR;
       pulse=TRUE;
       // Has the header pulse just been received?
       if (hp)
       {
           // Is the header duration in range?
           if (bw>HPL_MIN && bw            {
               hr=TRUE;
               br=0;
               data=0;
               ready=FALSE;
           }
           // is it a repeat code?
           else if (bw>RPT_MIN && bw            {
               data=IR_REPEAT;
               hr=FALSE;
               ready=TRUE;
           }
       }
       // Was there a bit pulse before, and also has the header been received?
       if(hr && pw>BP_MIN && pw        {
           if (bw>ONE_MIN && bw            {
               data<<=1;
               data++;
               br++;
           }
           else if (bw>ZERO_MIN && bw            {
               data<<=1;
               br++;
           }
           if (br==MAX_DATA_BITS)
           {
               hr=FALSE;
               ready=TRUE;
           }
       }
       hp=FALSE;
   }
   else
   // end of the pulse
   {
       pw=TACCR1;
       pulse=FALSE;
       // Is this a header pulse?
       if (pw>HP_MIN && pw        {
           // set Header Pulse Received flag
           hp=TRUE;
           // Reset timer
           TACTL |= TACLR;
       }
       else
       {
           hp=FALSE;
       }
   }
   if (ready)
   {
       ready = FALSE;
       _low_power_mode_off_on_exit();  // Return from LPM
   }
}

 

(edited - added a pullup resistor setting)

Link to post
Share on other sites
  • 11 months later...
  • 2 months later...
  • 9 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...