/*
  Copyright (c) 2011 Arduino.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "Arduino.h"
#include "pins_arduino.h"
#include "mik32_hal_gpio.h"

#ifdef __cplusplus
extern "C" {
#endif

// initialization
void pinMode(uint32_t PinNumber, uint32_t PinMode)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  // if pin number is greater than pin list size - return
  if ((PinNumber>=pinCommonQty()))
  {
    ErrorMsgHandler("pinMode(): pin number exceeds the total number of pins");
    return;
  }

  if (digitalPinHasPWM(PinNumber))
    // if the pin can use PWM, disable PWM
    analogWriteStop(PinNumber);

  // determine the port and the pin number in the port
  GPIO_TypeDef *GPIO_addr = digitalPinToPort(PinNumber);
  GPIO_InitStruct.Pin     = digitalPinToBitMask(PinNumber);

  // set up direction and pull up/down
  switch (PinMode)
  {
    case INPUT: 
      GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT;
      GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
      break;
    case INPUT_PULLUP:
      GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT;
      GPIO_InitStruct.Pull = HAL_GPIO_PULL_UP;
      break;
    case OUTPUT:
      GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT;
      GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
      break;
  }

  // init pin
  HAL_GPIO_Init(GPIO_addr, &GPIO_InitStruct);
  additionalPinsInit(PinNumber);
}

// write pin
void digitalWrite(uint32_t PinNumber, uint32_t Val)
{
  if ((PinNumber>=pinCommonQty()))
  {
    ErrorMsgHandler("digitalWrite(): pin number exceeds the total number of pins");
    return;
  }

  if (digitalPinHasPWM(PinNumber))
    // if the pin can use PWM, disable PWM
    analogWriteStop(PinNumber);

  HAL_GPIO_WritePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber), (Val == HIGH) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
}

// read pin
int digitalRead(uint32_t PinNumber)
{ 
  if ((PinNumber>=pinCommonQty()))
  {
    ErrorMsgHandler("digitalRead(): pin number exceeds the total number of pins");
    return -1;
  }
  if (digitalPinHasPWM(PinNumber))
    // if the pin can use PWM, disable PWM
    analogWriteStop(PinNumber);

  GPIO_PinState pinState = HAL_GPIO_ReadPin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber));
  return (pinState == GPIO_PIN_LOW) ? LOW : HIGH;
}

// toggle pin
void digitalToggle(uint32_t PinNumber)
{
  if ((PinNumber>=pinCommonQty()))
  {
    ErrorMsgHandler("digitalToggle(): pin number exceeds the total number of pins");
    return;
  }
  if (digitalPinHasPWM(PinNumber))
    // if the pin can use PWM, disable PWM
    analogWriteStop(PinNumber);
    
  HAL_GPIO_TogglePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber));
}

#ifdef __cplusplus
}
#endif
