/****************************************************************************/
/* 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 "spi1.h"
#include "spi2.h"
#include "analog.h"
#include "dig_io.h"

static char msg_buff[64];

/****************************************************************************/
/*                               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)
{
    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 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;
}

int actGetADCCmd(char* s)
{
	int bit = atoi(s);
	unsigned int analog1 = 0;
	unsigned int analog2 = 0;
	unsigned int analog3 = 0;
	unsigned int analog4 = 0;
	unsigned int analog5 = 0;
	unsigned int analog6 = 0;
	int conword = 0;
  	double value = 0;
	int cs_add = 0;

	if (bit < 9)
		cs_add = 8;
	else
		cs_add = 9;

		switch (bit) // Establish Control Word for each bit
		{
			case 0: conword = 134; break; // 8344 ch 0
			case 1: conword = 198; break; // 8344 ch 1
			case 2: conword = 150; break; // 8344 ch 2
			case 3: conword = 214; break; // 8344 ch 3
			case 4: conword = 166; break; // 8344 ch 4
			case 5: conword = 230; break; // 8344 ch 5
			case 6: conword = 182; break; // 8344 ch 6
			case 7: conword = 246; break; // 8344 ch 7
			case 8: conword = 150; break; // 8341 ch 0
			case 9: conword = 166; break; // 8341 ch 1
			case 10: conword = 86; break; // 8341 ch 2
			case 11: conword = 214; break; // 8341 ch 3
			default: break;
		}



	CSAddSet(cs_add);

	SPI2STATbits.SPIROV = 1;
	// spiReadWrite2(2); // setup up clock type in ADC chip (internal)
	Nop();
	
	spiReadWrite2(conword); // Send ADC control word
	Nop();
	analog1 = spiReadWrite2(0x00); // MSB
	analog2 = spiReadWrite2(0x00); // LSB
	analog3 = spiReadWrite2(0x00); // Extra Bit + Trailing zeroes?

	CSAddSet(99);
 
	/* Combine 2 8-bit analog words to 1 16-bit word */	
	analog4 = analog1;
    analog4 <<= 8;
    analog4 |= (0x00FF & analog2);

	analog4 <<=1; // shift resulting word 1 bit left

	analog3 >>= 7; // shift Extra bit to '1' position
	analog5 = 0x0000;
	analog5 <<=8;
	analog5 |= (0x00FF & analog3); // Mask Extra bit into 16-bit word

	analog6 = (analog4 | analog5); // Add Extra bit onto 16-bit word



	value = anaConvSample(bit, analog6,2);
	
	sprintf(msg_buff, "\r\nReturned Value = %f\r\n", value);
	serPutString(SER_CONSOLE, msg_buff);
	
	return ERR_SUCCESS;
}




/****************************************************************************/
/*                               Set commands                               */
/****************************************************************************/
int actSetStubCmd(char* s)
{
    int num = atoi(s);
    
    sprintf(msg_buff, "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;
}

/***************************************************************************/
/*                         Environ Bd Commands                             */
/***************************************************************************/
void CSAddSet(int address)
{
	switch(address)
	{
		case 0:
		{
			digSetOutBit(0,0);  // Add A
			digSetOutBit(1,0);  // Add B
			digSetOutBit(2,0);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}
		case 1:
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,0);  // Add B
			digSetOutBit(2,0);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}

		case 2:
		{
			digSetOutBit(0,0);  // Add A
			digSetOutBit(1,1);  // Add B
			digSetOutBit(2,0);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}

		case 3:
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,1);  // Add B
			digSetOutBit(2,0);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}
		case 4:
		{
			digSetOutBit(0,0);  // Add A
			digSetOutBit(1,0);  // Add B
			digSetOutBit(2,1);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}
	
		case 5:
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,0);  // Add B
			digSetOutBit(2,1);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}
		case 6:
		{
			digSetOutBit(0,0);  // Add A
			digSetOutBit(1,1);  // Add B
			digSetOutBit(2,1);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}
		case 7:
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,1);  // Add B
			digSetOutBit(2,1);  // Add C
			digSetOutBit(3,0);	// Add D
			break;
		}
		case 8:
		{
			digSetOutBit(0,0);  // Add A
			digSetOutBit(1,0);  // Add B
			digSetOutBit(2,0);  // Add C
			digSetOutBit(3,1);	// Add D
			break;
		}
		case 9:
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,0);  // Add B
			digSetOutBit(2,0);  // Add C
			digSetOutBit(3,1);	// Add D
			break;
		}	
		case 99:
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,1);  // Add B
			digSetOutBit(2,1);  // Add C
			digSetOutBit(3,1);	// Add D
			break;
		}	

	
		default: 
		{
			digSetOutBit(0,1);  // Add A
			digSetOutBit(1,1);  // Add B
			digSetOutBit(2,1);  // Add C
			digSetOutBit(3,1);	// Add D
			break;
		}
	}
	 
	sprintf(msg_buff, "\r\nIn CSAdd, CS = %d\r\n", address);
	serPutString(SER_CONSOLE, msg_buff);

	return;
}
