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);
}
}
}
}