Vinod Modhe / Mbed 2 deprecated IR_Remote

Dependencies:   mbed

main.cpp

Committer:
vin_jm
Date:
2013-03-09
Revision:
0:dc689f01feb2

File content as of revision 0:dc689f01feb2:

/*Vinod Modhe*/
/* 4180 Lab3 */

#include "mbed.h"
#include "IR_Def.h"
#include "NokiaLCD.h"

Ticker  system_clock;                                               //This will be used to increment a counter every msec inside it's ISR
Timer T;                                                            //Timer used for measuring time interval between successive edges of IR input signal
InterruptIn IR(p30);                                                //Pin to which IR receiver is connected
void IR_ISR();                                                      //ISR for decoding the IR signal
void dummy_ISR();                                                   //Required so that 'IR_ISR' is not called on both rising and falling edges of IR signal at the same time
void sys_tick();                                                    //ISR for 1 msec. system clock
void RGB_LED(int red, int green, int blue);                         //For writing to ShiftBrite
LocalFileSystem local("local");                                     // Create the local filesystem under the name "local"

//On board LEDs
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

//Pin for entering config mode
DigitalIn config_pin(p21);

//Power Switch Tail
DigitalOut switch_tail(p20);

//ShiftBrite
DigitalOut latch(p15);
DigitalOut enable(p16);
SPI spi(p11, p12, p13);

//Nokia LCD
NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6100); // mosi, sclk, cs, rst, type

//Global IR variables
uint8_t state = 0;                       //State variable for IR state machine
uint8_t Rx_count = 0;                                //Counter to count no. of bits received
uint32_t Rx_buf = 0;                 //To store recevied IR data
char Rx_flag = 0;                    //Flag which indicates that a valid IR command was received
uint32_t Rx_rep_count = 0;           //To keep track of how many repeat pulses are received
uint32_t Rx_rep_timeout_count = 0;   //Timer which clears the previously received IR command, once it reaches the set limit
uint32_t T_buf = 0;                  //Buffer to hold value of timer T
char Rx_ignore_rep_flag = 0;         //0 => Do not ignore repeat pulses

typedef struct IR_Key_Codes {
    uint32_t red_p,red_m;                   //Key codes for Red+ and Red-
    uint32_t green_p,green_m;               //Key codes for Green+ and Green-
    uint32_t blue_p,blue_m;                 //Key codes for Blue+ and Blue-
    uint32_t switch_tail;                   //Key code for power switch tail
} IR_t;

