예제 #1
0
파일: main.c 프로젝트: ib0t/OpenHR20
/*!
 *******************************************************************************
 * main program
 ******************************************************************************/
int main(void)
{
    //! initalization
    init();

	task=0;

    //! Enable interrupts
    sei();
    
    /* check EEPROM layout */
    if (EEPROM_read((uint16_t)&ee_layout)!=EE_LAYOUT) {
        LCD_PrintStringID(LCD_STRING_EEPr,LCD_MODE_ON);
        task_lcd_update();
        for(;;) {;}  //fatal error, stop startup
    }

	COM_init();

	// We should do the following once here to have valid data from the start

		
    /*!
    ****************************************************************************
    * main loop
    ***************************************************************************/
    for (;;){        
		// go to sleep with ADC conversion start
		asm volatile ("cli");
		if (
          ! task &&
          ((ASSR & (_BV(OCR2UB)|_BV(TCN2UB)|_BV(TCR2UB))) == 0) // ATmega169 datasheet chapter 17.8.1
            ) {
  			// nothing to do, go to sleep
            if(timer0_need_clock() || RS_need_clock()) {
			    SMCR = (0<<SM1)|(0<<SM0)|(1<<SE); // Idle mode
            } else {
    			if (sleep_with_ADC) {
    				SMCR = (0<<SM1)|(1<<SM0)|(1<<SE); // ADC noise reduction mode
				} else {
				    SMCR = (1<<SM1)|(1<<SM0)|(1<<SE); // Power-save mode
                }
            }

			if (sleep_with_ADC) {
				sleep_with_ADC=0;
				// start conversions
		        ADCSRA |= (1<<ADSC);
			}

			DEBUG_BEFORE_SLEEP();
			asm volatile ("sei");	//  sequence from ATMEL datasheet chapter 6.8.
			asm volatile ("sleep");
			asm volatile ("nop");
			DEBUG_AFTER_SLEEP(); 
			SMCR = (1<<SM1)|(1<<SM0)|(0<<SE); // Power-save mode
		} else {
			asm volatile ("sei");
		}

        // update LCD task
		if (task & TASK_LCD) {
			task&=~TASK_LCD;
			task_lcd_update();
			continue; // on most case we have only 1 task, iprove time to sleep
		}

		if (task & TASK_ADC) {
			task&=~TASK_ADC;
			if (task_ADC()==0) {
                // ADC is done
                // TODO
            }
			continue; // on most case we have only 1 task, iprove time to sleep
		}
		
        // communication
		if (task & TASK_COM) {
			task&=~TASK_COM;
			COM_commad_parse();
			continue; // on most case we have only 1 task, iprove time to sleep
		}

        // motor stop
        if (task & TASK_MOTOR_STOP) {
            task&=~TASK_MOTOR_STOP;
            MOTOR_timer_stop();
			continue; // on most case we have only 1 task, iprove time to sleep
        }

        // update motor possition
        if (task & TASK_MOTOR_PULSE) {
            task&=~TASK_MOTOR_PULSE;
            MOTOR_updateCalibration(mont_contact_pooling());
            MOTOR_timer_pulse();
			continue; // on most case we have only 1 task, iprove time to sleep
        }

		//! check keyboard and set keyboards events
		if (task & TASK_KB) {
			task&=~TASK_KB;
			task_keyboard();
		}

        if (task & TASK_RTC) {
            task&=~TASK_RTC;
            {
                bool minute = RTC_AddOneSecond();
                valve_wanted = CTL_update(minute,valve_wanted);
                if (minute && (RTC_GetDayOfWeek()==6) && (RTC_GetHour()==10) && (RTC_GetMinute()==0)) {
                    // every sunday 10:00AM
                    // TODO: improve this code!
                    // valve protection / CyCL
                    MOTOR_updateCalibration(0);
                }
            }
            MOTOR_updateCalibration(mont_contact_pooling());
            MOTOR_Goto(valve_wanted);
            task_keyboard_long_press_detect();
            if ((MOTOR_Dir==stop) || (config.allow_ADC_during_motor)) start_task_ADC();
            if (menu_auto_update_timeout>=0) {
                menu_auto_update_timeout--;
            }
            menu_view(false); // TODO: move it, it is wrong place
            LCD_Update(); // TODO: move it, it is wrong place
            // do not use continue here (menu_auto_update_timeout==0)
        }

		// menu state machine
		if (kb_events || (menu_auto_update_timeout==0)) {
           bool update = menu_controller(false);
           if (update) {
               menu_controller(true); // menu updated, call it again
           } 
           menu_view(update); // TODO: move it, it is wrong place
	       LCD_Update(); // TODO: move it, it is wrong place
		}
    } //End Main loop
예제 #2
0
파일: menu.c 프로젝트: robots/openhr20
/*!
 *******************************************************************************
 * \brief menu Controller
 * 
 * \returns true for controler restart  
 ******************************************************************************/
bool menu_controller(bool new_state) {
    int8_t wheel = wheel_proccess(); //signed number
	bool ret = false;
    switch (menu_state) {
    case menu_startup:
        if (new_state) {
            menu_auto_update_timeout=2;
        }
        if (menu_auto_update_timeout==0) {
            menu_state = menu_version;
            ret=true;
        }
        break;
    case menu_version:
        if (new_state) {
            menu_auto_update_timeout=2;
        }
        if (menu_auto_update_timeout==0) {
            #if (DEBUG_SKIP_DATETIME_SETTING_AFTER_RESET) || (REMOTE_SETTING_ONLY)
                menu_state = menu_home;
            #else
                menu_state = menu_set_year;
            #endif
            ret=true;
        }
        break;
#if (! REMOTE_SETTING_ONLY)
    case menu_set_year:
        if (wheel != 0) RTC_SetYear(RTC_GetYearYY()+wheel);
        if ( kb_events & KB_EVENT_PROG) {
            menu_state = menu_set_month;
            CTL_update_temp_auto();
            ret=true;
        }
        break;
    case menu_set_month:
        if (wheel != 0) RTC_SetMonth(RTC_GetMonth()+wheel);
        if ( kb_events & KB_EVENT_PROG ) {
            menu_state = menu_set_day;
            CTL_update_temp_auto();
            ret=true;
        }
        break;
    case menu_set_day:
        if (wheel != 0) RTC_SetDay(RTC_GetDay()+wheel);
        if ( kb_events & KB_EVENT_PROG ) {
            menu_state = menu_set_hour;
            CTL_update_temp_auto();
            ret=true;
        }
        break;
    case menu_set_hour:
        if (wheel != 0) RTC_SetHour(RTC_GetHour()+wheel);
        if ( kb_events & KB_EVENT_PROG ) {
            menu_state = menu_set_minute;
            CTL_update_temp_auto();
            ret=true;
        }
        break;
    case menu_set_minute:
        if (wheel != 0) {
            RTC_SetMinute(RTC_GetMinute()+wheel);
            RTC_SetSecond(0);
        }
        if ( kb_events & KB_EVENT_PROG ) {
            menu_state = menu_home;
            CTL_update_temp_auto();
            ret=true;
        }
        break;
#endif
    case menu_home_no_alter: // same as home screen, but without alternate contend
    case menu_home:         // home screen
    case menu_home2:        // alternate version, real temperature
    case menu_home3:        // alternate version, valve pos
    case menu_home4:        // alternate version, time    
#if MENU_SHOW_BATTERY
    case menu_home5:        // alternate version, battery    
#endif
        if ( kb_events & KB_EVENT_C ) {
            menu_state++;       // go to next alternate home screen
#if MENU_SHOW_BATTERY
            if (menu_state > menu_home5) menu_state=menu_home;
#else
            if (menu_state > menu_home4) menu_state=menu_home;
#endif
            ret=true; 
        } else {
            if (menu_locked) {
                if ( kb_events & (
                        KB_EVENT_WHEEL_PLUS  | KB_EVENT_WHEEL_MINUS | KB_EVENT_PROG
                        | KB_EVENT_AUTO | KB_EVENT_PROG_REWOKE | KB_EVENT_C_REWOKE | KB_EVENT_AUTO_REWOKE
                        | KB_EVENT_PROG_LONG | KB_EVENT_C_LONG | KB_EVENT_AUTO_LONG )) {
                    menu_auto_update_timeout=LONG_PRESS_THLD+1;
                    menu_state=menu_lock;
                    ret=true;
                    }
            } else { // not locked
                if ((menu_state == menu_home) || (menu_state == menu_home_no_alter)) {
                    if (wheel != 0) {
                        CTL_temp_change_inc(wheel);
                        menu_state = menu_home_no_alter;
						ret=true; 
                    } 			 
                    if ( kb_events & KB_EVENT_AUTO ) {
                        CTL_change_mode(CTL_CHANGE_MODE); // change mode
                        menu_state=menu_home_no_alter;
						ret=true; 
                    } else if ( kb_events & KB_EVENT_AUTO_REWOKE ) {
                        CTL_change_mode(CTL_CHANGE_MODE_REWOKE); // change mode
                        menu_state=menu_home_no_alter;
						ret=true; 
                    }
                } else {
                    if ( kb_events & (
                        KB_EVENT_WHEEL_PLUS  | KB_EVENT_WHEEL_MINUS | KB_EVENT_PROG
                        | KB_EVENT_AUTO | KB_EVENT_PROG_REWOKE | KB_EVENT_C_REWOKE | KB_EVENT_AUTO_REWOKE
                        | KB_EVENT_PROG_LONG | KB_EVENT_C_LONG | KB_EVENT_AUTO_LONG )) {
                            menu_state = menu_home;
							ret = true;
                    }
                }
                // TODO ....  
            }
        } 
        break;
#if (! REMOTE_SETTING_ONLY)
    case menu_set_timmer_dow_start:
        if (new_state) menu_set_dow=((config.timer_mode==1)?RTC_GetDayOfWeek():0);
        menu_state = menu_set_timmer_dow;
        // do not use break here
    case menu_set_timmer_dow:
        if (wheel != 0) menu_set_dow=(menu_set_dow+wheel+8)%8;
        if ( kb_events & KB_EVENT_PROG ) {
            menu_state=menu_set_timmer;
            menu_set_slot=0;
            config.timer_mode = (menu_set_dow>0);
            eeprom_config_save((uint16_t)(&config.timer_mode)-(uint16_t)(&config)); // save value to eeprom
                // update hourbar
            menu_update_hourbar((config.timer_mode==1)?RTC_GetDayOfWeek():0);
            ret=true; 
        } else if ( kb_events & KB_EVENT_AUTO ) { // exit without save
            menu_state=menu_home;
            ret=true; 
        }
        break;        
    case menu_set_timmer:
        if (new_state) {
            menu_set_time= RTC_DowTimerGet(menu_set_dow, menu_set_slot, &menu_set_mode);
            if (menu_set_time>24*60) menu_set_time=24*60;
        }
        if (wheel != 0) {
            menu_set_time=((menu_set_time/10+(24*6+1)+wheel)%(24*6+1))*10;
        }
        if ( kb_events & KB_EVENT_C ) {
            menu_set_mode=(menu_set_mode+5)%4;
        } else if ( kb_events & KB_EVENT_PROG ) {
            RTC_DowTimerSet(menu_set_dow, menu_set_slot, menu_set_time, menu_set_mode);
            if (++menu_set_slot>=RTC_TIMERS_PER_DOW) {
                if (menu_set_dow!=0) menu_set_dow=menu_set_dow%7+1; 
                menu_state=menu_set_timmer_dow;
            }
            CTL_update_temp_auto();
            menu_update_hourbar((config.timer_mode==1)?RTC_GetDayOfWeek():0);
            ret=true; 
        } else if ( kb_events & KB_EVENT_AUTO ) { // exit without save
            menu_state=menu_home;
            ret=true; 
        }
        break;
#endif
#if (! REMOTE_SETTING_ONLY)
    case menu_preset_temp0:
    case menu_preset_temp1:
    case menu_preset_temp2:
    case menu_preset_temp3:
        if (new_state) menu_set_temp=temperature_table[menu_state-menu_preset_temp0];
        if (wheel != 0) {
            menu_set_temp+=wheel;
            if (menu_set_temp > TEMP_MAX+1) menu_set_temp = TEMP_MAX+1;
            if (menu_set_temp < TEMP_MIN-1) menu_set_temp = TEMP_MIN-1;
        }
        if ( kb_events & KB_EVENT_PROG ) {
            temperature_table[menu_state-menu_preset_temp0]=menu_set_temp;
            eeprom_config_save(menu_state+((temperature_table-config_raw)-menu_preset_temp0));
            menu_state++; // menu_preset_temp3+1 == menu_home
            CTL_update_temp_auto();
            ret=true; 
        } else if ( kb_events & KB_EVENT_AUTO ) { // exit without save
            menu_state=menu_home;
            ret=true; 
        }
        break;
#endif
    default:
    case menu_lock:        // "bloc" message
        if (menu_auto_update_timeout==0) { menu_state=menu_home; ret=true; } 
        break;        
    case menu_service1:     // service menu        
    case menu_service2:        
        if (kb_events & KB_EVENT_AUTO) { 
            menu_state=menu_home; 
            ret=true;
        } else if (kb_events & KB_EVENT_C) { 
            menu_state=menu_service_watch; 
            ret=true;
        } else if (kb_events & KB_EVENT_PROG) {
            if (menu_state == menu_service2) {
                eeprom_config_save(service_idx); // save current value
                menu_state = menu_service1;
            } else {
                menu_state = menu_service2;
            }
        } else {
            if (menu_state == menu_service1) {
                // change index
                service_idx = (service_idx+wheel+CONFIG_RAW_SIZE)%CONFIG_RAW_SIZE;
            } else {
                // change value in RAM, to save press PROG
                int16_t min = (int16_t)config_min(service_idx);
                int16_t max_min_1 = (int16_t)(config_max(service_idx))-min+1;
                config_raw[service_idx] = (uint8_t) (
                        ((int16_t)(config_raw[service_idx])+(int16_t)wheel-min+max_min_1)%max_min_1+min);
                if (service_idx==0) LCD_Init();
            }
        }
        break;        
    case menu_service_watch:
        if (kb_events & KB_EVENT_AUTO) { 
            menu_state=menu_home; 
            ret=true;
        } else if (kb_events & KB_EVENT_C) { 
            menu_state=menu_service1; 
            ret=true;
        } else {
            service_watch_n=(service_watch_n+wheel+WATCH_N)%WATCH_N;
            if (wheel != 0) ret=true;
        }
        break;
    }
    if (events_common()) ret=true;
    if (ret && (service_idx<CONFIG_RAW_SIZE)) {
        // back config to default value
        config_raw[service_idx] = config_value(service_idx);
        service_idx = CONFIG_RAW_SIZE;
    }
    kb_events = 0; // clear unused keys
    return ret;
}