Merge pull request 'freeze-python-code' (#52) from freeze-python-code into main
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m38s
Check code formatting / Check-C-Format (push) Successful in 39m39s
Check code formatting / Check-Python-Flake8 (push) Successful in 12s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m38s
Check code formatting / Check-C-Format (push) Successful in 39m39s
Check code formatting / Check-Python-Flake8 (push) Successful in 12s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s
Reviewed-on: #52 Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de>
This commit was merged in pull request #52.
This commit is contained in:
@@ -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
|
||||
|
||||
3
software/boards/RPI_PICO_W/manifest-Rev1.py
Normal file
3
software/boards/RPI_PICO_W/manifest-Rev1.py
Normal file
@@ -0,0 +1,3 @@
|
||||
include("manifest.py")
|
||||
|
||||
module("hwconfig.py", "../../src/hwconfig_Rev1")
|
||||
3
software/boards/RPI_PICO_W/manifest-breadboard.py
Normal file
3
software/boards/RPI_PICO_W/manifest-breadboard.py
Normal file
@@ -0,0 +1,3 @@
|
||||
include("manifest.py")
|
||||
|
||||
module("hwconfig.py", "../../src/hwconfig_breadboard")
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2024 Matthias Blankertz <matthias@blankertz.org>
|
||||
|
||||
# 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))
|
||||
@@ -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()
|
||||
@@ -1,113 +0,0 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2024-2025 Matthias Blankertz <matthias@blankertz.org>
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user