summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-09-28 00:37:15 -0400
committerDeterminant <ted.sybil@gmail.com>2017-09-28 00:37:15 -0400
commit54449bb4bd610e3a9673722a098abf73159667db (patch)
tree7e8f45ff799a4e9e59ca89df5480e32cd31cd936
parente3a0899abde145a2212082041ffeaf0ca6529300 (diff)
add at24c support
-rw-r--r--src/at24c.rs42
-rw-r--r--src/ds3231.rs71
-rw-r--r--src/i2c.rs2
-rw-r--r--src/main.rs19
4 files changed, 102 insertions, 32 deletions
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<ShiftRegister> = None;
+static mut I2C: Option<i2c::I2C> = None;
static mut RTC: Option<ds3231::DS3231> = None;
+static mut ROM: Option<at24c::AT24C> = 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();