diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index a33e09a..2a614db 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -17,9 +17,9 @@ jobs: uses: actions/upload-artifact@v3 with: name: firmware-RPi-Pico-W - path: software/lib/micropython/ports/rp2/build-TONBERRY_RPI_PICO_W/firmware.uf2 + path: software/build/firmware-*.uf2 - name: Upload firmware w/ filesystem uses: actions/upload-artifact@v3 with: name: firmware-RPi-Pico-W-with-fs - path: software/lib/micropython/ports/rp2/build-TONBERRY_RPI_PICO_W/firmware-filesystem-*.uf2 + path: software/build/firmware-filesystem-*.uf2 diff --git a/software/boards/RPI_PICO_W/manifest-Rev1.py b/software/boards/RPI_PICO_W/manifest-Rev1.py new file mode 100644 index 0000000..277458b --- /dev/null +++ b/software/boards/RPI_PICO_W/manifest-Rev1.py @@ -0,0 +1,3 @@ +include("manifest.py") + +module("hwconfig.py", "../../src/hwconfig_Rev1") diff --git a/software/boards/RPI_PICO_W/manifest-breadboard.py b/software/boards/RPI_PICO_W/manifest-breadboard.py new file mode 100644 index 0000000..6551a41 --- /dev/null +++ b/software/boards/RPI_PICO_W/manifest-breadboard.py @@ -0,0 +1,3 @@ +include("manifest.py") + +module("hwconfig.py", "../../src/hwconfig_breadboard") diff --git a/software/boards/RPI_PICO_W/manifest.py b/software/boards/RPI_PICO_W/manifest.py index db382dd..f8cb12a 100644 --- a/software/boards/RPI_PICO_W/manifest.py +++ b/software/boards/RPI_PICO_W/manifest.py @@ -15,3 +15,10 @@ module("microdot.py", "../../lib/microdot/src/microdot/") # TonberryPico modules module("audiocore.py", "../../modules/audiocore") module("rp2_neopixel.py", "../../modules") + +module("main.py", "../../src") +module("app.py", "../../src") +module("mp3player.py", "../../src") +module("webserver.py", "../../src") +package("utils", base_path="../../src") +package("nfc", base_path="../../src") diff --git a/software/build.sh b/software/build.sh index b373a8e..6fd759a 100755 --- a/software/build.sh +++ b/software/build.sh @@ -6,9 +6,6 @@ set -eu ( cd lib/micropython make -C mpy-cross -j "$(nproc)" - make -C ports/rp2 BOARD=TONBERRY_RPI_PICO_W BOARD_DIR="$TOPDIR"/boards/RPI_PICO_W clean - make -C ports/rp2 BOARD=TONBERRY_RPI_PICO_W BOARD_DIR="$TOPDIR"/boards/RPI_PICO_W \ - USER_C_MODULES="$TOPDIR"/modules/micropython.cmake -j "$(nproc)" # build tonberry specific unix port of micropython make -C ports/unix VARIANT_DIR="$TOPDIR"/boards/tonberry_unix clean @@ -19,31 +16,40 @@ set -eu make -j "$(nproc)" ) -PICOTOOL=picotool -if ! command -v $PICOTOOL >/dev/null 2>&1; then - echo "system picotool not found, checking SDK build dir" - PICOTOOL=lib/micropython/ports/rp2/build-TONBERRY_RPI_PICO_W/_deps/picotool-build/picotool - if ! command -v $PICOTOOL >/dev/null 2>&1; then - echo "No picotool found, exiting" - exit 1 - fi -fi BUILDDIR=lib/micropython/ports/rp2/build-TONBERRY_RPI_PICO_W/ +OUTDIR=$(pwd)/build +mkdir -p "$OUTDIR" FS_STAGE_DIR=$(mktemp -d) +mkdir "$FS_STAGE_DIR"/fs trap 'rm -rf $FS_STAGE_DIR' EXIT -for hwconfig in src/hwconfig_*.py; do +tools/mklittlefs/mklittlefs -p 256 -s 868352 -c "$FS_STAGE_DIR"/fs "$FS_STAGE_DIR"/filesystem.bin + +for hwconfig in boards/RPI_PICO_W/manifest-*.py; do hwconfig_base=$(basename "$hwconfig") - hwname=${hwconfig_base##hwconfig_} + hwname=${hwconfig_base##manifest-} hwname=${hwname%%.py} - find src/ -iname '*.py' \! -iname 'hwconfig_*.py' | cpio -pdm "$FS_STAGE_DIR" - cp "$hwconfig" "$FS_STAGE_DIR"/src/hwconfig.py - tools/mklittlefs/mklittlefs -p 256 -s 868352 -c "$FS_STAGE_DIR"/src $BUILDDIR/filesystem.bin + hwconfig_abs=$(realpath "$hwconfig") + ( cd lib/micropython + make -C ports/rp2 BOARD=TONBERRY_RPI_PICO_W BOARD_DIR="$TOPDIR"/boards/RPI_PICO_W clean + make -C ports/rp2 BOARD=TONBERRY_RPI_PICO_W BOARD_DIR="$TOPDIR"/boards/RPI_PICO_W \ + USER_C_MODULES="$TOPDIR"/modules/micropython.cmake \ + FROZEN_MANIFEST="$hwconfig_abs" -j "$(nproc)" + ) + PICOTOOL=picotool + if ! command -v $PICOTOOL >/dev/null 2>&1; then + echo "system picotool not found, checking SDK build dir" + PICOTOOL=lib/micropython/ports/rp2/build-TONBERRY_RPI_PICO_W/_deps/picotool-build/picotool + if ! command -v $PICOTOOL >/dev/null 2>&1; then + echo "No picotool found, exiting" + exit 1 + fi + fi truncate -s 2M $BUILDDIR/firmware-filesystem.bin dd if=$BUILDDIR/firmware.bin of=$BUILDDIR/firmware-filesystem.bin bs=1k - dd if=$BUILDDIR/filesystem.bin of=$BUILDDIR/firmware-filesystem.bin bs=1k seek=1200 - $PICOTOOL uf2 convert $BUILDDIR/firmware-filesystem.bin $BUILDDIR/firmware-filesystem-"$hwname".uf2 - rm -r "${FS_STAGE_DIR:?}"/* + dd if="$FS_STAGE_DIR"/filesystem.bin of=$BUILDDIR/firmware-filesystem.bin bs=1k seek=1200 + cp $BUILDDIR/firmware.uf2 "$OUTDIR"/firmware-"$hwname".uf2 + $PICOTOOL uf2 convert $BUILDDIR/firmware-filesystem.bin "$OUTDIR"/firmware-filesystem-"$hwname".uf2 done -echo "Output in $BUILDDIR/firmware.uf2" -echo "Images with filesystem in" ${BUILDDIR}firmware-filesystem-*.uf2 +echo "Output in" "${OUTDIR}"/firmware-*.uf2 +echo "Images with filesystem in" "${OUTDIR}"/firmware-filesystem-*.uf2 diff --git a/software/flash.sh b/software/flash.sh index 459db12..bea671a 100755 --- a/software/flash.sh +++ b/software/flash.sh @@ -2,6 +2,8 @@ set -eu +TOPDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + check_command() { name=$1 @@ -16,7 +18,7 @@ check_command lsusb check_command picotool DEVICEPATH=/dev/disk/by-label/RPI-RP2 -IMAGEPATH=lib/micropython/ports/rp2/build-TONBERRY_RPI_PICO_W/ +IMAGEPATH=${TOPDIR}/build REVISION=Rev1 flash_via_mountpoint() @@ -83,7 +85,7 @@ if [ $# -gt 0 ]; then usage fi -IMAGEFILE="$IMAGEPATH"/firmware-filesystem-$REVISION.uf2 +IMAGEFILE="$IMAGEPATH"/firmware-$REVISION.uf2 if [ "$FLASH_VIA_MOUNTPOINT" -eq 0 ]; then flash_via_picotool diff --git a/software/src/hwconfig_Rev1.py b/software/src/hwconfig_Rev1/hwconfig.py similarity index 100% rename from software/src/hwconfig_Rev1.py rename to software/src/hwconfig_Rev1/hwconfig.py diff --git a/software/src/hwconfig_breadboard.py b/software/src/hwconfig_breadboard/hwconfig.py similarity index 100% rename from software/src/hwconfig_breadboard.py rename to software/src/hwconfig_breadboard/hwconfig.py diff --git a/software/src/led_test.py b/software/src/led_test.py deleted file mode 100644 index 0674460..0000000 --- a/software/src/led_test.py +++ /dev/null @@ -1,58 +0,0 @@ -# SPDX-License-Identifier: MIT -# Copyright (c) 2024 Matthias Blankertz - -# Run with mpremote.py run src/led_test.py - -from machine import Pin -from math import pi, sin, pow -from micropython import const -from rp2_neopixel import NeoPixel -from time import sleep, ticks_ms -import asyncio - -pin = Pin.board.GP16 -leds = const(10) -brightness = 0.5 - -np = NeoPixel(pin, leds) - -# test fill and write - -print("LEDs should now turn red") -np.fill((255, 0, 0)) -np.write() -sleep(1) - -print("LEDs should now turn green") -np.fill((0, 255, 0)) -np.write() -sleep(1) - -print("LEDs should now turn blue") -np.fill((0, 0, 255)) -np.write() -sleep(1) - - -# test async -def gamma(value, X=2.2): - return min(max(int(brightness * pow(value / 255.0, X) * 255.0 + 0.5), 0), 255) - - -async def rainbow(np, period=10): - count = 0.0 - while True: - for i in range(leds): - ofs = (count + i) % leds - np[i] = (gamma((sin(ofs / leds * 2 * pi) + 1) * 127), - gamma((sin(ofs / leds * 2 * pi + 2/3*pi) + 1) * 127), - gamma((sin(ofs / leds * 2 * pi + 4/3*pi) + 1) * 127)) - count += 0.2 - before = ticks_ms() - await np.async_write() - now = ticks_ms() - if before + 20 > now: - await asyncio.sleep_ms(20 - (now - before)) - -print("LEDs should now start rainbowing") -asyncio.run(rainbow(np)) diff --git a/software/src/mfrc522_test.py b/software/src/mfrc522_test.py deleted file mode 100644 index 2144183..0000000 --- a/software/src/mfrc522_test.py +++ /dev/null @@ -1,73 +0,0 @@ -from mfrc522 import MFRC522 -import asyncio -import time - -delay_sum = 0 -delay_count = 0 -max_delay = 0 - - -async def latency_test(): - global delay_sum - global delay_count - global max_delay - global min_delay - min_delay = 0xffffffff - await asyncio.sleep_ms(1) - while True: - for _ in range(2000): - before = time.ticks_us() - await asyncio.sleep(0) - after = time.ticks_us() - delay = after - before - delay_sum += delay - delay_count += 1 - if delay > max_delay: - max_delay = delay - if delay < min_delay: - min_delay = delay - await asyncio.sleep_ms(1) - print(f"delay (min / max / avg) [µs]: ({min_delay} / {max_delay} / {delay/delay_sum})") - - -def uid_to_string(uid: list): - return '0x' + ''.join(f'{i:02x}' for i in uid) - - -async def get_tag_uid(reader: MFRC522, poll_interval_ms: int = 50) -> list: - ''' - The maximum measured delay with poll_interval_ms=50 and a reader with tocard_retries=5 is - 15.9 ms: - delay (min / max / avg) [µs]: (360 / 15945 / 1.892923e-06) - - The maximum measured delay dropped to 11.6 ms by setting tocard_retries=1: - delay (min / max / avg) [µs]: (368 / 11696 / 6.204211e-06) - ''' - while True: - reader.init() - - # For now we omit the tag type - (stat, _) = reader.request(reader.REQIDL) - if stat == reader.OK: - (stat, uid) = reader.SelectTagSN() - if stat == reader.OK: - print(f"uid={uid_to_string(uid)}") - - await asyncio.sleep_ms(poll_interval_ms) - - -def main(): - reader = MFRC522(spi_id=1, sck=10, miso=12, mosi=11, cs=13, rst=9, tocard_retries=1) - - print("") - print("Please place card on reader") - print("") - - asyncio.create_task(get_tag_uid(reader)) - asyncio.create_task(latency_test()) - - asyncio.get_event_loop().run_forever() - - -if __name__ == "__main__": - main() diff --git a/software/src/test.py b/software/src/test.py deleted file mode 100644 index 7b09b82..0000000 --- a/software/src/test.py +++ /dev/null @@ -1,113 +0,0 @@ -# SPDX-License-Identifier: MIT -# Copyright (c) 2024-2025 Matthias Blankertz - -import aiorepl -import asyncio -import machine -import micropython -import os -import time -from machine import Pin -from math import pi, sin, pow -from micropython import const - -# Own modules -from audiocore import Audiocore -from mp3player import MP3Player -from rp2_neopixel import NeoPixel -from rp2_sd import SDCard - -micropython.alloc_emergency_exception_buf(100) - -leds = const(10) -brightness = 0.5 - - -def gamma(value, X=2.2): - return min(max(int(brightness * pow(value / 255.0, X) * 255.0 + 0.5), 0), 255) - - -async def rainbow(np, period=10): - count = 0.0 - while True: - for i in range(leds): - ofs = (count + i) % leds - np[i] = (gamma((sin(ofs / leds * 2 * pi) + 1) * 127), - gamma((sin(ofs / leds * 2 * pi + 2/3*pi) + 1) * 127), - gamma((sin(ofs / leds * 2 * pi + 4/3*pi) + 1) * 127)) - count += 0.2 - before = time.ticks_ms() - await np.async_write() - now = time.ticks_ms() - if before + 20 > now: - await asyncio.sleep_ms(20 - (now - before)) - - -# Set 8 mA drive strength and fast slew rate -machine.mem32[0x4001c004 + 6*4] = 0x67 -machine.mem32[0x4001c004 + 7*4] = 0x67 -machine.mem32[0x4001c004 + 8*4] = 0x67 - - -def list_sd(): - try: - sd = SDCard(mosi=Pin(3), miso=Pin(4), sck=Pin(2), ss=Pin(5), baudrate=15000000) - except OSError: - for i in range(leds): - np[i] = (255, 0, 0) - np.write() - return - try: - os.mount(sd, '/sd') - print(os.listdir(b'/sd')) - except OSError as ex: - print(f"{ex}") - - -delay_sum = 0 -delay_count = 0 -max_delay = 0 - - -async def latency_test(): - global delay_sum - global delay_count - global max_delay - await asyncio.sleep_ms(1) - while True: - for _ in range(2000): - before = time.ticks_us() - await asyncio.sleep(0) - after = time.ticks_us() - delay = after - before - delay_sum += delay - delay_count += 1 - if delay > max_delay: - max_delay = delay - await asyncio.sleep_ms(1) - print(f"Max delay {max_delay} us, average {delay/delay_sum} us") - -pin = Pin.board.GP16 -np = NeoPixel(pin, leds) - -# Test SD card -list_sd() - -# Test NeoPixel -asyncio.create_task(rainbow(np)) - -# Test audio -audioctx = Audiocore(Pin(8), Pin(6)) - -player = MP3Player(audioctx) - -# high prio for proc 1 -machine.mem32[0x40030000 + 0x00] = 0x10 - -testfiles = [b'/sd/' + name for name in os.listdir(b'/sd') if name.endswith(b'mp3')] -player.set_playlist(testfiles) -asyncio.create_task(player.task()) - - -asyncio.create_task(aiorepl.task({'player': player})) -asyncio.get_event_loop().run_forever()