USART activity handled using interrupts

This commit is contained in:
King Kévin 2013-10-14 20:19:16 +02:00
parent a3a1aadd02
commit dc6012f4e5
3 changed files with 43 additions and 37 deletions

View File

@ -12,6 +12,9 @@
#include "ir_nec.h"
/* global variables */
#define INPUT_MAX 255 /* max length for user input string */
char input[INPUT_MAX+2]; /* user input from USART */
volatile uint8_t input_i = 0; /* user input index */
volatile uint8_t pwr_ok; /* is power ok */
volatile uint8_t fan; /* fan signal state, to measure tachometer */
volatile uint8_t timer2_ovf = 0; /* to measure fan speed using timer 2 */
@ -19,25 +22,34 @@ static const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024}; /* timer
volatile uint16_t tachometer = 0; /* the tachometer time (from timer) */
volatile uint8_t ir; /* IR signal state, to measure IR code */
static const uint16_t TIMER1_PRESCALE[8] = {0,1,8,64,256,1024,0,0}; /* timer 1 CS1[2:0] values */
volatile uint16_t ir_tick; /* number of counter ticks per millisecond */
volatile uint8_t pulse = 0; /* pulse index within the burst */
#define PULSE_MAX 128 /* maximum number of pulses to save */
uint16_t burst[PULSE_MAX]; /* pulse times forming a burst (from timer) */
/* flags, set in the interrupts and handled in the main program */
volatile bool input_flag = false;
volatile bool power_flag = false;
/* UART receive interrupt */
ISR(USART_RX_vect) {
input[input_i] = getchar(); /* save input */
input[input_i+1] = 0; /* always end the string */
if (input_i<INPUT_MAX) { /* next character, if space is available */
input_i++;
}
input_flag = true; /* set flag */
}
/* power ok interrupt */
ISR(PCINT0_vect) { /* PCI0 Interrupt Vector for PCINT[7:0] */
if (pwr_ok!=(PINB&(1<<PWR_OK))) { /* did the PWR_OK pin state changed */
pwr_ok = PINB&(1<<PWR_OK); /* save new state */
if (pwr_ok) {
/* switch timer 2 on to start measuring the fan speed */
puts("power ok");
} else {
puts("power ko");
}
power_flag = true;
} else if (ir!=(PINB&(1<<IR))) { /* did the IR pin state changed */
ir = PINB&(1<<IR); /* save new state */
if (pulse>0) { /* save pulse, except the first */
burst[pulse-1] = TCNT1;
burst[pulse-1] = (TCNT1*1000UL)/ir_tick;
burst[pulse] = 0;
}
if (pulse<PULSE_MAX-1) { /* prepare to save next pulse */
@ -69,7 +81,6 @@ ISR(TIMER2_OVF_vect) { /* timer 2 overflow interrupt vector */
/* timer 1 interrupt used to measure IR pulse */
ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
if (pulse>0) {
pulse2time(burst,pulse-1);
time2nec(burst,pulse-1);
struct nec ir_data = nec2data(burst,pulse-1);
if (ir_data.valid) {
@ -79,7 +90,6 @@ ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
printf("IR addr: %u, command: %u\n",ir_data.address,ir_data.command);
}
}
OCR0A = ~OCR0A;
pulse = 0;
}
}
@ -140,8 +150,11 @@ static void ioinit(void)
/* clock/8 prescaler, offers most precision for 15ms (up to 28.5ms) */
TCCR1B |= (1<<CS11);
TCCR1B &= ~((1<<CS12)|(1<<CS10));
uint16_t prescale = TIMER1_PRESCALE[(TCCR1B&((1<<CS12)|(1<<CS11)|(1<<CS10)))>>CS10];
OCR1A = (uint32_t)(15*F_CPU)/(1000*prescale); /* set clear time to 15 ms (no IR toggle should be longer) */
uint16_t prescale = TIMER1_PRESCALE[(TCCR1B&((1<<CS12)|(1<<CS11)|(1<<CS10)))>>CS10]; /* timer 1 presacler */
if (0!=prescale) {
ir_tick = F_CPU/(1000*prescale); /* ticks per ms */
OCR1A = (uint32_t)(15*F_CPU)/(1000*prescale); /* 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 */
@ -159,35 +172,28 @@ static void ioinit(void)
sei(); /* enable interrupts */
}
/* convert burst to micro-seconds */
static void pulse2time(uint16_t* burst, uint8_t pulses)
{
uint16_t prescale = TIMER1_PRESCALE[(TCCR1B&((1<<CS12)|(1<<CS11)|(1<<CS10)))>>CS10]; /* timer 1 presacler */
uint16_t tick = F_CPU/(1000*prescale); /* ticks per ms */
if (0==prescale) {
return;
}
for (uint8_t i=0; i<pulse; i++) {
if (0==burst[i]) {
return;
}
burst[i] = (burst[i]*1000UL)/tick;
}
}
int main(void)
{
ioinit(); /* initialize IOs */
char input;
uint8_t command_i = 0; /* command index */
char c = 0;
puts("LED dimmer up & running");
_delay_ms(1000);
while(1) {
input = getchar();
printf("%c\n", input);
switch (input) {
while (true) {
/* handle user input */
while (input_flag) {
while (command_i<input_i) {
c = input[command_i++];
putchar(c); /* echo back */
}
input_flag = false;
}
}
{
_delay_ms(1000);
switch (c) {
case 'l':
PIND |= (1<<LED);
printf("LED: ");

View File

@ -17,4 +17,3 @@
#define CH2_5 PD7
static void ioinit(void);
static void pulse2time(uint16_t* burst, uint8_t pulses);

View File

@ -20,8 +20,9 @@ void uart_init(void)
#else
UCSR0A &= ~(1<<U2X0);
#endif
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); /* 8N1-bit data */
UCSR0B = (1<<RXEN0) | (1<<TXEN0); /* enable RX and TX */
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); /* 8N1 bit data */
UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* enable RX and TX */
UCSR0B |= (1<<RXCIE0); /* enable RX complete interrupt */
}
void uart_putchar(char c, FILE *stream)