/*
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  version 2 as published by the Free Software Foundation.
//  
//  DESCRIPTION
//  This sketch provides a way to control blinds from www.blinds.com using a 433MHz RF
//  signal. The motors in the blinds are Dooya DV24CE motors. 
// 
//  The sketch is based on Henrik Ekblad's <henrik.ekblad@gmail.com> MySensors project 
//  (https://github.com/mysensors/).  Credit also goes to Ray (http://rayshobby.net/?p=3381) 
//  for instruction on how to decode the RF signal from the remote as well as code for
//  sending the RF signal.
//  Developed by Pete Brutsch.
//  
//  REVISION HISTORY
//  Version 1.0 - March 19, 2014
// 
*/


//Include Vera related libraries
#include <MySensor.h>
#include <SPI.h>
#include <EEPROM.h>  
#include <RF24.h>

//Define Constants
//#define SEND_DATA 3 //Data pin for RF Transmitter
//#define ZERO_HIGH 376 //Delay for the high part of a 0 in microseconds
//#define ZERO_LOW 653 //Delay for the low part of a 0 in microseconds
//#define ONE_HIGH 713 //Delay for the high part of a 1 in microseconds
//#define ONE_LOW 317 //Delay for the low part of a 1 in microseconds

//New Timing
#define SEND_DATA 3 //Data pin for RF Transmitter
#define ZERO_HIGH 270 //Delay for the high part of a 0 in microseconds
#define ZERO_LOW 950 //Delay for the low part of a 0 in microseconds
#define ONE_HIGH 910 //Delay for the high part of a 1 in microseconds
#define ONE_LOW 300//Delay for the low part of a 1 in microseconds

//Vera related constants
#define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define NUMBER_OF_RELAYS 1 // Total number of attached relays
#define RELAY_ON 1  // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
// Set RADIO_ID to something unique in your sensor network (1-254)
// or set to AUTO if you want gw to assign a RADIO_ID for you.
#define RADIO_ID AUTO

/*
//NUMBER_OF_CHANNELS is used for the blinds channel. Enter the number of channels you are 
//using on your remote. If you are only using 2 of 5 channels enter 2.  Note: this code
//will start with channel 1 and increment up.  If you have different channels (ie 1 & 4)
//you will need to modify the code
*/
#define NUMBER_OF_CHANNELS  1  

MySensor gw;
// gw(9,10);

/*
//These 28 standard bits appear at the beginning of each transmit sequence: 
//0111011100000101010111001011.  They are then followed by 12 other 
//0111 0111 0000 0101 0101 1100 1011
//bits depending on the command being sent to the blind.  I don't have
//two remotes but I think these bits distinguish between the different
//remotes.  
//Because I'm not good at Arduino coding I needed to use someone else's
//code to send the bits.  They only used 8 bits and I couldn't get any 
//more to send.  Because if this I have broken up the 28 bits into 8 bit
//sections.  make sure to put 4 zeros at the beginning of the first
//sequence.  They will be ignored later in the code.
*/

unsigned char standardBits1 = 0b00001101; //integer value of the 28 bit standard sequence referenced above. "0b" prefix is for *******
unsigned char standardBits2 = 0b01011101;
unsigned char standardBits3 = 0b01000000;
unsigned char standardBits4 = 0b00000000;

//1 ON
//1101 0101 1101 0100 0000 00110
//1101 0101 1101 0100 0000 00110
//
//1 OFF  
//1101 0101 1101 0100 0000 11000
//1101 0101 1101 0100 0000 11000

int hey = 14;

void setup() {
   
  Serial.begin(BAUD_RATE);  // Used to write debug info

  gw.begin(incomingMessage, hey, true);
  gw.sendSketchInfo("Relay", "1.0");
  // Register sensors to gw (they will be created as child devices)
  for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
    // Register all sensors to gw (they will be created as child devices)
    gw.present(sensor, S_LIGHT);
    // Then set relay pins in output mode
    pinMode(pin, OUTPUT);   
    // Set relay to last known state (using eeprom storage) 
    digitalWrite(pin, gw.loadState(sensor)?RELAY_ON:RELAY_OFF);
  }
}

void loop() {
gw.process();
}
void incomingMessage(const MyMessage &message) {
  // We only expect one type of message from controller. But we better check anyway.
  if (message.type==V_LIGHT) {
     // Change relay state
     digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
     // Store state in eeprom
     gw.saveState(message.sensor, message.getBool());
     // Write some debug info
     Serial.print("Incoming change for sensor:");
     Serial.print(message.sensor);
     Serial.print(", New status: ");
     Serial.println(message.getBool());
     
       //  int incomingBlindData = atoi(message.data);
      
    if (message.getBool()==true){ //Stop
        blindAction(message.sensor, 1); //blindAction(channel, action) action: 1=up, 2=down, 3=stop
        Serial.println("on command");
    }
    else {//100 = Open/Up
       blindAction(message.sensor, 2);
       Serial.println("off command"); 
    }
//    else if (incomingBlindData == 0 || message.header.type==V_DOWN) { //0 = Closed/Down
//       blindAction(message.header.childId,2); 
//       Serial.println("DOWN command");
//    }
    
    
   } 
}

void fourBits(unsigned char bits){

  unsigned char i;
  int delayTime;

  for(i=0;i<4;i++) {
    int highTime;
    int lowTime;
    delayTime = ((bits>>(3-i)) & 1 ? 1 : 0); 
    
    if (delayTime == 1){
      highTime = ONE_HIGH;
      lowTime = ONE_LOW;
    }
    else {
      highTime = ZERO_HIGH;
      lowTime = ZERO_LOW;
    }
      digitalWrite(SEND_DATA, HIGH);
      delayMicroseconds(highTime);
      digitalWrite(SEND_DATA, LOW);    
      delayMicroseconds(lowTime);
  }

}

void eightBits(unsigned char bits){
    unsigned char k;
    int delayTime;
    for(k=0;k<8;k++) {
      int highTime;
      int lowTime;
      delayTime = ((bits>>(7-k)) & 1 ? 1 : 0); 
    
      if (delayTime == 1){
        highTime = ONE_HIGH;
        lowTime = ONE_LOW;
      }
      else {
        highTime = ZERO_HIGH;
        lowTime = ZERO_LOW;
      }
        digitalWrite(SEND_DATA, HIGH);
        delayMicroseconds(highTime);
        digitalWrite(SEND_DATA, LOW);    
        delayMicroseconds(lowTime);
    }
}


//Separator Delay Method (this is repeated frequently)
void separatorDelay(boolean upDown) {
  if(upDown == true){
    digitalWrite(SEND_DATA, LOW);
    delayMicroseconds(8020);
  }
  digitalWrite(SEND_DATA, HIGH);
  delayMicroseconds(4812);
  digitalWrite(SEND_DATA, LOW);
  delayMicroseconds(1479); 
  
}

void endDelay(){
  digitalWrite(SEND_DATA, LOW);
  delayMicroseconds(51895); //Time of delay at the end of each sequence
}



void blindAction(int c, bool a){
  //c or channel: Order on the remote from left to right 1-16 available
  //a or action: 1=up, 2=down, 3=stop

  char channel = (char)c;   
  unsigned char action;  //8 action bits.  Only the first 4 bits are used in the up/down end sequence
  unsigned char action2; //Last 4 bits from the up/down end sequence

  if(a==true){
    action = 0b11010101; //code for up
    action2 = 0b00000011;
  }
//  else if (a==false){
//    action = 0b11010101;
//    action2 = 0b00001100;
//  }
  else {
   action = 0b11010101;
    action2 = 0b00001100;
  }

  int i=0;

  //first 6 transmissions are the same for each blind action (up, down & stop)
  while(i<6){
    separatorDelay(false); //false unless in the last part of the up or down commands
    fourBits(standardBits1);
    eightBits(standardBits2);
    eightBits(standardBits3);
    eightBits(standardBits4);  
    fourBits(channel);
    eightBits(action);
    i++;
  }

  
  if (a==3){ //If a stop command is issued just send the end delay then exit the method
    endDelay();
  }
  else{//No stop issued so run through the last sequence
    separatorDelay(false); //send true because we are in the up/down end sequence so there is an additional delay
    fourBits(standardBits1);
    eightBits(standardBits2);
    eightBits(standardBits3);
    eightBits(standardBits4);  
    fourBits(channel);
    fourBits(action);
    fourBits(action2);
    
    int j=0;
    while(j<3){
      separatorDelay(true);
      fourBits(standardBits1);
      eightBits(standardBits2);
      eightBits(standardBits3);
      eightBits(standardBits4);  
      fourBits(channel);
      fourBits(action);
      fourBits(action2); 
      j++;
    }
    endDelay();
  }
}

