//----------------------------------------------------------------------------------
// <copyright file="pib.c" company="LiquidRobotics">
//	Copyright (c) Liquid Robotics Corporation.  All rights reserved.
// </copyright>
//
// <summary>
// 	Implements an alternate statistics tasks customized for the AVR 2650
// </summary>
//
// <owner>Mike Cookson</owner>
//---------------------------------------------------------------------------------

#include "includes.h"
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "pib.h"

/*PAGE*/
/*
 *******************************************************************************
 *                        DISABLES POWER TO ALL PIB MODULES
 *
 * Description :    Disables power to all PIB personality modules; this would be
 *					the initial condition of the program
 *
 * Arguments   :    n/a
 *
 * Returns     :    n/a
 *
 * Notes       :    
 *******************************************************************************
 */
void DisableAllPIBModules()
{
	uint8_t pibNum;

	for (pibNum = 1; pibNum <= 3; ++pibNum)
	{
		pib_module_configure(pibNum);
		pib_module_power_off(pibNum);
	}
}

/*PAGE*/
/*
 *******************************************************************************
 *              ENABLE/DISABLE POWER TO A GIVEN MODULE, DETECT SUCCESS
 *
 * Description :    Enables or disables power to a given PIB module and optionally
 *					detects if the module powered up.
 *
 * Arguments   :    pibNum is the personality module (1..3)
 *
 *                  enablePIB is set to true if the PIB module should be powered
 *					on or false if it should be powered off
 *
 *                  detectEnable is set to true if the routine should fail if
 *					the "power OK" signal does not come on after power is applied
 *					(waits 100 ms and checks up to 2 times)
 *
 * Returns     :    TRUE if successful, FALSE if pibNum is out of range or
 *					detectEnable is true and desired state (powered on or off)
 *					is not reached
 *
 * Notes       :    
 *******************************************************************************
 */
BOOLEAN EnablePIBModule(uint8_t pibNum, BOOLEAN enablePIB, BOOLEAN detectEnable)
{
	// fail if hte pib module is out of range
	if (!valid_pib_module(pibNum))
		return OS_FALSE;

	// set up the basic configuration for the PIB module (pins, etc.)
	pib_module_configure(pibNum);

	// power the PIB on or off, according to parameter
	if (enablePIB)
		pib_module_power_on(pibNum);
	else
		pib_module_power_off(pibNum);

	// if the result should bechecked ...
	if (detectEnable)
	{
		uint8_t times = 2;			// max times to check
		BOOLEAN success;			// status of operation

		// -- checking loop --

		do
		{
			// wait for 100 ms after switching the state
			OSTimeDlyHMSM(0,0,0,100);

			// set the success flag (power OK state should match enable state)
			success = (!!enablePIB == pib_module_power_OK(pibNum));
		}
		while(--times && !success);

		// if at the end the operation was not successful, then power off the PIB
		if (!success)
			pib_module_power_off(pibNum);

		return success;				// returns the success or failure state
	}
	else
		return OS_TRUE;				// if not checking result, just return TRUE
}










#define EEPROM_MAX	0x1000

#define EEPROM_FAIL		0x00
#define EEPROM_SUCCESS	0xFF

uint8_t EepromReadByte(void* eepromAddr, void* pData)
{
	unsigned retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < EEPROM_MAX)
	{
		eeprom_busy_wait();
		*((uint8_t*)pData) = eeprom_read_byte ((const uint8_t *)eepromAddr);
		retval = EEPROM_SUCCESS;
	}

	return retval;
}


uint8_t EepromReadWord(void* eepromAddr, void* pData)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < (EEPROM_MAX - 1))
	{
		eeprom_busy_wait();
		*((uint16_t*)pData) = eeprom_read_word ((const uint16_t *)eepromAddr);
		retval = EEPROM_SUCCESS;
	}

	return retval;
}


uint8_t EepromReadBlock(void* eepromAddr, void* pData, uint16_t length)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < EEPROM_MAX)
	{
		if((EEPROM_MAX - (uint16_t)eepromAddr) >= length)
		{
			eeprom_busy_wait();
			eeprom_read_block(pData, eepromAddr, length);
			retval = EEPROM_SUCCESS;
		}
	}
	 	
	return retval;
}



uint8_t EepromWriteByteSigned(void* eepromAddr, int8_t data)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < EEPROM_MAX)
	{
		eeprom_busy_wait();
		eeprom_write_byte((uint8_t*)eepromAddr, (uint8_t)data); 		
		retval = EEPROM_SUCCESS;
	}

	return retval;
}

uint8_t EepromWriteByteUnSigned(void* eepromAddr, uint8_t data)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < EEPROM_MAX)
	{
		eeprom_busy_wait();
		eeprom_write_byte((uint8_t*)eepromAddr, data); 		
		retval = EEPROM_SUCCESS;
	}

	return retval;
}



uint8_t EepromWriteWordSigned(void* eepromAddr, int16_t data)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < (EEPROM_MAX - 1))
	{
		eeprom_busy_wait();
		eeprom_write_word((uint16_t*)eepromAddr, (uint16_t)data); 		
		retval = EEPROM_SUCCESS;
	}

	return retval;
}


uint8_t EepromWriteWordUnSigned(void* eepromAddr, uint16_t data)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < (EEPROM_MAX - 1))
	{
		eeprom_busy_wait();
		eeprom_write_word((uint16_t*)eepromAddr, data); 		
		retval = EEPROM_SUCCESS;
	}

	return retval;
}



uint8_t EepromWriteBlock(void* eepromAddr, void* pData, uint16_t length)
{
	uint8_t retval = EEPROM_FAIL;

	if((uint16_t)eepromAddr < EEPROM_MAX)
	{
		if((EEPROM_MAX - (uint16_t)eepromAddr) >= length)
		{
			eeprom_busy_wait();
			eeprom_write_block(pData,eepromAddr, length);
			retval = EEPROM_SUCCESS;
		}
	}
	 		
	return retval;
}



//Command Parsing Routine
char getCommand(char** myCommand, prog_char* cmdListLong_P, uint8_t cmdSize, uint8_t numCmds, prog_char* cmdList_P, char* pParserList)
{
	char command = 0;
	char* result = NULL;

	if(strncmp(*myCommand, "--", 2) == 0)
	{
		//long command
		*myCommand+=2;
		result = strtok_r(NULL, pParserList, myCommand);

		for(int i = 0; i<numCmds; i++)
		{
			if(strncasecmp_P(result, cmdListLong_P, strlen_P(cmdListLong_P)) == 0)
			{
				memcpy_P(&command, &cmdList_P[i], 1);
				break;
			}
			cmdListLong_P += cmdSize;
		}
	}
	else if(strncmp(*myCommand, "-", 1) == 0)
	{
		//short Command
		*myCommand+=1;
		command = **myCommand;
		*myCommand+=1;

		if(memchr_P(cmdList_P, command, strlen_P(cmdList_P)) == NULL)
			command = 0;
	}

	return command;
}
