// 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"); }