Buttonbox 2013 Software

From TSG Doc
Jump to: navigation, search
/*
leonardo heeft andere pin mapping
 digitalWrite(pin, LOW); digitalWrite(pin, HIGH); -> 56 cycles
 CLR(PORTB, 0) ; SET(PORTB, 0); -> 2 cycles
 The macros used:
 #define CLR(x,y) (x&=(~(1<<y)))
 #define SET(x,y) (x|=(1<<y))
 switch dender is 1ms
 total BITSI loop takes 88 us 
 */

#include <EEPROM.h>
#include <SPI.h>
#include <digitalWriteFast.h>

#define DATAOUT 11//MOSI 
#define DATAIN  12//MISO 
#define SPICLOCK  13//Clock 

int address = 0;

// available modes
byte mode             = 1;
byte ShiftAnalogOut   = 2;
byte ShiftLED         = 3;
byte ShiftOutput      = 4;
byte ShiftAnalogIn    = 5;
//leonardo
//byte I[8] = { 6, 7, 8, 9, 20, 21, 22, 23};
//uno
//byte I[8] = { 6, 7, 8, 9, 16, 17, 18, 19};
//duemilanove
byte I[8] = { 6, 7, 8, 9, 16, 17, 18, 19};
unsigned long TimeOnSet_I[8]  = {
  0, 0, 0, 0, 0, 0, 0, 0};
boolean       Debouncing_I[8] = {
  false, false, false, false, false, false, false, false};

byte SerialInChr      = 1;
byte SerialOutChr     = 0;
byte AnalogInChr1     = 1;
byte AnalogInChr2     = 2;
byte AnalogOutChr1    = 0;
byte AnalogOutChr2    = 0;
byte TimeStamp        = 0;
byte SpeakerPin       = 14;
byte VoicekeyPin      = 15;
byte index            = 0;
byte BITSI            = 1;
byte BITSI_extend     = 2;
byte Personal         = 3;
char Detect_Function  = 'N';
byte treshold_Sound   = 1;     
byte treshold_Voice   = 25;     


unsigned long TimeoutDebounce = 2;
unsigned long TimeNow         = 0;
unsigned long TimeNow2        = 0;

unsigned int sensorValue_low_Voice = 1500;         // the sensor value
unsigned int sensorValue_high_Voice = 0;         // the sensor value
unsigned int sensorValue_high_Sound = 0;         // the sensor value
unsigned int ReadValue;

boolean Detect_Voice = false;
boolean Detect_Sound = false;
boolean Start_Tone = false;
boolean Send_An = false;
boolean Send_Marker = false;
boolean Recieve_led = false;
boolean Send_Led = false;


/* declare bit state memory booleans to find out if input values have changed since the last looptest */
boolean State_I[9]      = { 
  HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
boolean Prev_State_I[9] = { 
  HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};

void setup()
{
  Serial.begin(115200);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST); 
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  pinMode(SpeakerPin, OUTPUT);
  pinMode(VoicekeyPin, INPUT);
  pinMode(ShiftOutput, OUTPUT);
  pinMode(ShiftLED, OUTPUT);
  pinMode(ShiftAnalogIn, OUTPUT);
  InPortInputMode();
  SendOutput(255);

  //mode = EEPROM.read(address);
  ReadAndSendInput();
  if ((State_I[0] == LOW)  && (State_I[1] == HIGH) && (State_I[2] == HIGH) && (State_I[3] == HIGH) && 
      (State_I[4] == HIGH) && (State_I[5] == HIGH) && (State_I[6] == HIGH) && (State_I[7] == LOW)){
    mode = BITSI;
    EEPROM.write(address, mode);
      }
  else if ((State_I[0] == HIGH) && (State_I[1] == LOW) && (State_I[2] == HIGH) && (State_I[3] == HIGH) && 
           (State_I[4] == HIGH) && (State_I[5] == HIGH) && (State_I[6] == HIGH) && (State_I[7] == LOW)){
     mode = BITSI_extend;
     EEPROM.write(address, mode);
      }
  else{
   mode = EEPROM.read(address);
  }
  mode = BITSI;

  //########VOICE##########################################
  // callibrate the voice:
  /*if (mode == BITSI_extend) {
    Callibrate_Voice();    
    Serial.print("sensorValue_low_Voice = ");
    Serial.println( sensorValue_low_Voice );
    Serial.print("sensorValue_high_Voice = ");
    Serial.println( sensorValue_high_Voice );
  }*/
  //########SOUND##########################################
  // callibrate the Sound:
  if (mode == BITSI_extend) {
    Callibrate_Sound();
    //Serial.print("sensorValue_high_Sound = ");
    //Serial.println( sensorValue_high_Sound );
  }
  ///#######################################################

  // visual show mode to user
  for (byte i = 0; i < 1; i++) {
    SendLED(255);
    delay(500);
    SendLED(0);
    //delay(500);
  }

  if (mode == BITSI_extend) {
    tone(SpeakerPin, 956,100);//laag
    delay(200);
    tone(SpeakerPin, 1915,100);//hoog
    delay(100);
    noTone(SpeakerPin);
  }
  
  // what mode are we running?
  if (mode == BITSI) {
    Serial.begin(115200);
    Serial.println("BITSI mode, Ready!");
  }
  else if (mode == BITSI_extend) {
    Serial.begin(115200);
    Serial.println("BITSI_extend mode, Ready!");
  }
  else if (mode == Personal) {
    Serial.begin(115200);
    Serial.println("Personal mode, Ready!");
  }

}

