/*
 *  A converter for servo signal (1-2ms) to 0-10V analog 
 *
 *  ATtiny24A @ 4MHz
 *
*/

#define F_CPU 4000000

#define TEST_LOW  PORTA &= ~(1<<PA6)
#define TEST_HIGH PORTA  =  (1<<PA6)
#define TEST_TOG  PORTA ^=  (1<<PA6)

#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int main(void) {

    // init IOs

	DDRA  = (1<<PA6);	// TEST pin
    PORTA = 0xFF;       // all inputs, internal pull-ups
    DDRB  = (1<<PB2);   // PWM out to filter, OCR0A

    // init timer 0, PWM output OCR0A
    // mode 3, fast PWM, 8 bit, prescaler 1

    TCCR0A = (1<<COM0A1) | (1<<WGM01) | (1<<WGM00);     
    TCCR0B = (1<<CS00);
	OCR0A = 50;

    // init timer 1
    // input capture, mode 0, prescaler 8
    // input noise canceler
    // trigger on rising edge (for now)

    TCCR1A  = 0;
    TCCR1B  = (1<<ICNC1) | (1<<ICES1) | (1<<CS11);
    TIMSK1 |= (1<<ICIE1);

    sei();
    while(1) {
        set_sleep_mode(SLEEP_MODE_IDLE);
        sleep_mode();
    }
}

// measure pulse width 1-2ms

ISR(TIM1_CAPT_vect) {
    static uint16_t tr;
    uint16_t tf, delta;

//	TEST_TOG;

    if (TCCR1B & (1<<ICES1) ) { 			// rising edge
		//TEST_HIGH;
        tr = ICR1;
        TCCR1B  = (1<<ICNC1) | (1<<CS11);   // next trigger on falling edge
    } else {     			                // falling edge
		//TEST_LOW;
        tf = ICR1;
        TCCR1B  = (1<<ICNC1) | (1<<ICES1) | (1<<CS11);  // next trigger on rising edge
        delta = tf-tr;
        // limit range to 0-500 = 0-1ms
        if (delta < 500) delta = 500;
        delta -= 500;      // 1ms offset 
        if (delta > 500) delta = 500;
        // scale 1ms = 500 counts = 100%
        // OCR0A = 256 * delta / 500 = (262 * delta ) / 512 = (262 * delta ) >> 9
        OCR0A = (262L * delta) >> 9;
    }
    TIFR1 = (1<<ICF1);   // clear flag again after switching trigger edge
}
