Skip to content

Commit

Permalink
add ad5293 drivers include
Browse files Browse the repository at this point in the history
1. no-os initilization
2. calibration, wiper r/w ,hard/soft reset and other operation
3. daisy-chain multiple chip support

Signed-off-by: Mize <[email protected]>
  • Loading branch information
mi-zeng committed Nov 17, 2024
1 parent 63f4493 commit 88a821f
Show file tree
Hide file tree
Showing 5 changed files with 961 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/sphinx/source/drivers/ad5293.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: ../../../../drivers/potentiometer/ad5293/README.rst
7 changes: 7 additions & 0 deletions doc/sphinx/source/drivers_doc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,10 @@ POWER MANAGEMENT
drivers/lt8722
drivers/ltp8800
drivers/max42500

POTENTIOMETER
================
.. toctree::
:maxdepth: 1

drivers/ad5293
260 changes: 260 additions & 0 deletions drivers/potentiometer/ad5293/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
====================
AD5293 no-OS driver
====================

Supported Devices
------------------

`ad5293 <https://www.analog.com/en/products/ad5293.html>`_

Overview
---------
The AD5293 is a single-channel, 1024-position digital potentiometer with
a <1% end-to-end resistor tolerance error. The AD5293 performs the same
electronic adjustment function as a mechanical potentiometer with enhanced
resolution, solid state reliability, and superior low temperature coefficient
performance. This device is capable of operating at high voltages and supporting
both dual-supply operation at ±10.5 V to ±15 V and single-supply operation at 21 V to 30 V.
(in this documentation, the terms digital potentiometer and RDAC are used interchangeably)

The AD5293 contains a serial interface (SYNC, SCLK, DIN, and
SDO) that is compatible with SPI standards, as well as most DSPs.
The device allows data to be written to every register via the SPI.

Applications
------------
- Mechanical potentiometer replacement
- Instrumentation: gain and offset adjustment
- Programmable voltage-to-current conversion
- Programmable filters, delays, and time constants
- Programmable power supply
- Low resolution DAC replacements
- Sensor calibration

Device Configuration
--------------------

Multiple Chips Use
^^^^^^^^^^^^^^^^^^
Multiple chips could be used in application, daisy chaining topology can
minimizes the number of port pins required from the controlling IC. For
this driver, if more than 1 chip are used, daisy-chain topology is required.
All RESET pins are required to connect together.

Device Operation
----------------

Write Operation
^^^^^^^^^^^^^^^
In order to write to the RDAC calibration mode, you will need to
call the **ad5293_update_cali** to update calibration on specific
chip struct, then call the **ad5293_write_cali** to perform a write performance.

In order to write to the RDAC wiper value, you will need to
call the **ad5293_update_wiper** to update wiper value on specific
chip struct, then call the **ad5293_write_cali** to perform a write performance.
**RDAC register write protect register** is only unlocked in **ad5293_write_cali**
to pervent undesired wiper write.

Each write perform will write all chips, for multiple chips application,
update all relevant data before perform write.

Read Operation
^^^^^^^^^^^^^^
In order to read the RDAC calibration mode, you will need to
call the **ad5293_read_reg_cali**, calibration mode will be updated
to chip struct.

In order to read the RDAC wiper value, you will need to
call the **ad5293_read_reg_wiper**, wiper value will be updated
to chip struct.

Reset
^^^^^
In order to read the RDAC chips, you will need to
call the **ad5293_hard_reset** to implement hardware reset
with a low-to-high transition of the hardware RESET pin,
or call the **ad5293_soft_reset** to implement software reset
through SPI interface. After reset, RDAC registers are loaded
with midscale, the control registers are restored with default bits.

Minimize The SDO Power Dissipation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The SDO pin contains an open-drain N-channel FET that requires a pull-up
resistor if this pin is used. This pin could be place in by calling **ad5293_sdo_setfloat**
high impedence to minimize power dissipation. ( User should be careful with this operation,
SPI comminications integrity may be affected)

Get Data
^^^^^^^^
In order to get the RDAC calibration mode or wiper value from chips struct,
you will need to call the **ad5293_get_cali** or **ad5293_get_wiper**, which
returns data of specified chip.

Shutdown
^^^^^^^^
RDAC can be placed in a special state in which Terminal A is open-circuited
and Wiper W is connected to Terminal B, this is shutdown mode. Contents in
RDAC are not changed and all command through SPI are supported in this mode.
In order to RDAC to shut down mode, call **ad5293_shutdown** and input parameter
from enmu type **shutdown_t**.

Driver Initialization
---------------------
In order to be able to use the device, you will have to provide the support for
the communication protocol (SPI) as mentioned above.

