Skip to content

Commit 9a4efed

Browse files
committed
Start tweaking the workflow to sleep
1 parent 85dadf3 commit 9a4efed

File tree

17 files changed

+282
-90
lines changed

17 files changed

+282
-90
lines changed

main.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@
8888
#include "common-hal/canio/CAN.h"
8989
#endif
9090

91+
#if CIRCUITPY_SLEEPIO
92+
#include "shared-bindings/sleepio/__init__.h"
93+
#endif
94+
9195
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
9296
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
9397
if (lex == NULL) {
@@ -303,19 +307,6 @@ bool run_code_py(safe_mode_t safe_mode) {
303307
}
304308
}
305309

306-
for (uint8_t i = 0; i<=100; i++) {
307-
if (!usb_msc_ejected()) {
308-
//Go into light sleep
309-
break;
310-
}
311-
mp_hal_delay_ms(10);
312-
}
313-
314-
if (usb_msc_ejected()) {
315-
//Go into deep sleep
316-
common_hal_mcu_deep_sleep();
317-
}
318-
319310
// Display a different completion message if the user has no USB attached (cannot save files)
320311
if (!serial_connected_at_start) {
321312
serial_write_compressed(translate("\nCode done running. Waiting for reload.\n"));
@@ -326,6 +317,14 @@ bool run_code_py(safe_mode_t safe_mode) {
326317
bool refreshed_epaper_display = false;
327318
#endif
328319
rgb_status_animation_t animation;
320+
bool ok = result->return_code != PYEXEC_EXCEPTION;
321+
#if CIRCUITPY_SLEEPIO
322+
// If USB isn't enumerated then deep sleep.
323+
if (ok && !supervisor_workflow_active() && supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024) {
324+
common_hal_sleepio_deep_sleep();
325+
}
326+
#endif
327+
// Show the animation every N seconds.
329328
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
330329
while (true) {
331330
RUN_BACKGROUND_TASKS;
@@ -358,8 +357,24 @@ bool run_code_py(safe_mode_t safe_mode) {
358357
refreshed_epaper_display = maybe_refresh_epaperdisplay();
359358
}
360359
#endif
361-
362-
tick_rgb_status_animation(&animation);
360+
bool animation_done = tick_rgb_status_animation(&animation);
361+
if (animation_done && supervisor_workflow_active()) {
362+
#if CIRCUITPY_SLEEPIO
363+
int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64();
364+
// If USB isn't enumerated then deep sleep after our waiting period.
365+
if (ok && remaining_enumeration_wait < 0) {
366+
common_hal_sleepio_deep_sleep();
367+
return; // Doesn't actually get here.
368+
}
369+
#endif
370+
// Wake up every so often to flash the error code.
371+
if (!ok) {
372+
port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024);
373+
} else {
374+
port_interrupt_after_ticks(remaining_enumeration_wait);
375+
}
376+
port_sleep_until_interrupt();
377+
}
363378
}
364379
}
365380

