Compare commits

...

277 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
342 changed files with 31359 additions and 8560 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}}-nano-specs
restore-keys: |
workspace-micropython-${{env.MICROPYTHON_VERSION}}-nano-specs
# Check out MicroPython
- name: Checkout MicroPython
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
repository: micropython/micropython
ref: ${{env.MICROPYTHON_VERSION}}
submodules: false # MicroPython submodules are hideously broken
path: micropython
# Check out MicroPython Libs
- name: Checkout MicroPython Libs
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
repository: micropython/micropython-lib
path: micropython-lib
- name: Fetch Pico submodules
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
working-directory: micropython/ports/rp2
run: |
git submodule update --init ../../lib/pico-sdk
git submodule update --init ../../lib/cyw43-driver
git submodule update --init ../../lib/lwip
git submodule update --init ../../lib/mbedtls
git submodule update --init ../../lib/micropython-lib
git submodule update --init ../../lib/tinyusb
- 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
@ -80,114 +31,111 @@ jobs:
board: PIMORONI_TUFTY2040
- name: enviro
board: PICO_W_ENVIRO
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
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
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: Install Arm GNU Toolchain (arm-none-eabi-gcc)
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '9-2020-q2'
- name: "HACK: Clean ports/rp2/modules and ports/rp2/CMakeLists.txt"
shell: bash
working-directory: micropython/ports/rp2
- name: Install CCache
run: |
rm -rf modules
git checkout modules
- name: "HACK: Revert Patches" # Avoid an already-patched MicroPython tree breaking our build
shell: bash
working-directory: micropython
source $BUILD_TOOLS
apt_install_build_deps
- name: Checkout MicroPython & Submodules
run: |
git checkout lib/pico-sdk
git checkout ports/rp2/CMakeLists.txt
source $BUILD_TOOLS
micropython_clone
- name: "Py_Decl: Checkout py_decl"
uses: actions/checkout@v4
with:
repository: gadgetoid/py_decl
ref: v0.0.1
path: py_decl
- name: Build MPY Cross
run: |
source $BUILD_TOOLS
micropython_build_mpy_cross
- name: "HACK: CMakeLists.txt Disable C++ Exceptions Patch"
shell: bash
working-directory: micropython
run: git apply $GITHUB_WORKSPACE/pimoroni-pico-${{ github.sha }}/micropython/micropython_nano_specs.patch
run: |
source $BUILD_TOOLS
hack_patch_micropython_disable_exceptions
- name: "HACK: Pico SDK Patch"
if: matrix.patch == true
shell: bash
working-directory: micropython
run: |
$GITHUB_WORKSPACE/pimoroni-pico-${{ github.sha }}/micropython/board/pico-sdk-patch.sh ${{matrix.board}}
source $BUILD_TOOLS
hack_patch_pico_sdk
- name: Configure MicroPython
shell: bash
working-directory: micropython/ports/rp2
run: |
cmake -S . -B build-${{matrix.name}} -DPICO_BUILD_DOCS=0 -DUSER_C_MODULES=${{env.USER_C_MODULES}} -DMICROPY_BOARD_DIR=${{env.MICROPY_BOARD_DIR}} -DMICROPY_BOARD=${{matrix.board}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
source $BUILD_TOOLS
micropython_version
cmake_configure
- name: Build MicroPython # Multiple simultaneous jobs trigger https://github.com/pimoroni/pimoroni-pico/issues/761
- name: Build MicroPython
shell: bash
working-directory: micropython/ports/rp2
run: |
ccache --zero-stats || true
cmake --build build-${{matrix.name}} -j 1
ccache --show-stats || true
source $BUILD_TOOLS
cmake_build
- name: Rename .uf2 for artifact
- name: "Py_Decl: Verify UF2"
shell: bash
working-directory: micropython/ports/rp2/build-${{matrix.name}}
run: |
cp firmware.uf2 $RELEASE_FILE.uf2
python3 py_decl/py_decl.py --to-json --verify build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: Store .uf2 as artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{env.RELEASE_FILE}}.uf2
path: micropython/ports/rp2/build-${{matrix.name}}/${{env.RELEASE_FILE}}.uf2
name: ${{ env.RELEASE_FILE }}.uf2
path: build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: Upload .uf2
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
asset_path: micropython/ports/rp2/build-${{matrix.name}}/firmware.uf2
upload_url: ${{github.event.release.upload_url}}
asset_name: ${{env.RELEASE_FILE}}.uf2
asset_path: build-${{ matrix.name }}/firmware.uf2
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ env.RELEASE_FILE }}.uf2
asset_content_type: application/octet-stream

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).
@ -140,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

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

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

@ -61,3 +61,4 @@ add_subdirectory(encoder)
add_subdirectory(galactic_unicorn)
add_subdirectory(gfx_pack)
add_subdirectory(cosmic_unicorn)
add_subdirectory(stellar_unicorn)

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

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

@ -1,3 +1,11 @@
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)

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"
@ -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);
@ -476,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:
@ -509,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

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

View File

@ -1,13 +1,41 @@
set(LIB_NAME inky_frame_7)
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 psram_display inky73 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 psram_display)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/psram_display/psram_display.cmake)
endif()
if(NOT TARGET inky73)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/inky73/inky73.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_7)
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 psram_display inky73 jpegdec)
target_compile_options(${LIB_NAME} INTERFACE -Wno-error=reorder)

View File

@ -1,3 +1,19 @@
if(NOT TARGET hub75)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/hub75/hub75.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 interstate75)
add_library(${LIB_NAME} INTERFACE)

View File

