#define MESSAGE_TYPE_SIMPLE 0
#define MESSAGE_TYPE_ADVANCED 1

#define HETXPIN PINB5 // output 13 on arduino

// variables used for receiving the messages
unsigned int pulseWidth = 0;
unsigned int latchStage = 0;
signed int bitCount = 0;
byte bit = 0;
byte prevBit = 0;

// variables for storing the data received
unsigned long sender = 0;
unsigned int recipient = 0;
byte command = 0;
bool group = false;

// variables for sending messages
byte messageType;
unsigned int messageCount;

void setup(){

}

void send(unsigned int s, unsigned int r, byte c){
        // disable all interrupts
        TIMSK1 = 0;
        
        // reset variables
        messageCount = 0;
        latchStage = 0;
        bitCount = 0;
        bit = 0;
        prevBit = 0;
        pulseWidth = 10000;
        
        // set data to transmit
        sender = s;
        recipient = r;
        command = c;
        
        // specify encoding
        messageType = MESSAGE_TYPE_SIMPLE;
         
        initSend();
        
}

void initSend(){
 // ensure the transmitter pin is set for output
        DDRB |= _BV(HETXPIN);
        
        // the value that the timer will count up to before firing the interrupt
        OCR1A = (pulseWidth * 2);

        // toggle OC1A on compare match
        TCCR1A = _BV(COM1A0);

        // CTC mode: top of OCR1A, immediate update of OCR1A, TOV1 flag set on MAX
        TCCR1B |= _BV(WGM12);

        // enable timer interrupt for timer 1, disable input capture interrupt
        TIMSK1 = _BV(OCIE1A);
}

/**
 * The timer interrupt handler.
 * 
 * This is where the message is transmitted.
 * 
 * The timer interrupt is used to wait for the required length of time.  Each call of this
 * function toggles the output and determines the length of the time until the function is
 * called again.
 * 
 * Once the message has been transmitted this class will switch back to receiving.
 */
ISR(TIMER1_COMPA_vect)
{
        if(messageType == MESSAGE_TYPE_SIMPLE)
        {
                if(!prevBit && bitCount != 25)
                {
                        PORTB |= _BV(HETXPIN);
                }
                else
                {
                        PORTB &= ~_BV(HETXPIN);
                }
                
                if(bitCount % 2 == 0)
                {       // every other bit is a zero
                        bit = 0;
                }
                else if(bitCount < 8)
                {       // sender
                        bit = ((sender & _BV((bitCount - 1) / 2)) != 0);
                }
                else if(bitCount < 16)
                {       // recipient
                        bit = ((recipient & _BV((bitCount - 9) / 2)) != 0);
                }
                else if(bitCount < 24)
                {       // command
                        bit = ((command & _BV((bitCount - 17) / 2)) != 0);
                }
                
                if(bitCount == 25)
                {       // message finished
                        
                        bitCount = 0;
                        messageCount++;
                        
                        pulseWidth = 10000;
                        
                        if(messageCount == 5)
                        {       // go back to receiving
                                
                                messageCount = 0;
                                
                                TCCR1A = 0x00;
                                TCCR1B = 0x02;
                                TIMSK1 = _BV(ICIE1);
                                
                                return;
                        }
                }
                else
                {
                        if(prevBit && bit || !prevBit && !bit)
                        {
                                pulseWidth = 375;
                        }
                        else
                        {
                                pulseWidth = 1125;
                        }
                        
                        if(prevBit)
                        {
                                bitCount++;
                        }
                        
                        prevBit = !prevBit;
                }
        }

        // set the next delay
        OCR1A = (pulseWidth * 2);
}



void loop(){
  // in my test situation the sender ID=7 the receiver ID=12 the ON command=11
  send(7,12,11);
  delay(2000); // wait 2 sec
  send(7,12,7);
  delay(2000);

  
}