Compare commits

...

329 Commits

Author SHA1 Message Date
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
Connor Linfoot 32c10482d9
Add support for 96x48 display to Interstate75 (#867)
* Add DISPLAY_INTERSTATE75_96X48
2024-04-17 13:41:02 +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
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
Philip Howard a7a2e2bee0
Merge pull request #918 from pimoroni/patch-pngdec-1bit
PNGdec: Add greyscale support.
2024-03-27 12:59:25 +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
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
Philip Howard ee7f2758dd
Merge pull request #858 from pimoroni/patch-bump-micropython-oct-2023
CI: Bump MicroPython to v1.21.0.
2023-10-06 17:47:02 +01:00
Phil Howard 388d8af3dc Unicorn/others: Add SDCard library from micropython-lib to RPI_PICO_W builds. 2023-10-06 13:55:29 +01:00
Phil Howard 0f75a2839f Inky Frame: Include SDCard from micropython-lib. 2023-10-06 13:55:29 +01:00
Phil Howard e691628723 CI: Bump MicroPython to v1.21.0.
I swear I had no idea this was imminent.

Changes: 856e08b193...v1.21.0
2023-10-06 13:55:29 +01:00
Phil Howard 08ce4fbb81 MicroPython: Update boards to match upstream naming conventions. 2023-10-06 13:55:29 +01:00
Phil Howard 20de8a3198 CI: Bump MicroPython to 6f76d1c.
Changes: 856e08b193...6f76d1c7fa
2023-10-06 13:55:29 +01:00
Philip Howard 9499b7e908
Merge pull request #855 from pimoroni/patch-jpegdec
JPEGDEC: Treat byte arrays as raw JPEG data for #435.
2023-10-06 13:55:17 +01:00
Philip Howard 65fd3b1c5a
Merge pull request #850 from pimoroni/helgibbons-patch-1
IOExpander: add I2C address change example
2023-09-29 09:38:44 +01:00
Phil Howard 4b3e83f2ff JPEGDEC: Treat byte arrays as raw JPEG data for #435. 2023-09-29 09:18:55 +01:00
Philip Howard fc777ff0ca
Merge pull request #852 from pimoroni/helgibbons-patch-2
Add I2C pins for PicoVision
2023-09-27 10:57:10 +01:00
Hel Gibbons 5345cc42d2
Add I2C pins for PicoVision 2023-09-25 14:53:54 +01:00
Hel Gibbons 169ed9c763 IOExpander: add I2C address change example 2023-09-21 16:16:10 +01:00
Philip Howard 8eac60afc6
Merge pull request #846 from pimoroni/patch-bitmap-fixed-space
Bitmap Fonts: Fixed-width space for #765.
2023-09-15 09:32:23 +01:00
Phil Howard 93525a422f Bitmap Fonts: Fixed-width space for #765. 2023-09-15 09:07:59 +01:00
Hel Gibbons 36f3e3a69f
Merge pull request #844 from pimoroni/helgibbons-patch-1
Galactic: add links
2023-09-14 10:37:35 +01:00
Hel Gibbons 29a13305d2
Update README.md 2023-09-13 10:57:56 +01:00
Philip Howard 1f4704afdb
Merge pull request #843 from pimoroni/feature/picovector
PicoVector - Fixes & Improvements
2023-09-12 13:49:17 +01:00
Phil Howard ae7e6e8c6c PicoVector: Add a bounds method for polygon bounds. 2023-09-12 13:18:33 +01:00
Phil Howard 5f730ff400 PicoVector: Pass PicoGraphics clip into Pretty Poly. 2023-09-12 12:03:09 +01:00
Philip Howard c3919bd648
Merge pull request #840 from MichaelBell/patch-pretty-poly-perf
Improve pretty_poly performance
2023-09-11 12:03:25 +01:00
Philip Howard ed3ce45f00
Merge pull request #842 from MichaelBell/patch-fix-text-newline
Fix newlines in rotated text
2023-09-11 11:37:38 +01:00
Philip Howard 1a7deaab71
Merge pull request #841 from MichaelBell/patch-fix-vector-transform
Initialize all matrix values
2023-09-11 11:36:52 +01:00
Philip Howard 9735402ee3
Merge pull request #839 from MichaelBell/feature/fast-blend
Allow pen function for fast tile alpha blending
2023-09-11 11:36:04 +01:00
Philip Howard c045c405c3
Merge pull request #838 from MichaelBell/patch-micropython-build
Fix clean Micropython build
2023-09-11 10:32:46 +01:00
Mike Bell 80e1e16782 Fixes from compiling with gcc 12 2023-09-10 21:02:16 +01:00
Mike Bell cdd648f3f6 Small improvements to rotated font rendering 2023-09-10 17:20:44 +01:00
Mike Bell 81f42f25b6 Fix newlines in rotated text 2023-09-10 17:20:10 +01:00
Mike Bell 841c141ebf Interpolators for line segment, and faster transforms 2023-09-10 13:22:21 +01:00
Mike Bell c812eec432 Initialize all matrix values 2023-09-10 13:18:13 +01:00
Mike Bell 41eb2b503e Additional improvements to pretty_poly 2023-09-10 00:08:35 +01:00
Mike Bell 581481c2ef Improve pretty_poly performance
(cherry picked from commit 1077a12ff4fd958a7ea6d9e4fa5a86551eba5126)
2023-09-09 01:30:10 +01:00
Mike Bell e908d5e53e Allow pen function for fast tile alpha blending 2023-09-08 23:48:16 +01:00
Mike Bell 34b8ac9f0c Wrap pio.h includes in NO_QSTR so a fresh Micropython build doesn't fall over. 2023-09-08 18:59:25 +01:00
Philip Howard 9124b376d2
Merge pull request #837 from pimoroni/patch-tufty2040-vector
Tufty 2040: Vector examples.
2023-09-07 10:38:26 +01:00
Phil Howard c725b4eee0 Tufty 2040: Vector examples.
Add AdvRe.af for PicoW Explorer and Tufty 2040 spectrometer examples.
2023-09-07 10:14:32 +01:00
Philip Howard a334899b61
Merge pull request #783 from pimoroni/feature/ppaf
PicoVector.
2023-09-06 15:15:30 +01:00
Phil Howard cca2d569e4 PicoVector: Add vector spectrometer example for PicoW Explorer. 2023-09-06 14:07:23 +01:00
Philip Howard 3d8f8c9a83
Merge pull request #829 from ahnlak/lib-driver-include-fixes
Added includes to allow for libraries to be linked to out-of-tree
2023-09-06 10:32:53 +01:00
Phil Howard 788f6c3232 PicoVector: Add clock example for PicoW Explorer. 2023-09-06 10:31:40 +01:00
Phil Howard 231ceb70f2 PicoVector: Add basic polygon center of mass function. 2023-09-06 10:12:08 +01:00
Phil Howard c9fd68ec58 PNGDEC: Remove PNG RAM debug text. 2023-09-06 09:39:28 +01:00
Hel Gibbons b82429caf0
Merge pull request #834 from pimoroni/helgibbons-patch-1
Cosmic Unicorn: add link
2023-09-06 09:39:18 +01:00
Hel Gibbons 386a3594c0
Cosmic Unicorn: add link 2023-09-05 17:31:25 +01:00
Hel Gibbons 9e0b3adc0c
Merge pull request #830 from ahnlak/pico-unicorn-mp-examples
Added some PicoGraphics based MP examples for the PicoUnicorn
2023-09-05 16:46:52 +01:00
Pete Favelle 8c3a21ec1a Made sure all columns are used! 2023-09-05 16:09:02 +01:00
Pete Favelle 2f44e85431 Added some PicoGraphics based MP examples for the PicoUnicorn 2023-09-04 14:31:32 +01:00
Phil Howard 5a92a9c735 PNGDEC: Support for 2bpp indexed PNGs, fix open_RAM. 2023-09-04 13:55:15 +01:00
Pete Favelle 8a9ef39158 Added includes to allow for libraries to be linked to out-of-tree 2023-08-31 10:05:08 +01:00
Phil Howard c443f8d206 PicoVector: Tweak polygon tile rendering loop. 2023-08-22 09:32:28 +01:00
Phil Howard 591058fb12 PicoVector: Store pointer to PP mem. 2023-08-22 09:32:28 +01:00
Phil Howard cfe8b3c096 PicoVector: Text rotation support. 2023-08-22 09:32:28 +01:00
Phil Howard 9d0501a43c PicoVector: Polygon iter interface. 2023-08-22 09:32:28 +01:00
Phil Howard 7c5ebfce8c PicoVector: Matrix transforms and polygon type. 2023-08-22 09:32:28 +01:00
Phil Howard 61c9d7e9b6 PicoVector: Experimental matrix transforms. 2023-08-22 09:32:28 +01:00
Phil Howard c7d9fe411a PicoVector: Bugfixes and font/aa options. 2023-08-22 09:32:28 +01:00
Phil Howard 4671607b3a PicoVector: Vector anti-aliasing support. 2023-08-22 09:32:28 +01:00
Phil Howard 95ab839ba5 PicoVector: Text wrap support. 2023-08-22 09:32:28 +01:00
Phil Howard 9e430fd68c PicoVector: Better separation of concerns, add Alright Fonts support. 2023-08-22 09:32:28 +01:00
Phil Howard c9a8d5ef49 PicoVector: Move polygon drawing to a new home. 2023-08-22 09:32:28 +01:00
Phil Howard 38aaa04c5d Tufty 2040: Basic pretty polygon example. 2023-08-22 09:32:28 +01:00
Phil Howard e8dba75aff PicoGraphics: Use std:: prefix, fix some type issues. 2023-08-22 09:32:28 +01:00
Phil Howard 09a58b269f PicoGraphics: Various compile warning fixes for Pretty Poly. 2023-08-22 09:32:28 +01:00
Phil Howard cc7219b44a PicoGraphics: Experimental Pretty Poly bring-up. 2023-08-22 09:32:28 +01:00
Philip Howard 57042bfed3
Merge pull request #821 from pimoroni/dv_stick_minimal
PicoVision: Minimal changes required to support PV specific drivers/pen types.
2023-08-22 09:31:30 +01:00
Hel Gibbons dc4ee0d459
Merge pull request #822 from pimoroni/helgibbons-patch-1
stellar: correct paths to tiny font
2023-08-21 15:59:14 +01:00
Hel Gibbons 157180c476 stellar: correct path to font 2023-08-21 14:28:08 +01:00
Hel Gibbons 7344e4d1a4
stellar: correct path to 3x5 font 2023-08-21 14:16:25 +01:00
Phil Howard 1157e605a1 Picovision: Remove DV stick drivers to PV repo. 2023-08-21 14:04:49 +01:00
Philip Howard b82d16e8ae
Merge pull request #817 from pimoroni/feature/pico-explorer-pins
PicoGraphics: Add Pico W Explorer SPI pins.
2023-08-15 15:52:51 +01:00
Hel Gibbons 095122c606
Merge pull request #816 from pimoroni/helgibbons-patch-1
Galactic Unicorn: add link
2023-08-14 12:42:36 +01:00
Mike Bell 211e0aa618 DV Display: Fix unaligned read across page boundary 2023-08-14 12:40:15 +01:00
Mike Bell b8116fc371 DV Display: Ability to load sprites in native format 2023-08-14 12:40:15 +01:00
Mike Bell 0cfcb22aa4 DV Display: Add sprite test to cmake 2023-08-14 12:40:15 +01:00
Mike Bell 3cdfe558e8 DV Display: Ability to specify sprite blend mode 2023-08-14 12:40:15 +01:00
Mike Bell 103228a88d DV Display: Sprites in palette mode 2023-08-14 12:40:15 +01:00
Mike Bell 3a5f069ec1 DV Display: Fix clear sprite, fix tearing 2023-08-14 12:40:15 +01:00
Mike Bell 765b8a6226 DV Display: Begin exposing sprites 2023-08-14 12:40:15 +01:00
Mike Bell 3c2c7ccc94 DV Display: Support multiple scroll offsets 2023-08-14 12:40:15 +01:00
Mike Bell b9cd998709 DV Display: Allow scrolling by single pixel in x coordinate 2023-08-14 12:40:15 +01:00
Mike Bell 1a54f7b77d DV Display: Ability to specify a larger frame than the display, and scroll it 2023-08-14 12:40:15 +01:00
Mike Bell 8f78e3d6bc DV Display: Switch SWD loader back to pio0 to avoid conflict with wifi 2023-08-14 12:40:15 +01:00
Mike Bell a396512e7f DV Display: Expose reset functionality 2023-08-14 12:40:15 +01:00
Mike Bell 9a0b21d417 DV Display: Fix palette error 2023-08-14 12:40:15 +01:00
Mike Bell e9779fc0e7 DV Display: Probable fix for frame corruption 2023-08-14 12:40:15 +01:00
Mike Bell 559ce08e04 DV Display: Fix C++ examples 2023-08-14 12:40:15 +01:00
Phil Howard cbc05863c0 DV Display: Claim unused channels and SMs. 2023-08-14 12:40:15 +01:00
Phil Howard 7d8bbf5c08 DV Display: Claim DMA channels and cleanup unused pio_prog.
TODO: Use claim_unused_channel in a way that survives MicroPython soft reset.
2023-08-14 12:40:15 +01:00
Mike Bell 7e9f16d80c DV Display: Pixel doubled palette mode 2023-08-14 12:40:15 +01:00
Mike Bell 4b57162c06 DV Display: External I2C interface option 2023-08-14 12:40:15 +01:00
Phil Howard de4aaa80b6 DV Display: Refactor pio usage with mutex program loader. 2023-08-14 12:40:15 +01:00
Phil Howard 4afe062d19 MicroPython: Make DV display us fixed pio/dma. 2023-08-14 12:40:15 +01:00
Mike Bell 3bc215074c Make it possible to derive from DVDisplay if you want to do fancy things with the frame header 2023-08-14 12:40:15 +01:00
Mike Bell a6bd626334 RGB888 JPEG decode (implemented in some cases only) 2023-08-14 12:40:15 +01:00
Mike Bell 575e806cc8 Remove unnecessary data from JPEG range tables 2023-08-14 12:40:15 +01:00
Mike Bell be943bd5a0 Fix build 2023-08-14 12:40:15 +01:00
Mike Bell daf7232024 Limited support for palette and RGB888 modes 2023-08-14 12:40:15 +01:00
Mike Bell a7435c6a5e GPIO High and palette mode support 2023-08-14 12:40:15 +01:00
Mike Bell 5a6aa0186c Add EDID decoder 2023-08-14 12:40:15 +01:00
Mike Bell 360588ff67 LED control 2023-08-14 12:40:15 +01:00
Mike Bell 4ed1d61336 Ability to read EDID 2023-08-14 12:40:15 +01:00
Mike Bell 31b480d138 Support for half resolutions (pixel/line doubling in the driver) 2023-08-14 12:40:15 +01:00
Mike Bell c7049f4ff1 Ability to choose the resolution for the display 2023-08-14 12:40:15 +01:00
Mike Bell 1d8c836635 Read button state from display driver 2023-08-14 12:40:15 +01:00
Mike Bell e295e69c72 Slideshow from jpegs in SD card directory 2023-08-14 12:40:15 +01:00
Mike Bell 5971bc9ad8 Streamline RAM writes 2023-08-14 12:40:15 +01:00
Mike Bell a1caa9495c Buffer sequential writes 2023-08-14 12:40:15 +01:00
Mike Bell f4b8bc9025 Fix Micropython build 2023-08-14 12:40:15 +01:00
Mike Bell 2e8632f2b6 Use rescue DP to always get driver into a known state before load, boot via watchdog, better logging from driver. 2023-08-14 12:40:15 +01:00
Mike Bell da36b0ad32 Load DV Stick Driver over SWD. Currently unreliable. 2023-08-14 12:40:15 +01:00
Mike Bell 9acc270418 Growing circles - runs at 30FPS 2023-08-14 12:40:15 +01:00
Mike Bell 5f8e7556f0 Begin DV Stick display driver 2023-08-14 12:40:15 +01:00
Philip Howard a7efef0049
Merge pull request #815 from pimoroni/toolchain_env
Fix out of box failure when ARM toolchain is not in path
2023-08-14 12:27:44 +01:00
Hel Gibbons 5a5786d066
Merge pull request #812 from simonprickett/add-gfx-pack-carbon-intensity
Add gfx pack carbon intensity bar graph example.
2023-08-14 11:01:25 +01:00
Simon Prickett 710863099d Another go at the linter. 2023-08-14 10:40:43 +01:00
Simon Prickett 316957c263 Import order changed. 2023-08-12 13:39:18 +01:00
Simon Prickett 9b18ed2594 Further linter checks after running pylint in VSCode. 2023-08-12 13:38:25 +01:00
Simon Prickett 658025a99b Linter issues. 2023-08-12 13:33:03 +01:00
Hel Gibbons fef22530ea
Galactic Unicorn: add link 2023-08-11 16:38:33 +01:00
Angus Logan fc28845fb9 * Fix out of box failure when ARM toolchain is not in path
- Use pico_find_compiler to find linker
2023-08-11 11:48:58 +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
Simon Prickett 14eabf360f Adds carbon intensity graph example. 2023-08-07 22:47:01 +01:00
Simon Prickett fe805a711a Adds carbon intensity graph example. 2023-08-07 22:46:55 +01:00
Philip Howard d93839d56a
Merge pull request #793 from awjlogan/enviro-tidy
Enviro Pico description generation did not match f-string rounding
2023-08-04 10:43:06 +01:00
Philip Howard e1527c44d5
Merge pull request #811 from pimoroni/feature/rotation
Support for text and PNG 90-degree rotations
2023-08-04 10:42:17 +01:00
Phil Howard 4ad6df5cc3 PNGDEC: Rotation support. 2023-08-03 16:30:25 +01:00
Phil Howard 004c8de8eb Bitmap Fonts: Add rotation support.
* Fix bug with word-wrap ignoring \n
* Fix bug with word-wrap miscalculating word size
2023-08-03 16:30:25 +01:00
Philip Howard 3639b46881
Merge pull request #810 from pimoroni/patch-linting
CI: Fix linting issues.
2023-08-03 16:25:01 +01:00
Phil Howard b744f78a46 CI: Fix linting issues. 2023-08-03 16:06:24 +01:00
Philip Howard 5bc85c0e6d
Merge pull request #797 from North101/main
Make Galactic clock example responsive
2023-08-03 15:56:33 +01:00
ZodiusInfuser 6bd5a445ba
Merge pull request #809 from makosa-irvin/main
Added light sensor example to the cosmic and stellar unicorns
2023-08-03 15:35:43 +01:00
Irvin 6306d5e753 Minor formatting changes 2023-08-03 15:26:24 +01:00
Irvin f0bfc7c13b Improved readability 2023-08-03 15:19:01 +01:00
Irvin e1e467185a Minor changes on the unicorns 2023-08-03 15:03:55 +01:00
Irvin 7e65c15cfb Reduced flickering 2023-08-03 14:01:29 +01:00
Irvin Makosa 462724210c Modified the calculate_brightness function to reduce flickering on gu 2023-08-02 23:33:15 +01:00
Irvin Makosa 0b0474e062 Added light sensor example to the su 2023-08-02 01:15:38 +01:00
Irvin Makosa 90a2076b7b display percentage icon 2023-08-02 00:56:16 +01:00
Irvin Makosa e14903dd27 Added light sensor example on cu 2023-08-02 00:43:48 +01:00
Irvin Makosa f06d1035a4 Modified gu readme 2023-08-01 22:59:03 +01:00
Hel Gibbons d0c40af766
Merge pull request #807 from makosa-irvin/main
Added light sensor example with auto brightness feature
2023-08-01 12:35:44 +01:00
Hel Gibbons 439b97d96e
Merge pull request #806 from pimoroni/helgibbons-patch-1
Add link
2023-08-01 09:51:48 +01:00
Irvin Makosa 8bb5e17e65 Fixed minor formatting issues 2023-08-01 00:34:39 +01:00
Irvin b8cdff8f4f Added light sensor example with auto brightness feature 2023-07-31 17:31:02 +01:00
Hel Gibbons eb31f9b043
Add link 2023-07-31 17:28:52 +01:00
Phil Howard b368950f02 PicoGraphics: Add Pico W Explorer SPI pins. 2023-07-27 17:14:01 +01:00
Philip Howard 51574f839d
Merge pull request #802 from pimoroni/feature/pngdec
PicoGraphics: Add support for PNG decoding.
2023-07-27 11:01:40 +01:00
Hel Gibbons 03232bbeb5
Merge pull request #803 from pimoroni/examples/tiny2040
Tiny 2040: add button/LED example
2023-07-21 13:33:07 +01:00
Phil Howard 5ec6903f7f PNGDEC: Clean up API, add get_palette and index copy. 2023-07-21 13:23:08 +01:00
helgibbons c696cd5e2d Tiny 2040: add button/LED example 2023-07-21 13:03:44 +01:00
Phil Howard 6db7a9a0a6 PNGDEC: Add crude cropping/scaling. 2023-07-21 10:19:31 +01:00
Phil Howard 1630ddbbb2 PicoGraphics: Add support for PNG decoding. 2023-07-19 16:04:05 +01:00
Hel Gibbons 25237c54ce
Merge pull request #795 from pimoroni/patch/stellar-examples
Stellar: tidy examples
2023-07-04 19:06:17 +01:00
Alexander Wilde 16c2dc0356 Make Galatic clock example responsive 2023-07-04 10:41:33 +01:00
Hel Gibbons 8f5a94482b
Merge pull request #796 from thinkier/patch-1
Doc error in Pico Display Pack 2 README (C++)
2023-07-04 09:12:28 +01:00
thinkier aa8b158ba3
📝 maybe a copypaste error 2023-07-04 11:19:32 +10:00
Hel Gibbons 52df18e550 stellar: lint BME280/68x examples 2023-07-03 14:34:10 +01:00
Hel Gibbons 1d1b521dfb stellar: add BME280 and BME68x examples 2023-07-03 14:29:56 +01:00
Hel Gibbons 3786cbdfe6 Stellar: correct typo 2023-07-03 13:18:18 +01:00
Hel Gibbons 58cdc85b1f stellar: add encoder wheel demo 2023-07-03 12:15:12 +01:00
helgibbons 6b67f652c7 Stellar: adjust exchange_ticker.py 2023-07-02 19:17:24 +01:00
helgibbons 37638172ae Stellar: add temperature example 2023-07-02 19:02:08 +01:00
helgibbons 3236503805 Stellar: add pizazz to weather example 2023-07-02 17:48:53 +01:00
helgibbons ce24330842 Stellar: move font to common 2023-07-02 15:19:32 +01:00
helgibbons 130685eeeb Stellar: adjust html text example 2023-07-02 15:14:25 +01:00
Hel Gibbons 6afdfef45b Stellar: update weather example 2023-06-27 17:36:08 +01:00
Angus Logan 1e6e68356a Add rounding to lux report to prevent unit being overwritten
Correct unit for centigrade
2023-06-23 20:27:10 +01:00
Angus Logan d25c6953d0 Correct comment for backlight button functionality 2023-06-23 20:22:18 +01:00
Angus Logan 0a0b72701e Match descriptive terms to Python f-string rounding 2023-06-23 20:20:23 +01:00
Hel Gibbons 40f0554259
Merge pull request #792 from pimoroni/patch/co2-examples
SCD41: update examples
2023-06-23 16:13:54 +01:00
Hel Gibbons d9064f0162 SCD41: update Plasma Stick example 2023-06-23 15:23:41 +01:00
Hel Gibbons dc1f000134 SCD41: add Plasma 2040 example 2023-06-23 12:11:05 +01:00
Hel Gibbons 32ae70d16d SCD41: update example to use default pins 2023-06-23 11:55:25 +01:00
Hel Gibbons 8a6bb65d73
Merge pull request #791 from LionsPhil/doc765
Document PicoGraphics fixed_width
2023-06-23 10:01:57 +01:00
LionsPhil a0fe954b7c Document PicoGraphics fixed_width
(VSCode also stubbornly fixed some trailing space.)

Closes #765.
2023-06-22 23:58:03 +01:00
Hel Gibbons 951fe4d8b8 SCD41: update example to use default pins 2023-06-22 17:12:55 +01:00
Hel Gibbons cbaf1fa27d fix co2.py formatting 2023-06-22 12:20:25 +01:00
Hel Gibbons 16f8f0ab05 Adjust lava_lamp.py 2023-06-21 16:50:21 +01:00
Hel Gibbons d759522b08 Adjust clock.py
Clock now uses smaller font so it fits on the screen
2023-06-21 16:49:13 +01:00
Hel Gibbons 9307ea1360 add co2 example 2023-06-21 16:24:37 +01:00
Philip Howard 6fb35df544
Merge pull request #789 from pimoroni/feature/picographics-custom-fonts
PicoGraphics: Add MicroPython support for custom font data.
2023-06-19 08:56:34 +01:00
Phil Howard b0d63ef777 PicoGraphics: Add MicroPython support for custom font data. 2023-06-16 11:25:17 +01:00
Philip Howard d523eded0b
Merge pull request #716 from pimoroni/feature/bluetooth
MicroPython: Pico W Bluetooth Support
2023-06-16 11:15:37 +01:00
Phil Howard 090ce9d2c6 MicroPython: Enable Bluetooth support for Pico W builds. 2023-06-15 11:58:41 +01:00
Philip Howard 9d96d061e9
Merge pull request #786 from pimoroni/feature/stellar_unicorn
16% More Unicorn
2023-06-15 10:59:43 +01:00
Phil Howard 70a1b26041 ADC: Avoid re-initialising ADC.
Only init the ADC if it's not already running.

In MicroPython this could trounce an already initialised and configured ADC,
and would disable the temperature sensor if it had been enabled by a user
before initialising any of the affected libraries.
2023-06-04 21:46:23 +01:00
Phil Howard bff6bd023e Unicorn: Move gamma LUTs to pimoroni_common. 2023-06-04 21:46:12 +01:00
Phil Howard 19c57ebb20 Stellar: Refined stalemate detection in Life. 2023-06-01 20:21:24 +01:00
Phil Howard 94c5d74894 Stellar: Tweak & tidy examples. 2023-05-31 13:54:34 +01:00
ZodiusInfuser 67152e32e5 Copied Cosmic MPy examples to Stellar 2023-05-30 12:42:27 +01:00
ZodiusInfuser 7aa75e57a4 Add C++ examples for Stellar, and fix init 2023-05-30 12:06:58 +01:00
ZodiusInfuser 68f610184f Possible fix for stellar pio? 2023-05-30 11:16:51 +01:00
ZodiusInfuser aabe789f21 Initial setup for StellarUnicorn build 2023-05-30 10:32:25 +01:00
ZodiusInfuser bd4238945d Fixed case of some CosmicUnicorn variables 2023-05-30 10:25:33 +01:00
ZodiusInfuser ae252fbc6e Removed comma in *Unicorn readme code 2023-05-30 10:24:28 +01:00
Philip Howard d4609699ba
Merge pull request #781 from pimoroni/ci/caching-fun
CI: Add workflow version to cache key.
2023-05-25 11:31:39 +01:00
Philip Howard 74064407e9
Merge pull request #779 from pimoroni/picographics/fonts
PicoGraphics: Fixed-width bitmap font support.
2023-05-24 15:00:15 +01:00
Phil Howard 0a2e099886 CI: Add workflow version to cache key. 2023-05-18 11:55:21 +01:00
Hel Gibbons c8d3b6b7d1
Merge pull request #780 from pimoroni/helgibbons-patch-1
Add link to RGB Encoder Wheel shop page
2023-05-17 15:38:12 +01:00
Hel Gibbons 5aa227ff45
Update README.md 2023-05-17 14:04:16 +01:00
Phil Howard fba7b53c36 PicoGraphics: Fixed-width bitmap font support. 2023-05-15 11:03:39 +01:00
Philip Howard 00d1617947
Merge pull request #777 from pimoroni/patch-st7789-parallel-dma
Tufty 2040: DMA display update.
2023-05-12 14:19:31 +01:00
Phil Howard 652de85f4d Tufty 2040: RGB565 DMA display update.
Use DMA to transfer a native RGB565 display buffer to PIO rather than pushing into the TX FIFO in a loop.

Co-authored by @zx64 - https://github.com/pimoroni/pimoroni-pico/issues/776
2023-05-12 13:38:19 +01:00
Philip Howard 8648196cc2
Merge pull request #774 from pimoroni/breakout_encoder_wheel
Support for RGB Encoder Wheel Breakout
2023-05-12 11:58:15 +01:00
Philip Howard ec205fb045
Merge pull request #775 from MichaelBell/cosmic-ghost-fix
Ghosting fix for Cosmic
2023-05-12 09:14:01 +01:00
Mike Bell 5b31e018ff Possible ghosting fix for Cosmic 2023-05-10 20:09:59 +01:00
ZodiusInfuser d00185d831 Added C & MP interrupt example 2023-05-10 16:57:38 +01:00
ZodiusInfuser 0120975b3c Readme improvements 2023-05-10 16:08:51 +01:00
ZodiusInfuser 12e38c1157 Implemented GPIO MP support for Encoder wheel 2023-05-10 14:54:32 +01:00
Philip Howard 89699fd78f
Merge pull request #773 from pimoroni/ulab/bump-6.0.12
Ulab: Bump to 6.0.12.
2023-05-10 13:26:56 +01:00
Phil Howard 05cad0c157 Ulab: Bump to 6.0.12. 2023-05-10 13:03:47 +01:00
ZodiusInfuser 653090c89e Exposed support for GPIO pins on encoder wheel 2023-05-10 12:46:00 +01:00
Philip Howard 1c39da4997
Merge pull request #746 from mutatrum/main
Fix web server only serving file once and wifi country configuration
2023-05-09 14:15:04 +01:00
Philip Howard 092fbe472f
Merge pull request #748 from Quitsoon/patch-1
pico_rtc.py, Just a little PR for a possible typo :)
2023-05-09 14:00:18 +01:00
Philip Howard ecbd1e66de
Merge pull request #771 from raybellis/macos_fixes
Fixes for compilation under macOS / GCC 13.3.1
2023-05-09 13:48:05 +01:00
Ray Bellis bfb6490ec8 fix dangling pointer error 2023-05-08 13:19:47 +01:00
Ray Bellis 32dfdc6a20 use __builtin_bswap32 2023-05-08 13:17:51 +01:00
Ray Bellis 67df015bfe fonts need cstdint 2023-05-08 13:17:16 +01:00
Hel Gibbons 302d6ae0eb
Merge pull request #768 from pimoroni/helgibbons-patch-1
Cosmic: add links
2023-05-05 12:19:27 +01:00
Hel Gibbons 1be888f397
Cosmic: add links 2023-05-05 12:11:50 +01:00
Philip Howard 7491ced13b
Merge pull request #767 from pimoroni/1.14_lcd_improved
Display initialisation fixes for the Pico Display Pack 1.14" LCD
2023-05-04 15:42:37 +01:00
Niko Kotilainen 1dcad21ed2 Pico Display Pack: Display init fixes. 2023-05-04 15:07:27 +01:00
ZodiusInfuser 8966cbf348 Added C++ readme 2023-05-04 14:59:01 +01:00
Pete Favelle a59aa35df5
Improved inky's sleep_for, now handles up to 28 days (#754) 2023-05-04 14:54:23 +01:00
Philip Howard b6499e71fc
Merge pull request #764 from pimoroni/ci/smolmodules
Reduce size & workload of MicroPython build cache
2023-05-04 14:48:21 +01:00
ZodiusInfuser 5619274d3d Added MP readme 2023-05-04 14:10:39 +01:00
ZodiusInfuser 862806f357 Simplified example I2C setup 2023-05-04 14:10:12 +01:00
Phil Howard 7951ef9668 CI: Hack: Patch MicroPython to remove exception handling.
Force "-specs=nano.specs" on MicroPython builds and disable various stack unwinding and exception handling features for C++ modules.
2023-05-04 14:09:23 +01:00
ZodiusInfuser 4dadeb0d4d Add c++ examples readme 2023-05-04 11:16:55 +01:00
Phil Howard b30d9ca554 CI: Switch py modules from cmake hacks to manifest.py.
A long overdue fix. Uses board-specific manifest.py files to freeze Python modules, instead of polluting ports/rp2/modules.
2023-05-03 18:04:55 +01:00
ZodiusInfuser e0a405739c Fix namespace issue 2023-05-03 17:41:18 +01:00
ZodiusInfuser 9f925b5259 Ported most encoder wheel examples to C++ 2023-05-03 17:22:58 +01:00
Phil Howard 8648597134 CI: Clean ports/rp2/modules before each build. 2023-05-03 17:21:18 +01:00
ZodiusInfuser e3f9f14dcf Fix ioe reset timing out too early, and encoder reversed 2023-05-03 12:34:59 +01:00
ZodiusInfuser 226e7507dd Fix 2023-05-02 22:58:38 +01:00
ZodiusInfuser 1cfae8b5f8 More work on encoder wheel C++, adding reset to ioe 2023-05-02 22:55:19 +01:00
ZodiusInfuser 387df3bd12 Progress on encoder wheel C++ and MP 2023-05-02 17:31:11 +01:00
Phil Howard 45a2e0f5b1 MicroPython: Set hostname for Enviro and Inky. 2023-05-02 16:35:37 +01:00
Phil Howard e90ae33a99 CI: All MicroPython builds use local board dirs.
Simplify the build to use *only* local (to pimoroni-pico) copies of MicroPython board config dirs.

This allows us to specify MICROPY_C_HEAP_SIZE (and potentially other options) in board config rather than at build-time.
2023-05-02 16:21:11 +01:00
ZodiusInfuser d4d6cd1936 Progress on encoder wheel C++ and MP 2023-05-02 16:19:22 +01:00
Phil Howard dd4347dac3 CI: Grab only necessary modules.
Reduces the MicroPython cache from ~879MB down to ~187MB for a reduction of around 6,920MB across builds.
2023-05-02 15:35:02 +01:00
ZodiusInfuser 928c28b677 Switch to rom_map 2023-05-02 13:28:49 +01:00
ZodiusInfuser 2d45ed6ace Updated mp function list 2023-05-02 12:51:05 +01:00
ZodiusInfuser 178afd1469 remove description prints 2023-05-02 10:22:14 +01:00
ZodiusInfuser 6464f44437 Fix micropython config 2023-05-02 10:22:14 +01:00
ZodiusInfuser cd83a51e8a Fix micropython config 2023-05-02 10:22:14 +01:00
ZodiusInfuser f353525090 First porting of python examples 2023-05-02 10:22:14 +01:00
ZodiusInfuser 7c11593f7c Fix for IOExpander address not getting changed 2023-05-02 10:22:14 +01:00
ZodiusInfuser e3c3692e31 Test python for encoder 2023-05-02 10:22:14 +01:00
ZodiusInfuser 15978e5ddc Temporary fix for compiler issues 2023-05-02 10:22:14 +01:00
ZodiusInfuser 59d57a193b Initial support for Encoder wheel breakout 2023-05-02 10:22:14 +01:00
Quitsoon f6206876b7
Update pico_rtc.py
Just a little correction of the word "timer" instead of "alarm" for the last test.
2023-04-11 21:17:35 +02:00
mutatrum 7bdd85d677 Fix web server only serving file once and wifi country configuration 2023-04-08 16:57:01 +02:00
408 changed files with 35495 additions and 8658 deletions

View File

@ -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

View File

