Hacking into the iClicker2 for adding remote access abilities. http://www.amazon.com/I-Clicker-2-I-CLICKER/dp/1429280476
main.cpp
- Committer:
- jjones646
- Date:
- 2014-12-08
- Revision:
- 1:7ea05d050158
- Parent:
- 0:614bf9f43501
- Child:
- 2:77c859f607ac
File content as of revision 1:7ea05d050158:
#include "mbed.h" #include <string> #include <vector> // These are used for setting the serial buffer size and how long the mbed should wait between updates static const float SLEEP_TIME = 0.5; // x86 background process will only have updates every 1 second in ideal situations static const float PIN_DELAY = 0.05; // the time to wait for allowing the relays to fully cycle between transitions static const float POWER_UP_TIME = 5.0; // seconds for the device clicker to go from an OFF to ON state static const int NUM_CMDS = 8; // Used for signaling to the main loop if new serial data has arrived by the serial rx interrupt bool new_data; // Enumerations for the device's power state enum device_state_t { ON = 1, OFF = 2 }; // Object for linking to a computer via serial communication Serial pc(USBTX, USBRX); // Global string for storing the received serial data on the serial rx interrupt string gStr; void rx_interrupt(void) { int i = 0; // update global character array while (pc.readable() | (i<6) ) { gStr += pc.getc(); i++; wait(0.02); } new_data = 1; } void make_edge(DigitalOut& pin) { pin = !pin; wait(PIN_DELAY); pin = !pin; } void confirm_on(AnalogIn& ain) { uint16_t readings[3]; // get 5 initial readings for (int i=0; i<4; i++) { readings[i] = ain.read_u16(); wait(0.01); } for (int i=0; i<4; i++) { if (readings[i] < 60000) { confirm_on(ain); // break into recursion if past readings are not settled values } } } int main() { pc.baud(9600); // Blinking LED to show that mbed is running DigitalOut led1(LED1); // On/Off, Send DigitalOut controls[] = { p5, p25 }; // A, B, C, D, E DigitalOut selections[] = { p26, p27, p28, p29, p30 }; // Used for reading the clicker's voltage regulator output for determining if clicker is on/off AnalogIn pwr_status(p17); // Define the commands variable that holds a list of all valid serial commands std::vector<string> commands(NUM_CMDS); // Define the valid set of serial commands commands[0] = "clickerPower\n"; commands[1] = "clickerSend\n"; commands[2] = "sayHere\n"; commands[3] = "clickerA\n"; commands[4] = "clickerB\n"; commands[5] = "clickerC\n"; commands[6] = "clickerD\n"; commands[7] = "clickerE\n"; // Initialize all relays to off state for (int i=0; i<6; i++) selections[i] = 0; // get initial power readings uint16_t pwr_level = pwr_status.read_u16(); uint16_t pwr_level_new = pwr_status.read_u16(); device_state_t dev_power = ON; // initialize to an off state // variables for the main scope char current_selection = NULL; bool update_selection = false; int usr_cmd = 0; // Holding down active low Power button will put clicker in configuration mode...we don't want that controls[0] = 1; // Function to run at receiving serial data pc.attach(&rx_interrupt, Serial::RxIrq); // infinite processing loop while(1) { // pull in from globally allocated memory when interurpts are disabled __disable_irq(); pwr_level_new = pwr_status.read_u16(); if (new_data) { new_data = 0; // assign a valid command to variable for the switch case statement. If command is invalid, ignore for (int i=0; i<NUM_CMDS+1; i++) { if ( !(strcmp(gStr.c_str(), commands[i].c_str())) ) { usr_cmd = i+1; break; } } switch( usr_cmd ) { case 1: // clickerPower make_edge(controls[0]); break; case 2: // clickerSend if(current_selection) { // make_edge(controls[1]); pc.printf(" Answer submitted: %c\r\n", current_selection); current_selection = NULL; } else { pc.printf(" Must make a selection before attempting a submission\r\n"); } make_edge(controls[1]); // comment line out for final version. Used for testing purposes here break; case 3: // sayHere pc.printf(" Audio currently unsupported\r\n"); break; case 4: // clickerA current_selection = 'A'; update_selection = true; break; case 5: // clickerB current_selection = 'B'; update_selection = true; break; case 6: // clickerC current_selection = 'C'; update_selection = true; break; case 7: // clickerD current_selection = 'D'; update_selection = true; break; case 8: // clickerE current_selection = 'E'; update_selection = true; break; default: break; } } if (update_selection) { update_selection = false; if (dev_power == ON) { make_edge(selections[usr_cmd - 4]); pc.printf(" You have selected option %c\r\n", current_selection); } else { pc.printf(" Device is not on\r\n"); current_selection = NULL; } } // if clicker's voltage level has changed significantly... if ( abs(pwr_level_new - pwr_level) > 20000) { // settling time while ( abs(pwr_level_new - pwr_status.read_u16()) > 32 ) { // wait until the analog input settles to a steady state reading pwr_level_new = pwr_status.read_u16(); wait(0.1); } if (pwr_level_new < pwr_level) { // device is shutting down dev_power = OFF; } else if (pwr_level_new > pwr_level) { // device is turning on confirm_on(pwr_status); // wait for voltage levels to settle to steady value when powering up wait(POWER_UP_TIME); dev_power = ON; } // update the power level reading pwr_level = pwr_level_new; pc.printf(" Device power status updated. New status: %s\n\r", dev_power == ON ? "ON": "OFF"); } // clear all command related variables gStr.clear(); usr_cmd = 0; // turn interrupts back on before going into a sleeping state __enable_irq(); // blink that shit then be lazy led1 = !led1; wait(SLEEP_TIME); } }