/**
  ******************************************************************************
  * Tranceiver Project
  ******************************************************************************
  * This project works as a 433MHz tranceiver between a Raspberry Pi and a 
  * 433MHz tranceiver module. Target to run on a slower low power STM32L-CPU
  * System clock is 32MHz
  *
  * SysTick-counter is setup to handle the LED-flashing
  * The systick int is 1mS and it calles the LED-Handler
  * 
  * TIM2 is set to sample the Rx-input in a 10uS period. TIM2_IRQHandler()
  * HW is set to 32 prescaler + 10 counter period
  * 
  * TIM3 handles the micros() function by counting a 1mS variable.
  * HW is set to 32 prescaler + 1000 counter period
  *
  * The USART1 is used for comm to R-Pi. Also handled with interrupts.
  *
  * IO-Pins:
  * PA1	Output ENABLE
  * PA2	Output TX_ENABLE
  * PA3	Output TX_DATA
  * PB3	Input  RX_DATA
  * PB6	Output LED_BLUE
  * PB7	Output LED_GREEN
  *
  ******************************************************************************
*/

#include <stdio.h>
#include "sw_fifo.h"
#include "app.h"
#include "main.h"
#include "queue.h"
#include "led_blink.h"
#include "nexa.h"
#include "temp1.h"
#include "temp2.h"
#include "oregon.h"
#include "transmit.h"
#include "stm32l1xx_hal.h"
#include "stm32l1xx_hal_gpio.h"



volatile unsigned long width;


boolean disableRx = true;

void setup() {
  
  disableRx = true;
  
  digitalWrite(enablePin, LOW);
  digitalWrite(txEnablePin, LOW);
  digitalWrite(txPin, LOW); 
  
  // ------------------ INIT THE TRANCEIVER -------------------------
  // From powerdown mode (pin 4-5-6 low), 
  // 1. Drive high pin 6 (ENABLE)
  // 2. After 20us drive high pin 5 (RX/TX)200us, hold on 40us 
  // 3. Drive down 20us pin 6 (ENABLE).  
  digitalWrite(enablePin, HIGH); delayMicroseconds( 20 ); 
  digitalWrite(txEnablePin, HIGH); delayMicroseconds( 200 ); digitalWrite(txEnablePin, LOW);
  delayMicroseconds( 40 ); 
  digitalWrite(enablePin, LOW); delayMicroseconds( 20 ); digitalWrite(enablePin, HIGH);  
  delayMicroseconds( 200 );
  // ------------------ INIT THE TRANCEIVER -------------------------  
  
  rcvInitQueue();
  
  disableRx = false;
}


/*
//button = (int)HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
    
    digitalWrite(enablePin, blue);    
    //HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,(GPIO_PinState)blue); //blue);
*/

// Debug
__IO unsigned long long data[11] = {0,0,0,0,0,0,0,0,0,0,0};
__IO int data_cnt=0;

//********************************************************************
//                           LOOP
//
// Test-code: <NT1B5C1D83>
//********************************************************************
#define SER_RX_MODE_WAIT 0
#define SER_RX_MODE_RCV 1
#define SER_RX_MODE_END 2

void loop() {
  
  static int rxMode = SER_RX_MODE_WAIT;
  static int rxNum = 0;
  static unsigned char rxChars[20];
  
  static unsigned long last_rx_time = 0;
  
  static unsigned char txDataReady = 0;
  
  static unsigned long previous_x_data = 0;
  static unsigned long old_time=0;
  
  static unsigned long previous_temp1_x_data = 0;
  static unsigned long temp1_old_time=0;  
  
  static char hex[100];
  
  static boolean firstRun = true;

  static unsigned int width;
  
  //static OregonDecoderV2 orscV2;
  //static OregonDecoderV3 orscV3;
  
  static unsigned long previous_now = 0; // Get the current time
  unsigned long now = millis(); // Get the current time
  
  // Check millis() for wrapping (after 49 days)
  if( previous_now > now ) {
    last_rx_time = 0; // Reset last rx time    
  }
  
  // Display version information 5 sec after startup
  if( firstRun == true && now > 5000 ) {
    printf("\n\r433MHz STM32L Receiver module. Ver: 140111 08:02\n\r");  // **** VERSION ****
    firstRun = false;
  }
  
  if( rcvDeQueue(&width) ) {
    
    // Oregon V3
    
    
    // ********** TEMP1 ***********
    if( nextPulseTemp1(width) ) {
        
          last_rx_time = now;            // Set last rx time to now
        
          if( temp1_x_data != previous_temp1_x_data || now > (temp1_old_time+1000) ) {
              sprintf(hex,"<TR%08lX>",temp1_x_data);
              printf(hex);
              previous_temp1_x_data = temp1_x_data;
              blinkTheLED();
          }
          
          temp1_old_time = now;
          temp1ResetDecoder();
      }
    
      // ********** TEMP2 ***********
      if( nextPulseTemp2(width) ) {
        
          last_rx_time = now;            // Set last rx time to now
          sprintf(hex,"<Tr%016llX>",temp2_x_data);
          printf(hex);
          blinkTheLED();
          
          temp2ResetDecoder();
      }    
    
      // ***************** NEXA *********************
      if( nextPulseNexa(width) ) {
        
          last_rx_time = now;            // Set last rx time to now
        
          if( x_data != previous_x_data || now > (old_time+1000) ) {
              sprintf(hex,"<NR%08lX>\n\r",x_data);
              printf(hex);
              previous_x_data = x_data;
          }
          
          old_time = now;
          resetDecoder();
          blinkTheLED();
      }
  }
  
  // Serial receive of the available buffer, only if we are not waiting to transmit something
  if( serialAvailable() > 0 && txDataReady == 0 ) {
    
    unsigned char c = serialRead();
    
    // Reset if we receive an '%'
    if( rxMode == SER_RX_MODE_WAIT && c == '%' ) {
      HAL_NVIC_SystemReset();
    }
    
    switch( rxMode ) {
      
      case SER_RX_MODE_WAIT:
        if( c == '<' ) {
          rxMode = SER_RX_MODE_RCV;
          rxNum = 0;
        }
      break;
      
      case SER_RX_MODE_RCV:
        if( (c >= '0' && c<= '9') || (c >= 'A' && c<= 'Z') ) {
          rxChars[rxNum++] = c;
          if( rxNum == 1 && rxChars[0] != 'N' ) {
            rxMode = SER_RX_MODE_WAIT;
            rxNum = 0;
          }
          else if( rxNum == 2 && rxChars[1] != 'T' ) {
            rxMode = SER_RX_MODE_WAIT;
            rxNum = 0;
          }
          else if( rxNum == 10 ) {
            rxMode = SER_RX_MODE_END;
          }
        }
        else {
          rxMode = SER_RX_MODE_WAIT;
          rxNum = 0;
        }       
        break;
        
      case SER_RX_MODE_END:
        if( c == '>' ) {
          rxChars[rxNum] = '\0'; 
          txDataReady = 1;        // Flag that we have something to transmit
        }
        rxMode = SER_RX_MODE_WAIT;
        rxNum = 0;
        break;
    }
  }
  
  if( txDataReady == 1 && (now > (last_rx_time+100)) ) { // Transmit if it has passed more than 50mS since last rx
    txDataReady = 0;
    blinkTheTxLED();
    sendNexaCodeStr(rxChars);
  }
  
  previous_now = now;  // Store to check for wrapping of millis()
}



