ADAR300X no-OS Driver
See drivers/beamformer/adar300x (doxygen) for the Doxygen documentation.
Supported Devices
Overview
The ADAR3000 is a 17.7 GHz to 21.2 GHz transmit or receive, 4-beam and 4-element Ka band beamforming core chip for phased arrays. Each of the 16 RF channels provides a 31.5 dB gain range in 0.5 dB steps and up to 54.5 ps of time delay in 0.865 ps steps, through variable amplitude and phase (VAP) blocks. Every VAP contains a digital stepped attenuator (DSA) and a time delay unit (TDU).
The device stores 256 prestored beam positions in RAM, arranged as 64 beamstates per beam across 4 beams, plus a FIFO holding 64 beam positions as 16 beamstates per beam. A user programmable sequencer selects beamstates, and update, reset and mute commands can be applied to between 1 and 16 beams. An integrated 8-bit ADC serves an on-chip temperature sensor and two general purpose analog inputs, and the amplifier bias modes are programmable.
All on-chip registers are controlled through a 4-wire SPI. Four address pins
allow up to 16 devices to share the same serial lines, which the driver
supports through the dev_addr field and an optional shared SPI descriptor.
The part is supplied from a 1.2 V analog rail and a 1.8 V digital rail, and is
available in a 311-ball CSP_BGA specified from -40°C to +85°C.
Applications
Geosynchronous high-throughput satellite (GEO HTS)
Low earth orbit (LEO) constellations
Mobile satellite terminals (land, air, and sea)
Terrestrial, airborne and satellite phased arrays
Operation Modes
Each beam takes its beamstate from one of four sources, selected per beam with adar300x_set_beam_mode.
Mode |
Beamstate source |
Applied by |
|---|---|---|
|
Direct control registers |
An update command |
|
RAM, 64 beamstates per beam, stepped through by the sequencer |
Each update advances the sequencer by one beamstate |
|
FIFO, 16 beamstates per beam |
Each update dequeues one beamstate |
|
Direct control registers |
Immediately, on the SPI write |
In every mode except instantaneous direct, a reset or mute command sends the beam to its reset or mute beamstate instead.
ADAR300X Device Configuration
Driver Initialization
In order to be able to use the device, you will have to provide the support for the communication protocol (SPI), configured for mode 0, MSB first, at a clock rate of up to 1 MHz.
The first API to be called is adar300x_init. Make sure that it returns 0, which means that the driver was initialized correctly.
adar300x_init allocates the device descriptor, requests the optional
control GPIOs, pulses the hardware reset, brings up the SPI bus, issues the
soft reset sequence, proves the SPI link with a scratchpad write and read back
test, and finally checks the CHIPTYPE and PRODUCT_ID_L registers
against the part selected in type. A failed scratchpad test fails the
initialization; an unexpected CHIPTYPE or PRODUCT_ID_L is only reported
as a warning. Resources are released with adar300x_remove.
Register Access
Registers are accessed with a three byte SPI frame carrying a 16-bit address word followed by 8 bits of data. Bit 15 selects read or write, bits 13 down to 10 carry the chip address and bits 9 down to 0 the register address.
adar300x_reg_write writes a single register and adar300x_reg_read reads one back. adar300x_reg_update performs a read modify write under a caller supplied mask and skips the write when the value is unchanged.
Address Paging
Addresses 0x100 to 0x3FF are reused across six address pages selected
by register 0x008: page 0 holds the configuration registers, pages 1 to 4
the RAM of beams 0 to 3, and page 5 the FIFO load registers.
adar300x_set_page selects a page and caches the selection, so repeated
accesses to the same page do not repeat the register write.
adar300x_page_reg_write and adar300x_page_reg_read combine a page
selection with a register access.
The data sheet describes 0x000 to 0x0FF as common to all pages, but
beam commands written while the FIFO page is selected are ignored. The driver
therefore accesses every register above the standard SPI block at 0x000 to
0x00B with page 0 selected. The cached page is invalidated by both reset
paths, so a reset can never leave the driver believing that a stale page is
still selected.
Reset
adar300x_hard_reset pulses the RSTB pin, and fails with -ENODEV when no
reset GPIO is wired. adar300x_soft_reset issues the register based reset
sequence. adar300x_init pulses RSTB only when it is wired, and always
issues the soft reset sequence.
The data sheet recommends holding RSTB low across the supply ramp. When that is not possible it asks for at least two, and preferably three, back to back soft resets after power up, which adar300x_soft_reset performs.
Multiple Devices on One SPI Bus
Up to 16 devices may share the same SPI lines, distinguished by the 4-bit chip address transmitted in every frame, which must match the ADDR3 to ADDR0 strap pins of each part.
Initialize the first device normally and pass its spi_desc as
spi_desc_shared when initializing the others, each with its own
dev_addr. Only the device that owns the bus frees it in
adar300x_remove, so the shared descriptor stays valid until the owner is
removed last.
Beam Mode and Update Source
adar300x_set_beam_mode and adar300x_get_beam_mode select and read back the beamstate source of one beam, see Operation Modes.
Update, reset and mute are driven either by the UPDATE, RESET and MUTE pins or over SPI. adar300x_set_update_source_spi selects SPI when passed true, and adar300x_get_update_source_spi reads the selection back. The commands in Beam Commands only take effect with SPI selected.
Direct, Reset and Mute Beamstates
Three register banks hold one beamstate per beam each: the direct control bank, applied by an update in direct mode, and the reset and mute banks, applied by the reset and mute commands. They share one layout, so a single pair of functions covers all three.
adar300x_set_element writes, and adar300x_get_element reads, the delay
(ADAR300X_DELAY) or attenuation (ADAR300X_ATTENUATION) of one element
of one beam, in the bank selected by ADAR300X_BEAMSTATE_DIRECT,
ADAR300X_BEAMSTATE_RESET or ADAR300X_BEAMSTATE_MUTE. Both values are
6-bit, from 0 to 63: delay in 0.865 ps steps and attenuation in 0.5 dB steps.
Beam Commands
adar300x_beam_command applies ADAR300X_BEAM_CMD_UPDATE,
ADAR300X_BEAM_CMD_RESET or ADAR300X_BEAM_CMD_MUTE to every beam set in
a mask, bit 0 being beam 0. Reset and mute are qualifiers staged per beam and
applied by the update strobe, the same way the RESET and MUTE pins qualify the
UPDATE pin.
A beam in instantaneous direct mode ignores all three commands: updates have no effect because writes already apply immediately, and the data sheet states that such a beam cannot enter its reset or mute beamstate.
Amplifier Bias and Enable
Each beam amplifier has a 3-bit bias and an enable bit for each of four states, reset, operational, mute and sleep, set with adar300x_set_beam_amp and read with adar300x_get_beam_amp. The element amplifiers have the same controls for the operational and sleep states, through adar300x_set_element_amp and adar300x_get_element_amp. The amplifiers power up enabled with a bias of 3.
The data sheet also lists element amplifier mute registers at 0xD8 to
0xDB. They read back 0 and discard writes on the ADAR3000, so the driver
does not expose them.
Beamstate RAM
Each beam holds 64 beamstates in RAM, on its own address page. A beamstate is eight 6-bit values, the delay then the attenuation of each element in turn, packed MSB first into six bytes.
adar300x_set_ram_beamstate writes one beamstate from its eight unpacked values and adar300x_get_ram_beamstate reads one back. The read follows the data sheet's fetch protocol: a first read latches the whole beamstate and returns invalid data, after which the six bytes read back singly.
RAM Sequencer
In memory mode every update advances a beam's sequencer from the start pointer to the stop pointer, then wraps back to the start. adar300x_set_seq_range sets both pointers and adar300x_get_seq_range reads them. A stop pointer below the start pointer is valid and wraps from pointer 63 to pointer 0. The range powers up as 0 to 63.
FIFO
adar300x_load_fifo_beamstate queues one beamstate onto a beam's FIFO, which holds 16. The write to the last of the six load registers is what commits the beamstate, and a load onto a full FIFO is discarded by the device.
The FIFO cannot be read back. adar300x_get_fifo_pointers reads the write pointer, which advances on each load, and the read pointer, which advances on each update. Both wrap at 16, and a reset empties the queue by moving the read pointer onto the write pointer.
Temperature Sensor
adar300x_get_temp returns the raw 8-bit code of the on-chip temperature sensor. The on-chip ADC runs off SCLK, so a conversion only advances while the bus is active; the function supplies the dummy transactions and polls for the end of conversion.
The data sheet gives a slope of 1.09 LSB/°C and a nominal code of 127 at 25°C.
In integer millidegrees, using the defines in adar300x.h:
mdegc = ADAR300X_TEMP_NOMINAL_MDEGC +
((int)code - ADAR300X_TEMP_NOMINAL_CODE) *
ADAR300X_TEMP_SLOPE_NUM / ADAR300X_TEMP_SLOPE_DEN;
ADAR300X Driver Initialization Example
struct adar300x_dev *dev;
int ret;
struct no_os_uart_init_param uip = {
.device_id = UART_DEVICE_ID,
.baud_rate = UART_BAUDRATE,
.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,
};
struct adar300x_init_param adar300x_ip = {
.spi_init = {
.device_id = SPI_DEVICE_ID,
.chip_select = SPI_CS,
.max_speed_hz = 1000000,
.mode = NO_OS_SPI_MODE_0,
.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST,
.platform_ops = SPI_OPS,
.extra = SPI_EXTRA,
},
.spi_desc_shared = NULL,
.gpio_rstb = &adar300x_gpio_rstb_ip,
.gpio_mux_sel = &adar300x_gpio_mux_sel_ip,
.gpio_update = &adar300x_gpio_update_ip,
.gpio_reset = &adar300x_gpio_reset_ip,
.gpio_mute = &adar300x_gpio_mute_ip,
.type = ADAR3000,
.dev_addr = 0,
};
ret = adar300x_init(&dev, &adar300x_ip);
if (ret)
goto error;
ADAR300X no-OS IIO support
The ADAR300X IIO driver comes on top of the ADAR300X driver and offers support
for interfacing IIO clients through libiio. It exposes the same interface as
the Linux adar300x IIO driver, so channel and attribute names carry over,
with the differences listed in Differences from the Linux Driver.
ADAR300X IIO Device Configuration
Channels
The device has 33 channels. For each of the 16 elements, numbered
beam * 4 + element, there is a phase channel carrying the delay and a
power channel carrying the attenuation. The pattern continues through all
four beams:
Channels |
Beam |
Element |
Scan index |
|---|---|---|---|
|
0 |
0 |
0, 1 |
|
0 |
1 |
2, 3 |
|
1 |
0 |
8, 9 |
|
3 |
3 |
30, 31 |
|
none |
none |
not buffered |
Channel Attributes
out_phaseN_raw - delay of the element, 0 to 63, in the bank selected by the beam's load_modeout_phaseN_scale - 0.865, picoseconds of delay per stepout_powerN_raw - attenuation of the element, 0 to 63, in the bank selected by the beam's load_modeout_powerN_scale - 0.5, decibels of attenuation per stepin_temp16_raw - raw code of the temperature sensorin_temp16_offset - -99.75in_temp16_scale - 917.431192660, millidegrees Celsius per code
The temperature in millidegrees Celsius is (raw + offset) * scale.
The raw attributes of a beam address the bank chosen by its load_mode:
the direct control bank for direct and instant_direct, the reset or
mute bank for reset or mute, RAM beamstate ram_index for
memory, and a staging beamstate for fifo. In fifo load mode the
staged beamstate is queued when its eighth value, powerN of the beam's
element 3, is written.
Global Attributes
In the attributes below, N is the beam number, 0 to 3.
beamN_mode - beam mode: direct, memory, fifo, instant_direct, or reset or mute to have the next update apply that beamstatebeamN_mode_available - the accepted beamN_mode valuesbeamN_update - write any value to issue an update, or the reset or mute selected in beamN_mode; reads 0beamN_load_mode - bank addressed by the beam's channels and buffer, same values as beamN_modebeamN_load_mode_available - the accepted beamN_load_mode valuesbeamN_ram_index - RAM beamstate addressed by the channels in memory load mode, and the first one the buffer writes, 0 to 63beamN_ram_start - sequencer start pointer, 0 to 63beamN_ram_stop - sequencer stop pointer, 0 to 63beamN_fifo_rd - FIFO read pointer, read onlybeamN_fifo_wr - FIFO write pointer, read onlyupdate_intf_ctrl - source of update, reset and mute, pin or SPIupdate_intf_ctrl_available - the accepted update_intf_ctrl values
The amplifier attributes take a bias of 0 to 7 or an enable of 0 or 1:
beamN_amp_bias_<state>, beamN_amp_en_<state> - bias and enable of beam amplifier N, for <state> reset, operational, mute and sleepelementN_amp_bias_<state>, elementN_amp_en_<state> - bias and enable of element amplifier N, for <state> operational and sleep
Debug Attributes
direct_reg_access - raw register read and write. The address is not paged: select the page through register 0x008 first when reaching 0x100 and above
Output Buffer
The output buffer loads whole beamstates into RAM or the FIFO. Enable all eight
channels of each beam that takes part, phase4B to power4B+3 for beam
B; partially enabled beams are rejected. Each scan carries one beamstate
per enabled beam, whose load_mode must be memory or fifo:
memory- scannis written to RAM beamstateram_index + n. A buffer that would run past beamstate 63 is rejected.fifo- each scan is queued in turn. Loads beyond the 16 the FIFO holds are discarded by the device.
Each value takes one byte, of which the low six bits are used. The largest buffer, 64 beamstates for each of the four beams, is 2048 bytes.
Differences from the Linux Driver
The attribute names and behaviour follow the Linux driver except where it disagrees with the data sheet:
The
phasescale is 0.865 ps per step, the time delay the part actually applies. Linux reports 360 / 63 degrees, which is not a property of a true time delay unit.The
powerscale is 0.5 dB per step. Linux reports 31 / 63.The temperature offset and scale reproduce 25°C at code 127. The Linux values give 194 m°C there.
beamN_ram_indexcounts whole beamstates for the buffer. Linux adds it to the RAM address as a byte offset.The amplifier attributes are named after the bank they control. Linux names the beam amplifiers
ELnVand the element amplifiersELnH.
ADAR300X IIO Driver Initialization Example
#define ADAR300X_IIO_BUFFER_SIZE (ADAR300X_RAM_STATES_PER_BEAM * \
ADAR300X_IIO_BEAMS * \
ADAR300X_UNPACKED_BEAMSTATE_LEN)
static uint8_t adar300x_iio_buffer[ADAR300X_IIO_BUFFER_SIZE];
int ret;
struct adar300x_iio_dev *adar300x_iio_dev;
struct adar300x_iio_dev_init_param adar300x_iio_ip = {
.adar300x_dev_init = &adar300x_ip,
};
struct iio_data_buffer write_buff = {
.buff = adar300x_iio_buffer,
.size = sizeof(adar300x_iio_buffer),
};
struct iio_app_desc *app;
struct iio_app_init_param app_init_param = {0};
ret = adar300x_iio_init(&adar300x_iio_dev, &adar300x_iio_ip);
if (ret)
goto exit;
struct iio_app_device iio_devices[] = {
{
.name = "adar3000",
.dev = adar300x_iio_dev,
.dev_descriptor = adar300x_iio_dev->iio_dev,
.write_buff = &write_buff,
},
};
app_init_param.devices = iio_devices;
app_init_param.nb_devices = NO_OS_ARRAY_SIZE(iio_devices);
app_init_param.uart_init_params = uip;
ret = iio_app_init(&app, app_init_param);
if (ret)
goto remove_iio_adar300x;
return iio_app_run(app);