Subversion Repositories Projects

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

//############################################################################
// - PWM CTRL
// - 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
// - 11.12.2007
// - Make sure Fuses are programmed for internal 8 MHz RC Oscilator
//############################################################################*/

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

volatile unsigned int PPM_SIGNAL = 1520;
volatile unsigned char PPM_NEW = 0;
volatile unsigned char TMR1OvF = 0;
volatile unsigned int  TMR1MS;
volatile unsigned char CH0;
volatile unsigned char CH1;
volatile unsigned char CH2;
volatile unsigned char CH3;
volatile unsigned char CH4;
volatile unsigned char CH5;

uint16_t EEMEM EEPMIN=0x0000;
uint16_t EEMEM EEPMAX=0xffff;
uint16_t EEMEM EEPSIG=0xffff;


//led kennlinie, (noch nicht implementiert, nur vorbereitet)
unsigned char kl[256]={
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
};



/*##############################################################################*/
SIGNAL(SIG_OVERFLOW1)
{
        TMR1OvF++;
}


SIGNAL(SIG_INPUT_CAPTURE1)
{
        static unsigned int pos_ICR;
        static unsigned int ppm;
       
        if ((TCCR1B & (1<<ICES1)) != 0)                                         //rising edge
        {
                TCCR1B &= ~(1<<ICES1);                                                          //set falling egde
                TMR1OvF = 0;
                pos_ICR = ICR1;
        }
        else                                                                                    //falling edge
        {
                TCCR1B |= (1<<ICES1);                                                           //set rising egde
                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 * 3 + ppm) / 4;
                        PPM_SIGNAL = ppm;
                        if (PPM_NEW < 50) PPM_NEW++;
                }
               
        }

}

/*##############################################################################*/
SIGNAL(SIG_OVERFLOW0)
{
        // this function is called every 32us,
        // it is very important that it's execution time is as short as possible
        // currently it's about 20us

        static unsigned char counter = 254;
        static unsigned char ms1 = 0;
        static unsigned char ch0_tmp = 0;
        static unsigned char ch1_tmp = 0;
        static unsigned char ch2_tmp = 0;
        static unsigned char ch3_tmp = 0;
        static unsigned char ch4_tmp = 0;
        static unsigned char ch5_tmp = 0;
        unsigned char PORTB_BAK;
        unsigned char PORTD_BAK;       

        PORTB_BAK = PORTB;
        PORTD_BAK = PORTD;

        if (counter++ == 254)
        {
                PORTB_BAK LEDON (CH0_B | CH1_B | CH2_B);                //new cycle, output on
                PORTD_BAK LEDON (CH3_D | CH4_D | CH5_D);                //
                ch0_tmp = CH0;
                ch1_tmp = CH1;
                ch2_tmp = CH2;
                ch3_tmp = CH3;
                ch4_tmp = CH4;
                ch5_tmp = CH5;         
                counter = 0;
        }

        if (ch0_tmp == counter) PORTB_BAK LEDOFF CH0_B;         //channel value reached, output off
        if (ch1_tmp == counter) PORTB_BAK LEDOFF CH1_B;         //
        if (ch2_tmp == counter) PORTB_BAK LEDOFF CH2_B;         //
        if (ch3_tmp == counter) PORTD_BAK LEDOFF CH3_D;         //
        if (ch4_tmp == counter) PORTD_BAK LEDOFF CH4_D;         //
        if (ch5_tmp == counter) PORTD_BAK LEDOFF CH5_D;         //
       
        PORTB = PORTB_BAK;
        PORTD = PORTD_BAK;
       
        if (ms1++ == 32)
        {
                ms1=0;
                TMR1MS++;
        }
       



}


/*##############################################################################*/
unsigned int SetDelay (unsigned int t)
{
        unsigned char hi_byte;
        unsigned char lo_byte;  

        hi_byte = (TMR1MS >> 8);
        lo_byte = (TMR1MS & 0xff);
        if (hi_byte != (TMR1MS >> 8)) hi_byte = (TMR1MS >> 8);

        return(((hi_byte << 8) | lo_byte)  + t + 1);                                            
}


