/***********************************************************************************************************************
* Copyright (C) All rights reserved.
***********************************************************************************************************************/

/***********************************************************************************************************************
* @file    gpio.c
* @brief   This file implements device driver for GPIO module.
* @version V1.0.0
* @date    2019/12/24
***********************************************************************************************************************/

/***********************************************************************************************************************
Includes
***********************************************************************************************************************/
#include "BAT32A239.h"
#include "gpio.h"

/***********************************************************************************************************************
Pragma directive
***********************************************************************************************************************/

/***********************************************************************************************************************
Global variables and functions
***********************************************************************************************************************/



/**
 * @brief Set specified GPIO as output function. 
 *
 * @param port port address, such as &P0, &P1, &P2...
 * @param pinMsk 
 *             e.g., bit0: 0x01, bit1: 0x02, bit0~3: 0x0F, bit0~7: 0xFF
 */
void GPIO_Output_Enable(__IO uint8_t *port, uint8_t pinMsk)
{
    *(port - 0x2A0) &= ~pinMsk;  /*!< PMC=0: Digital Function   */
    *(port + 0x020) &= ~pinMsk;  /*!< PM =0: Output Function    */
}

/**
 * @brief Set specified GPIO as input function. 
 *
 * @param port port address, such as &P0, &P1, &P2...
 * @param pinMsk 
 *             e.g., bit0: 0x01, bit1: 0x02, bit0~3: 0x0F, bit0~7: 0xFF
 */
void GPIO_Input_Enable(__IO uint8_t *port, uint8_t pinMsk)
{
    *(port - 0x2A0) &= ~pinMsk;  /*!< PMC=0: Digital Function   */
    *(port + 0x020) |=  pinMsk;  /*!< PM =1: Input Function     */
}

/**
 * @brief Enable pull up resister of input GPIO . 
 *
 * @param port port address, such as &P0, &P1, &P2...
 * @param pinMsk 
 *             e.g., bit0: 0x01, bit1: 0x02, bit0~3: 0x0F, bit0~7: 0xFF
 */
void GPIO_PullUp_Enable(__IO uint8_t *port, uint8_t pinMsk)
{
    *(port - 0x2D0) |=  pinMsk;  /*!< PU =1: Pull Up enable         */
}

/**
 * @brief Disable pull up resister of input GPIO . 
 *
 * @param port port address, such as &P0, &P1, &P2...
 * @param pinMsk 
 *             e.g., bit0: 0x01, bit1: 0x02, bit0~3: 0x0F, bit0~7: 0xFF
 */
void GPIO_PullUp_Disable(__IO uint8_t *port, uint8_t pinMsk)
{
    *(port - 0x2D0) &=  ~pinMsk;  /*!< PU =0: Pull Up disable        */
}

/**
 * @brief Nch Open Drain Output mode
 *
 * @param port address, such as &P0, &P1, &P3, &P5, &P7
 * @param pinMsk
 *             e.g., bit0: 0x01, bit1: 0x02, bit0~3: 0x0F, bit0~7: 0xFF
 */
void GPIO_Nch_OpenDrain(__IO uint8_t *port, uint8_t pinMsk)
{
    *(port - 0x2B0) |=  pinMsk;  /*!< POM =1: Nch OpenDrain Output */
}

void GPIO_Ttl_Input(__IO uint8_t *port, uint8_t pinMsk)
{
    *(port - 0x2C0) |=  pinMsk;  /*!< PIM =1: TTL input */
}

/**
 * @brief Set specified value to GPIO output
 *
 * @param port port address, such as &P0, &P1, &P2...
 * @param value 
 */
void GPIO_Set_Value(__IO uint8_t *port, uint8_t value)
{
    *port = value;           /*!< PL = value */
}

/**
 * @brief Get value from GPIO input 
 *
 * @param port port address, such as &P0, &P1, &P2...
 *
 * @return 
 */
uint8_t GPIO_Get_Value(__IO uint8_t *port)
{
    //PORT->PMS = 0x01;        /*!< Digital output level of the pin is read */ 
    return (*port);          /*!< PL = value                              */
}

/**
  * @brief  Initializes the PORTx
  * @param  PORTx: where x can be 0~14
  * @param  PINx: where x can be 0~7
  * @param  MODEx: such as INPUT,PULLUP_INPUT,TTL_INPUT,ANALOG_INPUT,OUTPUT,OPENDRAIN_OUTPUT      
	*
  * @retval None
  */
