1use crate::driver::i2c::{Event, I2c, Result};
14use core::marker::PhantomData;
15
16pub const EE24_ADDRESS_DEFAULT: u32 = 0x50;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum EepromSize {
22 Kbit1 = 1,
24 Kbit2 = 2,
26 Kbit4 = 4,
28 Kbit8 = 8,
30 Kbit16 = 16,
32 Kbit32 = 32,
34 Kbit64 = 64,
36 Kbit128 = 128,
38 Kbit256 = 256,
40 Kbit512 = 512,
42}
43
44impl EepromSize {
45 pub fn page_size(&self) -> usize {
47 match self {
48 EepromSize::Kbit1 | EepromSize::Kbit2 => 8,
49 EepromSize::Kbit4 | EepromSize::Kbit8 | EepromSize::Kbit16 => 16,
50 _ => 32,
51 }
52 }
53
54 pub fn capacity(&self) -> usize {
56 (*self as usize) * 128 }
58
59 pub fn uses_8bit_addressing(&self) -> bool {
61 match self {
62 EepromSize::Kbit1
63 | EepromSize::Kbit2
64 | EepromSize::Kbit4
65 | EepromSize::Kbit8
66 | EepromSize::Kbit16 => true,
67 _ => false,
68 }
69 }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum EepromError {
75 I2cError(i32),
77 InvalidAddress,
79 DeviceNotReady,
81 WriteProtected,
83 Timeout,
85}
86
87impl From<i32> for EepromError {
88 fn from(err: i32) -> Self {
89 EepromError::I2cError(err)
90 }
91}
92
93pub type EepromResult<T> = core::result::Result<T, EepromError>;
94
95pub struct EepromConfig {
97 pub address: u32,
99 pub size: EepromSize,
101 pub wp_pin: Option<fn(bool)>, pub timeout_ms: u32,
105}
106
107impl Default for EepromConfig {
108 fn default() -> Self {
109 Self {
110 address: EE24_ADDRESS_DEFAULT,
111 size: EepromSize::Kbit32,
112 wp_pin: None,
113 timeout_ms: 100,
114 }
115 }
116}
117
118pub struct Eeprom<'a, I2C> {
120 i2c: I2C,
121 config: EepromConfig,
122 busy: bool,
123 _phantom: PhantomData<&'a ()>,
124}
125
126impl<'a, I2C> Eeprom<'a, I2C>
127where
128 I2C: I2c<'a>,
129{
130 pub fn new(mut i2c: I2C, config: EepromConfig) -> EepromResult<Self> {
132 i2c.initialize(|event| {
134 if event.contains(Event::BUS_ERROR) {
136 }
138 if event.contains(Event::TRANSFER_DONE) {
139 }
141 })
142 .map_err(EepromError::from)?;
143
144 let mut eeprom = Self {
145 i2c,
146 config,
147 busy: false,
148 _phantom: PhantomData,
149 };
150
151 eeprom.is_device_ready()?;
153
154 Ok(eeprom)
155 }
156
157 pub fn is_device_ready(&mut self) -> EepromResult<()> {
159 let status = self.i2c.get_status();
161 if status.bus_error {
162 return Err(EepromError::DeviceNotReady);
163 }
164 Ok(())
165 }
166
167 pub fn read(&mut self, address: u32, data: &mut [u8]) -> EepromResult<()> {
169 if self.busy {
170 return Err(EepromError::DeviceNotReady);
171 }
172
173 if address + data.len() as u32 > self.config.size.capacity() as u32 {
174 return Err(EepromError::InvalidAddress);
175 }
176
177 self.busy = true;
178
179 let result = match self.config.size {
180 EepromSize::Kbit1 | EepromSize::Kbit2 => {
181 self.read_with_8bit_address(address, data)
183 }
184 EepromSize::Kbit4 => {
185 self.read_4kbit(address, data)
187 }
188 EepromSize::Kbit8 => {
189 self.read_8kbit(address, data)
191 }
192 EepromSize::Kbit16 => {
193 self.read_16kbit(address, data)
195 }
196 _ => {
197 self.read_with_16bit_address(address, data)
199 }
200 };
201
202 self.busy = false;
203 result
204 }
205
206 pub fn write(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
208 if self.busy {
209 return Err(EepromError::DeviceNotReady);
210 }
211
212 if address + data.len() as u32 > self.config.size.capacity() as u32 {
213 return Err(EepromError::InvalidAddress);
214 }
215
216 self.busy = true;
217
218 if let Some(wp_control) = self.config.wp_pin {
220 wp_control(false);
221 }
222
223 let result = self.write_pages(address, data);
224
225 if let Some(wp_control) = self.config.wp_pin {
227 wp_control(true);
228 }
229
230 self.busy = false;
231 result
232 }
233
234 fn write_pages(&mut self, mut address: u32, mut data: &[u8]) -> EepromResult<()> {
236 let page_size = self.config.size.page_size();
237
238 while !data.is_empty() {
239 let bytes_to_page_end = page_size - (address as usize % page_size);
241 let write_size = core::cmp::min(data.len(), bytes_to_page_end);
242
243 self.write_chunk(address, &data[..write_size])?;
245
246 self.delay_ms(10);
248
249 address += write_size as u32;
251 data = &data[write_size..];
252 }
253
254 Ok(())
255 }
256
257 fn write_chunk(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
259 match self.config.size {
260 EepromSize::Kbit1 | EepromSize::Kbit2 => self.write_with_8bit_address(address, data),
261 EepromSize::Kbit4 => self.write_4kbit(address, data),
262 EepromSize::Kbit8 => self.write_8kbit(address, data),
263 EepromSize::Kbit16 => self.write_16kbit(address, data),
264 _ => self.write_with_16bit_address(address, data),
265 }
266 }
267
268 fn read_with_8bit_address(&mut self, address: u32, data: &mut [u8]) -> EepromResult<()> {
270 let addr_bytes = [address as u8];
272
273 self.i2c
275 .master_transmit(self.config.address, &addr_bytes, true)
276 .map_err(EepromError::from)?;
277
278 self.i2c
280 .master_receive(self.config.address, data, false)
281 .map_err(EepromError::from)?;
282
283 Ok(())
284 }
285
286 fn read_with_16bit_address(&mut self, address: u32, data: &mut [u8]) -> EepromResult<()> {
288 let addr_bytes = [(address >> 8) as u8, address as u8];
290
291 self.i2c
293 .master_transmit(self.config.address, &addr_bytes, true)
294 .map_err(EepromError::from)?;
295
296 self.i2c
298 .master_receive(self.config.address, data, false)
299 .map_err(EepromError::from)?;
300
301 Ok(())
302 }
303
304 fn read_4kbit(&mut self, address: u32, data: &mut [u8]) -> EepromResult<()> {
306 let device_addr = self.config.address | ((address & 0x0100) >> 7);
307 let mem_addr = [address as u8];
308
309 self.i2c
310 .master_transmit(device_addr, &mem_addr, true)
311 .map_err(EepromError::from)?;
312
313 self.i2c
314 .master_receive(device_addr, data, false)
315 .map_err(EepromError::from)?;
316
317 Ok(())
318 }
319
320 fn read_8kbit(&mut self, address: u32, data: &mut [u8]) -> EepromResult<()> {
322 let device_addr = self.config.address | ((address & 0x0300) >> 7);
323 let mem_addr = [address as u8];
324
325 self.i2c
326 .master_transmit(device_addr, &mem_addr, true)
327 .map_err(EepromError::from)?;
328
329 self.i2c
330 .master_receive(device_addr, data, false)
331 .map_err(EepromError::from)?;
332
333 Ok(())
334 }
335
336 fn read_16kbit(&mut self, address: u32, data: &mut [u8]) -> EepromResult<()> {
338 let device_addr = self.config.address | ((address & 0x0700) >> 7);
339 let mem_addr = [address as u8];
340
341 self.i2c
342 .master_transmit(device_addr, &mem_addr, true)
343 .map_err(EepromError::from)?;
344
345 self.i2c
346 .master_receive(device_addr, data, false)
347 .map_err(EepromError::from)?;
348
349 Ok(())
350 }
351
352 fn write_with_8bit_address(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
354 let mut buffer = [0u8; 256]; buffer[0] = address as u8;
356 buffer[1..=data.len()].copy_from_slice(data);
357
358 self.i2c
359 .master_transmit(self.config.address, &buffer[..=data.len()], false)
360 .map_err(EepromError::from)?;
361
362 Ok(())
363 }
364
365 fn write_with_16bit_address(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
367 let mut buffer = [0u8; 256]; buffer[0] = (address >> 8) as u8;
369 buffer[1] = address as u8;
370 buffer[2..2 + data.len()].copy_from_slice(data);
371
372 self.i2c
373 .master_transmit(self.config.address, &buffer[..2 + data.len()], false)
374 .map_err(EepromError::from)?;
375
376 Ok(())
377 }
378
379 fn write_4kbit(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
381 let device_addr = self.config.address | ((address & 0x0100) >> 7);
382 let mut buffer = [0u8; 256];
383 buffer[0] = address as u8;
384 buffer[1..=data.len()].copy_from_slice(data);
385
386 self.i2c
387 .master_transmit(device_addr, &buffer[..=data.len()], false)
388 .map_err(EepromError::from)?;
389
390 Ok(())
391 }
392
393 fn write_8kbit(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
395 let device_addr = self.config.address | ((address & 0x0300) >> 7);
396 let mut buffer = [0u8; 256];
397 buffer[0] = address as u8;
398 buffer[1..=data.len()].copy_from_slice(data);
399
400 self.i2c
401 .master_transmit(device_addr, &buffer[..=data.len()], false)
402 .map_err(EepromError::from)?;
403
404 Ok(())
405 }
406
407 fn write_16kbit(&mut self, address: u32, data: &[u8]) -> EepromResult<()> {
409 let device_addr = self.config.address | ((address & 0x0700) >> 7);
410 let mut buffer = [0u8; 256];
411 buffer[0] = address as u8;
412 buffer[1..=data.len()].copy_from_slice(data);
413
414 self.i2c
415 .master_transmit(device_addr, &buffer[..=data.len()], false)
416 .map_err(EepromError::from)?;
417
418 Ok(())
419 }
420
421 fn delay_ms(&self, _ms: u32) {
423 for _ in 0..1000 {
426 }
428 }
429
430 pub fn config(&self) -> &EepromConfig {
432 &self.config
433 }
434
435 pub fn is_busy(&self) -> bool {
437 self.busy
438 }
439}
440
441impl<'a, I2C> Eeprom<'a, I2C>
443where
444 I2C: I2c<'a>,
445{
446 pub fn read_byte(&mut self, address: u32) -> EepromResult<u8> {
448 let mut data = [0u8; 1];
449 self.read(address, &mut data)?;
450 Ok(data[0])
451 }
452
453 pub fn write_byte(&mut self, address: u32, data: u8) -> EepromResult<()> {
455 self.write(address, &[data])
456 }
457
458 pub fn read_u16(&mut self, address: u32) -> EepromResult<u16> {
460 let mut data = [0u8; 2];
461 self.read(address, &mut data)?;
462 Ok(u16::from_be_bytes(data))
463 }
464
465 pub fn write_u16(&mut self, address: u32, data: u16) -> EepromResult<()> {
467 self.write(address, &data.to_be_bytes())
468 }
469
470 pub fn read_u32(&mut self, address: u32) -> EepromResult<u32> {
472 let mut data = [0u8; 4];
473 self.read(address, &mut data)?;
474 Ok(u32::from_be_bytes(data))
475 }
476
477 pub fn write_u32(&mut self, address: u32, data: u32) -> EepromResult<()> {
479 self.write(address, &data.to_be_bytes())
480 }
481
482 pub fn clear_range(&mut self, start_address: u32, length: u32) -> EepromResult<()> {
484 let page_size = self.config.size.page_size() as u32;
485 let mut address = start_address;
486 let mut remaining = length;
487
488 while remaining > 0 {
489 let write_size = core::cmp::min(remaining, page_size);
490 let fill_data = [0xFF; 32]; self.write(address, &fill_data[..write_size as usize])?;
493
494 address += write_size;
495 remaining -= write_size;
496 }
497
498 Ok(())
499 }
500}