int main()
{
    switch_tail = 0;                                //Turn OFF the power switch tail

    led1 = led2 = led3 = led4 = 1;                  //Turn ON all LEDs to indicate initialization

    //Nokia LCD Init
    lcd.background(0x000000);                       //Set background to white
    lcd.cls();                                      //Clear Screen
    lcd.locate(0,1);                                //Go to line 1
    lcd.printf(" R   G   B  FAN");                  //Display this text
    lcd.locate(0,2);                                //Go to line 2
    lcd.printf(" 0   0   0  OFF");                  //Display this text
    lcd.locate(0,15);                               //Go to line 15
    lcd.printf("100 100 100");                      //Display this text

    config_pin.mode(PullUp);                            //Enable internal pullup

    wait(0.5);

    if(config_pin == 0) {                               //If config pin is pulled low, enter config mode, in which key codes are to be saved in the "IRCodes.txt" file
        led1 = led4 = 0;
        led2 = led3 = 1;
        wait(0.5);
        Rx_ignore_rep_flag = 1;                   //Ignore repeat pulses while in config mode

        IR_t temp;                                      //Temporary variable to hold the received key codes

        //IR Init
        IR.mode(PullNone);                              //Disable internal pullup
        system_clock.attach_us(&sys_tick, 1000);        //This will call the function 'sys_tick' every 1 msec.
        IR.fall(&IR_ISR);                               //Set IR interrupt to occur on falling edge
        IR.rise(&dummy_ISR);

        //Store the received IR codes into temp, while ignoring repeat pulses
        led1 = led2 = led3 = 0;
        led4 = 1;
        while(Rx_flag == 0);                                             //Wait for a valid command
        temp.red_p = Rx_buf;                                              //Copy it into the temp variable
        Rx_flag = 0;                                                     //Reset the flag

        led1 = led2 = led4 = 0;
        led3 = 1;
        while(Rx_flag == 0);
        temp.red_m = Rx_buf;
        Rx_flag = 0;

        led1 = led2 = 0;
        led3 = led4 = 1;
        while(Rx_flag == 0);
        temp.green_p = Rx_buf;
        Rx_flag = 0;

        led1 = led3 = led4 = 0;
        led2 = 1;
        while(Rx_flag == 0);
        temp.green_m = Rx_buf;
        Rx_flag = 0;

        led1 = led3 = 0;
        led2 = led4 = 1;
        while(Rx_flag == 0);
        temp.blue_p = Rx_buf;
        Rx_flag = 0;

        led1 = led4 = 0;
        led2 = led3 = 1;
        while(Rx_flag == 0);
        temp.blue_m = Rx_buf;
        Rx_flag = 0;

        led1 = 0;
        led2 = led3 = led4 = 1;
        while(Rx_flag == 0);
        temp.switch_tail = Rx_buf;
        Rx_flag = 0;

        FILE *fp = fopen("/local/IRCodes.txt", "w");  // Open "IRCodes.txt" on the local file system for writing

        if(fp != NULL) {                                                            //File was opened successfully
            //Write the key codes into the file one by one in the correct order
            fprintf(fp, "%x ", temp.red_p);
            fprintf(fp, "%x ", temp.red_m);
            fprintf(fp, "%x ", temp.green_p);
            fprintf(fp, "%x ", temp.green_m);
            fprintf(fp, "%x ", temp.blue_p);
            fprintf(fp, "%x ", temp.blue_m);
            fprintf(fp, "%x ", temp.switch_tail);

            fclose(fp);

            led1 = led2 = led3 = led4 = 1;
        } else {                                                                                //File could not be opened
            led1 = 1;
            led2 = 0;
            led3 = 1;
            led4 = 0;

            while(1) {                                                                      //Stop executing further code and display error lights
                led1 = !led1;
                led2 = !led2;
                led3 = !led3;
                led4 = !led4;

                wait(0.5);
            }
        }
        Rx_ignore_rep_flag = 0;                         //Disable this flag to not ignore repeat pulses while in normal mode
    }

    IR_t key_code;                                                                  //Struct variable holding all key codes

    //File System Init
    FILE *fp = fopen("/local/IRCodes.txt", "r");    // Open "IRCodes.txt" on the local file system for reading

    if(fp != NULL) {                                                                //File was opened successfully
        fscanf(fp, "%8x", &(key_code.red_p));                   //Read the key codes from the file into the respective struct members
        fscanf(fp, "%8x", &(key_code.red_m));
        fscanf(fp, "%8x", &(key_code.green_p));
        fscanf(fp, "%8x", &(key_code.green_m));
        fscanf(fp, "%8x", &(key_code.blue_p));
        fscanf(fp, "%8x", &(key_code.blue_m));
        fscanf(fp, "%8x", &(key_code.switch_tail));
        fclose(fp);
    } else {                                                                                //File could not be opened
        led1 = 1;
        led2 = 0;
        led3 = 1;
        led4 = 0;

        while(1) {                                                                      //Stop executing further code and display error lights
            led1 = !led1;
            led2 = !led2;
            led3 = !led3;
            led4 = !led4;

            wait(0.5);
        }
    }

    //Shiftbrite Init
    int red=0;
    int green=0;
    int blue=0;
    spi.format(16,0);
    spi.frequency(500000);
    enable=0;
    latch=0;
    wait(2);

    RGB_LED( red, green, blue);
    wait(.1);

    //IR Init
    IR.mode(PullNone);                        //Disable internal pullup
    system_clock.attach_us(&sys_tick, 1000);  //This will call the function 'sys_tick' every 1 msec.
    IR.fall(&IR_ISR);                         //Set IR interrupt to occur on falling edge
    IR.rise(&dummy_ISR);

    led1 = led2 = led3 = led4 = 0;            //Turn OFF all LEDs to indicate initialization is done

    while(1) {
        if(Rx_flag == 1) {
            Rx_flag = 0;

            if(Rx_buf == key_code.red_p) {
                if((red += 10) > 100) {
                    red = 100;
                }

                //Display the scaled rectangle
                lcd.fill(5,  28, 20, 90, 0x000000);                 //Erase original rectangle
                lcd.fill(5,  28, 20, (red/10 * 9), 0x0000FF);       //Draw red rectangle
            } else if(Rx_buf == key_code.red_m) {
                if((red -= 10) < 0) {
                    red = 0;
                }

                //Display the scaled rectangle
                lcd.fill(5,  28, 20, 90, 0x000000);                 //Erase original rectangle
                lcd.fill(5,  28, 20, (red/10 *9), 0x0000FF);        //Draw red rectangle
            } else if(Rx_buf == key_code.green_p) {
                if((green += 10) > 100) {
                    green = 100;
                }

                //Display the scaled rectangle
                lcd.fill(36,  28, 20, 90, 0x000000);                 //Erase original rectangle
                lcd.fill(36,  28, 20, (green/10 * 9), 0x00FF00);     //Draw green rectangle
            } else if(Rx_buf == key_code.green_m) {
                if((green -= 10) < 0) {
                    green = 0;
                }

                //Display the scaled rectangle
                lcd.fill(36,  28, 20, 90, 0x000000);                 //Erase original rectangle
                lcd.fill(36,  28, 20, (green/10 * 9), 0x00FF00);     //Draw green rectangle
            } else if(Rx_buf == key_code.blue_p) {
                if((blue += 10) > 100) {
                    blue = 100;
                }

                //Display the scaled rectangle
                lcd.fill(67,  28, 20, 90, 0x000000);                 //Erase original rectangle
                lcd.fill(67,  28, 20, (blue/10 * 9), 0xFF0000);      //Draw blue rectangle
            } else if(Rx_buf == key_code.blue_m) {
                if((blue -= 10) < 0) {
                    blue = 0;
                }

                //Display the scaled rectangle
                lcd.fill(67,  28, 20, 90, 0x000000);                 //Erase original rectangle
                lcd.fill(67,  28, 20, (blue/10* 9), 0xFF0000);          //Draw blue rectangle
            } else if((Rx_buf == key_code.switch_tail) && (Rx_rep_count == 0)) { //Do not consider repeat pulses for switch tail to avoid rapid switching
                switch_tail = !switch_tail;

                if(switch_tail == 0) {                              //Fan OFF
                    lcd.locate(0,2);                                //Go to line 2
                    lcd.printf(" 0   0   0  OFF");                  //Display this text
                } else if(switch_tail == 1) {                       //Fan ON
                    lcd.locate(0,2);                                //Go to line 2
                    lcd.printf(" 0   0   0  ON ");                  //Display this text
                }

            }

            RGB_LED( red, green, blue);                       //Write to ShiftBrite after receiving a valid command
            wait(.1);
        }

        wait_us(100);                                                     //Wait for 0.1ms
    }
}

