//How to Make (almost) Anything 2013
//Jeff Duval - jfduval@mit.edu
//10/28/2013
//==================================
//Capacitive button turns the lamp ON/OFF
//Potentiometer changes the brightness

#include <device.h>
#include <stdio.h>
#include <math.h>

uint8 ReadButton0(void)
{
	uint8 cap_value = 0;
	
	/* Update all baselines */
	CapSense_UpdateEnabledBaselines();
		
	/* Start scanning all enabled sensors */
	CapSense_ScanEnabledWidgets();	
	
	/* Wait for scanning to complete */
	while(CapSense_IsBusy()); 
		
	cap_value = CapSense_CheckIsSensorActive(CapSense_BUTTON0__BTN);
	
	return(cap_value);
}

#define MAX_CNT	2047
#define MIN_CNT 0
#define MAX_PWM	1842	//90%
#define MIN_PWM	21		//1%

//Gamma compensation
uint16 adc_to_pwm(uint16 adc)
{
	double adc_float = 0.0, buf = 0.0;
	uint16 out_pwm = 0;
	
	//Make sure ADC's in the range
	if(adc <= MIN_CNT)
		adc = 0;
	if(adc >= MAX_CNT)
		adc = MAX_CNT;
	
	//Convert to float, 0-1
	adc_float = (double)adc/2047.0;
	
	//Gamma decoding:
	buf = 2047*(pow(adc_float,2.5));
	
	//Back to uint16
	out_pwm = (uint16) buf;
	
	//PWM clipping:
	if(out_pwm <= MIN_PWM)
		out_pwm = MIN_PWM;
	if(out_pwm >= MAX_PWM)
		out_pwm = MAX_PWM;	
	
	//Return value
	return (out_pwm);	
}


void main()
{
	uint8 cnt = 0, button = 0;
	int16 adc_data = 0;
	uint16 pwmdc = 0;
	
	/* Enable Global Interrupts */
	CyGlobalIntEnable;
	
	/* Start the Clock and PWM components. Clock can be started automatically 
	after reset by enabling “Start on Reset” in the Clocks tab of 
	Blinking LED.cydwr. We are doing this manually for instructive purpose. */
	CapSense_Start();
	
	/* Initialize CapSense baselines by scanning enabled sensors */
    CapSense_InitializeAllBaselines();
	
	//Manual output setup:
	CY_SYS_PINS_SET_DRIVE_MODE(CYREG_PRT1_PC,0,CY_SYS_PINS_DM_STRONG);	//LED1
	CY_SYS_PINS_SET_DRIVE_MODE(CYREG_PRT1_PC,1,CY_SYS_PINS_DM_STRONG);	//LED2
	CY_SYS_PINS_SET_DRIVE_MODE(CYREG_PRT1_PC,2,CY_SYS_PINS_DM_STRONG);	//LED3	
	
	//Start ADC
	ADC_SAR_Seq_1_Start();
	ADC_SAR_Seq_1_StartConvert();
	
	//Start PWM
	PWM_1_WriteCompare(0);	//Initially off
	PWM_1_Start();
	
	for(;;)
    {
		//Read pot value (12 bits)
		adc_data = ADC_SAR_Seq_1_GetResult16(0);		
		if(adc_data < 0)
			adc_data = 0;
		
		//Format for PWM:
		pwmdc = (uint16)adc_data;
		if(pwmdc > 2047)
			pwmdc = 2047;
		else if(pwmdc < 0)
			pwmdc = 0;		
		
		//Read CapSense button
		button = ReadButton0();
		if(button)
		{
			while(ReadButton0());
			cnt++;
			
			CyDelay(50);
		}		
		
		//2 possible states
		if(cnt > 1)
			cnt = 0;		
		*(reg32 *) CYREG_PRT1_DR = cnt;
		
		//State machine
		switch(cnt)
		{
			case 0:
				PWM_1_WriteCompare(0);	//Light off
				break;
			case 1:
				PWM_1_WriteCompare(adc_to_pwm(pwmdc));	//PWM controls light
				break;
			case 2:
			case 3:
				//Unused for now. Does not change value
				break;
			default:
				PWM_1_WriteCompare(0);	//Light off
		}
    }
}

/* [] END OF FILE */
