/*
* Copyright (c) 2017 Texas Instruments Incorporated
*
* All rights reserved not granted herein.
* Limited License.
*
* Texas Instruments Incorporated grants a world-wide, royalty-free,
* non-exclusive license under copyrights and patents it now or hereafter
* owns or controls to make, have made, use, import, offer to sell and sell ("Utilize")
* this software subject to the terms herein.  With respect to the foregoing patent
* license, such license is granted  solely to the extent that any such patent is necessary
* to Utilize the software alone.  The patent license shall not apply to any combinations which
* include this software, other than combinations with devices manufactured by or for TI ("TI Devices").
* No hardware patent is licensed hereunder.
*
* Redistributions must preserve existing copyright notices and reproduce this license (including the
* above copyright notice and the disclaimer and (if applicable) source code license limitations below)
* in the documentation and/or other materials provided with the distribution
*
* Redistribution and use in binary form, without modification, are permitted provided that the following
* conditions are met:
*
*             * No reverse engineering, decompilation, or disassembly of this software is permitted with respect to any
*               software provided in binary form.
*             * any redistribution and use are licensed by TI for use only with TI Devices.
*             * Nothing shall obligate TI to provide you with source code for the software licensed and provided to you in object code.
*
* If software source code is provided to you, modification and redistribution of the source code are permitted
* provided that the following conditions are met:
*
*   * any redistribution and use of the source code, including any resulting derivative works, are licensed by
*     TI for use only with TI Devices.
*   * any redistribution and use of any object code compiled from the source code and any resulting derivative
*     works, are licensed by TI for use only with TI Devices.
*
* Neither the name of Texas Instruments Incorporated nor the names of its suppliers may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* DISCLAIMER.
*
* THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*******************************************************************************
 *
 * This file contains GPIO functions for the IWR1443 side demo executable.
 * GPIOs 0, 1 and 2 are mapped on the IR1443 as follows, but they are not
 * connected, which means they require a 0 Ohm resister added to the board.
 *
 *   GPIO 0: AR pin = N4,  EVM Header pin = J6.15  <- needs resistor R164
 *   GPIO 1: AR pin = N7,  EVM Header pin = J5.8   <- needs resistor R9
 *   GPIO 2: AR pin = N13, EVM Header pin = J5.18  <- needs resistor R8
 *
 *******************************************************************************/
/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>

#include <ti/drivers/pinmux/pinmux.h>

/* Demo Includes */
#include "iwr_gpio.h"


/* Globals */


//This function sets the direction of the selected GPIO.
//   port - 0 = GIO A, 1 = GIO B
//   pin  - 0..7
//   dir  - 0 = input, 1 = output
void gpio_set_direction(uint16_t port, uint16_t pin, uint16_t dir)
{
  volatile uint32_t *reg1;
  volatile uint32_t *reg2;
  uint32_t  mask;
  uint32_t  temp;

  if (port == GPIO_A)
  {
    reg1 = (uint32_t *)GPIO_GIODIR_REG; //direction register
    if (dir == GPIO_INPUT)
      reg2 = (uint32_t *)GPIO_GIOPULDIS_REG; //pull disable register (for input)
    else
      reg2 = (uint32_t *)GPIO_GIOPDR_REG; //open drain register (for output)
  }
  else
  {
    reg1 = (uint32_t *)(GPIO_GIODIR_REG + GPIO_GIOB_OFFSET);
    if (dir == GPIO_INPUT)
      reg2 = (uint32_t *)(GPIO_GIOPULDIS_REG + GPIO_GIOB_OFFSET);
    else
      reg2 = (uint32_t *)(GPIO_GIOPDR_REG + GPIO_GIOB_OFFSET);
  }

  mask = 1 << pin;
  temp = *reg1;

  if (dir == GPIO_INPUT)
  {
   *reg2 = temp | mask; //set the corresponding bit to disable pull
    mask = ~mask;
   *reg1 = temp & mask; //clear the bit to set input mode
  }
  else //output
  {
   *reg1 = temp | mask; //set the bit to set output mode
//    mask = ~mask;
//   *reg2 = temp & mask; //clear the corresponding bit for normal GPIO mode
  }
}


