// ---------------------------------------
// ***************************************
// CAPACITIVE WET SENSOR BASED ON TINY2313
// ***************************************
// ---------------------------------------

#define F_CPU 8000000UL // use internal RC

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

volatile unsigned char state = 0; 	// program state control flag
unsigned long timer_sum = 0;		// sum of 16x TCNT1 samples @ 2^16 bit
volatile unsigned short output = 0;
unsigned short average =0;	// sum over 16


int main(void)
{

	// bar graph outputs
	DDRD |= (1<<PD0); 	// Enable Output: White LED - 0
	DDRA |= (1<<PA1); 	// Enable Output: Red LED - 1
	DDRA |= (1<<PA0); 	// Enable Output: Red LED - 2
	DDRD |= (1<<PD2);	// Enable Output: Green LED - 3
	DDRD |= (1<<PD3);	// Enable Output: Green LED - 4
	DDRD |= (1<<PD4);	// Enable Output: Blue LED - 5
	DDRD |= (1<<PD5);	// Enable Output: Blue LED - 6

	// turn off all LEDs by putting output high (sink mode)
	PORTD |= (1 << PD0)|(1 << PD2)|(1 << PD3)|(1 << PD4)|(1 << PD5); 
	PORTA |= (1 << PA0)|(1 << PA1);

	// toggle white LED on startup, debugging purposes 
	PORTD ^= (1 << PD0);   // white toggle
	PORTD ^= (1 << PD0);   // white toggle
 	
	TCCR1A = 0; //Setup timer1 to normal operation 
 	 
  	// Setup analog comperator to generate rising edge interrupt 
	DIDR |= (1<<AIN1D)|(1<<AIN0D); 						// disable digital input buffer for analog comp in
  	ACSR |= (1<<ACIE)|(1<<ACIC)|(0<<ACIS1)|(0<<ACIS0); 	// setup & enable ana comp
	
	// enable pwm output on pb2, timer 0 output A 
	DDRB |= (1 << PB2); 				// enable output on pwm pin
	TCCR0A |= (1<<WGM01)|(1<<WGM00);;	// Fast PWM, TOP = 0xFF
	TCCR0A |= (1<<COM0A1)|(1<<COM0A0); 	// Set OC0A on Compare Match, clear OC0A at TOP
	TCCR0B |= (1<<CS00);//|(1<<WGM02); 	// No prescaling
	OCR0A = 0; 							// Initial output 0% duty cycle
	TIMSK |= (1<<TOIE0); 				// enable overflow interrupt of timer 0

	sei(); // enable int.



	while (1)
		{
			
		if (state == 0) // start new cycle 
			{
			DDRB |= (1<<PB0);	// set ain0 low to discharge cap
			_delay_us(5);		// wait for discharge
			DDRB &= ~(1<<PB0); 	// return ain0 to normal input

			state = 1;			// set state to next step (wait for ana comp ISR)
		
			TCNT1 =0;			// reset timer register
			TCCR1B = (1<<CS10);	// enable timer
			}
		
		if (state ==2) // only after ISR has triggered (after measurement)
			{
			timer_sum -= (timer_sum / 128); 	// subtract 1/128 from total, leaving 127/128 of total
			timer_sum += TCNT1; 				// add in 1/128 from timer1
			average = timer_sum / 128;			// calculate composite rolling average
			output = (timer_sum-256000) / 875;	// shift and div to get 0-255 range
			if (output > 255) { output = 255; } // check and fix overflow 
			
			// LED bar graph from average, 7 LEDS, increments of ~ xxx
			switch (average)  
				{ 
				case 0 ... 2536: 		// white - 0 - PD0
					PORTD &= ~(1<<PD0);
					PORTD |= (1 << PD2)|(1 << PD3)|(1 << PD4)|(1 << PD5); 
					PORTA |= (1 << PA0)|(1 << PA1);
					break;

				case 2537 ... 2723: 	// red - 1 - PA1
					PORTA &= ~(1 << PA1);
					PORTD |= (1 << PD0)|(1 << PD2)|(1 << PD3)|(1 << PD4)|(1 << PD5); 
					PORTA |= (1 << PA0);
					break;

				case 2724 ... 2910: 	// red - 2 - PA0
					PORTA &= ~(1 << PA0);
					PORTD |= (1 << PD0)|(1 << PD2)|(1 << PD3)|(1 << PD4)|(1 << PD5); 
					PORTA |= (1 << PA1);
					break;

				case 2911 ... 3097: 	// green - 3 - PD2
					PORTD &= ~(1<<PD2);
					PORTD |= (1 << PD0)|(1 << PD3)|(1 << PD4)|(1 << PD5); 
					PORTA |= (1 << PA0)|(1 << PA1);
					break;

				case 3098 ... 3284: 	// green - 4 - PD3
					PORTD &= ~(1<<PD3);
					PORTD |= (1 << PD0)|(1 << PD2)|(1 << PD4)|(1 << PD5); 
					PORTA |= (1 << PA0)|(1 << PA1);
					break;
				
				case 3285 ... 3471: 	// blue - 5 - PD4
					PORTD &= ~(1<<PD4);
					PORTD |= (1 << PD0)|(1 << PD2)|(1 << PD3)|(1 << PD5); 
					PORTA |= (1 << PA0)|(1 << PA1);
					break;

				case 3472 ... 65535: 	// blue - 6 - PD5
					PORTD &= ~(1<<PD5);
					PORTD |= (1 << PD0)|(1 << PD2)|(1 << PD3)|(1 << PD4); 
					PORTA |= (1 << PA0)|(1 << PA1);
					break;
				}

			state =0; // return state to repeat cycle
			}

		} // end of while loop


}

ISR (SIG_COMPARATOR)
	{
	if (ACSR & (1<<ACO)) // check if done
		{
		TCCR1B = 0;		// stop timer
		state = 2;		// measurement taken, procede to next step (calc average)
		}

	}

ISR (SIG_OVERFLOW0)
	{
	OCR0A = output;	// update pwm on overflow
	}