//--- Forever Loop method -----------------------------------------------------------------------------------------------------------
void loop()
{

  //--- BITSI ------------------------------------------------------------------------------------------------------
  if (mode == BITSI){
    //TimeNow2 = micros();
    byte index = 0;

    if (Serial.available()) {
      SerialInChr = Serial.read();
      SendLED(SerialInChr);
      SendOutput(SerialInChr);
    }

    TimeNow = millis();

    ReadAndSendInput();
    //ReadValue = ReadAnalogChannel(1); 
    //Serial.println(ReadValue,DEC); 

    //TimeNow2 = micros() - TimeNow2;
    //Serial.println(TimeNow2);
  }

  //--- personal implementation ---------------------------------------------------------------------------------------------
  else if (mode == BITSI_extend) {
    
    //TEST ANALOG OUT
    //TEST BUTTONS &
    //TEST MARKER 
    //TEST SOUND KEY &
    //TEST ANALOG IN &
    //TEST LEDS
    //TEST TONE &
    
    
    //TimeNow2 = micros();
    byte index = 0;

    if (Serial.available()) {
      SerialInChr = Serial.read();
      if (char(SerialInChr) == 'R'){  
        Detect_Function = 'N';}
      else if (Detect_Function == 'N'){
        if ((char(SerialInChr) == 'M') ||  
           (char(SerialInChr) == 'Y') ||
           (char(SerialInChr) == 'Z') ||
           (char(SerialInChr) == 'C') ||
           (char(SerialInChr) == 'A') ||
           (char(SerialInChr) == 'D') ||
           (char(SerialInChr) == 'L')) {
           Detect_Function = char(SerialInChr);
        }
        else if (char(SerialInChr) == 'T') {Start_Tone = true;}
      }
      else if(Detect_Function == 'D'){
        Detect_Function = 'N';
        if (char(SerialInChr) == 'S') {Detect_Sound = true;}
        if (char(SerialInChr) == 'V') {Detect_Voice = true;}}
      else if(Detect_Function == 'M'){
        Detect_Function = 'N';
        Send_Marker = true;}
      else if(Detect_Function == 'Y'){
        Detect_Function = 'N';
        Send_An = true;
        AnalogOutChr1 = SerialInChr;}
      else if(Detect_Function == 'Z'){
        Detect_Function = 'N';
        Send_An = true;
        AnalogOutChr2 = SerialInChr;}
      else if(Detect_Function == 'C'){
        Detect_Function = 'N';
        if (SerialInChr == 'S') {Callibrate_Sound();
        //Serial.print("sensorValue_high_Sound = ");
        //Serial.println( sensorValue_high_Sound );
        }
        else if (SerialInChr == 'V') {Callibrate_Voice();}}
      else if(Detect_Function == 'A'){
        Detect_Function = 'N';
        if (char(SerialInChr) == '1') {Serial.print(ReadAnalogChannel(1));}
        else if (char(SerialInChr) == '2') {Serial.print(ReadAnalogChannel(2));}
        else if (char(SerialInChr) == '3') {Serial.print(ReadAnalogChannel(3));}
        else if (char(SerialInChr) == '4') {Serial.print(ReadAnalogChannel(4));}}
      else if(Detect_Function == 'L'){
        Detect_Function = 'N';
        if (char(SerialInChr) == 'X'){
          SendLED(0);
          Send_Led = false;
          Recieve_led = false;}
        else if (char(SerialInChr) == 'I'){
          Send_Led = false;
          Recieve_led = true;}
        else if (char(SerialInChr) == 'O'){
          Send_Led = true;
          Recieve_led = false;}
      }
      else{Detect_Function = 'N';}
    }

    TimeNow = millis();

    if (Send_Marker){
      SendOutput(SerialInChr);
      Send_Marker = false;
      if (Send_Led){
        SendLED(SerialInChr);
      }
    }
    if (Recieve_led){
      //nog implementeren!!
      // SendLED(SerialInChr);
    }
    if (Send_An){
      SendAnalog(AnalogOutChr1, AnalogOutChr2);
      Send_An = false;
    }

    if (Start_Tone){
      tone(SpeakerPin, 1915,100);//laag
      delay(100);
      noTone(SpeakerPin);
      Start_Tone = false;
    }
    
    ReadAndSendInput();
    
    if (Detect_Voice) {
      ReadValue = ReadAnalogChannel(4);
      if (ReadValue < sensorValue_low_Voice) {
        Serial.print(char(86));
        Detect_Voice = false;
      }
      if  (ReadValue > sensorValue_high_Voice) { 
        Serial.print(char(86));
        Detect_Voice = false;
      }
    } 

    if (Detect_Sound) {
      ReadValue = ReadAnalogChannel(1);
      if  (ReadValue > (sensorValue_high_Sound + treshold_Sound)) { 
        //SendOutput( 255 );
        Serial.print(char(83));
        Detect_Sound = false;
        //SendOutput( 0 );
      }
    } 
   
    //TimeNow2 = micros() - TimeNow2;
    //Serial.println(TimeNow2);
  }
}


