/****************************************************************************/
/* Copyright 2010 MBARI.                                                    */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
#include <p24fxxxx.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sys_defs.h"

#include "actions.h"
#include "errors.h"
#include "parser.h"
#include "serial.h"
#include "dig_io.h"
#include "rtcc.h"
#include "spi_io.h"

#define MAX_CHARS   80  /* maximum command line entry length */
static char msg_buff[64];
char cmd_buff[MAX_CHARS];
#define ChipSelect OUT_BIT_13

/****************************************************************************/
/*                               Root commands                              */
/****************************************************************************/
int actGetCmd(char* s)
{
    return prsParse(s, cmdsGet, ERR_NO_SUB_COMMAND);
}

int actSetCmd(char* s)
{
    return prsParse(s, cmdsSet, ERR_NO_SUB_COMMAND);
}

int actClrCmd(char* s)
{
    return prsParse(s, cmdsClr, ERR_NO_SUB_COMMAND);
}

int actHelloKittyCmd(char* s)
{
    serPutString(SER_CONSOLE, "MEOW\r\n");
    return ERR_SUCCESS;
}

/****************************************************************************/
/*                               Get commands                               */
/****************************************************************************/

int actGetDinCmd(char* s)
{
    int bit = atoi(s);
    
    if ( digGetInBit(bit) )
        sprintf(msg_buff, "BIT %d IS HI\r\n", bit);
    else
        sprintf(msg_buff, "BIT %d IS LO\r\n", bit);

    serPutString(SER_CONSOLE, msg_buff);


    return ERR_SUCCESS;
}

int actGetDoutCmd(char* s)
{
    int bit = atoi(s);
    
    if ( digGetOutBit(bit) )
        sprintf(msg_buff, "BIT %d IS HI\r\n", bit);
    else
        sprintf(msg_buff, "BIT %d IS LO\r\n", bit);

    serPutString(SER_CONSOLE, msg_buff);


    return ERR_SUCCESS;
}

int actGetTimeCmd(char* s)
{
    DateTime dt;

    rtcRead(&dt);
    rtcDateToString(&dt, msg_buff);

    serPutString(SER_CONSOLE, "DATE: ");
    serPutString(SER_CONSOLE, msg_buff);
    serPutString(SER_CONSOLE, "\r\n");

    rtcTimeToString(&dt, msg_buff);

    serPutString(SER_CONSOLE, "TIME: ");
    serPutString(SER_CONSOLE, msg_buff);
    serPutString(SER_CONSOLE, "\r\n");
    
    return ERR_SUCCESS;
}


int actGetSRCmd(char* s)
{

	int bit = atoi(s);

	EEPROMReadStatusReg(0);	

	return ERR_SUCCESS;
}


int actGetMemCmd(char* s)
{
	int bit = atoi(s);
	
	int value = 0;
	value = EEPROMRead(00,01,00);
	return ERR_SUCCESS;
}

int actGetIDCmd(char* s)
{
	int bit = atoi(s);
	int ID = 0;

	ID = EEPROMReadID(0);
	sprintf(cmd_buff, "\rEEPROM ID =  %d\r\n", ID);
	serPutString(SER_CONSOLE, cmd_buff);
   
	return ERR_SUCCESS;
}

int actGetBdTypeCmd(char* s)
{
	int bit = atoi(s);
	int type = 0;

	type = GetBdType(bit);

	sprintf(cmd_buff, "\rThe board in slot %d is a type %d board.\r\n", bit, type);
	serPutString(SER_CONSOLE, cmd_buff);
	
	return ERR_SUCCESS;
}
	


/****************************************************************************/
/*                               Set commands                               */
/****************************************************************************/
int actSetDoutCmd(char* s)
{
    int bit = atoi(s);
    
    digSetOutBit(bit, 1);

    return ERR_SUCCESS;
}

int actSetTimeCmd(char* s)
{
    DateTime dt;

    if ( strlen(s) == 0 )
    {
        serPutString(SER_CONSOLE, "TIME SET FORMAT: hh:mm:ss:wd:DD:MM:YY\r\n");
        serPutString(SER_CONSOLE, "wd(week day): 0 = Sunday, 1 = Monday, etc.\r\n");
        return ERR_SUCCESS; 
    }
    
    sscanf(s, "%hhd:%hhd:%hhd:%hhd:%hhd:%hhd:%hhd", &dt.hours, &dt.minutes, 
           &dt.seconds, &dt.day_of_week, &dt.day, &dt.month, &dt.year);

    if ( !rtcSet(&dt) )
        serPutString(SER_CONSOLE, "ERR: FAILED TO SET RTC\r\n");

    return ERR_SUCCESS;
}


