diff --git a/lib/rtc_ds1307.c b/lib/rtc_ds1307.c index aff5071..3ca51f8 100644 --- a/lib/rtc_ds1307.c +++ b/lib/rtc_ds1307.c @@ -16,7 +16,7 @@ * @file rtc_ds1307.c * @author King Kévin * @date 2016-2017 - * @note peripherals used: I2C @ref rtc_ds1307_i2c + * @note peripherals used: I2C @ref i2c_i2c */ /* standard libraries */ @@ -31,87 +31,21 @@ #include "global.h" // global utilities #include "rtc_ds1307.h" // RTC header and definitions +#include "i2c.h" // i2c utilities -/** @defgroup rtc_ds1307_i2c I2C peripheral used to communicate with DS1307 RTC IC - * @{ - */ -/** I2C peripheral */ -#define RTC_DS1307_I2C 2 /**< I2C peripheral */ #define RTC_DS1307_I2C_ADDR 0x68 /**< DS1307 I2C address (fixed to 0b1101000) */ -/** @} */ void rtc_ds1307_setup(void) { // configure I2C peripheral - rcc_periph_clock_enable(RCC_I2C_SCL_PORT(RTC_DS1307_I2C)); // enable clock for I2C I/O peripheral - gpio_set_mode(I2C_SCL_PORT(RTC_DS1307_I2C), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, I2C_SCL_PIN(RTC_DS1307_I2C)); // setup I2C I/O pins - rcc_periph_clock_enable(RCC_I2C_SCL_PORT(RTC_DS1307_I2C)); // enable clock for I2C I/O peripheral - gpio_set_mode(I2C_SDA_PORT(RTC_DS1307_I2C), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, I2C_SDA_PIN(RTC_DS1307_I2C)); // setup I2C I/O pins - rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function - rcc_periph_clock_enable(RCC_I2C(RTC_DS1307_I2C)); // enable clock for I2C peripheral - i2c_reset(I2C(RTC_DS1307_I2C)); // reset configuration - i2c_peripheral_disable(I2C(RTC_DS1307_I2C)); // I2C needs to be disable to be configured - i2c_set_clock_frequency(I2C(RTC_DS1307_I2C), rcc_apb1_frequency/1000000); // configure the peripheral clock to the APB1 freq (where it is connected to) - i2c_set_standard_mode(I2C(RTC_DS1307_I2C)); // the DS1307 has a maximum I2C SCL freq if 100 kHz (corresponding to the standard mode) - i2c_set_ccr(I2C(RTC_DS1307_I2C), rcc_apb1_frequency/(100000*2)); // set Thigh/Tlow to generate frequency of 100 kHz - i2c_set_trise(I2C(RTC_DS1307_I2C), rcc_apb1_frequency/1000000); // max rise time for 100 kHz is 1000 ns (~1 MHz) - i2c_peripheral_enable(I2C(RTC_DS1307_I2C)); // enable I2C after configuration completed -} - -/** read memory from RTC IC - * @param[in] addr start address for memory to read - * @param[out] data buffer to store read memory - * @param[in] len number of byte to read from the memory - * @return if read succeeded - */ -static bool rtc_ds1307_read_memory(uint8_t addr, uint8_t* data, size_t len) -{ - bool to_return = false; // return if read succeeded - if (data==NULL || len==0) { // verify there it data to be read - goto error; - } - i2c_send_start(I2C(RTC_DS1307_I2C)); // send start condition to start transaction - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_SB)); // wait until start condition is transmitted - if (!(I2C_SR2(I2C(RTC_DS1307_I2C)) & I2C_SR2_MSL)) { // verify if in master mode - goto error; - } - i2c_send_7bit_address(I2C(RTC_DS1307_I2C), RTC_DS1307_I2C_ADDR, I2C_WRITE); // select slave - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_ADDR)); // wait until address is transmitted - if (!((I2C_SR2(I2C(RTC_DS1307_I2C)) & I2C_SR2_TRA))) { // verify we are in transmit mode (and read SR2 to clear ADDR) - goto error; - } - i2c_send_data(I2C(RTC_DS1307_I2C), addr); // send memory address we want to read - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_TxE)); // wait until byte has been transmitted - i2c_send_start(I2C(RTC_DS1307_I2C)); // send restart condition to switch from write to read mode - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_SB)); // wait until start condition is transmitted - i2c_send_7bit_address(I2C(RTC_DS1307_I2C), RTC_DS1307_I2C_ADDR, I2C_READ); // select slave - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_ADDR)); // wait until address is transmitted - if ((I2C_SR2(I2C(RTC_DS1307_I2C)) & I2C_SR2_TRA)) { // verify we are in read mode (and read SR2 to clear ADDR) - goto error; - } - for (size_t i=0; i>4)*10+(data[0]&0x0f); // convert BCD coding into seconds return to_return; } @@ -142,7 +78,8 @@ uint8_t rtc_ds1307_read_minutes(void) { uint8_t to_return = 0; // minutes to return uint8_t data[1] = {0}; // to read data over I2C - rtc_ds1307_read_memory(1, data, LENGTH(data)); // read a single byte containing minutes value + const uint8_t address[] = {0x01}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read a single byte containing minutes value to_return = (data[0]>>4)*10+(data[0]&0x0f); // convert BCD coding into minutes return to_return; } @@ -151,7 +88,8 @@ uint8_t rtc_ds1307_read_hours(void) { uint8_t to_return = 0; // hours to return uint8_t data[1] = {0}; // to read data over I2C - rtc_ds1307_read_memory(2, data, LENGTH(data)); // read a single byte containing hours value + const uint8_t address[] = {0x02}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read a single byte containing hours value if (data[0]&0x40) { // 12 hour mode if (data[0]&0x02) { // PM to_return += 12; // add the 12 hours @@ -168,7 +106,8 @@ uint8_t rtc_ds1307_read_day(void) { uint8_t to_return = 0; // day to return uint8_t data[1] = {0}; // to read data over I2C - rtc_ds1307_read_memory(3, data, LENGTH(data)); // read a single byte containing day value + const uint8_t address[] = {0x03}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read a single byte containing day value to_return = (data[0]&0x07); // convert BCD coding into days return to_return; } @@ -177,7 +116,8 @@ uint8_t rtc_ds1307_read_date(void) { uint8_t to_return = 0; // date to return uint8_t data[1] = {0}; // to read data over I2C - rtc_ds1307_read_memory(4, data, LENGTH(data)); // read a single byte containing date value + const uint8_t address[] = {0x04}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read a single byte containing date value to_return = ((data[0]&0x30)>>4)*10+(data[0]&0x0f); // convert BCD coding into date return to_return; } @@ -186,7 +126,8 @@ uint8_t rtc_ds1307_read_month(void) { uint8_t to_return = 0; // month to return uint8_t data[1] = {0}; // to read data over I2C - rtc_ds1307_read_memory(5, data, LENGTH(data)); // read a single byte containing month value + const uint8_t address[] = {0x05}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read a single byte containing month value to_return = ((data[0]&0x10)>>4)*10+(data[0]&0x0f); // convert BCD coding into month return to_return; } @@ -194,7 +135,8 @@ uint8_t rtc_ds1307_read_month(void) uint8_t rtc_ds1307_read_year(void) { uint8_t data[1] = {0}; // to read data over I2C - rtc_ds1307_read_memory(6, data, LENGTH(data)); // read a single byte containing year value + const uint8_t address[] = {0x06}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read a single byte containing year value uint8_t to_return = ((data[0]&0xf0)>>4)*10+(data[0]&0x0f); // convert BCD coding into year return to_return; } @@ -203,7 +145,8 @@ uint8_t* rtc_ds1307_read_time(void) { static uint8_t time[7] = {0}; // store time {seconds, minutes, hours, day, date, month, year} uint8_t data[7] = {0}; // to read data over I2C - rtc_ds1307_read_memory(0, data, LENGTH(data)); // read all time bytes + const uint8_t address[] = {0x00}; // memory address for data + i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // read all time bytes time[0] = ((data[0]&0x70)>>4)*10+(data[0]&0x0f); // convert seconds from BCD time[1] = (data[1]>>4)*10+(data[1]&0x0f); // convert minutes from BCD time[2] = 0; // re-initialize hours @@ -232,60 +175,31 @@ bool rtc_ds1307_read_ram(uint8_t* data, uint8_t start, uint8_t length) if (start>55 || start+length>56) { // out of bounds RAM return false; } - return rtc_ds1307_read_memory(0x08+start, data, length); // read RAM (starting at 0x08) -} -/** write memory into RTC IC - * @param[in] addr start address for memory to be written - * @param[in] data buffer to for memory to be written - * @param[in] len number of byte to write into the memory - * @return if write succeeded - */ -static bool rtc_ds1307_write_memory(uint8_t addr, uint8_t* data, size_t len) -{ - bool to_return = false; // return if read succeeded - if (data==NULL || len==0) { // verify there it data to be read - goto error; - } - i2c_send_start(I2C(RTC_DS1307_I2C)); // send start condition to start transaction - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_SB)); // wait until start condition is transmitted - if (!(I2C_SR2(I2C(RTC_DS1307_I2C)) & I2C_SR2_MSL)) { // verify if in master mode - goto error; - } - i2c_send_7bit_address(I2C(RTC_DS1307_I2C), RTC_DS1307_I2C_ADDR, I2C_WRITE); // select slave - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_ADDR)); // wait until address is transmitted - if (!((I2C_SR2(I2C(RTC_DS1307_I2C)) & I2C_SR2_TRA))) { // verify we are in transmit mode (and read SR2 to clear ADDR) - goto error; - } - i2c_send_data(I2C(RTC_DS1307_I2C), addr); // send memory address we want to read - while (!(I2C_SR1(I2C(RTC_DS1307_I2C)) & I2C_SR1_TxE)); // wait until byte has been transmitted - for (size_t i=0; i59) { return false; } - if (!rtc_ds1307_read_memory(0, data, 1)) { // read seconds with CH value + if (!i2c_read(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, 1)) { // read seconds with CH value return false; } data[0] &= 0x80; // only keep CH flag @@ -430,7 +360,7 @@ bool rtc_ds1307_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint } data[6] = (((year/10)%10)<<4)+(year%10); // encode year in BCD format - return rtc_ds1307_write_memory(0, data, LENGTH(data)); // write time values on RTC + return i2c_write(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // write time value on RTC } bool rtc_ds1307_write_ram(uint8_t* data, uint8_t start, uint8_t length) @@ -442,5 +372,6 @@ bool rtc_ds1307_write_ram(uint8_t* data, uint8_t start, uint8_t length) if (start>55 || start+length>56) { // out of bounds RAM return false; } - return rtc_ds1307_write_memory(0x08+start, data, length); // write RAM (starting at 0x08) + const uint8_t address[] = {0x08+start}; // memory address for data + return i2c_write(RTC_DS1307_I2C_ADDR, address, LENGTH(address), data, LENGTH(data)); // write RAM (starting at 0x08) }