Skip to content

Commit bdf3e9f

Browse files
committed
ledmatrix: Limit max brightness, and do custom brightness control
The new hardware is extremely bright, so we need to limit the brightness. We limit it so that the max power consumption is slightly under 500mA. This limit is done by using the scaling factor in the LED controller. This also has the advantage that we have more brightness levels available for each LED because we can use the full range (previously much of the range would be too bright to use, even with the first hardware revision). But since we can't use the scaling factor for brightness control anymore, we have to do the brightness calculation ourselves. Signed-off-by: Daniel Schaefer <[email protected]>
1 parent b4b4c83 commit bdf3e9f

File tree

5 files changed

+67
-50
lines changed

5 files changed

+67
-50
lines changed

fl16-inputmodules/src/control.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,7 @@ pub fn handle_command(
479479
}
480480
Command::SetBrightness(br) => {
481481
//let _ = serial.write("Brightness".as_bytes());
482-
state.brightness = *br;
483-
matrix
484-
.set_scaling(state.brightness)
485-
.expect("failed to set scaling");
482+
set_brightness(state, *br, matrix);
486483
None
487484
}
488485
Command::Percentage(p) => {
@@ -499,10 +496,7 @@ pub fn handle_command(
499496
PatternVals::ZigZag => state.grid = zigzag(),
500497
PatternVals::FullBrightness => {
501498
state.grid = percentage(100);
502-
state.brightness = 0xFF;
503-
matrix
504-
.set_scaling(state.brightness)
505-
.expect("failed to set scaling");
499+
set_brightness(state, BRIGHTNESS_LEVELS, matrix);
506500
}
507501
PatternVals::DisplayPanic => state.grid = display_panic(),
508502
PatternVals::DisplayLotus2 => state.grid = display_lotus2(),

fl16-inputmodules/src/fl16.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ where
2020
self.device.i2c
2121
}
2222

23+
// TODO: Maybe make this private and set it once in the constructor
2324
pub fn set_scaling(&mut self, scale: u8) -> Result<(), I2cError> {
2425
self.device.set_scaling(scale)
2526
}

fl16-inputmodules/src/matrix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub struct LedmatrixState {
2828
#[derive(Clone)]
2929
pub enum SleepState {
3030
Awake,
31-
Sleeping(Grid),
31+
Sleeping((Grid, u8)),
3232
}
3333

3434
#[allow(clippy::large_enum_variant)]

fl16-inputmodules/src/patterns.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use crate::matrix::*;
1212
/// math.ceil(WIDTH * HEIGHT / 8)
1313
pub const DRAW_BYTES: usize = 39;
1414

15+
/// Maximum number of brightneses levels
16+
pub const BRIGHTNESS_LEVELS: u8 = 255;
17+
1518
pub type Foo = LedMatrix<
1619
bsp::hal::I2C<
1720
I2C1,
@@ -270,14 +273,21 @@ pub fn _fill_grid(grid: &Grid, matrix: &mut Foo) {
270273
}
271274
}
272275

276+
pub fn set_brightness(state: &mut LedmatrixState, brightness: u8, matrix: &mut Foo) {
277+
state.brightness = brightness;
278+
fill_grid_pixels(state, matrix);
279+
}
280+
273281
/// Just sends two I2C commands for the entire grid
274-
pub fn fill_grid_pixels(grid: &Grid, matrix: &mut Foo) {
282+
pub fn fill_grid_pixels(state: &LedmatrixState, matrix: &mut Foo) {
275283
// 0xB4 LEDs on the first page, 0xAB on the second page
276284
let mut brightnesses = [0x00; 0xB4 + 0xAB];
277285
for y in 0..HEIGHT {
278286
for x in 0..WIDTH {
279287
let (register, page) = (matrix.device.calc_pixel)(x as u8, y as u8);
280-
brightnesses[(page as usize) * 0xB4 + (register as usize)] = grid.0[x][y];
288+
brightnesses[(page as usize) * 0xB4 + (register as usize)] =
289+
((state.grid.0[x][y] as u64) * (state.brightness as u64)
290+
/ (BRIGHTNESS_LEVELS as u64)) as u8;
281291
}
282292
}
283293
matrix.device.fill_matrix(&brightnesses).unwrap();

ledmatrix/src/main.rs

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ use rp2040_hal::{
1616
//use panic_probe as _;
1717
use rp2040_panic_usb_boot as _;
1818

19+
/// Static configuration whether sleep shohld instantly turn all LEDs on/off or
20+
/// slowly fade themm on/off
21+
const INSTANT_SLEEP: bool = false;
22+
23+
const MAX_CURRENT: usize = 500;
24+
25+
/// Maximum brightness out of 255
26+
/// Set to 94 because that results in just below 500mA current draw.
27+
const MAX_BRIGHTNESS: u8 = 94;
28+
1929
// TODO: Doesn't work yet, unless I panic right at the beginning of main
2030
//#[cfg(not(debug_assertions))]
2131
//use core::panic::PanicInfo;
@@ -65,9 +75,9 @@ use rp2040_panic_usb_boot as _;
6575
// .setup(&mut delay)
6676
// .expect("failed to setup rgb controller");
6777
//
68-
// matrix.set_scaling(100).expect("failed to set scaling");
78+
// set_brightness(state, 255, &mut matrix);
6979
// let grid = display_panic();
70-
// fill_grid_pixels(grid, &mut matrix);
80+
// fill_grid_pixels(state, &mut matrix);
7181
//
7282
// loop {}
7383
//}
@@ -166,7 +176,7 @@ fn main() -> ! {
166176
.manufacturer("Framework Computer Inc")
167177
.product("LED Matrix Input Module")
168178
.serial_number(serialnum)
169-
.max_power(200) // Device uses roughly 164mW when all LEDs are at full brightness
179+
.max_power(MAX_CURRENT)
170180
.device_release(device_release())
171181
.device_class(USB_CLASS_CDC)
172182
.build();
@@ -193,22 +203,22 @@ fn main() -> ! {
193203
grid: percentage(0),
194204
col_buffer: Grid::default(),
195205
animate: false,
196-
brightness: 120,
206+
brightness: 51, // Default to 51/255 = 20% brightness
197207
sleeping: SleepState::Awake,
198208
game: None,
199-
animation_period: 31_250, // 32 FPS
209+
animation_period: 31_250, // 31,250 us = 32 FPS
200210
};
201211

202212
let mut matrix = LedMatrix::configure(i2c);
203213
matrix
204214
.setup(&mut delay)
205-
.expect("failed to setup rgb controller");
215+
.expect("failed to setup RGB controller");
206216

207217
matrix
208-
.set_scaling(state.brightness)
218+
.set_scaling(MAX_BRIGHTNESS)
209219
.expect("failed to set scaling");
210220

211-
fill_grid_pixels(&state.grid, &mut matrix);
221+
fill_grid_pixels(&state, &mut matrix);
212222

213223
let timer = Timer::new(pac.TIMER, &mut pac.RESETS);
214224
let mut prev_timer = timer.get_counter().ticks();
@@ -239,7 +249,7 @@ fn main() -> ! {
239249
_ => {}
240250
}
241251

242-
fill_grid_pixels(&state.grid, &mut matrix);
252+
fill_grid_pixels(&state, &mut matrix);
243253
if state.animate {
244254
for x in 0..WIDTH {
245255
state.grid.0[x].rotate_right(1);
@@ -297,7 +307,7 @@ fn main() -> ! {
297307
buf[0], buf[1], buf[2], buf[3]
298308
)
299309
.unwrap();
300-
fill_grid_pixels(&state.grid, &mut matrix);
310+
fill_grid_pixels(&state, &mut matrix);
301311
}
302312
_ => {}
303313
}
@@ -366,21 +376,23 @@ fn handle_sleep(
366376
match (state.sleeping.clone(), go_sleeping) {
367377
(SleepState::Awake, false) => (),
368378
(SleepState::Awake, true) => {
369-
state.sleeping = SleepState::Sleeping(state.grid.clone());
370-
//state.grid = display_sleep();
371-
fill_grid_pixels(&state.grid, matrix);
379+
state.sleeping = SleepState::Sleeping((state.grid.clone(), state.brightness));
380+
// Perhaps we could have a sleep pattern. Probbaly not Or maybe
381+
// just for the first couple of minutes?
382+
// state.grid = display_sleep();
383+
// fill_grid_pixels(&state, matrix);
372384

373385
// Slowly decrease brightness
374-
delay.delay_ms(1000);
375-
let mut brightness = state.brightness;
376-
loop {
377-
delay.delay_ms(100);
378-
brightness = if brightness <= 5 { 0 } else { brightness - 5 };
379-
matrix
380-
.set_scaling(brightness)
381-
.expect("failed to set scaling");
382-
if brightness == 0 {
383-
break;
386+
if !INSTANT_SLEEP {
387+
delay.delay_ms(1000);
388+
let mut brightness = state.brightness;
389+
loop {
390+
delay.delay_ms(100);
391+
brightness = if brightness <= 5 { 0 } else { brightness - 5 };
392+
set_brightness(state, brightness, matrix);
393+
if brightness == 0 {
394+
break;
395+
}
384396
}
385397
}
386398

@@ -391,30 +403,30 @@ fn handle_sleep(
391403
//cortex_m::asm::wfi();
392404
}
393405
(SleepState::Sleeping(_), true) => (),
394-
(SleepState::Sleeping(old_grid), false) => {
406+
(SleepState::Sleeping((old_grid, old_brightness)), false) => {
395407
// Restore back grid before sleeping
396408
state.sleeping = SleepState::Awake;
397409
state.grid = old_grid;
398-
fill_grid_pixels(&state.grid, matrix);
410+
fill_grid_pixels(state, matrix);
399411

400412
// Power LED controller back on
401413
led_enable.set_high().unwrap();
402414

403415
// Slowly increase brightness
404-
delay.delay_ms(1000);
405-
let mut brightness = 0;
406-
loop {
407-
delay.delay_ms(100);
408-
brightness = if brightness >= state.brightness - 5 {
409-
state.brightness
410-
} else {
411-
brightness + 5
412-
};
413-
matrix
414-
.set_scaling(brightness)
415-
.expect("failed to set scaling");
416-
if brightness == state.brightness {
417-
break;
416+
if !INSTANT_SLEEP {
417+
delay.delay_ms(1000);
418+
let mut brightness = 0;
419+
loop {
420+
delay.delay_ms(100);
421+
brightness = if brightness >= old_brightness - 5 {
422+
old_brightness
423+
} else {
424+
brightness + 5
425+
};
426+
set_brightness(state, brightness, matrix);
427+
if brightness == old_brightness {
428+
break;
429+
}
418430
}
419431
}
420432
}

0 commit comments

Comments
 (0)