/**************************************************************************************************/
/* LOW VOLTAGE LOAD SWITCHER BOARD																  */
/* Copyright 2010 MBARI.                                                    					  */
/* MBARI Proprietary Information. All rights reserved.                      					  */
/* FILENAME:		actions.c																	  */
/* DESCRIPTION:		This file contains functions which define board commands.					  */
/* FUNCTION LIST:	CSAddSet(int address)														  */
/*					actGetCmd(char* s)															  */
/*					actSetCmd(char* s)															  */
/*					actClrCmd(char* s)															  */
/*					actResetCmd(char* s)														  */
/*					actHelloKittyCmd(char* s)													  */
/*					actSpi2TestCmd(char* s)														  */
/*					actGetCardInfoCmd(char* s)													  */
/*					actGetDinCmd(char* s)														  */
/*					actGetDoutCmd(char* s)														  */
/*					actGetSpiStatsCmd(char* s)													  */
/*					actSetStubCmd(char* s)														  */
/*					actSetDoutCmd(char* s)														  */
/*					actSetCSAddCmd(char* s)														  */
/*					actClrSpiStatsCmd(char* s)													  */
/*					actClrDoutCmd(char* s)														  */
/**************************************************************************************************/
#include <p24fxxxx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "card.h"
#include "sys_defs.h"
#include "actions.h"
#include "errors.h"
#include "parser.h"
#include "serial.h"
#include "spi1.h"
#include "spi2.h"
#include "dig_io.h"
#include "math.h"
#include "potentiometer.h"
#include "breaker.h"
#include "relay.h"

static char msg_buff[64];

/**************************************************************************************************/
/*                         LVLS Bd Commands                                						  */
/**************************************************************************************************/

////////////////////////////////////////////////////////////////////////////////////////////////////
//	NAME: 			CSAddSet(int address) 	
//	DESCRIPTION:	Controls chip select lines for I/O expander, digital potentiometers,
//					and analog to digital converters.
//	NOTES: 			DIO_05 does not have it's chip select tied to the multiplexer on
//					current board.  
//					Do not change the cases associated with the DIOs.  Otherwise, 
//					functions involving the DIO expanders will not function properly.
//					Cases will need to be added for additional devices (notably, ADC_03_CS
//					and ADC_04_CS) in later versions of this board.
////////////////////////////////////////////////////////////////////////////////////////////////////

void CSAddSet(int address)
{
	switch(address)
	{
		case 0:					//DIO_01_CS
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,0); // Add A
			digSetOutBit(12,0); // Add B
			digSetOutBit(13,0); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
		case 1:					//DIO_02_CS		*NOT USED ON CURRENT BOARD*
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,0); // Add A
			digSetOutBit(12,0); // Add B
			digSetOutBit(13,1); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
		case 2:					//DIO_03_CS		*NOT USED ON CURRENT BOARD*
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,0); // Add A
			digSetOutBit(12,0); // Add B
			digSetOutBit(13,0); // Add C
			digSetOutBit(14,1);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
		case 3:					//DIO_04_CS
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,0); // Add B
			digSetOutBit(13,0); // Add C
			digSetOutBit(14,1);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}

		case 4:					//DIO_05_CS	
		{
			PIC_DIO_05_CS = 0;					// BECAUSE THIS BOARD IS "SPECIAL"
			break;
		}
		case 5:					//ADC_01_CS
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,0); // Add B
			digSetOutBit(13,0); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}

		case 6:					//POT_01_CS
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,0); // Add A
			digSetOutBit(12,1); // Add B
			digSetOutBit(13,0); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}

		case 7:					//POT_02_CS
		{	
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,1); // Add B
			digSetOutBit(13,0); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}

	
		case 8:					//ADC_02_CS
		{	
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,0); // Add B
			digSetOutBit(13,1); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
		case 9:					//POT_03_CS
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,0); // Add A
			digSetOutBit(12,1); // Add B
			digSetOutBit(13,1); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
		case 10:				//POT_04_CS
		{
			digSetOutBit(10,0);	// Enable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,1); // Add B
			digSetOutBit(13,1); // Add C
			digSetOutBit(14,0);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
	
		case 99:
		{
			digSetOutBit(10,1);	// Disable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,1); // Add B
			digSetOutBit(13,1); // Add C
			digSetOutBit(14,1);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}	

	
		default: 
		{
			digSetOutBit(10,1);	// Disable
			digSetOutBit(11,1); // Add A
			digSetOutBit(12,1); // Add B
			digSetOutBit(13,1); // Add C
			digSetOutBit(14,1);	// Add D
			PIC_DIO_05_CS = 1;
			break;
		}
	}
	 
	//sprintf(spiOutBuff, "\r\nIn CSAdd, CS = %d\r\n", address);
	//serPutString(SER_CONSOLE, spiOutBuff);

	return;
}

