/*****************************************************
Chip type           : ATmega8L
Program type        : Application
Clock frequency     : 8.00 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

// Min and max motor voltages - outside this range, controller will not operate
#define MIN_BATT_VOLTAGE 15
#define MAX_BATT_VOLTAGE 30

// Max motor voltage - can be used if the battery voltage is higher than the max motor voltage
// This will restrict the maximum output voltage by limiting PWM if batt voltage is greater than this
#define MAX_MOTOR_VOLTAGE 999

#include <mega8.h>

// Standard Input/Output functions
#include <stdio.h>

unsigned char p; // p for pulse width

#define ADC_VREF_TYPE 0x40

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
	ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
	// Start the AD conversion
	ADCSRA|=0x40;
	// Wait for the AD conversion to complete
	while ((ADCSRA & 0x10)==0);
	ADCSRA|=0x10;
	return ADCW;
}


// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{        
    // Set the pulse width to p
    OCR1AL = p;
}

void main(void)
{
    int throttle, temperature, batt_voltage;


	// Input/Output Ports initialization
	// Port B initialization
	// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out 
	// State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=T 
	PORTB=0x00;
	DDRB=0x03;
	
	// Port C initialization
	// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
	// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
	PORTC=0x00;
	DDRC=0x00;
	
	// Port D initialization
	// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
	// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
	PORTD=0x00;
	DDRD=0x00;
	
	// Timer/Counter 0 initialization
	// Clock source: System Clock
	// Clock value: Timer 0 Stopped
	TCCR0=0x00;
	TCNT0=0x00;
	
	// Timer/Counter 1 initialization
	// Clock source: System Clock
	// Clock value: 7372.800 kHz
	// Mode: Fast PWM top=03FFh
	// OC1A output: Non-Inv.
	// OC1B output: Discon.
	// Noise Canceler: Off
	// Input Capture on Falling Edge
	// Timer 1 Overflow Interrupt: On
	// Input Capture Interrupt: Off
	// Compare A Match Interrupt: Off
	// Compare B Match Interrupt: Off
	TCCR1A=0x82; // was 0x83
	TCCR1B=0x19;
	TCNT1H=0x00;
	TCNT1L=0x00;
	ICR1H=0x00;
	ICR1L=0x3F;
	OCR1AH=0x00;
	OCR1AL=0x00;
	OCR1BH=0x00;
	OCR1BL=0x00;
	
	// Timer/Counter 2 initialization
	// Clock source: System Clock
	// Clock value: Timer 2 Stopped
	// Mode: Normal top=FFh
	// OC2 output: Disconnected
	ASSR=0x00;
	TCCR2=0x00;
	TCNT2=0x00;
	OCR2=0x00;
	
	// External Interrupt(s) initialization
	// INT0: Off
	// INT1: Off
	MCUCR=0x00;
	
	// Timer(s)/Counter(s) Interrupt(s) initialization
	TIMSK=0x04;
	
	// USART initialization
	// Communication Parameters: 8 Data, 1 Stop, No Parity
	// USART Receiver: On
	// USART Transmitter: On
	// USART Mode: Asynchronous
	// USART Baud rate: 115200 (Double Speed Mode)
	UCSRA=0x02;
	UCSRB=0x18;
	UCSRC=0x86;
	UBRRH=0x00;
	UBRRL=0x07;
	
	// Analog Comparator initialization
	// Analog Comparator: Off
	// Analog Comparator Input Capture by Timer/Counter 1: Off
	ACSR=0x80;
	SFIOR=0x00;
	
	// ADC initialization
	// ADC Clock frequency: 230.400 kHz
	// ADC Voltage Reference: AVCC pin
	ADMUX=ADC_VREF_TYPE & 0xff;
	ADCSRA=0x85;
	
	// Global enable interrupts
	#asm("sei")
	
	
	while (1)
	{      
		// let's take start 1/16th = no throttle and end 1/16th = full throttle
		//1/16th of 1024 is 64
		// We have 220 ohm resistors either side of the 5K pot
		// so USUALLY the range is restricted to about 44 to 980 of the 1024 ADC range
		// As such, if the ADC reads under ~12 or over 1012, we can assume the throttle pot is disconnected, or not connected properly
		
	   
		batt_voltage = read_adc(2) / 5; // 1024 == 200 volts, so it's about 5 per volt
		temperature = read_adc(1); // temperature is non-linear, but at 50% (512) the thermistor resistance matches the resistor
		throttle = read_adc(0);
		   
		if (temperature > 512 || batt_voltage < MIN_BATT_VOLTAGE || batt_voltage > MAX_BATT_VOLTAGE)
			PORTB = 0x00;
		else
			PORTB = 0x01;    
		
		if (throttle < 64 || throttle > 1012 || temperature > 512
			|| batt_voltage < MIN_BATT_VOLTAGE || batt_voltage > MAX_BATT_VOLTAGE)
		{
			DDRB=0x01;
		}
		else
		{
			DDRB = 0x03;
			
			if (throttle > 1023-64)
			{
				throttle = 1023;
			}
			else
			{
				throttle -= 64; // subtract 64
				throttle = throttle + (throttle >> 3); // scale by 1 1/8th
			}
			
			if (batt_voltage > MAX_MOTOR_VOLTAGE)
				throttle *= MAX_MOTOR_VOLTAGE / batt_voltage;
			
			
			p = throttle>>4;
			
		}
	};
}
