Subversion Repositories Projects

Rev

Blame | Last modification | View Log | RSS feed

//############################################################################
// - PPM2PentaxIR Main
// - ATMEGA8 mit 8MHz
// - Nur für den privaten Gebrauch
// - Keine Garantie auf Fehlerfreiheit
// - Kommerzielle Nutzung nur mit meiner Zustimmung
// - walter Meyer @ www.freakware.de
// - 30.11.2007
// - Make sure Fuses are programmed for internal 8 MHz RC Oscilator
//############################################################################*/

#include "main.h"
#include "uart.h"

volatile unsigned int ppm_signal = 0;
volatile unsigned char ppm_new = 0;
volatile unsigned char TMR1OvF = 0;
volatile unsigned char IRstate = 0;
volatile unsigned char IRdat = 0;
volatile unsigned char IRbit = 0;


SIGNAL(SIG_OVERFLOW1)
{
        TMR1OvF++;
}


SIGNAL(SIG_INPUT_CAPTURE1)
{
        static unsigned int pos_ICR;
        static unsigned int ppm;
       
        if ((TCCR1B & (1<<ICES1)) != 0)
        {
                TCCR1B &= ~(1<<ICES1);                                                          //invert trigger
                TMR1OvF = 0;
                pos_ICR = ICR1;
        }
        else                                                                                    //Negative Flanke
        {
                TCCR1B |= (1<<ICES1);
                ppm = (ICR1 - pos_ICR + (int) TMR1OvF * 65536);
                if ((ppm > 600) && (ppm < 2400))
                {
                        if (ppm > 2100) ppm = 2100;
                        if (ppm < 900) ppm = 900;
                        ppm = (ppm_signal * 7 + ppm) / 8;
                        ppm_signal = ppm;
                        ppm_new = 1;
                }
               
        }

}



/*##############################################################################*/
void StartIRModulation(void)
{
        //Timer1 Config for generation the 38Khz IR Modulation
        TCCR2 =         (0<<FOC2)|(0<<WGM20)|(0<<COM21)|(0<<COM20)|
                                (1<<WGM21) |(0<<CS22) |(0<<CS21) |(1<<CS20);                   

        OCR2 = 108;                                                                     //~38Khz @ 8Mhz

        //Timer 0 Config for getting right timing for IR Pattern
        TCCR0 = (1<<CS02)|(0<<CS01)|(1<<CS00);  // clk(@8MHz) / 1024 =  128us / clk (resolution)
        TIMSK &= ~(1<<TOIE0);                                           //

}


SIGNAL(SIG_OVERFLOW0)
{

        switch (IRstate)
        {
    case 1:
                TCCR2 setbit (1<<COM20);
                IRstate = 2;
                IRbit = 0;
                TCNT0 = 255 - (13000 / 128);
                break;
    case 2:
                TCCR2 clrbit (1<<COM20);
                IRstate = 3;
                if ((IRdat & 0x40) == 0)        TCNT0 = 255 - (1000 / 128);
                else TCNT0 = 255 - (3000 / 128);
                break;
    case 3:
                TCCR2 setbit (1<<COM20);       
                TCNT0 = 255 - (1000 / 128);
                IRdat = IRdat << 1;
                IRbit++;
                if (IRbit < 7) IRstate = 2;
                else
                {
                        IRstate = 4;
                        IRbit = 0;
                }
                break;
        case 4:
                TCCR2 clrbit (1<<COM20);       
                TCNT0 = 255 - (25000 / 128);
                if (IRbit < 20) IRstate = 4;
                else IRstate = 5;
                IRbit++;
                break;
        default:
                TIMSK &= ~(1<<TOIE0);
                IRstate = 0;
                break;

        }

}





/*##############################################################################*/
void SendIRSignal(unsigned char txbyte)
{
        while (IRstate != 0) {}                                         //IR already in action ?, if so, wait
        IRstate = 1;                                                                    //initial State
        IRdat = txbyte;                                                                 //copy IR Data
        TIFR &= TOV0;                                                                   //set TMR0 Int Flag
        TIMSK setbit (1<<TOIE0);                                                //Enable TMR0 Int      
}







/*##############################################################################*/
void StartPPM(void)
{
       
        //global timer1 Config
        TCCR1A =        (0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|
                                (0<<FOC1A) |(0<<FOC1B) |(0<<WGM10) |(0<<WGM11);                
    TCCR1B =    (1<<ICNC1)|(1<<ICES1)|(0<<WGM13)|
                                (0<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10);                               //ICP_POS_FLANKE

        // interrupts
        TIMSK |=        (1<<TICIE1)|(1<<TOIE1);                                                                 //ICP_INT_ENABLE and TIMER1_INT_ENABLE

}


int GetPPM(void)
{
        //this routines seems to be nesseccary, as reading a 16 bit value
        //on a 8 bit machine is not atomic, so if an interrupt apears between reading
        //low and high byte of the 16 bit value a wrong result is possible
       
        unsigned char intmask;
        unsigned int  ppm_temp;

        intmask = TIMSK;                                //backup interupt enable bits
        TIMSK &= ~(1<<TICIE1);                  //disable ppm interrupt
        ppm_temp = ppm_signal;
        TIMSK = intmask;                                //restore interupt enable bits
        return(ppm_temp);                               //return ppm_signal

}


/*##############################################################################*/
// MAIN
/*##############################################################################*/
int main (void)
{

    DDRC  = (1<<ledred);
    PORTC = 0x00;
    DDRD  = (1<<ledgreen);
    PORTD = 0x00;
    DDRB  = (1<<1)|(1<<2)|(1<<3);
    PORTB = 0x00;


        StartUART();
        StartPPM();
        StartIRModulation();
        sei();

   
    while (1)
        {
                //printf("%d ",ppm_signal);
                if (ppm_new == 1)
                {
                        ppm_new = 0;
                        if (GetPPM() > 1750)
                        {
                                SendIRSignal(ZOOM);
                                PORTC |= (1<<ledred);
                                while (GetPPM() > 1650)  {}
                                PORTC &= ~(1<<ledred);
                        }
                       
                        if (GetPPM() < 1250)
                        {
                                PORTD |= (1<<ledgreen);                
                                SendIRSignal(TRIGGER);
                                while (GetPPM() < 1350) {}
                                PORTD &= ~(1<<ledgreen);                       
                        }
                       
                }
        }


}