Exemplo n.º 1
0
Arquivo: main.c Projeto: 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
Exemplo n.º 2
0
/*!
 *******************************************************************************
 * \brief menu View
 ******************************************************************************/
void menu_view(bool clear) {
  switch (menu_state) {
    case menu_startup:
        LCD_AllSegments(LCD_MODE_ON);                   // all segments on
        break;
    case menu_version:
        clr_show1(LCD_SEG_COL1);
        LCD_PrintHexW(VERSION_N,LCD_MODE_ON);
        break; 
#if (! REMOTE_SETTING_ONLY)
	case menu_set_year:
        LCD_AllSegments(LCD_MODE_OFF); // all segments off
        LCD_PrintDecW(RTC_GetYearYYYY(),LCD_MODE_BLINK_1);
       break;
    case menu_set_month:
    case menu_set_day:
        clr_show1(LCD_SEG_COL1);           // decimal point
        LCD_PrintDec(RTC_GetMonth(), 0, ((menu_state==menu_set_month)?LCD_MODE_BLINK_1:LCD_MODE_ON));
        LCD_PrintDec(RTC_GetDay(), 2, ((menu_state==menu_set_day)?LCD_MODE_BLINK_1:LCD_MODE_ON));
       break;
    case menu_set_hour:
    case menu_set_minute: 
    case menu_home4: // time
#if HAVE_NEWLCD
        if (clear) clr_show1(LCD_SEG_COL2);
#else
        if (clear) clr_show2(LCD_SEG_COL1,LCD_SEG_COL2);
#endif
        LCD_PrintDec(RTC_GetHour(), 2, ((menu_state == menu_set_hour) ? LCD_MODE_BLINK_1 : LCD_MODE_ON));
        LCD_PrintDec(RTC_GetMinute(), 0, ((menu_state == menu_set_minute) ? LCD_MODE_BLINK_1 : LCD_MODE_ON));
       break;                                       
#else
    case menu_home4: // time
#if HAVE_NEWLCD
        if (clear) clr_show1(LCD_SEG_COL2);
#else
        if (clear) clr_show2(LCD_SEG_COL1,LCD_SEG_COL2);
#endif
        LCD_PrintDec(RTC_GetHour(), 2,  LCD_MODE_ON);
        LCD_PrintDec(RTC_GetMinute(), 0, LCD_MODE_ON);
       break;                                       
#endif
#if MENU_SHOW_BATTERY
	case menu_home5:        // battery 
		LCD_AllSegments(LCD_MODE_OFF);
        LCD_PrintDec(bat_average/100, 2, LCD_MODE_ON);
        LCD_PrintDec(bat_average%100, 0, LCD_MODE_ON);
       break;        
#endif                                                       
		

    case menu_home: // wanted temp / error code / adaptation status
        if (MOTOR_calibration_step>0) {
            clr_show1(LCD_SEG_BAR24);
            LCD_PrintChar(LCD_CHAR_A,3,LCD_MODE_ON);
            if (MOTOR_ManuCalibration==-1) LCD_PrintChar(LCD_CHAR_d,2,LCD_MODE_ON);
            LCD_PrintChar(LCD_CHAR_0 + (MOTOR_calibration_step%10), 0, LCD_MODE_ON);
            goto MENU_COMMON_STATUS; // optimization
        } else {
            if (clear) clr_show1(LCD_SEG_BAR24);
            if (CTL_error!=0) {
#if HAVE_NEWLCD==0
                if (CTL_error & CTL_ERR_BATT_LOW) {
                    LCD_PrintStringID(LCD_STRING_BAtt,LCD_MODE_BLINK_1);
                } else
#endif
								if (CTL_error & CTL_ERR_MONTAGE) {
                    LCD_PrintStringID(LCD_STRING_E2,LCD_MODE_ON);
                } else if (CTL_error & CTL_ERR_MOTOR) {
                    LCD_PrintStringID(LCD_STRING_E3,LCD_MODE_ON);
                } else
#if HAVE_NEWLCD==0
								if (CTL_error & CTL_ERR_BATT_WARNING) {
                    LCD_PrintStringID(LCD_STRING_BAtt,LCD_MODE_ON);
                } else
#endif
								if (CTL_error & CTL_ERR_RFM_SYNC) {
                    LCD_PrintStringID(LCD_STRING_E4,LCD_MODE_ON);
                }
                goto MENU_COMMON_STATUS; // optimization
            } else {
                if (mode_window()) {
                    LCD_PrintStringID(LCD_STRING_OPEn,LCD_MODE_ON);
                    goto MENU_COMMON_STATUS; // optimization
                }
            }
        } 
        // do not use break at this position / optimization
    case menu_home_no_alter: // wanted temp
        if (clear) clr_show1(LCD_SEG_BAR24);
        LCD_PrintTemp(CTL_temp_wanted,LCD_MODE_ON);
        //! \note hourbar status calculation is complex we don't want calculate it every view, use chache
        MENU_COMMON_STATUS:
        LCD_SetSeg(LCD_SEG_AUTO, (CTL_test_auto()?LCD_MODE_ON:LCD_MODE_OFF));
        LCD_SetSeg(LCD_SEG_MANU, (CTL_mode_auto?LCD_MODE_OFF:LCD_MODE_ON));
#if HAVE_NEWLCD
				if (CTL_error & (CTL_ERR_BATT_LOW | CTL_ERR_BATT_WARNING))
					LCD_SetSeg(LCD_SEG_BAT, (CTL_error & CTL_ERR_BATT_LOW)?LCD_MODE_BLINK_1:LCD_MODE_ON);
#endif
        LCD_HourBarBitmap(hourbar_buff);
       break;
    case menu_home2: // real temperature
        if (clear) LCD_AllSegments(LCD_MODE_OFF);
        LCD_PrintTempInt(temp_average,LCD_MODE_ON);
        break;
    case menu_home3: // valve pos
        if (clear) LCD_AllSegments(LCD_MODE_OFF);
        // LCD_PrintDec3(MOTOR_GetPosPercent(), 1 ,LCD_MODE_ON);
        // LCD_PrintChar(LCD_CHAR_2lines,0,LCD_MODE_ON);
        {
            uint8_t prc = MOTOR_GetPosPercent();
            if (prc<=100) {
                LCD_PrintDec3(MOTOR_GetPosPercent(), 0 ,LCD_MODE_ON);
            } else {
                LCD_PrintStringID(LCD_STRING_minusCminus,LCD_MODE_ON);
            }
        }
        break;
#if (! REMOTE_SETTING_ONLY)
    case menu_set_timmer_dow:
        clr_show1(LCD_SEG_PROG); // all segments off
        LCD_PrintDayOfWeek(menu_set_dow, LCD_MODE_BLINK_1);
        break;
    case menu_set_timmer:
        //! \todo calculate "hourbar" status, actual position in mode LCD_MODE_BLINK_1
        
//        clr_show3(LCD_SEG_COL1,LCD_SEG_COL2,LCD_SEG_PROG);
        clr_show2(LCD_SEG_COL1,LCD_SEG_COL2);
        timmers_patch_offset=timers_get_raw_index(menu_set_dow, menu_set_slot);
        timmers_patch_data = menu_set_time +  ((uint16_t)menu_set_mode<<12);
        LCD_HourBarBitmap(RTC_DowTimerGetHourBar(menu_set_dow));
        timmers_patch_offset=0xff;
        LCD_SetHourBarSeg(menu_set_time/60, LCD_MODE_BLINK_1);
        if (menu_set_time < 24*60) {
            LCD_PrintDec(menu_set_time/60, 2, LCD_MODE_BLINK_1);
            LCD_PrintDec(menu_set_time%60, 0, LCD_MODE_BLINK_1);        
        } else {
            LCD_PrintStringID(LCD_STRING_4xminus,LCD_MODE_BLINK_1);
        }
        show_selected_temperature_type(menu_set_mode,LCD_MODE_BLINK_1);
        break;                                                             
#endif
    case menu_lock:        // "bloc" message
        LCD_AllSegments(LCD_MODE_OFF); // all segments off
        LCD_PrintStringID(LCD_STRING_bloc,LCD_MODE_ON);
        break;
    case menu_service1: 
    case menu_service2:
        // service menu; left side index, right value
        LCD_AllSegments(LCD_MODE_ON);
        LCD_PrintHex(service_idx, 2, ((menu_state == menu_service1) ? LCD_MODE_BLINK_1 : LCD_MODE_ON));
        LCD_PrintHex(config_raw[service_idx], 0, ((menu_state == menu_service2) ? LCD_MODE_BLINK_1 : LCD_MODE_ON));
       break;
    case menu_service_watch:
        LCD_AllSegments(LCD_MODE_ON);
        LCD_PrintHexW(watch(service_watch_n),LCD_MODE_ON);
        LCD_SetHourBarSeg(service_watch_n, LCD_MODE_BLINK_1);
        break;
#if (! REMOTE_SETTING_ONLY)
    case menu_preset_temp0:
    case menu_preset_temp1:
    case menu_preset_temp2:
    case menu_preset_temp3:
        LCD_AllSegments(LCD_MODE_OFF);
        LCD_PrintTemp(menu_set_temp,LCD_MODE_BLINK_1);
        show_selected_temperature_type(menu_state-menu_preset_temp0,LCD_MODE_ON);
#endif
    default:
        break;                   
    }
    
    LCD_Update();
}