Skip to content

Commit 88383d0

Browse files
committed
b1display: Allow updating animation frequency
Signed-off-by: Daniel Schaefer <[email protected]>
1 parent 865119a commit 88383d0

File tree

5 files changed

+83
-4
lines changed

5 files changed

+83
-4
lines changed

b1display/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ Options:
6868
Set/get FPS [possible values: quarter, half, one, two, four, eight, sixteen, thirty-two]
6969
--power-mode [<POWER_MODE>]
7070
Set/get power mode [possible values: low, high]
71+
--animation-fps [<ANIMATION_FPS>]
72+
Set/get animation FPS
7173
--image-bw <IMAGE_BW>
7274
Display black&white image (300x400px)
7375
--clear-ram

b1display/src/main.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ use usbd_serial::{SerialPort, USB_CLASS_CDC};
4444

4545
// Used to demonstrate writing formatted strings
4646
use core::fmt::Debug;
47-
//use core::fmt::Write;
48-
//use heapless::String;
47+
use core::fmt::Write;
48+
use heapless::String;
4949

5050
use fl16_inputmodules::control::*;
5151
use fl16_inputmodules::graphics::*;
@@ -68,7 +68,7 @@ type B1ST7306 = ST7306<
6868
>;
6969

7070
const DEBUG: bool = false;
71-
const SCRNS_DELTA: i32 = 10;
71+
const SCRNS_DELTA: i32 = 5;
7272
const WIDTH: i32 = 300;
7373
const HEIGHT: i32 = 400;
7474
const SIZE: Size = Size::new(WIDTH as u32, HEIGHT as u32);
@@ -156,6 +156,7 @@ fn main() -> ! {
156156
hpm: HpmFps::ThirtyTwo,
157157
lpm: LpmFps::Two,
158158
},
159+
animation_period: 1_000_000, // 1000ms = 1Hz
159160
};
160161

