Porównaj commity

..

134 Commity

Autor SHA1 Wiadomość Data
Hel Gibbons f18f1ba259
Merge pull request #960 from johnbintz/patch-1
Add SPI import to SD card upload example
2024-06-14 11:27:52 +01:00
John Bintz f495fb8b70
Add SPI import to SD card upload example
As the code exists now, you won't be able to mount the SD card due to the missing import.
2024-06-14 06:08:11 -04:00
Philip Howard 7a2ebe5c0d
Merge pull request #952 from pimoroni/test/revert-1.23.0
TEST: Revert to v1.23.0.
2024-06-06 19:15:17 +01:00
Phil Howard 48f2446f6c CI: Cherry-pick our pins.csv patch. 2024-06-06 19:00:48 +01:00
Phil Howard 6eef96d9c9 CI: Revert to v1.23.0.
We'd moved past v1.23.0 to do our release in order to grab:

932f76c6ba

But this broke our builds due to:

https://github.com/micropython/micropython/issues/15220
2024-06-06 18:56:17 +01:00
Philip Howard 9771274e90
Merge pull request #950 from pimoroni/patch-getting-started-doc
Docs: Fix .uf2 names, add pico_usb.
2024-06-05 11:17:59 +01:00
Phil Howard 7c05770a44 Docs: Fix .uf2 names, add pico_usb. 2024-06-05 11:09:15 +01:00
Philip Howard 3440ab232c
Merge pull request #915 from pimoroni/feature/usb
MicroPython v1.23.0 + USB-compatible Pico firmware.
2024-06-04 20:31:18 +01:00
Phil Howard 7d0bb04d6d Keybow2040: Basic-ish USB examples. 2024-06-04 19:55:24 +01:00
Phil Howard 392890e99b RP_PICO_USB: New USB-enabled version of the stock Pico firmware.
⚠️ Warning: flash/firmware split is now 1Mb/1Mb to accomodate USB libs.

BACK UP YOUR PICO before flashing this build. It *will* trash your filesystem.

* Add new RP_PICO_USB board
* Use commit 932f76c6ba64c5a3e68de3324556d9979f09303b for 932f76c6ba
2024-06-04 19:55:24 +01:00
Phil Howard 7b7d9fe383 CI: Update MicroPython patch for > v1.22.2. 2024-06-04 19:55:24 +01:00
Phil Howard ccd00f6289 Ulab: Bump to 6.5.2 for MicroPython 1.23.0 compatibility. 2024-06-04 19:54:52 +01:00
Philip Howard 10fed7edaf
Merge pull request #946 from pimoroni/patch-sh1107-example
Fixed background in SH1107 example
2024-06-03 13:54:41 +01:00
Phil Howard 517f8ae1cd global: Remove the STATIC macro.
Reflect the changes proposed in micropython/micropython#13763.
2024-06-03 13:44:23 +01:00
thirdr 5b6903ce72 fixed background 2024-06-03 12:25:16 +01:00
Phil Howard 84cabe077d MicroPython: Switch QRCode to micropython/edge branch.
Includes fixes for:

