Commit Graph

29 Commits

Author SHA1 Message Date
936020df58 feat: Add and deploy frontend
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-16 20:41:40 +01:00
97e9742c75 feat: Add basic watchdog timer
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-07 13:09:34 +01:00
96759c999c fix: Block certain requests during playback
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m42s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 12s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 7s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s
Probably due to memory/stack overrun, some more involved web API
requests cause the system to hang if performed during playback. For now,
block these requests during playback.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-03 20:36:41 +01:00
a7e58853bb feat: Add api/v1/config to get, put config
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m40s
Check code formatting / Check-C-Format (push) Successful in 9s
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 12s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-03 20:12:29 +01:00
856bf34161 feat: Make button mapping configurable
- Remove Pin to button mapping from hwconfig, replace with a simple list
  of Pins to which buttons are attached
- Add BUTTON_MAP to config.json which maps indices in the HW button list
  to button names
- Update utils.Buttons to use the button map to connect the correct pins
  to the matching key codes

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-01 20:25:30 +01:00
83deb1b4c2 feat: Replace hardcoded timeouts in app with configurable
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-01 20:25:30 +01:00
2225906664 feat: Move LED_COUNT from hwconfig to config.json
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-01 20:25:30 +01:00
e07ee46518 style: Fix flake8 complaints
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m28s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
Remove unused imports in main.py

Add missing "global" in webserver and fix spacing.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-11-28 17:48:39 +01:00
340aea6be6 Factored out webserver sample into dedicated module 2025-11-11 22:30:18 +01:00
f64bbc27fd basic webserver works 2025-11-11 22:28:55 +01:00
abb880baca print network interface info 2025-11-11 22:28:49 +01:00
a59f00ad60 disabled wifi power management for now 2025-11-11 22:26:04 +01:00
869a92d998 feat: Implement shutdown on idle when on battery
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m24s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Allow the PlayerApp to turn off the device if it is idle for longer then
the timeout. The timeout is currently hardcoded to 1 minute, this will be
made configurable in the future.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-11-11 20:31:48 +01:00
696f7b956c feat: Change LED pattern based on playback state
Move the LED control to the utils.LedManager class. For the first
implementation, support two LED patterns 'idle' and 'playing'.

Extend the PlayerApp to set the LED pattern based on playback state.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-11-11 20:30:54 +01:00
b56e4f36b4 fix(main): Make upgrade from tag directories more ergonomical
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m21s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
As we don't have an API to upload files and create playlists yet, we
used the convention "tag uid as directory name" to allow testing
playback. With the introduction of the database in #39 "Add playlist db"
a builddb() function to initialize the database from the tag directories
was added, but it is not automatically called. To make the developer
experience more ergonomical, add a check for that automatically runs
builddb() when no database exists.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-11-02 18:06:18 +01:00
db136ed79a Wifi setup function with initial wlan config and per-board unique ssid
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m21s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
2025-11-02 17:21:48 +01:00
4512b91763 Merge PR #42 from remote-tracking branch 'origin/fix-sd-spi-hwconfig' into main
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m23s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>

Reviewed-on: #42
Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de>
2025-10-31 14:19:27 +01:00
502805e2e8 hwconfig: Fix pad config for SD SPI, move clockrate to hwconfig
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m19s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
The code snippet in hwconfig to adjust the drive strength was incorrect:
It was adjusting the wrong pins. This was probably not updated during
some pin shuffling in the breadboard phase.

Fix this by adjusting the correct pins. Experimentation shows that both
setting the slew rate to fast or setting the drive strength to 8 mA
(default: slow and 4 mA) is sufficient to make SD SPI work at 25 MHz on
the Rev1 PCB. For now, the combination 8 mA and slow is chosen (slow
slew rate should result in less high frequency EMI).

