//-------------------------------------------------------------------
// McStarSubs.cpp
//
// March 21, 2008
// Gene Massion
//-------------------------------------------------------------------

#include "stdafx.h"
#include <windows.h>
#include "gpio.h"
#include "ssp.h"
#include "clk.h"
#include "McStar.h"
#include "MapIO.hpp"
#include "resource.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <time.h>
#include <string.h>
#include <math.h>
#include "ADSmartIO.h"
#include <pm.h>

#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

//
// Define the method codes for how buffers are passed for I/O and FS controls
//

#define METHOD_BUFFERED                 0
#define METHOD_IN_DIRECT                1
#define METHOD_OUT_DIRECT               2
#define METHOD_NEITHER                  3

//
// Define the access check value for any access
//
//
// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
// constants *MUST* always be in sync.
//

#define FILE_ANY_ACCESS                 0
#define FILE_READ_ACCESS          ( 0x0001 )    // file & pipe
#define FILE_WRITE_ACCESS         ( 0x0002 )    // file & pipe


// begin_ntddk begin_nthal begin_ntifs
//
// Define the various device type values.  Note that values used by Microsoft
// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
// by customers.
//

#define DEVICE_TYPE ULONG

#define FILE_DEVICE_BEEP                0x00000001
#define FILE_DEVICE_CD_ROM              0x00000002
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM  0x00000003
#define FILE_DEVICE_CONTROLLER          0x00000004
#define FILE_DEVICE_DATALINK            0x00000005
#define FILE_DEVICE_DFS                 0x00000006
#define FILE_DEVICE_DISK                0x00000007
#define FILE_DEVICE_DISK_FILE_SYSTEM    0x00000008
#define FILE_DEVICE_FILE_SYSTEM         0x00000009
#define FILE_DEVICE_INPORT_PORT         0x0000000a
#define FILE_DEVICE_KEYBOARD            0x0000000b
#define FILE_DEVICE_MAILSLOT            0x0000000c
#define FILE_DEVICE_MIDI_IN             0x0000000d
#define FILE_DEVICE_MIDI_OUT            0x0000000e
#define FILE_DEVICE_MOUSE               0x0000000f
#define FILE_DEVICE_MULTI_UNC_PROVIDER  0x00000010
#define FILE_DEVICE_NAMED_PIPE          0x00000011
#define FILE_DEVICE_NETWORK             0x00000012
#define FILE_DEVICE_NETWORK_BROWSER     0x00000013
#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
#define FILE_DEVICE_NULL                0x00000015
#define FILE_DEVICE_PARALLEL_PORT       0x00000016
#define FILE_DEVICE_PHYSICAL_NETCARD    0x00000017
#define FILE_DEVICE_PRINTER             0x00000018
#define FILE_DEVICE_SCANNER             0x00000019
#define FILE_DEVICE_SERIAL_MOUSE_PORT   0x0000001a
#define FILE_DEVICE_SERIAL_PORT         0x0000001b
#define FILE_DEVICE_SCREEN              0x0000001c
#define FILE_DEVICE_SOUND               0x0000001d
#define FILE_DEVICE_STREAMS             0x0000001e
#define FILE_DEVICE_TAPE                0x0000001f
#define FILE_DEVICE_TAPE_FILE_SYSTEM    0x00000020
#define FILE_DEVICE_TRANSPORT           0x00000021
#define FILE_DEVICE_UNKNOWN             0x00000022
#define FILE_DEVICE_VIDEO               0x00000023
#define FILE_DEVICE_VIRTUAL_DISK        0x00000024
#define FILE_DEVICE_WAVE_IN             0x00000025
#define FILE_DEVICE_WAVE_OUT            0x00000026
#define FILE_DEVICE_8042_PORT           0x00000027
#define FILE_DEVICE_NETWORK_REDIRECTOR  0x00000028


extern volatile GPIO_REGS	*GpioRegPtr;
extern volatile SSP_REGS	*SspRegPtr;
extern volatile CLKMAN_REGS	*v_pClkRegs;

