Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions .github/workflows/python-linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ on:
jobs:
build:
name: Python Linting
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install Python
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55
with:
python-version: '3.13'

- name: Install Python Deps
run: |
python3 -m venv .venv
source .venv/bin/activate
python -m pip install flake8
run: source ci/python.sh && qa_prepare_all

- name: Lint MicroPython Examples
shell: bash
run: |
source .venv/bin/activate
python -m flake8 --show-source --ignore E501 examples/
run: source ci/python.sh && qa_examples_check

- name: Lint MicroPython Modules
shell: bash
run: source ci/python.sh && qa_modules_check
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ You can find the latest release at [https://github.com/pimoroni/unicorn/releases

* [Stellar 16x16 (Pico W)](https://shop.pimoroni.com/products/space-unicorns?variant=40842632953939)
* [Galactic 53x11 (Pico W)](https://shop.pimoroni.com/products/space-unicorns?variant=40842033561683)
* [Cosmic 32x32 (Pico W)](https://shop.pimoroni.com/products/space-unicorns?variant=40842626596947)
* [Cosmic 32x32 (Pico W)](https://shop.pimoroni.com/products/space-unicorns?variant=40842626596947)

## Other Resources

* [(C++) Galactic Unicorn Scrolling Quote Demo](https://github.com/ahnlak-rp2040/gu-scrolling-quote)
* [(C++) Multiple Unicorns as a single display](https://github.com/gadgetoid/gu-multiverse)
* [(C++) Galactic Unicorn Bluetooth Audio Visualizer](https://github.com/Gadgetoid/galactic-bluetooth-audio)
31 changes: 30 additions & 1 deletion boards/usermod-common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,36 @@ include(jpegdec/micropython)
include(qrcode/micropython/micropython)

# Sensors & Breakouts
include(micropython-common-breakouts)

# Include in Pico 2 W only, these make the build too big for Pico W :(
# Do you really need to connect a matrix to your matrix!?
if(PICO_BOARD EQUAL "pico2_w")
include(breakout_dotmatrix/micropython)
include(breakout_rgbmatrix5x5/micropython)
include(breakout_matrix11x7/micropython)
endif()

include(breakout_encoder/micropython)
include(breakout_encoder_wheel/micropython)
include(breakout_ioexpander/micropython)
include(breakout_ltr559/micropython)
include(breakout_as7262/micropython)
include(breakout_as7343/micropython)
include(breakout_msa301/micropython)
include(breakout_pmw3901/micropython)
include(breakout_mics6814/micropython)
include(breakout_potentiometer/micropython)
include(breakout_rtc/micropython)
include(breakout_trackball/micropython)
include(breakout_sgp30/micropython)
include(breakout_bh1745/micropython)
include(breakout_bme69x/micropython)
include(breakout_bme68x/micropython)
include(breakout_bme280/micropython)
include(breakout_bmp280/micropython)
include(breakout_icp10125/micropython)
include(breakout_scd41/micropython)
include(breakout_vl53l5cx/micropython)

# Utility
include(adcfft/micropython)
Expand Down
2 changes: 1 addition & 1 deletion ci/micropython.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export TERM=${TERM:="xterm-256color"}

MICROPYTHON_FLAVOUR="micropython"
MICROPYTHON_VERSION="master"
MICROPYTHON_VERSION="v1.25.0"

PIMORONI_PICO_FLAVOUR="pimoroni"
PIMORONI_PICO_VERSION="feature/picovector2-and-layers"
Expand Down
52 changes: 52 additions & 0 deletions ci/python.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Include:
# F = Pyflakes
# Q = Quotes
# E/W = pycodestyle (Whitespace, Line lengths etc)
# B - flake8-bugbear = Unused loop variables, sloppy code
# COM - flake8-commas
# BLE - flake8-blind-except
# C4 - flake8-comprehensions
# ISC - flake8-implicit-str-concat = Implicit string concat, eg: `"hello" "world"` on one line
# ICN - flake8-import-conventions = Import conventions
# PIE - flake8-pie = Misc silliness, catches range with a 0 start argument
# RET - flake8-return = Enforces straight-forward code around return statements
# SLF - flake8-self
# ARG - flake8-unused-arguments

# Ignore:
# E501 - "line too long". How narrow is your screen!?
# E402 - "module level import not at top of file". Needs must!
# COM812 - "Add trailing comma". These are a little obnoxious and weird.
# ICN001 - "numpy should be imported as np". No. No it should not.

QA_INCLUDE="F,Q,W,E,B,COM,BLE,C4,ISC,ICN,PIE,RSE,RET,SLF,ARG"
QA_IGNORE="E501,E402,COM812,ICN001"
QA_EXCLUDE=""

function qa_prepare_all {
pip install ruff
}

function qa_check {
ruff check --select "$QA_INCLUDE" --ignore "$QA_IGNORE" --exclude "$QA_EXCLUDE" "$1"
}

function qa_fix {
ruff check --select "$QA_INCLUDE" --ignore "$QA_IGNORE" --exclude "$QA_EXCLUDE" --fix "$1"
}

function qa_examples_check {
qa_check examples
}

function qa_examples_fix {
qa_fix examples
}

function qa_modules_check {
qa_check modules
}

function qa_modules_fix {
qa_fix modules
}
4 changes: 2 additions & 2 deletions examples/cosmic_unicorn/audio/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ def __stop_i2s(self):
if self.__audio_out is not None:
self.__audio_out.deinit() # Deinit any active I2S comms

self.__state == WavPlayer.NONE # Return to the none state
self.__state = WavPlayer.NONE # Return to the none state

def __i2s_callback(self, arg):
def __i2s_callback(self, arg): # noqa ARG002
# PLAY
if self.__state == WavPlayer.PLAY:
if self.__mode == WavPlayer.MODE_WAV:
Expand Down
3 changes: 1 addition & 2 deletions examples/cosmic_unicorn/audio/countdown_with_alarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ def reset(self):
self.timer.deinit()
self.timer_running = False

def countdown(self, arg):

def countdown(self, _arg):
if self.total_seconds == 0:
audio.play_wav("doorbell.wav", False)
self.reset()
Expand Down
28 changes: 14 additions & 14 deletions examples/cosmic_unicorn/cheerlights_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from cosmic import CosmicUnicorn
from picographics import PicoGraphics, DISPLAY_COSMIC_UNICORN as DISPLAY

URL = 'http://api.thingspeak.com/channels/1417/field/2/last.json'
URL = "http://api.thingspeak.com/channels/1417/field/2/last.json"

UPDATE_INTERVAL = 113 # refresh interval in secs. Be nice to free APIs!
# this esoteric number is used so that a column of LEDs equates (approximately) to an hour
Expand All @@ -24,28 +24,28 @@
def status_handler(mode, status, ip):
# reports wifi connection status
print(mode, status, ip)
print('Connecting to wifi...')
print("Connecting to wifi...")
if status is not None:
if status:
print('Wifi connection successful!')
print("Wifi connection successful!")
else:
print('Wifi connection failed!')
print("Wifi connection failed!")


def hex_to_rgb(hex):
# converts a hex colour code into RGB
h = hex.lstrip('#')
h = hex.lstrip("#")
r, g, b = (int(h[i:i + 2], 16) for i in (0, 2, 4))
return r, g, b


def get_data():
def get_data(_t=None):
# open the json file
print(f'Requesting URL: {URL}')
print(f"Requesting URL: {URL}")
r = urequests.get(URL)
# open the json data
j = r.json()
print('Data obtained!')
print("Data obtained!")
r.close()

# flash the onboard LED after getting data
Expand All @@ -54,11 +54,11 @@ def get_data():
pico_led.value(False)

# extract hex colour from the json data
hex = j['field2']
hex = j["field2"]

# add the new hex colour to the end of the array
colour_array.append(hex)
print(f'Colour added to array: {hex}')
print(f"Colour added to array: {hex}")
# remove the oldest colour in the array
colour_array.pop(0)
update_leds()
Expand Down Expand Up @@ -90,7 +90,7 @@ def update_leds():
cu.set_brightness(0.5)

# set up the Pico W's onboard LED
pico_led = Pin('LED', Pin.OUT)
pico_led = Pin("LED", Pin.OUT)

current_colour = graphics.create_pen(0, 0, 0)

Expand All @@ -101,15 +101,15 @@ def update_leds():
try:
network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler)
uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
except Exception as e:
print(f'Wifi connection failed! {e}')
except Exception as e: # noqa: BLE001
print(f"Wifi connection failed! {e}")

# get the first lot of data
get_data()

# start timer (the timer will call the function to update our data every UPDATE_INTERVAL)
timer = Timer(-1)
timer.init(period=UPDATE_INTERVAL * 1000, mode=Timer.PERIODIC, callback=lambda t: get_data())
timer.init(period=UPDATE_INTERVAL * 1000, mode=Timer.PERIODIC, callback=get_data)

while True:
# adjust brightness with LUX + and -
Expand Down
12 changes: 6 additions & 6 deletions examples/cosmic_unicorn/clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,26 @@ def from_hsv(h, s, v):
return int(p), int(q), int(v)
if i == 4:
return int(t), int(p), int(v)
if i == 5:
return int(v), int(p), int(q)
# if i == 5:
return int(v), int(p), int(q)


# function for drawing a gradient background
def gradient_background(start_hue, start_sat, start_val, end_hue, end_sat, end_val):
half_width = width // 2
for x in range(0, half_width):
for x in range(half_width):
hue = ((end_hue - start_hue) * (x / half_width)) + start_hue
sat = ((end_sat - start_sat) * (x / half_width)) + start_sat
val = ((end_val - start_val) * (x / half_width)) + start_val
colour = from_hsv(hue, sat, val)
graphics.set_pen(graphics.create_pen(int(colour[0]), int(colour[1]), int(colour[2])))
for y in range(0, height):
for y in range(height):
graphics.pixel(x, y)
graphics.pixel(width - x - 1, y)

colour = from_hsv(end_hue, end_sat, end_val)
graphics.set_pen(graphics.create_pen(int(colour[0]), int(colour[1]), int(colour[2])))
for y in range(0, height):
for y in range(height):
graphics.pixel(half_width, y)


Expand Down Expand Up @@ -127,7 +127,7 @@ def sync_time():
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
print("waiting for connection...")
time.sleep(0.2)

redraw_display_if_reqd()
Expand Down
12 changes: 6 additions & 6 deletions examples/cosmic_unicorn/cosmic_paint/cosmic_paint.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@


@server.route("/", methods=["GET"])
def route_index(request):
def route_index(_request):
return send_file("cosmic_paint/index.html")


@server.route("/static/<path:path>", methods=["GET"])
def route_static(request, path):
def route_static(_request, path):
return send_file(f"cosmic_paint/static/{path}")


Expand All @@ -38,7 +38,7 @@ def get_pixel(x, y):
return None


def flood_fill(x, y, r, g, b):
def flood_fill(x, y):
todo = []

def fill(x, y, c):
Expand Down Expand Up @@ -73,9 +73,9 @@ def fill(x, y, c):
fill(x, y, c)


@server.route('/paint')
@server.route("/paint")
@websocket.with_websocket
async def echo(request, ws):
async def echo(_request, ws):
while True:
data = await ws.receive()
try:
Expand All @@ -91,7 +91,7 @@ async def echo(request, ws):
data = await ws.receive()
x, y, r, g, b = [int(n) for n in data[0:5]]
graphics.set_pen(graphics.create_pen(r, g, b))
flood_fill(x, y, r, g, b)
flood_fill(x, y)

if data == "clear":
graphics.set_pen(graphics.create_pen(0, 0, 0))
Expand Down
4 changes: 2 additions & 2 deletions examples/cosmic_unicorn/eighties_super_computer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from cosmic import CosmicUnicorn
from picographics import PicoGraphics, DISPLAY_COSMIC_UNICORN as DISPLAY

'''
"""
Random LEDs blink on and off mimicing the look of a movie
super computer doing its work in the eighties.

You can adjust the brightness with LUX + and -.
'''
"""

cu = CosmicUnicorn()
graphics = PicoGraphics(DISPLAY)
Expand Down
Loading