can learn IR commands

This commit is contained in:
King Kévin 2013-10-19 13:27:21 +02:00
parent 7e86211c93
commit 2dba5b10d2
3 changed files with 172 additions and 79 deletions

View File

@ -62,6 +62,8 @@ 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 */
volatile bool learn_flag = false; /* learn an IR command for an action */
enum IR_ACTIONS to_learn = IR_ACTION_END; /* IR action to learn */
/* UART receive interrupt */
ISR(USART_RX_vect) {
@ -208,6 +210,115 @@ void ioinit(void)
sei(); /* enable interrupts */
}
void help(void)
{
printf("commands:\n"\
"\thelp display this help\n"\
"\tpower show power state\n"\
"\tpower on switch power on\n"\
"\tpower off switch power off\n"\
"\tfan show fan speed\n"\
"\tch X Y show channel [1-2].[1-5] brightness\n"\
"\tch X Y Z set channel [1-2].[1-5] brightness [0-255]\n"\
"\tir learn power learn the IR command to power on/off\n"\
"\tir learn mode learn the IR command to change between modes\n"\
"\tir learn brightness up learn the IR command to increase brightness\n"\
"\tir learn brightness down learn the IR command to decrease brightness\n"\
"\tir learn channel next learn the IR command to select next channel\n"\
"\tir learn channel previous learn the IR command to select previous channel\n"\
);
}
void uart_action(char* str)
{
const char* delimiter = " ";
char* word = strtok(str,delimiter);
if (!word) {
goto error;
}
if (0==strcmp(word,"help")) {
help();
} else if (0==strcmp(word,"power")) {
word = strtok(NULL,delimiter);
if (!word) {
if (PINB&(1<<nPS_ON)) {
puts("power is off");
} else {
puts("power is on");
}
} else if (0==strcmp(word,"on")) {
PORTB &= ~(1<<nPS_ON);
} else if (0==strcmp(word,"off")) {
PORTB |= (1<<nPS_ON);
} else {
goto error;
}
} else if (0==strcmp(word,"fan")) {
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);
} else {
printf("fan is off (or not detected)\n");
}
} else {
printf("fan speed measurement not started\n");
}
} else {
printf("fan is off (or not detected)\n");
}
} else if (0==strcmp(word,"ir")) {
word = strtok(NULL,delimiter);
if (0==strcmp(word,"learn")) {
word = strtok(NULL,delimiter);
if (0==strcmp(word,"power")) {
to_learn = POWER;
learn_flag = true;
} else if (0==strcmp(word,"mode")) {
to_learn = MODE;
learn_flag = true;
} else if (0==strcmp(word,"brightness")) {
word = strtok(NULL,delimiter);
if (0==strcmp(word,"up")) {
to_learn = BRIGHTNESS_UP;
learn_flag = true;
} else if (0==strcmp(word,"down")) {
to_learn = BRIGHTNESS_DOWN;
learn_flag = true;
} else {
goto error;
}
} else if (0==strcmp(word,"channel")) {
word = strtok(NULL,delimiter);
if (0==strcmp(word,"next")) {
to_learn = CHANNEL_NEXT;
learn_flag = true;
} else if (0==strcmp(word,"previous")) {
to_learn = CHANNEL_PREVIOUS;
learn_flag = true;
} else {
goto error;
}
} else {
goto error;
}
} else {
goto error;
}
} else {
goto error;
}
if (learn_flag) {
puts("press button on remote to learn code");
}
return;
error:
puts("command not recognized");
}
int main(void)
{
ioinit(); /* initialize IOs */
@ -234,8 +345,11 @@ int main(void)
puts("can't store setting");
return 0;
}
puts("settings created");
} else {
load_settings();
puts("settings loaded");
}
load_settings();
while (true) {
/* calculated PWM values */
@ -276,7 +390,16 @@ int main(void)
c = input[command_i++];
putchar(c);
}
uart_action(c);
if ('\n'==c || '\r'==c) {
if ('\r'==c) {
puts("");
}
if (command_i>1) {
input[command_i-1] = '\0';
uart_action(input);
}
input_i = command_i = 0;
}
uart_flag = false;
}
/* handle power state */
@ -308,7 +431,18 @@ int main(void)
ir_repeat = 0;
}
if (ir_repeat==0 || ir_repeat>3) {
ir_action(ir_data.address,ir_data.command);
if (learn_flag) {
if (to_learn<IR_ACTION_END) {
ir_keys[to_learn][0] = ir_data.address;
ir_keys[to_learn][1] = ir_data.command;
}
save_settings();
puts("IR code learned");
to_learn = IR_ACTION_END;
learn_flag = false;
} else {
ir_action(ir_data.address,ir_data.command);
}
}
}
pulse = 0; /* reset burst */
@ -318,82 +452,40 @@ int main(void)
return 0;
}
void uart_action(char c)
{
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':
//ch_1[0] = (ch_1[0]+1)%(LEVELS+1);
channel_flag = true;
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);
} else {
printf("fan off (or not detected)\n");
}
} else {
printf("fan speed measurement not started\n");
}
} else {
printf("fan off (or not detected)\n");
}
break;
}
}
void ir_action(uint8_t address, uint8_t command)
{
if (0==address && 72==command) {
printf("switching power supply ");
if (PINB&(1<<nPS_ON)) {
puts("on");
} else {
puts("off");
enum IR_ACTIONS ir_code = IR_ACTION_END;
for (ir_code=0; ir_code<IR_ACTION_END; ir_code++) {
if (ir_keys[ir_code][0]==address && ir_keys[ir_code][1]==command) {
break;
}
}
if (ir_code<IR_ACTION_END) {
switch (ir_code) {
case POWER:
printf("switching power supply ");
if (PINB&(1<<nPS_ON)) {
puts("on");
} else {
puts("off");
}
PINB |= (1<<nPS_ON);
break;
case MODE:
break;
case BRIGHTNESS_UP:
break;
case BRIGHTNESS_DOWN:
break;
case CHANNEL_NEXT:
break;
case CHANNEL_PREVIOUS:
break;
default:
printf("unhandled IR action: %u\n", ir_code);
break;
}
PINB |= (1<<nPS_ON);
} else {
printf("IR addr: %u, command: %u\n", address, command);
puts("IR command not learned");
}
}

View File

@ -31,5 +31,6 @@ extern volatile uint8_t* DDRS[CHANNELS_1+CHANNELS_2]; /* channel I/O configurati
extern const uint8_t BITS[CHANNELS_1+CHANNELS_2]; /* channel bits */
void ioinit(void);
void uart_action(char c);
void help(void);
void uart_action(char* str);
void ir_action(uint8_t address, uint8_t command);

View File

@ -9,8 +9,8 @@ enum IR_ACTIONS { /* the actions for the infrared remote control */
MODE,
BRIGHTNESS_UP,
BRIGHTNESS_DOWN,
CHANNEL_UP,
CHANNEL_DOWN,
CHANNEL_NEXT,
CHANNEL_PREVIOUS,
IR_ACTION_END
};
extern uint8_t ir_keys[IR_ACTION_END][2]; // the IR NEC values (address+command) for the actions