void MapRegisters( VOID )
{
	ULONG	sscr0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0;

	GpioRegPtr = (GPIO_REGS *)MapPhysicalAddr((GPIO_REGS *)GPIO_BASE_PHYSICAL,sizeof(GPIO_REGS));	// 1 Page
	if(GpioRegPtr == NULL)
		RETAILMSG(1,(L" Error 'cause GpioRegPtr == NULL \r\n"));

	SspRegPtr = (SSP_REGS *)MapPhysicalAddr((SSP_REGS *)NSSP_BASE_PHYSICAL,sizeof(SSP_REGS));	// 1 Page
	if(SspRegPtr == NULL)
		RETAILMSG(1,(L" Error 'cause SspRegPtr == NULL \r\n"));

	v_pClkRegs = (CLKMAN_REGS *)MapPhysicalAddr((CLKMAN_REGS *)CLK_BASE_PHYSICAL,sizeof(CLKMAN_REGS));	// 1 Page
	if(v_pClkRegs == NULL)
		RETAILMSG(1,(L" Error 'cause v_pClkRegs == NULL \r\n"));

	DEBUGMSG(1,(TEXT(" InitNSSP: + \r\n")));
	DEBUGMSG(1,(TEXT("Initial Register values before InitNSP \r\n")));
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GAFR2_U= 0x%x \r\n"),gafr));
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GPDR_2= 0x%x \r\n"),gpdr));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR0= 0x%x \r\n"),sscr0));
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR1= 0x%x \r\n"),sscr1));
	sspsp = READ_REGISTER_ULONG(&SspRegPtr->SSPSP);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSPSP= 0x%x \r\n"),sspsp));
}

void InitStdSPI( VOID )
{
	ULONG	sscr0=0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0,
			cken;

	// Disable SSP Clock
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken &= ~CLK_NSSP;
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);

	ULONG altFcn1 = 0x01;  // use 0x01 to enable Alternate Fuction 1 of the pin

	// Set GPIO 81 Alternate Functions : NSSP Transmit (Output Mode)
	ULONG pin81mask = 0x03 << 2;
	ULONG pin81AltFcn1 = (0x03 & altFcn1) << 2;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin81mask;								// Clear bits
	gafr |= pin81AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 82 Alternate Functions : NSSP Receive (Input Mode)
	ULONG pin82mask = 0x03 << 4;
	ULONG pin82AltFcn1 = (0x03 & altFcn1) << 4;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin82mask;								// Clear bits
	gafr |= pin82AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 83 Alternate Functions : NSSP Frame (Output Mode)
	ULONG pin83mask = 0x03 << 6;
	ULONG pin83AltFcn1 = (0x03 & altFcn1) << 6;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin83mask;								// Clear bits
	gafr |= pin83AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 84 Alternate Functions : NSSP Clock (Output Mode)
	ULONG pin84mask = 0x03 << 8;
	ULONG pin84AltFcn1 = (0x03 & altFcn1) << 8;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin84mask;								// Clear bits
	gafr |= pin84AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	//NOTE GPIO direction register must be written after PSP bits are set
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	gpdr |= (GPIO_81 | GPIO_83 | GPIO_84);
	gpdr &= (~GPIO_82);
	WRITE_REGISTER_ULONG(&GpioRegPtr->GPDR_2, gpdr);

	//Motorola, 
//	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, SSPCR0_FRF_Motorola | SSPCR0_SCR | SSPCR0_DSS_8 | SSPCR0_SSE);

	//Frame format FRF SPI, Serial Clock rate SCR 368, Data Size Select DSS 8 bit
	ULONG SerialClockRate=0x00;			
	sscr0 = (SerialClockRate << 8) | SSCR0_DSS_8;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
	WRITE_REGISTER_ULONG(&SspRegPtr->SSSR,  SSPSR_ROR);
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, DEFAULT_SSPCR1);

	// Enable SSP Clock 
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 |= SSPCR0_SSE;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken |= (CLK_NSSP);
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);;

	DEBUGMSG(1,(TEXT("Register values after InitNSP \r\n")));
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GAFR2_U= 0x%8x \r\n"),gafr));
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GPDR_2= 0x%8x \r\n"),gpdr));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR0= 0x%8x \r\n"),sscr0));
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR1= 0x%8x \r\n"),sscr1));
	sspsp = READ_REGISTER_ULONG(&SspRegPtr->SSPSP);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSPSP= 0x%8x \r\n"),sspsp));

	DEBUGMSG(1,(TEXT(" InitNSSP: - \r\n")));

	return ;
}

