diff --git a/fl16-inputmodules/src/control.rs b/fl16-inputmodules/src/control.rs index f5042f08..ec28c542 100644 --- a/fl16-inputmodules/src/control.rs +++ b/fl16-inputmodules/src/control.rs @@ -479,10 +479,7 @@ pub fn handle_command( } Command::SetBrightness(br) => { //let _ = serial.write("Brightness".as_bytes()); - state.brightness = *br; - matrix - .set_scaling(state.brightness) - .expect("failed to set scaling"); + set_brightness(state, *br, matrix); None } Command::Percentage(p) => { @@ -499,10 +496,7 @@ pub fn handle_command( PatternVals::ZigZag => state.grid = zigzag(), PatternVals::FullBrightness => { state.grid = percentage(100); - state.brightness = 0xFF; - matrix - .set_scaling(state.brightness) - .expect("failed to set scaling"); + set_brightness(state, BRIGHTNESS_LEVELS, matrix); } PatternVals::DisplayPanic => state.grid = display_panic(), PatternVals::DisplayLotus2 => state.grid = display_lotus2(), diff --git a/fl16-inputmodules/src/fl16.rs b/fl16-inputmodules/src/fl16.rs index 05e1f44b..7bf3efce 100644 --- a/fl16-inputmodules/src/fl16.rs +++ b/fl16-inputmodules/src/fl16.rs @@ -20,6 +20,7 @@ where self.device.i2c } + // TODO: Maybe make this private and set it once in the constructor pub fn set_scaling(&mut self, scale: u8) -> Result<(), I2cError> { self.device.set_scaling(scale) } diff --git a/fl16-inputmodules/src/matrix.rs b/fl16-inputmodules/src/matrix.rs index 63d56124..02f3529e 100644 --- a/fl16-inputmodules/src/matrix.rs +++ b/fl16-inputmodules/src/matrix.rs @@ -28,7 +28,7 @@ pub struct LedmatrixState { #[derive(Clone)] pub enum SleepState { Awake, - Sleeping(Grid), + Sleeping((Grid, u8)), } #[allow(clippy::large_enum_variant)] diff --git a/fl16-inputmodules/src/patterns.rs b/fl16-inputmodules/src/patterns.rs index 10d093f3..5f46b556 100644 --- a/fl16-inputmodules/src/patterns.rs +++ b/fl16-inputmodules/src/patterns.rs @@ -12,6 +12,9 @@ use crate::matrix::*; /// math.ceil(WIDTH * HEIGHT / 8) pub const DRAW_BYTES: usize = 39; +/// Maximum number of brightneses levels +pub const BRIGHTNESS_LEVELS: u8 = 255; + pub type Foo = LedMatrix< bsp::hal::I2C< I2C1, @@ -270,14 +273,21 @@ pub fn _fill_grid(grid: &Grid, matrix: &mut Foo) { } } +pub fn set_brightness(state: &mut LedmatrixState, brightness: u8, matrix: &mut Foo) { + state.brightness = brightness; + fill_grid_pixels(state, matrix); +} + /// Just sends two I2C commands for the entire grid -pub fn fill_grid_pixels(grid: &Grid, matrix: &mut Foo) { +pub fn fill_grid_pixels(state: &LedmatrixState, matrix: &mut Foo) { // 0xB4 LEDs on the first page, 0xAB on the second page let mut brightnesses = [0x00; 0xB4 + 0xAB]; for y in 0..HEIGHT { for x in 0..WIDTH { let (register, page) = (matrix.device.calc_pixel)(x as u8, y as u8); - brightnesses[(page as usize) * 0xB4 + (register as usize)] = grid.0[x][y]; + brightnesses[(page as usize) * 0xB4 + (register as usize)] = + ((state.grid.0[x][y] as u64) * (state.brightness as u64) + / (BRIGHTNESS_LEVELS as u64)) as u8; } } matrix.device.fill_matrix(&brightnesses).unwrap(); diff --git a/ledmatrix/src/main.rs b/ledmatrix/src/main.rs index 15de5f13..ae5d9cc8 100644 --- a/ledmatrix/src/main.rs +++ b/ledmatrix/src/main.rs @@ -16,6 +16,16 @@ use rp2040_hal::{ //use panic_probe as _; use rp2040_panic_usb_boot as _; +/// Static configuration whether sleep shohld instantly turn all LEDs on/off or +/// slowly fade themm on/off +const INSTANT_SLEEP: bool = false; + +const MAX_CURRENT: usize = 500; + +/// Maximum brightness out of 255 +/// Set to 94 because that results in just below 500mA current draw. +const MAX_BRIGHTNESS: u8 = 94; + // TODO: Doesn't work yet, unless I panic right at the beginning of main //#[cfg(not(debug_assertions))] //use core::panic::PanicInfo; @@ -65,9 +75,9 @@ use rp2040_panic_usb_boot as _; // .setup(&mut delay) // .expect("failed to setup rgb controller"); // -// matrix.set_scaling(100).expect("failed to set scaling"); +// set_brightness(state, 255, &mut matrix); // let grid = display_panic(); -// fill_grid_pixels(grid, &mut matrix); +// fill_grid_pixels(state, &mut matrix); // // loop {} //} @@ -166,7 +176,7 @@ fn main() -> ! { .manufacturer("Framework Computer Inc") .product("LED Matrix Input Module") .serial_number(serialnum) - .max_power(200) // Device uses roughly 164mW when all LEDs are at full brightness + .max_power(MAX_CURRENT) .device_release(device_release()) .device_class(USB_CLASS_CDC) .build(); @@ -193,22 +203,22 @@ fn main() -> ! { grid: percentage(0), col_buffer: Grid::default(), animate: false, - brightness: 120, + brightness: 51, // Default to 51/255 = 20% brightness sleeping: SleepState::Awake, game: None, - animation_period: 31_250, // 32 FPS + animation_period: 31_250, // 31,250 us = 32 FPS }; let mut matrix = LedMatrix::configure(i2c); matrix .setup(&mut delay) - .expect("failed to setup rgb controller"); + .expect("failed to setup RGB controller"); matrix - .set_scaling(state.brightness) + .set_scaling(MAX_BRIGHTNESS) .expect("failed to set scaling"); - fill_grid_pixels(&state.grid, &mut matrix); + fill_grid_pixels(&state, &mut matrix); let timer = Timer::new(pac.TIMER, &mut pac.RESETS); let mut prev_timer = timer.get_counter().ticks(); @@ -239,7 +249,7 @@ fn main() -> ! { _ => {} } - fill_grid_pixels(&state.grid, &mut matrix); + fill_grid_pixels(&state, &mut matrix); if state.animate { for x in 0..WIDTH { state.grid.0[x].rotate_right(1); @@ -297,7 +307,7 @@ fn main() -> ! { buf[0], buf[1], buf[2], buf[3] ) .unwrap(); - fill_grid_pixels(&state.grid, &mut matrix); + fill_grid_pixels(&state, &mut matrix); } _ => {} } @@ -366,21 +376,23 @@ fn handle_sleep( match (state.sleeping.clone(), go_sleeping) { (SleepState::Awake, false) => (), (SleepState::Awake, true) => { - state.sleeping = SleepState::Sleeping(state.grid.clone()); - //state.grid = display_sleep(); - fill_grid_pixels(&state.grid, matrix); + state.sleeping = SleepState::Sleeping((state.grid.clone(), state.brightness)); + // Perhaps we could have a sleep pattern. Probbaly not Or maybe + // just for the first couple of minutes? + // state.grid = display_sleep(); + // fill_grid_pixels(&state, matrix); // Slowly decrease brightness - delay.delay_ms(1000); - let mut brightness = state.brightness; - loop { - delay.delay_ms(100); - brightness = if brightness <= 5 { 0 } else { brightness - 5 }; - matrix - .set_scaling(brightness) - .expect("failed to set scaling"); - if brightness == 0 { - break; + if !INSTANT_SLEEP { + delay.delay_ms(1000); + let mut brightness = state.brightness; + loop { + delay.delay_ms(100); + brightness = if brightness <= 5 { 0 } else { brightness - 5 }; + set_brightness(state, brightness, matrix); + if brightness == 0 { + break; + } } } @@ -391,30 +403,30 @@ fn handle_sleep( //cortex_m::asm::wfi(); } (SleepState::Sleeping(_), true) => (), - (SleepState::Sleeping(old_grid), false) => { + (SleepState::Sleeping((old_grid, old_brightness)), false) => { // Restore back grid before sleeping state.sleeping = SleepState::Awake; state.grid = old_grid; - fill_grid_pixels(&state.grid, matrix); + fill_grid_pixels(state, matrix); // Power LED controller back on led_enable.set_high().unwrap(); // Slowly increase brightness - delay.delay_ms(1000); - let mut brightness = 0; - loop { - delay.delay_ms(100); - brightness = if brightness >= state.brightness - 5 { - state.brightness - } else { - brightness + 5 - }; - matrix - .set_scaling(brightness) - .expect("failed to set scaling"); - if brightness == state.brightness { - break; + if !INSTANT_SLEEP { + delay.delay_ms(1000); + let mut brightness = 0; + loop { + delay.delay_ms(100); + brightness = if brightness >= old_brightness - 5 { + old_brightness + } else { + brightness + 5 + }; + set_brightness(state, brightness, matrix); + if brightness == old_brightness { + break; + } } } }