#ifndef __H2201_BUTTONS_H__
#define __H2201_BUTTONS_H__

#include "driver/gpio.h"

#define H2201_BUTTONS_TAG "H2201_BUTTONS"

#define MASTER_VOLUME_BUTTON 35
#define TELEPHONE_VOLUME_BUTTON 34
#define PC_VOLUME_BUTTON 39
#define BLUETOOTH_VOLUME_BUTTON 36

#define MASTER_VOLUME_0DB 0x39
#define TELEPHONE_VOLUME_0DB 0x06
#define PC_VOLUME_0DB 0x06
#define BLUETOOTH_VOLUME_0DB 33

#define ROTARY_A_GPIO 27
#define ROTARY_B_GPIO 32

#define SHIFT_CLOCK 19
#define SHIFT_DATA 18
#define SHIFT_LATCH 5

#define DIPSWITCH_TEL_LEFT 1
#define DIPSWITCH_TEL_RIGHT 2
#define DIPSWITCH_PC_LEFT 3
#define DIPSWITCH_PC_RIGHT 4
#define DIPSWITCH_BT_LEFT 5
#define DIPSWITCH_BT_RIGHT 6

#define BUTTON_PRESS_EVENT 1
#define ENCODER_UP_EVENT 2
#define ENCODER_DOWN_EVENT 3

#define TABLE_COLS 4
typedef uint8_t table_row_t[TABLE_COLS];

#define TABLE_ROWS 7

#define DIR_NONE 0x0 // No complete step yet.
#define DIR_CW 0x10  // Clockwise step.
#define DIR_CCW 0x20 // Anti-clockwise step.

// Create the full-step state table (emits a code at 00 only)
#define R_START 0x0
#define F_CW_FINAL 0x1
#define F_CW_BEGIN 0x2
#define F_CW_NEXT 0x3
#define F_CCW_BEGIN 0x4
#define F_CCW_FINAL 0x5
#define F_CCW_NEXT 0x6

static const uint8_t H2201_encoder_transition_table[TABLE_ROWS][TABLE_COLS] = {
    // 00        01           10           11                  // BA
    {R_START, F_CW_BEGIN, F_CCW_BEGIN, R_START},           // R_START
    {F_CW_NEXT, R_START, F_CW_FINAL, R_START | DIR_CW},    // F_CW_FINAL
    {F_CW_NEXT, F_CW_BEGIN, R_START, R_START},             // F_CW_BEGIN
    {F_CW_NEXT, F_CW_BEGIN, F_CW_FINAL, R_START},          // F_CW_NEXT
    {F_CCW_NEXT, R_START, F_CCW_BEGIN, R_START},           // F_CCW_BEGIN
    {F_CCW_NEXT, F_CCW_FINAL, R_START, R_START | DIR_CCW}, // F_CCW_FINAL
    {F_CCW_NEXT, F_CCW_FINAL, F_CCW_BEGIN, R_START},       // F_CCW_NEXT
};

/**
 * @brief Struct carries all the information needed by this driver to manage the rotary encoder device.
 *        The fields of this structure should not be accessed directly.
 */
typedef struct
{
    gpio_num_t pin_a;         ///< GPIO for Signal A from the rotary encoder device
    gpio_num_t pin_b;         ///< GPIO for Signal B from the rotary encoder device
    QueueHandle_t queue;      ///< Handle for event queue, created by ::rotary_encoder_create_queue
    const table_row_t *table; ///< Pointer to active state transition table
    uint8_t table_state;      ///< Internal state
} rotary_encoder_info_t;

void H2201_shiftregister_init(void);
bool H2201_dipswitch_read(int sw);
void H2201_buttons_init(void);
void H2201_encoder_init(void);

#endif /* __H2201_BUTTONS_H__*/