summaryrefslogtreecommitdiff
path: root/ds1302.c
diff options
context:
space:
mode:
authorDavid Blajda <blajda@hotmail.com>2017-10-17 19:38:10 -0400
committerDavid Blajda <blajda@hotmail.com>2017-10-17 19:38:10 -0400
commitee820891c9f9c7db8aa5ea2ae24a71e1a3c16b31 (patch)
treeb99ef25a8e165f29d1efdf5c3faacd50f78c64f2 /ds1302.c
Initailize repository
Diffstat (limited to 'ds1302.c')
-rw-r--r--ds1302.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/ds1302.c b/ds1302.c
new file mode 100644
index 0000000..3d1152b
--- /dev/null
+++ b/ds1302.c
@@ -0,0 +1,210 @@
+#include "ds1302.h"
+#include <stdio.h>
+#include <time.h>
+
+uint8_t ds1302_readAddress(uint8_t address) {
+ return address | 0x01;
+}
+
+void ds1302_spi_session_start(struct ds1302_spi_session * session) {
+ /*Setup Pins*/
+ bcm2835_gpio_fsel(session->clock, BCM2835_GPIO_FSEL_OUTP);
+ bcm2835_gpio_fsel(session->select, BCM2835_GPIO_FSEL_OUTP);
+ bcm2835_gpio_fsel(session->io, BCM2835_GPIO_FSEL_OUTP);
+
+ bcm2835_gpio_write(session->clock, LOW);
+ bcm2835_delayMicroseconds(10);
+ bcm2835_gpio_write(session->select, HIGH);
+ bcm2835_gpio_write(session->io, LOW);
+
+ bcm2835_delayMicroseconds(10);
+}
+
+void ds1302_spi_session_end(struct ds1302_spi_session * session) {
+ bcm2835_gpio_write(session->select, LOW);
+ bcm2835_delayMicroseconds(10);
+}
+
+void ds1302_spi_session_write(struct ds1302_spi_session * session, int8_t value) {
+ bcm2835_gpio_fsel(session->io, BCM2835_GPIO_FSEL_OUTP);
+
+ for(int i = 0; i < 8; i++) {
+ /*The LSB is written first*/
+ uint8_t out = value & 0x01;
+ value = value >> 1;
+
+ uint8_t o;
+ if(out != 0x0)
+ o = HIGH;
+ else
+ o = LOW;
+
+ /*ds1302 reads the value while the clock is high. Ensure that value is written*/
+ bcm2835_gpio_write(session->io, o);
+ bcm2835_delayMicroseconds(DS1302_CLOCKDELAY);
+ bcm2835_gpio_write(session->clock, HIGH);
+ /*TODO: Lookup the required wait time*/
+ bcm2835_delayMicroseconds(DS1302_CLOCKDELAY);
+ bcm2835_gpio_write(session->clock, LOW);
+ }
+}
+
+uint8_t ds1302_spi_session_read(struct ds1302_spi_session * session) {
+ bcm2835_gpio_fsel(session->io, BCM2835_GPIO_FSEL_INPT);
+ uint8_t value = 0;
+
+ /*The LSB is read first*/
+ for(int i = 0; i < 8; i++) {
+ value = value >> 1 | bcm2835_gpio_lev(session->io) << 7;
+
+ bcm2835_gpio_write(session->clock, HIGH);
+ bcm2835_delayMicroseconds(DS1302_CLOCKDELAY);
+ bcm2835_gpio_write(session->clock, LOW);
+ //bcm2835_delayMicroseconds(DS1302_CLOCKDELAY);
+ }
+
+ return value;
+}
+
+uint8_t ds1302_set_writeprotect(struct ds1302_spi_session * session, uint8_t protect) {
+ if(protect != 0x0)
+ protect = 0x80;
+
+ ds1302_spi_session_write(session, DS1302_WRITE_PROTECT);
+ ds1302_spi_session_write(session, protect);
+}
+
+uint8_t ds1302_read_register(struct ds1302_spi_session * session, uint8_t address) {
+ ds1302_spi_session_write(session, ds1302_readAddress(address));
+ return ds1302_spi_session_read(session);
+}
+
+void ds1302_write_register(struct ds1302_spi_session * session, uint8_t address, uint8_t data) {
+ ds1302_spi_session_write(session, address);
+ ds1302_spi_session_write(session, data);
+}
+
+uint8_t ds1302_burst_read(struct ds1302_spi_session * session, ds1302BurstType type, uint8_t * output, size_t size) {
+ if(size <= 0)
+ return 0;
+
+ uint8_t command = ds1302_readAddress(DS1302_CLOCK_BURST);
+ uint8_t bytesRead = 0;
+
+ if(type == DS1302_MEMORY)
+ command = command | 0x40;
+
+ ds1302_spi_session_write(session, command);
+ /*read more about burst reads from memory*/
+ for(int i = 0; i < size && i < 9; i++) {
+ output[i] = ds1302_spi_session_read(session);
+ bytesRead++;
+ }
+
+ /*Pull the select line down to signal that we are done reading*/
+ bcm2835_gpio_write(session->select, LOW);
+ bcm2835_delayMicroseconds(10);
+ bcm2835_gpio_write(session->select, HIGH);
+
+ return bytesRead;
+}
+uint8_t ds1302_burst_write(struct ds1302_spi_session * session, ds1302BurstType type, uint8_t * input, size_t size) {
+ if(size <= 0)
+ return 0;
+
+ uint8_t command = DS1302_CLOCK_BURST;
+ uint8_t bytesWritten = 0;
+
+ if(type == DS1302_MEMORY)
+ command = command | 0x40;
+
+ ds1302_spi_session_write(session, command);
+
+ for(int i = 0; i < size; i++) {
+ ds1302_spi_session_write(session, input[i]);
+ bytesWritten++;
+ }
+
+ /*Pull the select line down to signal that we are done writing*/
+ bcm2835_gpio_write(session->select, LOW);
+ bcm2835_delayMicroseconds(10);
+ bcm2835_gpio_write(session->select, HIGH);
+
+ return bytesWritten;
+}
+
+/*Convert the base 10 hex representation to just base 10
+ The upper half represents the tens digit and the lower half
+ represents the ones digit.
+ Make sure to clear any bits that are not used in the representation.
+ (EG the 12/24 and AM/PM bits for the hour register)
+*/
+uint8_t ds1302_convertToDecimal(uint8_t input) {
+ uint8_t result = 0x0;
+ result = ((input >> 4) * 10) + (input & 0x0F);
+ return result;
+}
+
+/*Convert base 10 to the 10 hex representation
+ Inverse of ds1302_convertToDecimal
+*/
+uint8_t ds1302_convertToDecimalHex(uint8_t input) {
+ uint8_t result = 0x0;
+ uint8_t tens = input / 10;
+ uint8_t ones = input - (tens * 10);
+ result = (tens << 4) | ones;
+ return result;
+}
+
+void ds1302_getCalendarTime(struct ds1302_spi_session * session, struct tm * date) {
+ uint8_t data[7] = {0xff};
+ /*Clock hour format: High: 12hr, Low: 24h*/
+ uint8_t h12;
+ /*PM or AM: High: PM, Low: AM*/
+ uint8_t pm;
+ uint8_t hour;
+
+ ds1302_burst_read(session, DS1302_REGISTER, data, 7);
+
+ date->tm_sec = ds1302_convertToDecimal(data[0] & (~0x80));
+ date->tm_min = ds1302_convertToDecimal(data[1] & (~0x80));
+
+ /*struct tm represents hours in 24 format. Convert the 12hr clock to 24hr*/
+ h12 = data[2] & 0x80;
+ pm = data[2] & 0x20;
+ hour = ds1302_convertToDecimal(data[2] & 0x1F);
+ if(h12) {
+ if(pm) {
+ date->tm_hour = hour + 11;
+ } else {
+ date->tm_hour = hour - 1;
+ }
+ } else {
+ date->tm_hour = hour;
+ }
+
+ date->tm_mday = ds1302_convertToDecimal(data[3]);
+ /*struct tm starts counting from 0 whereas the ds1302 starts from 1*/
+ date->tm_mon = ds1302_convertToDecimal(data[4]) - 1;
+ /*struct tm starts counting from 0 whereas the ds1302 starts from 1*/
+ date->tm_wday = ds1302_convertToDecimal(data[5]) - 1;
+ /*Number of year that have passed since 1900*/
+ date->tm_year = (ds1302_convertToDecimal(data[6]) + DS1302_START_YEAR) - 1900;
+}
+
+void ds1302_setCalendarTime(struct ds1302_spi_session * session, struct tm * date) {
+ /*TODO: disable Write protect*/
+ uint8_t data[8] = {0};
+ uint8_t hour = 0;
+
+ data[0] = ds1302_convertToDecimalHex(date->tm_sec);
+ data[1] = ds1302_convertToDecimalHex(date->tm_min);
+ data[2] = ds1302_convertToDecimalHex(date->tm_hour);
+ data[3] = ds1302_convertToDecimalHex(date->tm_mday);
+ data[4] = ds1302_convertToDecimalHex(date->tm_mon + 1);
+ data[5] = ds1302_convertToDecimalHex(date->tm_wday + 1);
+ data[6] = ds1302_convertToDecimalHex((date->tm_year + 1900) - DS1302_START_YEAR);
+ data[7] = 0x00;
+
+ ds1302_burst_write(session, DS1302_REGISTER, data, 8);
+}