USART activity handled using interrupts
This commit is contained in:
parent
a3a1aadd02
commit
dc6012f4e5
74
src/main.c
74
src/main.c
|
@ -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: ");
|
||||
|
|
|
@ -17,4 +17,3 @@
|
|||
#define CH2_5 PD7
|
||||
|
||||
static void ioinit(void);
|
||||
static void pulse2time(uint16_t* burst, uint8_t pulses);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue