ddp_connection/protocol/
pixel_config.rs

1#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Copy)]
2#[repr(u8)]
3#[allow(dead_code)]
4pub enum DataType {
5    Undefined,
6    RGB,
7    HSL,
8    RGBW,
9    Grayscale,
10}
11
12#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Copy)]
13#[repr(u8)]
14#[allow(dead_code)]
15pub enum PixelFormat {
16    Undefined,
17    Pixel1Bits,
18    Pixel4Bits,
19    Pixel8Bits,
20    Pixel16Bits,
21    Pixel24Bits,
22    Pixel32Bits,
23}
24
25#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Copy)]
26#[allow(dead_code)]
27pub struct PixelConfig {
28    pub data_type: DataType,
29    pub data_size: PixelFormat,
30    pub customer_defined: bool,
31}
32
33impl From<u8> for PixelConfig {
34    fn from(byte: u8) -> Self {
35        let data_type = match (byte >> 3) & 0x07 {
36            0 => DataType::Undefined,
37            1 => DataType::RGB,
38            2 => DataType::HSL,
39            3 => DataType::RGBW,
40            4 => DataType::Grayscale,
41            _ => DataType::Undefined,
42        };
43
44        let data_size = match (byte & 0x07) as usize {
45            0 => PixelFormat::Undefined,
46            1 => PixelFormat::Pixel1Bits,
47            2 => PixelFormat::Pixel4Bits,
48            3 => PixelFormat::Pixel8Bits,
49            4 => PixelFormat::Pixel16Bits,
50            5 => PixelFormat::Pixel24Bits,
51            6 => PixelFormat::Pixel32Bits,
52            _ => PixelFormat::Undefined,
53        };
54
55        let customer_defined = (byte >> 7) != 0;
56
57        PixelConfig {
58            data_type,
59            data_size,
60            customer_defined,
61        }
62    }
63}
64
65impl Into<u8> for PixelConfig {
66    fn into(self) -> u8 {
67        let mut byte = 0u8;
68
69        byte |= match self.data_type {
70            DataType::Undefined => 0,
71            DataType::RGB => 1,
72            DataType::HSL => 2,
73            DataType::RGBW => 3,
74            DataType::Grayscale => 4,
75        } << 3;
76
77        byte |= match self.data_size {
78            PixelFormat::Undefined => 0,
79            PixelFormat::Pixel1Bits => 1,
80            PixelFormat::Pixel4Bits => 2,
81            PixelFormat::Pixel8Bits => 3,
82            PixelFormat::Pixel16Bits => 4,
83            PixelFormat::Pixel24Bits => 5,
84            PixelFormat::Pixel32Bits => 6,
85        };
86
87        if self.customer_defined {
88            byte |= 0x80;
89        }
90
91        byte
92    }
93}
94
95impl Default for PixelConfig {
96    fn default() -> Self {
97        Self {
98            data_type: DataType::RGB,
99            data_size: PixelFormat::Pixel24Bits,
100            customer_defined: Default::default(),
101        }
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn test_pixel_config_from_u8() {
111        // WLED oddities
112        {
113            let byte = 0x0A;
114            let pixel_config = PixelConfig::from(byte);
115
116            assert_eq!(pixel_config.data_type, DataType::RGB);
117            assert_eq!(pixel_config.data_size, PixelFormat::Pixel4Bits);
118            assert!(!pixel_config.customer_defined);
119        }
120
121        // RGB 24
122        {
123            let byte = 0x0D;
124            let pixel_config = PixelConfig::from(byte);
125
126            assert_eq!(pixel_config.data_type, DataType::RGB);
127            assert_eq!(pixel_config.data_size, PixelFormat::Pixel24Bits);
128            assert!(!pixel_config.customer_defined);
129        }
130
131        // RGBW 32
132        {
133            let byte = 0x1E;
134            let pixel_config = PixelConfig::from(byte);
135
136            assert_eq!(pixel_config.data_type, DataType::RGBW);
137            assert_eq!(pixel_config.data_size, PixelFormat::Pixel32Bits);
138            assert!(!pixel_config.customer_defined);
139        }
140    }
141}