Skip to content

Commit 1710ff1

Browse files
Merge pull request #75 from FrameworkComputer/foo
2 parents 7698eef + 8c809ad commit 1710ff1

File tree

8 files changed

+166
-52
lines changed

8 files changed

+166
-52
lines changed

.github/workflows/firmware.yml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
- run: cargo make --cwd b1display
3636
- run: cargo make --cwd c1minimal
3737
- run: cargo make --cwd ledmatrix build-release
38+
- run: cargo make --cwd ledmatrix build-release-10k
3839
- run: cargo make --cwd b1display build-release
3940
- run: cargo make --cwd c1minimal build-release
4041

@@ -44,17 +45,9 @@ jobs:
4445
sudo apt-get install -y libudev-dev
4546
cargo make --cwd b1display uf2
4647
cargo make --cwd c1minimal uf2
48+
cargo make --cwd ledmatrix build-release-10k-uf2
4749
cargo make --cwd ledmatrix uf2
4850
49-
- name: Upload UF2 files
50-
uses: actions/upload-artifact@v3
51-
with:
52-
name: inputmodule_fw_uf2
53-
path: |
54-
b1display.uf2
55-
c1minimal.uf2
56-
ledmatrix.uf2
57-
5851
- name: Convert to bin format
5952
run: |
6053
sudo apt-get update
@@ -63,14 +56,30 @@ jobs:
6356
cargo make --cwd c1minimal bin
6457
cargo make --cwd ledmatrix bin
6558
66-
- name: Upload bin files
59+
- name: Upload ledmatrix files
6760
uses: actions/upload-artifact@v3
6861
with:
6962
name: inputmodule_fw_bin
63+
path: |
64+
ledmatrix.bin
65+
ledmatrix.uf2
66+
ledmatrix_10k.uf2
67+
68+
- name: Upload b1display files
69+
uses: actions/upload-artifact@v3
70+
with:
71+
name: inputmodule_fw_uf2
7072
path: |
7173
b1display.bin
74+
b1display.uf2
75+
76+
- name: Upload c1minimal files
77+
uses: actions/upload-artifact@v3
78+
with:
79+
name: inputmodule_fw_uf2
80+
path: |
7281
c1minimal.bin
73-
ledmatrix.bin
82+
c1minimal.uf2
7483
7584
linting:
7685
name: Linting

.github/workflows/traditional-cargo.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ env:
2121

2222
jobs:
2323
firmware:
24-
name: Building
24+
name: Build firmware
2525
runs-on: [ubuntu-latest]
2626
steps:
2727
- uses: actions/checkout@v3
@@ -32,6 +32,7 @@ jobs:
3232
- run: cargo install flip-link
3333

3434
- run: cargo build -p ledmatrix
35+
- run: cargo build -p ledmatrix --features 10k
3536
- run: cargo build -p b1display
3637
- run: cargo build -p c1minimal
3738

fl16-inputmodules/src/matrix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub enum SleepState {
4848
Sleeping((Grid, u8)),
4949
}
5050

