st7305-lcd 0.2.0

Platform-independent no_std driver for the Sitronix ST7305 reflective LCD controller (embedded-hal 1.0, blocking and async)
Documentation
use crate::{command::WriteCommand, instr::Instr};

/// `NVMLOADCTRL` (§8.2.22): what is loaded from NVM and what triggers the
/// load.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NvmLoadControl {
    vs_en: SourceVoltageLoad,
    id_en: IdLoad,
    nrdtime: NvmLoadControlByTimer,
    nrdslp: NvmLoadControlBySleepOut,
}

impl NvmLoadControl {
    /// Register default `0x17, 0x00`: both items loaded, no trigger.
    pub const DEFAULT: Self = Self {
        vs_en: SourceVoltageLoad::Enable,
        id_en: IdLoad::Enable,
        nrdtime: NvmLoadControlByTimer::NotTrigger,
        nrdslp: NvmLoadControlBySleepOut::NotTrigger,
    };

    /// `VS_EN`: load the source high/low voltages.
    #[must_use]
    pub const fn with_source_voltage_load(mut self, v: SourceVoltageLoad) -> Self {
        self.vs_en = v;
        self
    }

    /// `ID_EN`: load ID1/ID2/ID3.
    #[must_use]
    pub const fn with_id_load(mut self, v: IdLoad) -> Self {
        self.id_en = v;
        self
    }

    /// `NRDTIME`: a timer triggers the NVM load.
    #[must_use]
    pub const fn with_control_by_timer(mut self, v: NvmLoadControlByTimer) -> Self {
        self.nrdtime = v;
        self
    }

    /// `NRDSLP`: sleep out triggers the NVM load.
    #[must_use]
    pub const fn with_control_by_sleep_out(mut self, v: NvmLoadControlBySleepOut) -> Self {
        self.nrdslp = v;
        self
    }

    const fn bytes(&self) -> [u8; 2] {
        [
            0x17 & !(0b11 << 1) | (self.vs_en as u8) << 2 | (self.id_en as u8) << 1,
            (self.nrdtime as u8) << 2 | (self.nrdslp as u8) << 1,
        ]
    }
}

impl Default for NvmLoadControl {
    fn default() -> Self {
        Self::DEFAULT
    }
}

impl WriteCommand for NvmLoadControl {
    const OPCODE: Instr = Instr::NVMLOADCTRL;
    type Params = [u8; 2];
    fn params(&self) -> Self::Params {
        self.bytes()
    }
}

/// `VS_EN`: source voltage load.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SourceVoltageLoad {
    /// Not loaded
    Disable = 0,
    /// Loaded
    Enable = 1,
}

/// `ID_EN`: ID1/ID2/ID3 load.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IdLoad {
    /// Not loaded
    Disable = 0,
    /// Loaded
    Enable = 1,
}

/// `NRDTIME`: NVM load by timer.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NvmLoadControlByTimer {
    /// The timer does not trigger a load
    NotTrigger = 0,
    /// The timer triggers a load
    Trigger = 1,
}

/// `NRDSLP`: NVM load by sleep out.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NvmLoadControlBySleepOut {
    /// Sleep out does not trigger a load
    NotTrigger = 0,
    /// Sleep out triggers a load
    Trigger = 1,
}

const _: () = assert!(matches!(NvmLoadControl::DEFAULT.bytes(), [0x17, 0x00]));

/// `NVMCTRL1` (§8.2.26): NVM read and program modes. The key bytes
/// `5Ah 69h EEh` are added by the command.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NvmWrRdControl {
    prog: ProgramMode,
    rd: ReadMode,
}

impl NvmWrRdControl {
    /// Register default: both modes off.
    pub const DEFAULT: Self = Self {
        prog: ProgramMode::Disable,
        rd: ReadMode::Disable,
    };

    /// `PROG`: program mode. Needs the `nvm-program` feature.
    #[cfg(feature = "nvm-program")]
    #[must_use]
    pub const fn with_program_mode(mut self, v: ProgramMode) -> Self {
        self.prog = v;
        self
    }

    /// `RD`: read mode.
    #[must_use]
    pub const fn with_read_mode(mut self, v: ReadMode) -> Self {
        self.rd = v;
        self
    }

    const fn bytes(&self) -> [u8; 4] {
        [
            0x5A,
            0x69,
            0xEE,
            (self.prog as u8) << 2 | (self.rd as u8) << 1,
        ]
    }
}

impl Default for NvmWrRdControl {
    fn default() -> Self {
        Self::DEFAULT
    }
}

impl WriteCommand for NvmWrRdControl {
    const OPCODE: Instr = Instr::NVMCTRL1;
    type Params = [u8; 4];
    fn params(&self) -> Self::Params {
        self.bytes()
    }
}

/// `PROG`: NVM program mode.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ProgramMode {
    /// Off
    Disable = 0,
    /// On. Always present, so that `nvm-program` stays additive; it can only be
    /// sent through `NvmWrRdControl::with_program_mode`, which needs the
    /// feature.
    Enable = 1,
}

/// `RD`: NVM read mode.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ReadMode {
    /// Off
    Disable = 0,
    /// On
    Enable = 1,
}

const _: () = assert!(matches!(
    NvmWrRdControl::DEFAULT.bytes(),
    [0x5A, 0x69, 0xEE, 0x00]
));

/// `NVMRDEN` (§8.2.28): enables NVM read mode (sends the key `4Ah A5h`).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NvmReadEnable;

impl NvmReadEnable {
    const fn bytes(&self) -> [u8; 2] {
        [0x4A, 0xA5]
    }
}

impl WriteCommand for NvmReadEnable {
    const OPCODE: Instr = Instr::NVMRDEN;
    type Params = [u8; 2];
    fn params(&self) -> Self::Params {
        self.bytes()
    }
}

const _: () = assert!(matches!(NvmReadEnable.bytes(), [0x4A, 0xA5]));

#[cfg(feature = "nvm-program")]
mod program;
#[cfg(feature = "nvm-program")]
pub use program::*;