
#include "stm32l1xx_hal.h"

#include "switches.h"


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 dial_pos[MAX_DIALS];
volatile int dial_last[MAX_DIALS]; // previous debounced switch position

volatile int push_pos[MAX_PUSHBUTTONS];

volatile static int sw_newstate[MAX_SWITCHES]; //< debounced switch state
volatile static int sw_count[MAX_SWITCHES]; //< debounce counter

static const sGPIOPin sw_arr[MAX_SWITCHES] =
	{ { SW1_I_GPIO_Port, SW1_I_Pin , 5}, // these two pins used to encode SW1 phase
			{ SW1_Q_GPIO_Port, SW1_Q_Pin, 5 }, // "                             SW1 phase
			{ SW2_I_GPIO_Port, SW2_I_Pin , 5}, // these two pins used to encode SW2 phase
			{ SW2_Q_GPIO_Port, SW2_Q_Pin , 5}, // "                             SW2 phase
			{ 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_SWITCHES; i++) {
	sw_newstate[i] = 0;
	sw_count[i] = 0;
}

// reset the dial positions
dial_pos[0] = 0;
dial_pos[1] = 0;
}

// this gray encodes the dial , but you cannot turn the switch back below 0
void EncodeDial(int i) {
if (i < MAX_DIALS && i >= 0) {
	int sw_index = i << 1;
	// dial 0 uses switches 0 and 1
	// dial 1 uses switches 2 and 3
	int current = sw_newstate[sw_index] | (sw_newstate[sw_index + 1] << 1);
	switch (dial_last[i]) {
	case PH_00:
		if (current == PH_10)
			dial_pos[i]++;
		if (current == PH_01 && dial_pos[i]>0)
			dial_pos[i]--;
		break;
	case PH_10:
		if (current == PH_11)
			dial_pos[i]++;
		if (current == PH_00 && dial_pos[i]>0)
			dial_pos[i]--;
		break;
	case PH_11:
		if (current == PH_01)
			dial_pos[i]++;
		if (current == PH_10 && dial_pos[i]>0)
			dial_pos[i]--;
		break;
	case PH_01:
		if (current == PH_00)
			dial_pos[i]++;
		if (current == PH_11 && dial_pos[i]>0)
			dial_pos[i]--;
		break;
	default:
		break;
	}
	dial_last[i] = current;
}

}

// this is the interrupt handler , dealling with the switches
void HandleSwitches(void)
{

  int i;

  for (i = 0; i < MAX_SWITCHES; 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;
		}
	 }
    }
  }
// we now have debounced switch states in sw_newstate . So we can go ahead and feed some of the

  EncodeDial(0);
  EncodeDial(1);
  push_pos[0] =sw_newstate[4];
  push_pos[1] =sw_newstate[5];

}

void reset_dial(int dial,int value) {
  if(dial>=0 && dial < MAX_DIALS)
	dial_pos[dial]= value;
}

