Esempio n. 1
0
/**
 * @brief Entry point to start execution at
 *
 * This is the main entry point where execution will start. It initializes the
 * hardware and enters an infinite loop handling any upcoming events not yet
 * covered.
 *
 * @note This function makes use of the attribute "OS_main". For details
 * refer to [1].
 *
 * [1]: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
 *
 * @return Should never return anything
 */
__attribute__((OS_main)) int main()
{

    uart_init();

    log_main("Init...\n");

    preferences_init();

    #if (ENABLE_DCF_SUPPORT == 1)

        dcf77_init();

    #endif

    display_init();
    datetime_init();
    ldr_init();
    pwm_init();
    irmp_init();
    timer_init();
    user_init();

    sei();

    pwm_on();

    log_main("Init finished\n");

    while (1) {

        brightness_handle();
        datetime_handle();
        handle_ir_code();

        #if (ENABLE_UART_PROTOCOL == 1)

            uart_protocol_handle();

        #endif /* (ENABLE_UART_PROTOCOL == 1) */

        #if (ENABLE_DCF_SUPPORT == 1)

            datetime_t dt;

            // TODO: Make sure dcf77_getDateTime() validates its result
            if (dcf77_get_datetime(&dt)) {

                datetime_set(&dt);

            }

        #endif

    }

}
Esempio n. 2
0
/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * MAIN: main routine
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */

