/*******************************************************************************
* Name: demo.c 
* 
* Description: Demo Functions that use the API calls in this project. 
* 
* Texas Instruments, Inc
* 
* Version: 1.0
*******************************************************************************/

/*
 * Copyright (C) {2011} Texas Instruments Incorporated - http://www.ti.com/ 
 * 
 * 
 *  Redistribution and use in source and binary forms, with or without 
 *  modification, are permitted provided that the following conditions 
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the   
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
*/

// Include Project Library Headers
#include "device.h"
#include "init.h"
#include "LED.h"
#include "PWM.h"
#include "SMBus.h"
#include "misc.h"

/* ****************************************************************************
 * Function Name: ADC_Demo
 * 
 * Description: Demo function to test out the functionality of the ADC
 * routines. Data read from the slave device is stored in local variables. 
 * ***************************************************************************/
void ADC_Demo(void)
{
	
	volatile unsigned int Batt_1_V = 0;
	volatile unsigned int Batt_1_I = 0;
	volatile unsigned int Batt_2_V = 0;
	volatile unsigned int Batt_2_I = 0;
		
	ADC_Init();
	Batt_1_V = VI_ADC_Read(BATT_1, CHANNEL_VOLTAGE);
	Batt_1_I = VI_ADC_Read(BATT_1, CHANNEL_CURRENT);
	Batt_2_V = VI_ADC_Read(BATT_2, CHANNEL_VOLTAGE);
	Batt_2_I = VI_ADC_Read(BATT_2, CHANNEL_CURRENT);
	
	// Set Breakpoint Here
	__no_operation();	
}

/* ****************************************************************************
 * Function Name: SMBus_Slave_Demo
 * 
 * Description: Demo function to test out the functionality of the SMBus
 * routines with the MSP430 configured as a SLAVE. Data written to the MSP430
 * device is stored. 
 * ***************************************************************************/
void SMBus_Slave_Demo(void)
{
	volatile unsigned int charging_current = 0;
	volatile unsigned int charging_voltage = 0;
	volatile unsigned int battery_status = 0;
	volatile unsigned char smbus_command = 0;
	
	/* 
	 * Because the bq device broadcasts the charging voltage/current every  
	 * 30-60 seconds but broadcasts battery status every 6-15 seconds, a 
	 * polling loop is required which will look for the battery status command
	 * and store only the latest battery status. When it detects a command
	 * different than battery status, it breaks out of the loop and stores
	 * the charging current & charging voltage.
	 */
	do {
		
		// Initialize the MSP430 to slave mode for receiving bytes
		SMBus_Initialize(SMBUS_SLAVE_MODE);	
		SMBus_Monitor_Slave_Broadcast();	// Monitor for Broadcast
		SMBus_Reset(SMBus_Start_Flag);		// Reset the Bus 
		SMBus_Start_Flag = SMBUS_START_FLAG_RESET; 

		// Parse out the command byte				
		smbus_command = SMBus_Data_To_Slave[0];
		if(smbus_command == SBS_CMD_BATTERY_STATUS)
		{
			// If the command byte matches, then parse the data bytes
			battery_status = SMBus_Data_To_Slave[2] << 8 | SMBus_Data_To_Slave[1];
		}
		
	} while(smbus_command == SBS_CMD_BATTERY_STATUS);
		
	// Parse out the command byte		
	if(smbus_command == SBS_CMD_CHARGING_CURRENT)
	{
		// If the command byte matches, then parse the data bytes
		charging_current = SMBus_Data_To_Slave[2] << 8 | SMBus_Data_To_Slave[1];
	}	
	
	// Initialize the MSP430 to slave mode for receiving bytes
	SMBus_Initialize(SMBUS_SLAVE_MODE);	
	SMBus_Monitor_Slave_Broadcast();
	SMBus_Reset(SMBus_Start_Flag);		// Reset the Bus 
	SMBus_Start_Flag = SMBUS_START_FLAG_RESET; 
			
	// Parse out the command byte				
	smbus_command = SMBus_Data_To_Slave[0];
	if(smbus_command == SBS_CMD_CHARGING_VOLTAGE)
	{
		// If the command byte matches, then parse the data bytes
		charging_voltage = SMBus_Data_To_Slave[2] << 8 | SMBus_Data_To_Slave[1];
	}	
	
	// Set Breakpoint Here
	__no_operation();	
	
}	

/* ****************************************************************************
 * Function Name: SMBus_Master_Demo
 * 
 * Description: Demo function to test out the functionality of the SMBus
 * routines with the MSP430 configured as a MASTER. Data read from the slave 
 * device is stored in local variables. 
 * ***************************************************************************/
