max7219_driver/
lib.rs

1//! This crate provides a platform agnostic driver for the MAX7219 LED Driver IC.
2//!
3//! This driver was built using the [embedded-hal](https://docs.rs/embedded-hal/0.2.7/embedded_hal/) traits.
4//!
5//! ## Usage
6//!
7//! An updated version of the library should be available on crates.io. Add the following to your Cargo.toml to get is a dependency.
8//! ```rust
9//! [dependencies]
10//! max7219-driver = "*"
11//! ```
12//!
13//! ### Instantiating
14//!
15//! Create an instance of the driver with the `new` method, by passing SPI and Output pin instances.
16//! ```rust
17//! use max7219-driver::MAX7219;
18//! let spi = // SPI instantiation code
19//! let cs = // Output pin instantiation code
20//! let mut max7219 = MAX7219::new(spi, cs).unwrap();
21//! ```
22//!
23//! ### Initializing
24//!
25//! Initialize the driver instance with the `init_display` method. A boolean needs to be specified to indicate whether to clear the display after init or not.
26//! ```rust
27//!  max7219.init_display(true);
28//! ```
29//!
30//! ## Cascading Multiple MAX7219 Devices
31//!
32//! If you are cascading multiple devices that are driving 8x8 LED Dot Matrices instead use the `MAX7219LedMat` driver as follows:
33//!
34//! ### Instantiating
35//!
36//! ```rust
37//! use max7219-driver::MAX7219LedMat;
38//! let spi = // SPI instantiation code
39//! let cs = // Output pin instantiation code
40//! let mut max7219: MAX7219LedMat<_, _, BUFLEN, COUNT> = MAX7219LedMat::new(spi, cs).unwrap();
41//! ```
42//!
43//! `BUFLEN` should be replaced with value equivalent to the total number of pixels/LED in the cascaded displays
44//! and `COUNT` with the number of displays
45//!
46//! Example:
47//!
48//! If four displays are cascaded then `BUFLEN` should be replaced with 256 (= 8 x 8 x 4) and `COUNT` replaced with 4 resulting in
49//!
50//! ```rust
51//! let mut max7219: MAX7219LedMat<_, _, 256, 4> = MAX7219LedMat::new(spi, cs).unwrap();
52//! ```
53//!
54//! ### Initializing
55//!
56//! Exactly the same as earlier, the new driver takes care of initializing all the cscaded displays.
57//!
58//! ```rust
59//!  max7219.init_display(true);
60//! ```
61
62#![no_std]
63
64use embedded_graphics::pixelcolor::BinaryColor;
65use embedded_hal as hal;
66
67use embedded_graphics::prelude::*;
68
69use num_enum::TryFromPrimitive;
70
71use hal::blocking::spi::Write;
72use hal::digital::v2::OutputPin;
73use hal::spi::{Mode, Phase, Polarity};
74
75/// This is a constant for convenience so that the SPI module can be configured with the correct SPI mode compatible the MAX7219 device
76pub const MODE: Mode = Mode {
77    phase: Phase::CaptureOnFirstTransition,
78    polarity: Polarity::IdleLow,
79};
80
81/// The MAX7219 Driver that initializes and communicates with a single MAX7219 IC or chain of ICs.
82/// This driver usage is specific to connecting the 8x8 LED Dot Matrix
83pub struct MAX7219LedMat<SPI, CS, const BUFLEN: usize, const COUNT: usize> {
84    spi: SPI,
85    cs: CS,
86    framebuffer: [u8; BUFLEN],
87}
88
89impl<SPI, CS, const BUFLEN: usize, const COUNT: usize> MAX7219LedMat<SPI, CS, BUFLEN, COUNT>
90where
91    SPI: Write<u8>,
92    CS: OutputPin,
93{
94    ///
95    /// Constructor method. Creates a new instance of the MAX7219 driver.
96    ///
97    /// # Arguments
98    ///
99    /// * `spi` - a SPI peripheral instance
100    /// * `cs` - a OutputPin instance
101    ///
102    /// # Errors
103    ///
104    /// * `DriverError` - returned if there is an error during transfer or addressing device
105    ///
106    pub fn new(spi: SPI, cs: CS) -> Result<Self, DriverError> {
107        let max7219 = MAX7219LedMat::<SPI, CS, BUFLEN, COUNT> {
108            spi: spi,
109            cs: cs,
110            framebuffer: [0; BUFLEN],
111        };
112        Ok(max7219)
113    }
114
115    /// Method to flush framebuffer to display. This method needs to be called everytime a new framebuffer is created,
116    /// otherwise the frame will not appear on the screen.
117    ///     
118    /// # Arguments
119    ///
120    /// * None
121    ///
122    /// # Errors
123    ///
124    /// * `DriverError` - returned if there is an error during transfer or addressing device
125    ///
126    pub fn flush(&mut self) -> Result<(), DriverError> {
127        // Iterate over all row addresses
128        for addr in 0..8 {
129            // Prepare Device to accept data
130            self.cs.set_low().map_err(|_| DriverError::PinError)?;
131
132            // Send frame data for each Display
133            for disp in (0..COUNT).rev() {
134                let base = ((disp + addr) * COUNT) * 8;
135                let arr = &self.framebuffer[base..base + 8];
136                // Convert each row in the framebuffer to a decimal num
137                let mut res: u8 = 0;
138                for i in 0..arr.len() {
139                    res |= arr[i] << arr.len() - 1 - i;
140                }
141                self.spi
142                    .write(&[addr as u8 + 1, res])
143                    .map_err(|_| DriverError::SpiError)?;
144            }
145
146            // Latch Data Sent to Device(s)
147            self.cs.set_high().map_err(|_| DriverError::PinError)?;
148        }
149        Ok(())
150    }
151
152    ///
153    /// Transmits raw data to the MAX7219 IC.
154    ///
155    /// # Arguments
156    ///
157    /// * `arr` - slice of data that needs to be transmitted
158    ///
159    /// # Errors
160    ///
161    /// * `DriverError` - returned if there is an error during transfer or addressing device
162    ///
163    pub fn transmit_raw_data(&mut self, arr: &[u8]) -> Result<(), DriverError> {
164        self.cs.set_low().map_err(|_| DriverError::PinError)?;
165        let transfer = self.spi.write(&arr).map_err(|_| DriverError::SpiError);
166        self.cs.set_high().map_err(|_| DriverError::PinError)?;
167        transfer
168    }
169
170    ///
171    /// Configures the power mode of the MAX7219 IC.
172    ///
173    /// # Arguments
174    ///
175    /// * `mode` - one of the options in the `Shutdown` enum
176    ///
177    pub fn config_power_mode(&mut self, mode: Shutdown) -> () {
178        let data: u8 = match mode {
179            Shutdown::NormalOperation => 0x01,
180            Shutdown::ShutDownMode => 0x00,
181        };
182
183        let send_array: [u8; 2] = [Command::Shutdown as u8, data];
184        // Transmit Data
185        self.transmit_raw_data(&send_array).unwrap();
186    }
187
188    ///
189    /// Configures the decode mode on the input sent to the MAX7219 IC.
190    ///
191    /// # Arguments
192    ///
193    /// * `mode` - one of the options in the `DecodeMode` enum
194    ///
195    pub fn config_decode_mode(&mut self, mode: DecodeMode) -> () {
196        // - Prepare Information to be Sent
197        // 8-bit Data/Command Corresponding to No Decode Mode
198        let data: u8 = match mode {
199            DecodeMode::NoDecode => 0x00,
200            DecodeMode::CodeB0 => 0x01,
201            DecodeMode::CodeB30 => 0x0F,
202            DecodeMode::CodeB70 => 0xFF,
203        };
204        // Package into array to pass to SPI write method
205        // Write method will grab array and send all data in it
206        let send_array: [u8; 2] = [Command::DecodeMode as u8, data];
207        // Transmit Data
208        self.transmit_raw_data(&send_array).unwrap();
209    }
210
211    ///
212    /// Configures the intensity of the LEDs on the display connected to the MAX7219 IC.
213    ///
214    /// # Arguments
215    ///
216    /// * `mode` - one of the options in the `Intensity` enum
217    ///
218    pub fn config_intensity(&mut self, mode: Intensity) -> () {
219        // - Prepare Information to be Sent
220        // 8-bit Data/Command Corresponding to No Decode Mode
221        let data: u8 = match mode {
222            Intensity::Min => 0x00,
223            Intensity::Ratio3_32 => 0x01,
224            Intensity::Ratio5_32 => 0x02,
225            Intensity::Ratio7_32 => 0x03,
226            Intensity::Ratio9_32 => 0x04,
227            Intensity::Ratio11_32 => 0x05,
228            Intensity::Ratio13_32 => 0x06,
229            Intensity::Ratio15_32 => 0x07,
230            Intensity::Ratio17_32 => 0x08,
231            Intensity::Ratio19_32 => 0x09,
232            Intensity::Ratio21_32 => 0x0A,
233            Intensity::Ratio23_32 => 0x0B,
234            Intensity::Ratio25_32 => 0x0C,
235            Intensity::Ratio27_32 => 0x0D,
236            Intensity::Ratio29_32 => 0x0E,
237            Intensity::Max => 0x0F,
238        };
239        // Package into array to pass to SPI write method
240        // Write method will grab array and send all data in it
241        let send_array: [u8; 2] = [Command::Intensity as u8, data];
242        // Transmit Data
243        self.transmit_raw_data(&send_array).unwrap();
244    }
245
246    ///
247    /// Configures the scanlimit for the MAX7219 IC.
248    /// Applicable mostly to seven segment displays if certain digits (ex. on the left)
249    /// need not to be shown.
250    ///
251    /// # Arguments
252    ///
253    /// * `mode` - one of the options in the `ScanLimit` enum
254    ///
255    pub fn config_scan_limit(&mut self, mode: ScanLimit) -> () {
256        // - Prepare Information to be Sent
257        // 8-bit Data/Command Corresponding to No Decode Mode
258        let data: u8 = match mode {
259            ScanLimit::Display0Only => 0x00,
260            ScanLimit::Display0And1 => 0x01,
261            ScanLimit::Display0To2 => 0x02,
262            ScanLimit::Display0To3 => 0x03,
263            ScanLimit::Display0To4 => 0x04,
264            ScanLimit::Display0To5 => 0x05,
265            ScanLimit::Display0To6 => 0x06,
266            ScanLimit::Display0To7 => 0x07,
267        };
268        // Package into array to pass to SPI write method
269        // Write method will grab array and send all data in it
270        let send_array: [u8; 2] = [Command::ScanLimit as u8, data];
271        // Transmit Data
272        self.transmit_raw_data(&send_array).unwrap();
273    }
274
275    ///
276    /// Method to perform a visual test of the display.
277    /// If performing a test, display needs to be put back in normal operation mode after done.
278    ///
279    /// # Arguments
280    ///
281    /// * `mode` - one of the options in the `DisplayTest` enum
282    ///
283    pub fn display_test(&mut self, mode: DisplayTest) -> () {
284        // - Prepare Information to be Sent
285        // 8-bit Data/Command Corresponding to No Decode Mode
286        let data: u8 = match mode {
287            DisplayTest::NormalOperationMode => 0x00,
288            DisplayTest::DisplayTestMode => 0x01,
289        };
290        // Package into array to pass to SPI write method
291        // Write method will grab array and send all data in it
292        let send_array: [u8; 2] = [Command::DisplayTest as u8, data];
293        // Transmit Data
294        self.transmit_raw_data(&send_array).unwrap();
295    }
296
297    ///
298    /// Method to draw a row if the MAX7219 is driving an 8x8 LED dot matrix display.
299    /// Alternatively method will draw a digit in case the MAX7219 is driving a seven-segment display
300    ///
301    /// # Arguments
302    ///
303    /// * `digit_addr` - one of the options in the `DigitRowAddress` enum
304    /// * `led_data` - the led row or seven segment digit activation data
305    ///
306    pub fn draw_row_or_digit(&mut self, digit_addr: DigitRowAddress, led_data: u8) -> () {
307        // Can do an exhaustive match of DigitRowAddress
308        // let addr: u8 = match digit_addr {
309        //     DigitRowAddress::Digit0 => 0x01,
310        //     DigitRowAddress::Digit1 => 0x02,
311        //     DigitRowAddress::Digit2 => 0x03,
312        //     DigitRowAddress::Digit3 => 0x04,
313        //     DigitRowAddress::Digit4 => 0x05,
314        //     DigitRowAddress::Digit5 => 0x06,
315        //     DigitRowAddress::Digit6 => 0x07,
316        //     DigitRowAddress::Digit7 => 0x08,
317        // };
318        // OR typecast DigitRowAddress passed through digit_addr as u8
319        let send_array: [u8; 2] = [digit_addr as u8, led_data];
320        self.transmit_raw_data(&send_array).unwrap();
321        ()
322    }
323
324    ///
325    /// Method to clear the display.
326    ///
327    pub fn clear_display(&mut self) -> () {
328        for i in 1..9 {
329            self.transmit_raw_data(&[i, 0]).unwrap();
330        }
331    }
332
333    ///
334    /// Method to initialize the MAX7219 and the connected display.
335    /// This method has to be called before doing any display operations otherwise the display will not operate properly.
336    /// The method provides an option to leave the display uncleared after initalization.
337    ///  
338    /// # Arguments
339    ///
340    /// * `clr_display` - Boolean that reflects whether the display should be cleared or not after init
341    ///
342    pub fn init_display(&mut self, clr_display: bool) -> () {
343        // 1.a) Power Up Device
344        self.config_power_mode(Shutdown::NormalOperation);
345        // 1.b) Set up Decode Mode
346        self.config_decode_mode(DecodeMode::NoDecode);
347        // 1.c) Configure Scan Limit
348        self.config_scan_limit(ScanLimit::Display0To7);
349        // 1.d) Configure Intensity
350        self.config_intensity(Intensity::Ratio15_32);
351        // 1.e) Optional Screen Clear on Init
352        if clr_display {
353            self.clear_display();
354        }
355    }
356}
357
358/// The MAX7219 Driver that initializes and communicates with a single MAX7219 IC.
359pub struct MAX7219<SPI, CS> {
360    spi: SPI,
361    cs: CS,
362}
363
364///
365/// Possible Errors that can be raised either
366/// during communication with the MAX7219 chip over SPI
367/// or controlling the chip select pin.
368///
369#[derive(Debug)]
370pub enum DriverError {
371    /// An error occurred when working with SPI
372    SpiError,
373    /// An error occurred when working with a PIN
374    PinError,
375}
376
377impl<SPI, CS> MAX7219<SPI, CS>
378where
379    SPI: Write<u8>,
380    CS: OutputPin,
381{
382    ///
383    /// Constructor method. Creates a new instance of the MAX7219 driver.
384    ///
385    /// # Arguments
386    ///
387    /// * `spi` - a SPI peripheral instance
388    /// * `cs` - a OutputPin instance
389    ///
390    /// # Errors
391    ///
392    /// * `DriverError` - returned if there is an error during transfer or addressing device
393    ///
394    pub fn new(spi: SPI, cs: CS) -> Result<Self, DriverError> {
395        let max7219 = MAX7219 { spi: spi, cs: cs };
396        Ok(max7219)
397    }
398
399    ///
400    /// Transmits raw data to the MAX7219 IC.
401    ///
402    /// # Arguments
403    ///
404    /// * `arr` - slice of data that needs to be transmitted
405    ///
406    /// # Errors
407    ///
408    /// * `DriverError` - returned if there is an error during transfer or addressing device
409    ///
410    pub fn transmit_raw_data(&mut self, arr: &[u8]) -> Result<(), DriverError> {
411        self.cs.set_low().map_err(|_| DriverError::PinError)?;
412        let transfer = self.spi.write(&arr).map_err(|_| DriverError::SpiError);
413        self.cs.set_high().map_err(|_| DriverError::PinError)?;
414        transfer
415    }
416
417    ///
418    /// Configures the power mode of the MAX7219 IC.
419    ///
420    /// # Arguments
421    ///
422    /// * `mode` - one of the options in the `Shutdown` enum
423    ///
424    pub fn config_power_mode(&mut self, mode: Shutdown) -> () {
425        let data: u8 = match mode {
426            Shutdown::NormalOperation => 0x01,
427            Shutdown::ShutDownMode => 0x00,
428        };
429
430        let send_array: [u8; 2] = [Command::Shutdown as u8, data];
431        // Transmit Data
432        self.transmit_raw_data(&send_array).unwrap();
433    }
434
435    ///
436    /// Configures the decode mode on the input sent to the MAX7219 IC.
437    ///
438    /// # Arguments
439    ///
440    /// * `mode` - one of the options in the `DecodeMode` enum
441    ///
442    pub fn config_decode_mode(&mut self, mode: DecodeMode) -> () {
443        // - Prepare Information to be Sent
444        // 8-bit Data/Command Corresponding to No Decode Mode
445        let data: u8 = match mode {
446            DecodeMode::NoDecode => 0x00,
447            DecodeMode::CodeB0 => 0x01,
448            DecodeMode::CodeB30 => 0x0F,
449            DecodeMode::CodeB70 => 0xFF,
450        };
451        // Package into array to pass to SPI write method
452        // Write method will grab array and send all data in it
453        let send_array: [u8; 2] = [Command::DecodeMode as u8, data];
454        // Transmit Data
455        self.transmit_raw_data(&send_array).unwrap();
456    }
457
458    ///
459    /// Configures the intensity of the LEDs on the display connected to the MAX7219 IC.
460    ///
461    /// # Arguments
462    ///
463    /// * `mode` - one of the options in the `Intensity` enum
464    ///
465    pub fn config_intensity(&mut self, mode: Intensity) -> () {
466        // - Prepare Information to be Sent
467        // 8-bit Data/Command Corresponding to No Decode Mode
468        let data: u8 = match mode {
469            Intensity::Min => 0x00,
470            Intensity::Ratio3_32 => 0x01,
471            Intensity::Ratio5_32 => 0x02,
472            Intensity::Ratio7_32 => 0x03,
473            Intensity::Ratio9_32 => 0x04,
474            Intensity::Ratio11_32 => 0x05,
475            Intensity::Ratio13_32 => 0x06,
476            Intensity::Ratio15_32 => 0x07,
477            Intensity::Ratio17_32 => 0x08,
478            Intensity::Ratio19_32 => 0x09,
479            Intensity::Ratio21_32 => 0x0A,
480            Intensity::Ratio23_32 => 0x0B,
481            Intensity::Ratio25_32 => 0x0C,
482            Intensity::Ratio27_32 => 0x0D,
483            Intensity::Ratio29_32 => 0x0E,
484            Intensity::Max => 0x0F,
485        };
486        // Package into array to pass to SPI write method
487        // Write method will grab array and send all data in it
488        let send_array: [u8; 2] = [Command::Intensity as u8, data];
489        // Transmit Data
490        self.transmit_raw_data(&send_array).unwrap();
491    }
492
493    ///
494    /// Configures the scanlimit for the MAX7219 IC.
495    /// Applicable mostly to seven segment displays if certain digits (ex. on the left)
496    /// need not to be shown.
497    ///
498    /// # Arguments
499    ///
500    /// * `mode` - one of the options in the `ScanLimit` enum
501    ///
502    pub fn config_scan_limit(&mut self, mode: ScanLimit) -> () {
503        // - Prepare Information to be Sent
504        // 8-bit Data/Command Corresponding to No Decode Mode
505        let data: u8 = match mode {
506            ScanLimit::Display0Only => 0x00,
507            ScanLimit::Display0And1 => 0x01,
508            ScanLimit::Display0To2 => 0x02,
509            ScanLimit::Display0To3 => 0x03,
510            ScanLimit::Display0To4 => 0x04,
511            ScanLimit::Display0To5 => 0x05,
512            ScanLimit::Display0To6 => 0x06,
513            ScanLimit::Display0To7 => 0x07,
514        };
515        // Package into array to pass to SPI write method
516        // Write method will grab array and send all data in it
517        let send_array: [u8; 2] = [Command::ScanLimit as u8, data];
518        // Transmit Data
519        self.transmit_raw_data(&send_array).unwrap();
520    }
521
522    ///
523    /// Method to perform a visual test of the display.
524    /// If performing a test, display needs to be put back in normal operation mode after done.
525    ///
526    /// # Arguments
527    ///
528    /// * `mode` - one of the options in the `DisplayTest` enum
529    ///
530    pub fn display_test(&mut self, mode: DisplayTest) -> () {
531        // - Prepare Information to be Sent
532        // 8-bit Data/Command Corresponding to No Decode Mode
533        let data: u8 = match mode {
534            DisplayTest::NormalOperationMode => 0x00,
535            DisplayTest::DisplayTestMode => 0x01,
536        };
537        // Package into array to pass to SPI write method
538        // Write method will grab array and send all data in it
539        let send_array: [u8; 2] = [Command::DisplayTest as u8, data];
540        // Transmit Data
541        self.transmit_raw_data(&send_array).unwrap();
542    }
543
544    ///
545    /// Method to draw a row if the MAX7219 is driving an 8x8 LED dot matrix display.
546    /// Alternatively method will draw a digit in case the MAX7219 is driving a seven-segment display
547    ///
548    /// # Arguments
549    ///
550    /// * `digit_addr` - one of the options in the `DigitRowAddress` enum
551    /// * `led_data` - the led row or seven segment digit activation data
552    ///
553    pub fn draw_row_or_digit(&mut self, digit_addr: DigitRowAddress, led_data: u8) -> () {
554        // Can do an exhaustive match of DigitRowAddress
555        // let addr: u8 = match digit_addr {
556        //     DigitRowAddress::Digit0 => 0x01,
557        //     DigitRowAddress::Digit1 => 0x02,
558        //     DigitRowAddress::Digit2 => 0x03,
559        //     DigitRowAddress::Digit3 => 0x04,
560        //     DigitRowAddress::Digit4 => 0x05,
561        //     DigitRowAddress::Digit5 => 0x06,
562        //     DigitRowAddress::Digit6 => 0x07,
563        //     DigitRowAddress::Digit7 => 0x08,
564        // };
565        // OR typecast DigitRowAddress passed through digit_addr as u8
566        let send_array: [u8; 2] = [digit_addr as u8, led_data];
567        self.transmit_raw_data(&send_array).unwrap();
568        ()
569    }
570
571    ///
572    /// Method to clear the display.
573    ///
574    pub fn clear_display(&mut self) -> () {
575        for i in 1..9 {
576            self.transmit_raw_data(&[i, 0]).unwrap();
577        }
578    }
579
580    ///
581    /// Method to initialize the MAX7219 and the connected display.
582    /// This method has to be called before doing any display operations otherwise the display will not operate properly.
583    /// The method provides an option to leave the display uncleared after initalization.
584    ///  
585    /// # Arguments
586    ///
587    /// * `clr_display` - Boolean that reflects whether the display should be cleared or not after init
588    ///
589    pub fn init_display(&mut self, clr_display: bool) -> () {
590        // 1.a) Power Up Device
591        self.config_power_mode(Shutdown::NormalOperation);
592        // 1.b) Set up Decode Mode
593        self.config_decode_mode(DecodeMode::NoDecode);
594        // 1.c) Configure Scan Limit
595        self.config_scan_limit(ScanLimit::Display0To7);
596        // 1.d) Configure Intensity
597        self.config_intensity(Intensity::Ratio15_32);
598        // 1.e) Optional Screen Clear on Init
599        if clr_display {
600            self.clear_display();
601        }
602    }
603}
604
605impl<SPI, CS, const BUFLEN: usize, const COUNT: usize> DrawTarget
606    for MAX7219LedMat<SPI, CS, BUFLEN, COUNT>
607{
608    type Color = BinaryColor;
609    type Error = core::convert::Infallible;
610
611    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
612    where
613        I: IntoIterator<Item = Pixel<Self::Color>>,
614    {
615        let bb = self.bounding_box();
616        pixels
617            .into_iter()
618            .filter(|Pixel(pos, _color)| bb.contains(*pos))
619            .for_each(|Pixel(pos, color)| {
620                let index: u32 = pos.x as u32 + pos.y as u32 * 8;
621                self.framebuffer[index as usize] = color.is_on() as u8;
622            });
623        Ok(())
624    }
625}
626
627impl<SPI, CS, const BUFLEN: usize, const COUNT: usize> OriginDimensions
628    for MAX7219LedMat<SPI, CS, BUFLEN, COUNT>
629{
630    fn size(&self) -> Size {
631        Size::new(COUNT as u32 * 8, 8)
632    }
633}
634
635/// Enumeration of commands in the register map of the MAX7219.
636pub enum Command {
637    NoOp = 0x00,
638    DecodeMode = 0x09,
639    Intensity = 0x0A,
640    ScanLimit = 0x0B,
641    Shutdown = 0x0C,
642    DisplayTest = 0x0F,
643}
644
645/// Enumeration of the MAX7219 power modes.
646pub enum Shutdown {
647    ShutDownMode,
648    NormalOperation,
649}
650
651/// Enumeration of the MAX7219 decode modes for BCD encoded input.
652pub enum DecodeMode {
653    NoDecode = 0x00,
654    CodeB0 = 0x01,
655    CodeB30 = 0x0F,
656    CodeB70 = 0xFF,
657}
658
659/// Enumeration of the MAX7219 supported LED intensity values.
660pub enum Intensity {
661    Min = 0x00,
662    Ratio3_32 = 0x01,
663    Ratio5_32 = 0x02,
664    Ratio7_32 = 0x03,
665    Ratio9_32 = 0x04,
666    Ratio11_32 = 0x05,
667    Ratio13_32 = 0x06,
668    Ratio15_32 = 0x07,
669    Ratio17_32 = 0x08,
670    Ratio19_32 = 0x09,
671    Ratio21_32 = 0x0A,
672    Ratio23_32 = 0x0B,
673    Ratio25_32 = 0x0C,
674    Ratio27_32 = 0x0D,
675    Ratio29_32 = 0x0E,
676    Max = 0x0F,
677}
678
679/// Enumeration of the MAX7219 display scan limits
680pub enum ScanLimit {
681    Display0Only = 0x00,
682    Display0And1 = 0x01,
683    Display0To2 = 0x02,
684    Display0To3 = 0x03,
685    Display0To4 = 0x04,
686    Display0To5 = 0x05,
687    Display0To6 = 0x06,
688    Display0To7 = 0x07,
689}
690
691/// Enumeration of the MAX7219 display test modes
692pub enum DisplayTest {
693    NormalOperationMode = 0x00,
694    DisplayTestMode = 0x01,
695}
696
697/// Enumeration of the MAX7219 digit/row addresses
698#[repr(u8)]
699#[derive(Debug, TryFromPrimitive)]
700pub enum DigitRowAddress {
701    Digit0 = 0x01,
702    Digit1 = 0x02,
703    Digit2 = 0x03,
704    Digit3 = 0x04,
705    Digit4 = 0x05,
706    Digit5 = 0x06,
707    Digit6 = 0x07,
708    Digit7 = 0x08,
709}