Skip to content

Commit cd94275

Browse files
committed
Add Bangle.js 2, JDI memory displays and ACeP epd
This 2-in-1 PR started with the goal of support the Bangle.js 2 smartwatch with *no USB*. * Adds "secure" DFU build support with a committed private key. * Adds 3-bit color support with one dummy bit for the JDI memory display * Allows nrf boards to have a board_background_task() run in RUN_BACKGROUND_TASK. This is needed because the Bangle.js 2 uses the watchdog to reset. * Renamed port_background_task() to port_background_tick() to indicate it runs on tick, not RUN_BACKGROUND_TASK. * Marks serial connected when the display terminal is inited. This means that safe mode messages show up on the display. ACep, 7-color epaper displays also pack 3 bits in 4. So, I added that support as well. * Adds 3-bit ACeP color support for 7-color e-paper displays. (Not watch related but similar due to color depth.) * Allows a refresh sequence instead of a single int command. The 7" ACeP display requires a data byte for refresh. * Adds optional delay after resetting the display. The ACeP displays need this. (Probably to load LUTs from flash.) * Adds a cleaning phase for ACeP displays before the real refresh. For both: * Add dither support to Palette. * Palette no longer converts colors when set. Instead, it caches converted colors at each index. * ColorConverter now caches the last converted color. It should make conversions faster for repeated colors (not dithering.)
1 parent c8a325a commit cd94275

File tree

49 files changed

+701
-175
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+701
-175
lines changed

locale/circuitpython.pot

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,6 @@ msgstr ""
202202
msgid "%q out of range"
203203
msgstr ""
204204

205-
#: ports/atmel-samd/common-hal/microcontroller/Pin.c
206-
msgid "%q pin invalid"
207-
msgstr ""
208-
209205
#: py/objrange.c py/objslice.c shared-bindings/random/__init__.c
210206
msgid "%q step cannot be zero"
211207
msgstr ""
@@ -1210,9 +1206,11 @@ msgid "Internal watchdog timer expired."
12101206
msgstr ""
12111207

12121208
#: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c
1209+
#: shared-bindings/displayio/EPaperDisplay.c
12131210
msgid "Invalid %q"
12141211
msgstr ""
12151212

1213+
#: ports/atmel-samd/common-hal/microcontroller/Pin.c
12161214
#: shared-bindings/microcontroller/Pin.c
12171215
msgid "Invalid %q pin"
12181216
msgstr ""

ports/atmel-samd/background.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,8 @@ void port_finish_background_task(void) {
5757
}
5858
#endif
5959

60+
void port_background_tick(void) {
61+
}
62+
6063
void port_background_task(void) {
6164
}

ports/atmel-samd/boards/openbook_m4/board.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ uint8_t stop_sequence[] = {
5252
0x02, 0x80, 0xf0 // Power off
5353
};
5454

55+
uint8_t refresh_sequence[] = {
56+
0x12, 0x00
57+
};
58+
5559
void board_init(void) {
5660
busio_spi_obj_t *spi = &displays[0].fourwire_bus.inline_bus;
5761
common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, false);
@@ -74,6 +78,7 @@ void board_init(void) {
7478
bus,
7579
start_sequence,
7680
sizeof(start_sequence),
81+
0, // start up time
7782
stop_sequence,
7883
sizeof(stop_sequence),
7984
300, // width
@@ -92,13 +97,15 @@ void board_init(void) {
9297
NO_COMMAND, // write_color_ram_command (can add this for grayscale eventually)
9398
false, // color_bits_inverted
9499
0x000000, // highlight_color
95-
0x12, // refresh_display_command
100+
refresh_sequence, // refresh_display_sequence
101+
sizeof(refresh_sequence),
96102
40, // refresh_time
97103
&pin_PA01, // busy_pin
98104
false, // busy_state
99105
5, // seconds_per_frame
100106
false, // chip_select (don't always toggle chip select)
101107
false, // grayscale
108+
false, // acep
102109
false); // two_byte_sequence_length
103110
}
104111

ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,10 @@ CIRCUITPY_DISPLAY_FONT = $(TOP)/ports/atmel-samd/boards/ugame10/brutalist-6.bdf
5353

5454
# Override optimization to keep binary small
5555
OPTIMIZATION_FLAGS = -Os
56+
57+
# We don't have room for the fonts for terminalio for certain languages,
58+
# so turn off terminalio and force a clean build.
59+
ifneq (,$(filter $(TRANSLATION),ja ko ru))
60+
CIRCUITPY_TERMINALIO = 0
61+
RELEASE_NEEDS_CLEAN_BUILD = 1
62+
endif

ports/atmel-samd/common-hal/microcontroller/Pin.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,5 @@ mcu_pin_function_t *mcu_find_pin_function(mcu_pin_function_t *table, const mcu_p
211211
return table;
212212
}
213213
}
214-
mp_raise_ValueError_varg(translate("%q pin invalid"), name);
214+
mp_raise_ValueError_varg(translate("Invalid %q pin"), name);
215215
}