VOID InitPSP( VOID )
{
	ULONG	sscr0=0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0,
			cken;

	// Disable SSP Clock
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken &= ~CLK_NSSP;
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);

	ULONG altFcn1 = 0x01;  // use 0x01 to enable Alternate Fuction 1 of the pin

	// Set GPIO 81 Alternate Functions : NSSP Transmit (Output Mode)
	ULONG pin81mask = 0x03 << 2;
	ULONG pin81AltFcn1 = (0x03 & altFcn1) << 2;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin81mask;								// Clear bits
	gafr |= pin81AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 82 Alternate Functions : NSSP Receive (Input Mode)
	ULONG pin82mask = 0x03 << 4;
	ULONG pin82AltFcn1 = (0x03 & altFcn1) << 4;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin82mask;								// Clear bits
	gafr |= pin82AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 83 Alternate Functions : NSSP Frame 
	ULONG pin83mask = 0x03 << 6;
	ULONG pin83AltFcn1 = (0x03 & altFcn1) << 6;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin83mask;								// Clear bits
	gafr |= pin83AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 84 Alternate Functions : NSSP Clock (Output Mode)
	ULONG pin84mask = 0x03 << 8;
	ULONG pin84AltFcn1 = (0x03 & altFcn1) << 8;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin84mask;								// Clear bits
	gafr |= pin84AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set PSP mode
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, DEFAULT_SSPCR1);

	ULONG FRFMask = 0x03 << 4;
	ULONG PSPMode = 0x03 << 4;
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 &= ~FRFMask;			// Clear bits
	sscr0 |= PSPMode;			// Register SSCR0 bits 5:4
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

	// Set Frame Slave mode
	ULONG SFRMDIRMask = 0x01 << 24;
	ULONG FRMSlaveMode = 0x01 << 24;
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	sscr1 &= ~SFRMDIRMask;			// Clear bits
	sscr1 |= FRMSlaveMode;			// Register SSCR1 bits 24
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

	// Set receive without transmit mode 
	ULONG RWOTMask = 0x01 << 23;
	ULONG RWOTMode = 0x01 << 23;
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	sscr1 &= ~RWOTMask;			// Clear bits
	sscr1 |= RWOTMode;			// Register SSCR1 bits 24
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

	// Set clock not free running 
	ULONG SCFRMask = 0x01 << 28;
	ULONG SCFRMode = 0x01 << 28;
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	sscr1 &= ~SCFRMask;			// Clear bits
	sscr1 |= SCFRMode;			// Register SSCR1 bits 24
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

	//NOTE GPIO direction register must be written after PSP bits are set
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	gpdr |= (GPIO_81 | GPIO_84);
	gpdr &= (~GPIO_82);
	gpdr &= (~GPIO_83); //NSSP Frame will be an input in slave mode
	WRITE_REGISTER_ULONG(&GpioRegPtr->GPDR_2, gpdr);

	//Set Serial Clock rate 
	ULONG SCRMask = 0xFFF << 8;
	ULONG SCRValue = 0x01 << 8;
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 &= ~SCRMask;			// Clear bits
	sscr0 |= SCRValue;			
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

	//Set 24 bit data size
	ULONG DSSMask = 0x100007;
	ULONG DSSValue = SSCR0_DSS_24;
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 &= ~DSSMask;			// Clear bits
	sscr0 |= DSSValue;			
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
//	sscr0 = (SerialClockRate << 8) | SSCR0_DSS_24;
//	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
	//Not sure why they do this
	WRITE_REGISTER_ULONG(&SspRegPtr->SSSR,  SSPSR_ROR);

	// Enable SSP Clock 
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 |= SSPCR0_SSE;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken |= (CLK_NSSP);
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);;

	DEBUGMSG(1,(TEXT("Register values after Init PSP \r\n")));
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GAFR2_U= 0x%8x \r\n"),gafr));
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GPDR_2= 0x%8x \r\n"),gpdr));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR0= 0x%8x \r\n"),sscr0));
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR1= 0x%8x \r\n"),sscr1));
	sspsp = READ_REGISTER_ULONG(&SspRegPtr->SSPSP);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSPSP= 0x%8x \r\n"),sspsp));

	DEBUGMSG(1,(TEXT(" InitNSSP: - \r\n")));

	return ;
}

