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"
|
#include "ir_nec.h"
|
||||||
|
|
||||||
/* global variables */
|
/* 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 pwr_ok; /* is power ok */
|
||||||
volatile uint8_t fan; /* fan signal state, to measure tachometer */
|
volatile uint8_t fan; /* fan signal state, to measure tachometer */
|
||||||
volatile uint8_t timer2_ovf = 0; /* to measure fan speed using timer 2 */
|
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 uint16_t tachometer = 0; /* the tachometer time (from timer) */
|
||||||
volatile uint8_t ir; /* IR signal state, to measure IR code */
|
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 */
|
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 */
|
volatile uint8_t pulse = 0; /* pulse index within the burst */
|
||||||
#define PULSE_MAX 128 /* maximum number of pulses to save */
|
#define PULSE_MAX 128 /* maximum number of pulses to save */
|
||||||
uint16_t burst[PULSE_MAX]; /* pulse times forming a burst (from timer) */
|
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 */
|
/* 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) {
|
power_flag = true;
|
||||||
/* switch timer 2 on to start measuring the fan speed */
|
|
||||||
puts("power ok");
|
|
||||||
} else {
|
|
||||||
puts("power ko");
|
|
||||||
}
|
|
||||||
} else if (ir!=(PINB&(1<<IR))) { /* did the IR pin state changed */
|
} else if (ir!=(PINB&(1<<IR))) { /* did the IR pin state changed */
|
||||||
ir = PINB&(1<<IR); /* save new state */
|
ir = PINB&(1<<IR); /* save new state */
|
||||||
if (pulse>0) { /* save pulse, except the first */
|
if (pulse>0) { /* save pulse, except the first */
|
||||||
burst[pulse-1] = TCNT1;
|
burst[pulse-1] = (TCNT1*1000UL)/ir_tick;
|
||||||
burst[pulse] = 0;
|
burst[pulse] = 0;
|
||||||
}
|
}
|
||||||
if (pulse<PULSE_MAX-1) { /* prepare to save next pulse */
|
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 */
|
/* timer 1 interrupt used to measure IR pulse */
|
||||||
ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
|
ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
|
||||||
if (pulse>0) {
|
if (pulse>0) {
|
||||||
pulse2time(burst,pulse-1);
|
|
||||||
time2nec(burst,pulse-1);
|
time2nec(burst,pulse-1);
|
||||||
struct nec ir_data = nec2data(burst,pulse-1);
|
struct nec ir_data = nec2data(burst,pulse-1);
|
||||||
if (ir_data.valid) {
|
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);
|
printf("IR addr: %u, command: %u\n",ir_data.address,ir_data.command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OCR0A = ~OCR0A;
|
|
||||||
pulse = 0;
|
pulse = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,8 +150,11 @@ static void ioinit(void)
|
||||||
/* clock/8 prescaler, offers most precision for 15ms (up to 28.5ms) */
|
/* clock/8 prescaler, offers most precision for 15ms (up to 28.5ms) */
|
||||||
TCCR1B |= (1<<CS11);
|
TCCR1B |= (1<<CS11);
|
||||||
TCCR1B &= ~((1<<CS12)|(1<<CS10));
|
TCCR1B &= ~((1<<CS12)|(1<<CS10));
|
||||||
uint16_t prescale = TIMER1_PRESCALE[(TCCR1B&((1<<CS12)|(1<<CS11)|(1<<CS10)))>>CS10];
|
uint16_t prescale = TIMER1_PRESCALE[(TCCR1B&((1<<CS12)|(1<<CS11)|(1<<CS10)))>>CS10]; /* timer 1 presacler */
|
||||||
OCR1A = (uint32_t)(15*F_CPU)/(1000*prescale); /* set clear time to 15 ms (no IR toggle should be longer) */
|
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 */
|
TIFR1 &= ~(1<<OCF1A); /* clear timer 1 overflow interrupt flag */
|
||||||
TIMSK1 |= (1<<OCIE1A); /* enable timer 1 overflow interrupt */
|
TIMSK1 |= (1<<OCIE1A); /* enable timer 1 overflow interrupt */
|
||||||
|
|
||||||
|
@ -159,35 +172,28 @@ static void ioinit(void)
|
||||||
sei(); /* enable interrupts */
|
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)
|
int main(void)
|
||||||
{
|
{
|
||||||
ioinit(); /* initialize IOs */
|
ioinit(); /* initialize IOs */
|
||||||
|
|
||||||
char input;
|
uint8_t command_i = 0; /* command index */
|
||||||
|
char c = 0;
|
||||||
|
|
||||||
puts("LED dimmer up & running");
|
puts("LED dimmer up & running");
|
||||||
_delay_ms(1000);
|
while (true) {
|
||||||
while(1) {
|
/* handle user input */
|
||||||
input = getchar();
|
while (input_flag) {
|
||||||
printf("%c\n", input);
|
while (command_i<input_i) {
|
||||||
switch (input) {
|
c = input[command_i++];
|
||||||
|
putchar(c); /* echo back */
|
||||||
|
}
|
||||||
|
input_flag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_delay_ms(1000);
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
case 'l':
|
case 'l':
|
||||||
PIND |= (1<<LED);
|
PIND |= (1<<LED);
|
||||||
printf("LED: ");
|
printf("LED: ");
|
||||||
|
|
|
@ -17,4 +17,3 @@
|
||||||
#define CH2_5 PD7
|
#define CH2_5 PD7
|
||||||
|
|
||||||
static void ioinit(void);
|
static void ioinit(void);
|
||||||
static void pulse2time(uint16_t* burst, uint8_t pulses);
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ void uart_init(void)
|
||||||
#else
|
#else
|
||||||
UCSR0A &= ~(1<<U2X0);
|
UCSR0A &= ~(1<<U2X0);
|
||||||
#endif
|
#endif
|
||||||
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); /* 8N1-bit data */
|
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); /* 8N1 bit data */
|
||||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0); /* enable RX and TX */
|
UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* enable RX and TX */
|
||||||
|
UCSR0B |= (1<<RXCIE0); /* enable RX complete interrupt */
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_putchar(char c, FILE *stream)
|
void uart_putchar(char c, FILE *stream)
|
||||||
|
|
Loading…
Reference in New Issue