//int main(void) __attribute__((noreturn)); /* saves some Bytes but produces warning */
int
main (void)
{
  static DATETIME  datetime;  

  uart_init();                                                                  // initialize uart
  log_main("Init...\n");

  wcEeprom_init();

# if (DCF_PRESENT == 1)
    dcf77_init ();                                                              // initialize dcf77
# endif

  display_init ();                                                              // initialize display

  { // local to save stack
    uint8_t     i2c_errorcode;
    uint8_t     i2c_status;
    if (! i2c_rtc_init (&i2c_errorcode, &i2c_status))                           // initialize rtc
    {
      log_main("RTC init failed\n");
      // TODO: error handling
    }
  }

  ldr_init ();                                                                  // initialize ldr
  pwm_init ();                                                                  // initialize pwm
  irmp_init ();                                                                 // initialize irmp
  timer_init ();                                                                // initialize timer
  user_init();

  sei ();                                                                       // enable interrupts

  pwm_on ();                                                                    // switch on pwm

  //pwm_set_base_brightness_step(MAX_PWM_STEPS-1); /// @todo remove if ldr stuff is working


  log_main("Init finished\n");

  for (;;)
  {
    handle_brightness ();
    handle_datetime (&datetime);                                                // check & display new time, if necessary
    handle_ir_code ();                                                          // handle ir user interaction

#   if (DCF_PRESENT == 1)
      if (dcf77_getDateTime (&datetime))                                        // handle dcf77 examination (enable_dcf77_ISR must be TRUE to enable analysis)
      {
        i2c_rtc_write (&datetime);
        soft_seconds = datetime.ss;
        user_setNewTime (&datetime);
      }
#   endif  /** (DCF_PRESENT == 1) */
  }
}
Esempio n. 3
0
void setup()
{
	uint8_t i;
	cli(); //stop interrupts
	
	//Configure tube pins as PIN_OUTs
	for(i = 0; i < 4; i++)
	{
		set_pin_inout(&pins_d1[i], PIN_OUT);
		set_pin_inout(&pins_d2[i], PIN_OUT);
		set_pin_inout(&pins_d3[i], PIN_OUT);
		set_pin_inout(&pins_d4[i], PIN_OUT);
	}

	//configure led pin as PIN_OUT
	set_pin_inout(&pin_leds, PIN_OUT);

	//configure button pins as PIN_IN
	set_pin_inout(&pins_but[0], PIN_IN);
	set_pin_inout(&pins_but[1], PIN_IN);

	//enable internal pullup resistors for buttons
	set_pin(&pins_but[0], 1);
	set_pin(&pins_but[1], 1);
	
	dcf77_init(&g_time);
	
	//set timer1 interrupt at 100Hz
	TCCR1A = 0; // set entire TCCR1A register to 0
	TCCR1B = 0; // same for TCCR1B
	TCNT1  = 0; //initialize counter value to 0
	// set compare match register for 100hz increments
	OCR1A = 19999; // = (16*10^6) / (100*8) - 1 (must be <65536)
	TCCR1B |= (1 << WGM12); // turn on CTC mode
	TCCR1B |= (1 << CS11); // Set CS11 bit for 8 prescaler
	TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt

	sei(); //enable interrupts
}
Esempio n. 4
0
// main program body
int main(void)
{
	WDTCTL = WDTPW + WDTHOLD;	// Stop WDT

	board_init(); // init dco and leds
	lcm_init(); // lcd
	rtc_timer_init(); // init 32kHz timer
	uart_init(); // init uart (communication)
	//buttons_init(); // buttons
	dcf77_init(); // dcf77 receiver


    #if DCF77_DEBUG
    lcm_goto(0,0);
    lcm_prints("DCF");
    #endif

	while(1)
	{
        __bis_SR_register(CPUOFF + GIE); // enter sleep mode (leave on rtc second event)
        tstruct tnow;
        rtc_get_time(&tnow);
        char tstr[16];
        sprint_time(&tnow,tstr);
        lcm_goto(1,0);
        lcm_prints(tstr);
        str_add_lineend(tstr,16);
        uart_puts(tstr);
        uint8_t b=get_button();
        if (b)
        {
            /*lcm_goto(0,3);
            tstr[0]='0'+b;
            tstr[1]='\0';
            lcm_prints(tstr);*/
            if (b==3) // test rtc set function
            {
                tnow.second = 0;
                tnow.minute = 33;
                tnow.hour = 22;
                tnow.dayow = 2;
                rtc_set_time(&tnow);
            }
        }
        #if DCF77_DEBUG
        // dcf
        if (symbol_ready)
        {
            int ci=0;
            lcm_goto(0,3);
            tstr[ci++]=h2c(tunestatus);
            tstr[ci++]=' ';
            tstr[ci++]=h2c(last_symbol);
            tstr[ci++]=' ';
            tstr[ci++]=h2c((int)last_Q/100%10);
            tstr[ci++]=h2c((int)last_Q/10%10);
            tstr[ci++]=h2c((int)last_Q%10);
            tstr[ci++]=' ';
            tstr[ci++]=h2c((int)(finetune>>12));
            tstr[ci++]=h2c((int)(finetune>>8)&0x0F);
            tstr[ci++]=h2c((int)(finetune>>4)&0x0F);
            tstr[ci++]=h2c((int)(finetune&0x0F));
            tstr[ci++]='\0';
            lcm_prints(tstr);
            symbol_ready = false;
        }
        #endif
	}

	return -1;
}
Esempio n. 5
0
/*-------------------------------------------------------------------------------------------------------------------------------------------
 * main function
 *-------------------------------------------------------------------------------------------------------------------------------------------
 */
int
main ()
{
    static uint_fast8_t     last_ldr_value = 0xFF;
    struct tm               tm;
    LISTENER_DATA           lis;
    ESP8266_INFO *          esp8266_infop;
    uint_fast8_t            esp8266_is_up = 0;
    uint_fast8_t            code;

#if SAVE_RAM == 0
    IRMP_DATA               irmp_data;
    uint32_t                stop_time;
    uint_fast8_t            cmd;
#endif
    uint_fast8_t            status_led_cnt              = 0;
    uint_fast8_t            display_flag                = DISPLAY_FLAG_UPDATE_ALL;
    uint_fast8_t            show_temperature            = 0;
    uint_fast8_t            time_changed                = 0;
    uint_fast8_t            power_is_on                 = 1;
    uint_fast8_t            night_power_is_on           = 1;
    uint_fast8_t            ldr_value;
    uint_fast8_t            ap_mode = 0;

    SystemInit ();
    SystemCoreClockUpdate();                                                // needed for Nucleo board

#if defined (STM32F103)                                                     // disable JTAG to get back PB3, PB4, PA13, PA14, PA15
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);                    // turn on clock for the alternate function register
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                // disable the JTAG, enable the SWJ interface
#endif

    log_init ();                                                            // initilize logger on uart