@@ -406,7 +421,9 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
406421
if (!skip_boot_output) {
407422
// Wait 1.5 seconds before opening CIRCUITPY_BOOT_OUTPUT_FILE for write,
408423
// in case power is momentary or will fail shortly due to, say a low, battery.
409-
mp_hal_delay_ms(1500);
424+
if (common_hal_sleepio_get_reset_reason() == RESET_REASON_POWER_VALID) {
425+
mp_hal_delay_ms(1500);
426+
}
410427

411428
// USB isn't up, so we can write the file.
412429
filesystem_set_internal_writable_by_usb(false);

ports/esp32s2/common-hal/alarm_touch/__init__.c

Lines changed: 0 additions & 7 deletions
This file was deleted.

shared-bindings/alarm_touch/__init__.c

Lines changed: 0 additions & 28 deletions
This file was deleted.

shared-bindings/alarm_touch/__init__.h

Lines changed: 0 additions & 14 deletions
This file was deleted.

shared-bindings/sleepio/ResetReason.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/enum.h"
28+
29+
#include "shared-bindings/sleepio/ResetReason.h"
30+
31+
MAKE_ENUM_VALUE(sleepio_reset_reason_type, reset_reason, POWER_VALID, RESET_REASON_POWER_VALID);
32+
MAKE_ENUM_VALUE(sleepio_reset_reason_type, reset_reason, SOFTWARE, RESET_REASON_SOFTWARE);
33+
MAKE_ENUM_VALUE(sleepio_reset_reason_type, reset_reason, DEEP_SLEEP_ALARM, RESET_REASON_DEEP_SLEEP_ALARM);
34+
MAKE_ENUM_VALUE(sleepio_reset_reason_type, reset_reason, EXTERNAL, RESET_REASON_EXTERNAL);
35+
36+
//| class ResetReason:
37+
//| """The reason the chip was last reset"""
38+
//|
39+
//| POWER_VALID: object
40+
//| """The chip was reset and started once power levels were valid."""
41+
//|
42+
//| SOFTWARE: object
43+
//| """The chip was reset from software."""
44+
//|
45+
//| DEEP_SLEEP_ALARM: object
46+
//| """The chip was reset for deep sleep and started by an alarm."""
47+
//|
48+
//| EXTERNAL: object
49+
//| """The chip was reset by an external input such as a button."""
50+
//|
51+
MAKE_ENUM_MAP(sleepio_reset_reason) {
52+
MAKE_ENUM_MAP_ENTRY(reset_reason, POWER_VALID),
53+
MAKE_ENUM_MAP_ENTRY(reset_reason, SOFTWARE),
54+
MAKE_ENUM_MAP_ENTRY(reset_reason, DEEP_SLEEP_ALARM),
55+
MAKE_ENUM_MAP_ENTRY(reset_reason, EXTERNAL),
56+
};
57+
STATIC MP_DEFINE_CONST_DICT(sleepio_reset_reason_locals_dict, sleepio_reset_reason_locals_table);
58+
59+
MAKE_PRINTER(sleepio, sleepio_reset_reason);
60+
61+
MAKE_ENUM_TYPE(sleepio, ResetReason, sleepio_reset_reason);

shared-bindings/sleepio/ResetReason.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
typedef enum {
30+
RESET_REASON_POWER_APPLIED,
31+
RESET_REASON_SOFTWARE,
32+
RESET_REASON_DEEP_SLEEP_ALARM,
33+
RESET_REASON_BUTTON,
34+
} sleepio_reset_reason_t;
35+
36+
extern const mp_obj_type_t sleepio_reset_reason_type;

shared-bindings/sleepio/__init__.c

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,17 @@
4747
//| """The most recent alarm to wake us up from a sleep (light or deep.)"""
4848
//|
4949

50+
//| reset_reason: ResetReason
51+
//| """The reason the chip started up from reset state. This can may be power up or due to an alarm."""
52+
//|
53+
5054
//| def sleep_until_alarm(alarm: Alarm, ...) -> Alarm:
5155
//| """Performs a light sleep until woken by one of the alarms. The alarm that woke us up is
5256
//| returned."""
5357
//| ...
5458
//|
5559

5660
STATIC mp_obj_t sleepio_sleep_until_alarm(size_t n_args, const mp_obj_t *args) {
57-
// mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
58-
// vstr_t vstr;
59-
// vstr_init_len(&vstr, size);
60-
// byte *p = (byte*)vstr.buf;
61-
// memset(p, 0, size);
62-
// byte *end_p = &p[size];
63-
// shared_modules_struct_pack_into(args[0], p, end_p, n_args - 1, &args[1]);
64-
// return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
6561
}
6662
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sleepio_sleep_until_alarm_obj, 1, MP_OBJ_FUN_ARGS_MAX, sleepio_sleep_until_alarm);
6763

@@ -71,14 +67,6 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sleepio_sleep_until_alarm_obj, 1, MP_OBJ_FUN
7167
//| ...
7268
//|
7369
STATIC mp_obj_t sleepio_set_alarms(size_t n_args, const mp_obj_t *args) {
74-
// mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
75-
// vstr_t vstr;
76-
// vstr_init_len(&vstr, size);
77-
// byte *p = (byte*)vstr.buf;
78-
// memset(p, 0, size);
79-
// byte *end_p = &p[size];
80-
// shared_modules_struct_pack_into(args[0], p, end_p, n_args - 1, &args[1]);
81-
// return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
8270
}
8371
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sleepio_set_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, sleepio_set_alarms);
8472

