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

Dependencies:   mbed

Committer:
sjsm3
Date:
Tue Dec 09 13:43:26 2014 +0000
Revision:
2:77c859f607ac
Parent:
1:7ea05d050158
added speaker functionality

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