/****************************************************************************/
/*                               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 actResetCmd(char* s)
{
    asm("reset");
    return ERR_SUCCESS;
}

int actHelloKittyCmd(char* s)
{
    sprintf(spiOutBuff, "MEOW\r\n");
    return ERR_SUCCESS;
}

int actSpi2TestCmd(char* s)
{
    unsigned char in1 = 0, in2 = 0, in3 = 0;
    unsigned int i;
    
    while (1)
    {
        CSAddSet(8);
        spiReadWrite2(0b10000111);
        Nop();
        
        in1 = spiReadWrite2(0);
        in2 = spiReadWrite2(0);
        in3 = spiReadWrite2(0);
        
        //CSAddSet(99);
        sprintf(msg_buff, "in1 = %d, in2 = %d, in3 = %d\r\n", in1, in2, in3);
        serPutString(SER_CONSOLE, msg_buff);
    }
    
    return ERR_SUCCESS;
}

/****************************************************************************/
/*                               Get commands                               */
/****************************************************************************/
int actGetConditions(char* s)
{
	int OC, OV, UV;
	int channel = atoi(s);

	OC = condOverCurr(channel);
	OV = condOverVolt(channel);
	UV = condUnderVolt(channel);

	sprintf(msg_buff, "OC: %d\r\n", OC);
	serPutString(SER_CONSOLE, msg_buff);
	sprintf(msg_buff, "OV: %d\r\n", OV);
	serPutString(SER_CONSOLE, msg_buff);
	sprintf(msg_buff, "UV: %d\r\n\n", UV);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;
}

int actGetBrkrState(char* s)
{
	int chan = atoi(s);
	int state;

	state = brkrState(chan);

	sprintf(msg_buff, "BRKR STATE: %d\r\n", state);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;
}

int actGetRelayState(char* s)
{
	int chan = atoi(s);
	int state;

	state = relayState(chan);

	sprintf(msg_buff, "RELAY STATE: %d\r\n", state);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;
}

int actGetCardInfoCmd(char* s)
{
    cardInfoDump(&cardInfo);
    return ERR_SUCCESS;
}

int actGetDinCmd(char* s)
{
    int bit = atoi(s);
    
    if ( digGetInBit(bit) )
        sprintf(spiOutBuff, "BIT %d IS HI\r\n", bit);
    else
        sprintf(spiOutBuff, "BIT %d IS LO\r\n", bit);

    serPutString(SER_CONSOLE, spiOutBuff);

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

    serPutString(SER_CONSOLE, spiOutBuff);

    return ERR_SUCCESS;
}

int actGetSpiStatsCmd(char* s)
{
    unsigned int stat;
    
    stat = spiGetIrqCnt();
    sprintf(msg_buff, "SPI IRQ COUNT = %u\r\n", stat);
    serPutString(SER_CONSOLE, msg_buff);
    
    stat = spiGetCmdCnt();
    sprintf(msg_buff, "SPI CMD COUNT = %u\r\n", stat);
    serPutString(SER_CONSOLE, msg_buff);
    
    stat = spiGetInfoCnt();
    sprintf(msg_buff, "SPI INFO COUNT = %u\r\n", stat);
    serPutString(SER_CONSOLE, msg_buff);
    
    stat = spiGetReadCnt();
    sprintf(msg_buff, "SPI READ COUNT = %u\r\n", stat);
    serPutString(SER_CONSOLE, msg_buff);
    
    stat = spiGetWriteCnt();
    sprintf(msg_buff, "SPI WRITE COUNT = %u\r\n", stat);
    serPutString(SER_CONSOLE, msg_buff);
    
    if ( SPI1STATbits.SPIROV )
        serPutString(SER_CONSOLE, "SPI OVERFLOW BIT  = 1\r\n");
    else
        serPutString(SER_CONSOLE, "SPI OVERFLOW BIT  = 0\r\n");


    sprintf(msg_buff, "SPI1STAT = 0x%04X\r\n", SPI1STAT);
    serPutString(SER_CONSOLE, msg_buff);


    if ( _SPI1IF )
        serPutString(SER_CONSOLE, "_SPI1IF = 1\r\n");
    else
        serPutString(SER_CONSOLE, "_SPI1IF = 0\r\n");

    if ( _SPI1IE )
        serPutString(SER_CONSOLE, "_SPI1IE = 1\r\n");
    else
        serPutString(SER_CONSOLE, "_SPI1IE = 0\r\n");

    return ERR_SUCCESS;
}


/****************************************************************************/
/*                               Set commands                               */
/****************************************************************************/
int actSetWiper3(char* s)
{
	int dummy, data;
	int val = atoi(s);

	dummy = potReadWrite(POT_01_CS, WRITE, WIPER_3, val);
	data = potReadWrite(POT_01_CS, READ, WIPER_3, 0);
	sprintf(msg_buff, "WIPER 3 READ AS: %d\r\n", data);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;
}

int actSetBrkrReset(char* s)
{
	int chan = atoi(s);

	brkrReset(chan);

	return ERR_SUCCESS;

}

