added simple IR receiver burst recording

This commit is contained in:
King Kévin 2013-10-14 11:24:51 +02:00
parent e310bb4a85
commit ec8defaa99
1 changed files with 84 additions and 40 deletions

View File

@ -10,22 +10,37 @@
#include "uart.h" #include "uart.h"
/* global variables */ /* global variables */
volatile uint8_t pwr_ok; volatile uint8_t pwr_ok; /* is power ok */
volatile uint8_t fan; volatile uint8_t fan; /* fan signal state, to measure tachometer */
volatile uint16_t tachometer = 0; volatile uint8_t timer2_ovf = 0; /* to measure fan speed using timer 2 */
volatile uint8_t timer2_ovf = 0; static const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024}; /* timer 2 CS2[2:0] values */
volatile uint16_t tachometer = 0; /* the tachometer time (from timer) */
volatile uint8_t ir; /* IR signal state, to measure IR code */
volatile uint8_t pulse_i = 1; /* pulse index */
# define PULSE_MAX 64 /* maximum number of pulses to save */
volatile uint16_t pulse[PULSE_MAX]; /* pulse times (from timer) */
const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024};
/* PWR_OK interrupt */ /* power ok interrupt */
ISR(PCINT0_vect) { /* PCI0 Interrupt Vector for PCINT[7:0] */ ISR(PCINT0_vect) { /* PCI0 Interrupt Vector for PCINT[7:0] */
if (pwr_ok!=(PINB&(1<<PWR_OK))) { /* did the PWR_OK pin state changed */ if (pwr_ok!=(PINB&(1<<PWR_OK))) { /* did the PWR_OK pin state changed */
pwr_ok = PINB&(1<<PWR_OK); /* save new state */ pwr_ok = PINB&(1<<PWR_OK); /* save new state */
if (pwr_ok) { if (pwr_ok) {
/* switch timer 2 on to start measuring the fan speed */
puts("power ok"); puts("power ok");
} else { } else {
puts("power ko"); puts("power ko");
} }
} else if (ir!=(PINB&(1<<IR))) { /* did the IR pin state changed */
ir = PINB&(1<<IR); /* save new state */
if (pulse_i>0) { /* save pulse, except the first */
pulse[pulse_i-1] = TCNT1;
pulse[pulse_i] = 0;
}
if (pulse_i<PULSE_MAX-1) { /* prepare to save next pulse */
pulse_i++;
}
TCNT1 = 0; /* clear timer 1 */
} }
} }
@ -33,18 +48,26 @@ ISR(PCINT0_vect) { /* PCI0 Interrupt Vector for PCINT[7:0] */
ISR(PCINT1_vect) { /* PCI0 Interrupt Vector for PCINT[14:8] */ ISR(PCINT1_vect) { /* PCI0 Interrupt Vector for PCINT[14:8] */
if (fan!=(PINC&(1<<FAN))) { /* did the FAN pin state changed */ if (fan!=(PINC&(1<<FAN))) { /* did the FAN pin state changed */
fan = PINC&(1<<FAN); /* save new state */ fan = PINC&(1<<FAN); /* save new state */
if (fan) { if (fan) { /* only react to rising edge */
tachometer = timer2_ovf*256+TCNT2; /* save time */ tachometer = (uint16_t)(timer2_ovf<<8)+TCNT2; /* save time */
TCNT2 = 0; /* reset timer 2 */ TCNT2 = 0; /* reset timer 2 */
timer2_ovf = 0; /* reset timer 2 overflow counter */ timer2_ovf = 0; /* reset timer 2 */
} }
} }
} }
/* timer 2 interrupt used to measure fan tachometer */ /* timer 2 interrupt used to measure fan speed based on tachometer */
ISR(TIMER2_OVF_vect) { /* timer 2 overflow interrupt verctor */ ISR(TIMER2_OVF_vect) { /* timer 2 overflow interrupt vector */
if(pwr_ok) { /* only measure tachometer if power is ok */ if (timer2_ovf<0xff) { /* prevent overflow */
timer2_ovf++; /* increase time 2 overflow counter */ timer2_ovf++; /* increase tachometer counter */
}
}
/* timer 1 interrupt used to measure IR pulse */
ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
if (pulse_i>0) {
pulse_i = 0;
OCR0A = ~OCR0A;
} }
} }
@ -59,9 +82,21 @@ static void ioinit(void)
PCICR |= (1<<PCIE0); /* enable interrupt for PCINT[7:0] */ PCICR |= (1<<PCIE0); /* enable interrupt for PCINT[7:0] */
PCMSK0 |= (1<<PCINT1); /* enable interrupt for PCINT1 */ PCMSK0 |= (1<<PCINT1); /* enable interrupt for PCINT1 */
/* configure peripherals */ /* configure LED (on PD6/OC0A) */
DDRB &= ~(1<<IR); /* IR receiver is input */ DDRD |= (1<<LED); /* LED is output */
/* use timer 1 to produce a PWM */
/* use phase correct PWM mode (because fast PWM is always on for at least 1 cycle) */
TCCR0A &= ~(1<<WGM01);
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<WGM02);
/* /64 prescale timer */
TCCR0B &= ~(1<<CS02);
TCCR0B |= (1<<CS01)|(1<<CS00);
/* clear on match, because the pin is used as sink */
TCCR0A |= (1<<COM0A1)|(1<<COM0A0);
/* start with LED on */
OCR0A = 0xff;
/* configure FAN */ /* configure FAN */
DDRC &= ~(1<<FAN); /* FAN (PC5/PCINT13) is input */ DDRC &= ~(1<<FAN); /* FAN (PC5/PCINT13) is input */
fan = PINC&(1<<FAN); /* save state */ fan = PINC&(1<<FAN); /* save state */
@ -72,12 +107,30 @@ static void ioinit(void)
/* use normal mode */ /* use normal mode */
TCCR2A &= ~((1<<WGM20)|(1<<WGM21)); TCCR2A &= ~((1<<WGM20)|(1<<WGM21));
TCCR2B &= ~(1<<WGM22); TCCR2B &= ~(1<<WGM22);
/* /256 prescale timer */ /* clock/64 prescaler */
TCCR2B |= (1<<CS22)|(1<<CS21); TCCR2B |= (1<<CS22);
TCCR2B &= ~(1<<CS20); TCCR2B &= ~((1<<CS21)|(1<<CS20));
TIFR2 &= ~(1<<TOV2); /* clear timer 2 overflow interrupt flag */ TIFR2 &= ~(1<<TOV2); /* clear timer 2 overflow interrupt flag */
TIMSK2 |= (1<<TOIE2); /* enable timer 2 overflow interrupt */ TIMSK2 |= (1<<TOIE2); /* enable timer 2 overflow interrupt */
/* configure IR receiver */
DDRB &= ~(1<<IR); /* IR (PB0/PCINT0) receiver is input */
ir = PINB&(1<<IR); /* save state */
PCIFR &= ~(1<<PCIF0); /* clear interrupt flag */
PCICR |= (1<<PCIE0); /* enable interrupt for PCINT[7:0] */
PCMSK0 |= (1<<PCINT0); /* enable interrupt for PCINT0 */
/* use timer 1 to measure IR pulse */
/* use CTC mode */
TCCR1A &= ~((1<<WGM10)|(1<<WGM11));
TCCR1B |= (1<<WGM12);
TCCR1B &= ~(1<<WGM13);
/* clock/8 prescaler, offers most precision for 15ms (up to 28.5ms) */
TCCR1B |= (1<<CS11);
TCCR1B &= ~((1<<CS12)|(1<<CS10));
OCR1A = (uint32_t)(15*F_CPU)/(1000*8); /* set clear time to 15 ms (no IR toggle should be longer) */
TIFR1 &= ~(1<<OCF1A); /* clear timer 1 overflow interrupt flag */
TIMSK1 |= (1<<OCIE1A); /* enable timer 1 overflow interrupt */
/* configure channels (used for powering LEDs using an nMOS) */ /* configure channels (used for powering LEDs using an nMOS) */
DDRC |= (1<<CH1_1)|(1<<CH1_2)|(1<<CH1_3)|(1<<CH1_4)|(1<<CH1_5); /* CH1_x is output */ DDRC |= (1<<CH1_1)|(1<<CH1_2)|(1<<CH1_3)|(1<<CH1_4)|(1<<CH1_5); /* CH1_x is output */
PORTC &= ~((1<<CH1_1)|(1<<CH1_2)|(1<<CH1_3)|(1<<CH1_4)|(1<<CH1_5)); /* switch off CH1_x */ PORTC &= ~((1<<CH1_1)|(1<<CH1_2)|(1<<CH1_3)|(1<<CH1_4)|(1<<CH1_5)); /* switch off CH1_x */
@ -89,20 +142,6 @@ static void ioinit(void)
stdout = &uart_output; stdout = &uart_output;
stdin = &uart_input; stdin = &uart_input;
/* configure LED (on PD6/OC0A) */
DDRD |= (1<<LED); /* LED is output */
/* use phase correct PWM mode (because fast PWM is always on for at least 1 cycle) */
TCCR0A &= ~(1<<WGM01);
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<WGM02);
/* /64 prescale timer */
TCCR0B &= ~(1<<CS02);
TCCR0B |= (1<<CS01)|(1<<CS00);
/* clear on match, because the pin is used as sink */
TCCR0A |= (1<<COM0A1)|(1<<COM0A0);
/* start with LED on */
OCR0A = 0xff;
sei(); /* enable interrupts */ sei(); /* enable interrupts */
} }
@ -112,7 +151,7 @@ int main(void)
char input; char input;
puts("Hello world!"); puts("LED dimmer up & running");
_delay_ms(1000); _delay_ms(1000);
while(1) { while(1) {
input = getchar(); input = getchar();
@ -238,24 +277,29 @@ int main(void)
if (OCR0A>0) { if (OCR0A>0) {
OCR0A--; OCR0A--;
} }
printf("decreasing LED: %d\n",OCR0A); printf("decreasing LED: %u\n",OCR0A);
break; break;
case '+': case '+':
if (OCR0A<0xff) { if (OCR0A<0xff) {
OCR0A++; OCR0A++;
} }
printf("increasing LED: %d\n",OCR0A); printf("increasing LED: %u\n",OCR0A);
break; break;
case 't': case 't':
if (tachometer) { if (tachometer) {
uint16_t prescale = TIMER2_PRESCALE[TCCR2B&((1<<CS22)|(1<<CS21)|(1<<CS20))]; uint16_t prescale = TIMER2_PRESCALE[TCCR2B&((1<<CS22)|(1<<CS21)|(1<<CS20))];
if (prescale) { if (prescale) {
uint32_t speed = ((60*F_CPU)/(prescale*(uint32_t)tachometer))/2; if (timer2_ovf<0xff) {
printf("fan speed: %lurpm\n",speed); uint32_t speed = ((60*F_CPU)/(prescale*(uint32_t)tachometer))/2; /* calculate speed. 2 pulses per revolution */
printf("fan speed: %lurpm\n",timer2_ovf); printf("fan speed: %lurpm\n",speed);
} else {
printf("fan off (or not detected)\n");
}
} else {
printf("fan speed measurement not started\n");
} }
} else { } else {
printf("fan off or too slow\n"); printf("fan off (or not detected)\n");
} }
break; break;
} }