@ -1,3 +1,19 @@
if(NOT TARGET motor)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/motor/motor.cmake)
endif()
if(NOT TARGET servo)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/servo/servo.cmake)
endif()
if(NOT TARGET encoder)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/encoder/encoder.cmake)
endif()
if(NOT TARGET plasma)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/plasma/plasma.cmake)
endif()
add_library(inventor INTERFACE)
target_sources(inventor INTERFACE
@ -7,4 +23,4 @@ target_sources(inventor INTERFACE
target_include_directories(inventor INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(inventor INTERFACE pico_stdlib hardware_pwm hardware_pio hardware_i2c pimoroni_i2c motor servo encoder plasma pimoroni_i2c)
target_link_libraries(inventor INTERFACE pico_stdlib hardware_pwm hardware_pio hardware_i2c pimoroni_i2c motor servo encoder plasma)

View File

@ -68,6 +68,7 @@
enum {
RGB565_LITTLE_ENDIAN = 0,
RGB565_BIG_ENDIAN,
RGB888_LITTLE_ENDIAN,
EIGHT_BIT_GRAYSCALE,
FOUR_BIT_DITHERED,
TWO_BIT_DITHERED,

View File

@ -182,138 +182,82 @@ static const uint16_t usGrayTo565[] = {0x0000,0x0000,0x0000,0x0000,0x0020,0x0020
//
// Clip and convert red value into 5-bits for RGB565
//
static const uint16_t usRangeTableR[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 0
0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,
0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,
0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,
0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,
0x2800,0x2800,0x2800,0x2800,0x2800,0x2800,0x2800,0x2800,
0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,
0x3800,0x3800,0x3800,0x3800,0x3800,0x3800,0x3800,0x3800,
0x4000,0x4000,0x4000,0x4000,0x4000,0x4000,0x4000,0x4000,
0x4800,0x4800,0x4800,0x4800,0x4800,0x4800,0x4800,0x4800,
0x5000,0x5000,0x5000,0x5000,0x5000,0x5000,0x5000,0x5000,
0x5800,0x5800,0x5800,0x5800,0x5800,0x5800,0x5800,0x5800,
0x6000,0x6000,0x6000,0x6000,0x6000,0x6000,0x6000,0x6000,
0x6800,0x6800,0x6800,0x6800,0x6800,0x6800,0x6800,0x6800,
0x7000,0x7000,0x7000,0x7000,0x7000,0x7000,0x7000,0x7000,
0x7800,0x7800,0x7800,0x7800,0x7800,0x7800,0x7800,0x7800,
0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,
0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,
0x9000,0x9000,0x9000,0x9000,0x9000,0x9000,0x9000,0x9000,
0x9800,0x9800,0x9800,0x9800,0x9800,0x9800,0x9800,0x9800,
0xa000,0xa000,0xa000,0xa000,0xa000,0xa000,0xa000,0xa000,
0xa800,0xa800,0xa800,0xa800,0xa800,0xa800,0xa800,0xa800,
0xb000,0xb000,0xb000,0xb000,0xb000,0xb000,0xb000,0xb000,
0xb800,0xb800,0xb800,0xb800,0xb800,0xb800,0xb800,0xb800,
0xc000,0xc000,0xc000,0xc000,0xc000,0xc000,0xc000,0xc000,
0xc800,0xc800,0xc800,0xc800,0xc800,0xc800,0xc800,0xc800,
0xd000,0xd000,0xd000,0xd000,0xd000,0xd000,0xd000,0xd000,
0xd800,0xd800,0xd800,0xd800,0xd800,0xd800,0xd800,0xd800,
0xe000,0xe000,0xe000,0xe000,0xe000,0xe000,0xe000,0xe000,
0xe800,0xe800,0xe800,0xe800,0xe800,0xe800,0xe800,0xe800,
0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800, // 256
static const uint16_t usRangeTableR[] = {0x0000, // 0
0x0800,
0x1000,
0x1800,
0x2000,
0x2800,
0x3000,
0x3800,
0x4000,
0x4800,
0x5000,
0x5800,
0x6000,
0x6800,
0x7000,
0x7800,
0x8000,
0x8800,
0x9000,
0x9800,
0xa000,
0xa800,
0xb000,
0xb800,
0xc000,
0xc800,
0xd000,
0xd800,
0xe000,
0xe800,
0xf000,
0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800, // 32
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 64
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 96
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//
// Clip and convert green value into 5-bits for RGB565
// Clip and convert green value into 6-bits for RGB565
//
static const uint16_t usRangeTableG[] = {0x0000,0x0000,0x0000,0x0000,0x0020,0x0020,0x0020,0x0020, // 0
0x0040,0x0040,0x0040,0x0040,0x0060,0x0060,0x0060,0x0060,
0x0080,0x0080,0x0080,0x0080,0x00a0,0x00a0,0x00a0,0x00a0,
0x00c0,0x00c0,0x00c0,0x00c0,0x00e0,0x00e0,0x00e0,0x00e0,
0x0100,0x0100,0x0100,0x0100,0x0120,0x0120,0x0120,0x0120,
0x0140,0x0140,0x0140,0x0140,0x0160,0x0160,0x0160,0x0160,
0x0180,0x0180,0x0180,0x0180,0x01a0,0x01a0,0x01a0,0x01a0,
0x01c0,0x01c0,0x01c0,0x01c0,0x01e0,0x01e0,0x01e0,0x01e0,
0x0200,0x0200,0x0200,0x0200,0x0220,0x0220,0x0220,0x0220,
0x0240,0x0240,0x0240,0x0240,0x0260,0x0260,0x0260,0x0260,
0x0280,0x0280,0x0280,0x0280,0x02a0,0x02a0,0x02a0,0x02a0,
0x02c0,0x02c0,0x02c0,0x02c0,0x02e0,0x02e0,0x02e0,0x02e0,
0x0300,0x0300,0x0300,0x0300,0x0320,0x0320,0x0320,0x0320,
0x0340,0x0340,0x0340,0x0340,0x0360,0x0360,0x0360,0x0360,
0x0380,0x0380,0x0380,0x0380,0x03a0,0x03a0,0x03a0,0x03a0,
0x03c0,0x03c0,0x03c0,0x03c0,0x03e0,0x03e0,0x03e0,0x03e0,
0x0400,0x0400,0x0400,0x0400,0x0420,0x0420,0x0420,0x0420,
0x0440,0x0440,0x0440,0x0440,0x0460,0x0460,0x0460,0x0460,
0x0480,0x0480,0x0480,0x0480,0x04a0,0x04a0,0x04a0,0x04a0,
0x04c0,0x04c0,0x04c0,0x04c0,0x04e0,0x04e0,0x04e0,0x04e0,
0x0500,0x0500,0x0500,0x0500,0x0520,0x0520,0x0520,0x0520,
0x0540,0x0540,0x0540,0x0540,0x0560,0x0560,0x0560,0x0560,
0x0580,0x0580,0x0580,0x0580,0x05a0,0x05a0,0x05a0,0x05a0,
0x05c0,0x05c0,0x05c0,0x05c0,0x05e0,0x05e0,0x05e0,0x05e0,
0x0600,0x0600,0x0600,0x0600,0x0620,0x0620,0x0620,0x0620,
0x0640,0x0640,0x0640,0x0640,0x0660,0x0660,0x0660,0x0660,
0x0680,0x0680,0x0680,0x0680,0x06a0,0x06a0,0x06a0,0x06a0,
0x06c0,0x06c0,0x06c0,0x06c0,0x06e0,0x06e0,0x06e0,0x06e0,
0x0700,0x0700,0x0700,0x0700,0x0720,0x0720,0x0720,0x0720,
0x0740,0x0740,0x0740,0x0740,0x0760,0x0760,0x0760,0x0760,
0x0780,0x0780,0x0780,0x0780,0x07a0,0x07a0,0x07a0,0x07a0,
0x07c0,0x07c0,0x07c0,0x07c0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0, // 256
static const uint16_t usRangeTableG[] = {0x0000,0x0020, // 0
0x0040,0x0060,
0x0080,0x00a0,
0x00c0,0x00e0,
0x0100,0x0120,
0x0140,0x0160,
0x0180,0x01a0,
0x01c0,0x01e0,
0x0200,0x0220,
0x0240,0x0260,
0x0280,0x02a0,
0x02c0,0x02e0,
0x0300,0x0320,
0x0340,0x0360,
0x0380,0x03a0,
0x03c0,0x03e0,
0x0400,0x0420,
0x0440,0x0460,
0x0480,0x04a0,
0x04c0,0x04e0,
0x0500,0x0520,
0x0540,0x0560,
0x0580,0x05a0,
0x05c0,0x05e0,
0x0600,0x0620,
0x0640,0x0660,
0x0680,0x06a0,
0x06c0,0x06e0,
0x0700,0x0720,
0x0740,0x0760,
0x0780,0x07a0,
0x07c0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0, // 64
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
@ -321,160 +265,56 @@ static const uint16_t usRangeTableG[] = {0x0000,0x0000,0x0000,0x0000,0x0020,0x00
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 128
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 196
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//
// Clip and convert blue value into 5-bits for RGB565
//
static const uint16_t usRangeTableB[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 0
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,
0x0005,0x0005,0x0005,0x0005,0x0005,0x0005,0x0005,0x0005,
0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,
0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,
0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,
0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,
0x000c,0x000c,0x000c,0x000c,0x000c,0x000c,0x000c,0x000c,
0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
0x000e,0x000e,0x000e,0x000e,0x000e,0x000e,0x000e,0x000e,
0x000f,0x000f,0x000f,0x000f,0x000f,0x000f,0x000f,0x000f,
0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,
0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
0x0012,0x0012,0x0012,0x0012,0x0012,0x0012,0x0012,0x0012,
0x0013,0x0013,0x0013,0x0013,0x0013,0x0013,0x0013,0x0013,
0x0014,0x0014,0x0014,0x0014,0x0014,0x0014,0x0014,0x0014,
0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,
0x0016,0x0016,0x0016,0x0016,0x0016,0x0016,0x0016,0x0016,
0x0017,0x0017,0x0017,0x0017,0x0017,0x0017,0x0017,0x0017,
0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,
0x0019,0x0019,0x0019,0x0019,0x0019,0x0019,0x0019,0x0019,
0x001a,0x001a,0x001a,0x001a,0x001a,0x001a,0x001a,0x001a,
0x001b,0x001b,0x001b,0x001b,0x001b,0x001b,0x001b,0x001b,
0x001c,0x001c,0x001c,0x001c,0x001c,0x001c,0x001c,0x001c,
0x001d,0x001d,0x001d,0x001d,0x001d,0x001d,0x001d,0x001d,
0x001e,0x001e,0x001e,0x001e,0x001e,0x001e,0x001e,0x001e,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f, // 256
static const uint16_t usRangeTableB[] = {0x0000, // 0
0x0001,
0x0002,
0x0003,
0x0004,
0x0005,
0x0006,
0x0007,
0x0008,
0x0009,
0x000a,
0x000b,
0x000c,
0x000d,
0x000e,
0x000f,
0x0010,
0x0011,
0x0012,
0x0013,
0x0014,
0x0015,
0x0016,
0x0017,
0x0018,
0x0019,
0x001a,
0x001b,
0x001c,
0x001d,
0x001e,
0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f, // 32
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 64
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 96
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
//
@ -2288,9 +2128,9 @@ static void JPEGPixelLE(uint16_t *pDest, int iY, int iCb, int iCr)
iCBG = -1409 * (iCb-0x80);
iCRG = -2925 * (iCr-0x80);
iCRR = 5742 * (iCr-0x80);
usPixel = usRangeTableB[((iCBB + iY) >> 12) & 0x3ff]; // blue pixel
usPixel |= usRangeTableG[((iCBG + iCRG + iY) >> 12) & 0x3ff]; // green pixel
usPixel |= usRangeTableR[((iCRR + iY) >> 12) & 0x3ff]; // red pixel
usPixel = usRangeTableB[((iCBB + iY) >> 15) & 0x7f]; // blue pixel
usPixel |= usRangeTableG[((iCBG + iCRG + iY) >> 14) & 0xff]; // green pixel
usPixel |= usRangeTableR[((iCRR + iY) >> 15) & 0x7f]; // red pixel
pDest[0] = usPixel;
#endif
} /* JPEGPixelLE() */
@ -2304,9 +2144,9 @@ static void JPEGPixelBE(uint16_t *pDest, int iY, int iCb, int iCr)
iCBG = -1409 * (iCb-0x80);
iCRG = -2925 * (iCr-0x80);
iCRR = 5742 * (iCr-0x80);
usPixel = usRangeTableB[((iCBB + iY) >> 12) & 0x3ff]; // blue pixel
usPixel |= usRangeTableG[((iCBG + iCRG + iY) >> 12) & 0x3ff]; // green pixel
usPixel |= usRangeTableR[((iCRR + iY) >> 12) & 0x3ff]; // red pixel
usPixel = usRangeTableB[((iCBB + iY) >> 15) & 0x7f]; // blue pixel
usPixel |= usRangeTableG[((iCBG + iCRG + iY) >> 14) & 0xff]; // green pixel
usPixel |= usRangeTableR[((iCRR + iY) >> 15) & 0x7f]; // red pixel
pDest[0] = __builtin_bswap16(usPixel);
} /* JPEGPixelBE() */
@ -2340,13 +2180,13 @@ static void JPEGPixel2LE(uint16_t *pDest, int iY1, int iY2, int iCb, int iCr)
iCBG = -1409 * (iCb-0x80);
iCRG = -2925 * (iCr-0x80);
iCRR = 5742 * (iCr-0x80);
ulPixel1 = usRangeTableB[((iCBB + iY1) >> 12) & 0x3ff]; // blue pixel
ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 12) & 0x3ff]; // green pixel
ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 12) & 0x3ff]; // red pixel
ulPixel1 = usRangeTableB[((iCBB + iY1) >> 15) & 0x7f]; // blue pixel
ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 14) & 0xff]; // green pixel
ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 15) & 0x7f]; // red pixel
ulPixel2 = usRangeTableB[((iCBB + iY2) >> 12) & 0x3ff]; // blue pixel
ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 12) & 0x3ff]; // green pixel
ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 12) & 0x3ff]; // red pixel
ulPixel2 = usRangeTableB[((iCBB + iY2) >> 15) & 0x7f]; // blue pixel
ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 14) & 0xff]; // green pixel
ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 15) & 0x7f]; // red pixel
*(uint32_t *)&pDest[0] = (ulPixel1 | (ulPixel2<<16));
#endif
} /* JPEGPixel2LE() */
@ -2360,16 +2200,42 @@ static void JPEGPixel2BE(uint16_t *pDest, int32_t iY1, int32_t iY2, int32_t iCb,
iCBG = -1409L * (iCb-0x80);
iCRG = -2925L * (iCr-0x80);
iCRR = 5742L * (iCr-0x80);
ulPixel1 = usRangeTableB[((iCBB + iY1) >> 12) & 0x3ff]; // blue pixel
ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 12) & 0x3ff]; // green pixel
ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 12) & 0x3ff]; // red pixel
ulPixel1 = usRangeTableB[((iCBB + iY1) >> 15) & 0x7f]; // blue pixel
ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 14) & 0xff]; // green pixel
ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 15) & 0x7f]; // red pixel
ulPixel2 = usRangeTableB[((iCBB + iY2) >> 12) & 0x3ff]; // blue pixel
ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 12) & 0x3ff]; // green pixel
ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 12) & 0x3ff]; // red pixel
ulPixel2 = usRangeTableB[((iCBB + iY2) >> 15) & 0x7f]; // blue pixel
ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 14) & 0xff]; // green pixel
ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 15) & 0x7f]; // red pixel
*(uint32_t *)&pDest[0] = __builtin_bswap16(ulPixel1) | ((uint32_t)__builtin_bswap16(ulPixel2)<<16);
} /* JPEGPixel2BE() */
static void JPEGPixelLE888(uint8_t *pDest, int iY, int iCb, int iCr)
{
int32_t iCBB, iCBG, iCRG, iCRR;
uint32_t uVal;
iCBB = 7258 * (iCb-0x80);
iCBG = -1409 * (iCb-0x80);
iCRG = -2925 * (iCr-0x80);
iCRR = 5742 * (iCr-0x80);
// Red
uVal = ((iCRR + iY) >> 13) & 0x1FF;
if (uVal & 0x100) uVal = 0;
*pDest++ = uVal;
// Green
uVal = ((iCBG + iCRG + iY) >> 13) & 0x1FF;
if (uVal & 0x100) uVal = 0;
*pDest++ = uVal;
// Blue
uVal = ((iCBB + iY) >> 13) & 0x1FF;
if (uVal & 0x100) uVal = 0;
*pDest++ = uVal;
}
static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch)
{
int iCr, iCb;
@ -2378,6 +2244,7 @@ static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch)
int iRow;
uint8_t *pY, *pCr, *pCb;
uint16_t *pOutput = &pJPEG->usPixels[x];
uint8_t *pOutput8 = ((uint8_t*)pJPEG->usPixels) + x * 3;
pY = (unsigned char *)&pJPEG->sMCUs[0*DCTSIZE];
pCb = (unsigned char *)&pJPEG->sMCUs[1*DCTSIZE];
@ -2474,6 +2341,17 @@ static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch)
JPEGPixelLE(pOutput+iCol, Y, iCb, iCr);
} // for col
}
else if (pJPEG->ucPixelType == RGB888_LITTLE_ENDIAN)
{
for (iCol=0; iCol<8; iCol++) // up to 4x2 cols to do
{
iCr = *pCr++;
iCb = *pCb++;
Y = (int)(*pY++) << 12;
JPEGPixelLE888(pOutput8+iCol*3, Y, iCb, iCr);
} // for col
pOutput8 += iPitch * 3;
}
else
{
for (iCol=0; iCol<8; iCol++) // up to 4x2 cols to do
@ -2829,6 +2707,7 @@ static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch)
int iRow, iCol, iXCount, iYCount;
uint8_t *pY, *pCr, *pCb;
uint16_t *pOutput = &pJPEG->usPixels[x];
uint8_t *pOutput8 = ((uint8_t*)pJPEG->usPixels) + x * 3;
pY = (uint8_t *)&pJPEG->sMCUs[0*DCTSIZE];
pCb = (uint8_t *)&pJPEG->sMCUs[2*DCTSIZE];
@ -2960,6 +2839,11 @@ static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch)
JPEGPixelLE(pOutput + iCol, Y1, Cb, Cr);
JPEGPixelLE(pOutput + iPitch + iCol, Y2, Cb, Cr);
}
else if (pJPEG->ucPixelType == RGB888_LITTLE_ENDIAN)
{
JPEGPixelLE888(pOutput8 + iCol*3, Y1, Cb, Cr);
JPEGPixelLE888(pOutput8 + (iPitch + iCol)*3, Y2, Cb, Cr);
}
else
{
JPEGPixelBE(pOutput + iCol, Y1, Cb, Cr);
@ -2972,6 +2856,7 @@ static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch)
pCb += 8;
pCr += 8;
pOutput += iPitch*2; // next 2 lines of dest pixels
pOutput8 += iPitch*6;
}
} /* JPEGPutMCU12() */
static void JPEGPutMCU21(JPEGIMAGE *pJPEG, int x, int iPitch)
@ -3229,6 +3114,8 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG)
cDCTable2 = pJPEG->JPCI[2].dc_tbl_no;
cACTable2 = pJPEG->JPCI[2].ac_tbl_no;
iDCPred0 = iDCPred1 = iDCPred2 = mcuCX = mcuCY = 0;
printf("SubSample mode: 0x%x\n", pJPEG->ucSubSample);
switch (pJPEG->ucSubSample) // set up the parameters for the different subsampling options
{
@ -3287,6 +3174,8 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG)
iMCUCount = MAX_BUFFERED_PIXELS / (mcuCX * mcuCY);
if (pJPEG->ucPixelType == EIGHT_BIT_GRAYSCALE)
iMCUCount *= 2; // each pixel is only 1 byte
else if (pJPEG->ucPixelType == RGB888_LITTLE_ENDIAN)
iMCUCount = (iMCUCount >> 1) + (iMCUCount >> 3); // each picel is 3 bytes
if (iMCUCount > cx)
iMCUCount = cx; // don't go wider than the image
if (iMCUCount > pJPEG->iMaxMCUs) // did the user set an upper bound on how many pixels per JPEGDraw callback?
@ -3296,6 +3185,9 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG)
jd.iBpp = 16;
switch (pJPEG->ucPixelType)
{
case RGB888_LITTLE_ENDIAN:
jd.iBpp = 24;
break;
case EIGHT_BIT_GRAYSCALE:
jd.iBpp = 8;
break;

View File

@ -1,3 +1,19 @@
if(NOT TARGET plasma)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/plasma/plasma.cmake)
endif()
if(NOT TARGET motor)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/motor/motor.cmake)
endif()
if(NOT TARGET motor_cluster)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/motor/motor_cluster.cmake)
endif()
if(NOT TARGET encoder)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/encoder/encoder.cmake)
endif()
add_library(motor2040 INTERFACE)
target_include_directories(motor2040 INTERFACE ${CMAKE_CURRENT_LIST_DIR})