int actSetRelayOn(char* s)
{
	int chan = atoi(s);

	relayOn(chan);

	return ERR_SUCCESS;

}

int actSetRelayOff(char* s)
{
	int chan = atoi(s);

	relayOff(chan);

	return ERR_SUCCESS;

}

int actSetOC1Cmd(char* s)
{	
	int dummy, data, OC;
	int NUM = atoi(s);
	OC = NUM;

	//OV = Round(NUM/.125);
	dummy = potReadWrite(POT_01_CS, WRITE, WIPER_0, OC);
	sprintf(msg_buff, "CHAN1 OVER CURRENT SET TO: %d\r\n", NUM);
	serPutString(SER_CONSOLE, msg_buff);
	data = potReadWrite(POT_01_CS, READ, WIPER_0, 0);
	sprintf(msg_buff, "CHAN1 OVER CURRENT READ AS: %d\r\n", data);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;

}

int actSetOV1Cmd(char* s)
{	
	int dummy, data, OV;
	int NUM = atoi(s);
	OV = NUM;

	//OV = Round(NUM/.125);
	dummy = potReadWrite(POT_01_CS, WRITE, WIPER_1, OV);
	sprintf(msg_buff, "CHAN1 OVER VOLTAGE SET TO: %d\r\n", NUM);
	serPutString(SER_CONSOLE, msg_buff);
	data = potReadWrite(POT_01_CS, READ, WIPER_1, 0);
	sprintf(msg_buff, "CHAN1 OVER VOLTAGE READ AS: %d\r\n", data);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;

}

int actSetUV1Cmd(char* s)
{	
	int dummy, data, UV;
	int NUM = atoi(s);
	UV = NUM;

	//OV = Round(NUM/.125);
	dummy = potReadWrite(POT_01_CS, WRITE, WIPER_2, UV);
	sprintf(msg_buff, "CHAN1 UNDER VOLTAGE SET TO: %d\r\n", NUM);
	serPutString(SER_CONSOLE, msg_buff);
	data = potReadWrite(POT_01_CS, READ, WIPER_2, 0);
	sprintf(msg_buff, "CHAN1 UNDER VOLTAGE READ AS: %d\r\n", data);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;

}

int actSetOC2Cmd(char* s)
{	
	int dummy, data, OC;
	int NUM = atoi(s);
	OC = NUM;
	//OV = Round(NUM/.125);

	dummy = potReadWrite(POT_02_CS, WRITE, WIPER_0, OC);
	sprintf(msg_buff, "CHAN2 OVER CURRENT SET TO: %d\r\n", NUM);
	serPutString(SER_CONSOLE, msg_buff);


	return ERR_SUCCESS;

}

int actSetOV2Cmd(char* s)
{	
	int dummy, data, OV;
	int NUM = atoi(s);
	OV = NUM;
	//OV = Round(NUM/.125);

	dummy = potReadWrite(POT_02_CS, WRITE, WIPER_1, OV);
	sprintf(msg_buff, "CHAN2 OVER VOLTAGE SET TO: %d\r\n", NUM);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;

}

int actSetUV2Cmd(char* s)
{	
	int dummy, data, UV;
	int NUM = atoi(s);
	UV = NUM;

	//OV = Round(NUM/.125);
	dummy = potReadWrite(POT_02_CS, WRITE, WIPER_2, UV);
	sprintf(msg_buff, "CHAN2 UNDER VOLTAGE SET TO: %d\r\n", NUM);
	serPutString(SER_CONSOLE, msg_buff);

	return ERR_SUCCESS;

}

int actSetStubCmd(char* s)
{
    int num = atoi(s);
    
    sprintf(spiOutBuff, "actSetStubCmd() = %d\r\n", num);
    serPutString(SER_CONSOLE, msg_buff);

    return ERR_SUCCESS;
}

int actSetDoutCmd(char* s)
{
    int bit = atoi(s);
    
    digSetOutBit(bit, 1);

    return ERR_SUCCESS;
}

int actSetCSAddCmd(char* s)
{
	int cs = atoi(s);

	CSAddSet(cs);

	return ERR_SUCCESS;
}

/****************************************************************************/
/*                              Clear commands                              */
/****************************************************************************/
int actClrSpiStatsCmd(char* s)
{
    spiClrIrqCnt();
    spiClrCmdCnt();
    spiClrInfoCnt();
    spiClrReadCnt();
    spiClrWriteCnt();

    /* clear SPI overflow */
    SPI1STATbits.SPIROV = 0;
    
    return ERR_SUCCESS;
}

int actClrDoutCmd(char* s)
{
    int bit = atoi(s);
    
    digSetOutBit(bit, 0);

    return ERR_SUCCESS;
}
/******************* misc ***********************/

int Round(float myfloat)
{
  double integral;
  float fraction = (float)modf(myfloat, &integral);
 
  if (fraction >= 0.5)
    integral += 1;
  if (fraction <= -0.5)
    integral -= 1;
 
  return (int)integral;
}