/*##############################################################################*/
char CheckDelay(unsigned int t)
{
        unsigned char hi_byte;
        unsigned char lo_byte;  

        hi_byte = (TMR1MS >> 8);
        lo_byte = (TMR1MS & 0xff);
        if (hi_byte != (TMR1MS >> 8)) hi_byte = (TMR1MS >> 8);

        return(((t - ((hi_byte << 8) | lo_byte)) & 0x8000) >> 9);
}



/*##############################################################################*/
void StartPWM(void)
{
        //Timer 0 Config
        TCCR0 = (0<<CS02)|(0<<CS01)|(1<<CS00);          // (@8MHz) =  1/8us Clk = 256/8 = 32us overflow
        TIMSK setbit (1<<TOIE0);                                                // enable Int

}


/*##############################################################################*/
void StartPPM(void)
{
       
        //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

}


/*##############################################################################*/
unsigned 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 temp_hi;
        unsigned char temp_lo;  

        temp_hi = (PPM_SIGNAL >> 8);
        temp_lo = (PPM_SIGNAL & 0xff);
        if (temp_hi != (PPM_SIGNAL >> 8)) temp_hi = (PPM_SIGNAL >> 8);
        return( (temp_hi << 8) | temp_lo);                                            

}


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

        #define STEP            256
        #define MUL                     1
        #define REDUCE          2
       
        #define EEPSIGNATURE    0x55aa

        #define inimin          1200
        #define inimax          1800   

        unsigned int    ppm;
        signed int              color; 
        unsigned int    setupdly;
        unsigned int    ppmtodly;      
        unsigned int    flashdly;
        unsigned char   setup;
        unsigned int    lmax;
        unsigned int    lmin;
        unsigned int    max;
        unsigned int    min;
        signed long             temp1; 
        signed long             temp2;         

    DDRB  = (CH0_B|CH1_B|CH2_B);
    PORTB = 0x00;

    DDRC  = (ledred);
    PORTC = 0x00;

    DDRD  = (ledgreen|CH3_D|CH4_D|CH5_D);
    PORTD = 0x00;

        CH0 = 0;
        CH1 = 0;
        CH2 = 0;
        CH3 = 0;
        CH4 = 0;
        CH5 = 0;       

        lmax = 0x0000;
        lmin = 0xffff;