//########SUBROUTINES##########################################

void InPortInputMode(){
  for (int pin=0; pin<8; pin++) {
    pinMode(I[pin], INPUT); // send 1
    digitalWriteFast2(I[pin], HIGH); 
  }
}

void SendOutput( byte Mark1 ) {    
  digitalWriteFast2(ShiftOutput,LOW);
  SPI.transfer(Mark1);
  digitalWriteFast2(ShiftOutput,HIGH);
}

void SendLED( byte Mark1 ) {    
  digitalWriteFast2(ShiftLED,LOW);
  SPI.transfer(Mark1);
  digitalWriteFast2(ShiftLED,HIGH);
}

void ReadAndSendInput() {     
  /* Process input bits
   *
   * The input bits are monitored for state changes. If bit 0 goes from low to high, a capital 'A' character
   * is sent back to the PC over the serial line.
   * When it changes back from high to low, a lowercase 'a' character is sent to the PC.
   * For bits 0 to 7, the characters A-H and a-h are sent respectively.
   *
   * It is possible to connect mechanical switches to each of the input, because the input bits are debounced.
   * After a bit changes state, it will be ignored for a debouncing interval of [TimeoutDebounce] miliseconds.
   */

  for (index = 0; index < 8; index = index + 1) {
    State_I[index] = digitalReadFast2(I[index]);
    /* check for bit state change = egde, but not within debouncing interval */
    if ((Prev_State_I[index] != State_I[index]) & !Debouncing_I[index]) {
      /* respond with the corresponding character */
      if (State_I[index] == HIGH) {
        Serial.print(char(97 + index));
      }
      else {
        Serial.print(char(65 + index));
      }

      /* start debouncing */
      TimeOnSet_I[index] = TimeNow;
      Debouncing_I[index] = true;

      /* save new previous bit state */
      Prev_State_I[index] = State_I[index];
    }
  }

  /* reset debouncing status for each bit if the debounce interval has elapsed */
  for (index = 0; index < 8; index = index + 1) {
    if (Debouncing_I[index] & ((TimeNow - TimeOnSet_I[index]) > TimeoutDebounce)) {
      Debouncing_I[index] = false;
    }
  }
}