161162
const INVERTED: bool = false;
@@ -222,6 +223,7 @@ fn main() -> ! {
222223

223224
let timer = Timer::new(pac.TIMER, &mut pac.RESETS);
224225
let mut prev_timer = timer.get_counter().ticks();
226+
let mut ticks = 0;
225227

226228
let mut logo_pos = Point::new(LOGO_OFFSET_X, LOGO_OFFSET_Y);
227229

@@ -231,10 +233,32 @@ fn main() -> ! {
231233
handle_sleep(host_sleeping, &mut state, &mut delay, &mut disp);
232234

233235
// Handle period display updates. Don't do it too often
234-
if timer.get_counter().ticks() > prev_timer + 500_000 {
236+
if timer.get_counter().ticks() > prev_timer + state.animation_period {
235237
prev_timer = timer.get_counter().ticks();
236238

237239
if let Some(ref mut screensaver) = state.screensaver {
240+
let seconds = ticks / (1_000_000 / state.animation_period);
241+
#[allow(clippy::modulo_one)]
242+
let second_decimals = ticks % (1_000_000 / state.animation_period);
243+
Rectangle::new(Point::new(0, 0), Size::new(300, 50))
244+
.into_styled(PrimitiveStyle::with_fill(Rgb565::WHITE))
245+
.draw(&mut disp)
246+
.unwrap();
247+
let mut text: String<32> = String::new();
248+
write!(
249+
&mut text,
250+
"{:>4} Ticks ({:>4}.{} s)",
251+
ticks, seconds, second_decimals
252+
)
253+
.unwrap();
254+
// Uncomment to draw the ticks on the screen
255+
//draw_text(
256+
// &mut disp,
257+
// &text,
258+
// Point::new(0, 0),
259+
//).unwrap();
260+
ticks += 1;
261+
238262
logo_pos = {
239263
let (x, y) = (logo_pos.x, logo_pos.y);
240264
let w = logo_rect.size.width as i32;

fl16-inputmodules/src/control.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub enum CommandVals {
6363
ScreenSaver = 0x19,
6464
SetFps = 0x1A,
6565
SetPowerMode = 0x1B,
66+
AnimationPeriod = 0x1C,
6667
Version = 0x20,
6768
}
6869

@@ -170,6 +171,8 @@ pub enum Command {
170171
GetFps,
171172
SetPowerMode(u8),
172173
GetPowerMode,
174+
SetAnimationPeriod(u16),
175+
GetAnimationPeriod,
173176
_Unknown,
174177
}
175178

@@ -210,6 +213,7 @@ pub struct B1DIsplayState {
210213
pub screensaver: Option<ScreenSaverState>,
211214
pub power_mode: PowerMode,
212215
pub fps_config: FpsConfig,
216+
pub animation_period: u64,
213217
}
214218

215219
pub fn parse_command(count: usize, buf: &[u8]) -> Option<Command> {
@@ -408,6 +412,14 @@ pub fn parse_module_command(count: usize, buf: &[u8]) -> Option<Command> {
408412
} else {
409413
Command::GetPowerMode
410414
}),
415+
Some(CommandVals::AnimationPeriod) => {
416+
if count == 3 + 2 {
417+
let period = u16::from_le_bytes([buf[3], buf[4]]);
418+
Some(Command::SetAnimationPeriod(period))
419+
} else {
420+
Some(Command::GetAnimationPeriod)
421+
}
422+
}
411423
_ => None,
412424
}
413425
} else {
@@ -697,6 +709,17 @@ where
697709
};
698710
Some(response)
699711
}
712+
Command::SetAnimationPeriod(period) => {
713+
state.animation_period = (*period as u64) * 1_000;
714+
None
715+
}
716+
Command::GetAnimationPeriod => {
717+
// TODO: Doesn't seem to work when the FPS is 16 or higher
718+
let mut response: [u8; 32] = [0; 32];
719+
let period_ms = state.animation_period / 1_000;
720+
response[0..2].copy_from_slice(&(period_ms as u16).to_le_bytes());
721+
Some(response)
722+
}
700723
_ => handle_generic_command(command),
701724
}
702725
}

inputmodule-control/src/b1display.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ pub struct B1DisplaySubcommand {
7272
#[arg(long)]
7373
pub power_mode: Option<Option<PowerMode>>,
7474

75+
/// Set/get animation FPS
76+
#[arg(long)]
77+
pub animation_fps: Option<Option<u16>>,
78+
7579
/// Display black&white image (300x400px)
7680
#[arg(long)]
7781
pub image_bw: Option<String>,

inputmodule-control/src/inputmodule.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum Command {
4242
ScreenSaver = 0x19,
4343
Fps = 0x1A,
4444
PowerMode = 0x1B,
45+
AnimationPeriod = 0x1C,
4546
Version = 0x20,
4647
}
4748

@@ -272,6 +273,9 @@ pub fn serial_commands(args: &crate::ClapCli) {
272273
if let Some(power_mode) = b1display_args.power_mode {
273274
power_mode_cmd(serialdev, power_mode);
274275
}
276+
if let Some(fps) = b1display_args.animation_fps {
277+
animation_fps_cmd(serialdev, fps);
278+
}
275279
if let Some(image_path) = &b1display_args.image_bw {
276280
b1display_bw_image_cmd(serialdev, image_path);
277281
}
@@ -860,6 +864,28 @@ fn set_power_mode(port: &mut Box<dyn SerialPort>, mode: PowerMode) {
860864
}
861865
}
862866

867+
fn animation_fps_cmd(serialdev: &str, arg: Option<u16>) {
868+
let mut port = serialport::new(serialdev, 115_200)
869+
.timeout(SERIAL_TIMEOUT)
870+
.open()
871+
.expect("Failed to open port");
872+
873+
if let Some(fps) = arg {
874+
let period = (1000 / fps).to_le_bytes();
875+
simple_cmd_port(&mut port, Command::AnimationPeriod, &[period[0], period[1]]);
876+
} else {
877+
simple_cmd_port(&mut port, Command::AnimationPeriod, &[]);
878+
879+
let mut response: Vec<u8> = vec![0; 32];
880+
port.read_exact(response.as_mut_slice())
881+
.expect("Found no data!");
882+
883+
println!("Response: {:X?}", response);
884+
let period = u16::from_le_bytes([response[0], response[1]]);
885+
println!("Animation Frequency: {}ms / {}Hz", period, 1_000 / period);
886+
}
887+
}
888+
863889
fn set_color_cmd(serialdev: &str, color: Color) {
864890
let args = match color {
865891
Color::White => &[0xFF, 0xFF, 0xFF],

0 commit comments

Comments
 (0)