summaryrefslogtreecommitdiff
path: root/src/at24c.rs
blob: 169c048df75cd6f2018c397589a6f5553f24c53a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use i2c::{I2C, TransDir};

const AT24C_ADDR: u8 = 0b1010111; /* suppose A0, A1, A2 = 1 */

pub struct AT24C<'a>(&'a I2C<'a>);

impl<'a> AT24C<'a> {
    pub fn new(i2c: &'a I2C<'a>) -> AT24C<'a> {
        AT24C(i2c)
    }

    pub fn read(&self, start: u16, size: usize, buf: &mut [u8]) {
        let &AT24C(ref i2c) = self;
        i2c.conf_ack(true); /* enable ack */
        i2c.start(true, true); /* start condition (for writing addr) */
        while !i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, true) {
            i2c.start(true, true);
        }
        i2c.send(((start >> 8) & 0x0f) as u8, true); /* first word addr */
        i2c.send((start & 0xff) as u8, true);        /* second word addr */
        i2c.start(true, true); /* restart to read */
        i2c.send_addr(AT24C_ADDR, TransDir::RECEIVER, true);
        for i in 0..(size - 1) {
            buf[i] = i2c.recv(true);
        }
        i2c.conf_ack(false); /* nack */
        buf[size - 1] = i2c.recv(true);
        i2c.stop(true);
    }

    pub fn page_write(&self, start: u16, size: usize, buf: &[u8]) {
        let &AT24C(ref i2c) = self;
        i2c.conf_ack(true); /* enable ack */
        i2c.start(true, true); /* start condition (for writing addr) */
        while !i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, true) {
            i2c.start(true, true);
        }
        i2c.send(((start >> 8) & 0x0f) as u8, true); /* first word addr */
        i2c.send((start & 0xff) as u8, true);        /* second word addr */
        for i in 0..size {
            i2c.send(buf[i], true);
        }
        i2c.stop(true);
    }

    pub fn write(&self, start: u16, size: usize, buf: &[u8]) {
        let end = start + size as u16 - 1;
        let pg_s_off = start & 0x1f;
        let pg_e_off = end & 0x1f;
        let pg_s = start >> 5;
        let pg_e = end >> 5;
        if pg_s == pg_e {
            self.page_write(start, size, buf);
        } else {
            let mut buf = buf;
            self.page_write(start, (0x20 - pg_s_off) as usize, buf);
            buf = &buf[0x20 - pg_s_off as usize..];
            for i in (pg_s + 1)..pg_e {
                self.page_write(i << 5, 0x20, buf);
                buf = &buf[0x20..];
            }
            self.page_write(pg_e << 5, (pg_e_off + 1) as usize, buf);
        }
    }
}