commit
4148670d8f
3 changed files with 217 additions and 0 deletions
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* pcf8523.h |
||||
* |
||||
* Created on: Mar 25, 2023 |
||||
* Author: Daniel Peter Chokola |
||||
*/ |
||||
|
||||
#ifndef PCF8523_INC_PCF8523_H_ |
||||
#define PCF8523_INC_PCF8523_H_ |
||||
|
||||
/* Includes */ |
||||
#include <stdint.h> |
||||
#include "i2c.h" |
||||
#include "time.h" |
||||
|
||||
/* Definitions */ |
||||
|
||||
/* Data Structures */ |
||||
typedef struct pcf8523_s { |
||||
I2C_HandleTypeDef *hi2c; |
||||
} pcf8523_t; |
||||
|
||||
/* Function Prototypes */ |
||||
int32_t pcf8523_init(pcf8523_t *pcf8523, I2C_HandleTypeDef *hi2c); |
||||
time_t pcf8523_now(pcf8523_t *pcf8523); |
||||
int32_t pcf8523_set_time_t(pcf8523_t *pcf8523, time_t *time); |
||||
int32_t pcf8523_set_time(pcf8523_t *pcf8523, struct tm *t); |
||||
|
||||
#endif /* PCF8523_INC_PCF8523_H_ */ |
@ -0,0 +1,173 @@
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* pcf8523.c |
||||
* |
||||
* Created on: Mar 25, 2023 |
||||
* Author: Daniel Peter Chokola |
||||
*/ |
||||
|
||||
|
||||
/* Includes */ |
||||
#include "pcf8523.h" |
||||
#include "i2c.h" |
||||
#include "time.h" |
||||
|
||||
/* Definitions */ |
||||
/* I2C addresses */ |
||||
#define PCF_I2C_W (0xd0) |
||||
#define PCF_I2C_R (0xd1) |
||||
/* Registers */ |
||||
#define PCF_REG_CONTROL_1 (0x00) |
||||
#define PCF_REG_CONTROL_2 (0x01) |
||||
#define PCF_REG_CONTROL_3 (0x02) |
||||
#define PCF_REG_SECONDS (0x03) |
||||
#define PCF_REG_MINUTES (0x04) |
||||
#define PCF_REG_HOURS (0x05) |
||||
#define PCF_REG_DAYS (0x06) |
||||
#define PCF_REG_WEEKDAYS (0x07) |
||||
#define PCF_REG_MONTHS (0x08) |
||||
#define PCF_REG_YEARS (0x09) |
||||
#define PCF_REG_MINUTE_ALARM (0x0A) |
||||
#define PCF_REG_HOUR_ALARM (0x0B) |
||||
#define PCF_REG_DAY_ALARM (0x0C) |
||||
#define PCF_REG_WEEKDAY_ALARM (0x0D) |
||||
#define PCF_REG_OFFSET (0x0E) |
||||
#define PCF_REG_TMR_CLKOUT_CTRL (0x0F) |
||||
#define PCF_REG_TMR_A_FREQ_CTRL (0x10) |
||||
#define PCF_REG_TMR_A_REG (0x11) |
||||
#define PCF_REG_TMR_B_FREQ_CTRL (0x12) |
||||
#define PCF_REG_TMR_B_REG (0x13) |
||||
/* Bitmasks */ |
||||
#define PCF_MASK_CTL1_CAP_SEL (0x80) /* internal oscillator capacitor selection for quartz crystals with a corresponding load capacitance */ |
||||
#define PCF_MASK_CTL1_STOP (0x20) /* 0 RTC time circuits running; 1 RTC time circuits frozen */ |
||||
#define PCF_MASK_CTL1_SR (0x10) /* 0 no software reset; 1 initiate software reset */ |
||||
#define PCF_MASK_CTL1_12_24 (0x08) /* 0 24 hour mode is selected; 1 12 hour mode is selected */ |
||||
#define PCF_MASK_CTL1_SIE (0x04) /* 0 second interrupt disabled; 1 second interrupt enabled */ |
||||
#define PCF_MASK_CTL1_AIE (0x02) /* 0 alarm interrupt disabled; 1 alarm interrupt enabled */ |
||||
#define PCF_MASK_CTL1_CIE (0x01) /* 0 no correction interrupt generated; 1 interrupt pulses are generated at every correction cycle */ |
||||
#define PCF_MASK_CTL2_WTAF (0x80) /* 0 no watchdog timer A interrupt generated; 1 flag set when watchdog timer A interrupt generated */ |
||||
#define PCF_MASK_CTL2_CTAF (0x40) /* 0 no countdown timer A interrupt generated; 1 flag set when countdown timer A interrupt generated */ |
||||
#define PCF_MASK_CTL2_CTBF (0x20) /* 0 no countdown timer B interrupt generated; 1 flag set when countdown timer B interrupt generated */ |
||||
#define PCF_MASK_CTL2_SF (0x10) /* 0 no second interrupt generated; 1 flag set when second interrupt generated */ |
||||
#define PCF_MASK_CTL2_AF (0x08) /* 0 no alarm interrupt generated; 1 flag set when alarm triggered */ |
||||
#define PCF_MASK_CTL2_WTAIE (0x04) /* 0 watchdog timer A interrupt is disabled; 1 watchdog timer A interrupt is enabled */ |
||||
#define PCF_MASK_CTL2_CTAIE (0x02) /* 0 countdown timer A interrupt is disabled; 1 countdown timer A interrupt is enabled */ |
||||
#define PCF_MASK_CTL2_CTBIE (0x01) /* 0 countdown timer B interrupt is disabled; 1 countdown timer B interrupt is enabled */ |
||||
#define PCF_MASK_CTL3_PM (0xe0) /* battery switch-over and battery low detection control */ |
||||
#define PCF_MASK_CTL3_BSF (0x08) /* 0 no battery switch-over interrupt generated; 1 flag set when battery switch-over occurs */ |
||||
#define PCF_MASK_CTL3_BLF (0x04) /* 0 battery status ok; 1 battery status low; flag is read-only */ |
||||
#define PCF_MASK_CTL3_BSIE (0x02) /* 0 no interrupt generated from battery switch-over flag, BSF; 1 interrupt generated when BSF is set */ |
||||
#define PCF_MASK_CTL3_BLIE (0x01) /* 0 no interrupt generated from battery low flag, BLF; 1 interrupt generated when BLF is set */ |
||||
#define PCF_CMD_CTL1_RESET (0x58) /* software reset */ |
||||
/* Slick Macros */ |
||||
#define bin2bcd(x) ((x / 10) * 6 + x) |
||||
#define bcd2bin(x) (x - ((x >> 4) * 6)) |
||||
#define return_if_fail(cond) \ |
||||
if(!(cond)) { return; } |
||||
#define return_val_if_fail(cond, val) \ |
||||
if(!(cond)) { return (val); } |
||||
#define return_null_if_fail(cond) return_val_if_fail((cond), NULL) |
||||
|
||||
/* Private Variables */ |
||||
|
||||
/* Function Prototypes */ |
||||
static void pcf8253_write_byte(pcf8523_t *pcf8523, uint8_t reg, uint8_t data); |
||||
static void pcf8253_read_byte(pcf8523_t *pcf8523, uint8_t reg, uint8_t *data); |
||||
static void pcf8253_write(pcf8523_t *pcf8523, uint8_t reg, uint8_t *data, uint16_t len); |
||||
static void pcf8253_read(pcf8523_t *pcf8523, uint8_t reg, uint8_t *data, uint16_t len); |
||||
|
||||
/* Function Definitions */ |
||||
int32_t pcf8523_init(pcf8523_t *pcf8523, I2C_HandleTypeDef *hi2c) |
||||
{ |
||||
uint8_t tmp; |
||||
|
||||
return_val_if_fail(pcf8523, -1); |
||||
return_val_if_fail(hi2c, -1); |
||||
|
||||
pcf8523->hi2c = hi2c; |
||||
/* initiate reset */ |
||||
pcf8253_write_byte(pcf8523, PCF_REG_CONTROL_1, PCF_CMD_CTL1_RESET); |
||||
/* check if the device is initialized */ |
||||
pcf8253_read_byte(pcf8523, PCF_REG_CONTROL_3, &tmp); |
||||
if((tmp & PCF_MASK_CTL3_PM) == PCF_MASK_CTL3_PM) |
||||
{ |
||||
/* the RTC has not been initialized -- initialize it */ |
||||
/* FIXME: I don't know how to initialize it. */ |
||||
/* turn on battery switchover mode */ |
||||
pcf8253_write_byte(pcf8523, PCF_REG_CONTROL_3, 0x00); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
time_t pcf8523_now(pcf8523_t *pcf8523) |
||||
{ |
||||
struct tm t = { 0 }; |
||||
time_t time; |
||||
uint8_t buf[7]; |
||||
|
||||
return_val_if_fail(pcf8523, -1); |
||||
|
||||
/* read current time */ |
||||
pcf8253_read(pcf8523, PCF_REG_SECONDS, buf, 7); |
||||
t.tm_sec = bcd2bin(buf[0]); |
||||
t.tm_min = bcd2bin(buf[1]); |
||||
t.tm_hour = bcd2bin(buf[2]); |
||||
t.tm_mday = bcd2bin(buf[3]); |
||||
t.tm_wday = bcd2bin(buf[4]); /* ignored by mktime */ |
||||
t.tm_mon = bcd2bin(buf[5]); |
||||
t.tm_year = bcd2bin(buf[6]) + 2000; |
||||
time = mktime(&t); |
||||
|
||||
return time; |
||||
} |
||||
|
||||
int32_t pcf8523_set_time_t(pcf8523_t *pcf8523, time_t *time) |
||||
{ |
||||
struct tm *t; |
||||
|
||||
return_val_if_fail(pcf8523, -1); |
||||
return_val_if_fail(time, -1); |
||||
|
||||
t = gmtime(time); |
||||
|
||||
return pcf8523_set_time(pcf8523, t); |
||||
} |
||||
|
||||
int32_t pcf8523_set_time(pcf8523_t *pcf8523, struct tm *t) |
||||
{ |
||||
uint8_t buf[7]; |
||||
|
||||
return_val_if_fail(pcf8523, -1); |
||||
return_val_if_fail(t, -1); |
||||
|
||||
buf[0] = bin2bcd(t->tm_sec); |
||||
buf[1] = bin2bcd(t->tm_min); |
||||
buf[2] = bin2bcd(t->tm_hour); |
||||
buf[3] = bin2bcd(t->tm_mday); |
||||
buf[4] = bin2bcd(t->tm_wday); |
||||
buf[5] = bin2bcd(t->tm_mon); |
||||
buf[6] = bin2bcd(t->tm_year % 100); |
||||
pcf8253_write(pcf8523, PCF_REG_SECONDS, buf, 7); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static void pcf8253_write_byte(pcf8523_t *pcf8523, uint8_t reg, uint8_t data) |
||||
{ |
||||
HAL_I2C_Mem_Write(pcf8523->hi2c, PCF_I2C_W, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 10); |
||||
} |
||||
|
||||
static void pcf8253_read_byte(pcf8523_t *pcf8523, uint8_t reg, uint8_t *data) |
||||
{ |
||||
HAL_I2C_Mem_Read(pcf8523->hi2c, PCF_I2C_R, reg, I2C_MEMADD_SIZE_8BIT, data, 1, 10); |
||||
} |
||||
|
||||
static void pcf8253_write(pcf8523_t *pcf8523, uint8_t reg, uint8_t *data, uint16_t len) |
||||
{ |
||||
HAL_I2C_Mem_Write(pcf8523->hi2c, PCF_I2C_W, reg, I2C_MEMADD_SIZE_8BIT, data, len, 10); |
||||
} |
||||
|
||||
static void pcf8253_read(pcf8523_t *pcf8523, uint8_t reg, uint8_t *data, uint16_t len) |
||||
{ |
||||
HAL_I2C_Mem_Read(pcf8523->hi2c, PCF_I2C_R, reg, I2C_MEMADD_SIZE_8BIT, data, len, 10); |
||||
} |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
# SX127x |
||||
## Introduction |
||||
This library implements support for the [PCF8523](https://www.nxp.com/products/peripherals-and-logic/signal-chain/real-time-clocks/rtcs-with-ic-bus/100-na-real-time-clock-calendar-with-battery-backup:PCF8523) real-time clock. It is written for the STM32 HAL using blocking I2C calls. |
||||
|
||||
## Usage |
||||
Clone this repository, or add it as a submodule, to your STM32 project under the Drivers/ directory. |
||||
|
||||
Example: |
||||
``` |
||||
#include "pcf8523.h" |
||||
pcf8523_t pcf8523; |
||||
time_t now; |
||||
pcf8523_init(&pcf8523, &hi2c); |
||||
now = pcf8523_now(&pcf8523); |
||||
``` |
Loading…
Reference in new issue