diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index d9319b9eff..291b11469c 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -124,6 +124,10 @@ ifneq (,$(filter ds1307,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c endif +ifneq (,$(filter ds3234,$(USEMODULE))) + FEATURES_REQUIRED += periph_spi +endif + ifneq (,$(filter dsp0401,$(USEMODULE))) USEMODULE += xtimer FEATURES_REQUIRED += periph_gpio diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 9a64c0867e..e4d4a38427 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -66,6 +66,10 @@ ifneq (,$(filter ds1307,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ds1307/include endif +ifneq (,$(filter ds3234,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ds3234/include +endif + ifneq (,$(filter dsp0401,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/dsp0401/include endif diff --git a/drivers/ds3234/Makefile b/drivers/ds3234/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/ds3234/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/ds3234/ds3234.c b/drivers/ds3234/ds3234.c new file mode 100644 index 0000000000..99662983be --- /dev/null +++ b/drivers/ds3234/ds3234.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 Eistec AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + */ + +/** + * @ingroup drivers_ds3234 + * @{ + * + * @file + * @brief Driver for the DS3234 Extremely Accurate SPI Bus RTC with + * Integrated Crystal and SRAM, from Maxim + * + * @author Joakim Nohlgård + * @} + */ + +#include +#include +#include "ds3234.h" +#include "ds3234_regs.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* SPI command byte parameters */ +#define DS3234_CMD_READ (0x00) +#define DS3234_CMD_WRITE (0x80) + + +/** + * @brief Read one or more registers from the sensor + * + * @param[in] dev device descriptor + * @param[in] addr register address + * @param[in] len number of bytes to read + * @param[out] buf destination buffer + */ +static void ds3234_read_reg(const ds3234_params_t *dev, uint8_t addr, size_t len, uint8_t *buf) +{ + uint8_t command = DS3234_CMD_READ | addr; + /* Acquire exclusive access to the bus. */ + spi_acquire(dev->spi, dev->cs, SPI_MODE_3, dev->clk); + /* Perform the transaction */ + spi_transfer_regs(dev->spi, dev->cs, command, NULL, buf, len); + /* Release the bus for other threads. */ + spi_release(dev->spi); +} + +/** + * @brief Write a register value to the sensor + * + * @param[in] dev device descriptor + * @param[in] addr register address + * @param[in] len register size + * @param[in] buf source buffer + */ +static void ds3234_write_reg(const ds3234_params_t *dev, uint8_t addr, size_t len, const uint8_t *buf) +{ + uint8_t command = DS3234_CMD_WRITE | addr; + /* Acquire exclusive access to the bus. */ + spi_acquire(dev->spi, dev->cs, SPI_MODE_3, dev->clk); + /* Perform the transaction */ + spi_transfer_regs(dev->spi, dev->cs, command, buf, NULL, len); + /* Release the bus for other threads. */ + spi_release(dev->spi); +} + +int ds3234_pps_init(const ds3234_params_t *dev) +{ + /* initialize CS pin */ + int res = spi_init_cs(dev->spi, dev->cs); + if (res < 0) { + return DS3234_NO_SPI; + } + DEBUG("ds3234: init on SPI_DEV(%u)\n", dev->spi); + + if (ENABLE_DEBUG) { + for (int k = 0; k <= 0x19; ++k) { + uint8_t dbg_reg = 0; + ds3234_read_reg(dev, k, 1, &dbg_reg); + DEBUG("%2x: %2x\n", k, dbg_reg); + } + } + uint8_t reg = 0; + ds3234_read_reg(dev, DS323X_REG_CONTROL, 1, ®); + + /* set reg to a non-zero known value to check if device is present */ + reg |= DS323X_REG_CONTROL_RS1_MASK; + + ds3234_write_reg(dev, DS323X_REG_CONTROL, 1, ®); + uint8_t readback = 0; + ds3234_read_reg(dev, DS323X_REG_CONTROL, 1, &readback); + if (reg != readback) { + DEBUG("ds3234: readback mismatch: expected %u, actual %u\n", (unsigned)reg, (unsigned)readback); + return DS3234_NO_DEV; + } + + /* The control register is configured to: + * - Enable the oscillator + * - Enable an square wave output on the SQW pin + * - Sets the square wave frequency to 1 Hz + */ + reg &= ~(DS323X_REG_CONTROL_EOSC_MASK | DS323X_REG_CONTROL_INTCN_MASK | + DS323X_REG_CONTROL_RS1_MASK | DS323X_REG_CONTROL_RS2_MASK); + ds3234_write_reg(dev, DS323X_REG_CONTROL, 1, ®); + + return DS3234_OK; +} diff --git a/drivers/ds3234/include/ds3234_params.h b/drivers/ds3234/include/ds3234_params.h new file mode 100644 index 0000000000..fc95c6ab3d --- /dev/null +++ b/drivers/ds3234/include/ds3234_params.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 SKF AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ds3234 + * + * @{ + * @file + * @brief Default configuration for DS3234 devices + * + * @author Joakim Nohlgård + */ + +#ifndef DS3234_PARAMS_H +#define DS3234_PARAMS_H + +#include "board.h" +#include "ds3234.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Set default configuration parameters for the DS3234 devices + * @{ + */ +#ifndef DS3234_PARAM_SPI +#define DS3234_PARAM_SPI (SPI_DEV(0)) +#endif +#ifndef DS3234_PARAM_CS +#define DS3234_PARAM_CS (GPIO_PIN(0, 0)) +#endif +#ifndef DS3234_PARAM_CLK +#define DS3234_PARAM_CLK (SPI_CLK_1MHZ) +#endif +#ifndef DS3234_PARAMS +#define DS3234_PARAMS \ + { \ + .spi = DS3234_PARAM_SPI, \ + .cs = DS3234_PARAM_CS, \ + .clk = DS3234_PARAM_CLK, \ + } +#endif +/**@}*/ + +/** + * @brief Configure DS3234 devices + */ +static const ds3234_params_t ds3234_params[] = +{ + DS3234_PARAMS +}; + +#ifdef __cplusplus +} +#endif + +#endif /* DS3234_PARAMS_H */ +/** @} */ diff --git a/drivers/ds3234/include/ds3234_regs.h b/drivers/ds3234/include/ds3234_regs.h new file mode 100644 index 0000000000..b466cc351b --- /dev/null +++ b/drivers/ds3234/include/ds3234_regs.h @@ -0,0 +1,75 @@ +/* + * Copyright 2018 SKF AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ds3234 + * @{ + * + * @file + * @brief Register map for the DS323x driver + * + * @author Joakim Nohlgård + */ + +#ifndef DS3234_REGS_H +#define DS3234_REGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Register addresses + * @{ + */ +enum { + DS323X_REG_TIME_SECONDS = (0x00), + DS323X_REG_TIME_MINUTES = (0x01), + DS323X_REG_TIME_HOURS = (0x02), + DS323X_REG_TIME_WEEKDAY = (0x03), + DS323X_REG_TIME_DATE = (0x04), + DS323X_REG_TIME_MONTH = (0x05), + DS323X_REG_TIME_YEAR = (0x06), + DS323X_REG_ALARM1_SECONDS = (0x07), + DS323X_REG_ALARM1_MINUTES = (0x08), + DS323X_REG_ALARM1_HOURS = (0x09), + DS323X_REG_ALARM1_DAYDATE = (0x0A), + DS323X_REG_ALARM2_MINUTES = (0x0B), + DS323X_REG_ALARM2_HOURS = (0x0C), + DS323X_REG_ALARM2_DAYDATE = (0x0D), + DS323X_REG_CONTROL = (0x0E), + DS323X_REG_CONTROL_STATUS = (0x0F), + DS323X_REG_XTAL_AGING = (0x10), + DS323X_REG_TEMP_MSB = (0x11), + DS323X_REG_TEMP_LSB = (0x12), + DS323X_REG_TEMP_DISABLE = (0x13), + DS323X_REG_SRAM_ADDR = (0x18), + DS323X_REG_SRAM_DATA = (0x19), +}; +/** @} */ + +/** + * @name Control register bits + * @{ + */ +#define DS323X_REG_CONTROL_EOSC_MASK (0x80) /**< Enable oscillator */ +#define DS323X_REG_CONTROL_BBSQW_MASK (0x40) /**< Battery-Backed Square-Wave Enable */ +#define DS323X_REG_CONTROL_CONV_MASK (0x20) /**< Convert Temperature */ +#define DS323X_REG_CONTROL_RS2_MASK (0x10) /**< Rate Select 2 */ +#define DS323X_REG_CONTROL_RS1_MASK (0x08) /**< Rate Select 1 */ +#define DS323X_REG_CONTROL_INTCN_MASK (0x04) /**< Interrupt Control */ +#define DS323X_REG_CONTROL_A2IE_MASK (0x02) /**< Alarm 2 Interrupt Enable */ +#define DS323X_REG_CONTROL_A1IE_MASK (0x01) /**< Alarm 1 Interrupt Enable */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* DS3234_REGS_H */ +/** @} */ diff --git a/drivers/include/ds3234.h b/drivers/include/ds3234.h new file mode 100644 index 0000000000..8ade9acdbf --- /dev/null +++ b/drivers/include/ds3234.h @@ -0,0 +1,69 @@ +/* + * Copyright 2018 SKF AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_ds3234 DS3234 Extremely Accurate SPI RTC + + * @brief Driver for Maxim DS3234 Extremely Accurate SPI Bus RTC with + * Integrated Crystal and SRAM + + * @{ + * + * @file + * @brief DS3234 device driver + * + * @author Joakim Nohlgård + */ + +#ifndef DS3234_H +#define DS3234_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Parameters for the DS3234 device driver + */ +typedef struct { + spi_t spi; /**< SPI bus the sensor is connected to */ + spi_clk_t clk; /**< SPI bus clock speed */ + gpio_t cs; /**< CS pin GPIO handle */ +} ds3234_params_t; + +/** + * @brief Return codes for the DS3234 device driver + */ +enum ds3234_return_codes { + DS3234_OK = 0, + DS3234_NO_DEV = 1, + DS3234_NO_SPI = 2 +}; + +/** + * @brief Initialize the DS3234 RTC as a PPS device + * + * This will enable square wave output on the SQW pin at 1 Hz + * + * @param params DS3234 circuit parameters + * + * @return DS3234_OK on success + * @return DS3234_NO_SPI if cannot initiate SPI + * @return DS3234_NO_DEV if the device is not found on the bus + */ +int ds3234_pps_init(const ds3234_params_t *params); + +#ifdef __cplusplus +} +#endif + +#endif /* DS3234_H */ +/** @} */ diff --git a/tests/driver_ds3234/Makefile b/tests/driver_ds3234/Makefile new file mode 100644 index 0000000000..f81de77dc0 --- /dev/null +++ b/tests/driver_ds3234/Makefile @@ -0,0 +1,5 @@ +include ../Makefile.tests_common + +USEMODULE += ds3234 + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_ds3234/README.md b/tests/driver_ds3234/README.md new file mode 100644 index 0000000000..0387b85e3e --- /dev/null +++ b/tests/driver_ds3234/README.md @@ -0,0 +1,10 @@ +# About + +This is a simple test application for the DS3234 SPI RTC driver PPS output. + +# Usage + +This test application will initialize the RTC with the following parameters: + - Oscillator enabled + - Square wave output enabled + - Square wave frequency: 1 Hz diff --git a/tests/driver_ds3234/main.c b/tests/driver_ds3234/main.c new file mode 100644 index 0000000000..43862e478b --- /dev/null +++ b/tests/driver_ds3234/main.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2018 SKF AB + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test application for the DS3234 RTC driver + * + * @author Joakim Nohlgård + +#include "board.h" +#include "ds3234.h" +#include "ds3234_params.h" + +int main(void) +{ + puts("DS3234 RTC PPS test application\n"); + + for (unsigned k = 0; k < (sizeof(ds3234_params) / sizeof(ds3234_params[0])); ++k) { + printf("Init #%u... ", k); + int res = ds3234_pps_init(&ds3234_params[k]); + if (res == 0) { + puts("[OK]"); + } + else { + puts("[Failed]\n"); + return 1; + } + } + + puts("DS3234 init done.\n"); + puts("Check SQW pin on all connected DS3234 for a 1 Hz square wave signal\n"); + + while (1) { + /* Spin */ + } + + return 0; +}