#include "MatrixKey.h"
#include "main.h"

// EDB7 xx EDB7
uint8_t const KeyTable[16] = {
    0xEE, 0xDE, 0xBE, 0x7E,
    0xED, 0xDD, 0xBD, 0x7D,
    0xEB, 0xDB, 0xBB, 0x7B,
    0xE7, 0xD7, 0xB7, 0x77,
};

void LineIn_RowOut(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Pin = KeyRow_Pin | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(KeyRow_GPIO_Port, &GPIO_InitStruct);

    /*Configure GPIO pins : PCPin PC1 PC2 PC3 */
    GPIO_InitStruct.Pin = KeyLine_Pin | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KeyLine_GPIO_Port, &GPIO_InitStruct);
}

void LineOut_RowIn(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Pin = KeyLine_Pin | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(KeyLine_GPIO_Port, &GPIO_InitStruct);

    /*Configure GPIO pins : PCPin PC1 PC2 PC3 */
    GPIO_InitStruct.Pin = KeyRow_Pin | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KeyRow_GPIO_Port, &GPIO_InitStruct);
}

uint8_t MatrixKeyScan(void) {
    static uint8_t Keystate = State0;
    static uint8_t KeyLine, KeyRow;
    static uint16_t KeyOld;

    uint8_t KeyValue = NO_KEY;

    switch (Keystate) {
    case State0:
        LineOut_RowIn();
        /*Configure GPIO pin Output Level */
        HAL_GPIO_WritePin(KeyLine_GPIO_Port, KeyLine_Pin | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_RESET); // 这四个按位或操作后是0x0F
        KeyRow = KeyRow_GPIO_Port->IDR & 0x00F0;

        LineIn_RowOut();
        HAL_GPIO_WritePin(KeyRow_GPIO_Port, KeyRow_Pin | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7, GPIO_PIN_RESET);
        KeyLine = KeyLine_GPIO_Port->IDR & 0x000F;

        KeyOld = KeyLine | KeyRow;
        if (KeyOld != NO_KEY) {
            Keystate = State1;
        } else {
            Keystate = State0;
        }
        break;

    case State1:
        LineOut_RowIn();
        /*Configure GPIO pin Output Level */
        HAL_GPIO_WritePin(KeyLine_GPIO_Port, KeyLine_Pin | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_RESET); // 这四个按位或操作后是0x0F
        KeyRow = KeyRow_GPIO_Port->IDR & 0x00F0;

        LineIn_RowOut();
        HAL_GPIO_WritePin(KeyRow_GPIO_Port, KeyRow_Pin | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7, GPIO_PIN_RESET);
        KeyLine = KeyLine_GPIO_Port->IDR & 0x000F;

        if ((KeyLine | KeyRow) == KeyOld) {
            Keystate = State2;
        } else {
            Keystate = State0;
        }
        break;

    case State2:
        LineOut_RowIn();
        /*Configure GPIO pin Output Level */
        HAL_GPIO_WritePin(KeyLine_GPIO_Port, KeyLine_Pin | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_RESET); // 这四个按位或操作后是0x0F
        KeyRow = KeyRow_GPIO_Port->IDR & 0x00F0;
        if (KeyRow == 0xF0) {   // 键已释放
            Keystate = State0;
            KeyValue = KeyOld; 
        } else {
            Keystate = State2;
        }
        break;

    default:
        break;
    }
    return KeyValue;
}