/*
 * PinController.cpp
 *
 *  Created on: Jun 15, 2018
 *      Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert
 */

#include "PinController.h"
#include "utility/config.h"
#include "utility/LoggerFactory.h"

#ifndef NO_WIRING_PI
#include <wiringPi.h>
#include <mcp23017.h>
#else
#warning "Include testing wiringPi library"
#include "utility/wiringPiTesting.hpp"
#endif

namespace flippR_driver
{

std::once_flag PinController::GPIO_LIB_INITIALIZED;

PinController::PinController()
{
  CLOG(DEBUG, OUTPUT_LOGGER) << "Created PinController";
  std::call_once(GPIO_LIB_INITIALIZED, wiringPiSetup);
}

void PinController::initialize_input_pin(uint8_t address)
{
  pinMode(address, INPUT);
}

void PinController::initialize_output_pin(const uint8_t address)
{
  pinMode(address, OUTPUT);
}

void PinController::write_pin(uint8_t address, bool value)
{
  digitalWrite(address, value);
}

bool PinController::read_pin(uint8_t address)
{
  return PULLDOWN == digitalRead(address);
}

void PinController::initialize_port_expander(const uint8_t i2c_address, const uint8_t pin_base)
{
  auto initialized_port_extender = this->initialized_port_extenders.insert(std::pair<uint8_t, uint8_t>(i2c_address, pin_base));
  if(not initialized_port_extender.second)
  {
    if(initialized_port_extender.first->second != pin_base)
    {
      char hex_string[4];
      sprintf(hex_string, "%X", i2c_address);
      CLOG(WARNING, OUTPUT_LOGGER) << "Port extender with address 0x" << hex_string
                                 << " is already initialized with pin base " << int(pin_base) << ". Check config files!";
    }
    return;
  }

  mcp23017Setup(pin_base, i2c_address);
  char hex_string[4];
  sprintf(hex_string, "%X", i2c_address);
  CLOG(INFO, OUTPUT_LOGGER) << "MCP23017 initialized with i2c-address 0x" << hex_string << " and pin-base " << int(pin_base) << ".";
}

}