#if SAVE_RAM == 0
    irmp_init ();                                                           // initialize IRMP
#endif
    timer2_init ();                                                         // initialize timer2 for IRMP, DCF77, EEPROM etc.
    delay_init (DELAY_RESOLUTION_1_US);                                     // initialize delay functions with granularity of 1 us
    board_led_init ();                                                      // initialize GPIO for green LED on disco or nucleo board
    button_init ();                                                         // initialize GPIO for user button on disco or nucleo board
    rtc_init ();                                                            // initialize I2C RTC
    eeprom_init ();                                                         // initialize I2C EEPROM

    if (button_pressed ())                                                  // set ESP8266 into flash mode
    {
        board_led_on ();
        esp8266_flash ();
    }

    log_msg ("\r\nWelcome to WordClock Logger!");
    log_msg ("----------------------------");
    log_str ("Version: ");
    log_msg (VERSION);

    if (rtc_is_up)
    {
        log_msg ("rtc is online");
    }
    else
    {
        log_msg ("rtc is offline");
    }

    if (eeprom_is_up)
    {
        log_msg ("eeprom is online");
        read_version_from_eeprom ();
        log_printf ("current eeprom version: 0x%08x\r\n", eeprom_version);

        if ((eeprom_version & 0xFF0000FF) == 0x00000000)
        {                                                               // Upper and Lower Byte must be 0x00
            if (eeprom_version >= EEPROM_VERSION_1_5_0)
            {
#if SAVE_RAM == 0
                log_msg ("reading ir codes from eeprom");
                remote_ir_read_codes_from_eeprom ();
#endif
                log_msg ("reading display configuration from eeprom");
                display_read_config_from_eeprom ();

                log_msg ("reading timeserver data from eeprom");
                timeserver_read_data_from_eeprom ();
            }

            if (eeprom_version >= EEPROM_VERSION_1_7_0)
            {
                log_msg ("reading night timers from eeprom");
                night_read_data_from_eeprom ();
            }
        }
    }
    else
    {
        log_msg ("eeprom is offline");
    }

    ldr_init ();                                                            // initialize LDR (ADC)
    display_init ();                                                        // initialize display

    dcf77_init ();                                                          // initialize DCF77

    night_init ();                                                          // initialize night time routines

    short_isr = 1;
    temp_init ();                                                           // initialize DS18xx
    short_isr = 0;

    display_reset_led_states ();
    display_mode                = display_get_display_mode ();
    animation_mode              = display_get_animation_mode ();
    auto_brightness             = display_get_automatic_brightness_control ();

    if (eeprom_is_up)
    {
        if (eeprom_version != EEPROM_VERSION)
        {
            log_printf ("updating EEPROM to version 0x%08x\r\n", EEPROM_VERSION);

            eeprom_version = EEPROM_VERSION;
            write_version_to_eeprom ();
#if SAVE_RAM == 0
            remote_ir_write_codes_to_eeprom ();
#endif
            display_write_config_to_eeprom ();
            timeserver_write_data_to_eeprom ();
            night_write_data_to_eeprom ();
            eeprom_version = EEPROM_VERSION;
        }
    }

    ds3231_flag = 1;

