2013-10-15 13:37:30 +02:00
|
|
|
/* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
/* This is the main part of the LED light controller program.
|
|
|
|
* It handles all peripherals (power, fan, channels, IR, serial)
|
|
|
|
*/
|
|
|
|
/* This program is specifically designed for hardware version A,
|
|
|
|
* with schematic revision 2, and layout revision 5.
|
|
|
|
*/
|
2013-10-12 17:05:01 +02:00
|
|
|
#include <stdint.h> /* Standard Integer Types */
|
|
|
|
#include <stdio.h> /* Standard IO facilities */
|
|
|
|
#include <stdlib.h> /* General utilities */
|
2013-10-14 16:47:25 +02:00
|
|
|
#include <stdbool.h> /* Boolean */
|
2013-10-12 17:05:01 +02:00
|
|
|
#include <string.h> /* Strings */
|
|
|
|
#include <avr/io.h> /* AVR device-specific IO definitions */
|
|
|
|
#include <util/delay.h> /* Convenience functions for busy-wait delay loops */
|
2013-10-13 16:47:46 +02:00
|
|
|
#include <avr/interrupt.h> /* Interrupts */
|
2013-10-12 17:05:01 +02:00
|
|
|
|
2013-10-12 18:19:39 +02:00
|
|
|
#include "main.h"
|
|
|
|
#include "uart.h"
|
2013-10-14 16:47:25 +02:00
|
|
|
#include "ir_nec.h"
|
2013-10-17 13:29:01 +02:00
|
|
|
#include "settings.h"
|
2013-10-12 17:05:01 +02:00
|
|
|
|
2013-10-13 16:47:46 +02:00
|
|
|
/* global variables */
|
2013-10-14 20:19:16 +02:00
|
|
|
#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 */
|
2013-10-14 11:24:51 +02:00
|
|
|
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 */
|
2013-10-17 13:29:01 +02:00
|
|
|
const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024}; /* timer 2 CS2[2:0] values */
|
2013-10-14 11:24:51 +02:00
|
|
|
volatile uint16_t tachometer = 0; /* the tachometer time (from timer) */
|
|
|
|
volatile uint8_t ir; /* IR signal state, to measure IR code */
|
2013-10-17 13:29:01 +02:00
|
|
|
const uint16_t TIMER1_PRESCALE[8] = {0,1,8,64,256,1024,0,0}; /* timer 1 CS1[2:0] values */
|
2013-10-14 20:19:16 +02:00
|
|
|
volatile uint16_t ir_tick; /* number of counter ticks per millisecond */
|
2013-10-14 16:47:25 +02:00
|
|
|
volatile uint8_t pulse = 0; /* pulse index within the burst */
|
2013-10-14 13:36:25 +02:00
|
|
|
#define PULSE_MAX 128 /* maximum number of pulses to save */
|
2013-10-14 16:47:25 +02:00
|
|
|
uint16_t burst[PULSE_MAX]; /* pulse times forming a burst (from timer) */
|
2013-10-13 19:39:31 +02:00
|
|
|
|
2013-10-15 13:20:49 +02:00
|
|
|
/* channel variables */
|
|
|
|
#define LEVELS 10 /* the number of PWM levels */
|
2013-10-17 13:29:01 +02:00
|
|
|
volatile uint8_t ch_tick = 0; /* the tick counter for the channel PWM */
|
2013-10-15 13:20:49 +02:00
|
|
|
|
2013-10-14 20:19:16 +02:00
|
|
|
/* flags, set in the interrupts and handled in the main program */
|
2013-10-15 13:20:49 +02:00
|
|
|
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 */
|
2013-10-14 20:19:16 +02:00
|
|
|
|
|
|
|
/* 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++;
|
|
|
|
}
|
2013-10-15 13:20:49 +02:00
|
|
|
uart_flag = true; /* set flag */
|
2013-10-14 20:19:16 +02:00
|
|
|
}
|
2013-10-13 16:47:46 +02:00
|
|
|
|
2013-10-14 11:24:51 +02:00
|
|
|
/* power ok interrupt */
|
2013-10-13 19:39:31 +02:00
|
|
|
ISR(PCINT0_vect) { /* PCI0 Interrupt Vector for PCINT[7:0] */
|
2013-10-13 16:47:46 +02:00
|
|
|
if (pwr_ok!=(PINB&(1<<PWR_OK))) { /* did the PWR_OK pin state changed */
|
|
|
|
pwr_ok = PINB&(1<<PWR_OK); /* save new state */
|
2013-10-14 20:19:16 +02:00
|
|
|
power_flag = true;
|
2013-10-14 11:24:51 +02:00
|
|
|
} else if (ir!=(PINB&(1<<IR))) { /* did the IR pin state changed */
|
|
|
|
ir = PINB&(1<<IR); /* save new state */
|
2013-10-14 13:36:25 +02:00
|
|
|
if (pulse>0) { /* save pulse, except the first */
|
2013-10-14 20:19:16 +02:00
|
|
|
burst[pulse-1] = (TCNT1*1000UL)/ir_tick;
|
2013-10-14 13:36:25 +02:00
|
|
|
burst[pulse] = 0;
|
2013-10-14 11:24:51 +02:00
|
|
|
}
|
2013-10-14 13:36:25 +02:00
|
|
|
if (pulse<PULSE_MAX-1) { /* prepare to save next pulse */
|
|
|
|
pulse++;
|
2013-10-14 11:24:51 +02:00
|
|
|
}
|
|
|
|
TCNT1 = 0; /* clear timer 1 */
|
2013-10-13 16:47:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-13 19:39:31 +02:00
|
|
|
/* fan tachometer interrupt */
|
|
|
|
ISR(PCINT1_vect) { /* PCI0 Interrupt Vector for PCINT[14:8] */
|
|
|
|
if (fan!=(PINC&(1<<FAN))) { /* did the FAN pin state changed */
|
|
|
|
fan = PINC&(1<<FAN); /* save new state */
|
2013-10-14 11:24:51 +02:00
|
|
|
if (fan) { /* only react to rising edge */
|
|
|
|
tachometer = (uint16_t)(timer2_ovf<<8)+TCNT2; /* save time */
|
2013-10-13 19:39:31 +02:00
|
|
|
TCNT2 = 0; /* reset timer 2 */
|
2013-10-14 11:24:51 +02:00
|
|
|
timer2_ovf = 0; /* reset timer 2 */
|
2013-10-13 19:39:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-14 11:24:51 +02:00
|
|
|
/* timer 2 interrupt used to measure fan speed based on tachometer */
|
|
|
|
ISR(TIMER2_OVF_vect) { /* timer 2 overflow interrupt vector */
|
|
|
|
if (timer2_ovf<0xff) { /* prevent overflow */
|
|
|
|
timer2_ovf++; /* increase tachometer counter */
|
2013-10-14 20:40:52 +02:00
|
|
|
} else {
|
|
|
|
tachometer = 0; /* indicate no speed can be measured */
|
2013-10-14 20:45:08 +02:00
|
|
|
if (pwr_ok) { /* warn the fan is dead while the power in on */
|
|
|
|
power_flag = true;
|
|
|
|
}
|
|
|
|
timer2_ovf = 0;
|
2013-10-14 11:24:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-14 20:40:52 +02:00
|
|
|
/* timer 1 interrupt used to timeout IR burst */
|
2013-10-14 11:24:51 +02:00
|
|
|
ISR(TIMER1_COMPA_vect) { /* timer 1 OCR1A match interrupt vector */
|
2013-10-14 20:40:52 +02:00
|
|
|
if (pulse>0 && !ir_flag) { /* warm an burst is ready when the timeout triggered */
|
|
|
|
ir_flag = true;
|
2013-10-13 19:39:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-15 13:20:49 +02:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2013-10-17 13:29:01 +02:00
|
|
|
void ioinit(void)
|
2013-10-12 17:05:01 +02:00
|
|
|
{
|
2013-10-13 11:46:53 +02:00
|
|
|
/* configure power */
|
2013-10-13 16:47:46 +02:00
|
|
|
DDRB |= (1<<nPS_ON); /* nPS_ON is output */
|
|
|
|
PORTB |= (1<<nPS_ON); /* switch off power supply */
|
|
|
|
DDRB &= ~(1<<PWR_OK); /* PWR_ON (PB1/PCINT1) is input */
|
|
|
|
pwr_ok = PINB&(1<<PWR_OK); /* save state */
|
|
|
|
PCIFR &= ~(1<<PCIF0); /* clear interrupt flag */
|
|
|
|
PCICR |= (1<<PCIE0); /* enable interrupt for PCINT[7:0] */
|
|
|
|
PCMSK0 |= (1<<PCINT1); /* enable interrupt for PCINT1 */
|
2013-10-13 11:46:53 +02:00
|
|
|
|
2013-10-14 11:24:51 +02:00
|
|
|
/* configure LED (on PD6/OC0A) */
|
|
|
|
DDRD |= (1<<LED); /* LED is output */
|
2013-10-15 13:20:49 +02:00
|
|
|
PORTD &= ~(1<<LED); /* switch LED on */
|
2013-10-14 11:24:51 +02:00
|
|
|
|
2013-10-13 19:39:31 +02:00
|
|
|
/* configure FAN */
|
|
|
|
DDRC &= ~(1<<FAN); /* FAN (PC5/PCINT13) is input */
|
|
|
|
fan = PINC&(1<<FAN); /* save state */
|
|
|
|
PCIFR &= ~(1<<PCIF1); /* clear interrupt flag */
|
|
|
|
PCICR |= (1<<PCIE1); /* enable interrupt for PCINT[14:8] */
|
|
|
|
PCMSK1 |= (1<<PCINT13); /* enable interrupt for PCINT1 */
|
|
|
|
/* use timer 2 to measure the tachometer */
|
|
|
|
/* use normal mode */
|
|
|
|
TCCR2A &= ~((1<<WGM20)|(1<<WGM21));
|
|
|
|
TCCR2B &= ~(1<<WGM22);
|
2013-10-14 11:24:51 +02:00
|
|
|
/* clock/64 prescaler */
|
|
|
|
TCCR2B |= (1<<CS22);
|
|
|
|
TCCR2B &= ~((1<<CS21)|(1<<CS20));
|
2013-10-16 21:56:05 +02:00
|
|
|
TIFR2 = (1<<TOV2); /* clear timer 2 overflow interrupt flag */
|
2013-10-13 19:39:31 +02:00
|
|
|
TIMSK2 |= (1<<TOIE2); /* enable timer 2 overflow interrupt */
|
2013-10-13 11:46:53 +02:00
|
|
|
|
2013-10-14 11:24:51 +02:00
|
|
|
/* configure IR receiver */
|
|
|
|
DDRB &= ~(1<<IR); /* IR (PB0/PCINT0) receiver is input */
|
|
|
|
ir = PINB&(1<<IR); /* save state */
|
2013-10-16 21:56:05 +02:00
|
|
|
PCIFR = (1<<PCIF0); /* clear interrupt flag */
|
2013-10-14 11:24:51 +02:00
|
|
|
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));
|
2013-10-14 20:19:16 +02:00
|
|
|
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) */
|
|
|
|
}
|
2013-10-15 13:20:49 +02:00
|
|
|
TIFR1 &= ~(1<<OCF1A); /* clear timer 1 compare interrupt flag */
|
|
|
|
TIMSK1 |= (1<<OCIE1A); /* enable timer 1 compare interrupt */
|
2013-10-14 11:24:51 +02:00
|
|
|
|
2013-10-13 11:46:53 +02:00
|
|
|
/* 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 */
|
|
|
|
PORTC &= ~((1<<CH1_1)|(1<<CH1_2)|(1<<CH1_3)|(1<<CH1_4)|(1<<CH1_5)); /* switch off CH1_x */
|
|
|
|
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 */
|
|
|
|
|
2013-10-15 13:20:49 +02:00
|
|
|
/* 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 */
|
2013-10-16 21:56:05 +02:00
|
|
|
TIFR0 = (1<<OCF0A); /* clear timer 0 compare interrupt flag */
|
2013-10-15 13:20:49 +02:00
|
|
|
TIMSK0 |= (1<<OCIE0A); /* enable timer 0 compare interrupt */
|
|
|
|
|
2013-10-13 11:46:53 +02:00
|
|
|
/* use UART as terminal */
|
|
|
|
uart_init();
|
2013-10-12 18:19:39 +02:00
|
|
|
stdout = &uart_output;
|
|
|
|
stdin = &uart_input;
|
2013-10-13 11:46:53 +02:00
|
|
|
|
2013-10-13 16:47:46 +02:00
|
|
|
sei(); /* enable interrupts */
|
2013-10-12 17:05:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
ioinit(); /* initialize IOs */
|
|
|
|
|
2013-10-14 20:19:16 +02:00
|
|
|
uint8_t command_i = 0; /* command index */
|
2013-10-14 20:45:08 +02:00
|
|
|
struct nec ir_data; /* last IR data */
|
|
|
|
ir_data.valid = false;
|
|
|
|
ir_data.repeat = false;
|
|
|
|
ir_data.address = 0;
|
|
|
|
ir_data.command = 0;
|
|
|
|
uint8_t ir_repeat = 0; /* number of times the IR data has been repeated */
|
2013-10-12 17:05:01 +02:00
|
|
|
|
2013-10-17 13:29:01 +02:00
|
|
|
uint8_t on[CHANNELS_1+CHANNELS_2]; /* times when to switch on the output on the channels */
|
|
|
|
uint8_t off[CHANNELS_1+CHANNELS_2]; /* times when to switch off the output on the channels */
|
2013-10-15 13:20:49 +02:00
|
|
|
channel_flag = true; /* calculate above values later */
|
|
|
|
|
2013-10-14 11:24:51 +02:00
|
|
|
puts("LED dimmer up & running");
|
2013-10-17 13:29:01 +02:00
|
|
|
verify_settings();
|
|
|
|
return 0;
|
2013-10-14 20:19:16 +02:00
|
|
|
while (true) {
|
2013-10-15 13:20:49 +02:00
|
|
|
/* calculated PWM values */
|
|
|
|
while (channel_flag) {
|
|
|
|
uint8_t start = 0;
|
2013-10-17 13:29:01 +02:00
|
|
|
for (uint8_t i=0; i<CHANNELS_1+CHANNELS_2; i++) {
|
|
|
|
on[i] = (start)%LEVELS;
|
|
|
|
off[i] = (on[i]+brightness[mode][i])%LEVELS;
|
|
|
|
start = (start+brightness[mode][i])%LEVELS;
|
2013-10-15 13:20:49 +02:00
|
|
|
}
|
|
|
|
channel_flag = false;
|
|
|
|
}
|
|
|
|
/* generate PWM for channel */
|
|
|
|
while (pwm_flag) {
|
|
|
|
if (pwr_ok) {
|
2013-10-17 13:29:01 +02:00
|
|
|
for (int i=0; i<CHANNELS_1+CHANNELS_2; i++) {
|
|
|
|
if (on[i]==ch_tick) {
|
|
|
|
if (on[i]!=off[i]) {
|
|
|
|
*(PORTS[i]) |= (1<<BITS[i]);
|
|
|
|
} else if (brightness[mode][i]==0) {
|
|
|
|
*(PORTS[i]) &= ~(1<<BITS[i]);
|
2013-10-15 13:20:49 +02:00
|
|
|
} else {
|
2013-10-17 13:29:01 +02:00
|
|
|
*(PORTS[i]) |= (1<<BITS[i]);
|
2013-10-15 13:20:49 +02:00
|
|
|
}
|
2013-10-17 13:29:01 +02:00
|
|
|
} else if (off[i]==ch_tick) {
|
|
|
|
*(PORTS[i]) &= ~(1<<BITS[i]);
|
2013-10-15 13:20:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
PIND |= (1<<LED);
|
|
|
|
}
|
|
|
|
pwm_flag = false;
|
|
|
|
}
|
|
|
|
/* handle UART input */
|
|
|
|
while (uart_flag) {
|
2013-10-14 20:40:52 +02:00
|
|
|
/* echo back */
|
|
|
|
char c = 0;
|
2013-10-14 20:19:16 +02:00
|
|
|
while (command_i<input_i) {
|
|
|
|
c = input[command_i++];
|
2013-10-14 20:40:52 +02:00
|
|
|
putchar(c);
|
2013-10-14 20:19:16 +02:00
|
|
|
}
|
2013-10-14 20:45:08 +02:00
|
|
|
uart_action(c);
|
2013-10-15 13:20:49 +02:00
|
|
|
uart_flag = false;
|
2013-10-14 20:19:16 +02:00
|
|
|
}
|
2013-10-14 20:40:52 +02:00
|
|
|
/* handle power state */
|
|
|
|
while (power_flag) {
|
|
|
|
if (pwr_ok) {
|
|
|
|
puts("power ok");
|
|
|
|
/* verify if FAN is present */
|
2013-10-14 20:45:08 +02:00
|
|
|
_delay_ms(500);
|
2013-10-14 20:40:52 +02:00
|
|
|
if (0==tachometer) {
|
|
|
|
puts("FAN not on, switching power off");
|
|
|
|
PORTB |= (1<<nPS_ON);
|
2013-10-13 11:46:53 +02:00
|
|
|
}
|
2013-10-14 20:40:52 +02:00
|
|
|
} else {
|
2013-10-14 20:45:08 +02:00
|
|
|
puts("power off");
|
2013-10-14 20:40:52 +02:00
|
|
|
}
|
2013-10-14 20:45:08 +02:00
|
|
|
power_flag = false;
|
2013-10-14 20:40:52 +02:00
|
|
|
}
|
|
|
|
/* handle IR input */
|
|
|
|
while (ir_flag) {
|
|
|
|
time2nec(burst,pulse-1); /* convert raw time burst in NEC format */
|
2013-10-14 20:45:08 +02:00
|
|
|
struct nec ir_tmp = nec2data(burst,pulse-1); /* decode NEC burst */
|
|
|
|
if (ir_tmp.valid) {
|
|
|
|
if (ir_tmp.repeat) {
|
|
|
|
if (ir_repeat<0xff) {
|
|
|
|
ir_repeat++;
|
|
|
|
}
|
2013-10-13 11:46:53 +02:00
|
|
|
} else {
|
2013-10-14 20:45:08 +02:00
|
|
|
ir_data = ir_tmp;
|
|
|
|
ir_repeat = 0;
|
|
|
|
}
|
|
|
|
if (ir_repeat==0 || ir_repeat>3) {
|
|
|
|
ir_action(ir_data.address,ir_data.command);
|
2013-10-13 12:19:17 +02:00
|
|
|
}
|
2013-10-14 20:40:52 +02:00
|
|
|
}
|
|
|
|
pulse = 0; /* reset burst */
|
|
|
|
ir_flag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-10-17 13:29:01 +02:00
|
|
|
void uart_action(char c)
|
2013-10-14 20:40:52 +02:00
|
|
|
{
|
|
|
|
switch (c) {
|
|
|
|
case 'l':
|
|
|
|
PIND |= (1<<LED);
|
|
|
|
printf("LED: ");
|
|
|
|
if (PIND&(1<<LED)) {
|
|
|
|
puts("off");
|
|
|
|
} else {
|
|
|
|
puts("on");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
printf("switching power supply ");
|
|
|
|
if (PINB&(1<<nPS_ON)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
PINB |= (1<<nPS_ON);
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
printf("power: ");
|
|
|
|
if (PINB&(1<<PWR_OK)) {
|
|
|
|
puts("ok");
|
|
|
|
} else {
|
|
|
|
puts("ko");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '1':
|
2013-10-17 13:29:01 +02:00
|
|
|
//ch_1[0] = (ch_1[0]+1)%(LEVELS+1);
|
2013-10-15 13:20:49 +02:00
|
|
|
channel_flag = true;
|
2013-10-14 20:40:52 +02:00
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
PINC |= (1<<CH1_2);
|
|
|
|
printf("CH1_2: ");
|
|
|
|
if (PINC&(1<<CH1_2)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '3':
|
|
|
|
PINC |= (1<<CH1_3);
|
|
|
|
printf("CH1_3: ");
|
|
|
|
if (PINC&(1<<CH1_3)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '4':
|
|
|
|
PINC |= (1<<CH1_4);
|
|
|
|
printf("CH1_4: ");
|
|
|
|
if (PINC&(1<<CH1_4)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '5':
|
|
|
|
PINC |= (1<<CH1_5);
|
|
|
|
printf("CH1_5: ");
|
|
|
|
if (PINC&(1<<CH1_5)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '6':
|
|
|
|
PIND |= (1<<CH2_1);
|
|
|
|
printf("CH2_1: ");
|
|
|
|
if (PIND&(1<<CH2_1)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '7':
|
|
|
|
PIND |= (1<<CH2_2);
|
|
|
|
printf("CH2_2: ");
|
|
|
|
if (PIND&(1<<CH2_2)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
PIND |= (1<<CH2_3);
|
|
|
|
printf("CH2_3: ");
|
|
|
|
if (PIND&(1<<CH2_3)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '9':
|
|
|
|
PIND |= (1<<CH2_4);
|
|
|
|
printf("CH2_4: ");
|
|
|
|
if (PIND&(1<<CH2_4)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
PIND |= (1<<CH2_5);
|
|
|
|
printf("CH2_5: ");
|
|
|
|
if (PIND&(1<<CH2_5)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
if (OCR0A>0) {
|
|
|
|
OCR0A--;
|
|
|
|
}
|
|
|
|
printf("decreasing LED: %u\n",OCR0A);
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
if (OCR0A<0xff) {
|
|
|
|
OCR0A++;
|
|
|
|
}
|
|
|
|
printf("increasing LED: %u\n",OCR0A);
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
if (tachometer) {
|
|
|
|
uint16_t prescale = TIMER2_PRESCALE[TCCR2B&((1<<CS22)|(1<<CS21)|(1<<CS20))];
|
|
|
|
if (prescale) {
|
|
|
|
if (timer2_ovf<0xff) {
|
|
|
|
uint32_t speed = ((60*F_CPU)/(prescale*(uint32_t)tachometer))/2; /* calculate speed. 2 pulses per revolution */
|
|
|
|
printf("fan speed: %lurpm\n",speed);
|
2013-10-14 11:24:51 +02:00
|
|
|
} else {
|
2013-10-14 20:40:52 +02:00
|
|
|
printf("fan off (or not detected)\n");
|
2013-10-13 19:39:31 +02:00
|
|
|
}
|
|
|
|
} else {
|
2013-10-14 20:40:52 +02:00
|
|
|
printf("fan speed measurement not started\n");
|
2013-10-13 19:39:31 +02:00
|
|
|
}
|
2013-10-14 20:40:52 +02:00
|
|
|
} else {
|
|
|
|
printf("fan off (or not detected)\n");
|
|
|
|
}
|
|
|
|
break;
|
2013-10-12 17:05:01 +02:00
|
|
|
}
|
|
|
|
}
|
2013-10-14 20:45:08 +02:00
|
|
|
|
2013-10-17 13:29:01 +02:00
|
|
|
void ir_action(uint8_t address, uint8_t command)
|
2013-10-14 20:45:08 +02:00
|
|
|
{
|
|
|
|
if (0==address && 72==command) {
|
|
|
|
printf("switching power supply ");
|
|
|
|
if (PINB&(1<<nPS_ON)) {
|
|
|
|
puts("on");
|
|
|
|
} else {
|
|
|
|
puts("off");
|
|
|
|
}
|
|
|
|
PINB |= (1<<nPS_ON);
|
|
|
|
} else {
|
|
|
|
printf("IR addr: %u, command: %u\n", address, command);
|
|
|
|
}
|
|
|
|
}
|