Hacking into the iClicker2 for adding remote access abilities. http://www.amazon.com/I-Clicker-2-I-CLICKER/dp/1429280476

Dependencies:   mbed

Committer:
jjones646
Date:
Mon Dec 08 20:31:02 2014 +0000
Revision:
1:7ea05d050158
Parent:
0:614bf9f43501
Child:
2:77c859f607ac
new

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jjones646 0:614bf9f43501 1 #include "mbed.h"
jjones646 0:614bf9f43501 2 #include <string>
jjones646 0:614bf9f43501 3 #include <vector>
jjones646 0:614bf9f43501 4
jjones646 0:614bf9f43501 5 // These are used for setting the serial buffer size and how long the mbed should wait between updates
jjones646 0:614bf9f43501 6 static const float SLEEP_TIME = 0.5; // x86 background process will only have updates every 1 second in ideal situations
jjones646 0:614bf9f43501 7 static const float PIN_DELAY = 0.05; // the time to wait for allowing the relays to fully cycle between transitions
jjones646 0:614bf9f43501 8 static const float POWER_UP_TIME = 5.0; // seconds for the device clicker to go from an OFF to ON state
jjones646 0:614bf9f43501 9 static const int NUM_CMDS = 8;
jjones646 1:7ea05d050158 10
jjones646 1:7ea05d050158 11 // Used for signaling to the main loop if new serial data has arrived by the serial rx interrupt
jjones646 0:614bf9f43501 12 bool new_data;
jjones646 0:614bf9f43501 13
jjones646 0:614bf9f43501 14 // Enumerations for the device's power state
jjones646 0:614bf9f43501 15 enum device_state_t {
jjones646 0:614bf9f43501 16 ON = 1,
jjones646 0:614bf9f43501 17 OFF = 2
jjones646 0:614bf9f43501 18 };
jjones646 0:614bf9f43501 19
jjones646 0:614bf9f43501 20 // Object for linking to a computer via serial communication
jjones646 0:614bf9f43501 21 Serial pc(USBTX, USBRX);
jjones646 0:614bf9f43501 22
jjones646 0:614bf9f43501 23 // Global string for storing the received serial data on the serial rx interrupt
jjones646 0:614bf9f43501 24 string gStr;
jjones646 0:614bf9f43501 25
jjones646 0:614bf9f43501 26
jjones646 0:614bf9f43501 27 void rx_interrupt(void)
jjones646 0:614bf9f43501 28 {
jjones646 0:614bf9f43501 29 int i = 0;
jjones646 0:614bf9f43501 30
jjones646 0:614bf9f43501 31 // update global character array
jjones646 0:614bf9f43501 32 while (pc.readable() | (i<6) ) {
jjones646 0:614bf9f43501 33 gStr += pc.getc();
jjones646 1:7ea05d050158 34 i++;
jjones646 1:7ea05d050158 35 wait(0.02);
jjones646 0:614bf9f43501 36 }
jjones646 1:7ea05d050158 37
jjones646 1:7ea05d050158 38 new_data = 1;
jjones646 0:614bf9f43501 39 }
jjones646 0:614bf9f43501 40
jjones646 0:614bf9f43501 41
jjones646 0:614bf9f43501 42 void make_edge(DigitalOut& pin)
jjones646 0:614bf9f43501 43 {
jjones646 0:614bf9f43501 44 pin = !pin;
jjones646 0:614bf9f43501 45 wait(PIN_DELAY);
jjones646 0:614bf9f43501 46 pin = !pin;
jjones646 0:614bf9f43501 47 }
jjones646 0:614bf9f43501 48
jjones646 0:614bf9f43501 49
jjones646 1:7ea05d050158 50 void confirm_on(AnalogIn& ain)
jjones646 1:7ea05d050158 51 {
jjones646 0:614bf9f43501 52 uint16_t readings[3];
jjones646 1:7ea05d050158 53
jjones646 0:614bf9f43501 54 // get 5 initial readings
jjones646 1:7ea05d050158 55 for (int i=0; i<4; i++) {
jjones646 0:614bf9f43501 56 readings[i] = ain.read_u16();
jjones646 0:614bf9f43501 57 wait(0.01);
jjones646 0:614bf9f43501 58 }
jjones646 1:7ea05d050158 59
jjones646 1:7ea05d050158 60 for (int i=0; i<4; i++) {
jjones646 1:7ea05d050158 61 if (readings[i] < 60000) {
jjones646 1:7ea05d050158 62 confirm_on(ain); // break into recursion if past readings are not settled values
jjones646 1:7ea05d050158 63 }
jjones646 0:614bf9f43501 64 }
jjones646 0:614bf9f43501 65 }
jjones646 0:614bf9f43501 66
jjones646 0:614bf9f43501 67
jjones646 0:614bf9f43501 68 int main()
jjones646 0:614bf9f43501 69 {
jjones646 1:7ea05d050158 70 pc.baud(9600);
jjones646 1:7ea05d050158 71
jjones646 0:614bf9f43501 72 // Blinking LED to show that mbed is running
jjones646 0:614bf9f43501 73 DigitalOut led1(LED1);
jjones646 0:614bf9f43501 74
jjones646 1:7ea05d050158 75 // On/Off, Send
jjones646 1:7ea05d050158 76 DigitalOut controls[] = { p5, p25 };
jjones646 0:614bf9f43501 77
jjones646 0:614bf9f43501 78 // A, B, C, D, E
jjones646 1:7ea05d050158 79 DigitalOut selections[] = { p26, p27, p28, p29, p30 };
jjones646 1:7ea05d050158 80
jjones646 1:7ea05d050158 81 // Used for reading the clicker's voltage regulator output for determining if clicker is on/off
jjones646 1:7ea05d050158 82 AnalogIn pwr_status(p17);
jjones646 1:7ea05d050158 83
jjones646 1:7ea05d050158 84 // Define the commands variable that holds a list of all valid serial commands
jjones646 1:7ea05d050158 85 std::vector<string> commands(NUM_CMDS);
jjones646 1:7ea05d050158 86
jjones646 1:7ea05d050158 87 // Define the valid set of serial commands
jjones646 0:614bf9f43501 88 commands[0] = "clickerPower\n";
jjones646 1:7ea05d050158 89 commands[1] = "clickerSend\n";
jjones646 1:7ea05d050158 90 commands[2] = "sayHere\n";
jjones646 1:7ea05d050158 91 commands[3] = "clickerA\n";
jjones646 1:7ea05d050158 92 commands[4] = "clickerB\n";
jjones646 1:7ea05d050158 93 commands[5] = "clickerC\n";
jjones646 1:7ea05d050158 94 commands[6] = "clickerD\n";
jjones646 1:7ea05d050158 95 commands[7] = "clickerE\n";
jjones646 1:7ea05d050158 96
jjones646 1:7ea05d050158 97 // Initialize all relays to off state
jjones646 1:7ea05d050158 98 for (int i=0; i<6; i++)
jjones646 1:7ea05d050158 99 selections[i] = 0;
jjones646 1:7ea05d050158 100
jjones646 1:7ea05d050158 101 // get initial power readings
jjones646 1:7ea05d050158 102 uint16_t pwr_level = pwr_status.read_u16();
jjones646 1:7ea05d050158 103 uint16_t pwr_level_new = pwr_status.read_u16();
jjones646 1:7ea05d050158 104
jjones646 0:614bf9f43501 105 device_state_t dev_power = ON; // initialize to an off state
jjones646 1:7ea05d050158 106
jjones646 1:7ea05d050158 107 // variables for the main scope
jjones646 0:614bf9f43501 108 char current_selection = NULL;
jjones646 0:614bf9f43501 109 bool update_selection = false;
jjones646 1:7ea05d050158 110 int usr_cmd = 0;
jjones646 1:7ea05d050158 111
jjones646 1:7ea05d050158 112 // Holding down active low Power button will put clicker in configuration mode...we don't want that
jjones646 1:7ea05d050158 113 controls[0] = 1;
jjones646 1:7ea05d050158 114
jjones646 1:7ea05d050158 115 // Function to run at receiving serial data
jjones646 0:614bf9f43501 116 pc.attach(&rx_interrupt, Serial::RxIrq);
jjones646 1:7ea05d050158 117
jjones646 0:614bf9f43501 118 // infinite processing loop
jjones646 0:614bf9f43501 119 while(1) {
jjones646 0:614bf9f43501 120
jjones646 0:614bf9f43501 121 // pull in from globally allocated memory when interurpts are disabled
jjones646 0:614bf9f43501 122 __disable_irq();
jjones646 1:7ea05d050158 123
jjones646 1:7ea05d050158 124 pwr_level_new = pwr_status.read_u16();
jjones646 0:614bf9f43501 125
jjones646 1:7ea05d050158 126 if (new_data) {
jjones646 1:7ea05d050158 127 new_data = 0;
jjones646 0:614bf9f43501 128
jjones646 1:7ea05d050158 129 // assign a valid command to variable for the switch case statement. If command is invalid, ignore
jjones646 1:7ea05d050158 130 for (int i=0; i<NUM_CMDS+1; i++) {
jjones646 1:7ea05d050158 131 if ( !(strcmp(gStr.c_str(), commands[i].c_str())) ) {
jjones646 1:7ea05d050158 132 usr_cmd = i+1;
jjones646 1:7ea05d050158 133 break;
jjones646 1:7ea05d050158 134 }
jjones646 0:614bf9f43501 135 }
jjones646 0:614bf9f43501 136
jjones646 1:7ea05d050158 137 switch( usr_cmd ) {
jjones646 1:7ea05d050158 138 case 1: // clickerPower
jjones646 1:7ea05d050158 139 make_edge(controls[0]);
jjones646 1:7ea05d050158 140 break;
jjones646 1:7ea05d050158 141
jjones646 1:7ea05d050158 142 case 2: // clickerSend
jjones646 1:7ea05d050158 143 if(current_selection) {
jjones646 1:7ea05d050158 144 // make_edge(controls[1]);
jjones646 1:7ea05d050158 145 pc.printf(" Answer submitted: %c\r\n", current_selection);
jjones646 1:7ea05d050158 146 current_selection = NULL;
jjones646 0:614bf9f43501 147 } else {
jjones646 1:7ea05d050158 148 pc.printf(" Must make a selection before attempting a submission\r\n");
jjones646 0:614bf9f43501 149 }
jjones646 1:7ea05d050158 150 make_edge(controls[1]); // comment line out for final version. Used for testing purposes here
jjones646 1:7ea05d050158 151 break;
jjones646 1:7ea05d050158 152
jjones646 1:7ea05d050158 153 case 3: // sayHere
jjones646 1:7ea05d050158 154 pc.printf(" Audio currently unsupported\r\n");
jjones646 1:7ea05d050158 155 break;
jjones646 1:7ea05d050158 156
jjones646 1:7ea05d050158 157 case 4: // clickerA
jjones646 1:7ea05d050158 158 current_selection = 'A';
jjones646 1:7ea05d050158 159 update_selection = true;
jjones646 1:7ea05d050158 160 break;
jjones646 1:7ea05d050158 161
jjones646 1:7ea05d050158 162 case 5: // clickerB
jjones646 1:7ea05d050158 163 current_selection = 'B';
jjones646 1:7ea05d050158 164 update_selection = true;
jjones646 1:7ea05d050158 165 break;
jjones646 1:7ea05d050158 166
jjones646 1:7ea05d050158 167 case 6: // clickerC
jjones646 1:7ea05d050158 168 current_selection = 'C';
jjones646 1:7ea05d050158 169 update_selection = true;
jjones646 1:7ea05d050158 170 break;
jjones646 1:7ea05d050158 171
jjones646 1:7ea05d050158 172 case 7: // clickerD
jjones646 1:7ea05d050158 173 current_selection = 'D';
jjones646 1:7ea05d050158 174 update_selection = true;
jjones646 1:7ea05d050158 175 break;
jjones646 1:7ea05d050158 176
jjones646 1:7ea05d050158 177 case 8: // clickerE
jjones646 1:7ea05d050158 178 current_selection = 'E';
jjones646 1:7ea05d050158 179 update_selection = true;
jjones646 1:7ea05d050158 180 break;
jjones646 1:7ea05d050158 181
jjones646 1:7ea05d050158 182 default:
jjones646 1:7ea05d050158 183 break;
jjones646 1:7ea05d050158 184 }
jjones646 0:614bf9f43501 185 }
jjones646 1:7ea05d050158 186
jjones646 1:7ea05d050158 187
jjones646 1:7ea05d050158 188 if (update_selection) {
jjones646 1:7ea05d050158 189
jjones646 1:7ea05d050158 190 update_selection = false;
jjones646 1:7ea05d050158 191
jjones646 1:7ea05d050158 192 if (dev_power == ON) {
jjones646 1:7ea05d050158 193 make_edge(selections[usr_cmd - 4]);
jjones646 1:7ea05d050158 194 pc.printf(" You have selected option %c\r\n", current_selection);
jjones646 1:7ea05d050158 195
jjones646 1:7ea05d050158 196 } else {
jjones646 1:7ea05d050158 197 pc.printf(" Device is not on\r\n");
jjones646 1:7ea05d050158 198 current_selection = NULL;
jjones646 1:7ea05d050158 199 }
jjones646 1:7ea05d050158 200 }
jjones646 1:7ea05d050158 201
jjones646 1:7ea05d050158 202 // if clicker's voltage level has changed significantly...
jjones646 1:7ea05d050158 203 if ( abs(pwr_level_new - pwr_level) > 20000) {
jjones646 0:614bf9f43501 204
jjones646 1:7ea05d050158 205 // settling time
jjones646 1:7ea05d050158 206 while ( abs(pwr_level_new - pwr_status.read_u16()) > 32 ) {
jjones646 1:7ea05d050158 207 // wait until the analog input settles to a steady state reading
jjones646 1:7ea05d050158 208 pwr_level_new = pwr_status.read_u16();
jjones646 1:7ea05d050158 209 wait(0.1);
jjones646 1:7ea05d050158 210 }
jjones646 1:7ea05d050158 211
jjones646 1:7ea05d050158 212 if (pwr_level_new < pwr_level) { // device is shutting down
jjones646 1:7ea05d050158 213 dev_power = OFF;
jjones646 1:7ea05d050158 214
jjones646 1:7ea05d050158 215 } else if (pwr_level_new > pwr_level) { // device is turning on
jjones646 1:7ea05d050158 216 confirm_on(pwr_status); // wait for voltage levels to settle to steady value when powering up
jjones646 1:7ea05d050158 217 wait(POWER_UP_TIME);
jjones646 1:7ea05d050158 218 dev_power = ON;
jjones646 1:7ea05d050158 219 }
jjones646 1:7ea05d050158 220
jjones646 1:7ea05d050158 221 // update the power level reading
jjones646 1:7ea05d050158 222 pwr_level = pwr_level_new;
jjones646 1:7ea05d050158 223 pc.printf(" Device power status updated. New status: %s\n\r", dev_power == ON ? "ON": "OFF");
jjones646 1:7ea05d050158 224 }
jjones646 1:7ea05d050158 225
jjones646 1:7ea05d050158 226
jjones646 1:7ea05d050158 227 // clear all command related variables
jjones646 1:7ea05d050158 228 gStr.clear();
jjones646 1:7ea05d050158 229 usr_cmd = 0;
jjones646 1:7ea05d050158 230
jjones646 0:614bf9f43501 231 // turn interrupts back on before going into a sleeping state
jjones646 0:614bf9f43501 232 __enable_irq();
jjones646 0:614bf9f43501 233
jjones646 0:614bf9f43501 234 // blink that shit then be lazy
jjones646 0:614bf9f43501 235 led1 = !led1;
jjones646 0:614bf9f43501 236 wait(SLEEP_TIME);
jjones646 0:614bf9f43501 237 }
jjones646 0:614bf9f43501 238 }