//This function reads the selected GPIO. The return value is 1 (logic high)
//or 0 (logic low) for the pin.
//   port - 0 = GIO A, 1 = GIO B
//   pin  - 0..7
uint8_t gpio_read(uint16_t port, uint16_t pin)
{
  volatile uint32_t *reg;
  uint32_t  mask;
  uint32_t  temp;

  if (port == GPIO_A)
    reg = (uint32_t *)GPIO_GIODIN_REG;
  else
    reg = (uint32_t *)(GPIO_GIODIN_REG + GPIO_GIOB_OFFSET);

  mask = 1 << pin;
  temp = *reg & mask;

  return (temp >> pin);
}


//This function writes the selected GPIO.
//   port - 0 = GIO A, 1 = GIO B
//   pin  - 0..7
//   value- 0 or 1
void gpio_write(uint16_t port, uint16_t pin, uint8_t value)
{
  volatile uint32_t *reg;
  uint32_t  mask;

  if (port == GPIO_A)
  {
    if (value)
      reg = (uint32_t *)GPIO_GIODSET_REG;
    else
      reg = (uint32_t *)GPIO_GIODCLR_REG;
  }
  else
  {
    if (value)
      reg = (uint32_t *)(GPIO_GIODSET_REG + GPIO_GIOB_OFFSET);
    else
      reg = (uint32_t *)(GPIO_GIODCLR_REG + GPIO_GIOB_OFFSET);
  }

  mask = 1 << pin;
 *reg = mask;
}


//Turn LED DS3 On (IWR1443 EVM)
void gpio_led_on(void)
{
  gpio_write(0, 2, 1);
}


//Turn LED DS3 Off (IWR1443 EVM)
void gpio_led_off(void)
{
  gpio_write(0, 2, 0);
}


#if 0 //only needed if test BSS has taken control
void gpio_shutdown(void)
{
  volatile uint32_t *reg;

  //Put the GIO module into reset
  reg = (uint32_t *)GPIO_GIOGCR0_REG;
 *reg = 0;
}
#endif


/* GIO initialization steps from the TRM:
 * 1) Release Peripheral Reset by setting PENA bit in Clock Control Register (0xFFFFFFD0)
 * 2) Enable clock to GIO through PCR (Check device datasheet for the peripheral select)
 * 3) Bring GIO out of reset by writing 1 to GIOGCR0.
 *
 * Then, for an input GPIO:
 *   . Clear corresponding bits in GIODIR to 0.
 *   . Enable pull?
 *     . No:  Set corresponding bits in GIOPULDIS to 1
 *     . Yes: Clear corresponding bits in GIOPULDIS to 0
 *   . Pull up/down?
 *     . Down: Clear corresponding bits in GIOPSL to 0
 *     . Up:   Set corresponding bits in GIOPSL to 1
 *   . Read value from GIODIN
 *
 * Else, for an output GPIO:
 *   . Set corresponding bits in GIODIR to 1
 *   . Open drain?
 *     . No:  Set corresponding bits in GIOPDR to 1
 *     . Yes: Clear corresponding bits in GIOPDR to 0
 *   . Output 1 or 0?
 *     . 1: Write 1 to corresponding bits in GIODSET
 *     . 0: Write 1 to corresponding bits in GIODCLR
 */
void gpio_init(void)
{
  //GPIO module init has been moved to setGpio0atReset() (reset function)

  //Prepare the user LED (DS3) for use
  gpio_set_direction(GPIO_A, 2, GPIO_OUTPUT);
}


//This function is only needed if testing with BSS firmware that uses GPIO.
//It performs the functionality now in setGpio0atReset.
void gpio_reinit(void)
{
  volatile uint32_t *reg;

  //Bring the GIO module out of reset
  reg = (uint32_t *)GPIO_GIOGCR0_REG;
 *reg = 1;

  //Configure AR_GPIO_0/PIN N4 (J6.15) for communication with MSP432
  gpio_set_direction(GPIO_A, 4, GPIO_INPUT);

  /* Setup Pinmux for GPIO 0 (J6.15) */
  Pinmux_Set_OverrideCtrl(SOC_XWR14XX_PINN4_PADAB, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
  Pinmux_Set_FuncSel(SOC_XWR14XX_PINN4_PADAB, SOC_XWR14XX_PINN4_PADAB_GPIO_0);

  gpio_init();
}
