ADAR4000

ADAR4000/ADAR4001 2 GHz to 18 GHz, Single Beam, 4-Element Beamformer Linux Device Driver.

The ADAR4000 and ADAR4001 are wideband beamformer ICs operating from 2 GHz to 18 GHz, designed for transmit and receive phased array applications, respectively. Both feature a true time delay core for beam-squint free operation, with configurable delays up to 508 ps and fine resolution down to 2 ps. Each path includes a 31.5 dB digital step attenuator with 0.5 dB steps. They support SPI control for up to 16 devices and include on-chip RAM and FIFO for storing and sequencing beamstates.

Supported Devices

Evaluation Boards

Description

This is a Linux industrial I/O (Linux Industrial I/O Subsystem) subsystem driver, targeting RF Transceivers. The industrial I/O subsystem provides a unified framework for drivers for many different types of converters and sensors using a number of different physical interfaces (i2c, spi, etc). See Linux Industrial I/O Subsystem for more information.

Source Code

Status

Source

Mainlined?

git

WIP

Files

Function

File

driver

adar4000x.c

devicetree bindings

adi,adar400x.yaml

Example Linux Device-Tree Initialization

The ADAR4000 driver is a spi-bus driver and can currently only be instantiated via device tree.

Required devicetree properties:

  • compatible: Should always be adi,adar4000, adi,adar4001

  • reg: SPI slave select number

Optional properties:

  • adi,num-devices: Number of devices connected to the SPI bus. Default is 1.

Function

File

RPI Device Tree

WIP

Enabling Linux driver support

Configure kernel with make menuconfig (alternatively use make xconfig or make qconfig)

Note

The ADAR4000 driver depends on CONFIG_SPI

Adding Linux driver support

Configure kernel with make menuconfig (alternatively use make xconfig or make qconfig)

Linux Kernel Configuration
    Device Drivers  --->
    <*>     Industrial I/O support --->
        --- Industrial I/O support
        -*-   Enable ring buffer support within IIO
        -*-     Industrial I/O lock free software ring
        -*-   Enable triggered sampling support

              *** Analog to digital converters ***
        [--snip--]

        <*>   Analog Devices ADAR4000 and ADR4001 Beamformer driver

        [--snip--]

Driver testing / API

Important

SPI writes and reads for certain attributes are delayed because of how the hardware behaves. So, updates to certain properties take a couple of seconds to be reflected in a read-back from hardware.

Each and every IIO device, typically a hardware chip, has a device folder under /sys/bus/iio/devices/iio:deviceX. Where X is the IIO index of the device. Under every of these directory folders reside a set of files, depending on the characteristics and features of the hardware device in question. These files are consistently generalized and documented in the IIO ABI documentation. In order to determine which IIO deviceX corresponds to which hardware device, the user can read the name file /sys/bus/iio/devices/iio:deviceX/name. In case the sequence in which the iio device drivers are loaded/registered is constant, the numbering is constant and may be known in advance.

root:/> cd /sys/bus/iio/devices/
root:/sys/bus/iio/devices> ls
iio:device0  iio:device1  iio:device2  iio:device3
root:/sys/bus/iio/devices> cd iio:device0
root@analog:/sys/bus/iio/devices/iio:device0# ls -l
total 0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 active_device
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL3
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL3
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL3
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL3
-r--r--r-- 1 root root 4096 Oct  1 14:25 beam0_fifo_rd
-r--r--r-- 1 root root 4096 Oct  1 14:25 beam0_fifo_wr
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_mode
-r--r--r-- 1 root root 4096 Oct  1 14:25 beam0_mode_available
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_ram_start
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_ram_stop
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_sequencer_ptr_index
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_update
--w------- 1 root root 4096 Oct  1 14:25 beamstate_fifo
--w------- 1 root root 4096 Oct  1 14:25 beamstate_ram
-r--r--r-- 1 root root 4096 Oct  1 14:25 name
lrwxrwxrwx 1 root root    0 Oct  1 14:25 of_node -> ../../../../../../../../firmware/devicetree/base/soc/spi@7e204000/adar4000@0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase0_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase0_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase1_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase1_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase2_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase2_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase3_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase3_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power0_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power0_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power1_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power1_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power2_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power2_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power3_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power3_scale
drwxr-xr-x 2 root root    0 Oct  1 14:25 power
lrwxrwxrwx 1 root root    0 Oct  1 14:25 subsystem -> ../../../../../../../../bus/iio
-rw-r--r-- 1 root root 4096 Oct  1 14:25 uevent
-r--r--r-- 1 root root 4096 Oct  1 14:25 waiting_for_supplier
root@analog:/sys/bus/iio/devices/iio:device0#

Channel attributes

  • raw - Multiplied with scale will result in a physical value.

  • scale - Multiplied with raw will result in a physical value.

  • delay = raw * scale

  • gain = raw * scale

