#include <SPI.h>
#include <LoRa.h>
#include "cbds3234.h"
void ICACHE_RAM_ATTR timeInterruptFunction();
#define LORA_SYNC_WORD 0xF3
#define LORA_CS_PIN D1 // GPIO5
CBDS3234* cbDS3234;
volatile uint32_t timeTriggers = 0;
int ds3234ChipSelectPin = D8; // GPIO15
int ds3234InterruptPin = D2; // SQW -> GPIO4
timeParameters timeValues = {
00, // seconds
30, // minutes
9, // hour
5, // d Sun=1,Mon=2,Tue=3,Wed=4,Thu=5,Fri=6,Sat=7
2, // date = 2nd
4, // month = April
21 // year = 2021
};
bool readSensors = false;
void setup() {
Serial.begin(115200);
while(!Serial) {;}
delay(1000);
LoRa.setPins(LORA_CS_PIN, -1, 0);
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
LoRa.setSyncWord(LORA_SYNC_WORD);
Serial.println("LoRa started!");
cbDS3234 = new CBDS3234(ds3234ChipSelectPin, ds3234InterruptPin, &timeInterruptFunction);
byte originalConfig = cbDS3234->init(CBDS3234::INTERRUPT_FREQUENCY_1HZ);
}
void loop() {
// this is fine and return 195, 1110011
byte controlRegister = cbDS3234->getControlRegister();
Serial.print("controlRegisterLoop = ");
Serial.print(controlRegister);
Serial.print(",");
Serial.println(controlRegister, BIN);
if (readSensors) {
cbDS3234->readDateAndTime(&timeValues);
displayTime();
readSensors = false;
// this is fine again, 195
controlRegister = cbDS3234->getControlRegister();
Serial.print("controlRegisterLoop2 = ");
Serial.print(controlRegister);
Serial.print(",");
Serial.println(controlRegister, BIN);
Serial.println("beginPacket");
LoRa.beginPacket();
// this is broken now, returns 255
controlRegister = cbDS3234->getControlRegister();
Serial.print("controlRegisterLoop = ");
Serial.print(controlRegister);
Serial.print(",");
Serial.println(controlRegister, BIN);
}
}
void timeInterruptFunction() {
// accurate to frequency of SQW that we chose
timeTriggers++;
if (timeTriggers < 5) { // every 10s flag to loop()
return;
}
timeTriggers = 0;
readSensors = true;
}
void displayTime() {
Serial.print(cbDS3234->dayOfWeek(timeValues.dy));
Serial.print(" ");
Serial.println(cbDS3234->formattedDateAndTime(&timeValues));
}
#include "cbds3234.h"
const char* CBDS3234Days[] = {
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
};
static uint8_t convertValueIN(uint8_t value);
static uint8_t convertValueOUT(uint8_t value);
const int CBDS3234::INTERRUPT_FREQUENCY_1HZ = 1;
const int CBDS3234::INTERRUPT_FREQUENCY_1024KHZ = 2;
const int CBDS3234::INTERRUPT_FREQUENCY_4096KHZ = 3;
const int CBDS3234::INTERRUPT_FREQUENCY_8192KHZ = 4;
const int CBDS3234::INTERRUPT_FREQUENCY_OFF = 5;
// p14 control register
#define WRITE_CONTROL_REGISTER 0x8E
#define READ_CONTROL_REGISTER 0x0E
// p12 address map timekeeping registers
#define WRITE_TIME_REGISTER 0x80
#define READ_TIME_REGISTER 0x00
CBDS3234::CBDS3234(int chipSelectPin, int interruptPin, void (*sqwFunction)()) {
_chipSelectPin = chipSelectPin;
_interruptPin = interruptPin;
_sqwFunction = sqwFunction;
}
byte CBDS3234::getControlRegister() {
digitalWrite(_chipSelectPin, LOW);
SPI.transfer(READ_CONTROL_REGISTER);
byte changedConfig = SPI.transfer(0x00);
digitalWrite(_chipSelectPin, HIGH);
return changedConfig;
}
byte CBDS3234::init(int interruptFrequency) {
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE1);
pinMode(_chipSelectPin, OUTPUT);
digitalWrite(_chipSelectPin, LOW);
SPI.transfer(READ_CONTROL_REGISTER);
byte originalConfig = SPI.transfer(0x00); // receive from READ_CONTROL_REGISTER
digitalWrite(_chipSelectPin, HIGH);
delay(10); // in case controller is too fast for chip
byte configModifier;
byte newConfig;
if (interruptFrequency == CBDS3234::INTERRUPT_FREQUENCY_OFF) {
// bit 6 BBSQW = 0
configModifier = 0b10111111; // turn off bit 6 BBSQW
newConfig = configModifier & originalConfig; // bitwise AND
}
else {
uint8_t frequencyOption = interruptFrequency - 1; // now 0-3 instead of 1-4
configModifier = (frequencyOption << 3) | 0b01000000;
newConfig = configModifier | (originalConfig & 0b11100011);
}
digitalWrite(_chipSelectPin, LOW);
SPI.transfer(WRITE_CONTROL_REGISTER);
SPI.transfer(newConfig);
digitalWrite(_chipSelectPin, HIGH);
delay(10);
attachInterrupt(digitalPinToInterrupt(_interruptPin), _sqwFunction, RISING);
delay(10);
digitalWrite(_chipSelectPin, LOW);
SPI.transfer(READ_CONTROL_REGISTER);
byte changedConfig = SPI.transfer(0x00);
digitalWrite(_chipSelectPin, HIGH);
return originalConfig;
}
void CBDS3234::setDateAndTime(timeParameters* timeValues) {
pinMode(_chipSelectPin, OUTPUT);
digitalWrite(_chipSelectPin, LOW);
SPI.transfer(WRITE_TIME_REGISTER);
SPI.transfer(convertValueOUT(timeValues->ss)); // write to 0x80
SPI.transfer(convertValueOUT(timeValues->mm)); // write to 0x81
SPI.transfer(convertValueOUT(timeValues->hh)); // write to 0x82
SPI.transfer(convertValueOUT(timeValues->dy)); // write to 0x83
SPI.transfer(convertValueOUT(timeValues->d)); // write to 0x84
SPI.transfer(convertValueOUT(timeValues->m)); // write to 0x85
SPI.transfer(convertValueOUT(timeValues->y)); // write to 0x86
digitalWrite(_chipSelectPin, HIGH);
delay(10);
}
void CBDS3234::readDateAndTime(timeParameters* timeValues) {
pinMode(_chipSelectPin, OUTPUT);
digitalWrite(_chipSelectPin, LOW);
SPI.transfer(READ_TIME_REGISTER);
// the chip will automatically increment the register to be read from to after each read
timeValues->ss = convertValueIN(SPI.transfer(0x00)); // read from 0x80
timeValues->mm = convertValueIN(SPI.transfer(0x00)); // read from 0x81
timeValues->hh = convertValueIN(SPI.transfer(0x00)); // read from 0x82
timeValues->dy = convertValueIN(SPI.transfer(0x00)); // read from 0x83
timeValues->d = convertValueIN(SPI.transfer(0x00)); // read from 0x84
timeValues->m = convertValueIN(SPI.transfer(0x00)); // read from 0x85
timeValues->y = convertValueIN(SPI.transfer(0x00)); // read from 0x86
digitalWrite(_chipSelectPin, HIGH);
delay(10);
}
char* CBDS3234::formattedDateAndTime(timeParameters* timeValues) {
static char dateAndTime[18] = {'\0'};
snprintf(dateAndTime, sizeof(dateAndTime), "%02u/%02u/%02u %02u:%02u:%02u",
timeValues->d,
timeValues->m,
timeValues->y,
timeValues->hh,
timeValues->mm,
timeValues->ss
);
return dateAndTime;
}
String CBDS3234::dayOfWeek(uint8_t dayOfWeekFromDS3234) {
return CBDS3234Days[dayOfWeekFromDS3234 - 1];
}
static uint8_t convertValueIN(uint8_t value) {
uint8_t convertedValue = value - 6 * (value >> 4);
return convertedValue;
}
static uint8_t convertValueOUT(uint8_t value) {
uint8_t convertedValue = value + 6 * (value / 10);
return convertedValue;
}
#ifndef _CBDS3234_H
#define _CBDS3234_H
#include <Arduino.h>
#include <SPI.h>
typedef struct timeParameters {
uint8_t ss; // seconds
uint8_t mm; // minutes
uint8_t hh; // hour
uint8_t dy; // day
uint8_t d; // date
uint8_t m; // month
uint8_t y; // year
};
extern const char* CBDS3234Days[];
class CBDS3234 {
int _chipSelectPin;
int _interruptPin;
void (*_sqwFunction)();
public:
CBDS3234(int chipSelectPin, int interruptPin, void (*sqwFunction)());
byte getControlRegister();
byte init(int interruptFrequency);
void setDateAndTime(timeParameters* timeValues);
void readDateAndTime(timeParameters* timeValues);
String dayOfWeek(uint8_t dayOfWeekFromDS3234);
char* formattedDateAndTime(timeParameters* timeValues);
static const int INTERRUPT_FREQUENCY_1HZ; // 1Hz
static const int INTERRUPT_FREQUENCY_1024KHZ; // 1.024KHz
static const int INTERRUPT_FREQUENCY_4096KHZ; // 4.096KHz
static const int INTERRUPT_FREQUENCY_8192KHZ; // 8.192KHz
static const int INTERRUPT_FREQUENCY_OFF; // OFF
};
#endif