void SMBus_Master_Demo(void)
{
	volatile unsigned char smbus_access_status = 0x0;
	volatile unsigned int slave_voltage = 0;
	volatile signed int slave_current = 0;
	volatile signed int slave_average_current = 0;
	volatile unsigned int slave_charging_current = 0;
	volatile unsigned int slave_charging_voltage = 0;
	volatile unsigned int slave_cell_voltage_1 = 0;
	volatile unsigned int slave_cell_voltage_2 = 0;
	volatile unsigned int slave_cell_voltage_3 = 0;
	volatile unsigned int slave_cell_voltage_4 = 0;
	volatile unsigned char slave_manufacturer_name[12];
	volatile unsigned char slave_device_name[8];
	volatile unsigned int slave_design_voltage = 0;
	volatile unsigned int slave_temperature = 0;
	volatile unsigned int slave_battery_status = 0;
	
	// Initialize the MSP430 as a MASTER
	SMBus_Initialize(SMBUS_MASTER_MODE);	
		
	// Read Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_VOLTAGE, SMBUS_MASTER_MODE_READ, 2);	
	slave_voltage = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Voltage (mV) 
	smbus_access_status = SMBus_Access_PEC(SBS_CMD_VOLTAGE, SMBUS_MASTER_MODE_READ, 2);	
	slave_voltage = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Current (mA) 
	smbus_access_status = SMBus_Access(SBS_CMD_CURRENT, SMBUS_MASTER_MODE_READ, 2);
	slave_current = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Average Current (mA) 
	smbus_access_status = SMBus_Access(SBS_CMD_AVERAGE_CURRENT, SMBUS_MASTER_MODE_READ, 2);
	slave_average_current = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Charging Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CHARGING_VOLTAGE, SMBUS_MASTER_MODE_READ, 2);
	slave_charging_voltage = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Charging Current (mA) 
	smbus_access_status = SMBus_Access(SBS_CMD_CHARGING_CURRENT, SMBUS_MASTER_MODE_READ, 2);			
	slave_charging_current = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Cell 1 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_1, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_1 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Cell 2 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_2, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_2 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Cell 3 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_3, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_3 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Cell 4 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_4, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_4 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Manufacturer Name of the slave device
	smbus_access_status = SMBus_Access(SBS_CMD_MANUFACTURER_NAME, SMBUS_MASTER_MODE_READ, 12);
	{
		unsigned short element = 0;
		for (element = 0; element < 12; element++) 
		{
			slave_manufacturer_name[element] = SMBus_Data_From_Slave[element];
		}
	}
	
	// Read Slave Device Name 
	smbus_access_status = SMBus_Access(SBS_CMD_DEVICE_NAME, SMBUS_MASTER_MODE_READ, 8);
	{
		unsigned short element = 0;
		for (element = 0; element < 8; element++) 
		{
			slave_device_name[element] = SMBus_Data_From_Slave[element];
		}
	}	
	
	// Read Design Voltage (mV)
	smbus_access_status = SMBus_Access(SBS_CMD_DESIGN_VOLTAGE, SMBUS_MASTER_MODE_READ, 2);
	slave_design_voltage = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Write Design Voltage (mV) 	
	SMBus_Data_To_Slave[0] = DESIGN_VOLTAGE_VALUE & (0xFF);
	SMBus_Data_To_Slave[1] = (DESIGN_VOLTAGE_VALUE >> 8) & (0xFF);
	smbus_access_status = SMBus_Access(SBS_CMD_DESIGN_VOLTAGE, SMBUS_MASTER_MODE_WRITE, 2);
	
	// Delay required for data to be written to the EEPROM in the 
	// slave device. 	
	Delay_Timer(4);			
	
	// Initialize the MSP430 as a MASTER
	SMBus_Initialize(SMBUS_MASTER_MODE);	
	
	// Write Design Voltage (mV) 	
	SMBus_Data_To_Slave[0] = DESIGN_VOLTAGE_VALUE & (0xFF);
	SMBus_Data_To_Slave[1] = (DESIGN_VOLTAGE_VALUE >> 8) & (0xFF);
	smbus_access_status = SMBus_Access_PEC(SBS_CMD_DESIGN_VOLTAGE, SMBUS_MASTER_MODE_WRITE, 2);	
	
	// Delay required for data to be written to the EEPROM in the 
	// slave device. 	
	Delay_Timer(4);
	
	// Initialize the MSP430 as a MASTER
	SMBus_Initialize(SMBUS_MASTER_MODE);	

	// Read Cell 1 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_1, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_1 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Cell 2 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_2, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_2 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Cell 3 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_3, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_3 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Dummy delay - for testing only!
	Delay_Timer(1);
	
	// Initialize the MSP430 as a MASTER
	SMBus_Initialize(SMBUS_MASTER_MODE);	
	
	// Read Temperature (0.1 K)
	smbus_access_status = SMBus_Access(SBS_CMD_TEMPERATURE, SMBUS_MASTER_MODE_READ, 2);
	slave_temperature = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Cell 4 Voltage (mV) 
	smbus_access_status = SMBus_Access(SBS_CMD_CELL_VOLTAGE_4, SMBUS_MASTER_MODE_READ, 2);			
	slave_cell_voltage_4 = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];
	
	// Read Design Voltage (mV)
	smbus_access_status = SMBus_Access(SBS_CMD_DESIGN_VOLTAGE, SMBUS_MASTER_MODE_READ, 2);
	slave_design_voltage = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];	
	
	// Read Status Register in Slave
	smbus_access_status = SMBus_Access(SBS_CMD_BATTERY_STATUS, SMBUS_MASTER_MODE_READ, 2);
	slave_battery_status = SMBus_Data_From_Slave[1] << 8 | SMBus_Data_From_Slave[0];		
	
	// Set Breakpoint Here
	__no_operation();
	
}

