Skip to content

Commit

Permalink
CI: With-filesystem builds.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gadgetoid committed Dec 2, 2024
1 parent a434437 commit 344d76f
Show file tree
Hide file tree
Showing 52 changed files with 3,317 additions and 13 deletions.
24 changes: 17 additions & 7 deletions .github/workflows/micropython.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,32 @@ jobs:
shell: bash
run: |
source $CI_PROJECT_ROOT/ci/micropython.sh && ci_debug
source $(dpkg -L virtualenvwrapper | grep "virtualenvwrapper.sh")
mkvirtualenv "dir2uf2"
ci_cmake_build ${{ matrix.name }}
mv "$CI_BUILD_ROOT/${{ matrix.name }}.uf2" "$CI_BUILD_ROOT/$RELEASE_FILE.uf2"
mv "$CI_BUILD_ROOT/${{ matrix.name }}-with-filesystem.uf2" "$CI_BUILD_ROOT/$RELEASE_FILE-with-filesystem.uf2"
- name: "Artifacts: Upload .uf2"
uses: actions/upload-artifact@v4
with:
name: ${{ env.RELEASE_FILE }}.uf2
path: ${{ env.CI_BUILD_ROOT }}/${{ env.RELEASE_FILE }}.uf2

- name: "Artifacts: Upload .uf2 (With Filesystem)"
uses: actions/upload-artifact@v4
with:
name: ${{ env.RELEASE_FILE }}.uf2
path: ${{ env.CI_BUILD_ROOT }}/${{ env.RELEASE_FILE }}-with-filesystem.uf2

- name: "Release: Upload .uf2"
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: softprops/action-gh-release@v1
with:
files: ${{ env.CI_BUILD_ROOT }}/${{ env.RELEASE_FILE }}.uf2

- name: "Release: Upload .uf2 (With Filesystem)"
if: github.event_name == 'release'
uses: softprops/action-gh-release@v1
with:
asset_path: ${{ env.CI_BUILD_ROOT }}/${{ env.RELEASE_FILE }}.uf2
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ env.RELEASE_FILE }}.uf2
asset_content_type: application/octet-stream
files: ${{ env.CI_BUILD_ROOT }}/${{ env.RELEASE_FILE }}-with-filesystem.uf2
3 changes: 3 additions & 0 deletions boards/pico2_w_inky/manifest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.py
lib/*
lib/*/*
3 changes: 3 additions & 0 deletions boards/pico_w_inky/manifest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.py
lib/*
lib/*/*
23 changes: 17 additions & 6 deletions ci/micropython.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function ci_micropython_build_mpy_cross {
}

function ci_apt_install_build_deps {
sudo apt update && sudo apt install ccache
sudo apt update && sudo apt install ccache python3-virtualenvwrapper virtualenvwrapper
}