void RGB_LED(int red, int green, int blue)
{
    unsigned int low_color=0;
    unsigned int high_color=0;
    high_color=(blue<<4)|((red&0x3C0)>>6);
    low_color=(((red&0x3F)<<10)|(green));
    spi.write(high_color);
    spi.write(low_color);
    latch=1;
    latch=0;
}

void sys_tick()
{
    if(Rx_rep_timeout_count < 0xFFFF) { //Do not increment counter beyond 0xFFFF to prevent roll-over
        ++Rx_rep_timeout_count;       //Increment this counter every 1msec.
    }
}

void IR_ISR()
{
    if(state == 0) {
        T.stop();               //Stop timer
        T.reset();              //Reset timer
        T.start();              //Start timer
        IR.rise(&IR_ISR);       //Set IR interrupt to occur on rising edge
        IR.fall(&dummy_ISR);
        state = 1;              //Go to next state
        Rx_count = 0;           //Clear the received bits counter
    } else if(state == 1) {
        T.stop();                          //Stop timer
        T_buf = (uint32_t)T.read_us();     //Read timer
        T.reset();                         //Reset timer
        T.start();                         //Start timer
        IR.fall(&IR_ISR);                  //Set IR interrupt to occur on falling edge
        IR.rise(&dummy_ISR);

        if(T_buf <= IR_9000us_UL && T_buf >= IR_9000us_LL) { //Check for preamble start pulse(9ms)
            state = 2;  //Go to next state
        } else {
            state = 0; //Reset the state machine
        }
    } else if(state == 2) {
        T.stop();                          //Stop timer
        T_buf = (uint32_t)T.read_us();     //Read the value in timer
        T.reset();                         //Reset timer
        T.start();                         //Start timer
        IR.fall(&IR_ISR);                  //Set IR interrupt to occur on falling edge
        IR.rise(&dummy_ISR);

        if(T_buf <= IR_4500us_UL && T_buf >= IR_4500us_LL) { //Check for preamble space(4.5ms)
            state = 3;                  //Go to next state
            Rx_rep_timeout_count = 0;   //Reset counter
            Rx_rep_count = 0;           //Reset the repeat pulse counter
        } else if(T_buf <= IR_2250us_UL && T_buf >= IR_2250us_LL) { //Check for repeat pulse(2.25ms)
            state = 0;                      //Reset the state machine

            if(Rx_rep_count < 0xFFFF) {
                if(Rx_rep_timeout_count < IR_rep_timeout_ms) {  //Only increment the repeat pulse counter if the delay between two successive repeat pulses is less than 135msec.
                    Rx_rep_timeout_count = 0;                   //Reset the counter everytime a valid repeat pulse is received
                    ++Rx_rep_count;
                } else {                                         //Invald repeat pulse received
                    Rx_rep_count = 0;                            //Reset counter
                    Rx_flag = 0;                                 //Clear the flag to indicate that an IR command was not received
                    Rx_buf = 0;                                  //Clear the previously received command
                }
            }
            goto ahead;                    //Repeat the previous command
        } else { //Wrong pulse
            Rx_rep_count = 0;     //Reset counter
            state = 0;                       //Reset the state machine
        }
    } else if(state == 3) {
        T.stop();                      //Stop timer
        T_buf = T.read_us();          //Read the value in timer
        T.reset();                     //Reset timer
        T.start();                     //Start timer
        IR.fall(&IR_ISR);              //Set IR interrupt to occur on falling edge
        IR.rise(&dummy_ISR);

        if(T_buf <= IR_1_UL_us && T_buf >= IR_1_LL_us) { //Check if bit is '1'(2.25ms)
            ++Rx_count;              //Increment the bit counter
            Rx_buf >>= 1;
            Rx_buf |= 0x80000000;     //Shift in a '1' from the left side
            state = 3;               //Remain in current state
        } else if(T_buf <= IR_0_UL_us && T_buf >= IR_0_LL_us) { //Check if bit is '0'(1.12ms)
            ++Rx_count;         //Increment the bit counter
            Rx_buf >>= 1;        //Shift in a '0' from the left side
            state = 3;          //Remain in current state
        } else { //Invalid data received
            Rx_count = 0;//Reset the bit counter
            state = 0;   //Reset state m/c
        }

        if(Rx_count == 32) { //Check if all 32 bits have been received
            state = 0;       //Reset state m/c

ahead:

            if(!((Rx_rep_count > 0) && (Rx_ignore_rep_flag == 1))) {
                Rx_flag = 1;                             //Set this flag for repeat pulses only if repeat pulses are to be considered
            }
            Rx_rep_timeout_count = 0;         //Reset the counter everytime a valid command is received
        }
    }
}

void dummy_ISR()
{
    //Do nothing
}