diff --git a/README.md b/README.md index 29b3056..f848c06 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,62 @@ # Makecode Extension to enable power management on micro:bit (V2) -Use this extension to add all the blocks you will need to power the micro:bit on and off in your program when you are using the [latest micro:bit](https://microbit.org/new-microbit/). +Use this extension to add all the blocks you will need to use less power in your program when you are using the [latest micro:bit](https://microbit.org/new-microbit/). This extension might be useful when you want to conserve battery power, such as during a data logging activity. + ## Usage -### Put the micro:bit to sleep 💤 +### Put the micro:bit to sleep in a low power mode 💤 -To make the micro:bit sleep, you need to send a request to power it down. The ``||power.powerDownRequest||`` block will ask the micro:bit to power down at the next opportunity, such as when the current code operation has been allowed to complete. +The ``||power.lowPowerRequest||`` block will ask the micro:bit to switch to low power mode at the next opportunity, such as when the current code operation has been allowed to complete, or inside ``||basic.pause(ms)||``. ```blocks input.onButtonPressed(Button.B, function () { - power.powerDownRequest() + power.lowPowerRequest() }) ``` -You can also ask the micro:bit to enter a ``||power.deepSleep||`` where it will pause until a wake up event occurs and power down at the next opportunity. +You can send ``||power.lowPowerRequest(LowPowerMode.Wait)||``. Then micro:bit will also pause until a full power event occurs. + +The ``||power.lowPowerPause(ms)||`` block will ask the micro:bit to sleep for a set interval in milliseconds. -The ``||power.deepSleepPause(ms)||`` block will also ask the micro:bit to sleep for a set interval in milliseconds. +In low power mode, the micro:bit is asleep, and your program is paused. When the micro:bit wakes up to full power mode, your program continues from the point it stopped. -You can also use the ``||PowerDown.prevent||`` and ``||PowerDown.allow||`` blocks to block a power down request until the code inside the two blocks has finished running. It is expected that you would use these blocks in pairs. +You can use the ``||power.lowPowerEnable(PowerDown.prevent)||`` and ``||power.lowPowerEnable(PowerDown.allow)||`` blocks to block low power requests until the code between the two blocks has finished running. It is expected that you would use these blocks in pairs. ```blocks basic.forever(function () { - power.powerDownEnable(PowerDown.prevent) + power.lowPowerEnable(PowerDown.prevent) led.plot(2, 2) basic.pause(1000) led.unplot(2, 2) led.plot(2, 1) basic.pause(1000) led.unplot(2, 1) - power.powerDownEnable(PowerDown.allow) - power.powerDownRequest() + power.lowPowerEnable(PowerDown.allow) + power.lowPowerRequest() }) ``` -### Wake the micro:bit from sleep ⏰ +### Wake up the micro:bit to full power mode ⏰ -In order to wake the micro:bit, you need to define an event to trigger the wake up call. +In order to wake up the micro:bit to full power mode, you need to define an event to trigger the wake up call. You can wake the micro:bit when a button or pin is pressed. In this example, the micro:bit will wake up when Button A or Pin 0 has been pressed. ```blocks -power.wakeOnEnable(PowerWakeup.A) -power.wakeOnEnable(PowerWakeup.P0) +power.fullPowerOn(FullPowerSource.A) +power.fullPowerOn(FullPowerSource.P0) ``` You can also wake the micro:bit at a set time interval in milliseconds. In this example, the micro:bit will wake up every minute and show a smiley face on the screen ```blocks -power.wakeEvery(60000, function () { +power.fullPowerEvery(60000, function () { basic.showIcon(IconNames.Happy) basic.clearScreen() + power.lowPowerRequest() }) ``` diff --git a/power.cpp b/power.cpp index 1f3bdbb..c8e77f8 100644 --- a/power.cpp +++ b/power.cpp @@ -18,58 +18,77 @@ #endif // MICROBIT_CODAL -enum class PowerWakeup { +enum class FullPowerSource { + //% block="button A" A = MICROBIT_ID_BUTTON_A, + //% block="button B" B = MICROBIT_ID_BUTTON_B, + //% block="pin P0" P0 = MICROBIT_ID_IO_P0, + //% block="pin P1" P1 = MICROBIT_ID_IO_P1, + //% block="pin P2" P2 = MICROBIT_ID_IO_P2 }; -enum class PowerDown { - prevent, - allow +enum class LowPowerMode { + //% block="continue" + Continue = 0, + //% block="wait" + Wait = 1 +}; + +enum class LowPowerEnable { + //% block="prevent" + Prevent, + //% block="allow" + Allow }; +//% block="Power" +//% icon="\uf011" +//% color=#AA278D namespace power { #if MICROBIT_CODAL int timerEventValue = 1; #endif // MICROBIT_CODAL -/** - * Pause until a wake up event occurs, and request power down when idle. - */ -//% -void deepSleep() { -#if MICROBIT_CODAL - uBit.power.deepSleep(); -#else - uBit.sleep(0); -#endif -} - +void lowPowerRequest(LowPowerMode mode = LowPowerMode::Continue); /** - * Request power down when idle, and return immediately. + * Request low power when the next idle + * @param mode If Continue, then return immediately; if Wait, then pause until a power-up event occurs */ +//% help=power/low-power-request +//% group="micro:bit (V2)" +//% weight=700 +//% block="request low power||and $mode" //% -void powerDownRequest() { +void lowPowerRequest(LowPowerMode mode) { #if MICROBIT_CODAL - uBit.power.deepSleepAsync(); + if ( mode == LowPowerMode::Wait) + uBit.power.deepSleep(); + else + uBit.power.deepSleepAsync(); #else uBit.sleep(0); #endif -} +} /** - * Pause for a fixed interval, and request power down when idle. + * Pause for a fixed interval, and request low power when idle. * @param interval The period of time to pause, in milliseconds. */ +//% help=power/low-power-for +//% group="micro:bit (V2)" +//% weight=600 +//% interval.shadow=longTimePicker +//% block="request low power for $interval ms" //% -void deepSleepPause(unsigned interval) { +void lowPowerPause(int interval) { #if MICROBIT_CODAL uBit.power.deepSleep(interval); #else @@ -79,38 +98,23 @@ void deepSleepPause(unsigned interval) { /** - * Do something repeatedy using a wake-up timer. - * @param interval time (in ms) for the timer. - * @param body code to execute - */ -//% -void wakeEvery(unsigned interval, Action body) { -#if MICROBIT_CODAL - registerWithDal( MICROBIT_ID_MAKECODE_POWER, timerEventValue, body); - // CODAL_TIMER_EVENT_FLAGS_WAKEUP makes the timer event trigger power up - system_timer_event_after( 0, MICROBIT_ID_MAKECODE_POWER, timerEventValue, CODAL_TIMER_EVENT_FLAGS_WAKEUP); - system_timer_event_every( interval, MICROBIT_ID_MAKECODE_POWER, timerEventValue++, CODAL_TIMER_EVENT_FLAGS_WAKEUP); -#else - target_panic(PANIC_VARIANT_NOT_SUPPORTED); -#endif -} - - -/** - * Prevent or allow power down during deepSleep. + * Prevent or allow low power. * Prevent and allow requests should occur in pairs. * The default is to allow. */ +//% help=power/low-power-enable +//% weight=500 +//% block="low power %enable" //% -void powerDownEnable(PowerDown choice) { +void lowPowerEnable(LowPowerEnable enable) { #if MICROBIT_CODAL - switch ( choice) + switch ( enable) { - case PowerDown::prevent: + case LowPowerEnable::Prevent: uBit.power.powerDownDisable(); break; - case PowerDown::allow: + case LowPowerEnable::Allow: uBit.power.powerDownEnable(); break; @@ -122,10 +126,11 @@ void powerDownEnable(PowerDown choice) { /** - * Determine if power down during deepSleep is enabled + * Determine if low power is enabled */ +//% help=power/low-power-is-enabled //% -bool powerDownIsEnabled() { +bool lowPowerIsEnabled() { #if MICROBIT_CODAL return uBit.power.powerDownIsEnabled(); #else @@ -135,29 +140,55 @@ bool powerDownIsEnabled() { /** - * Set whether the source should trigger power save wake-up. + * Do something repeatedy with full power using a timer. + * @param interval the time (in ms) for the timer. + * @param code the code to execute + */ +//% help=power/full-power-every +//% group="micro:bit (V2)" +//% weight=800 +//% blockAllowMultiple=1 +//% interval.shadow=longTimePicker +//% afterOnStart=true +//% block="full power every $interval ms" +//% +void fullPowerEvery(int interval, Action code) { +#if MICROBIT_CODAL + registerWithDal( MICROBIT_ID_MAKECODE_POWER, timerEventValue, code); + // CODAL_TIMER_EVENT_FLAGS_WAKEUP makes the timer event trigger power up + system_timer_event_after( 0, MICROBIT_ID_MAKECODE_POWER, timerEventValue, CODAL_TIMER_EVENT_FLAGS_WAKEUP); + system_timer_event_every( interval, MICROBIT_ID_MAKECODE_POWER, timerEventValue++, CODAL_TIMER_EVENT_FLAGS_WAKEUP); +#else + target_panic(PANIC_VARIANT_NOT_SUPPORTED); +#endif +} + + +/** + * Set whether the source should trigger full power. * @param source the source to set - * @param wake true to trigger wake-up or false for no wake-up + * @param enable true to trigger full power */ +//% help=power/full-power-source-enable //% -void wakeOn(PowerWakeup source, bool wake) { +void fullPowerSourceEnable(FullPowerSource source, bool enable) { #if MICROBIT_CODAL switch ( source) { - case PowerWakeup::A: - uBit.buttonA.wakeOnActive(wake ? 1 : 0); + case FullPowerSource::A: + uBit.buttonA.wakeOnActive(enable ? 1 : 0); break; - case PowerWakeup::B: - uBit.buttonB.wakeOnActive(wake ? 1 : 0); + case FullPowerSource::B: + uBit.buttonB.wakeOnActive(enable ? 1 : 0); break; - case PowerWakeup::P0: - case PowerWakeup::P1: - case PowerWakeup::P2: + case FullPowerSource::P0: + case FullPowerSource::P1: + case FullPowerSource::P2: { MicroBitPin *pin = getPin((int)source); - pin->wakeOnActive(wake ? 1 : 0); + pin->wakeOnActive(enable ? 1 : 0); break; } default: @@ -168,35 +199,27 @@ void wakeOn(PowerWakeup source, bool wake) { /** - * Set the source to trigger power save wake-up. - * @param source the source to set - */ -//% -void wakeOnEnable(PowerWakeup source) { - wakeOn(source, true); -} - -/** - * Determine if the source will trigger power save wake-up. - * @param source the source to set - * @return true is wake-up is enabled + * Determine if the source will trigger full power. + * @param source the source to check + * @return true if the source will trigger full power */ +//% help=power/full-power-source-is-enabled //% -bool wakeOnIsEnabled(PowerWakeup source) { +bool fullPowerSourceIsEnabled(FullPowerSource source) { #if MICROBIT_CODAL switch ( source) { - case PowerWakeup::A: + case FullPowerSource::A: return uBit.buttonA.isWakeOnActive() ? true : false; break; - case PowerWakeup::B: + case FullPowerSource::B: return uBit.buttonB.isWakeOnActive() ? true : false; break; - case PowerWakeup::P0: - case PowerWakeup::P1: - case PowerWakeup::P2: + case FullPowerSource::P0: + case FullPowerSource::P1: + case FullPowerSource::P2: { MicroBitPin *pin = getPin((int)source); return pin->isWakeOnActive() ? true : false; @@ -210,4 +233,18 @@ bool wakeOnIsEnabled(PowerWakeup source) { } +/** + * Set the source to trigger full power. + * @param source the source to set + */ +//% help=power/full-power-on +//% group="micro:bit (V2)" +//% weight=900 +//% block="full power on %source" +//% +void fullPowerOn(FullPowerSource source) { + fullPowerSourceEnable(source, true); +} + + } // namespace power diff --git a/power.ts b/power.ts index bcab286..7a245bc 100644 --- a/power.ts +++ b/power.ts @@ -4,116 +4,140 @@ * SPDX-License-Identifier: MIT */ - const enum PowerWakeup { - A = 1, // MICROBIT_ID_BUTTON_A - B = 2, // MICROBIT_ID_BUTTON_B - P0 = 100, // MICROBIT_ID_IO_P0 - P1 = 101, // MICROBIT_ID_IO_P1 - P2 = 102, // MICROBIT_ID_IO_P2 - } - - - const enum PowerDown { - prevent = 0, - allow = 1, - } - - - //% block="Power" - //% icon="\uf011" - //% color=#AA278D - namespace power { - - /** - * Pause until a wake up event occurs, and request power down when idle. - */ - //% help=power/deep-sleep - //% blockGap=8 - //% group="micro:bit (V2)" - //% weight=800 - //% block="deep sleep" shim=power::deepSleep - export function deepSleep(): void { basic.pause(0) } - - /** - * Request power down when idle, and return immediately. - */ - //% help=power/deep-sleep-async - //% blockGap=8 - //% group="micro:bit (V2)" - //% weight=400 - //% block="request power down" shim=power::powerDownRequest - export function powerDownRequest(): void { basic.pause(0) } - - /** - * Pause for a fixed interval, and request power down when idle. - * @param interval The period of time to pause, in milliseconds. - */ - //% help=power/deep-sleep-pause - //% blockGap=8 - //% group="micro:bit (V2)" - //% weight=700 - //% block="deep sleep pause $interval ms" - //% interval.shadow=longTimePicker shim=power::deepSleepPause - export function deepSleepPause(interval: number): void { basic.pause(interval) } - - /** - * Do something repeatedy using a wake-up timer. - * @param interval time (in ms) for the timer. - * @param body code to execute - */ - //% help=power/wake-every - //% blockAllowMultiple=1 - //% interval.shadow=longTimePicker - //% afterOnStart=true - //% group="micro:bit (V2)" - //% weight=600 - //% block="wake every $interval ms" shim=power::wakeEvery - export function wakeEvery(interval: number, body: () => void): void { basic.pause(0) } - - /** - * Prevent or allow power down during deepSleep. - * Prevent and allow requests should occur in pairs. - * The default is to allow. - */ - //% help=power/power-down - //% blockGap=8 - //% group="micro:bit (V2)" - //% weight=500 - //% block="power down %choice" shim=power::powerDownEnable - export function powerDownEnable(choice: PowerDown): void { basic.pause(0) } - - /** - * Determine if power down during deepSleep is enabled - */ - //% help=power/power-down-enabled - //% group="micro:bit (V2)" shim=power::powerDownIsEnabled - export function powerDownIsEnabled(): boolean { return true } - - /** - * Set whether the source should trigger power save wake-up. - * @param source the source to set - * @param wake true to trigger wake-up or false for no wake-up - */ - //% help=power/wake-on - //% group="micro:bit (V2)" shim=power::wakeOn - export function wakeOn(source: PowerWakeup, wake: boolean): void { basic.pause(0) } - - /** - * Set the source to trigger power save wake-up. - * @param source the source to set - */ - //% help=power/wake-on - //% blockGap=8 - //% group="micro:bit (V2)" - //% weight=900 - //% block="wake on %source" shim=power::wakeOnEnable - export function wakeOnEnable(source: PowerWakeup): void { basic.pause(0) } - - /** - * Determine if the source will trigger power save wake-up. - * @param source the source to set - * @return true is wake-up is enabled - */ - //% help=power/wake-on-enabled shim=power::wakeOnIsEnabled - export function wakeOnIsEnabled(source: PowerWakeup): boolean { return false } +const enum FullPowerSource { + //% block="button A" + A = DAL.MICROBIT_ID_BUTTON_A, // 1 + //% block="button B" + B = DAL.MICROBIT_ID_BUTTON_B, // 2 + //% block="pin P0" + P0 = DAL.MICROBIT_ID_IO_P0, // 100 + //% block="pin P1" + P1 = DAL.MICROBIT_ID_IO_P1, // 101 + //% block="pin P2" + P2 = DAL.MICROBIT_ID_IO_P2 // 102 +} + + +const enum LowPowerMode { + //% block="continue" + Continue = 0, + //% block="wait" + Wait = 1 +} + + +const enum LowPowerEnable { + //% block="prevent" + Prevent = 0, + //% block="allow" + Allow = 1 +} + + +//% block="Power" +//% icon="\uf011" +//% color=#AA278D +namespace power { + +/** + * Request low power when the next idle + * @param mode If Continue, then return immediately; if Wait, then pause until a power-up event occurs + */ +//% help=power/low-power-request +//% group="micro:bit (V2)" +//% weight=700 +//% block="request low power||and $mode" +//% shim=power::lowPowerRequest +export function lowPowerRequest(mode?: LowPowerMode): void { + basic.pause(0) +} + +/** + * Pause for a fixed interval, and request low power when idle. + * @param interval The period of time to pause, in milliseconds. + */ +//% help=power/low-power-for +//% group="micro:bit (V2)" +//% weight=600 +//% interval.shadow=longTimePicker +//% block="request low power for $interval ms" +//% shim=power::lowPowerPause +export function lowPowerPause(interval: number): void { + basic.pause(interval) +} + +/** + * Prevent or allow low power. + * Prevent and allow requests should occur in pairs. + * The default is to allow. + */ +//% help=power/low-power-enable +//% weight=500 +//% block="low power %enable" +//% shim=power::lowPowerEnable +export function lowPowerEnable(enable: LowPowerEnable): void { + return +} + +/** + * Determine if low power is enabled + */ +//% help=power/low-power-is-enabled +//% shim=power::lowPowerIsEnabled +export function lowPowerIsEnabled(): boolean { + return false +} + +/** + * Do something repeatedy with full power using a timer. + * @param interval the time (in ms) for the timer. + * @param code the code to execute + */ +//% help=power/full-power-every +//% group="micro:bit (V2)" +//% weight=800 +//% blockAllowMultiple=1 +//% interval.shadow=longTimePicker +//% afterOnStart=true +//% block="full power every $interval ms" +//% shim=power::fullPowerEvery +export function fullPowerEvery(interval: number, code: () => void): void { + loops.everyInterval(interval, code) +} + +/** + * Set whether the source should trigger full power. + * @param source the source to set + * @param enable true to trigger full power + */ +//% help=power/full-power-source-enable +//% shim=power::fullPowerSourceEnable +export function fullPowerSourceEnable(source: FullPowerSource, enable: boolean): void { + return +} + +/** + * Determine if the source will trigger full power. + * @param source the source to check + * @return true if the source will trigger full power + */ +//% help=power/full-power-source-is-enabled +//% shim=power::fullPowerSourceIsEnabled +export function fullPowerSourceIsEnabled(source: FullPowerSource): boolean { + return false +} + +/** + * Set the source to trigger full power. + * @param source the source to set + */ +//% help=power/full-power-on +//% group="micro:bit (V2)" +//% weight=900 +//% block="full power on %source" +//% shim=power::fullPowerOn +export function fullPowerOn(source: FullPowerSource): void { + return +} + } diff --git a/pxt.json b/pxt.json index 463bdc2..ee77133 100644 --- a/pxt.json +++ b/pxt.json @@ -1,14 +1,14 @@ { "name": "power", - "version": "0.1.0", + "version": "0.2.1", "description": "Power saving. micro:bit (V2) only.", "dependencies": { "core": "*" }, "files": [ - "README.md", + "power.cpp", "power.ts", - "power.cpp" + "README.md" ], "testFiles": [ "test.ts" diff --git a/test.ts b/test.ts index ec5d176..a9d9085 100644 --- a/test.ts +++ b/test.ts @@ -5,41 +5,41 @@ */ function flash(x: number) { - power.powerDownEnable(PowerDown.prevent) + power.lowPowerEnable(LowPowerEnable.Prevent) led.plot(x, 0) basic.pause(1000) led.unplot(x, 0) led.plot(x, 1) basic.pause(1000) led.unplot(x, 1) - power.powerDownEnable(PowerDown.allow) + power.lowPowerEnable(LowPowerEnable.Allow) } input.onButtonPressed(Button.A, function () { flash(1) - power.powerDownRequest() + power.lowPowerRequest(LowPowerMode.Continue) }) input.onButtonPressed(Button.B, function () { flash(2) - power.powerDownRequest() + power.lowPowerRequest(LowPowerMode.Continue) }) basic.showString("POWER") -power.wakeOnEnable(PowerWakeup.A) -power.wakeOnEnable(PowerWakeup.B) +power.fullPowerOn(FullPowerSource.A) +power.fullPowerOn(FullPowerSource.B) -power.wakeEvery(6000, function () { +power.fullPowerEvery(6000, function () { flash(3) - power.powerDownRequest() + power.lowPowerRequest(LowPowerMode.Continue) }) basic.forever(function () { flash(0) - power.deepSleepPause(20000) + power.lowPowerPause(20000) }) basic.forever(function () { flash(4) - power.deepSleep() + power.lowPowerRequest(LowPowerMode.Wait) })