use crate::hal::i2c::{self, Operation};
pub struct HT16K33<I2C> {
i2c: I2C,
address: u8,
display: DisplaySetup,
}
enum RowIntStatus {
Row,
IntActiveLow,
IntActiveHigh,
}
impl Into<u8> for RowIntStatus {
fn into(self) -> u8 {
let base = 0b10100000;
base | match self {
RowIntStatus::Row => 0b00,
RowIntStatus::IntActiveLow => 0b01,
RowIntStatus::IntActiveHigh => 0b11,
}
}
}
#[derive(Clone, Copy)]
struct DisplaySetup {
on_off: DisplayOnOff,
blinking: DisplayBlink,
}
impl Into<u8> for DisplaySetup {
fn into(self) -> u8 {
let byte = 0b10000000;
let byte = byte | match self.on_off {
DisplayOnOff::Off => 0,
DisplayOnOff::On => 1,
};
byte | match self.blinking {
DisplayBlink::Off => 0b000,
DisplayBlink::TwoHz => 0b010,
DisplayBlink::OneHz => 0b100,
DisplayBlink::HalfHz => 0b110,
}
}
}
#[derive(Clone, Copy)]
pub enum DisplayOnOff {On, Off}
#[derive(Clone, Copy)]
pub enum DisplayBlink {Off, TwoHz, OneHz, HalfHz}
impl Default for DisplaySetup {
fn default() -> Self {
Self { on_off: DisplayOnOff::On, blinking: DisplayBlink::Off }
}
}
impl <I2C, E> HT16K33<I2C>
where
I2C: i2c::I2c<Error = E>,
{
pub fn new(i2c: I2C, address: u8) -> Self {
Self {i2c, address, display: DisplaySetup::default()}
}
pub async fn setup(&mut self) -> Result<(), E> {
self.enable_oscillator().await?;
self.set_row_int(RowIntStatus::Row).await?;
self.set_display_setup().await
}
pub async fn write_to_common(&mut self, common_id: u8, pin_states: &[u8; 2]) -> Result<(), E> {
let ram_address = (common_id << 1) & 0b00001110;
self.i2c.write(self.address, &[ram_address, pin_states[0], pin_states[1]]).await
}
pub async fn write_whole_display(&mut self, pin_states: &[u8]) -> Result<(), E> {
let ram_address = 0b00000000;
self.i2c.transaction(self.address, &mut [Operation::Write(&[ram_address]), Operation::Write(pin_states)]).await
}
async fn enable_oscillator(&mut self) -> Result<(), E> {
self.i2c.write(self.address, &[0b00100001]).await
}
async fn set_row_int(&mut self, row_int: RowIntStatus) -> Result<(), E> {
self.i2c.write(self.address, &[row_int.into()]).await
}
async fn set_display_setup(&mut self) -> Result<(), E> {
self.i2c.write(self.address, &[self.display.into()]).await
}
pub async fn set_display_on_off(&mut self, status: DisplayOnOff) -> Result<(), E> {
self.display.on_off = status;
self.set_display_setup().await
}
pub async fn set_display_blink(&mut self, status: DisplayBlink) -> Result<(), E> {
self.display.blinking = status;
self.set_display_setup().await
}
pub async fn read_keys(&mut self, keys: &mut [u8]) -> Result<(), E> {
self.i2c.write_read(self.address, &[0x40], keys).await
}
}