int actSetWRENCmd(char* s)
{
	int bit = atoi(s);
	EEPROMWriteEnable();
	return ERR_SUCCESS;
}

int actSetWRDICmd(char* s)
{
	int bit = atoi(s);
	EEPROMWriteDisable(0);
	return ERR_SUCCESS;
}

int actSetSRCmd(char* s)
{
	int bit = atoi(s);
	EEPROMWriteStatusReg(bit);
	return ERR_SUCCESS;
}

int actSetMemCmd(char* s)
{
	int bit = atoi(s);
	EEPROMWrite(00,01,00,bit);
	return ERR_SUCCESS;
}

int actSetBusAddCmd(char* s)
{
	int bit = atoi(s);

	BusAddSet(bit);
	
	return ERR_SUCCESS;
}

int actSetBdSelCmd(char* s)
{
	int bit = atoi(s);

	BusAddSet(bit);
	digSetOutBit(14,1);	

	return ERR_SUCCESS;
}

int actSetBdUnselCmd(char* s)
{
	int bit = atoi(s);
	
	BusAddSet(10);
	digSetOutBit(14,0);

	return ERR_SUCCESS;
}



/****************************************************************************/
/*                              Clear commands                              */
/****************************************************************************/
int actClrDoutCmd(char* s)
{
    int bit = atoi(s);
    
    digSetOutBit(bit, 0);

    return ERR_SUCCESS;
}

int actClrPageCmd(char* s)
{
	int bit = atoi(s);
	
	EEPROMPageErase(00,01,00);
	return ERR_SUCCESS;
}

		



/****************************************************************************/
/*                    CPU Board commands		                            */
/****************************************************************************/

void EEPROMWriteEnable(void)
{
	digSetOutBit(7,0);
	spiReadWrite2(6);  // 6 = WREN
	digSetOutBit(7,1);

	return;
}

void EEPROMWriteDisable(char* s)
{
	int bit = atoi(s);

	digSetOutBit(7,0);
	spiReadWrite2(4); // 4 = WRDI
	digSetOutBit(7,1);

	return;
}


void EEPROMWrite(int add1, int add2, int add3, int data)
{

	int data2 = 0;
	int data3 = 0;
	data2 = data + 1;
	data3 = data + 2;

	//EEPROMWriteEnable();
	digSetOutBit(7,0);
	spiReadWrite2(2); // 2 = WRITE
	spiReadWrite2(add1);
	spiReadWrite2(add2);
	spiReadWrite2(add3);
	spiReadWrite2(data);
	Nop();
	spiReadWrite2(data2);
	Nop();
	spiReadWrite2(data3);
	digSetOutBit(7,1);

	return;
}

int EEPROMRead(int addMSB, int addMID, int addLSB)
{

	unsigned int value = 0;
	unsigned int value2 = 0;
	unsigned int value3 = 0;
	int addLSB2 = 0;
	int addLSB3 = 0;

	addLSB2 = addLSB + 1;
	addLSB3 = addLSB + 2;

	digSetOutBit(7,0);
	spiReadWrite2(3); // 3 = READ
	spiReadWrite2(addMSB);
	spiReadWrite2(addMID);
	spiReadWrite2(addLSB);
	value = spiReadWrite2(0);
	value2 = spiReadWrite2(0);
	value3 = spiReadWrite2(0);
	digSetOutBit(7,1);
	
	sprintf(cmd_buff, "\rEEPROM Data at Address: %d%d%d =  %d\r\n", addMSB, addMID, addLSB, value);
	serPutString(SER_CONSOLE, cmd_buff);

	sprintf(cmd_buff, "\rEEPROM Data at Address: %d%d%d =  %d\r\n", addMSB, addMID, addLSB2, value2);
	serPutString(SER_CONSOLE, cmd_buff);
	
	sprintf(cmd_buff, "\rEEPROM Data at Address: %d%d%d =  %d\r\n", addMSB, addMID, addLSB3, value3);
	serPutString(SER_CONSOLE, cmd_buff);

	return value;
}

void EEPROMReadStatusReg(char* s)
{
	int bit = atoi(s);
	unsigned int value = 0;

	digSetOutBit(7,0);
	spiReadWrite2(5); // 5 = RDSR
	Nop();
	value = spiReadWrite2(0);
	digSetOutBit(7,1);
	
	sprintf(cmd_buff, "\rEEPROM Status Register =  %d\r\n", value);
	serPutString(SER_CONSOLE, cmd_buff);

	return;
}


