#![deny(warnings)]
#![no_std]
extern crate bit_field;
extern crate embedded_hal as hal;
use bit_field::BitField;
use hal::blocking::i2c::{Write, WriteRead};
pub const DEFAULT_SLAVE_ADDR: u8 = 0x60;
pub struct Max6955<I2C> {
i2c: I2C,
addr: u8,
}
impl<I2C, E> Max6955<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
{
pub fn new(i2c: I2C) -> Result<Self, E> {
let max6955 = Max6955 {
i2c,
addr: DEFAULT_SLAVE_ADDR,
};
Ok(max6955)
}
pub fn with_address(i2c: I2C, addr: u8) -> Result<Self, E> {
let max6955 = Max6955 { i2c, addr };
Ok(max6955)
}
pub fn set_address(&mut self, addr: u8) {
self.addr = addr;
}
pub fn set_global_intensity(&mut self, intensity: u8) -> Result<(), E> {
self.write_register(Register::GlobalIntensity, intensity)?;
Ok(())
}
pub fn set_blink(&mut self, mode: BlinkMode, rate: BlinkRate) -> Result<(), E> {
self.set_configuration_bit(ConfigBitFlag::Blink, mode.value())?;
self.set_configuration_bit(ConfigBitFlag::BlinkRate, rate.value())
}
pub fn powerup(&mut self) -> Result<(), E> {
self.set_configuration_bit(ConfigBitFlag::Shutdown, true)
}
pub fn shutdown(&mut self) -> Result<(), E> {
self.set_configuration_bit(ConfigBitFlag::Shutdown, false)
}
pub fn set_digit_type(&mut self, digit_type: DigitType) -> Result<(), E> {
self.write_register(Register::DigitType, digit_type.value())
}
pub fn set_pin_mode(&mut self, port: usize, pin_mode: PinMode) -> Result<(), E> {
let mut port_config: u8 = self.read_register(Register::PortConfiguration)?;
let config = match pin_mode {
PinMode::Input => *port_config.set_bit(port, true),
PinMode::Output => *port_config.set_bit(port, false),
};
self.write_register(Register::PortConfiguration, config)
}
pub fn set_decode_mode(&mut self, mode: DecodeMode) -> Result<(), E> {
self.write_register(Register::DecodeMode, mode.value())
}
pub fn test(&mut self, enable: bool) -> Result<(), E> {
if enable {
self.write_register(Register::DisplayTest, 0x01)
} else {
self.write_register(Register::DisplayTest, 0x00)
}
}
pub fn clear_display(&mut self) -> Result<(), E> {
self.write_str("")
}
pub fn write_str(&mut self, text: &str) -> Result<(), E> {
let mut row: [u8; 9] = [b' '; 9];
row[0] = Register::Digit0Plane0.addr();
for (i, c) in text.chars().enumerate() {
row[i + 1] = match c {
' '..='~' => c as u8,
_ => b' ',
}
}
self.i2c.write(self.addr, &row)
}
fn write_register(&mut self, reg: Register, byte: u8) -> Result<(), E> {
self.i2c.write(self.addr, &[reg.addr(), byte])
}
fn set_configuration_bit(&mut self, bit: ConfigBitFlag, set: bool) -> Result<(), E> {
let mut config: u8 = self.read_register(Register::Configuration)?;
config.set_bit(bit.value(), set);
self.write_register(Register::Configuration, config)
}
fn read_register(&mut self, reg: Register) -> Result<u8, E> {
let mut buffer: [u8; 8] = [0; 8];
self.read_registers(reg, &mut buffer)?;
Ok(buffer[0])
}
fn read_registers(&mut self, reg: Register, buffer: &mut [u8; 8]) -> Result<(), E> {
self.i2c.write_read(self.addr, &[reg.addr()], buffer)
}
}
pub enum Register {
NoOp = 0x00,
DecodeMode = 0x01,
GlobalIntensity = 0x02,
ScanLimit = 0x03,
Configuration = 0x04,
GpioData = 0x05,
PortConfiguration = 0x06,
DisplayTest = 0x07,
KeyAMaskDebounce = 0x08,
KeyBMaskDebounce = 0x09,
KeyCMaskDebounce = 0x0A,
KeyDMaskDebounce = 0x0B,
DigitType = 0x0C,
KeyBPressed = 0x0D,
KeyCPressed = 0x0E,
KeyDPressed = 0x0F,
Intensity10 = 0x10,
Intensity32 = 0x11,
Intensity54 = 0x12,
Intensity76 = 0x13,
Intensity10a = 0x14,
Intensity32a = 0x15,
Intensity54a = 0x16,
Intensity76a = 0x17,
Digit0Plane0 = 0x20,
Digit1Plane0 = 0x21,
Digit2Plane0 = 0x22,
Digit3Plane0 = 0x23,
Digit4Plane0 = 0x24,
Digit5Plane0 = 0x25,
Digit6Plane0 = 0x26,
Digit7Plane0 = 0x27,
Digit0Plane1 = 0x40,
Digit1Plane1 = 0x41,
Digit2Plane1 = 0x42,
Digit3Plane1 = 0x43,
Digit4Plane1 = 0x44,
Digit5Plane1 = 0x45,
Digit6Plane1 = 0x46,
Digit7Plane1 = 0x47,
}
impl Register {
pub fn addr(self) -> u8 {
self as u8
}
}
pub enum ConfigBitFlag {
Shutdown = 0x00,
BlinkRate = 0x02,
Blink = 0x03,
BlinkTiming = 0x04,
ClearDigit = 0x05,
Intensity = 0x06,
BlinkPhase = 0x07,
}
impl ConfigBitFlag {
pub fn value(self) -> usize {
self as usize
}
}
pub enum DigitType {
Seg7_16 = 0x00,
D0_14 = 0x01,
D0D2_14 = 0x07,
Seg14 = 0xFF,
}
impl DigitType {
pub fn value(self) -> u8 {
self as u8
}
}
pub enum DecodeMode {
NoDecode = 0x00,
HexD0 = 0x01,
HexD0D2 = 0x07,
Hex = 0xFF,
}
impl DecodeMode {
pub fn value(self) -> u8 {
self as u8
}
}
pub enum PinMode {
Input,
Output,
}
pub enum BlinkMode {
Disable,
Enable,
}
impl BlinkMode {
pub fn value(self) -> bool {
match self {
BlinkMode::Disable => false,
BlinkMode::Enable => true,
}
}
}
pub enum BlinkRate {
Fast,
Slow,
}
impl BlinkRate {
pub fn value(self) -> bool {
match self {
BlinkRate::Slow => false,
BlinkRate::Fast => true,
}
}
}