/* ****************************************************************************
 * Function Name: PWM_Demo
 * 
 * Description: Demo function to test out the PWM signals. 
 * ***************************************************************************/
void PWM_Demo(void)
{
	PWM_Control(BATT_1, CHANNEL_VOLTAGE, PWM_ON, 0.1*PWM_DUTY_100);	// 10% Duty
	PWM_Control(BATT_1, CHANNEL_CURRENT, PWM_ON, 0.2*PWM_DUTY_100); // 20% Duty 
	PWM_Control(BATT_2, CHANNEL_VOLTAGE, PWM_ON, 0.5*PWM_DUTY_100); // 50% Duty
	PWM_Control(BATT_2, CHANNEL_CURRENT, PWM_ON, 0.8*PWM_DUTY_100); // 80% Duty
}

/* ****************************************************************************
 * Function Name: LED_Demo
 * 
 * Description: Demo function to test out the LEDs.  
 * ***************************************************************************/
void LED_Demo(void)
{
	LED_Control(LED_NUM_0,LED_MODE_BLINK,LED_BLINK_RATE_FAST);
    LED_Control(LED_NUM_1,LED_MODE_OFF,LED_BLINK_RATE_SLOW);
    LED_Control(LED_NUM_2,LED_MODE_BLINK,LED_BLINK_RATE_MEDIUM);
    LED_Control(LED_NUM_3,LED_MODE_BLINK,LED_BLINK_RATE_SLOW);
    LED_Control(LED_NUM_4,LED_MODE_ON,LED_BLINK_RATE_MEDIUM);
    LED_Control(LED_NUM_5,LED_MODE_BLINK,LED_BLINK_RATE_SLOW);
    LED_Control(LED_NUM_6,LED_MODE_BLINK,LED_BLINK_RATE_FAST);
}

/* ****************************************************************************
 * Function Name: Fan_Demo
 * 
 * Description: Demo function to test out the Fan port.   
 * ***************************************************************************/
void Fan_Demo(void)
{
	// Initialize Fan port to output
	Fan_Init();
	
	// Turn Fan ON
	Fan_Control(FAN_ON);
	
	// Set Breakpoint Here
	__no_operation();
	
	// Turn Fan OFF
	Fan_Control(FAN_OFF);		
}

/* ****************************************************************************
 * Function Name: Battery_Cal_Demo
 * 
 * Description: Demo function to test out the Battery Calibration Resistors.   
 * ***************************************************************************/
void Battery_Cal_Demo(void)
{
	// Turn on battery calibration resistors
	Calibrate_Battery(BATT_1, CAL_ON);
	Calibrate_Battery(BATT_2, CAL_ON);
	
	// Set Breakpoint Here
	__no_operation();
	
	// Turn off battery calibration resistors
	Calibrate_Battery(BATT_1, CAL_OFF);
	Calibrate_Battery(BATT_2, CAL_OFF);		
		
}

/* ****************************************************************************
 * Function Name: PWM_Ramp_Up_Demo
 * 
 * Description: Demo function to ramp up the PWM output signals.  
 * ***************************************************************************/
void PWM_Ramp_Up_Demo(void)
{
	int counter = 0;			// Loop Counter
	
	// Turn off PWM signals to Battery 2 
	PWM_Control(BATT_2, CHANNEL_VOLTAGE, PWM_OFF, 0*PWM_DUTY_100); // 0% Duty
	PWM_Control(BATT_2, CHANNEL_CURRENT, PWM_OFF, 0*PWM_DUTY_100); // 0% Duty

	// Set the Battery 1, Current PWM to 10% duty cycle 
	PWM_Control(BATT_1, CHANNEL_CURRENT, PWM_ON, 0.1*PWM_DUTY_100);	// 10% Duty
	
	// Gradually ramp up the PWM duty cycle from 1% to 25%
	for(counter = 1; counter < 25; counter++) {
		Delay_Timer(2);			// 50 msec delay
		PWM_Control(BATT_1, CHANNEL_VOLTAGE, PWM_ON, counter*0.01*PWM_DUTY_100); 
	}
}