View File

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

View File

@ -1,6 +1,6 @@
# Pico Display 2.0" Pack <!-- omit in toc -->
Our Pico Display Pack offers a vibrant 1.14" (240x135) IPS LCD screen for your Raspberry Pi Pico it also includes four switches and and an RGB LED!
Our Pico Display Pack offers a vibrant 2.0" (320x240) IPS LCD screen for your Raspberry Pi Pico it also includes four switches and and an RGB LED!
- [Example Program](#example-program)
- [Function Reference](#function-reference)
@ -81,4 +81,4 @@ Pico Display uses our Pico Graphics library to draw graphics and text. For more
### ST7789
Pico Display uses the ST7789 display driver to handle the LCD. For more information [read the ST7789 README.](../../drivers/st7789/README.md).
Pico Display uses the ST7789 display driver to handle the LCD. For more information [read the ST7789 README.](../../drivers/st7789/README.md).

View File

@ -1,5 +1,10 @@
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/st7789/st7789.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake)
if(NOT TARGET st7789)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/st7789/st7789.cmake)
endif()
if(NOT TARGET pico_graphics)
include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake)
endif()
add_library(pico_explorer INTERFACE)

View File

@ -8,6 +8,7 @@ namespace pimoroni {
int PicoGraphics::reset_pen(uint8_t i) {return -1;};
int PicoGraphics::create_pen(uint8_t r, uint8_t g, uint8_t b) {return -1;};
int PicoGraphics::create_pen_hsv(float h, float s, float v){return -1;};
void PicoGraphics::set_pixel_alpha(const Point &p, const uint8_t a) {};
void PicoGraphics::set_pixel_dither(const Point &p, const RGB &c) {};
void PicoGraphics::set_pixel_dither(const Point &p, const RGB565 &c) {};
void PicoGraphics::set_pixel_dither(const Point &p, const uint8_t &c) {};
@ -16,6 +17,7 @@ namespace pimoroni {
int PicoGraphics::get_palette_size() {return 0;}
RGB* PicoGraphics::get_palette() {return nullptr;}
bool PicoGraphics::supports_alpha_blend() {return false;}
void PicoGraphics::set_dimensions(int width, int height) {
bounds = clip = {0, 0, width, height};
@ -132,7 +134,7 @@ namespace pimoroni {
if (bitmap_font) {
bitmap::character(bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
rectangle(Rect(x, y, w, h));
}, c, p.x, p.y, std::max(1.0f, s));
}, c, p.x, p.y, std::max(1.0f, s), int32_t(a) % 360);
return;
}
@ -144,11 +146,11 @@ namespace pimoroni {
}
}
void PicoGraphics::text(const std::string_view &t, const Point &p, int32_t wrap, float s, float a, uint8_t letter_spacing) {
void PicoGraphics::text(const std::string_view &t, const Point &p, int32_t wrap, float s, float a, uint8_t letter_spacing, bool fixed_width) {
if (bitmap_font) {
bitmap::text(bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
rectangle(Rect(x, y, w, h));
}, t, p.x, p.y, wrap, std::max(1.0f, s), letter_spacing);
}, t, p.x, p.y, wrap, std::max(1.0f, s), letter_spacing, fixed_width, int32_t(a) % 360);
return;
}
@ -166,8 +168,8 @@ namespace pimoroni {
}
}
int32_t PicoGraphics::measure_text(const std::string_view &t, float s, uint8_t letter_spacing) {
if (bitmap_font) return bitmap::measure_text(bitmap_font, t, std::max(1.0f, s), letter_spacing);
int32_t PicoGraphics::measure_text(const std::string_view &t, float s, uint8_t letter_spacing, bool fixed_width) {
if (bitmap_font) return bitmap::measure_text(bitmap_font, t, std::max(1.0f, s), letter_spacing, fixed_width);
if (hershey_font) return hershey::measure_text(hershey_font, t, s);
return 0;
}
@ -266,7 +268,7 @@ namespace pimoroni {
int32_t ex = points[j].x;
int32_t px = int32_t(sx + float(fy - sy) / float(ey - sy) * float(ex - sx));
nodes[n++] = px < clip.x ? clip.x : (px >= clip.x + clip.w ? clip.x + clip.w - 1 : px);// clamp(int32_t(sx + float(fy - sy) / float(ey - sy) * float(ex - sx)), clip.x, clip.x + clip.w);
nodes[n++] = px;
}
}

