From 54449bb4bd610e3a9673722a098abf73159667db Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 28 Sep 2017 00:37:15 -0400 Subject: add at24c support --- src/at24c.rs | 42 +++++++++++++++++++++++++++++++++++ src/ds3231.rs | 71 +++++++++++++++++++++++++++++++++++------------------------ src/i2c.rs | 2 +- src/main.rs | 19 ++++++++++++++-- 4 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 src/at24c.rs diff --git a/src/at24c.rs b/src/at24c.rs new file mode 100644 index 0000000..534f736 --- /dev/null +++ b/src/at24c.rs @@ -0,0 +1,42 @@ +extern crate stm32f103xx; +use i2c::{I2C, TransDir, DutyType}; + +const AT24C_ADDR: u8 = 0b1010111; /* suppose A0, A1, A2 = 1 */ + +pub struct AT24C<'a, 'b: 'a>(&'a I2C<'a, 'b>); + +impl<'a, 'b> AT24C<'a, 'b> { + pub fn new(i2c: &'a I2C<'a, 'b>) -> AT24C<'a, 'b> { + 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) */ + i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, 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) */ + i2c.send_addr(AT24C_ADDR, TransDir::TRANSMITTER, 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); + } +} diff --git a/src/ds3231.rs b/src/ds3231.rs index 6800f6a..375ce21 100644 --- a/src/ds3231.rs +++ b/src/ds3231.rs @@ -4,8 +4,9 @@ use i2c::{I2C, TransDir, DutyType}; const DS3231_ADDR: u8 = 0b1101000; const DS3231_REG_SEC: u8 = 0x00; const DS3231_REG_CTL: u8 = 0x0e; +const DS3231_REG_TEMP: u8 = 0x11; -pub struct DS3231<'a, 'b>(I2C<'a, 'b>); +pub struct DS3231<'a, 'b: 'a>(&'a I2C<'a, 'b>); pub struct Date { pub second: u8, @@ -19,10 +20,14 @@ pub struct Date { pub am_enabled: bool } +pub struct Temp { + pub cels: i8, + pub quarter: u8 +} + impl<'a, 'b> DS3231<'a, 'b> { - pub fn new(i2c_reg: &'a stm32f103xx::i2c1::RegisterBlock, - rcc_reg: &'b stm32f103xx::rcc::RegisterBlock) -> DS3231<'a, 'b> { - DS3231(I2C::new(i2c_reg, rcc_reg)) + pub fn new(i2c: &'a I2C<'a, 'b>) -> DS3231<'a, 'b> { + DS3231(i2c) } fn bcd2dec(bcd: u8) -> u8 { @@ -33,33 +38,38 @@ impl<'a, 'b> DS3231<'a, 'b> { ((dec / 10) << 4) | (dec % 10) } - pub fn init(&self) { - let &DS3231(ref i2c) = self; - i2c.init(0x01, 400_000, DutyType::DUTY1); - i2c.start(true, true); - i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); - i2c.send(DS3231_REG_CTL, true); - i2c.send(0x00, true); - i2c.send(0x00, true); - i2c.stop(true); - } - - pub fn read_fulldate(&self) -> Date { - let mut buf: [u8; 7] = [0; 7]; + fn read_register(&self, start: u8, size: usize, buf: &mut [u8]){ let &DS3231(ref i2c) = self; i2c.conf_ack(true); /* enable ack */ i2c.start(true, true); /* start condition (for writing reg addr) */ i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); - i2c.send(DS3231_REG_SEC, true); + i2c.send(start, true); /* restart condition (for reading val from the reg addr) */ i2c.start(true, true); i2c.send_addr(DS3231_ADDR, TransDir::RECEIVER, true); - for i in 0..6 { + for i in 0..(size - 1) { buf[i] = i2c.recv(true); } i2c.conf_ack(false); /* disable ack (send nack) */ - buf[6] = i2c.recv(true); + buf[size - 1] = i2c.recv(true); + i2c.stop(true); + } + + fn write_register(&self, start: u8, size: usize, buf: &[u8]) { + let &DS3231(ref i2c) = self; + i2c.conf_ack(true); + i2c.start(true, true); /* start condition for writing */ + i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); + i2c.send(start, true); + for i in 0..size { + i2c.send(buf[i], true); + } i2c.stop(true); + } + + pub fn read_fulldate(&self) -> Date { + let mut buf: [u8; 7] = [0; 7]; + self.read_register(DS3231_REG_SEC, 7, &mut buf); let am_enabled = (buf[2] >> 6) & 1 == 1; let hour = if am_enabled { (buf[2] & 0x0f) + ((buf[2] >> 4) & 1) * 10 @@ -79,7 +89,6 @@ impl<'a, 'b> DS3231<'a, 'b> { } pub fn write_fulldate(&self, date: &Date) { - let &DS3231(ref i2c) = self; let hour = if date.am_enabled { (1 << 6) | ((if date.am {0} else {1}) << 5) | ((date.hour / 10) << 4) | (date.hour % 10) @@ -93,13 +102,17 @@ impl<'a, 'b> DS3231<'a, 'b> { DS3231::dec2bcd(date.date), DS3231::dec2bcd(date.month), DS3231::dec2bcd(date.year)]; - i2c.conf_ack(true); - i2c.start(true, true); /* start condition for writing */ - i2c.send_addr(DS3231_ADDR, TransDir::TRANSMITTER, true); - i2c.send(DS3231_REG_SEC, true); - for i in 0..7 { - i2c.send(buf[i], true); - } - i2c.stop(true); + self.write_register(DS3231_REG_SEC, 7, &buf); + } + + pub fn write_control(&self) { + let buf: [u8; 2] = [0; 2]; + self.write_register(DS3231_REG_CTL, 2, &buf); + } + + pub fn read_temperature(&self) -> Temp { + let mut buf: [u8; 2] = [0; 2]; + self.read_register(DS3231_REG_TEMP, 2, &mut buf); + Temp{cels: buf[0] as i8, quarter: buf[1] >> 6} } } diff --git a/src/i2c.rs b/src/i2c.rs index 473442c..89e2072 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -14,7 +14,7 @@ const FLAGS_MASK: u32 = 0x00ffffff; const HSI_VALUE: u32 = 8000000; const HSE_VALUE: u32 = 8000000; -pub struct I2C<'a, 'b> { +pub struct I2C<'a, 'b: 'a> { i2c: &'a stm32f103xx::i2c1::RegisterBlock, rcc: &'b stm32f103xx::rcc::RegisterBlock, } diff --git a/src/main.rs b/src/main.rs index 0b63e58..2b3c97c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use stm32f103xx::{GPIOA, GPIOB, RCC, SYST, I2C1}; use cortex_m::peripheral::SystClkSource; mod i2c; mod ds3231; +mod at24c; struct ShiftRegister<'a> { gpioa: &'a stm32f103xx::gpioa::RegisterBlock, @@ -21,7 +22,9 @@ struct Clock { const RESET_PERIOD: u8 = 10; static mut SR: Option = None; +static mut I2C: Option = None; static mut RTC: Option = None; +static mut ROM: Option = None; static mut DIGITS: [u8; 6] = [0; 6]; static mut TIME: Clock = Clock{sec: 0, min: 0, hr: 0, reset: 0}; @@ -159,12 +162,17 @@ fn main() { rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); unsafe { - RTC = Some(ds3231::DS3231::new(i2c, rcc)); + I2C = Some(i2c::I2C::new(i2c, rcc)); + let i2c = I2C.as_mut().unwrap(); + RTC = Some(ds3231::DS3231::new(i2c)); + ROM = Some(at24c::AT24C::new(i2c)); SR = Some(ShiftRegister::new(gpioa, 24)); + + i2c.init(0x01, 400_000, i2c::DutyType::DUTY1); SR.as_mut().unwrap().output_bits(0); + let rtc = RTC.as_mut().unwrap(); /* initialize the ds3231 */ - rtc.init(); /* rtc.write_fulldate(&ds3231::Date{second: 30, minute: 48, @@ -176,6 +184,13 @@ fn main() { am: false, am_enabled: false}); */ + /* + let rom = ROM.as_mut().unwrap(); + let mut buf: [u8; 16] = [0; 16]; + rom.read(0, 16, &mut buf); + let mut buf2: [u8; 4] = [0, 1, 2, 3]; + rom.page_write(0, 4, &buf2); + */ } update_clock(); -- cgit v1.2.3