From f50ce819cff50e06251772a6b8dc2cf05f5d389f Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 16 Sep 2024 15:42:56 +0100 Subject: [PATCH] Experimental: Add Badger 2350. This board does not exist in any meaningful sense. Don't get excited. Actually, do get excited- we're cooking up something *better.* --- .github/workflows/micropython.yml | 35 ++- firmware/PIMORONI_BADGER2350/board.json | 17 ++ .../PIMORONI_BADGER2350/lib/badger2040.py | 205 ++++++++++++++++++ firmware/PIMORONI_BADGER2350/lib/badger_os.py | 186 ++++++++++++++++ firmware/PIMORONI_BADGER2350/manifest.py | 3 + .../PIMORONI_BADGER2350/micropython.cmake | 69 ++++++ .../PIMORONI_BADGER2350/mpconfigboard.cmake | 11 + firmware/PIMORONI_BADGER2350/mpconfigboard.h | 2 + .../PIMORONI_BADGER2350/pimoroni_badger2350.h | 121 +++++++++++ firmware/PIMORONI_BADGER2350/pins.csv | 35 +++ firmware/PIMORONI_BADGER2350/uf2-manifest.txt | 18 ++ firmware/modules/wakeup/wakeup.c | 36 ++- 12 files changed, 718 insertions(+), 20 deletions(-) create mode 100644 firmware/PIMORONI_BADGER2350/board.json create mode 100644 firmware/PIMORONI_BADGER2350/lib/badger2040.py create mode 100644 firmware/PIMORONI_BADGER2350/lib/badger_os.py create mode 100644 firmware/PIMORONI_BADGER2350/manifest.py create mode 100644 firmware/PIMORONI_BADGER2350/micropython.cmake create mode 100644 firmware/PIMORONI_BADGER2350/mpconfigboard.cmake create mode 100644 firmware/PIMORONI_BADGER2350/mpconfigboard.h create mode 100644 firmware/PIMORONI_BADGER2350/pimoroni_badger2350.h create mode 100644 firmware/PIMORONI_BADGER2350/pins.csv create mode 100644 firmware/PIMORONI_BADGER2350/uf2-manifest.txt diff --git a/.github/workflows/micropython.yml b/.github/workflows/micropython.yml index 06417d9..0d33cda 100644 --- a/.github/workflows/micropython.yml +++ b/.github/workflows/micropython.yml @@ -7,9 +7,10 @@ on: types: [created] env: - MICROPYTHON_VERSION: v1.23.0 - PIMORONI_PICO_VERSION: v1.23.0-1 - WORKFLOW_VERSION: v3 + MICROPYTHON_FLAVOUR: pimoroni/micropython + MICROPYTHON_VERSION: feature/psram + PIMORONI_PICO_VERSION: ci/micropython-edge + WORKFLOW_VERSION: v5 jobs: deps: @@ -30,7 +31,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' uses: actions/checkout@v4 with: - repository: micropython/micropython + repository: ${{env.MICROPYTHON_FLAVOUR}} ref: ${{env.MICROPYTHON_VERSION}} submodules: false # MicroPython submodules are hideously broken path: micropython @@ -58,6 +59,7 @@ jobs: needs: deps name: Build ${{matrix.name}} runs-on: ubuntu-20.04 + continue-on-error: true strategy: matrix: include: @@ -67,6 +69,9 @@ jobs: - name: Badger 2040 W shortname: badger2040w board: PIMORONI_BADGER2040W + - name: Badger 2350 + shortname: badger2350 + board: PIMORONI_BADGER2350 env: RELEASE_FILE: pimoroni-${{matrix.shortname}}-${{github.event.release.tag_name || github.sha}}-micropython.uf2 @@ -110,34 +115,26 @@ jobs: uses: actions/checkout@v4 with: repository: gadgetoid/py_decl - ref: v0.0.1 + ref: v0.0.2 path: py_decl # Check out dir2u2f - uses: actions/checkout@v4 with: repository: gadgetoid/dir2uf2 - ref: v0.0.5 + ref: v0.0.7 path: dir2uf2 - # HACK: Patch startup overclock into Pico SDK - - name: "HACK: Startup Overclock Patch" - shell: bash - working-directory: micropython/lib/pico-sdk - run: | - git apply "${{env.FIRMWARE_DIR}}/startup_overclock.patch" - - - name: "HACK: MicroPython out of tree board pins.csv fix" - shell: bash - working-directory: micropython - run: | - git apply "${{env.FIRMWARE_DIR}}/932f76c6ba64c5a3e68de3324556d9979f09303b.patch" + - name: Install Arm GNU Toolchain (arm-none-eabi-gcc) + uses: carlosperate/arm-none-eabi-gcc-action@v1 + with: + release: '9-2020-q2' # Install apt packages - name: Install CCache & Compiler shell: bash run: - sudo apt update && sudo apt install ccache gcc-arm-none-eabi + sudo apt update && sudo apt install ccache # Build firmware - name: Configure MicroPython diff --git a/firmware/PIMORONI_BADGER2350/board.json b/firmware/PIMORONI_BADGER2350/board.json new file mode 100644 index 0000000..1034a11 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/board.json @@ -0,0 +1,17 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "296*128 e-Ink", + "Buttons" + ], + "images": [ + ], + "mcu": "rp2350", + "product": "Badger2350 (2MiB)", + "thumbnail": "", + "url": "", + "vendor": "Pimoroni" +} diff --git a/firmware/PIMORONI_BADGER2350/lib/badger2040.py b/firmware/PIMORONI_BADGER2350/lib/badger2040.py new file mode 100644 index 0000000..78af8d1 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/lib/badger2040.py @@ -0,0 +1,205 @@ +import machine +import micropython +from picographics import PicoGraphics, DISPLAY_INKY_PACK +import time +import wakeup +import cppmem + + +BUTTON_DOWN = 11 +BUTTON_A = 12 +BUTTON_B = 13 +BUTTON_C = 14 +BUTTON_UP = 15 +BUTTON_USER = 23 + +BUTTON_MASK = 0b11111 << 11 + +SYSTEM_VERY_SLOW = 0 +SYSTEM_SLOW = 1 +SYSTEM_NORMAL = 2 +SYSTEM_FAST = 3 +SYSTEM_TURBO = 4 + +UPDATE_NORMAL = 0 +UPDATE_MEDIUM = 1 +UPDATE_FAST = 2 +UPDATE_TURBO = 3 + +LED = 25 +ENABLE_3V3 = 10 +BUSY = 26 + +WIDTH = 296 +HEIGHT = 128 + +SYSTEM_FREQS = [ + 4000000, + 12000000, + 48000000, + 133000000, + 250000000 +] + +BUTTONS = { + BUTTON_DOWN: machine.Pin(BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN), + BUTTON_A: machine.Pin(BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN), + BUTTON_B: machine.Pin(BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN), + BUTTON_C: machine.Pin(BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN), + BUTTON_UP: machine.Pin(BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN), + BUTTON_USER: machine.Pin(BUTTON_USER, machine.Pin.IN, machine.Pin.PULL_UP), +} + +WAKEUP_MASK = 0 + +enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT) +enable.on() + +cppmem.set_mode(cppmem.MICROPYTHON) + + +def is_wireless(): + return False + + +def woken_by_rtc(): + return False # Badger 2040 does not include an RTC + + +def woken_by_button(): + return wakeup.get_gpio_state() & BUTTON_MASK > 0 + + +def pressed_to_wake(button): + return wakeup.get_gpio_state() & (1 << button) > 0 + + +def reset_pressed_to_wake(): + wakeup.reset_gpio_state() + + +def pressed_to_wake_get_once(button): + global WAKEUP_MASK + if button == BUTTON_USER: + return False + result = (wakeup.get_gpio_state() & ~WAKEUP_MASK & (1 << button)) > 0 + WAKEUP_MASK |= (1 << button) + return result + + +def system_speed(speed): + try: + machine.freq(SYSTEM_FREQS[speed]) + except IndexError: + pass + + +def turn_on(): + enable.on() + + +def turn_off(): + time.sleep(0.05) + enable.off() + # Simulate an idle state on USB power by blocking + # until a button event + while True: + for pin, button in BUTTONS.items(): + if pin == BUTTON_USER: + if not button.value(): + return + continue + if button.value(): + return + + +def sleep_for(minutes=None): + raise RuntimeError("Badger 2040 does not include an RTC.") + + +pico_rtc_to_pcf = pcf_to_pico_rtc = sleep_for + + +class Badger2040(): + def __init__(self): + self.display = PicoGraphics(DISPLAY_INKY_PACK) + self._led = machine.PWM(machine.Pin(LED)) + self._led.freq(1000) + self._led.duty_u16(0) + self._update_speed = 0 + + def __getattr__(self, item): + # Glue to redirect calls to PicoGraphics + return getattr(self.display, item) + + def update(self): + t_start = time.ticks_ms() + self.display.update() + t_elapsed = time.ticks_ms() - t_start + + delay_ms = [4700, 2600, 900, 250][self._update_speed] + + if t_elapsed < delay_ms: + time.sleep((delay_ms - t_elapsed) / 1000) + + def set_update_speed(self, speed): + self.display.set_update_speed(speed) + self._update_speed = speed + + def led(self, brightness): + brightness = max(0, min(255, brightness)) + self._led.duty_u16(int(brightness * 256)) + + def invert(self, invert): + raise RuntimeError("Display invert not supported in PicoGraphics.") + + def thickness(self, thickness): + raise RuntimeError("Thickness not supported in PicoGraphics.") + + def halt(self): + turn_off() + + def keepalive(self): + turn_on() + + def pressed(self, button): + return BUTTONS[button].value() == (0 if button == BUTTON_USER else 1) or pressed_to_wake_get_once(button) + + def pressed_any(self): + for pin, button in BUTTONS.items(): + if pin == BUTTON_USER: + if not button.value(): + return True + continue + if button.value(): + return True + return False + + @micropython.native + def icon(self, data, index, data_w, icon_size, x, y): + s_x = (index * icon_size) % data_w + s_y = int((index * icon_size) / data_w) + + for o_y in range(icon_size): + for o_x in range(icon_size): + o = ((o_y + s_y) * data_w) + (o_x + s_x) + bm = 0b10000000 >> (o & 0b111) + if data[o >> 3] & bm: + self.display.pixel(x + o_x, y + o_y) + + def image(self, data, w, h, x, y): + for oy in range(h): + row = data[oy] + for ox in range(w): + if row & 0b1 == 0: + self.display.pixel(x + ox, y + oy) + row >>= 1 + + def isconnected(self): + return False + + def ip_address(self): + return (0, 0, 0, 0) + + def connect(self): + pass diff --git a/firmware/PIMORONI_BADGER2350/lib/badger_os.py b/firmware/PIMORONI_BADGER2350/lib/badger_os.py new file mode 100644 index 0000000..ce4cc19 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/lib/badger_os.py @@ -0,0 +1,186 @@ +import os +import gc +import time +import json +import machine +import badger2040 + + +def get_battery_level(): + return 0 + # Battery measurement + vbat_adc = machine.ADC(badger2040.PIN_BATTERY) + vref_adc = machine.ADC(badger2040.PIN_1V2_REF) + vref_en = machine.Pin(badger2040.PIN_VREF_POWER) + vref_en.init(machine.Pin.OUT) + vref_en.value(0) + + # Enable the onboard voltage reference + vref_en.value(1) + + # Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries + vdd = 1.24 * (65535 / vref_adc.read_u16()) + vbat = ( + (vbat_adc.read_u16() / 65535) * 3 * vdd + ) # 3 in this is a gain, not rounding of 3.3V + + # Disable the onboard voltage reference + vref_en.value(0) + + # Convert the voltage to a level to display onscreen + return vbat + + +def get_disk_usage(): + # f_bfree and f_bavail should be the same? + # f_files, f_ffree, f_favail and f_flag are unsupported. + f_bsize, f_frsize, f_blocks, f_bfree, _, _, _, _, _, f_namemax = os.statvfs("/") + + f_total_size = f_frsize * f_blocks + f_total_free = f_bsize * f_bfree + f_total_used = f_total_size - f_total_free + + f_used = 100 / f_total_size * f_total_used + f_free = 100 / f_total_size * f_total_free + + return f_total_size, f_used, f_free + + +def state_running(): + state = {"running": "launcher"} + state_load("launcher", state) + return state["running"] + + +def state_clear_running(): + running = state_running() + state_modify("launcher", {"running": "launcher"}) + return running != "launcher" + + +def state_set_running(app): + state_modify("launcher", {"running": app}) + + +def state_launch(): + app = state_running() + if app is not None and app != "launcher": + launch(app) + + +def state_delete(app): + try: + os.remove("/state/{}.json".format(app)) + except OSError: + pass + + +def state_save(app, data): + try: + with open("/state/{}.json".format(app), "w") as f: + f.write(json.dumps(data)) + f.flush() + except OSError: + import os + try: + os.stat("/state") + except OSError: + os.mkdir("/state") + state_save(app, data) + + +def state_modify(app, data): + state = {} + state_load(app, state) + state.update(data) + state_save(app, state) + + +def state_load(app, defaults): + try: + data = json.loads(open("/state/{}.json".format(app), "r").read()) + if type(data) is dict: + defaults.update(data) + return True + except (OSError, ValueError): + pass + + state_save(app, defaults) + return False + + +def launch(file): + state_set_running(file) + + gc.collect() + + button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN) + button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN) + + def quit_to_launcher(pin): + if button_a.value() and button_c.value(): + machine.reset() + + button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=quit_to_launcher) + button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=quit_to_launcher) + + try: + __import__(file) + + except ImportError: + # If the app doesn't exist, notify the user + warning(None, f"Could not launch: {file}") + time.sleep(4.0) + except Exception as e: + # If the app throws an error, catch it and display! + print(e) + warning(None, str(e)) + time.sleep(4.0) + + # If the app exits or errors, do not relaunch! + state_clear_running() + machine.reset() # Exit back to launcher + + +# Draw an overlay box with a given message within it +def warning(display, message, width=badger2040.WIDTH - 20, height=badger2040.HEIGHT - 20, line_spacing=20, text_size=0.6): + print(message) + + if display is None: + display = badger2040.Badger2040() + display.led(128) + + # Draw a light grey background + display.set_pen(12) + display.rectangle((badger2040.WIDTH - width) // 2, (badger2040.HEIGHT - height) // 2, width, height) + + width -= 20 + height -= 20 + + display.set_pen(15) + display.rectangle((badger2040.WIDTH - width) // 2, (badger2040.HEIGHT - height) // 2, width, height) + + # Take the provided message and split it up into + # lines that fit within the specified width + words = message.split(" ") + + lines = [] + current_line = "" + for word in words: + if display.measure_text(current_line + word + " ", text_size) < width: + current_line += word + " " + else: + lines.append(current_line.strip()) + current_line = word + " " + lines.append(current_line.strip()) + + display.set_pen(0) + + # Display each line of text from the message, centre-aligned + num_lines = len(lines) + for i in range(num_lines): + length = display.measure_text(lines[i], text_size) + current_line = (i * line_spacing) - ((num_lines - 1) * line_spacing) // 2 + display.text(lines[i], (badger2040.WIDTH - length) // 2, (badger2040.HEIGHT // 2) + current_line, badger2040.WIDTH, text_size) + + display.update() diff --git a/firmware/PIMORONI_BADGER2350/manifest.py b/firmware/PIMORONI_BADGER2350/manifest.py new file mode 100644 index 0000000..9213643 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/manifest.py @@ -0,0 +1,3 @@ +include("$(PORT_DIR)/boards/manifest.py") + +freeze("lib/") \ No newline at end of file diff --git a/firmware/PIMORONI_BADGER2350/micropython.cmake b/firmware/PIMORONI_BADGER2350/micropython.cmake new file mode 100644 index 0000000..5cc54d1 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/micropython.cmake @@ -0,0 +1,69 @@ +set(PIMORONI_PICO_PATH ../../../../pimoroni-pico) +include(${CMAKE_CURRENT_LIST_DIR}/../pimoroni_pico_import.cmake) + +include_directories(${PIMORONI_PICO_PATH}/micropython) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../") +list(APPEND CMAKE_MODULE_PATH "${PIMORONI_PICO_PATH}/micropython") +list(APPEND CMAKE_MODULE_PATH "${PIMORONI_PICO_PATH}/micropython/modules") + +# Enable support for string_view (for PicoGraphics) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +# Essential +include(pimoroni_i2c/micropython) +include(pimoroni_bus/micropython) + +# Pico Graphics Essential +include(hershey_fonts/micropython) +include(bitmap_fonts/micropython) +include(picographics/micropython) + +# Pico Graphics Extra +include(jpegdec/micropython) +include(pngdec/micropython) +include(qrcode/micropython/micropython) + +# Sensors & Breakouts +include(micropython-common-breakouts) +# TODO: Fix datetime issues, only used by W anyway?? +# include(pcf85063a/micropython) + +# Utility +include(adcfft/micropython) + +# Use our LOCAL wakeup module from firmware/modules/wakeup +#include(firmware/modules/wakeup/micropython) +#target_compile_definitions(usermod_wakeup INTERFACE +# -DWAKEUP_PIN_MASK=0b10000000000000010000000000 +# -DWAKEUP_PIN_DIR=0b10000000000000010000000000 +# -DWAKEUP_PIN_VALUE=0b10000000000000010000000000 +#) + +# Note: cppmem is *required* for C++ code to function on MicroPython +# it redirects `malloc` and `free` calls to MicroPython's heap +include(cppmem/micropython) + +# LEDs & Matrices +include(plasma/micropython) + +# Servos & Motors +include(pwm/micropython) +include(servo/micropython) +include(encoder/micropython) +include(motor/micropython) + +# version.py and pimoroni.py +include(modules_py/modules_py) + +# TODO: Use `include(micropython-disable-exceptions)` +# Do not include stack unwinding & exception handling for C++ user modules +target_compile_definitions(usermod INTERFACE PICO_CXX_ENABLE_EXCEPTIONS=0) +target_compile_options(usermod INTERFACE $<$: + -fno-exceptions + -fno-unwind-tables + -fno-rtti + -fno-use-cxa-atexit +>) +target_link_options(usermod INTERFACE -specs=nano.specs) diff --git a/firmware/PIMORONI_BADGER2350/mpconfigboard.cmake b/firmware/PIMORONI_BADGER2350/mpconfigboard.cmake new file mode 100644 index 0000000..d020e0b --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/mpconfigboard.cmake @@ -0,0 +1,11 @@ +# cmake file for Pimoroni Badger 2350 +set(PICO_BOARD "pimoroni_badger2350") +set(PICO_PLATFORM "rp2350") + +# Make sure we find pimoroni_badger2350.h (PICO_BOARD) in the current dir +set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}) + +# Board specific version of the frozen manifest +set(MICROPY_FROZEN_MANIFEST ${CMAKE_CURRENT_LIST_DIR}/manifest.py) + +set(MICROPY_C_HEAP_SIZE 4096) \ No newline at end of file diff --git a/firmware/PIMORONI_BADGER2350/mpconfigboard.h b/firmware/PIMORONI_BADGER2350/mpconfigboard.h new file mode 100644 index 0000000..955b268 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Pimoroni Badger2350 4MB" +#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (1 * 1024 * 1024)) diff --git a/firmware/PIMORONI_BADGER2350/pimoroni_badger2350.h b/firmware/PIMORONI_BADGER2350/pimoroni_badger2350.h new file mode 100644 index 0000000..92b1c7d --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/pimoroni_badger2350.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +// ----------------------------------------------------- +// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO +// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES +// ----------------------------------------------------- + +// pico_cmake_set PICO_PLATFORM=rp2350 + +#ifndef _BOARDS_PIMORONI_BADGER2350_H +#define _BOARDS_PIMORONI_BADGER2350_H + +// For board detection +#define PIMORONI_BADGER2350 + +// --- BOARD SPECIFIC --- +#define BADGER2350_UART 0 +#define BADGER2350_TX_PIN 0 +#define BADGER2350_RX_PIN 1 + +#define BADGER2350_I2C 0 +#define BADGER2350_INT_PIN 3 +#define BADGER2350_SDA_PIN 4 +#define BADGER2350_SCL_PIN 5 + +#define BADGER2350_3V3_EN_PIN 10 + +#define BADGER2350_SW_DOWN_PIN 11 +#define BADGER2350_SW_A_PIN 12 +#define BADGER2350_SW_B_PIN 13 +#define BADGER2350_SW_C_PIN 14 +#define BADGER2350_SW_UP_PIN 15 + +#define BADGER2350_INKY_SPI 0 +#define BADGER2350_INKY_MISO_PIN 16 +#define BADGER2350_INKY_CSN_PIN 17 +#define BADGER2350_INKY_SCK_PIN 18 +#define BADGER2350_INKY_MOSI_PIN 19 +#define BADGER2350_INKY_DC_PIN 20 +#define BADGER2350_INKY_RESET_PIN 21 +#define BADGER2350_INKY_BUSY_PIN 26 + +#define BADGER2350_USER_SW_PIN 23 +#define BADGER2350_USER_LED_PIN 25 + +#define BADGER2350_VBUS_DETECT_PIN 24 +#define BADGER2350_VREF_POWER_PIN 27 +#define BADGER2350_1V2_REF_PIN 28 +#define BADGER2350_BAT_SENSE_PIN 29 + +// --- RP2350 VARIANT --- +#define PICO_RP2350A 1 + +// --- UART --- +#ifndef PICO_DEFAULT_UART +#define PICO_DEFAULT_UART BADGER2350_UART +#endif + +#ifndef PICO_DEFAULT_UART_TX_PIN +#define PICO_DEFAULT_UART_TX_PIN BADGER2350_TX_PIN +#endif + +#ifndef PICO_DEFAULT_UART_RX_PIN +#define PICO_DEFAULT_UART_RX_PIN BADGER2350_RX_PIN +#endif + +// --- LED --- +#ifndef PICO_DEFAULT_LED_PIN +#define PICO_DEFAULT_LED_PIN BADGER2350_USER_LED_PIN +#endif +// no PICO_DEFAULT_WS2812_PIN + +// --- I2C --- +#ifndef PICO_DEFAULT_I2C +#define PICO_DEFAULT_I2C BADGER2350_I2C +#endif +#ifndef PICO_DEFAULT_I2C_SDA_PIN +#define PICO_DEFAULT_I2C_SDA_PIN BADGER2350_SDA_PIN +#endif +#ifndef PICO_DEFAULT_I2C_SCL_PIN +#define PICO_DEFAULT_I2C_SCL_PIN BADGER2350_SCL_PIN +#endif + +// --- SPI --- +#ifndef PICO_DEFAULT_SPI +#define PICO_DEFAULT_SPI BADGER2350_INKY_SPI +#endif +#ifndef PICO_DEFAULT_SPI_SCK_PIN +#define PICO_DEFAULT_SPI_SCK_PIN BADGER2350_INKY_SCK_PIN +#endif +#ifndef PICO_DEFAULT_SPI_TX_PIN +#define PICO_DEFAULT_SPI_TX_PIN BADGER2350_INKY_MOSI_PIN +#endif +#ifndef PICO_DEFAULT_SPI_RX_PIN +#define PICO_DEFAULT_SPI_RX_PIN BADGER2350_INKY_MISO_PIN +#endif +#ifndef PICO_DEFAULT_SPI_CSN_PIN +#define PICO_DEFAULT_SPI_CSN_PIN BADGER2350_INKY_CSN_PIN +#endif + +// --- FLASH --- +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 2 +#endif + +// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (2 * 1024 * 1024) +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024) +#endif + +#ifndef PICO_RP2350_A2_SUPPORTED +#define PICO_RP2350_A2_SUPPORTED 1 +#endif + +#endif \ No newline at end of file diff --git a/firmware/PIMORONI_BADGER2350/pins.csv b/firmware/PIMORONI_BADGER2350/pins.csv new file mode 100644 index 0000000..75f0d4f --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/pins.csv @@ -0,0 +1,35 @@ +GP0,GPIO0 +GP1,GPIO1 +GP2,GPIO2 +GP3,GPIO3 +GP4,GPIO4 +GP5,GPIO5 +GP6,GPIO6 +GP7,GPIO7 +GP8,GPIO8 +GP9,GPIO9 +GP10,GPIO10 +GP11,GPIO11 +GP12,GPIO12 +GP13,GPIO13 +GP14,GPIO14 +GP15,GPIO15 +GP16,GPIO16 +GP17,GPIO17 +GP18,GPIO18 +GP19,GPIO19 +GP20,GPIO20 +GP21,GPIO21 +GP22,GPIO22 +GP25,GPIO25 +GP26,GPIO26 +GP27,GPIO27 +GP28,GPIO28 +DOWN,GPIO11 +A,GPIO12 +B,GPIO13 +C,GPIO14 +UP,GPIO15 +EN_3V3,GPIO10 +LED,GPIO25 +BUSY,GPIO26 \ No newline at end of file diff --git a/firmware/PIMORONI_BADGER2350/uf2-manifest.txt b/firmware/PIMORONI_BADGER2350/uf2-manifest.txt new file mode 100644 index 0000000..74e9cb9 --- /dev/null +++ b/firmware/PIMORONI_BADGER2350/uf2-manifest.txt @@ -0,0 +1,18 @@ +launcher.py +main.py +examples/*.png +examples/badge.py +examples/clock.py +examples/ebook.py +examples/fonts.py +examples/help.py +examples/image.py +examples/info.py +examples/list.py +examples/qrgen.py +images/*.jpg +images/*.txt +badges/*.txt +badges/*.jpg +books/*.txt +icons/*.png \ No newline at end of file diff --git a/firmware/modules/wakeup/wakeup.c b/firmware/modules/wakeup/wakeup.c index 22b96fd..e06ca1e 100644 --- a/firmware/modules/wakeup/wakeup.c +++ b/firmware/modules/wakeup/wakeup.c @@ -1,4 +1,25 @@ #include "wakeup.h" +#include "hardware/gpio.h" +#include "wakeup.config.hpp" +#include "pico/runtime_init.h" + + +uint32_t runtime_wakeup_gpio_state = 0; + +// Pins to toggle on wakeup +#ifndef WAKEUP_PIN_MASK +#define WAKEUP_PIN_MASK ((0b1 << 2) | (0b1 << 6)) +#endif + +// Direction +#ifndef WAKEUP_PIN_DIR +#define WAKEUP_PIN_DIR ((0b1 << 2) | (0b1 << 6)) +#endif + +// Value +#ifndef WAKEUP_PIN_VALUE +#define WAKEUP_PIN_VALUE ((0b1 << 2) | (0b1 << 6)) +#endif static MP_DEFINE_CONST_FUN_OBJ_0(Wakeup_get_gpio_state_obj, Wakeup_get_gpio_state); static MP_DEFINE_CONST_FUN_OBJ_0(Wakeup_reset_gpio_state_obj, Wakeup_reset_gpio_state); @@ -19,4 +40,17 @@ const mp_obj_module_t wakeup_user_cmodule = { MP_REGISTER_MODULE(MP_QSTR_wakeup, wakeup_user_cmodule, MODULE_WAKEUP_ENABLED); #else MP_REGISTER_MODULE(MP_QSTR_wakeup, wakeup_user_cmodule); -#endif \ No newline at end of file +#endif + +void runtime_init_latch(void) { + runtime_wakeup_gpio_state = gpio_get_all(); + + gpio_init_mask(WAKEUP_PIN_MASK); + gpio_set_dir_masked(WAKEUP_PIN_MASK, WAKEUP_PIN_DIR); + gpio_put_masked(WAKEUP_PIN_MASK, WAKEUP_PIN_VALUE); +}; + +// After runtime_init_early_resets, PICO_RUNTIME_INIT_EARLY_RESETS ? +PICO_RUNTIME_INIT_FUNC_HW(runtime_init_latch, "00101"); +// Too early? +// PICO_RUNTIME_INIT_FUNC_HW(runtime_init_latch, PICO_RUNTIME_INIT_EARLIEST); \ No newline at end of file