VOID InitTISSP( VOID )
{
	ULONG	sscr0=0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0,
			cken;

	// Disable SSP Clock
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken &= ~CLK_NSSP;
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);

	ULONG altFcn1 = 0x01;  // use 0x01 to enable Alternate Fuction 1 of the pin

	// Set GPIO 81 Alternate Functions : NSSP Transmit (Output Mode)
	ULONG pin81mask = 0x03 << 2;
	ULONG pin81AltFcn1 = (0x03 & altFcn1) << 2;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin81mask;								// Clear bits
	gafr |= pin81AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 82 Alternate Functions : NSSP Receive (Input Mode)
	ULONG pin82mask = 0x03 << 4;
	ULONG pin82AltFcn1 = (0x03 & altFcn1) << 4;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin82mask;								// Clear bits
	gafr |= pin82AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 83 Alternate Functions : NSSP Frame 
	ULONG pin83mask = 0x03 << 6;
	ULONG pin83AltFcn1 = (0x03 & altFcn1) << 6;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin83mask;								// Clear bits
	gafr |= pin83AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 84 Alternate Functions : NSSP Clock (Output Mode)
	ULONG pin84mask = 0x03 << 8;
	ULONG pin84AltFcn1 = (0x03 & altFcn1) << 8;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin84mask;								// Clear bits
	gafr |= pin84AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set TI SSP mode
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, DEFAULT_SSPCR1);

	ULONG FRFMask = 0x03 << 4;
	ULONG TIMode = 0x01 << 4;
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 &= ~FRFMask;			// Clear bits
	sscr0 |= TIMode;			// Register SSCR0 bits 5:4
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

	// Set Frame Slave mode
	ULONG SFRMDIRMask = 0x01 << 24;
	ULONG FRMSlaveMode = 0x01 << 24;
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	sscr1 &= ~SFRMDIRMask;			// Clear bits
	sscr1 |= FRMSlaveMode;			// Register SSCR1 bits 24
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

	// Set receive without transmit mode 
	ULONG RWOTMask = 0x01 << 23;
	ULONG RWOTMode = 0x01 << 23;
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	sscr1 &= ~RWOTMask;			// Clear bits
	sscr1 |= RWOTMode;			// Register SSCR1 bits 24
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

	//NOTE GPIO direction register must be written after PSP bits are set
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	gpdr |= (GPIO_81 | GPIO_84);
	gpdr &= (~GPIO_82);
	gpdr &= (~GPIO_83); //NSSP Frame will be an input in slave mode
	WRITE_REGISTER_ULONG(&GpioRegPtr->GPDR_2, gpdr);

	//Set Serial Clock rate 
	ULONG SCRMask = 0xFFF << 8;
	ULONG SCRValue = 0x01 << 8;
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 &= ~SCRMask;			// Clear bits
	sscr0 |= SCRValue;			
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

	//Set 24 bit data size
	ULONG DSSMask = 0x100007;
	ULONG DSSValue = SSCR0_DSS_24;
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 &= ~DSSMask;			// Clear bits
	sscr0 |= DSSValue;			
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
//	sscr0 = (SerialClockRate << 8) | SSCR0_DSS_24;
//	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
	//Not sure why they do this
	WRITE_REGISTER_ULONG(&SspRegPtr->SSSR,  SSPSR_ROR);

	// Enable SSP Clock 
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 |= SSPCR0_SSE;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken |= (CLK_NSSP);
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);;

	DEBUGMSG(1,(TEXT("Register values after Init PSP \r\n")));
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GAFR2_U= 0x%8x \r\n"),gafr));
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GPDR_2= 0x%8x \r\n"),gpdr));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR0= 0x%8x \r\n"),sscr0));
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR1= 0x%8x \r\n"),sscr1));
	sspsp = READ_REGISTER_ULONG(&SspRegPtr->SSPSP);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSPSP= 0x%8x \r\n"),sspsp));

	DEBUGMSG(1,(TEXT(" InitNSSP: - \r\n")));

	return ;
}

