diff --git a/.mbedignore b/.mbedignore index c65b9bff..716f3498 100644 --- a/.mbedignore +++ b/.mbedignore @@ -13,7 +13,7 @@ projects/ad7134_iio/ projects/ad717x_iio/ projects/ad719x_iio/ projects/ad777x_iio/ -projects/ad4696_iio/ +projects/ad469x_iio/ projects/ad579x_iio/ projects/ad7606_iio/ projects/ad77681_iio/ diff --git a/projects/ad4696_iio/.gitignore b/projects/ad4696_iio/.gitignore deleted file mode 100644 index 8468edba..00000000 --- a/projects/ad4696_iio/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -*.swp -*.profile* -build -app/no-OS -Visual* -Code* -.gitattributes -.vs/ -*.sln -*.vgdbproj -*.TMP -*.user -scripts/__pycache__ -tests/.pytest_cache -tests/__pycache__ -tests/func/__pycache__ -tests/output \ No newline at end of file diff --git a/projects/ad4696_iio/app/app_config.c b/projects/ad4696_iio/app/app_config.c deleted file mode 100644 index 70e85295..00000000 --- a/projects/ad4696_iio/app/app_config.c +++ /dev/null @@ -1,187 +0,0 @@ -/***************************************************************************//** - * @file app_config.c - * @brief Application configurations module - * @details This module contains the configurations needed for IIO application -******************************************************************************** - * Copyright (c) 2021-23 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 -#include "app_config.h" -#include "no_os_error.h" -#include "no_os_gpio.h" -#include "no_os_irq.h" -#include "no_os_pwm.h" -#include "no_os_uart.h" - -/******************************************************************************/ -/************************ Macros/Constants ************************************/ -/******************************************************************************/ - -/******************************************************************************/ -/*************************** Types Declarations *******************************/ -/******************************************************************************/ -/* UART init parameters structure */ -struct no_os_uart_init_param uart_init_params = { - .device_id = NULL, - .baud_rate = IIO_UART_BAUD_RATE, - .size = NO_OS_UART_CS_8, - .parity = NO_OS_UART_PAR_NO, - .stop = NO_OS_UART_STOP_1_BIT, - .platform_ops = &uart_ops, - .extra = &uart_extra_init_params -}; - -/* External interrupt init parameters */ -struct no_os_irq_init_param trigger_gpio_irq_params = { - .irq_ctrl_id = 0, - .platform_ops = &trigger_gpio_irq_ops, - .extra = &trigger_gpio_irq_extra_params -}; - -/* External interrupt callback descriptor */ -static struct no_os_callback_desc ext_int_callback_desc = { - .callback = burst_capture_callback, - .ctx = NULL, - .peripheral = NO_OS_GPIO_IRQ -}; - -/* PWM init parameters */ -static struct no_os_pwm_init_param pwm_init_params = { - .id = 0, - .period_ns = CONV_TRIGGER_PERIOD_NSEC(DEFAULT_SAMPLING_RATE), // PWM period in nsec - .duty_cycle_ns = CONV_TRIGGER_DUTY_CYCLE_NSEC(DEFAULT_SAMPLING_RATE), // PWM duty cycle in nsec - .extra = &pwm_extra_init_params -}; - -/* External interrupt descriptor */ -struct no_os_irq_ctrl_desc *trigger_irq_desc; - -/* UART console output descriptor */ -struct no_os_uart_desc *uart_desc; - -/* PWM descriptor */ -struct no_os_pwm_desc *pwm_desc; - -/******************************************************************************/ -/************************ Functions Prototypes ********************************/ -/******************************************************************************/ - -/******************************************************************************/ -/************************ Functions Definitions *******************************/ -/******************************************************************************/ -/** - * @brief Initialize the UART peripheral. - * @return 0 in case of success, negative error code otherwise. - */ -static int32_t init_uart(void) -{ - int32_t ret; - - ret = no_os_uart_init(&uart_desc, &uart_init_params); - if (ret) { - return ret; - } - - return 0; -} - -/** - * @brief Initialize the IRQ controller. - * @return 0 in case of success, negative error code otherwise. - * @details This function initialize the interrupts for system peripherals. - */ -static int32_t init_interrupt(void) -{ - int32_t ret; - - /* Init interrupt controller for external interrupt */ - ret = no_os_irq_ctrl_init(&trigger_irq_desc, &trigger_gpio_irq_params); - if (ret) { - return ret; - } - -#if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE) - /* The BSY pin has been tied as the interrupt source to sense the - * End of Conversion. The registered callback function is responsible - * of reading the raw samples via the SPI bus */ - ret = no_os_irq_register_callback(trigger_irq_desc, - TRIGGER_INT_ID, - &ext_int_callback_desc); - if (ret) { - return ret; - } - - ret = no_os_irq_trigger_level_set(trigger_irq_desc, - TRIGGER_INT_ID, NO_OS_IRQ_EDGE_FALLING); - if (ret) { - return ret; - } - - ret = no_os_irq_disable(trigger_irq_desc, TRIGGER_INT_ID); - if (ret) { - return ret; - } -#endif - return 0; -} - -/** - * @brief Initialize the PWM interface. - * @return 0 in case of success, negative error code otherwise. - */ -int32_t init_pwm(void) -{ - int32_t ret; - - /* Initialize the PWM interface to generate PWM signal - * for recurring function calls */ - ret = no_os_pwm_init(&pwm_desc, &pwm_init_params); - if (ret) { - return ret; - } - - /* Disable the PWM interface.*/ - ret = no_os_pwm_disable(pwm_desc); - if (ret) { - return ret; - } - - return 0; -} - -/** - * @brief Initializing system peripherals - * @return 0 in case of success, negative error code otherwise. - * @details This function initializes system peripherals for the application - */ -int32_t init_system(void) -{ - int32_t ret; - - ret = init_uart(); - if (ret) { - return ret; - } - - ret = init_interrupt(); - if (ret) { - return ret; - } - -#if defined(USE_SDRAM) - ret = sdram_init(); - if (ret) { - return ret; - } -#endif - return 0; -} \ No newline at end of file diff --git a/projects/ad4696_iio/app/iio_ad4696.c b/projects/ad4696_iio/app/iio_ad4696.c deleted file mode 100644 index d2daec07..00000000 --- a/projects/ad4696_iio/app/iio_ad4696.c +++ /dev/null @@ -1,974 +0,0 @@ -/***************************************************************************//** - * @file iio_ad4696.c - * @brief Implementation of AD4696 IIO application interfaces - * @details This module acts as an interface for AD4696 IIO application -******************************************************************************** - * Copyright (c) 2021-23 Analog Devices, Inc. - * - * 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 -#include -#include - -#include "app_config.h" -#include "iio_ad4696.h" -#include "ad4696_support.h" -#include "ad4696_user_config.h" -#include "no_os_error.h" -#include "no_os_util.h" -#include "no_os_gpio.h" -#include "no_os_pwm.h" -#include "no_os_print_log.h" -#include "iio_trigger.h" - -/******** Forward declaration of getter/setter functions ********/ -static int iio_ad469x_attr_get(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv); - -static int iio_ad469x_attr_set(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv); - -static int iio_ad469x_attr_available_get(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv); - -static int iio_ad469x_attr_available_set(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv); - -/******************************************************************************/ -/************************ Macros/Constants ************************************/ -/******************************************************************************/ -#define AD469X_CHN_ATTR(_name, _priv) {\ - .name = _name,\ - .priv = _priv,\ - .show = iio_ad469x_attr_get,\ - .store = iio_ad469x_attr_set\ -} - -#define AD469X_CHN_AVAIL_ATTR(_name, _priv) {\ - .name = _name,\ - .priv = _priv,\ - .show = iio_ad469x_attr_available_get,\ - .store = iio_ad469x_attr_available_set\ -} - -#define AD469X_IIO_CH(_name, _idx) {\ - .name = _name #_idx, \ - .ch_type = IIO_VOLTAGE,\ - .ch_out = false,\ - .indexed = true,\ - .channel = _idx,\ - .scan_index = _idx,\ - .scan_type = &ad469x_iio_scan_type,\ - .attributes = iio_ad469x_ch_attributes\ -} - -/* ADC data buffer size */ -#if defined(USE_SDRAM) -#define adc_data_buffer SDRAM_START_ADDRESS -#define DATA_BUFFER_SIZE SDRAM_SIZE_BYTES -#else -#define DATA_BUFFER_SIZE (32768) // 32kbytes -static int8_t adc_data_buffer[DATA_BUFFER_SIZE]; -#endif - -/* Number of IIO devices */ -#define NUM_OF_IIO_DEVICES 1 - -/* IIO trigger name */ -#define AD4696_IIO_TRIGGER_NAME "ad469x_iio_trigger" - -/* ADC Raw to Voltage conversion default scale factor for IIO client */ -#if defined(PSEUDO_BIPOLAR_MODE) -/* Device supports pseudo-bipolar mode only with INX- = Vref / 2 */ -#define DEFAULT_SCALE (((DEFAULT_VREF / 2) / ADC_MAX_COUNT_BIPOLAR) * 1000) -#else -#define DEFAULT_SCALE ((DEFAULT_VREF / ADC_MAX_COUNT_UNIPOLAR) * 1000) -#endif - -/* 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) - -#define REGISTER_MAX_VAL 0x017F - -/* Timeout count to avoid stuck into potential infinite loop while checking - * for new data into an acquisition buffer. The actual timeout factor is determined - * through 'sampling_frequency' attribute of IIO app, but this period here makes sure - * we are not stuck into a forever loop in case data capture is interrupted - * or failed in between. - * Note: This timeout factor is dependent upon the MCU clock frequency. Below timeout - * is tested for SDP-K1 platform @180Mhz default core clock */ -#define BUF_READ_TIMEOUT 0xffffffff - -/******************************************************************************/ -/*************************** Types Declarations *******************************/ -/******************************************************************************/ - -/* Pointer to the struct representing the AD4696 IIO device */ -struct ad469x_dev *p_ad469x_dev = NULL; - -/* Variable to store the sampling rate */ -static uint32_t ad469x_sampling_frequency = DEFAULT_SAMPLING_RATE; - -/* IIO interface descriptor */ -static struct iio_desc *p_ad469x_iio_desc; - -/* AD4696 IIO device descriptor */ -static struct iio_device *p_iio_ad469x_dev; - -/* AD4696 IIO hw trigger descriptor */ -static struct iio_hw_trig *ad4696_hw_trig_desc; - -/* Number of active channels in any data buffer read request */ -static volatile uint8_t num_of_active_channels = 0; - -/* Flag for checking the end of conversion in burst mode */ -static volatile bool conversion_flag = false; - -/* Flag to indicate data capture status */ -static volatile bool start_data_capture = false; - -/* Flag to indicate conversion mode status */ -static volatile bool exit_conv_mode; - -/* Flag to indicate if size of the buffer is updated according to requested - * number of samples for the multi-channel IIO buffer data alignment */ -static volatile bool buf_size_updated = false; - -/* AD469X attribute unique IDs */ -enum ad469x_attribute_ids { - ADC_RAW, - ADC_SCALE, - ADC_OFFSET, - - ADC_SAMPLING_FREQUENCY, -}; - -/* IIOD channels configurations */ -struct scan_type ad469x_iio_scan_type = { -#if (DEFAULT_POLARITY_MODE == PSEUDO_BIPOLAR_MODE) - .sign = 's', -#else - .sign = 'u', -#endif - .realbits = CHN_STORAGE_BITS, - .storagebits = ADC_RESOLUTION, - .shift = 0, - .is_big_endian = false -}; - -/* AD469X device channel attributes list */ -static struct iio_attribute iio_ad469x_ch_attributes[] = { - AD469X_CHN_ATTR("raw", ADC_RAW), - AD469X_CHN_ATTR("scale", ADC_SCALE), - AD469X_CHN_ATTR("offset", ADC_OFFSET), - END_ATTRIBUTES_ARRAY, -}; - -/* AD469X device (global) attributes list */ -static struct iio_attribute iio_ad469x_global_attributes[] = { - AD469X_CHN_ATTR("sampling_frequency", ADC_SAMPLING_FREQUENCY), - END_ATTRIBUTES_ARRAY, -}; - -static struct iio_channel iio_ad469x_channels[] = { - /* 24-bit ADC Pseudo Differential Input Channels (Count= 8) */ - AD469X_IIO_CH("Chn", 0), - AD469X_IIO_CH("Chn", 1), - AD469X_IIO_CH("Chn", 2), - AD469X_IIO_CH("Chn", 3), - AD469X_IIO_CH("Chn", 4), - AD469X_IIO_CH("Chn", 5), - AD469X_IIO_CH("Chn", 6), - AD469X_IIO_CH("Chn", 7), - AD469X_IIO_CH("Chn", 8), - AD469X_IIO_CH("Chn", 9), - AD469X_IIO_CH("Chn", 10), - AD469X_IIO_CH("Chn", 11), - AD469X_IIO_CH("Chn", 12), - AD469X_IIO_CH("Chn", 13), - AD469X_IIO_CH("Chn", 14), - AD469X_IIO_CH("Chn", 15) -}; - -/* Scale value per channel */ -static float ad469x_attr_scale_val[NO_OF_CHANNELS] = { - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE, - DEFAULT_SCALE -}; - -/* AD4696 IIOD debug attributes list */ -static struct iio_attribute ad469x_debug_attributes[] = { - END_ATTRIBUTES_ARRAY -}; - -/******************************************************************************/ -/************************ Functions Definitions *******************************/ -/******************************************************************************/ -/*! - * @brief Getter/Setter for the raw, offset and scale attribute value - * @param device[in, out]- Pointer to IIO device instance - * @param buf[in]- IIO input data buffer - * @param len[in]- Number of input bytes - * @param channel[in] - input channel - * @param priv[in] - Attribute private ID - * @return Number of characters read/written - */ -static int iio_ad469x_attr_get(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv) -{ - uint32_t adc_data_raw = 0; - /* In pseudo-bipolar mode the offset is determined depending upon - * the raw adc value. Hence it has been defined as static */ - static int32_t offset = 0; - int32_t ret; - - if (buf == NULL) { - return -ENOMEM; - } - - switch (priv) { - case ADC_RAW: - ret = ad469x_read_single_sample(p_ad469x_dev, channel->ch_num, &adc_data_raw); - if (ret) { - return ret; - } -#if (DEFAULT_POLARITY_MODE == PSEUDO_BIPOLAR_MODE) - if (adc_data_raw >= ADC_MAX_COUNT_BIPOLAR) { - offset = -ADC_MAX_COUNT_UNIPOLAR; - } else { - offset = 0; - } -#endif - return snprintf(buf, len, "%d", adc_data_raw); - - case ADC_SCALE: - return sprintf(buf, "%g", ad469x_attr_scale_val[channel->ch_num]); - - case ADC_OFFSET: - return sprintf(buf, "%d", offset); - - case ADC_SAMPLING_FREQUENCY: - return snprintf(buf, len, "%ld", ad469x_sampling_frequency); - - default: - break; - } - - return -EINVAL; -} - -/*! - * @brief Setter function for AD469X attributes - * @param device[in, out]- Pointer to IIO device instance - * @param buf[in]- IIO input data buffer - * @param len[in]- Number of expected bytes - * @param channel[in] - input channel - * @param priv[in] - Attribute private ID - * @return len in case of success, negative error code otherwise - */ -static int iio_ad469x_attr_set(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv) -{ - int ret; - - switch (priv) { - /****************** ADC global setters ******************/ - - /* These Attributes are only read only */ - case ADC_RAW: - case ADC_OFFSET: - case ADC_SCALE: - break; - - case ADC_SAMPLING_FREQUENCY: - ad469x_sampling_frequency = no_os_str_to_uint32(buf); - - ret = no_os_pwm_enable(pwm_desc); - if (ret) { - return ret; - } - - ret = no_os_pwm_set_period(pwm_desc, - CONV_TRIGGER_PERIOD_NSEC(ad469x_sampling_frequency)); - if (ret) { - return ret; - } - - ret = no_os_pwm_set_duty_cycle(pwm_desc, - CONV_TRIGGER_DUTY_CYCLE_NSEC(ad469x_sampling_frequency)); - if (ret) { - return ret; - } - - ret = no_os_pwm_disable(pwm_desc); - if (ret) { - return ret; - } - - return len; - - default: - break; - } - - return len; -} - -/*! - * @brief Attribute available getter function for AD469X attributes - * @param device[in, out]- Pointer to IIO device instance - * @param buf[in]- IIO input data buffer - * @param len[in]- Number of input bytes - * @param channel[in] - input channel - * @param priv[in] - Attribute private ID - * @return len in case of success, negative error code otherwise - */ -static int iio_ad469x_attr_available_get(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv) -{ - return len; -} - -/*! - * @brief Attribute available setter function for AD469X attributes - * @param device[in, out]- Pointer to IIO device instance - * @param buf[in]- IIO input data buffer - * @param len[in]- Number of input bytes - * @param channel[in] - input channel - * @param priv[in] - Attribute private ID - * @return len in case of success, negative error code otherwise - */ -static int iio_ad469x_attr_available_set(void *device, - char *buf, - uint32_t len, - const struct iio_ch_info *channel, - intptr_t priv) -{ - return len; -} - -/*! - * @brief Read the debug register value - * @param dev[in, out]- Pointer to IIO device instance - * @param reg[in]- Register address to read from - * @param readval[out]- Pointer to variable to read data into - * @return 0 in case of success, negative value otherwise - */ -static int32_t iio_ad469x_debug_reg_read(void *dev, - uint32_t reg, - uint32_t *readval) -{ - int32_t ret; - - if (!readval || (reg > REGISTER_MAX_VAL)) { - return -EINVAL; - } - - ret = ad469x_spi_reg_read(p_ad469x_dev, reg, (uint8_t *)readval); - if (NO_OS_IS_ERR_VALUE(ret)) { - return ret; - } - - return 0; -} - -/*! - * @brief Write the debug register value - * @param dev[in, out]- Pointer to IIO device instance - * @param reg[in]- Register address to write - * @param writeval[out]- Variable storing data to write - * @return 0 in case of success, negative value otherwise - */ -static int32_t iio_ad469x_debug_reg_write(void *dev, - uint32_t reg, - uint32_t writeval) -{ - int32_t ret; - - if (reg > REGISTER_MAX_VAL) { - return -EINVAL; - } - - ret = ad469x_spi_reg_write(p_ad469x_dev, reg, (uint8_t)writeval); - if (NO_OS_IS_ERR_VALUE(ret)) { - return ret; - } - - return 0; -} - -/*! - * @brief Start a data capture in continuous/burst mode - * @return 0 in case of success, negative error code otherwise - */ -static int32_t ad4696_adc_start_data_capture(void) -{ - int32_t ret; - start_data_capture = true; - exit_conv_mode = false; - - ret = no_os_pwm_enable(pwm_desc); - if (ret) { - return ret; - } - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - ret = iio_trig_enable(ad4696_hw_trig_desc); - if (ret) { - return ret; - } -#else - ret = no_os_irq_enable(trigger_irq_desc, TRIGGER_INT_ID); - if (ret) { - return ret; - } -#endif - - /* Enter into conversion mode */ - ret = ad469x_enter_conversion_mode(p_ad469x_dev); - if (ret) { - return ret; - } - - return 0; -} - -/*! - * @brief Stop a data capture from continuous/burst mode - * @return 0 in case of success, negative error code otherwise - */ -static int32_t ad4696_adc_stop_data_capture(void) -{ - int32_t ret; - uint32_t timeout = BUF_READ_TIMEOUT; - start_data_capture = false; - - while (!exit_conv_mode && (timeout > 0)) { - timeout--; - }; - - if (timeout == 0) { - /* This returns the empty buffer */ - return -EIO; - } - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - /* Disable the interrupt */ - ret = iio_trig_enable(ad4696_hw_trig_desc); - if (ret) { - return ret; - } -#else - ret = no_os_irq_disable(trigger_irq_desc, TRIGGER_INT_ID); - if (ret) { - return ret; - } -#endif - - /* Stop Generating PWM signal */ - ret = no_os_pwm_disable(pwm_desc); - if (ret) { - return ret; - } - - return 0; -} - -/** - * @brief Prepares the device for data transfer. - * @param dev[in, out]- Application descriptor. - * @param mask[in]- Number of bytes to transfer. - * @return 0 in case of success, error code otherwise. - */ -static int32_t iio_ad469x_prepare_transfer(void *dev, uint32_t mask) -{ - uint32_t ch_mask = 0x1; - uint8_t chn; - int32_t ret; - buf_size_updated = false; - num_of_active_channels = 0; - - /* Reset the lower byte of the standard sequencer configuration register*/ - ret = ad469x_spi_reg_write(p_ad469x_dev, - AD469x_REG_SEQ_LB, - AD469x_SEQ_CHANNELS_RESET); - if (ret) { - return ret; - } - - /* Reset the upper byte of the standard sequencer configuration register*/ - ret = ad469x_spi_reg_write(p_ad469x_dev, - AD469x_REG_SEQ_UB, - AD469x_SEQ_CHANNELS_RESET); - if (ret) { - return ret; - } - - /* Write the lower byte of the channel mask to the lower byte - * of the standard sequencer configuration register - * */ - ret = ad469x_spi_reg_write(p_ad469x_dev, - AD469x_REG_SEQ_LB, - AD469x_SEQ_LB_CONFIG(mask)); - if (ret) { - return ret; - } - - /* Write the upper byte of the channel mask to the upper byte - * of the standard sequencer configuration register - * */ - ret = ad469x_spi_reg_write(p_ad469x_dev, - AD469x_REG_SEQ_UB, - AD469x_SEQ_UB_CONFIG(mask)); - if (ret) { - return ret; - } - - /* Updates the count of total number of active channels */ - for (chn = 0; chn < NO_OF_CHANNELS; chn++) { - if (mask & ch_mask) { - num_of_active_channels++; - } - ch_mask <<= 1; - } - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - ret = ad4696_adc_start_data_capture(); - if (ret) { - return ret; - } -#endif - - return 0; -} - -/** - * @brief Terminate current data transfer - * @param dev[in, out]- Application descriptor. - * @return 0 in case of success, negative error code otherwise. - */ -static int32_t iio_ad469x_end_transfer(void *dev) -{ - int32_t ret; - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - - ret = ad4696_adc_stop_data_capture(); - if (ret) { - return ret ; - } - - return 0; -#endif -} - -/** - * @brief Push data into IIO buffer when trigger handler IRQ is invoked - * @param iio_dev_data[in] - IIO device data instance - * @return 0 in case of success or negative value otherwise - */ -int32_t ad469x_trigger_handler(struct iio_device_data *iio_dev_data) -{ - int32_t ret; - uint8_t adc_data[2] = { 0 }; - - if (start_data_capture) { - if (!buf_size_updated) { - /* Update total buffer size according to bytes per scan for proper - * alignment of multi-channel IIO buffer data */ - iio_dev_data->buffer->buf->size = ((uint32_t)(DATA_BUFFER_SIZE / - iio_dev_data->buffer->bytes_per_scan)) * iio_dev_data->buffer->bytes_per_scan; - buf_size_updated = true; - } - - /* Read the sample for channel which has been sampled recently */ - ret = no_os_spi_write_and_read(p_ad469x_dev->spi_desc, - adc_data, BYTES_PER_SAMPLE); - if (ret) { - return -EIO; - } - - no_os_swap(adc_data[0], adc_data[1]); - - return no_os_cb_write(iio_dev_data->buffer->buf, - adc_data, - BYTES_PER_SAMPLE); - } else { - /* Enter into register mode or exit from conversion mode */ - ad469x_exit_conversion_mode(p_ad469x_dev); - exit_conv_mode = true; - } - - return 0; -} - -/*! - * @brief Interrupt Service Routine to monitor end of conversion event. - * @param context[in] - Callback context (unused) - * @return none - */ -void burst_capture_callback(void *context) -{ - conversion_flag = true; - - if (!start_data_capture) { - /* Enter into register mode or exit from conversion mode */ - ad469x_exit_conversion_mode(p_ad469x_dev); - exit_conv_mode = true; - } -} - -/** - * @brief Read buffer data corresponding to AD4696 IIO device. - * @param [in, out] iio_dev_data - Device descriptor. - * @return Number of samples read. - */ -static int32_t iio_ad469x_submit_samples(struct iio_device_data *iio_dev_data) -{ - int32_t ret = 0; - -#if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE) - uint32_t timeout = BUF_READ_TIMEOUT; - uint32_t sample_index = 0; - uint8_t adc_sample[2] = { 0 }; - uint32_t nb_of_samples; - - if (!iio_dev_data) { - return -EINVAL; - } - - nb_of_samples = iio_dev_data->buffer->size / BYTES_PER_SAMPLE; - - if (!buf_size_updated) { - /* Update total buffer size according to bytes per scan for proper - * alignment of multi-channel IIO buffer data */ - iio_dev_data->buffer->buf->size = nb_of_samples * BYTES_PER_SAMPLE * - num_of_active_channels; - buf_size_updated = true; - } - - /* Start data capture */ - ret = ad4696_adc_start_data_capture(); - if (ret) { - return ret; - } - - while (sample_index < nb_of_samples) { - /* Check for status of conversion flag */ - while (!conversion_flag && timeout > 0) { - timeout--; - } - - if (timeout <= 0) { - return -ETIMEDOUT; - } - - conversion_flag = false; - - /* Read data over spi interface (in continuous read mode) */ - ret = no_os_spi_write_and_read(p_ad469x_dev->spi_desc, - adc_sample, - BYTES_PER_SAMPLE); - if (ret) { - return -EIO; - } - - no_os_swap(adc_sample[0], adc_sample[1]); - - ret = no_os_cb_write(iio_dev_data->buffer->buf, - adc_sample, - BYTES_PER_SAMPLE); - if (ret) { - return -EIO; - } - - sample_index++; - memset(adc_sample, 0, BYTES_PER_SAMPLE); - } - - /* Stop data capture */ - ret = ad4696_adc_stop_data_capture(); - if (ret) { - return ret; - } - -#endif - return 0; -} - -/********************************************************* - * IIO Attributes and Structures - ********************************************************/ -/** - * @brief Init for reading/writing and parameterization of a - * AD4696 IIO device - * @param desc[in,out] - IIO device descriptor - * @return 0 in case of success, negative error code otherwise - */ -static int32_t iio_ad4696_init(struct iio_device **desc) -{ - struct iio_device *iio_ad469x_inst; - - iio_ad469x_inst = calloc(1, sizeof(struct iio_device)); - if (!iio_ad469x_inst) { - return -EINVAL; - } - - iio_ad469x_inst->num_ch = NO_OS_ARRAY_SIZE(iio_ad469x_channels); - iio_ad469x_inst->channels = iio_ad469x_channels; - iio_ad469x_inst->attributes = iio_ad469x_global_attributes; - iio_ad469x_inst->debug_attributes = ad469x_debug_attributes; - - iio_ad469x_inst->submit = iio_ad469x_submit_samples; - iio_ad469x_inst->pre_enable = iio_ad469x_prepare_transfer; - iio_ad469x_inst->post_disable = iio_ad469x_end_transfer; - iio_ad469x_inst->read_dev = NULL; - iio_ad469x_inst->write_dev = NULL; - iio_ad469x_inst->debug_reg_read = iio_ad469x_debug_reg_read; - iio_ad469x_inst->debug_reg_write = iio_ad469x_debug_reg_write; -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - iio_ad469x_inst->trigger_handler = ad469x_trigger_handler; -#endif - - *desc = iio_ad469x_inst; - - return 0; -} - -/** - * @brief Initialization of AD4696 IIO hardware trigger specific parameters - * @param desc[in,out] - IIO hardware trigger descriptor - * @return 0 in case of success, negative error code otherwise - */ -static int32_t ad469x_iio_trigger_param_init(struct iio_hw_trig **desc) -{ - int32_t ret; - struct iio_hw_trig_init_param ad469x_hw_trig_init_params; - struct iio_hw_trig *hw_trig_desc; - - hw_trig_desc = calloc(1, sizeof(struct iio_hw_trig)); - if (!hw_trig_desc) { - return -ENOMEM; - } - - ad469x_hw_trig_init_params.irq_id = TRIGGER_INT_ID; - ad469x_hw_trig_init_params.name = AD4696_IIO_TRIGGER_NAME; - ad469x_hw_trig_init_params.irq_trig_lvl = NO_OS_IRQ_EDGE_FALLING; - ad469x_hw_trig_init_params.irq_ctrl = trigger_irq_desc; - ad469x_hw_trig_init_params.cb_info.event = NO_OS_EVT_GPIO; - ad469x_hw_trig_init_params.cb_info.peripheral = NO_OS_GPIO_IRQ; - ad469x_hw_trig_init_params.cb_info.handle = trigger_gpio_handle; - ad469x_hw_trig_init_params.iio_desc = p_ad469x_iio_desc; - - /* Initialize hardware trigger */ - ret = iio_hw_trig_init(&hw_trig_desc, &ad469x_hw_trig_init_params); - if (ret) { - return ret; - } - - *desc = hw_trig_desc; - - return 0; -} - -/** - * @brief Release resources allocated for IIO device - * @param desc[in] - IIO device descriptor - * @return 0 in case of success, negative value otherwise - */ -static int32_t iio_ad469x_remove(struct iio_desc *desc) -{ - int32_t status; - - if (!desc) { - return -EINVAL; - } - - status = iio_remove(desc); - if (status) { - return status; - } - - return 0; -} - -/** - * @brief Release resources allocated for IIO device - * @param desc[in] - IIO device descriptor - * @return 0 in case of success, negative value otherwise - */ -int32_t ad4696_iio_initialize(void) -{ - int32_t init_status; - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - static struct iio_trigger ad469x_iio_trig_desc = { - .is_synchronous = true, - .enable = NULL, - .disable = NULL - }; - - static struct iio_trigger_init iio_trigger_init_params = { - .descriptor = &ad469x_iio_trig_desc, - .name = AD4696_IIO_TRIGGER_NAME, - }; -#endif - - /* IIO interface init parameters */ - struct iio_init_param iio_init_params = { - .phy_type = USE_UART, -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - .trigs = &iio_trigger_init_params, -#endif - }; - - /* IIOD init parameters */ - static struct iio_device_init iio_device_init_params[NUM_OF_IIO_DEVICES] = { - { -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - .trigger_id = "trigger0", -#endif - } - }; - - /* Init the system peripherals */ - init_status = init_system(); - if (init_status) { - return init_status; - } - - /* Initialize AD4696 device and peripheral interface */ - init_status = ad469x_init(&p_ad469x_dev, &ad4696_init_str); - if (init_status) { - return init_status; - } - - /* Configures the polarity mode */ -#if (DEFAULT_POLARITY_MODE == PSEUDO_BIPOLAR_MODE) - init_status = ad469x_polarity_mode_select(p_ad469x_dev, - AD469x_PSEUDO_BIPOLAR_MODE); -#else - init_status = ad469x_polarity_mode_select(p_ad469x_dev, - AD469x_UNIPOLAR_MODE); -#endif - if (init_status) { - return init_status; - } - - /* Configure reference control register */ - init_status = ad469x_reference_config(p_ad469x_dev); - if (init_status) { - return init_status; - } - - /* Register and initialize the AD4696 device into IIO interface */ - init_status = iio_ad4696_init(&p_iio_ad469x_dev); - if (init_status) { - return init_status; - } - - /* Register and initialize the AD4696 device into IIO interface */ - init_status = iio_ad4696_init(&p_iio_ad469x_dev); - if (init_status) { - return init_status; - } - - /* Initialize the IIO interface */ - iio_device_init_params[0].name = ACTIVE_DEVICE_NAME; - iio_device_init_params[0].raw_buf = adc_data_buffer; - iio_device_init_params[0].raw_buf_len = DATA_BUFFER_SIZE; - - iio_device_init_params[0].dev = p_ad469x_dev; - iio_device_init_params[0].dev_descriptor = p_iio_ad469x_dev; - - iio_init_params.nb_devs++; - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - iio_init_params.nb_trigs++; -#endif - - /* Initialize the IIO interface */ - iio_init_params.uart_desc = uart_desc; - iio_init_params.devs = iio_device_init_params; - init_status = iio_init(&p_ad469x_iio_desc, &iio_init_params); - if (init_status) { - pr_err("IIO Init Failed"); - iio_ad469x_remove(p_ad469x_iio_desc); - return -ENOSYS; - } - -#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) - init_status = ad469x_iio_trigger_param_init(&ad4696_hw_trig_desc); - if (init_status) { - return init_status; - } -#endif - - init_status = init_pwm(); - if (init_status) { - return init_status; - } - - return 0; -} - -/** - * @brief Run the ad469x IIO event handler - * @return None - */ -void ad4696_iio_event_handler(void) -{ - iio_step(p_ad469x_iio_desc); -} \ No newline at end of file diff --git a/projects/ad4696_iio/src.mk b/projects/ad4696_iio/src.mk deleted file mode 100644 index 31501862..00000000 --- a/projects/ad4696_iio/src.mk +++ /dev/null @@ -1,27 +0,0 @@ -############## Platform Name ############# -PLATFORM_NAME = mbed - -################ All the .c and .cpp Files in SOURCE_DIRS are used in Build (Not Recursive) ##################### -################ PROJECT_APP Variable Points to "Project_Name/app" Directory -SOURCE_DIRS += $(PROJECT_APP) -SOURCE_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/adc/ad469x -SOURCE_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/eeprom/24xx32a -SOURCE_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/api -SOURCE_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/platform/mbed -SOURCE_DIRS += $(LIBRARIES_PATH)/no-OS/iio -SOURCE_DIRS += $(LIBRARIES_PATH)/no-OS/util -SOURCE_DIRS += $(LIBRARIES_PATH)/precision-converters-library/board_info -SOURCE_DIRS += $(LIBRARIES_PATH)/precision-converters-library/sdp_k1_sdram - -################# If Need to Add Only One File in any Directory Use "SOURCE_FILES" Variable ##################### -################ Example SOURCE_FILES += $(PROJECT_APP)/main.c - -################ SOURCE_INCLUDE_PATHS contain path of Header Files Used in Build ################################ -SOURCE_INCLUDE_PATHS += $(PROJECT_APP) -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/no-OS/drivers/adc/ad469x -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/no-OS/drivers/eeprom/24xx32a -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/no-OS/drivers/platform/mbed -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/no-OS/iio -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/no-OS/include -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/precision-converters-library/board_info -SOURCE_INCLUDE_PATHS += $(LIBRARIES_PATH)/precision-converters-library/sdp_k1_sdram diff --git a/projects/ad469x_iio/.gitignore b/projects/ad469x_iio/.gitignore new file mode 100644 index 00000000..ac5a4e23 --- /dev/null +++ b/projects/ad469x_iio/.gitignore @@ -0,0 +1,30 @@ +*.swp +*.profile* +build +Visual* +Code* +.gitattributes +.vs/ +*.sln +*.vgdbproj +*.TMP +*.user +scripts/__pycache__ +tests/.pytest_cache +tests/__pycache__ +tests/func/__pycache__ +tests/output +STM32/.settings +STM32/Core +STM32/Drivers +STM32/.mxproject +STM32/.cproject +STM32/.project +STM32/Debug +STM32/STM32F469NIHX_FLASH.ld +STM32/STM32F469NIHX_RAM.ld +STM32/*.vgdbsettings +STM32/*.vcxproj +STM32/*.vcxproj.filters +STM32/*.props +STM32/*.xml \ No newline at end of file diff --git a/projects/ad469x_iio/.mbedignore b/projects/ad469x_iio/.mbedignore new file mode 100644 index 00000000..5449861d --- /dev/null +++ b/projects/ad469x_iio/.mbedignore @@ -0,0 +1,4 @@ +app/app_config_stm32.c +app/app_config_stm32.h +app/stm32_gpio_irq_generated.c +STM32/ \ No newline at end of file diff --git a/projects/ad4696_iio/README.txt b/projects/ad469x_iio/README.txt similarity index 100% rename from projects/ad4696_iio/README.txt rename to projects/ad469x_iio/README.txt diff --git a/projects/ad469x_iio/STM32/.extSettings b/projects/ad469x_iio/STM32/.extSettings new file mode 100644 index 00000000..c37aa37e --- /dev/null +++ b/projects/ad469x_iio/STM32/.extSettings @@ -0,0 +1,24 @@ +[ProjectFiles] +HeaderPath=../app;../../../libraries/no-OS/util;../../../libraries/no-OS/include;../../../libraries/no-OS/drivers/platform/stm32;../../../libraries/no-OS/iio;../../../libraries/no-OS/drivers/api;../../../libraries/precision-converters-library/board_info/;../../../libraries/precision-converters-library/common/;../../../libraries/no-OS/drivers/eeprom/24xx32a/;../../../libraries/no-OS/drivers/adc/ad469x/; + +[Groups] +app/=../app/main.c;../app/main.c;../app/ad469x_iio.c;../app/ad469x_iio.h;../app/ad469x_support.c;../app/ad469x_support.h;../app/app_config.h;../app/app_config.c;../app/app_config_stm32.c;../app/app_config_stm32.h;../app/stm32_gpio_irq_generated.c;../app/stm32_hal.h;../app/ad469x_user_config.c;../app/ad469x_user_config.h;../app/eeprom_config.c;../app/eeprom_config.h + +app/libraries/precision-converters-library/board_info/=../../../libraries/precision-converters-library/board_info/board_info.c;../../../libraries/precision-converters-library/board_info/board_info.h; + +app/libraries/precision-converters-library/common/=../../../libraries/precision-converters-library/common/common.h;../../../libraries/precision-converters-library/common/common.c; + +app/libraries/no-OS/=../../../libraries/no-OS/util/;../../../libraries/no-OS/include; + +app/libraries/no-OS/drivers/eeprom/24xx32a/=../../../libraries/no-OS/drivers/eeprom/24xx32a/24xx32a.c;../../../libraries/no-OS/drivers/eeprom/24xx32a/24xx32a.h; + +app/libraries/no-OS/drivers/adc/ad469x/=../../../libraries/no-OS/drivers/adc/ad469x/ad469x.c;../../../libraries/no-OS/drivers/adc/ad469x/ad469x.h; + +app/libraries/no-OS/drivers/platform/stm32/=../../../libraries/no-OS/drivers/platform/stm32/stm32_delay.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_gpio.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_gpio.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_gpio_irq.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_gpio_irq.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_spi.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_spi.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_i2c.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_i2c.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_uart.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_uart.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_delay.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_irq.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_irq.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_pwm.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_pwm.h;../../../libraries/no-OS/drivers/platform/stm32/stm32_dma.c;../../../libraries/no-OS/drivers/platform/stm32/stm32_dma.h; + +app/libraries/no-OS/iio/=../../../libraries/no-OS/iio/iio.c;../../../libraries/no-OS/iio/iio.h;../../../libraries/no-OS/iio/iiod.h;../../../libraries/no-OS/iio/iiod.c;../../../libraries/no-OS/iio/iio_trigger.c;../../../libraries/no-OS/iio/iio_types.h;../../../libraries/no-OS/iio/iio_trigger.h; + +app/libraries/no-OS/drivers/api/=../../../libraries/no-OS/drivers/api/no_os_gpio.c;../../../libraries/no-OS/drivers/api/no_os_spi.c;../../../libraries/no-OS/drivers/api/no_os_irq.c;../../../libraries/no-OS/drivers/api/no_os_i2c.c;../../../libraries/no-OS/drivers/api/no_os_eeprom.c;../../../libraries/no-OS/drivers/api/no_os_uart.c;../../../libraries/no-OS/drivers/api/no_os_pwm.c;../../../libraries/no-OS/drivers/api/no_os_dma.c; + +[Others] +Define=_USE_STD_INT_TYPES;TINYIIOD_VERSION_MAJOR;TINYIIOD_VERSION_MINOR;TINYIIOD_VERSION_GIT;IIOD_BUFFER_SIZE;IIO_IGNORE_BUFF_OVERRUN_ERR;USE_PHY_COM_PORT;NO_OS_VERSION;USE_STANDARD_SPI; \ No newline at end of file diff --git a/projects/ad469x_iio/STM32/ad469x_iio.ioc b/projects/ad469x_iio/STM32/ad469x_iio.ioc new file mode 100644 index 00000000..184a786c --- /dev/null +++ b/projects/ad469x_iio/STM32/ad469x_iio.ioc @@ -0,0 +1,313 @@ +#MicroXplorer Configuration settings - do not modify +CAD.formats= +CAD.pinconfig= +CAD.provider= +Dma.Request0=SPI1_RX +Dma.Request1=TIM1_CH3 +Dma.Request2=TIM8_CH1 +Dma.Request3=TIM8_CH4/TRIG/COM +Dma.Request4=TIM8_UP +Dma.RequestsNb=5 +Dma.SPI1_RX.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.SPI1_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.SPI1_RX.0.Instance=DMA2_Stream0 +Dma.SPI1_RX.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.SPI1_RX.0.MemInc=DMA_MINC_ENABLE +Dma.SPI1_RX.0.Mode=DMA_CIRCULAR +Dma.SPI1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.SPI1_RX.0.PeriphInc=DMA_PINC_DISABLE +Dma.SPI1_RX.0.Priority=DMA_PRIORITY_VERY_HIGH +Dma.SPI1_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +Dma.TIM1_CH3.1.Direction=DMA_PERIPH_TO_MEMORY +Dma.TIM1_CH3.1.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.TIM1_CH3.1.Instance=DMA2_Stream6 +Dma.TIM1_CH3.1.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.TIM1_CH3.1.MemInc=DMA_MINC_ENABLE +Dma.TIM1_CH3.1.Mode=DMA_NORMAL +Dma.TIM1_CH3.1.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.TIM1_CH3.1.PeriphInc=DMA_PINC_DISABLE +Dma.TIM1_CH3.1.Priority=DMA_PRIORITY_LOW +Dma.TIM1_CH3.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +Dma.TIM8_CH1.2.Direction=DMA_MEMORY_TO_PERIPH +Dma.TIM8_CH1.2.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.TIM8_CH1.2.Instance=DMA2_Stream2 +Dma.TIM8_CH1.2.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.TIM8_CH1.2.MemInc=DMA_MINC_ENABLE +Dma.TIM8_CH1.2.Mode=DMA_CIRCULAR +Dma.TIM8_CH1.2.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.TIM8_CH1.2.PeriphInc=DMA_PINC_DISABLE +Dma.TIM8_CH1.2.Priority=DMA_PRIORITY_LOW +Dma.TIM8_CH1.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +Dma.TIM8_CH4/TRIG/COM.3.Direction=DMA_PERIPH_TO_MEMORY +Dma.TIM8_CH4/TRIG/COM.3.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.TIM8_CH4/TRIG/COM.3.Instance=DMA2_Stream7 +Dma.TIM8_CH4/TRIG/COM.3.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.TIM8_CH4/TRIG/COM.3.MemInc=DMA_MINC_ENABLE +Dma.TIM8_CH4/TRIG/COM.3.Mode=DMA_NORMAL +Dma.TIM8_CH4/TRIG/COM.3.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.TIM8_CH4/TRIG/COM.3.PeriphInc=DMA_PINC_DISABLE +Dma.TIM8_CH4/TRIG/COM.3.Priority=DMA_PRIORITY_LOW +Dma.TIM8_CH4/TRIG/COM.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +Dma.TIM8_UP.4.Direction=DMA_PERIPH_TO_MEMORY +Dma.TIM8_UP.4.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.TIM8_UP.4.Instance=DMA2_Stream1 +Dma.TIM8_UP.4.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.TIM8_UP.4.MemInc=DMA_MINC_ENABLE +Dma.TIM8_UP.4.Mode=DMA_NORMAL +Dma.TIM8_UP.4.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.TIM8_UP.4.PeriphInc=DMA_PINC_DISABLE +Dma.TIM8_UP.4.Priority=DMA_PRIORITY_LOW +Dma.TIM8_UP.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode +File.Version=6 +GPIO.groupedBy=Group By Peripherals +KeepUserPlacement=false +Mcu.CPN=STM32F469NIH6 +Mcu.Family=STM32F4 +Mcu.IP0=DMA +Mcu.IP1=I2C1 +Mcu.IP10=UART5 +Mcu.IP2=NVIC +Mcu.IP3=RCC +Mcu.IP4=SPI1 +Mcu.IP5=SYS +Mcu.IP6=TIM1 +Mcu.IP7=TIM2 +Mcu.IP8=TIM4 +Mcu.IP9=TIM8 +Mcu.IPNb=11 +Mcu.Name=STM32F469NIHx +Mcu.Package=TFBGA216 +Mcu.Pin0=PB8 +Mcu.Pin1=PB4 +Mcu.Pin10=PH0/OSC_IN +Mcu.Pin11=PH1/OSC_OUT +Mcu.Pin12=PG7 +Mcu.Pin13=PD12 +Mcu.Pin14=PA1 +Mcu.Pin15=PA7 +Mcu.Pin16=PB1 +Mcu.Pin17=VP_SYS_VS_Systick +Mcu.Pin18=VP_TIM1_VS_ClockSourceINT +Mcu.Pin19=VP_TIM2_VS_ClockSourceITR +Mcu.Pin2=PB3 +Mcu.Pin20=VP_TIM4_VS_ControllerModeGated +Mcu.Pin21=VP_TIM4_VS_ClockSourceITR +Mcu.Pin22=VP_TIM8_VS_ControllerModeTrigger +Mcu.Pin23=VP_TIM8_VS_ClockSourceINT +Mcu.Pin24=VP_TIM8_VS_ClockSourceITR +Mcu.Pin25=VP_TIM8_VS_no_output1 +Mcu.Pin26=VP_TIM8_VS_OPM +Mcu.Pin3=PC12 +Mcu.Pin4=PA15 +Mcu.Pin5=PB7 +Mcu.Pin6=PG9 +Mcu.Pin7=PD2 +Mcu.Pin8=PA10 +Mcu.Pin9=PC15/OSC32_OUT +Mcu.PinsNb=27 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32F469NIHx +MxCube.Version=6.11.0 +MxDb.Version=DB.6.0.110 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DMA2_Stream0_IRQn=true\:0\:0\:false\:true\:true\:1\:true\:true\:true +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.EXTI15_10_IRQn=true\:0\:0\:false\:false\:false\:true\:true\:false +NVIC.EXTI9_5_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.ForceEnableDMAVector=false +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.I2C1_ER_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.I2C1_EV_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false +NVIC.TIM1_CC_IRQn=true\:0\:0\:false\:true\:false\:2\:true\:true\:true +NVIC.TIM8_CC_IRQn=true\:0\:0\:false\:true\:false\:3\:true\:true\:true +NVIC.UART5_IRQn=true\:0\:0\:false\:false\:false\:true\:true\:false +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +PA1.Locked=true +PA1.Signal=GPIO_Output +PA10.Locked=true +PA10.Signal=S_TIM1_CH3 +PA15.GPIOParameters=GPIO_Speed +PA15.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA15.Locked=true +PA15.Signal=S_TIM2_CH1_ETR +PA7.Locked=true +PA7.Mode=Full_Duplex_Master +PA7.Signal=SPI1_MOSI +PB1.Mode=PWM Generation3 CH3N +PB1.Signal=TIM1_CH3N +PB3.GPIOParameters=GPIO_PuPd +PB3.GPIO_PuPd=GPIO_PULLUP +PB3.Locked=true +PB3.Mode=Full_Duplex_Master +PB3.Signal=SPI1_SCK +PB4.Locked=true +PB4.Mode=Full_Duplex_Master +PB4.Signal=SPI1_MISO +PB7.Locked=true +PB7.Mode=I2C +PB7.Signal=I2C1_SDA +PB8.Mode=I2C +PB8.Signal=I2C1_SCL +PC12.Mode=Asynchronous +PC12.Signal=UART5_TX +PC15/OSC32_OUT.Locked=true +PC15/OSC32_OUT.Signal=GPXTI15 +PD12.Locked=true +PD12.Signal=S_TIM4_CH1 +PD2.Mode=Asynchronous +PD2.Signal=UART5_RX +PG7.GPIOParameters=GPIO_ModeDefaultEXTI +PG7.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING +PG7.Locked=true +PG7.Signal=GPXTI7 +PG9.GPIOParameters=GPIO_Speed +PG9.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PG9.Locked=true +PG9.Signal=GPIO_Output +PH0/OSC_IN.Mode=HSE-External-Oscillator +PH0/OSC_IN.Signal=RCC_OSC_IN +PH1/OSC_OUT.Mode=HSE-External-Oscillator +PH1/OSC_OUT.Signal=RCC_OSC_OUT +PinOutPanel.CurrentBGAView=Top +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32F469NIHx +ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.27.1 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=false +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=true +ProjectManager.PreviousToolchain=STM32CubeIDE +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=ad469x_iio.ioc +ProjectManager.ProjectName=ad469x_iio +ProjectManager.ProjectStructure= +ProjectManager.RegisterCallBack=I2C,SPI,TIM,UART +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=STM32CubeIDE +ProjectManager.ToolChainLocation= +ProjectManager.UAScriptAfterPath= +ProjectManager.UAScriptBeforePath= +ProjectManager.UnderRoot=true +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-false,2-SystemClock_Config-RCC-false-HAL-false,3-MX_DMA_Init-DMA-false-HAL-false,4-MX_UART5_Init-UART5-false-HAL-false,5-MX_SPI1_Init-SPI1-false-HAL-false,6-MX_I2C1_Init-I2C1-false-HAL-false,7-MX_TIM1_Init-TIM1-false-HAL-false,8-MX_TIM2_Init-TIM2-false-HAL-false,9-MX_TIM4_Init-TIM4-false-HAL-false,10-MX_TIM8_Init-TIM8-false-HAL-false +RCC.AHBFreq_Value=180000000 +RCC.APB1CLKDivider=RCC_HCLK_DIV4 +RCC.APB1Freq_Value=45000000 +RCC.APB1TimFreq_Value=90000000 +RCC.APB2CLKDivider=RCC_HCLK_DIV2 +RCC.APB2Freq_Value=90000000 +RCC.APB2TimFreq_Value=180000000 +RCC.CortexFreq_Value=180000000 +RCC.DSIFreq_Value=20000000 +RCC.DSITXEscFreq_Value=5000000 +RCC.EthernetFreq_Value=180000000 +RCC.FCLKCortexFreq_Value=180000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=180000000 +RCC.HSE_VALUE=8000000 +RCC.HSICalibrationValue=16 +RCC.I2SFreq_Value=192000000 +RCC.IPParameters=AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,DSIFreq_Value,DSITXEscFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSICalibrationValue,I2SFreq_Value,LCDTFTFreq_Value,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLDSIFreq_Value,PLLDSIVCOFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLRCLKFreq_Value,PLLRFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIRCLKFreq_Value,PLLSourceVirtual,RTCFreq_Value,RTCHSEDivFreq_Value,SAIAFreq_Value,SAIBFreq_Value,SDIOFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USBFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAIOutputFreq_Value +RCC.LCDTFTFreq_Value=96000000 +RCC.MCO2PinFreq_Value=180000000 +RCC.PLLCLKFreq_Value=180000000 +RCC.PLLDSIFreq_Value=160000000 +RCC.PLLDSIVCOFreq_Value=320000000 +RCC.PLLI2SQCLKFreq_Value=96000000 +RCC.PLLI2SRCLKFreq_Value=192000000 +RCC.PLLM=4 +RCC.PLLN=180 +RCC.PLLQCLKFreq_Value=90000000 +RCC.PLLRCLKFreq_Value=180000000 +RCC.PLLRFreq_Value=180000000 +RCC.PLLSAIPCLKFreq_Value=192000000 +RCC.PLLSAIQCLKFreq_Value=96000000 +RCC.PLLSAIRCLKFreq_Value=192000000 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE +RCC.RTCFreq_Value=32000 +RCC.RTCHSEDivFreq_Value=4000000 +RCC.SAIAFreq_Value=96000000 +RCC.SAIBFreq_Value=96000000 +RCC.SDIOFreq_Value=90000000 +RCC.SYSCLKFreq_VALUE=180000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.USBFreq_Value=90000000 +RCC.VCOI2SOutputFreq_Value=384000000 +RCC.VCOInputFreq_Value=2000000 +RCC.VCOOutputFreq_Value=360000000 +RCC.VCOSAIOutputFreq_Value=384000000 +SH.GPXTI15.0=GPIO_EXTI15 +SH.GPXTI15.ConfNb=1 +SH.GPXTI7.0=GPIO_EXTI7 +SH.GPXTI7.ConfNb=1 +SH.S_TIM1_CH3.0=TIM1_CH3 +SH.S_TIM1_CH3.ConfNb=1 +SH.S_TIM2_CH1_ETR.0=TIM2_CH1,PWM Generation1 CH1 +SH.S_TIM2_CH1_ETR.ConfNb=1 +SH.S_TIM4_CH1.0=TIM4_CH1,PWM Generation1 CH1 +SH.S_TIM4_CH1.ConfNb=1 +SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2 +SPI1.CalculateBaudRate=45.0 MBits/s +SPI1.DataSize=SPI_DATASIZE_8BIT +SPI1.Direction=SPI_DIRECTION_2LINES +SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler +SPI1.Mode=SPI_MODE_MASTER +SPI1.VirtualType=VM_MASTER +TIM1.Channel-PWM\ Generation3\ CH3N=TIM_CHANNEL_3 +TIM1.IPParameters=Period,Channel-PWM Generation3 CH3N,TIM_MasterOutputTrigger +TIM1.Period=180-1 +TIM1.TIM_MasterOutputTrigger=TIM_TRGO_RESET +TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM2.IPParameters=Period,Channel-PWM Generation1 CH1,Pulse-PWM Generation1 CH1 +TIM2.Period=180-1 +TIM2.Pulse-PWM\ Generation1\ CH1=80-1 +TIM4.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM4.IPParameters=Channel-PWM Generation1 CH1 +TIM8.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM8.BreakState=TIM_BREAK_ENABLE +TIM8.Channel-PWM\ Generation1\ No\ Output=TIM_CHANNEL_1 +TIM8.IPParameters=Channel-PWM Generation1 No Output,RepetitionCounter,AutoReloadPreload,TIM_MasterSlaveMode,BreakState +TIM8.RepetitionCounter=2 +TIM8.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_ENABLE +UART5.BaudRate=230400 +UART5.IPParameters=VirtualMode,BaudRate +UART5.VirtualMode=Asynchronous +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_TIM1_VS_ClockSourceINT.Mode=Internal +VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT +VP_TIM2_VS_ClockSourceITR.Mode=TriggerSource_ITR0 +VP_TIM2_VS_ClockSourceITR.Signal=TIM2_VS_ClockSourceITR +VP_TIM4_VS_ClockSourceITR.Mode=TriggerSource_ITR0 +VP_TIM4_VS_ClockSourceITR.Signal=TIM4_VS_ClockSourceITR +VP_TIM4_VS_ControllerModeGated.Mode=Gated Mode +VP_TIM4_VS_ControllerModeGated.Signal=TIM4_VS_ControllerModeGated +VP_TIM8_VS_ClockSourceINT.Mode=Internal +VP_TIM8_VS_ClockSourceINT.Signal=TIM8_VS_ClockSourceINT +VP_TIM8_VS_ClockSourceITR.Mode=TriggerSource_ITR0 +VP_TIM8_VS_ClockSourceITR.Signal=TIM8_VS_ClockSourceITR +VP_TIM8_VS_ControllerModeTrigger.Mode=Trigger Mode +VP_TIM8_VS_ControllerModeTrigger.Signal=TIM8_VS_ControllerModeTrigger +VP_TIM8_VS_OPM.Mode=OPM_bit +VP_TIM8_VS_OPM.Signal=TIM8_VS_OPM +VP_TIM8_VS_no_output1.Mode=PWM Generation1 No Output +VP_TIM8_VS_no_output1.Signal=TIM8_VS_no_output1 +board=custom diff --git a/projects/ad469x_iio/app/ad469x_iio.c b/projects/ad469x_iio/app/ad469x_iio.c new file mode 100644 index 00000000..cdd4beb1 --- /dev/null +++ b/projects/ad469x_iio/app/ad469x_iio.c @@ -0,0 +1,1475 @@ +/***************************************************************************//** + * @file ad469x_iio.c + * @brief Implementation of AD469x IIO application interfaces + * @details This module acts as an interface for AD469x IIO application +******************************************************************************** + * Copyright (c) 2021-24 Analog Devices, Inc. + * + * 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 +#include +#include + +#include "app_config.h" +#include "ad469x_iio.h" +#include "ad469x_support.h" +#include "ad469x_user_config.h" +#include "common.h" +#include "no_os_error.h" +#include "no_os_util.h" +#include "no_os_gpio.h" +#include "no_os_pwm.h" +#include "no_os_print_log.h" +#include "iio_trigger.h" + +/******** Forward declaration of getter/setter functions ********/ +static int ad469x_iio_attr_get(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv); + +static int ad469x_iio_attr_set(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv); + +static int ad469x_iio_attr_available_get(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv); + +static int ad469x_iio_attr_available_set(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv); + +static void ad469x_update_scale(uint8_t ref_set); + +/******************************************************************************/ +/************************ Macros/Constants ************************************/ +/******************************************************************************/ +#define AD469X_CHN_ATTR(_name, _priv) {\ + .name = _name,\ + .priv = _priv,\ + .show = ad469x_iio_attr_get,\ + .store = ad469x_iio_attr_set\ +} + +#define AD469X_CHN_AVAIL_ATTR(_name, _priv) {\ + .name = _name,\ + .priv = _priv,\ + .show = ad469x_iio_attr_available_get,\ + .store = ad469x_iio_attr_available_set\ +} + +#define AD469X_IIO_CH(_name, _idx) {\ + .name = _name #_idx, \ + .ch_type = IIO_VOLTAGE,\ + .ch_out = false,\ + .indexed = true,\ + .channel = _idx,\ + .scan_index = _idx,\ + .scan_type = &ad469x_iio_scan_type,\ + .attributes = ad469x_iio_ch_attributes\ +} + +/* ADC data buffer size */ +#if defined(USE_SDRAM) +#define adc_data_buffer SDRAM_START_ADDRESS +#define DATA_BUFFER_SIZE SDRAM_SIZE_BYTES +#else +#define DATA_BUFFER_SIZE (32768) // 32kbytes +static int8_t adc_data_buffer[DATA_BUFFER_SIZE]; +#endif + +/* Number of IIO devices */ +#define NUM_OF_IIO_DEVICES 1 + +/* IIO trigger name */ +#define AD469x_IIO_TRIGGER_NAME "ad469x_iio_trigger" + +#define REGISTER_MAX_VAL 0x017F + +/* Converts pwm period in nanoseconds to sampling frequency in samples per second */ +#define PWM_PERIOD_TO_FREQUENCY(x) (1000000000.0 / x) + +/* Timeout count to avoid stuck into potential infinite loop while checking + * for new data into an acquisition buffer. The actual timeout factor is determined + * through 'sampling_frequency' attribute of IIO app, but this period here makes sure + * we are not stuck into a forever loop in case data capture is interrupted + * or failed in between. + * Note: This timeout factor is dependent upon the MCU clock frequency. Below timeout + * is tested for SDP-K1 platform @180Mhz default core clock */ +#define BUF_READ_TIMEOUT 0xffffffff + +/* Scale factor for gain correction */ +#define AD469X_GAIN_CORR_SCALE(x) (float)(x) / (float)(ADC_MAX_COUNT_BIPOLAR) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/* Pointer to the struct representing the AD469x IIO device */ +struct ad469x_dev *p_ad469x_dev = NULL; + +/* Variable to store the sampling rate */ +static uint32_t ad469x_sampling_frequency = SAMPLING_RATE; + +/* IIO interface descriptor */ +static struct iio_desc *p_ad469x_iio_desc; + +/* AD469x IIO device descriptor */ +static struct iio_device *p_ad469x_iio_dev; + +/* AD469x IIO hw trigger descriptor */ +static struct iio_hw_trig *ad469x_hw_trig_desc; + +/* Number of active channels in any data buffer read request */ +static volatile uint8_t num_of_active_channels = 0; + +/* Flag for checking the end of conversion in burst mode */ +volatile bool ad469x_conversion_flag = false; + +/* Flag to indicate data capture status */ +static volatile bool start_data_capture = false; + +/* Flag to indicate conversion mode status */ +static volatile bool exit_conv_mode; + +/* Variable to store number of requested samples */ +static uint32_t nb_of_samples; + +/* Variable to store start of buffer address */ +volatile uint32_t *buff_start_addr; + +/* Dummy tx data for Timer DMA */ +static uint8_t data_tx = 0; + +/* Flag to indicate if DMA has been configured for windowed capture */ +volatile bool dma_config_updated = false; + +/* Flag to indicate if size of the buffer is updated according to requested + * number of samples for the multi-channel IIO buffer data alignment */ +static volatile bool buf_size_updated = false; + +/* EVB HW validation status */ +static bool hw_mezzanine_is_valid; + +/* AD469X attribute unique IDs */ +enum ad469x_attribute_ids { + ADC_RAW, + ADC_SCALE, + ADC_OFFSET, + ADC_REFERENCE_SEL, + ADC_OFFSET_CORRECTION, + ADC_GAIN_CORRECTION, + ADC_AIN_HIGH_Z, + + ADC_SAMPLING_FREQUENCY, +}; + +/* IIOD channels configurations */ +struct scan_type ad469x_iio_scan_type = { +#if (DEFAULT_POLARITY_MODE == PSEUDO_BIPOLAR_MODE) + .sign = 's', +#else + .sign = 'u', +#endif + .realbits = CHN_STORAGE_BITS, + .storagebits = ADC_RESOLUTION, + .shift = 0, +#if (INTERFACE_MODE == SPI_DMA) + .is_big_endian = true +#else + .is_big_endian = false +#endif +}; + +/* AD469X device channel attributes list */ +static struct iio_attribute ad469x_iio_ch_attributes[] = { + AD469X_CHN_ATTR("raw", ADC_RAW), + AD469X_CHN_ATTR("scale", ADC_SCALE), + AD469X_CHN_ATTR("offset", ADC_OFFSET), + AD469X_CHN_ATTR("offset_correction", ADC_OFFSET_CORRECTION), + AD469X_CHN_ATTR("gain_correction", ADC_GAIN_CORRECTION), + AD469X_CHN_ATTR("ain_high_z", ADC_AIN_HIGH_Z), + AD469X_CHN_AVAIL_ATTR("ain_high_z_available", ADC_AIN_HIGH_Z), + END_ATTRIBUTES_ARRAY, +}; + +/* AD469X device (global) attributes list */ +static struct iio_attribute ad469x_iio_global_attributes[] = { + AD469X_CHN_ATTR("sampling_frequency", ADC_SAMPLING_FREQUENCY), + AD469X_CHN_ATTR("reference_sel", ADC_REFERENCE_SEL), + AD469X_CHN_AVAIL_ATTR("reference_sel_available", ADC_REFERENCE_SEL), + END_ATTRIBUTES_ARRAY, +}; + +static struct iio_channel ad469x_iio_channels[] = { + /* 16-bit ADC Pseudo Differential Input Channels (Count= 8) */ + AD469X_IIO_CH("Chn", 0), + AD469X_IIO_CH("Chn", 1), + AD469X_IIO_CH("Chn", 2), + AD469X_IIO_CH("Chn", 3), + AD469X_IIO_CH("Chn", 4), + AD469X_IIO_CH("Chn", 5), + AD469X_IIO_CH("Chn", 6), + AD469X_IIO_CH("Chn", 7), +#if defined(DEV_AD4696) + AD469X_IIO_CH("Chn", 8), + AD469X_IIO_CH("Chn", 9), + AD469X_IIO_CH("Chn", 10), + AD469X_IIO_CH("Chn", 11), + AD469X_IIO_CH("Chn", 12), + AD469X_IIO_CH("Chn", 13), + AD469X_IIO_CH("Chn", 14), + AD469X_IIO_CH("Chn", 15) +#endif +}; + +/* Scale value per channel */ +static float ad469x_attr_scale_val; + +/* AD469x IIOD debug attributes list */ +static struct iio_attribute ad469x_debug_attributes[] = { + END_ATTRIBUTES_ARRAY +}; + +/* Permissible values for Reference */ +static char *ad469x_ref_sel[] = { + "2P5V", + "3P0V", + "3P3V", + "4P096V", + "5V", +}; + +/* Values for status of analog input high Z Mode */ +static char *ad469x_ain_high_z[] = { + "disable", + "enable" +}; + +/* Vref Values */ +static float ad469x_vref_values[] = { 2.5, 3.0, 3.3, 4.096, 5.0 }; + +/* Offset correction value */ +static uint32_t ad469x_offset_correction = 0; + +/* Gain correction value */ +static uint32_t ad469x_gain_correction = 0x8000; + +/* Global Pointer for IIO Device Data */ +volatile struct iio_device_data* global_iio_dev_data; + +/* Global variable for number of samples */ +uint32_t global_nb_of_samples; + +/* Global variable for data read from CB functions */ +int32_t data_read; + +#if (INTERFACE_MODE == SPI_DMA) +/* STM32 SPI Init params */ +struct stm32_spi_init_param* spi_init_param; + +/* Rx DMA channel descriptor */ +struct no_os_dma_ch* rxch; + +/* Tx DMA channel descriptor */ +struct no_os_dma_ch* txch; +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Set the sampling rate and get the updated value + * supported by MCU platform + * @param sampling_rate[in,out] - Sampling rate value + * @return 0 in case of success, negative error code otherwise + */ +int32_t ad469x_update_sampling_frequency(uint32_t* sampling_rate) +{ + int32_t ret; + uint32_t pwm_period_ns; + + if (!sampling_rate) { + return -EINVAL; + } + + if (*sampling_rate > SAMPLING_RATE) { + *sampling_rate = SAMPLING_RATE; + } + +#if (INTERFACE_MODE == SPI_DMA) + cs_init_params.period_ns = CONV_TRIGGER_PERIOD_NSEC(ad469x_sampling_frequency); + pwm_init_params.period_ns = CONV_TRIGGER_PERIOD_NSEC(ad469x_sampling_frequency); + + /* Initialize PWM with the updated rate */ + ret = init_pwm(); + if (ret) { + return ret; + } + + /* Get the actual period of the PWM */ + ret = no_os_pwm_get_period(pwm_desc, &pwm_period_ns); + if (ret) { + return ret; + } + + ad469x_sampling_frequency = PWM_PERIOD_TO_FREQUENCY(pwm_period_ns); +#else +#if (ACTIVE_PLATFORM == MBED_PLATFORM) + ret = no_os_pwm_enable(pwm_desc); + if (ret) { + return ret; + } +#endif + + ret = no_os_pwm_set_period(pwm_desc, + CONV_TRIGGER_PERIOD_NSEC(ad469x_sampling_frequency)); + if (ret) { + return ret; + } + +#if (INTERFACE_MODE == SPI_INTERRUPT) + ret = no_os_pwm_set_duty_cycle(pwm_desc, + CONV_TRIGGER_DUTY_CYCLE_NSEC(CONV_TRIGGER_PERIOD_NSEC( + ad469x_sampling_frequency))); + if (ret) { + return ret; + } +#else + ret = no_os_pwm_set_period(pwm_desc, + CONV_TRIGGER_PERIOD_NSEC(ad469x_sampling_frequency)); + if (ret) { + return ret; + } +#endif + +#if (ACTIVE_PLATFORM == MBED_PLATFORM) + ret = no_os_pwm_disable(pwm_desc); + if (ret) { + return ret; + } +#endif +#endif // INTERFACE_MODE + + + return ret; +} + +/*! + * @brief Getter/Setter for the raw, offset and scale attribute value + * @param device[in, out]- Pointer to IIO device instance + * @param buf[in]- IIO input data buffer + * @param len[in]- Number of input bytes + * @param channel[in] - input channel + * @param priv[in] - Attribute private ID + * @return Number of characters read/written + */ +static int ad469x_iio_attr_get(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv) +{ + uint32_t adc_data_raw = 0; + /* In pseudo-bipolar mode the offset is determined depending upon + * the raw adc value. Hence it has been defined as static */ + static int32_t offset = 0; + uint32_t pwm_period; + int32_t ret; + enum ad469x_ref_set ref_sel; + uint8_t offset_corr_lsb; + uint8_t offset_corr_msb; + uint8_t gain_corr_lsb; + uint8_t gain_corr_msb; + float scale_value; + enum ad469x_ain_high_z ain_high_z; + + if (buf == NULL) { + return -ENOMEM; + } + + switch (priv) { + case ADC_RAW: + ret = ad469x_read_single_sample(p_ad469x_dev, channel->ch_num, &adc_data_raw); + if (ret) { + return ret; + } +#if (DEFAULT_POLARITY_MODE == PSEUDO_BIPOLAR_MODE) + if (adc_data_raw >= ADC_MAX_COUNT_BIPOLAR) { + offset = -ADC_MAX_COUNT_UNIPOLAR; + } else { + offset = 0; + } + + /* Apply the offset correction value */ + offset += ad469x_offset_correction; +#endif + return snprintf(buf, len, "%d", adc_data_raw); + + case ADC_SCALE: + scale_value = ad469x_attr_scale_val * AD469X_GAIN_CORR_SCALE( + ad469x_gain_correction); + + return sprintf(buf, "%0.10f", scale_value); + + case ADC_OFFSET: + return sprintf(buf, "%d", offset); + + case ADC_OFFSET_CORRECTION: + /* Read the offset correction register LSB */ + ret = ad469x_spi_reg_read(p_ad469x_dev, + AD469x_REG_OFFSET_IN(channel->ch_num), + &offset_corr_lsb); + if (ret) { + return ret; + } + + /* Read the offset correction register MSB */ + ret = ad469x_spi_reg_read(p_ad469x_dev, + AD469x_REG_OFFSET_IN(channel->ch_num) + 1, + &offset_corr_msb); + if (ret) { + return ret; + } + + ad469x_offset_correction = offset_corr_lsb + ((uint16_t)offset_corr_msb << 8); + + return sprintf(buf, "%d", ad469x_offset_correction); + + case ADC_GAIN_CORRECTION: + /* Read the gain correction register LSB */ + ret = ad469x_spi_reg_read(p_ad469x_dev, + AD469x_REG_GAIN_IN(channel->ch_num), + &gain_corr_lsb); + if (ret) { + return ret; + } + + /* Read the gain correction register MSB */ + ret = ad469x_spi_reg_read(p_ad469x_dev, + AD469x_REG_GAIN_IN(channel->ch_num) + 1, + &gain_corr_msb); + if (ret) { + return ret; + } + + ad469x_gain_correction = gain_corr_lsb + ((uint16_t)gain_corr_msb << 8); + + return sprintf(buf, "%d", ad469x_gain_correction); + + case ADC_SAMPLING_FREQUENCY: + return snprintf(buf, len, "%ld", ad469x_sampling_frequency); + + case ADC_REFERENCE_SEL: + ret = ad469x_get_reference(device, &ref_sel); + if (ret) { + return ret; + } + + return sprintf(buf, "%s", ad469x_ref_sel[ref_sel]); + + case ADC_AIN_HIGH_Z: + ret = ad469x_get_ain_high_z_status(device, channel->ch_num, &ain_high_z); + if (ret) { + return ret; + } + + return sprintf(buf, "%s", ad469x_ain_high_z[ain_high_z]); + + default: + return -EINVAL; + } + + return len; +} + +/*! + * @brief Setter function for AD469X attributes + * @param device[in, out]- Pointer to IIO device instance + * @param buf[in]- IIO input data buffer + * @param len[in]- Number of expected bytes + * @param channel[in] - input channel + * @param priv[in] - Attribute private ID + * @return len in case of success, negative error code otherwise + */ +static int ad469x_iio_attr_set(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv) +{ + int ret; + uint8_t ref_sel; + uint8_t offset_corr_lsb; + uint8_t offset_corr_msb; + uint8_t gain_corr_lsb; + uint8_t gain_corr_msb; + uint8_t ain_high_z; + + switch (priv) { + /****************** ADC global setters ******************/ + + /* These Attributes are only read only */ + case ADC_RAW: + case ADC_OFFSET: + case ADC_SCALE: + break; + case ADC_OFFSET_CORRECTION: + ad469x_offset_correction = no_os_str_to_uint32(buf); + offset_corr_lsb = ad469x_offset_correction; + offset_corr_msb = ad469x_offset_correction >> 8; + + /* Update offset register LSB */ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_OFFSET_IN(channel->ch_num), + offset_corr_lsb); + if (ret) { + return ret; + } + + /* Update offset register MSB */ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_OFFSET_IN(channel->ch_num) + 1, + offset_corr_msb); + if (ret) { + return ret; + } + + break; + + case ADC_GAIN_CORRECTION: + ad469x_gain_correction = no_os_str_to_uint32(buf); + gain_corr_lsb = ad469x_gain_correction; + gain_corr_msb = ad469x_gain_correction >> 8; + + /* Update offset register LSB */ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_GAIN_IN(channel->ch_num), + gain_corr_lsb); + if (ret) { + return ret; + } + + /* Update offset register MSB */ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_GAIN_IN(channel->ch_num) + 1, + gain_corr_msb); + if (ret) { + return ret; + } + + break; + + case ADC_SAMPLING_FREQUENCY: + ad469x_sampling_frequency = no_os_str_to_uint32(buf); + + ret = ad469x_update_sampling_frequency(ad469x_sampling_frequency); + if (ret) { + return ret; + } + + return len; + + case ADC_REFERENCE_SEL: + for (ref_sel = AD469x_2P4_2P75; ref_sel <= AD469x_4P5_5P1; ref_sel++) { + if (!strcmp(buf, ad469x_ref_sel[ref_sel])) { + break; + } + } + + /* Set the value of selected reference */ + ret = ad469x_set_reference(device, ref_sel); + if (ret) { + return ret; + } + + /* Update the scale value as per selected Vref */ + ad469x_update_scale(ref_sel); + + break; + + case ADC_AIN_HIGH_Z: + for (ain_high_z = AD469x_AIN_HIGH_Z_DISABLE; + ain_high_z <= AD469x_AIN_HIGH_Z_ENABLE; ain_high_z++) { + if (!strcmp(buf, ad469x_ain_high_z[ain_high_z])) { + break; + } + } + + ret = ad469x_configure_ain_high_z(device, channel->ch_num, ain_high_z); + if (ret) { + return ret; + } + + break; + + default: + return -EINVAL; + } + + return len; +} + +/*! + * @brief Attribute available getter function for AD469X attributes + * @param device[in, out]- Pointer to IIO device instance + * @param buf[in]- IIO input data buffer + * @param len[in]- Number of input bytes + * @param channel[in] - input channel + * @param priv[in] - Attribute private ID + * @return len in case of success, negative error code otherwise + */ +static int ad469x_iio_attr_available_get(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv) +{ + switch (priv) { + case ADC_REFERENCE_SEL: + return sprintf(buf, + "%s %s %s %s %s", + ad469x_ref_sel[0], + ad469x_ref_sel[1], + ad469x_ref_sel[2], + ad469x_ref_sel[3], + ad469x_ref_sel[4]); + + case ADC_AIN_HIGH_Z: + return sprintf(buf, + "%s %s", + ad469x_ain_high_z[0], + ad469x_ain_high_z[1]); + + default: + break; + } + + return len; +} + +/*! + * @brief Attribute available setter function for AD469X attributes + * @param device[in, out]- Pointer to IIO device instance + * @param buf[in]- IIO input data buffer + * @param len[in]- Number of input bytes + * @param channel[in] - input channel + * @param priv[in] - Attribute private ID + * @return len in case of success, negative error code otherwise + */ +static int ad469x_iio_attr_available_set(void *device, + char *buf, + uint32_t len, + const struct iio_ch_info *channel, + intptr_t priv) +{ + return len; +} + +/*! + * @brief Read the debug register value + * @param dev[in, out]- Pointer to IIO device instance + * @param reg[in]- Register address to read from + * @param readval[out]- Pointer to variable to read data into + * @return 0 in case of success, negative value otherwise + */ +static int32_t ad469x_iio_debug_reg_read(void *dev, + uint32_t reg, + uint32_t *readval) +{ + int32_t ret; + + if (!readval || (reg > REGISTER_MAX_VAL)) { + return -EINVAL; + } + + ret = ad469x_spi_reg_read(p_ad469x_dev, reg, (uint8_t *)readval); + if (NO_OS_IS_ERR_VALUE(ret)) { + return ret; + } + + return 0; +} + +/*! + * @brief Write the debug register value + * @param dev[in, out]- Pointer to IIO device instance + * @param reg[in]- Register address to write + * @param writeval[out]- Variable storing data to write + * @return 0 in case of success, negative value otherwise + */ +static int32_t ad469x_iio_debug_reg_write(void *dev, + uint32_t reg, + uint32_t writeval) +{ + int32_t ret; + + if (reg > REGISTER_MAX_VAL) { + return -EINVAL; + } + + ret = ad469x_spi_reg_write(p_ad469x_dev, reg, (uint8_t)writeval); + if (NO_OS_IS_ERR_VALUE(ret)) { + return ret; + } + + return 0; +} + +/*! + * @brief Start a data capture in continuous/burst mode + * @return 0 in case of success, negative error code otherwise + */ +static int32_t ad469x_adc_start_data_capture(void) +{ + int32_t ret; + start_data_capture = true; + exit_conv_mode = false; + +#if (INTERFACE_MODE == SPI_INTERRUPT) + ret = no_os_pwm_enable(pwm_desc); + if (ret) { + return ret; + } + +#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + ret = iio_trig_enable(ad469x_hw_trig_desc); + if (ret) { + return ret; + } +#else + ret = no_os_irq_enable(trigger_irq_desc, TRIGGER_INT_ID); + if (ret) { + return ret; + } +#endif +#endif + + /* Enter into conversion mode */ + ret = ad469x_enter_conversion_mode(p_ad469x_dev); + if (ret) { + return ret; + } + + return 0; +} + +/*! + * @brief Stop a data capture from continuous/burst mode + * @return 0 in case of success, negative error code otherwise + */ +static int32_t ad469x_adc_stop_data_capture(void) +{ + int32_t ret; + uint32_t timeout = BUF_READ_TIMEOUT; + start_data_capture = false; + exit_conv_mode = true; + +#if (INTERFACE_MODE == SPI_INTERRUPT) + while (!exit_conv_mode && (timeout > 0)) { + timeout--; + }; + + if (timeout == 0) { + /* This returns the empty buffer */ + return -EIO; + } + +#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + /* Disable the interrupt */ + ret = iio_trig_enable(ad469x_hw_trig_desc); + if (ret) { + return ret; + } +#else + ret = no_os_irq_disable(trigger_irq_desc, TRIGGER_INT_ID); + if (ret) { + return ret; + } +#endif + + /* Stop Generating PWM signal */ + ret = no_os_pwm_disable(pwm_desc); + if (ret) { + return ret; + } +#endif +#if (INTERFACE_MODE == SPI_DMA) + /* Stop timers */ + stm32_timer_stop(); + + /* Abort DMA Transfers */ + stm32_abort_dma_transfer(); + + /* Configure CS and CNV back to GPIO Mode */ + stm32_cs_output_gpio_config(true); + stm32_cnv_output_gpio_config(true); + + spi_init_param = ad469x_init_str.spi_init->extra; + spi_init_param->dma_init = NULL; + + /* Init SPI Interface in normal mode (Non DMA) */ + ret = no_os_spi_init(&p_ad469x_dev->spi_desc, ad469x_init_str.spi_init); + if (ret) { + return ret; + } + + /* The exit command word needs to be + * sent after the conversion pulse. + */ + ret = ad469x_trigger_conversion(p_ad469x_dev); + if (ret) { + return ret; + } + + ret = ad469x_exit_conversion_mode(p_ad469x_dev); + if (ret) { + return ret; + } +#endif + + return 0; +} + +/** + * @brief Prepares the device for data transfer. + * @param dev[in, out]- Application descriptor. + * @param mask[in]- Number of bytes to transfer. + * @return 0 in case of success, error code otherwise. + */ +static int32_t ad469x_iio_prepare_transfer(void *dev, uint32_t mask) +{ + uint32_t ch_mask = 0x1; + uint8_t chn; + int32_t ret; + buf_size_updated = false; + num_of_active_channels = 0; + + /* Reset the lower byte of the standard sequencer configuration register*/ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_SEQ_LB, + AD469x_SEQ_CHANNELS_RESET); + if (ret) { + return ret; + } + + /* Reset the upper byte of the standard sequencer configuration register*/ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_SEQ_UB, + AD469x_SEQ_CHANNELS_RESET); + if (ret) { + return ret; + } + + /* Write the lower byte of the channel mask to the lower byte + * of the standard sequencer configuration register + * */ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_SEQ_LB, + AD469x_SEQ_LB_CONFIG(mask)); + if (ret) { + return ret; + } + + /* Write the upper byte of the channel mask to the upper byte + * of the standard sequencer configuration register + * */ + ret = ad469x_spi_reg_write(p_ad469x_dev, + AD469x_REG_SEQ_UB, + AD469x_SEQ_UB_CONFIG(mask)); + if (ret) { + return ret; + } + + /* Updates the count of total number of active channels */ + for (chn = 0; chn < NO_OF_CHANNELS; chn++) { + if (mask & ch_mask) { + num_of_active_channels++; + } + ch_mask <<= 1; + } + +#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) \ + || (INTERFACE_MODE == SPI_INTERRUPT) + ret = ad469x_adc_start_data_capture(); + if (ret) { + return ret; + } +#endif +#if (INTERFACE_MODE == SPI_DMA) + ret = ad469x_enter_conversion_mode(p_ad469x_dev); + if (ret) { + return ret; + } + + spi_init_param = ad469x_init_str.spi_init->extra; + spi_init_param->pwm_init = &cs_init_params; + spi_init_param->dma_init = &ad469x_dma_init_param; + + rxch = (struct no_os_dma_ch*)no_os_calloc(1, sizeof(*rxch)); + if (!rxch) + return -ENOMEM; + + txch = (struct no_os_dma_ch*)no_os_calloc(1, sizeof(*txch)); + if (!txch) + return -ENOMEM; + + rxch->irq_num = Rx_DMA_IRQ_ID; + rxch->extra = &rxdma_channel; + txch->extra = &txdma_channel; + + spi_init_param->rxdma_ch = rxch; + spi_init_param->txdma_ch = txch; + + /* Init SPI interface in DMA Mode */ + ret = no_os_spi_init(&p_ad469x_dev->spi_desc, ad469x_init_str.spi_init); + if (ret) { + return ret; + } + + /* Configure CS and CNV in Alternate function Mode */ + stm32_cs_output_gpio_config(false); + stm32_cnv_output_gpio_config(false); + + /* Init PWM */ + ret = init_pwm(); + if (ret) { + return ret; + } + + /* Configure Timer 1 parameters */ + tim1_config(); +#endif + + return 0; +} + +/** + * @brief Terminate current data transfer + * @param dev[in, out]- Application descriptor. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad469x_iio_end_transfer(void *dev) +{ + int32_t ret; + +#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) \ + || (INTERFACE_MODE == SPI_DMA) + + ret = ad469x_adc_stop_data_capture(); + if (ret) { + return ret ; + } + + buf_size_updated = false; + dma_config_updated = false; +#endif + + return 0; +} + +/** + * @brief Push data into IIO buffer when trigger handler IRQ is invoked + * @param iio_dev_data[in] - IIO device data instance + * @return 0 in case of success or negative value otherwise + */ +int32_t ad469x_trigger_handler(struct iio_device_data *iio_dev_data) +{ + int32_t ret; + uint8_t adc_data[2] = { 0 }; + + if (start_data_capture) { + if (!buf_size_updated) { + /* Update total buffer size according to bytes per scan for proper + * alignment of multi-channel IIO buffer data */ + iio_dev_data->buffer->buf->size = ((uint32_t)(DATA_BUFFER_SIZE / + iio_dev_data->buffer->bytes_per_scan)) * iio_dev_data->buffer->bytes_per_scan; + buf_size_updated = true; + } + + /* Read the sample for channel which has been sampled recently */ + ret = no_os_spi_write_and_read(p_ad469x_dev->spi_desc, + adc_data, BYTES_PER_SAMPLE); + if (ret) { + return -EIO; + } + + no_os_swap(adc_data[0], adc_data[1]); + + return no_os_cb_write(iio_dev_data->buffer->buf, + adc_data, + BYTES_PER_SAMPLE); + } else { + /* Enter into register mode or exit from conversion mode */ + ad469x_exit_conversion_mode(p_ad469x_dev); + exit_conv_mode = true; + } + + return 0; +} + +/*! + * @brief Interrupt Service Routine to monitor end of conversion event. + * @param context[in] - Callback context (unused) + * @return none + */ +void burst_capture_callback(void *context) +{ + ad469x_conversion_flag = true; + + if (!start_data_capture) { + /* Enter into register mode or exit from conversion mode */ + ad469x_exit_conversion_mode(p_ad469x_dev); + exit_conv_mode = true; + } +} + +/** + * @brief Read buffer data corresponding to AD469x IIO device. + * @param [in, out] iio_dev_data - Device descriptor. + * @return Number of samples read. + */ +static int32_t ad469x_iio_submit_samples(struct iio_device_data *iio_dev_data) +{ + int32_t ret; + uint32_t timeout = BUF_READ_TIMEOUT; + uint32_t sample_index = 0; + uint8_t adc_sample[2] = { 0 }; + int32_t data_read; + ad469x_conversion_flag = false; + uint16_t local_tx_data = 0; + nb_of_samples = iio_dev_data->buffer->size / BYTES_PER_SAMPLE; + +#if (INTERFACE_MODE == SPI_DMA) + /* STM32 SPI Descriptor */ + struct stm32_spi_desc* sdesc = p_ad469x_dev->spi_desc->extra; + + /* SPI Message */ + struct no_os_spi_msg ad469x_spi_msg = { + .tx_buff = (uint32_t*)local_tx_data, + .bytes_number = nb_of_samples * (BYTES_PER_SAMPLE) + }; +#endif // INTERFACE_MODE + + if (!iio_dev_data) { + return -EINVAL; + } + + global_nb_of_samples = nb_of_samples; + global_iio_dev_data = iio_dev_data; + + if (!buf_size_updated) { + /* Update total buffer size according to bytes per scan for proper + * alignment of multi-channel IIO buffer data */ + iio_dev_data->buffer->buf->size = iio_dev_data->buffer->size; + buf_size_updated = true; + } + +#if (INTERFACE_MODE == SPI_INTERRUPT) + /* Start data capture */ + ret = ad469x_adc_start_data_capture(); + if (ret) { + return ret; + } + + while (sample_index < nb_of_samples) { + /* Check for status of conversion flag */ + while (!ad469x_conversion_flag && timeout > 0) { + timeout--; + } + + if (timeout <= 0) { + return -ETIMEDOUT; + } + + ad469x_conversion_flag = false; + + /* Read data over spi interface (in continuous read mode) */ + ret = no_os_spi_write_and_read(p_ad469x_dev->spi_desc, + adc_sample, + BYTES_PER_SAMPLE); + if (ret) { + return -EIO; + } + + no_os_swap(adc_sample[0], adc_sample[1]); + + ret = no_os_cb_write(iio_dev_data->buffer->buf, + adc_sample, + BYTES_PER_SAMPLE); + if (ret) { + return -EIO; + } + + sample_index++; + memset(adc_sample, 0, BYTES_PER_SAMPLE); + } + + /* Stop data capture */ + ret = ad469x_adc_stop_data_capture(); + if (ret) { + return ret; + } +#else // SPI_DMA_MODE +#if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE) + ret = no_os_cb_prepare_async_write(iio_dev_data->buffer->buf, + nb_of_samples * (BYTES_PER_SAMPLE), &buff_start_addr, &data_read); + if (ret) { + return ret; + } + + if (!dma_config_updated) { + ad469x_spi_msg.rx_buff = (uint32_t*)buff_start_addr; + + ret = no_os_spi_transfer_dma_async(p_ad469x_dev->spi_desc, &ad469x_spi_msg, + 1, receivecomplete_callback, NULL); + if (ret) { + return ret; + } + + no_os_pwm_disable(sdesc->pwm_desc); // CS PWM + htim2.Instance->CNT = 0; + htim1.Instance->CNT = 0; + dma_config_updated = true; + + /* Configure Tx trigger timer parameters */ + tim8_config(); + } + + /* Enable Timers */ + stm32_timer_enable(); + + while (ad469x_conversion_flag != true && timeout > 0) { + timeout--; + } + + if (!timeout) { + return -EIO; + } + + no_os_cb_end_async_write(iio_dev_data->buffer->buf); +#else + if (!dma_config_updated) { + ret = no_os_cb_prepare_async_write(iio_dev_data->buffer->buf, + nb_of_samples * (BYTES_PER_SAMPLE), &buff_start_addr, &data_read); + if (ret) { + return ret; + } + ad469x_spi_msg.rx_buff = (uint32_t*) buff_start_addr; + + ret = no_os_spi_transfer_dma_async(p_ad469x_dev->spi_desc, &ad469x_spi_msg, + 1, NULL, NULL); + if (ret) { + return ret; + } + no_os_pwm_disable(sdesc->pwm_desc); // CS PWM + htim2.Instance->CNT = 0; + htim1.Instance->CNT = 0; + dma_config_updated = true; + /* Configure Tx trigger timer parameters */ + tim8_config(); + + /* Enable timers */ + stm32_timer_enable(); + } + +#endif +#endif + + return 0; +} + +/********************************************************* + * IIO Attributes and Structures + ********************************************************/ +/** + * @brief Init for reading/writing and parameterization of a + * AD469x IIO device + * @param desc[in,out] - IIO device descriptor + * @return 0 in case of success, negative error code otherwise + */ +static int32_t ad469x_iio_init(struct iio_device **desc) +{ + struct iio_device *ad469x_iio_inst; + + ad469x_iio_inst = calloc(1, sizeof(struct iio_device)); + if (!ad469x_iio_inst) { + return -EINVAL; + } + + ad469x_iio_inst->num_ch = NO_OS_ARRAY_SIZE(ad469x_iio_channels); + ad469x_iio_inst->channels = ad469x_iio_channels; + ad469x_iio_inst->attributes = ad469x_iio_global_attributes; + ad469x_iio_inst->debug_attributes = ad469x_debug_attributes; + + ad469x_iio_inst->submit = ad469x_iio_submit_samples; + ad469x_iio_inst->pre_enable = ad469x_iio_prepare_transfer; + ad469x_iio_inst->post_disable = ad469x_iio_end_transfer; + ad469x_iio_inst->read_dev = NULL; + ad469x_iio_inst->write_dev = NULL; + ad469x_iio_inst->debug_reg_read = ad469x_iio_debug_reg_read; + ad469x_iio_inst->debug_reg_write = ad469x_iio_debug_reg_write; +#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + ad469x_iio_inst->trigger_handler = ad469x_trigger_handler; +#endif + + *desc = ad469x_iio_inst; + + return 0; +} + +/** + * @brief Initialization of AD469x IIO hardware trigger specific parameters + * @param desc[in,out] - IIO hardware trigger descriptor + * @return 0 in case of success, negative error code otherwise + */ +static int32_t ad469x_iio_trigger_param_init(struct iio_hw_trig **desc) +{ + int32_t ret; + struct iio_hw_trig_init_param ad469x_hw_trig_init_params; + struct iio_hw_trig *hw_trig_desc; + + hw_trig_desc = calloc(1, sizeof(struct iio_hw_trig)); + if (!hw_trig_desc) { + return -ENOMEM; + } + + ad469x_hw_trig_init_params.irq_id = TRIGGER_INT_ID; + ad469x_hw_trig_init_params.name = AD469x_IIO_TRIGGER_NAME; + ad469x_hw_trig_init_params.irq_trig_lvl = NO_OS_IRQ_EDGE_FALLING; + ad469x_hw_trig_init_params.irq_ctrl = trigger_irq_desc; + ad469x_hw_trig_init_params.cb_info.event = NO_OS_EVT_GPIO; + ad469x_hw_trig_init_params.cb_info.peripheral = NO_OS_GPIO_IRQ; + ad469x_hw_trig_init_params.cb_info.handle = trigger_gpio_handle; + ad469x_hw_trig_init_params.iio_desc = p_ad469x_iio_desc; + + /* Initialize hardware trigger */ + ret = iio_hw_trig_init(&hw_trig_desc, &ad469x_hw_trig_init_params); + if (ret) { + return ret; + } + + *desc = hw_trig_desc; + + return 0; +} + +/** + * @brief Release resources allocated for IIO device + * @param desc[in] - IIO device descriptor + * @return 0 in case of success, negative value otherwise + */ +static int32_t ad469x_iio_remove(struct iio_desc *desc) +{ + int32_t status; + + if (!desc) { + return -EINVAL; + } + + status = iio_remove(desc); + if (status) { + return status; + } + + return 0; +} + +/** + * @brief Update the scale value + * @param ref_set[in] - Value of VREF_SET + * @return None + */ +static void ad469x_update_scale(uint8_t ref_set) +{ + /* ADC Raw to Voltage conversion default scale factor for IIO client */ +#if defined(PSEUDO_BIPOLAR_MODE) + /* Device supports pseudo-bipolar mode only with INX- = Vref / 2 */ + ad469x_attr_scale_val = (((ad469x_vref_values[ref_set] / 2) / + ADC_MAX_COUNT_BIPOLAR) * 1000); +#else + ad469x_attr_scale_val = ((ad469x_vref_values[ref_set] / ADC_MAX_COUNT_UNIPOLAR) + * 1000); +#endif +} + +/** + * @brief Release resources allocated for IIO device + * @param desc[in] - IIO device descriptor + * @return 0 in case of success, negative value otherwise + */ +int32_t ad469x_iio_initialize(void) +{ + int32_t init_status; + enum ad469x_ref_set ref_set; // Value of reference + +#if (INTERFACE_MODE == SPI_INTERRUPT) && \ + (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + static struct iio_trigger ad469x_iio_trig_desc = { + .is_synchronous = true, + .enable = NULL, + .disable = NULL + }; + + static struct iio_trigger_init iio_trigger_init_params = { + .descriptor = &ad469x_iio_trig_desc, + .name = AD469x_IIO_TRIGGER_NAME, + }; +#endif + + /* IIO interface init parameters */ + struct iio_init_param iio_init_params = { + .phy_type = USE_UART, +#if (INTERFACE_MODE == SPI_INTERRUPT) && \ + (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + .trigs = &iio_trigger_init_params, +#endif + }; + + /* IIOD init parameters */ + static struct iio_device_init iio_device_init_params[NUM_OF_IIO_DEVICES] = { + { +#if (INTERFACE_MODE == SPI_INTERRUPT) && \ + (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + .trigger_id = "trigger0", +#endif + } + }; + + /* Init the system peripherals */ + init_status = init_system(); + if (init_status) { + return init_status; + } + +#if !defined(DEV_AD4696) + /* Read context attributes */ + init_status = get_iio_context_attributes(&iio_init_params.ctx_attrs, + &iio_init_params.nb_ctx_attr, + eeprom_desc, + HW_MEZZANINE_NAME, + STR(HW_CARRIER_NAME), + &hw_mezzanine_is_valid); + if (init_status) { + return init_status; + } + + if (hw_mezzanine_is_valid) { +#endif + /* Initialize AD469x device and peripheral interface */ + init_status = ad469x_init(&p_ad469x_dev, &ad469x_init_str); + if (init_status) { + return init_status; + } + + /* Configures the polarity mode */ +#if (DEFAULT_POLARITY_MODE == PSEUDO_BIPOLAR_MODE) + init_status = ad469x_polarity_mode_select(p_ad469x_dev, + AD469x_PSEUDO_BIPOLAR_MODE); +#else + init_status = ad469x_polarity_mode_select(p_ad469x_dev, + AD469x_UNIPOLAR_MODE); +#endif + if (init_status) { + return init_status; + } + + /* Configure reference control register */ + init_status = ad469x_reference_config(p_ad469x_dev); + if (init_status) { + return init_status; + } + +#if !defined(DEV_AD4696) + /* Configure the GP0 as the data ready pin */ + init_status = ad469x_set_busy(p_ad469x_dev, AD469x_busy_gp0); + if (init_status) { + return init_status; + } +#endif + + /* Register and initialize the AD469x device into IIO interface */ + init_status = ad469x_iio_init(&p_ad469x_iio_dev); + if (init_status) { + return init_status; + } + + /* Initialize the IIO interface */ + iio_device_init_params[0].name = ACTIVE_DEVICE_NAME; + iio_device_init_params[0].raw_buf = adc_data_buffer; + iio_device_init_params[0].raw_buf_len = DATA_BUFFER_SIZE; + + iio_device_init_params[0].dev = p_ad469x_dev; + iio_device_init_params[0].dev_descriptor = p_ad469x_iio_dev; + + iio_init_params.nb_devs++; + +#if (INTERFACE_MODE == SPI_INTERRUPT) && \ + (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + iio_init_params.nb_trigs++; +#endif + +#if !defined(DEV_AD4696) + } +#endif + + /* Initialize the IIO interface */ + iio_init_params.uart_desc = uart_iio_com_desc; + iio_init_params.devs = iio_device_init_params; + init_status = iio_init(&p_ad469x_iio_desc, &iio_init_params); + if (init_status) { + pr_err("IIO Init Failed"); + ad469x_iio_remove(p_ad469x_iio_desc); + return -ENOSYS; + } + +#if (INTERFACE_MODE == SPI_INTERRUPT) && \ + (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + init_status = ad469x_iio_trigger_param_init(&ad469x_hw_trig_desc); + if (init_status) { + return init_status; + } +#endif + + init_status = init_pwm(); + if (init_status) { + return init_status; + } + + /* Read the value of Set reference */ + init_status = ad469x_get_reference(p_ad469x_dev, &ref_set); + if (init_status) { + return init_status; + } + + /* Update scale */ + ad469x_update_scale(ref_set); + + return 0; +} + +/** + * @brief Run the ad469x IIO event handler + * @return None + */ +void ad469x_iio_event_handler(void) +{ + iio_step(p_ad469x_iio_desc); +} diff --git a/projects/ad4696_iio/app/iio_ad4696.h b/projects/ad469x_iio/app/ad469x_iio.h similarity index 86% rename from projects/ad4696_iio/app/iio_ad4696.h rename to projects/ad469x_iio/app/ad469x_iio.h index d6c98374..107e424e 100644 --- a/projects/ad4696_iio/app/iio_ad4696.h +++ b/projects/ad469x_iio/app/ad469x_iio.h @@ -1,6 +1,6 @@ /***************************************************************************//** -* @file iio_ad4696.h -* @brief Header file of iio_ad4696 +* @file ad469x_iio.h +* @brief Header file of ad469x_iio ******************************************************************************** * Copyright (c) 2021-22 Analog Devices, Inc. * @@ -9,8 +9,8 @@ * By using this software you agree to the terms of the associated * Analog Devices Software License Agreement. *******************************************************************************/ -#ifndef IIO_AD4696_H_ -#define IIO_AD4696_H_ +#ifndef IIO_AD469X_H_ +#define IIO_AD469X_H_ /******************************************************************************/ /***************************** Include Files **********************************/ @@ -30,7 +30,7 @@ /*************************** Types Declarations *******************************/ /******************************************************************************/ -/* AD4696 global device instance for accessing device specific APIs */ +/* AD469x global device instance for accessing device specific APIs */ extern struct ad469x_dev *p_ad469x_dev; /******************************************************************************/ @@ -38,9 +38,9 @@ extern struct ad469x_dev *p_ad469x_dev; /******************************************************************************/ /* Init the IIO interface */ -int32_t ad4696_iio_initialize(void); +int32_t ad469x_iio_initialize(void); /* Run the IIO event handler */ -void ad4696_iio_event_handler(void); +void ad469x_iio_event_handler(void); -#endif /* IIO_AD4696_H_ */ \ No newline at end of file +#endif /* IIO_AD469X_H_ */ \ No newline at end of file diff --git a/projects/ad4696_iio/app/ad4696_support.c b/projects/ad469x_iio/app/ad469x_support.c similarity index 95% rename from projects/ad4696_iio/app/ad4696_support.c rename to projects/ad469x_iio/app/ad469x_support.c index 8984f3a5..2abb0ca1 100644 --- a/projects/ad4696_iio/app/ad4696_support.c +++ b/projects/ad469x_iio/app/ad469x_support.c @@ -1,8 +1,8 @@ /*************************************************************************//** - * @file ad4696_support.c + * @file ad469x_support.c * @brief AD469x device No-OS driver supports ****************************************************************************** -* Copyright (c) 2021-22 Analog Devices, Inc. +* Copyright (c) 2021-23 Analog Devices, Inc. * * All rights reserved. * @@ -18,8 +18,8 @@ #include #include "app_config.h" -#include "ad4696_support.h" -#include "ad4696_user_config.h" +#include "ad469x_support.h" +#include "ad469x_user_config.h" #include "no_os_error.h" #include "no_os_gpio.h" #include "no_os_spi.h" @@ -120,9 +120,9 @@ int32_t ad469x_trigger_conversion(struct ad469x_dev *device) * (when used for PWM) in analog mode, after disabling or * removing the PWM object. * In this applications, the conversion trigger pin is being shared with - * ad4696 drivers as gpio output pin and is configured in output mode + * ad469x drivers as gpio output pin and is configured in output mode * only when it is initialized. - * Hence we need to reinitialize the gpio so that ad4696 driver + * Hence we need to reinitialize the gpio so that ad469x driver * can gain access to pin configured in output mode. * */ ret = no_os_gpio_remove(device->gpio_convst); @@ -130,7 +130,7 @@ int32_t ad469x_trigger_conversion(struct ad469x_dev *device) return ret; } - ret = no_os_gpio_get(&device->gpio_convst, ad4696_init_str.gpio_convst); + ret = no_os_gpio_get(&device->gpio_convst, ad469x_init_str.gpio_convst); if (ret) { return ret; } diff --git a/projects/ad4696_iio/app/ad4696_support.h b/projects/ad469x_iio/app/ad469x_support.h similarity index 92% rename from projects/ad4696_iio/app/ad4696_support.h rename to projects/ad469x_iio/app/ad469x_support.h index 75fc2a78..f7f34d3e 100644 --- a/projects/ad4696_iio/app/ad4696_support.h +++ b/projects/ad469x_iio/app/ad469x_support.h @@ -1,8 +1,8 @@ /***************************************************************************//** - * @file ad4696_support.h + * @file ad469x_support.h * @brief Header for AD469x No-OS driver supports ******************************************************************************** - * Copyright (c) 2021-22 Analog Devices, Inc. + * Copyright (c) 2021-23 Analog Devices, Inc. * * All rights reserved. * @@ -11,8 +11,8 @@ * Analog Devices Software License Agreement. *******************************************************************************/ -#ifndef AD4696_SUPPORT_H_ -#define AD4696_SUPPORT_H_ +#ifndef AD469X_SUPPORT_H_ +#define AD469X_SUPPORT_H_ /******************************************************************************/ /***************************** Include Files **********************************/ @@ -28,9 +28,6 @@ /* Number of AD469x registers */ #define NUM_OF_REGISTERS 0x17F -/* Default channel range for AD4696 devices */ -#define DEFAULT_VREF (5.0) - /* AD469x_REG_TEMPERATURE */ #define AD469x_TEMPERATURE_MSK NO_OS_GENMASK(0,0) @@ -86,4 +83,4 @@ int32_t ad469x_read_single_sample(struct ad469x_dev *device, uint8_t chn_num, uint32_t *data); -#endif /* AD4696_SUPPORT_H_ */ +#endif /* AD469X_SUPPORT_H_ */ diff --git a/projects/ad4696_iio/app/ad4696_user_config.c b/projects/ad469x_iio/app/ad469x_user_config.c similarity index 77% rename from projects/ad4696_iio/app/ad4696_user_config.c rename to projects/ad469x_iio/app/ad469x_user_config.c index e184da36..295bb3eb 100644 --- a/projects/ad4696_iio/app/ad4696_user_config.c +++ b/projects/ad469x_iio/app/ad469x_user_config.c @@ -1,8 +1,8 @@ /*************************************************************************//** - * @file ad4696_user_config.c - * @brief User configuration file for AD4696 device + * @file ad469x_user_config.c + * @brief User configuration file for AD469x device ****************************************************************************** -* Copyright (c) 2021-22 Analog Devices, Inc. +* Copyright (c) 2021-23 Analog Devices, Inc. * * All rights reserved. * @@ -17,8 +17,8 @@ #include #include "app_config.h" -#include "ad4696_user_config.h" -#include "ad4696_support.h" +#include "ad469x_user_config.h" +#include "ad469x_support.h" #include "no_os_gpio.h" /******************************************************************************/ @@ -32,36 +32,39 @@ /******************************************************************************/ struct no_os_gpio_init_param gpio_init_reset = { - .number = RESET_PIN, + .port = RESET_PORT_NUM, + .number = RESET_PIN_NUM, .platform_ops = &gpio_ops, - .extra = NULL + .extra = &reset_extra_init_params }; struct no_os_gpio_init_param gpio_init_convst = { - .number = CONVST_PIN, + .port = CNV_PORT_NUM, + .number = CNV_PIN_NUM, .platform_ops = &gpio_ops, - .extra = NULL + .extra = &cnv_extra_init_params }; struct no_os_gpio_init_param gpio_init_busy = { - .number = BUSY_PIN, + .port = BSY_PORT_NUM, + .number = BSY_PIN_NUM, .platform_ops = &gpio_ops, - .extra = &bsy_gpio_extra_init_params + .extra = &bsy_extra_init_params }; struct no_os_spi_init_param spi_init_params = { + .device_id = SPI_DEVICE_ID, .max_speed_hz = 22500000, // Max SPI Speed - .chip_select = SPI_CSB, // Chip Select + .chip_select = SPI_CS_PIN_NUM, // Chip Select .mode = NO_OS_SPI_MODE_3, // CPOL = 1, CPHA = 1 .platform_ops = &spi_ops, .extra = &spi_extra_init_params // SPI extra configurations }; -/* Initialize the AD4696 device structure */ -struct ad469x_init_param ad4696_init_str = { +/* Initialize the AD469x device structure */ +struct ad469x_init_param ad469x_init_str = { // Define SPI init parameters structure .spi_init = &spi_init_params, - // Define GPIOs init parameter structure .gpio_resetn = &gpio_init_reset, .gpio_convst = &gpio_init_convst, @@ -70,4 +73,4 @@ struct ad469x_init_param ad4696_init_str = { .std_seq_pin_pairing = AD469x_INx_COM, .ch_sequence = AD469x_standard_seq, .dev_id = ACTIVE_DEVICE -}; \ No newline at end of file +}; diff --git a/projects/ad4696_iio/app/ad4696_user_config.h b/projects/ad469x_iio/app/ad469x_user_config.h similarity index 81% rename from projects/ad4696_iio/app/ad4696_user_config.h rename to projects/ad469x_iio/app/ad469x_user_config.h index eee0078d..3d254c25 100644 --- a/projects/ad4696_iio/app/ad4696_user_config.h +++ b/projects/ad469x_iio/app/ad469x_user_config.h @@ -1,8 +1,8 @@ /*************************************************************************//** - * @file ad4696_user_config.h - * @brief Header for AD4696 user configuration file + * @file ad469x_user_config.h + * @brief Header for AD469x user configuration file ****************************************************************************** -* Copyright (c) 2021 Analog Devices, Inc. +* Copyright (c) 2021-23 Analog Devices, Inc. * * All rights reserved. * @@ -11,8 +11,8 @@ * Analog Devices Software License Agreement. *****************************************************************************/ -#ifndef AD4696_USER_CONFIG_H -#define AD4696_USER_CONFIG_H +#ifndef AD469X_USER_CONFIG_H +#define AD469X_USER_CONFIG_H /******************************************************************************/ /***************************** Include Files **********************************/ @@ -28,6 +28,6 @@ /******************************************************************************/ /********************** Variables and User Defined Data Types *****************/ /******************************************************************************/ -extern struct ad469x_init_param ad4696_init_str; +extern struct ad469x_init_param ad469x_init_str; -#endif /* end of AD4696_USER_CONFIG_H */ +#endif /* end of AD469X_USER_CONFIG_H */ diff --git a/projects/ad469x_iio/app/app_config.c b/projects/ad469x_iio/app/app_config.c new file mode 100644 index 00000000..ad561f77 --- /dev/null +++ b/projects/ad469x_iio/app/app_config.c @@ -0,0 +1,353 @@ +/***************************************************************************//** + * @file app_config.c + * @brief Application configurations module + * @details This module contains the configurations needed for IIO application +******************************************************************************** + * Copyright (c) 2021-24 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 +#include "app_config.h" +#include "no_os_error.h" +#include "no_os_gpio.h" +#include "no_os_irq.h" +#include "no_os_pwm.h" +#include "no_os_uart.h" +#include "common.h" + +/******************************************************************************/ +/************************ Macros/Constants ************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +/* UART init parameters for IIO comm port */ +struct no_os_uart_init_param uart_iio_comm_init_params = { + .device_id = UART_MODULE, + .asynchronous_rx = false, + .baud_rate = IIO_UART_BAUD_RATE, + .size = NO_OS_UART_CS_8, + .parity = NO_OS_UART_PAR_NO, + .stop = NO_OS_UART_STOP_1_BIT, + .irq_id = UART_IRQ, +#if defined(USE_VIRTUAL_COM_PORT) + .platform_ops = &vcom_ops, + .extra = &vcom_extra_init_params +#else + .platform_ops = &uart_ops, + .extra = &uart_extra_init_params +#endif +}; + +/* UART init parameters for console comm port */ +struct no_os_uart_init_param uart_console_stdio_init_params = { + .device_id = UART_MODULE, + .asynchronous_rx = false, + .baud_rate = IIO_UART_BAUD_RATE, + .size = NO_OS_UART_CS_8, + .parity = NO_OS_UART_PAR_NO, + .stop = NO_OS_UART_STOP_1_BIT, +#if defined(USE_VIRTUAL_COM_PORT) + /* If virtual com port is primary IIO comm port, use physical port for stdio + * console. Applications which does not support VCOM, should not satisfy this + * condition */ + .platform_ops = &uart_ops, + .extra = &uart_extra_init_params +#else +#if defined(CONSOLE_STDIO_PORT_AVAILABLE) + /* Applications which uses phy COM port as primary IIO comm port, + * can use VCOM as console stdio port provided it is available. + * Else, alternative phy com port can be used for console stdio ops if available */ + .platform_ops = &vcom_ops, + .extra = &vcom_extra_init_params +#endif +#endif +}; + +/* External interrupt init parameters */ +struct no_os_irq_init_param trigger_gpio_irq_params = { + .irq_ctrl_id = TRIGGER_GPIO_PIN, + .platform_ops = &trigger_gpio_irq_ops, + .extra = &trigger_gpio_irq_extra_params +}; + +/* External interrupt callback descriptor */ +static struct no_os_callback_desc ext_int_callback_desc = { + .callback = burst_capture_callback, + .ctx = NULL, + .event = NO_OS_EVT_GPIO, + .peripheral = NO_OS_GPIO_IRQ +}; + +#if (ACTIVE_PLATFORM == STM32_PLATFORM) +/* PWM GPIO init parameters */ +struct no_os_gpio_init_param pwm_gpio_params = { + .port = CNV_PORT_NUM, + .number = CNV_PIN_NUM, + .platform_ops = &gpio_ops, + .extra = &pwm_gpio_extra_init_params +}; +#endif + +/* PWM init parameters for conversion pulses */ +struct no_os_pwm_init_param pwm_init_params = { + .id = TIMER1_ID, + .period_ns = CONV_TRIGGER_PERIOD_NSEC(SAMPLING_RATE), +#if (INTERFACE_MODE == SPI_DMA) + /* If SPI_DMA is enabled, this pwm is also + * also used to trigger a spi tx dma transaction. + * */ + .duty_cycle_ns = CNV_DUTY_RATIO_NS, + .polarity = NO_OS_PWM_POLARITY_HIGH, +#else + .duty_cycle_ns = CONV_TRIGGER_DUTY_CYCLE_NSEC(CONV_TRIGGER_PERIOD_NSEC(SAMPLING_RATE)), +#endif +#if (ACTIVE_PLATFORM == STM32_PLATFORM) + .pwm_gpio = &pwm_gpio_params, +#endif + .platform_ops = &pwm_ops, + .extra = &pwm_extra_init_params +}; + +#if (INTERFACE_MODE == SPI_DMA) +/* PWM chip select init paramaters */ +struct no_os_pwm_init_param cs_init_params = { + .id = TIMER2_ID, + .period_ns = CONV_TRIGGER_PERIOD_NSEC(SAMPLING_RATE), + .duty_cycle_ns = CHIP_SELECT_DUTY_CYCLE_NS, + .polarity = NO_OS_PWM_POLARITY_HIGH, + .platform_ops = &pwm_ops, + .extra = &cs_extra_init_params +}; +#endif +/* I2C init parameters */ +static struct no_os_i2c_init_param no_os_i2c_init_params = { + .device_id = I2C_DEV_ID, + .platform_ops = &i2c_ops, + .max_speed_hz = 100000, +#if (ACTIVE_PLATFORM == MBED_PLATFORM) + .extra = &i2c_extra_init_params +#endif +}; + +/* EEPROM init parameters */ +static struct eeprom_24xx32a_init_param eeprom_extra_init_params = { + .i2c_init = &no_os_i2c_init_params +}; + +/* EEPROM init parameters */ +static struct no_os_eeprom_init_param eeprom_init_params = { + .device_id = 0, + .platform_ops = &eeprom_24xx32a_ops, + .extra = &eeprom_extra_init_params +}; + +/* Note: When in SPI_DMA mode, the pwm_desc here not only + * generates the conversion pulses, but also triggers + * the dummy spi tx dma (8 bits) transaction for fetching + * the MSB of the sampled data. + * */ +struct no_os_pwm_desc *pwm_desc; +struct no_os_uart_desc *uart_iio_com_desc; +struct no_os_uart_desc *uart_console_stdio_desc; +struct no_os_gpio_desc *trigger_gpio_desc; +struct no_os_irq_ctrl_desc *trigger_irq_desc; +struct no_os_eeprom_desc *eeprom_desc; + +#if (INTERFACE_MODE == SPI_DMA) +/* PWM descriptor for controlling the CS pulse. + */ +struct no_os_pwm_desc *cs_desc; + +/* Tx Trigger Init params */ +struct no_os_pwm_init_param tx_trigger_init_params = { + .id = TIMER8_ID, + .period_ns = TX_TRIGGER_PERIOD, + .duty_cycle_ns = TX_TRIGGER_DUTY_RATIO, + .polarity = NO_OS_PWM_POLARITY_LOW, + .platform_ops = &pwm_ops, + .extra = &tx_trigger_extra_init_params, +}; + +/* AD469x DMA Descriptor */ +struct no_os_dma_desc* ad469x_dma_desc; + +/* Tx Trgiger PWM descriptor */ +struct no_os_pwm_desc* tx_trigger_desc; + +/* DMA Init params */ +struct no_os_dma_init_param ad469x_dma_init_param = { + .id = 0, + .num_ch = AD469x_DMA_NUM_CHANNELS, + .platform_ops = &dma_ops, + .sg_handler = receivecomplete_callback, +}; + +/* CS GPIO Init params */ +struct no_os_gpio_init_param cs_pwm_gpio_params = { + .port = SPI_CS_PORT_NUM, + .number = SPI_CS_PIN_NUM, + .platform_ops = &gpio_ops, + .extra = &cs_pwm_gpio_extra_init_params +}; +#endif + +/******************************************************************************/ +/************************ Functions Prototypes ********************************/ +/******************************************************************************/ + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ +/** + * @brief Initialize the UART peripheral. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t init_uart(void) +{ + int32_t ret; + + /* Initialize the serial link for IIO communication */ + ret = no_os_uart_init(&uart_iio_com_desc, &uart_iio_comm_init_params); + if (ret) { + return ret; + } + +#if defined(CONSOLE_STDIO_PORT_AVAILABLE) + /* Initialize the serial link for console stdio communication */ + ret = no_os_uart_init(&uart_console_stdio_desc, + &uart_console_stdio_init_params); + if (ret) { + return ret; + } +#endif + + return 0; +} + +/** + * @brief Initialize the IRQ controller. + * @return 0 in case of success, negative error code otherwise. + * @details This function initialize the interrupts for system peripherals. + */ +static int32_t init_interrupt(void) +{ + int32_t ret; + + /* Init interrupt controller for external interrupt */ + ret = no_os_irq_ctrl_init(&trigger_irq_desc, &trigger_gpio_irq_params); + if (ret) { + return ret; + } + +#if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE) + /* The BSY pin has been tied as the interrupt source to sense the + * End of Conversion. The registered callback function is responsible + * of reading the raw samples via the SPI bus */ + ret = no_os_irq_register_callback(trigger_irq_desc, + TRIGGER_INT_ID, + &ext_int_callback_desc); + if (ret) { + return ret; + } + + ret = no_os_irq_trigger_level_set(trigger_irq_desc, + TRIGGER_INT_ID, NO_OS_IRQ_EDGE_FALLING); + if (ret) { + return ret; + } + + ret = no_os_irq_disable(trigger_irq_desc, TRIGGER_INT_ID); + if (ret) { + return ret; + } +#endif + return 0; +} + +/** + * @brief Initialize the PWM interface. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t init_pwm(void) +{ + int32_t ret; + + /* Initialize the PWM interface to generate conversion signal. + * If SPI_DMA is enabled, pwm interface is also used to + * trigger dummy spi tx dma transcation to fetch MSB of + * sampled data. + * */ + ret = no_os_pwm_init(&pwm_desc, &pwm_init_params); + if (ret) { + return ret; + } + + ret = no_os_pwm_disable(pwm_desc); + if (ret) { + return ret; + } + +#if (INTERFACE_MODE == SPI_DMA) + ret = no_os_pwm_init(&tx_trigger_desc, &tx_trigger_init_params); + if (ret) { + return ret; + } + + ret = no_os_pwm_disable(tx_trigger_desc); + if (ret) { + return ret; + } +#endif + + return 0; +} + +/** + * @brief Initializing system peripherals + * @return 0 in case of success, negative error code otherwise. + * @details This function initializes system peripherals for the application + */ +int32_t init_system(void) +{ + int32_t ret; + +#if (ACTIVE_PLATFORM == STM32_PLATFORM) + stm32_system_init(); +#endif + + ret = init_uart(); + if (ret) { + return ret; + } + +#if (INTERFACE_MODE == SPI_INTERRUPT) + ret = init_interrupt(); + if (ret) { + return ret; + } +#endif + +#if defined(USE_SDRAM) + ret = sdram_init(); + if (ret) { + return ret; + } +#endif + + ret = eeprom_init(&eeprom_desc, &eeprom_init_params); + if (ret) { + return ret; + } + + return 0; +} diff --git a/projects/ad4696_iio/app/app_config.h b/projects/ad469x_iio/app/app_config.h similarity index 57% rename from projects/ad4696_iio/app/app_config.h rename to projects/ad469x_iio/app/app_config.h index 17036517..55cfa28d 100644 --- a/projects/ad4696_iio/app/app_config.h +++ b/projects/ad469x_iio/app/app_config.h @@ -1,8 +1,8 @@ /*************************************************************************//** * @file app_config.h - * @brief Configuration file for AD4696 device applications + * @brief Configuration file for AD469x device applications ****************************************************************************** -* Copyright (c) 2021-23 Analog Devices, Inc. +* Copyright (c) 2021-24 Analog Devices, Inc. * * All rights reserved. * @@ -24,10 +24,11 @@ /********************** Macros and Constants Definition ***********************/ /******************************************************************************/ -/* List of supported platforms*/ -#define MBED_PLATFORM 1 +/* List of supported platforms */ +#define MBED_PLATFORM 0 +#define STM32_PLATFORM 1 -/* List of data capture modes for AD4696 device */ +/* List of data capture modes for AD469X device */ #define CONTINUOUS_DATA_CAPTURE 0 #define BURST_DATA_CAPTURE 1 @@ -35,6 +36,10 @@ #define UNIPOLAR_MODE 0 #define PSEUDO_BIPOLAR_MODE 1 +/* List of data capture methods supported by hardware platform */ +#define SPI_DMA 0 +#define SPI_INTERRUPT 1 + /* Select the ADC data capture mode (default is CC mode) */ #if !defined(DATA_CAPTURE_MODE) #define DATA_CAPTURE_MODE CONTINUOUS_DATA_CAPTURE @@ -45,6 +50,17 @@ #define ACTIVE_PLATFORM MBED_PLATFORM #endif +/* Note: The STM32 platform supports SPI interrupt and SPI DMA Mode + * for data capturing. The MBED platform supports only SPI interrupt mode + * */ +#if !defined(INTERFACE_MODE) +#if (ACTIVE_PLATFORM == STM32_PLATFORM) +#define INTERFACE_MODE SPI_DMA +#else // Mbed +#define INTERFACE_MODE SPI_INTERRUPT +#endif +#endif + /* Enable the UART/VirtualCOM port connection (default VCOM) */ //#define USE_PHY_COM_PORT // Uncomment to select UART @@ -58,26 +74,33 @@ #if (ACTIVE_PLATFORM == MBED_PLATFORM) #include "app_config_mbed.h" -#define HW_CARRIER_NAME STR(TARGET_NAME) +#define HW_CARRIER_NAME TARGET_NAME +#define uart_extra_init_params mbed_uart_extra_init_params +#define vcom_extra_init_params mbed_vcom_extra_init_params +#define bsy_extra_init_params mbed_gpio_bsy_extra_init_params +#define cnv_extra_init_params mbed_gpio_cnv_extra_init_params +#define reset_extra_init_params mbed_gpio_reset_extra_init_params +#define trigger_gpio_irq_extra_params mbed_trigger_gpio_irq_init_params +#define spi_extra_init_params mbed_spi_extra_init_params +#define pwm_extra_init_params mbed_pwm_extra_init_params +#define i2c_extra_init_params mbed_i2c_extra_init_params +#elif (ACTIVE_PLATFORM == STM32_PLATFORM) +#include "app_config_stm32.h" +#define HW_CARRIER_NAME TARGET_NAME /* Redefine the init params structure mapping w.r.t. platform */ -#define bsy_gpio_extra_init_params mbed_gpio_bsy_extra_init_params -#define trigger_gpio_irq_extra_params mbed_trigger_gpio_irq_init_params -#if defined(USE_VIRTUAL_COM_PORT) -#define uart_extra_init_params mbed_vcom_extra_init_params -#define uart_ops mbed_virtual_com_ops -#else -#define uart_extra_init_params mbed_uart_extra_init_params -#define uart_ops mbed_uart_ops -#endif -#define spi_extra_init_params mbed_spi_extra_init_params -#define pwm_extra_init_params mbed_pwm_extra_init_params -#define gpio_ops mbed_gpio_ops -#define spi_ops mbed_spi_ops -#define trigger_gpio_irq_ops mbed_gpio_irq_ops -#define trigger_gpio_handle 0 // Unused macro -#define TRIGGER_GPIO_PORT 0 // Unused macro -#define TRIGGER_INT_ID GPIO_IRQ_ID1 +#define uart_extra_init_params stm32_uart_extra_init_params +#define spi_extra_init_params stm32_spi_extra_init_params +#define cnv_extra_init_params stm32_gpio_cnv_extra_init_params +#define pwm_extra_init_params stm32_pwm_cnv_extra_init_params +#define pwm_gpio_extra_init_params stm32_pwm_gpio_extra_init_params +#define bsy_extra_init_params stm32_gpio_gp0_extra_init_params +#define gp1_extra_init_params stm32_gpio_gp1_extra_init_params +#define trigger_gpio_irq_extra_params stm32_gpio_irq_extra_init_params +#define reset_extra_init_params stm32_gpio_reset_extra_init_params +#define cs_extra_init_params stm32_cs_extra_init_params +#define tx_trigger_extra_init_params stm32_tx_trigger_extra_init_params +#define cs_pwm_gpio_extra_init_params stm32_cs_pwm_gpio_extra_init_params #else #error "No/Invalid active platform selected" #endif @@ -94,27 +117,18 @@ #if defined(DEV_AD4696) #define ACTIVE_DEVICE ID_AD4696 #define ACTIVE_DEVICE_NAME "ad4696" -#elif defined(DEV_AD4695) -#define ACTIVE_DEVICE ID_AD4695 -#define ACTIVE_DEVICE_NAME "ad4695" +#define HW_MEZZANINE_NAME "EVAL-AD4696-FMCZ" +#define NO_OF_CHANNELS 16 #else #warning No/Unsupported ADxxxxy symbol defined. AD4696 defined #define DEV_AD4696 #define ACTIVE_DEVICE ID_AD4696 #define ACTIVE_DEVICE_NAME "ad4696" +#define HW_MEZZANINE_NAME "EVAL-AD4696-ARDZ" +#define NO_OF_CHANNELS 16 #endif -#if defined(DEV_AD4696) -#define NO_OF_CHANNELS 16 -#define ADC_RESOLUTION 16 -#elif defined(DEV_AD4695) -#define NO_OF_CHANNELS 16 -#define ADC_RESOLUTION 16 -#else -/* Default config for AD4696 */ -#define NO_OF_CHANNELS 16 #define ADC_RESOLUTION 16 -#endif // **** Note for User: Polarity Mode selection **** // /* Since the pin pairing option is same for all the channels in @@ -129,9 +143,6 @@ * */ #define DEFAULT_POLARITY_MODE PSEUDO_BIPOLAR_MODE -/* Pins to be used an interrupt to trigger callback function */ -#define EXT_TRIGGER_PIN BUSY_PIN - /* ADC max count (full scale value) for unipolar inputs */ #define ADC_MAX_COUNT_UNIPOLAR (uint32_t)((1 << ADC_RESOLUTION) - 1) @@ -147,7 +158,7 @@ #endif /* Used to form a VCOM serial number */ -#define FIRMWARE_NAME "ad4696_iio" +#define FIRMWARE_NAME "ad469x_iio" #if !defined(PLATFORM_NAME) #define PLATFORM_NAME HW_CARRIER_NAME @@ -159,14 +170,37 @@ #define VIRTUAL_COM_PORT_VID 0x0456 #define VIRTUAL_COM_PORT_PID 0xb66c /* Serial number string is formed as: application name + device (target) name + platform (host) name */ -#define VIRTUAL_COM_SERIAL_NUM (FIRMWARE_NAME "_" DEVICE_NAME "_" PLATFORM_NAME) +#define VIRTUAL_COM_SERIAL_NUM (FIRMWARE_NAME "_" DEVICE_NAME "_" STR(PLATFORM_NAME)) /* Baud rate for IIO application UART interface */ #define IIO_UART_BAUD_RATE (230400) +/* Check if any serial port available for use as console stdio port */ +#if defined(USE_PHY_COM_PORT) +/* If PHY com is selected, VCOM or alternate PHY com port can act as a console stdio port */ +#if (ACTIVE_PLATFORM == MBED_PLATFORM) +#define CONSOLE_STDIO_PORT_AVAILABLE +#endif +#else +/* If VCOM is selected, PHY com port will/should act as a console stdio port */ +#define CONSOLE_STDIO_PORT_AVAILABLE +#endif + /* Enable/Disable the use of SDRAM for ADC data capture buffer */ //#define USE_SDRAM // Uncomment to use SDRAM as data buffer +/* 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) + /******************************************************************************/ /********************** Variables and User Defined Data Types *****************/ /******************************************************************************/ @@ -174,9 +208,21 @@ /******************************************************************************/ /************************ Public Declarations *********************************/ /******************************************************************************/ -extern struct no_os_uart_desc *uart_desc; +extern struct no_os_uart_desc *uart_iio_com_desc; extern struct no_os_pwm_desc *pwm_desc; extern struct no_os_irq_ctrl_desc *trigger_irq_desc; +extern struct no_os_eeprom_desc *eeprom_desc; +#if (INTERFACE_MODE == SPI_DMA) +extern struct no_os_pwm_init_param cs_init_params; +extern struct no_os_dma_init_param ad469x_dma_init_param; +extern struct no_os_gpio_init_param pwm_gpio_params; +extern struct no_os_gpio_init_param cs_pwm_gpio_params; +extern volatile struct iio_device_data* global_iio_dev_data; +extern struct no_os_pwm_init_param pwm_init_params; +extern uint32_t global_nb_of_samples; +extern volatile uint32_t* buff_start_addr; +extern int32_t data_read; +#endif /* Initializing system peripherals */ int32_t init_pwm(void); @@ -184,4 +230,4 @@ int32_t init_system(void); /* callback function in burst mode */ extern void burst_capture_callback(void *context); -#endif //APP_CONFIG_H \ No newline at end of file +#endif //APP_CONFIG_H diff --git a/projects/ad4696_iio/app/app_config_mbed.c b/projects/ad469x_iio/app/app_config_mbed.c similarity index 75% rename from projects/ad4696_iio/app/app_config_mbed.c rename to projects/ad469x_iio/app/app_config_mbed.c index 6d264d3f..9529f6ae 100644 --- a/projects/ad4696_iio/app/app_config_mbed.c +++ b/projects/ad469x_iio/app/app_config_mbed.c @@ -29,19 +29,29 @@ /* UART Mbed platform specific init parameters */ struct mbed_uart_init_param mbed_uart_extra_init_params = { .uart_tx_pin = UART_TX, - .uart_rx_pin = UART_RX + .uart_rx_pin = UART_RX, +#if defined(USE_PHY_COM_PORT) + .is_console_stdio_port = false +#else + .is_console_stdio_port = true +#endif }; /* VCOM Mbed platform specific init parameters */ struct mbed_uart_init_param mbed_vcom_extra_init_params = { .vendor_id = VIRTUAL_COM_PORT_VID, .product_id = VIRTUAL_COM_PORT_PID, - .serial_number = VIRTUAL_COM_SERIAL_NUM + .serial_number = VIRTUAL_COM_SERIAL_NUM, +#if defined(USE_VIRTUAL_COM_PORT) + .is_console_stdio_port = false +#else + .is_console_stdio_port = true +#endif }; /* External interrupt Mbed platform specific parameters */ struct mbed_gpio_irq_init_param mbed_trigger_gpio_irq_init_params = { - .gpio_irq_pin = EXT_TRIGGER_PIN + .gpio_irq_pin = BSY_PIN_NUM }; /* SPI Mbed platform specific parameters */ @@ -54,10 +64,26 @@ struct mbed_spi_init_param mbed_spi_extra_init_params = { /* PWM Mbed platform specific parameters */ struct mbed_pwm_init_param mbed_pwm_extra_init_params = { - .pwm_pin = PWM_PIN + .pwm_pin = CNV_PIN_NUM }; /* GPIO Mbed platform specific parameters */ struct mbed_gpio_init_param mbed_gpio_bsy_extra_init_params = { .pin_mode = PullNone +}; + +/* GPIO Mbed platform specific parameters */ +struct mbed_gpio_init_param mbed_gpio_reset_extra_init_params = { + .pin_mode = PullNone +}; + +/* GPIO Mbed platform specific parameters */ +struct mbed_gpio_init_param mbed_gpio_cnv_extra_init_params = { + .pin_mode = PullNone +}; + +/* I2C Mbed platform specific parameters */ +struct mbed_i2c_init_param mbed_i2c_extra_init_params = { + .i2c_sda_pin = I2C_SDA, + .i2c_scl_pin = I2C_SCL }; \ No newline at end of file diff --git a/projects/ad4696_iio/app/app_config_mbed.h b/projects/ad469x_iio/app/app_config_mbed.h similarity index 57% rename from projects/ad4696_iio/app/app_config_mbed.h rename to projects/ad469x_iio/app/app_config_mbed.h index 9222be19..17c613c0 100644 --- a/projects/ad4696_iio/app/app_config_mbed.h +++ b/projects/ad469x_iio/app/app_config_mbed.h @@ -26,12 +26,13 @@ #include "mbed_gpio_irq.h" #include "mbed_gpio.h" #include "mbed_pwm.h" +#include "mbed_i2c.h" /******************************************************************************/ /********************** Macros and Constants Definition ***********************/ /******************************************************************************/ -/* Pin mapping for AD4696 w.r.t Arduino Headers */ +/* Pin mapping for AD469x w.r.t Arduino Headers */ #define SPI_CSB ARDUINO_UNO_D10 #define SPI_HOST_SDO ARDUINO_UNO_D11 #define SPI_HOST_SDI ARDUINO_UNO_D12 @@ -41,11 +42,10 @@ #define UART_TX CONSOLE_TX #define UART_RX CONSOLE_RX -/* Pins used to trigger, reset and/or read a new (periodic) conversion event */ -#define RESET_PIN ARDUINO_UNO_D5 -#define BUSY_PIN ARDUINO_UNO_D7 -#define CONVST_PIN ARDUINO_UNO_D6 -#define PWM_PIN ARDUINO_UNO_D6 +#define I2C_SCL ARDUINO_UNO_D15 +#define I2C_SDA ARDUINO_UNO_D14 + +#define DIGI_GOOD_PIN ARDUINO_UNO_D6 /* Define the max possible sampling (or output data) rate for a given platform. * This is also used to find the time period to trigger a periodic conversion event. @@ -53,10 +53,43 @@ * IIO client. This is derived by testing the firmware on SDP-K1 controller board * @22Mhz SPI clock. The max possible ODR can vary from board to board and * data continuity is not guaranteed above this ODR on IIO oscilloscope */ -#define DEFAULT_SAMPLING_RATE (62500) +#define SAMPLING_RATE (62500) #define CONV_TRIGGER_PERIOD_NSEC(x) (((float)(1.0 / x) * 1000000) * 1000) #define CONV_TRIGGER_DUTY_CYCLE_NSEC(x) (CONV_TRIGGER_PERIOD_NSEC(x) / 10) +/* Redefine the init params structure mapping w.r.t. Mbed platform */ +#define gpio_ops mbed_gpio_ops +#define spi_ops mbed_spi_ops +#define i2c_ops mbed_i2c_ops +#define uart_ops mbed_uart_ops +#define vcom_ops mbed_virtual_com_ops +#define pwm_ops mbed_pwm_ops +#define gpio_ops mbed_gpio_ops +#define spi_ops mbed_spi_ops +#define trigger_gpio_irq_ops mbed_gpio_irq_ops +#define trigger_gpio_handle 0 // Unused macro +#define TRIGGER_GPIO_PORT 0 // Unused macro +#define TRIGGER_GPIO_PIN ARDUINO_UNO_D2 +#define TIMER1_ID 0 // Unused macro +#define TIMER2_ID 0 // Unused macro +#define TRIGGER_INT_ID 0 // Unused macro +#define I2C_DEV_ID 0 // Unused macro +#define UART_MODULE 0 // Unused macro +#define UART_IRQ 0 // Unused macro +#define SPI_DEVICE_ID 0 // Unused macro +#define SPI_CS_PIN_NUM ARDUINO_UNO_D10 +#define CNV_PIN_NUM ARDUINO_UNO_D9 +#define CNV_PORT_NUM 0 // Unused macro +#define GP0_PIN_NUM 0 // Unused macro +#define GP0_PORT_NUM 0 // Unused macro +#define GP1_PIN_NUM 0 // Unused macro +#define GP1_PORT_NUM 0 // Unused macro +#define BSY_PIN_NUM ARDUINO_UNO_D2 +#define BSY_PORT_NUM 0 // Unused macro +#define RESET_PIN_NUM ARDUINO_UNO_D4 +#define RESET_PORT_NUM 0 // Unused macro +#define MAX_SPI_SCLK 22500000 + /******************************************************************************/ /********************** Public/Extern Declarations ****************************/ /******************************************************************************/ @@ -67,5 +100,8 @@ extern struct mbed_uart_init_param mbed_uart_extra_init_params; extern struct mbed_uart_init_param mbed_vcom_extra_init_params; extern struct mbed_spi_init_param mbed_spi_extra_init_params; extern struct mbed_pwm_init_param mbed_pwm_extra_init_params; +extern struct mbed_i2c_init_param mbed_i2c_extra_init_params; +extern struct mbed_gpio_init_param mbed_gpio_reset_extra_init_params; +extern struct mbed_gpio_init_param mbed_gpio_cnv_extra_init_params; #endif /* APP_CONFIG_MBED_H_ */ \ No newline at end of file diff --git a/projects/ad469x_iio/app/app_config_stm32.c b/projects/ad469x_iio/app/app_config_stm32.c new file mode 100644 index 00000000..021c2c41 --- /dev/null +++ b/projects/ad469x_iio/app/app_config_stm32.c @@ -0,0 +1,352 @@ +/***************************************************************************//** + * @file app_config_stm32.c + * @brief Source file for STM32 platform configurations +******************************************************************************** +* Copyright (c) 2023-2024 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 +#include "app_config.h" +#include "app_config_stm32.h" +#include "ad469x_iio.h" +#include "ad469x.h" +#include "no_os_pwm.h" + +/******************************************************************************/ +/************************ Macros/Constants ************************************/ +/******************************************************************************/ + +/* Timer channel output */ +#define TIM_CCMR_CCS_OUTPUT 0 + +/* Compare pulse as trigger event */ +#define TIM_CR2_MMS_COMPARE_PULSE 3 + +/* Trigger mode as slave mode */ +#define TIM_SMCR_SMS_TRIGGER 6 + +/* TIM1 as ITR source */ +#define TIM_ITR_SOURCE 0 + +extern volatile bool ad469x_conversion_flag; + +/******************************************************************************/ +/******************** Variables and User Defined Data Types *******************/ +/******************************************************************************/ + +/************************** Note **************************/ +/* Most of the configurations specific to SPI_DMA implementation + * such as clock configuration, timer master or slave mode, + * has been done through the auto generated initialization code. + * */ + +/* STM32 UART specific parameters */ +struct stm32_uart_init_param stm32_uart_extra_init_params = { + .huart = &huart5, +}; + +/* STM32 SPI specific parameters */ +struct stm32_spi_init_param stm32_spi_extra_init_params = { + .chip_select_port = SPI_CS_PORT_NUM, + .get_input_clock = HAL_RCC_GetPCLK2Freq +}; + +/* STM32 GPIO specific parameters */ +struct stm32_gpio_init_param stm32_gpio_cnv_extra_init_params = { + .mode = GPIO_MODE_OUTPUT_PP, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, +}; + +/* STM32 GPIO specific parameters */ +struct stm32_gpio_init_param stm32_gpio_gp0_extra_init_params = { + .mode = GPIO_MODE_INPUT, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, +}; + +/* STM32 GPIO specific parameters */ +struct stm32_gpio_init_param stm32_gpio_gp1_extra_init_params = { + .mode = GPIO_MODE_INPUT, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, +}; + +/* STM32 GPIO specific parameters */ +struct stm32_gpio_init_param stm32_gpio_reset_extra_init_params = { + .mode = GPIO_MODE_OUTPUT_PP, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, +}; + +/* STM32 GPIO IRQ specific parameters */ +struct stm32_gpio_irq_init_param stm32_gpio_irq_extra_init_params = { + .port_nb = GP0_PORT_NUM, /* Port G */ +}; + +/* STM32 PWM GPIO specific parameters */ +struct stm32_gpio_init_param stm32_pwm_gpio_extra_init_params = { + .mode = GPIO_MODE_AF_PP, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, + .alternate = GPIO_AF1_TIM1 +}; + +/* STM32 PWM for specific parameters */ +struct stm32_pwm_init_param stm32_pwm_cnv_extra_init_params = { + .prescaler = TIMER_1_PRESCALER, + .timer_autoreload = true, + .mode = TIM_OC_PWM2, + .timer_chn = TIMER_CHANNEL_3, + .complementary_channel = true, + .get_timer_clock = HAL_RCC_GetPCLK2Freq, + .clock_divider = TIMER_1_CLK_DIVIDER +}; + +#if (INTERFACE_MODE == SPI_DMA) +/* STM32 PWM specific parameters */ +struct stm32_pwm_init_param stm32_cs_extra_init_params = { + .prescaler = TIMER_2_PRESCALER, + .timer_autoreload = false, + .mode = TIM_OC_PWM1, + .timer_chn = TIMER_CHANNEL_1, + .complementary_channel = false, + .get_timer_clock = HAL_RCC_GetPCLK1Freq, + .clock_divider = TIMER_2_CLK_DIVIDER +}; + +/* STM32 PWM specific init params */ +struct stm32_pwm_init_param stm32_tx_trigger_extra_init_params = { + .prescaler = TIMER_8_PRESCALER, + .timer_autoreload = true, + .mode = TIM_OC_TOGGLE, + .timer_chn = TIMER_CHANNEL_1, + .complementary_channel = false, + .get_timer_clock = HAL_RCC_GetPCLK1Freq, + .clock_divider = TIMER_8_CLK_DIVIDER +}; + +/* STM32 Tx DMA channel extra init params */ +struct stm32_dma_channel txdma_channel = { + .hdma = &hdma_tim8_ch1, + .ch_num = AD469x_TxDMA_CHANNEL_NUM, + .mem_increment = false, + .mem_data_alignment = DATA_ALIGN_BYTE, + .per_data_alignment = DATA_ALIGN_BYTE, + .dma_mode = DMA_CIRCULAR_MODE +}; + +/* STM32 Rx DMA channel extra init params */ +struct stm32_dma_channel rxdma_channel = { + .hdma = &hdma_spi1_rx, + .ch_num = AD469x_RxDMA_CHANNEL_NUM, + .mem_increment = true, + .mem_data_alignment = DATA_ALIGN_BYTE, + .per_data_alignment = DATA_ALIGN_BYTE, + .dma_mode = DMA_CIRCULAR_MODE, +}; + +/* STM32 CS GPIO Extra init params in PWM Mode */ +struct stm32_gpio_init_param stm32_cs_pwm_gpio_extra_init_params = { + .mode = GPIO_MODE_AF_PP, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, + .alternate = GPIO_AF1_TIM2 +}; + +/* STM32 CS GPIO Extra init params in GPIO Mode */ +struct stm32_gpio_init_param stm32_cs_gpio_extra_init_params = { + .mode = GPIO_MODE_OUTPUT_PP, + .speed = GPIO_SPEED_FREQ_VERY_HIGH, +}; + +/* STM32 SPI Descriptor*/ +volatile struct stm32_spi_desc* sdesc; +#endif + +/******************************************************************************/ +/************************** Functions Declaration *****************************/ +/******************************************************************************/ +void receivecomplete_callback(DMA_HandleTypeDef * hdma); + +/******************************************************************************/ +/************************** Functions Definition ******************************/ +/******************************************************************************/ +/** + * @brief Initialize the STM32 system peripherals + * @return None + */ +void stm32_system_init(void) +{ + HAL_Init(); + SystemClock_Config(); +#if (INTERFACE_MODE == SPI_DMA) + /* If SPI_DMA mode is enabled, we don't need DMA initialization + * and Timer 2 initialization which is used for generating the + * chip select signals. + */ + MX_DMA_Init(); + MX_TIM2_Init(); + MX_TIM8_Init(); +#endif + MX_GPIO_Init(); + MX_UART5_Init(); + MX_I2C1_Init(); + MX_TIM1_Init(); + MX_SPI1_Init(); +#if (INTERFACE_MODE == SPI_INTERRUPT) + HAL_NVIC_DisableIRQ(DMA2_Stream0_IRQn); +#else + HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); +#endif +} + +/** + * @brief Starts the timer signal generation for + * PWM and OC channels all at once. + * @return None + */ +void stm32_timer_enable(void) +{ +#if (INTERFACE_MODE == SPI_DMA) + sdesc = p_ad469x_dev->spi_desc->extra; + + no_os_pwm_enable(sdesc->pwm_desc); // CS Pwm; + no_os_pwm_enable(pwm_desc); // CNV PWM +#endif +} + +/** + * @brief Disable PWM signals + * @return None + */ +void stm32_timer_stop(void) +{ +#if (INTERFACE_MODE == SPI_DMA) + int ret; + sdesc = p_ad469x_dev->spi_desc->extra; + + no_os_pwm_disable(pwm_desc);// CNV PWM + no_os_pwm_disable(sdesc->pwm_desc); // CS PWM + + TIM8->DIER &= ~TIM_DIER_CC1DE; + + /* Disable RX DMA */ + CLEAR_BIT(sdesc->hspi.Instance->CR2, SPI_CR2_RXDMAEN); +#endif +} + +/** + * @brief Abort DMA Transfers + * @return None + */ +void stm32_abort_dma_transfer(void) +{ +#if (INTERFACE_MODE == SPI_DMA) + int ret; + + sdesc = p_ad469x_dev->spi_desc->extra; + + ret = no_os_dma_xfer_abort(sdesc->dma_desc, sdesc->rxdma_ch); + if (ret) { + return ret; + } + + ret = no_os_dma_xfer_abort(sdesc->dma_desc, sdesc->txdma_ch); + if (ret) { + return ret; + } +#endif +} + +/** + * @brief Configures the chip select pin as output mode. + * @param is_gpio[in] Mode of the Pin + * @return None + */ +void stm32_cs_output_gpio_config(bool is_gpio) +{ +#if (INTERFACE_MODE == SPI_DMA) + struct no_os_gpio_desc* cs_gpio_desc; + + if (is_gpio) { + cs_pwm_gpio_params.extra = &stm32_cs_gpio_extra_init_params; + } else { + cs_pwm_gpio_params.extra = &stm32_cs_pwm_gpio_extra_init_params; + } + + no_os_gpio_get(&cs_gpio_desc, &cs_pwm_gpio_params); +#endif +} + + +/** + * @brief Configures the conversion pin as output mode. + * @param is_gpio[in] Mode of the Pin + * @return None + */ +void stm32_cnv_output_gpio_config(bool is_gpio) +{ +#if (INTERFACE_MODE == SPI_DMA) + struct no_os_gpio_desc* cnv_gpio_desc; + + if (is_gpio) { + pwm_gpio_params.extra = &stm32_gpio_cnv_extra_init_params; + + } else { + pwm_gpio_params.extra = &stm32_pwm_gpio_extra_init_params; + } + no_os_gpio_get(&cnv_gpio_desc, &pwm_gpio_params); +#endif +} + +void tim1_config(void) +{ +#if (INTERFACE_MODE == SPI_DMA) + TIM1->EGR = TIM_EGR_UG;// Generate update event + TIM1->CR2 = (TIM_CR2_MMS_COMPARE_PULSE * + TIM_CR2_MMS_0); +#endif +} + +void tim8_config(void) +{ +#if (INTERFACE_MODE == SPI_DMA) + TIM8->RCR = BYTES_PER_SAMPLE - 1; + TIM8->CCMR1 = (TIM_CCMR_CCS_OUTPUT * TIM_CCMR1_CC1S_0); + TIM8->EGR = TIM_EGR_UG;// Generate update event + TIM8->SMCR = (TIM_ITR_SOURCE * TIM_SMCR_TS_0) + | (TIM_SMCR_SMS_TRIGGER * + TIM_SMCR_SMS_0); + TIM8->CR1 = (1 * TIM_CR1_OPM); // Enable one pulse mode + TIM8->DIER |= TIM_DIER_CC1DE; // Generate DMA request after overflow +#endif +} + +/** + * @brief Callback function to flag the capture of number + * of requested samples. + * @return None + */ + +void receivecomplete_callback(DMA_HandleTypeDef* hdma) +{ +#if (INTERFACE_MODE == SPI_DMA) +#if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE) + sdesc = p_ad469x_dev->spi_desc->extra; + + no_os_pwm_disable(sdesc->pwm_desc); // CS PWM + no_os_pwm_disable(pwm_desc);// CNV PWM + htim2.Instance->CNT = 0; + + ad469x_conversion_flag = true; + +#else (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE) + no_os_cb_end_async_write(global_iio_dev_data->buffer->buf); + no_os_cb_prepare_async_write(global_iio_dev_data->buffer->buf, + global_nb_of_samples * (BYTES_PER_SAMPLE), &buff_start_addr, &data_read); +#endif // DATA_CAPTURE_MODE +#endif // INTERFACE_MODE +} \ No newline at end of file diff --git a/projects/ad469x_iio/app/app_config_stm32.h b/projects/ad469x_iio/app/app_config_stm32.h new file mode 100644 index 00000000..1b239bce --- /dev/null +++ b/projects/ad469x_iio/app/app_config_stm32.h @@ -0,0 +1,161 @@ +/***************************************************************************//** + * @file app_config_stm32.h + * @brief Header file for STM32 platform configurations +******************************************************************************** + * Copyright (c) 2023,24 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. +*******************************************************************************/ + +#ifndef APP_CONFIG_STM32_H_ +#define APP_CONFIG_STM32_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include + +#include "stm32_hal.h" +#include "stm32_i2c.h" +#include "stm32_irq.h" +#include "stm32_gpio_irq.h" +#include "stm32_spi.h" +#include "stm32_gpio.h" +#include "stm32_uart.h" +#include "stm32_pwm.h" +#include "stm32_dma.h" + +/******************************************************************************/ +/********************** Macros and Constants Definition ***********************/ +/******************************************************************************/ +/* Note: The SDP-K1 board with the STM32F469NI MCU has been used +* for developing the firmware. The below parameters will change depending +* on the controller used. */ +#define TARGET_NAME SDP_K1 + +/* Pin mapping for AD4052 w.r.t Arduino Headers */ +#define I2C_DEV_ID 1 // I2C1 +#define UART_MODULE 5 // UART5 +#define UART_IRQ UART5_IRQn +#define SPI_DEVICE_ID 1 // SPI1 +#define SPI_CS_PIN_NUM 15 // PA_15 +#define SPI_CS_PORT_BASE GPIOA +#define SPI_CS_PORT_NUM 0 // PORTA = 0 +#define CNV_PIN_NUM 15 // PB_15 +#define CNV_PORT_NUM 1 // PORTB = 1 +#define CNV_PORT_BASE GPIOB +#define GP0_PIN_NUM 7 // PG_7 +#define GP0_PORT_NUM 6 // PORTG = 6 +#define GP1_PIN_NUM 10 // PG_10 +#define GP1_PORT_NUM 6 // PORTG = 6 +#define BSY_PIN_NUM GP0_PIN_NUM +#define BSY_PORT_NUM GP0_PORT_NUM +#define RESET_PIN_NUM 9 // PG_9 +#define RESET_PORT_NUM 6 // PORTG = 6 +#define TRIGGER_INT_ID GP0_PIN_NUM +#define TRIGGER_GPIO_PORT 0 // Unused macro +#define TRIGGER_GPIO_PIN GP0_PIN_NUM +#define MAX_SPI_SCLK 22500000 + +#define gpio_ops stm32_gpio_ops +#define spi_ops stm32_spi_ops +#define i2c_ops stm32_i2c_ops +#define uart_ops stm32_uart_ops +#define pwm_ops stm32_pwm_ops +#define trigger_gpio_irq_ops stm32_gpio_irq_ops +#define dma_ops stm32_dma_ops +#define trigger_gpio_handle 0 // Unused macro + +/* Timer specific macros used for calculating pwm + * period and duty cycle */ +#define TIMER_1_PRESCALER 1 +#define TIMER_2_PRESCALER 0 +#define TIMER_1_CLK_DIVIDER 2 +#define TIMER_2_CLK_DIVIDER 2 +#define TIMER_8_PRESCALER 0 +#define TIMER_8_CLK_DIVIDER 2 + +/* Timer Channels */ +#define TIMER_CHANNEL_1 1 +#define TIMER_CHANNEL_2 2 +#define TIMER_CHANNEL_3 3 + +#define TIMER1_ID 1 +#define TIMER2_ID 2 +#define TIMER8_ID 8 + +#define Rx_DMA_IRQ_ID DMA2_Stream0_IRQn +#define AD469x_TxDMA_CHANNEL_NUM DMA_CHANNEL_7 +#define AD469x_RxDMA_CHANNEL_NUM DMA_CHANNEL_3 + +/* Define the max possible sampling (or output data) rate for a given platform. + * This is also used to find the time period to trigger a periodic conversion event. + * Note: Max possible ODR is 500KSPS per channel for burst/continuous data capture on + * IIO client. This is derived by testing the firmware on STM32F469NI MCU @22Mhz SPI clock. + * The max possible ODR can vary from board to board and data continuity is not guaranteed + * above this ODR on IIO oscilloscope + */ +#if (INTERFACE_MODE == SPI_INTERRUPT) +#define SAMPLING_RATE (62500) +#define CONV_TRIGGER_DUTY_CYCLE_NSEC(x) (x / 10) +#else +#define SAMPLING_RATE (500000) +#define CHIP_SELECT_DUTY_CYCLE_NS 300 +#endif +#define CONV_TRIGGER_PERIOD_NSEC(x) (((float)(1.0 / x) * 1000000) * 1000) + +#define AD469x_DMA_NUM_CHANNELS 2 + +/* PWM configuration for 22.5MHz SPI clock */ +#define TX_TRIGGER_PERIOD 406 +#define TX_TRIGGER_DUTY_RATIO 50 + +#define CNV_DUTY_RATIO_NS 1310 + +/******************************************************************************/ +/********************** Public/Extern Declarations ****************************/ +/******************************************************************************/ +extern I2C_HandleTypeDef hi2c1; +extern SPI_HandleTypeDef hspi1; +extern DMA_HandleTypeDef hdma_spi1_rx; +extern TIM_HandleTypeDef htim1; +extern TIM_HandleTypeDef htim2; +extern DMA_HandleTypeDef hdma_tim1_ch3; +extern DMA_HandleTypeDef hdma_tim1_ch2; +extern TIM_HandleTypeDef htim12; +extern UART_HandleTypeDef huart5; +extern volatile bool data_ready; + +extern struct stm32_uart_init_param stm32_uart_extra_init_params; +extern struct stm32_spi_init_param stm32_spi_extra_init_params; +extern struct stm32_gpio_init_param stm32_gpio_cnv_extra_init_params; +extern struct stm32_gpio_init_param stm32_gpio_gp0_extra_init_params; +extern struct stm32_gpio_init_param stm32_gpio_gp1_extra_init_params; +extern struct stm32_gpio_init_param stm32_gpio_reset_extra_init_params; +extern struct stm32_gpio_irq_init_param stm32_gpio_irq_extra_init_params; +extern struct stm32_gpio_init_param stm32_pwm_gpio_extra_init_params; +extern struct stm32_pwm_init_param stm32_pwm_cnv_extra_init_params; +#if (INTERFACE_MODE == SPI_DMA) +extern struct stm32_pwm_init_param stm32_cs_extra_init_params; +extern struct stm32_pwm_init_param stm32_tx_trigger_extra_init_params; +extern DMA_HandleTypeDef hdma_tim8_ch1; +extern struct stm32_dma_channel rxdma_channel; +extern struct stm32_dma_channel txdma_channel; +extern struct stm32_gpio_init_param stm32_cs_pwm_gpio_extra_init_params; + +void receivecomplete_callback(DMA_HandleTypeDef* hdma); +void stm32_cnv_output_gpio_config(bool is_gpio); +void stm32_cs_output_gpio_config(bool is_gpio); +void stm32_abort_dma_transfer(void); +void stm32_timer_enable(void); +void stm32_timer_stop(void); +void tim8_config(void); +void tim1_config(void); +#endif + +void stm32_system_init(void); + +#endif /* APP_CONFIG_STM32_H_ */ diff --git a/projects/ad4696_iio/app/main.c b/projects/ad469x_iio/app/main.c similarity index 83% rename from projects/ad4696_iio/app/main.c rename to projects/ad469x_iio/app/main.c index 73c09344..e02b9ec2 100644 --- a/projects/ad4696_iio/app/main.c +++ b/projects/ad469x_iio/app/main.c @@ -1,10 +1,10 @@ /***************************************************************************//** * @file main.c - * @brief Main module for AD4696 IIO application - * @details This module invokes the AD4696 IIO interfaces + * @brief Main module for AD469x IIO application + * @details This module invokes the AD469x IIO interfaces * through forever loop. ******************************************************************************** - * Copyright (c) 2021-22 Analog Devices, Inc. + * Copyright (c) 2021-23 Analog Devices, Inc. * * All rights reserved. * @@ -19,7 +19,7 @@ #include #include -#include "iio_ad4696.h" +#include "ad469x_iio.h" /******************************************************************************/ /********************** Macros and Constants Definitions **********************/ @@ -35,14 +35,14 @@ */ int main(void) { - /* Initialize the AD4696 IIO interface */ - if (ad4696_iio_initialize()) { + /* Initialize the AD469x IIO interface */ + if (ad469x_iio_initialize()) { printf("IIO initialization failure!!\r\n"); } while (1) { /* Monitor the IIO client events */ - ad4696_iio_event_handler(); + ad469x_iio_event_handler(); } } diff --git a/projects/ad469x_iio/app/stm32_gpio_irq_generated.c b/projects/ad469x_iio/app/stm32_gpio_irq_generated.c new file mode 100644 index 00000000..15e71236 --- /dev/null +++ b/projects/ad469x_iio/app/stm32_gpio_irq_generated.c @@ -0,0 +1,43 @@ +#include "no_os_error.h" +#include "stm32_hal.h" +int stm32_get_exti_irq_id_from_pin(uint8_t pin_nb, IRQn_Type *irq_id) +{ + /* Note: The irq_id number used here are specific to STM32F469NI MCU on the SDP-K1 board + * The below parameters will change depending on the controller used. + * */ + switch(pin_nb) { + case 4: + *irq_id = EXTI4_IRQn; + break; + case 0: + *irq_id = EXTI0_IRQn; + break; + case 2: + *irq_id = EXTI2_IRQn; + break; + case 1: + *irq_id = EXTI1_IRQn; + break; + case 3: + *irq_id = EXTI3_IRQn; + break; + case 5: + case 6: + case 7: + case 8: + case 9: + *irq_id = EXTI9_5_IRQn; + break; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + *irq_id = EXTI15_10_IRQn; + break; + default: + return -ENOSYS; + } + return 0; +} diff --git a/projects/ad4696_iio/ci_build.groovy b/projects/ad469x_iio/ci_build.groovy similarity index 97% rename from projects/ad4696_iio/ci_build.groovy rename to projects/ad469x_iio/ci_build.groovy index 28ffef33..ccba97c1 100644 --- a/projects/ad4696_iio/ci_build.groovy +++ b/projects/ad469x_iio/ci_build.groovy @@ -4,7 +4,7 @@ def getBuildMatrix(projectName) { // This map is for building all targets when merging to main or develop branches buildMap = [ PLATFORM_NAME: ['SDP_K1', 'NUCLEO_L552ZE_Q', 'DISCO_F769NI'], - ACTIVE_DEVICE: ['DEV_AD4696'], + ACTIVE_DEVICE: ['DEV_AD4697'], COM_TYPE: ['USE_PHY_COM_PORT','USE_VIRTUAL_COM_PORT'], SDRAM: ['USE_SDRAM', 'NO_SDRAM'] ] @@ -12,7 +12,7 @@ def getBuildMatrix(projectName) { // This map is for building targets that is always build buildMap = [ PLATFORM_NAME: ['SDP_K1'], - ACTIVE_DEVICE: ['DEV_AD4696'], + ACTIVE_DEVICE: ['DEV_AD4697'], COM_TYPE: ['USE_VIRTUAL_COM_PORT'], SDRAM: ['NO_SDRAM'] ] @@ -58,7 +58,7 @@ def getTestMatrix(projectName) { // This map is for testing all targets when merging to main or develop branches testMap = [ PLATFORM_NAME: ['SDP_K1'], - ACTIVE_DEVICE: ['DEV_AD4696'], + ACTIVE_DEVICE: ['DEV_AD4697'], COM_TYPE: ['USE_VIRTUAL_COM_PORT'], SDRAM: ['NO_SDRAM'] ] @@ -66,7 +66,7 @@ def getTestMatrix(projectName) { // This map is for testing target that is always tested testMap = [ PLATFORM_NAME: ['SDP_K1'], - ACTIVE_DEVICE: ['DEV_AD4696'], + ACTIVE_DEVICE: ['DEV_AD4697'], COM_TYPE: ['USE_VIRTUAL_COM_PORT'], SDRAM: ['NO_SDRAM'] ] diff --git a/projects/ad4696_iio/Makefile b/projects/ad469x_iio/makefile similarity index 100% rename from projects/ad4696_iio/Makefile rename to projects/ad469x_iio/makefile diff --git a/projects/ad4696_iio/scripts/ad4696.py b/projects/ad469x_iio/scripts/ad4696.py similarity index 100% rename from projects/ad4696_iio/scripts/ad4696.py rename to projects/ad469x_iio/scripts/ad4696.py diff --git a/projects/ad4696_iio/scripts/ad4696_data_capture.py b/projects/ad469x_iio/scripts/ad4696_data_capture.py similarity index 100% rename from projects/ad4696_iio/scripts/ad4696_data_capture.py rename to projects/ad469x_iio/scripts/ad4696_data_capture.py diff --git a/projects/ad4696_iio/scripts/requirements.txt b/projects/ad469x_iio/scripts/requirements.txt similarity index 100% rename from projects/ad4696_iio/scripts/requirements.txt rename to projects/ad469x_iio/scripts/requirements.txt diff --git a/projects/ad469x_iio/src.mk b/projects/ad469x_iio/src.mk new file mode 100644 index 00000000..9764b313 --- /dev/null +++ b/projects/ad469x_iio/src.mk @@ -0,0 +1,24 @@ +# All the .c and .cpp and .h Files in SRC_DIRS are used in Build (Recursive) +SRC_DIRS += $(PROJECT_APP_PATH) +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/adc/ad469x +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/eeprom/24xx32a +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/api +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/platform/mbed +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/iio +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/util +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/include +SRC_DIRS += $(LIBRARIES_PATH)/precision-converters-library/common +SRC_DIRS += $(LIBRARIES_PATH)/precision-converters-library/board_info +SRC_DIRS += $(LIBRARIES_PATH)/precision-converters-library/sdp_k1_sdram + +ifeq 'mbed' '$(PLATFORM)' +# ALL_IGNORED_FILES variable used for excluding particular source files in SRC_DIRS in Build +SRC_DIRS += $(LIBRARIES_PATH)/no-OS/drivers/platform/mbed/ +ALL_IGNORED_FILES += $(PROJECT_APP_PATH)/app_config_stm32.c +ALL_IGNORED_FILES += $(PROJECT_APP_PATH)/stm32_gpio_irq_generated.c +ALL_IGNORED_FILES += $(PROJECT_APP_PATH)/app_config_stm32.h + +# Extra Macros +override NEW_CFLAGS += -DACTIVE_PLATFORM=MBED_PLATFORM +endif + diff --git a/projects/ad4696_iio/tests/conftest.py b/projects/ad469x_iio/tests/conftest.py similarity index 95% rename from projects/ad4696_iio/tests/conftest.py rename to projects/ad469x_iio/tests/conftest.py index a50b4439..f9fea197 100644 --- a/projects/ad4696_iio/tests/conftest.py +++ b/projects/ad469x_iio/tests/conftest.py @@ -39,7 +39,7 @@ def serial_port(serialport, serialcomtype, devicename, platformname): print("{}: {} [{}]".format(port, desc, hwid)) # Get the COM port number corresponding to virtualCOM port parameters for vcom_serial_port in serial.tools.list_ports.comports(): - if (vcom_serial_port.vid == ADI_USB_VID and vcom_serial_port.pid == ADI_USB_PID and vcom_serial_port.serial_number == vcom_serial_number): + if (vcom_serial_port.vid == ADI_USB_VID and vcom_serial_port.pid == ADI_USB_PID and (vcom_serial_port.serial_number).lower() == (vcom_serial_number).lower()): break yield vcom_serial_port.device else: diff --git a/projects/ad4696_iio/tests/func/ad4696.py b/projects/ad469x_iio/tests/func/ad4696.py similarity index 100% rename from projects/ad4696_iio/tests/func/ad4696.py rename to projects/ad469x_iio/tests/func/ad4696.py diff --git a/projects/ad4696_iio/tests/func/test_ad4696_example.py b/projects/ad469x_iio/tests/func/test_ad4696_example.py similarity index 100% rename from projects/ad4696_iio/tests/func/test_ad4696_example.py rename to projects/ad469x_iio/tests/func/test_ad4696_example.py diff --git a/projects/ad4696_iio/tests/pytest.ini b/projects/ad469x_iio/tests/pytest.ini similarity index 100% rename from projects/ad4696_iio/tests/pytest.ini rename to projects/ad469x_iio/tests/pytest.ini