11# Lotus Input Module Firmware
22
3- See below sections for LED Matrix, LCD Display and C1 Minimal module details.
3+ This repository contains both the firmware for the Lotus input modules, as well
4+ as the tool to control them.
45
5- Rust project setup based off of: https://github.com/rp-rs/rp2040-project-template
6+ Rust firmware project setup based off of: https://github.com/rp-rs/rp2040-project-template
67
7- ## Features
8+ ## Modules
89
9- - Reset into bootloader when firmware crashes/panics
10+ See pages of the individual modules for details about how they work and how
11+ they're controlled.
12+
13+ - [ LED Matrix] ( ledmatrix/README.md )
14+ - [ 2nd Display] ( b1display/README.md )
15+ - [ Minimal C1 Input Module] ( c1minimal/README.md )
16+
17+ ## Generic Features
18+
19+ All modules are built with an RP2040 microcontroller
20+ Features that all modules share
21+
22+ - Firmware written in bare-metal Rust
23+ - Reset into RP2040 bootloader when firmware crashes/panics
24+ - Sleep Mode to save power
1025- API over USB ACM Serial Port - Requires no Drivers on Windows and Linux
11- - Display various pre-programmed patterns
12- - Light up a percentage of the screen
13- - Change brightness
14- - Send a black/white image to the display
15- - Send a greyscale image to the display
1626 - Go to sleep
1727 - Reset into bootloader
18- - Scroll and loop the display content vertically
19- - A commandline script and graphical application to control it
20- - Sleep Mode
21- - Transition slowly turns off/on the LEDs
22- - Current hardware does not have the SLEEP# GPIO connected, can't sleep automatically
28+ - Control and read module state (brightness, displayed image, ...)
2329
24- Future features:
30+ ## Control from the host
2531
26- - API
27- - Send a greyscale image to display
28- - Read current system state (brightness, sleeping, ...)
32+ To build your own application see the: [ API command documentation] ( commands.md )
2933
30- ## Control from the host
34+ Or use our ` inputmodule-control ` app. Optionally there are is also a
35+ [ Python script] ( python.md ) .
36+
37+ For device specific commands, see their individual documentation pages.
38+
39+ Common commands:
40+
41+ ###### Listing available devices
42+
43+ ``` sh
44+ > inputmodule-control --list
45+ /dev/ttyACM0
46+ VID 0x32AC
47+ PID 0x0020
48+ SN FRAKDEAM0020110001
49+ Product Lotus_LED_Matrix
50+ /dev/ttyACM1
51+ VID 0x32AC
52+ PID 0x0021
53+ SN FRAKDEAM0000000000
54+ Product Lotus_B1_Display
55+ ```
3156
32- Requirements: Python, [ PySimpleGUI ] ( https://www.pysimplegui.org ) and optionally [ pillow ] ( https://pillow.readthedocs.io/en/stable/index.html )
57+ ###### Apply command to single device
3358
34- Use ` control.py ` . Either the commandline, see ` control.py --help ` or the graphical version: ` control.py --gui `
59+ By default a command will be sent to all devices that can be found, to apply it
60+ to a single device, specify the COM port.
61+ In this example the command is targeted at ` b1-display ` , so it will only apply
62+ to this module type.
3563
3664```
37- options:
38- -h, --help show this help message and exit
39- --bootloader Jump to the bootloader to flash new firmware
40- --sleep, --no-sleep Simulate the host going to sleep or waking up
41- --brightness BRIGHTNESS
42- Adjust the brightness. Value 0-255
43- --animate, --no-animate
44- Start/stop vertical scrolling
45- --pattern {full,lotus,gradient,double-gradient,zigzag,panic,lotus2}
46- Display a pattern
47- --image IMAGE Display a PNG or GIF image in black and white only)
48- --image-grey IMAGE_GREY
49- Display a PNG or GIF image in greyscale
50- --percentage PERCENTAGE
51- Fill a percentage of the screen
52- --clock Display the current time
53- --string STRING Display a string or number, like FPS
54- --symbols SYMBOLS [SYMBOLS ...]
55- Show symbols (degF, degC, :), snow, cloud, ...)
56- --gui Launch the graphical version of the program
57- --blink Blink the current pattern
58- --breathing Breathing of the current pattern
59- --eq EQ [EQ ...] Equalizer
60- --random-eq Random Equalizer
61- --wpm WPM Demo
62- --snake Snake
63- --all-brightnesses Show every pixel in a different brightness
64- --set-color {white,black,red,green,blue,cyan,yellow,purple}
65- Set RGB color (C1 Minimal Input Module)
66- --get-color Get RGB color (C1 Minimal Input Module)
67- -v, --version Get device version
68- --serial-dev SERIAL_DEV
69- Change the serial dev. Probably /dev/ttyACM0 on Linux, COM0 on Windows
65+ # Example on Linux
66+ > inputmodule-control --serial-dev /dev/ttyACM0 b1-display --pattern black
67+
68+ # Example on Windows
69+ > inputmodule-control.exe --serial-dev COM5 b1-display --pattern black
7070```
7171
72- Examples
72+ ###### Send command when device connects
7373
74- ``` sh
75- # Launch graphical application
76- ./control.py --gui
74+ By default the app tries to connect with the device and aborts if it can't
75+ connect. But you might want to start the app, have it wait until the device is
76+ connected and then send the command.
7777
78- # Show current time and keep updating it
79- ./control.py --clock
78+ ```
79+ > inputmodule-control b1-display --pattern black
80+ Failed to find serial devivce. Please manually specify with --serial-dev
8081
81- # Draw PNG or GIF
82- ./control.py --image stripe.gif
83- ./control.py --image stripe.png
82+ # No failure, waits until the device is connected, sends command and exits
83+ > inputmodule-control --wait-for-device b1-display --pattern black
8484
85- # Change brightness (0-255)
86- ./control.py --brightness 50
85+ # If the device is already connected, it does nothing, just wait 1s.
86+ # This means you can run this command by a system service and restart it when
87+ # it finishes. Then it will only ever do anything if the device reconnects.
88+ > inputmodule-control --wait-for-device b1-display --pattern black
89+ Device already present. No need to wait. Not executing command.
8790```
8891
89- ## Control via Rust binary
92+ ## Update the Firmware
9093
91- Currently have to specify the build target because it's not possible to specify a per package build target.
92- Tracking issue: https://github.com/rust-lang/cargo/issues/9406
94+ First, put the module into bootloader mode.
95+
96+ This can be done either by pressing the bootsel button while plugging it in or
97+ by using one of the following commands:
9398
99+ ``` sh
100+ inputmodule-control led-matrix --bootloader
101+ inputmodule-control b1-display --bootloader
102+ inputmodule-control c1-minimal --bootloader
94103```
95- > cargo build --target x86_64-unknown-linux-gnu -p inputmodule-control
96- > cargo run --target x86_64-unknown-linux-gnu -p inputmodule-control
104+
105+ Then the module will present itself in the same way as a USB thumb drive.
106+ Copy the UF2 firmware file onto it and the device will flash and reset automatically.
107+ Alternatively when building from source, run one of the following commands:
108+
109+ ``` sh
110+ cargo run -p ledmatrix
111+ cargo run -p b1display
112+ cargo run -p c1minimal
97113```
98114
99- ## Building
115+ ## Building the firmware
100116
101117Dependencies: Rust
102118
103- Prepare Rust toolchain:
119+ Prepare Rust toolchain (once) :
104120
105121``` sh
106122rustup target install thumbv6m-none-eabi
@@ -116,36 +132,33 @@ cargo build -p b1display
116132cargo build -p c1minimal
117133```
118134
119- Generate UF2 file:
135+ Generate the UF2 update file:
120136
121137``` sh
122138elf2uf2-rs target/thumbv6m-none-eabi/debug/ledmatrix ledmatrix.uf2
123139elf2uf2-rs target/thumbv6m-none-eabi/debug/b1display b1dipslay.uf2
124- elf2uf2-rs target/thumbv6m-none-eabi/debug/b1display c1minimal.uf2
140+ elf2uf2-rs target/thumbv6m-none-eabi/debug/c1minimal c1minimal.uf2
125141```
126142
127- ## Flashing
143+ ## Building the Application
128144
129- First, put the module into bootloader mode, which will expose a filesystem
145+ Dependencies: Rust, pkg-config, libudev
130146
131- This can be done by pressing the bootsel button while plugging it in.
147+ Currently have to specify the build target because it's not possible to specify a per package build target.
148+ Tracking issue: https://github.com/rust-lang/cargo/issues/9406
132149
133- ``` sh
134- cargo run -p ledmatrix
135- cargo run -p b1display
136- cargo run -p c1minimal
137150```
138-
139- Or by copying the above generated UF2 file to the partition mounted when the
140- module is in the bootloder.
151+ > cargo build --target x86_64-unknown-linux-gnu -p inputmodule-control
152+ > cargo run --target x86_64-unknown-linux-gnu -p inputmodule-control
153+ ```
141154
142155### Check the firmware version of the device
143156
144- ###### In-band using ` control.py `
157+ ###### In-band using commandline
145158
146159``` sh
147- > ./ control.py --version
148- Device version : 0.1.2
160+ > inputmodule- control b1-display --version
161+ Device Version : 0.1.3
149162```
150163
151164###### By looking at the USB descriptor
@@ -169,30 +182,3 @@ Additionally the panic message is written to flash, which can be read as follows
169182sudo picotool save -r 0x15000000 0x15004000 message.bin
170183strings message.bin | head
171184```
172-
173- ## LED Matrix
174-
175- It's a 9x34 (306) LED matrix, controlled by RP2040 MCU and IS31FL3741A LED controller.
176-
177- Connection to the host system is via USB 2.0 and currently there is a USB Serial API to control it without reflashing.
178-
179- ## B1 Display
180-
181- ## C1 Minimal Input Module
182-
183- It's a very minimal input module. Many GPIO pins are exposed so that headers
184- can be soldered onto them. Additionally there are pads for a WS2812/Neopixel
185- compatible RGB LED.
186-
187- When booting up this LED is lit in green color.
188- Its color and brightness can be controlled via the commands:
189-
190- ``` sh
191- > ./control.py --brightness 255
192- > ./control.py --get-brightness
193- Current brightness: 255
194-
195- > ./control.py --set-color yellow
196- > ./control.py --get-color
197- Current color: RGB:(255, 255, 0)
198- ```
0 commit comments