DWORD dwReadSSPNoPush( VOID )
{
	ULONG Count=0x3ffff;

	while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_RNE) == 0)
	{
		if(Count-- == 0)
			break;
	}

	return READ_REGISTER_ULONG(&SspRegPtr->SSDR);
}

int dwReadSSP( VOID )
{
	int count=0x3ffff;
	ulong value;
	
	while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_RNE) == 0)
	{
		if(count-- == 0)
			break;
	}
	
	if( count <= 0)
	{
		DEBUGMSG(1,(TEXT("Read SSP timed out with RNE = 0\n")));
		return 0xFFFFFFFF;
	}
	else
	{	
		value = READ_REGISTER_ULONG(&SspRegPtr->SSDR);
//		DEBUGMSG(1,(TEXT("Count = %08x SSDR Register = %08x \n"), count, value));
		return value;
	}
}

bool SendSSPMessage(BYTE *pBuf, int num)
{
	int i;

	USHORT us;
	ULONG Count=0x3ffff;

	DEBUGMSG(1,(L"Data sent:     0x"));
	for (i=0;i<num;i++)
	{
		Count=0x3ffff;

		while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_TNF) == 0)
		{
			if(Count-- == 0 )
			{
				break;
			}			
		}

		if(Count == 0 )
		{
			break;
		}			

		us = pBuf[i];

	    WRITE_REGISTER_ULONG(&SspRegPtr->SSDR, us);
		DEBUGMSG(1,(L" %04x",us));
	}
	DEBUGMSG(1,(L"\r\n"));

	if(Count == 0 )
	{
		goto error_return;
	}			

	// Show the bytes that were pushed out during the command sending

	DEBUGMSG(1,(TEXT("Data received: ")));
	for (i=0;i<num;i++)
	{
		DEBUGMSG(1,(TEXT(" %04x"),dwReadSSPNoPush()));
	}
	DEBUGMSG(1,(TEXT("\r\n")));

	return TRUE;

error_return:

	return FALSE;
}

bool ToggleGPIO( VOID )
{
	int				i;
	unsigned long	ulTemp,
					set,
					clear;

	//Toggle EIO8 and EIO9 (GPIO 106 and 107)
	//Set bits to output
/*	ulTemp = READ_REGISTER_ULONG(&GPDR3RegPtr->GPDR_3);
	ulTemp |= 0x11 << 10;
	WRITE_REGISTER_ULONG(&GPDR3RegPtr->GPDR_3, ulTemp);
	set = READ_REGISTER_ULONG(&GPSR3RegPtr->GPSR_3);
	set |= 0x11 << 10;
	clear = READ_REGISTER_ULONG(&GPCR3RegPtr->GPCR_3);
	clear |= 0x11 << 10;
	
	for(i=0; i<100; i++)
	{
		WRITE_REGISTER_ULONG(&GPSR3RegPtr->GPSR_3, set);
		WRITE_REGISTER_ULONG(&GPCR3RegPtr->GPCR_3, clear);
	}*/
	return TRUE;
}

bool ReadConfig( CFGDATA& configData )
{
	FILE *configFile;
	char inString[80],
	 	 *label,
		 *value;
	

	if ( (configFile = fopen( "\\Storage Card\\McStar\\McStarConfig.txt", "r")) != NULL)
		DEBUGMSG(1,(TEXT("Opened Configuration File \n")));
	else
	{
		//process error
	}


	while( !feof(configFile) ) 
	{
		fgets(inString, 80, configFile);
		label = strtok(inString, ":");
		value = strtok(NULL, ":") ;

		if (strcmp(label, "Sample rate") == 0)
		{
			if ( (configData.sampleRate = atoi(value)) == 0)
			{
				// process error
			}
			DEBUGMSG(1,(TEXT("Sample rate %d\n"), configData.sampleRate));
			label = "";
		}
		else if (strcmp(label, "Number of samples per record") == 0)
		{
			if ( (configData.numSamples = atoi(value)) == 0)
			{
				// process error
			}
			DEBUGMSG(1,(TEXT("Samples per record %d\n"), configData.numSamples));
			label = "";
		}
		else if (strcmp(label, "Number of hydrophones") == 0)
		{
			if ( (configData.numPhones = atoi(value)) == 0)
			{
				// process error
			}
			DEBUGMSG(1,(TEXT("Hydrophones %d\n"), configData.numPhones));
			label = "";
		}
		else if (strcmp(label, "Number of records per Flash Disk file") == 0)
		{
			if ( (configData.numRecords = atoi(value)) == 0)
			{
				// process error
			}
			DEBUGMSG(1,(TEXT("Records per Flash Disk File %d\n"), configData.numRecords));
			label = "";
		}

		else if (strcmp(label, "Number of Flash Disk files per USB write") == 0)
		{
			if ( (configData.numFiles = atoi(value)) == 0)
			{
				// process error
			}
			DEBUGMSG(1,(TEXT("Flash Disk files per USB write %d\n"), configData.numFiles));
			label = "";
		}
		else if (strcmp(label, "Seconds to sleep between acquisitions") == 0)
		{
			if ( (configData.sleepPeriod = atoi(value)) == 0)
			{
				// process error
			}
			DEBUGMSG(1,(TEXT("Sleep Period rate %d\n"), configData.sleepPeriod));
			label = "";
		}
	}

	fclose(configFile);
	return TRUE;
}