void Callibrate_Voice(){
  sensorValue_low_Voice = 1500;         // the sensor value
  sensorValue_high_Voice = 0;         // the sensor value
  for (int i=0; i <= 1200; i++){
    ReadValue = ReadAnalogChannel(4);
    if (ReadValue < sensorValue_low_Voice) {
      sensorValue_low_Voice = ReadValue;
    }
    if  (ReadValue > sensorValue_high_Voice) { 
      sensorValue_high_Voice = ReadValue;
    }
  } 
  sensorValue_low_Voice = sensorValue_low_Voice - treshold_Voice;
  sensorValue_high_Voice = sensorValue_high_Voice + treshold_Voice;
}

void Callibrate_Sound(){
  sensorValue_high_Sound = 0;         // the sensor value
  ReadValue = ReadAnalogChannel(1);
  ReadValue = ReadAnalogChannel(1);
  for (int i=0; i <= 2400; i++){
    ReadValue = ReadAnalogChannel(1);
    if  (ReadValue > sensorValue_high_Sound) { 
      sensorValue_high_Sound = ReadValue;
    }
  } 
}

/*void VoiceKey() {
  ReadValue = ReadAnalogChannel(4);
  if (ReadValue > (sensorValue_high_Voice)){
    nosound = 0;
  }
  else if (ReadValue < (sensorValue_low_Voice)) {
    nosound = 0;
  } 
  else {
    nosound = nosound + 1;
  }
  if ((detect_Voice) && (nosound == 0)){
    detect_Voice = false;
    Serial.write("V");
  }
  if (nosound == 1100){
    //OutPortWrite(0);
    Serial.write("v");
    detect_Voice = true;
    //Serial.print(128,DEC);
  }
}*/

int ReadAnalogChannel(int channel){
  SPI.end();
  pinMode(DATAIN, INPUT);
  pinMode(DATAOUT, OUTPUT);
  pinMode(SPICLOCK, OUTPUT);
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);

  digitalWriteFast2(ShiftAnalogIn,LOW); //Select adc
  // setup bits to be written
  for (int i=7; i>=3; i--){
    digitalWriteFast2(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWriteFast2(SPICLOCK,HIGH);
    digitalWriteFast2(SPICLOCK,LOW);    
  }

  digitalWriteFast2(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWriteFast2(SPICLOCK,LOW);
  digitalWriteFast2(SPICLOCK,HIGH);  
  digitalWriteFast2(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
    adcvalue+=digitalReadFast2(DATAIN)<<i;
    //cycle clock
    digitalWriteFast2(SPICLOCK,HIGH);
    digitalWriteFast2(SPICLOCK,LOW);
  }
  digitalWriteFast2(ShiftAnalogIn, HIGH); //turn off device
  SPI.begin();
  //adcvalue = adcvalue >> 4;
  return adcvalue;
}
/*
int ReadAnalogChannel(int channel) {    
  //digitalWriteFast2(ShiftAnalogIn, LOW);      // select the MCP3204
  byte commandbits = B00001101;          //command bits - 0000, start, mode, chn, MSBF
  unsigned int b1 = 0;                   // get the return var's ready
  unsigned int b2 = 0;
  commandbits|=((channel-1)<<1);         // update the command bit to select either ch 1 or 2
  digitalWrite(ShiftAnalogIn, LOW);      // select the MCP3204
  SPI.transfer(commandbits);             // send out the command bits
  const int hi = SPI.transfer(b1);       // read back the result high byte
  const int lo = SPI.transfer(b2);       // then the low byte
  digitalWrite(ShiftAnalogIn, HIGH);     // let the DAC go, we'done
  b1 = lo + (hi << 8);                   // assemble the two bytes into a word
  b1 = b1 >> 4;
  return (b1);                      // We have got a 12bit answer but strip LSB's if
}
*/

void SendAnalog( byte analog1, byte analog2) {    
  digitalWriteFast2(ShiftAnalogOut,LOW);
  SPI.transfer(analog1);
  SPI.transfer(analog2);
  digitalWriteFast2(ShiftAnalogOut,HIGH);
}