#include "WSPeripherals.h"

WSPeripherals::WSPeripherals(const BoardConfig &boardConfig): _boardConfig(boardConfig), _HTU21(HTU21D_RES_RH12_TEMP14), _NRF(boardConfig.NRFCe, boardConfig.NRFCs)
{}

uint8_t WSPeripherals::init()
{
  uint8_t toReturn(0);
  //We initialize used pins :
  pinMode(_boardConfig.LDOEnable, OUTPUT);
  _3V3PowerRail(OFF);
  pinMode(_boardConfig.LDRVSensEnable, OUTPUT);
  digitalWrite(_boardConfig.LDRVSensEnable, HIGH); //High means that it is disabled and low is active /!\/
  pinMode(_boardConfig.BATVSensEnable, OUTPUT);
  digitalWrite(_boardConfig.BATVSensEnable, LOW);
  
  //Unused pins are set as inputs with internal pullup inable to reduce power consumption during sleep
  pinMode(0,INPUT_PULLUP);
  //pinMode(1,INPUT_PULLUP); TX pin for serial
  pinMode(6,INPUT_PULLUP);
  pinMode(7,INPUT_PULLUP);
  pinMode(8,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
  pinMode(11,INPUT_PULLUP);
  pinMode(12,INPUT_PULLUP);
  pinMode(A2,INPUT_PULLUP);
  pinMode(A3,INPUT_PULLUP);
  pinMode(A6,INPUT_PULLUP);
  pinMode(A7,INPUT_PULLUP);

  //We check that every external devices are responding
  _3V3PowerRail(ON);
  toReturn |= _BMP280.begin(0x76);
  toReturn |= _HTU21.begin() << 1;
  toReturn |= _NRF.begin() << 2;
  _3V3PowerRail(OFF);
  return toReturn;
}

uint8_t WSPeripherals::initExternalPeripherals()
{
  uint8_t toReturn(0);
  
  toReturn |= _BMP280.begin(0x76);
  toReturn |= _HTU21.begin() << 1;
  toReturn |= _NRF.begin() << 2;

  //We disable the I2C internal pullups :
  digitalWrite(SDA, LOW);
  digitalWrite(SCL, LOW);
  
  return toReturn;
}

float WSPeripherals::batteryVoltage()
{
  //We close the voltage divider bridge and we do the measurement
  digitalWrite(_boardConfig.BATVSensEnable, HIGH);
  int rawBatteryValue = analogRead(_boardConfig.BATAnalogVSens);
  digitalWrite(_boardConfig.BATVSensEnable, LOW);
  
  return float(rawBatteryValue) * ADC_QUANTUM * VOLTAGE_DIV_COEFF; 
}

int WSPeripherals::sunlightMeasurement()
{
  //We enable the voltage divider bridge and we do the measurement
  digitalWrite(_boardConfig.LDRVSensEnable, LOW);
  int rawSunlightMeasurement = analogRead(_boardConfig.LDRAnalogVSens);
  digitalWrite(_boardConfig.LDRVSensEnable, HIGH);
  
  return rawSunlightMeasurement;
}

void WSPeripherals::temperatureAndATMPressureFromBMP280(float *temperature, float *ATMPressure)
{
  if(!temperature && !ATMPressure)return;
  
  _BMP280.setSampling( Adafruit_BMP280::MODE_FORCED,
                        Adafruit_BMP280::SAMPLING_X16,
                        Adafruit_BMP280::SAMPLING_X16,
                        Adafruit_BMP280::FILTER_X16,
                        Adafruit_BMP280::STANDBY_MS_4000);
  if(temperature)
    *temperature = _BMP280.readTemperature();
  
  if(ATMPressure)
    *ATMPressure = _BMP280.readPressure();
}

float WSPeripherals::temperatureFromHTU21()
{
  return _HTU21.readTemperature();
}

float WSPeripherals::humidity()
{
  return _HTU21.readHumidity();
}

float WSPeripherals::compensatedHumidity()
{
  return _HTU21.readCompensatedHumidity();
}

void WSPeripherals::_3V3PowerRail(State state)
{
  digitalWrite(_boardConfig.LDOEnable, state);
  if(state) //We let some time for the voltage to stabilize on the rail. 
    delay(10);
}

const RF24 &WSPeripherals::getRadio(){return _NRF;}

void WSPeripherals::applyRadioConfig(uint8_t channel, uint8_t paLevel, rf24_datarate_e datarate)
{
  _NRF.setChannel(channel);
  _NRF.setPALevel(paLevel);
  _NRF.setDataRate(datarate);
}
