/*
 * main.c
 *
 *  Created on: Oct 20, 2012
 *      Author: Trol
 */

#include <avr/io.h>
#include <stdlib.h>
#include <stdbool.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
/*
Temperature to ADC value conversation
	-50		501
	-45		489
	-40		477
	-35		465
	-30		453
	-25		441
	-20		429
	-15		417
	-10		405
	-5		394
	0		382
	5		370
	10		358
	15		347
	20		335
	25		323
	30		312
	35		300
	40		289
	45		277
	50		266
	55		255
	60		243
	65		232
	70		221
	75		210
	80		198
	85		187
	90		176
	95		165
	100		154
	105		143
	110		132
	115		121
	120		111
	125		100
	130		89
	135		78
*/

#define FIRST_THRESHOLD_ADC			289	// 40 grad
#define SECOND_THRESHOLD_ADC		277	// 45 grad
#define BACK_SECOND_THRESHOLD		284	// 42 grad
#define BEEPER_TRESHOLD				210	// 75 grad


#define FIRST_THRESHOLD_PWM			180
#define SECOND_THRESHOLD_PWM		255

#define TEMP_SENSOR_ADC_PIN			2
#define SPEAKER_PIN					1

#define START_BEEP_NUMBER			1
#define START_BEEP_DURATION			20

#define WARNING_BEEP_PERIOD			500

#define BEEPER_AC					0


inline static void setPower(uint8_t val);
inline static uint8_t calcPower(uint16_t v);
inline static void adcStart(uint8_t pin);


volatile bool beep = false;


/**
 * ADC interrupt handler
 */
ISR(ADC_vect) {
	uint8_t admux = ADMUX & 3;
	if ( admux == TEMP_SENSOR_ADC_PIN ) {
		uint16_t v;

		v = ADCL;
		v += ADCH << 8;

		setPower(calcPower(v));
		adcStart(TEMP_SENSOR_ADC_PIN);

		beep = v < BEEPER_TRESHOLD;

		wdt_reset();
	}
}

/**
 *
 */
inline static void adcStart(uint8_t pin) {
	ADMUX = pin;// | _BV(REFS0);	// not use internal 1.1V voltage reference
	// enable ADC, start convert, enable interrupt, prescaler = 64
	ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1);
}


/**
 *
 */
inline static void setup() {
	// pins
	DDRB = _BV(0)|_BV(1);
	PORTB = 0;

	// PWM
	TCCR0A = _BV(WGM01)|_BV(WGM00)|_BV(COM0A1);
	TCCR0B = _BV(CS00);

	OCR0A = 0;

	sei();
}


/**
 *
 */
inline static void setPower(uint8_t val) {
	OCR0A = val;
}


/**
 *
 */
inline static uint8_t calcPower(uint16_t v) {

	static uint16_t disableCount = 0;
	static bool backFromSecond = false;

	if ( v <= SECOND_THRESHOLD_ADC ) {
		disableCount = 50000;
		backFromSecond = true;
		return SECOND_THRESHOLD_PWM;
	}
	if ( v <= FIRST_THRESHOLD_ADC ) {
		disableCount = 50000;
		if ( backFromSecond && v <= BACK_SECOND_THRESHOLD ) {
			return SECOND_THRESHOLD_PWM;
		}
		backFromSecond = false;
		return FIRST_THRESHOLD_PWM;
	}
	backFromSecond = false;
	if ( disableCount > 0 ) {
		disableCount--;
		return FIRST_THRESHOLD_PWM;
	}
	return 0;
}



/**
 *
 */
int main(void) {
	setup();

	wdt_enable(WDTO_250MS);

	adcStart(TEMP_SENSOR_ADC_PIN);

	bool on = false;
	uint16_t pulseCounter = 0;
	bool startBeep = true;
	while(1) {
		if (beep || startBeep) {
			_delay_us(1000);

			if ( startBeep ) {
				if (++pulseCounter % 1000 < START_BEEP_DURATION) {
#if BEEPER_AC
					on = false;
#else
					on = !on;
#endif
				}
				if ( pulseCounter > START_BEEP_DURATION*START_BEEP_NUMBER*2 ) {
					startBeep = false;
					on = false;
				}
			} else {
				if (++pulseCounter % WARNING_BEEP_PERIOD*2 < WARNING_BEEP_PERIOD) {
#if BEEPER_AC
					on = false;
#else
					on = !on;
#endif
				}
			}


			if (on) {
				PORTB |= _BV(SPEAKER_PIN);
			} else {
				PORTB &= ~_BV(SPEAKER_PIN);
			}
#if BEEPER_AC
			on = !on;
#endif
		} else {
			on = false;
			PORTB &= ~_BV(SPEAKER_PIN);
		}
	}

}