//      StartUART();
        StartPPM();
        //StartI2C();
        StartPWM();
        sei();

        min = inimin;                                                                                           //default min
        max = inimax;                                                                                           //default max

        if (eeprom_read_word(&EEPSIG) != EEPSIGNATURE)                          //check eep if signature is there
        {
                eeprom_write_word(&EEPMIN, min);                                                //no, write initial min
                eeprom_write_word(&EEPMAX, max);                                                //and max values
                eeprom_write_word(&EEPSIG, EEPSIGNATURE);                               //along with eep signature
        }
        else
        {

                min = eeprom_read_word(&EEPMIN);                                                //signature ok
                max = eeprom_read_word(&EEPMAX);                                                //read min and max
        }


        setup = 0;                                                                                                      //reset setup toggle counter
        setupdly = SetDelay(5000);
        ppmtodly = SetDelay(5000);     
        flashdly = SetDelay(1000);                                                             
   
    while (1)
        {

                if (PPM_NEW > 20)                                                                               //ppm Signal ok
                {
                        PORTC clrbit ledred;
                        ppm = GetPPM();                        
                        ppmtodly = SetDelay(500);                                                       //reset timeout                
                        if (lmax < ppm) lmax=ppm;                                                       //update impulse max
                        if (lmin > ppm) lmin=ppm;                                                       //and min boundarys
                }
                else
                {
                        PORTC setbit ledred;                                                            //ppm signal not ok
                        ppm = min;                                                                                      //set ppm to minimum
                }
               

                if (CheckDelay(ppmtodly))                                                               //timeout
                {
                        ppmtodly = SetDelay(5000);             
                        PPM_NEW = 0;                                                                            //set ppm signal not ok
                }      


                if (setup < 6)
                {
                        if ((ppm > 1600) && ((setup&1)==0)) setup++;            //
                        if ((ppm < 1400) && ((setup&1)==1)) setup++;            //

                        if (CheckDelay(flashdly))                                                      
                        {      
                                CH0 = CH0 ^ 0xff;
                                CH1 = CH1 ^ 0xff;
                                CH2 = CH2 ^ 0xff;
                                flashdly = SetDelay(250);                                                              
                        }
                }

                if (setup == 6)                                                                                 //if stick is toggled 6 times
                {                                                                                                               //within setup timeout
                        PORTD setbit ledgreen;                                                          //store ppm min and max
                        setupdly = SetDelay(3000);                                                      //for 2000ms
                        eeprom_write_word(&EEPMIN, lmin);                                       //in eeprom
                        eeprom_write_word(&EEPMAX, lmax);      
                        min = lmin;                                                                                    
                        max = lmax;
                        setup = 7;                                                                                      //enter PWM toggle mode

                }


                if (setup == 7)
                {
                        if (CheckDelay(flashdly))                                                       //each 25ms toggle PWM's
                        {      
                                CH0 = CH0 ^ 0xff;
                                CH1 = CH1 ^ 0xff;
                                CH2 = CH2 ^ 0xff;
                                flashdly = SetDelay(25);                                                               
                        }
               
                }

                if (CheckDelay(setupdly))                                                               //setup timeout reached
                {
                        setup = 8;                                                                                      //lockdown setup
                        PORTD clrbit ledgreen;
                }

               
                if (setup == 8)
                {
               
                       

                        temp1 = ((long)STEP * 6 * 20000) / ((max-REDUCE) - (min+REDUCE));
                        temp2 = (((int)ppm - ((int)min+REDUCE)) * temp1);
                        color = temp2 / 20000;
                       
                        if (color < 0) color = 0;
                        if (color > ((STEP*6)+1)) color = ((STEP*6)+1);

               
                        //printf("p %u  ",ppm);
                        //printf("pm %u  ",(min+REDUCE));
                        //printf("t1 %li  ",temp1);
                        //printf("t2 %li  ",temp2);
                        //printf("c %i\n  ",color);                                    
               
               
                        // Farbablauf: rot > Violett > blau > tuerkis > gruen > gelb >
                        if ((color >= (STEP * 0)) && (color < (STEP * 1)))
                        {
                                CH0 = MUL * ((color - (STEP * 0)));                             //fade in red > red (red only)
                                CH1 = 0;
                                CH2 = 0;
                        }
                        if ((color >= (STEP * 1)) && (color < (STEP * 2)))
                        {
                                CH0 = ((STEP-1) * MUL);
                                CH1 = 0;
                                CH2 = MUL * ((color - (STEP * 1)));                             //fade in blue > purple (red + blue)
                        }
                        if ((color >= (STEP * 2)) && (color < (STEP * 3)))
                        {
                                CH0 = MUL * ((STEP - 1) - (color - (STEP * 2)));        //fade out red > blue (blue only)
                                CH1 = 0;
                                CH2 = ((STEP-1) * MUL);
                        }
                        if ((color >= (STEP * 3)) && (color < (STEP * 4)))
                        {
                                CH0 = 0;
                                CH1 = MUL * ((color - (STEP * 3)));                             //fade in green > cyan (blue + green)
                                CH2 = ((STEP-1) * MUL);
                        }
                        if ((color >= (STEP * 4)) && (color < (STEP * 5)))
                        {
                                CH0 = 0;
                                CH1 = ((STEP-1) * MUL);
                                CH2 = MUL * ((STEP - 1) - (color - (STEP * 4)));        //fade out blue > green (green only)
                        }
                        if ((color >= (STEP * 5)) && (color < (STEP * 6)))
                        {
                                CH0 = MUL * ((color - (STEP * 5)));                             //fade in red > yellow (green + red)
                                CH1 = ((STEP-1) * MUL);
                                CH2 = 0;
                        }
                        if (color >= (STEP * 6))  
                        {
                                CH0 = ((STEP-1) * MUL);                                                 //fade in red > yellow (green + red)
                                CH1 = ((STEP-1) * MUL);
                                CH2 = 0;
                        }
                }


        }

}