Device Struct Description
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: C
struct ad5293_dev {
/* SPI */
struct no_os_spi_desc *spi_desc;
/* GPIO */
struct no_os_gpio_desc *gpio_reset;
/* number of chips */
uint16_t chip_num;
/* pointer of chip struct */
struct ad5293_chip_info* chip; //point to chip 0
};
ad5293_dev
overall device information holder, multiple chips are regards as one device
no_os_spi_desc
no-os lib definded spi device instance handler
no_os_gpio_desc
no-os lib definded gpio instance handler for reset pin
chip_num
number of chips
ad5293_chip_info
pointer to allocated memory for **ad5293_chip_info** structs, total amount
is chip_num*sizeof(ad5293_chip_info), different chip information is accessed
by different pointer offset(array operation)

Driver Initialization Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
An initialization and test example on stm32 could be

.. code-block:: C
#define RESET_PORT 0 //PORT A
#define RESET_PIN 11
#define RDAC_CS_PORT 1 //PORT B
#define RDAC_CS_PIN 12
//function
uint32_t get_spi2_clock(void);
//adi device pointer define
struct ad5293_dev* pad5293_dev;
uint32_t get_spi2_clock(void)
{
return LL_RCC_GetSPIClockFreq(LL_RCC_SPI123_CLKSOURCE);
}
void rdac_init(void)
{
int32_t ret = 0;
struct ad5293_init_param rdac_init;
//start timer 5 as delay counter
delay_init();
struct no_os_gpio_init_param RESET_init;
struct stm32_gpio_init_param RESET_init_stm;
RESET_init.port = RESET_PORT;
RESET_init.number = RESET_PIN;
RESET_init.pull = NO_OS_PULL_NONE;
RESET_init.platform_ops = & stm32_gpio_ops;
RESET_init.extra = (void*) & RESET_init_stm;
RESET_init_stm.mode = GPIO_MODE_OUTPUT_PP;
RESET_init_stm.speed = GPIO_SPEED_FREQ_HIGH;
RESET_init_stm.alternate = 0;
rdac_init.gpio_reset = & RESET_init;
//spi GPIO init struct preparation
struct stm32_spi_init_param stm32_spi_init;
stm32_spi_init.chip_select_port = RDAC_CS_PORT; //GPIO CS PORT
stm32_spi_init.get_input_clock = & get_spi2_clock;
stm32_spi_init.alternate = 0;
rdac_init.spi_init.extra = (void*) & stm32_spi_init;
rdac_init.spi_init.platform_ops = & stm32_spi_ops;
rdac_init.spi_init.device_id = 2; //spi device 1
rdac_init.spi_init.max_speed_hz = 200 * 1000; //3mHz
rdac_init.spi_init.chip_select = RDAC_CS_PIN; //GPIO CS PIN
rdac_init.spi_init.mode = NO_OS_SPI_MODE_1;
rdac_init.spi_init.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST;
rdac_init.spi_init.platform_delays.cs_delay_first = 0; //delay before transfer
rdac_init.spi_init.platform_delays.cs_delay_last = 0; //delay after transfer
rdac_init.chip_num = 6;
ret = ad5293_init( & pad5293_dev, & rdac_init);
if(ret)
printf("rdac init error. \r\n");
}
void rdac_test(void)
{
int i, cali_val[pad5293_dev->chip_num];
int16_t wp_value[pad5293_dev->chip_num];
ad5293_hard_reset(pad5293_dev);
no_os_mdelay(1);
for(i = 0;i < pad5293_dev->chip_num;i++)
{
ad5293_update_cali(pad5293_dev, CALI_NORMAL, i);
ad5293_update_wiper(pad5293_dev, 768, i);
}
ad5293_write_cali(pad5293_dev);
ad5293_write_wiper(pad5293_dev);
ad5293_read_reg_cali(pad5293_dev);
ad5293_read_reg_wiper(pad5293_dev);
no_os_mdelay(1);
for(i = 0;i < pad5293_dev->chip_num;i++)
{
cali_val[i] = ad5293_get_cali(pad5293_dev, i);
wp_value[i] = ad5293_get_wiper(pad5293_dev, i);
}
ad5293_shutdown(pad5293_dev, SHUTDOWN);
no_os_mdelay(1);
ad5293_shutdown(pad5293_dev, NORMAL);
no_os_mdelay(1);
ad5293_soft_reset(pad5293_dev);
no_os_mdelay(1);
for(i = 0;i < pad5293_dev->chip_num;i++)
{
ad5293_update_cali(pad5293_dev, CALI_NORMAL, i);
ad5293_update_wiper(pad5293_dev, 256, i);
}
ad5293_write_cali(pad5293_dev);
ad5293_write_wiper(pad5293_dev);
ad5293_read_reg_cali(pad5293_dev);
ad5293_read_reg_wiper(pad5293_dev);
no_os_mdelay(1);
}
Loading

0 comments on commit 88a821f

Please sign in to comment.