#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
#include <iostream>

#include "cspi_1.h"
#include "cspi_1_registers.h"
#include "iomux.h"

using namespace std;

const uint32_t	UART_ClockFrequency				= 25000000;

// Status Register Bit Definitions

const uint32_t	BO 	= (1 << 7); // Bit Counter Overflow (slave mode only)
const uint32_t	RO	= (1 << 6); // RX FIFO Overflow
const uint32_t	RF	= (1 << 5); // RX FIFO Full 
const uint32_t	RH	= (1 << 4); // RX FIFO Half Full
const uint32_t	RR	= (1 << 3); // RX FIFO Ready (non empty)
const uint32_t	TF	= (1 << 2); // TX FIFO Full
const uint32_t	TH	= (1 << 1);	// TX FIFO Half Full
const uint32_t	TE	= (1 << 0);	// TX FIFO Empty

uint32_t Polled_CSPI_1::sampleCounter;

void Polled_CSPI_1::InitializeMasterMode(void)
{
	// Clear the CSPI control register as good hygiene
	regWrite(CSPI_1::CONTROL, 0);

	// Disable all interrupts, since this a polled device
	regWrite(CSPI_1::INTERRUPT, 0);

	// Disable DMA transfers
	regWrite(CSPI_1::DMA, 0);

	// Don't insert any delays between transfers
	// Data should be moved into the CPU as fast as possible
	regWrite(CSPI_1::PERIOD, 0);

	// Assert Chip Select 0 (-SS0) during access
	bitWrite(CSPI_1::CONTROL, CSPI_1::CHIPSELECT, 0);

	// Trigger SPI transfers by falling edge of -SPI_DRDY
	bitWrite(CSPI_1::CONTROL, CSPI_1::DRCTL, 1);
//OR (GM)
	// -SPI_DRDY Don't care
	 //bitWrite(CSPI_1::CONTROL, CSPI_1::DRCTL, 0);

	// Transfer at IPG_CLOCK/4 rate (aka fastest)
	// TO DO: What the hell is IPG_CLOCK?
	bitWrite(CSPI_1::CONTROL, CSPI_1::DATARATE, 1);

	// Transfer 24 bits during each SPI transfer
	bitWrite(CSPI_1::CONTROL, CSPI_1::BITCOUNT, 23);

	// Make the CSPI chip select active low
	bitWrite(CSPI_1::CONTROL, CSPI_1::SSPOL, 0);

	// Negate the CSPI chip select between transfers
	bitWrite(CSPI_1::CONTROL, CSPI_1::SSCTL, 1);

	// Output data on the falling edge of the SPI clock
	// Sample data on the rising edge of the SPI clock
	bitWrite(CSPI_1::CONTROL, CSPI_1::PHA, 0);
	bitWrite(CSPI_1::CONTROL, CSPI_1::POL, 0);

	// Start a TX Burst immediately (useful only during loopback)
	bitWrite(CSPI_1::CONTROL, CSPI_1::SMC, 0);

	// Set XCH to 1 because what the Hell
	bitWrite(CSPI_1::CONTROL, CSPI_1::XCH, 1);

	// Configure Master Mode
	bitWrite(CSPI_1::CONTROL, CSPI_1::MODE, 1);
	cout << "CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI = " << hex << regRead(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI) << endl;
	cout << "CSPI_1_MOSI_MISO_SS_SS1          = " << hex << regRead(IOMUX::CSPI_1_MOSI_MISO_SS_SS1) << endl;
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_3_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_3_INPUT,  IOMUX::FUNCTIONAL_INPUT);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_2_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_2_INPUT,  IOMUX::FUNCTIONAL_INPUT);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_1_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_1_INPUT,  IOMUX::FUNCTIONAL_INPUT);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_0_OUTPUT, IOMUX::GPIO);
	bitWrite(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI, IOMUX::SIGNAL_0_OUTPUT, IOMUX::NO_INPUTS_SELECTED);

	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_3_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_3_INPUT,  IOMUX::FUNCTIONAL_INPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_2_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_2_INPUT,  IOMUX::FUNCTIONAL_INPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_1_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_1_INPUT,  IOMUX::FUNCTIONAL_INPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_0_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_0_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	cout << "CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI = " << hex << regRead(IOMUX::CSPI_1_SS2_SCLK_SDRY_CSPI_2_MOSI) << endl;
	cout << "CSPI_1_MOSI_MISO_SS_SS1          = " << hex << regRead(IOMUX::CSPI_1_MOSI_MISO_SS_SS1) << endl;
}

void Polled_CSPI_1::Enable()
{
	bitWrite(CSPI_1::CONTROL, CSPI_1::EN, 1);	
}

void Polled_CSPI_1::Disable()
{
	bitWrite(CSPI_1::CONTROL, CSPI_1::EN, 0);	
}		

void Polled_CSPI_1::EnableLoopback()
{
//	bitWrite(CSPI_1::TEST, CSPI_1::LBC, 1);	
	regWrite(CSPI_1::TEST, 0x4000);
}

void Polled_CSPI_1::DisableLoopback()
{
//	bitWrite(CSPI_1::TEST, CSPI_1::LBC, 0);
	regWrite(CSPI_1::TEST, 0);
}

bool Polled_CSPI_1::SampleAvailable(void)
{
	return ((regRead(CSPI_1::STATUS) & RR) ? true : false);
}

bool Polled_CSPI_1::ReceiveOverrun(void)
{
	return ((regRead(CSPI_1::STATUS) & RO) ? true : false);
}

uint32_t Polled_CSPI_1::GetSample(void)
{
	// Wait until the RX fifo is non empty
	while ((regRead(CSPI_1::STATUS) & RR) == 0) 
		;

	return regRead(CSPI_1::RXDATA);
}

void Polled_CSPI_1::SendSample(uint32_t sample)
{
	// Wait until the TX FIFO non full
	while ((regRead(CSPI_1::STATUS) & TF) == 1)
		;
	regWrite(CSPI_1::TXDATA, sample);
	bitWrite(CSPI_1::CONTROL, CSPI_1::XCH, 1);
}