void EEPROMWriteStatusReg(int RegValue)
{
	EEPROMWriteEnable();

	digSetOutBit(7,0);
	spiReadWrite2(1); // 1 = WRSR
	// Nop();
	spiReadWrite2(RegValue);
	digSetOutBit(7,1);

	return;
}


void EEPROMPageErase(int addMSB, int addMID, int addLSB)
{
	digSetOutBit(7,0);
	spiReadWrite2(66); // 66 = PE 
	spiReadWrite2(addMSB);
	spiReadWrite2(addMID);
	spiReadWrite2(addLSB);
	digSetOutBit(7,1);
	return;
}

void EEPROMSectorErase(char* s)
{

	return;
}

void EEPROMChipErase(char* s)
{

	return;
}

void EEPROMPowerDown(char* s)
{

	return;
}


int EEPROMReadID(char* s)
{

	int bit = atoi(s);
	int ID = 0;

	digSetOutBit(7,0);
	spiReadWrite2(171); // 171 = RDID 
	spiReadWrite2(01);
	spiReadWrite2(11);
	spiReadWrite2(11); // any address will work
	ID = spiReadWrite2(0);
	digSetOutBit(7,1);

	return ID;
}


void BusAddSet(int address)
{
	switch(address)
	{
		case 0:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,0);  // Add 0
			digSetOutBit(2,0);  // Add 1
			digSetOutBit(3,0);	// Add 2
			break;
		}
		case 1:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,1);  // Add 0
			digSetOutBit(2,0);  // Add 1
			digSetOutBit(3,0);	// Add 2
			break;
		}

		case 2:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,0);  // Add 0
			digSetOutBit(2,1);  // Add 1
			digSetOutBit(3,0);  // Add 2
			break;
		}

		case 3:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,1);  // Add 0
			digSetOutBit(2,1);  // Add 1
			digSetOutBit(3,0);	// Add 2
			break;
		}
		case 4:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,0);  // Add 0
			digSetOutBit(2,0);  // Add 1
			digSetOutBit(3,1);  // Add 2
			break;
		}
	
		case 5:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,1);  // Add 0
			digSetOutBit(2,0);  // Add 1
			digSetOutBit(3,1);	// Add 2
			break;
		}
		case 6:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,0);  // Add 0
			digSetOutBit(2,1);  // Add 1
			digSetOutBit(3,1);	// Add 2
			break;
		}
		case 7:
		{
			digSetOutBit(0,1);  // Gate
			digSetOutBit(1,1);  // Add 0
			digSetOutBit(2,1);  // Add 1
			digSetOutBit(3,1);  // Add 2
			break;
		}
		default: 
		{
			digSetOutBit(0,0);  // Gate
			digSetOutBit(1,0);  // Add 0
			digSetOutBit(2,0);  // Add 1
			digSetOutBit(3,0);	// Add 2
			break;
		}
	}
	 
	return;
}


void BdSelSet(int slot)
{

	BusAddSet(slot);
	digSetOutBit(14,1);

	return;
}

void BdUnselSet(int slot)
{
	BusAddSet(10);
	digSetOutBit(14,0);

	return;
}

int GetBdType(int slot)
{
	int type = 0;

	BdSelSet(slot);
	SPI1STATbits.SPIROV = 0;
	spiReadWrite1(57);
	type = spiReadWrite1(0);
	Nop();
	//spiReadWrite1(8);
	BdUnselSet(slot);

	return type;
}

int GetSlotAssign(int slot, int spare)
{
	int i = 0;
  	static int slot_type[8] = {0};
	static int slot_num[8] = {0};
	static int types[8] = {0};
	int type = 0;	
	
	if (slot == 8)
	{
		for (i = 0; i<8; i++)
		{
		  	BdSelSet(i); // selects a slot and cs
			SPI1STATbits.SPIROV = 0;
			spiReadWrite1(57);
			slot_type[i] = spiReadWrite1(0); // read and store board type
			BdUnselSet(i); 
		}		
	}
	else
	{
		type = slot_type[slot];	
	}

	for(i=0;i<8;i++)
	{
		sprintf(cmd_buff, "\r\nSlot #%d is Board Type = %d", i, slot_type[i]);
		serPutString(SER_CONSOLE, cmd_buff);
	}

	return type;
}

	






	