tm1637_embedded_hal/
mappings.rs

1//! Mappings for 7-segment display characters.
2//!
3//! This module is only available when the `mappings` feature of this
4//! library is activated.
5
6//       A
7//      ---
8//  F  |   |  B
9//      -G-
10//  E  |   |  C
11//      ---
12//       D
13
14/// Maps the segment from the device to its bit.
15#[repr(u8)]
16#[derive(Clone, Copy)]
17#[cfg_attr(feature = "impl-defmt-format", derive(defmt::Format))]
18#[cfg_attr(feature = "impl-debug", derive(core::fmt::Debug))]
19pub enum SegmentBits {
20    /// A segment
21    SegA = 0b00000001,
22    /// B segment
23    SegB = 0b00000010,
24    /// C segment
25    SegC = 0b00000100,
26    /// D segment
27    SegD = 0b00001000,
28    /// E segment
29    SegE = 0b00010000,
30    /// F segment
31    SegF = 0b00100000,
32    /// G segment
33    SegG = 0b01000000,
34    /// Double point
35    ///
36    /// ## Usage
37    /// `Or` this bit with the bit responsible for displaying the double point. Often second position.
38    SegPoint = 0b10000000,
39}
40
41impl SegmentBits {
42    /// Returns all segments.
43    pub const fn all() -> [SegmentBits; 8] {
44        [
45            SegmentBits::SegA,
46            SegmentBits::SegB,
47            SegmentBits::SegC,
48            SegmentBits::SegD,
49            SegmentBits::SegE,
50            SegmentBits::SegF,
51            SegmentBits::SegG,
52            SegmentBits::SegPoint,
53        ]
54    }
55
56    /// Returns all segments as u8.
57    pub const fn all_u8() -> [u8; 8] {
58        [
59            SegmentBits::SegA as u8,
60            SegmentBits::SegB as u8,
61            SegmentBits::SegC as u8,
62            SegmentBits::SegD as u8,
63            SegmentBits::SegE as u8,
64            SegmentBits::SegF as u8,
65            SegmentBits::SegG as u8,
66            SegmentBits::SegPoint as u8,
67        ]
68    }
69}
70
71/// Maps a digit to its closest possible representation on a 7-segment display.
72#[repr(u8)]
73#[derive(Clone, Copy)]
74#[cfg_attr(feature = "impl-defmt-format", derive(defmt::Format))]
75#[cfg_attr(feature = "impl-debug", derive(core::fmt::Debug))]
76pub enum DigitBits {
77    /// 0
78    Zero = 0b00111111,
79    /// 1
80    One = 0b00000110,
81    /// 2
82    Two = 0b01011011,
83    /// 3
84    Three = 0b01001111,
85    /// 4
86    Four = 0b01100110,
87    /// 5
88    Five = 0b01101101,
89    /// 6
90    Six = 0b01111101,
91    /// 7
92    Seven = 0b00000111,
93    /// 8
94    Eight = 0b01111111,
95    /// 9
96    Nine = 0b01101111,
97}
98
99impl DigitBits {
100    /// Returns all digits.
101    pub const fn all() -> [DigitBits; 10] {
102        [
103            DigitBits::Zero,
104            DigitBits::One,
105            DigitBits::Two,
106            DigitBits::Three,
107            DigitBits::Four,
108            DigitBits::Five,
109            DigitBits::Six,
110            DigitBits::Seven,
111            DigitBits::Eight,
112            DigitBits::Nine,
113        ]
114    }
115
116    /// Returns all digits as [`u8`].
117    pub const fn all_u8() -> [u8; 10] {
118        [
119            DigitBits::Zero as u8,
120            DigitBits::One as u8,
121            DigitBits::Two as u8,
122            DigitBits::Three as u8,
123            DigitBits::Four as u8,
124            DigitBits::Five as u8,
125            DigitBits::Six as u8,
126            DigitBits::Seven as u8,
127            DigitBits::Eight as u8,
128            DigitBits::Nine as u8,
129        ]
130    }
131
132    /// Creates a new [`DigitBits`] from a [`u8`] digit.
133    pub fn from_digit(digit: u8) -> Self {
134        match digit {
135            0 => DigitBits::Zero,
136            1 => DigitBits::One,
137            2 => DigitBits::Two,
138            3 => DigitBits::Three,
139            4 => DigitBits::Four,
140            5 => DigitBits::Five,
141            6 => DigitBits::Six,
142            7 => DigitBits::Seven,
143            8 => DigitBits::Eight,
144            9 => DigitBits::Nine,
145            _ => DigitBits::Zero,
146        }
147    }
148}
149
150/// Maps a upside-down digit to its closest possible representation on a 7-segment display.
151#[repr(u8)]
152#[derive(Clone, Copy)]
153#[cfg_attr(feature = "impl-defmt-format", derive(defmt::Format))]
154#[cfg_attr(feature = "impl-debug", derive(core::fmt::Debug))]
155pub enum UpsideDownDigitBits {
156    /// Upside-down 0
157    Zero = 0b00111111,
158    /// Upside-down 1
159    One = 0b00110000,
160    /// Upside-down 2
161    Two = 0b01011011,
162    /// Upside-down 3
163    Three = 0b01111001,
164    /// Upside-down 4
165    Four = 0b01110100,
166    /// Upside-down 5
167    Five = 0b01101101,
168    /// Upside-down 6
169    Six = 0b01101111,
170    /// Upside-down 7
171    Seven = 0b00111000,
172    /// Upside-down 8
173    Eight = 0b01111111,
174    /// Upside-down 9
175    Nine = 0b01111101,
176}
177impl UpsideDownDigitBits {
178    /// Returns all digits.
179    pub const fn all() -> [UpsideDownDigitBits; 10] {
180        [
181            UpsideDownDigitBits::Zero,
182            UpsideDownDigitBits::One,
183            UpsideDownDigitBits::Two,
184            UpsideDownDigitBits::Three,
185            UpsideDownDigitBits::Four,
186            UpsideDownDigitBits::Five,
187            UpsideDownDigitBits::Six,
188            UpsideDownDigitBits::Seven,
189            UpsideDownDigitBits::Eight,
190            UpsideDownDigitBits::Nine,
191        ]
192    }
193
194    /// Returns all digits as [`u8`].
195    pub const fn all_u8() -> [u8; 10] {
196        [
197            UpsideDownDigitBits::Zero as u8,
198            UpsideDownDigitBits::One as u8,
199            UpsideDownDigitBits::Two as u8,
200            UpsideDownDigitBits::Three as u8,
201            UpsideDownDigitBits::Four as u8,
202            UpsideDownDigitBits::Five as u8,
203            UpsideDownDigitBits::Six as u8,
204            UpsideDownDigitBits::Seven as u8,
205            UpsideDownDigitBits::Eight as u8,
206            UpsideDownDigitBits::Nine as u8,
207        ]
208    }
209
210    /// Creates a new [`DigitBits`] from a [`u8`] digit.
211    pub fn from_digit(digit: u8) -> Self {
212        match digit {
213            0 => UpsideDownDigitBits::Zero,
214            1 => UpsideDownDigitBits::One,
215            2 => UpsideDownDigitBits::Two,
216            3 => UpsideDownDigitBits::Three,
217            4 => UpsideDownDigitBits::Four,
218            5 => UpsideDownDigitBits::Five,
219            6 => UpsideDownDigitBits::Six,
220            7 => UpsideDownDigitBits::Seven,
221            8 => UpsideDownDigitBits::Eight,
222            9 => UpsideDownDigitBits::Nine,
223            _ => UpsideDownDigitBits::Zero,
224        }
225    }
226}
227
228/// Maps a character to its closest possible representation on a 7-segment display.
229#[repr(u8)]
230#[derive(Clone, Copy)]
231#[cfg_attr(feature = "impl-defmt-format", derive(defmt::Format))]
232#[cfg_attr(feature = "impl-debug", derive(core::fmt::Debug))]
233pub enum UpCharBits {
234    /// Uppercase A
235    UpA = 0x77,
236    /// Uppercase B
237    UpB = 0x7F,
238    /// Uppercase C
239    UpC = 0x39,
240    /// Uppercase E
241    UpE = 0x79,
242    // can be also done like this (OR'ing segment bits) :
243    /// Uppercase F
244    UpF = SegmentBits::SegA as u8
245        | SegmentBits::SegF as u8
246        | SegmentBits::SegE as u8
247        | SegmentBits::SegG as u8,
248    /// Uppercase G
249    UpG = 0x3D,
250    /// Uppercase H
251    UpH = 0x76,
252    /// Uppercase I
253    UpI = 0x30,
254    /// Uppercase J
255    UpJ = 0x1E,
256    /// Uppercase L
257    UpL = 0x38,
258    /// Uppercase O
259    UpO = 0x3F,
260    /// Uppercase P
261    UpP = 0x73,
262    /// Uppercase S
263    UpS = 0x6D,
264    /// Uppercase U
265    UpU = 0x3E,
266    /// Uppercase Z
267    UpZ = 0x5B,
268}
269
270impl UpCharBits {
271    /// Returns all uppercase characters.
272    pub const fn all() -> [UpCharBits; 15] {
273        [
274            UpCharBits::UpA,
275            UpCharBits::UpB,
276            UpCharBits::UpC,
277            UpCharBits::UpE,
278            UpCharBits::UpF,
279            UpCharBits::UpG,
280            UpCharBits::UpH,
281            UpCharBits::UpI,
282            UpCharBits::UpJ,
283            UpCharBits::UpL,
284            UpCharBits::UpO,
285            UpCharBits::UpP,
286            UpCharBits::UpS,
287            UpCharBits::UpU,
288            UpCharBits::UpZ,
289        ]
290    }
291
292    /// Returns all uppercase characters as [`u8`].
293    pub const fn all_u8() -> [u8; 15] {
294        [
295            UpCharBits::UpA as u8,
296            UpCharBits::UpB as u8,
297            UpCharBits::UpC as u8,
298            UpCharBits::UpE as u8,
299            UpCharBits::UpF as u8,
300            UpCharBits::UpG as u8,
301            UpCharBits::UpH as u8,
302            UpCharBits::UpI as u8,
303            UpCharBits::UpJ as u8,
304            UpCharBits::UpL as u8,
305            UpCharBits::UpO as u8,
306            UpCharBits::UpP as u8,
307            UpCharBits::UpS as u8,
308            UpCharBits::UpU as u8,
309            UpCharBits::UpZ as u8,
310        ]
311    }
312}
313
314/// Maps a character to its closest possible representation on a 7-segment display.
315#[repr(u8)]
316#[derive(Clone, Copy)]
317#[cfg_attr(feature = "impl-defmt-format", derive(defmt::Format))]
318#[cfg_attr(feature = "impl-debug", derive(core::fmt::Debug))]
319pub enum LoCharBits {
320    /// Lowercase A
321    LoA = 0x5F,
322    /// Lowercase B
323    LoB = 0x7C,
324    /// Lowercase C
325    LoC = 0x58,
326    /// Lowercase D
327    LoD = 0x5E,
328    /// Lowercase e
329    LoE = 0x7B,
330    /// Lowercase G
331    LoG = 0x6F,
332    /// Lowercase H
333    LoH = 0x74,
334    /// Lowercase I
335    LoI = 0x10,
336    /// Lowercase N
337    LoN = 0x54,
338    /// Lowercase O
339    LoO = 0x5C,
340    /// Lowercase Q
341    LoQ = 0x67,
342    /// Lowercase R
343    LoR = 0x50,
344    /// Lowercase T
345    LoT = 0x78,
346    /// Lowercase U
347    LoU = 0x1C,
348    /// Lowercase Y
349    LoY = 0x6E,
350}
351
352impl LoCharBits {
353    /// Returns all lowercase characters.
354    pub const fn all() -> [LoCharBits; 15] {
355        [
356            LoCharBits::LoA,
357            LoCharBits::LoB,
358            LoCharBits::LoC,
359            LoCharBits::LoD,
360            LoCharBits::LoE,
361            LoCharBits::LoG,
362            LoCharBits::LoH,
363            LoCharBits::LoI,
364            LoCharBits::LoN,
365            LoCharBits::LoO,
366            LoCharBits::LoQ,
367            LoCharBits::LoR,
368            LoCharBits::LoT,
369            LoCharBits::LoU,
370            LoCharBits::LoY,
371        ]
372    }
373
374    /// Returns all lowercase characters as [`u8`].
375    pub const fn all_u8() -> [u8; 15] {
376        [
377            LoCharBits::LoA as u8,
378            LoCharBits::LoB as u8,
379            LoCharBits::LoC as u8,
380            LoCharBits::LoD as u8,
381            LoCharBits::LoE as u8,
382            LoCharBits::LoG as u8,
383            LoCharBits::LoH as u8,
384            LoCharBits::LoI as u8,
385            LoCharBits::LoN as u8,
386            LoCharBits::LoO as u8,
387            LoCharBits::LoQ as u8,
388            LoCharBits::LoR as u8,
389            LoCharBits::LoT as u8,
390            LoCharBits::LoU as u8,
391            LoCharBits::LoY as u8,
392        ]
393    }
394}
395
396/// Maps a character to its closest possible representation on a 7-segment display.
397#[repr(u8)]
398#[derive(Clone, Copy)]
399#[cfg_attr(feature = "impl-defmt-format", derive(defmt::Format))]
400#[cfg_attr(feature = "impl-debug", derive(core::fmt::Debug))]
401pub enum SpecialCharBits {
402    /// Space symbol
403    Space = 0,
404    /// Minus or dash symbol
405    Minus = SegmentBits::SegG as u8,
406    /// Underscore (_)
407    Underscore = SegmentBits::SegD as u8,
408    /// Equal sign (=)
409    Equals = SegmentBits::SegG as u8 | SegmentBits::SegD as u8,
410    /// Question mark (?)
411    QuestionMark = SegmentBits::SegA as u8
412        | SegmentBits::SegB as u8
413        | SegmentBits::SegG as u8
414        | SegmentBits::SegE as u8,
415}
416
417impl SpecialCharBits {
418    /// Returns all special characters.
419    pub const fn all() -> [SpecialCharBits; 5] {
420        [
421            SpecialCharBits::Space,
422            SpecialCharBits::Minus,
423            SpecialCharBits::Underscore,
424            SpecialCharBits::Equals,
425            SpecialCharBits::QuestionMark,
426        ]
427    }
428
429    /// Returns all special characters as [`u8`].
430    pub const fn all_u8() -> [u8; 5] {
431        [
432            SpecialCharBits::Space as u8,
433            SpecialCharBits::Minus as u8,
434            SpecialCharBits::Underscore as u8,
435            SpecialCharBits::Equals as u8,
436            SpecialCharBits::QuestionMark as u8,
437        ]
438    }
439}
440
441/// Flips the segments of a byte upside down.
442///
443/// Swaps the segments:
444/// - A and D
445/// - B and C
446/// - E and F
447pub const fn flip(byte: u8) -> u8 {
448    let a_d_swapped = ((byte & 0b00001000) >> 3) | ((byte & 0b00000001) << 3);
449    let b_c_swapped = ((byte & 0b00000100) >> 1) | ((byte & 0b00000010) << 1);
450    let e_f_swapped = ((byte & 0b00100000) >> 1) | ((byte & 0b00010000) << 1);
451
452    (byte & 0b11000000) | a_d_swapped | b_c_swapped | e_f_swapped
453}
454
455/// Mirrors the segments of a byte.
456///
457/// Swaps the segments:
458/// - B and F
459/// - C and E
460pub const fn mirror(byte: u8) -> u8 {
461    let b_f_swapped = ((byte & 0b00100000) >> 4) | ((byte & 0b00000010) << 4);
462    let c_e_swapped = ((byte & 0b00010000) >> 2) | ((byte & 0b00000100) << 2);
463
464    (byte & 0b11001001) | b_f_swapped | c_e_swapped
465}
466
467/// Flips and mirrors the segments of a byte.
468///
469/// See [`flip`] and [`mirror`] for more information.
470pub const fn flip_mirror(byte: u8) -> u8 {
471    mirror(flip(byte))
472}
473
474/// Converts an `ASCII` byte to a 7-segment display byte.
475///
476/// Unknown characters are converted to `0` (all segments off).
477///
478/// # Note
479///
480/// Rust strings are `UTF-8` encoded, so what you see as a single character may be multiple bytes.
481///
482/// # Example
483///
484/// Display `Err` text on a 4-digit display:
485///
486/// ```rust,ignore
487/// let err = "Err".as_bytes().iter().copied().map(from_ascii_byte);
488/// tm.write_segments_raw_iter(0, err).ok();
489/// ```
490pub const fn from_ascii_byte(byte: u8) -> u8 {
491    match byte {
492        b'0' => DigitBits::Zero as u8,
493        b'1' => DigitBits::One as u8,
494        b'2' => DigitBits::Two as u8,
495        b'3' => DigitBits::Three as u8,
496        b'4' => DigitBits::Four as u8,
497        b'5' => DigitBits::Five as u8,
498        b'6' => DigitBits::Six as u8,
499        b'7' => DigitBits::Seven as u8,
500        b'8' => DigitBits::Eight as u8,
501        b'9' => DigitBits::Nine as u8,
502
503        b'A' => UpCharBits::UpA as u8,
504        b'B' => UpCharBits::UpB as u8,
505        b'C' => UpCharBits::UpC as u8,
506        b'E' => UpCharBits::UpE as u8,
507        b'F' => UpCharBits::UpF as u8,
508        b'G' => UpCharBits::UpG as u8,
509        b'H' => UpCharBits::UpH as u8,
510        b'I' => UpCharBits::UpI as u8,
511        b'J' => UpCharBits::UpJ as u8,
512        b'L' => UpCharBits::UpL as u8,
513        b'O' => UpCharBits::UpO as u8,
514        b'P' => UpCharBits::UpP as u8,
515        b'S' => UpCharBits::UpS as u8,
516        b'U' => UpCharBits::UpU as u8,
517        b'Z' => UpCharBits::UpZ as u8,
518
519        b'a' => LoCharBits::LoA as u8,
520        b'b' => LoCharBits::LoB as u8,
521        b'c' => LoCharBits::LoC as u8,
522        b'd' => LoCharBits::LoD as u8,
523        b'e' => LoCharBits::LoE as u8,
524        b'g' => LoCharBits::LoG as u8,
525        b'h' => LoCharBits::LoH as u8,
526        b'i' => LoCharBits::LoI as u8,
527        b'n' => LoCharBits::LoN as u8,
528        b'o' => LoCharBits::LoO as u8,
529        b'q' => LoCharBits::LoQ as u8,
530        b'r' => LoCharBits::LoR as u8,
531        b't' => LoCharBits::LoT as u8,
532        b'u' => LoCharBits::LoU as u8,
533        b'y' => LoCharBits::LoY as u8,
534
535        b' ' => SpecialCharBits::Space as u8,
536        b'-' => SpecialCharBits::Minus as u8,
537        b'_' => SpecialCharBits::Underscore as u8,
538        b'=' => SpecialCharBits::Equals as u8,
539        b'?' => SpecialCharBits::QuestionMark as u8,
540
541        _ => 0,
542    }
543}
544
545/// Converts a `char` to a 7-segment display byte. See [`from_ascii_byte`] for more information.
546pub const fn from_char(c: char) -> u8 {
547    from_ascii_byte(c as u8)
548}
549
550#[cfg(test)]
551mod tests {
552    use super::*;
553
554    #[test]
555    fn flipped_four() {
556        let four = DigitBits::Four as u8;
557        let flipped_four = flip(four);
558        let should_flipped_four = SegmentBits::SegB as u8
559            | SegmentBits::SegC as u8
560            | SegmentBits::SegE as u8
561            | SegmentBits::SegG as u8;
562
563        assert_eq!(flipped_four, should_flipped_four);
564    }
565
566    #[test]
567    fn flipped_e() {
568        let e = UpCharBits::UpE as u8;
569        let flipped_e = flip(e);
570        let should_flipped_e = UpCharBits::UpE as u8;
571
572        assert_eq!(flipped_e, should_flipped_e);
573    }
574
575    #[test]
576    fn mirrored_four() {
577        let four = DigitBits::Four as u8;
578        let mirrored_four = mirror(four);
579        let should_mirrored_four = SegmentBits::SegB as u8
580            | SegmentBits::SegE as u8
581            | SegmentBits::SegF as u8
582            | SegmentBits::SegG as u8;
583
584        assert_eq!(mirrored_four, should_mirrored_four);
585    }
586
587    #[test]
588    fn mirrored_e() {
589        let e = UpCharBits::UpE as u8;
590        let mirrored_e = mirror(e);
591        let should_mirrored_e = SegmentBits::SegA as u8
592            | SegmentBits::SegB as u8
593            | SegmentBits::SegC as u8
594            | SegmentBits::SegD as u8
595            | SegmentBits::SegG as u8;
596
597        assert_eq!(mirrored_e, should_mirrored_e);
598    }
599
600    #[test]
601    fn flipped_mirrored_four() {
602        let four = DigitBits::Four as u8;
603        let flipped_mirrored_four = flip_mirror(four);
604        let should_flipped_mirrored_four = SegmentBits::SegC as u8
605            | SegmentBits::SegE as u8
606            | SegmentBits::SegF as u8
607            | SegmentBits::SegG as u8;
608
609        assert_eq!(flipped_mirrored_four, should_flipped_mirrored_four);
610    }
611
612    #[test]
613    fn mirrored_flipped_is_flipped_mirrored() {
614        let four = DigitBits::Four as u8;
615
616        let mirrored_flipped_four = mirror(flip(four));
617        let flipped_mirrored_four = flip(mirror(four));
618
619        assert_eq!(mirrored_flipped_four, flipped_mirrored_four);
620    }
621
622    #[test]
623    fn flipped_flipped_is_original() {
624        let seven = DigitBits::Seven as u8;
625
626        let flipped_flipped_seven = flip(flip(seven));
627
628        assert_eq!(seven, flipped_flipped_seven);
629    }
630
631    #[test]
632    fn mirrored_mirrored_is_original() {
633        let five = DigitBits::Five as u8;
634
635        let mirrored_mirrored_five = mirror(mirror(five));
636
637        assert_eq!(five, mirrored_mirrored_five);
638    }
639}