Esempio n. 1
0
// Application entry point.
int main() {
    // ==== Setup clock ====
    // 8/1 = 8 MHz core clock. APB1 & APB2 clock derive on AHB clock
    Clk.SetupBusDividers(ahbDiv1, apbDiv1, apbDiv1);
    Clk.UpdateFreqValues();

    // Init OS
    halInit();
    chSysInit();
    Init();

    bool ExtPwrOn = false;

    while(TRUE) {
#ifndef TESTING
        Indication();
        if(IsExtPwrOn()) {
            // Detect power change
            if(!ExtPwrOn) {
                Uart.Printf("ExtPwrOn\r");
                ExtPwrOn = true;
                App.Enabled = false;
                SwitchOffEverything();
                // Lower CPU freq
                chSysLock();
                Clk.SetupBusDividers(ahbDiv8, apbDiv1, apbDiv1);
                Clk.UpdateFreqValues();
                Clk.UpdateSysTimer();
                chSysUnlock();
            }
            App.Status = IsCharging()? stCharging : stChargeCompleted;
        }
        else {
            if(ExtPwrOn) {
                Uart.Printf("ExtPwrOff\r");
                SwitchOffEverything();
                ExtPwrOn = false;
                // Increase CPU freq
                chSysLock();
                Clk.SetupBusDividers(ahbDiv1, apbDiv1, apbDiv1);
                Clk.UpdateFreqValues();
                Clk.UpdateSysTimer();
                chSysUnlock();
                App.Status = stIdle;
                App.Enabled = true;
            }
        }
#else
        chThdSleepMilliseconds(999);
        if(!Acc[0].IsOperational) {
            Uart.Printf("Acc fail\r");
            Acc[0].Init();
        }
        else {
            Acc[0].ReadAccelerations();
            Uart.Printf("%d %d %d\r", Acc[0].a[0], Acc[0].a[1], Acc[0].a[2]);
        }
#endif
    } // while 1
}
AutoPtr<ArrayOf<Double> > CGeckoBatteryManager::GetCurrentInformation()
{
    AutoPtr<ArrayOf<Double> > info = ArrayOf<Double>::Alloc(3);
    (*info)[0] = GetLevel();
    (*info)[1] = IsCharging() ? 1.0 : 0.0;
    (*info)[2] = GetRemainingTime();
    return info;
}
ECode CGeckoBatteryManager::OnRecieve(
    /* [in] */ IContext *pContext,
    /* [in] */ IIntent *pIntent)
{
    String action;
    pIntent->GetAction(&action);
    if (!action.Equals(IIntent::ACTION_BATTERY_CHANGED)) {
        printf("GeckoBatteryManager" "Got an unexpected intent!");
        return NOERROR;
    }

    Boolean previousCharging = IsCharging();
    Double previousLevel = GetLevel();

    Boolean booleanExtra;
    pIntent->GetBooleanExtra(
                String("present")/*BatteryManager_EXTRA_PRESENT*/,
                false, &booleanExtra);
    if (booleanExtra) {
        Int32 plugged;
        pIntent->GetInt32Extra(String("plugged")/*BatteryManager_EXTRA_PLUGGED*/, -1, &plugged);

        if (plugged == -1) {
            sCharging = kDefaultCharging;
            printf("GeckoBatteryManager" "Failed to get the plugged status!");
        }
        else {
            // Likely, if plugged > 0, it's likely plugged and charging but the doc
            // isn't clear about that.
            sCharging = plugged != 0;
        }

        if (sCharging != previousCharging) {
            sRemainingTime = kUnknownRemainingTime;
            // The new remaining time is going to take some time to show up but
            // it's the best way to show a not too wrong value.
            ASSERT_SUCCEEDED(CDate::New(0, (IDate**)&sLastLevelChange));
        }

        // We need two doubles because sLevel is a double.
        Double current;
        Double max;
        pIntent->GetDoubleExtra(String("level")/*BatteryManager_EXTRA_LEVEL*/, -1, &current);
        pIntent->GetDoubleExtra(String("scale")/*BatteryManager_EXTRA_SCALE*/, -1, &max);

        if (current == -1 || max == -1) {
            printf("GeckoBatteryManager" "Failed to get battery level!");
            sLevel = kDefaultLevel;
        }
        else {
            sLevel = current / max;
        }

        if (sLevel == 1.0 && sCharging) {
            sRemainingTime = 0.0;
        }
        else if (sLevel != previousLevel) {
            // Estimate remaining time.
            Int64 changeTime;
            sLastLevelChange->GetTime(&changeTime);
            if (changeTime != 0) {
                AutoPtr<IDate> currentTime;
                ASSERT_SUCCEEDED(CDate::New((IDate**)&currentTime));

                Int64 curTime;
                currentTime->GetTime(&curTime);
                Int64 dt = (curTime - changeTime) / 1000;
                Double dLevel = sLevel - previousLevel;

                if (sCharging) {
                    if (dLevel < 0) {
                        printf("GeckoBatteryManager"  "When charging, level should increase!");
                        sRemainingTime = kUnknownRemainingTime;
                    }
                    else {
                        sRemainingTime = Math::Round(dt / dLevel * (1.0 - sLevel));
                    }
                }
                else {
                    if (dLevel > 0) {
                        printf("GeckoBatteryManager" "When discharging, level should decrease!");
                        sRemainingTime = kUnknownRemainingTime;
                    }
                    else {
                        sRemainingTime = Math::Round(dt / -dLevel * sLevel);
                    }
                }

                sLastLevelChange = currentTime;
            }
            else {
                // That's the first time we got an update, we can't do anything.
                CDate::New((IDate**)&sLastLevelChange);
            }
        }
    }
    else {
        sLevel = kDefaultLevel;
        sCharging = kDefaultCharging;
        sRemainingTime = kDefaultRemainingTime;
    }

    /*
     * We want to inform listeners if the following conditions are fulfilled:
     *  - we have at least one observer;
     *  - the charging state or the level has changed.
     *
     * Note: no need to check for a remaining time change given that it's only
     * updated if there is a level change or a charging change.
     *
     * The idea is to prevent doing all the way to the DOM code in the child
     * process to finally not send an event.
     */
    if (sNotificationsEnabled &&
        (previousCharging != IsCharging() || previousLevel != GetLevel())) {
        GeckoAppShell::NotifyBatteryChange(GetLevel(), IsCharging(), GetRemainingTime());
    }
    return NOERROR;
}
void ButtonGuardThread(void* pvParameters)
{
	unsigned long ulTick = 0;
	s_ulIdleTick = 0;
	unsigned long ulLongKeepOff = 0;
	
	unsigned long ulChrgTick = 0;
	bool bEnableRunning = true;
	while(1) {
		ulTick++;
		
		//	按钮状态检测
		int nBtnAction = ButtonCheck();
		if (nBtnAction != BTN_NOACTION) {
			s_ulIdleTick = 0;
			
			if ( (nBtnAction==BTN_PUSHDOWN) && g_bRunning ) {
				g_bRunning = false;
				MotorRun(g_bRunning);
				bEnableRunning = false;
			}
			else if ( (nBtnAction==BTN_POPUP) && !g_bRunning ) {
				if (!bEnableRunning) {
					bEnableRunning = true;
				}
				else {
					if (g_bRunable) {	//	如果不在SimpleLink操作阶段则不能运行探头
						g_bRunning = true;
						MotorRun(g_bRunning);
					}
				}
			}
			
			ulLongKeepOff = 0;	//	长按关机计数
		} else {	//	长按关机状态下关闭电源
			if ( s_nStatOut == BTN_UP) {
				ulLongKeepOff = 0;
			} else {
				++ulLongKeepOff;
				if (ulLongKeepOff/100 > 8) {	//	长按8秒关闭电源
					MotorRun(false);
					TurnOff();
				}
			}
			
			//	注:
			//		长按关机是为了避免运输工程中,如果探头的按钮受到挤压而开机;
			//	在这种状态下,按钮控制芯片并不会在一定时间后主动关闭电源,从而
			//	会导致电源耗尽或者其他潜在风险。
			//		故而解决的方法是检测按钮是否长时间(8S)处于未知或者按下
			//	状态,一旦检测到则关闭电源。
			//												吴文斌
			//											2015 - 3 - 30
		}
		
		//	充电状态检测
		if (IsCharging()) {
			ulChrgTick++;
			if (ulChrgTick > 20) {			
				TRACE("Begin Charging...\n\r");	
				g_bRunning = false;
				MotorRun(g_bRunning);
				TurnOff();
			}
		}
		else {
			ulChrgTick = 0;
		}
		
		
		//	待机时间检测
		++s_ulIdleTick;
		if (	(s_ulIdleTick/100/60 > 10)	//	连续运行10分钟则停止运行
			&&	g_bRunning )
		{
			TRACE("10min to Stop Running...\n\r");
			g_bRunning = !g_bRunning;
			MotorRun(g_bRunning);
		}
		if ( s_ulIdleTick/100/60 > 15) {		//	待机时间超过15分钟则关闭电源
			TRACE("15min to Power Off...\n\r");
			TurnOff();
		}
		
		
		vTaskDelay(10/portTICK_PERIOD_MS);
	}
}