void PORT_Init(PORT_TypeDef PORTx,PIN_TypeDef PINx,PIN_ModeDef MODEx)
{
  	uint8_t mode = MODEx;
	uint8_t pos = 1<<PINx;
	
	switch(mode)
	{
		case INPUT:
			*((volatile uint8_t*)(&PORT->PMC0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PM0+PORTx)) |= pos;
			*((volatile uint8_t*)(&PORT->PIM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->POM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PU0+PORTx)) &= ~pos;
			break;
		case PULLUP_INPUT:
			*((volatile uint8_t*)(&PORT->PMC0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PM0+PORTx)) |= pos;
			*((volatile uint8_t*)(&PORT->PIM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->POM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PU0+PORTx)) |= pos;
			break;
		case TTL_INPUT:
			*((volatile uint8_t*)(&PORT->PMC0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PM0+PORTx)) |= pos;
			*((volatile uint8_t*)(&PORT->PIM0+PORTx)) |= pos;
			*((volatile uint8_t*)(&PORT->POM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PU0+PORTx)) &= ~pos;
			break;
		case ANALOG_INPUT:
			*((volatile uint8_t*)(&PORT->PMC0+PORTx)) |= pos;
			break;
		case OUTPUT:
			*((volatile uint8_t*)(&PORT->PMC0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PIM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->POM0+PORTx)) &= ~pos;
			break;
		case OPENDRAIN_OUTPUT:
			*((volatile uint8_t*)(&PORT->PMC0+PORTx)) &= ~pos;
			
			*((volatile uint8_t*)(&PORT->PM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->PIM0+PORTx)) &= ~pos;
			*((volatile uint8_t*)(&PORT->POM0+PORTx)) |= pos;
			break;
	}
}


/**
  * @brief  Set the PORTx bit
  * @param  PORTx: where x can be 0~14
  * @param  PINx: where x can be 0~7    
	*
  * @retval None
  */
void PORT_SetBit(PORT_TypeDef PORTx,PIN_TypeDef PINx)
{
	uint8_t pos = 1<<PINx;
	*((volatile uint8_t*)(&PORT->P0+PORTx)) |= pos;
}

/**
  * @brief  Clear the PORTx bit
  * @param  PORTx: where x can be 0~14
  * @param  PINx: where x can be 0~7    
	*
  * @retval None
  */
void PORT_ClrBit(PORT_TypeDef PORTx,PIN_TypeDef PINx)
{
	uint8_t pos = 1<<PINx;
	*((volatile uint8_t*)(&PORT->P0+PORTx)) &= ~pos;
}

/**
  * @brief  Toggle the PORTx bit
  * @param  PORTx: where x can be 0~14
  * @param  PINx: where x can be 0~7    
	*
  * @retval None
 **/
void PORT_ToggleBit(PORT_TypeDef PORTx,PIN_TypeDef PINx)
{
	uint8_t pos = 1<<PINx;
	*((volatile uint8_t*)(&PORT->P0+PORTx)) ^= pos;
}

/**
  * @brief  Get the PORTx bit
  * @param  PORTx: where x can be 0~14
  * @param  PINx: where x can be 0~7    
	*
  * @retval None
  */
uint8_t PORT_GetBit(PORT_TypeDef PORTx,PIN_TypeDef PINx)
{
	uint8_t pos = 1<<PINx;
	//PORT->PMS = 0x01;        /*!< Digital output level of the pin is read */
	return *((volatile uint8_t*)(&PORT->P0+PORTx))&pos;
}


