Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: sdp_k1_sdram
Diff: app/ad7689_iio.c
- Revision:
- 2:007533849deb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/ad7689_iio.c Thu Jul 21 16:45:24 2022 +0530
@@ -0,0 +1,513 @@
+/***************************************************************************//**
+ * @file ad7689_iio.c
+ * @brief Implementation of AD7689 IIO application interfaces
+********************************************************************************
+ * Copyright (c) 2021-22 Analog Devices, Inc.
+ * All rights reserved.
+ *
+ * This software is proprietary to Analog Devices, Inc. and its licensors.
+ * By using this software you agree to the terms of the associated
+ * Analog Devices Software License Agreement.
+*******************************************************************************/
+
+/******************************************************************************/
+/***************************** Include Files **********************************/
+/******************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "ad7689_iio.h"
+#include "app_config.h"
+#include "ad7689_user_config.h"
+#include "ad7689_data_capture.h"
+#include "no_os_error.h"
+
+/******************************************************************************/
+/********************* Macros and Constants Definition ************************/
+/******************************************************************************/
+
+/* ADC Raw to Voltage conversion default scale factor for IIO client */
+#if defined(BIPOLAR)
+/* Device supports only pseudo-bipolar mode. INX- = Vref / 2 */
+#define ADC_DEFAULT_SCALE (((ADC_DEFAULT_REF_VOLTAGE / 2) / ADC_MAX_COUNT_BIPOLAR) * 1000)
+#else
+#define ADC_DEFAULT_SCALE ((ADC_DEFAULT_REF_VOLTAGE / ADC_MAX_COUNT_UNIPOLAR) * 1000)
+#endif
+
+/* The output of temperature sensor is always unipolar (streight-binary) */
+#define TEMPERATURE_SENSITIVITY 0.283 // 283mv
+#define ROOM_TEMPERATURE 25.0
+#define TEMPERATURE_CONV_SCALE (ROOM_TEMPERATURE / TEMPERATURE_SENSITIVITY) * \
+ ((ADC_DEFAULT_REF_VOLTAGE / ADC_MAX_COUNT_UNIPOLAR) * 1000)
+
+/* Bytes per sample. This count should divide the total 256 bytes into 'n' equivalent
+ * ADC samples as IIO library requests only 256bytes of data at a time in a given
+ * data read query.
+ * For 1 to 8-bit ADC, bytes per sample = 1 (2^0)
+ * For 9 to 16-bit ADC, bytes per sample = 2 (2^1)
+ * For 17 to 32-bit ADC, bytes per sample = 4 (2^2)
+ **/
+#define BYTES_PER_SAMPLE sizeof(uint16_t) // For ADC resolution of 16-bits
+
+/* Number of data storage bits (needed for IIO client to plot ADC data) */
+#define CHN_STORAGE_BITS (BYTES_PER_SAMPLE * 8)
+
+/* Private IDs for IIO attributes */
+#define IIO_RAW_ATTR_ID 0
+#define IIO_SCALE_ATTR_ID 1
+#define IIO_OFFSET_ATTR_ID 2
+
+/******************************************************************************/
+/******************** Variables and User Defined Data Types *******************/
+/******************************************************************************/
+
+/* IIO interface descriptor */
+static struct iio_desc *p_ad7689_iio_desc;
+
+/* Device name */
+static const char dev_name[] = ACTIVE_DEVICE_NAME;
+
+/* Pointer to the struct representing the AD7689 IIO device */
+struct ad7689_dev *p_ad7689_dev_inst = NULL;
+
+/* Device attributes with default values */
+
+/* Scale attribute value per channel */
+static float attr_scale_val[ADC_CHN_COUNT] = {
+ ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE,
+#if !defined(DEV_AD7682)
+ ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE,
+#endif
+ TEMPERATURE_CONV_SCALE
+};
+
+/* AD7689 current configuration */
+struct ad7689_config ad7689_current_config;
+
+/******************************************************************************/
+/************************** Functions Declarations ****************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/************************ Functions Definitions *******************************/
+/******************************************************************************/
+
+/*!
+ * @brief Getter/Setter for the sampling frequency attribute value
+ * @param device- pointer to IIO device structure
+ * @param buf- pointer to buffer holding attribute value
+ * @param len- length of buffer string data
+ * @param channel- pointer to IIO channel structure
+ * @param id- Attribute ID (optional)
+ * @return Number of characters read/written
+ * @Note This attribute is used to define the timeout period in IIO
+ * client during data capture.
+ * Timeout = (number of requested samples * (1/sampling frequency)) + 1sec
+ * e.g. if sampling frequency = 60KSPS and requested samples = 400
+ * Timeout = (400 * (1/60000)) + 1 = 1.0067sec = ~1sec
+ */
+static int get_sampling_frequency(void *device,
+ char *buf,
+ uint32_t len,
+ const struct iio_ch_info *channel,
+ intptr_t id)
+{
+ return sprintf(buf, "%d", SAMPLING_RATE);
+}
+
+static int set_sampling_frequency(void *device,
+ char *buf,
+ uint32_t len,
+ const struct iio_ch_info *channel,
+ intptr_t id)
+{
+ /* sampling frequency is read-only attribute */
+ return len;
+}
+
+
+/*!
+ * @brief Getter/Setter for the raw, offset and scale attribute value
+ * @param device- pointer to IIO device structure
+ * @param buf- pointer to buffer holding attribute value
+ * @param len- length of buffer string data
+ * @param channel- pointer to IIO channel structure
+ * @param id- Attribute ID (optional)
+ * @return Number of characters read/written
+ */
+static int get_adc_raw(void *device,
+ char *buf,
+ uint32_t len,
+ const struct iio_ch_info *channel,
+ intptr_t id)
+{
+ static uint32_t adc_data_raw = 0;
+ int32_t offset = 0;
+ int32_t ret;
+
+ switch (id) {
+ case IIO_RAW_ATTR_ID:
+ /* Capture the raw adc data */
+ ret = read_single_sample((uint8_t)channel->ch_num, &adc_data_raw);
+ if (ret) {
+ return sprintf(buf, " %s", "Error");
+ }
+ return sprintf(buf, "%d", adc_data_raw);
+
+ case IIO_SCALE_ATTR_ID:
+ return sprintf(buf, "%g", attr_scale_val[channel->ch_num]);
+
+ case IIO_OFFSET_ATTR_ID:
+#if defined(BIPOLAR)
+ if (channel->ch_num == TEMPERATURE_CHN) {
+ offset = 0;
+ } else {
+ if (adc_data_raw >= ADC_MAX_COUNT_BIPOLAR) {
+ offset = -ADC_MAX_COUNT_UNIPOLAR;
+ } else {
+ offset = 0;
+ }
+ }
+#endif
+ return sprintf(buf, "%d", offset);
+
+ default:
+ break;
+ }
+
+ return len;
+}
+
+static int set_adc_raw(void *device,
+ char *buf,
+ uint32_t len,
+ const struct iio_ch_info *channel,
+ intptr_t id)
+{
+ /* ADC raw, offset and scale are read-only attributes */
+ return len;
+}
+
+/**
+ * @brief Read buffer data corresponding to AD4170 IIO device
+ * @param iio_dev_data[in] - Pointer to IIO device data structure
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t iio_ad7689_submit_buffer(struct iio_device_data *iio_dev_data)
+{
+ uint32_t ret;
+
+ /* Read the samples counts equal to buffer size/block */
+ ret = read_buffered_data(&iio_dev_data->buffer->buf->buff,
+ iio_dev_data->buffer->size);
+
+ /* Increment the write spin count as buffer reads all 'n' samples
+ * in one go which is also the size of buffer block for a given instance.
+ * The read spin count is incremented from IIO library during buffer
+ * write/offloading into transmit buffer */
+ if (iio_dev_data->buffer->buf->write.spin_count >= UINT32_MAX) {
+ iio_dev_data->buffer->buf->write.spin_count = 0;
+ }
+
+ iio_dev_data->buffer->buf->write.spin_count += 1;
+
+ return ret;
+}
+
+/**
+ * @brief Transfer the device data into memory (optional)
+ * @param dev_instance[in] - IIO device instance
+ * @param ch_mask[in] - Channels select mask
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t iio_ad7689_prepare_transfer(void *dev_instance,
+ uint32_t ch_mask)
+{
+ return prepare_data_transfer(ch_mask, ADC_CHN_COUNT, BYTES_PER_SAMPLE);
+}
+
+/**
+ * @brief Perform tasks before end of current data transfer
+ * @param dev[in] - IIO device instance
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t iio_ad7689_end_transfer(void *dev)
+{
+ return end_data_transfer();
+}
+
+/*********************************************************
+ * IIO Attributes and Structures
+ ********************************************************/
+
+/* IIOD channels attributes list */
+struct iio_attribute channel_input_attributes[] = {
+ {
+ .name = "raw",
+ .show = get_adc_raw,
+ .store = set_adc_raw,
+ .priv = IIO_RAW_ATTR_ID
+ },
+ {
+ .name = "scale",
+ .show = get_adc_raw,
+ .store = set_adc_raw,
+ .priv = IIO_SCALE_ATTR_ID
+ },
+ {
+ .name = "offset",
+ .show = get_adc_raw,
+ .store = set_adc_raw,
+ .priv = IIO_OFFSET_ATTR_ID
+ },
+
+ END_ATTRIBUTES_ARRAY
+};
+
+/* IIOD context attributes list */
+static struct iio_context_attribute iio_context_attributes[] = {
+ {
+ .name = "hw_mezzanine",
+ .value = HW_MEZZANINE_NAME
+ },
+ {
+ .name = "hw_carrier",
+ .value = HW_CARRIER_NAME
+ },
+ {
+ .name = "hw_name",
+ .value = HW_NAME
+ },
+ END_ATTRIBUTES_ARRAY
+};
+
+/* IIOD device (global) attributes list */
+static struct iio_attribute global_attributes[] = {
+ {
+ .name = "sampling_frequency",
+ .show = get_sampling_frequency,
+ .store = set_sampling_frequency,
+ },
+
+ END_ATTRIBUTES_ARRAY
+};
+
+/* IIOD channels configurations */
+struct scan_type chn_scan = {
+#if defined(BIPOLAR)
+ .sign = 's',
+#else
+ .sign = 'u',
+#endif
+ .realbits = CHN_STORAGE_BITS,
+ .storagebits = CHN_STORAGE_BITS,
+ .shift = 0,
+ .is_big_endian = false
+};
+
+static struct iio_channel iio_ad7689_channels[] = {
+ {
+ .name = "voltage0",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 0,
+ .scan_index = 0,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true,
+ },
+ {
+ .name = "voltage1",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 1,
+ .scan_index = 1,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+ {
+ .name = "voltage2",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 2,
+ .scan_index = 2,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+ {
+ .name = "voltage3",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 3,
+ .scan_index = 3,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+#if !defined(DEV_AD7682)
+ {
+ .name = "voltage4",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 4,
+ .scan_index = 4,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+ {
+ .name = "voltage5",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 5,
+ .scan_index = 5,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+ {
+ .name = "voltage6",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 6,
+ .scan_index = 6,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+ {
+ .name = "voltage7",
+ .ch_type = IIO_VOLTAGE,
+ .channel = 7,
+ .scan_index = 7,
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+#endif
+ {
+ .name = "temperature",
+ .ch_type = IIO_TEMP,
+#if !defined(DEV_AD7682)
+ .channel = 8,
+ .scan_index = 8,
+#else
+ .channel = 4,
+ .scan_index = 4,
+#endif
+ .scan_type = &chn_scan,
+ .attributes = channel_input_attributes,
+ .ch_out = false,
+ .indexed = true
+ },
+};
+
+
+/**
+ * @brief Init for reading/writing and parameterization of a
+ * ad7689 IIO device
+ * @param desc[in,out] - IIO device descriptor
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t iio_ad7689_init(struct iio_device **desc)
+{
+ struct iio_device *iio_ad7689_inst;
+
+ iio_ad7689_inst = calloc(1, sizeof(struct iio_device));
+ if (!iio_ad7689_inst) {
+ return -EINVAL;
+ }
+
+ iio_ad7689_inst->num_ch = sizeof(iio_ad7689_channels) / sizeof(
+ iio_ad7689_channels[0]);
+ iio_ad7689_inst->channels = iio_ad7689_channels;
+ iio_ad7689_inst->attributes = global_attributes;
+ iio_ad7689_inst->context_attributes = iio_context_attributes;
+
+ iio_ad7689_inst->submit = iio_ad7689_submit_buffer;
+ iio_ad7689_inst->pre_enable = iio_ad7689_prepare_transfer;
+ iio_ad7689_inst->post_disable = iio_ad7689_end_transfer;
+
+ iio_ad7689_inst->debug_reg_read = NULL;
+ iio_ad7689_inst->debug_reg_write = NULL;
+
+ *desc = iio_ad7689_inst;
+
+ return 0;
+}
+
+/**
+ * @brief Initialize the IIO interface for AD7689 IIO device
+ * @return none
+ * @return 0 in case of success, negative error code otherwise
+ */
+int32_t ad7689_iio_initialize(void)
+{
+ int32_t init_status;
+
+ /* IIO device descriptor */
+ struct iio_device *p_iio_ad7689_dev;
+
+ /* IIO interface init parameters */
+ struct iio_init_param iio_init_params = {
+ .phy_type = USE_UART,
+ .nb_devs = 1,
+ };
+
+ /* IIOD init parameters */
+ struct iio_device_init iio_device_init_params = {
+ .name = (char *)dev_name,
+ .raw_buf = adc_data_buffer,
+ .raw_buf_len = DATA_BUFFER_SIZE
+ };
+
+ /* Init the system peripherals */
+ init_status = init_system();
+ if (init_status) {
+ return init_status;
+ }
+
+ /* Initialize AD7689 device and peripheral interface */
+ init_status = ad7689_init(&p_ad7689_dev_inst, &ad7689_init_params);
+ if (init_status) {
+ return init_status;
+ }
+
+ /* Initialize the AD7689 IIO application interface */
+ init_status = iio_ad7689_init(&p_iio_ad7689_dev);
+ if (init_status) {
+ return init_status;
+ }
+
+ /* Initialize the IIO interface */
+ iio_init_params.uart_desc = uart_desc;
+ iio_device_init_params.dev = p_ad7689_dev_inst;
+ iio_device_init_params.dev_descriptor = p_iio_ad7689_dev;
+ iio_init_params.devs = &iio_device_init_params;
+ init_status = iio_init(&p_ad7689_iio_desc, &iio_init_params);
+ if (init_status) {
+ return init_status;
+ }
+
+ /* Load the init config into current configuration */
+ memcpy(&ad7689_current_config, &ad7689_init_params.config,
+ sizeof(ad7689_current_config));
+
+ return 0;
+}
+
+/**
+ * @brief Run the AD7689 IIO event handler
+ * @return none
+ * @details This function monitors the new IIO client event
+ */
+void ad7689_iio_event_handler(void)
+{
+ (void)iio_step(p_ad7689_iio_desc);
+}