diff --git a/examples/esp32/blocking/Cargo.lock b/examples/esp32/blocking/Cargo.lock index 9ee424e..fa4ab0c 100644 --- a/examples/esp32/blocking/Cargo.lock +++ b/examples/esp32/blocking/Cargo.lock @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "tm1637-embedded-hal" -version = "0.1.0" +version = "0.3.0" dependencies = [ "duplicate", "embedded-hal 1.0.0", diff --git a/tm1637/Cargo.toml b/tm1637/Cargo.toml index d4c425a..1292ddc 100644 --- a/tm1637/Cargo.toml +++ b/tm1637/Cargo.toml @@ -10,12 +10,7 @@ keywords = ["tm1637", "embedded-hal", "no-std", "embedded"] readme = "../README.md" [features] -default = [ - "async", - "impl-debug", - "mappings", - "formatters", -] # TODO remove mappings, formatters before release +default = ["async", "impl-debug"] async = ["dep:embedded-hal", "dep:embedded-hal-async"] blocking = ["dep:embedded-hal"] mappings = [] diff --git a/tm1637/src/device.rs b/tm1637/src/device.rs index af71bb1..f5fe4f1 100644 --- a/tm1637/src/device.rs +++ b/tm1637/src/device.rs @@ -240,7 +240,7 @@ pub mod module { /// Write the given bytes to the display starting from the given position. /// - /// ## Notes: + /// # Notes: /// - Positions greater than [`TM1637::num_positions`] will be ignored. /// - Bytes with index greater than [`TM1637::num_positions`] will be ignored. /// @@ -279,6 +279,38 @@ pub mod module { self.brightness = brightness; self.write_cmd_raw(brightness as u8).await } + + /// Move all segments across the display starting and ending at `position`. + /// + /// If the length of the bytes is less than or equal to [`TM1637::num_positions`] - `position`, the bytes will only be written to the display. + /// + /// `N` is the size of the internal window used to move the segments. Please make sure that `N` is equal to [`TM1637::num_positions`]. + /// [`TM1637::num_positions`] will be removed in the future in favor of a constant generic parameter representing the number of positions. + pub async fn move_segments_raw( + &mut self, + position: u8, + bytes: &[u8], + delay_ms: u32, + ) -> Result<(), ERR> { + let num_positions = self.num_positions as usize; + + if bytes.len() <= num_positions - position as usize { + return self.write_segments_raw(position, bytes).await; + } + + for i in 0..=bytes.len() { + let mut window = [0u8; N]; + for j in 0..num_positions { + window[j] = bytes[(i + j) % bytes.len()]; + } + + tri!(self.write_segments_raw(position, &window).await); + + self.delay.delay_ms(delay_ms).await; + } + + Ok(()) + } } } diff --git a/tm1637/src/mappings.rs b/tm1637/src/mappings.rs index bf1ed98..e65ee0a 100644 --- a/tm1637/src/mappings.rs +++ b/tm1637/src/mappings.rs @@ -471,6 +471,82 @@ pub const fn flip_mirror(byte: u8) -> u8 { mirror(flip(byte)) } +/// Converts an `ASCII` byte to a 7-segment display byte. +/// +/// Unknown characters are converted to `0` (all segments off). +/// +/// # Note +/// +/// Rust strings are `UTF-8` encoded, so what you see as a single character may be multiple bytes. +/// +/// # Example +/// +/// Display `Err` text on a 4-digit display: +/// +/// ```rust,ignore +/// let err = "Err".as_bytes().iter().copied().map(from_ascii_byte); +/// tm.write_segments_raw_iter(0, err).ok(); +/// ``` +pub const fn from_ascii_byte(byte: u8) -> u8 { + match byte { + b'0' => DigitBits::Zero as u8, + b'1' => DigitBits::One as u8, + b'2' => DigitBits::Two as u8, + b'3' => DigitBits::Three as u8, + b'4' => DigitBits::Four as u8, + b'5' => DigitBits::Five as u8, + b'6' => DigitBits::Six as u8, + b'7' => DigitBits::Seven as u8, + b'8' => DigitBits::Eight as u8, + b'9' => DigitBits::Nine as u8, + + b'A' => UpCharBits::UpA as u8, + b'B' => UpCharBits::UpB as u8, + b'C' => UpCharBits::UpC as u8, + b'E' => UpCharBits::UpE as u8, + b'F' => UpCharBits::UpF as u8, + b'G' => UpCharBits::UpG as u8, + b'H' => UpCharBits::UpH as u8, + b'I' => UpCharBits::UpI as u8, + b'J' => UpCharBits::UpJ as u8, + b'L' => UpCharBits::UpL as u8, + b'O' => UpCharBits::UpO as u8, + b'P' => UpCharBits::UpP as u8, + b'S' => UpCharBits::UpS as u8, + b'U' => UpCharBits::UpU as u8, + b'Z' => UpCharBits::UpZ as u8, + + b'a' => LoCharBits::LoA as u8, + b'b' => LoCharBits::LoB as u8, + b'c' => LoCharBits::LoC as u8, + b'd' => LoCharBits::LoD as u8, + b'e' => LoCharBits::LoE as u8, + b'g' => LoCharBits::LoG as u8, + b'h' => LoCharBits::LoH as u8, + b'i' => LoCharBits::LoI as u8, + b'n' => LoCharBits::LoN as u8, + b'o' => LoCharBits::LoO as u8, + b'q' => LoCharBits::LoQ as u8, + b'r' => LoCharBits::LoR as u8, + b't' => LoCharBits::LoT as u8, + b'u' => LoCharBits::LoU as u8, + b'y' => LoCharBits::LoY as u8, + + b' ' => SpecialCharBits::Space as u8, + b'-' => SpecialCharBits::Minus as u8, + b'_' => SpecialCharBits::Underscore as u8, + b'=' => SpecialCharBits::Equals as u8, + b'?' => SpecialCharBits::QuestionMark as u8, + + _ => 0, + } +} + +/// Converts a `char` to a 7-segment display byte. See [`from_ascii_byte`] for more information. +pub const fn from_char(c: char) -> u8 { + from_ascii_byte(c as u8) +} + #[cfg(test)] mod tests { use super::*;