@@ -87,16 +75,23 @@ mp_map_elem_t sleepio_module_globals_table[] = {
8775
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sleepio) },
8876

8977
{ MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none },
78+
{ MP_ROM_QSTR(MP_QSTR_reset_reason), mp_const_none },
9079

9180
{ MP_ROM_QSTR(MP_QSTR_sleep_until_alarm), sleepio_sleep_until_alarm_obj },
9281
{ MP_ROM_QSTR(MP_QSTR_set_alarms), sleepio_set_alarms_obj },
9382
};
9483
STATIC MP_DEFINE_CONST_DICT(sleepio_module_globals, sleepio_module_globals_table);
9584

85+
// These are called from common hal code to set the current wake alarm.
9686
void common_hal_sleepio_set_wake_alarm(mp_obj_t alarm) {
9787
// sleepio_module_globals_table[1].value = alarm;
9888
}
9989

90+
// These are called from common hal code to set the current wake alarm.
91+
void common_hal_sleepio_set_reset_reason(mp_obj_t reset_reason) {
92+
// sleepio_module_globals_table[1].value = alarm;
93+
}
94+
10095
const mp_obj_module_t sleepio_module = {
10196
.base = { &mp_type_module },
10297
.globals = (mp_obj_dict_t*)&sleepio_module_globals,

shared-bindings/sleepio/__init__.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
#include "py/obj.h"
55

6-
// This is implemented by shared-bindings so that implementations can set the
7-
// newest alarm source.
8-
extern void common_hal_sleepio_set_wake_alarm(mp_obj_t alarm);
6+
extern mp_obj_t common_hal_sleepio_get_wake_alarm(void);
7+
extern sleepio_reset_reason_t common_hal_sleepio_get_reset_reason(void);
98

109
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_SLEEPIO___INIT___H

supervisor/serial.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,4 @@ char serial_read(void);
4747
bool serial_bytes_available(void);
4848
bool serial_connected(void);
4949

50-
extern volatile bool _serial_connected;
5150
#endif // MICROPY_INCLUDED_SUPERVISOR_SERIAL_H

supervisor/shared/rgb_led_status.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
367367
status->found_main = found_main;
368368
status->total_exception_cycle = 0;
369369
status->ok = result->return_code != PYEXEC_EXCEPTION;
370+
status->cycles = 0;
370371
if (status->ok) {
371372
// If this isn't an exception, skip exception sorting and handling
372373
return;
@@ -411,14 +412,16 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
411412
#endif
412413
}
413414

414-
void tick_rgb_status_animation(rgb_status_animation_t* status) {
415+
bool tick_rgb_status_animation(rgb_status_animation_t* status) {
415416
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED))
416417
uint32_t tick_diff = supervisor_ticks_ms32() - status->pattern_start;
417418
if (status->ok) {
418419
// All is good. Ramp ALL_DONE up and down.
419420
if (tick_diff > ALL_GOOD_CYCLE_MS) {
420421
status->pattern_start = supervisor_ticks_ms32();
421-
tick_diff = 0;
422+
status->cycles++;
423+
new_status_color(BLACK);
424+
return status->cycles;
422425
}
423426

424427
uint16_t brightness = tick_diff * 255 / (ALL_GOOD_CYCLE_MS / 2);
@@ -433,7 +436,8 @@ void tick_rgb_status_animation(rgb_status_animation_t* status) {
433436
} else {
434437
if (tick_diff > status->total_exception_cycle) {
435438
status->pattern_start = supervisor_ticks_ms32();
436-
tick_diff = 0;
439+
status->cycles++;
440+
return;
437441
}
438442
// First flash the file color.
439443
if (tick_diff < EXCEPTION_TYPE_LENGTH_MS) {

0 commit comments

Comments
 (0)