initialize repository
This commit is contained in:
162
ds1302.c
Normal file
162
ds1302.c
Normal file
@@ -0,0 +1,162 @@
|
||||
#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();
|
||||
}
|
||||
Reference in New Issue
Block a user