16 Commits

Author SHA1 Message Date
e447902001 feat: Move tagmode setting to config.json, remove playlistdb settings
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m35s
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 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-16 20:41:40 +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
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
7d3cdbabe4 feat(app): Implement tag handling modes according to #28.
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 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
If the tagmode setting is 'tagremains' (the default): Play as long as the
tag is on the reader, with a 5 second timeout (i.e. playback stops when
tag is gone for more than 5 seconds).

If the tagmode setting is 'tagstartstop': Playback starts when a tag is
seen. Presenting a different tag causes the playback to stop and
playback for the new tag to start. Re-presenting the same tag used to
start with a no-tag-time of 5 seconds or more in between stops playback.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-11-04 19:25:10 +01:00
b5e3df1054 refactor(app): Refactor tag handling
Split the tag handling in PlayerApp into two parts: The low level
handling of changed/removed tags from the Nfc reader, including the
timeout processing is moved into the nested TagStateMachine class. The
main PlayerApp has two new (internal) callbacks "onNewTag" and
"onTagRemoved" which are called when a new tag is presented or a tag was
actually removed. This will hopefully make the implementation of #28
"Configurable Tag Handling" cleaner.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-11-04 19:25:10 +01:00
6a9ff9eb0a playlistdb: Implement shuffle
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m22s
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 8s
Run pytests / Check-Pytest (push) Successful in 11s
Initial implementation of shuffle with a naive algorithm.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-31 14:21:35 +01:00
7327549eea refactor(playlistdb): Enforce constant entry index length
To simplify the playlist handling, enforce that the indices are always
formatted to the same length (5, which allows for 100000 entries, that
should be enough).

Then make the position stored in the Playlist object be a simple integer
instead of a database key. This simplifies the code, and will make
implementing shuffle much easier.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-31 14:21:35 +01:00
7e532ec641 app, mp3player: Hook up playlists 'offset' persist mode
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-31 14:21:35 +01:00
5013e2359d playlistdb: Add shuffle and persist settings
Add documentation of playlist database schema in DEVELOP.md.

Add settings for persist and shuffle to BTreeDB. Implement the different
persist modes. Shuffle will be implemented in a followup commit.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-10-31 14:21:35 +01:00
5625f43f81 playlistdb: testing lexicographic sorting of db entries
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 9s
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
2025-10-14 21:21:16 +02:00
4507275a02 app: Fix bug when a tag that has no playlist is encountered 2025-10-07 22:23:54 +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