From ee820891c9f9c7db8aa5ea2ae24a71e1a3c16b31 Mon Sep 17 00:00:00 2001 From: David Blajda Date: Tue, 17 Oct 2017 19:38:10 -0400 Subject: Initailize repository --- ds1302.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 ds1302.c (limited to 'ds1302.c') 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 +#include + +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); +} -- cgit v1.2.3