Analog Peripherals Appendix (SiWx91x Devices)#
This appendix provides reference material, implementation examples, and frequently asked questions (FAQ) for analog peripherals on SiWx917 devices.
It defines key terminology and acronyms, includes extended examples for practical use cases, and offers troubleshooting guidance to help developers integrate analog peripherals efficiently.
Glossary#
The glossary defines key technical terms and acronyms used throughout the Analog Peripherals Guide for quick reference.
Term | Definition |
|---|---|
ADC (analog-to-digital converter) | Converts analog voltages to digital values for software processing. |
DAC (digital-to-analog converter) | Converts digital values into analog voltages for biasing, control loops, or waveforms. |
DMA (direct memory access) | Transfers ADC and DAC data between memory and peripheral FIFOs without CPU involvement. |
FIFO (first-in, first-out buffer) | Temporary analog data storage for continuous sampling or waveform streaming. |
MSPS (mega samples per second) | Measurement of ADC and DAC throughput in millions of samples per second. |
SPS (samples per second) | Sampling rate in samples per second. |
PS (power state) | Operating states defining performance vs. energy use (PS4, PS3, and PS2). |
ULP (ultra-low-power) | Peripherals designed for minimal current usage and continuous operation in deeper sleep modes. |
VREF (reference voltage) | Voltage used as the maximum reference for ADC conversion and DAC output scaling. |
Acronyms#
Acronym | Definition |
|---|---|
ADC | Analog-to-digital converter |
API | Application programming interface |
DAC | Digital-to-analog converter |
DMA | Direct memory access |
FIFO | First in, first out |
GPIO | General-purpose input/output |
MSPS | Mega samples per second |
PS | Power state |
SDK | Software development kit |
SPS | Samples per second |
UC | Universal Configurator |
ULP | Ultra-low power |
VREF | Voltage reference |
Extended Examples#
The following examples demonstrate practical ADC and DAC implementations on SiWx917 devices, including configuration, sampling, and data processing techniques.
Example 1: Multi-Channel Temperature Monitoring#
#include "sl_si91x_adc.h"
#include <stdio.h>
#define NUM_TEMP_SENSORS 4
#define TEMP_SAMPLE_RATE 100
static int16_t temperature_readings[NUM_TEMP_SENSORS];
static uint8_t current_channel = 0;
static bool conversion_complete = false;
static const float temp_coefficients[NUM_TEMP_SENSORS] = {0.01f, 0.01f, 0.02f, 0.005f};
static void temperature_adc_callback(uint8_t channel_no, uint8_t event) {
if (event == SL_ADC_DATA_READY) {
sl_si91x_adc_read_data(adc_config, ¤t_channel,
&temperature_readings[current_channel]);
conversion_complete = true;
}
}
void setup_temperature_monitoring(void) {
sl_adc_config_t adc_config = {
.operation_mode = SL_ADC_STATIC_MODE,
.num_of_channel_enable = NUM_TEMP_SENSORS
};
sl_adc_channel_config_t channel_config = {0};
if (sl_si91x_adc_init(channel_config, adc_config, 3.3f) != SL_STATUS_OK) {
printf("ADC initialization failed\n");
return;
}
sl_si91x_adc_register_event_callback(temperature_adc_callback);
printf("Temperature monitoring system initialized\n");
}
float read_temperature(uint8_t sensor_id) {
if (sensor_id >= NUM_TEMP_SENSORS) return -999.0f;
float voltage = (temperature_readings[sensor_id] * 3.3f) / 4096.0f;
return voltage / temp_coefficients[sensor_id];
}
void temperature_monitoring_task(void) {
for (int i = 0; i < NUM_TEMP_SENSORS; i++) {
current_channel = i;
conversion_complete = false;
sl_si91x_adc_start(adc_config);
while (!conversion_complete) sl_sleeptimer_delay_millisecond(1);
printf("Sensor %d: %.2f°C\n", i, read_temperature(i));
}
}Example 2: Audio Signal Generation Using DAC#
#include "sl_si91x_dac.h"
#include <math.h>
#define AUDIO_SAMPLE_RATE 44100
#define BUFFER_SIZE 256
#define FREQUENCY_HZ 1000
static int16_t audio_buffer_1[BUFFER_SIZE];
static int16_t audio_buffer_2[BUFFER_SIZE];
static bool buffer_1_active = true;
static uint32_t sample_index = 0;
static void audio_dac_callback(uint8_t event) {
if (event == SL_DAC_FIFO_EMPTY) {
if (buffer_1_active) {
sl_si91x_dac_write_data(audio_buffer_1, BUFFER_SIZE);
fill_audio_buffer(audio_buffer_2);
} else {
sl_si91x_dac_write_data(audio_buffer_2, BUFFER_SIZE);
fill_audio_buffer(audio_buffer_1);
}
buffer_1_active = !buffer_1_active;
}
}
void fill_audio_buffer(int16_t *buffer) {
for (int i = 0; i < BUFFER_SIZE; i++) {
float t = (float)(sample_index + i) / AUDIO_SAMPLE_RATE;
buffer[i] = (int16_t)(2048 + 2047 * sinf(2.0f * M_PI * FREQUENCY_HZ * t));
}
sample_index += BUFFER_SIZE;
}
void setup_audio_generation(void) {
sl_dac_clock_config_t dac_clock = {.soc_pll_clock = 80000000, .soc_pll_reference_clock = 40000000};
if (sl_si91x_dac_init(&dac_clock) != SL_STATUS_OK) return;
sl_dac_config_t dac_config = {.operating_mode = SL_DAC_FIFO_MODE, .dac_sample_rate = AUDIO_SAMPLE_RATE};
sl_si91x_dac_set_configuration(dac_config, 3.3f);
sl_si91x_dac_register_event_callback(audio_dac_callback);
fill_audio_buffer(audio_buffer_1);
fill_audio_buffer(audio_buffer_2);
sl_si91x_dac_write_data(audio_buffer_1, BUFFER_SIZE);
printf("Audio generation started at %d Hz\n", FREQUENCY_HZ);
}Example 3: Battery Monitoring with ULP ADC#
#include "sl_si91x_ulp_adc.h"
#define BATTERY_CHANNEL 0
#define LOW_BATTERY_THRESHOLD 3.0f
static float battery_voltage = 0.0f;
static bool low_battery_alert = false;
static void battery_monitor_callback(uint8_t channel_no, uint8_t event) {
if (event == SL_ADC_DATA_READY && channel_no == BATTERY_CHANNEL) {
int16_t adc_reading;
sl_si91x_adc_read_data(adc_config, NULL, &adc_reading);
battery_voltage = (adc_reading * 3.3f * 2.0f) / 4096.0f;
if (battery_voltage < LOW_BATTERY_THRESHOLD) {
low_battery_alert = true;
printf("Low battery: %.2fV\n", battery_voltage);
}
}
}Frequently Asked Questions (FAQ)#
Q: What is the difference between static and FIFO mode in ADC?
A: Static mode performs single conversions on demand, while FIFO mode continuously samples and buffers results.
Q: Can standard and ULP analog peripherals operate simultaneously?
A: Typically, applications use either standard or ULP peripherals depending on performance and power needs.
Q: What is the maximum ADC sampling rate?
A: The standard ADC supports 2.5 MSPS, while the ULP ADC supports 63 KSPS.
Q: How do I calculate voltage from ADC readings?
A: Voltage = (ADC_Reading * VREF) / 4096.
Q: Can DAC operate in sleep modes?
A: The ULP DAC supports operation in PS2 (sleep), while the standard DAC requires PS4 (active).
Q: Does configuration persist through sleep cycles?
A: Configuration may reset in deep sleep. Implement save-and-restore logic.
Q: How do I minimize noise in ADC readings?
A: Use a stable VREF, proper grounding, moderate sampling rates, and averaging.
Q: What load can the DAC drive?
A: The standard DAC drives ≥ 1 kΩ; ULP DAC requires ≥ 10 kΩ.
Q: Can I use DMA with ADC/DAC?
A: Yes, both support DMA in FIFO mode for efficient data transfer.
Q: How do I select the best reference voltage?
A: Choose VREF based on input range. Use a higher VREF for large signals and a lower VREF for higher precision.