day09/ex03/src/lib/pcf8563.c
2026-04-27 15:23:42 +02:00

87 lines
2.2 KiB
C

// https://tronixstuff.com/2013/08/13/tutorial-arduino-and-pcf8563-real-time-clock-ic/
// https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf
#include "lib/pcf8563.h"
#include "lib/i2c.h"
#include "lib/uart.h"
#include "lib/utils.h"
t_error pcf8563_read_date(pcf8563_date* out) {
uint8_t bytes[7] = {0};
pcf8563_date ret;
ERR_RET(i2c_start());
ERR_RET(i2c_write(I2C_ADDR(PCF8563address, TW_WRITE)));
ERR_RET(i2c_write(0x2));
ERR_RET(i2c_stop());
ERR_RET(i2c_start());
ERR_RET(i2c_write(I2C_ADDR(PCF8563address, TW_READ)));
for (uint8_t i = 0; i < 6; i++)
ERR_RET(i2c_read_ack(&bytes[i]));
ERR_RET(i2c_read_nack(&bytes[6]));
ret.second = bcdToDec(bytes[0] & 0b01111111);
ret.minute = bcdToDec(bytes[1] & 0b01111111);
ret.hour = bcdToDec(bytes[2] & 0b00111111);
ret.dayOfMonth = bcdToDec(bytes[3] & 0b00111111);
ret.dayOfWeek = bcdToDec(bytes[4] & 0b00000111);
ret.month = bcdToDec(bytes[5] & 0b00011111);
ret.year = bcdToDec(bytes[6]) + ((bytes[5] & 0b10000000) ? 1900 : 2000);
*out = ret;
return NO_ERROR;
}
t_error pcf8563_set_date(pcf8563_date date) {
ERR_RET(i2c_start());
ERR_RET(i2c_write(I2C_ADDR(PCF8563address, TW_WRITE)));
ERR_RET(i2c_write(0x2));
ERR_RET(i2c_write(decToBcd(date.second)));
ERR_RET(i2c_write(decToBcd(date.minute)));
ERR_RET(i2c_write(decToBcd(date.hour)));
ERR_RET(i2c_write(decToBcd(date.dayOfMonth)));
ERR_RET(i2c_write(decToBcd(date.dayOfWeek)));
uint8_t month = decToBcd(date.month);
if (date.year < 2000)
month |= 0b10000000; // set century bit for 1900s
else
month &= 0b01111111; // clear for 2000s
ERR_RET(i2c_write(month));
ERR_RET(i2c_write(decToBcd(date.year % 100)) /*- ((date.year > 1999) ? 2000 : 1900)))*/);
ERR_RET(i2c_stop());
return NO_ERROR;
}
void pcf8563_print_date(pcf8563_date* date) {
if (date->dayOfMonth < 10)
uart_tx('0');
uart_send_u8(date->dayOfMonth);
uart_tx('/');
if (date->month < 10)
uart_tx('0');
uart_send_u8(date->month);
uart_tx('/');
uart_send_u16(date->year);
uart_tx(' ');
if (date->hour < 10)
uart_tx('0');
uart_send_u8(date->hour);
uart_tx(':');
if (date->minute < 10)
uart_tx('0');
uart_send_u8(date->minute);
uart_tx(':');
if (date->second < 10)
uart_tx('0');
uart_send_u8(date->second);
uart_sendstring("\r\n");
}