#include "core/config.h"
#if CONFIG_KEYSW
#error outdated, 20/11/2020, not compatible with ACM2543, use keycontrol_ll.c instead
#include "drivers/keycontrol/keycontrol.h"
#include "core/gpio.h"
#include "core/csect.h"
#include "core/config_pins.h"

 // KeySwitch version SC3v4_UPC2163, SC3v4, v3(UPC2163), NEC
 //     PLS HEADER  (o)    (o)    (o)    (o)    (o)    (o)   |  PCB HOLE
 // __________                                  GND    VCC   |  Common Pin
 // __________      64     63     62     61                  |  LPC1758 Pin
 // __________     P0.9   P0.8   P0.7   P0.6                 |  LPC1758 port
 // __________     [1]    [2]    [3]    [4]                  |  Logic Port Desc
 // __________     PA0    PA1    PA2    PA3                  |  STM32L151CB version


 static bool KeySwitch_Init();
 static bool KeySwitch_SetKeyState( tKeySwitchState_t state );
 static bool KeySwitch_GetKeyState( tKeySwitchState_t * pstate );
 static bool KeySwitch_GetKeyCode( tKeySwitchCode_t * pcode );
 static void KeySwitch_DeInit();
 static tKeySwitchState_t keyState = KEYCONTROL_STATE_INVALID;
 static tKeySwitchCode_t  keyCode = 0;
 static bool bInitialized = false;

 typedef enum
 {
    eLLKeySw_StaticPort_1,
    eLLKeySw_StaticPort_2,
    eLLKeySw_StaticPort_3,
    eLLKeySw_StaticPort_4,
 }
 e_LLKeySwitch_StaticPorts_t;
 static void LL_KeySwitch_SetStaticPort( e_LLKeySwitch_StaticPorts_t port, bool state );

 const sKeySwitchControl_t KeySwitchHandle = 
 {
     .Init = KeySwitch_Init, 
     .SetKeyState = KeySwitch_SetKeyState,
     .GetKeyState = KeySwitch_GetKeyState,
     .GetKeyCode = KeySwitch_GetKeyCode,
     .DeInit = KeySwitch_DeInit
 };
 
 static bool KeySwitch_Init()
 {    
    DI();
    // Configure GPIO pins for KeySwitch control : PA0...PA3
    #if CONFIG_PORT__SINGLEPORTINIT
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L1|CONFIG_PIN__SWKEYPP_L2|CONFIG_PIN__SWKEYPP_L3|CONFIG_PIN__SWKEYPP_L4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L1, &GPIO_InitStruct);
    }
    #else
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L1;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L1, &GPIO_InitStruct);
    }
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L2;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L2, &GPIO_InitStruct);
    }
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L3;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L3, &GPIO_InitStruct);
    }
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L4, &GPIO_InitStruct);
    }
    #endif
    bInitialized = true;

    EI();

    if( ! KeySwitch_SetKeyState( KEYCONTROL_STATE_DEFAULT ) )
    {
        KeySwitch_DeInit();

        return false;
    }

    

    return true;
 }

 static bool KeySwitch_SetKeyState( tKeySwitchState_t state )
 {
    bool set = true;

    DI();

    if( !bInitialized )
    {
        set = false;
    }
    else
    {
        switch( state )
        {
           case KEYCONTROL_STATE_INVALID: 
                keyState = KEYCONTROL_STATE_INVALID;
           break;

           case KEYCONTROL_STATE_SHORTALL: keyCode=0x00000340;   // Short A / Short B   // 0b0000 0000 0000 0000 0000 0011 0100 0000   1101
           break;

           case KEYCONTROL_STATE_OPENALL:  keyCode=0x000003c0;   // Open A / Open B     // 0b0000 0000 0000 0000 0000 0011 1100 0000   1111
           break;

           case KEYCONTROL_STATE_LOADALL:  keyCode=0x00000080;   // Load A / Load B     // 0b0000 0000 0000 0000 0000 0000 1000 0000   0010
           break;

           case KEYCONTROL_STATE_THRUAB:   keyCode=0x000002C0;   //      Thru           // 0b0000 0000 0000 0000 0000 0010 1100 0000   1011
           break;

           case KEYCONTROL_STATE_LDASHALL: keyCode=0x00000140;   // Load A / Short B    // 0b0000 0000 0000 0000 0000 0001 0100 0000   0101
           break;

           case KEYCONTROL_STATE_LDBSHALL: keyCode=0x00000300;   // Load B / Short A    // 0b0000 0000 0000 0000 0000 0011 0000 0000   1100
           break;

           case KEYCONTROL_STATE_CHECK:    keyCode=0x00000240;   //   Thru Atten        // 0b0000 0000 0000 0000 0000 0010 0100 0000   1001
           break;

           default:
               set = false;
        }
    }

    if( set ) 
    {  
       LL_KeySwitch_SetStaticPort( eLLKeySw_StaticPort_1, (keyCode & (1ul<<6)) );
       LL_KeySwitch_SetStaticPort( eLLKeySw_StaticPort_2, (keyCode & (1ul<<7)) );
       LL_KeySwitch_SetStaticPort( eLLKeySw_StaticPort_3, (keyCode & (1ul<<8)) );
       LL_KeySwitch_SetStaticPort( eLLKeySw_StaticPort_4, (keyCode & (1ul<<9)) );       

       keyState = state;   
    }

    EI();

    return set;
 }

 static void LL_KeySwitch_SetStaticPort( e_LLKeySwitch_StaticPorts_t port, bool state )
 {   
     
     switch( port )
     {
        // LogicPort #1 = PA0
        case eLLKeySw_StaticPort_1: HAL_GPIO_WritePin( CONFIG_PORT__SWKEYPP_L1, CONFIG_PIN__SWKEYPP_L1, ((state)?GPIO_PIN_SET:GPIO_PIN_RESET) );
        break;
        // LogicPort #2 = PA1
        case eLLKeySw_StaticPort_2: HAL_GPIO_WritePin( CONFIG_PORT__SWKEYPP_L2, CONFIG_PIN__SWKEYPP_L2, ((state)?GPIO_PIN_SET:GPIO_PIN_RESET) );
        break;
        // LogicPort #3 = PA2
        case eLLKeySw_StaticPort_3: HAL_GPIO_WritePin( CONFIG_PORT__SWKEYPP_L3, CONFIG_PIN__SWKEYPP_L3, ((state)?GPIO_PIN_SET:GPIO_PIN_RESET) );
        break;
        // LogicPort #4 = PA3
        case eLLKeySw_StaticPort_4: HAL_GPIO_WritePin( CONFIG_PORT__SWKEYPP_L4, CONFIG_PIN__SWKEYPP_L4, ((state)?GPIO_PIN_SET:GPIO_PIN_RESET) );
        break;        
     }
     
 }

 static bool KeySwitch_GetKeyState( tKeySwitchState_t * pstate )
 {
    if( pstate )
    {
       DI(); 
         if( bInitialized ) 
              *pstate = keyState; 
         else
              *pstate = KEYCONTROL_STATE_INVALID;
       EI();
       return true; 
    }

    return false; 
 }

 static bool KeySwitch_GetKeyCode( tKeySwitchCode_t * pcode )
 {
    if( pcode )
    {
       __DI__ *pcode = keyCode; __EI__
       return true; 
    }

    return false; 
 }

 static void KeySwitch_DeInit()
 {
    

    DI();

    bInitialized = false;
    #if CONFIG_PORT__SINGLEPORTINIT
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    // Configure GPIO pins for KeySwitch control : PA0...PA3
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L1|CONFIG_PIN__SWKEYPP_L2|CONFIG_PIN__SWKEYPP_L3|CONFIG_PIN__SWKEYPP_L4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;    
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L1, &GPIO_InitStruct);
    }
    #else
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    // Configure GPIO pins for KeySwitch control : PA0...PA3
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;    
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L1, &GPIO_InitStruct);
    }
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    // Configure GPIO pins for KeySwitch control : PA0...PA3
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L2;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;    
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L2, &GPIO_InitStruct);
    }
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    // Configure GPIO pins for KeySwitch control : PA0...PA3
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L3;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;    
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L3, &GPIO_InitStruct);
    }
    {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    // Configure GPIO pins for KeySwitch control : PA0...PA3
    GPIO_InitStruct.Pin = CONFIG_PIN__SWKEYPP_L4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;    
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(CONFIG_PORT__SWKEYPP_L4, &GPIO_InitStruct);
    }
    #endif
    EI();
 }
#endif
