/*
 * transmitter.c
 *
 *  Created on: Dec 22, 2014
 *      Author: hutch
 */

#include "transmitter.h"
#include <stdint.h>
#include "supportFiles/buttons.h"
#include "supportFiles/switches.h"
#include "supportFiles/mio.h"
#include "supportFiles/utils.h"
#include <stdio.h>

// From Steve Schultz's email:
// Clock frequency for transmitter signals: 100 kHz
// Transmitter frequency is: clock/Ticks
// Ticks: 26    28    30    32    36    40    44    50    56    64    74    88
// This means that for the first signal it will be low for 13/100e3=0.14ms and then high for 0.14ms.

#define FREQUENCY_COUNT 10
#define BTN0_MASK 0x1
#define BTN1_MASK 0x2
#define TRANSMITTER_HIGH_VALUE 1
#define TRANSMITTER_LOW_VALUE 0

const uint16_t frequencyTickTable[FREQUENCY_COUNT] = {26, 28, 30, 32, 36, 40, 44, 50, 56, 64};
static bool initFlag = false;
static bool transmitter_testModeFlag = false;
static bool transmitter_startFlag = false;
static uint16_t transmitter_frequencyNumber;

enum transmitter_control_st_t {
	init_st,
	wait_for_startFlag,
	output_low_st,
	output_high_st
} transmitter_currentState = init_st;

// Need to run the init before calling transmitter_tick().
void transmitter_init() {
	if (!initFlag) {
		buttons_init();
		switches_init();
		mio_init(false);
		mio_setPinAsOutput(TRANSMITTER_OUTPUT_PIN);	// Output is a single MIO pin.
	}
	initFlag = true;
}

void transmitter_enableTestMode() {
	transmitter_testModeFlag = true;
}

void transmitter_disableTestMode() {
	transmitter_testModeFlag = false;
}

void transmitter_start() {
	transmitter_startFlag = true;
}

void transmitter_stop() {
	transmitter_startFlag = false;
}

void transmitter_setFrequencyNumber(uint16_t frequencyNumber) {
	if (frequencyNumber >= FREQUENCY_COUNT)				// If the switch value is beyond the max, just set it to the max frequency.
		transmitter_frequencyNumber = FREQUENCY_COUNT-1;
	else
		transmitter_frequencyNumber = frequencyNumber;
}

void transmitter_tick() {
	static uint16_t tickCount = 0;		// Keep track of tick-count to generate the correct square wave.
	static uint16_t tickValue = 0;		// This is the tick value (essentially the frequency) chosen by the switches.
	// Output action.
	switch(transmitter_currentState) {
	case init_st:
		tickCount = 0;
		break;
	case wait_for_startFlag:
		break;
	case output_low_st:
		tickCount++;
		mio_writePin(TRANSMITTER_OUTPUT_PIN, TRANSMITTER_LOW_VALUE);
		if (transmitter_testModeFlag)
			printf("0");
		break;
	case output_high_st:
		tickCount++;
		mio_writePin(TRANSMITTER_OUTPUT_PIN, TRANSMITTER_HIGH_VALUE);
		if (transmitter_testModeFlag)
			printf("1");
		break;
	}

	// Next-state update.
	switch(transmitter_currentState) {
	case init_st:
		transmitter_currentState = wait_for_startFlag;
		break;
	case wait_for_startFlag:
		if (transmitter_startFlag) {								// Mealy state, transition if start flag is true.
			tickValue = frequencyTickTable[transmitter_frequencyNumber]/2;
			tickCount = 0;														// Starting to generate the signal from scratch.
			transmitter_currentState = output_low_st;	// Go to the state that drives the transmitter output low.
		}
		break;
	case output_low_st:
		if (tickCount == tickValue) {
			tickCount = 0;			// Mealy action.
			transmitter_currentState = output_high_st;
		}
		break;
	case output_high_st:
		if (tickCount == tickValue) {
			tickCount = 0;			// Mealy action.
			// Keep transmitting if the button is still pushed.
			if (transmitter_startFlag) {
				transmitter_currentState = output_low_st;
			} else
				transmitter_currentState = wait_for_startFlag;
			if (transmitter_testModeFlag)
				printf("\n\r");
		}
		break;
	}
}

// Prints out the clock waveform to stdio. Terminates when BTN1 is pressed.
// Prints out one line of 1s and 0s that represent one period of the clock signal, in terms of ticks.
void transmitter_runTest() {
	printf("starting transmitter_runTest()\n\r");
	transmitter_init();
	transmitter_enableTestMode();							// Prints diagnostics to stdio.
	while (!(buttons_read() & BTN1_MASK)) {		// Run continously until btn1 is pressed.
		transmitter_tick();
		utils_msDelay(10);
	}
	printf("exiting transmitter_runTest()\n\r");
	transmitter_disableTestMode();
}


















