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}