// ********************* ARCHIVE **********************
/*
void loop() {
  
  __IO int button;
  static unsigned int width;
  static unsigned long last_rx_time = 0;
  static unsigned long old_time=0;
  static unsigned long previous_x_data = 0;
  static unsigned char txDataReady = 0;
  static unsigned long txData = 0;
  static unsigned long previous_now = 0; // Get the current time
  unsigned long now = millis();
  
  // Check millis() for wrapping (after 49 days)
  if( previous_now > now ) {
    last_rx_time = 0; // Reset last rx time    
  }
    
  
  // NEXA RX Loop
  if( rcvDeQueue(&width) ) {
    
      // ***************** TEMP1 *********************
      if( nextPulseTemp1(width) ) {
        
          static unsigned long long previous_temp1_x_data = 0;
          
          
          //if( previous_temp1_x_data != temp1_x_data ) {
          
           temp1_x_data = (temp1_x_data & 0x0FFF); // Just keep the temperature
            
            if( data_cnt<10 ) {
              data[data_cnt] = temp1_x_data;
              data_cnt++;
            }
            else {
              data_cnt=0;
            }
            blinkTheLED();

          //}
          previous_temp1_x_data = temp1_x_data;
          temp1ResetDecoder();
      }
    
      // ***************** NEXA *********************
      if( nextPulseNexa(width) ) {
        
          last_rx_time = now;            // Set last rx time to now
        
          if( x_data != previous_x_data || now > (old_time+1000) ) {
              previous_x_data = x_data;
              
              // We have received a nexa code.

          }
          
          old_time = now;
          resetDecoder();
          blinkTheLED();
      }
  }
  
  if( txDataReady == 1 && (now > (last_rx_time+100)) ) { // Transmit if it has passed more than 50mS since last rx
    txDataReady = 0;
    sendNexaCode(txData);
  }
  
  previous_now = now;  // Store to check for wrapping of millis()
}
*/
/*  
  button = (int)HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
  if( button == 1 ) {
    sendNexaCode(708298896UL);
  }
*/


/*              
              volatile NEXA_QUEUE_DATA qd;
              
              
                qd.remote_id = (x_data & 0xFFFFFFC0) >>6;
                qd.group     = (x_data & 0x00000020) >>5;
                qd.onOff     = (x_data & 0x00000010) >>4;
                qd.channel   = (x_data & 0x0000000C) >>2;
                qd.button    = (x_data & 0x00000003);
                
                if( qd.remote_id == 11067170 &&         // This is the id of the white newer 8-button Nexa remote
                    qd.group == 0 &&
                    qd.channel == 0 &&
                    qd.button == 0 ) {
                      
                      // We got the trigger code ! Yohoo 
                      // Now resend the same code (with one higher button value)
                      qd.button++;
                      
                      //qd.remote_id -= 120;
                      
                      txData  = ((qd.remote_id << 6) & 0xFFFFFFC0 );
                      txData |= ((qd.group     << 5) & 0x00000020 );
                      txData |= ((qd.onOff     << 4) & 0x00000010 );
                      txData |= ((qd.channel   << 2) & 0x0000000C );
                      txData |= ((qd.button        ) & 0x00000003 );
                      
                      txDataReady = 1;        // Flag that we have something to transmit
                }
*/