//////////////////////////////////////////////////////
// First things first, all the includes we need     //
//////////////////////////////////////////////////////

#include "hardware.h"		// We need the header for this code
#include "afsk.h"			// We also need to know about the AFSK modem

#include <cpu/irq.h>		// Interrupt functions from BertOS

#include <avr/io.h>			// AVR IO functions from BertOS
#include <avr/interrupt.h>	// AVR interrupt functions from BertOS

// A reference to our modem "object"
static Afsk *modem;

//////////////////////////////////////////////////////
// And now for the actual hardware functions        //
//////////////////////////////////////////////////////

// M1 correction = 9500
// M2 correction = 40000
#define FREQUENCY_CORRECTION 9500

// This function initializes the ADC and configures
// it the way we need.
void hw_afsk_adcInit(int ch, Afsk *_modem)
{
	// Store a reference to our modem "object"
	modem = _modem;

	// Also make sure that we are not trying to use
	// a pin that can't be used for analog input
	ASSERT(ch <= 5);

	// We need a timer to control how often our sampling functions
	// should run. To do this we will need to change some registers.
	// First we do some configuration on the Timer/Counter Control
	// Register 1, aka Timer1.
	//
	// The following bits are set:
	// CS10: ClockSource 10, sets no prescaler on the clock,
	// meaning it will run at the same speed as the CPU, ie 16MHz
	// WGM13 and WGM12 together enables "Timer Mode 12", which
	// is Clear Timer on Compare, compare set to TOP, and the
	// source for the TOP value is ICR1 (Input Capture Register1).
	// TOP means that we specify a maximum value for the timer, and
	// once that value is reached, an interrupt will be triggered.
	// The timer will then start from zero again. As just noted,
	// the place we specify this value is in the ICR1 register.
	TCCR1A = 0;									
	TCCR1B = BV(CS10) | BV(WGM13) | BV(WGM12);

	// We now set the ICR1 register to what count value we want to
	// reset (and thus trigger the interrupt) at.
	// Since the timer is running at 16MHz, the counter will be
	// incremented 16 million times each second, and we want the
	// interrupt to trigger 9600 times each second. The formula for
	// calculating the value of ICR1 (the TOP value) is:
	//    (CPUClock / Prescaler) / desired frequency - 1
	// So that's what well put in this register to set up our
	// 9.6KHz sampling rate. Note that we can also specify a clock
	// correction to this calculation. If you measure your processors
	// actual clock speed to 16.095MHz, define FREQUENCY_CORRECTION
	// as 9500, and the actual sampling (and this modulation and
	// demodulation) will be much closer to an actual 9600 Hz.
	// No crystals are perfect though, and will also drift with
	// temperature variations, but if you have a board with a
	// crystal that is way off frequency, this can help alot.
	ICR1 = (((CPU_FREQ+FREQUENCY_CORRECTION)) / 9600) - 1;
	kprintf("ICR1=%d",ICR1);

	// Set reference to AVCC (5V), select pin
	// Set the ADMUX register. The first part (BV(REFS0)) sets
	// the reference voltage to VCC (5V), and the next selects
	// the ADC channel (basically what pin we are capturing on)
	ADMUX = BV(REFS0) | ch;

	DDRC &= ~BV(ch);	// Set the selected channel (pin) to input
	PORTC &= ~BV(ch);	// Initialize the selected pin to LOW
	DIDR0 |= BV(ch);	// Disable the Digital Input Buffer on selected pin

	// Now a little more configuration to get the ADC working
	// the way we want
	ADCSRB = 	BV(ADTS2) |	// Setting these three on (1-1-1) sets the ADC to
				BV(ADTS1) |	// "Timer1 capture event". That means we can declare
				BV(ADTS0);	// an ISR in the ADC Vector, that will then get called
							// everytime the ADC has a sample ready, which will
							// happen at the 9.6Khz sampling rate we set up earlier
				
	ADCSRA = 	BV(ADEN) |	// ADC Enable - Yes, we need to turn it on :)
				BV(ADSC) |	// ADC Start Converting - Tell it to start doing conversions
				BV(ADATE) | // Enable autotriggering - Enables the autotrigger on complete
				BV(ADIE) |  // ADC Interrupt enable - Enables an interrupt to be called
				BV(ADPS2);  // Enable prescaler flag 2 (1-0-0 = division by 16 = 1MHz)
							// This sets the ADC to run at 1MHz. This is out of spec,
							// Since it's normal operating range is only up to 200KHz.
							// But don't worry, it's not dangerous! I promise it wont
							// blow up :) There is a downside to running at this speed
							// though, hence the "out of spec", which is that we get
							// a much lower resolution on the output. In this case,
							// it's not a problem though, since we don't need the full
							// 10-bit resolution, so we'll take fast and less precise!
}


// This declares the Interrupt Service routine that will
// get called everytime the ADC finishes taking a sample.
// What actually happens here is that we take a piece of
// code, store it somewhere in memory, and then put the
// address of that "somewhere" into the Interrupt Vector
// Table of the processor, in this case the position 
// "ADC_vect". This lets the processor know what to do
// when all the timing and configuration we just set up
// finally* ends up triggering the interrupt.
bool hw_afsk_dac_isr;
DECLARE_ISR(ADC_vect) {
	TIFR1 = BV(ICF1);

	// Call the routine for analysing the captured sample
	// Notice that we read the ADC sample, and then bitshift
	// by two places to the right, effectively eliminating
	// two bits of precision. But we didn't have those
	// anyway, because the ADC is running at high speed.
	// We then subtract 128 from the value, to get the
	// representation to match an AC waveform. We need to
	// do this because the AC waveform (from the audio input)
	// is biased by +2.5V, which is nessecary, since the ADC
	// can't read negative voltages. By doing this simple
	// math, we bring it back to an AC representation
	// we can do further calculations on.
	afsk_adc_isr(modem, ((int16_t)((ADC) >> 2) - 128));

	// We also need to check if we're supposed to spit
	// out some modulated data to the DAC.
	if (hw_afsk_dac_isr)
		// If there is, it's easy to actually do so. We
		// calculate what the sample should be in the
		// DAC ISR, and apply the bitmask 11110000. This
		// simoultaneously spits out our 4-bit digital
		// sample to the four pins connected to our DAC
		// circuit, which then converts it to an analog
		// waveform. The reason for the " | BV(3)" is that
		// we also need to trigger another pin controlled
		// by the PORTD register. This is the PTT pin
		// which tells the radio to open it transmitter.
		PORTD = (afsk_dac_isr(modem) & 0xF0) | BV(3); 
	else
		// If we're not supposed to transmit anything, we
		// keep quiet by continously sending 128, which
		// when converted to an AC waveform by the DAC,
		// equates to a steady, unchanging 0 volts.
		PORTD = 128;
}


// * "finally" is probably the wrong description here.
// "All the f'ing time" is probably more accurate :)
// but it felt like it was a long way down here,
// writing all the explanations. I think this is a
// nice testament to how efficient and smart these
// processors are. The actual code to set up what
// took a long time to explain, is really very short.