* "mp_obj_malloc_with_finaliser" replacing "m_new_obj_with_finaliser"
* "STATIC" macro dropped in favour of "static"
2024-06-03 11:40:29 +01:00
Phil Howard 64e26dc6f4 CI: Bump MicroPython to master.
CI will always run against the latest MicroPython commit.
2024-06-03 11:40:29 +01:00
Phil Howard 47e3aed88f MicroPython: Switch to mp_obj_malloc_with_finaliser. 2024-06-03 11:40:29 +01:00
Philip Howard bf6fa4bc45
Merge pull request #916 from pimoroni/examples/audio
i2s audio examples
2024-06-03 11:35:59 +01:00
Philip Howard 0b133c750e
Merge pull request #931 from pimoroni/driver/as7343
AS7343: New driver for the 14 channel spectrometer
2024-06-03 11:34:45 +01:00
Philip Howard 5691573f89
Merge pull request #933 from pimoroni/feature/scannable-release-names
CI: Scannable artifact and release names.
2024-06-03 11:34:07 +01:00
Philip Howard b41bb4abf7
Merge pull request #943 from pimoroni/patch-bme280-examples
Fixed result status bug
2024-06-03 11:33:11 +01:00
Philip Howard 8b928d8891
Merge pull request #944 from pimoroni/patch-tufty-example
Fixed button polarity
2024-06-03 11:32:09 +01:00
Philip Howard 56e6d66c9b
Merge pull request #945 from pimoroni/patch-mics6814-pins
Corrected pin definitions for OX and RED
2024-06-03 11:31:15 +01:00
thirdr ffa12c2165 corrected pin defs 2024-06-03 10:31:46 +01:00
thirdr b9f3990995 fixed button polarity 2024-06-03 09:11:49 +01:00
thirdr cca4f3f7f1 fixed result status bug 2024-05-31 12:38:58 +01:00
Philip Howard 981a38b989
Merge pull request #928 from pimoroni/examples/pngdec
Examples/pngdec
2024-05-30 23:32:14 +01:00
Philip Howard 25786def35
Merge pull request #942 from pimoroni/patch-inky-launcher
Patch inky launcher
2024-05-30 19:21:28 +01:00
thirdr a387e45098 linting fix 2024-05-30 13:32:48 +01:00
thirdr 452d700ba1 Improved XML parsing/bug fix from Pico Vision 2024-05-30 13:29:48 +01:00
Hel Gibbons 9d7d651565
Merge pull request #940 from exussum12/patch-3
Add link to png
2024-05-24 16:57:25 +01:00
Scott Dutton b3a0c4fb9d
Add link to png 2024-05-21 11:13:42 +01:00
thirdr f962c3cd3c linting 2024-05-13 12:27:23 +01:00
thirdr b5a040f6cc correct layout on pico display 1 & 2 2024-05-13 12:27:23 +01:00
thirdr d790d3d344 fixed background colour 2024-05-13 12:18:36 +01:00
thirdr ba7b8388bf fixed background colour 2024-05-13 12:18:36 +01:00
thirdr 829f688285 offset palette example 2024-05-13 12:18:36 +01:00
thirdr 8fb17a3c26 adjustment to scale and location 2024-05-13 12:18:36 +01:00
thirdr 4db7cc61ab png palette offset example 2024-05-13 12:18:36 +01:00
thirdr c510a3c875 Changed the png used 2024-05-13 12:18:36 +01:00
thirdr 425f132096 png decode example for tufty 2024-05-13 12:18:36 +01:00
thirdr 76683acb0d png decode example for display pack 2024-05-13 12:18:36 +01:00
thirdr 7c287192de Error handling 2024-05-13 12:18:36 +01:00
thirdr f15c657b44 pngdec example for inky 2024-05-13 12:18:36 +01:00
Philip Howard f3b53b6b5f
Merge pull request #939 from coadkins/coadkins-patch-1
Add PNG File subsection to Pico Graphics documentation
2024-05-09 11:02:35 +01:00
coadkins 37c4d22527
Add PNG File subsection to Pico Graphics documentation
I added a subsection for PNG File support in Pico Graphics by copying and adapting the text from these release notes - https://github.com/pimoroni/pimoroni-pico/releases/tag/v1.20.4 - about the PNGdec functionality.
2024-05-08 11:22:07 -04:00
Philip Howard 616b1cc8d6
Merge pull request #938 from pimoroni/ci/py_decl
CI: Add py_decl verify step to catch binary overflows.
2024-05-03 12:25:04 +01:00
Phil Howard 45a9925072 CI: Add py_decl verify step to catch binary overflows. 2024-05-03 10:59:35 +01:00
thirdr 3998b0c8bf simple example for Pico Audio Pack 2024-04-22 15:35:53 +01:00
Connor Linfoot 32c10482d9
Add support for 96x48 display to Interstate75 (#867)
* Add DISPLAY_INTERSTATE75_96X48
2024-04-17 13:41:02 +01:00
Phil Howard 6ed743b32c Docs: Update MicroPython setup to reflect new names. 2024-04-17 13:06:04 +01:00
Phil Howard 17d59f4729 CI: Scannable artifact and release names.
When I go to fetch an artifact for a MicroPython build my brain is
always confounded by the repetition of "pimoroni-" before each file.

Change the names so the product is up-front, so the list is easier
to scan-read through.
2024-04-17 13:00:40 +01:00
Philip Howard 4c44b77193
Merge pull request #912 from pimoroni/patch-picodisplay-180
PicoDisplay: Fix misalignment on rotated Pico Displays (fixes #562.)
2024-04-17 12:54:18 +01:00
Phil Howard 5510c82564 PicoDisplay: Fix rotation offset for #562.
Pico Display would have a pixel offset at 90 and 180 degree rotations.

Add a special case offset tweak for these, and demystify the rotate_180 variable.
2024-04-17 12:44:40 +01:00
Philip Howard 3a10b29f54
Merge pull request #920 from pimoroni/patch-inky7-update-timeout
inky73: Add busy wait timeout.
2024-04-17 12:42:53 +01:00
Phil Howard 8cf276b992 inky73: Add busy wait timeout.
Add a timeout to fix Inky 7.3" hanging on batteries.

Basically assumes the update has finished if it takes > 45s, and allows a subsequent attempt
rather than hanging indefinitely.

Raised, texted and fixed by w3stbam: https://github.com/pimoroni/pimoroni-pico/pull/900

Rewritten as mentioned in the PR.
2024-04-17 12:33:24 +01:00
Phil Howard 8bb17087d9 AS7343: Tufty 2040 spectrometer example. 2024-04-15 11:57:40 +01:00
Phil Howard 6fcbaf5616 AS7343: MicroPython bindings. 2024-04-15 11:53:34 +01:00
Phil Howard 6803f00b31 AS7343: New 14-channel spectral sensor driver. 2024-04-15 11:53:34 +01:00
Phil Howard 6e71a62c65 Pimoroni I2C: Add reg_write_uint16. 2024-04-15 11:53:34 +01:00
Philip Howard f1ea35fbbf
Merge pull request #911 from pimoroni/patch-unicorn-brightness
G/S/C Unicorn: Fix get_brightness to use correct max value.
2024-04-11 17:45:48 +01:00
Philip Howard c066325ca0
Merge pull request #909 from pimoroni/patch-ltr559-interrupt
LTR559: Add interrupt.py demo from #169.
2024-04-11 17:41:58 +01:00
Philip Howard fd4eb165f8
Merge pull request #930 from pimoroni/patch-misc-ci-fixes
Slightly less frustrating MicroPython builds.
2024-04-11 17:08:44 +01:00
Phil Howard 8fc8a8ee06 CI: Rename tiny2040 to tiny2040_8mb.
It was not super obvious that this build is specific to the 8mb
version of Tiny 2040.
2024-04-11 17:01:21 +01:00
Phil Howard 3bfb548686 CI: Continue other MicroPython builds if one fails.
In almost all cases it's more useful to know if a given build
is likely to succeed rather than have *everything* fail. This
change adjusts the workflow to allow other builds to continue
if one fails.
2024-04-11 17:01:09 +01:00
Philip Howard 9edcdcc126
Merge pull request #919 from pimoroni/patch-pngdec-palette-offset
PNGdec: Add support for palette offsets and greyscale copy mode
2024-04-11 16:32:08 +01:00
Philip Howard e8e550b18b
Merge pull request #929 from pimoroni/patch/wordclock
Fixed arg order bug
2024-04-11 14:57:07 +01:00
thirdr cdb7b4bf2c fixed arg order bug 2024-04-11 14:02:26 +01:00
Philip Howard 4fc3095433
Merge pull request #925 from pimoroni/patch-actions-nodejs
CI: Update actions to fix nodejs deprecation warnings.
2024-04-08 12:58:00 +01:00
Phil Howard 9c5b529754 CI: Update actions to fix nodejs deprecation warnings. 2024-04-08 12:47:14 +01:00
ZodiusInfuser a87d5581aa
Merge pull request #923 from pimoroni/patch/inventor_encoders
Added example for reading speeds from Inventor 2040W's encoders
2024-04-03 14:57:41 +01:00
ZodiusInfuser 44d7875f7e Relocated example and updated readme 2024-04-03 14:37:26 +01:00
ZodiusInfuser a90c31fb3b More explanation of encoder capture 2024-04-03 14:29:17 +01:00
ZodiusInfuser 458b0ac209 Added a speed reading example for inventor 2024-04-03 14:29:01 +01:00
Phil Howard a537672dd4 PNGdec: Don't convert greys if mode=COPY. 2024-03-28 15:35:05 +00:00
Phil Howard d34e692f51 PNGdec: Don't add palette_offset twice. 2024-03-28 15:30:32 +00:00
Phil Howard 27b913124c PNGdec: Add copy support and offset to greyscale. 2024-03-28 15:04:06 +00:00
Phil Howard c7b788cd1d PNGdec: Add palette offset arg.
Allow index colour PNGs to be copied with a palette offset.

EG: a 4bit PNG could be offset 16 times for as many colour variations.
2024-03-28 15:04:02 +00:00
Philip Howard c386b3e9cf
Merge pull request #910 from pimoroni/patch-readme-stubs
README.md: Add link to pimoroni-pico-stubs.
2024-03-28 10:17:02 +00:00
thirdr b499296867 added amp enable to audio.py 2024-03-27 14:38:01 +00:00
thirdr 193adaca72 linting fix 2024-03-27 13:01:35 +00:00
Philip Howard a7a2e2bee0
Merge pull request #918 from pimoroni/patch-pngdec-1bit
PNGdec: Add greyscale support.
2024-03-27 12:59:25 +00:00
thirdr b0babcfe9f fixed audio 'pop' 2024-03-27 12:57:44 +00:00
Phil Howard 19fa8864cf PNGdec: Add greyscale support.
Add an optional MODE_PEN to draw the PNG in the current pen colour.

Best used with, but not limited to, 1bit PNG images.
2024-03-27 12:49:09 +00:00
thirdr e34b2420c6 i2s audio examples 2024-03-26 08:41:48 +00:00
Phil Howard 964cf5eedf G/S/C Unicorn: Fix get_brightness to use correct max value.
Add a comment noting that 256 is the correct maximum brightness.
2024-03-11 21:14:43 +00:00
Phil Howard eab1595352 README.md: Add link to pimoroni-pico-stubs. 2024-03-11 15:04:18 +00:00
Phil Howard 5dd76ed31b LTR559: Add interrupt.py demo from #169. 2024-03-11 13:38:07 +00:00
Philip Howard 6eb0f90e53
Merge pull request #904 from pimoroni/ci/micropython-1.22.2
CI: Bump MicroPython to v1.22.2.
2024-03-06 10:29:16 +00:00
Phil Howard b0d53dadb3 Hub75: avoid clobbering shared IRQ handlers.
MicroPython's DMA class uses shared IRQ handlers, which would be
clobbered by Hub75's use of an exclusive handler.

Additionally clean up some dead code (DMA_IRQ_1??), more epxlicitly
clean up the claimed PIOs and programs, and do not use a fixed
DMA channel. This seems to have fixed a bug whereupon Hub75 would
hardlock on the 5th soft reset.
2024-03-05 10:30:48 +00:00
Phil Howard ad518064e9 CI: Bump MicroPython to v1.22.2. 2024-02-27 16:43:47 +00:00
Philip Howard d83107474e
Merge pull request #907 from pimoroni/patch-pngdec-1bit
Fixes for PNGDEC on Badger 2040 / Badger 2040 W
2024-02-27 16:42:12 +00:00
Phil Howard c4f70df1cf Pen1BitY: Correct RGB to dither lookup conversion. 2024-02-27 13:54:25 +00:00
Phil Howard 10221066dd PNGDEC: Support for 1bpp. 2024-02-27 13:31:52 +00:00
Philip Howard ab64fcaccc
Merge pull request #899 from pimoroni/jpegdec/width_height_fix
JPEGDEC: Backport width/height changes from pngdec.
2024-02-27 12:21:17 +00:00
Hel Gibbons 32c63c343d
Merge pull request #905 from pimoroni/helgibbons-patch-3
Plasma Stick: add link
2024-02-26 14:24:49 +00:00
Hel Gibbons 8d964bce2c
Plasma Stick: add link 2024-02-26 14:08:56 +00:00
ZodiusInfuser 8ca47d6405
Merge pull request #890 from robberwick/motor2040_i2c_pins
Add I2C pin definitions to motor2040 and servo2040 headers
2024-02-13 12:00:05 +00:00
Skyler Mansfield b23a71b889 JPEGDEC: Backport width/height changes from pngdec.
Open JPEG file or stream to read width/height before decode.
2024-01-23 16:18:13 +00:00
Philip Howard 6b23c1526d
Merge pull request #898 from pimoroni/patch-tufty2040-567
st7789: Remove mystery meat command implicated by #567.
2024-01-23 15:09:49 +00:00
Phil Howard c19b2276f1 st7789: Remove mystery meat command implicated by #567.
This should, in theory, fix the weird display corruption bug affecting Tufty 2040.
2024-01-23 13:14:12 +00:00
Philip Howard 392d75b00d
Merge pull request #878 from pimoroni/ci/tooling
CI: Move some workflow steps into ci/micropython.sh
2024-01-19 10:32:20 +00:00
Philip Howard 911cbb710e
Merge pull request #877 from pacohope/tz-adjust
add adjustment for time zone offset
2024-01-16 14:35:16 +00:00
Philip Howard 4e3e2c836d
Merge pull request #876 from pimoroni/docs/picoscroll
update picoscroll docs
2024-01-16 14:27:06 +00:00
Philip Howard 5bd5334379
Merge pull request #813 from andrewjw/andrewjw-patch-1
fix: Only set time if the wlan is connected
2024-01-16 14:18:37 +00:00
Philip Howard 9ddbb17a82
Merge pull request #860 from pimoroni/patch-bye-bye-badger
Badger2040/2040W: Remove old/incompatible examples.
2024-01-16 14:17:08 +00:00
Phil Howard 5126263f91 Badger2038/2040W: Remove old/incompatible examples.
Badger now lives at: https://github.com/pimoroni/badger2040
2024-01-16 14:01:34 +00:00
Philip Howard 0d3fce9b9d
Merge pull request #883 from raybellis/main
fix hue errors in plasma_stick_rainbows
2024-01-16 11:32:43 +00:00
Rob Berwick 9e6a0725c0 add `I2C_*` definitions to `servo2040.hpp`
Add pin definitions for `I2C_INT`, `I2C_SDA`, and `I2C_SCL` to `servo2040.hpp`
2024-01-08 13:08:44 +00:00
Rob Berwick 3e81b245a1 add I2C_INT & reorder
Add `I2C_INT` to `motor2040.hpp` and put pin defs in numeric order.
2024-01-08 12:57:30 +00:00
Phil Howard bd6bd289d1 CI: Try to ccache mpy-cross 2024-01-08 11:20:08 +00:00
Phil Howard b6953c25a1 CI: Tidy up build steps 2024-01-08 11:20:08 +00:00
Phil Howard b5df0ac277 CI: Setup version env, patch skipped message. 2024-01-08 11:20:08 +00:00
Phil Howard 116bbb1296 CI: Use arm-none-eabi-gcc-action
Speeds up toolchain install (when cached) to ~7s an decouples us from the runner OS ARM GCC version.
2024-01-08 11:20:08 +00:00
Phil Howard 6154116662 CI: Move build steps to a bash script. 2024-01-08 11:20:04 +00:00
Phil Howard d45daef654 MicroPython: Switch from MICROPY_EVENT_POLL_HOOK to mp_event_handle_nowait().
Note: Unsure if mp_event_handle_nowait() is the right answer in all cases,
but this seems to be what we want in our blocking loops.
2024-01-08 10:33:28 +00:00
Phil Howard 1b3d9d9fb2 Pimoroni I2C: Update to use modmachine.h consolidated header. 2024-01-08 10:15:28 +00:00
Phil Howard 4dd76525f6 CI: Update MicroPython patch for v1.22.1. 2024-01-08 10:06:17 +00:00
Phil Howard 3bac13fcc8 CI: Bump MicroPython to v1.22.1. 2024-01-08 09:46:43 +00:00
Hel Gibbons bff245324b
Merge pull request #886 from bitcdr/feature/add-other-resource-to-plasma-stick-examples-readme
[Plasma Stick 2040W] add Plasma LEDs link
2024-01-03 14:36:04 +00:00
Hel Gibbons 400347b862
Merge pull request #888 from everyplace/main
[Inky Frame] Fix news headline redirect example
2024-01-03 13:03:42 +00:00
Ray Bellis da0ac1821f resolve precision error in python example too 2024-01-02 22:22:09 +00:00
Rob Berwick 6dcc0d4fa0 Add I2C pin definitions to motor2040 header
Add definitions for the QW/ST connector SDA & SCL pins
2024-01-01 20:07:58 +00:00
Erin Sparling fc3f8e5654 Updated commented out url protocols as well 2023-12-29 13:26:33 -05:00
Erin Sparling c001f9bb59 Swapped protocol for https so redirect handling isn't necessary 2023-12-29 13:24:08 -05:00
Erin Sparling 59fa0a1ff8 Added comment for 7.3 frame 2023-12-29 13:23:31 -05:00
Stefan Werder a803c3cee4 add Plasma LEDs link 2023-12-21 00:43:19 +01:00
Ray Bellis 6fd667b1ca fix hue errors in plasma_stick_rainbows 2023-12-13 21:43:01 +00:00
Paco Hope 078d81312f add adjustment for time zone offset 2023-11-14 22:05:12 -05:00
Hel Gibbons a60c856ea8 update picoscroll docs 2023-11-09 12:53:03 +00:00
Philip Howard b4451c3bdc
Merge pull request #862 from pimoroni/patch-polygon-clip
Pico Graphics: Avoid unecessary and broken polygon scanline clip.
2023-10-16 10:46:58 +01:00
Phil Howard ce42d814a7 Pico Graphics: Avoid unecessary and broken polygon scanline clip. 2023-10-16 09:56:40 +01:00
Andrew Wilkinson 14c7f6c9c8
fix: Only set time if the wlan is connected
Previously, if we dropped out of the wlan loop early because of an error (wlan.status() < 0) it would still print "Connected", and try to set the time.
2023-08-10 15:58:52 +01:00
253 zmienionych plików z 4289 dodań i 8377 usunięć

Wyświetl plik

@ -25,7 +25,7 @@ jobs:
steps:
- name: Compiler Cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: /home/runner/.ccache
key: ccache-cmake-${{github.ref}}-${{matrix.board}}-${{github.sha}}
@ -34,13 +34,13 @@ jobs:
ccache-cmake-${{github.ref}}
ccache-cmake
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
# Check out the Pico SDK
- name: Checkout Pico SDK
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: raspberrypi/pico-sdk
path: pico-sdk
@ -48,7 +48,7 @@ jobs:
# Check out the Pico Extras
- name: Checkout Pico Extras
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: raspberrypi/pico-extras
path: pico-extras

Wyświetl plik

@ -7,72 +7,23 @@ on:
types: [created]
env:
MICROPYTHON_VERSION: v1.21.0
WORKFLOW_VERSION: v1
MICROPYTHON_VERSION: v1.23.0
jobs:
deps:
runs-on: ubuntu-20.04
name: Dependencies
steps:
- name: Workspace Cache
id: cache
uses: actions/cache@v3
with:
path: ${{runner.workspace}}
key: workspace-micropython-${{env.MICROPYTHON_VERSION}}-${{env.WORKFLOW_VERSION}}
restore-keys: |
workspace-micropython-${{env.MICROPYTHON_VERSION}}-${{env.WORKFLOW_VERSION}}
# Check out MicroPython
- name: Checkout MicroPython
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
repository: micropython/micropython
ref: ${{env.MICROPYTHON_VERSION}}
submodules: false # MicroPython submodules are hideously broken
path: micropython
# Check out MicroPython Libs
- name: Checkout MicroPython Libs
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
repository: micropython/micropython-lib
path: micropython-lib
- name: Fetch Pico submodules
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: micropython/ports/rp2
run: |
git submodule update --init ../../lib/pico-sdk
git submodule update --init ../../lib/cyw43-driver
git submodule update --init ../../lib/lwip
git submodule update --init ../../lib/mbedtls
git submodule update --init ../../lib/micropython-lib
git submodule update --init ../../lib/tinyusb
git submodule update --init ../../lib/btstack
- name: Build mpy-cross
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: micropython/mpy-cross
run: make
build:
needs: deps
name: ${{matrix.name}} (${{matrix.board}})
name: ${{ matrix.name }} (${{ matrix.board }})
runs-on: ubuntu-20.04
continue-on-error: true
strategy:
matrix:
include:
- name: pico
board: RPI_PICO
- name: pico_usb
board: RPI_PICO_USB
- name: picow
board: RPI_PICO_W
- name: tiny2040
- name: tiny2040_8mb
board: PIMORONI_TINY2040
- name: picolipo_4mb
board: PIMORONI_PICOLIPO_4MB
@ -82,7 +33,6 @@ jobs:
board: PIMORONI_TUFTY2040
- name: enviro
board: PICO_W_ENVIRO
patch: true
- name: galactic_unicorn
board: RPI_PICO_W
- name: cosmic_unicorn
@ -91,93 +41,103 @@ jobs:
board: RPI_PICO_W
- name: inky_frame
board: PICO_W_INKY
patch: true
env:
# MicroPython version will be contained in github.event.release.tag_name for releases
RELEASE_FILE: pimoroni-${{matrix.name}}-${{github.event.release.tag_name || github.sha}}-micropython
MICROPY_BOARD_DIR: "$GITHUB_WORKSPACE/pimoroni-pico-${{ github.sha }}/micropython/board/${{ matrix.BOARD }}"
USER_C_MODULES: "$GITHUB_WORKSPACE/pimoroni-pico-${{ github.sha }}/micropython/modules/micropython-${{matrix.name}}.cmake"
RELEASE_FILE: ${{ matrix.name }}-${{ github.event.release.tag_name || github.sha }}-pimoroni-micropython
PIMORONI_PICO_DIR: "${{ github.workspace }}/pimoroni-pico-${{ github.sha }}"
MICROPY_BOARD_DIR: "${{ github.workspace }}/pimoroni-pico-${{ github.sha }}/micropython/board/${{ matrix.BOARD }}"
USER_C_MODULES: "${{ github.workspace }}/pimoroni-pico-${{ github.sha }}/micropython/modules/micropython-${{ matrix.name }}.cmake"
TAG_OR_SHA: ${{ github.event.release.tag_name || github.sha }}
MICROPY_BOARD: ${{ matrix.board }}
BOARD_NAME: ${{ matrix.name }}
BUILD_TOOLS: pimoroni-pico-${{ github.sha }}/ci/micropython.sh
steps:
- name: Compiler Cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: /home/runner/.ccache
key: ccache-micropython-${{matrix.name}}-${{github.ref}}-${{github.sha}}
key: ccache-micropython-${{ matrix.name }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-micropython-${{matrix.name}}-${{github.ref}}
ccache-micropython-${{matrix.name}}-
- name: Workspace Cache
uses: actions/cache@v3
with:
path: ${{runner.workspace}}
key: workspace-micropython-${{env.MICROPYTHON_VERSION}}-${{env.WORKFLOW_VERSION}}
restore-keys: |
workspace-micropython-${{env.MICROPYTHON_VERSION}}-${{env.WORKFLOW_VERSION}}
ccache-micropython-${{ matrix.name }}-${{ github.ref }}
ccache-micropython-${{ matrix.name }}-
- name: Install Compiler & CCache
if: runner.os == 'Linux'
run: |
sudo apt update && sudo apt install ccache gcc-arm-none-eabi
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
path: pimoroni-pico-${{ github.sha }}
- name: Set MicroPython Version Env Vars
shell: bash
- name: Install Arm GNU Toolchain (arm-none-eabi-gcc)
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '9-2020-q2'
- name: Install CCache
run: |
echo "MICROPY_GIT_TAG=$MICROPYTHON_VERSION, ${{matrix.name}} ${{github.event.release.tag_name || github.sha}}" >> $GITHUB_ENV
echo "MICROPY_GIT_HASH=$MICROPYTHON_VERSION-${{github.event.release.tag_name || github.sha}}" >> $GITHUB_ENV
source $BUILD_TOOLS
apt_install_build_deps
- name: Checkout MicroPython & Submodules
run: |
source $BUILD_TOOLS
micropython_clone
- name: "Py_Decl: Checkout py_decl"
uses: actions/checkout@v4
with:
repository: gadgetoid/py_decl
ref: v0.0.1
path: py_decl
- name: Build MPY Cross
run: |
source $BUILD_TOOLS
micropython_build_mpy_cross
- name: "HACK: CMakeLists.txt Disable C++ Exceptions Patch"
shell: bash
working-directory: micropython
run: git apply $GITHUB_WORKSPACE/pimoroni-pico-${{ github.sha }}/micropython/micropython_nano_specs.patch
run: |
source $BUILD_TOOLS
hack_patch_micropython_disable_exceptions
- name: "HACK: Pico SDK Patch"
if: matrix.patch == true
shell: bash
working-directory: micropython
run: |
$GITHUB_WORKSPACE/pimoroni-pico-${{ github.sha }}/micropython/board/pico-sdk-patch.sh ${{matrix.board}}
source $BUILD_TOOLS
hack_patch_pico_sdk
- name: Configure MicroPython
shell: bash
working-directory: micropython/ports/rp2
run: |
cmake -S . -B build-${{matrix.name}} -DPICO_BUILD_DOCS=0 -DUSER_C_MODULES=${{env.USER_C_MODULES}} -DMICROPY_BOARD_DIR=${{env.MICROPY_BOARD_DIR}} -DMICROPY_BOARD=${{matrix.board}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
source $BUILD_TOOLS
micropython_version
cmake_configure
- name: Build MicroPython # Multiple simultaneous jobs trigger https://github.com/pimoroni/pimoroni-pico/issues/761
- name: Build MicroPython
shell: bash
working-directory: micropython/ports/rp2
run: |
ccache --zero-stats || true
cmake --build build-${{matrix.name}} -j 1
ccache --show-stats || true
source $BUILD_TOOLS
cmake_build
- name: Rename .uf2 for artifact
- name: "Py_Decl: Verify UF2"
shell: bash
working-directory: micropython/ports/rp2/build-${{matrix.name}}
run: |
cp firmware.uf2 $RELEASE_FILE.uf2
python3 py_decl/py_decl.py --to-json --verify build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: Store .uf2 as artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{env.RELEASE_FILE}}.uf2
path: micropython/ports/rp2/build-${{matrix.name}}/${{env.RELEASE_FILE}}.uf2
name: ${{ env.RELEASE_FILE }}.uf2
path: build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: Upload .uf2
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
asset_path: micropython/ports/rp2/build-${{matrix.name}}/firmware.uf2
upload_url: ${{github.event.release.upload_url}}
asset_name: ${{env.RELEASE_FILE}}.uf2
asset_path: build-${{ matrix.name }}/firmware.uf2
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ env.RELEASE_FILE }}.uf2
asset_content_type: application/octet-stream

Wyświetl plik

@ -9,7 +9,7 @@ jobs:
name: Python Linting
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Python Deps
run: python3 -m pip install flake8

Wyświetl plik

@ -44,6 +44,10 @@ You can find MicroPython examples for supported sensors, packs and bases in the
* [MicroPython Examples](micropython/examples)
You can also install MicroPython stubs into Visual Studio Code to give you auto-complete, see:
* [MicroPython Stubs](https://github.com/pimoroni/pimoroni-pico-stubs)
# C/C++
Advanced users that want to unleash the full power of Pico can use our C++ libraries. If you know what you're doing and want to build your own Pimoroni Pico project then start with the [Pimoroni Pico SDK Boilerplate](https://github.com/pimoroni/pico-boilerplate).

77
ci/micropython.sh 100644
Wyświetl plik

@ -0,0 +1,77 @@
export TERM=${TERM:="xterm-256color"}
function log_success {
echo -e "$(tput setaf 2)$1$(tput sgr0)"
}
function log_inform {
echo -e "$(tput setaf 6)$1$(tput sgr0)"
}
function log_warning {
echo -e "$(tput setaf 1)$1$(tput sgr0)"
}
function micropython_clone {
log_inform "Using MicroPython $MICROPYTHON_VERSION"
git clone https://github.com/micropython/micropython
cd micropython
git checkout $MICROPYTHON_VERSION
git cherry-pick -n 932f76c6ba64c5a3e68de3324556d9979f09303b
git submodule update --init lib/pico-sdk
git submodule update --init lib/cyw43-driver
git submodule update --init lib/lwip
git submodule update --init lib/mbedtls
git submodule update --init lib/micropython-lib
git submodule update --init lib/tinyusb
git submodule update --init lib/btstack
cd ../
}
function micropython_build_mpy_cross {
cd micropython/mpy-cross
ccache --zero-stats || true
CROSS_COMPILE="ccache " make
ccache --show-stats || true
cd ../../
}
function apt_install_build_deps {
sudo apt update && sudo apt install ccache
}
function micropython_version {
echo "MICROPY_GIT_TAG=$MICROPYTHON_VERSION, $BOARD_NAME $TAG_OR_SHA" >> $GITHUB_ENV
echo "MICROPY_GIT_HASH=$MICROPYTHON_VERSION-$TAG_OR_SHA" >> $GITHUB_ENV
}
function hack_patch_micropython_disable_exceptions {
cd micropython
git apply $PIMORONI_PICO_DIR/micropython/micropython_nano_specs.patch
cd ../
}
function hack_patch_pico_sdk {
# pico-sdk-patch.sh will apply the patch if it exists
cd micropython
$PIMORONI_PICO_DIR/micropython/board/pico-sdk-patch.sh $MICROPY_BOARD
cd ../
}
function cmake_configure {
cmake -S micropython/ports/rp2 -B build-$BOARD_NAME \
-DPICO_BUILD_DOCS=0 \
-DUSER_C_MODULES=$USER_C_MODULES \
-DMICROPY_BOARD_DIR=$MICROPY_BOARD_DIR \
-DMICROPY_BOARD=$MICROPY_BOARD \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
}
function cmake_build {
ccache --zero-stats || true
cmake --build build-$BOARD_NAME -j 2
ccache --show-stats || true
cd build-$BOARD_NAME
cp firmware.uf2 $RELEASE_FILE.uf2
}

Wyświetl plik

@ -40,6 +40,15 @@ namespace pimoroni {
i2c_write_blocking(i2c, address, buffer, 2, false);
}
void I2C::reg_write_uint16(uint8_t address, uint8_t reg, uint16_t value) {
uint8_t buffer[3] = {
reg,
(uint8_t)((value & 0xff00) >> 8),
(uint8_t)(value & 0x00ff)
};
i2c_write_blocking(i2c, address, buffer, 3, false);
}
uint8_t I2C::reg_read_uint8(uint8_t address, uint8_t reg) {
uint8_t value;
i2c_write_blocking(i2c, address, &reg, 1, false);

Wyświetl plik

@ -63,6 +63,7 @@ namespace pimoroni {
i2c_inst_t* pin_to_inst(uint pin);
void reg_write_uint8(uint8_t address, uint8_t reg, uint8_t value);
void reg_write_uint16(uint8_t address, uint8_t reg, uint16_t value);
uint8_t reg_read_uint8(uint8_t address, uint8_t reg);
uint16_t reg_read_uint16(uint8_t address, uint8_t reg);
int16_t reg_read_int16(uint8_t address, uint8_t reg);

Wyświetl plik

@ -16,6 +16,7 @@ add_subdirectory(is31fl3731)
add_subdirectory(fatfs)
add_subdirectory(sdcard)
add_subdirectory(as7262)
add_subdirectory(as7343)
add_subdirectory(bh1745)
add_subdirectory(bme68x)
add_subdirectory(bmp280)

Wyświetl plik

@ -0,0 +1 @@
include(as7343.cmake)

Wyświetl plik

@ -0,0 +1,10 @@
set(DRIVER_NAME as7343)
add_library(${DRIVER_NAME} INTERFACE)
target_sources(${DRIVER_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_i2c pimoroni_i2c)

Wyświetl plik

@ -0,0 +1,160 @@
#include <cstdlib>
#include <math.h>
#include <map>
#include <vector>
#include <cstring>
#include "as7343.hpp"
namespace pimoroni {
bool AS7343::init() {
if(interrupt != PIN_UNUSED) {
gpio_set_function(interrupt, GPIO_FUNC_SIO);
gpio_set_dir(interrupt, GPIO_IN);
gpio_pull_up(interrupt);
}
uint8_t aux_id, revision_id, hardware_id;
get_version(aux_id, revision_id, hardware_id);
if(hardware_id != HARDWARE_ID) {
return false;
}
reset();
bank_select(0);
// Enable all 7 channels in output FIFO
i2c->set_bits(address, reg::FIFO_MAP, 0, FIFO_MAP_CH5 | FIFO_MAP_CH4 | FIFO_MAP_CH3 | FIFO_MAP_CH2 | FIFO_MAP_CH1 | FIFO_MAP_CH0 | FIFO_MAP_ASTATUS);
// Set the PON bit
i2c->reg_write_uint8(address, reg::ENABLE, ENABLE_WEN | ENABLE_SMUXEN | ENABLE_SP_EN | ENABLE_PON);
return true;
}
void AS7343::reset() {
i2c->reg_write_uint8(address, reg::CONTROL, CONTROL_SW_RESET);
sleep_ms(1000);
}
i2c_inst_t* AS7343::get_i2c() const {
return i2c->get_i2c();
}
int AS7343::get_sda() const {
return i2c->get_sda();
}
int AS7343::get_scl() const {
return i2c->get_scl();
}
int AS7343::get_int() const {
return interrupt;
}
void AS7343::bank_select(uint8_t bank) {
if(bank == 1) {
i2c->set_bits(address, reg::CFG0, 0, CFG0_BANK);
} else {
i2c->clear_bits(address, reg::CFG0, 0, CFG0_BANK);
}
}
void AS7343::get_version(uint8_t &auxid, uint8_t &revid, uint8_t &hwid) {
bank_select(1);
auxid = i2c->reg_read_uint8(address, reg::AUXID) & 0b00001111;
revid = i2c->reg_read_uint8(address, reg::REVID) & 0b00000111;
hwid = i2c->reg_read_uint8(address, reg::ID);
bank_select(0);
}
void AS7343::set_gain(float gain) {
if(gain == 0.5f) {
i2c->reg_write_uint8(address, reg::CFG1, 0);
} else {
uint16_t ugain = (uint16_t)gain;
uint16_t bitlength = 0;
while(ugain > 0) {
bitlength++;
ugain >>= 1;
}
i2c->reg_write_uint8(address, reg::CFG1, bitlength & 0x1f);
}
}
void AS7343::set_channels(channel_count channel_count) {
this->read_cycles = uint8_t(channel_count) / 6;
this->ch_count = (uint8_t)channel_count;
uint8_t temp = i2c->reg_read_uint8(address, reg::CFG20) & ~CFG20_18_CH;
switch(channel_count) {
case channel_count::SIX_CHANNEL:
temp |= CFG20_6_CH;
break;
case channel_count::TWELVE_CHANNEL:
temp |= CFG20_12_CH;
break;
case channel_count::EIGHTEEN_CHANNEL:
temp |= CFG20_18_CH;
break;
}
i2c->reg_write_uint8(address, reg::CFG20, temp);
}
void AS7343::set_illumination_current(float current) {
current -= 4;
current /= 2.0f;
uint8_t temp = i2c->reg_read_uint8(address, reg::LED) & 0b10000000;
temp |= (uint8_t)current;
i2c->reg_write_uint8(address, reg::LED, temp);
}
void AS7343::set_illumination_led(bool state) {
uint8_t temp = i2c->reg_read_uint8(address, reg::LED) & 0b01111111;
temp |= state ? 0x80 : 0x00;
i2c->reg_write_uint8(address, reg::LED, temp);
}
void AS7343::set_measurement_time(float measurement_time_ms) {
constexpr float resolution = 2.78f;
i2c->reg_write_uint8(address, reg::WTIME, (uint8_t)((measurement_time_ms - resolution) / resolution));
}
void AS7343::set_integration_time(float integration_time_us, uint8_t repeat) {
constexpr float resolution = 2.78f;
constexpr float max_astep = (65534 + 1) * resolution;
if (integration_time_us <= max_astep) {
i2c->reg_write_uint8(address, reg::ATIME, repeat - 1);
i2c->reg_write_uint16(address, reg::ASTEP, (uint16_t)((integration_time_us - resolution) / resolution) & 0xfffe);
} else {
// Time out of range...
}
}
void AS7343::read_fifo(uint16_t *buf) {
uint16_t expected_results = read_cycles * 7;
uint16_t result_slot = 0;
while (i2c->reg_read_uint8(address, reg::FIFO_LVL) < expected_results) {
sleep_ms(1);
}
while (i2c->reg_read_uint8(address, reg::FIFO_LVL) > 0 && expected_results > 0) {
buf[result_slot] = i2c->reg_read_uint16(address, reg::FDATA);
expected_results--;
result_slot++;
}
}
AS7343::reading AS7343::read() {
reading result;
read_fifo((uint16_t *)&result);
return result;
}
}

Wyświetl plik

@ -0,0 +1,139 @@
#pragma once
#include <string>
#include "hardware/i2c.h"
#include "hardware/gpio.h"
#include "common/pimoroni_common.hpp"
#include "common/pimoroni_i2c.hpp"
#include "as7343_regs.hpp"
namespace pimoroni {
class AS7343 {
//--------------------------------------------------
// Constants
//--------------------------------------------------
public:
static const uint8_t DEFAULT_I2C_ADDRESS = 0x39;
//--------------------------------------------------
// Enums
//--------------------------------------------------
public:
enum class channel_count : uint8_t {
SIX_CHANNEL = 6,
TWELVE_CHANNEL = 12,
EIGHTEEN_CHANNEL = 18
};
/*
enum class COMPENSATION_GAIN : float {
F1 = 1.84f,
F2 = 6.03f,
FZ = 4.88f,
F3 = 13.74f,
F4 = 3.37f,
FY = 2.82f,
F5 = 6.72f,
FXL = 2.22f,
F6 = 3.17f,
F7 = 1.95f,
F8 = 12.25f,
NIR = 1.00f,
};
*/
//--------------------------------------------------
// Substructures
//--------------------------------------------------
public:
struct reading {
// Cycle 1
uint16_t FZ = 0; // 428-480 nm
uint16_t FY = 0; // 534-593 nm
uint16_t FXL = 0; // 593-628 nm
uint16_t NIR = 0; // 849-903 nm
uint16_t c1_vis_tl = 0; // Visible top-left
uint16_t c1_vis_br = 0; // Visible bottom-right
uint16_t c1_astatus = 0; // (c1_astatus >> 8) & 0b10001111
// 0b10000000 = saturated
// 0b00001111 = gain lowest nibble
// Cycle 2
uint16_t F2 = 0; // 408-448 nm
uint16_t F3 = 0; // 448-500 mn
uint16_t F4 = 0; // 500-534 nm
uint16_t F6 = 0; // 618-665 nm
uint16_t c2_vis_tl = 0;
uint16_t c2_vis_br = 0;
uint16_t c2_astatus = 0;
// Cycle 3
uint16_t F1 = 0; // 396-408 nm
uint16_t F5 = 0; // 531-594 nm
uint16_t F7 = 0; // 685-715 nm
uint16_t F8 = 0; // 715-766 nm
uint16_t c3_vis_tl = 0;
uint16_t c3_vis_br = 0;
uint16_t c3_astatus = 0;
};
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
I2C *i2c;
// interface pins with our standard defaults where appropriate
int8_t address = DEFAULT_I2C_ADDRESS;
uint interrupt = PIN_UNUSED;
uint8_t read_cycles = 1;
uint8_t ch_count = (uint8_t)channel_count::SIX_CHANNEL;
//--------------------------------------------------
// Constructors/Destructor
//--------------------------------------------------
public:
AS7343(uint interrupt = PIN_UNUSED) : AS7343(new I2C(), interrupt) {};
AS7343(I2C *i2c, uint interrupt = PIN_UNUSED) : i2c(i2c), interrupt(interrupt) {}
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
bool init();
void reset();
// For print access in micropython
i2c_inst_t* get_i2c() const;
int get_sda() const;
int get_scl() const;
int get_int() const;
void get_version(uint8_t &auxid, uint8_t &revid, uint8_t &hwid);
reading read();
void read_fifo(uint16_t *buf);
void set_gain(float gain);
void set_illumination_current(float current);
void set_illumination_led(bool state);
void set_measurement_time(float measurement_time_ms);
void set_integration_time(float integration_time_us, uint8_t repeat=1);
void set_channels(channel_count channel_count);
private:
void bank_select(uint8_t bank=0);
};
}

Wyświetl plik

@ -0,0 +1,157 @@
#pragma once
#include <stdint.h>
namespace pimoroni {
/***** Device registers and masks here *****/
enum reg {
// Bank 1
AUXID = 0x58, // AUXID = 0b00001111
REVID = 0x59, // REVID = 0b00000111
ID = 0x5A, // ID = 0b11111111
CFG12 = 0x66, // SP_TH_CH = 0b00000111
// Bank 0
ENABLE = 0x80, // FDEN = 0b01000000
// SMUXEN = 0b00010000
// WEN = 0b00001000
// SP_EN = 0b00000010
// PON = 0b00000001
ATIME = 0x81, // ATIME = 0b11111111
// Integration Time Step Size
// 0 = 2.87us
// n 2.87us x (n + 1)
ASTEP = 0xD4, // STEP = 0xFFFF
// Spectral Measurement Wait Time
// 0 = 1 cycle = 2.78ms
// n = 2.78ms x (n + 1)
WTIME = 0x83, // WTIME = 0b11111111
SP_TH = 0x84, // SP_TH_L = 0xFFFF0000 Spectral Low Threshold
// SP_TH_H = 0x0000FFFF Spectral High Threshold
STATUS = 0x93, // ASAT = 0b10000000 Spectral Saturation (if ASIEN set)
// AINT = 0b00001000 Spectral Channel Interrupt (if SP_IEN set)
// FINT = 0b00000100 FIFO Buffer Interrupt
// SINT = 0b00000001 System Interrupt
ASTATUS = 0x94,// ASAT = 0b10000000 Saturation Status
// AGAIN = 0b00000111 Gain Status
DATA = 0x95, // 36 bytes, fields 0 to 17 (2 bytes eac)
STATUS2 = 0x90,// AVALID = 0b01000000 Spectral Data Valid
// ASAT_DIG = 0b00010000 Digital Saturation
// ASAT_ANA = 0b00001000 Analog Saturation
// FDSAT_ANA= 0b00000010 Flicker Analog Saturation
// FDSAT_DIG= 0b00000001 Flicker Digital Saturation
STATUS3 = 0x91,// INT_SP_H = 0b00100000 Spectral Above High Threshold
// INT_SP_L = 0b00010000 Spectral Below Low Threshold
STATUS5 = 0xBB,// SINT_FD = 0b00001000 Flicker Detect Interrupt (if SIEN_FD set)
// SINT_SMUX= 0b00000100 SMUS Operation Interrupt (SMUX exec finished)
STATUS4 = 0xBC,// FIFO_OV = 0b10000000 FIFO Buffer Overflow
// OVTEMP = 0b00100000 Over Temperature
// FD_TRIG = 0b00010000 Flicker Detect Trigger Error
// SD_TRIG = 0b00000100 Spectral Trigger Error
// SAI_ACT = 0b00000010 Sleep After Interrupt Active
// INT_BUSY = 0b00000001 Initialization busy (1 for ~300us after power on)
CFG0 = 0xBF, // LOW_POWER= 0b00100000
// REG_BANK = 0b00010000 0 - Register 0x80 and above
// 1 - Register 0x20 to 0x7f
// WLONG = 0b00000100 Increase WTIME by factor of 16
// Spectral Engines Gain Setting
// 0 = 0.5x, # 1 = 1x, 2 = 2x, 12 = 2048x
// GAINx = 1 << (n - 1)
CFG1 = 0xC6,
CFG3 = 0xC7, // SAI = 0b00100000 Sleep after interrupt
CFG6 = 0xF5, // SMUS_CMD = 0b00011000 0 - ROM_init
// 1 - Read_SMUX
// 2 - Write_SMUX
CFG8 = 0xC9, // FIFO_TH = 0b11000000 0b00, 0b01, 0b10, 0b11
CFG9 = 0xCA, // SIEN_FD = 0b01000000 System Interrupt Flicker Detection
// SIEN_SMUX= 0b00010000 System Interrupt SMUX Operation
CFG10 = 0x65, // FD_PERS = 0b00000111 Flicker Detect Persistence
// Number of results that must differ before status change
PERS = 0xCF, // APERS = 0b00001111
GPIO = 0x6B, // GPIO_INV = 0b00001000 Invert GPIO output
// GPIO_IN_EN=0b00000100 Enable GPIO input
// GPIO_OUT = 0b00000010 GPIO Output
// GPIO_IN = 0b00000001 GPIO Input
CFG20 = 0xD6, // FD_FIFO_8b=0b10000000 Enable 8bit FIFO mode for Flicker Detect (FD_TIME < 256)
// auto_SMUX= 0b01100000 Auto channel read-out
LED = 0xCD, // LED_ACT = 0b10000000 External LED (LDR) Control
// LED_DRIVE= 0b01111111 External LED drive strength (N - 4) >> 1
// Flicker Detection AGC Gain Max
// Max = 2^N (0 = 0.5x)
AGC_GAIN_MAX = 0xD7, // ADC_FD_GAIN_MAX = 0b11110000
AZ_CONFIG = 0xDE, // AT_NTH_ITERATION = 0b11111111 Auto-zero Frequency
// 0 - Never (Not Recommended)
// n - Every n integration cycles
// 255 - only before first measurement cycle
FD_TIME_1 = 0xE0, // FD_TIME=0b11111111 Flicker Detection Integration Time (Do not change if FDEN = 1 & PON = 1)
FD_TIME_2 = 0xE2, // FD_GAIN=0b11111000 Flicker Detection Gain (0 = 0.5x, 1 = 1x, 2 = 2x, 12 = 2048x)
// FD_TIME=0b00000111 Flicker Detection Time (Do not change if FDEN = 1 & PON = 1)
FD_CFG0 = 0xDF, // FIFO_WRITE_FD = 0b10000000 Write flicker raw data to FIFO (1 byte per sample)
FD_STATUS = 0xE3, // FD_VALID=0b00100000
// FD_SAT = 0b00010000
// FD_120HZ_VALID = 0b00001000
// FD_100HZ_VALID = 0b00000100
// FD_120HZ = 0b00000010
// FD_100HZ = 0b00000001
INTERNAB = 0xF9, // ASIEN = 0b10000000 Saturation Interrupt Enable
// SP_IEN = 0b00001000 Spectral Interrupt Enable
// FIEN = 0b00000100 FIFO Buffer Interrupt Enable
// SIEN = 0b00000001 System Interrupt Enable
CONTROL = 0xFA, // SW_RESET = 0b00001000 Software Reset
// SP_MAN_AZ= 0b00000100 Spectral Manual Auto-zero
// FIFO_CLR = 0b00000010 FIFO Buffer Clear
// CLEAR_SAI_ACT = 0b00000001 Clear sleep-after-interrupt
FIFO_MAP = 0xFC, // CH5 = 0b01000000
// CH4 = 0b00100000
// CH3 = 0b00010000
// CH2 = 0b00001000
// CH1 = 0b00000100
// CH0 = 0b00000010
// ASTATUS = 0b00000001
FIFO_LVL = 0xFD,
FDATA = 0xFE // 0xFFFF
};
constexpr uint8_t HARDWARE_ID = 0b10000001;
constexpr uint8_t CFG0_LOW_POWER = 0b00100000;
constexpr uint8_t CFG0_BANK = 0b00010000;
constexpr uint8_t CFG0_WLONG = 0b00000100;
constexpr uint8_t CFG20_6_CH = 0b00000000;
constexpr uint8_t CFG20_12_CH = 0b01000000;
constexpr uint8_t CFG20_18_CH = 0b01100000;
constexpr uint8_t ENABLE_FDEN = 0b01000000;
constexpr uint8_t ENABLE_SMUXEN = 0b00010000;
constexpr uint8_t ENABLE_WEN = 0b00001000;
constexpr uint8_t ENABLE_SP_EN = 0b00000010;
constexpr uint8_t ENABLE_PON = 0b00000001;
constexpr uint8_t FD_CFG0_FIFO_WRITE = 0b10000000;
constexpr uint8_t FD_VALID = 0b00100000;
constexpr uint8_t FD_SAT = 0b00010000;
constexpr uint8_t FD_120HZ_VALID = 0b00001000;
constexpr uint8_t FD_100HZ_VALID = 0b00000100;
constexpr uint8_t FD_120HZ = 0b00000010;
constexpr uint8_t FD_100HZ = 0b00000001;
constexpr uint8_t INTERNAB_ASIEN = 0b10000000;
constexpr uint8_t INTERNAB_SP_IEN = 0b00001000;
constexpr uint8_t INTERNAB_FIEN = 0b00000100;
constexpr uint8_t INTERNAB_SIEN = 0b00000001;
constexpr uint8_t CONTROL_SW_RESET = 0b00001000;
constexpr uint8_t CONTROL_SP_MAN_AZ = 0b00000100;
constexpr uint8_t CONTROL_FIFO_CLR = 0b00000010;
constexpr uint8_t CONTROL_CLEAR_SAI_ACT = 0b00000001;
constexpr uint8_t FIFO_MAP_CH5 = 0b01000000;
constexpr uint8_t FIFO_MAP_CH4 = 0b00100000;
constexpr uint8_t FIFO_MAP_CH3 = 0b00010000;
constexpr uint8_t FIFO_MAP_CH2 = 0b00001000;
constexpr uint8_t FIFO_MAP_CH1 = 0b00000100;
constexpr uint8_t FIFO_MAP_CH0 = 0b00000010;
constexpr uint8_t FIFO_MAP_ASTATUS = 0b00000001;
}

Wyświetl plik

@ -113,12 +113,6 @@ void Hub75::FM6126A_setup() {
void Hub75::start(irq_handler_t handler) {
if(handler) {
dma_channel = 0;
// Try as I might, I can't seem to coax MicroPython into leaving PIO in a known state upon soft reset
// check for claimed PIO and prepare a clean slate.
stop(handler);
if (panel_type == PANEL_FM6126A) {
FM6126A_setup();
}
@ -139,7 +133,7 @@ void Hub75::start(irq_handler_t handler) {
// Prevent flicker in Python caused by the smaller dataset just blasting through the PIO too quickly
pio_sm_set_clkdiv(pio, sm_data, width <= 32 ? 2.0f : 1.0f);
dma_channel_claim(dma_channel);
dma_channel = dma_claim_unused_channel(true);
dma_channel_config config = dma_channel_get_default_config(dma_channel);
channel_config_set_transfer_data_size(&config, DMA_SIZE_32);
channel_config_set_bswap(&config, false);
@ -148,15 +142,13 @@ void Hub75::start(irq_handler_t handler) {
// Same handler for both DMA channels
irq_set_exclusive_handler(DMA_IRQ_0, handler);
irq_set_exclusive_handler(DMA_IRQ_1, handler);
irq_add_shared_handler(DMA_IRQ_0, handler, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
dma_channel_set_irq0_enabled(dma_channel, true);
irq_set_enabled(pio_get_dreq(pio, sm_data, true), true);
irq_set_enabled(DMA_IRQ_0, true);
row = 0;
bit = 0;
@ -169,10 +161,9 @@ void Hub75::start(irq_handler_t handler) {
void Hub75::stop(irq_handler_t handler) {
irq_set_enabled(DMA_IRQ_0, false);
irq_set_enabled(DMA_IRQ_1, false);
irq_set_enabled(pio_get_dreq(pio, sm_data, true), false);
if(dma_channel_is_claimed(dma_channel)) {
if(dma_channel != -1 && dma_channel_is_claimed(dma_channel)) {
dma_channel_set_irq0_enabled(dma_channel, false);
irq_remove_handler(DMA_IRQ_0, handler);
//dma_channel_wait_for_finish_blocking(dma_channel);
@ -184,17 +175,21 @@ void Hub75::stop(irq_handler_t handler) {
if(pio_sm_is_claimed(pio, sm_data)) {
pio_sm_set_enabled(pio, sm_data, false);
pio_sm_drain_tx_fifo(pio, sm_data);
pio_remove_program(pio, &hub75_data_rgb888_program, data_prog_offs);
pio_sm_unclaim(pio, sm_data);
}
if(pio_sm_is_claimed(pio, sm_row)) {
pio_sm_set_enabled(pio, sm_row, false);
pio_sm_drain_tx_fifo(pio, sm_row);
if (inverted_stb) {
pio_remove_program(pio, &hub75_row_inverted_program, row_prog_offs);
} else {
pio_remove_program(pio, &hub75_row_program, row_prog_offs);
}
pio_sm_unclaim(pio, sm_row);
}
pio_clear_instruction_memory(pio);
// Make sure the GPIO is in a known good state
// since we don't know what the PIO might have done with it
gpio_put_masked(0b111111 << pin_r0, 0);

Wyświetl plik

@ -73,7 +73,7 @@ class Hub75 {
Pixel background = 0;
// DMA & PIO
uint dma_channel = 0;
int dma_channel = -1;
uint bit = 0;
uint row = 0;

Wyświetl plik

@ -47,8 +47,9 @@ namespace pimoroni {
return !(sr.read() & 128);
}
void Inky73::busy_wait() {
while(is_busy()) {
void Inky73::busy_wait(uint timeout_ms) {
absolute_time_t timeout = make_timeout_time_ms(timeout_ms);
while(is_busy() && !time_reached(timeout)) {
tight_loop_contents();
}
}

Wyświetl plik

@ -70,7 +70,7 @@ namespace pimoroni {
// Methods
//--------------------------------------------------
public:
void busy_wait();
void busy_wait(uint timeout_ms=45000);
void reset();
void power_off();

Wyświetl plik

@ -89,7 +89,6 @@ namespace pimoroni {
if(width == 320 && height == 240) {
command(reg::GCTRL, 1, "\x35");
command(reg::VCOMS, 1, "\x1f");
command(0xd6, 1, "\xa1"); // ???
command(reg::GMCTRP1, 14, "\xD0\x08\x11\x08\x0C\x15\x39\x33\x50\x36\x13\x14\x29\x2D");
command(reg::GMCTRN1, 14, "\xD0\x08\x10\x08\x06\x06\x39\x44\x51\x0B\x16\x14\x2F\x31");
}
@ -134,8 +133,6 @@ namespace pimoroni {
void ST7789::configure_display(Rotation rotate) {
bool rotate180 = rotate == ROTATE_180 || rotate == ROTATE_90;
if(rotate == ROTATE_90 || rotate == ROTATE_270) {
std::swap(width, height);
}
@ -186,20 +183,30 @@ namespace pimoroni {
// Pico Display
if(width == 240 && height == 135) {
caset[0] = 40; // 240 cols
caset[1] = 279;
raset[0] = 53; // 135 rows
raset[1] = 187;
madctl = rotate180 ? MADCTL::ROW_ORDER : MADCTL::COL_ORDER;
caset[1] = 40 + width - 1;
raset[0] = 52; // 135 rows
raset[1] = 52 + height - 1;
if (rotate == ROTATE_0) {
raset[0] += 1;
raset[1] += 1;
}
madctl = rotate == ROTATE_180 ? MADCTL::ROW_ORDER : MADCTL::COL_ORDER;
madctl |= MADCTL::SWAP_XY | MADCTL::SCAN_ORDER;
}
// Pico Display at 90 degree rotation
if(width == 135 && height == 240) {
caset[0] = 52; // 135 cols
caset[1] = 186;
caset[1] = 52 + width - 1;
raset[0] = 40; // 240 rows
raset[1] = 279;
madctl = rotate180 ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
raset[1] = 40 + height - 1;
madctl = 0;
if (rotate == ROTATE_90) {
caset[0] += 1;
caset[1] += 1;
madctl = MADCTL::COL_ORDER | MADCTL::ROW_ORDER;
}
madctl = rotate == ROTATE_90 ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
}
// Pico Display 2.0
@ -208,7 +215,7 @@ namespace pimoroni {
caset[1] = 319;
raset[0] = 0;
raset[1] = 239;
madctl = rotate180 ? MADCTL::ROW_ORDER : MADCTL::COL_ORDER;
madctl = (rotate == ROTATE_180 || rotate == ROTATE_90) ? MADCTL::ROW_ORDER : MADCTL::COL_ORDER;
madctl |= MADCTL::SWAP_XY | MADCTL::SCAN_ORDER;
}
@ -218,7 +225,7 @@ namespace pimoroni {
caset[1] = 239;
raset[0] = 0;
raset[1] = 319;
madctl = rotate180 ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
madctl = (rotate == ROTATE_180 || rotate == ROTATE_90) ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
}
// Byte swap the 16bit rows/cols values

Wyświetl plik

@ -19,6 +19,7 @@ add_subdirectory(breakout_bme688)
add_subdirectory(breakout_bmp280)
add_subdirectory(breakout_bme280)
add_subdirectory(breakout_as7262)
add_subdirectory(as7343)
add_subdirectory(breakout_bh1745)
add_subdirectory(breakout_icp10125)
add_subdirectory(breakout_scd41)

Wyświetl plik

@ -0,0 +1 @@
include("${CMAKE_CURRENT_LIST_DIR}/as7343_demo.cmake")

Wyświetl plik

@ -0,0 +1,16 @@
set(OUTPUT_NAME as7343_demo)
add_executable(
${OUTPUT_NAME}
as7343_demo.cpp
)
# enable usb output, disable uart output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_enable_stdio_uart(${OUTPUT_NAME} 1)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME} pico_stdlib as7343)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,69 @@
#include "pico/stdlib.h"
#include "common/pimoroni_common.hpp"
#include "as7343.hpp"
using namespace pimoroni;
I2C i2c(6, 7);
AS7343 as7343(&i2c);
int main() {
stdio_init_all();
printf("AS7343 Demo\n");
as7343.init();
printf("Init done...\n");
uint8_t aux_id;
uint8_t revision_id;
uint8_t hardware_id;
as7343.get_version(aux_id, revision_id, hardware_id);
printf("Aux: %d, Rev: %d, HW: %d\n", aux_id, revision_id, hardware_id);
printf("set_channels\n");
as7343.set_channels(AS7343::channel_count::EIGHTEEN_CHANNEL);
printf("set_gain\n");
as7343.set_gain(1024);
printf("set_measurement_time\n");
as7343.set_measurement_time(500);
printf("set_integration_time\n");
as7343.set_integration_time(27800);
printf("set_illumination_current\n");
as7343.set_illumination_current(4);
printf("set_illumination_led\n");
as7343.set_illumination_led(true);
printf("start...\n");
while(true) {
AS7343::reading reading = as7343.read();
printf("FZ: %d FY: %d FXL: %d NIR: %d F2 %d F3: %d F4: %d F5: %d F1: %d F5: %d F7: %d F8: %d \n",
reading.FZ,
reading.FY,
reading.FXL,
reading.NIR,
reading.F2,
reading.F3,
reading.F4,
reading.F6,
reading.F1,
reading.F5,
reading.F7,
reading.F8
);
sleep_ms(1000);
}
return 0;
}

Wyświetl plik

@ -25,7 +25,7 @@ int main() {
while (1) {
BME280::bme280_reading result = bme280.read_forced();
printf("%s %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", result.status == BME280_OK ? "OK" : "ER", result.temperature, result.pressure, result.humidity);
printf("%s %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", result.status ? "OK" : "ER", result.temperature, result.pressure, result.humidity);
sleep_ms(1000);
}

Wyświetl plik

@ -30,7 +30,7 @@ int main() {
// }
// }
graphics.set_pen(1);
graphics.set_pen(15);
graphics.clear();
float s = (sin(i / 10.0f) * 1.0f) + 1.5f;

Wyświetl plik

@ -34,10 +34,15 @@ int main() {
while(true) {
offset += float(SPEED) / 2000.0f;
if (offset > 1.0) {
offset -= 1.0;
}
for(auto i = 0u; i < NUM_LEDS; ++i) {
float hue = float(i) / NUM_LEDS;
led_strip.set_hsv(i, hue + offset, 1.0f, 1.0f);
hue += offset;
hue -= floor(hue);
led_strip.set_hsv(i, hue, 1.0f, 1.0f);
}
sleep_ms(1000 / UPDATES);

Wyświetl plik

@ -45,7 +45,7 @@ int main() {
while(true) {
BME280::bme280_reading result = bme.read_forced();
printf("%s %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", result.status == BME280_OK ? "OK" : "ER", result.temperature, result.pressure, result.humidity);
printf("%s %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", result.status ? "OK" : "ER", result.temperature, result.pressure, result.humidity);
// calculates a colour
float hue = HUE_START + ((float)(result.temperature - MIN) * (float)(HUE_END - HUE_START) / (float)(MAX - MIN));

Wyświetl plik

@ -32,11 +32,11 @@ ST7789 st7789(
PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr);
Button button_a(Tufty2040::A);
Button button_b(Tufty2040::B);
Button button_c(Tufty2040::C);
Button button_up(Tufty2040::UP);
Button button_down(Tufty2040::DOWN);
Button button_a(Tufty2040::A, Polarity::ACTIVE_HIGH);
Button button_b(Tufty2040::B, Polarity::ACTIVE_HIGH);
Button button_c(Tufty2040::C, Polarity::ACTIVE_HIGH);
Button button_up(Tufty2040::UP, Polarity::ACTIVE_HIGH);
Button button_down(Tufty2040::DOWN, Polarity::ACTIVE_HIGH);
uint32_t time() {
absolute_time_t t = get_absolute_time();

Wyświetl plik

@ -20,9 +20,9 @@ namespace pimoroni {
static const uint8_t LED_B = 2;
static const uint8_t MICS_VREF = 14;
static const uint8_t MICS_RED = 12;
static const uint8_t MICS_RED = 13;
static const uint8_t MICS_NH3 = 11;
static const uint8_t MICS_OX = 13;
static const uint8_t MICS_OX = 12;
static const uint8_t MICS_HEATER_EN = 1;
static const bool INVERT_OUTPUT = true; //true for common cathode, false for common anode

Wyświetl plik

@ -494,11 +494,14 @@ namespace pimoroni {
void CosmicUnicorn::set_brightness(float value) {
value = value < 0.0f ? 0.0f : value;
value = value > 1.0f ? 1.0f : value;
// Max brightness is - in fact - 256 since it's applied with:
// result = (channel * brightness) >> 8
// eg: (255 * 256) >> 8 == 255
this->brightness = floor(value * 256.0f);
}
float CosmicUnicorn::get_brightness() {
return this->brightness / 255.0f;
return this->brightness / 256.0f;
}
void CosmicUnicorn::adjust_brightness(float delta) {

Wyświetl plik

@ -488,11 +488,14 @@ namespace pimoroni {
void GalacticUnicorn::set_brightness(float value) {
value = value < 0.0f ? 0.0f : value;
value = value > 1.0f ? 1.0f : value;
// Max brightness is - in fact - 256 since it's applied with:
// result = (channel * brightness) >> 8
// eg: (255 * 256) >> 8 == 255
this->brightness = floor(value * 256.0f);
}
float GalacticUnicorn::get_brightness() {
return this->brightness / 255.0f;
return this->brightness / 256.0f;
}
void GalacticUnicorn::adjust_brightness(float delta) {

Wyświetl plik

@ -47,6 +47,10 @@ namespace motor {
const uint LED_DATA = 18;
const uint NUM_LEDS = 1;
const uint I2C_INT = 19;
const uint I2C_SDA = 20;
const uint I2C_SCL = 21;
const uint USER_SW = 23;
const uint ADC_ADDR_0 = 22;

Wyświetl plik

@ -268,7 +268,7 @@ namespace pimoroni {
int32_t ex = points[j].x;
int32_t px = int32_t(sx + float(fy - sy) / float(ey - sy) * float(ex - sx));
nodes[n++] = px < clip.x ? clip.x : (px >= clip.x + clip.w ? clip.x + clip.w - 1 : px);// clamp(int32_t(sx + float(fy - sy) / float(ey - sy) * float(ex - sx)), clip.x, clip.x + clip.w);
nodes[n++] = px;
}
}

Wyświetl plik

@ -15,7 +15,7 @@ namespace pimoroni {
}
void PicoGraphics_Pen1BitY::set_pen(uint8_t r, uint8_t g, uint8_t b) {
color = std::max(r, std::max(g, b));
color = std::max(r, std::max(g, b)) >> 4;
}
void PicoGraphics_Pen1BitY::set_pixel(const Point &p) {

Wyświetl plik

@ -30,6 +30,10 @@ namespace servo {
const uint LED_DATA = 18;
const uint NUM_LEDS = 6;
const uint I2C_INT = 19;
const uint I2C_SDA = 20;
const uint I2C_SCL = 21;
const uint USER_SW = 23;
const uint ADC_ADDR_0 = 22;

Wyświetl plik

@ -485,11 +485,14 @@ namespace pimoroni {
void StellarUnicorn::set_brightness(float value) {
value = value < 0.0f ? 0.0f : value;
value = value > 1.0f ? 1.0f : value;
// Max brightness is - in fact - 256 since it's applied with:
// result = (channel * brightness) >> 8
// eg: (255 * 256) >> 8 == 255
this->brightness = floor(value * 256.0f);
}
float StellarUnicorn::get_brightness() {
return this->brightness / 255.0f;
return this->brightness / 256.0f;
}
void StellarUnicorn::adjust_brightness(float delta) {

Wyświetl plik

@ -0,0 +1,20 @@
{
"deploy": [
"../deploy.md"
],
"docs": "",
"features": [
"Breadboard friendly",
"Castellated Pads",
"Micro USB"
],
"id": "rp2-pico",
"images": [
"rp2-pico.jpg"
],
"mcu": "rp2040",
"product": "Pico",
"thumbnail": "",
"url": "https://www.raspberrypi.com/products/raspberry-pi-pico/",
"vendor": "Raspberry Pi"
}

Wyświetl plik

@ -0,0 +1,10 @@
include("$(PORT_DIR)/boards/manifest.py")
include("../manifest_pico.py")
require("usb-device")
require("usb-device-hid")
require("usb-device-cdc")
require("usb-device-keyboard")
require("usb-device-mouse")
require("usb-device-midi")

Wyświetl plik

@ -0,0 +1,7 @@
# cmake file for Raspberry Pi Pico
set(PICO_BOARD "pico")
# Board specific version of the frozen manifest
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
set(MICROPY_C_HEAP_SIZE 4096)

Wyświetl plik

@ -0,0 +1,4 @@
// Board and hardware specific configuration
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
#define MICROPY_HW_FLASH_STORAGE_BYTES (1024 * 1024)
#define MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE 1

Wyświetl plik

@ -0,0 +1,28 @@
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
LED,GPIO25
1 GP0 GPIO0
2 GP1 GPIO1
3 GP2 GPIO2
4 GP3 GPIO3
5 GP4 GPIO4
6 GP5 GPIO5
7 GP6 GPIO6
8 GP7 GPIO7
9 GP8 GPIO8
10 GP9 GPIO9
11 GP10 GPIO10
12 GP11 GPIO11
13 GP12 GPIO12
14 GP13 GPIO13
15 GP14 GPIO14
16 GP15 GPIO15
17 GP16 GPIO16
18 GP17 GPIO17
19 GP18 GPIO18
20 GP19 GPIO19
21 GP20 GPIO20
22 GP21 GPIO21
23 GP22 GPIO22
24 GP25 GPIO25
25 GP26 GPIO26
26 GP27 GPIO27
27 GP28 GPIO28
28 LED GPIO25

Wyświetl plik

@ -2,4 +2,4 @@ freeze("../modules_py", "gfx_pack.py")
freeze("../modules_py", "interstate75.py")
freeze("../modules_py", "pimoroni.py")
freeze("../modules_py", "boot.py")
freeze("../modules_py", "boot.py")

Wyświetl plik

@ -7,4 +7,6 @@ if [[ -f "$FIXUP_DIR/$BOARD/pico_sdk.patch" ]]; then
echo "Applying pico_sdk.patch"
cd $MPY_DIR/lib/pico-sdk
git apply "$FIXUP_DIR/$BOARD/pico_sdk.patch"
else
echo "Skipping patch. $FIXUP_DIR/$BOARD/pico_sdk.patch not found!"
fi

Wyświetl plik

@ -1,104 +1,3 @@
# Badger 2040 Examples <!-- omit in toc -->
:warning: This code has been deprecated in favour of a dedicated Badger 2040 project: https://github.com/pimoroni/badger2040
- [Function Examples](#function-examples)
- [Battery](#battery)
- [Button Test](#button-test)
- [LED](#led)
- [Pin interrupt](#pin-interrupt)
- [Application Examples](#application-examples)
- [Badge](#badge)
- [Checklist](#checklist)
- [Clock](#clock)
- [E-Book](#e-book)
- [Fonts](#fonts)
- [Image](#image)
- [QR gen](#qr-gen)
- [Launcher](#launcher)
- [Conway](#conway)
## Function Examples
### Battery
[battery.py](battery.py)
An example of how to read the battery voltage and display a battery level indicator.
### Button Test
[button_test.py](button_test.py)
An example of how to read Badger2040's buttons and display a unique message for each.
### LED
[led.py](led.py)
Blinks Badger's LED on and off.
### Pin interrupt
[pin_interrupt.py](pin_interrupt.py)
An example of drawing text and graphics and using the buttons.
## Application Examples
### Badge
[badge.py](badge.py)
Create your own name badge! This application looks for two files on your MicroPython drive:
* `badge.txt` - A text file containing 6 lines, corresponding to the 6 different pieces of text on the badge
* `badge-image.bin` - A 104x128px 1-bit colour depth image to display alongside the text. You can use `examples/badger2040/image_converter/convert.py` to convert them:
```shell
python3 convert.py --binary --resize image_file_1.png image_file_2.png image_file_3.png
```
### Checklist
[list.py](list.py)
A checklist application, letting you navigate through items and tick each of them off.
* `checklist.txt` - A text file containing the titles of items for the list.
### Clock
[clock.py](clock.py)
A simple clock showing the time and date, that uses the E Ink's fast speed to update every second.
### E-Book
[ebook.py](ebook.py)
A mini text file e-reader. Comes pre-loaded with an excerpt of The Wind In the Willows.
### Fonts
[fonts.py](fonts.py)
A demonstration of the various fonts that can be used in your programs.
### Image
[image.py](image.py)
An image gallery. Displays and lets you cycle through any images stored within the MicroPython device's `/images` directory. Images must be 296x128 pixels with 1-bit colour depth. You can use `examples/badger2040/image_converter/convert.py` to convert them:
```shell
python3 convert.py --binary --resize image_file_1.png image_file_2.png image_file_3.png
```
### QR gen
[qrgen.py](qrgen.py)
Displays and lets you cycle through multiple QR codes, with configuration stored in text files within the MicroPython device's `/qrcodes` directory.
- `/qrcodes/qrcode.txt` - A text file containing 9 lines. The first line should be a URL which will be converted into and displayed as a QR code. Up to 8 more lines of information can be added, which will be shown as plain text to the right of the QR code.
- `/qrcodes/*.txt` - additional text files can be created using the same format. All text files can be cycled through.
### Launcher
[launcher.py](launcher.py)
A launcher-style application, providing a menu of other applications that can be loaded, as well as information such as battery level.
### Conway
[conway.py](conway.py)
Conway's classic Game of Life, implemented on the Badger. Note: this application is *not* linked from the Launcher by default - it can be run directly using Thonny or your MicroPython editor of choice, or you can modify the Launcher to add it (you'll want to update `launchericons.png` as well)

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.4 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 36 KiB

Wyświetl plik

@ -1,6 +0,0 @@
try:
open("main.py", "r")
except OSError:
with open("main.py", "w") as f:
f.write("import _launcher")
f.flush()

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 9.7 KiB

Wyświetl plik

@ -1,183 +0,0 @@
import time
import badger2040
import badger_os
# Global Constants
WIDTH = badger2040.WIDTH
HEIGHT = badger2040.HEIGHT
IMAGE_WIDTH = 104
COMPANY_HEIGHT = 30
DETAILS_HEIGHT = 20
NAME_HEIGHT = HEIGHT - COMPANY_HEIGHT - (DETAILS_HEIGHT * 2) - 2
TEXT_WIDTH = WIDTH - IMAGE_WIDTH - 1
COMPANY_TEXT_SIZE = 0.6
DETAILS_TEXT_SIZE = 0.5
LEFT_PADDING = 5
NAME_PADDING = 20
DETAIL_SPACING = 10
DEFAULT_TEXT = """mustelid inc
H. Badger
RP2040
2MB Flash
E ink
296x128px"""
BADGE_IMAGE = bytearray(int(IMAGE_WIDTH * HEIGHT / 8))
try:
open("badge-image.bin", "rb").readinto(BADGE_IMAGE)
except OSError:
try:
import badge_image
BADGE_IMAGE = bytearray(badge_image.data())
del badge_image
except ImportError:
pass
# ------------------------------
# Utility functions
# ------------------------------
# Reduce the size of a string until it fits within a given width
def truncatestring(text, text_size, width):
while True:
length = display.measure_text(text, text_size)
if length > 0 and length > width:
text = text[:-1]
else:
text += ""
return text
# ------------------------------
# Drawing functions
# ------------------------------
# Draw the badge, including user text
def draw_badge():
display.pen(0)
display.clear()
# Draw badge image
display.image(BADGE_IMAGE, IMAGE_WIDTH, HEIGHT, WIDTH - IMAGE_WIDTH, 0)
# Draw a border around the image
display.pen(0)
display.thickness(1)
display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - 1, 0)
display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - IMAGE_WIDTH, HEIGHT - 1)
display.line(WIDTH - IMAGE_WIDTH, HEIGHT - 1, WIDTH - 1, HEIGHT - 1)
display.line(WIDTH - 1, 0, WIDTH - 1, HEIGHT - 1)
# Uncomment this if a white background is wanted behind the company
# display.pen(15)
# display.rectangle(1, 1, TEXT_WIDTH, COMPANY_HEIGHT - 1)
# Draw the company
display.pen(15) # Change this to 0 if a white background is used
display.font("serif")
display.thickness(3)
display.text(company, LEFT_PADDING, (COMPANY_HEIGHT // 2) + 1, COMPANY_TEXT_SIZE)
# Draw a white background behind the name
display.pen(15)
display.thickness(1)
display.rectangle(1, COMPANY_HEIGHT + 1, TEXT_WIDTH, NAME_HEIGHT)
# Draw the name, scaling it based on the available width
display.pen(0)
display.font("sans")
display.thickness(4)
name_size = 2.0 # A sensible starting scale
while True:
name_length = display.measure_text(name, name_size)
if name_length >= (TEXT_WIDTH - NAME_PADDING) and name_size >= 0.1:
name_size -= 0.01
else:
display.text(name, (TEXT_WIDTH - name_length) // 2, (NAME_HEIGHT // 2) + COMPANY_HEIGHT + 1, name_size)
break
# Draw a white backgrounds behind the details
display.pen(15)
display.thickness(1)
display.rectangle(1, HEIGHT - DETAILS_HEIGHT * 2, TEXT_WIDTH, DETAILS_HEIGHT - 1)
display.rectangle(1, HEIGHT - DETAILS_HEIGHT, TEXT_WIDTH, DETAILS_HEIGHT - 1)
# Draw the first detail's title and text
display.pen(0)
display.font("sans")
display.thickness(3)
name_length = display.measure_text(detail1_title, DETAILS_TEXT_SIZE)
display.text(detail1_title, LEFT_PADDING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), DETAILS_TEXT_SIZE)
display.thickness(2)
display.text(detail1_text, 5 + name_length + DETAIL_SPACING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), DETAILS_TEXT_SIZE)
# Draw the second detail's title and text
display.thickness(3)
name_length = display.measure_text(detail2_title, DETAILS_TEXT_SIZE)
display.text(detail2_title, LEFT_PADDING, HEIGHT - (DETAILS_HEIGHT // 2), DETAILS_TEXT_SIZE)
display.thickness(2)
display.text(detail2_text, LEFT_PADDING + name_length + DETAIL_SPACING, HEIGHT - (DETAILS_HEIGHT // 2), DETAILS_TEXT_SIZE)
# ------------------------------
# Program setup
# ------------------------------
# Create a new Badger and set it to update NORMAL
display = badger2040.Badger2040()
display.led(128)
display.update_speed(badger2040.UPDATE_NORMAL)
# Open the badge file
try:
badge = open("badge.txt", "r")
except OSError:
with open("badge.txt", "w") as f:
f.write(DEFAULT_TEXT)
f.flush()
badge = open("badge.txt", "r")
# Read in the next 6 lines
company = badge.readline() # "mustelid inc"
name = badge.readline() # "H. Badger"
detail1_title = badge.readline() # "RP2040"
detail1_text = badge.readline() # "2MB Flash"
detail2_title = badge.readline() # "E ink"
detail2_text = badge.readline() # "296x128px"
# Truncate all of the text (except for the name as that is scaled)
company = truncatestring(company, COMPANY_TEXT_SIZE, TEXT_WIDTH)
detail1_title = truncatestring(detail1_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail1_text = truncatestring(detail1_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail1_title, DETAILS_TEXT_SIZE))
detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE))
# ------------------------------
# Main program
# ------------------------------
draw_badge()
while True:
if display.pressed(badger2040.BUTTON_A) or display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C) or display.pressed(badger2040.BUTTON_UP) or display.pressed(badger2040.BUTTON_DOWN):
badger_os.warning(display, "To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt")
time.sleep(4)
draw_badge()
display.update()
# If on battery, halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -1,183 +0,0 @@
"""Keep track of app state in persistent flash storage."""
import os
import gc
import time
import json
import machine
import badger2040
def get_battery_level():
# 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[1:])
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:
try:
__import__(file[1:]) # Try to import _[file] (drop underscore prefix)
except ImportError:
__import__(file) # Failover to importing [_file]
except ImportError:
# If the app doesn't exist, notify the user
warning(None, "Could not launch: " + file[1:])
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 - 40, height=badger2040.HEIGHT - 40, line_spacing=20, text_size=0.6):
if display is None:
display = badger2040.Badger2040()
display.led(128)
# Draw a light grey background
display.pen(12)
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.pen(0)
display.thickness(2)
# 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, text_size)
display.update()

Wyświetl plik

@ -1,163 +0,0 @@
import badger2040
from machine import Pin, ADC
import time
# Global Constants
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
MAX_BATTERY_VOLTAGE = 4.0
MIN_BATTERY_VOLTAGE = 3.2
WIDTH = badger2040.WIDTH
HEIGHT = badger2040.HEIGHT
BATT_WIDTH = 200
BATT_HEIGHT = 100
BATT_BORDER = 10
BATT_TERM_WIDTH = 20
BATT_TERM_HEIGHT = 50
BATT_BAR_PADDING = 10
BATT_BAR_HEIGHT = BATT_HEIGHT - (BATT_BORDER * 2) - (BATT_BAR_PADDING * 2)
BATT_BAR_START = ((WIDTH - BATT_WIDTH) // 2) + BATT_BORDER + BATT_BAR_PADDING
BATT_BAR_END = ((WIDTH + BATT_WIDTH) // 2) - BATT_BORDER - BATT_BAR_PADDING
NUM_BATT_BARS = 4
# ------------------------------
# Utility functions
# ------------------------------
def map_value(input, in_min, in_max, out_min, out_max):
return (((input - in_min) * (out_max - out_min)) / (in_max - in_min)) + out_min
# ------------------------------
# Drawing functions
# ------------------------------
# Draw the frame of the reader
def draw_battery(level, resolution):
display.pen(15)
display.clear()
display.thickness(1)
# Draw the battery outline
display.pen(0)
display.rectangle(
(WIDTH - BATT_WIDTH) // 2, (HEIGHT - BATT_HEIGHT) // 2, BATT_WIDTH, BATT_HEIGHT
)
display.rectangle(
(WIDTH + BATT_WIDTH) // 2,
(HEIGHT - BATT_TERM_HEIGHT) // 2,
BATT_TERM_WIDTH,
BATT_TERM_HEIGHT,
)
display.pen(15)
display.rectangle(
(WIDTH - BATT_WIDTH) // 2 + BATT_BORDER,
(HEIGHT - BATT_HEIGHT) // 2 + BATT_BORDER,
BATT_WIDTH - BATT_BORDER * 2,
BATT_HEIGHT - BATT_BORDER * 2,
)
# Add a special check for no battery
if level < 1:
X = WIDTH // 2
Y = HEIGHT // 2
display.pen(0)
display.thickness(1)
thickness = (BATT_BORDER * 3) // 2
start_extra = thickness // 3
end_extra = (thickness * 2) // 3
for i in range(0, thickness):
excess = i // 2
display.line(
X - (BATT_HEIGHT // 2) + i - excess - start_extra,
Y - (BATT_HEIGHT // 2) - excess - start_extra,
X + (BATT_HEIGHT // 2) + i - excess + end_extra,
Y + (BATT_HEIGHT // 2) - excess + end_extra,
)
display.pen(15)
for i in range(0 - thickness, 0):
display.line(
X - (BATT_HEIGHT // 2) + i,
Y - (BATT_HEIGHT // 2),
X + (BATT_HEIGHT // 2) + i,
Y + (BATT_HEIGHT // 2),
)
else:
# Draw the battery bars
display.pen(0)
length = (
BATT_BAR_END - BATT_BAR_START - ((NUM_BATT_BARS - 1) * BATT_BAR_PADDING)
) // NUM_BATT_BARS
current_level = 0.0
normalised_level = level / resolution
for i in range(NUM_BATT_BARS):
current_level = (1.0 * i) / NUM_BATT_BARS
if normalised_level > current_level:
pos = i * (length + BATT_BAR_PADDING)
display.rectangle(
BATT_BAR_START + pos,
(HEIGHT - BATT_BAR_HEIGHT) // 2,
length,
BATT_BAR_HEIGHT,
)
display.update()
# ------------------------------
# Program setup
# ------------------------------
# Create a new Badger and set it to update FAST
display = badger2040.Badger2040()
display.update_speed(badger2040.UPDATE_FAST)
# Set up the ADCs for measuring battery voltage
vbat_adc = ADC(badger2040.PIN_BATTERY)
vref_adc = ADC(badger2040.PIN_1V2_REF)
vref_en = Pin(badger2040.PIN_VREF_POWER)
vref_en.init(Pin.OUT)
vref_en.value(0)
# ------------------------------
# Main program loop
# ------------------------------
last_level = -1
while True:
# 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)
# Print out the voltage
print("Battery Voltage = ", vbat, "V", sep="")
# Convert the voltage to a level to display onscreen
level = int(
map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, NUM_BATT_BARS)
)
# Only draw if the battery level has changed significantly
if level != last_level:
draw_battery(level, NUM_BATT_BARS)
last_level = level
time.sleep(1)

Wyświetl plik

@ -1,67 +0,0 @@
import badger2040
import machine
import time
display = badger2040.Badger2040()
display.update_speed(badger2040.UPDATE_TURBO)
display.pen(15)
display.clear()
display.update()
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
# the User button (boot/usr on back of board) is inverted from the others
button_user = machine.Pin(badger2040.BUTTON_USER, machine.Pin.IN, machine.Pin.PULL_UP)
message = None
message_y = 60
def button(pin):
global message
if message is not None:
return
if pin == button_a:
message = "Button a"
return
if pin == button_b:
message = "Button b"
return
if pin == button_c:
message = "Button c"
return
if pin == button_up:
message = "Button Up"
return
if pin == button_down:
message = "Button Down"
return
if pin == button_user:
message = "Button Usr"
return
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_user.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
while True:
if message is not None:
display.pen(15)
display.clear()
display.pen(0)
display.thickness(4)
display.text(message, 6, message_y, 1.4)
for _ in range(2):
display.update()
message = None
time.sleep(0.1)

Wyświetl plik

@ -1,154 +0,0 @@
import time
import machine
import badger2040
# We're going to keep the badger on, so slow down the system clock if on battery
badger2040.system_speed(badger2040.SYSTEM_SLOW)
rtc = machine.RTC()
display = badger2040.Badger2040()
display.led(128)
display.update_speed(badger2040.UPDATE_TURBO)
display.font("gothic")
cursors = ["year", "month", "day", "hour", "minute"]
set_clock = False
cursor = 0
last = 0
# Set up the buttons
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
def days_in_month(month, year):
if month == 2 and ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0):
return 29
return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month - 1]
# Button handling function
def button(pin):
global last, set_clock, cursor, year, month, day, hour, minute
time.sleep(0.01)
if not pin.value():
return
if button_a.value() and button_c.value():
machine.reset()
adjust = 0
changed = False
if pin == button_b:
set_clock = not set_clock
changed = True
if not set_clock:
rtc.datetime((year, month, day, 0, hour, minute, second, 0))
if set_clock:
if pin == button_c:
cursor += 1
cursor %= len(cursors)
if pin == button_a:
cursor -= 1
cursor %= len(cursors)
if pin == button_up:
adjust = 1
if pin == button_down:
adjust = -1
if cursors[cursor] == "year":
year += adjust
year = max(year, 2022)
day = min(day, days_in_month(month, year))
if cursors[cursor] == "month":
month += adjust
month = min(max(month, 1), 12)
day = min(day, days_in_month(month, year))
if cursors[cursor] == "day":
day += adjust
day = min(max(day, 1), days_in_month(month, year))
if cursors[cursor] == "hour":
hour += adjust
hour %= 24
if cursors[cursor] == "minute":
minute += adjust
minute %= 60
if set_clock or changed:
draw_clock()
# Register the button handling function with the buttons
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
def draw_clock():
hms = "{:02}:{:02}:{:02}".format(hour, minute, second)
ymd = "{:04}/{:02}/{:02}".format(year, month, day)
hms_width = display.measure_text(hms, 1.8)
hms_offset = int((badger2040.WIDTH / 2) - (hms_width / 2))
h_width = display.measure_text(hms[0:2], 1.8)
mi_width = display.measure_text(hms[3:5], 1.8)
mi_offset = display.measure_text(hms[0:3], 1.8)
ymd_width = display.measure_text(ymd, 1.0)
ymd_offset = int((badger2040.WIDTH / 2) - (ymd_width / 2))
y_width = display.measure_text(ymd[0:4], 1.0)
m_width = display.measure_text(ymd[5:7], 1.0)
m_offset = display.measure_text(ymd[0:5], 1.0)
d_width = display.measure_text(ymd[8:10], 1.0)
d_offset = display.measure_text(ymd[0:8], 1.0)
display.pen(15)
display.clear()
display.pen(0)
display.thickness(5)
display.text(hms, hms_offset, 40, 1.8)
display.thickness(3)
display.text(ymd, ymd_offset, 100, 1.0)
if set_clock:
if cursors[cursor] == "year":
display.line(ymd_offset, 120, ymd_offset + y_width, 120)
if cursors[cursor] == "month":
display.line(ymd_offset + m_offset, 120, ymd_offset + m_offset + m_width, 120)
if cursors[cursor] == "day":
display.line(ymd_offset + d_offset, 120, ymd_offset + d_offset + d_width, 120)
if cursors[cursor] == "hour":
display.line(hms_offset, 70, hms_offset + h_width, 70)
if cursors[cursor] == "minute":
display.line(hms_offset + mi_offset, 70, hms_offset + mi_offset + mi_width, 70)
display.update()
year, month, day, wd, hour, minute, second, _ = rtc.datetime()
if (year, month, day) == (2021, 1, 1):
rtc.datetime((2022, 2, 28, 0, 12, 0, 0, 0))
last_second = second
while True:
if not set_clock:
year, month, day, wd, hour, minute, second, _ = rtc.datetime()
if second != last_second:
draw_clock()
last_second = second
time.sleep(0.01)

Wyświetl plik

@ -1,215 +0,0 @@
import math
import time
from random import random
import machine
import badger2040
# Overclock the RP2040 to run the sim faster
badger2040.system_speed(badger2040.SYSTEM_TURBO)
# ------------------------------
# Program setup
# ------------------------------
# Global constants
CELL_SIZE = 6 # Size of cell in pixels
INITIAL_DENSITY = 0.3 # Density of cells at start
# Create a new Badger and set it to update TURBO
screen = badger2040.Badger2040()
screen.led(128)
screen.update_speed(badger2040.UPDATE_TURBO)
restart = False # should sim be restarted
# ------------------------------
# Button functions
# ------------------------------
# Button handling function
def button(pin):
global restart
# if 'a' button is pressed, restart the sim
if pin == button_a:
restart = True
# Set up button
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
# ------------------------------
# Screen functions
# ------------------------------
# Remove everything from the screen
def init_screen():
screen.update_speed(badger2040.UPDATE_NORMAL)
screen.pen(15)
screen.clear()
screen.update()
screen.update_speed(badger2040.UPDATE_TURBO)
# ------------------------------
# Classes
# ------------------------------
# Define a 'cell'
class Cell:
def __init__(self):
self._alive = False
def make_alive(self):
self._alive = True
def make_dead(self):
self._alive = False
def is_alive(self):
return self._alive
# Define the whole board
class Board:
def __init__(self):
self._rows = math.floor(badger2040.WIDTH / CELL_SIZE)
self._columns = math.floor(badger2040.HEIGHT / CELL_SIZE)
self._grid = [[Cell() for _ in range(self._columns)] for _ in range(self._rows)]
self._initialise_board()
# Draw the board to the screen
def draw_board(self):
row_idx = 0
column_idx = 0
for row in self._grid:
column_idx = 0
for cell in row:
if cell.is_alive():
screen.pen(0)
else:
screen.pen(15)
screen.rectangle(
row_idx * CELL_SIZE, column_idx * CELL_SIZE, CELL_SIZE, CELL_SIZE
)
column_idx += 1
row_idx += 1
screen.update()
# Generate the first iteration of the board
def _initialise_board(self):
for row in self._grid:
for cell in row:
if random() <= INITIAL_DENSITY:
cell.make_alive()
# Get the neighbour cells for a given cell
def get_neighbours(self, current_row, current_column):
# Cells either side of current cell
neighbour_min = -1
neighbour_max = 2
neighbours = []
for row in range(neighbour_min, neighbour_max):
for column in range(neighbour_min, neighbour_max):
neighbour_row = current_row + row
neighbour_column = current_column + column
# Don't count the current cell
if not (
neighbour_row == current_row and neighbour_column == current_column
):
# It's a toroidal world so go all the way round if necessary
if (neighbour_row) < 0:
neighbour_row = self._rows - 1
elif (neighbour_row) >= self._rows:
neighbour_row = 0
if (neighbour_column) < 0:
neighbour_column = self._columns - 1
elif (neighbour_column) >= self._columns:
neighbour_column = 0
neighbours.append(self._grid[neighbour_row][neighbour_column])
return neighbours
# Calculate the next generation
def create_next_generation(self):
to_alive = []
to_dead = []
changed = False
for row in range(len(self._grid)):
for column in range(len(self._grid[row])):
# Get all the neighours that are alive
alive_neighbours = []
for neighbour_cell in self.get_neighbours(row, column):
if neighbour_cell.is_alive():
alive_neighbours.append(neighbour_cell)
current_cell = self._grid[row][column]
# Apply the Conway GoL rules (B3/S23)
if current_cell.is_alive():
if len(alive_neighbours) < 2 or len(alive_neighbours) > 3:
to_dead.append(current_cell)
if len(alive_neighbours) == 3 or len(alive_neighbours) == 2:
to_alive.append(current_cell)
else:
if len(alive_neighbours) == 3:
to_alive.append(current_cell)
for cell in to_alive:
if not cell.is_alive():
# The board has changed since the previous generation
changed = True
cell.make_alive()
for cell in to_dead:
if cell.is_alive():
# The board has changed since the previous generation
changed = True
cell.make_dead()
return changed
# ------------------------------
# Main program loop
# ------------------------------
def main():
global restart
init_screen()
board = Board()
board.draw_board()
time.sleep(0.5)
while True:
# The 'a' button has been pressed so restart sim
if restart:
init_screen()
restart = False
board = Board()
board.draw_board()
time.sleep(0.5)
# The board didn't update since the previous generation
if not board.create_next_generation():
screen.update_speed(badger2040.UPDATE_NORMAL)
board.draw_board()
screen.update_speed(badger2040.UPDATE_TURBO)
time.sleep(5)
restart = True
# Draw the next generation
else:
board.draw_board()
main()

Wyświetl plik

@ -1,263 +0,0 @@
import badger2040
import time
import gc
import badger_os
# **** Put the name of your text file here *****
text_file = "book.txt" # File must be on the MicroPython device
try:
open(text_file, "r")
except OSError:
try:
# If the specified file doesn't exist,
# pre-populate with Wind In The Willows
import witw
with open(text_file, "wb") as f:
f.write(witw.data())
f.flush()
time.sleep(0.1)
del witw
except ImportError:
pass
gc.collect()
# Global Constants
WIDTH = badger2040.WIDTH
HEIGHT = badger2040.HEIGHT
ARROW_THICKNESS = 3
ARROW_WIDTH = 18
ARROW_HEIGHT = 14
ARROW_PADDING = 2
TEXT_PADDING = 4
TEXT_WIDTH = WIDTH - TEXT_PADDING - TEXT_PADDING - ARROW_WIDTH
FONTS = ["sans", "gothic", "cursive", "serif"]
FONT_THICKNESSES = [2, 1, 1, 2]
# ------------------------------
# Drawing functions
# ------------------------------
# Draw a upward arrow
def draw_up(x, y, width, height, thickness, padding):
border = (thickness // 4) + padding
display.line(x + border, y + height - border,
x + (width // 2), y + border)
display.line(x + (width // 2), y + border,
x + width - border, y + height - border)
# Draw a downward arrow
def draw_down(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw the frame of the reader
def draw_frame():
display.pen(15)
display.clear()
display.pen(12)
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
display.pen(0)
display.thickness(ARROW_THICKNESS)
if state["current_page"] > 0:
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# ------------------------------
# Program setup
# ------------------------------
# Global variables
state = {
"last_offset": 0,
"current_page": 0,
"font_idx": 0,
"text_size": 0.5,
"offsets": []
}
badger_os.state_load("ebook", state)
text_spacing = int(34 * state["text_size"])
# Create a new Badger and set it to update FAST
display = badger2040.Badger2040()
display.led(128)
display.update_speed(badger2040.UPDATE_FAST)
# ------------------------------
# Render page
# ------------------------------
def render_page():
row = 0
line = ""
pos = ebook.tell()
next_pos = pos
add_newline = False
display.font(FONTS[state["font_idx"]])
while True:
# Read a full line and split it into words
words = ebook.readline().split(" ")
# Take the length of the first word and advance our position
next_word = words[0]
if len(words) > 1:
next_pos += len(next_word) + 1
else:
next_pos += len(next_word) # This is the last word on the line
# Advance our position further if the word contains special characters
if '\u201c' in next_word:
next_word = next_word.replace('\u201c', '\"')
next_pos += 2
if '\u201d' in next_word:
next_word = next_word.replace('\u201d', '\"')
next_pos += 2
if '\u2019' in next_word:
next_word = next_word.replace('\u2019', '\'')
next_pos += 2
# Rewind the file back from the line end to the start of the next word
ebook.seek(next_pos)
# Strip out any new line characters from the word
next_word = next_word.strip()
# If an empty word is encountered assume that means there was a blank line
if len(next_word) == 0:
add_newline = True
# Append the word to the current line and measure its length
appended_line = line
if len(line) > 0 and len(next_word) > 0:
appended_line += " "
appended_line += next_word
appended_length = display.measure_text(appended_line, state["text_size"])
# Would this appended line be longer than the text display area, or was a blank line spotted?
if appended_length >= TEXT_WIDTH or add_newline:
# Yes, so write out the line prior to the append
print(line)
display.pen(0)
display.thickness(FONT_THICKNESSES[0])
display.text(line, TEXT_PADDING, (row * text_spacing) + (text_spacing // 2) + TEXT_PADDING, state["text_size"])
# Clear the line and move on to the next row
line = ""
row += 1
# Have we reached the end of the page?
if (row * text_spacing) + text_spacing >= HEIGHT:
print("+++++")
display.update()
# Reset the position to the start of the word that made this line too long
ebook.seek(pos)
return
else:
# Set the line to the word and advance the current position
line = next_word
pos = next_pos
# A new line was spotted, so advance a row
if add_newline:
print("")
row += 1
if (row * text_spacing) + text_spacing >= HEIGHT:
print("+++++")
display.update()
return
add_newline = False
else:
# The appended line was not too long, so set it as the line and advance the current position
line = appended_line
pos = next_pos
# ------------------------------
# Main program loop
# ------------------------------
launch = True
changed = False
# Open the book file
ebook = open(text_file, "r")
if len(state["offsets"]) > state["current_page"]:
ebook.seek(state["offsets"][state["current_page"]])
else:
state["current_page"] = 0
state["offsets"] = []
while True:
# Was the next page button pressed?
if display.pressed(badger2040.BUTTON_DOWN):
state["current_page"] += 1
changed = True
# Was the previous page button pressed?
if display.pressed(badger2040.BUTTON_UP):
if state["current_page"] > 0:
state["current_page"] -= 1
if state["current_page"] == 0:
ebook.seek(0)
else:
ebook.seek(state["offsets"][state["current_page"] - 1]) # Retrieve the start position of the last page
changed = True
if display.pressed(badger2040.BUTTON_A):
state["text_size"] += 0.1
if state["text_size"] > 0.8:
state["text_size"] = 0.5
text_spacing = int(34 * state["text_size"])
state["offsets"] = []
ebook.seek(0)
state["current_page"] = 0
changed = True
if display.pressed(badger2040.BUTTON_B):
state["font_idx"] += 1
if (state["font_idx"] >= len(FONTS)):
state["font_idx"] = 0
state["offsets"] = []
ebook.seek(0)
state["current_page"] = 0
changed = True
if launch and not changed:
if state["current_page"] > 0 and len(state["offsets"]) > state["current_page"] - 1:
ebook.seek(state["offsets"][state["current_page"] - 1])
changed = True
launch = False
if changed:
draw_frame()
render_page()
# Is the next page one we've not displayed before?
if state["current_page"] >= len(state["offsets"]):
state["offsets"].append(ebook.tell()) # Add its start position to the state["offsets"] list
badger_os.state_save("ebook", state)
changed = False
display.halt()

Wyświetl plik

@ -1,134 +0,0 @@
import badger2040
import badger_os
# Global Constants
FONT_NAMES = (
("sans", 0.7, 2),
("gothic", 0.7, 2),
("cursive", 0.7, 2),
("serif", 0.7, 2),
("serif_italic", 0.7, 2),
("bitmap6", 3, 1),
("bitmap8", 2, 1),
("bitmap14_outline", 1, 1)
)
WIDTH = badger2040.WIDTH
HEIGHT = badger2040.HEIGHT
MENU_TEXT_SIZE = 0.5
MENU_SPACING = 16
MENU_WIDTH = 84
MENU_PADDING = 5
TEXT_INDENT = MENU_WIDTH + 10
ARROW_THICKNESS = 3
ARROW_WIDTH = 18
ARROW_HEIGHT = 14
ARROW_PADDING = 2
# ------------------------------
# Drawing functions
# ------------------------------
# Draw a upward arrow
def draw_up(x, y, width, height, thickness, padding):
border = (thickness // 4) + padding
display.line(x + border, y + height - border,
x + (width // 2), y + border)
display.line(x + (width // 2), y + border,
x + width - border, y + height - border)
# Draw a downward arrow
def draw_down(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw the frame of the reader
def draw_frame():
display.pen(15)
display.clear()
display.pen(12)
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
display.pen(0)
display.thickness(ARROW_THICKNESS)
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Draw the fonts and menu
def draw_fonts():
display.font("bitmap8")
display.thickness(1)
for i in range(len(FONT_NAMES)):
name, size, thickness = FONT_NAMES[i]
display.pen(0)
if i == state["selected_font"]:
display.rectangle(0, i * MENU_SPACING, MENU_WIDTH, MENU_SPACING)
display.pen(15)
display.text(name, MENU_PADDING, (i * MENU_SPACING) + int((MENU_SPACING - 8) / 2), MENU_TEXT_SIZE)
name, size, thickness = FONT_NAMES[state["selected_font"]]
display.font(name)
display.thickness(thickness)
y = 0 if name.startswith("bitmap") else 10
display.pen(0)
for line in ("The quick", "brown fox", "jumps over", "the lazy dog.", "0123456789", "!\"£$%^&*()"):
display.text(line, TEXT_INDENT, y, size)
y += 22
display.thickness(1)
display.update()
# ------------------------------
# Program setup
# ------------------------------
# Global variables
state = {"selected_font": 0}
badger_os.state_load("fonts", state)
# Create a new Badger and set it to update FAST
display = badger2040.Badger2040()
display.led(128)
display.update_speed(badger2040.UPDATE_FAST)
changed = not badger2040.woken_by_button()
# ------------------------------
# Main program loop
# ------------------------------
while True:
if display.pressed(badger2040.BUTTON_UP):
state["selected_font"] -= 1
if state["selected_font"] < 0:
state["selected_font"] = len(FONT_NAMES) - 1
changed = True
if display.pressed(badger2040.BUTTON_DOWN):
state["selected_font"] += 1
if state["selected_font"] >= len(FONT_NAMES):
state["selected_font"] = 0
changed = True
if changed:
draw_frame()
draw_fonts()
badger_os.state_save("fonts", state)
changed = False
display.halt()

Wyświetl plik

@ -1,42 +0,0 @@
import badger2040
from badger2040 import WIDTH
TEXT_SIZE = 0.45
LINE_HEIGHT = 20
display = badger2040.Badger2040()
display.led(128)
display.pen(0)
display.rectangle(0, 0, WIDTH, 16)
display.thickness(1)
display.pen(15)
display.text("badgerOS", 3, 8, 0.4)
display.text("help", WIDTH - display.measure_text("help", 0.4) - 4, 8, 0.4)
display.pen(0)
TEXT_SIZE = 0.62
y = 20 + int(LINE_HEIGHT / 2)
display.thickness(2)
display.font("sans")
display.text("Up/Down - Change page", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.text("a, b or c - Launch app", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.text("a & c - Exit app", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
y += 8
display.text("Up/Down & User - Font size", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.text("a & User - Toggle invert", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.update()
# Call halt in a loop, on battery this switches off power.
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
while True:
display.halt()

Wyświetl plik

@ -1,127 +0,0 @@
import os
import sys
import time
import badger2040
from badger2040 import HEIGHT
import badger_os
REAMDE = """
Images must be 296x128 pixel with 1bit colour depth.
You can use examples/badger2040/image_converter/convert.py to convert them:
python3 convert.py --binary --resize image_file_1.png image_file_2.png image_file_3.png
Create a new "images" directory via Thonny, and upload the .bin files there.
"""
OVERLAY_BORDER = 40
OVERLAY_SPACING = 20
OVERLAY_TEXT_SIZE = 0.5
TOTAL_IMAGES = 0
# Turn the act LED on as soon as possible
display = badger2040.Badger2040()
display.led(128)
# Try to preload BadgerPunk image
try:
os.mkdir("images")
import badgerpunk
with open("images/badgerpunk.bin", "wb") as f:
f.write(badgerpunk.data())
f.flush()
with open("images/readme.txt", "w") as f:
f.write(REAMDE)
f.flush()
del badgerpunk
except (OSError, ImportError):
pass
# Load images
try:
IMAGES = [f for f in os.listdir("/images") if f.endswith(".bin")]
TOTAL_IMAGES = len(IMAGES)
except OSError:
pass
image = bytearray(int(296 * 128 / 8))
state = {
"current_image": 0,
"show_info": True
}
def show_image(n):
file = IMAGES[n]
name = file.split(".")[0]
open("images/{}".format(file), "r").readinto(image)
display.image(image)
if state["show_info"]:
name_length = display.measure_text(name, 0.5)
display.pen(0)
display.rectangle(0, HEIGHT - 21, name_length + 11, 21)
display.pen(15)
display.rectangle(0, HEIGHT - 20, name_length + 10, 20)
display.pen(0)
display.text(name, 5, HEIGHT - 10, 0.5)
for i in range(TOTAL_IMAGES):
x = 286
y = int((128 / 2) - (TOTAL_IMAGES * 10 / 2) + (i * 10))
display.pen(0)
display.rectangle(x, y, 8, 8)
if state["current_image"] != i:
display.pen(15)
display.rectangle(x + 1, y + 1, 6, 6)
display.update()
if TOTAL_IMAGES == 0:
display.pen(15)
display.clear()
badger_os.warning(display, "To run this demo, create an /images directory on your device and upload some 1bit 296x128 pixel images.")
time.sleep(4.0)
sys.exit()
badger_os.state_load("image", state)
changed = not badger2040.woken_by_button()
while True:
if display.pressed(badger2040.BUTTON_UP):
if state["current_image"] > 0:
state["current_image"] -= 1
changed = True
if display.pressed(badger2040.BUTTON_DOWN):
if state["current_image"] < TOTAL_IMAGES - 1:
state["current_image"] += 1
changed = True
if display.pressed(badger2040.BUTTON_A):
state["show_info"] = not state["show_info"]
changed = True
if display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C):
display.pen(15)
display.clear()
badger_os.warning(display, "To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/")
display.update()
print(state["current_image"])
time.sleep(4)
changed = True
if changed:
badger_os.state_save("image", state)
show_image(state["current_image"])
changed = False
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -1,42 +0,0 @@
import badger2040
from badger2040 import WIDTH
TEXT_SIZE = 0.45
LINE_HEIGHT = 16
display = badger2040.Badger2040()
display.led(128)
display.pen(0)
display.rectangle(0, 0, WIDTH, 16)
display.thickness(1)
display.pen(15)
display.text("badgerOS", 3, 8, 0.4)
display.text("info", WIDTH - display.measure_text("help", 0.4) - 4, 8, 0.4)
display.pen(0)
y = 16 + int(LINE_HEIGHT / 2)
display.text("Made by Pimoroni, powered by MicroPython", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.text("Dual-core RP2040, 133MHz, 264KB RAM", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.text("2MB Flash (1MB OS, 1MB Storage)", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
display.text("296x128 pixel Black/White e-Ink", 0, y, TEXT_SIZE)
y += LINE_HEIGHT
y += LINE_HEIGHT
display.thickness(2)
display.text("For more info:", 0, y, TEXT_SIZE)
display.thickness(1)
y += LINE_HEIGHT
display.text("https://pimoroni.com/badger2040", 0, y, TEXT_SIZE)
display.update()
# Call halt in a loop, on battery this switches off power.
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
while True:
display.halt()

Wyświetl plik

@ -1,241 +0,0 @@
import gc
import time
import math
import badger2040
from badger2040 import WIDTH
import launchericons
import badger_os
# Reduce clock speed to 48MHz
badger2040.system_speed(badger2040.SYSTEM_NORMAL)
changed = False
exited_to_launcher = False
woken_by_button = badger2040.woken_by_button() # Must be done before we clear_pressed_to_wake
if badger2040.pressed_to_wake(badger2040.BUTTON_A) and badger2040.pressed_to_wake(badger2040.BUTTON_C):
# Pressing A and C together at start quits app
exited_to_launcher = badger_os.state_clear_running()
else:
# Otherwise restore previously running app
badger_os.state_launch()
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
MAX_BATTERY_VOLTAGE = 4.0
MIN_BATTERY_VOLTAGE = 3.2
display = badger2040.Badger2040()
display.led(128)
state = {
"page": 0,
"font_size": 1,
"inverted": False,
"running": "launcher"
}
badger_os.state_load("launcher", state)
display.invert(state["inverted"])
icons = bytearray(launchericons.data())
icons_width = 576
examples = [
("_clock", 0),
("_fonts", 1),
("_ebook", 2),
("_image", 3),
("_list", 4),
("_badge", 5),
("_qrgen", 8),
("_info", 6),
("_help", 7),
]
font_sizes = (0.5, 0.7, 0.9)
# Approximate center lines for buttons A, B and C
centers = (41, 147, 253)
MAX_PAGE = math.ceil(len(examples) / 3)
def map_value(input, in_min, in_max, out_min, out_max):
return (((input - in_min) * (out_max - out_min)) / (in_max - in_min)) + out_min
def draw_battery(level, x, y):
# Outline
display.thickness(1)
display.pen(15)
display.rectangle(x, y, 19, 10)
# Terminal
display.rectangle(x + 19, y + 3, 2, 4)
display.pen(0)
display.rectangle(x + 1, y + 1, 17, 8)
if level < 1:
display.pen(0)
display.line(x + 3, y, x + 3 + 10, y + 10)
display.line(x + 3 + 1, y, x + 3 + 11, y + 10)
display.pen(15)
display.line(x + 2 + 2, y - 1, x + 4 + 12, y + 11)
display.line(x + 2 + 3, y - 1, x + 4 + 13, y + 11)
return
# Battery Bars
display.pen(15)
for i in range(4):
if level / 4 > (1.0 * i) / 4:
display.rectangle(i * 4 + x + 2, y + 2, 3, 6)
def draw_disk_usage(x):
_, f_used, _ = badger_os.get_disk_usage()
display.image(
bytearray(
(
0b00000000,
0b00111100,
0b00111100,
0b00111100,
0b00111000,
0b00000000,
0b00000000,
0b00000001,
)
),
8,
8,
x,
4,
)
display.pen(15)
display.rectangle(x + 10, 3, 80, 10)
display.pen(0)
display.rectangle(x + 11, 4, 78, 8)
display.pen(15)
display.rectangle(x + 12, 5, int(76 / 100.0 * f_used), 6)
display.text("{:.2f}%".format(f_used), x + 91, 8, 0.4)
def render():
display.pen(15)
display.clear()
display.pen(0)
display.thickness(2)
max_icons = min(3, len(examples[(state["page"] * 3):]))
for i in range(max_icons):
x = centers[i]
label, icon = examples[i + (state["page"] * 3)]
label = label[1:].replace("_", " ")
display.pen(0)
display.icon(icons, icon, icons_width, 64, x - 32, 24)
w = display.measure_text(label, font_sizes[state["font_size"]])
display.text(label, x - int(w / 2), 16 + 80, font_sizes[state["font_size"]])
for i in range(MAX_PAGE):
x = 286
y = int((128 / 2) - (MAX_PAGE * 10 / 2) + (i * 10))
display.pen(0)
display.rectangle(x, y, 8, 8)
if state["page"] != i:
display.pen(15)
display.rectangle(x + 1, y + 1, 6, 6)
display.pen(0)
display.rectangle(0, 0, WIDTH, 16)
display.thickness(1)
draw_disk_usage(90)
vbat = badger_os.get_battery_level()
bat = int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4))
draw_battery(bat, WIDTH - 22 - 3, 3)
display.pen(15)
display.text("badgerOS", 3, 8, 0.4)
display.update()
def wait_for_user_to_release_buttons():
pr = display.pressed
while pr(badger2040.BUTTON_A) or pr(badger2040.BUTTON_B) or pr(badger2040.BUTTON_C) or pr(badger2040.BUTTON_UP) or pr(badger2040.BUTTON_DOWN):
time.sleep(0.01)
def launch_example(index):
wait_for_user_to_release_buttons()
file = examples[(state["page"] * 3) + index][0]
for k in locals().keys():
if k not in ("gc", "file", "badger_os"):
del locals()[k]
gc.collect()
badger_os.launch(file)
def button(pin):
global changed
changed = True
if not display.pressed(badger2040.BUTTON_USER): # User button is NOT held down
if pin == badger2040.BUTTON_A:
launch_example(0)
if pin == badger2040.BUTTON_B:
launch_example(1)
if pin == badger2040.BUTTON_C:
launch_example(2)
if pin == badger2040.BUTTON_UP:
if state["page"] > 0:
state["page"] -= 1
render()
if pin == badger2040.BUTTON_DOWN:
if state["page"] < MAX_PAGE - 1:
state["page"] += 1
render()
else: # User button IS held down
if pin == badger2040.BUTTON_UP:
state["font_size"] += 1
if state["font_size"] == len(font_sizes):
state["font_size"] = 0
render()
if pin == badger2040.BUTTON_DOWN:
state["font_size"] -= 1
if state["font_size"] < 0:
state["font_size"] = 0
render()
if pin == badger2040.BUTTON_A:
state["inverted"] = not state["inverted"]
display.invert(state["inverted"])
render()
if exited_to_launcher or not woken_by_button:
wait_for_user_to_release_buttons()
display.update_speed(badger2040.UPDATE_MEDIUM)
render()
display.update_speed(badger2040.UPDATE_FAST)
while True:
if display.pressed(badger2040.BUTTON_A):
button(badger2040.BUTTON_A)
if display.pressed(badger2040.BUTTON_B):
button(badger2040.BUTTON_B)
if display.pressed(badger2040.BUTTON_C):
button(badger2040.BUTTON_C)
if display.pressed(badger2040.BUTTON_UP):
button(badger2040.BUTTON_UP)
if display.pressed(badger2040.BUTTON_DOWN):
button(badger2040.BUTTON_DOWN)
if changed:
badger_os.state_save("launcher", state)
changed = False
display.halt()

Wyświetl plik

@ -1,15 +0,0 @@
# Blinky badger fun!
import badger2040
import time
badger = badger2040.Badger2040()
while True:
# increase badger.led brightness from 0 to 255 and back down to zero
for i in range(0, 255):
badger.led(i)
time.sleep_ms(10)
for i in range(255, 0, -1):
badger.led(i)
time.sleep_ms(10)

Wyświetl plik

@ -1,315 +0,0 @@
import binascii
import badger2040
import badger_os
# **** Put your list title here *****
list_title = "Checklist"
list_file = "checklist.txt"
# Global Constants
WIDTH = badger2040.WIDTH
HEIGHT = badger2040.HEIGHT
ARROW_THICKNESS = 3
ARROW_WIDTH = 18
ARROW_HEIGHT = 14
ARROW_PADDING = 2
MAX_ITEM_CHARS = 26
TITLE_TEXT_SIZE = 0.7
ITEM_TEXT_SIZE = 0.6
ITEM_SPACING = 20
LIST_START = 40
LIST_PADDING = 2
LIST_WIDTH = WIDTH - LIST_PADDING - LIST_PADDING - ARROW_WIDTH
LIST_HEIGHT = HEIGHT - LIST_START - LIST_PADDING - ARROW_HEIGHT
# Default list items - change the list items by editing checklist.txt
list_items = ["Badger", "Badger", "Badger", "Badger", "Badger", "Mushroom", "Mushroom", "Snake"]
save_checklist = False
try:
with open("checklist.txt", "r") as f:
raw_list_items = f.read()
if raw_list_items.find(" X\n") != -1:
# Have old style checklist, preserve state and note we should resave the list to remove the Xs
list_items = []
state = {
"current_item": 0,
"checked": []
}
for item in raw_list_items.strip().split("\n"):
if item.endswith(" X"):
state["checked"].append(True)
item = item[:-2]
else:
state["checked"].append(False)
list_items.append(item)
state["items_hash"] = binascii.crc32("\n".join(list_items))
badger_os.state_save("list", state)
save_checklist = True
else:
list_items = [item.strip() for item in raw_list_items.strip().split("\n")]
except OSError:
save_checklist = True
if save_checklist:
with open("checklist.txt", "w") as f:
for item in list_items:
f.write(item + "\n")
# ------------------------------
# Drawing functions
# ------------------------------
# Draw the list of items
def draw_list(items, item_states, start_item, highlighted_item, x, y, width, height, item_height, columns):
item_x = 0
item_y = 0
current_col = 0
for i in range(start_item, len(items)):
if i == highlighted_item:
display.pen(12)
display.rectangle(item_x, item_y + y - (item_height // 2), width // columns, item_height)
display.pen(0)
display.text(items[i], item_x + x + item_height, item_y + y, ITEM_TEXT_SIZE)
draw_checkbox(item_x, item_y + y - (item_height // 2), item_height, 15, 0, 2, item_states[i], 2)
item_y += item_height
if item_y >= height - (item_height // 2):
item_x += width // columns
item_y = 0
current_col += 1
if current_col >= columns:
return
# Draw a upward arrow
def draw_up(x, y, width, height, thickness, padding):
border = (thickness // 4) + padding
display.line(x + border, y + height - border,
x + (width // 2), y + border)
display.line(x + (width // 2), y + border,
x + width - border, y + height - border)
# Draw a downward arrow
def draw_down(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw a left arrow
def draw_left(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + width - border, y + border,
x + border, y + (height // 2))
display.line(x + border, y + (height // 2),
x + width - border, y + height - border)
# Draw a right arrow
def draw_right(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + width - border, y + (height // 2))
display.line(x + width - border, y + (height // 2),
x + border, y + height - border)
# Draw a tick
def draw_tick(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + ((height * 2) // 3),
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw a cross
def draw_cross(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border, x + width - border, y + height - border)
display.line(x + width - border, y + border, x + border, y + height - border)
# Draw a checkbox with or without a tick
def draw_checkbox(x, y, size, background, foreground, thickness, tick, padding):
border = (thickness // 2) + padding
display.pen(background)
display.rectangle(x + border, y + border, size - (border * 2), size - (border * 2))
display.pen(foreground)
display.thickness(thickness)
display.line(x + border, y + border, x + size - border, y + border)
display.line(x + border, y + border, x + border, y + size - border)
display.line(x + size - border, y + border, x + size - border, y + size - border)
display.line(x + border, y + size - border, x + size - border, y + size - border)
if tick:
draw_tick(x, y, size, size, thickness, 2 + border)
# ------------------------------
# Program setup
# ------------------------------
changed = not badger2040.woken_by_button()
state = {
"current_item": 0,
}
badger_os.state_load("list", state)
items_hash = binascii.crc32("\n".join(list_items))
if "items_hash" not in state or state["items_hash"] != items_hash:
# Item list changed, or not yet written reset the list
state["current_item"] = 0
state["items_hash"] = items_hash
state["checked"] = [False] * len(list_items)
changed = True
# Global variables
items_per_page = 0
# Create a new Badger and set it to update FAST
display = badger2040.Badger2040()
display.led(128)
if changed:
display.update_speed(badger2040.UPDATE_FAST)
else:
display.update_speed(badger2040.UPDATE_TURBO)
# Find out what the longest item is
longest_item = 0
for i in range(len(list_items)):
while True:
item = list_items[i]
item_length = display.measure_text(item, ITEM_TEXT_SIZE)
if item_length > 0 and item_length > LIST_WIDTH - ITEM_SPACING:
list_items[i] = item[:-1]
else:
break
longest_item = max(longest_item, display.measure_text(list_items[i], ITEM_TEXT_SIZE))
# And use that to calculate the number of columns we can fit onscreen and how many items that would give
list_columns = 1
while longest_item + ITEM_SPACING < (LIST_WIDTH // (list_columns + 1)):
list_columns += 1
items_per_page = ((LIST_HEIGHT // ITEM_SPACING) + 1) * list_columns
# ------------------------------
# Main program loop
# ------------------------------
while True:
if len(list_items) > 0:
if display.pressed(badger2040.BUTTON_A):
if state["current_item"] > 0:
page = state["current_item"] // items_per_page
state["current_item"] = max(state["current_item"] - (items_per_page) // list_columns, 0)
if page != state["current_item"] // items_per_page:
display.update_speed(badger2040.UPDATE_FAST)
changed = True
if display.pressed(badger2040.BUTTON_B):
state["checked"][state["current_item"]] = not state["checked"][state["current_item"]]
changed = True
if display.pressed(badger2040.BUTTON_C):
if state["current_item"] < len(list_items) - 1:
page = state["current_item"] // items_per_page
state["current_item"] = min(state["current_item"] + (items_per_page) // list_columns, len(list_items) - 1)
if page != state["current_item"] // items_per_page:
display.update_speed(badger2040.UPDATE_FAST)
changed = True
if display.pressed(badger2040.BUTTON_UP):
if state["current_item"] > 0:
state["current_item"] -= 1
changed = True
if display.pressed(badger2040.BUTTON_DOWN):
if state["current_item"] < len(list_items) - 1:
state["current_item"] += 1
changed = True
if changed:
badger_os.state_save("list", state)
display.pen(15)
display.clear()
display.pen(12)
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
display.rectangle(0, HEIGHT - ARROW_HEIGHT, WIDTH, ARROW_HEIGHT)
y = LIST_PADDING + 12
display.pen(0)
display.thickness(3)
display.text(list_title, LIST_PADDING, y, TITLE_TEXT_SIZE)
y += 12
display.pen(0)
display.thickness(2)
display.line(LIST_PADDING, y, WIDTH - LIST_PADDING - ARROW_WIDTH, y)
if len(list_items) > 0:
page_item = 0
if items_per_page > 0:
page_item = (state["current_item"] // items_per_page) * items_per_page
# Draw the list
display.pen(0)
display.thickness(2)
draw_list(list_items, state["checked"], page_item, state["current_item"], LIST_PADDING, LIST_START,
LIST_WIDTH, LIST_HEIGHT, ITEM_SPACING, list_columns)
# Draw the interaction button icons
display.pen(0)
display.thickness(ARROW_THICKNESS)
# Previous item
if state["current_item"] > 0:
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Next item
if state["current_item"] < (len(list_items) - 1):
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Previous column
if state["current_item"] > 0:
draw_left((WIDTH // 7) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Next column
if state["current_item"] < (len(list_items) - 1):
draw_right(((WIDTH * 6) // 7) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
if state["checked"][state["current_item"]]:
# Tick off item
draw_cross((WIDTH // 2) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_HEIGHT, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
else:
# Untick item
draw_tick((WIDTH // 2) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_HEIGHT, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
else:
# Say that the list is empty
empty_text = "Nothing Here"
text_length = display.measure_text(empty_text, ITEM_TEXT_SIZE)
display.text(empty_text, ((LIST_PADDING + LIST_WIDTH) - text_length) // 2, (LIST_HEIGHT // 2) + LIST_START - (ITEM_SPACING // 4), ITEM_TEXT_SIZE)
display.update()
display.update_speed(badger2040.UPDATE_TURBO)
changed = False
display.halt()

Wyświetl plik

@ -1,55 +0,0 @@
function (convert_image TARGET IMAGE)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../modules/${IMAGE}.py
COMMAND
cd ${CMAKE_CURRENT_LIST_DIR}/assets && python3 ../../../../examples/badger2040/image_converter/convert.py --out_dir ${CMAKE_CURRENT_BINARY_DIR}/../modules --py ${IMAGE}.png
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/assets/${IMAGE}.png
)
target_sources(${TARGET} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/../modules/${IMAGE}.py)
endfunction()
function (convert_raw TARGET SRC DST)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../modules/${DST}.py
COMMAND
cd ${CMAKE_CURRENT_LIST_DIR}/assets && python3 ../../../../examples/badger2040/image_converter/data_to_py.py ${CMAKE_CURRENT_LIST_DIR}/assets/${SRC} ${CMAKE_CURRENT_BINARY_DIR}/../modules/${DST}.py
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/assets/${SRC}
)
target_sources(${TARGET} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/../modules/${DST}.py)
endfunction()
function (copy_module TARGET SRC DST)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../modules/${DST}.py
COMMAND
cp ${SRC} ${CMAKE_CURRENT_BINARY_DIR}/../modules/${DST}.py
DEPENDS ${SRC}
)
target_sources(${TARGET} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/../modules/${DST}.py)
endfunction()
convert_image(usermod_badger2040 badge_image)
convert_image(usermod_badger2040 badgerpunk)
convert_image(usermod_badger2040 launchericons)
convert_raw(usermod_badger2040 289-0-wind-in-the-willows-abridged.txt witw)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/assets/boot.py boot)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/launcher.py _launcher)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/clock.py _clock)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/fonts.py _fonts)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/ebook.py _ebook)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/image.py _image)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/list.py _list)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badge.py _badge)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/help.py _help)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/info.py _info)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/qrgen.py _qrgen)
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badger_os.py badger_os)

Wyświetl plik

@ -1,65 +0,0 @@
import badger2040
import machine
display = badger2040.Badger2040()
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
display.thickness(10)
display.pen(0)
display.line(0, 5, 295, 5)
display.line(0, 123, 295, 123)
display.thickness(1)
for x in range(14):
display.line(x * 20, 10, x * 20, 118)
display.line(0, 0, 295, 127)
display.line(0, 127, 295, 0)
display.font("sans")
display.thickness(5)
display.text("Hello World", 10, 30, 1.0)
display.pen(7)
display.text("Hello World", 10, 60, 1.0)
display.pen(11)
display.text("Hello World", 10, 90, 1.0)
display.update()
dirty = False
pressed = None
def button(pin):
global dirty, pressed
if pin == button_a:
pressed = "Button A"
dirty = True
return
if pin == button_b:
pressed = "Button B"
dirty = True
return
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
# This breaks Thonny, since it's no longer possible to Stop the code
# need to press the reset button on the board...
# It will also crash your USB bus, probably, your whole bus...
# @micropython.asm_thumb
# def lightsleep():
# wfi()
while True:
if dirty:
display.pen(15)
display.clear()
display.pen(0)
display.text(pressed, 10, 60, 2.0)
display.update()
dirty = False
# machine.lightsleep() # Currently imposible to wake from this on IRQ

Wyświetl plik

@ -1,155 +0,0 @@
import badger2040
import qrcode
import time
import os
import badger_os
# Check that the qrcodes directory exists, if not, make it
try:
os.mkdir("qrcodes")
except OSError:
pass
# Load all available QR Code Files
try:
CODES = [f for f in os.listdir("/qrcodes") if f.endswith(".txt")]
except OSError:
CODES = []
# create demo QR code file if no QR code files exist
if len(CODES) == 0:
try:
new_qr_code_filename = "qrcode.txt"
with open(f"/qrcodes/{new_qr_code_filename}", "w") as text:
text.write("""https://pimoroni.com/badger2040
Badger 2040
* 296x128 1-bit e-ink
* six user buttons
* user LED
* 2MB QSPI flash
Scan this code to learn
more about Badger 2040.
""")
text.flush()
# Set the CODES list to contain the new_qr_code_filename (created above)
CODES = [new_qr_code_filename]
except OSError:
CODES = []
TOTAL_CODES = len(CODES)
display = badger2040.Badger2040()
code = qrcode.QRCode()
state = {
"current_qr": 0
}
def set_state_current_index_in_range():
badger_os.state_load("qrcodes", state)
if state["current_qr"] >= len(CODES):
state["current_qr"] = len(CODES) - 1 # set to last index (zero-based). Note: will set to -1 if currently 0
if state["current_qr"] < 0: # check that the index is not negative, thus still out of range
state["current_qr"] = 0
badger_os.state_save("qrcodes", state)
def measure_qr_code(size, code):
w, h = code.get_size()
module_size = int(size / w)
return module_size * w, module_size
def draw_qr_code(ox, oy, size, code):
size, module_size = measure_qr_code(size, code)
display.pen(15)
display.rectangle(ox, oy, size, size)
display.pen(0)
for x in range(size):
for y in range(size):
if code.get_module(x, y):
display.rectangle(ox + x * module_size, oy + y * module_size, module_size, module_size)
def draw_qr_file(n):
display.led(128)
file = CODES[n]
try:
with open(f"/qrcodes/{file}", "r") as codetext:
lines = codetext.read().strip().split("\n")
except OSError:
lines = ["", "", "", "", "", "", "", "", "", ""]
code_text = lines.pop(0)
title_text = lines.pop(0)
detail_text = lines
# Clear the Display
display.pen(15) # Change this to 0 if a white background is used
display.clear()
display.pen(0)
code.set_text(code_text)
size, _ = measure_qr_code(128, code)
left = top = int((badger2040.HEIGHT / 2) - (size / 2))
draw_qr_code(left, top, 128, code)
left = 128 + 5
display.thickness(2)
display.text(title_text, left, 20, 0.5)
display.thickness(1)
top = 40
for line in detail_text:
display.text(line, left, top, 0.4)
top += 10
if TOTAL_CODES > 1:
for i in range(TOTAL_CODES):
x = 286
y = int((128 / 2) - (TOTAL_CODES * 10 / 2) + (i * 10))
display.pen(0)
display.rectangle(x, y, 8, 8)
if state["current_qr"] != i:
display.pen(15)
display.rectangle(x + 1, y + 1, 6, 6)
display.update()
set_state_current_index_in_range()
changed = not badger2040.woken_by_button()
while True:
if TOTAL_CODES > 1:
if display.pressed(badger2040.BUTTON_UP):
if state["current_qr"] > 0:
state["current_qr"] -= 1
changed = True
if display.pressed(badger2040.BUTTON_DOWN):
if state["current_qr"] < TOTAL_CODES - 1:
state["current_qr"] += 1
changed = True
if display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C):
display.pen(15)
display.clear()
badger_os.warning(display, "To add QR codes, connect Badger2040 to a PC, load up Thonny, and see qrgen.py.")
time.sleep(4)
changed = True
if changed:
draw_qr_file(state["current_qr"])
badger_os.state_save("qrcodes", state)
changed = False
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -1,3 +0,0 @@
SSID = ""
PSK = ""
COUNTRY = "" # Change to your local two-letter ISO 3166-1 country code

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 7.7 KiB

Wyświetl plik

@ -1,7 +0,0 @@
mustelid inc
H. Badger
RP2040
2MB Flash
E ink
296x128px
/badges/badge.jpg

Wyświetl plik

@ -1,172 +0,0 @@
import time
import badger2040w
import badger_os
import jpegdec
# Global Constants
WIDTH = badger2040w.WIDTH
HEIGHT = badger2040w.HEIGHT
IMAGE_WIDTH = 104
COMPANY_HEIGHT = 30
DETAILS_HEIGHT = 20
NAME_HEIGHT = HEIGHT - COMPANY_HEIGHT - (DETAILS_HEIGHT * 2) - 2
TEXT_WIDTH = WIDTH - IMAGE_WIDTH - 1
COMPANY_TEXT_SIZE = 0.6
DETAILS_TEXT_SIZE = 0.5
LEFT_PADDING = 5
NAME_PADDING = 20
DETAIL_SPACING = 10
BADGE_PATH = "/badges/badge.txt"
DEFAULT_TEXT = """mustelid inc
H. Badger
RP2040
2MB Flash
E ink
296x128px
/badges/badge.jpg
"""
# ------------------------------
# Utility functions
# ------------------------------
# Reduce the size of a string until it fits within a given width
def truncatestring(text, text_size, width):
while True:
length = display.measure_text(text, text_size)
if length > 0 and length > width:
text = text[:-1]
else:
text += ""
return text
# ------------------------------
# Drawing functions
# ------------------------------
# Draw the badge, including user text
def draw_badge():
display.set_pen(0)
display.clear()
# Draw badge image
jpeg.open_file(badge_image)
jpeg.decode(WIDTH - IMAGE_WIDTH, 0)
# Draw a border around the image
display.set_pen(0)
display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - 1, 0)
display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - IMAGE_WIDTH, HEIGHT - 1)
display.line(WIDTH - IMAGE_WIDTH, HEIGHT - 1, WIDTH - 1, HEIGHT - 1)
display.line(WIDTH - 1, 0, WIDTH - 1, HEIGHT - 1)
# Uncomment this if a white background is wanted behind the company
# display.set_pen(15)
# display.rectangle(1, 1, TEXT_WIDTH, COMPANY_HEIGHT - 1)
# Draw the company
display.set_pen(15) # Change this to 0 if a white background is used
display.set_font("serif")
display.text(company, LEFT_PADDING, (COMPANY_HEIGHT // 2) + 1, WIDTH, COMPANY_TEXT_SIZE)
# Draw a white background behind the name
display.set_pen(15)
display.rectangle(1, COMPANY_HEIGHT + 1, TEXT_WIDTH, NAME_HEIGHT)
# Draw the name, scaling it based on the available width
display.set_pen(0)
display.set_font("sans")
name_size = 2.0 # A sensible starting scale
while True:
name_length = display.measure_text(name, name_size)
if name_length >= (TEXT_WIDTH - NAME_PADDING) and name_size >= 0.1:
name_size -= 0.01
else:
display.text(name, (TEXT_WIDTH - name_length) // 2, (NAME_HEIGHT // 2) + COMPANY_HEIGHT + 1, WIDTH, name_size)
break
# Draw a white backgrounds behind the details
display.set_pen(15)
display.rectangle(1, HEIGHT - DETAILS_HEIGHT * 2, TEXT_WIDTH, DETAILS_HEIGHT - 1)
display.rectangle(1, HEIGHT - DETAILS_HEIGHT, TEXT_WIDTH, DETAILS_HEIGHT - 1)
# Draw the first detail's title and text
display.set_pen(0)
display.set_font("sans")
name_length = display.measure_text(detail1_title, DETAILS_TEXT_SIZE)
display.text(detail1_title, LEFT_PADDING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), WIDTH, DETAILS_TEXT_SIZE)
display.text(detail1_text, 5 + name_length + DETAIL_SPACING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), WIDTH, DETAILS_TEXT_SIZE)
# Draw the second detail's title and text
name_length = display.measure_text(detail2_title, DETAILS_TEXT_SIZE)
display.text(detail2_title, LEFT_PADDING, HEIGHT - (DETAILS_HEIGHT // 2), WIDTH, DETAILS_TEXT_SIZE)
display.text(detail2_text, LEFT_PADDING + name_length + DETAIL_SPACING, HEIGHT - (DETAILS_HEIGHT // 2), WIDTH, DETAILS_TEXT_SIZE)
# ------------------------------
# Program setup
# ------------------------------
# Create a new Badger and set it to update NORMAL
display = badger2040w.Badger2040W()
display.led(128)
display.set_update_speed(badger2040w.UPDATE_NORMAL)
display.set_thickness(2)
jpeg = jpegdec.JPEG(display.display)
# Open the badge file
try:
badge = open(BADGE_PATH, "r")
except OSError:
with open(BADGE_PATH, "w") as f:
f.write(DEFAULT_TEXT)
f.flush()
badge = open(BADGE_PATH, "r")
# Read in the next 6 lines
company = badge.readline() # "mustelid inc"
name = badge.readline() # "H. Badger"
detail1_title = badge.readline() # "RP2040"
detail1_text = badge.readline() # "2MB Flash"
detail2_title = badge.readline() # "E ink"
detail2_text = badge.readline() # "296x128px"
badge_image = badge.readline() # /badges/badge.jpg
# Truncate all of the text (except for the name as that is scaled)
company = truncatestring(company, COMPANY_TEXT_SIZE, TEXT_WIDTH)
detail1_title = truncatestring(detail1_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail1_text = truncatestring(detail1_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail1_title, DETAILS_TEXT_SIZE))
detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE))
# ------------------------------
# Main program
# ------------------------------
draw_badge()
while True:
if display.pressed(badger2040w.BUTTON_A) or display.pressed(badger2040w.BUTTON_B) or display.pressed(badger2040w.BUTTON_C) or display.pressed(badger2040w.BUTTON_UP) or display.pressed(badger2040w.BUTTON_DOWN):
badger_os.warning(display, "To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt")
time.sleep(4)
draw_badge()
display.update()
# If on battery, halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -1,94 +0,0 @@
import time
import machine
import ntptime
import badger2040w
display = badger2040w.Badger2040W()
display.set_update_speed(2)
display.set_thickness(4)
WIDTH, HEIGHT = display.get_bounds()
try:
display.connect()
if display.isconnected():
ntptime.settime()
except (RuntimeError, OSError):
pass # no WiFI
rtc = machine.RTC()
display.set_font("gothic")
def draw_clock():
global second_offset, second_unit_offset
hms = "{:02}:{:02}:{:02}".format(hour, minute, second)
ymd = "{:04}/{:02}/{:02}".format(year, month, day)
hms_width = display.measure_text(hms, 1.8)
hms_offset = int((WIDTH / 2) - (hms_width / 2))
ymd_width = display.measure_text(ymd, 1.0)
ymd_offset = int((WIDTH / 2) - (ymd_width / 2))
display.set_pen(15)
display.clear()
display.set_pen(0)
display.text(hms, hms_offset, 40, 0, 1.8)
display.text(ymd, ymd_offset, 100, 0, 1.0)
display.set_update_speed(2)
display.update()
display.set_update_speed(3)
hms = "{:02}:{:02}:".format(hour, minute)
second_offset = hms_offset + display.measure_text(hms, 1.8)
hms = "{:02}:{:02}:{}".format(hour, minute, second // 10)
second_unit_offset = hms_offset + display.measure_text(hms, 1.8)
def draw_second():
global second_offset, second_unit_offset
display.set_pen(15)
display.rectangle(second_offset, 8, 75, 56)
display.set_pen(0)
if second // 10 != last_second // 10:
s = "{:02}".format(second)
display.text(s, second_offset, 40, 0, 1.8)
display.partial_update(second_offset, 8, 75, 56)
s = "{}".format(second // 10)
second_unit_offset = second_offset + display.measure_text(s, 1.8)
else:
s = "{}".format(second % 10)
display.text(s, second_unit_offset, 40, 0, 1.8)
display.partial_update(second_unit_offset, 8, 75 - (second_unit_offset - second_offset), 56)
year, month, day, wd, hour, minute, second, _ = rtc.datetime()
if (year, month, day) == (2021, 1, 1):
rtc.datetime((2022, 2, 28, 0, 12, 0, 0, 0))
last_second = second
last_minute = minute
draw_clock()
while True:
year, month, day, wd, hour, minute, second, _ = rtc.datetime()
if second != last_second:
if minute != last_minute:
draw_clock()
last_minute = minute
else:
draw_second()
last_second = second
time.sleep(0.01)

Wyświetl plik

@ -1,244 +0,0 @@
import badger2040w
import gc
import badger_os
# **** Put the name of your text file here *****
text_file = "/books/289-0-wind-in-the-willows-abridged.txt" # File must be on the MicroPython device
gc.collect()
# Global Constants
WIDTH = badger2040w.WIDTH
HEIGHT = badger2040w.HEIGHT
ARROW_THICKNESS = 3
ARROW_WIDTH = 18
ARROW_HEIGHT = 14
ARROW_PADDING = 2
TEXT_PADDING = 4
TEXT_WIDTH = WIDTH - TEXT_PADDING - TEXT_PADDING - ARROW_WIDTH
FONTS = ["sans", "gothic", "cursive", "serif"]
THICKNESSES = [2, 1, 1, 2]
# ------------------------------
# Drawing functions
# ------------------------------
# Draw a upward arrow
def draw_up(x, y, width, height, thickness, padding):
border = (thickness // 4) + padding
display.line(x + border, y + height - border,
x + (width // 2), y + border)
display.line(x + (width // 2), y + border,
x + width - border, y + height - border)
# Draw a downward arrow
def draw_down(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw the frame of the reader
def draw_frame():
display.set_pen(15)
display.clear()
display.set_pen(12)
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
display.set_pen(0)
if state["current_page"] > 0:
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# ------------------------------
# Program setup
# ------------------------------
# Global variables
state = {
"last_offset": 0,
"current_page": 0,
"font_idx": 0,
"text_size": 0.5,
"offsets": []
}
badger_os.state_load("ebook", state)
text_spacing = int(34 * state["text_size"])
# Create a new Badger and set it to update FAST
display = badger2040w.Badger2040W()
display.led(128)
display.set_update_speed(badger2040w.UPDATE_FAST)
# ------------------------------
# Render page
# ------------------------------
def render_page():
row = 0
line = ""
pos = ebook.tell()
next_pos = pos
add_newline = False
display.set_font(FONTS[state["font_idx"]])
display.set_thickness(THICKNESSES[state["font_idx"]])
while True:
# Read a full line and split it into words
words = ebook.readline().split(" ")
# Take the length of the first word and advance our position
next_word = words[0]
if len(words) > 1:
next_pos += len(next_word) + 1
else:
next_pos += len(next_word) # This is the last word on the line
# Advance our position further if the word contains special characters
if '\u201c' in next_word:
next_word = next_word.replace('\u201c', '\"')
next_pos += 2
if '\u201d' in next_word:
next_word = next_word.replace('\u201d', '\"')
next_pos += 2
if '\u2019' in next_word:
next_word = next_word.replace('\u2019', '\'')
next_pos += 2
# Rewind the file back from the line end to the start of the next word
ebook.seek(next_pos)
# Strip out any new line characters from the word
next_word = next_word.strip()
# If an empty word is encountered assume that means there was a blank line
if len(next_word) == 0:
add_newline = True
# Append the word to the current line and measure its length
appended_line = line
if len(line) > 0 and len(next_word) > 0:
appended_line += " "
appended_line += next_word
appended_length = display.measure_text(appended_line, state["text_size"])
# Would this appended line be longer than the text display area, or was a blank line spotted?
if appended_length >= TEXT_WIDTH or add_newline:
# Yes, so write out the line prior to the append
print(line)
display.set_pen(0)
display.text(line, TEXT_PADDING, (row * text_spacing) + (text_spacing // 2) + TEXT_PADDING, WIDTH, state["text_size"])
# Clear the line and move on to the next row
line = ""
row += 1
# Have we reached the end of the page?
if (row * text_spacing) + text_spacing >= HEIGHT:
print("+++++")
display.update()
# Reset the position to the start of the word that made this line too long
ebook.seek(pos)
return
else:
# Set the line to the word and advance the current position
line = next_word
pos = next_pos
# A new line was spotted, so advance a row
if add_newline:
print("")
row += 1
if (row * text_spacing) + text_spacing >= HEIGHT:
print("+++++")
display.update()
return
add_newline = False
else:
# The appended line was not too long, so set it as the line and advance the current position
line = appended_line
pos = next_pos
# ------------------------------
# Main program loop
# ------------------------------
launch = True
changed = False
# Open the book file
ebook = open(text_file, "r")
if len(state["offsets"]) > state["current_page"]:
ebook.seek(state["offsets"][state["current_page"]])
else:
state["current_page"] = 0
state["offsets"] = []
while True:
# Was the next page button pressed?
if display.pressed(badger2040w.BUTTON_DOWN):
state["current_page"] += 1
changed = True
# Was the previous page button pressed?
if display.pressed(badger2040w.BUTTON_UP):
if state["current_page"] > 0:
state["current_page"] -= 1
if state["current_page"] == 0:
ebook.seek(0)
else:
ebook.seek(state["offsets"][state["current_page"] - 1]) # Retrieve the start position of the last page
changed = True
if display.pressed(badger2040w.BUTTON_A):
state["text_size"] += 0.1
if state["text_size"] > 0.8:
state["text_size"] = 0.5
text_spacing = int(34 * state["text_size"])
state["offsets"] = []
ebook.seek(0)
state["current_page"] = 0
changed = True
if display.pressed(badger2040w.BUTTON_B):
state["font_idx"] += 1
if (state["font_idx"] >= len(FONTS)):
state["font_idx"] = 0
state["offsets"] = []
ebook.seek(0)
state["current_page"] = 0
changed = True
if launch and not changed:
if state["current_page"] > 0 and len(state["offsets"]) > state["current_page"] - 1:
ebook.seek(state["offsets"][state["current_page"] - 1])
changed = True
launch = False
if changed:
draw_frame()
render_page()
# Is the next page one we've not displayed before?
if state["current_page"] >= len(state["offsets"]):
state["offsets"].append(ebook.tell()) # Add its start position to the state["offsets"] list
badger_os.state_save("ebook", state)
changed = False
display.halt()

Wyświetl plik

@ -1,129 +0,0 @@
import badger2040w
import badger_os
# Global Constants
FONT_NAMES = (
("sans", 0.7, 2),
("gothic", 0.7, 2),
("cursive", 0.7, 2),
("serif", 0.7, 2),
("serif_italic", 0.7, 2),
("bitmap6", 3, 1),
("bitmap8", 2, 1),
("bitmap14_outline", 1, 1)
)
WIDTH = badger2040w.WIDTH
HEIGHT = badger2040w.HEIGHT
MENU_TEXT_SIZE = 0.5
MENU_SPACING = 16
MENU_WIDTH = 84
MENU_PADDING = 5
TEXT_INDENT = MENU_WIDTH + 10
ARROW_THICKNESS = 3
ARROW_WIDTH = 18
ARROW_HEIGHT = 14
ARROW_PADDING = 2
# ------------------------------
# Drawing functions
# ------------------------------
# Draw a upward arrow
def draw_up(x, y, width, height, thickness, padding):
border = (thickness // 4) + padding
display.line(x + border, y + height - border,
x + (width // 2), y + border)
display.line(x + (width // 2), y + border,
x + width - border, y + height - border)
# Draw a downward arrow
def draw_down(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw the frame of the reader
def draw_frame():
display.set_pen(15)
display.clear()
display.set_pen(12)
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
display.set_pen(0)
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Draw the fonts and menu
def draw_fonts():
display.set_font("bitmap8")
for i in range(len(FONT_NAMES)):
name, size, thickness = FONT_NAMES[i]
display.set_pen(0)
if i == state["selected_font"]:
display.rectangle(0, i * MENU_SPACING, MENU_WIDTH, MENU_SPACING)
display.set_pen(15)
display.text(name, MENU_PADDING, (i * MENU_SPACING) + int((MENU_SPACING - 8) / 2), WIDTH, MENU_TEXT_SIZE)
name, size, thickness = FONT_NAMES[state["selected_font"]]
display.set_font(name)
y = 0 if name.startswith("bitmap") else 10
display.set_pen(0)
for line in ("The quick", "brown fox", "jumps over", "the lazy dog.", "0123456789", "!\"£$%^&*()"):
display.text(line, TEXT_INDENT, y, WIDTH, size)
y += 22
display.update()
# ------------------------------
# Program setup
# ------------------------------
# Global variables
state = {"selected_font": 0}
badger_os.state_load("fonts", state)
# Create a new Badger and set it to update FAST
display = badger2040w.Badger2040W()
display.led(128)
display.set_update_speed(badger2040w.UPDATE_FAST)
changed = not badger2040w.woken_by_button()
# ------------------------------
# Main program loop
# ------------------------------
while True:
if display.pressed(badger2040w.BUTTON_UP):
state["selected_font"] -= 1
if state["selected_font"] < 0:
state["selected_font"] = len(FONT_NAMES) - 1
changed = True
if display.pressed(badger2040w.BUTTON_DOWN):
state["selected_font"] += 1
if state["selected_font"] >= len(FONT_NAMES):
state["selected_font"] = 0
changed = True
if changed:
draw_frame()
draw_fonts()
badger_os.state_save("fonts", state)
changed = False
display.halt()

Wyświetl plik

@ -1,41 +0,0 @@
import badger2040w
from badger2040w import WIDTH
TEXT_SIZE = 0.45
LINE_HEIGHT = 20
display = badger2040w.Badger2040W()
display.led(128)
display.set_thickness(2)
# Clear to white
display.set_pen(15)
display.clear()
display.set_font("bitmap8")
display.set_pen(0)
display.rectangle(0, 0, WIDTH, 16)
display.set_pen(15)
display.text("badgerOS", 3, 4, WIDTH, 1)
display.text("help", WIDTH - display.measure_text("help", 0.4) - 4, 4, WIDTH, 1)
display.set_font("sans")
display.set_pen(0)
TEXT_SIZE = 0.62
y = 20 + int(LINE_HEIGHT / 2)
display.set_font("sans")
display.text("Up/Down - Change page", 0, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.text("a, b or c - Launch app", 0, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.text("a & c - Exit app", 0, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.update()
# Call halt in a loop, on battery this switches off power.
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
while True:
display.halt()

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.8 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.9 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.6 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.1 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.3 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.0 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.5 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.5 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.9 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.5 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 1.6 KiB

Wyświetl plik

@ -1,119 +0,0 @@
import os
import sys
import time
import badger2040w
from badger2040w import HEIGHT, WIDTH
import badger_os
import jpegdec
REAMDE = """
Images must be 296x128 pixel JPEGs
Create a new "images" directory via Thonny, and upload your .jpg files there.
"""
OVERLAY_BORDER = 40
OVERLAY_SPACING = 20
OVERLAY_TEXT_SIZE = 0.5
TOTAL_IMAGES = 0
# Turn the act LED on as soon as possible
display = badger2040w.Badger2040W()
display.led(128)
jpeg = jpegdec.JPEG(display.display)
# Try to preload BadgerPunk image
try:
os.mkdir("/images")
with open("/images/readme.txt", "w") as f:
f.write(REAMDE)
f.flush()
except (OSError, ImportError):
pass
# Load images
try:
IMAGES = [f for f in os.listdir("/images") if f.endswith(".jpg")]
TOTAL_IMAGES = len(IMAGES)
except OSError:
pass
state = {
"current_image": 0,
"show_info": True
}
def show_image(n):
file = IMAGES[n]
name = file.split(".")[0]
jpeg.open_file("/images/{}".format(file))
jpeg.decode()
if state["show_info"]:
name_length = display.measure_text(name, 0.5)
display.set_pen(0)
display.rectangle(0, HEIGHT - 21, name_length + 11, 21)
display.set_pen(15)
display.rectangle(0, HEIGHT - 20, name_length + 10, 20)
display.set_pen(0)
display.text(name, 5, HEIGHT - 10, WIDTH, 0.5)
for i in range(TOTAL_IMAGES):
x = 286
y = int((128 / 2) - (TOTAL_IMAGES * 10 / 2) + (i * 10))
display.set_pen(0)
display.rectangle(x, y, 8, 8)
if state["current_image"] != i:
display.set_pen(15)
display.rectangle(x + 1, y + 1, 6, 6)
display.update()
if TOTAL_IMAGES == 0:
display.set_pen(15)
display.clear()
badger_os.warning(display, "To run this demo, create an /images directory on your device and upload some 1bit 296x128 pixel images.")
time.sleep(4.0)
sys.exit()
badger_os.state_load("image", state)
changed = not badger2040w.woken_by_button()
while True:
if display.pressed(badger2040w.BUTTON_UP):
if state["current_image"] > 0:
state["current_image"] -= 1
changed = True
if display.pressed(badger2040w.BUTTON_DOWN):
if state["current_image"] < TOTAL_IMAGES - 1:
state["current_image"] += 1
changed = True
if display.pressed(badger2040w.BUTTON_A):
state["show_info"] = not state["show_info"]
changed = True
if display.pressed(badger2040w.BUTTON_B) or display.pressed(badger2040w.BUTTON_C):
display.set_pen(15)
display.clear()
badger_os.warning(display, "To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/")
display.update()
print(state["current_image"])
time.sleep(4)
changed = True
if changed:
badger_os.state_save("image", state)
show_image(state["current_image"])
changed = False
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -1,44 +0,0 @@
import badger2040w
from badger2040w import WIDTH
TEXT_SIZE = 1
LINE_HEIGHT = 15
display = badger2040w.Badger2040W()
display.led(128)
# Clear to white
display.set_pen(15)
display.clear()
display.set_font("bitmap8")
display.set_pen(0)
display.rectangle(0, 0, WIDTH, 16)
display.set_pen(15)
display.text("badgerOS", 3, 4, WIDTH, 1)
display.text("info", WIDTH - display.measure_text("help", 0.4) - 4, 4, WIDTH, 1)
display.set_pen(0)
y = 16 + int(LINE_HEIGHT / 2)
display.text("Made by Pimoroni, powered by MicroPython", 5, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.text("Dual-core RP2040, 133MHz, 264KB RAM", 5, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.text("2MB Flash (1MB OS, 1MB Storage)", 5, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.text("296x128 pixel Black/White e-Ink", 5, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
y += LINE_HEIGHT
display.text("For more info:", 5, y, WIDTH, TEXT_SIZE)
y += LINE_HEIGHT
display.text("https://pimoroni.com/badger2040w", 5, y, WIDTH, TEXT_SIZE)
display.update()
# Call halt in a loop, on battery this switches off power.
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
while True:
display.halt()

Wyświetl plik

@ -1,312 +0,0 @@
import binascii
import badger2040w
import badger_os
# **** Put your list title here *****
list_title = "Checklist"
list_file = "checklist.txt"
# Global Constantsu
WIDTH = badger2040w.WIDTH
HEIGHT = badger2040w.HEIGHT
ARROW_THICKNESS = 3
ARROW_WIDTH = 18
ARROW_HEIGHT = 14
ARROW_PADDING = 2
MAX_ITEM_CHARS = 26
TITLE_TEXT_SIZE = 0.7
ITEM_TEXT_SIZE = 0.6
ITEM_SPACING = 20
LIST_START = 40
LIST_PADDING = 2
LIST_WIDTH = WIDTH - LIST_PADDING - LIST_PADDING - ARROW_WIDTH
LIST_HEIGHT = HEIGHT - LIST_START - LIST_PADDING - ARROW_HEIGHT
# Default list items - change the list items by editing checklist.txt
list_items = ["Badger", "Badger", "Badger", "Badger", "Badger", "Mushroom", "Mushroom", "Snake"]
save_checklist = False
try:
with open("checklist.txt", "r") as f:
raw_list_items = f.read()
if raw_list_items.find(" X\n") != -1:
# Have old style checklist, preserve state and note we should resave the list to remove the Xs
list_items = []
state = {
"current_item": 0,
"checked": []
}
for item in raw_list_items.strip().split("\n"):
if item.endswith(" X"):
state["checked"].append(True)
item = item[:-2]
else:
state["checked"].append(False)
list_items.append(item)
state["items_hash"] = binascii.crc32("\n".join(list_items))
badger_os.state_save("list", state)
save_checklist = True
else:
list_items = [item.strip() for item in raw_list_items.strip().split("\n")]
except OSError:
save_checklist = True
if save_checklist:
with open("checklist.txt", "w") as f:
for item in list_items:
f.write(item + "\n")
# ------------------------------
# Drawing functions
# ------------------------------
# Draw the list of items
def draw_list(items, item_states, start_item, highlighted_item, x, y, width, height, item_height, columns):
item_x = 0
item_y = 0
current_col = 0
for i in range(start_item, len(items)):
if i == highlighted_item:
display.set_pen(12)
display.rectangle(item_x, item_y + y - (item_height // 2), width // columns, item_height)
display.set_pen(0)
display.text(items[i], item_x + x + item_height, item_y + y, WIDTH, ITEM_TEXT_SIZE)
draw_checkbox(item_x, item_y + y - (item_height // 2), item_height, 15, 0, 2, item_states[i], 2)
item_y += item_height
if item_y >= height - (item_height // 2):
item_x += width // columns
item_y = 0
current_col += 1
if current_col >= columns:
return
# Draw a upward arrow
def draw_up(x, y, width, height, thickness, padding):
border = (thickness // 4) + padding
display.line(x + border, y + height - border,
x + (width // 2), y + border)
display.line(x + (width // 2), y + border,
x + width - border, y + height - border)
# Draw a downward arrow
def draw_down(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw a left arrow
def draw_left(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + width - border, y + border,
x + border, y + (height // 2))
display.line(x + border, y + (height // 2),
x + width - border, y + height - border)
# Draw a right arrow
def draw_right(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border,
x + width - border, y + (height // 2))
display.line(x + width - border, y + (height // 2),
x + border, y + height - border)
# Draw a tick
def draw_tick(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + ((height * 2) // 3),
x + (width // 2), y + height - border)
display.line(x + (width // 2), y + height - border,
x + width - border, y + border)
# Draw a cross
def draw_cross(x, y, width, height, thickness, padding):
border = (thickness // 2) + padding
display.line(x + border, y + border, x + width - border, y + height - border)
display.line(x + width - border, y + border, x + border, y + height - border)
# Draw a checkbox with or without a tick
def draw_checkbox(x, y, size, background, foreground, thickness, tick, padding):
border = (thickness // 2) + padding
display.set_pen(background)
display.rectangle(x + border, y + border, size - (border * 2), size - (border * 2))
display.set_pen(foreground)
display.line(x + border, y + border, x + size - border, y + border)
display.line(x + border, y + border, x + border, y + size - border)
display.line(x + size - border, y + border, x + size - border, y + size - border)
display.line(x + border, y + size - border, x + size - border, y + size - border)
if tick:
draw_tick(x, y, size, size, thickness, 2 + border)
# ------------------------------
# Program setup
# ------------------------------
changed = not badger2040w.woken_by_button()
state = {
"current_item": 0,
}
badger_os.state_load("list", state)
items_hash = binascii.crc32("\n".join(list_items))
if "items_hash" not in state or state["items_hash"] != items_hash:
# Item list changed, or not yet written reset the list
state["current_item"] = 0
state["items_hash"] = items_hash
state["checked"] = [False] * len(list_items)
changed = True
# Global variables
items_per_page = 0
# Create a new Badger and set it to update FAST
display = badger2040w.Badger2040W()
display.led(128)
display.set_font("sans")
display.set_thickness(2)
if changed:
display.set_update_speed(badger2040w.UPDATE_FAST)
else:
display.set_update_speed(badger2040w.UPDATE_TURBO)
# Find out what the longest item is
longest_item = 0
for i in range(len(list_items)):
while True:
item = list_items[i]
item_length = display.measure_text(item, ITEM_TEXT_SIZE)
if item_length > 0 and item_length > LIST_WIDTH - ITEM_SPACING:
list_items[i] = item[:-1]
else:
break
longest_item = max(longest_item, display.measure_text(list_items[i], ITEM_TEXT_SIZE))
# And use that to calculate the number of columns we can fit onscreen and how many items that would give
list_columns = 1
while longest_item + ITEM_SPACING < (LIST_WIDTH // (list_columns + 1)):
list_columns += 1
items_per_page = ((LIST_HEIGHT // ITEM_SPACING) + 1) * list_columns
# ------------------------------
# Main program loop
# ------------------------------
while True:
if len(list_items) > 0:
if display.pressed(badger2040w.BUTTON_A):
if state["current_item"] > 0:
page = state["current_item"] // items_per_page
state["current_item"] = max(state["current_item"] - (items_per_page) // list_columns, 0)
if page != state["current_item"] // items_per_page:
display.update_speed(badger2040w.UPDATE_FAST)
changed = True
if display.pressed(badger2040w.BUTTON_B):
state["checked"][state["current_item"]] = not state["checked"][state["current_item"]]
changed = True
if display.pressed(badger2040w.BUTTON_C):
if state["current_item"] < len(list_items) - 1:
page = state["current_item"] // items_per_page
state["current_item"] = min(state["current_item"] + (items_per_page) // list_columns, len(list_items) - 1)
if page != state["current_item"] // items_per_page:
display.update_speed(badger2040w.UPDATE_FAST)
changed = True
if display.pressed(badger2040w.BUTTON_UP):
if state["current_item"] > 0:
state["current_item"] -= 1
changed = True
if display.pressed(badger2040w.BUTTON_DOWN):
if state["current_item"] < len(list_items) - 1:
state["current_item"] += 1
changed = True
if changed:
badger_os.state_save("list", state)
display.set_pen(15)
display.clear()
display.set_pen(12)
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
display.rectangle(0, HEIGHT - ARROW_HEIGHT, WIDTH, ARROW_HEIGHT)
y = LIST_PADDING + 12
display.set_pen(0)
display.text(list_title, LIST_PADDING, y, WIDTH, TITLE_TEXT_SIZE)
y += 12
display.set_pen(0)
display.line(LIST_PADDING, y, WIDTH - LIST_PADDING - ARROW_WIDTH, y)
if len(list_items) > 0:
page_item = 0
if items_per_page > 0:
page_item = (state["current_item"] // items_per_page) * items_per_page
# Draw the list
display.set_pen(0)
draw_list(list_items, state["checked"], page_item, state["current_item"], LIST_PADDING, LIST_START,
LIST_WIDTH, LIST_HEIGHT, ITEM_SPACING, list_columns)
# Draw the interaction button icons
display.set_pen(0)
# Previous item
if state["current_item"] > 0:
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Next item
if state["current_item"] < (len(list_items) - 1):
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Previous column
if state["current_item"] > 0:
draw_left((WIDTH // 7) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
# Next column
if state["current_item"] < (len(list_items) - 1):
draw_right(((WIDTH * 6) // 7) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
if state["checked"][state["current_item"]]:
# Tick off item
draw_cross((WIDTH // 2) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_HEIGHT, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
else:
# Untick item
draw_tick((WIDTH // 2) - (ARROW_WIDTH // 2), HEIGHT - ARROW_HEIGHT,
ARROW_HEIGHT, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
else:
# Say that the list is empty
empty_text = "Nothing Here"
text_length = display.measure_text(empty_text, ITEM_TEXT_SIZE)
display.text(empty_text, ((LIST_PADDING + LIST_WIDTH) - text_length) // 2, (LIST_HEIGHT // 2) + LIST_START - (ITEM_SPACING // 4), WIDTH, ITEM_TEXT_SIZE)
display.update()
display.set_update_speed(badger2040w.UPDATE_TURBO)
changed = False
display.halt()

Wyświetl plik

@ -1,48 +0,0 @@
import badger2040w as badger2040
from badger2040w import WIDTH
import network
TEXT_SIZE = 1
LINE_HEIGHT = 16
# Display Setup
display = badger2040.Badger2040W()
display.led(128)
# Connects to the wireless network. Ensure you have entered your details in WIFI_CONFIG.py :).
display.connect()
net = network.WLAN(network.STA_IF).ifconfig()
# Page Header
display.set_pen(15)
display.clear()
display.set_pen(0)
display.set_pen(0)
display.rectangle(0, 0, WIDTH, 20)
display.set_pen(15)
display.text("badgerOS", 3, 4)
display.text("Network Details", WIDTH - display.measure_text("Network Details") - 4, 4)
display.set_pen(0)
y = 35 + int(LINE_HEIGHT / 2)
if net:
display.text("> LOCAL IP: {}".format(net[0]), 0, y, WIDTH)
y += LINE_HEIGHT
display.text("> Subnet: {}".format(net[1]), 0, y, WIDTH)
y += LINE_HEIGHT
display.text("> Gateway: {}".format(net[2]), 0, y, WIDTH)
y += LINE_HEIGHT
display.text("> DNS: {}".format(net[3]), 0, y, WIDTH)
else:
display.text("> No network connection!", 0, y, WIDTH)
y += LINE_HEIGHT
display.text("> Check details in WIFI_CONFIG.py", 0, y, WIDTH)
display.update()
# Call halt in a loop, on battery this switches off power.
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
while True:
display.halt()

Wyświetl plik

@ -1,215 +0,0 @@
import badger2040w as badger2040
from badger2040w import WIDTH
import machine
from urllib import urequest
import gc
import qrcode
import badger_os
# URLS to use (Entertainment, Science and Technology)
URL = ["http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml",
"http://feeds.bbci.co.uk/news/science_and_environment/rss.xml",
"http://feeds.bbci.co.uk/news/technology/rss.xml"]
code = qrcode.QRCode()
state = {
"current_page": 0,
"feed": 2
}
badger_os.state_load("news", state)
# Display Setup
display = badger2040.Badger2040W()
display.led(128)
display.set_update_speed(2)
# Setup buttons
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
def read_until(stream, char):
result = b""
while True:
c = stream.read(1)
if c == char:
return result
result += c
def discard_until(stream, c):
while stream.read(1) != c:
pass
def parse_xml_stream(s, accept_tags, group_by, max_items=3):
tag = []
text = b""
count = 0
current = {}
while True:
char = s.read(1)
if len(char) == 0:
break
if char == b"<":
next_char = s.read(1)
# Discard stuff like <?xml vers...
if next_char == b"?":
discard_until(s, b">")
continue
# Detect <![CDATA
elif next_char == b"!":
s.read(1) # Discard [
discard_until(s, b"[") # Discard CDATA[
text = read_until(s, b"]")
discard_until(s, b">") # Discard ]>
gc.collect()
elif next_char == b"/":
current_tag = read_until(s, b">")
top_tag = tag[-1]
# Populate our result dict
if top_tag in accept_tags:
current[top_tag.decode("utf-8")] = text.decode("utf-8")
# If we've found a group of items, yield the dict
elif top_tag == group_by:
yield current
current = {}
count += 1
if count == max_items:
return
tag.pop()
text = b""
gc.collect()
continue
else:
current_tag = read_until(s, b">")
tag += [next_char + current_tag.split(b" ")[0]]
text = b""
gc.collect()
else:
text += char
def measure_qr_code(size, code):
w, h = code.get_size()
module_size = int(size / w)
return module_size * w, module_size
def draw_qr_code(ox, oy, size, code):
size, module_size = measure_qr_code(size, code)
display.set_pen(15)
display.rectangle(ox, oy, size, size)
display.set_pen(0)
for x in range(size):
for y in range(size):
if code.get_module(x, y):
display.rectangle(ox + x * module_size, oy + y * module_size, module_size, module_size)
# A function to get the data from an RSS Feed, this in case BBC News.
def get_rss(url):
try:
stream = urequest.urlopen(url)
output = list(parse_xml_stream(stream, [b"title", b"description", b"guid", b"pubDate"], b"item"))
return output
except OSError as e:
print(e)
return False
# Connects to the wireless network. Ensure you have entered your details in WIFI_CONFIG.py :).
display.connect()
print(state["feed"])
feed = get_rss(URL[state["feed"]])
def draw_page():
# Clear the display
display.set_pen(15)
display.clear()
display.set_pen(0)
# Draw the page header
display.set_font("bitmap6")
display.set_pen(0)
display.rectangle(0, 0, WIDTH, 20)
display.set_pen(15)
display.text("News", 3, 4)
display.text("Page: " + str(state["current_page"] + 1), WIDTH - display.measure_text("Page: ") - 4, 4)
display.set_pen(0)
display.set_font("bitmap8")
# Draw articles from the feed if they're available.
if feed:
page = state["current_page"]
display.set_pen(0)
display.text(feed[page]["title"], 2, 30, WIDTH - 130, 2)
code.set_text(feed[page]["guid"])
draw_qr_code(WIDTH - 100, 25, 100, code)
else:
display.set_pen(0)
display.rectangle(0, 60, WIDTH, 25)
display.set_pen(15)
display.text("Unable to display news! Check your network settings in WIFI_CONFIG.py", 5, 65, WIDTH, 1)
display.update()
draw_page()
while 1:
changed = False
if button_down.value():
if state["current_page"] < 2:
state["current_page"] += 1
changed = True
if button_up.value():
if state["current_page"] > 0:
state["current_page"] -= 1
changed = True
if button_a.value():
state["feed"] = 0
state["current_page"] = 0
feed = get_rss(URL[state["feed"]])
badger_os.state_save("news", state)
changed = True
if button_b.value():
state["feed"] = 1
state["current_page"] = 0
feed = get_rss(URL[state["feed"]])
badger_os.state_save("news", state)
changed = True
if button_c.value():
state["feed"] = 2
state["current_page"] = 0
feed = get_rss(URL[state["feed"]])
badger_os.state_save("news", state)
changed = True
if changed:
draw_page()

Wyświetl plik

@ -1,139 +0,0 @@
import badger2040w
import qrcode
import time
import os
import badger_os
# Check that the qrcodes directory exists, if not, make it
try:
os.mkdir("/qrcodes")
except OSError:
pass
# Check that there is a qrcode.txt, if not preload
try:
text = open("/qrcodes/qrcode.txt", "r")
except OSError:
text = open("/qrcodes/qrcode.txt", "w")
text.write("""https://pimoroni.com/badger2040w
Badger 2040 W
* 296x128 1-bit e-ink
* 2.4GHz wireless
* five user buttons
* user LED
* 2MB QSPI flash
Scan this code to learn
more about Badger 2040 W.
""")
text.flush()
text.seek(0)
# Load all available QR Code Files
try:
CODES = [f for f in os.listdir("/qrcodes") if f.endswith(".txt")]
TOTAL_CODES = len(CODES)
except OSError:
pass
print(f'There are {TOTAL_CODES} QR Codes available:')
for codename in CODES:
print(f'File: {codename}')
display = badger2040w.Badger2040W()
code = qrcode.QRCode()
state = {
"current_qr": 0
}
def measure_qr_code(size, code):
w, h = code.get_size()
module_size = int(size / w)
return module_size * w, module_size
def draw_qr_code(ox, oy, size, code):
size, module_size = measure_qr_code(size, code)
display.set_pen(15)
display.rectangle(ox, oy, size, size)
display.set_pen(0)
for x in range(size):
for y in range(size):
if code.get_module(x, y):
display.rectangle(ox + x * module_size, oy + y * module_size, module_size, module_size)
def draw_qr_file(n):
display.led(128)
file = CODES[n]
codetext = open("/qrcodes/{}".format(file), "r")
lines = codetext.read().strip().split("\n")
code_text = lines.pop(0)
title_text = lines.pop(0)
detail_text = lines
# Clear the Display
display.set_pen(15) # Change this to 0 if a white background is used
display.clear()
display.set_pen(0)
code.set_text(code_text)
size, _ = measure_qr_code(128, code)
left = top = int((badger2040w.HEIGHT / 2) - (size / 2))
draw_qr_code(left, top, 128, code)
left = 128 + 5
display.text(title_text, left, 20, badger2040w.WIDTH, 2)
top = 40
for line in detail_text:
display.text(line, left, top, badger2040w.WIDTH, 1)
top += 10
if TOTAL_CODES > 1:
for i in range(TOTAL_CODES):
x = 286
y = int((128 / 2) - (TOTAL_CODES * 10 / 2) + (i * 10))
display.set_pen(0)
display.rectangle(x, y, 8, 8)
if state["current_qr"] != i:
display.set_pen(15)
display.rectangle(x + 1, y + 1, 6, 6)
display.update()
badger_os.state_load("qrcodes", state)
changed = not badger2040w.woken_by_button()
while True:
if TOTAL_CODES > 1:
if display.pressed(badger2040w.BUTTON_UP):
if state["current_qr"] > 0:
state["current_qr"] -= 1
changed = True
if display.pressed(badger2040w.BUTTON_DOWN):
if state["current_qr"] < TOTAL_CODES - 1:
state["current_qr"] += 1
changed = True
if display.pressed(badger2040w.BUTTON_B) or display.pressed(badger2040w.BUTTON_C):
display.set_pen(15)
display.clear()
badger_os.warning(display, "To add QR codes, connect Badger 2040 W to a PC, load up Thonny, and add files to /qrcodes directory.")
time.sleep(4)
changed = True
if changed:
draw_qr_file(state["current_qr"])
badger_os.state_save("qrcodes", state)
changed = False
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()

Wyświetl plik

@ -1,106 +0,0 @@
# This example grabs current weather details from Open Meteo and displays them on Badger 2040 W.
# Find out more about the Open Meteo API at https://open-meteo.com
import badger2040w as badger2040
from badger2040w import WIDTH
import urequests
import jpegdec
# Set your latitude/longitude here (find yours by right clicking in Google Maps!)
LAT = 53.38609085276884
LNG = -1.4239983439328177
TIMEZONE = "auto" # determines time zone from lat/long
URL = "http://api.open-meteo.com/v1/forecast?latitude=" + str(LAT) + "&longitude=" + str(LNG) + "&current_weather=true&timezone=" + TIMEZONE
# Display Setup
display = badger2040.Badger2040W()
display.led(128)
display.set_update_speed(2)
jpeg = jpegdec.JPEG(display.display)
# Connects to the wireless network. Ensure you have entered your details in WIFI_CONFIG.py :).
display.connect()
def get_data():
global weathercode, temperature, windspeed, winddirection, date, time
print(f"Requesting URL: {URL}")
r = urequests.get(URL)
# open the json data
j = r.json()
print("Data obtained!")
print(j)
# parse relevant data from JSON
current = j["current_weather"]
temperature = current["temperature"]
windspeed = current["windspeed"]
winddirection = calculate_bearing(current["winddirection"])
weathercode = current["weathercode"]
date, time = current["time"].split("T")
r.close()
def calculate_bearing(d):
# calculates a compass direction from the wind direction in degrees
dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
ix = round(d / (360. / len(dirs)))
return dirs[ix % len(dirs)]
def draw_page():
# Clear the display
display.set_pen(15)
display.clear()
display.set_pen(0)
# Draw the page header
display.set_font("bitmap6")
display.set_pen(0)
display.rectangle(0, 0, WIDTH, 20)
display.set_pen(15)
display.text("Weather", 3, 4)
display.set_pen(0)
display.set_font("bitmap8")
if temperature is not None:
# Choose an appropriate icon based on the weather code
# Weather codes from https://open-meteo.com/en/docs
# Weather icons from https://fontawesome.com/
if weathercode in [71, 73, 75, 77, 85, 86]: # codes for snow
jpeg.open_file("/icons/icon-snow.jpg")
elif weathercode in [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82]: # codes for rain
jpeg.open_file("/icons/icon-rain.jpg")
elif weathercode in [1, 2, 3, 45, 48]: # codes for cloud
jpeg.open_file("/icons/icon-cloud.jpg")
elif weathercode in [0]: # codes for sun
jpeg.open_file("/icons/icon-sun.jpg")
elif weathercode in [95, 96, 99]: # codes for storm
jpeg.open_file("/icons/icon-storm.jpg")
jpeg.decode(13, 40, jpegdec.JPEG_SCALE_FULL)
display.set_pen(0)
display.text(f"Temperature: {temperature}°C", int(WIDTH / 3), 28, WIDTH - 105, 2)
display.text(f"Wind Speed: {windspeed}kmph", int(WIDTH / 3), 48, WIDTH - 105, 2)
display.text(f"Wind Direction: {winddirection}", int(WIDTH / 3), 68, WIDTH - 105, 2)
display.text(f"Last update: {date}, {time}", int(WIDTH / 3), 88, WIDTH - 105, 2)
else:
display.set_pen(0)
display.rectangle(0, 60, WIDTH, 25)
display.set_pen(15)
display.text("Unable to display weather! Check your network settings in WIFI_CONFIG.py", 5, 65, WIDTH, 1)
display.update()
get_data()
draw_page()
# Call halt in a loop, on battery this switches off power.
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
while True:
display.halt()

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 2.3 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.2 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.9 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.0 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.0 KiB

Wyświetl plik

@ -1,3 +0,0 @@
Images must be 296x128 pixel JPEGs
Create a new "images" directory via Thonny, and upload your .jpg files there.

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 9.0 KiB

Some files were not shown because too many files have changed in this diff Show More