function ci_prepare_all {
Expand Down Expand Up @@ -98,7 +98,8 @@ function ci_cmake_configure {
log_warning "Invalid board: $MICROPY_BOARD_DIR"
return 1
fi
cmake -S $CI_BUILD_ROOT/micropython/ports/rp2 -B build-$BOARD \
BUILD_DIR="$CI_BUILD_ROOT/build-$BOARD"
cmake -S $CI_BUILD_ROOT/micropython/ports/rp2 -B "$BUILD_DIR" \
-DPICOTOOL_FORCE_FETCH_FROM_GIT=1 \
-DPICO_BUILD_DOCS=0 \
-DPICO_NO_COPRO_DIS=1 \
Expand All @@ -112,13 +113,23 @@ function ci_cmake_configure {

function ci_cmake_build {
BOARD=$1
MICROPY_BOARD_DIR=$CI_PROJECT_ROOT/boards/$BOARD
EXAMPLES_DIR=$CI_PROJECT_ROOT/examples/inkylauncher/
TOOLS_DIR=$CI_BUILD_ROOT/tools
BUILD_DIR="$CI_BUILD_ROOT/build-$BOARD"
ccache --zero-stats || true
cmake --build build-$BOARD -j 2
cmake --build $BUILD_DIR -j 2
ccache --show-stats || true
if [ -d "tools/py_decl" ]; then
if [ -d "$TOOLS_DIR/py_decl" ]; then
log_inform "Tools found, verifying .uf2 with py_decl..."
python3 tools/py_decl/py_decl.py --to-json --verify "build-$BOARD/firmware.uf2"
python3 "$TOOLS_DIR/py_decl/py_decl.py" --to-json --verify "$BUILD_DIR/firmware.uf2"
fi
log_inform "Copying .uf2 to $(pwd)/$BOARD.uf2"
cp build-$BOARD/firmware.uf2 $BOARD.uf2
cp "$BUILD_DIR/firmware.uf2" $BOARD.uf2

if [ -f "$MICROPY_BOARD_DIR/manifest.txt" ] && [ -d "$TOOLS_DIR/dir2uf2" ]; then
log_inform "Creating $(pwd)/$BOARD-with-filesystem.uf2"
python3 -m pip install littlefs-python==0.12.0
$TOOLS_DIR/dir2uf2/dir2uf2 --fs-compact --sparse --append-to "$(pwd)/$BOARD.uf2" --manifest "$MICROPY_BOARD_DIR/manifest.txt" --filename with-filesystem.uf2 "$EXAMPLES_DIR"
fi
}
110 changes: 110 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Pico Inky Frame MicroPython Examples <!-- omit in toc -->

- [PicoGraphics](#picographics)
- [Examples](#examples)
- [Button Test](#button-test)
- [Carbon Intensity](#carbon-intensity)
- [Daily Activity](#daily-activity)
- [Dithering](#dithering)
- [Image Gallery](#image-gallery)
- [LED PWM](#led-pwm)
- [News](#news)
- [PlaceKitten](#placekitten)
- [Quote of the Day](#quote-of-the-day)
- [Random Joke](#random-joke)
- [RTC Demo](#rtc-demo)
- [SD Card Test](#sd-card-test)
- [XKCD Daily](#xkcd-daily)

## PicoGraphics

You can draw on Inky Frame using our tiny PicoGraphics display library.
- [PicoGraphics MicroPython function reference](../../modules/picographics)

## Examples

The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` from the `common` directory to be saved to your Pico W. Open up `WIFI_CONFIG.py` in Thonny to add your wifi details (and save it when you're done).

You'll also need to install the `micropython-urllib.urequest` library using Thonny's 'Tools' > 'Manage Packages' or `common/lib/urllib` which contains a compiled `.mpy` version that uses less RAM. You should place this directory in `lib` on your Pico W.

### Button Test
[button_test.py](button_test.py)

Inky Frame's buttons (and the RTC alarm, busy signal from the screen and external trigger from the hack header) are connected to a shift register to help conserve pins, and to allow these inputs to wake the board up from sleep.

This example demonstrates a simple way of reading when a button has been pushed by reading the shift register and checking if the bit in a specific position is 0 or 1.

### Carbon Intensity
[carbon_intensity.py](carbon_intensity.py)

This example connects to the Carbon Intensity API to give you a regional forecast of how your (UK) electricity is being generated and its carbon impact.

Find out more at https://carbonintensity.org.uk/

### Daily Activity
[inky_frame_daily_activity.py](inky_frame_daily_activity.py)

Generate a random activity from Bored API.

### Dithering
[inky_frame_dithering.py](inky_frame_dithering.py)

A basic example showing automatic dithering in action, as PicoGraphics tries to use Inky Frame's limited colour palette to match arbitrary colours.

### Image Gallery
[/image_gallery](../inky_frame/image_gallery)

This photo frame example displays local images on Inky Frame and lets you switch between them with the buttons. Use `image_gallery.py` if your images are stored on your Pico, or `image_gallery_sd.py` if the images are on your SD card.

### LED PWM
[led_pwm.py](led_pwm.py)

A basic example showing how you can control the brightness of Inky Frame's LEDs using PWM.

### News
[inky_frame_news.py](inky_frame_news.py)

Display headlines from BBC News.

### PlaceKitten
[inky_frame_placekitten.py](inky_frame_placekitten.py)

Download a random (from a small subset) image from PlaceKitten.

### Quote of the Day
[inky_frame_quote_of_the_day.py](inky_frame_quote_of_the_day.py)

Load the WikiQuotes Quote of the Day and display it.

### Random Joke
[inky_frame_random_joke.py](inky_frame_random_joke.py)

Load a random joke from JokeAPI.dev and display it.

Jokes are rendered into images "offline" by our feed2image service for two reasons:

1. Saves the Pico W having to process them
2. JokeAPI.dev needs TLS1.3 which Pico W does not support!

For bugs/contributions or to complain about a joke, see: https://github.com/pimoroni/feed2image

### RTC Demo
[inky_frame_rtc_demo.py](inky_frame_rtc_demo.py)

A basic example that sets the time/date from an NTP server, syncs the Inky and Pico RTCs and and makes Inky Frame wake up on a timer.

### SD Card Test
[sd_test.py](sd_test.py)

This simple example shows how to read and write from the SD card on Inky Frame.

### XKCD Daily
[inky_frame_xkcd_daily.py](inky_frame_xkcd_daily.py)

Download and display the daily webcomic from https://xkcd.com/

The webcomic is rendered "offline" by our feed2image service since xkcd.com requires TLS1.3!

For bugs/contributions see: https://github.com/pimoroni/feed2image


86 changes: 86 additions & 0 deletions examples/button_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# This example shows you a simple, non-interrupt way of reading Inky Frame's buttons with a loop that checks to see if buttons are pressed.

from pimoroni import ShiftRegister
# from picographics import PicoGraphics, DISPLAY_INKY_FRAME as DISPLAY # 5.7"
# from picographics import PicoGraphics, DISPLAY_INKY_FRAME_4 as DISPLAY # 4.0"
from picographics import PicoGraphics, DISPLAY_INKY_FRAME_7 as DISPLAY # 7.3"
from machine import Pin

display = PicoGraphics(display=DISPLAY)

display.set_font("bitmap8")

# Inky Frame uses a shift register to read the buttons
SR_CLOCK = 8
SR_LATCH = 9
SR_OUT = 10

sr = ShiftRegister(SR_CLOCK, SR_LATCH, SR_OUT)

# set up the button LEDs
button_a_led = Pin(11, Pin.OUT)
button_b_led = Pin(12, Pin.OUT)
button_c_led = Pin(13, Pin.OUT)
button_d_led = Pin(14, Pin.OUT)
button_e_led = Pin(15, Pin.OUT)


# a handy function we can call to clear the screen
# display.set_pen(1) is white and display.set_pen(0) is black
def clear():
display.set_pen(1)
display.clear()


# set up
clear()
display.set_pen(0)
display.text("Press any button!", 10, 10, scale=4)
display.update()

while True:
button_a_led.off()
button_b_led.off()
button_c_led.off()
button_d_led.off()
button_e_led.off()

# read the shift register
# we can tell which button has been pressed by checking if a specific bit is 0 or 1
result = sr.read()
button_a = sr[7]
button_b = sr[6]
button_c = sr[5]
button_d = sr[4]
button_e = sr[3]

if button_a == 1: # if a button press is detected then...
button_a_led.on()
clear() # clear to white
display.set_pen(4) # change the pen colour
display.text("Button A pressed", 10, 10, scale=4) # display some text on the screen
display.update() # update the display
elif button_b == 1:
button_b_led.on()
clear()
display.set_pen(6)
display.text("Button B pressed", 10, 50, scale=4)
display.update()
elif button_c == 1:
button_c_led.on()
clear()
display.set_pen(5)
display.text("Button C pressed", 10, 90, scale=4)
display.update()
elif button_d == 1:
button_d_led.on()
clear()
display.set_pen(2)
display.text("Button D pressed", 10, 130, scale=4)
display.update()
elif button_e == 1:
button_e_led.on()
clear()
display.set_pen(3)
display.text("Button E pressed", 10, 170, scale=4)
display.update()
59 changes: 59 additions & 0 deletions examples/button_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This example allows you to test Inky Frame's buttons
# It does not update the screen.

from pimoroni import ShiftRegister
from machine import Pin
import time


# Inky Frame uses a shift register to read the buttons
SR_CLOCK = 8
SR_LATCH = 9
SR_OUT = 10

sr = ShiftRegister(SR_CLOCK, SR_LATCH, SR_OUT)


# Simple class to debounce button input and handle LED
class Button:
def __init__(self, idx, led, debounce=50):
self.led = Pin(led, Pin.OUT) # LEDs are just regular IOs
self.led.on()
self._idx = idx
self._debounce_time = debounce
self._changed = time.ticks_ms()
self._last_value = None

def debounced(self):
return time.ticks_ms() - self._changed > self._debounce_time

def get(self, sr):
value = sr[self._idx]
if value != self._last_value and self.debounced():
self._last_value = value
self._changed = time.ticks_ms()
return value


button_a = Button(7, 11)
button_b = Button(6, 12)
button_c = Button(5, 13)
button_d = Button(4, 14)
button_e = Button(3, 15)


while True:
sr.read()

if button_a.get(sr):
button_a.led.toggle()
if button_b.get(sr):
button_b.led.toggle()
if button_c.get(sr):
button_c.led.toggle()
if button_d.get(sr):
button_d.led.toggle()
if button_e.get(sr):
button_e.led.toggle()

time.sleep(1.0 / 60) # Poll 60 times/second
Loading

0 comments on commit 344d76f

Please sign in to comment.