Also make the SD clock rate adjustable in hwconfig, and set it to 25 MHz
for Rev1 and 15 MHz for the breadboard setup.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-13 23:38:33 +02:00
16d5180d34 playlistdb: Allow up to 100k tracks; Add validate method; docstrings
- Increase the formatting of playlist entries to allow up to 100000
  tracks. Also enforce that playlist entries are indexed by integers
  using the validate method.

- Add a validate method to validate the data stored in the
  btreedb. Optionally dump the contents to stdout. For testing, add a
  validate+dump by default when opening the db. This can be removed once
  the playlistdb is validated.
2025-10-07 22:23:54 +02:00
69e119a8a0 Add playlist database
Add playlist database based on the micropython 'btree' module.
Supported features are:
* Create playlist
* Load playlist
* Store position in playlist

Different playlist modes will be added in a followup for #24.

Implements #23.

The playlist data is stored in the btree database in a hierarchical
schema. The hierarchy levels are separated by the '/' character.
Currently, the schema is as follows: The top level for a playlist is the
'tag' id encoded as a hexadecimal string. Beneath this, the 'playlist'
key contains the elements in the playlist. The exact keys used for the
playlist entries are not specified, they are enumerated in native sort
order to build the playlist. When writing a playlist using the
playlistdb module, the keys are 000, 001, etc. by default.  The
'playlistpos' key is also located under the 'tag' key and stores the key
of the current playlist entry.

For example, a playlist with two entries 'a.mp3' and 'b.mp3' for a tag
with the id '00aa11bb22' would be stored in the following key/value
pairs in the btree db:
- 00aa11bb22/playlist/000: a.mp3
- 00aa11bb22/playlist/001: b.mp3
- 00aa11bb22/playlistpos: 000

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-07 22:23:51 +02:00
da90228ab5 Make hardware configurable
Move hardware-specifics (pin assignments, power management) to
hwconfig_*.py.

The build system will build a firmware image
firmware-filesystem-$variant.uf2 for all variants for which a
hwconfig_$variant.py file exits. Inside the filesystem image, the
selected variants hwconfig_$variant.py file will always be named
hwconfig.py.

At runtime, main.py will attempt to import hwconfig which will load the
configuration for the correct variant.

Currently, the hwconfig_* modules are expected to define the pin mapping
and implement a board_init method.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-07 22:12:44 +02:00
27110b7b62 Add infrastructure for pytest and mypy
Make mypy run with proper type stubs for micropython RP2.
Add basic structure for pytest testing.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-08-27 13:42:08 +02:00
e9bd4f72b6 Handle partitioned and unpartitioned SD cards
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m28s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Add utils.MBRPartition to implement basic partitioned device support.

Try to mount partition 1 of SDCard first, if that fails, try to mount
entire device as FAT file system.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-08-05 21:16:09 +02:00
ce02daad3a Move playlist handling from mp3player to app
All checks were successful
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 8s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m28s
This completes the move of the nfc-mp3-demo to the new architecture.
2025-05-20 22:04:27 +02:00
7712c25627 Turn TimerManager into a Singleton 2025-05-20 22:04:27 +02:00
903840f982 wip: New architecture
Change PlayerApp to new architecture
 - depedencies injected via named tuple
 - some initial type checking
 - move on button press logic to PlayerApp

TODO: Adapt MP3 player
2025-05-20 22:04:27 +02:00
b477aba94c Add initial button handling 2025-05-20 22:04:27 +02:00
f0c3fe4db8 Use context managers to ensure deinit of audiocore and sd 2025-05-20 22:04:27 +02:00
d02776eea8 Add basic application for playback based on NFC tags
Copy and clean up test.py to main.py. Add app module (currently on
app.py, maybe make it a directory later) for application classes.

Implement app.TimerManager to allow scheduling of delayed events in the
micropython async framework.

Implement app.TagPlaybackManager which handles playing back MP3 files
based on the NFC tag reader. Currently, simply plays all MP3 files in a
folder, for which the folder name matches the tag id, in order. Resume,
random and other features not yet supported.
2025-05-20 22:04:27 +02:00