Device attributes

  • active_device – Select device for multiple connected devices

  • beam0_fifo_rd - FIFO read pointer

  • beam0_fifo_wr - FIFO write pointer

  • beam0_mode - Beam operation mode

  • beam0_mode_available - Possible values: direct memory fifo instant_direct reset mute

  • beam0_ram_index - Starting position in memory for saving beamstates

  • beam0_ram_start - Start beamstate in memory. Default: 0

  • beam0_ram_stop - Stop beamstate in memory. Default: 63

  • beam0_update - Update beamstate

  • beamstate_ram – Beamstate data for RAM mode, can be in table format or echo command

  • beamstate_fifo – Beamstate data for FIFO mode

  • amp_bias_mute_ELxA

  • amp_bias_operational_ELxA

  • amp_bias_operational_ELxA

  • amp_bias_reset_ELxA

  • amp_bias_sleep_ELxA

  • amp_bias_sleep_ELxA

  • amp_en_mute_ELx

  • amp_en_operational_ELx

  • amp_en_operational_ELx

  • amp_en_reset_ELx

  • amp_en_sleep_ELx

  • amp_en_sleep_ELx

Beam components
  • Beam0: power0, phase0, power1, phase1, power2, phase2, power3, phase3

Show device name
root@analog:/sys/bus/iio/devices/iio:device0> cat name
adar4000
Read/Write Register

Read scratchpad:

root@analog:/sys/bus/iio/devices/iio:device0# iio_reg adar4000 0x0a
0x0

Write scratchpad:

root@analog:/sys/bus/iio/devices/iio:device0# iio_reg adar4000 0x0a 0x12
Beamstate Mode

Description:

  • beam0_mode - Specifies the mode corresponding to where the values are saved. The device can be configured into one of the following modes:

  • Direct: Data will be saved into registers corresponding to the direct mode.

  • RAM: Data will be saved into RAM, allowing for temporary storage and faster access.

  • FIFO: Data will be saved into a First-In-First-Out queue, ensuring that the first data entered is the first to be processed.

  • Reset: The device will reset, clearing any stored data, and returning to its initial state.

  • Mute: The device will enter a mute state, where no data is processed or saved.

When configuring beam0_mode to mute or reset this will set the commanded beam to a user predefined beamstate and bias setting for the amplifiers.

root@analog:/sys/bus/iio/devices/iio:device0# cat beam0_mode_available
direct ram fifo instant_direct mute reset

Direct Mode

Write:

root@analog:/sys/bus/iio/devices/iio:device0# echo direct > beam0_mode

Read :

root@analog:/sys/bus/iio/devices/iio:device0# cat beam0_mode
direct

This mode means that data will be saved into registers corresponding to the direct mode.

Writing beamstate in direct mode:
root@analog:/sys/bus/iio/devices/iio:device0# echo 10 > out_phase0_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 11 > out_phase1_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 12 > out_phase2_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 13 > out_phase3_raw

root@analog:/sys/bus/iio/devices/iio:device0# echo 21 > out_power0_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 22 > out_power1_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 23 > out_power2_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 24 > out_power3_raw

Input value can be verified by reading the channel attribute.

root@analog:/sys/bus/iio/devices/iio:device0# cat out_phase0_raw
10

To load the current beamstate in the direct control registers into the VAPs, write 1 to beam0_update.

root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > beam0_update

RAM

Custom 64 beamstates can be loaded at any time via the beamstate_ram attribute in table format. Table must be in this format:

Index

Element

Delay

Attenuation

Example beamstate table:

<index elements delay attn ADAR400x beamstate>
0, 0, 12, 23
0, 1, 45, 11
0, 2, 34, 7
0, 3, 29, 18
1, 0, 5, 22
1, 1, 16, 33
1, 2, 8, 44
1, 3, 21, 9
...
63, 0, 8, 18
63, 1, 21, 7
63, 2, 3, 30
63, 3, 17, 13
</beamstate>

Note

Do not modify or remove the header and footer; it will be used as a mark for the driver.

Last row denotes beamstate index 63, element 3 with a delay value of 17 and attenuation value of 13.

The table can be applied to the attribute by setting first the beam mode to ram.

root@analog:/sys/bus/iio/devices/iio:device0# echo ram > beam0_mode

Allow permission to write on the attribute.

root@analog:/sys/bus/iio/devices/iio:device0# chmod 666 beamstate_ram

Lastly apply the beamstate table. Look through your beamstate table.

root@analog:/sys/bus/iio/devices/iio:device0# cat ram_beamstate > beamstate_ram

Write 1 to beam0_update advances the active sequencer pointer and loads that beamstate data into the VAPs.

root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > beam0_update

Alternatively, beamstate data can be applied directly using echo command. Example:

root@analog:/sys/bus/iio/devices/iio:device0# echo 0, 1, 32, 28 > beamstate_ram

FIFO

Similar process with RAM mode. Table can be modified up to 16 beamstates.

root@analog:/sys/bus/iio/devices/iio:device0# echo fifo > beam0_mode
root@analog:/sys/bus/iio/devices/iio:device0# chmod 666 beamstate_fifo
root@analog:/sys/bus/iio/devices/iio:device0# cat fifo_beamstate > beamstate_fifo

Write 1 to beam0_update to dequeue the next beamstate in the FIFO and load it into the VAPs.

root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > beam0_update

More Information