library for controlling tv remote with gestures

Dependencies:   HCSR04 SI1143 command mbed-rtos mbed

main.cpp

Committer:
cardenb
Date:
2015-12-08
Revision:
0:35878487eafe

File content as of revision 0:35878487eafe:

#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.
  }
}