bool GetData( int numSamples, int sampleRate, int* pData)
{
	// routine to read ADC for numSamples
	int	 i;
	double pi = 3.1415926535,
		   freq = 10000,
		   time,
		   dTemp;

	for(i = 0; i < numSamples; i++)
	{
		time = i / sampleRate;
		dTemp = sin( 2 * pi * freq * time );
		*(pData + i) = int(dTemp * 50000);
	}

	return TRUE;
}


void CreateFlashFilename( char fileName[80] )
{
	// routine to create a file name

	char	cTemp[10];

	__time64_t t64Time;
    
	struct tm timeNow;
    
	_time64( &t64Time );
	if( (_localtime64_s(&timeNow, &t64Time)) !=0)
	{
		// process error
	}
	
	strcpy(fileName, "\\Storage Card\\McStar\\Data\\");
	_itoa(timeNow.tm_year, cTemp, 10);
	strcat(cTemp, "-");
	strcat(fileName, cTemp);
	_itoa(timeNow.tm_yday, cTemp, 10);
	strcat(cTemp, "-");
	strcat(fileName, cTemp);
	_itoa(timeNow.tm_hour, cTemp, 10);
	strcat(cTemp, "-");
	strcat(fileName, cTemp);
	_itoa(timeNow.tm_min, cTemp, 10);
	strcat(cTemp, "-");
	strcat(fileName, cTemp);
	_itoa(timeNow.tm_sec, cTemp, 10);
	strcat(fileName, cTemp);

	return;
}

bool WriteToUSBDisk()
{
	// routine to write files stored on flash disk to USB disk
	return TRUE;
}

void GoToSleep( int sleepPeriod )
{
	// routine to put Bitsy to sleep
}

