vcnl36825t_rs/
lib.rs

1#![no_std]
2
3use device_driver::{implement_device, AddressableDevice, RegisterDevice};
4use embedded_hal::i2c::{Error, ErrorKind, I2c};
5use registers::PsSt;
6
7const VCNL36825T_ADDRESS: u8 = 0x60;
8const VCNL36825T_ID: u16 = 0x0026;
9
10#[derive(Debug)]
11pub enum PSError {
12    InvalidID,
13    I2CError(ErrorKind),
14}
15pub struct VCNL36825T<I2C> {
16    i2c: I2C,
17}
18
19impl<I2C> AddressableDevice for VCNL36825T<I2C> {
20    type AddressType = u8;
21}
22
23impl<I2C: I2c> RegisterDevice for VCNL36825T<I2C> {
24    type Error = PSError;
25
26    fn write_register<const SIZE_BYTES: usize>(
27        &mut self,
28        address: Self::AddressType,
29        data: &device_driver::bitvec::prelude::BitArray<[u8; SIZE_BYTES]>,
30    ) -> Result<(), Self::Error> {
31        let mut buffer = [0u8; 3];
32        buffer[0] = address;
33        buffer[1..].copy_from_slice(&data.as_raw_slice()[..SIZE_BYTES]);
34        self.i2c
35            .write(VCNL36825T_ADDRESS, &buffer)
36            .map_err(|e| PSError::I2CError(e.kind()))
37    }
38
39    fn read_register<const SIZE_BYTES: usize>(
40        &mut self,
41        address: Self::AddressType,
42        data: &mut device_driver::bitvec::prelude::BitArray<[u8; SIZE_BYTES]>,
43    ) -> Result<(), Self::Error> {
44        let mut buffer = [0u8; 2];
45        self.i2c
46            .write_read(VCNL36825T_ADDRESS, &[address], &mut buffer)
47            .map_err(|e| PSError::I2CError(e.kind()))?;
48        data.as_raw_mut_slice()[..SIZE_BYTES].copy_from_slice(&buffer[..SIZE_BYTES]);
49        Ok(())
50    }
51}
52
53impl<I2C: I2c + Default> Default for VCNL36825T<I2C> {
54    fn default() -> Self {
55        Self::new(I2C::default()).unwrap()
56    }
57}
58
59impl<I2C: I2c> VCNL36825T<I2C> {
60    pub fn new(i2c: I2C) -> Result<Self, PSError> {
61        let mut vcnl36825t = VCNL36825T { i2c };
62        if vcnl36825t.id().read().unwrap().device_id() != VCNL36825T_ID {
63            return Err(PSError::InvalidID);
64        }
65        vcnl36825t.ps_thdl().clear()?;
66        Ok(vcnl36825t)
67    }
68
69    pub fn destroy(self) -> I2C {
70        self.i2c
71    }
72
73    pub fn power_on(&mut self) -> Result<(), PSError> {
74        self.ps_conf_1().write(|w| w.res_1(1).res_2(1))?;
75        self.ps_conf_2().write(|w| w.ps_st(PsSt::Stop))?;
76        self.ps_conf_1()
77            .write(|w| w.ps_on(true).ps_cal(true).res_1(1).res_2(1))?;
78        self.ps_conf_2().write(|w| w.ps_st(PsSt::Start))
79    }
80}
81
82pub mod registers {
83    use super::*;
84    implement_device!(
85        impl<I2C> VCNL36825T<I2C> {
86            register PS_CONF1 {
87                type RWType = ReadWrite;
88                type ByteOrder = LE;
89                const ADDRESS: u8 = 0x00;
90                const SIZE_BITS: usize = 16;
91                const RESET_VALUE: [u8] = [0x01, 0x00];
92                res1: u8 = 0..1,
93                ps_on: bool = 1,
94                ps_cal: bool = 7,
95                res2: u8 = 9..10,
96
97            },
98            register PS_CONF2 {
99                type RWType = ReadWrite;
100                type ByteOrder = LE;
101                const ADDRESS: u8 = 0x03;
102                const SIZE_BITS: usize = 16;
103                const RESET_VALUE: [u8] = [0x01, 0x00];
104
105                ps_st: u8 as enum PsSt {
106                    Start = 0,
107                    Stop = 1,
108                } = 0..1,
109                ps_smart_pers: bool = 1,
110                ps_int: u8 as enum PsInt {
111                    IntOff = 0,
112                    IntOn = 1,
113                } = 2..4,
114                ps_pers: u8 as enum PsPers {
115                    Pers1 = 0,
116                    Pers2 = 1,
117                    Pers3 = 2,
118                    Pers4 = 3,
119                } = 4..6,
120                ps_period: u8 as enum PsPeriod {
121                    Period10ms = 0,
122                    Period20ms = 1,
123                    Period40ms = 2,
124                    Period80ms = 3,
125                } = 6..8,
126                ps_hg: bool = 10,
127                ps_itb: u8 as enum PsItb {
128                    Itb25us = 0,
129                    Itb50us = 1,
130                } = 11..12,
131                ps_mps: u8 as enum PsMps {
132                    Mps1 = 0,
133                    Mps2 = 1,
134                    Mps4 = 2,
135                    Mps8 = 3,
136                } = 12..14,
137                ps_it: u8 as enum PsIt {
138                    It1T = 0,
139                    It2T = 1,
140                    It4T = 2,
141                    It8T = 3,
142                } = 14..16,
143            },
144            register PS_CONF3 {
145                type RWType = ReadWrite;
146                type ByteOrder = LE;
147                const ADDRESS: u8 = 0x04;
148                const SIZE_BITS: usize = 16;
149                const RESET_VALUE: [u8] = [0x00, 0x00];
150
151                ps_sp_int: bool = 2,
152                res3: u8 = 3..4,
153                ps_forcenum: u8 as enum PsForcenum {
154                    OneCycle = 0,
155                    TwoCycle = 1,
156                } = 4..5,
157                ps_trig: u8 as enum PsTrig {
158                    NoPSActive = 0,
159                    OneTimeCycle = 1,
160                } = 5..6,
161                ps_af: u8 as enum PsAF {
162                    AutoMode = 0,
163                    ForceMode = 1,
164                } = 6..7,
165                i_vcsel: u8 as enum IVcsel {
166                    I10mA = 2,
167                    I12mA = 3,
168                    I14mA = 4,
169                    I16mA = 5,
170                    I18mA = 6,
171                    I20mA = 7,
172                } = 8..12,
173                ps_hd: u8 as enum PsHd {
174                    HD12Bits = 0,
175                    HD16Bits = 1,
176                } = 12..13,
177                ps_sc: u8 as enum PsSc {
178                    SunlightCancellationDisable = 0,
179                    SunlightCancellationEnable = 7,
180                } = 13..16,
181            },
182            register PS_THDL {
183                type RWType = ReadWrite;
184                type ByteOrder = LE;
185                const ADDRESS: u8 = 0x05;
186                const SIZE_BITS: usize = 16;
187                const RESET_VALUE: [u8] = [0x00, 0x00];
188                value: u16 = 0..12,
189            },
190            register PS_THDH {
191                type RWType = ReadWrite;
192                type ByteOrder = LE;
193                const ADDRESS: u8 = 0x06;
194                const SIZE_BITS: usize = 16;
195                const RESET_VALUE: [u8] = [0x00, 0x00];
196                value: u16 = 0..12,
197            },
198            register PS_CANC {
199                type RWType = ReadWrite;
200                type ByteOrder = LE;
201                const ADDRESS: u8 = 0x07;
202                const SIZE_BITS: usize = 16;
203                const RESET_VALUE: [u8] = [0x00, 0x00];
204                value: u16 = 0..12,
205            },
206            register PS_CONF4 {
207                type RWType = ReadWrite;
208                type ByteOrder = LE;
209                const ADDRESS: u8 = 0x08;
210                const SIZE_BITS: usize = 16;
211                const RESET_VALUE: [u8] = [0x00, 0x00];
212
213                ps_ac_int: bool = 0,
214                ps_ac_trig: bool = 2,
215                ps_ac: bool = 3,
216                ps_ac_num: u8 as enum PsAcNum {
217                    Num1 = 0,
218                    Num2 = 1,
219                    Num4 = 2,
220                    Num8 = 3,
221                } = 4..6,
222                ps_ac_period: u8 as enum PsAcPeriod {
223                    Period3ms = 0,
224                    Period6ms = 1,
225                    Period12ms = 2,
226                    Period24ms = 3,
227                } = 6..8,
228                ps_lpen: bool = 8,
229                ps_lpper: u8 as enum PsLpPeriod {
230                    Period40ms = 0,
231                    Period80ms = 1,
232                    Period160ms = 2,
233                    Period320ms = 3,
234                } = 9..11,
235            },
236            register PS_DATA {
237                type RWType = ReadOnly;
238                type ByteOrder = LE;
239                const ADDRESS: u8 = 0xF8;
240                const SIZE_BITS: usize = 16;
241                const RESET_VALUE: [u8] = [0x00, 0x00];
242                value: u16 = 0..12,
243            },
244            register INT_FLAG {
245                type RWType = ReadOnly;
246                type ByteOrder = LE;
247                const ADDRESS: u8 = 0xF9;
248                const SIZE_BITS: usize = 16;
249                const RESET_VALUE: [u8] = [0x00, 0x00];
250                ps_if_away: bool = 8,
251                ps_if_close: bool = 9,
252                ps_spflag: bool = 12,
253                ps_acflag: bool = 12,
254            },
255            register ID {
256                type RWType = ReadOnly;
257                type ByteOrder = LE;
258                const ADDRESS: u8 = 0xFA;
259                const SIZE_BITS: usize = 16;
260                const RESET_VALUE: [u8] = [0x26, 0x00];
261                device_id: u16 = 0..12,
262            },
263            register PS_AC_DATA {
264                type RWType = ReadOnly;
265                type ByteOrder = LE;
266                const ADDRESS: u8 = 0xFB;
267                const SIZE_BITS: usize = 16;
268                const RESET_VALUE: [u8] = [0x00, 0x00];
269                value: u16 = 0..12,
270                ac_sun: bool = 14,
271                ac_busy: bool = 15,
272            },
273        }
274    );
275}