#include "ds1302.h" void _prepare_read(uint8_t address); void _prepare_write(uint8_t address); uint8_t _read_byte(); void _write_byte(uint8_t value); void _make_clock_cycle(); void _end_transfer(); #define REG_SECONDS 0x80 // SEC #define REG_MINUTES 0x82 // MIN #define REG_HOUR 0x84 // HR #define REG_DATE 0x86 // DATE #define REG_MONTH 0x88 // MONTH #define REG_DAY 0x8A // DAY #define REG_YEAR 0x8C // YEAR #define REG_WP 0x8E // CONTROL // TRICKLE CHARGER 1001000_ 0x90 #define REG_BURST 0xBE // CLOCK BURST #define REG_RAM00 0xC0 #define REG_RAM_BURST 0xFE void ds1302_init() { gpio_init(PIN_RTC_RESET); gpio_set_dir(PIN_RTC_RESET, GPIO_OUT); gpio_put(PIN_RTC_RESET, LOW); gpio_init(PIN_RTC_CLOCK); gpio_set_dir(PIN_RTC_CLOCK, GPIO_OUT); gpio_put(PIN_RTC_CLOCK, LOW); gpio_init(PIN_RTC_IO); gpio_set_dir(PIN_RTC_IO, GPIO_IN); } int ds1302_is_clock_halted() { _prepare_read(REG_SECONDS); uint8_t seconds = _read_byte(); _end_transfer(); return (seconds & 0b10000000); } void ds1302_get_datetime(DateTime *dt) { _prepare_read(REG_BURST); dt->second = ds1302_decode_bcd(_read_byte() & 0b01111111); dt->minute = ds1302_decode_bcd(_read_byte() & 0b01111111); dt->hour = ds1302_decode_bcd(_read_byte() & 0b00111111); dt->day = ds1302_decode_bcd(_read_byte() & 0b00111111); dt->month = ds1302_decode_bcd(_read_byte() & 0b00011111); dt->dow = ds1302_decode_bcd(_read_byte() & 0b00000111); dt->year = ds1302_decode_bcd(_read_byte() & 0b01111111); _end_transfer(); } void ds1302_set_datetime(DateTime *dt) { // disable write protection _prepare_write(REG_WP); _write_byte(0b00000000); // 0, false _end_transfer(); // OR call writeProtect(0) _prepare_write(REG_BURST); _write_byte(ds1302_encode_bcd(dt->second % 60)); _write_byte(ds1302_encode_bcd(dt->minute % 60)); _write_byte(ds1302_encode_bcd(dt->hour % 24)); _write_byte(ds1302_encode_bcd(dt->day % 32)); _write_byte(ds1302_encode_bcd(dt->month % 13)); _write_byte(ds1302_encode_bcd(dt->dow % 8)); _write_byte(ds1302_encode_bcd(dt->year % 100)); _write_byte(0b10000000); _end_transfer(); } void ds1302_halt() { _prepare_write(REG_SECONDS); _write_byte(0b10000000); _end_transfer(); } void _prepare_read(uint8_t address) { gpio_set_dir(PIN_RTC_IO, GPIO_OUT); gpio_put(PIN_RTC_RESET, HIGH); uint8_t command = 0b10000001 | address; _write_byte(command); gpio_set_dir(PIN_RTC_IO, GPIO_IN); } void _prepare_write(uint8_t address) { gpio_set_dir(PIN_RTC_IO, GPIO_OUT); gpio_put(PIN_RTC_RESET, HIGH); uint8_t command = 0b10000000 | address; _write_byte(command); } void _end_transfer() { gpio_put(PIN_RTC_RESET, LOW); } uint8_t _read_byte() { uint8_t byte = 0; for (uint8_t b = 0; b < 8; b++) { if (gpio_get(PIN_RTC_IO) == HIGH) byte |= 0x01 << b; _make_clock_cycle(); } return byte; } void _write_byte(uint8_t value) { for (uint8_t b = 0; b < 8; b++) { gpio_put(PIN_RTC_IO, (value & 0x01) ? HIGH : LOW); _make_clock_cycle(); value >>= 1; } } void _make_clock_cycle() { gpio_put(PIN_RTC_CLOCK, HIGH); sleep_us(1); gpio_put(PIN_RTC_CLOCK, LOW); sleep_us(1); } void ds1302_get_ram_byte(uint8_t addr, uint8_t *data) { _prepare_read(addr); *data = _read_byte(); _end_transfer(); } void ds1302_set_ram_byte(uint8_t addr, uint8_t *data) { _prepare_write(addr); _write_byte(*data); _end_transfer(); } void ds1302_set_write_protection(int enable) { _prepare_write(REG_WP); _write_byte(enable); _end_transfer(); } void ds1302_write_ram_bulk(const uint8_t *data, int len) { if (len <= 0 || len > 31) { return; } _prepare_write(REG_RAM_BURST); for (int i = 0; i < len; i++) { _write_byte(data[i]); } _end_transfer(); } void ds1302_read_ram_bulk(uint8_t *data, int len) { if (len <= 0 || len > 31) { return; } _prepare_read(REG_RAM_BURST); for (int i = 0; i < len; i++) { data[i] = _read_byte(); } _end_transfer(); }