#if SAVE_RAM == 0
    stop_time = uptime + 3;                                                 // wait 3 seconds for IR signal...
    display_set_status_led (1, 1, 1);                                       // show white status LED

    while (uptime < stop_time)
    {
        if (irmp_get_data (&irmp_data))                                     // got IR signal?
        {
            display_set_status_led (1, 0, 0);                               // yes, show red status LED
            delay_sec (1);                                                  // and wait 1 second
            (void) irmp_get_data (&irmp_data);                              // flush input of IRMP now
            display_set_status_led (0, 0, 0);                               // and switch status LED off

            log_msg ("calling IR learn function");
            if (remote_ir_learn ())                                         // learn IR commands
            {
                remote_ir_write_codes_to_eeprom ();                         // if successful, save them in EEPROM
            }
            break;                                                          // and break the loop
        }
    }
#endif

    display_set_status_led (0, 0, 0);                                       // switch off status LED

    esp8266_init ();
    esp8266_infop = esp8266_get_info ();

    while (1)
    {
        if (! ap_mode && esp8266_is_up && button_pressed ())                // if user pressed user button, set ESP8266 to AP mode
        {
            ap_mode = 1;
            log_msg ("user button pressed: configuring esp8266 as access point");
            esp8266_is_online = 0;
            esp8266_infop->is_online = 0;
            esp8266_infop->ipaddress[0] = '\0';
            esp8266_accesspoint ("wordclock", "1234567890");
        }


        if (status_led_cnt)
        {
            status_led_cnt--;

            if (! status_led_cnt)
            {
                display_set_status_led (0, 0, 0);
            }
        }

        if ((code = listener (&lis)) != 0)
        {
            display_set_status_led (1, 0, 0);                               // got net command, light red status LED
            status_led_cnt = STATUS_LED_FLASH_TIME;

            switch (code)
            {
                case LISTENER_SET_COLOR_CODE:                               // set color
                {
                    display_set_colors (&(lis.rgb));
                    log_printf ("command: set colors to %d %d %d\r\n", lis.rgb.red, lis.rgb.green, lis.rgb.blue);
                    break;
                }

                case LISTENER_POWER_CODE:                                   // power on/off
                {
                    if (power_is_on != lis.power)
                    {
                        power_is_on = lis.power;
                        display_flag = DISPLAY_FLAG_UPDATE_ALL;
                        log_msg ("command: set power");
                    }
                    break;
                }

                case LISTENER_DISPLAY_MODE_CODE:                            // set display mode
                {
                    if (display_mode != lis.mode)
                    {
                        display_mode = display_set_display_mode (lis.mode);
                        display_flag = DISPLAY_FLAG_UPDATE_ALL;
                        log_printf ("command: set display mode to %d\r\n", display_mode);
                    }
                    break;
                }

                case LISTENER_ANIMATION_MODE_CODE:                          // set animation mode
                {
                    if (animation_mode != lis.mode)
                    {
                        animation_mode = display_set_animation_mode (lis.mode);
                        animation_flag = 0;
                        display_flag = DISPLAY_FLAG_UPDATE_ALL;
                        log_printf ("command: set animation mode to %d\r\n", animation_flag);
                    }
                    break;
                }

                case LISTENER_DISPLAY_TEMPERATURE_CODE:                     // set animation mode
                {
                    show_temperature = 1;
                    log_msg ("command: show temperature");
                    break;
                }

                case LISTENER_SET_BRIGHTNESS_CODE:                          // set brightness
                {
                    if (auto_brightness)
                    {
                        auto_brightness = 0;
                        last_ldr_value = 0xFF;
                        display_set_automatic_brightness_control (auto_brightness);
                    }
                    display_set_brightness (lis.brightness);
                    display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                    log_printf ("command: set brightness to %d, disable autmomatic brightness control per LDR\r\n", lis.brightness);
                    break;
                }

                case LISTENER_SET_AUTOMATIC_BRIHGHTNESS_CODE:               // automatic brightness control on/off
                {
                    if (lis.automatic_brightness_control)
                    {
                        auto_brightness = 1;
                        log_msg ("command: enable automatic brightness control");
                    }
                    else
                    {
                        auto_brightness = 0;
                        log_msg ("command: disable automatic brightness control");
                    }

                    last_ldr_value = 0xFF;
                    display_set_automatic_brightness_control (auto_brightness);
                    break;
                }

                case LISTENER_TEST_DISPLAY_CODE:                            // test display
                {
                    log_msg ("command: start display test");
                    display_test ();
                    break;
                }

                case LISTENER_SET_DATE_TIME_CODE:                           // set date/time
                {
                    if (rtc_is_up)
                    {
                        rtc_set_date_time (&(lis.tm));
                    }

                    if (hour != (uint_fast8_t) lis.tm.tm_hour || minute != (uint_fast8_t) lis.tm.tm_min)
                    {
                        display_flag = DISPLAY_FLAG_UPDATE_ALL;
                    }

                    wday   = lis.tm.tm_wday;
                    hour   = lis.tm.tm_hour;
                    minute = lis.tm.tm_min;
                    second = lis.tm.tm_sec;

                    log_printf ("command: set time to %s %4d-%02d-%02d %02d:%02d:%02d\r\n",
                                wdays_en[lis.tm.tm_wday], lis.tm.tm_year + 1900, lis.tm.tm_mon + 1, lis.tm.tm_mday,
                                lis.tm.tm_hour, lis.tm.tm_min, lis.tm.tm_sec);
                    break;
                }

                case LISTENER_GET_NET_TIME_CODE:                            // get net time
                {
                    net_time_flag = 1;
                    log_msg ("command: start net time request");
                    break;
                }

                case LISTENER_IR_LEARN_CODE:                                // IR learn
                {
#if SAVE_RAM == 0
                    log_msg ("command: learn IR codes");

                    if (remote_ir_learn ())
                    {
                        remote_ir_write_codes_to_eeprom ();
                    }
#endif
                    break;
                }

                case LISTENER_SAVE_DISPLAY_CONFIGURATION:                   // save display configuration
                {
                    display_write_config_to_eeprom ();
                    log_msg ("command: save display settings");
                    break;
                }
            }
        }

        if (auto_brightness && ldr_poll_brightness (&ldr_value))
        {
            if (ldr_value + 1 < last_ldr_value || ldr_value > last_ldr_value + 1)           // difference greater than 2
            {
                log_printf ("ldr: old brightnes: %d new brightness: %d\r\n", last_ldr_value, ldr_value);
                last_ldr_value = ldr_value;
                display_set_brightness (ldr_value);
                display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
            }
        }

        if (!esp8266_is_up)                                                 // esp8266 up yet?
        {
            if (esp8266_infop->is_up)
            {
                esp8266_is_up = 1;
                log_msg ("esp8266 now up");
            }
        }
        else
        {                                                                   // esp8266 is up...
            if (! esp8266_is_online)                                        // but not online yet...
            {
                if (esp8266_infop->is_online)                               // now online?
                {
                    char buf[32];
                    esp8266_is_online = 1;

                    log_msg ("esp8266 now online");
                    sprintf (buf, "  IP %s", esp8266_infop->ipaddress);
                    display_banner (buf);
                    display_flag = DISPLAY_FLAG_UPDATE_ALL;

                    net_time_flag = 1;
                }
            }
        }

        if (dcf77_time(&tm))
        {
            display_set_status_led (1, 1, 0);                       // got DCF77 time, light yellow = green + red LED

            status_led_cnt = 50;

            if (rtc_is_up)
            {
                rtc_set_date_time (&tm);
            }

            if (hour != (uint_fast8_t) tm.tm_hour || minute != (uint_fast8_t) tm.tm_min)
            {
                display_flag = DISPLAY_FLAG_UPDATE_ALL;
            }

            wday        = tm.tm_wday;
            hour        = tm.tm_hour;
            minute      = tm.tm_min;
            second      = tm.tm_sec;

            log_printf ("dcf77: %s %4d-%02d-%02d %02d:%02d:%02d\r\n",
                         wdays_en[tm.tm_wday], tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
        }

        if (ds3231_flag)
        {
            if (rtc_is_up && rtc_get_date_time (&tm))
            {
                if (hour != (uint_fast8_t) tm.tm_hour || minute != (uint_fast8_t) tm.tm_min)
                {
                    display_flag = DISPLAY_FLAG_UPDATE_ALL;
                }

                wday        = tm.tm_wday;
                hour        = tm.tm_hour;
                minute      = tm.tm_min;
                second      = tm.tm_sec;

                log_printf ("read rtc: %s %4d-%02d-%02d %02d:%02d:%02d\r\n",
                             wdays_en[tm.tm_wday], tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
            }

            ds3231_flag = 0;
        }

        if (auto_brightness && ldr_conversion_flag)
        {
            ldr_start_conversion ();
            ldr_conversion_flag = 0;
        }

        if (net_time_flag)
        {
            if (esp8266_infop->is_online)
            {
                display_set_status_led (0, 0, 1);                       // light blue status LED
                status_led_cnt = STATUS_LED_FLASH_TIME;
                timeserver_start_timeserver_request ();                 // start a timeserver request, answer follows...
            }

            net_time_flag = 0;
            net_time_countdown = 3800;                                  // next net time after 3800 sec
        }

        if (show_time_flag)                                             // set every full minute
        {
#if WCLOCK24H == 1
            display_flag = DISPLAY_FLAG_UPDATE_ALL;
#else
            if (minute % 5)
            {
                display_flag = DISPLAY_FLAG_UPDATE_MINUTES;             // only update minute LEDs
            }
            else
            {
                display_flag = DISPLAY_FLAG_UPDATE_ALL;
            }
#endif
            show_time_flag = 0;
        }

        if (power_is_on == night_power_is_on && night_check_night_times (power_is_on, wday, hour * 60 + minute))
        {
            power_is_on         = ! power_is_on;
            night_power_is_on   = ! night_power_is_on;
            display_flag        = DISPLAY_FLAG_UPDATE_ALL;
            log_printf ("Found Timer: %s at %02d:%02d\r\n", power_is_on ? "on" : "off", hour, minute);
        }

        if (show_temperature)
        {
            uint_fast8_t temperature_index;

            show_temperature = 0;

            if (ds18xx_is_up)
            {
                short_isr = 1;
                temperature_index = temp_read_temp_index ();
                short_isr = 0;
                log_printf ("got temperature from DS18xxx: %d%s\r\n", temperature_index / 2, (temperature_index % 2) ? ".5" : "");
            }
            else if (rtc_is_up)
            {
                temperature_index = rtc_get_temperature_index ();
                log_printf ("got temperature from RTC: %d%s\r\n", temperature_index / 2, (temperature_index % 2) ? ".5" : "");
            }
            else
            {
                temperature_index = 0xFF;
                log_msg ("no temperature available");
            }

            if (temperature_index != 0xFF)
            {
                display_temperature (power_is_on, temperature_index);

#if WCLOCK24H == 1                                                          // WC24H shows temperature with animation, WC12H rolls itself
                uint32_t    stop_time;

                stop_time = uptime + 5;

                while (uptime < stop_time)
                {
                    if (animation_flag)
                    {
                        animation_flag = 0;
                        display_animation ();
                    }
                }
#endif
                display_flag = DISPLAY_FLAG_UPDATE_ALL;                     // force update
            }
        }

        if (display_flag)                                                   // refresh display (time/mode changed)
        {
            log_msg ("update display");

#if WCLOCK24H == 1
            if (display_mode == MODES_COUNT - 1)                            // temperature
            {
                uint_fast8_t temperature_index;

                if (ds18xx_is_up)
                {
                    short_isr = 1;
                    temperature_index = temp_read_temp_index ();
                    short_isr = 0;
                    log_printf ("got temperature from DS18xxx: %d%s\r\n", temperature_index / 2, (temperature_index % 2) ? ".5" : "");
                }
                else if (rtc_is_up)
                {
                    temperature_index = rtc_get_temperature_index ();
                    log_printf ("got temperature from RTC: %d%s\r\n", temperature_index / 2, (temperature_index % 2) ? ".5" : "");
                }
                else
                {
                    temperature_index = 0x00;
                    log_msg ("no temperature available");
                }

                display_clock (power_is_on, 0, temperature_index - 20, display_flag);    // show new time
            }
            else
            {
                display_clock (power_is_on, hour, minute, display_flag);    // show new time
            }
#else
            display_clock (power_is_on, hour, minute, display_flag);        // show new time
#endif
            display_flag = DISPLAY_FLAG_NONE;
        }

        if (animation_flag)
        {
            animation_flag = 0;
            display_animation ();
        }

        if (dcf77_flag)
        {
            dcf77_flag = 0;
            dcf77_tick ();
        }

#if SAVE_RAM == 0
        cmd = remote_ir_get_cmd ();                                         // get IR command

        if (cmd != REMOTE_IR_CMD_INVALID)                                   // got IR command, light green LED
        {
            display_set_status_led (1, 0, 0);
            status_led_cnt = STATUS_LED_FLASH_TIME;
        }

        if (cmd != REMOTE_IR_CMD_INVALID)                                   // if command valid, log command code
        {
            switch (cmd)
            {
                case REMOTE_IR_CMD_POWER:                         log_msg ("IRMP: POWER key");                  break;
                case REMOTE_IR_CMD_OK:                            log_msg ("IRMP: OK key");                     break;
                case REMOTE_IR_CMD_DECREMENT_DISPLAY_MODE:        log_msg ("IRMP: decrement display mode");     break;
                case REMOTE_IR_CMD_INCREMENT_DISPLAY_MODE:        log_msg ("IRMP: increment display mode");     break;
                case REMOTE_IR_CMD_DECREMENT_ANIMATION_MODE:      log_msg ("IRMP: decrement animation mode");   break;
                case REMOTE_IR_CMD_INCREMENT_ANIMATION_MODE:      log_msg ("IRMP: increment animation mode");   break;
                case REMOTE_IR_CMD_DECREMENT_HOUR:                log_msg ("IRMP: decrement hour");             break;
                case REMOTE_IR_CMD_INCREMENT_HOUR:                log_msg ("IRMP: increment hour");             break;
                case REMOTE_IR_CMD_DECREMENT_MINUTE:              log_msg ("IRMP: decrement minute");           break;
                case REMOTE_IR_CMD_INCREMENT_MINUTE:              log_msg ("IRMP: increment minute");           break;
                case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS_RED:      log_msg ("IRMP: decrement red brightness");   break;
                case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS_RED:      log_msg ("IRMP: increment red brightness");   break;
                case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS_GREEN:    log_msg ("IRMP: decrement green brightness"); break;
                case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS_GREEN:    log_msg ("IRMP: increment green brightness"); break;
                case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS_BLUE:     log_msg ("IRMP: decrement blue brightness");  break;
                case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS_BLUE:     log_msg ("IRMP: increment blue brightness");  break;
                case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS:          log_msg ("IRMP: decrement brightness");       break;
                case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS:          log_msg ("IRMP: increment brightness");       break;
                case REMOTE_IR_CMD_GET_TEMPERATURE:               log_msg ("IRMP: get temperature");            break;
            }
        }

        switch (cmd)
        {
            case REMOTE_IR_CMD_POWER:
            {
                power_is_on = ! power_is_on;

                display_flag        = DISPLAY_FLAG_UPDATE_ALL;
                break;
            }

            case REMOTE_IR_CMD_OK:
            {
                display_write_config_to_eeprom ();
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_DISPLAY_MODE:                      // decrement display mode
            {
                display_mode = display_decrement_display_mode ();
                display_flag = DISPLAY_FLAG_UPDATE_ALL;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_DISPLAY_MODE:                      // increment display mode
            {
                display_mode = display_increment_display_mode ();
                display_flag = DISPLAY_FLAG_UPDATE_ALL;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_ANIMATION_MODE:                    // decrement display mode
            {
                animation_mode = display_decrement_animation_mode ();
                display_flag = DISPLAY_FLAG_UPDATE_ALL;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_ANIMATION_MODE:                    // increment display mode
            {
                animation_mode = display_increment_animation_mode ();
                display_flag = DISPLAY_FLAG_UPDATE_ALL;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_HOUR:                              // decrement hour
            {
                if (hour > 0)
                {
                    hour--;
                }
                else
                {
                    hour = 23;
                }

                second          = 0;
                display_flag    = DISPLAY_FLAG_UPDATE_ALL;
                time_changed    = 1;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_HOUR:                              // increment hour
            {
                if (hour < 23)
                {
                     hour++;
                }
                else
                {
                    hour =  0;
                }

                second          = 0;
                display_flag    = DISPLAY_FLAG_UPDATE_ALL;
                time_changed    = 1;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_MINUTE:                            // decrement minute
            {
                if (minute > 0)
                {
                    minute--;
                }
                else
                {
                    minute = 59;
                }

                second          = 0;
                display_flag    = DISPLAY_FLAG_UPDATE_ALL;
                time_changed    = 1;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_MINUTE:                            // increment minute
            {
                if (minute < 59)
                {
                    minute++;
                }
                else
                {
                    minute = 0;
                }

                second          = 0;
                display_flag    = DISPLAY_FLAG_UPDATE_ALL;
                time_changed    = 1;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS_RED:                    // decrement red brightness
            {
                display_decrement_color_red ();
                display_flag        = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS_RED:                    // increment red brightness
            {
                display_increment_color_red ();
                display_flag        = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS_GREEN:                  // decrement green brightness
            {
                display_decrement_color_green ();
                display_flag        = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS_GREEN:                  // increment green brightness
            {
                display_increment_color_green ();
                display_flag        = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS_BLUE:                   // decrement blue brightness
            {
                display_decrement_color_blue ();
                display_flag        = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS_BLUE:                   // increment blue brightness
            {
                display_increment_color_blue ();
                display_flag        = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_AUTO_BRIGHTNESS_CONTROL:                     // toggle auto brightness
            {
                auto_brightness = ! auto_brightness;
                last_ldr_value = 0xFF;
                display_set_automatic_brightness_control (auto_brightness);
                display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_DECREMENT_BRIGHTNESS:                        // decrement brightness
            {
                if (auto_brightness)
                {
                    auto_brightness = 0;
                    last_ldr_value = 0xFF;
                    display_set_automatic_brightness_control (auto_brightness);
                    display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                }

                display_decrement_brightness ();
                display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_INCREMENT_BRIGHTNESS:                        // increment brightness
            {
                if (auto_brightness)
                {
                    auto_brightness = 0;
                    last_ldr_value = 0xFF;
                    display_set_automatic_brightness_control (auto_brightness);
                    display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                }

                display_increment_brightness ();
                display_flag = DISPLAY_FLAG_UPDATE_NO_ANIMATION;
                break;
            }

            case REMOTE_IR_CMD_GET_TEMPERATURE:                             // get temperature
            {
                show_temperature    = 1;
                break;
            }

            default:
            {
                break;
            }
        }
#endif // SAVE_RAM == 0

        if (time_changed)
        {
            if (rtc_is_up)
            {
                tm.tm_hour = hour;
                tm.tm_min  = minute;
                tm.tm_sec  = second;
                rtc_set_date_time (&tm);
            }

            time_changed = 0;
        }
    }

    return 0;
}