library for controlling tv remote with gestures

Dependencies:   HCSR04 SI1143 command mbed-rtos mbed

Revision:
0:35878487eafe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Dec 08 03:10:08 2015 +0000
@@ -0,0 +1,221 @@
+#define DIST_MAX 40 // Maximum distance in cm, anything above is ignored.
+// Threshold for up/down commands.
+// If higher, command is "up". If lower, "down".
+#define DIST_THRES 20
+
+#include "mbed.h"
+#include "rtos.h"
+#include "hcsr04.h"
+#include "SI1143.h"
+#include "command.h"
+
+Serial pc(USBTX, USBRX); // tx, rx
+HCSR04 usensor(p7, p6);
+SI1143 sensor(p28, p27);
+
+DigitalOut l1(LED1);
+DigitalOut l2(LED2);
+DigitalOut l3(LED3);
+DigitalOut l4(LED4);
+
+int value;
+
+unsigned int dist;
+int sense1, sense2, sense3;
+
+const float period = 1.0;
+const float power_execute_count = 3.0 / period;
+float power_count = 0;
+Mutex led_mut;
+Mutex ir_mut;
+
+bool flag = false;
+
+const int num_commands = 5;
+enum COMMANDS {
+  POWER_COM,
+  CHANNEL_UP,
+  CHANNEL_DOWN,
+  VOLUME_UP,
+  VOLUME_DOWN,
+  NONE,
+};
+const string com_names[num_commands] = {"power", "channel up", "channel down",
+                                        "volume up", "volume down"};
+
+Command coms[num_commands];
+
+Ticker power_ticker;
+enum MODE {
+  NO_MODE = 0,
+  CHANNEL = 1,
+  POWER = 2,
+  VOLUME = 3,
+
+};
+
+enum DIRECTION {
+    NO_DIR,
+    UP,
+    DOWN,
+};
+DIRECTION dir = NO_DIR;
+MODE mode = NO_MODE;
+
+void set_led(uint8_t led_vals) {
+  led_mut.lock();
+  l1 = led_vals & 1;
+  led_vals = led_vals >> 1;
+  l2 = led_vals & 1;
+  led_vals = led_vals >> 1;
+  l3 = led_vals & 1;
+  led_vals = led_vals >> 1;
+  l4 = led_vals & 1;
+  led_mut.unlock();
+}
+
+void ExecutePowerCommand() {
+  ir_mut.lock();
+  coms[POWER_COM].TransmitCommand();
+  ir_mut.unlock();
+  mode = NO_MODE;
+}
+
+void CheckForPower() {
+  if (mode == POWER) {
+    if (power_count == power_execute_count) {
+      ExecutePowerCommand();
+    }
+    ++power_count;
+  } else {
+    power_count = 0;
+    set_led(0);
+  }
+}
+
+int handleDist(int dist) {
+  if (dist > DIST_THRES) {
+    return 1;
+  } else {
+    return -1;
+  }
+}
+
+void parallax_thread(void const *args) {
+  int sen = 50;
+  while (true) {
+    sense1 = sensor.get_ps1(1);
+    sense2 = sensor.get_ps2(1);
+    sense3 = sensor.get_ps3(1);
+
+
+    if (sense1 > sen || sense2 > sen || sense3 > sen) {
+      if (sense1 > sense2 && sense1 > sense3) {
+        set_led(1);
+        mode = CHANNEL;
+      }
+
+      else if (sense2 > sense1 && sense2 > sense3) {
+        mode = POWER;
+        set_led(3);
+      }
+
+      else if (sense3 > sense1 && sense3 > sense2) {
+        set_led(2);
+        mode = VOLUME;
+      }
+    } else {
+        if( mode == POWER) {
+            mode = NO_MODE;
+        }
+    }
+    Thread::wait(300);
+  }
+}
+
+void ultrasound_thread(void const *args) {
+  while (true) {
+    usensor.start();
+    dist = usensor.get_dist_cm();
+    if (dist < DIST_MAX) {
+      int d = 500; // first delay is longer for single volume change
+
+      while (dist < DIST_MAX) {
+        value = handleDist(dist); // is up or down?
+        // doIR(CONTROL_VOL, value); // fire off IR signal
+        if (value == 1) {
+          set_led(8);
+          dir = UP;
+          Thread::wait(100);
+          set_led(0);
+        } else {
+          set_led(4);
+          dir = DOWN;
+          Thread::wait(100);
+          set_led(0);
+        }
+        usensor.start();
+        Thread::wait(d);              // wait
+        dist = usensor.get_dist_cm(); // check for hand again
+        d = 100; // delays are shorter for quick multiple volume adjustment
+      }
+      // this stops accidental channel change after volume adjustment
+      Thread::wait(500);
+    } else {
+        dir = NO_DIR;
+    }
+    Thread::wait(50); // Short enough to detect all swipes.
+  }
+}
+
+void transmit_thread(const void* args) {
+    while(true) {
+        COMMANDS com = NONE;
+        if(mode == VOLUME && dir == UP) {
+            com = VOLUME_UP;
+        } else if(mode == VOLUME && dir == DOWN) {
+            com = VOLUME_DOWN;
+        } else if(mode == CHANNEL && dir == UP) {
+            com = CHANNEL_UP;
+        } else if(mode == CHANNEL && dir == DOWN) {
+            com = CHANNEL_DOWN;
+        } else {
+            com = NONE;
+        }
+        if(com != NONE) {
+            ir_mut.lock();
+            coms[com].TransmitCommand();
+            ir_mut.unlock();
+        }
+        Thread::wait(10);
+    }
+}
+
+void setup(void) {
+  // Serial.begin(9600);
+  // device.baud(2400);
+  pc.printf("Ready to decode IR!\r\n");
+
+  for( int i = 0; i < num_commands; ++i) {
+    coms[i] = Command(com_names[i]);
+    coms[i].LearnCommand(pc);
+  }
+  // Setup the baseline
+  sensor.bias(1, 5);
+  wait(1);
+}
+
+int main() {
+
+  setup();
+  power_ticker.attach(&CheckForPower, period);
+  set_led(0);
+
+  Thread mode_checker(parallax_thread);
+  Thread range_checker(ultrasound_thread);
+  Thread transmit_checker(transmit_thread);
+
+  while (1) {
+    // spin.
+  }
+}