
#include "stm32l1xx_hal.h"

#include "switches.h"
#include "main.h"

const int SHIFT = 1;
typedef enum
{
  PH_00 = 0,
  PH_10 = 2,
  PH_11 = 3,
  PH_01 = 1,
} eGreyCode;

typedef struct
{
  GPIO_TypeDef *GPIO;
  uint16_t Pin;
  uint16_t Debounce;
} sGPIOPin;

volatile int push_pos[MAX_PUSHBUTTONS];
volatile int sw_count[MAX_PUSHBUTTONS];    //< debounced switch state
volatile int sw_newstate[MAX_PUSHBUTTONS]; //< debounced switch state

volatile int dial_count[MAX_DIALS];
volatile int dial_pos[MAX_DIALS];
volatile int dial_last[MAX_DIALS]; // previous debounced switch position

static const sGPIOPin sw_arr[MAX_PUSHBUTTONS] =
    {
        {SW1_PUSH_GPIO_Port, SW1_PUSH_Pin, 10}, // two debounced switches
        {SW2_PUSH_GPIO_Port, SW2_PUSH_Pin, 10},
};

// call this to setup switch states
void InitSwitches(void)
{
  int i;

  for (i = 0; i < MAX_PUSHBUTTONS; i++)
  {
    sw_newstate[i] = 0;
    sw_count[i] = 0;
    push_pos[i] = 0;
  }
  // reset the dial positions
  for (i = 0; i < MAX_DIALS; i++)
  {
    dial_pos[i] = 0;
    dial_last[i] = 0; 
  }
  dial_count[0] = __HAL_TIM_GET_COUNTER(&htim9) >> SHIFT;
  dial_count[1] = __HAL_TIM_GET_COUNTER(&htim3) >> SHIFT;
}

// this is the interrupt handler , dealling with the switches
void HandleSwitches(void)
{

  int i;

  for (i = 0; i < MAX_PUSHBUTTONS; i++)
  {

    int sw = HAL_GPIO_ReadPin(sw_arr[i].GPIO, sw_arr[i].Pin) == GPIO_PIN_RESET;

    // bouncing, reset counter
    if (sw == sw_newstate[i])
    {
      sw_count[i] = 0;
    }
    else
    {
      // count up to debounce time
      if (sw_count[i] < sw_arr[i].Debounce)
      {
        sw_count[i]++;

        if (sw_count[i] == sw_arr[i].Debounce)
        {
          sw_newstate[i] = sw;
        }
      }
    }
  }
  push_pos[0] = sw_newstate[0];
  push_pos[1] = sw_newstate[1];

  // use the modulus counters from the timer counters
  int cnt0 = __HAL_TIM_GET_COUNTER(&htim9) >> SHIFT; // counts 4 per step
  int cnt1 = __HAL_TIM_GET_COUNTER(&htim3) >> SHIFT; // counts 4 per step

  // always count up, or count down to zero but dont wrap

  // if ((dial_pos[0] != 0) || (cnt0 > dial_count[0]))
  dial_pos[0] += cnt0 - dial_count[0];
  dial_count[0] = cnt0;

  // if ((dial_pos[1] != 0) || (cnt1 > dial_count[1]))
  dial_pos[1] += cnt1 - dial_count[1];
  dial_count[1] = cnt1;
}

get_dial_diff(int dial)
{
  if (dial > MAX_DIALS || dial < 0)
    return 0;
  // read value once
  int pos = dial_pos[dial];
  int diff = pos - dial_last[dial];
  dial_last[dial] = pos;
  return diff;
}
