Rev 55 |
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
= 1500;
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
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
();
if (eeprom_read_word
(&EEPSIG
) != EEPSIGNATURE
) //check eep if signature is there
{
min
= 1100; //default min
max
= 1900; //default max
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
;
}
printf("ppm: %d / min: %d / max: %d\n",ppm
,min
,max
);
if (setup
== 8)
{
temp1
= (STEP
* (signed long)30000 * (signed long)6) / ((max
-REDUCE
) - (min
+REDUCE
));
temp2
= ((ppm
- (min
+REDUCE
)) * temp1
);
color
= temp2
/ 30000;
if (color
< 0) color
= 0;
if (color
> (STEP
* 6)) color
= (STEP
* 6);
printf("color: %d\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;
}
}
}
}