ADAQ7980 no-OS Driver

See drivers/adc/adaq7980 (doxygen) for the Doxygen documentation.

Supported Devices

Overview

The ADAQ7980 is a 16-bit µModule ADC with an integrated system-in-package design. It combines a high-accuracy SAR ADC, low-power ADC driver, reference buffer, and power management block within a compact 5mm x 4mm LGA package. The ADAQ7980 operates at 1 MSPS. The ADAQ7980 supports multiple supply voltages (1.8V to 5V) and offers a wide temperature operating range of -55°C to +125°C. Featuring SPI-compatible interfaces, it can be configured in daisy-chain modes, suitable for automated test equipment and medical instruments.

Applications

  • Automated test equipment (ATE)

  • Battery powered instrumentation

  • Communications

  • Data acquisition

  • Process control

  • Medical instruments

Operation Modes

Mode Name

Description

Configuration Bits

Typical Use Case

3-wire CS Mode with Busy Indicator

Operates with an SPI-compatible interface using a busy indicator for conversion status.

Set SDI high; Use 3-wire with CNV, SCK, and SDO enabled.

Suitable for applications needing minimal connections while retaining conversion status visibility.

3-wire CS Mode Without Busy Indicator

Uses SPI-compatible interface without a busy indicator

Set SDI high; Use 3-wire with CNV, SCK, and SDO.

Ideal for systems where reduced wiring is critical and conversion status checks are managed in software.

4-wire CS Mode with Busy Indicator

Utilizes a 4-wire SPI interface and busy indicator for improved data integrity during conversion.

Set SDI high; Include an extra wire for busy status signal.

Used in applications requiring robust data communication assurance.

4-wire CS Mode Without Busy Indicator

Operates with a 4-wire SPI interface without busy indicators, emphasizing simplicity in design.

Set SDI high; Use CNV, SCK, SDO, and SDI.

Effective where additional communication monitoring is unnecessary.

Chain Mode with Busy Indicator

Multiple ADCs can be daisy-chained with a busy indicator to manage conversion sequences

Set SDI low with external busy signal; Use 4-wire configuration.

Built for cascading ADCs in complex data acquisition systems requiring conversion synchronization

Chain Mode without Busy Indicator

Allows daisy-chaining ADCs without an internal busy management, relying on external control.

Set SDI low; Use 3-wire configuration.

Common in systems with precise external timing and control over conversion cycles.

PD_AMP Shutdown

Minimizes power consumption by shutting down the amplifier when idle.

Drive PD_AMP low to reduce current draw to 2.9 µA.

Essential for power-sensitive application like a battery operated device

Device Configuration

Device Initialization

The adaq7980_setup function initializes the ADAQ7980 by configuring SPI communication, PWM trigger generation, and GPIO settings. It allocates memory for the device structure, configures power-down control, and initializes SPI and PWM interfaces. This sets the device for operation, streamlining the integration process.

Data Acquisition

The ad7980_read_data function reads data from the ADAQ7980 via SPI engine offload mode. Given the device structure, a data buffer, and sample count, it sets up SPI engine offload messages for chip select operations and efficient data transfers, ensuring high-speed acquisition and data integrity for precise measurements.

Driver Initialization Example

#include <stdbool.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <xil_cache.h>
#include "parameters.h"
#include "adaq7980.h"
#include "no_os_pwm.h"
#include "axi_pwm_extra.h"
#include "no_os_gpio.h"
#include "xilinx_gpio.h"
#include "no_os_error.h"

#define ADAQ7980_EVB_SAMPLE_NO 1000

int main()
{
    uint16_t buf[ADAQ7980_EVB_SAMPLE_NO] __attribute__((aligned));
    struct adaq7980_dev *dev;
    int32_t ret, i;

    struct spi_engine_offload_init_param spi_engine_offload_init_param = {
        .offload_config = OFFLOAD_RX_EN,
        .rx_dma_baseaddr = ADAQ7980_DMA_BASEADDR,
    };

    struct spi_engine_init_param spi_eng_init_param  = {
        .ref_clk_hz = 100000000,
        .type = SPI_ENGINE,
        .spi_engine_baseaddr = ADAQ7980_SPI_ENGINE_BASEADDR,
        .cs_delay = 0,
        .data_width = 16,
    };

    struct axi_pwm_init_param axi_pwm_init = {
        .base_addr = AXI_PWMGEN_BASEADDR,
        .ref_clock_Hz = 100000000,
        .channel = 0,
    };

    struct no_os_pwm_init_param trigger_pwm_init = {
        .period_ns = 10000,     /* 100Khz */
        .duty_cycle_ns = 10,
        .polarity = NO_OS_PWM_POLARITY_HIGH,
        .extra = &axi_pwm_init,
    };

    struct xil_gpio_init_param gpio_extra_param = {
        .device_id = GPIO_DEVICE_ID,
        .type = GPIO_PS,
    };

    struct no_os_gpio_init_param adaq7980_pd_ldo = {
        .number = GPIO_0,
        .platform_ops = &xil_gpio_ops,
        .extra = &gpio_extra_param
    };
    struct no_os_gpio_init_param adaq7980_ref_pd = {
        .number = GPIO_REF_PUB,
        .platform_ops = &xil_gpio_ops,
        .extra = &gpio_extra_param
    };
    struct no_os_gpio_init_param adaq7980_rbuf_pd = {
        .number = GPIO_RBUF_PUB,
        .platform_ops = &xil_gpio_ops,
        .extra = &gpio_extra_param
    };

    struct no_os_spi_init_param spi_init = {
        .chip_select = SPI_ADAQ7980_CS,
        .max_speed_hz = 10000000,
        .mode = NO_OS_SPI_MODE_2,
        .platform_ops = &spi_eng_platform_ops,
        .extra = (void*)&spi_eng_init_param,
    };

    struct adaq7980_init_param adaq7980_init_param = {
        .spi_init = &spi_init,
        .offload_init_param = &spi_engine_offload_init_param,
        .trigger_pwm_init = &trigger_pwm_init,
        .gpio_pd_ldo = &adaq7980_pd_ldo,
    };

    Xil_DCacheDisable();
    Xil_ICacheEnable();

    ret = adaq7980_setup(&dev, &adaq7980_init_param);
    if (ret < 0)
        return -1;

    while (1) {
        ret = ad7980_read_data(dev, buf, ADAQ7980_EVB_SAMPLE_NO);
        if (ret < 0)
            return -1;

        for (i = 0; i < ADAQ7980_EVB_SAMPLE_NO; i++)
            printf("ADC sample %"PRIu32" %"PRIu16" \n", i, buf[i]);
    }

    printf("Success\n\r");

    Xil_ICacheDisable();

    return 0;
}