@ -7,70 +7,21 @@ on:
types: [created]
env:
MICROPYTHON_VERSION: v1.20.0
MICROPYTHON_VERSION: v1.22.2
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}}-with-libs
restore-keys: |
workspace-micropython-${{env.MICROPYTHON_VERSION}}-with-libs
# 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 base MicroPython submodules
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: micropython
run: git submodule update --init
- name: Fetch Pico SDK submodules
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: micropython/lib/pico-sdk
run: git submodule update --init
- 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: PICO
board: RPI_PICO
- name: picow
board: PICO_W
- name: tiny2040
board: RPI_PICO_W
- name: tiny2040_8mb
board: PIMORONI_TINY2040
- name: picolipo_4mb
board: PIMORONI_PICOLIPO_4MB
@ -78,114 +29,113 @@ jobs:
board: PIMORONI_PICOLIPO_16MB
- name: tufty2040
board: PIMORONI_TUFTY2040
local_board_dir: true
- name: enviro
board: PICO_W_ENVIRO
local_board_dir: true
patch: true
- name: galactic_unicorn
board: PICO_W
board: RPI_PICO_W
- name: cosmic_unicorn
board: PICO_W
board: RPI_PICO_W
- name: stellar_unicorn
board: RPI_PICO_W
- name: inky_frame
board: PICO_W_INKY
local_board_dir: true
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: pimoroni-${{ matrix.name }}-${{ github.event.release.tag_name || github.sha }}-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}}
restore-keys: |
workspace-micropython-${{env.MICROPYTHON_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
- 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: |
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
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
- name: "HACK: Revert Pico SDK Patch" # Avoid an already-patched MicroPython tree breaking our build
shell: bash
working-directory: micropython/lib/pico-sdk
run: |
git checkout .
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 (Local Board Dir)
if: matrix.local_board_dir == true
- 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_C_HEAP_SIZE=4096 -DMICROPY_BOARD=${{matrix.board}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Configure MicroPython (Upstream Board Dir)
if: matrix.local_board_dir != true
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_C_HEAP_SIZE=4096 -DMICROPY_BOARD=${{matrix.board}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build MicroPython # Multiple simultaneous jobs trigger https://github.com/pimoroni/pimoroni-pico/issues/761
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
micropython_version
cmake_configure
- name: Rename .uf2 for artifact
- name: Build MicroPython
shell: bash
working-directory: micropython/ports/rp2/build-${{matrix.name}}
run: |
cp firmware.uf2 $RELEASE_FILE.uf2
source $BUILD_TOOLS
cmake_build
- name: "Py_Decl: Verify UF2"
shell: bash
run: |
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

View File

@ -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

View File

@ -10,6 +10,8 @@ set(CMAKE_CXX_STANDARD 17)
# Initialize the SDK
pico_sdk_init()
pico_find_compiler(PICO_COMPILER_LD ${PICO_GCC_TRIPLE}-ld)
function(add_resource target file)
get_filename_component(NAME ${ARGV1} NAME_WE)
set(FILENAME ${ARGV1})
@ -21,7 +23,7 @@ function(add_resource target file)
${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}
${CMAKE_CURRENT_BINARY_DIR}
COMMAND arm-none-eabi-ld -r -b binary -o ${NAME}.o ${FILENAME}
COMMAND ${PICO_COMPILER_LD} -r -b binary -o ${NAME}.o ${FILENAME}
DEPENDS ${FILENAME}
)

View File

@ -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).
@ -116,6 +120,7 @@ We also maintain a C++/CMake boilerplate with GitHub workflows configured for te
* MICS6814 - Gas Sensor - https://shop.pimoroni.com/products/mics6814-gas-sensor-breakout
* RGB Potentiometer - https://shop.pimoroni.com/products/rgb-potentiometer-breakout
* RGB Encoder - https://shop.pimoroni.com/products/rgb-encoder-breakout
* RGB Encoder Wheel - https://shop.pimoroni.com/products/rgb-encoder-wheel-breakout
* IO Expander - https://shop.pimoroni.com/products/io-expander
* RV3028 - Real-Time Clock (RTC) - https://shop.pimoroni.com/products/rv3028-real-time-clock-rtc-breakout
* ST7735 - 0.96" LCD - https://shop.pimoroni.com/products/0-96-spi-colour-lcd-160x80-breakout
@ -139,6 +144,7 @@ We also maintain a C++/CMake boilerplate with GitHub workflows configured for te
* ICP10125 - High Accuracy Pressure / Altitude / Temperature Sensor - https://shop.pimoroni.com/products/icp10125-air-pressure-breakout
* SCD41 CO2 Sensor (Carbon Dioxide / Temperature / Humidity) - https://shop.pimoroni.com/products/scd41-co2-sensor-breakout
* VL53L5CX 8x8 Time of Flight Array Sensor - https://shop.pimoroni.com/products/vl53l5cx-time-of-flight-tof-sensor-breakout
* RGB Encoder Wheel - https://shop.pimoroni.com/products/rgb-encoder-wheel-breakout
## Kits

75
ci/micropython.sh Normal file
View File

@ -0,0 +1,75 @@
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 --depth=1 --branch=$MICROPYTHON_VERSION
cd micropython
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
}

BIN
common/fonts/3x5.bitmapfont Normal file

Binary file not shown.

View File

@ -78,7 +78,7 @@ namespace pimoroni {
return to_ms_since_boot(get_absolute_time());
}
constexpr uint8_t GAMMA_8BIT[256] = {
inline constexpr uint8_t GAMMA_8BIT[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
@ -98,7 +98,7 @@ namespace pimoroni {
/* Moved from pico_unicorn.cpp
v = (uint16_t)(powf((float)(n) / 255.0f, 2.2) * 16383.0f + 0.5f) */
constexpr uint16_t GAMMA_14BIT[256] = {
inline constexpr uint16_t GAMMA_14BIT[256] = {
0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 16, 20, 23, 28, 32,
37, 42, 48, 54, 61, 67, 75, 82, 90, 99, 108, 117, 127, 137, 148, 159,
170, 182, 195, 207, 221, 234, 249, 263, 278, 294, 310, 326, 343, 361, 379, 397,

View File

@ -41,6 +41,6 @@ add_subdirectory(pms5003)
add_subdirectory(sh1107)
add_subdirectory(st7567)
add_subdirectory(psram_display)
add_subdirectory(inky73)
add_subdirectory(shiftregister)
add_subdirectory(mlx90640)
add_subdirectory(inky73)
add_subdirectory(mlx90640)

View File

@ -11,7 +11,7 @@ namespace pimoroni {
public:
Analog(uint pin, float amplifier_gain = 1.0f, float resistor = 0.0f, float offset = 0.0f) :
pin(pin), amplifier_gain(amplifier_gain), resistor(resistor), offset(offset) {
adc_init();
if (!(adc_hw->cs & ADC_CS_EN_BITS)) adc_init();
//Make sure GPIO is high-impedance, no pullups etc
adc_gpio_init(pin);

View File

@ -4,7 +4,10 @@
#include "hardware/irq.h"
#include "hardware/clocks.h"
#include "encoder.hpp"
#ifndef NO_QSTR
#include "encoder.pio.h"
#endif
#define LAST_STATE(state) ((state) & 0b0011)
#define CURR_STATE(state) (((state) & 0b1100) >> 2)

View File

@ -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);

View File

@ -5,7 +5,10 @@
#include "hardware/dma.h"
#include "hardware/irq.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#ifndef NO_QSTR
#include "hub75.pio.h"
#endif
namespace pimoroni {
const uint DATA_BASE_PIN = 0;
@ -70,7 +73,7 @@ class Hub75 {
Pixel background = 0;
// DMA & PIO
uint dma_channel = 0;
int dma_channel = -1;
uint bit = 0;
uint row = 0;

View File

@ -4,7 +4,10 @@
#include "hardware/pio.h"
#include "hardware/dma.h"
#include "hardware/irq.h"
#ifndef NO_QSTR
#include "hub75.pio.h"
#endif
const uint DATA_BASE_PIN = 0;
const uint DATA_N_PINS = 6;

View File

@ -1,3 +1,7 @@
if(NOT TARGET shiftregister)
include(${CMAKE_CURRENT_LIST_DIR}/../shiftregister/shiftregister.cmake)
endif()
set(DRIVER_NAME inky73)
add_library(${DRIVER_NAME} INTERFACE)

View File

@ -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();
}
}

View File

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

View File

@ -320,8 +320,21 @@ namespace pimoroni {
Pin::adc(1, 7, 0)}
{}
bool IOExpander::init(bool skipChipIdCheck) {
bool succeeded = true;
bool IOExpander::init(bool skipChipIdCheck, bool perform_reset) {
if(!skipChipIdCheck) {
uint16_t chip_id = get_chip_id();
if(chip_id != CHIP_ID) {
if(debug) {
printf("Chip ID invalid: %04x expected: %04x\n", chip_id, CHIP_ID);
}
return false;
}
}
// Reset the chip if requested, to put it into a known state
if(perform_reset && !reset()) {
return false;
}
if(interrupt != PIN_UNUSED) {
gpio_set_function(interrupt, GPIO_FUNC_SIO);
@ -331,17 +344,36 @@ namespace pimoroni {
enable_interrupt_out(true);
}
if(!skipChipIdCheck) {
uint16_t chip_id = get_chip_id();
if(chip_id != CHIP_ID) {
if(debug) {
printf("Chip ID invalid: %04x expected: %04x\n", chip_id, CHIP_ID);
}
succeeded = false;
return true;
}
uint8_t IOExpander::check_reset() {
uint8_t user_flash_reg = reg::USER_FLASH;
uint8_t value;
if(i2c_write_blocking(i2c->get_i2c(), address, &user_flash_reg, 1, false) == PICO_ERROR_GENERIC) {
return 0x00;
}
if(i2c_read_blocking(i2c->get_i2c(), address, (uint8_t *)&value, sizeof(uint8_t), false) == PICO_ERROR_GENERIC) {
return 0x00;
}
return value;
}
bool IOExpander::reset() {
uint32_t start_time = millis();
set_bits(reg::CTRL, ctrl_mask::RESET);
// Wait for a register to read its initialised value
while(check_reset() != 0x78) {
sleep_ms(1);
if(millis() - start_time >= RESET_TIMEOUT_MS) {
if(debug)
printf("Timed out waiting for Reset!");
return false;
}
}
return succeeded;
return true;
}
i2c_inst_t* IOExpander::get_i2c() const {
@ -370,7 +402,7 @@ namespace pimoroni {
void IOExpander::set_address(uint8_t address) {
set_bit(reg::CTRL, 4);
i2c->reg_write_uint8(address, reg::ADDR, address);
i2c->reg_write_uint8(this->address, reg::ADDR, address);
this->address = address;
sleep_ms(250); //TODO Handle addr change IOError better
//wait_for_flash()
@ -491,13 +523,35 @@ namespace pimoroni {
return divider_good;
}
void IOExpander::set_pwm_period(uint16_t value, bool load) {
void IOExpander::set_pwm_period(uint16_t value, bool load, bool wait_for_load) {
value &= 0xffff;
i2c->reg_write_uint8(address, reg::PWMPL, (uint8_t)(value & 0xff));
i2c->reg_write_uint8(address, reg::PWMPH, (uint8_t)(value >> 8));
if(load)
pwm_load();
pwm_load(wait_for_load);
}
uint16_t IOExpander::set_pwm_frequency(float frequency, bool load, bool wait_for_load) {
uint32_t period = (uint32_t)(CLOCK_FREQ / frequency);
if (period / 128 > MAX_PERIOD) {
return MAX_PERIOD;
}
if (period < 2) {
return 2;
}
uint8_t divider = 1;
while ((period > MAX_PERIOD) && (divider < MAX_DIVIDER)) {
period >>= 1;
divider <<= 1;
}
period = MIN(period, MAX_PERIOD); // Should be unnecessary because of earlier raised errors, but kept in case
set_pwm_control(divider);
set_pwm_period((uint16_t)(period - 1), load, wait_for_load);
return (uint16_t)period;
}
uint8_t IOExpander::get_mode(uint8_t pin) {
@ -669,7 +723,7 @@ namespace pimoroni {
}
}
void IOExpander::output(uint8_t pin, uint16_t value, bool load) {
void IOExpander::output(uint8_t pin, uint16_t value, bool load, bool wait_for_load) {
if(pin < 1 || pin > NUM_PINS) {
printf("Pin should be in range 1-14.");
return;
@ -685,7 +739,7 @@ namespace pimoroni {
i2c->reg_write_uint8(address, io_pin.reg_pwml, (uint8_t)(value & 0xff));
i2c->reg_write_uint8(address, io_pin.reg_pwmh, (uint8_t)(value >> 8));
if(load)
pwm_load();
pwm_load(wait_for_load);
}
else {
if(value == LOW) {

View File

@ -26,6 +26,8 @@ namespace pimoroni {
static const uint8_t PIN_MODE_PWM = 0b00101; // PWM, Output, Push-Pull mode
static const uint8_t PIN_MODE_ADC = 0b01010; // ADC, Input-only (high-impedance)
static const uint32_t RESET_TIMEOUT_MS = 1000;
public:
static const uint8_t DEFAULT_I2C_ADDRESS = 0x18;
@ -45,6 +47,10 @@ namespace pimoroni {
static const uint16_t LOW = 0;
static const uint16_t HIGH = 1;
static const uint32_t CLOCK_FREQ = 24000000;
static const uint32_t MAX_PERIOD = (1 << 16) - 1;
static const uint32_t MAX_DIVIDER = (1 << 7);
//--------------------------------------------------
// Subclasses
@ -171,7 +177,12 @@ namespace pimoroni {
// Methods
//--------------------------------------------------
public:
bool init(bool skip_chip_id_check = false);
bool init(bool skip_chip_id_check = false, bool perform_reset = false);
private:
uint8_t check_reset();
public:
bool reset();
// For print access in micropython
i2c_inst_t* get_i2c() const;
@ -198,7 +209,8 @@ namespace pimoroni {
void pwm_clear(bool wait_for_clear = true);
bool pwm_clearing();
bool set_pwm_control(uint8_t divider);
void set_pwm_period(uint16_t value, bool load = true);
void set_pwm_period(uint16_t value, bool load = true, bool wait_for_load = true);
uint16_t set_pwm_frequency(float frequency, bool load = true, bool wait_for_load = true);
uint8_t get_mode(uint8_t pin);
void set_mode(uint8_t pin, uint8_t mode, bool schmitt_trigger = false, bool invert = false);
@ -206,7 +218,7 @@ namespace pimoroni {
int16_t input(uint8_t pin, uint32_t adc_timeout = 1);
float input_as_voltage(uint8_t pin, uint32_t adc_timeout = 1);
void output(uint8_t pin, uint16_t value, bool load = true);
void output(uint8_t pin, uint16_t value, bool load = true, bool wait_for_load = true);
void setup_rotary_encoder(uint8_t channel, uint8_t pin_a, uint8_t pin_b, uint8_t pin_c = 0, bool count_microsteps = false);
int16_t read_rotary_encoder(uint8_t channel);

View File

@ -64,8 +64,8 @@ namespace pimoroni {
}
void LTP305::set_character(uint8_t x, uint16_t ch) {
uint8_t *data = nullptr;
for(auto c : dotfont) {
const uint8_t *data = nullptr;
for(const auto& c : dotfont) {
if(c.code == ch) {
data = &c.data[0];
break;
@ -128,4 +128,4 @@ namespace pimoroni {
i2c->reg_write_uint8(address, CMD_BRIGHTNESS, brightness);
i2c->reg_write_uint8(address, CMD_UPDATE, 0x01);
}
}
}

View File

@ -1,3 +1,7 @@
if(NOT TARGET pwm)
include(${CMAKE_CURRENT_LIST_DIR}/../pwm/pwm.cmake)
endif()
set(DRIVER_NAME motor)
add_library(${DRIVER_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET pwm_cluster)
include(${CMAKE_CURRENT_LIST_DIR}/../pwm/pwm_cluster.cmake)
endif()
set(DRIVER_NAME motor_cluster)
add_library(${DRIVER_NAME} INTERFACE)

View File

@ -14,7 +14,9 @@ found here: https://github.com/raspberrypi/pico-examples/tree/master/pio/apa102
#include <math.h>
#include <cstdint>
#ifndef NO_QSTR
#include "apa102.pio.h"
#endif
#include "pico/stdlib.h"
#include "hardware/pio.h"

View File

@ -14,7 +14,9 @@ found here: https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812
#include <math.h>
#include <cstdint>
#ifndef NO_QSTR
#include "ws2812.pio.h"
#endif
#include "pico/stdlib.h"
#include "hardware/pio.h"

View File

@ -1,7 +1,10 @@
#include "pwm_cluster.hpp"
#include "hardware/gpio.h"
#include "hardware/clocks.h"
#ifndef NO_QSTR
#include "pwm_cluster.pio.h"
#endif
// Uncomment the below line to enable debugging
//#define DEBUG_MULTI_PWM

View File

@ -7,7 +7,9 @@
#define _PIO_SPI_H
#include "hardware/pio.h"
#ifndef NO_QSTR
#include "spi.pio.h"
#endif
typedef struct pio_spi_inst {
PIO pio;

View File

@ -1,3 +1,7 @@
if(NOT TARGET pwm)
include(${CMAKE_CURRENT_LIST_DIR}/../pwm/pwm.cmake)
endif()
set(DRIVER_NAME servo)
add_library(${DRIVER_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET pwm_cluster)
include(${CMAKE_CURRENT_LIST_DIR}/../pwm/pwm_cluster.cmake)
endif()
set(DRIVER_NAME servo_cluster)
add_library(${DRIVER_NAME} INTERFACE)

View File

@ -89,11 +89,19 @@ 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");
}
if(width == 240 && height == 135) { // Pico Display Pack (1.14" 240x135)
command(reg::VRHS, 1, "\x00"); // VRH Voltage setting
command(reg::GCTRL, 1, "\x75"); // VGH and VGL voltages
command(reg::VCOMS, 1, "\x3D"); // VCOM voltage
command(0xd6, 1, "\xa1"); // ???
command(reg::GMCTRP1, 14, "\x70\x04\x08\x09\x09\x05\x2A\x33\x41\x07\x13\x13\x29\x2f");
command(reg::GMCTRN1, 14, "\x70\x03\x09\x0A\x09\x06\x2B\x34\x41\x07\x12\x14\x28\x2E");
}
command(reg::INVON); // set inversion mode
command(reg::SLPOUT); // leave sleep mode
command(reg::DISPON); // turn display on
@ -125,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);
}
@ -177,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
@ -199,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;
}
@ -209,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
@ -231,29 +247,13 @@ namespace pimoroni {
}
void ST7789::write_blocking_parallel(const uint8_t *src, size_t len) {
const uint8_t *p = src;
while(len--) {
// Does not byte align correctly
//pio_sm_put_blocking(parallel_pio, parallel_sm, *p);
while (pio_sm_is_tx_fifo_full(parallel_pio, parallel_sm))
;
*(volatile uint8_t*)&parallel_pio->txf[parallel_sm] = *p;
p++;
}
write_blocking_dma(src, len);
dma_channel_wait_for_finish_blocking(st_dma);
uint32_t sm_stall_mask = 1u << (parallel_sm + PIO_FDEBUG_TXSTALL_LSB);
parallel_pio->fdebug = sm_stall_mask;
while (!(parallel_pio->fdebug & sm_stall_mask))
;
/*uint32_t mask = 0xff << d0;
while(len--) {
gpio_put(wr_sck, false);
uint8_t v = *src++;
gpio_put_masked(mask, v << d0);
//asm("nop;");
gpio_put(wr_sck, true);
asm("nop;");
}*/
// This may cause a race between PIO and the
// subsequent chipselect deassert for the last pixel
while(!pio_sm_is_tx_fifo_empty(parallel_pio, parallel_sm))
;
}
void ST7789::command(uint8_t command, size_t len, const char *data) {

View File

@ -11,7 +11,9 @@
#include "libraries/pico_graphics/pico_graphics.hpp"
#ifndef NO_QSTR
#include "st7789_parallel.pio.h"
#endif
#include <algorithm>

View File

@ -217,7 +217,7 @@ namespace pimoroni {
i2c->read_blocking(address, (uint8_t *)&value, 4, false);
// TODO do we need to bswap this return value?
return __bswap32(value);
return __builtin_bswap32(value);
}
// set distance mode to Short, Medium, or Long

View File

@ -1,5 +1,6 @@
add_subdirectory(breakout_dotmatrix)
add_subdirectory(breakout_encoder)
add_subdirectory(breakout_encoder_wheel)
add_subdirectory(breakout_ioexpander)
add_subdirectory(breakout_ltr559)
add_subdirectory(breakout_colourlcd160x80)
@ -60,3 +61,4 @@ add_subdirectory(encoder)
add_subdirectory(galactic_unicorn)
add_subdirectory(gfx_pack)
add_subdirectory(cosmic_unicorn)
add_subdirectory(stellar_unicorn)

View File

@ -0,0 +1,9 @@
add_subdirectory(buttons)
add_subdirectory(chase_game)
add_subdirectory(clock)
add_subdirectory(colour_picker)
add_subdirectory(encoder)
add_subdirectory(gpio_pwm)
add_subdirectory(interrupt)
add_subdirectory(led_rainbow)
add_subdirectory(stop_watch)

View File

@ -0,0 +1,77 @@
# RGB Encoder Wheel Breakout Examples (C++) <!-- omit in toc -->
- [Function Examples](#function-examples)
- [Buttons](#buttons)
- [Encoder](#encoder)
- [Interrupt](#interrupt)
- [LED Examples](#led-examples)
- [LED Rainbow](#led-rainbow)
- [Clock](#clock)
- [Interactive Examples](#interactive-examples)
- [Colour Picker](#colour-picker)
- [Stop Watch](#stop-watch)
- [Chase Game](#chase-game)
- [GPIO Examples](#gpio-examples)
- [GPIO PWM](#gpio-pwm)
## Function Examples
### Buttons
[buttons/buttons.cpp](buttons/buttons.cpp)
A demonstration of reading the 5 buttons on Encoder Wheel.
### Encoder
[encoder/encoder.cpp](encoder/encoder.cpp)
A demonstration of reading the rotary dial of the Encoder Wheel breakout.
### Interrupt
[interrupt/interrupt.cpp](interrupt/interrupt.cpp)
How to read the buttons and rotary dial of the Encoder Wheel breakout, only when an interrupt occurs.
## LED Examples
### LED Rainbow
[led_rainbow/led_rainbow.cpp](led_rainbow/led_rainbow.cpp)
Displays a rotating rainbow pattern on Encoder Wheel's LED ring.
### Clock
[clock/clock.cpp](clock/clock.cpp)
Displays a 12 hour clock on Encoder Wheel's LED ring, getting time from the system.
## Interactive Examples
### Colour Picker
[colour_picker/colour_picker.cpp](colour_picker/colour_picker.cpp)
Create a colour wheel on the Encoder Wheel's LED ring, and use all functions of the wheel to interact with it.
### Stop Watch
[stop_watch/stop_watch.cpp](stop_watch/stop_watch.cpp)
Display a circular stop-watch on the Encoder Wheel's LED ring.
### Chase Game
[chase_game/chase_game.cpp](chase_game/chase_game.cpp)
A simple alignment game. Use Encoder Wheel's rotary dial to align the coloured band to the white goal. The closer to the goal, the greener your coloured band will be. When you reach the goal, the goal will move to a new random position.
## GPIO Examples
### GPIO PWM
[gpio_pwm/gpio_pwm.cpp](gpio_pwm/gpio_pwm.cpp)
Output a sine wave PWM sequence on the Encoder Wheel's side GPIO pins.

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_buttons)
add_executable(${OUTPUT_NAME} buttons.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,96 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
A demonstration of reading the 5 buttons on Encoder Wheel.
*/
// Constants
const std::string BUTTON_NAMES[] = {"Up", "Down", "Left", "Right", "Centre"};
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
bool last_pressed[NUM_BUTTONS] = {false, false, false, false, false};
bool pressed[NUM_BUTTONS] = {false, false, false, false, false};
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Loop forever
while(true) {
// Read all of the encoder wheel's buttons
for(int b = 0 ; b < NUM_BUTTONS; b++) {
pressed[b] = wheel.pressed(b);
if(pressed[b] != last_pressed[b]) {
printf("%s %s\n", BUTTON_NAMES[b].c_str(), pressed[b] ? "Pressed" : "Released");
}
last_pressed[b] = pressed[b];
}
// Clear the LED ring
wheel.clear();
for(int i = 0; i < NUM_LEDS; i++) {
if(i % 6 == 3) {
wheel.set_rgb(i, 64, 64, 64);
}
}
// If up is pressed, set the top LEDs to yellow
if(pressed[UP]) {
int mid = NUM_LEDS;
for(int i = mid - 2; i < mid + 3; i++) {
wheel.set_rgb(i % NUM_LEDS, 255, 255, 0);
}
}
// If right is pressed, set the right LEDs to red
if(pressed[RIGHT]) {
int mid = NUM_LEDS / 4;
for(int i = mid - 2; i < mid + 3; i++) {
wheel.set_rgb(i % NUM_LEDS, 255, 0, 0);
}
}
// If down is pressed, set the bottom LEDs to green
if(pressed[DOWN]) {
int mid = NUM_LEDS / 2;
for(int i = mid - 2; i < mid + 3; i++) {
wheel.set_rgb(i % NUM_LEDS, 0, 255, 0);
}
}
// If left is pressed, set the left LEDs to blue
if(pressed[LEFT]) {
int mid = (NUM_LEDS * 3) / 4;
for(int i = mid - 2; i < mid + 3; i++) {
wheel.set_rgb(i % NUM_LEDS, 0, 0, 255);
}
}
// If centre is pressed, set the diagonal LEDs to half white
if(pressed[CENTRE]) {
for(int i = 0; i < NUM_LEDS; i++) {
if(i % 6 >= 2 && i % 6 <= 4) {
wheel.set_rgb(i, 128, 128, 128);
}
}
}
wheel.show();
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_chase_game)
add_executable(${OUTPUT_NAME} chase_game.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,148 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
A simple alignment game. Use Encoder Wheel's rotary dial to align the coloured band
to the white goal. The closer to the goal, the greener your coloured band will be.
When you reach the goal, the goal will move to a new random position.
*/
// The band colour hues to show in Angle mode
constexpr float GOAL_HUE = 0.333f;
constexpr float FAR_HUE = 0.0f;
// The width and colour settings for the band
constexpr float BAND_WIDTH = 5.0f;
constexpr float BAND_SATURATION = 1.0f;
constexpr float BAND_IN_GOAL_SATURATION = 0.5f;
constexpr float BAND_BRIGHTNESS = 1.0f;
// The width and colour settings for the goal
// Goal should be wider than the band by a small amount
constexpr float GOAL_MARGIN = 1.0f;
constexpr float GOAL_WIDTH = BAND_WIDTH + (2.0f * GOAL_MARGIN);
constexpr float GOAL_BRIGHTNESS = 0.4f;
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
float goal_position = 0.0f;
int16_t band_position = 0;
// Maps a value from one range to another
float map(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// Shows a band and goal with the given widths at the positions on the strip
void colour_band(float centre_position, float width, float goal_position, float goal_width, float hue) {
if(centre_position >= 0.0f && width > 0.0f && goal_width > 0.0) {
float band_start = centre_position - (width / 2);
float band_end = centre_position + (width / 2);
float band_centre = centre_position;
float goal_start = goal_position - (goal_width / 2);
float goal_end = goal_position + (goal_width / 2);
// Go through each led in the strip
for(int i = 0; i < NUM_LEDS; i++) {
// Set saturation and brightness values for if the led is inside or outside of the goal
float saturation = BAND_SATURATION;
float brightness = 0.0f;
if(i >= goal_start && i < goal_end) {
saturation = BAND_IN_GOAL_SATURATION;
brightness = GOAL_BRIGHTNESS;
}
if(goal_end >= NUM_LEDS && i + NUM_LEDS < goal_end) {
saturation = BAND_IN_GOAL_SATURATION;
brightness = GOAL_BRIGHTNESS;
}
if(goal_start < 0 && i - NUM_LEDS >= goal_start) {
saturation = BAND_IN_GOAL_SATURATION;
brightness = GOAL_BRIGHTNESS;
}
float val = brightness;
float sat = 0.0f;
if(i >= band_start && i < band_end) {
// Inside the band
if(i < band_centre) {
// Transition into the band
val = map(i, band_centre, band_start, BAND_BRIGHTNESS, brightness);
sat = map(i, band_centre, band_start, BAND_SATURATION, saturation);
}
else {
val = map(i, band_centre, band_end, BAND_BRIGHTNESS, brightness);
sat = map(i, band_centre, band_end, BAND_SATURATION, saturation);
}
}
else if(band_end >= NUM_LEDS && i + NUM_LEDS < band_end && i < band_centre) {
val = map(i + NUM_LEDS, band_centre, band_end, BAND_BRIGHTNESS, brightness);
sat = map(i + NUM_LEDS, band_centre, band_end, BAND_SATURATION, saturation);
}
else if(band_start < 0 && i - NUM_LEDS >= band_start && i >= band_centre) {
val = map(i - NUM_LEDS, band_centre, band_start, BAND_BRIGHTNESS, brightness);
sat = map(i - NUM_LEDS, band_centre, band_start, BAND_SATURATION, saturation);
}
//else {
// Outside of the band
//}
wheel.set_hsv(i, hue, sat, val);
}
wheel.show();
}
}
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Loop forever
while(true) {
band_position = wheel.step();
// Convert the difference between the band and goal positions into a colour hue
float diff1, diff2;
if(band_position > goal_position) {
diff1 = band_position - goal_position;
diff2 = (goal_position + NUM_LEDS) - band_position;
}
else {
diff1 = goal_position - band_position;
diff2 = (band_position + NUM_LEDS) - goal_position;
}
float position_diff = MIN(diff1, diff2);
float hue = map(position_diff, 0, NUM_LEDS / 2.0f, GOAL_HUE, FAR_HUE);
// Convert the band and goal positions to positions on the LED strip
float strip_band_position = map(band_position, 0, NUM_LEDS, 0.0f, (float)NUM_LEDS);
float strip_goal_position = map(goal_position, 0, NUM_LEDS, 0.0f, (float)NUM_LEDS);
// Draw the band and goal
colour_band(strip_band_position, BAND_WIDTH, strip_goal_position, GOAL_WIDTH, hue);
// Check if the band is within the goal, and if so, set a new goal
if(band_position >= goal_position - GOAL_MARGIN && band_position <= goal_position + GOAL_MARGIN)
goal_position = rand() % NUM_LEDS;
if(band_position >= NUM_LEDS && band_position + NUM_LEDS < goal_position + GOAL_MARGIN)
goal_position = rand() % NUM_LEDS;
if(goal_position - GOAL_MARGIN < 0 && band_position - NUM_LEDS >= goal_position + GOAL_MARGIN)
goal_position = rand() % NUM_LEDS;
}
}
return 0;
}

View File

@ -0,0 +1,14 @@
set(OUTPUT_NAME encoderwheel_clock)
add_executable(${OUTPUT_NAME} clock.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
hardware_rtc
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,114 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
Displays a 12 hour clock on Encoder Wheel's LED ring, getting time from the system.
*/
// Datetime Indices
const uint HOUR = 4;
const uint MINUTE = 5;
const uint SECOND = 6;
// Constants
constexpr float BRIGHTNESS = 1.0f; // The brightness of the LEDs
const uint UPDATES = 50; // How many times the LEDs will be updated per second
const uint UPDATE_RATE_US = 1000000 / UPDATES;
// Handy values for the number of milliseconds
constexpr float MILLIS_PER_SECOND = 1000;
constexpr float MILLIS_PER_MINUTE = MILLIS_PER_SECOND * 60;
constexpr float MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60;
constexpr float MILLIS_PER_HALF_DAY = MILLIS_PER_HOUR * 12;
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Calculates the brightness of an LED based on its index and a position along the LED ring
int led_brightness_at(int led, float position, float half_width = 1.0f, float span = 1.0f) {
float brightness = 0.0f;
float upper = position + half_width;
float lower = position - half_width;
if(led > position)
brightness = CLAMP((upper - led) / span, 0.0f, 1.0f);
else
brightness = CLAMP((led - lower) / span, 0.0f, 1.0f);
// Handle the LEDs being in a circle
if(upper >= NUM_LEDS)
brightness = CLAMP(((upper - NUM_LEDS) - led) / span, brightness, 1.0f);
else if(lower < 0.0f)
brightness = CLAMP((led - (lower + NUM_LEDS)) / span, brightness, 1.0f);
return (int)(brightness * BRIGHTNESS * 255);
}
int main() {
stdio_init_all();
// Start on Thursday 4th of May 2023 14:20:00
datetime_t now = {
.year = 2023,
.month = 05,
.day = 04,
.dotw = 4, // 0 is Sunday, so 4 is Thursday
.hour = 14,
.min = 20,
.sec = 00
};
// Start the RTC
rtc_init();
rtc_set_datetime(&now);
// clk_sys is >2000x faster than clk_rtc, so datetime is not updated immediately when rtc_get_datetime() is called.
// tbe delay is up to 3 RTC clock cycles (which is 64us with the default clock settings)
sleep_us(64);
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Loop forever
while(true) {
// Record the start time of this loop
absolute_time_t start_time = get_absolute_time();
// Get the current system time
rtc_get_datetime(&now);
// Convert the seconds, minutes, and hours into milliseconds (this is done to give a smoother animation, particularly for the seconds hand)
uint sec_as_millis = (now.sec * MILLIS_PER_SECOND);
uint min_as_millis = (now.min * MILLIS_PER_MINUTE) + sec_as_millis;
uint hour_as_millis = ((now.hour % 12) * MILLIS_PER_HOUR) + min_as_millis;
// Calculate the position on the LED ring that the, second, minute, and hour hands should be
float sec_pos = MIN(sec_as_millis / MILLIS_PER_MINUTE, 1.0f) * NUM_LEDS;
float min_pos = MIN(min_as_millis / MILLIS_PER_HOUR, 1.0f) * NUM_LEDS;
float hour_pos = MIN(hour_as_millis / MILLIS_PER_HALF_DAY, 1.0f) * NUM_LEDS;
for(int i = 0; i < NUM_LEDS; i++) {
// Turn on the LEDs close to the position of the current second, minute, and hour
int r = led_brightness_at(i, sec_pos);
int g = led_brightness_at(i, min_pos);
int b = led_brightness_at(i, hour_pos);
wheel.set_rgb(i, r, g, b);
}
wheel.show();
// Sleep until the next update, accounting for how long the above operations took to perform
sleep_until(delayed_by_us(start_time, UPDATE_RATE_US));
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_colour_picker)
add_executable(${OUTPUT_NAME} colour_picker.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,168 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
Create a colour wheel on the Encoder Wheel's LED ring, and use all functions of the wheel to interact with it.
Rotate the wheel to select a Hue
Press the up direction to increase Brightness
Press the down direction to decrease Brightness
Press the left direction to decrease Saturation
Press the right direction to increase Saturation
Press the centre to hide the selection marker
*/
// Constants
constexpr float BRIGHTNESS_STEP = 0.02f; // How much to increase or decrease the brightness each update
constexpr float SATURATION_STEP = 0.02f; // How much to increase or decrease the saturation each update
const uint UPDATES = 50; // How many times to update the LEDs per second
const uint UPDATE_RATE_US = 1000000 / UPDATES;
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
float brightness = 1.0f;
float saturation = 1.0f;
int position = 0;
bool changed = true;
bool last_centre_pressed = false;
// Struct for storing RGB values
struct Pixel {
uint8_t r;
uint8_t g;
uint8_t b;
Pixel() : r(0), g(0), b(0) {};
Pixel(uint8_t r, uint8_t g, uint8_t b) : r(r), g(g), b(b) {};
};
// Basic function to convert Hue, Saturation and Value to an RGB colour
Pixel hsv_to_rgb(float h, float s, float v) {
if(h < 0.0f) {
h = 1.0f + fmodf(h, 1.0f);
}
int i = int(h * 6);
float f = h * 6 - i;
v = v * 255.0f;
float sv = s * v;
float fsv = f * sv;
auto p = uint8_t(-sv + v);
auto q = uint8_t(-fsv + v);
auto t = uint8_t(fsv - sv + v);
uint8_t bv = uint8_t(v);
switch (i % 6) {
default:
case 0: return Pixel(bv, t, p);
case 1: return Pixel(q, bv, p);
case 2: return Pixel(p, bv, t);
case 3: return Pixel(p, q, bv);
case 4: return Pixel(t, p, bv);
case 5: return Pixel(bv, p, q);
}
}
// Simple function to clamp a value between 0.0 and 1.0
float clamp01(float value) {
return MAX(MIN(value, 1.0f), 0.0f);
}
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Loop forever
while(true) {
// Record the start time of this loop
absolute_time_t start_time = get_absolute_time();
// If up is pressed, increase the brightness
if(wheel.pressed(UP)) {
brightness += BRIGHTNESS_STEP;
changed = true; // Trigger a change
}
// If down is pressed, decrease the brightness
if(wheel.pressed(DOWN)) {
brightness -= BRIGHTNESS_STEP;
changed = true; // Trigger a change
}
// If right is pressed, increase the saturation
if(wheel.pressed(RIGHT)) {
saturation += SATURATION_STEP;
changed = true; // Trigger a change
}
// If left is pressed, decrease the saturation
if(wheel.pressed(LEFT)) {
saturation -= SATURATION_STEP;
changed = true; // Trigger a change
}
// Limit the brightness and saturation between 0.0 and 1.0
brightness = clamp01(brightness);
saturation = clamp01(saturation);
// Check if the encoder has been turned
if(wheel.delta() != 0) {
// Update the position based on the count change
position = wheel.step();
changed = true; // Trigger a change
}
// If centre is pressed, trigger a change
bool centre_pressed = wheel.pressed(CENTRE);
if(centre_pressed != last_centre_pressed) {
changed = true;
}
last_centre_pressed = centre_pressed;
// Was a change triggered?
if(changed) {
// Print the colour at the current hue, saturation, and brightness
Pixel pixel = hsv_to_rgb((float)position / NUM_LEDS, saturation, brightness);
printf("Colour Code = #%02x%02x%02x\n", pixel.r, pixel.g, pixel.b);
// Set the LED at the current position to either the actual colour,
// or an inverted version to show a "selection marker"
if(centre_pressed)
wheel.set_rgb(position, pixel.r, pixel.g, pixel.b);
else
wheel.set_rgb(position, 255 - pixel.r, 255 - pixel.g, 255 - pixel.b);
// Set the LEDs below the current position
for(int i = 0; i < position; i++) {
wheel.set_hsv(i, (float)i / NUM_LEDS, saturation, brightness);
}
// Set the LEDs after the current position
for(int i = position + 1; i < NUM_LEDS; i++) {
wheel.set_hsv(i, (float)i / NUM_LEDS, saturation, brightness);
}
wheel.show();
changed = false;
}
// Sleep until the next update, accounting for how long the above operations took to perform
sleep_until(delayed_by_us(start_time, UPDATE_RATE_US));
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_encoder)
add_executable(${OUTPUT_NAME} encoder.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,60 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
A demonstration of reading the rotary dial of the Encoder Wheel breakout.
*/
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
int position = 0;
float hue = 0.0f;
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Set the first LED
wheel.clear();
wheel.set_hsv(position, hue, 1.0f, 1.0f);
wheel.show();
// Loop forever
while(true) {
// Has the dial been turned since the last time we checked?
int16_t change = wheel.delta();
if(change != 0) {
// Print out the direction the dial was turned, and the count
if(change > 0)
printf("Clockwise, Count = %d\n", wheel.count());
else
printf("Counter Clockwise, Count = %d\n", wheel.count());
// Record the new position (from 0 to 23)
position = wheel.step();
// Record a colour hue from 0.0 to 1.0
hue = fmodf(wheel.revolutions(), 1.0f);
// Set the LED at the new position to the new hue
wheel.clear();
wheel.set_hsv(position, hue, 1.0f, 1.0f);
wheel.show();
}
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_gpio_pwm)
add_executable(${OUTPUT_NAME} gpio_pwm.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,74 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
Output a sine wave PWM sequence on the Encoder Wheel's side GPIO pins.
Press the centre button to stop the program.
*/
// Constants
constexpr float SPEED = 5.0f; // The speed that the LEDs will cycle at
const uint UPDATES = 50; // How many times the LEDs will be updated per second
const uint UPDATE_RATE_US = 1000000 / UPDATES;
constexpr float FREQUENCY = 1000.0f; // The frequency to run the PWM at
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
float offset = 0.0f;
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Set the PWM frequency for the GPIOs
uint16_t period = wheel.gpio_pwm_frequency(FREQUENCY);
// Set the GPIO pins to PWM outputs
for(int i = 0; i < NUM_GPIOS; i++) {
wheel.gpio_pin_mode(GPIOS[i], IOExpander::PIN_PWM);
}
// Loop forever
while(!wheel.pressed(CENTRE)) {
// Record the start time of this loop
absolute_time_t start_time = get_absolute_time();
offset += SPEED / 1000.0f;
// Update all the PWMs
for(int i = 0; i < NUM_GPIOS; i++) {
float angle = (((float)i / NUM_GPIOS) + offset) * M_PI;
uint16_t duty = (uint16_t)(((sinf(angle) / 2.0f) + 0.5f) * period);
// Set the GPIO pin to the new duty cycle, but do not load it yet
wheel.gpio_pin_value(GPIOS[i], duty, false);
}
// Have all the PWMs load at once
wheel.gpio_pwm_load();
// Sleep until the next update, accounting for how long the above operations took to perform
sleep_until(delayed_by_us(start_time, UPDATE_RATE_US));
}
// Turn off the PWM outputs
for(int i = 0; i < NUM_GPIOS; i++) {
wheel.gpio_pin_value(GPIOS[i], 0);
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_interrupt)
add_executable(${OUTPUT_NAME} interrupt.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,84 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
How to read the buttons and rotary dial of the Encoder Wheel breakout, only when an interrupt occurs.
*/
// Constants
const std::string BUTTON_NAMES[] = {"Up", "Down", "Left", "Right", "Centre"};
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c,
BreakoutEncoderWheel::DEFAULT_IOE_I2C_ADDRESS,
BreakoutEncoderWheel::DEFAULT_LED_I2C_ADDRESS,
3); // 3 for BG_BASE, 22 for EXPLORER_BASE, or 19 for some RP2040 boards
// If wiring the breakout via the qw/st connector, use the below line instead
// BreakoutEncoderWheel wheel(&i2c);
// Variables
bool last_pressed[NUM_BUTTONS] = {false, false, false, false, false};
bool pressed[NUM_BUTTONS] = {false, false, false, false, false};
int position = 0;
float hue = 0.0f;
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Set the first LED
wheel.clear();
wheel.set_hsv(position, hue, 1.0f, 1.0f);
wheel.show();
// Clear any left over interrupt from previous code
wheel.clear_interrupt_flag();
// Loop forever
while(true) {
// Check if the interrupt has fired
if(wheel.get_interrupt_flag()) {
wheel.clear_interrupt_flag();
// Read all of the encoder wheel's buttons
for(int b = 0 ; b < NUM_BUTTONS; b++) {
pressed[b] = wheel.pressed(b);
if(pressed[b] != last_pressed[b]) {
printf("%s %s\n", BUTTON_NAMES[b].c_str(), pressed[b] ? "Pressed" : "Released");
}
last_pressed[b] = pressed[b];
}
// The interrupt may have come from several sources,
// so check if it was a position change
int new_position = wheel.step();
if(new_position != position) {
// Record the new position (from 0 to 23)
position = new_position;
printf("Position = %d\n", position);
// Record a colour hue from 0.0 to 1.0
hue = fmodf(wheel.revolutions(), 1.0f);
// Set the LED at the new position to the new hue
wheel.clear();
wheel.set_hsv(position, hue, 1.0f, 1.0f);
wheel.show();
}
}
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_led_rainbow)
add_executable(${OUTPUT_NAME} led_rainbow.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,54 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
Displays a rotating rainbow pattern on Encoder Wheel's LED ring.
*/
// Constants
constexpr float SPEED = 5.0f; // The speed that the LEDs will cycle at
constexpr float BRIGHTNESS = 1.0f; // The brightness of the LEDs
const uint UPDATES = 50; // How many times the LEDs will be updated per second
const uint UPDATE_RATE_US = 1000000 / UPDATES;
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
float offset = 0.0;
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Loop forever
while(true) {
// Record the start time of this loop
absolute_time_t start_time = get_absolute_time();
offset += SPEED / 1000.0f;
// Update all the LEDs
for(int i = 0; i < NUM_LEDS; i++) {
float hue = (float)i / NUM_LEDS;
wheel.set_hsv(i, hue + offset, 1.0, BRIGHTNESS);
}
wheel.show();
// Sleep until the next update, accounting for how long the above operations took to perform
sleep_until(delayed_by_us(start_time, UPDATE_RATE_US));
}
}
return 0;
}

View File

@ -0,0 +1,13 @@
set(OUTPUT_NAME encoderwheel_stop_watch)
add_executable(${OUTPUT_NAME} stop_watch.cpp)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME}
pico_stdlib
breakout_encoder_wheel
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

View File

@ -0,0 +1,151 @@
#include <math.h>
#include <string>
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
#include "time.h"
using namespace pimoroni;
using namespace encoderwheel;
/*
Display a circular stop-watch on the Encoder Wheel's LED ring.
Press the centre button to start the stopwatch, then again to pause and resume.
*/
// Constants
constexpr float BRIGHTNESS = 1.0f; // The brightness of the LEDs
const uint UPDATES = 50; // How many times the LEDs will be updated per second
const uint MINUTE_UPDATES = UPDATES * 60; // How many times the LEDs will be updated per minute
const uint HOUR_UPDATES = MINUTE_UPDATES * 60; // How many times the LEDs will be updated per hour
const uint UPDATE_RATE_US = 1000000 / UPDATES;
constexpr float IDLE_PULSE_MIN = 0.2f; // The brightness (between 0.0 and 1.0) that the idle pulse will go down to
constexpr float IDLE_PULSE_MAX = 0.5f; // The brightness (between 0.0 and 1.0) that the idle pulse will go up to
constexpr float IDLE_PULSE_TIME = 2.0f; // The time (in seconds) to perform a complete idle pulse
constexpr uint UPDATES_PER_PULSE = IDLE_PULSE_TIME * UPDATES;
// The state constants used for program flow
enum State {
IDLE = 0,
COUNTING,
PAUSED
};
// Create a new BreakoutEncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Variables
State state = IDLE;
uint idle_update = 0;
uint second_update = 0;
uint minute_update = 0;
uint hour_update = 0;
bool last_centre_pressed = false;
int main() {
stdio_init_all();
// Attempt to initialise the encoder wheel
if(wheel.init()) {
// Record the current time
absolute_time_t current_time = get_absolute_time();
// Run the update loop forever
while(true) {
// Record the start time of this loop
absolute_time_t start_time = get_absolute_time();
// Read whether or not the wheen centre has been pressed
bool centre_pressed = wheel.pressed(CENTRE);
if(centre_pressed && centre_pressed != last_centre_pressed) {
switch(state) {
case IDLE: // If we're currently idle, switch to counting
second_update = 0;
minute_update = 0;
hour_update = 0;
state = COUNTING;
break;
case COUNTING: // If we're counting, switch to paused
state = PAUSED;
break;
case PAUSED: // If we're paused, switch back to counting
state = COUNTING;
}
}
last_centre_pressed = centre_pressed;
switch(state) {
// If we're idle, perform a pulsing animation to show the stopwatch is ready to go
case IDLE:
{
float percent_along = MIN((float)idle_update / (float)UPDATES_PER_PULSE, 1.0f);
float brightness = ((cosf(percent_along * M_PI * 2.0f) + 1.0f) / 2.0f) * ((IDLE_PULSE_MAX - IDLE_PULSE_MIN)) + IDLE_PULSE_MIN;
// Update all the LEDs
for(int i = 0; i < NUM_LEDS; i++) {
wheel.set_hsv(i, 0.0, 0.0, brightness);
}
wheel.show();
// Advance to the next update, wrapping around to zero if at the end
idle_update += 1;
if(idle_update >= UPDATES_PER_PULSE) {
idle_update = 0;
}
}
break;
// If we're counting, perform the stopwatch animation
case COUNTING:
{
// Calculate how many LED channels should light, as a proportion of a second, minute, and hour
float r_to_light = MIN((float)second_update / UPDATES, 1.0f) * 24.0f;
float g_to_light = MIN((float)minute_update / MINUTE_UPDATES, 1.0f) * 24.0f;
float b_to_light = MIN((float)hour_update / HOUR_UPDATES, 1.0f) * 24.0f;
// Set each LED, such that ones below the current time are fully lit, ones after
// are off, and the one at the transition is at a percentage of the brightness
for(int i = 0; i < NUM_LEDS; i++) {
int r = (int)(CLAMP(r_to_light - i, 0.0f, 1.0f) * BRIGHTNESS * 255.0f);
int g = (int)(CLAMP(g_to_light - i, 0.0f, 1.0f) * BRIGHTNESS * 255.0f);
int b = (int)(CLAMP(b_to_light - i, 0.0f, 1.0f) * BRIGHTNESS * 255.0f);
wheel.set_rgb(i, r, g, b);
}
wheel.show();
// Advance the second updates count, wrapping around to zero if at the end
second_update += 1;
if(second_update >= UPDATES) {
second_update = 0;
}
// Advance the minute updates count, wrapping around to zero if at the end
minute_update += 1;
if(minute_update >= MINUTE_UPDATES) {
minute_update = 0;
}
// Advance the hour updates count, wrapping around to zero if at the end
hour_update += 1;
if(hour_update >= HOUR_UPDATES) {
hour_update = 0;
}
}
break;
case PAUSED:
// Do nothing
break;
}
// Sleep until the next update, accounting for how long the above operations took to perform
current_time = delayed_by_us(start_time, UPDATE_RATE_US);
sleep_until(current_time);
}
}
return 0;
}

View File

@ -3,7 +3,11 @@
#include "pico_explorer.hpp"
#include "pico/stdlib.h"
#include "encoder.hpp"
#ifndef NO_QSTR
#include "quadrature_out.pio.h"
#endif
#include "drivers/st7789/st7789.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "button.hpp"

View File

@ -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);

View File

@ -0,0 +1,84 @@
add_executable(
stellar_rainbow_text
stellar_rainbow_text.cpp
)
# Pull in pico libraries that we need
target_link_libraries(stellar_rainbow_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics stellar_unicorn)
pico_enable_stdio_usb(stellar_rainbow_text 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(stellar_rainbow_text)
add_executable(
stellar_rainbow
stellar_rainbow.cpp
)
# Pull in pico libraries that we need
target_link_libraries(stellar_rainbow pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics stellar_unicorn)
pico_enable_stdio_usb(stellar_rainbow 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(stellar_rainbow)
add_executable(
stellar_eighties_super_computer
stellar_eighties_super_computer.cpp
)
# Pull in pico libraries that we need
target_link_libraries(stellar_eighties_super_computer pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics stellar_unicorn)
pico_enable_stdio_usb(stellar_eighties_super_computer 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(stellar_eighties_super_computer)
add_executable(
stellar_fire_effect
stellar_fire_effect.cpp
)
# Pull in pico libraries that we need
target_link_libraries(stellar_fire_effect pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics stellar_unicorn)
pico_enable_stdio_usb(stellar_fire_effect 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(stellar_fire_effect)
add_executable(
stellar_scroll_text
stellar_scroll_text.cpp
)
# Pull in pico libraries that we need
target_link_libraries(stellar_scroll_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics stellar_unicorn)
pico_enable_stdio_usb(stellar_scroll_text 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(stellar_scroll_text)
add_executable(
stellar_lava_lamp
stellar_lava_lamp.cpp
)
# Pull in pico libraries that we need
target_link_libraries(stellar_lava_lamp pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics stellar_unicorn)
pico_enable_stdio_usb(stellar_lava_lamp 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(stellar_lava_lamp)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "stellar_unicorn.hpp"
using namespace pimoroni;
PicoGraphics_PenRGB888 graphics(16, 16, nullptr);
StellarUnicorn stellar_unicorn;
float lifetime[16][16];
float age[16][16];
int main() {
stdio_init_all();
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
lifetime[x][y] = 1.0f + ((rand() % 10) / 100.0f);
age[x][y] = ((rand() % 100) / 100.0f) * lifetime[x][y];
}
}
stellar_unicorn.init();
while(true) {
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_UP)) {
stellar_unicorn.adjust_brightness(+0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
stellar_unicorn.adjust_brightness(-0.01);
}
graphics.set_pen(0, 0, 0);
graphics.clear();
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
if(age[x][y] < lifetime[x][y] * 0.3f) {
graphics.set_pen(230, 150, 0);
graphics.pixel(Point(x, y));
}else if(age[x][y] < lifetime[x][y] * 0.5f) {
float decay = (lifetime[x][y] * 0.5f - age[x][y]) * 5.0f;
graphics.set_pen(decay * 230, decay * 150, 0);
graphics.pixel(Point(x, y));
}
if(age[x][y] >= lifetime[x][y]) {
age[x][y] = 0.0f;
lifetime[x][y] = 1.0f + ((rand() % 10) / 100.0f);
}
age[x][y] += 0.01f;
}
}
stellar_unicorn.update(&graphics);
sleep_ms(10);
}
return 0;
}

View File

@ -0,0 +1,115 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "pico/stdlib.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "stellar_unicorn.hpp"
using namespace pimoroni;
PicoGraphics_PenRGB888 graphics(16, 16, nullptr);
StellarUnicorn stellar_unicorn;
// extra row of pixels for sourcing flames and averaging
int width = 16;
int height = 17;
// a buffer that's at least big enough to store 55 x 15 values (to allow for both orientations)
float heat[2000] = {0.0f};
void set(int x, int y, float v) {
heat[x + y * width] = v;
}
float get(int x, int y) {
/*if(x < 0 || x >= width || y < 0 || y >= height) {
return 0.0f;
}*/
x = x < 0 ? 0 : x;
x = x >= width ? width - 1 : x;
return heat[x + y * width];
}
int main() {
stdio_init_all();
stellar_unicorn.init();
stellar_unicorn.set_brightness(0.2);
bool landscape = true;
/*
while(true) {
stellar_unicorn.set_pixel(0, 0, 255, 0, 0);
stellar_unicorn.set_pixel(1, 1, 0, 255, 0);
stellar_unicorn.set_pixel(2, 2, 0, 0, 255);
}*/
while(true) {
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_UP)) {
stellar_unicorn.adjust_brightness(+0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
stellar_unicorn.adjust_brightness(-0.01);
}
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
float value = get(x, y);
graphics.set_pen(0, 0, 0);
if(value > 0.5f) {
graphics.set_pen(255, 255, 180);
}else if(value > 0.4f) {
graphics.set_pen(220, 160, 0);
}else if(value > 0.3f) {
graphics.set_pen(180, 30, 0);
}else if(value > 0.22f) {
graphics.set_pen(20, 20, 20);
}
if(landscape) {
graphics.pixel(Point(x, y));
}else{
graphics.pixel(Point(y, x));
}
// update this pixel by averaging the below pixels
float average = (get(x, y) + get(x, y + 2) + get(x, y + 1) + get(x - 1, y + 1) + get(x + 1, y + 1)) / 5.0f;
// damping factor to ensure flame tapers out towards the top of the displays
average *= 0.95f;
// update the heat map with our newly averaged value
set(x, y, average);
}
}
stellar_unicorn.update(&graphics);
// clear the bottom row and then add a new fire seed to it
for(int x = 0; x < width; x++) {
set(x, height - 1, 0.0f);
}
// add a new random heat source
int source_count = landscape ? 5 : 1;
for(int c = 0; c < source_count; c++) {
int px = (rand() % (width - 4)) + 2;
set(px , height - 2, 1.0f);
set(px + 1, height - 2, 1.0f);
set(px - 1, height - 2, 1.0f);
set(px , height - 1, 1.0f);
set(px + 1, height - 1, 1.0f);
set(px - 1, height - 1, 1.0f);
}
sleep_ms(20);
}
return 0;
}

View File

@ -0,0 +1,148 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "stellar_unicorn.hpp"
using namespace pimoroni;
PicoGraphics_PenRGB888 graphics(16, 16, nullptr);
StellarUnicorn stellar_unicorn;
// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel
// Outputs are rgb in the range 0-255 for each channel
void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
float i = floor(h * 6.0f);
float f = h * 6.0f - i;
v *= 255.0f;
uint8_t p = v * (1.0f - s);
uint8_t q = v * (1.0f - f * s);
uint8_t t = v * (1.0f - (1.0f - f) * s);
switch (int(i) % 6) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
}
struct blob_t {
float x, y;
float r;
float dx, dy;
};
constexpr int blob_count = 20;
int main() {
stdio_init_all();
stellar_unicorn.init();
stellar_unicorn.set_brightness(0.5);
// randomise blob start positions, directions, and size
std::array<blob_t, blob_count> blobs;
for(auto &blob : blobs) {
blob.x = rand() % 16;
blob.y = rand() % 16;
blob.r = ((rand() % 40) / 10.0f) + 5.0f;
blob.dx = ((rand() % 2) / 10.0f) - 0.05f;
blob.dy = ((rand() % 3) / 10.0f) - 0.1f;
}
float hue = 0.0f;
while(true) {
// allow user to adjust brightness
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_UP)) {
stellar_unicorn.adjust_brightness(+0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
stellar_unicorn.adjust_brightness(-0.01);
}
uint start_ms = to_ms_since_boot(get_absolute_time());
// calculate the influence of each blob on the liquid based
// on their distance to each pixel. this causes blobs to
// "merge" into each other when we use fixed thresholds to
// determine which colour to draw with
float liquid[16][16] = {0.0f};
for(auto &blob : blobs) {
float r_sq = blob.r * blob.r;
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
float d_sq = (x - blob.x) * (x - blob.x) + (y - blob.y) * (y - blob.y);
if(d_sq <= r_sq) {
// add this blobs influence to this pixel
liquid[x][y] += 1.0f - (d_sq / r_sq);
}
}
}
}
// update the blob positions
for(auto &blob : blobs) {
blob.x += blob.dx;
blob.y += blob.dy;
// if we hit the edge then bounce!
if(blob.x < 0.0f || blob.x >= 11.0f) {
blob.dx *= -1.0f;
}
if(blob.y < 0.0f || blob.y >= 53.0f) {
blob.dy *= -1.0f;
}
}
// rotate the hue
hue += 0.001f;
// calculate dark, medium, and bright shades for rendering the
// lava
uint8_t dark_r, dark_g, dark_b;
from_hsv(hue, 1.0f, 0.3f, dark_r, dark_g, dark_b);
uint8_t mid_r, mid_g, mid_b;
from_hsv(hue, 1.0f, 0.6f, mid_r, mid_g, mid_b);
uint8_t bright_r, bright_g, bright_b;
from_hsv(hue, 1.0f, 1.0f, bright_r, bright_g, bright_b);
// clear the canvas
graphics.set_pen(0, 0, 0);
graphics.clear();
// render the lava
for(int y = 0; y < 16; y++) {
for(int x = 0; x < 16; x++) {
float v = liquid[x][y];
// select a colour for this pixel based on how much
// "blobfluence" there is at this position in the liquid
if(v >= 1.5f) {
graphics.set_pen(bright_r, bright_g, bright_b);
graphics.pixel(Point(y, x));
}else if(v >= 1.25f) {
graphics.set_pen(mid_r, mid_g, mid_b);
graphics.pixel(Point(y, x));
}else if(v >= 1.0f) {
graphics.set_pen(dark_r, dark_g, dark_b);
graphics.pixel(Point(y, x));
}
}
}
uint end_ms = to_ms_since_boot(get_absolute_time());
printf("rendering took %dms\n", end_ms - start_ms);
stellar_unicorn.update(&graphics);
}
return 0;
}

View File

@ -0,0 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "stellar_unicorn.hpp"
using namespace pimoroni;
PicoGraphics_PenRGB888 graphics(16, 16, nullptr);
StellarUnicorn stellar_unicorn;
// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel
// Outputs are rgb in the range 0-255 for each channel
void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
float i = floor(h * 6.0f);
float f = h * 6.0f - i;
v *= 255.0f;
uint8_t p = v * (1.0f - s);
uint8_t q = v * (1.0f - f * s);
uint8_t t = v * (1.0f - (1.0f - f) * s);
switch (int(i) % 6) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
}
void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) {
int w = graphics.measure_text(t, s);
p.x += (53 / 2) - (w / 2);
p.y += (11 / 2);
graphics.text(t, Point(p.x, p.y), -1, s, a);
//graphics.text(t, Point(p.x + 1, p.y), -1, s, a);
//graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a);
//graphics.text(t, Point(p.x, p.y + 1), -1, s, a);
}
struct star_t {
float dx, dy, x, y, a;
uint8_t brightness() {
int b = a / 5;
return b > 15 ? 15 : b;
}
};
void init_star(star_t &s) {
s.x = ((rand() % 100) / 5.0f) - 10.0f;
s.y = ((rand() % 100) / 10.0f) - 5.0f;
s.dx = s.x / 10.0f;
s.dy = s.y / 10.0f;
s.a = 0;
}
void step_star(star_t &s) {
s.x += s.dx;
s.y += s.dy;
s.a++;
if(s.a > 100) {
init_star(s);
}
}
int main() {
stdio_init_all();
uint8_t hue_map[16][3];
for(int i = 0; i < 16; i++) {
from_hsv(i / 16.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]);
}
star_t stars[100];
for(int i = 0; i < 100; i++) {
init_star(stars[i]);
stars[i].a = i;
}
gpio_set_function(28, GPIO_FUNC_SIO);
gpio_set_dir(28, GPIO_OUT);
for(int i = 0; i < 10; i++) {
gpio_put(28, !gpio_get(28));
sleep_ms(100);
}
sleep_ms(1000);
gpio_put(28,true);
stellar_unicorn.init();
float i = 0;
float hue_offset = 0.0f;
bool animate = true;
float stripe_width = 3.0f;
float speed = 1.0f;
float curve = 0.0f;
while(true) {
if(animate) {
i += speed;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_VOLUME_UP)) {
curve += 0.05;
if(hue_offset > 1.0f) hue_offset = 1.0f;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_VOLUME_DOWN)) {
curve -= 0.05;
if(hue_offset < 0.0f) hue_offset = 0.0f;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_UP)) {
stellar_unicorn.adjust_brightness(+0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
stellar_unicorn.adjust_brightness(-0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_SLEEP)) {
animate = false;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_A)) {
speed += 0.05f;
speed = speed >= 10.0f ? 10.0f : speed;
animate = true;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_B)) {
speed -= 0.05f;
speed = speed <= 0.0f ? 0.0f : speed;
animate = true;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_C)) {
stripe_width += 0.05f;
stripe_width = stripe_width >= 10.0f ? 10.0f : stripe_width;
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_D)) {
stripe_width -= 0.05f;
stripe_width = stripe_width <= 1.0f ? 1.0f : stripe_width;
}
for(int x = 0; x < 16; x++) {
for(int y = 0; y < 16; y++) {
int v = ((sin((x + y) / stripe_width + (sin((y * 3.1415927f * 2.0f) / 11.0f) * curve) + i / 15.0f) + 1.5f) / 2.5f) * 255.0f;
uint8_t r = (hue_map[x][0] * v) / 256;
uint8_t g = (hue_map[x][1] * v) / 256;
uint8_t b = (hue_map[x][2] * v) / 256;
graphics.set_pen(r, g, b);
graphics.pixel(Point(x, y));
}
}
stellar_unicorn.update(&graphics);
printf("%d\n", stellar_unicorn.light());
sleep_ms(20);
}
printf("done\n");
return 0;
}

View File

@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "stellar_unicorn.hpp"
using namespace pimoroni;
PicoGraphics_PenRGB888 graphics(16, 16, nullptr);
StellarUnicorn stellar_unicorn;
// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel
// Outputs are rgb in the range 0-255 for each channel
void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
float i = floor(h * 6.0f);
float f = h * 6.0f - i;
v *= 255.0f;
uint8_t p = v * (1.0f - s);
uint8_t q = v * (1.0f - f * s);
uint8_t t = v * (1.0f - (1.0f - f) * s);
switch (int(i) % 6) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
}
void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) {
int w = graphics.measure_text(t, s);
p.x += (16 / 2) - (w / 2);
p.y += (16 / 2);
graphics.text(t, Point(p.x, p.y), -1, s, a);
graphics.text(t, Point(p.x + 1, p.y), -1, s, a);
graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a);
graphics.text(t, Point(p.x, p.y + 1), -1, s, a);
}
int main() {
uint8_t hue_map[16][3];
for(int i = 0; i < 16; i++) {
from_hsv(i / 16.0f, 1.0f, 0.5f, hue_map[i][0], hue_map[i][1], hue_map[i][2]);
}
stellar_unicorn.init();
graphics.set_font("sans");
uint i = 0;
while(true) {
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_UP)) {
stellar_unicorn.adjust_brightness(+0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
stellar_unicorn.adjust_brightness(-0.01);
}
i++;
graphics.set_pen(0, 0, 0);
graphics.clear();
float s = 0.4f;//0.65f + (sin(i / 25.0f) * 0.15f);
float a = 1.0f;// (sin(i / 25.0f) * 100.0f);
float x = (sin((i) / 50.0f) * 45.0f);
float y = (cos((i) / 40.0f) * 2.5f);
graphics.set_pen(255, 255, 255);
text("Galactic Unicorn", Point(x, y), s, a);
uint8_t *p = (uint8_t *)graphics.frame_buffer;
for(size_t i = 0; i < 16 * 16; i++) {
int x = i % 16;
int y = i / 16;
uint r = *p++;
uint g = *p++;
uint b = *p++;
p++;
if(r > 0) {
r = hue_map[x][0];
g = hue_map[x][1];
b = hue_map[x][2];
}
graphics.set_pen(r, g, b);
graphics.pixel(Point(x, y));
}
stellar_unicorn.update(&graphics);
}
printf("done\n");
return 0;
}

View File

@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "stellar_unicorn.hpp"
using namespace pimoroni;
PicoGraphics_PenRGB888 graphics(16, 16, nullptr);
StellarUnicorn stellar_unicorn;
std::string message = "Pirate. Monkey. Robot. Ninja.";
// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel
// Outputs are rgb in the range 0-255 for each channel
void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
float i = floor(h * 6.0f);
float f = h * 6.0f - i;
v *= 255.0f;
uint8_t p = v * (1.0f - s);
uint8_t q = v * (1.0f - f * s);
uint8_t t = v * (1.0f - (1.0f - f) * s);
switch (int(i) % 6) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
}
int main() {
stdio_init_all();
stellar_unicorn.init();
float scroll = -16.0f;
while(true) {
//uint time_ms = to_ms_since_boot(get_absolute_time());
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_UP)) {
stellar_unicorn.adjust_brightness(+0.01);
}
if(stellar_unicorn.is_pressed(stellar_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
stellar_unicorn.adjust_brightness(-0.01);
}
int width = graphics.measure_text(message, 1);
scroll += 0.125f;
if(scroll > width) {
scroll = -16.0f;
}
graphics.set_pen(0, 0, 0);
graphics.clear();
uint8_t r = 0, g = 0, b = 0;
from_hsv(scroll / 100.0f, 1.0f, 0.5f, r, g, b);
graphics.set_pen(r, g, b);
graphics.text(message, Point(0 - scroll, 5), -1, 0.55);
stellar_unicorn.update(&graphics);
sleep_ms(10);
}
return 0;
}

View File

@ -2,6 +2,7 @@ add_subdirectory(hershey_fonts)
add_subdirectory(bitmap_fonts)
add_subdirectory(breakout_dotmatrix)
add_subdirectory(breakout_encoder)
add_subdirectory(breakout_encoder_wheel)
add_subdirectory(breakout_ioexpander)
add_subdirectory(breakout_ltr559)
add_subdirectory(breakout_rgbmatrix5x5)
@ -35,9 +36,11 @@ add_subdirectory(motor2040)
add_subdirectory(inventor2040w)
add_subdirectory(adcfft)
add_subdirectory(jpegdec)
add_subdirectory(pngdec)
add_subdirectory(inky_frame)
add_subdirectory(inky_frame_7)
add_subdirectory(galactic_unicorn)
add_subdirectory(gfx_pack)
add_subdirectory(interstate75)
add_subdirectory(cosmic_unicorn)
add_subdirectory(stellar_unicorn)

View File

@ -47,7 +47,7 @@ void ADCFFT::init() {
// Initialize the ADC harware
// (resets it, enables the clock, spins until the hardware is ready)
adc_init();
if (!(adc_hw->cs & ADC_CS_EN_BITS)) adc_init();
// Select analog mux input (0...3 are GPIO 26, 27, 28, 29; 4 is temp sensor)
adc_select_input(adc_channel);

View File

@ -1,12 +1,14 @@
add_library(automation INTERFACE)
target_sources(automation INTERFACE
${CMAKE_CURRENT_LIST_DIR}/automation.cpp
)
target_include_directories(automation INTERFACE ${CMAKE_CURRENT_LIST_DIR})
#include(${PIMORONI_PICO_PATH}/drivers/analog/analog.cmake)
# Pull in pico libraries that we need
target_link_libraries(automation INTERFACE pico_stdlib hardware_pwm hardware_i2c pimoroni_i2c analog)
if(NOT TARGET analog)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/analog/analog.cmake)
endif()
add_library(automation INTERFACE)
target_sources(automation INTERFACE
${CMAKE_CURRENT_LIST_DIR}/automation.cpp
)
target_include_directories(automation INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(automation INTERFACE pico_stdlib hardware_pwm hardware_i2c pimoroni_i2c analog)

View File

@ -1,11 +1,23 @@
set(LIB_NAME badger2040)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE bitmap_fonts hershey_fonts pico_stdlib hardware_pwm uc8151_legacy)
if(NOT TARGET uc8151_legacy)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/uc8151_legacy/uc8151_legacy.cmake)
endif()
if(NOT TARGET bitmap_fonts)
include(${CMAKE_CURRENT_LIST_DIR}/../bitmap_fonts/bitmap_fonts.cmake)
endif()
if(NOT TARGET hershey_fonts)
include(${CMAKE_CURRENT_LIST_DIR}/../hershey_fonts/hershey_fonts.cmake)
endif()
set(LIB_NAME badger2040)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE bitmap_fonts hershey_fonts uc8151_legacy pico_stdlib hardware_pwm)

View File

@ -1,11 +1,15 @@
#include "bitmap_fonts.hpp"
namespace bitmap {
int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage) {
int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage, bool fixed_width) {
if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp
return 0;
}
if(fixed_width) {
return font->max_width * scale;
}
uint8_t char_index = c;
if(char_index > 127) {
@ -21,7 +25,7 @@ namespace bitmap {
return font->widths[char_index] * scale;
}
int32_t measure_text(const font_t *font, const std::string_view &t, const uint8_t scale, const uint8_t letter_spacing) {
int32_t measure_text(const font_t *font, const std::string_view &t, const uint8_t scale, const uint8_t letter_spacing, bool fixed_width) {
int32_t text_width = 0;
unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195;
for(auto c : t) {
@ -31,14 +35,14 @@ namespace bitmap {
} else if (c == unicode_sorta::PAGE_195_START) {
continue;
}
text_width += measure_character(font, c, scale, codepage);
text_width += measure_character(font, c, scale, codepage, fixed_width);
text_width += letter_spacing * scale;
codepage = unicode_sorta::PAGE_195; // Reset back to default
}
return text_width;
}
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale, unicode_sorta::codepage_t codepage) {
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale, int32_t rotation, unicode_sorta::codepage_t codepage) {
if(c < 32 || c > 127 + 64) { // + 64 char remappings defined in unicode_sorta.hpp
return;
}
@ -85,7 +89,8 @@ namespace bitmap {
uint8_t accent_offset = char_index < 65 ? offset_upper : offset_lower;
// Offset our y position to account for our column canvas being 32 pixels
int y_offset = y - (8 * scale);
// this gives us 8 "pixels" of headroom above the letters for diacritic marks
int font_offset = (8 * scale);
// Iterate through each horizontal column of font (and accent) data
for(uint8_t cx = 0; cx < font->widths[char_index]; cx++) {
@ -94,6 +99,8 @@ namespace bitmap {
// We shift the char down 8 pixels to make room for an accent above.
uint32_t data = *d << 8;
int32_t o_x = cx * scale;
// For fonts that are taller than 8 pixels (up to 16) they need two bytes
if(two_bytes_per_column) {
d++;
@ -109,7 +116,28 @@ namespace bitmap {
// Draw the 32 pixel column
for(uint8_t cy = 0; cy < 32; cy++) {
if((1U << cy) & data) {
rectangle(x + (cx * scale), y_offset + (cy * scale), scale, scale);
int32_t o_y = cy * scale;
int32_t px = 0;
int32_t py = 0;
switch (rotation) {
case 0:
px = x + o_x;
py = y - font_offset + o_y;
break;
case 90:
px = x + font_offset - o_y;
py = y + o_x;
break;
case 180:
px = x - o_x;
py = y + font_offset - o_y;
break;
case 270:
px = x - font_offset + o_y;
py = y - o_x;
break;
}
rectangle(px, py, scale, scale);
}
}
@ -119,10 +147,14 @@ namespace bitmap {
}
}
void text(const font_t *font, rect_func rectangle, const std::string_view &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale, const uint8_t letter_spacing) {
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
void text(const font_t *font, rect_func rectangle, const std::string_view &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale, const uint8_t letter_spacing, bool fixed_width, int32_t rotation) {
uint32_t char_offset = 0;
uint32_t line_offset = 0; // line (if wrapping) offset
unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195;
int32_t space_width = measure_character(font, ' ', scale, codepage, fixed_width);
space_width += letter_spacing * scale;
size_t i = 0;
while(i < t.length()) {
// find length of current word
@ -148,38 +180,53 @@ namespace bitmap {
} else if (t[j] == unicode_sorta::PAGE_195_START) {
continue;
}
word_width += measure_character(font, t[j], scale, codepage);
word_width += measure_character(font, t[j], scale, codepage, fixed_width);
word_width += letter_spacing * scale;
codepage = unicode_sorta::PAGE_195;
}
// if this word would exceed the wrap limit then
// move to the next line
if(co != 0 && co + word_width > (uint32_t)wrap) {
co = 0;
lo += (font->height + 1) * scale;
if(char_offset != 0 && char_offset + word_width > (uint32_t)wrap) {
char_offset = 0;
line_offset += (font->height + 1) * scale;
}
// draw word
for(size_t j = i; j < next_break; j++) {
for(size_t j = i; j < std::min(next_break + 1, t.length()); j++) {
if (t[j] == unicode_sorta::PAGE_194_START) {
codepage = unicode_sorta::PAGE_194;
continue;
} else if (t[j] == unicode_sorta::PAGE_195_START) {
continue;
}
if (t[j] == '\n') {
lo += (font->height + 1) * scale;
co = 0;
if (t[j] == '\n') { // Linebreak
line_offset += (font->height + 1) * scale;
char_offset = 0;
} else if (t[j] == ' ') { // Space
char_offset += space_width;
} else {
character(font, rectangle, t[j], x + co, y + lo, scale, codepage);
co += measure_character(font, t[j], scale, codepage);
co += letter_spacing * scale;
switch(rotation) {
case 0:
character(font, rectangle, t[j], x + char_offset, y + line_offset, scale, rotation, codepage);
break;
case 90:
character(font, rectangle, t[j], x - line_offset, y + char_offset, scale, rotation, codepage);
break;
case 180:
character(font, rectangle, t[j], x - char_offset, y - line_offset, scale, rotation, codepage);
break;
case 270:
character(font, rectangle, t[j], x + line_offset, y - char_offset, scale, rotation, codepage);
break;
}
char_offset += measure_character(font, t[j], scale, codepage, fixed_width);
char_offset += letter_spacing * scale;
}
codepage = unicode_sorta::PAGE_195;
}
// move character offset to end of word and add a space
co += font->widths[0] * scale;
// move character offset
i = next_break += 1;
}
}

View File

@ -19,9 +19,9 @@ namespace bitmap {
typedef std::function<void(int32_t x, int32_t y, int32_t w, int32_t h)> rect_func;
int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195);
int32_t measure_text(const font_t *font, const std::string_view &t, const uint8_t scale = 2, const uint8_t letter_spacing = 1);
int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195, bool fixed_width = false);
int32_t measure_text(const font_t *font, const std::string_view &t, const uint8_t scale = 2, const uint8_t letter_spacing = 1, bool fixed_width = false);
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale = 2, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195);
void text(const font_t *font, rect_func rectangle, const std::string_view &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale = 2, const uint8_t letter_spacing = 1);
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale = 2, int32_t rotation = 0, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195);
void text(const font_t *font, rect_func rectangle, const std::string_view &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale = 2, const uint8_t letter_spacing = 1, bool fixed_width = false, int32_t rotation = 0);
}

View File

@ -4,7 +4,7 @@
const bitmap::font_t font8 {
.height = 8,
.max_width = 6,
.max_width = 5,
.widths = {
3, 1, 3, 5, 4, 4, 4, 1, 3, 3, 3, 3, 2, 3, 2, 4,
4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 1, 2, 3, 3, 3, 4,
@ -17,123 +17,123 @@ const bitmap::font_t font8 {
5, 4, 4, 5, 4, 4, 4, 4, 3
},
.data = {
0x00,0x00,0x00,0x00,0x00,0x00, //
0x5f,0x00,0x00,0x00,0x00,0x00, // !
0x03,0x00,0x03,0x00,0x00,0x00, // "
0x28,0x7c,0x28,0x7c,0x28,0x00, // #
0x24,0x7a,0x2f,0x12,0x00,0x00, // $
0x66,0x10,0x08,0x66,0x00,0x00, // %
0x36,0x49,0x49,0x7c,0x00,0x00, // &
0x03,0x00,0x00,0x00,0x00,0x00, // '
0x1c,0x22,0x41,0x00,0x00,0x00, // (
0x41,0x22,0x1c,0x00,0x00,0x00, // )
0x54,0x38,0x54,0x00,0x00,0x00, // *
0x10,0x38,0x10,0x00,0x00,0x00, // +
0x80,0x60,0x00,0x00,0x00,0x00, // ,
0x10,0x10,0x10,0x00,0x00,0x00, // -
0x60,0x60,0x00,0x00,0x00,0x00, // .
0x60,0x18,0x06,0x01,0x00,0x00, // /
0x3e,0x41,0x41,0x3e,0x00,0x00, // 0
0x42,0x7f,0x40,0x00,0x00,0x00, // 1
0x62,0x51,0x49,0x46,0x00,0x00, // 2
0x21,0x49,0x4d,0x33,0x00,0x00, // 3
0x18,0x16,0x11,0x7f,0x00,0x00, // 4
0x4f,0x49,0x49,0x31,0x00,0x00, // 5
0x3c,0x4a,0x49,0x30,0x00,0x00, // 6
0x01,0x61,0x19,0x07,0x00,0x00, // 7
0x36,0x49,0x49,0x36,0x00,0x00, // 8
0x06,0x49,0x29,0x1e,0x00,0x00, // 9
0x33,0x00,0x00,0x00,0x00,0x00, // :
0x80,0x6c,0x00,0x00,0x00,0x00, // ;
0x10,0x28,0x44,0x00,0x00,0x00, // <
0x28,0x28,0x28,0x00,0x00,0x00, // =
0x44,0x28,0x10,0x00,0x00,0x00, // >
0x02,0x51,0x09,0x06,0x00,0x00, // ?
0x3e,0x49,0x55,0x5e,0x00,0x00, // @
0x7e,0x09,0x09,0x7e,0x00,0x00, // A
0x7f,0x49,0x49,0x36,0x00,0x00, // B
0x3e,0x41,0x41,0x22,0x00,0x00, // C
0x7f,0x41,0x41,0x3e,0x00,0x00, // D
0x7f,0x49,0x49,0x41,0x00,0x00, // E
0x7f,0x09,0x09,0x01,0x00,0x00, // F
0x3e,0x41,0x49,0x79,0x00,0x00, // G
0x7f,0x08,0x08,0x7f,0x00,0x00, // H
0x41,0x7f,0x41,0x00,0x00,0x00, // I
0x30,0x40,0x40,0x3f,0x00,0x00, // J
0x7f,0x08,0x14,0x63,0x00,0x00, // K
0x7f,0x40,0x40,0x40,0x00,0x00, // L
0x7f,0x02,0x04,0x02,0x7f,0x00, // M
0x7f,0x02,0x04,0x7f,0x00,0x00, // N
0x3e,0x41,0x41,0x3e,0x00,0x00, // O
0x7f,0x09,0x09,0x06,0x00,0x00, // P
0x3e,0x41,0x21,0x5e,0x00,0x00, // Q
0x7f,0x09,0x19,0x66,0x00,0x00, // R
0x46,0x49,0x49,0x31,0x00,0x00, // S
0x01,0x01,0x7f,0x01,0x01,0x00, // T
0x3f,0x40,0x40,0x3f,0x00,0x00, // U
0x7f,0x40,0x20,0x1f,0x00,0x00, // V
0x3f,0x40,0x20,0x40,0x3f,0x00, // W
0x77,0x08,0x08,0x77,0x00,0x00, // X
0x47,0x48,0x48,0x3f,0x00,0x00, // Y
0x71,0x49,0x45,0x43,0x00,0x00, // Z
0x7f,0x41,0x00,0x00,0x00,0x00, // [
0x01,0x06,0x18,0x60,0x00,0x00, // "\"
0x41,0x7f,0x00,0x00,0x00,0x00, // ]
0x04,0x02,0x04,0x00,0x00,0x00, // ^
0x40,0x40,0x40,0x00,0x00,0x00, // _
0x01,0x01,0x00,0x00,0x00,0x00, // `
0x20,0x54,0x54,0x78,0x00,0x00, // a
0x7f,0x44,0x44,0x38,0x00,0x00, // b
0x38,0x44,0x44,0x28,0x00,0x00, // c
0x38,0x44,0x44,0x7f,0x00,0x00, // d
0x38,0x54,0x54,0x58,0x00,0x00, // e
0x7e,0x09,0x09,0x02,0x00,0x00, // f
0x18,0xa4,0xa4,0x7c,0x00,0x00, // g
0x7f,0x04,0x04,0x78,0x00,0x00, // h
0x04,0x7d,0x40,0x00,0x00,0x00, // i
0x60,0x80,0x80,0x7d,0x00,0x00, // j
0x7f,0x10,0x28,0x44,0x00,0x00, // k
0x01,0x7f,0x40,0x00,0x00,0x00, // l
0x7c,0x04,0x78,0x04,0x78,0x00, // m
0x7c,0x04,0x04,0x78,0x00,0x00, // n
0x38,0x44,0x44,0x38,0x00,0x00, // o
0xfc,0x24,0x24,0x18,0x00,0x00, // p
0x18,0x24,0x24,0xfc,0x00,0x00, // q
0x7c,0x08,0x04,0x04,0x00,0x00, // r
0x48,0x54,0x54,0x24,0x00,0x00, // s
0x3e,0x44,0x44,0x20,0x00,0x00, // t
0x3c,0x40,0x40,0x7c,0x00,0x00, // u
0x7c,0x40,0x20,0x1c,0x00,0x00, // v
0x3c,0x40,0x20,0x40,0x3c,0x00, // w
0x6c,0x10,0x10,0x6c,0x00,0x00, // x
0x1c,0xa0,0xa0,0x7c,0x00,0x00, // y
0x64,0x54,0x4c,0x00,0x00,0x00, // z
0x08,0x3e,0x41,0x00,0x00,0x00, // {
0x7f,0x00,0x00,0x00,0x00,0x00, // |
0x41,0x3e,0x08,0x00,0x00,0x00, // }
0x08,0x04,0x08,0x04,0x00,0x00, // ~
0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, //
0x5f,0x00,0x00,0x00,0x00, // !
0x03,0x00,0x03,0x00,0x00, // "
0x28,0x7c,0x28,0x7c,0x28, // #
0x24,0x7a,0x2f,0x12,0x00, // $
0x66,0x10,0x08,0x66,0x00, // %
0x36,0x49,0x49,0x7c,0x00, // &
0x03,0x00,0x00,0x00,0x00, // '
0x1c,0x22,0x41,0x00,0x00, // (
0x41,0x22,0x1c,0x00,0x00, // )
0x54,0x38,0x54,0x00,0x00, // *
0x10,0x38,0x10,0x00,0x00, // +
0x80,0x60,0x00,0x00,0x00, // ,
0x10,0x10,0x10,0x00,0x00, // -
0x60,0x60,0x00,0x00,0x00, // .
0x60,0x18,0x06,0x01,0x00, // /
0x3e,0x41,0x41,0x3e,0x00, // 0
0x42,0x7f,0x40,0x00,0x00, // 1
0x62,0x51,0x49,0x46,0x00, // 2
0x21,0x49,0x4d,0x33,0x00, // 3
0x18,0x16,0x11,0x7f,0x00, // 4
0x4f,0x49,0x49,0x31,0x00, // 5
0x3c,0x4a,0x49,0x30,0x00, // 6
0x01,0x61,0x19,0x07,0x00, // 7
0x36,0x49,0x49,0x36,0x00, // 8
0x06,0x49,0x29,0x1e,0x00, // 9
0x33,0x00,0x00,0x00,0x00, // :
0x80,0x6c,0x00,0x00,0x00, // ;
0x10,0x28,0x44,0x00,0x00, // <
0x28,0x28,0x28,0x00,0x00, // =
0x44,0x28,0x10,0x00,0x00, // >
0x02,0x51,0x09,0x06,0x00, // ?
0x3e,0x49,0x55,0x5e,0x00, // @
0x7e,0x09,0x09,0x7e,0x00, // A
0x7f,0x49,0x49,0x36,0x00, // B
0x3e,0x41,0x41,0x22,0x00, // C
0x7f,0x41,0x41,0x3e,0x00, // D
0x7f,0x49,0x49,0x41,0x00, // E
0x7f,0x09,0x09,0x01,0x00, // F
0x3e,0x41,0x49,0x79,0x00, // G
0x7f,0x08,0x08,0x7f,0x00, // H
0x41,0x7f,0x41,0x00,0x00, // I
0x30,0x40,0x40,0x3f,0x00, // J
0x7f,0x08,0x14,0x63,0x00, // K
0x7f,0x40,0x40,0x40,0x00, // L
0x7f,0x02,0x04,0x02,0x7f, // M
0x7f,0x02,0x04,0x7f,0x00, // N
0x3e,0x41,0x41,0x3e,0x00, // O
0x7f,0x09,0x09,0x06,0x00, // P
0x3e,0x41,0x21,0x5e,0x00, // Q
0x7f,0x09,0x19,0x66,0x00, // R
0x46,0x49,0x49,0x31,0x00, // S
0x01,0x01,0x7f,0x01,0x01, // T
0x3f,0x40,0x40,0x3f,0x00, // U
0x7f,0x40,0x20,0x1f,0x00, // V
0x3f,0x40,0x20,0x40,0x3f, // W
0x77,0x08,0x08,0x77,0x00, // X
0x47,0x48,0x48,0x3f,0x00, // Y
0x71,0x49,0x45,0x43,0x00, // Z
0x7f,0x41,0x00,0x00,0x00, // [
0x01,0x06,0x18,0x60,0x00, // "\"
0x41,0x7f,0x00,0x00,0x00, // ]
0x04,0x02,0x04,0x00,0x00, // ^
0x40,0x40,0x40,0x00,0x00, // _
0x01,0x01,0x00,0x00,0x00, // `
0x20,0x54,0x54,0x78,0x00, // a
0x7f,0x44,0x44,0x38,0x00, // b
0x38,0x44,0x44,0x28,0x00, // c
0x38,0x44,0x44,0x7f,0x00, // d
0x38,0x54,0x54,0x58,0x00, // e
0x7e,0x09,0x09,0x02,0x00, // f
0x18,0xa4,0xa4,0x7c,0x00, // g
0x7f,0x04,0x04,0x78,0x00, // h
0x04,0x7d,0x40,0x00,0x00, // i
0x60,0x80,0x80,0x7d,0x00, // j
0x7f,0x10,0x28,0x44,0x00, // k
0x01,0x7f,0x40,0x00,0x00, // l
0x7c,0x04,0x78,0x04,0x78, // m
0x7c,0x04,0x04,0x78,0x00, // n
0x38,0x44,0x44,0x38,0x00, // o
0xfc,0x24,0x24,0x18,0x00, // p
0x18,0x24,0x24,0xfc,0x00, // q
0x7c,0x08,0x04,0x04,0x00, // r
0x48,0x54,0x54,0x24,0x00, // s
0x3e,0x44,0x44,0x20,0x00, // t
0x3c,0x40,0x40,0x7c,0x00, // u
0x7c,0x40,0x20,0x1c,0x00, // v
0x3c,0x40,0x20,0x40,0x3c, // w
0x6c,0x10,0x10,0x6c,0x00, // x
0x1c,0xa0,0xa0,0x7c,0x00, // y
0x64,0x54,0x4c,0x00,0x00, // z
0x08,0x3e,0x41,0x00,0x00, // {
0x7f,0x00,0x00,0x00,0x00, // |
0x41,0x3e,0x08,0x00,0x00, // }
0x08,0x04,0x08,0x04,0x00, // ~
0x00,0x00,0x00,0x00,0x00,
// Extra
0x7e,0x09,0x7f,0x49,0x49,0x00, // Æ
0x7e,0x24,0x24,0x18,0x00,0x00, // Þ
0x7e,0x09,0x49,0x36,0x00,0x00, // ß
0x20,0x54,0x78,0x54,0x58,0x00, // æ
0x7f,0x24,0x24,0x18,0x00,0x00, // þ
0x08,0x7e,0x49,0x41,0x00,0x00, // £
0x47,0x48,0x48,0x3f,0x00,0x00, // ¥
0x38,0x44,0x44,0x28,0x00,0x00, // ©
0x02,0x05,0x02,0x00,0x00,0x00, // °
0x7e,0x09,0x7f,0x49,0x49, // Æ
0x7e,0x24,0x24,0x18,0x00, // Þ
0x7e,0x09,0x49,0x36,0x00, // ß
0x20,0x54,0x78,0x54,0x58, // æ
0x7f,0x24,0x24,0x18,0x00, // þ
0x08,0x7e,0x49,0x41,0x00, // £
0x47,0x48,0x48,0x3f,0x00, // ¥
0x38,0x44,0x44,0x28,0x00, // ©
0x02,0x05,0x02,0x00,0x00, // °
// Accents + Offsets
// All chars are shifted 8px down into a 32 pixel canvas for combining with accents.
// Accent shift values (the first two numbers in each line below) move the accent down to meet them.
// These are the shift values for lower and UPPER case letters respectively.
6,4, 0x00,0x00,0x01,0x02,0x00,0x00, // Grave
6,4, 0x00,0x00,0x02,0x01,0x00,0x00, // Acute
6,4, 0x00,0x02,0x01,0x02,0x00,0x00, // Circumflex
6,4, 0x00,0x01,0x02,0x01,0x02,0x00, // Tilde
6,4, 0x00,0x01,0x00,0x01,0x00,0x00, // Diaresis
6,4, 0x00,0x02,0x05,0x02,0x00,0x00, // Ring Above
6,4, 0x00,0x80,0x40,0x00,0x00,0x00, // Stroke
9,9, 0x00,0x00,0xa0,0x40,0x00,0x00 // Cedilla
6,4, 0x00,0x00,0x01,0x02,0x00, // Grave
6,4, 0x00,0x00,0x02,0x01,0x00, // Acute
6,4, 0x00,0x02,0x01,0x02,0x00, // Circumflex
6,4, 0x00,0x01,0x02,0x01,0x02, // Tilde
6,4, 0x00,0x01,0x00,0x01,0x00, // Diaresis
6,4, 0x00,0x02,0x05,0x02,0x00, // Ring Above
6,4, 0x00,0x80,0x40,0x00,0x00, // Stroke
9,9, 0x00,0x00,0xa0,0x40,0x00 // Cedilla
}
};

View File

@ -1,3 +1,7 @@
if(NOT TARGET as7262)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/as7262/as7262.cmake)
endif()
set(LIB_NAME breakout_as7262)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET bh1745)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/bh1745/bh1745.cmake)
endif()
set(LIB_NAME breakout_bh1745)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET ltp305)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ltp305/ltp305.cmake)
endif()
set(LIB_NAME breakout_dotmatrix)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET ioexpander)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ioexpander/ioexpander.cmake)
endif()
set(LIB_NAME breakout_encoder)
add_library(${LIB_NAME} INTERFACE)

View File

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

View File

@ -0,0 +1,334 @@
# RGB Encoder Wheel Breakout (C++) <!-- omit in toc -->
This is the C++ library reference for the [Pimoroni RGB Encoder Wheel Breakout](https://shop.pimoroni.com/products/rgb-encoder-wheel-breakout).
## Table of Content <!-- omit in toc -->
- [Getting Started](#getting-started)
- [Reading the Buttons](#reading-the-buttons)
- [Reading the Encoder](#reading-the-encoder)
- [Count and Angle](#count-and-angle)
- [Count Delta](#count-delta)
- [Step and Turn](#step-and-turn)
- [Changing the Direction](#changing-the-direction)
- [Resetting to Zero](#resetting-to-zero)
- [LEDs](#leds)
- [Setting an LED](#setting-an-led)
- [RGB](#rgb)
- [HSV](#hsv)
- [Clear all LEDs](#clear-all-leds)
- [Showing](#showing)
- [GPIOs](#gpios)
- [Setup](#setup)
- [Mode](#mode)
- [As Input or ADC](#as-input-or-adc)
- [As Output](#as-output)
- [As PWM](#as-pwm)
- [Delayed Loading](#delayed-loading)
- [Limitations](#limitations)
- [Function Reference](#function-reference)
- [Constants Reference](#constants-reference)
- [Address Constants](#address-constants)
- [Value Constants](#value-constants)
- [Button Constants](#button-constants)
- [GPIO Constants](#gpio-constants)
- [Count Constants](#count-constants)
## Getting Started
To start coding for your Encoder Wheel breakout, you will first need to create an object for accessing the I2C bus that the breakout is connected to. The easiest way to do this is via the `PimoroniI2C` class, with one of the handy pin constants from `pimoroni`, like so:
```c++
#include "pimoroni_i2c.hpp"
using namespace pimoroni;
I2C i2c(BOARD::BREAKOUT_GARDEN);
```
This creates a `i2c` object that can be passed into the Encoder Wheel's class as part of its creation:
```c++
#include "breakout_encoder_wheel.hpp"
using namespace encoderwheel;
BreakoutEncoderWheel wheel(&i2c);
```
The above lines of code import the `BreakoutEncoderWheel` class and create an instance of it, called `wheel`. This will be used in the rest of the examples going forward.
## Reading the Buttons
EncoderWheel has five buttons, covering up, down, left, right, and centre. These can be read using the `.pressed(button)` function, which accepts a button number between `0` and `4`. For convenience, each button can be referred to using these constants:
* `UP` = `0`
* `DOWN` = `1`
* `LEFT` = `2`
* `RIGHT` = `3`
* `CENTRE` = `4`
For example, to read the centre button you would write:
```c++
bool centre_state = wheel.pressed(CENTRE);
```
You can also get the number of buttons using the `NUM_BUTTONS` constant.
## Reading the Encoder
Within the directional buttons of the Encoder Wheel breakout is a rotary encoder with 24 counts per revolution.
### Count and Angle
The current count can be read by calling `.count()`. It can also be read back as either the number of `.revolutions()` of the encoder, or the angle in `.degrees()` or `.radians()`.
Be aware that the count is stored as an integer, if it is continually increased or decreased it will eventually wrap at `+32767` and `-32768`. This will cause a jump in the returned by `.revolutions()`, `degrees()` and `.radians()`, that will need handling by your code.
### Count Delta
Often you are not interested in the exact count that the encoder is at, but rather if the count has changed since the last time you checked. This change can be read by calling `.delta()` at regular intervals. The returned value can then be used with a check in code, for the value being non-zero.
### Step and Turn
Sometimes it can be useful to know the encoder's position in the form of which step it is at and how many turns have occurred. The current step can be read by calling `.step()`, which returns a value from `0` to `23`, and the number of turns can be read by calling `.turn()`.
These functions differ from reading the `.count()` or `.revolutions()` by using separate counters, and so avoid the wrapping issue that these functions experience.
### Changing the Direction
The counting direction of an encoder can be changed by calling `.direction(REVERSED_DIR)` at any time in code. The `REVERSED_DIR` constant comes from `pimoroni_common.hpp`. There is also a `NORMAL_DIR` constant, though this is the default.
### Resetting to Zero
There are times where an encoder's count (and related values) need to be reset back to zero. This can be done by calling `.zero()`.
## LEDs
The Encoder Wheel breakout features 24 RGB LEDs arranged in a ring around the wheel. This is the same number as there are steps on the wheel, letting you use the LEDs to show the current step of the wheel.
### Setting an LED
You can set the colour of a LED on the ring in either the RGB colourspace, or HSV (Hue, Saturation, Value). HSV is useful for creating rainbow patterns.
#### RGB
Set the first LED - `0` - to Purple `255, 0, 255`:
```c++
wheel.set_rgb(0, 255, 0, 255);
```
#### HSV
Set the first LED - `0` - to Red `0.0`:
```c++
wheel.set_hsv(0, 0.0f, 1.0f, 1.0f);
```
### Clear all LEDs
To turn off all the LEDs, the function `.clear()` can be called. This simply goes through each LED and sets its RGB colour to black, making them emit no light.
This function is useful to have at the end of your code to turn the lights off, otherwise they will continue to show the last colours they were given.
### Showing
Changes to the LEDs do not get applied immediately, due to the amount of I2C communication involved. As such, to have the LEDs show what they have been set to after calling the `.set_rgb()`, `.set_hsv()`, and `.clear()` functions, a specific call to `.show()` needs to be made.
## GPIOs
There are three spare GPIO pins on the edge of Encoder Wheel. These can be used as digital outputs, pwm outputs, digital inputs, and analog inputs.
### Setup
To start using a GPIO pin, one of the handy constants from the `encoderwheel` namespace can be used to reference them (see [GPIO Constants](#gpio-constants)).
Then you need to import the constants for the pin mode to use. These are on the `IOExpander` class that Encoder Wheel is based on.
```c++
#import "breakout_ioexpander.hpp"
using namespace pimoroni;
// For input
IOExpander::PIN_IN; // or PIN_IN_PU of a pull-up is wanted
// For output
IOExpander::PIN_OUT;
// For PWM
IOExpander::PIN_PWM;
// For ADC
IOExpander::PIN_ADC;
```
### Mode
With the intended constants imported, the mode of a GPIO pin can be set by calling `.gpio_pin_mode(gpio, mode)`:
```c++
wheel.gpio_pin_mode(GP7, IOExpander::PIN_<IN or IN_PU or OUT or PWM or ADC>);
```
It is also possible to read the current mode of a GPIO pin by calling `.gpio_pin_mode(gpio)`:
```c++
mode = wheel.gpio_pin_mode(GP7);
```
### As Input or ADC
The current value of an GPIO pin in input or ADC mode can be read by calling `.gpio_pin_value(gpio)`:
```c++
value = wheel.gpio_pin_value(GP7);
```
If the mode is digital, the value will either be `0` or `1`.
If the mode is analog, the value will be a voltage from `0.0` to `3.3`.
### As Output
The current value of a GPIO pin in output mode can be set by calling `.gpio_pin_value(gpio, value)`:
```c++
wheel.gpio_pin_value(GP7, value);
```
The expected value is either `0` or `1`, or `True` or `False`.
### As PWM
The GPIO pins can also be set as PWM outputs. The `PIN_PWM` constant can be accessed from the `IOExpander` class, and passed into the `.gpio_pin_mode()` function.
The frequency of the PWM signal can then be configured by calling `.gpio_pwm_frequency()`, which accepts a frequency (in Hz). It returns the cycle period, which should be used to set duty cycles.
Finally, the duty cycle of the PWM signal can be set by calling `.gpio_pin_value()` and providing it with a value between `0` and the cycle period.
Below is an example of setting a gpio pin to output a 25KHz signal with a 50% duty cycle:
```c++
#include "pimoroni_i2c.hpp"
#include "breakout_encoder_wheel.hpp"
using namespace pimoroni;
using namespace encoderwheel;
// Initialise EncoderWheel
I2C i2c(BOARD::BREAKOUT_GARDEN);
BreakoutEncoderWheel wheel(&i2c);
// Setup the gpio pin as a PWM output
wheel.gpio_pin_mode(GP7, IOExpander::PIN_PWM);
// Set the gpio pin's frequency to 25KHz, and record the cycle period
uint16_t period = wheel.gpio_pwm_frequency(25000.0f);
// Output a 50% duty cycle square wave
wheel.gpio_pin_value(GP7, (int)(period * 0.5f));
```
#### Delayed Loading
By default, changes to a gpio pin's frequency or value are applied immediately. However, sometimes this may not be wanted, and instead you want all pins to receive updated parameters at the same time, regardless of how long the code ran that calculated the update.
For this purpose, `.gpio_pwm_frequency()` and `.gpio_pin_value()` include an optional parameter `load`, which by default is `true`. To avoid this "loading" set the parameter to `false`. Then either the last call can include a `true`, or a specific call to `.gpio_pwm_load()` can be made.
In addition, any function that performs a load, including the `.gpio_pwm_load()` function, can be made to wait until the new PWM value has been sent out of the pins. By default this is disabled, but can be enabled by including setting the `wait_for_load` parameter to `true` in the relevant function calls.
#### Limitations
All of Encoder Wheel's PWM outputs share the same timing parameters. This means that GP7, GP8, and GP9 share the same frequency. Keep this in mind if changing the frequency of one, as the others will not automatically know about the change, resulting in unexpected duty cycle outputs.
## Function Reference
Here is the complete list of functions available on the `BreakoutEncoderWheel` class:
```c++
BreakoutEncoderWheel(uint8_t ioe_address = DEFAULT_IOE_I2C_ADDRESS, uint8_t led_address = DEFAULT_LED_I2C_ADDRESS);
BreakoutEncoderWheel(I2C *i2c, uint8_t ioe_address = 0x13, uint8_t led_address = 0x77, uint interrupt = PIN_UNUSED, uint32_t timeout = 1, bool debug = false);
bool init(bool skip_chip_id_check = false);
void set_ioe_address(uint8_t address);
bool get_interrupt_flag();
void clear_interrupt_flag();
bool pressed(uint button);
int16_t count();
int16_t delta();
void zero();
int16_t step();
int16_t turn();
float revolutions();
float degrees();
float radians();
Direction direction();
void direction(Direction direction);
void set_rgb(int index, int r, int g, int b);
void set_hsv(int index, float h, float s = 1.0f, float v = 1.0f);
void clear();
void show();
uint8_t gpio_pin_mode(uint8_t gpio);
void gpio_pin_mode(uint8_t gpio, uint8_t mode);
int16_t gpio_pin_value(uint8_t gpio);
float gpio_pin_value_as_voltage(uint8_t gpio);
void gpio_pin_value(uint8_t gpio, uint16_t value, bool load = true, bool wait_for_load = false);
void gpio_pwm_load(bool wait_for_load = true);
uint16_t gpio_pwm_frequency(float frequency, bool load = true, bool wait_for_load = false);
```
## Constants Reference
Here is the complete list of public constants on the `BreakoutEncoderWheel` class:
### Address Constants
* `DEFAULT_IOE_I2C_ADDR` = `0x13`
* `DEFAULT_LED_I2C_ADDR` = `0x77`
* `ALTERNATE_LED_I2C_ADDR` = `0x74`
### Value Constants
* `DEFAULT_DIRECTION` = `NORMAL_DIR`
* `DEFAULT_TIMEOUT` = `1`
Here is the complete list of public constants in the `encoderwheel` namespace:
### Button Constants
* `UP` = `0`
* `DOWN` = `1`
* `LEFT` = `2`
* `RIGHT` = `3`
* `CENTRE` = `4`
### GPIO Constants
* `GP7` = `7`
* `GP8` = `8`
* `GP9` = `9`
* `GPIOS` = (`7`, `8`, `9`)
### Count Constants
* `NUM_LEDS` = `24`
* `NUM_BUTTONS` = `5`
* `NUM_GPIOS` = `5`

View File

@ -0,0 +1,19 @@
if(NOT TARGET ioexpander)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ioexpander/ioexpander.cmake)
endif()
if(NOT TARGET is31fl3731)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/is31fl3731/is31fl3731.cmake)
endif()
set(LIB_NAME breakout_encoder_wheel)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib ioexpander is31fl3731)

View File

@ -0,0 +1,260 @@
#include "breakout_encoder_wheel.hpp"
#include <algorithm>
#include <cmath>
namespace pimoroni {
namespace encoderwheel {
bool BreakoutEncoderWheel::init(bool skip_chip_id_check) {
bool success = false;
if(ioe.init(skip_chip_id_check, true) && led_ring.init()) {
ioe.setup_rotary_encoder(ENC_CHANNEL, ENC_TERM_A, ENC_TERM_B, 0, true); // count microsteps
ioe.set_mode(SW_UP, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_DOWN, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_LEFT, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_RIGHT, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_CENTRE, IOExpander::PIN_IN_PU);
ioe.set_pin_interrupt(SW_UP, true);
ioe.set_pin_interrupt(SW_DOWN, true);
ioe.set_pin_interrupt(SW_LEFT, true);
ioe.set_pin_interrupt(SW_RIGHT, true);
ioe.set_pin_interrupt(SW_CENTRE, true);
led_ring.enable({
0b00000000, 0b10111111,
0b00111110, 0b00111110,
0b00111111, 0b10111110,
0b00000111, 0b10000110,
0b00110000, 0b00110000,
0b00111111, 0b10111110,
0b00111111, 0b10111110,
0b01111111, 0b11111110,
0b01111111, 0b00000000
}, 0);
success = true;
}
return success;
}
i2c_inst_t* BreakoutEncoderWheel::get_i2c() const {
return ioe.get_i2c();
}
int BreakoutEncoderWheel::get_ioe_address() const {
return ioe.get_address();
}
int BreakoutEncoderWheel::get_led_address() const {
return led_ring.get_address();
}
int BreakoutEncoderWheel::get_sda() const {
return ioe.get_sda();
}
int BreakoutEncoderWheel::get_scl() const {
return ioe.get_scl();
}
int BreakoutEncoderWheel::get_int() const {
return ioe.get_int();
}
void BreakoutEncoderWheel::set_ioe_address(uint8_t address) {
ioe.set_address(address);
}
bool BreakoutEncoderWheel::get_interrupt_flag() {
return ioe.get_interrupt_flag();
}
void BreakoutEncoderWheel::clear_interrupt_flag() {
ioe.clear_interrupt_flag();
}
bool BreakoutEncoderWheel::pressed(uint button) {
switch(button) {
case 0:
return ioe.input(SW_UP) == 0;
case 1:
return ioe.input(SW_DOWN) == 0;
case 2:
return ioe.input(SW_LEFT) == 0;
case 3:
return ioe.input(SW_RIGHT) == 0;
case 4:
return ioe.input(SW_CENTRE) == 0;
default:
return false;
}
}
int16_t BreakoutEncoderWheel::count() {
take_encoder_reading();
return enc_count;
}
int16_t BreakoutEncoderWheel::delta() {
take_encoder_reading();
// Determine the change in counts since the last time this function was performed
int16_t change = enc_count - last_delta_count;
last_delta_count = enc_count;
return change;
}
void BreakoutEncoderWheel::zero() {
ioe.clear_rotary_encoder(ENC_CHANNEL);
enc_count = 0;
enc_step = 0;
enc_turn = 0;
last_raw_count = 0;
last_delta_count = 0;
}
int16_t BreakoutEncoderWheel::step() {
take_encoder_reading();
return enc_step;
}
int16_t BreakoutEncoderWheel::turn() {
take_encoder_reading();
return enc_turn;
}
float BreakoutEncoderWheel::revolutions() {
return (float)count() / (float)ENC_COUNTS_PER_REV;
}
float BreakoutEncoderWheel::degrees() {
return revolutions() * 360.0f;
}
float BreakoutEncoderWheel::radians() {
return revolutions() * M_PI * 2.0f;
}
Direction BreakoutEncoderWheel::direction() {
return enc_direction;
}
void BreakoutEncoderWheel::direction(Direction direction) {
enc_direction = direction;
}
void BreakoutEncoderWheel::set_rgb(int index, int r, int g, int b) {
RGBLookup rgb = lookup_table[index];
led_ring.set(rgb.r, r);
led_ring.set(rgb.g, g);
led_ring.set(rgb.b, b);
}
void BreakoutEncoderWheel::set_hsv(int index, float h, float s, float v) {
int r, g, b;
if(h < 0.0f) {
h = 1.0f + fmodf(h, 1.0f);
}
int i = int(h * 6);
float f = h * 6 - i;
v = v * 255.0f;
float sv = s * v;
float fsv = f * sv;
auto p = uint8_t(-sv + v);
auto q = uint8_t(-fsv + v);
auto t = uint8_t(fsv - sv + v);
uint8_t bv = uint8_t(v);
switch (i % 6) {
default:
case 0: r = bv; g = t; b = p; break;
case 1: r = q; g = bv; b = p; break;
case 2: r = p; g = bv; b = t; break;
case 3: r = p; g = q; b = bv; break;
case 4: r = t; g = p; b = bv; break;
case 5: r = bv; g = p; b = q; break;
}
set_rgb(index, r, g, b);
}
void BreakoutEncoderWheel::clear() {
led_ring.clear();
}
void BreakoutEncoderWheel::show() {
led_ring.update();
}
uint8_t BreakoutEncoderWheel::gpio_pin_mode(uint8_t gpio) {
assert(gpio < GP7 || gpio > GP9);
return ioe.get_mode(gpio);
}
void BreakoutEncoderWheel::gpio_pin_mode(uint8_t gpio, uint8_t mode) {
assert(gpio < GP7 || gpio > GP9);
ioe.set_mode(gpio, mode);
}
int16_t BreakoutEncoderWheel::gpio_pin_value(uint8_t gpio) {
assert(gpio < GP7 || gpio > GP9);
return ioe.input(gpio);
}
float BreakoutEncoderWheel::gpio_pin_value_as_voltage(uint8_t gpio) {
assert(gpio < GP7 || gpio > GP9);
return ioe.input_as_voltage(gpio);
}
void BreakoutEncoderWheel::gpio_pin_value(uint8_t gpio, uint16_t value, bool load, bool wait_for_load) {
assert(gpio < GP7 || gpio > GP9);
ioe.output(gpio, value, load, wait_for_load);
}
void BreakoutEncoderWheel::gpio_pwm_load(bool wait_for_load) {
ioe.pwm_load(wait_for_load);
}
uint16_t BreakoutEncoderWheel::gpio_pwm_frequency(float frequency, bool load, bool wait_for_load) {
return ioe.set_pwm_frequency(frequency, load, wait_for_load);
}
void BreakoutEncoderWheel::take_encoder_reading() {
// Read the current count
int16_t raw_count = ioe.read_rotary_encoder(ENC_CHANNEL) / ENC_COUNT_DIVIDER;
int16_t raw_change = raw_count - last_raw_count;
last_raw_count = raw_count;
// Invert the change
if(enc_direction == REVERSED_DIR) {
raw_change = 0 - raw_change;
}
enc_count += raw_change;
enc_step += raw_change;
if(raw_change > 0) {
while(enc_step >= ENC_COUNTS_PER_REV) {
enc_step -= ENC_COUNTS_PER_REV;
enc_turn += 1;
}
}
else if(raw_change < 0) {
while(enc_step < 0) {
enc_step += ENC_COUNTS_PER_REV;
enc_turn -= 1;
}
}
}
}
}

View File

@ -0,0 +1,161 @@
#pragma once
#include "drivers/ioexpander/ioexpander.hpp"
#include "drivers/is31fl3731/is31fl3731.hpp"
#include "common/pimoroni_common.hpp"
namespace pimoroni {
namespace encoderwheel {
static const uint8_t NUM_LEDS = 24;
static const uint8_t NUM_BUTTONS = 5;
static const uint8_t NUM_GPIOS = 3;
static const uint8_t UP = 0;
static const uint8_t DOWN = 1;
static const uint8_t LEFT = 2;
static const uint8_t RIGHT = 3;
static const uint8_t CENTRE = 4;
static const uint8_t GP7 = 7;
static const uint8_t GP8 = 8;
static const uint8_t GP9 = 9;
static const uint8_t GPIOS[] = {GP7, GP8, GP9};
class BreakoutEncoderWheel {
struct RGBLookup {
uint8_t r;
uint8_t g;
uint8_t b;
};
//--------------------------------------------------
// Constants
//--------------------------------------------------
public:
static const uint8_t DEFAULT_IOE_I2C_ADDRESS = 0x13;
static const uint8_t DEFAULT_LED_I2C_ADDRESS = 0x77;
static const uint8_t ALTERNATE_LED_I2C_ADDRESS = 0x74;
static const Direction DEFAULT_DIRECTION = NORMAL_DIR;
static const uint32_t DEFAULT_TIMEOUT = 1;
private:
static const uint8_t ENC_CHANNEL = 1;
static const uint8_t ENC_TERM_A = 3;
static const uint8_t ENC_TERM_B = 12;
static const uint8_t ENC_COUNTS_PER_REV = 24;
static const uint8_t ENC_COUNT_DIVIDER = 2;
static const uint8_t SW_UP = 13;
static const uint8_t SW_DOWN = 4;
static const uint8_t SW_LEFT = 11;
static const uint8_t SW_RIGHT = 2;
static const uint8_t SW_CENTRE = 1;
// This wonderful lookup table maps the LEDs on the encoder wheel
// from their 3x24 (remember, they're RGB) configuration to
// their specific location in the 144 pixel buffer.
static constexpr RGBLookup lookup_table[24] = {
{128, 32, 48},
{129, 33, 49},
{130, 17, 50},
{131, 18, 34},
{132, 19, 35},
{133, 20, 36},
{134, 21, 37},
{112, 80, 96},
{113, 81, 97},
{114, 82, 98},
{115, 83, 99},
{116, 84, 100},
{117, 68, 101},
{118, 69, 85},
{127, 47, 63},
{121, 41, 57},
{122, 25, 58},
{123, 26, 42},
{124, 27, 43},
{125, 28, 44},
{126, 29, 45},
{15, 95, 111},
{8, 89, 105},
{9, 90, 106},
};
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
IOExpander ioe;
IS31FL3731 led_ring;
Direction enc_direction = DEFAULT_DIRECTION;
int16_t enc_count = 0;
int16_t enc_step = 0;
int16_t enc_turn = 0;
int16_t last_raw_count = 0;
int16_t last_delta_count = 0;
//--------------------------------------------------
// Constructors/Destructor
//--------------------------------------------------
public:
BreakoutEncoderWheel(uint8_t ioe_address = DEFAULT_IOE_I2C_ADDRESS, uint8_t led_address = DEFAULT_LED_I2C_ADDRESS)
: BreakoutEncoderWheel(new I2C(), ioe_address, led_address) {}
BreakoutEncoderWheel(I2C *i2c, uint8_t ioe_address = DEFAULT_IOE_I2C_ADDRESS, uint8_t led_address = DEFAULT_LED_I2C_ADDRESS, uint interrupt = PIN_UNUSED, uint32_t timeout = DEFAULT_TIMEOUT, bool debug = false)
: ioe(i2c, ioe_address, interrupt, timeout, debug), led_ring(i2c, led_address) {}
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
bool init(bool skip_chip_id_check = false);
// For print access in micropython
i2c_inst_t* get_i2c() const;
int get_ioe_address() const;
int get_led_address() const;
int get_sda() const;
int get_scl() const;
int get_int() const;
// Calls through to IOExpander class
void set_ioe_address(uint8_t address);
bool get_interrupt_flag();
void clear_interrupt_flag();
// Encoder breakout specific
bool pressed(uint button);
int16_t count();
int16_t delta();
void zero();
int16_t step();
int16_t turn();
float revolutions();
float degrees();
float radians();
Direction direction();
void direction(Direction direction);
void set_rgb(int index, int r, int g, int b);
void set_hsv(int index, float h, float s = 1.0f, float v = 1.0f);
void clear();
void show();
uint8_t gpio_pin_mode(uint8_t gpio);
void gpio_pin_mode(uint8_t gpio, uint8_t mode);
int16_t gpio_pin_value(uint8_t gpio);
float gpio_pin_value_as_voltage(uint8_t gpio);
void gpio_pin_value(uint8_t gpio, uint16_t value, bool load = true, bool wait_for_load = false);
void gpio_pwm_load(bool wait_for_load = true);
uint16_t gpio_pwm_frequency(float frequency, bool load = true, bool wait_for_load = false);
private:
void take_encoder_reading();
};
}
}

View File

@ -1,3 +1,7 @@
if(NOT TARGET ioexpander)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ioexpander/ioexpander.cmake)
endif()
set(LIB_NAME breakout_ioexpander)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET ltr559)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ltr559/ltr559.cmake)
endif()
set(LIB_NAME breakout_ltr559)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET is31fl3731)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/is31fl3731/is31fl3731.cmake)
endif()
set(LIB_NAME breakout_matrix11x7)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET ioexpander)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ioexpander/ioexpander.cmake)
endif()
set(LIB_NAME breakout_mics6814)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET msa301)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/msa301/msa301.cmake)
endif()
set(LIB_NAME breakout_msa301)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET pmw3901)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/pmw3901/pmw3901.cmake)
endif()
set(LIB_NAME breakout_paa5100)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET pmw3901)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/pmw3901/pmw3901.cmake)
endif()
set(LIB_NAME breakout_pmw3901)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET ioexpander)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/ioexpander/ioexpander.cmake)
endif()
set(LIB_NAME breakout_potentiometer)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET is31fl3731)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/is31fl3731/is31fl3731.cmake)
endif()
set(LIB_NAME breakout_rgbmatrix5x5)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET rv3028)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/rv3028/rv3028.cmake)
endif()
set(LIB_NAME breakout_rtc)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET sgp30)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/sgp30/sgp30.cmake)
endif()
set(LIB_NAME breakout_sgp30)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET trackball)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/trackball/trackball.cmake)
endif()
set(LIB_NAME breakout_trackball)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,7 @@
if(NOT TARGET pico_graphics)
include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake)
endif()
add_library(cosmic_unicorn INTERFACE)
pico_generate_pio_header(cosmic_unicorn ${CMAKE_CURRENT_LIST_DIR}/cosmic_unicorn.pio)

View File

@ -6,8 +6,10 @@
#include "hardware/clocks.h"
#ifndef NO_QSTR
#include "cosmic_unicorn.pio.h"
#include "audio_i2s.pio.h"
#endif
#include "cosmic_unicorn.hpp"
@ -31,17 +33,13 @@
// for each row:
// for each bcd frame:
// 0: 00111111 // row pixel count (minus one)
// 1 - 64: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
// 65 - 67: xxxxxxxx, xxxxxxxx, xxxxxxxx // dummy bytes to dword align
// 68: xxxxrrrr // row select bits
// 69 - 71: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
// 1: xxxxrrrr // row select bits
// 2 - 65: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
// 66 - 67: xxxxxxxx, xxxxxxxx, // dummy bytes to dword align
// 68 - 71: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
//
// .. and back to the start
static uint16_t r_gamma_lut[256] = {0};
static uint16_t g_gamma_lut[256] = {0};
static uint16_t b_gamma_lut[256] = {0};
static uint32_t dma_channel;
static uint32_t dma_ctrl_channel;
static uint32_t audio_dma_channel;
@ -122,19 +120,6 @@ namespace pimoroni {
// Tear down the old GU instance's hardware resources
partial_teardown();
}
// create 14-bit gamma luts
for(uint16_t v = 0; v < 256; v++) {
// gamma correct the provided 0-255 brightness value onto a
// 0-65535 range for the pwm counter
float r_gamma = 1.8f;
r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
float g_gamma = 1.8f;
g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
float b_gamma = 1.8f;
b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
}
// for each row:
// for each bcd frame:
@ -154,18 +139,19 @@ namespace pimoroni {
uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)];
p[ 0] = 64 - 1; // row pixel count
p[68] = row; // row select
p[ 1] = row; // row select
// set the number of bcd ticks for this frame
uint32_t bcd_ticks = (1 << frame);
p[69] = (bcd_ticks & 0xff) >> 0;
p[70] = (bcd_ticks & 0xff00) >> 8;
p[71] = (bcd_ticks & 0xff0000) >> 16;
p[68] = (bcd_ticks & 0xff) >> 0;
p[69] = (bcd_ticks & 0xff00) >> 8;
p[70] = (bcd_ticks & 0xff0000) >> 16;
p[71] = (bcd_ticks & 0xff000000) >> 24;
}
}
// setup light sensor adc
adc_init();
if (!(adc_hw->cs & ADC_CS_EN_BITS)) adc_init();
adc_gpio_init(LIGHT_SENSOR);
gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false);
@ -475,9 +461,9 @@ namespace pimoroni {
g = (g * this->brightness) >> 8;
b = (b * this->brightness) >> 8;
uint16_t gamma_r = r_gamma_lut[r];
uint16_t gamma_g = g_gamma_lut[g];
uint16_t gamma_b = b_gamma_lut[b];
uint16_t gamma_r = GAMMA_14BIT[r];
uint16_t gamma_g = GAMMA_14BIT[g];
uint16_t gamma_b = GAMMA_14BIT[b];
// for each row:
// for each bcd frame:
@ -491,7 +477,7 @@ namespace pimoroni {
// set the appropriate bits in the separate bcd frames
for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) {
uint8_t *p = &bitstream[y * ROW_BYTES + (BCD_FRAME_BYTES * frame) + 1 + x];
uint8_t *p = &bitstream[y * ROW_BYTES + (BCD_FRAME_BYTES * frame) + 2 + x];
uint8_t red_bit = gamma_r & 0b1;
uint8_t green_bit = gamma_g & 0b1;
@ -508,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) {

View File

@ -2,6 +2,7 @@
#include "hardware/pio.h"
#include "pico_graphics.hpp"
#include "common/pimoroni_common.hpp"
#include "../pico_synth/pico_synth.hpp"
namespace pimoroni {

View File

@ -21,10 +21,10 @@
; for each row:
; for each bcd frame:
; 0: 00111111 // row pixel count (minus one)
; 1 - 64: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
; 65 - 67: xxxxxxxx, xxxxxxxx, xxxxxxxx // dummy bytes to dword align
; 68: xxxxrrrr // row select bits
; 69 - 71: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
; 1: xxxxrrrr // row select bits
; 2 - 65: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
; 66 - 67: xxxxxxxx, xxxxxxxx // dummy bytes to dword align
; 68 - 71: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
;
; .. and back to the start
@ -33,6 +33,7 @@
; loop over row pixels
out y, 8 ; get row pixel count (minus 1 because test is pre decrement)
out pins, 8 ; output row select
pixels:
; red bit
@ -63,15 +64,13 @@ pixels:
jmp y-- pixels
out null, 24 ; discard dummy bytes
out pins, 8 ; output row select
out null, 16 ; discard dummy bytes
set pins, 0b110 [5] ; latch high, blank high
set pins, 0b000 ; blank low (enable output)
; loop over bcd delay period
out y, 24 ; get bcd delay counter value
out y, 32 ; get bcd delay counter value
bcd_delay:
jmp y-- bcd_delay

View File

@ -1,3 +1,7 @@
if(NOT TARGET pico_graphics)
include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake)
endif()
add_library(galactic_unicorn INTERFACE)
pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio)

View File

@ -6,8 +6,10 @@
#include "hardware/clocks.h"
#ifndef NO_QSTR
#include "galactic_unicorn.pio.h"
#include "audio_i2s.pio.h"
#endif
#include "galactic_unicorn.hpp"
@ -38,10 +40,6 @@
//
// .. and back to the start
static uint16_t r_gamma_lut[256] = {0};
static uint16_t g_gamma_lut[256] = {0};
static uint16_t b_gamma_lut[256] = {0};
static uint32_t dma_channel;
static uint32_t dma_ctrl_channel;
static uint32_t audio_dma_channel;
@ -122,19 +120,6 @@ namespace pimoroni {
// Tear down the old GU instance's hardware resources
partial_teardown();
}
// create 14-bit gamma luts
for(uint16_t v = 0; v < 256; v++) {
// gamma correct the provided 0-255 brightness value onto a
// 0-65535 range for the pwm counter
float r_gamma = 1.8f;
r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
float g_gamma = 1.8f;
g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
float b_gamma = 1.8f;
b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
}
// for each row:
// for each bcd frame:
@ -166,7 +151,7 @@ namespace pimoroni {
}
// setup light sensor adc
adc_init();
if (!(adc_hw->cs & ADC_CS_EN_BITS)) adc_init();
adc_gpio_init(LIGHT_SENSOR);
gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false);
@ -470,9 +455,9 @@ namespace pimoroni {
g = (g * this->brightness) >> 8;
b = (b * this->brightness) >> 8;
uint16_t gamma_r = r_gamma_lut[r];
uint16_t gamma_g = g_gamma_lut[g];
uint16_t gamma_b = b_gamma_lut[b];
uint16_t gamma_r = GAMMA_14BIT[r];
uint16_t gamma_g = GAMMA_14BIT[g];
uint16_t gamma_b = GAMMA_14BIT[b];
// for each row:
// for each bcd frame:
@ -503,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) {

View File

@ -2,6 +2,7 @@
#include "hardware/pio.h"
#include "pico_graphics.hpp"
#include "common/pimoroni_common.hpp"
#include "../pico_synth/pico_synth.hpp"
namespace pimoroni {

View File

@ -1,3 +1,19 @@
if(NOT TARGET st7567)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/st7567/st7567.cmake)
endif()
if(NOT TARGET button)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/button/button.cmake)
endif()
if(NOT TARGET rgbled)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/rgbled/rgbled.cmake)
endif()
if(NOT TARGET pico_graphics)
include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake)
endif()
set(LIB_NAME gfx_pack)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,6 +1,7 @@
#include <map>
#include <string>
#include <functional>
#include <cstdint>
namespace hershey {
struct font_glyph_t {
@ -50,4 +51,4 @@ namespace hershey {
bool has_font(std::string_view font);
const font_t* font(std::string_view font);
}
}

View File

@ -1,11 +1,35 @@
set(LIB_NAME inky_frame)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE hardware_i2c pico_graphics hardware_spi hardware_pwm bitmap_fonts hershey_fonts pico_stdlib sdcard fatfs pcf85063a uc8159 jpegdec)
if(NOT TARGET sdcard)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/sdcard/sdcard.cmake)
endif()
if(NOT TARGET fatfs)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/fatfs/fatfs.cmake)
endif()
if(NOT TARGET pcf85063a)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/pcf85063a/pcf85063a.cmake)
endif()
if(NOT TARGET uc8159)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/uc8159/uc8159.cmake)
endif()
if(NOT TARGET jpegdec)
include(${CMAKE_CURRENT_LIST_DIR}/../jpegdec/jpegdec.cmake)
endif()
if(NOT TARGET pico_graphics)
include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake)
endif()
set(LIB_NAME inky_frame)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE hardware_i2c pico_graphics hardware_spi hardware_pwm bitmap_fonts hershey_fonts pico_stdlib sdcard fatfs pcf85063a uc8159 jpegdec)

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