View File

@ -26,6 +26,7 @@
namespace pimoroni {
typedef uint8_t RGB332;
typedef uint16_t RGB565;
typedef uint16_t RGB555;
typedef uint32_t RGB888;
@ -46,7 +47,19 @@ namespace pimoroni {
g((c >> 8) & 0xff),
b(c & 0xff) {}
constexpr RGB(int16_t r, int16_t g, int16_t b) : r(r), g(g), b(b) {}
constexpr uint8_t blend(uint8_t s, uint8_t d, uint8_t a) {
return d + ((a * (s - d) + 127) >> 8);
}
constexpr RGB blend(RGB with, const uint8_t alpha) {
return RGB(
blend(with.r, r, alpha),
blend(with.g, g, alpha),
blend(with.b, b, alpha)
);
}
static RGB from_hsv(float h, float s, float v) {
float i = floor(h * 6.0f);
float f = h * 6.0f - i;
@ -108,6 +121,14 @@ namespace pimoroni {
return __builtin_bswap16(p);
}
constexpr RGB555 to_rgb555() {
uint16_t p = ((r & 0b11111000) << 7) |
((g & 0b11111000) << 2) |
((b & 0b11111000) >> 3);
return p;
}
constexpr RGB565 to_rgb332() {
return (r & 0b11100000) | ((g & 0b11100000) >> 3) | ((b & 0b11000000) >> 6);
}
@ -192,7 +213,10 @@ namespace pimoroni {
PEN_RGB332,
PEN_RGB565,
PEN_RGB888,
PEN_INKY7
PEN_INKY7,
PEN_DV_RGB555,
PEN_DV_P5,
PEN_DV_RGB888,
};
void *frame_buffer;
@ -256,6 +280,7 @@ namespace pimoroni {
virtual int get_palette_size();
virtual RGB* get_palette();
virtual bool supports_alpha_blend();
virtual int create_pen(uint8_t r, uint8_t g, uint8_t b);
virtual int create_pen_hsv(float h, float s, float v);
@ -264,9 +289,12 @@ namespace pimoroni {
virtual void set_pixel_dither(const Point &p, const RGB &c);
virtual void set_pixel_dither(const Point &p, const RGB565 &c);
virtual void set_pixel_dither(const Point &p, const uint8_t &c);
virtual void set_pixel_alpha(const Point &p, const uint8_t a);
virtual void frame_convert(PenType type, conversion_callback_func callback);
virtual void sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent);
virtual bool render_pico_vector_tile(const Rect &bounds, uint8_t* alpha_data, uint32_t stride, uint8_t alpha_type) { return false; }
void set_font(const bitmap::font_t *font);
void set_font(const hershey::font_t *font);
void set_font(std::string_view name);
@ -286,8 +314,8 @@ namespace pimoroni {
void rectangle(const Rect &r);
void circle(const Point &p, int32_t r);
void character(const char c, const Point &p, float s = 2.0f, float a = 0.0f);
void text(const std::string_view &t, const Point &p, int32_t wrap, float s = 2.0f, float a = 0.0f, uint8_t letter_spacing = 1);
int32_t measure_text(const std::string_view &t, float s = 2.0f, uint8_t letter_spacing = 1);
void text(const std::string_view &t, const Point &p, int32_t wrap, float s = 2.0f, float a = 0.0f, uint8_t letter_spacing = 1, bool fixed_width = false);
int32_t measure_text(const std::string_view &t, float s = 2.0f, uint8_t letter_spacing = 1, bool fixed_width = false);
void polygon(const std::vector<Point> &points);
void triangle(Point p1, Point p2, Point p3);
void line(Point p1, Point p2);
@ -459,6 +487,9 @@ namespace pimoroni {
void set_pixel_span(const Point &p, uint l) override;
void set_pixel_dither(const Point &p, const RGB &c) override;
void set_pixel_dither(const Point &p, const RGB565 &c) override;
void set_pixel_alpha(const Point &p, const uint8_t a) override;
bool supports_alpha_blend() override {return true;}
void sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) override;
@ -528,6 +559,12 @@ namespace pimoroni {
virtual void read_pixel_span(const Point &p, uint l, T *data) {};
};
class IPaletteDisplayDriver {
public:
virtual void write_palette_pixel(const Point &p, uint8_t colour) = 0;
virtual void write_palette_pixel_span(const Point &p, uint l, uint8_t colour) = 0;
virtual void set_palette_colour(uint8_t entry, RGB888 colour) = 0;
};
class PicoGraphics_PenInky7 : public PicoGraphics {
public:

View File

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

View File

@ -34,6 +34,15 @@ namespace pimoroni {
*buf++ = color;
}
}
void PicoGraphics_PenRGB332::set_pixel_alpha(const Point &p, const uint8_t a) {
if(!bounds.contains(p)) return;
uint8_t *buf = (uint8_t *)frame_buffer;
RGB332 blended = RGB(buf[p.y * bounds.w + p.x]).blend(RGB(color), a).to_rgb332();
buf[p.y * bounds.w + p.x] = blended;
};
void PicoGraphics_PenRGB332::set_pixel_dither(const Point &p, const RGB &c) {
if(!bounds.contains(p)) return;
uint8_t _dmv = dither16_pattern[(p.x & 0b11) | ((p.y & 0b11) << 2)];

View File

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

View File

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

View File

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

View File

@ -2,7 +2,9 @@
#include "hardware/irq.h"
#include "common/pimoroni_common.hpp"
#ifndef NO_QSTR
#include "pico_unicorn.pio.h"
#endif
#include "pico_unicorn.hpp"
// pixel data is stored as a stream of bits delivered in the

View File

@ -0,0 +1,181 @@
#include <cstdint>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <optional>
#include <map>
#include "alright_fonts.hpp"
using namespace pretty_poly;
namespace alright_fonts {
/*
utility functions
*/
pretty_poly::rect_t measure_character(text_metrics_t &tm, uint16_t codepoint) {
if(tm.face.glyphs.count(codepoint) == 1) {
glyph_t glyph = tm.face.glyphs[codepoint];
return {0, 0, ((glyph.advance * tm.size) / 128), tm.size};
}
return {0, 0, 0, 0};
}
/*
render functions
*/
void render_character(text_metrics_t &tm, uint16_t codepoint, pretty_poly::point_t<int> origin) {
if(tm.face.glyphs.count(codepoint) == 1) {
glyph_t glyph = tm.face.glyphs[codepoint];
// scale is a fixed point 16:16 value, our font data is already scaled to
// -128..127 so to get the pixel size we want we can just shift the
// users requested size up one bit
unsigned scale = tm.size << 9;
pretty_poly::draw_polygon<int8_t>(glyph.contours, origin, scale);
}
}
template<typename mat_t>
void render_character(text_metrics_t &tm, uint16_t codepoint, pretty_poly::point_t<int> origin, mat_t transform) {
if(tm.face.glyphs.count(codepoint) == 1) {
glyph_t glyph = tm.face.glyphs[codepoint];
// scale is a fixed point 16:16 value, our font data is already scaled to
// -128..127 so to get the pixel size we want we can just shift the
// users requested size up one bit
unsigned scale = tm.size << 9;
std::vector<pretty_poly::contour_t<int8_t>> contours;
contours.reserve(glyph.contours.size());
unsigned int total_points = 0;
for(auto i = 0u; i < glyph.contours.size(); i++) {
total_points += glyph.contours[i].count;;
}
point_t<int8_t> *points = (point_t<int8_t> *)malloc(sizeof(point_t<int8_t>) * total_points);
for(auto i = 0u; i < glyph.contours.size(); i++) {
const unsigned int count = glyph.contours[i].count;
for(auto j = 0u; j < count; j++) {
point_t<float> point(glyph.contours[i].points[j].x, glyph.contours[i].points[j].y);
point *= transform;
points[j] = point_t<int8_t>(point.x, point.y);
}
contours.emplace_back(points, count);
points += count;
}
pretty_poly::draw_polygon<int8_t>(contours, origin, scale);
free(contours[0].points);
}
}
template void render_character<pretty_poly::mat3_t>(text_metrics_t &tm, uint16_t codepoint, pretty_poly::point_t<int> origin, pretty_poly::mat3_t transform);
template void render_character<pretty_poly::mat2_t>(text_metrics_t &tm, uint16_t codepoint, pretty_poly::point_t<int> origin, pretty_poly::mat2_t transform);
/*
load functions
*/
// big endian stream value helpers
uint16_t ru16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
int16_t rs16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
uint32_t ru32(file_io &ifs) {uint8_t dw[4]; ifs.read((char *)dw, 4); return dw[0] << 24 | dw[1] << 16 | dw[2] << 8 | dw[3];}
uint8_t ru8(file_io &ifs) {uint8_t w; ifs.read(&w, 1); return w;}
int8_t rs8(file_io &ifs) {int8_t w; ifs.read(&w, 1); return w;}
bool face_t::load(file_io &ifs) {
char marker[4];
ifs.read(marker, sizeof(marker));
// check header magic bytes are present
if(memcmp(marker, "af!?", 4) != 0) {
// doesn't start with magic marker
return false;
}
// number of glyphs embedded in font file
this->glyph_count = ru16(ifs);
// extract flags and ensure none set
this->flags = ru16(ifs);
if(this->flags != 0) {
// unknown flags set
return false;
}
// extract glyph dictionary
uint16_t glyph_entry_size = 9;
uint32_t contour_data_offset = 8 + this->glyph_count * glyph_entry_size;
for(auto i = 0; i < this->glyph_count; i++) {
glyph_t g;
g.codepoint = ru16(ifs);
g.bounds.x = rs8(ifs);
g.bounds.y = rs8(ifs);
g.bounds.w = ru8(ifs);
g.bounds.h = ru8(ifs);
g.advance = ru8(ifs);
if(ifs.fail()) {
// could not read glyph dictionary entry
return false;
}
// allocate space for the contour data and read it from the font file
uint16_t contour_data_length = ru16(ifs);
// remember where we are in the dictionary
int pos = ifs.tell();
// read contour data
ifs.seek(contour_data_offset);
while(true) {
// get number of points in contour
uint16_t count = ru16(ifs);
// if count is zero then this is the end of contour marker
if(count == 0) {
break;
}
// allocate space to store point data for contour and read
// from file
pretty_poly::point_t<int8_t> *points = new pretty_poly::point_t<int8_t>[count];
ifs.read((char *)points, count * 2);
g.contours.push_back({points, count});
}
// return back to position in dictionary
ifs.seek(pos);
contour_data_offset += contour_data_length;
if(ifs.fail()) {
// could not read glyph contour data
return false;
}
this->glyphs[g.codepoint] = g;
}
return true;
}
bool face_t::load(std::string_view path) {
file_io ifs(path);
if(ifs.fail()) {
// could not open file
return false;
}
return load(ifs);
}
}

View File

@ -0,0 +1,75 @@
#include <cstdint>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <optional>
#include <map>
#include "pretty_poly.hpp"
namespace alright_fonts {
struct glyph_t {
uint16_t codepoint;
pretty_poly::rect_t bounds;
uint8_t advance;
std::vector<pretty_poly::contour_t<int8_t>> contours;
};
struct face_t {
uint16_t glyph_count;
uint16_t flags;
std::map<uint16_t, glyph_t> glyphs;
face_t() {};
face_t(pretty_poly::file_io &ifs) {load(ifs);}
face_t(std::string_view path) {load(path);}
bool load(pretty_poly::file_io &ifs);
bool load(std::string_view path);
};
enum alignment_t {
left = 0,
center = 1,
right = 2,
justify = 4,
top = 8,
bottom = 16
};
struct text_metrics_t {
face_t face; // font to write in
int size; // text size in pixels
uint scroll; // vertical scroll offset
int line_height; // spacing between lines (%)
int letter_spacing; // spacing between characters
int word_spacing; // spacing between words
alignment_t align; // horizontal and vertical alignment
//optional<mat3_t> transform; // arbitrary transformation
pretty_poly::antialias_t antialiasing = pretty_poly::X4; // level of antialiasing to apply
void set_size(int s) {
size = s;
line_height = size;
letter_spacing = 0;
word_spacing = size / 2;
}
text_metrics_t() {};
};
/*
utility functions
*/
pretty_poly::rect_t measure_character(text_metrics_t &tm, uint16_t codepoint);
/*
render functions
*/
void render_character(text_metrics_t &tm, uint16_t codepoint, pretty_poly::point_t<int> origin);
template<typename mat_t>
void render_character(text_metrics_t &tm, uint16_t codepoint, pretty_poly::point_t<int> origin, mat_t transform);
}

View File

@ -0,0 +1,9 @@
add_library(pico_vector
${CMAKE_CURRENT_LIST_DIR}/pico_vector.cpp
${CMAKE_CURRENT_LIST_DIR}/pretty_poly.cpp
${CMAKE_CURRENT_LIST_DIR}/alright_fonts.cpp
)
target_include_directories(pico_vector INTERFACE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(pico_vector pico_stdlib hardware_interp)

View File

@ -0,0 +1,192 @@
#include "pico_vector.hpp"
#include <vector>
namespace pimoroni {
void PicoVector::polygon(std::vector<pretty_poly::contour_t<picovector_point_type>> contours, Point origin, int scale) {
pretty_poly::settings::clip = {graphics->clip.x, graphics->clip.y, graphics->clip.w, graphics->clip.h};
pretty_poly::draw_polygon<picovector_point_type>(
contours,
pretty_poly::point_t<int>(origin.x, origin.y),
scale);
}
void PicoVector::rotate(std::vector<pretty_poly::contour_t<picovector_point_type>> &contours, Point origin, float angle) {
pretty_poly::point_t<picovector_point_type> t{(picovector_point_type)origin.x, (picovector_point_type)origin.y};
angle = (2 * (float)M_PI / 360.f) * angle;
pretty_poly::mat2_t r = pretty_poly::mat2_t::rotation(angle);
for(auto &contour : contours) {
for(auto i = 0u; i < contour.count; i++) {
contour.points[i] -= t;
contour.points[i] *= r;
contour.points[i] += t;
}
}
}
void PicoVector::translate(std::vector<pretty_poly::contour_t<picovector_point_type>> &contours, Point translation) {
pretty_poly::point_t<picovector_point_type> t{(picovector_point_type)translation.x, (picovector_point_type)translation.y};
for(auto &contour : contours) {
for(auto i = 0u; i < contour.count; i++) {
contour.points[i] += t;
}
}
}
void PicoVector::rotate(pretty_poly::contour_t<picovector_point_type> &contour, Point origin, float angle) {
pretty_poly::point_t<picovector_point_type> t{(picovector_point_type)origin.x, (picovector_point_type)origin.y};
angle = (2 * (float)M_PI / 360.f) * angle;
pretty_poly::mat2_t r = pretty_poly::mat2_t::rotation(angle);
for(auto i = 0u; i < contour.count; i++) {
contour.points[i] -= t;
contour.points[i] *= r;
contour.points[i] += t;
}
}
void PicoVector::translate(pretty_poly::contour_t<picovector_point_type> &contour, Point translation) {
pretty_poly::point_t<picovector_point_type> t{(picovector_point_type)translation.x, (picovector_point_type)translation.y};
for(auto i = 0u; i < contour.count; i++) {
contour.points[i] += t;
}
}
Point PicoVector::text(std::string_view text, Point origin) {
// Copy clipping bounds from the PicoGraphics instance
pretty_poly::settings::clip = {graphics->clip.x, graphics->clip.y, graphics->clip.w, graphics->clip.h};
// TODO: Normalize types somehow, so we're not converting?
pretty_poly::point_t<int> caret = pretty_poly::point_t<int>(origin.x, origin.y);
// Align text from the bottom left
caret.y += text_metrics.size;
int16_t space_width = alright_fonts::measure_character(text_metrics, ' ').w;
if (space_width == 0) {
space_width = text_metrics.word_spacing;
}
size_t i = 0;
while(i < text.length()) {
size_t next_space = text.find(' ', i + 1);
if(next_space == std::string::npos) {
next_space = text.length();
}
size_t next_linebreak = text.find('\n', i + 1);
if(next_linebreak == std::string::npos) {
next_linebreak = text.length();
}
size_t next_break = std::min(next_space, next_linebreak);
uint16_t word_width = 0;
for(size_t j = i; j < next_break; j++) {
word_width += alright_fonts::measure_character(text_metrics, text[j]).w;
word_width += text_metrics.letter_spacing;
}
if(caret.x != 0 && caret.x + word_width > graphics->clip.w) {
caret.x = origin.x;
caret.y += text_metrics.line_height;
}
for(size_t j = i; j < std::min(next_break + 1, text.length()); j++) {
if (text[j] == '\n') { // Linebreak
caret.x = origin.x;
caret.y += text_metrics.line_height;
} else if (text[j] == ' ') { // Space
caret.x += space_width;
} else {
alright_fonts::render_character(text_metrics, text[j], caret);
}
caret.x += alright_fonts::measure_character(text_metrics, text[j]).w;
caret.x += text_metrics.letter_spacing;
}
i = next_break + 1;
}
return Point(caret.x, caret.y);
}
Point PicoVector::text(std::string_view text, Point origin, float angle) {
// Copy clipping bounds from the PicoGraphics instance
pretty_poly::settings::clip = {graphics->clip.x, graphics->clip.y, graphics->clip.w, graphics->clip.h};
// TODO: Normalize types somehow, so we're not converting?
pretty_poly::point_t<float> caret(0, 0);
// Prepare a transformation matrix for character and offset rotation
angle = (2 * (float)M_PI / 360.f) * angle;
pretty_poly::mat2_t transform = pretty_poly::mat2_t::rotation(angle);
// Align text from the bottom left
caret.y += text_metrics.line_height;
caret *= transform;
pretty_poly::point_t<float> space;
pretty_poly::point_t<float> carriage_return(0, -text_metrics.line_height);
space.x = alright_fonts::measure_character(text_metrics, ' ').w;
if (space.x == 0) {
space.x = text_metrics.word_spacing;
}
space *= transform;
carriage_return *= transform;
const pretty_poly::point_t<float> initial_carriage_return = carriage_return;
size_t i = 0;
while(i < text.length()) {
size_t next_space = text.find(' ', i + 1);
if(next_space == std::string::npos) {
next_space = text.length();
}
size_t next_linebreak = text.find('\n', i + 1);
if(next_linebreak == std::string::npos) {
next_linebreak = text.length();
}
size_t next_break = std::min(next_space, next_linebreak);
uint16_t word_width = 0;
for(size_t j = i; j < next_break; j++) {
word_width += alright_fonts::measure_character(text_metrics, text[j]).w;
word_width += text_metrics.letter_spacing;
}
if(caret.x != 0 && caret.x + word_width > graphics->clip.w) {
caret -= carriage_return;
carriage_return = initial_carriage_return;
}
for(size_t j = i; j < std::min(next_break + 1, text.length()); j++) {
if (text[j] == '\n') { // Linebreak
caret -= carriage_return;
carriage_return = initial_carriage_return;
} else if (text[j] == ' ') { // Space
caret += space;
carriage_return += space;
} else {
alright_fonts::render_character(text_metrics, text[j], pretty_poly::point_t<int>(origin.x + caret.x, origin.y + caret.y), transform);
}
pretty_poly::point_t<float> advance(
alright_fonts::measure_character(text_metrics, text[j]).w + text_metrics.letter_spacing,
0
);
advance *= transform;
caret += advance;
carriage_return += advance;
}
i = next_break + 1;
}
return Point(caret.x, caret.y);
}
}

View File

@ -0,0 +1,87 @@
#include "pretty_poly.hpp"
#include "alright_fonts.hpp"
#include "pico_graphics.hpp"
namespace pimoroni {
// Integer point types cause compound error in transformations
typedef float picovector_point_type;
class PicoVector {
private:
PicoGraphics *graphics;
alright_fonts::text_metrics_t text_metrics;
const uint8_t alpha_map[4] {0, 128, 192, 255};
public:
PicoVector(PicoGraphics *graphics, void *mem = nullptr) : graphics(graphics) {
pretty_poly::init(mem);
set_options([this](const pretty_poly::tile_t &tile) -> void {
uint8_t *tile_data = tile.data;
if(this->graphics->supports_alpha_blend() && pretty_poly::settings::antialias != pretty_poly::NONE) {
if (this->graphics->render_pico_vector_tile({tile.bounds.x, tile.bounds.y, tile.bounds.w, tile.bounds.h},
tile.data,
tile.stride,
(uint8_t)pretty_poly::settings::antialias)) {
return;
}
for(auto y = 0; y < tile.bounds.h; y++) {
for(auto x = 0; x < tile.bounds.w; x++) {
uint8_t alpha = *tile_data++;
if (alpha >= 4) {
this->graphics->set_pixel({x + tile.bounds.x, y + tile.bounds.y});
} else if (alpha > 0) {
alpha = alpha_map[alpha];
this->graphics->set_pixel_alpha({x + tile.bounds.x, y + tile.bounds.y}, alpha);
}
}
tile_data += tile.stride - tile.bounds.w;
}
} else {
for(auto y = 0; y < tile.bounds.h; y++) {
for(auto x = 0; x < tile.bounds.w; x++) {
uint8_t alpha = *tile_data++;
if (alpha) {
this->graphics->set_pixel({x + tile.bounds.x, y + tile.bounds.y});
}
}
tile_data += tile.stride - tile.bounds.w;
}
}
}, graphics->supports_alpha_blend() ? pretty_poly::X4 : pretty_poly::NONE, {graphics->clip.x, graphics->clip.y, graphics->clip.w, graphics->clip.h});
}
void set_antialiasing(pretty_poly::antialias_t antialias) {
set_options(pretty_poly::settings::callback, antialias, pretty_poly::settings::clip);
}
void set_font_size(unsigned int font_size) {
text_metrics.set_size(font_size);
}
bool set_font(std::string_view font_path, unsigned int font_size) {
bool result = text_metrics.face.load(font_path);
set_font_size(font_size);
return result;
}
void rotate(std::vector<pretty_poly::contour_t<picovector_point_type>> &contours, Point origin, float angle);
void translate(std::vector<pretty_poly::contour_t<picovector_point_type>> &contours, Point translation);
void rotate(pretty_poly::contour_t<picovector_point_type> &contour, Point origin, float angle);
void translate(pretty_poly::contour_t<picovector_point_type> &contour, Point translation);
Point text(std::string_view text, Point origin);
Point text(std::string_view text, Point origin, float angle);
void polygon(std::vector<pretty_poly::contour_t<picovector_point_type>> contours, Point origin = Point(0, 0), int scale=65536);
static constexpr size_t pretty_poly_buffer_size() {
return pretty_poly::buffer_size();
};
};
}

View File

@ -0,0 +1,339 @@
#include <cstdint>
#include <algorithm>
#include <optional>
#include <cstring>
#include <new>
#include <filesystem>
#include <fstream>
#include "pretty_poly.hpp"
#include "hardware/interp.h"
#ifdef PP_DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif
namespace pretty_poly {
uint8_t *tile_buffer;
int (*nodes)[32];
unsigned *node_counts;
// default tile bounds to X1 antialiasing
rect_t tile_bounds(0, 0, tile_buffer_size / node_buffer_size, node_buffer_size);
// user settings
namespace settings {
rect_t clip(0, 0, 320, 240);
tile_callback_t callback;
antialias_t antialias = antialias_t::NONE;
}
void init(void *memory) {
uintptr_t m = (uintptr_t)memory;
tile_buffer = new(memory) uint8_t[tile_buffer_size];
node_counts = new((void *)(m + tile_buffer_size)) unsigned[node_buffer_size];
nodes = new((void *)(m + tile_buffer_size + (node_buffer_size * sizeof(unsigned)))) int[node_buffer_size][32];
}
void set_options(tile_callback_t callback, antialias_t antialias, rect_t clip) {
settings::callback = callback;
settings::antialias = antialias;
settings::clip = clip;
// recalculate the tile size for rendering based on antialiasing level
int tile_height = node_buffer_size >> antialias;
tile_bounds = rect_t(0, 0, tile_buffer_size / tile_height, tile_height);
}
// dy step (returns 1, 0, or -1 if the supplied value is > 0, == 0, < 0)
inline constexpr int sign(int v) {
// assumes 32-bit int/unsigned
return ((unsigned)-v >> 31) - ((unsigned)v >> 31);
}
// write out the tile bits
void debug_tile(const tile_t &tile) {
debug(" - tile %d, %d (%d x %d)\n", tile.bounds.x, tile.bounds.y, tile.bounds.w, tile.bounds.h);
for(auto y = 0; y < tile.bounds.h; y++) {
debug("[%3d]: ", y);
for(auto x = 0; x < tile.bounds.w; x++) {
debug("%d", tile.get_value(x, y));
}
debug("\n");
}
debug("-----------------------\n");
}
void add_line_segment_to_nodes(const point_t<int> &start, const point_t<int> &end) {
// swap endpoints if line "pointing up", we do this because we
// alway skip the last scanline (so that polygons can but cleanly
// up against each other without overlap)
int sx = start.x, sy = start.y, ex = end.x, ey = end.y;
if(ey < sy) {
std::swap(sy, ey);
std::swap(sx, ex);
}
// Early out if line is completely outside the tile, or has no lines
if (ey < 0 || sy >= (int)node_buffer_size || sy == ey) return;
debug(" + line segment from %d, %d to %d, %d\n", sx, sy, ex, ey);
// Determine how many in-bounds lines to render
int y = std::max(0, sy);
int count = std::min((int)node_buffer_size, ey) - y;
// Handle cases where x is completely off to one side or other
if (std::max(sx, ex) <= 0) {
while (count--) {
nodes[y][node_counts[y]++] = 0;
++y;
}
return;
}
const int full_tile_width = (tile_bounds.w << settings::antialias);
if (std::min(sx, ex) >= full_tile_width) {
while (count--) {
nodes[y][node_counts[y]++] = full_tile_width;
++y;
}
return;
}
// Normal case
int x = sx;
int e = 0;
const int xinc = sign(ex - sx);
const int einc = abs(ex - sx) + 1;
const int dy = ey - sy;
// If sy < 0 jump to the start, note this does use a divide
// but potentially saves many wasted loops below, so is likely worth it.
if (sy < 0) {
e = einc * -sy;
int xjump = e / dy;
e -= dy * xjump;
x += xinc * xjump;
}
interp1->base[1] = full_tile_width;
interp1->accum[0] = x;
// loop over scanlines
while(count--) {
// consume accumulated error
while(e > dy) {e -= dy; interp1->add_raw[0] = xinc;}
// clamp node x value to tile bounds
const int nx = interp1->peek[0];
debug(" + adding node at %d, %d\n", x, y);
// add node to node list
nodes[y][node_counts[y]++] = nx;
// step to next scanline and accumulate error
y++;
e += einc;
}
}
template<typename T>
void build_nodes(const contour_t<T> &contour, const tile_t &tile, point_t<int> origin, int scale) {
int ox = (origin.x - tile.bounds.x) << settings::antialias;
int oy = (origin.y - tile.bounds.y) << settings::antialias;
// start with the last point to close the loop
point_t<int> last(
(((int(contour.points[contour.count - 1].x) * scale) << settings::antialias) / 65536) + ox,
(((int(contour.points[contour.count - 1].y) * scale) << settings::antialias) / 65536) + oy
);
for(auto i = 0u; i < contour.count; i++) {
point_t<int> point(
(((int(contour.points[i].x) * scale) << settings::antialias) / 65536) + ox,
(((int(contour.points[i].y) * scale) << settings::antialias) / 65536) + oy
);
add_line_segment_to_nodes(last, point);
last = point;
}
}
void render_nodes(const tile_t &tile, rect_t &bounds) {
int maxy = -1;
bounds.y = 0;
bounds.x = tile.bounds.w;
int maxx = 0;
int anitialias_mask = (1 << settings::antialias) - 1;
for(auto y = 0; y < (int)node_buffer_size; y++) {
if(node_counts[y] == 0) {
if (y == bounds.y) ++bounds.y;
continue;
}
std::sort(&nodes[y][0], &nodes[y][0] + node_counts[y]);
uint8_t* row_data = &tile.data[(y >> settings::antialias) * tile.stride];
bool rendered_any = false;
for(auto i = 0u; i < node_counts[y]; i += 2) {
int sx = nodes[y][i + 0];
int ex = nodes[y][i + 1];
if(sx == ex) {
continue;
}
rendered_any = true;
maxx = std::max((ex - 1) >> settings::antialias, maxx);
debug(" - render span at %d from %d to %d\n", y, sx, ex);
if (settings::antialias) {
int ax = sx >> settings::antialias;
const int aex = ex >> settings::antialias;
bounds.x = std::min(ax, bounds.x);
if (ax == aex) {
row_data[ax] += ex - sx;
continue;
}
row_data[ax] += (1 << settings::antialias) - (sx & anitialias_mask);
for(ax++; ax < aex; ax++) {
row_data[ax] += (1 << settings::antialias);
}
// This might add 0 to the byte after the end of the row, we pad the tile data
// by 1 byte to ensure that is OK
row_data[ax] += ex & anitialias_mask;
}
else {
bounds.x = std::min(sx, bounds.x);
for(int x = sx; x < ex; x++) {
row_data[x]++;
}
}
}
if (rendered_any) {
debug(" - rendered line %d\n", y);
maxy = y;
}
else if (y == bounds.y) {
debug(" - render nothing on line %d\n", y);
++bounds.y;
}
}
bounds.y >>= settings::antialias;
maxy >>= settings::antialias;
bounds.w = (maxx >= bounds.x) ? maxx + 1 - bounds.x : 0;
bounds.h = (maxy >= bounds.y) ? maxy + 1 - bounds.y : 0;
debug(" - rendered tile bounds %d, %d (%d x %d)\n", bounds.x, bounds.y, bounds.w, bounds.h);
}
template<typename T>
void draw_polygon(T *points, unsigned count) {
std::vector<contour_t<T>> contours;
contour_t<T> c(points, count);
contours.push_back(c);
draw_polygon<T>(contours);
}
template<typename T>
void draw_polygon(const std::vector<contour_t<T>>& contours, point_t<int> origin, int scale) {
debug("> draw polygon with %lu contours\n", contours.size());
if(contours.size() == 0) {
return;
}
// determine extreme bounds
rect_t polygon_bounds = contours[0].bounds();
for(auto &contour : contours) {
polygon_bounds = polygon_bounds.merge(contour.bounds());
}
polygon_bounds.x = ((polygon_bounds.x * scale) / 65536) + origin.x;
polygon_bounds.y = ((polygon_bounds.y * scale) / 65536) + origin.y;
polygon_bounds.w = ((polygon_bounds.w * scale) / 65536);
polygon_bounds.h = ((polygon_bounds.h * scale) / 65536);
debug(" - bounds %d, %d (%d x %d)\n", polygon_bounds.x, polygon_bounds.y, polygon_bounds.w, polygon_bounds.h);
debug(" - clip %d, %d (%d x %d)\n", settings::clip.x, settings::clip.y, settings::clip.w, settings::clip.h);
interp_hw_save_t interp1_save;
interp_save(interp1, &interp1_save);
interp_config cfg = interp_default_config();
interp_config_set_clamp(&cfg, true);
interp_config_set_signed(&cfg, true);
interp_set_config(interp1, 0, &cfg);
interp1->base[0] = 0;
//memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
// iterate over tiles
debug(" - processing tiles\n");
for(auto y = polygon_bounds.y; y < polygon_bounds.y + polygon_bounds.h; y += tile_bounds.h) {
for(auto x = polygon_bounds.x; x < polygon_bounds.x + polygon_bounds.w; x += tile_bounds.w) {
tile_t tile;
tile.bounds = rect_t(x, y, tile_bounds.w, tile_bounds.h).intersection(settings::clip);
tile.stride = tile_bounds.w;
tile.data = tile_buffer;
debug(" : %d, %d (%d x %d)\n", tile.bounds.x, tile.bounds.y, tile.bounds.w, tile.bounds.h);
// if no intersection then skip tile
if(tile.bounds.empty()) {
debug(" : empty when clipped, skipping\n");
continue;
}
// clear existing tile data and nodes
memset(node_counts, 0, node_buffer_size * sizeof(unsigned));
memset(tile.data, 0, tile_buffer_size);
// build the nodes for each contour
for(const contour_t<T> &contour : contours) {
debug(" : build nodes for contour\n");
build_nodes(contour, tile, origin, scale);
}
debug(" : render the tile\n");
// render the tile
rect_t bounds;
render_nodes(tile, bounds);
if (bounds.empty()) {
continue;
}
tile.data += bounds.x + tile.stride * bounds.y;
tile.bounds.x += bounds.x;
tile.bounds.y += bounds.y;
tile.bounds.w = bounds.w;
tile.bounds.h = bounds.h;
settings::callback(tile);
}
}
interp_restore(interp1, &interp1_save);
}
}
template void pretty_poly::draw_polygon<int>(const std::vector<contour_t<int>>& contours, point_t<int> origin, int scale);
template void pretty_poly::draw_polygon<float>(const std::vector<contour_t<float>>& contours, point_t<int> origin, int scale);
template void pretty_poly::draw_polygon<uint8_t>(const std::vector<contour_t<uint8_t>>& contours, point_t<int> origin, int scale);
template void pretty_poly::draw_polygon<int8_t>(const std::vector<contour_t<int8_t>>& contours, point_t<int> origin, int scale);

View File

@ -0,0 +1,73 @@
#pragma once
#include <cstdint>
#include <algorithm>
#include <optional>
#include <cstring>
#include <new>
#include <filesystem>
#include <fstream>
#include <functional>
#include "pretty_poly_types.hpp"
namespace pretty_poly {
class file_io {
private:
void *state;
size_t filesize = 0;
public:
file_io(std::string_view path);
~file_io();
size_t seek(size_t pos);
size_t read(void *buf, size_t len);
size_t tell();
bool fail();
};
// buffer that each tile is rendered into before callback
constexpr unsigned tile_buffer_size = 1024;
// polygon node buffer handles at most 16 line intersections per scanline
// is this enough for cjk/emoji? (requires a 2kB buffer)
constexpr unsigned node_buffer_size = 32;
typedef std::function<void(const tile_t &tile)> tile_callback_t;
// user settings
namespace settings {
extern rect_t clip;
extern tile_callback_t callback;
extern antialias_t antialias;
}
constexpr size_t buffer_size() {
return tile_buffer_size + (node_buffer_size * sizeof(unsigned)) + (node_buffer_size * 32 * sizeof(int));
}
constexpr size_t buffer_size();
void init(void *memory);
void set_options(tile_callback_t callback, antialias_t antialias, rect_t clip);
// dy step (returns 1, 0, or -1 if the supplied value is > 0, == 0, < 0)
inline constexpr int sign(int v);
// write out the tile bits
void debug_tile(const tile_t &tile);
void add_line_segment_to_nodes(const point_t<int> &start, const point_t<int> &end);
template<typename T>
void build_nodes(const contour_t<T> &contour, const tile_t &tile, point_t<int> origin = point_t<int>(0, 0), int scale = 65536);
void render_nodes(const tile_t &tile, rect_t &bounds);
template<typename T>
void draw_polygon(T *points, unsigned count);
template<typename T>
void draw_polygon(const std::vector<contour_t<T>>& contours, point_t<int> origin = point_t<int>(0, 0), int scale = 65536);
}

View File

@ -0,0 +1,162 @@
#pragma once
#include <cstdint>
#include <math.h>
#include <vector>
#ifdef PP_DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...)
#endif
namespace pretty_poly {
enum antialias_t {NONE = 0, X4 = 1, X16 = 2};
// 3x3 matrix for coordinate transformations
struct mat3_t {
float v00 = 0.0f, v10 = 0.0f, v20 = 0.0f, v01 = 0.0f, v11 = 0.0f, v21 = 0.0f, v02 = 0.0f, v12 = 0.0f, v22 = 0.0f;
mat3_t() = default;
mat3_t(const mat3_t &m) = default;
inline mat3_t& operator*= (const mat3_t &m) {
float r00 = this->v00 * m.v00 + this->v01 * m.v10 + this->v02 * m.v20;
float r01 = this->v00 * m.v01 + this->v01 * m.v11 + this->v02 * m.v21;
float r02 = this->v00 * m.v02 + this->v01 * m.v12 + this->v02 * m.v22;
float r10 = this->v10 * m.v00 + this->v11 * m.v10 + this->v12 * m.v20;
float r11 = this->v10 * m.v01 + this->v11 * m.v11 + this->v12 * m.v21;
float r12 = this->v10 * m.v02 + this->v11 * m.v12 + this->v12 * m.v22;
float r20 = this->v20 * m.v00 + this->v21 * m.v10 + this->v22 * m.v20;
float r21 = this->v20 * m.v01 + this->v21 * m.v11 + this->v22 * m.v21;
float r22 = this->v20 * m.v02 + this->v21 * m.v12 + this->v22 * m.v22;
this->v00 = r00; this->v01 = r01; this->v02 = r02;
this->v10 = r10; this->v11 = r11; this->v12 = r12;
this->v20 = r20; this->v21 = r21; this->v22 = r22;
return *this;
}
static mat3_t identity() {mat3_t m; m.v00 = m.v11 = m.v22 = 1.0f; return m;}
static mat3_t rotation(float a) {
float c = cosf(a), s = sinf(a); mat3_t r = mat3_t::identity();
r.v00 = c; r.v01 = -s; r.v10 = s; r.v11 = c; return r;}
static mat3_t translation(float x, float y) {
mat3_t r = mat3_t::identity(); r.v02 = x; r.v12 = y; return r;}
static mat3_t scale(float x, float y) {
mat3_t r = mat3_t::identity(); r.v00 = x; r.v11 = y; return r;}
};
// 2x2 matrix for rotations and scales
struct mat2_t {
float v00 = 0.0f, v10 = 0.0f, v01 = 0.0f, v11 = 0.0f;
mat2_t() = default;
mat2_t(const mat2_t &m) = default;
inline mat2_t& operator*= (const mat2_t &m) {
float r00 = this->v00 * m.v00 + this->v01 * m.v10;
float r01 = this->v00 * m.v01 + this->v01 * m.v11;
float r10 = this->v10 * m.v00 + this->v11 * m.v10;
float r11 = this->v10 * m.v01 + this->v11 * m.v11;
this->v00 = r00; this->v01 = r01;
this->v10 = r10; this->v11 = r11;
return *this;
}
static mat2_t identity() {mat2_t m; m.v00 = m.v11 = 1.0f; return m;}
static mat2_t rotation(float a) {
float c = cosf(a), s = sinf(a); mat2_t r;
r.v00 = c; r.v01 = -s; r.v10 = s; r.v11 = c; return r;}
static mat2_t scale(float x, float y) {
mat2_t r; r.v00 = x; r.v11 = y; return r;}
};
// point type for contour points
template<typename T = int>
struct __attribute__ ((packed)) point_t {
T x, y;
point_t(T x, T y) : x(x), y(y) {}
point_t() : x(0), y(0) {}
inline point_t& operator-= (const point_t &a) {x -= a.x; y -= a.y; return *this;}
inline point_t& operator+= (const point_t &a) {x += a.x; y += a.y; return *this;}
inline point_t& operator*= (const float a) {x *= a; y *= a; return *this;}
inline point_t& operator*= (const mat2_t &a) {this->transform(a); return *this;}
inline point_t& operator*= (const mat3_t &a) {this->transform(a); return *this;}
inline point_t& operator/= (const float a) {x /= a; y /= a; return *this;}
inline point_t& operator/= (const point_t &a) {x /= a.x; y /= a.y; return *this;}
void transform(const mat3_t &m) {
float tx = x, ty = y;
this->x = (m.v00 * tx + m.v01 * ty + m.v02);
this->y = (m.v10 * tx + m.v11 * ty + m.v12);
}
void transform(const mat2_t &m) {
float tx = x, ty = y;
this->x = (m.v00 * tx + m.v01 * ty);
this->y = (m.v10 * tx + m.v11 * ty);
}
};
template<typename T> inline point_t<T> operator- (point_t<T> lhs, const point_t<T> &rhs) { lhs -= rhs; return lhs; }
template<typename T> inline point_t<T> operator- (const point_t<T> &rhs) { return point_t<T>(-rhs.x, -rhs.y); }
template<typename T> inline point_t<T> operator+ (point_t<T> lhs, const point_t<T> &rhs) { lhs += rhs; return lhs; }
template<typename T> inline point_t<T> operator* (point_t<T> lhs, const float rhs) { lhs *= rhs; return lhs; }
template<typename T> inline point_t<T> operator* (point_t<T> lhs, const point_t<T> &rhs) { lhs *= rhs; return lhs; }
template<typename T> inline point_t<T> operator* (point_t<T> lhs, const mat3_t &rhs) { lhs *= rhs; return lhs; }
template<typename T> inline point_t<T> operator/ (point_t<T> lhs, const float rhs) { lhs /= rhs; return lhs; }
template<typename T> inline point_t<T> operator/ (point_t<T> lhs, const point_t<T> &rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
// rect type for bounds and clipping rectangles
struct rect_t {
int x, y, w, h;
rect_t() : x(0), y(0), w(0), h(0) {}
rect_t(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {}
bool empty() const {return this->w == 0 || this->h == 0;}
rect_t intersection(const rect_t &c) {
return rect_t(std::max(this->x, c.x), std::max(this->y, c.y),
std::max(0, std::min(this->x + this->w, c.x + c.w) - std::max(this->x, c.x)),
std::max(0, std::min(this->y + this->h, c.y + c.h) - std::max(this->y, c.y)));
}
rect_t merge(const rect_t &c) {
return rect_t(std::min(this->x, c.x), std::min(this->y, c.y),
std::max(this->x + this->w, c.x + c.w) - std::min(this->x, c.x),
std::max(this->y + this->h, c.y + c.h) - std::min(this->y, c.y));
}
};
struct tile_t {
rect_t bounds;
unsigned stride;
uint8_t *data;
tile_t() {};
inline int get_value(int x, int y) const {
return this->data[x + y * this->stride];
}
};
template<typename T>
struct contour_t {
point_t<T> *points;
unsigned count;
contour_t() {}
contour_t(const std::vector<point_t<T>>& v) : points(v.data()), count(v.size()) {};
contour_t(point_t<T> *points, unsigned count) : points(points), count(count) {};
// TODO: Make this work, it's so much nicer to use auto point : contour
//point_t<T> *begin() const { return points; };
//point_t<T> *end() const { return points + count * sizeof(point_t<T>); };
rect_t bounds() const {
T minx = this->points[0].x, maxx = minx;
T miny = this->points[0].y, maxy = miny;
for(auto i = 1u; i < this->count; i++) {
minx = std::min(minx, this->points[i].x);
miny = std::min(miny, this->points[i].y);
maxx = std::max(maxx, this->points[i].x);
maxy = std::max(maxy, this->points[i].y);
}
return rect_t(minx, miny, maxx - minx, maxy - miny);
}
};
}

View File

@ -1,4 +1,7 @@
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/esp32spi/esp32spi.cmake)
if(NOT TARGET esp32spi)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/esp32spi/esp32spi.cmake)
endif()
add_library(pico_wireless INTERFACE)
target_sources(pico_wireless INTERFACE

View File

@ -1,3 +1,7 @@
if(NOT TARGET plasma)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/plasma/plasma.cmake)
endif()
add_library(plasma2040 INTERFACE)
target_include_directories(plasma2040 INTERFACE ${CMAKE_CURRENT_LIST_DIR})

View File

@ -1,3 +1,7 @@
if(NOT TARGET plasma)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/plasma/plasma.cmake)
endif()
add_library(plasma_stick INTERFACE)
target_include_directories(plasma_stick INTERFACE ${CMAKE_CURRENT_LIST_DIR})

View File

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

204
libraries/pngdec/LICENSE Normal file
View File

@ -0,0 +1,204 @@
Copyright 2020 BitBank Software, Inc. All rights reserved.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

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