From d4f65018d471c77efa674bf30d5b5938fe6ca3a3 Mon Sep 17 00:00:00 2001 From: marco Date: Wed, 20 Sep 2006 20:40:14 +0000 Subject: [PATCH] Added TC520 ADC driver. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@724 38d2e660-2303-0410-9eaa-f027e97ec537 --- drv/tc520.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ drv/tc520.h | 30 ++++++++++++ hw/hw_tc520.h | 51 +++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100755 drv/tc520.c create mode 100755 drv/tc520.h create mode 100755 hw/hw_tc520.h diff --git a/drv/tc520.c b/drv/tc520.c new file mode 100755 index 00000000..16df6158 --- /dev/null +++ b/drv/tc520.c @@ -0,0 +1,132 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief TC520 ADC driver (implementation) + * + * \version $Id$ + * \author Francesco Sacchi + * \author Marco Benelli + */ + +#include +#include + +#include + +#include +#include +#include + +#include + +static Serial *spi_ser; + +#define TC520_CONVERSION_TIMEOUT ms_to_ticks(1000) +#define INIT_LOAD_VALUE 0x00 + +/** + * Start an AD conversion and return result. + * To start a conversion first we must pull down CE pin. + * The ADC starts a convertion and keeps the DV pin high until the end. + * At this point, we can read the conversion value by SPI. + * The convertion result is yield in 3 bytes. + * First byte: + * bit | Value + * ----|------- + * 7 | Overrange + * 6 | Polarity + * 5:0 | data bits 15:10 + * + * Second byte: data 9:2 + * + * Third byte: + * bit | Value + * ----|------- + * 7 | data bit 1 + * 6 | data bit 0 + * 5:0 | '0' + * + * So, to get the result we must shift and recompose the bits. + * \Note Ovverrange bit is handled as the 17th data bit. + */ +tc520_data_t tc520_read(void) +{ + /* Start convertion and wait */ + CE_LOW(); + ticks_t start = timer_clock(); + do + { + /* timeout check */ + if (timer_clock() - start >= TC520_CONVERSION_TIMEOUT) + { + ASSERT(0); + CE_HIGH(); + return TC520_MAX_VALUE; + } + } + while(DV_LOW()); + + start = timer_clock(); + do + { + /* timeout check */ + if (timer_clock() - start >= TC520_CONVERSION_TIMEOUT) + { + ASSERT(0); + CE_HIGH(); + return TC520_MAX_VALUE; + } + } + while(DV_HIGH()); + + /* Ok, convertion finished, read result */ + CE_HIGH(); + READ_LOW(); + + /* RX buffer could be dirty...*/ + ser_purge(spi_ser); + + /* I/O buffer */ + uint8_t buf[3] = "\x0\x0\x0"; + + /* Dummy write to activate recv */ + ser_write(spi_ser, buf, sizeof(buf)); + ser_drain(spi_ser); + READ_HIGH(); + + /* recv */ + ASSERT(ser_read(spi_ser, buf, sizeof(buf)) == sizeof(buf)); + + tc520_data_t res; + + /* Recompose data */ + res = (((tc520_data_t)(buf[0] & 0x3F)) << 10) | (((tc520_data_t)buf[1]) << 2) | (((tc520_data_t)buf[2]) >> 6); + + #define OVERRANGE_BIT BV(7) + /* Handle overrange bit as 17th bit */ + if (buf[0] & OVERRANGE_BIT) + res |= BV32(16); + + return res; +} + + +/** + * Initialize tc520 A/D converter driver + */ +void tc520_init(Serial *spi_port) +{ + spi_ser = spi_port; + /* init io ports */ + TC520_HW_INIT; + /* Send initial load value */ + LOAD_LOW(); + ser_putchar(INIT_LOAD_VALUE, spi_ser); + ser_drain(spi_ser); + LOAD_HIGH(); +} diff --git a/drv/tc520.h b/drv/tc520.h new file mode 100755 index 00000000..c264ad20 --- /dev/null +++ b/drv/tc520.h @@ -0,0 +1,30 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief TC520 ADC driver (intercace) + * + * \version $Id$ + * \author Francesco Sacchi + * \author Marco Benelli + */ + +#ifndef DRV_TC520_H +#define DRV_TC520_H + +#include +#include + +typedef uint32_t tc520_data_t; + +/* 17 bit max value */ +#define TC520_MAX_VALUE 0x1FFFFUL + +tc520_data_t tc520_read(void); +void tc520_init(Serial *spi_port); + +#endif /* DRV_TC520_H */ diff --git a/hw/hw_tc520.h b/hw/hw_tc520.h new file mode 100755 index 00000000..0fc2320f --- /dev/null +++ b/hw/hw_tc520.h @@ -0,0 +1,51 @@ +/** + * \file + * + * + * \version $Id$ + * + * \brief TC520 hardware-specific definitions + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#ifndef HW_TC520_H +#define HW_TC520_H + +#include +#include + +#define CE_PIN PE6 +#define DV_PIN PE5 +#define LOAD_PIN PE3 +#define READ_PIN PE4 + +#define TC520_DDR DDRE +#define TC520_PORT PORTE +#define TC520_PIN PINE + +#define DV_HIGH() (TC520_PIN & BV(DV_PIN)) +#define DV_LOW() (!DV_HIGH()) + +#define CE_HIGH() (TC520_PORT |= BV(CE_PIN)) +#define CE_LOW() (TC520_PORT &= ~BV(CE_PIN)) + +#define LOAD_HIGH() (TC520_PORT |= BV(LOAD_PIN)) +#define LOAD_LOW() (TC520_PORT &= ~BV(LOAD_PIN)) + +#define READ_HIGH() (TC520_PORT |= BV(READ_PIN)) +#define READ_LOW() (TC520_PORT &= ~BV(READ_PIN)) + +#define TC520_HW_INIT \ +do\ +{\ + TC520_PORT |= (BV(CE_PIN) | BV(LOAD_PIN) | BV(READ_PIN));\ + TC520_DDR |= (BV(CE_PIN) | BV(LOAD_PIN) | BV(READ_PIN));\ + TC520_DDR &= ~BV(DV_PIN);\ +}\ +while(0) + +#endif /* HW_TC520_H */ -- 2.25.1