ports/broadcom/background.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@ void port_start_background_task(void) {
3333
void port_finish_background_task(void) {
3434
}
3535

36+
void port_background_tick(void) {
37+
}
38+
3639
void port_background_task(void) {
3740
}

ports/cxd56/background.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "supervisor/filesystem.h"
3131
#include "supervisor/shared/stack.h"
3232

33+
void port_background_tick(void) {
34+
}
3335
void port_background_task(void) {
3436
}
3537
void port_start_background_task(void) {

ports/espressif/background.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,17 @@
4040
#include "common-hal/pulseio/PulseIn.h"
4141
#endif
4242

43-
void port_background_task(void) {
43+
void port_background_tick(void) {
4444
// Zero delay in case FreeRTOS wants to switch to something else.
4545
vTaskDelay(0);
4646
#if CIRCUITPY_PULSEIO
4747
pulsein_background();
4848
#endif
4949
}
5050

51+
void port_background_task(void) {
52+
}
53+
5154
void port_start_background_task(void) {
5255
}
5356

ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ const uint8_t display_stop_sequence[] = {
109109
0x02, 0x00 // Power off
110110
};
111111

112+
const uint8_t refresh_sequence[] = {
113+
0x12, 0x00
114+
};
115+
112116
void board_init(void) {
113117
// Debug UART
114118
#ifdef DEBUG
@@ -137,6 +141,7 @@ void board_init(void) {
137141
display,
138142
bus,
139143
display_start_sequence, sizeof(display_start_sequence),
144+
0, // start up time
140145
display_stop_sequence, sizeof(display_stop_sequence),
141146
296, // width
142147
128, // height
@@ -154,13 +159,14 @@ void board_init(void) {
154159
0x13, // write_color_ram_command
155160
false, // color_bits_inverted
156161
0x000000, // highlight_color
157-
0x12, // refresh_display_command
162+
refresh_sequence, sizeof(refresh_sequence),
158163
1.0, // refresh_time
159164
&pin_GPIO5, // busy_pin
160165
false, // busy_state
161166
5.0, // seconds_per_frame
162167
false, // always_toggle_chip_select
163168
true, // grayscale
169+
false, // acep
164170
false); // two_byte_sequence_length
165171
}
166172

ports/litex/background.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
void port_background_task(void) {
3434
}
35+
void port_background_tick(void) {
36+
}
3537
void port_start_background_task(void) {
3638
}
3739
void port_finish_background_task(void) {

ports/mimxrt10xx/background.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,14 @@
2828
#include "supervisor/port.h"
2929

3030
void port_background_task(void) {
31+
}
32+
33+
void port_background_tick(void) {
3134
#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
3235
audio_dma_background();
3336
#endif
3437
}
38+
3539
void port_start_background_task(void) {
3640
}
3741
void port_finish_background_task(void) {

ports/nrf/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ UF2_FAMILY_ID_nrf52840 = 0xADA52840
206206
UF2_FAMILY_ID_nrf52833 = 0x621E937A
207207

208208

209-
all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.combined.hex
209+
all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.combined.hex $(BUILD)/firmware.espruino.zip
210210

211211
$(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE)
212212
$(STEPECHO) "LINK $@"
@@ -301,6 +301,11 @@ dfu-gen: $(BUILD)/dfu-package.zip
301301
$(BUILD)/dfu-package.zip: $(BUILD)/firmware.hex
302302
$(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $^ $(BUILD)/dfu-package.zip
303303

304+
# Espruino DFU
305+
$(BUILD)/firmware.espruino.zip: $(BUILD)/firmware.hex
306+
$(NRFUTIL) pkg generate $(BUILD)/firmware.espruino.zip --application $^ --application-version 0xff --hw-version 52 --sd-req 0xa9,0xae,0xb6 --key-file espruino_dfu_private_key.pem
307+
308+
espruino-dfu-gen: $(BUILD)/firmware.espruino.zip
304309

305310
include $(TOP)/py/mkrules.mk
306311

ports/nrf/background.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include "background.h"
28+
2729
#include "py/runtime.h"
2830
#include "supervisor/filesystem.h"
2931
#include "supervisor/port.h"
@@ -44,14 +46,23 @@
4446

4547
void port_start_background_task(void) {
4648
}
49+
4750
void port_finish_background_task(void) {
4851
}
4952

50-
void port_background_task(void) {
53+
void port_background_tick(void) {
5154
#if CIRCUITPY_AUDIOPWMIO
5255
audiopwmout_background();
5356
#endif
5457
#if CIRCUITPY_AUDIOBUSIO
5558
i2s_background();
5659
#endif
5760
}
61+
62+
// Allow boards to override this.
63+
MP_WEAK void board_background_task(void) {
64+
}
65+
66+
void port_background_task(void) {
67+
board_background_task();
68+
}

ports/nrf/background.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@
2727
#ifndef MICROPY_INCLUDED_NRF_BACKGROUND_H
2828
#define MICROPY_INCLUDED_NRF_BACKGROUND_H
2929

30+
void board_background_task(void);
31+
3032
#endif // MICROPY_INCLUDED_NRF_BACKGROUND_H
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 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 "supervisor/board.h"
28+
#include "background.h"
29+
#include "mpconfigboard.h"
30+
31+
#include "shared-bindings/busio/SPI.h"
32+
#include "shared-bindings/displayio/FourWire.h"
33+
#include "shared-bindings/framebufferio/FramebufferDisplay.h"
34+
#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h"
35+
#include "shared-module/displayio/__init__.h"
36+
37+
digitalio_digitalinout_obj_t extcomin;
38+
digitalio_digitalinout_obj_t display_on;
39+
40+
uint32_t last_down_ticks_ms;
41+
42+
void board_init(void) {
43+
common_hal_digitalio_digitalinout_construct(&extcomin, &pin_P0_06);
44+
common_hal_digitalio_digitalinout_switch_to_output(&extcomin, true, DRIVE_MODE_PUSH_PULL);
45+
common_hal_digitalio_digitalinout_never_reset(&extcomin);
46+
47+
common_hal_digitalio_digitalinout_construct(&display_on, &pin_P0_07);
48+
common_hal_digitalio_digitalinout_switch_to_output(&display_on, true, DRIVE_MODE_PUSH_PULL);
49+
common_hal_digitalio_digitalinout_never_reset(&display_on);
50+
51+
sharpdisplay_framebuffer_obj_t *fb = &allocate_display_bus()->sharpdisplay;
52+
fb->base.type = &sharpdisplay_framebuffer_type;
53+
54+
busio_spi_obj_t *spi = &fb->inline_bus;
55+
common_hal_busio_spi_construct(spi, &pin_P0_26, &pin_P0_27, NULL, false);
56+
common_hal_busio_spi_never_reset(spi);
57+
58+
common_hal_sharpdisplay_framebuffer_construct(fb, spi, &pin_P0_05, 500000, 176, 176, true);
59+
60+
primary_display_t *display = allocate_display();
61+
framebufferio_framebufferdisplay_obj_t *self = &display->framebuffer_display;
62+
self->base.type = &framebufferio_framebufferdisplay_type;
63+
common_hal_framebufferio_framebufferdisplay_construct(self, fb, 0, true);
64+
}
65+
66+
bool board_requests_safe_mode(void) {
67+
return false;
68+
}
69+
70+
void reset_board(void) {
71+
nrf_gpio_cfg_input(17, NRF_GPIO_PIN_PULLUP);
72+
}
73+
74+
void board_deinit(void) {
75+
// common_hal_displayio_release_displays();
76+
}
77+
78+
void board_background_task(void) {
79+
if (!nrf_gpio_pin_read(17)) {
80+
if (last_down_ticks_ms == 0) {
81+
last_down_ticks_ms = supervisor_ticks_ms32();
82+
}
83+
} else {
84+
last_down_ticks_ms = 0;
85+
}
86+
// If the button isn't pressed, then feed the watchdog.
87+
if (last_down_ticks_ms == 0) {
88+
NRF_WDT->RR[0] = 0x6E524635;
89+
return;
90+
}
91+
// if the button has been pressed less than 5 seconds, then feed the watchdog.
92+
uint32_t now = supervisor_ticks_ms32();
93+
if (now - last_down_ticks_ms < 5000) {
94+
NRF_WDT->RR[0] = 0x6E524635;
95+
}
96+
// Don't feed the watchdog so that it'll expire and kick us to the bootloader.
97+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Glenn Ruben Bakke
7+
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#include "nrfx/hal/nrf_gpio.h"
29+
30+
#define MICROPY_HW_BOARD_NAME "Espruino Bangle.js 2"
31+
#define MICROPY_HW_MCU_NAME "nRF52840"
32+
33+
#define MICROPY_HW_LED_STATUS (&pin_P0_19)
34+
35+
#if SPI_FLASH_FILESYSTEM
36+
#define SPI_FLASH_MOSI_PIN &pin_P0_15
37+
#define SPI_FLASH_MISO_PIN &pin_P0_13
38+
#define SPI_FLASH_SCK_PIN &pin_P0_16
39+
#define SPI_FLASH_CS_PIN &pin_P0_14
40+
#endif
41+
42+
#define CIRCUITPY_BOOT_BUTTON (&pin_P0_17)
43+
44+
#define BOARD_HAS_32KHZ_XTAL (1)

0 commit comments

Comments
 (0)