#include "MBPeripherals.h"

void defaultExtIntIsr(void){}

MBPeripherals::MBPeripherals(const BoardConfig &boardConfig, void (*extIntIsr)(void)): _boardConfig(boardConfig), _NRF(boardConfig.NRFCe, boardConfig.NRFCs)
{
  if(!extIntIsr)
    _extIntIsr = &(defaultExtIntIsr); //We provide a default ISR
}

uint8_t MBPeripherals::init()
{
  uint8_t toReturn(0);
  //We initialize needed IOs :
  pinMode(_boardConfig.ExternalInt, INPUT);
  pinMode(_boardConfig.LDOEnable, OUTPUT);
  _3V3PowerRail(OFF);
  pinMode(_boardConfig.SwitchVSensEnable, INPUT_PULLUP);
  pinMode(_boardConfig.BattVSensEnable, OUTPUT);
  digitalWrite(_boardConfig.BattVSensEnable, LOW);
  
  //Unused pins are set as inputs with internal pullup enabled 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(A4,INPUT_PULLUP);
  pinMode(A5,INPUT_PULLUP);
  pinMode(A6,INPUT_PULLUP);
  pinMode(A7,INPUT_PULLUP);

  //We check that every external devices are responding
  _3V3PowerRail(ON);
  toReturn |= _NRF.begin();
  _3V3PowerRail(OFF);

  attachInterrupt(digitalPinToInterrupt(_boardConfig.ExternalInt), _extIntIsr, FALLING);

  return toReturn;
}

uint8_t MBPeripherals::initExternalPeripherals(void)
{
  uint8_t toReturn(0);
  
  toReturn |= _NRF.begin();
  
  return toReturn;
}

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

void MBPeripherals::_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 &MBPeripherals::getRadio(void){return _NRF;}

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

MAILBOX_EVENT_e MBPeripherals::readMailboxEvent(void)
{
  pinMode(_boardConfig.SwitchVSensEnable, OUTPUT);
  digitalWrite(_boardConfig.SwitchVSensEnable, HIGH);
  int analogValue = analogRead(_boardConfig.SwitchAnalogVSens);
  digitalWrite(_boardConfig.SwitchVSensEnable, LOW);
  pinMode(_boardConfig.SwitchVSensEnable, INPUT_PULLUP);

  if(analogValue < 526)
    return MAILBOX_EVENT_e::MAILBOX_LETTER;
  else if(analogValue >= 526 && analogValue < 711)
    return MAILBOX_EVENT_e::MAILBOX_PACKAGE;
  else if(analogValue >= 711 && analogValue < 1000)
    return MAILBOX_EVENT_e::MAILBOX_COLLECTED;
  else return MAILBOX_EVENT_e::MAILBOX_UNKNOWN;
}

void MBPeripherals::maskExtInt(void)
{
  detachInterrupt(digitalPinToInterrupt(_boardConfig.ExternalInt));
}

void MBPeripherals::unmaskExtInt(void)
{
  attachInterrupt(digitalPinToInterrupt(_boardConfig.ExternalInt), _extIntIsr, FALLING);
}
