use bitflags::bitflags;
use rppal::spi::{self, Spi};
use std::error::Error;

const CLOCK_SPEED: u32 = 1_000_000; // 1 MHz

bitflags! {
    struct MCP3208_0: u8 {
        const START = 0b0000_0100; // start bit
        const SGL   = 0b0000_0010; // SGL (絶対値)
        const D2    = 0b0000_0001; // チャネル選択 (2ビット目)
    }
}

/// MCP3208 ADコンバータ。
pub struct MCP3208 {
    device: Spi,
}

impl MCP3208 {
    /// 新たなMCP3208型の値を返す。
    pub fn new() -> Result<Self, Box<dyn Error>> {
        let device = Spi::new(
            spi::Bus::Spi0,
            spi::SlaveSelect::Ss0,
            CLOCK_SPEED,
            spi::Mode::Mode0,
        )?;

        Ok(Self { device })
    }

    /// 0〜100%の範囲で、明るさを返す。
    /// 大きい方が明るい。
    pub fn brightness(&self) -> Option<f64> {
        let mut read_buf: [u8; 3] = [0; 3];
        let write_buf: [u8; 3] = [(MCP3208_0::START | MCP3208_0::SGL).bits, 0, 0];

        match self.device.transfer(&mut read_buf, &write_buf) {
            Ok(_) => {
                let val = ((read_buf[1] & 0b0000_1111) as u16) << 8 | read_buf[0] as u16;
                Some(val as f64 / 4096.0_f64 * 100.0)
            }
            Err(e) => {
                eprintln!("{e}");
                None
            }
        }
    }
}
