Skip to content

Commit a9b38fb

Browse files
committed
feat: add support for brightness control
1 parent 5d745ab commit a9b38fb

File tree

2 files changed

+65
-12
lines changed

2 files changed

+65
-12
lines changed

src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{fs, path::PathBuf};
66
use anyhow::{Context, Result};
77
use badgemagic::{
88
ble::Device as BleDevice,
9-
protocol::{Mode, PayloadBuffer, Speed, Style},
9+
protocol::{Brightness, Mode, PayloadBuffer, Speed, Style},
1010
usb_hid::Device as UsbDevice,
1111
};
1212
use base64::Engine;
@@ -63,6 +63,8 @@ enum TransportProtocol {
6363
#[derive(Deserialize)]
6464
#[serde(deny_unknown_fields)]
6565
struct Config {
66+
#[serde(default)]
67+
brightness: Option<Brightness>,
6668
#[serde(rename = "message")]
6769
messages: Vec<Message>,
6870
}
@@ -148,6 +150,7 @@ fn gnerate_payload(args: &mut Args) -> Result<PayloadBuffer> {
148150
};
149151

150152
let mut payload = PayloadBuffer::new();
153+
payload.set_brightness(config.brightness.unwrap_or_default());
151154

152155
for message in config.messages {
153156
let mut style = Style::default();

src/protocol.rs

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Protocol used to update the badge
22
3-
use std::num::TryFromIntError;
4-
53
#[cfg(feature = "embedded-graphics")]
64
use embedded_graphics::{
75
draw_target::DrawTarget,
@@ -11,6 +9,7 @@ use embedded_graphics::{
119
primitives::Rectangle,
1210
Drawable,
1311
};
12+
use std::num::TryFromIntError;
1413
use time::OffsetDateTime;
1514
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, U16};
1615

@@ -54,7 +53,7 @@ impl Style {
5453
self
5554
}
5655

57-
/// Show a dotted border arround the display.
56+
/// Show a dotted border around the display.
5857
/// ```
5958
/// use badgemagic::protocol::Style;
6059
/// # (
@@ -161,7 +160,7 @@ impl TryFrom<u8> for Speed {
161160
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162161
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
163162
pub enum Mode {
164-
/// Scroll thorugh the message from left to right
163+
/// Scroll through the message from left to right
165164
#[default]
166165
Left,
167166

@@ -193,14 +192,47 @@ pub enum Mode {
193192
Laser,
194193
}
195194

195+
/// Display Brightness
196+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
197+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
198+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
199+
pub enum Brightness {
200+
#[default]
201+
Full = 0x00,
202+
ThreeQuarters = 0x10,
203+
Half = 0x20,
204+
OneQuarter = 0x30,
205+
}
206+
207+
impl From<Brightness> for u8 {
208+
fn from(value: Brightness) -> Self {
209+
value as u8
210+
}
211+
}
212+
213+
impl TryFrom<u8> for Brightness {
214+
type Error = TryFromIntError;
215+
216+
fn try_from(value: u8) -> Result<Self, Self::Error> {
217+
Ok(match value {
218+
0x00 => Self::Full,
219+
0x10 => Self::ThreeQuarters,
220+
0x20 => Self::Half,
221+
0x30 => Self::OneQuarter,
222+
_ => return Err(u8::try_from(-1).unwrap_err()),
223+
})
224+
}
225+
}
226+
196227
const MSG_PADDING_ALIGN: usize = 64;
197228

198-
const MAGIC: [u8; 6] = *b"wang\0\0";
229+
const MAGIC: [u8; 5] = *b"wang\0";
199230

200231
#[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
201232
#[repr(C)]
202233
struct Header {
203-
magic: [u8; 6],
234+
magic: [u8; 5],
235+
brightness: u8,
204236
blink: u8,
205237
border: u8,
206238
speed_and_mode: [u8; 8],
@@ -241,7 +273,7 @@ impl Timestamp {
241273

242274
/// Buffer to create a payload
243275
///
244-
/// A payload consits of up to 8 messages
276+
/// A payload consists of up to 8 messages
245277
/// ```
246278
/// # #[cfg(feature = "embedded-graphics")]
247279
/// # fn main() {
@@ -252,7 +284,7 @@ impl Timestamp {
252284
/// primitives::{PrimitiveStyle, Rectangle, Styled},
253285
/// };
254286
///
255-
/// let mut buffer = PayloadBuffer::new();
287+
/// let mut buffer = PayloadBuffer::default();
256288
/// buffer.add_message_drawable(
257289
/// Style::default(),
258290
/// &Styled::new(
@@ -283,6 +315,7 @@ impl PayloadBuffer {
283315
num_messages: 0,
284316
data: Header {
285317
magic: MAGIC,
318+
brightness: 0,
286319
blink: 0,
287320
border: 0,
288321
speed_and_mode: [0; 8],
@@ -300,6 +333,10 @@ impl PayloadBuffer {
300333
Header::mut_from_prefix(&mut self.data).unwrap().0
301334
}
302335

336+
pub fn set_brightness(&mut self, brightness: Brightness) {
337+
self.header_mut().brightness = brightness.into();
338+
}
339+
303340
/// Return the current number of messages
304341
pub fn num_messages(&mut self) -> usize {
305342
self.num_messages as usize
@@ -368,7 +405,7 @@ impl PayloadBuffer {
368405
&self.data
369406
}
370407

371-
/// Convert the payload buffe into bytes (with padding)
408+
/// Convert the payload buffer into bytes (with padding)
372409
#[allow(clippy::missing_panics_doc)] // should never panic
373410
#[must_use]
374411
pub fn into_padded_bytes(self) -> impl AsRef<[u8]> {
@@ -484,10 +521,9 @@ impl DrawTarget for MessageBuffer<'_> {
484521

485522
#[cfg(test)]
486523
mod test {
524+
use super::{Brightness, Speed};
487525
use std::ops::Range;
488526

489-
use super::Speed;
490-
491527
#[test]
492528
fn speed_to_u8_and_back() {
493529
const VALID_SPEED_VALUES: Range<u8> = 1..8;
@@ -499,4 +535,18 @@ mod test {
499535
}
500536
}
501537
}
538+
539+
#[test]
540+
fn brightness_to_u8() {
541+
const VALID_BRIGHTNESS_VALUES: [(Brightness, u8); 4] = [
542+
(Brightness::Full, 0x00),
543+
(Brightness::ThreeQuarters, 0x10),
544+
(Brightness::Half, 0x20),
545+
(Brightness::OneQuarter, 0x30),
546+
];
547+
548+
for (value, raw) in VALID_BRIGHTNESS_VALUES {
549+
assert_eq!(u8::from(value), raw);
550+
}
551+
}
502552
}

0 commit comments

Comments
 (0)