0,0 → 1,245 |
//############################################################################ |
// - 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" |
#include "twislave.h" |
|
volatile unsigned int ppm_signal = 1500; |
volatile unsigned char ppm_new = 0; |
volatile unsigned char TMR1OvF = 0; |
volatile unsigned char IRstate = 0; |
volatile unsigned char IRdat = 0; |
volatile unsigned char TMR65ms = 0; |
|
|
|
SIGNAL(SIG_OVERFLOW1) |
{ |
TMR1OvF++; |
TMR65ms++; |
} |
|
|
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 * 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) |
{ |
static unsigned char IRbit; |
|
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(); |
StartI2C(); |
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); |
TMR65ms = 0; //reset 65ms Timer |
while (GetPPM() < 1350) |
{ |
if (TMR65ms > 15 * 1) break; //about 1 sec. repeat time |
} |
PORTD &= ~(1<<ledgreen); |
} |
|
} |
|
if (I2C_IN == TRIGGER) |
{ |
PORTD |= (1<<ledgreen); |
SendIRSignal(TRIGGER); |
PORTD &= ~(1<<ledgreen); |
} |
|
if (I2C_IN == ZOOM) |
{ |
PORTD |= (1<<ledred); |
SendIRSignal(ZOOM); |
PORTD &= ~(1<<ledred); |
} |
|
|
} |
|
|
} |