// 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, ¤t); 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**)¤tTime)); 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); } }