#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;

// 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)
{
	unsigned int uiTemp;

	//GM Get the default values before we play with anything
	DEBUGMSG(1, (_T("Initial CSPI1 Register Values\n")));
	uiTemp = regRead(IOMUX::GPR);
	DEBUGMSG(1, (_T("Initial GPR = 0x%8x\n"), uiTemp));
	uiTemp = regRead(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI);
	DEBUGMSG(1, (_T("Initial CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI = 0x%8x\n"), uiTemp));
	uiTemp = regRead(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1);
	DEBUGMSG(1, (_T("Initial CSPI_1mux_MOSI_MISO_SS_SS1 = 0x%8x\n"), uiTemp));

	//GM Setup the IOMUXC
	bitWrite(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI, IOMUX::SIGNAL_3_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI, IOMUX::SIGNAL_3_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	bitWrite(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI, IOMUX::SIGNAL_2_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI, IOMUX::SIGNAL_2_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	bitWrite(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI, IOMUX::SIGNAL_1_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI, IOMUX::SIGNAL_1_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_3_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_3_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_2_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_2_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_1_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_1_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_0_OUTPUT, IOMUX::FUNCTIONAL_OUTPUT);
	bitWrite(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1, IOMUX::SIGNAL_0_INPUT,  IOMUX::FUNCTIONAL_INPUT);

	uiTemp = regRead(IOMUX::CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI);
	DEBUGMSG(1, (_T("New CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI = 0x%8x\n"), uiTemp));
	uiTemp = regRead(IOMUX::CSPI_1mux_MOSI_MISO_SS_SS1);
	DEBUGMSG(1, (_T("New CSPI_1mux_MOSI_MISO_SS_SS1 = 0x%8x\n"), uiTemp));

	// 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);

	// Configure Master Mode
	bitWrite(CSPI_1::CONTROL, CSPI_1::MODE, 1);

	// Assert Chip Select 0 (-SS0) during access
	bitWrite(CSPI_1::CONTROL, CSPI_1::CHIPSELECT, 0);

//GM
	switch( 2 )
	{
		case 0:	// -SPI_DRDY Don't care 
			bitWrite(CSPI_1::CONTROL, CSPI_1::DRCTL, 0);
			break;
		case 1:	// Trigger SPI transfers by falling edge of -SPI_DRDY
			bitWrite(CSPI_1::CONTROL, CSPI_1::DRCTL, 1);
			break;
		case 2:	// Trigger SPI transfers by low level on -SPI_DRDY
			bitWrite(CSPI_1::CONTROL, CSPI_1::DRCTL, 2);
			break;
	}

	// Transfer at IPG_CLOCK/4 rate (aka fastest)
	// TO DO: What is IPG_CLOCK freq?
	bitWrite(CSPI_1::CONTROL, CSPI_1::DATARATE, 0);

	// 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 on TXFIFO write
	//bitWrite(CSPI_1::CONTROL, CSPI_1::SMC, 1);
//GM or
	//GM Start a Burst based on XCH bit
	bitWrite(CSPI_1::CONTROL, CSPI_1::SMC, 0);

	// Set XCH to 1 
	//GM I think this need to wait until just before we're ready to read a sample
	//bitWrite(CSPI_1::CONTROL, CSPI_1::XCH, 1);

	uiTemp = regRead(CSPI_1::CONTROL);
	DEBUGMSG(1, (_T("New CSPI_1 Control = 0x%8x\n"), uiTemp));
}

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);	
//GM	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)
{
	uint32_t	ADCValue;

		regWrite(CSPI_1::TXDATA, 0);	
		bitWrite(CSPI_1::CONTROL, CSPI_1::XCH, 1);	

		// Wait until the RX fifo is non empty
		while ((regRead(CSPI_1::STATUS) & RR) == 0)
		{}
		ADCValue = regRead(CSPI_1::RXDATA);
//		DEBUGMSG(1, (_T("ADCValue = %x \n"), ADCValue));

	return ADCValue;
}

int Polled_CSPI_1::GetNSamples( unsigned int* ptr, int N )
{
	int		i;

	for(i=0; i<N; i++)
	{
		regWrite(CSPI_1::TXDATA, 0);	
		bitWrite(CSPI_1::CONTROL, CSPI_1::XCH, 1);	

		// Wait until the RX fifo is non empty
		while ((regRead(CSPI_1::STATUS) & RR) == 0)
		{}
		*(ptr + i) = regRead(CSPI_1::RXDATA);
	}

	return i;
}

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);
//GM	bitWrite(CSPI_1::CONTROL, CSPI_1::XCH, 1);
}
