Files
velometer/ds1302.c
2026-09-10 14:35:16 +03:00

163 lines
3.9 KiB
C

#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();
}