51-
#[derive(Copy, Clone, Debug)]
51+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5252
pub enum SleepReason {
5353
Command,
5454
SleepPin,

fl16-inputmodules/src/patterns.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,17 @@ pub fn zigzag() -> Grid {
359359

360360
grid
361361
}
362+
363+
pub fn every_nth_col(n: usize) -> Grid {
364+
let mut grid = Grid::default();
365+
366+
for y in 0..HEIGHT {
367+
for x in 0..WIDTH {
368+
if x % n == 0 {
369+
grid.0[x][y] = 0xFF;
370+
}
371+
}
372+
}
373+
374+
grid
375+
}

ledmatrix/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ edition = "2021"
33
name = "ledmatrix"
44
version = "0.1.6"
55

6+
[features]
7+
10k = []
8+
69
[dependencies]
710
cortex-m.workspace = true
811
cortex-m-rt.workspace = true

ledmatrix/Makefile.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
extend = "../Makefile.toml"
22

3+
[tasks.build-release-10k]
4+
command = "cargo"
5+
args = ["build", "--target=thumbv6m-none-eabi", "--release", "--features", "10k"]
6+
7+
[tasks.build-release-10k-uf2]
8+
command = "elf2uf2-rs"
9+
args = ["../target/thumbv6m-none-eabi/release/ledmatrix", "../target/thumbv6m-none-eabi/release/ledmatrix_10k.uf2"]
10+
dependencies = ["build-release-10k"]
11+
install_crate = "elf2uf2-rs"
12+
313
[tasks.uf2]
414
command = "elf2uf2-rs"
515
args = ["../target/thumbv6m-none-eabi/release/ledmatrix", "../target/thumbv6m-none-eabi/release/ledmatrix.uf2"]

ledmatrix/src/main.rs

Lines changed: 95 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ const MAX_CURRENT: usize = 500;
4242
/// Maximum brightness out of 255
4343
/// On HW Rev 1 from BizLink set to 94 to have just below 500mA current draw.
4444
/// BizLink HW Rev 2 has a larger current limiting resistor
45+
#[cfg(feature = "10k")]
46+
const MAX_BRIGHTNESS: u8 = 94;
47+
#[cfg(not(feature = "10k"))]
4548
const MAX_BRIGHTNESS: u8 = 255;
4649

4750
// TODO: Doesn't work yet, unless I panic right at the beginning of main
@@ -215,6 +218,18 @@ fn main() -> ! {
215218
&clocks.peripheral_clock,
216219
);
217220

221+
// Detect whether the dip1 pin is connected
222+
// We switched from bootsel button to DIP-switch with general purpose DIP1 pin in DVT2
223+
let mut dip1_present = false;
224+
let dip1 = pins.dip1.into_pull_up_input();
225+
if dip1.is_low().unwrap() {
226+
dip1_present = true;
227+
}
228+
let dip1 = dip1.into_pull_down_input();
229+
if dip1.is_high().unwrap() {
230+
dip1_present = true;
231+
}
232+
218233
let mut state = LedmatrixState {
219234
grid: percentage(0),
220235
col_buffer: Grid::default(),
@@ -226,6 +241,14 @@ fn main() -> ! {
226241
pwm_freq: PwmFreqArg::P29k,
227242
debug_mode: false,
228243
};
244+
if dip1_present {
245+
state.debug_mode = dip1.is_high().unwrap();
246+
}
247+
if !show_startup_animation(&state) {
248+
// If no startup animation, render another pattern
249+
// Lighting up every second column is a good pattern to test for noise.
250+
state.grid = every_nth_col(2);
251+
};
229252

230253
let mut matrix = LedMatrix::configure(i2c);
231254
matrix
@@ -246,9 +269,6 @@ fn main() -> ! {
246269
let mut sleep_timer = timer.get_counter().ticks();
247270

248271
let mut startup_percentage = Some(0);
249-
if !STARTUP_ANIMATION || state.debug_mode {
250-
state.grid = percentage(100);
251-
}
252272

253273
// Detect whether the sleep pin is connected
254274
// Early revisions of the hardware didn't have it wired up, if that is the
@@ -263,25 +283,16 @@ fn main() -> ! {
263283
sleep_present = true;
264284
}
265285

266-
// Detect whether the dip1 pin is connected
267-
// We switched from bootsel button to DIP-switch with general purpose DIP1 pin in DVT2
268-
let mut dip1_present = false;
269-
let dip1 = pins.dip1.into_pull_up_input();
270-
if dip1.is_low().unwrap() {
271-
dip1_present = true;
272-
}
273-
let dip1 = dip1.into_pull_down_input();
274-
if sleep.is_high().unwrap() {
275-
dip1_present = true;
276-
}
277-
278286
let mut usb_initialized = false;
279287
let mut usb_suspended = false;
280288
let mut last_usb_suspended = usb_suspended;
281289
let mut sleep_reason: Option<SleepReason> = None;
290+
let mut last_sleep_reason: Option<SleepReason>;
282291
let mut last_host_sleep = sleep.is_low().unwrap();
283292

284293
loop {
294+
last_sleep_reason = sleep_reason;
295+
285296
if dip1_present {
286297
state.debug_mode = dip1.is_high().unwrap();
287298
}
@@ -293,11 +304,13 @@ fn main() -> ! {
293304
// Or if it currently sleeping. Don't change if not sleeping
294305
// because then sleep is controlled by timing or by API.
295306
if host_sleep_changed || host_sleeping {
296-
sleep_reason = if host_sleeping {
297-
Some(SleepReason::SleepPin)
298-
} else {
299-
None
300-
};
307+
sleep_reason = assign_sleep_reason(
308+
last_sleep_reason,
309+
sleep_reason,
310+
host_sleeping,
311+
host_sleep_changed,
312+
SleepReason::SleepPin,
313+
);
301314
}
302315
last_host_sleep = host_sleeping;
303316
}
@@ -311,17 +324,25 @@ fn main() -> ! {
311324
// initialized for the first time. But we don't want to show the
312325
// sleep animation during startup.
313326
if usb_initialized && (usb_suspended_changed || usb_suspended) {
314-
sleep_reason = if usb_suspended {
315-
Some(SleepReason::UsbSuspend)
316-
} else {
317-
None
318-
};
327+
sleep_reason = assign_sleep_reason(
328+
last_sleep_reason,
329+
sleep_reason,
330+
usb_suspended,
331+
usb_suspended_changed,
332+
SleepReason::UsbSuspend,
333+
);
319334
}
320335
last_usb_suspended = usb_suspended;
321336

322337
// Go to sleep after the timer has run out
323338
if timer.get_counter().ticks() > sleep_timer + SLEEP_TIMEOUT && !state.debug_mode {
324-
sleep_reason = Some(SleepReason::Timeout);
339+
sleep_reason = assign_sleep_reason(
340+
last_sleep_reason,
341+
sleep_reason,
342+
true,
343+
true,
344+
SleepReason::Timeout,
345+
);
325346
}
326347
// Constantly resetting timer during sleep is same as reset it once on waking up.
327348
// This means the timer ends up counting the time spent awake.
@@ -342,7 +363,7 @@ fn main() -> ! {
342363
if matches!(state.sleeping, SleepState::Awake) && render_again {
343364
// On startup slowly turn the screen on - it's a pretty effect :)
344365
match startup_percentage {
345-
Some(p) if p <= 100 && (STARTUP_ANIMATION || state.debug_mode) => {
366+
Some(p) if p <= 100 && show_startup_animation(&state) => {
346367
state.grid = percentage(p);
347368
startup_percentage = Some(p + 5);
348369
}
@@ -396,11 +417,13 @@ fn main() -> ! {
396417
}
397418
(Some(command), _) => {
398419
if let Command::Sleep(go_sleeping) = command {
399-
sleep_reason = if go_sleeping {
400-
Some(SleepReason::Command)
401-
} else {
402-
None
403-
};
420+
sleep_reason = assign_sleep_reason(
421+
last_sleep_reason,
422+
sleep_reason,
423+
go_sleeping,
424+
true,
425+
SleepReason::Command,
426+
);
404427
} else {
405428
// If already sleeping, wake up.
406429
// This means every command will wake the device up.
@@ -520,14 +543,40 @@ fn get_random_byte(rosc: &RingOscillator<Enabled>) -> u8 {
520543
byte
521544
}
522545

523-
fn dyn_sleep_mode(state: &mut LedmatrixState) -> SleepMode {
546+
fn dyn_sleep_mode(state: &LedmatrixState) -> SleepMode {
524547
if state.debug_mode {
525548
SleepMode::Debug
526549
} else {
527550
SLEEP_MODE
528551
}
529552
}
530553

554+
fn debug_mode(state: &LedmatrixState) -> bool {
555+
dyn_sleep_mode(state) == SleepMode::Debug
556+
}
557+
558+
fn show_startup_animation(state: &LedmatrixState) -> bool {
559+
// Show startup animation
560+
STARTUP_ANIMATION && !debug_mode(state)
561+
}
562+
563+
fn assign_sleep_reason(
564+
previous: Option<SleepReason>,
565+
current: Option<SleepReason>,
566+
need_sleep: bool,
567+
// Whether the signal has actually changed in between firing
568+
signal_changed: bool,
569+
new: SleepReason,
570+
) -> Option<SleepReason> {
571+
if !need_sleep {
572+
None
573+
} else if current.is_some() && (Some(new) == previous || !signal_changed) {
574+
current
575+
} else {
576+
Some(new)
577+
}
578+
}
579+
531580
// Will do nothing if already in the right state
532581
fn handle_sleep(
533582
sleep_reason: Option<SleepReason>,
@@ -537,6 +586,7 @@ fn handle_sleep(
537586
led_enable: &mut gpio::Pin<Gpio29, gpio::Output<gpio::PushPull>>,
538587
) {
539588
match (state.sleeping.clone(), sleep_reason) {
589+
// Awake and staying awake
540590
(SleepState::Awake, None) => (),
541591
(SleepState::Awake, Some(sleep_reason)) => {
542592
state.sleeping = SleepState::Sleeping((state.grid.clone(), state.brightness));
@@ -553,26 +603,34 @@ fn handle_sleep(
553603
}
554604
}
555605

556-
// Turn LED controller off to save power
557-
if dyn_sleep_mode(state) == SleepMode::Debug {
606+
if debug_mode(state) {
558607
state.grid = display_sleep_reason(sleep_reason);
559608
fill_grid_pixels(state, matrix);
560609
} else {
610+
// Turn LED controller off to save power
561611
led_enable.set_low().unwrap();
562612
}
563613

564614
// TODO: Set up SLEEP# pin as interrupt and wfi
565615
//cortex_m::asm::wfi();
566616
}
567-
(SleepState::Sleeping(_), Some(_)) => (),
617+
// Already sleeping and new sleep reason => just keep sleeping
618+
(SleepState::Sleeping(_), Some(sleep_reason)) => {
619+
// If debug mode is enabled, then make sure the latest sleep reason is displayed
620+
if debug_mode(state) {
621+
state.grid = display_sleep_reason(sleep_reason);
622+
fill_grid_pixels(state, matrix);
623+
}
624+
}
625+
// Sleeping and need to wake up
568626
(SleepState::Sleeping((old_grid, old_brightness)), None) => {
569627
// Restore back grid before sleeping
570628
state.sleeping = SleepState::Awake;
571629
state.grid = old_grid;
572630
fill_grid_pixels(state, matrix);
573631

574632
// Power LED controller back on
575-
if dyn_sleep_mode(state) != SleepMode::Debug {
633+
if !debug_mode(state) {
576634
led_enable.set_high().unwrap();
577635
}
578636

0 commit comments

Comments
 (0)