void GPIO_Init(GPIO_Config_Mode_en_t enGPIOConfigMode)
{
    if (enGPIOConfigMode == GPIO_WAKEUP_MODE)
    {
        PORT_Init(CAN0_STB, OUTPUT);
        PORT_SetBit(CAN0_STB);

        PORT_Init(OBD_N_In, INPUT);
        PORT_Init(AutoStarStop_N_In, INPUT);
        
        PORT_Init(L_BD433CTRL_OUT, OUTPUT);
        PORT_SetBit(L_BD433CTRL_OUT); 

        PORT_Init(SWDIO, INPUT);

        PORT_Init(X32768_OUT, OUTPUT);
        PORT_SetBit(X32768_OUT);

        PORT_Init(X32768_IN, INPUT);
        PORT_Init(SWCLK, INPUT);

        PORT_Init(MCU_XO, OUTPUT);
        PORT_SetBit(MCU_XO);
        PORT_Init(MCU_XI, INPUT);

        PORT_Init(MCU_TOUCH_OUT, INPUT);
        PORT_SetBit(MCU_TOUCH_OUT); 

        PORT_Init(MCU_TOUCH_SCL, OUTPUT);
        PORT_SetBit(MCU_TOUCH_SCL);

        PORT_Init(MCU_TOUCH_SDA, OUTPUT);
        PORT_SetBit(MCU_TOUCH_SDA);

        PORT_Init(Backlight_P_In, INPUT);

        PORT_Init(VCC3V3_TOUCH_EN, OUTPUT);
        PORT_SetBit(VCC3V3_TOUCH_EN);

        PORT_Init(LightVehHundredsCtrl, OUTPUT);
        PORT_ClrBit(LightVehHundredsCtrl);

        PORT_Init(LightBATTCtrl, OUTPUT);
        PORT_ClrBit(LightBATTCtrl);

        PORT_Init(LightModeCtrl, OUTPUT);
        PORT_ClrBit(LightModeCtrl);

        PORT_Init(LightVehTensCtrl, OUTPUT);
        PORT_ClrBit(LightVehTensCtrl);

        PORT_Init(SEG_LED_SD, OPENDRAIN_OUTPUT);
        PORT_Init(SEG_LED_SCL, OPENDRAIN_OUTPUT);
        PORT_Init(SEG_LED_CSB, OUTPUT);

        PORT_Init(IIC_SCL_24G16 , OPENDRAIN_OUTPUT);
        PORT_SetBit(IIC_SCL_24G16);  
        PORT_Init(IIC_SDA_24G16, OPENDRAIN_OUTPUT);
        PORT_SetBit(IIC_SDA_24G16);

        PORT_Init(HighBeam_P_In, INPUT);
        PORT_Init(LeftTurn_P_In, INPUT);
        PORT_Init(TirePressure_N_In, INPUT);
        
        PORT_Init(PWM_BL, OUTPUT);
        PORT_ClrBit(PWM_BL);

        PORT_Init(OilPressure_N_In, INPUT);
        PORT_Init(RightTurn_P_In, INPUT);

        PORT_Init(VCC5V_LED_EN, OUTPUT);
        PORT_SetBit(VCC5V_LED_EN); 
        PORT_Init(VCC5V_AW39112DNR_EN, OUTPUT);
        PORT_SetBit(VCC5V_AW39112DNR_EN); 

        PORT_Init(RevSpeed_In, INPUT);

       // PORT_Init(IIC2_SCL_LDR , OPENDRAIN_OUTPUT);
       // PORT_SetBit(IIC2_SCL_LDR);  
       // PORT_Init(IIC2_SDA_LDR , OPENDRAIN_OUTPUT);
       // PORT_SetBit(IIC2_SDA_LDR);

        PORT_Init(SEG_LCD_SD1, OUTPUT);
        PORT_Init(SEG_LCD_SCL1, OUTPUT);
        PORT_Init(SEG_LCD_CSB1, OUTPUT);
        PORT_Init(SEG_LCD_SD, OUTPUT);
        PORT_Init(SEG_LCD_SCL, OUTPUT);
        PORT_Init(SEG_LCD_CSB, OUTPUT);

        PORT_Init(Fuel_Vcc_en, OUTPUT);
        PORT_ClrBit(Fuel_Vcc_en);
        PORT_Init(Fuel1_In, INPUT);
        PORT_Init(Fuel_Vref_In, INPUT);

        PORT_Init(CHECK_KL15ad_In, ANALOG_INPUT);
        PORT_Init(CHECK_KL30_In, INPUT);
        PORT_Init(CHECK_KL15_In, INPUT);	

        PORT_Init(AVREFP_In, INPUT);
        PORT_Init(AVREFM_In, INPUT);

        PORT_Init(CAN0_RX, INPUT);
        PORT_Init(CAN0_TX, OUTPUT);
        PORT_SetBit(CAN0_TX); 

        PORT_Init(ABS_N_In, INPUT);

        PORT_Init(TLight_OUT, OUTPUT);
        PORT_ClrBit(TLight_OUT);

				
        PORT->PIOR0  =  0x00; /*外围IO重定向寄存器0*/
        PORT->PIOR1  =  0x00; /*外围IO重定向寄存器1*/
        PORT->PIOR2  =  0x00; /*外围IO重定向寄存器2*/
        PORT->PIOR3  =  0x00; /*外围IO重定向寄存器3*/
    }
    else
    {
        PORT_Init(CAN0_STB      , OUTPUT);
        PORT_SetBit(CAN0_STB);  
        
        PORT_Init(OBD_N_In, INPUT);
        PORT_Init(AutoStarStop_N_In, INPUT);
        
        PORT_Init(L_BD433CTRL_OUT, OUTPUT);
        PORT_ClrBit(L_BD433CTRL_OUT); 

        PORT_Init(SWDIO, INPUT);

        PORT_Init(X32768_OUT, INPUT);
        PORT_Init(X32768_IN, INPUT);

        PORT_Init(SWCLK, INPUT);

        PORT_Init(MCU_XO, INPUT);
        PORT_Init(MCU_XI, INPUT);
        
        PORT_Init(MCU_TOUCH_OUT, INPUT);
        //PORT_SetBit(MCU_TOUCH_OUT); 

        PORT_Init(MCU_TOUCH_SCL, OUTPUT);
        PORT_SetBit(MCU_TOUCH_SCL);

        PORT_Init(MCU_TOUCH_SDA, OUTPUT);
        PORT_SetBit(MCU_TOUCH_SDA);

        PORT_Init(Backlight_P_In, INPUT);

        PORT_Init(VCC3V3_TOUCH_EN, OUTPUT);
        PORT_ClrBit(VCC3V3_TOUCH_EN);

        PORT_Init(LightVehHundredsCtrl, OUTPUT);
        PORT_ClrBit(LightVehHundredsCtrl);

        PORT_Init(LightBATTCtrl, OUTPUT);
        PORT_ClrBit(LightBATTCtrl);

        PORT_Init(LightModeCtrl, OUTPUT);
        PORT_ClrBit(LightModeCtrl);

        PORT_Init(LightVehTensCtrl, OUTPUT);
        PORT_ClrBit(LightVehTensCtrl);

        PORT_Init(SEG_LED_SD, OPENDRAIN_OUTPUT);
        PORT_ClrBit(SEG_LED_SD);
        PORT_Init(SEG_LED_SCL, OPENDRAIN_OUTPUT);
        PORT_ClrBit(SEG_LED_SCL);
        PORT_Init(SEG_LED_CSB, OUTPUT);
        PORT_ClrBit(SEG_LED_CSB);

        PORT_Init(IIC_SCL_24G16 , OPENDRAIN_OUTPUT);
        PORT_SetBit(IIC_SCL_24G16);  
        PORT_Init(IIC_SDA_24G16 , OPENDRAIN_OUTPUT);
        PORT_SetBit(IIC_SDA_24G16);

        PORT_Init(HighBeam_P_In, INPUT);
        PORT_Init(LeftTurn_P_In   , INPUT);
        PORT_Init(TirePressure_N_In, INPUT);

        PORT_Init(PWM_BL        , OUTPUT);
        PORT_ClrBit(PWM_BL);

        PORT_Init(OilPressure_N_In, INPUT);
        PORT_Init(RightTurn_P_In  , INPUT);

        PORT_Init(VCC5V_LED_EN, OUTPUT);
        PORT_ClrBit(VCC5V_LED_EN); 
        PORT_Init(VCC5V_AW39112DNR_EN, OUTPUT);
        PORT_ClrBit(VCC5V_AW39112DNR_EN); 

        PORT_Init(RevSpeed_In, INPUT);

        PORT_Init(SEG_LCD_SD1, OUTPUT);
        PORT_ClrBit(SEG_LCD_SD1);
        PORT_Init(SEG_LCD_SCL1, OUTPUT);
        PORT_ClrBit(SEG_LCD_SCL1);
        PORT_Init(SEG_LCD_CSB1, OUTPUT);
        PORT_ClrBit(SEG_LCD_CSB1);
        PORT_Init(SEG_LCD_SD, OUTPUT);
        PORT_ClrBit(SEG_LCD_SD);
        PORT_Init(SEG_LCD_SCL, OUTPUT);
        PORT_ClrBit(SEG_LCD_SCL);
        PORT_Init(SEG_LCD_CSB, OUTPUT);
        PORT_ClrBit(SEG_LCD_CSB);

        PORT_Init(IIC2_SCL_LDR , OPENDRAIN_OUTPUT);
        PORT_SetBit(IIC2_SCL_LDR);  
        PORT_Init(IIC2_SDA_LDR , OPENDRAIN_OUTPUT);
        PORT_SetBit(IIC2_SDA_LDR);

        PORT_Init(Fuel_Vcc_en   , OUTPUT);
        PORT_ClrBit(Fuel_Vcc_en);
        PORT_Init(Fuel1_In      , ANALOG_INPUT);
        PORT_Init(Fuel_Vref_In  , ANALOG_INPUT);

        PORT_Init(CHECK_KL15ad_In, ANALOG_INPUT);
        PORT_Init(CHECK_KL30_In , ANALOG_INPUT);
        PORT_Init(CHECK_KL15_In , INPUT);

        PORT_Init(AVREFP_In     , ANALOG_INPUT);
        PORT_Init(AVREFM_In     , ANALOG_INPUT);

        PORT_Init(CAN0_RX       , INPUT);
        PORT_Init(CAN0_TX, OUTPUT);
        PORT_ClrBit(CAN0_TX); 

        PORT_Init(ABS_N_In, INPUT);

        PORT_Init(TLight_OUT, OUTPUT);
        PORT_ClrBit(TLight_OUT);

				
        PORT->PIOR0  =  0x00; /*外围IO重定向寄存器0*/
        PORT->PIOR1  =  0x00; /*外围IO重定向寄存器1*/
        PORT->PIOR2  =  0x00; /*外围IO重定向寄存器2*/
        PORT->PIOR3  =  0x00; /*外围IO重定向寄存器3*/        
    }
}



