task scheduler and handlers implemented (basics)
This commit is contained in:
parent
72182dc780
commit
95910b32fa
138
src/main.c
138
src/main.c
|
@ -18,19 +18,33 @@ 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 */
|
||||
static const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024}; /* timer 2 CS2[2:0] values */
|
||||
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 */
|
||||
static const uint16_t TIMER1_PRESCALE[8] = {0,1,8,64,256,1024,0,0}; /* timer 1 CS1[2:0] values */
|
||||
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) */
|
||||
|
||||
/* channel variables */
|
||||
#define LEVELS 10 /* the number of PWM levels */
|
||||
uint8_t ch_tick = 0; /* the tick counter for the channel PWM */
|
||||
#define OUTPUTS_1 5 /* the number of outputs for channel 1 */
|
||||
#define OUTPUTS_2 5 /* the number of outputs for channel 2 */
|
||||
volatile uint8_t* PORTS_1[OUTPUTS_1] = {&PORTC,&PORTC,&PORTC,&PORTC,&PORTC}; /* channel 1 output ports */
|
||||
volatile uint8_t* PORTS_2[OUTPUTS_2] = {&PORTD,&PORTD,&PORTD,&PORTD,&PORTD}; /* channel 2 output ports */
|
||||
uint8_t BITS_1[OUTPUTS_1] = {PC0,PC1,PC2,PC3,PC4}; /* channel 1 output bits */
|
||||
uint8_t BITS_2[OUTPUTS_2] = {PD2,PD3,PD4,PD5,PD7}; /* channel 2 output bits */
|
||||
uint8_t ch_1[OUTPUTS_1]; /* the level value for the channel 1 outputs */
|
||||
uint8_t ch_2[OUTPUTS_2]; /* the level value for the channel 2 outputs */
|
||||
|
||||
/* flags, set in the interrupts and handled in the main program */
|
||||
volatile bool input_flag = false;
|
||||
volatile bool power_flag = false;
|
||||
volatile bool ir_flag = false;
|
||||
volatile bool uart_flag = false; /* an incoming activity on the UART */
|
||||
volatile bool power_flag = false; /* a change in the power or fan */
|
||||
volatile bool ir_flag = false; /* to process a burst */
|
||||
volatile bool pwm_flag = false; /* to trigger a PWM tick */
|
||||
volatile bool channel_flag = false; /* indicate a change in the channel PWM values */
|
||||
|
||||
/* UART receive interrupt */
|
||||
ISR(USART_RX_vect) {
|
||||
|
@ -39,7 +53,7 @@ ISR(USART_RX_vect) {
|
|||
if (input_i<INPUT_MAX) { /* next character, if space is available */
|
||||
input_i++;
|
||||
}
|
||||
input_flag = true; /* set flag */
|
||||
uart_flag = true; /* set flag */
|
||||
}
|
||||
|
||||
/* power ok interrupt */
|
||||
|
@ -92,6 +106,12 @@ ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
|
|||
}
|
||||
}
|
||||
|
||||
/* timer 0 interrupt used generate a PWM for the channels */
|
||||
ISR(TIMER0_COMPA_vect) { /* timer 0 OCR0A match interrupt vector */
|
||||
ch_tick = (ch_tick+1)%LEVELS;
|
||||
pwm_flag = true;
|
||||
}
|
||||
|
||||
static void ioinit(void)
|
||||
{
|
||||
/* configure power */
|
||||
|
@ -105,18 +125,7 @@ static void ioinit(void)
|
|||
|
||||
/* configure LED (on PD6/OC0A) */
|
||||
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;
|
||||
PORTD &= ~(1<<LED); /* switch LED on */
|
||||
|
||||
/* configure FAN */
|
||||
DDRC &= ~(1<<FAN); /* FAN (PC5/PCINT13) is input */
|
||||
|
@ -153,8 +162,8 @@ static void ioinit(void)
|
|||
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 */
|
||||
TIFR1 &= ~(1<<OCF1A); /* clear timer 1 compare interrupt flag */
|
||||
TIMSK1 |= (1<<OCIE1A); /* enable timer 1 compare interrupt */
|
||||
|
||||
/* 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 */
|
||||
|
@ -162,6 +171,18 @@ static void ioinit(void)
|
|||
DDRD |= (1<<CH2_1)|(1<<CH2_2)|(1<<CH2_3)|(1<<CH2_4)|(1<<CH2_5); /* CH2_x is output */
|
||||
PORTD &= ~((1<<CH2_1)|(1<<CH2_2)|(1<<CH2_3)|(1<<CH2_4)|(1<<CH2_5)); /* switch off CH2_x */
|
||||
|
||||
/* use timer 0 as source for the channel PWM */
|
||||
/* use CTC mode */
|
||||
TCCR0A |= (1<<WGM01);
|
||||
TCCR0A &= ~(1<<WGM00);
|
||||
TCCR0B &= ~(1<<WGM02);
|
||||
/* /64 prescale timer */
|
||||
TCCR0B &= ~(1<<CS02);
|
||||
TCCR0B |= (1<<CS01)|(1<<CS00);
|
||||
OCR0A = 0xff; /* set PWM speed */
|
||||
TIFR0 &= ~(1<<OCF0A); /* clear timer 0 compare interrupt flag */
|
||||
TIMSK0 |= (1<<OCIE0A); /* enable timer 0 compare interrupt */
|
||||
|
||||
/* use UART as terminal */
|
||||
uart_init();
|
||||
stdout = &uart_output;
|
||||
|
@ -182,10 +203,72 @@ int main(void)
|
|||
ir_data.command = 0;
|
||||
uint8_t ir_repeat = 0; /* number of times the IR data has been repeated */
|
||||
|
||||
/* initialize channel output PWM values */
|
||||
for (uint8_t i=0; i<OUTPUTS_1; i++) {
|
||||
ch_1[i] = 0;
|
||||
}
|
||||
for (uint8_t i=0; i<OUTPUTS_2; i++) {
|
||||
ch_2[i] = 0;
|
||||
}
|
||||
uint8_t on_1[5] = {0,0,0,0,0}; /* times when to switch on the outputs for channel 1 */
|
||||
uint8_t on_2[5] = {0,0,0,0,0}; /* times when to switch on the outputs for channel 2 */
|
||||
uint8_t off_1[5] = {0,0,0,0,0}; /* times when to switch off the outputs for channel 1 */
|
||||
uint8_t off_2[5] = {0,0,0,0,0}; /* times when to switch off the outputs for channel 2 */
|
||||
channel_flag = true; /* calculate above values later */
|
||||
|
||||
puts("LED dimmer up & running");
|
||||
while (true) {
|
||||
/* handle user input */
|
||||
while (input_flag) {
|
||||
/* calculated PWM values */
|
||||
while (channel_flag) {
|
||||
uint8_t start = 0;
|
||||
for (uint8_t i=0; i<OUTPUTS_1; i++) {
|
||||
on_1[i] = (start)%LEVELS;
|
||||
off_1[i] = (on_1[i]+ch_1[i])%LEVELS;
|
||||
start = (start+ch_1[i])%LEVELS;
|
||||
}
|
||||
start = 0;
|
||||
for (uint8_t i=0; i<OUTPUTS_2; i++) {
|
||||
on_2[i] = (start)%LEVELS;
|
||||
off_2[i] = (on_2[i]+ch_2[i])%LEVELS;
|
||||
start = (start+ch_2[i])%LEVELS;
|
||||
}
|
||||
channel_flag = false;
|
||||
}
|
||||
/* generate PWM for channel */
|
||||
while (pwm_flag) {
|
||||
if (pwr_ok) {
|
||||
for (int i=0; i<OUTPUTS_1; i++) {
|
||||
if (on_1[i]==ch_tick) {
|
||||
if (on_1[i]!=off_1[i]) {
|
||||
*(PORTS_1[i]) |= (1<<BITS_1[i]);
|
||||
} else if (ch_1[i]==0) {
|
||||
*(PORTS_1[i]) &= ~(1<<BITS_1[i]);
|
||||
} else {
|
||||
*(PORTS_1[i]) |= (1<<BITS_1[i]);
|
||||
}
|
||||
} else if (off_1[i]==ch_tick) {
|
||||
*(PORTS_1[i]) &= ~(1<<BITS_1[i]);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<OUTPUTS_2; i++) {
|
||||
if (on_2[i]==ch_tick) {
|
||||
if (on_2[i]!=off_2[i]) {
|
||||
*(PORTS_2[i]) |= (1<<BITS_2[i]);
|
||||
} else if (ch_2[i]==0) {
|
||||
*(PORTS_2[i]) &= ~(1<<BITS_2[i]);
|
||||
} else {
|
||||
*(PORTS_2[i]) |= (1<<BITS_2[i]);
|
||||
}
|
||||
} else if (off_2[i]==ch_tick) {
|
||||
*(PORTS_2[i]) &= ~(1<<BITS_2[i]);
|
||||
}
|
||||
}
|
||||
PIND |= (1<<LED);
|
||||
}
|
||||
pwm_flag = false;
|
||||
}
|
||||
/* handle UART input */
|
||||
while (uart_flag) {
|
||||
/* echo back */
|
||||
char c = 0;
|
||||
while (command_i<input_i) {
|
||||
|
@ -193,7 +276,7 @@ int main(void)
|
|||
putchar(c);
|
||||
}
|
||||
uart_action(c);
|
||||
input_flag = false;
|
||||
uart_flag = false;
|
||||
}
|
||||
/* handle power state */
|
||||
while (power_flag) {
|
||||
|
@ -264,13 +347,8 @@ static void uart_action(char c)
|
|||
}
|
||||
break;
|
||||
case '1':
|
||||
PINC |= (1<<CH1_1);
|
||||
printf("CH1_1: ");
|
||||
if (PINC&(1<<CH1_1)) {
|
||||
puts("on");
|
||||
} else {
|
||||
puts("off");
|
||||
}
|
||||
ch_1[0] = (ch_1[0]+1)%(LEVELS+1);
|
||||
channel_flag = true;
|
||||
break;
|
||||
case '2':
|
||||
PINC |= (1<<CH1_2);
|
||||
|
|
Loading…
Reference in New Issue