void SetPowerState( BOOL powerState )
{
	LPVOID	m_hUSB,
			m_hCKEN,
			m_hAC97;
	DWORD	*ptr;

	ADSmartIO *smartIOCtrl	= 0;
	DWORD	dwValue;

typedef struct {
    UINT uDeviceId;
    UINT uMsg;
    DWORD dwUser;
    DWORD dwParam1;
    DWORD dwParam2;
} MMDRV_MESSAGE_PARAMS, *PMMDRV_MESSAGE_PARAMS;


	MMDRV_MESSAGE_PARAMS Parm;
	DWORD				 BytesReturned;
	DWORD				 Dummy;

	HANDLE	m_hWav;
	
#define	WPDM_PRIVATE_TURN_ON_AUDIO				0xD0
#define	WPDM_PRIVATE_TURN_ON_AUDIO_AMP			0xD1
#define	WPDM_PRIVATE_TURN_OFF_AUDIO				0xD2
#define	WPDM_PRIVATE_TURN_OFF_AUDIO_AMP			0xD3
#define	WPDM_PRIVATE_QUERY_AUDIO_AMP_POWER		0xD4
#define	WPDM_PRIVATE_QUERY_AUDIO_CODEC_POWER	0xD5
#define IOCTL_WAV_MESSAGE    CTL_CODE(FILE_DEVICE_SOUND,    3, METHOD_BUFFERED, FILE_ANY_ACCESS)


	smartIOCtrl = new ADSmartIO;
	if (smartIOCtrl == NULL)
	{
		RETAILMSG (TRUE, (L"Out of memory\r\n"));
		return;
	}

	if(powerState == LOW_POWER)
	{
		(*smartIOCtrl).SetBacklightState (false);	//Turn off the LCD

		//Turn off the USB port
		m_hUSB = MapAddress(USB_BASE);
		ptr = (DWORD*)m_hUSB;
		ptr += (UHCCOMS_OFFSET / sizeof(DWORD));
		*ptr |= 0x1;		// Set the HCR bit
		Sleep(1);

		ptr = (DWORD*)m_hUSB;
		ptr += (UHCRHS_OFFSET / sizeof(DWORD));
		*ptr |= 0x1;		// Set the LPS bit

		ptr = (DWORD*)m_hUSB;
		ptr += (UHCHR_OFFSET / sizeof(DWORD));
		*ptr |= 0x1;		// Set the SSE bit

		//Turn off the USB clocks and the PWM clocks
		m_hCKEN = MapAddress(CKEN_BASE);
		ptr = (DWORD*)m_hCKEN;
		*ptr &= ~0x0C00;		// Clear the USB clock enable bits
		*ptr &= ~0x03;			// Clear the PWM clock enable bits
/*
		//Turn off the AC97
		m_hAC97 = MapAddress(AC97_BASE);
		ptr = (DWORD*)m_hAC97;
		ptr += (AC97x26_OFFSET / sizeof(DWORD));
		*ptr |= 0x1000;		// Set AC97 Powerdown register PR4 bit

		// wait for GSR[cdone]
		ptr = (DWORD*)m_hAC97;
		ptr += (AC97GSR_OFFSET / sizeof(DWORD));
		while( (*ptr & 0x00080000) == 0)
			DEBUGMSG(1,(TEXT("AC97 GSR Register CDONE = %d\n"), (*ptr & 0x00080000)));
		
		ptr = (DWORD*)m_hAC97;
		ptr += (AC97GCR_OFFSET / sizeof(DWORD));
		*ptr |= 0x08; // Set the ACOFF bit

		//Set the AC97 bit in CKEN
		m_hCKEN = MapAddress(CKEN_BASE);
		ptr = (DWORD*)m_hCKEN;
		*ptr |= 0x80000000;

		//Wait for GSR[ACOFFD]
		ptr = (DWORD*)m_hAC97;
		ptr += (AC97GSR_OFFSET / sizeof(DWORD));
		while( (*ptr & 0x00000008) == 0)
			DEBUGMSG(1,(TEXT("AC97 GSR Register ACOFFD= %d\n"), (*ptr & 0x00080000)));

		//Clear the AC97 bit in CKEN and clear the AC97 clock enable
		m_hCKEN = MapAddress(CKEN_BASE);
		ptr = (DWORD*)m_hCKEN;
		*ptr &= ~0x80000000;
		*ptr &= ~0x00000004;
*/
		UnmapAddress(m_hUSB);
		UnmapAddress(m_hCKEN);
//		UnmapAddress(m_hAC97);

		m_hWav = CreateFile(TEXT("WAV1:"), GENERIC_READ|GENERIC_WRITE,
            				0, NULL, OPEN_EXISTING, 0, NULL);


	Parm.uMsg=WPDM_PRIVATE_TURN_OFF_AUDIO_AMP;
	DeviceIoControl(m_hWav,IOCTL_WAV_MESSAGE,(LPVOID)&Parm, sizeof(MMDRV_MESSAGE_PARAMS),&Dummy, sizeof(Dummy),&BytesReturned, NULL );



//		dwValue = SetDevicePower(_T("{A32942B7-920C-486b-B0E6-92A702A99B35}\\LAN90001"), POWER_NAME, D3);
//		printf("Set device power returned: %d \n", dwValue);
	}
	else
	{
		(*smartIOCtrl).SetBacklightState (true);
//		dwValue = SetDevicePower(_T("{A32942B7-920C-486b-B0E6-92A702A99B35}\\LAN90001"), POWER_NAME, D0);
//		printf("Set device power returned: %d \n", dwValue);
	}

	delete smartIOCtrl;
}

