/** * @file ad9102_device.c * @brief AD9102 waveform-generation device driver. */ #include "ad9102_device.h" #include "board_io.h" #include "main.h" /* AD9102 register map used by the existing firmware. See ad9102.pdf. */ #define AD9102_REG_SPICONFIG 0x0000u #define AD9102_REG_POWERCONFIG 0x0001u #define AD9102_REG_CLOCKCONFIG 0x0002u #define AD9102_REG_RAMUPDATE 0x001Du #define AD9102_REG_PAT_STATUS 0x001Eu #define AD9102_REG_PAT_TYPE 0x001Fu #define AD9102_REG_WAV_CONFIG 0x0027u #define AD9102_REG_PAT_TIMEBASE 0x0028u #define AD9102_REG_PAT_PERIOD 0x0029u #define AD9102_REG_DAC_PAT 0x002Bu #define AD9102_REG_SAW_CONFIG 0x0037u #define AD9102_REG_START_DLY 0x005Cu #define AD9102_REG_START_ADDR 0x005Du #define AD9102_REG_STOP_ADDR 0x005Eu #define AD9102_REG_CFG_ERROR 0x0060u #define AD9102_REG_SRAM_DATA_BASE 0x6000u #define AD9102_PAT_STATUS_RUN (1u << 0) #define AD9102_SAW_TYPE_UP 0u #define AD9102_SAW_TYPE_TRIANGLE 2u #define AD9102_SAW_STEP_DEFAULT 1u #define AD9102_PAT_PERIOD_BASE_DEFAULT 0x2u #define AD9102_START_DELAY_BASE_DEFAULT 0x1u #define AD9102_PAT_TIMEBASE_HOLD_DEFAULT 0x1u #define AD9102_PAT_PERIOD_DEFAULT 0xFFFFu #define AD9102_EX4_WAV_CONFIG 0x3212u #define AD9102_EX4_SAW_CONFIG 0x0606u #define AD9102_EX2_WAV_CONFIG 0x3030u #define AD9102_EX2_DAC_PAT 0x0101u #define AD9102_EX2_SAW_CONFIG 0x0200u #define AD9102_SRAM_PAT_PERIOD_BASE_DEFAULT 0x1u #define AD9102_SRAM_START_DELAY_BASE_DEFAULT 0x1u #define AD9102_SRAM_START_DLY_DEFAULT 0x0000u #define AD9102_SRAM_RAMP_MIN (-8192) #define AD9102_SRAM_RAMP_MAX (8191) #define AD9102_REG_COUNT 66u #define AD9102_WAVE_MAX_CHUNK_SAMPLES 12u static const uint16_t g_ad9102_reg_addr[AD9102_REG_COUNT] = { 0x0000u, 0x0001u, 0x0002u, 0x0003u, 0x0004u, 0x0005u, 0x0006u, 0x0007u, 0x0008u, 0x0009u, 0x000Au, 0x000Bu, 0x000Cu, 0x000Du, 0x000Eu, 0x001Fu, 0x0020u, 0x0022u, 0x0023u, 0x0024u, 0x0025u, 0x0026u, 0x0027u, 0x0028u, 0x0029u, 0x002Au, 0x002Bu, 0x002Cu, 0x002Du, 0x002Eu, 0x002Fu, 0x0030u, 0x0031u, 0x0032u, 0x0033u, 0x0034u, 0x0035u, 0x0036u, 0x0037u, 0x003Eu, 0x003Fu, 0x0040u, 0x0041u, 0x0042u, 0x0043u, 0x0044u, 0x0045u, 0x0047u, 0x0050u, 0x0051u, 0x0052u, 0x0053u, 0x0054u, 0x0055u, 0x0056u, 0x0057u, 0x0058u, 0x0059u, 0x005Au, 0x005Bu, 0x005Cu, 0x005Du, 0x005Eu, 0x005Fu, 0x001Eu, 0x001Du }; static const uint16_t g_ad9102_example4_regval[AD9102_REG_COUNT] = { 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x4000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x1F00u, 0x0000u, 0x0000u, 0x0000u, 0x000Eu, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x3212u, 0x0121u, 0xFFFFu, 0x0000u, 0x0101u, 0x0003u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x4000u, 0x0000u, 0x0606u, 0x1999u, 0x9A00u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0FA0u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x16FFu, 0x0001u, 0x0001u }; static const uint16_t g_ad9102_example2_regval[AD9102_REG_COUNT] = { 0x0000u, 0x0E00u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x4000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x1F00u, 0x0000u, 0x0000u, 0x0000u, 0x000Eu, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x3030u, 0x0111u, 0xFFFFu, 0x0000u, 0x0101u, 0x0003u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x4000u, 0x0000u, 0x0200u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0FA0u, 0x0000u, 0x3FF0u, 0x0100u, 0x0001u, 0x0001u }; typedef struct ad9102_upload_state_t { uint8_t active; uint16_t expected_samples; uint16_t written_samples; } ad9102_upload_state_t; static ad9102_upload_state_t g_upload_state; static void ad9102_write_reg(uint16_t address, uint16_t value) { uint16_t command = (uint16_t)(address & 0x7FFFu); uint32_t timeout = 0u; board_io_configure_spi2_mode(LL_SPI_POLARITY_LOW, LL_SPI_PHASE_1EDGE); HAL_GPIO_WritePin(DAC_LD1_CS_GPIO_Port, DAC_LD1_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_SET); if (!LL_SPI_IsEnabled(SPI2)) { LL_SPI_Enable(SPI2); } HAL_GPIO_WritePin(AD9102_CS_GPIO_Port, AD9102_CS_Pin, GPIO_PIN_RESET); while ((!LL_SPI_IsActiveFlag_TXE(SPI2)) && (timeout++ < 1000u)) { } LL_SPI_TransmitData16(SPI2, command); timeout = 0u; while ((!LL_SPI_IsActiveFlag_RXNE(SPI2)) && (timeout++ < 1000u)) { } (void)SPI2->DR; timeout = 0u; while ((!LL_SPI_IsActiveFlag_TXE(SPI2)) && (timeout++ < 1000u)) { } LL_SPI_TransmitData16(SPI2, value); timeout = 0u; while ((!LL_SPI_IsActiveFlag_RXNE(SPI2)) && (timeout++ < 1000u)) { } (void)SPI2->DR; HAL_GPIO_WritePin(AD9102_CS_GPIO_Port, AD9102_CS_Pin, GPIO_PIN_SET); } static uint16_t ad9102_read_reg(uint16_t address) { uint16_t command = (uint16_t)(0x8000u | (address & 0x7FFFu)); uint16_t value; uint32_t timeout = 0u; board_io_configure_spi2_mode(LL_SPI_POLARITY_LOW, LL_SPI_PHASE_1EDGE); HAL_GPIO_WritePin(DAC_LD1_CS_GPIO_Port, DAC_LD1_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_SET); if (!LL_SPI_IsEnabled(SPI2)) { LL_SPI_Enable(SPI2); } HAL_GPIO_WritePin(AD9102_CS_GPIO_Port, AD9102_CS_Pin, GPIO_PIN_RESET); while ((!LL_SPI_IsActiveFlag_TXE(SPI2)) && (timeout++ < 1000u)) { } LL_SPI_TransmitData16(SPI2, command); timeout = 0u; while ((!LL_SPI_IsActiveFlag_RXNE(SPI2)) && (timeout++ < 1000u)) { } (void)SPI2->DR; timeout = 0u; while ((!LL_SPI_IsActiveFlag_TXE(SPI2)) && (timeout++ < 1000u)) { } LL_SPI_TransmitData16(SPI2, 0x0000u); timeout = 0u; while ((!LL_SPI_IsActiveFlag_RXNE(SPI2)) && (timeout++ < 1000u)) { } value = LL_SPI_ReceiveData16(SPI2); HAL_GPIO_WritePin(AD9102_CS_GPIO_Port, AD9102_CS_Pin, GPIO_PIN_SET); return value; } static void ad9102_write_reg_table(const uint16_t *values, uint16_t count) { uint16_t index; for (index = 0u; index < count; ++index) { ad9102_write_reg(g_ad9102_reg_addr[index], values[index]); } } static void ad9102_reset_upload_state(void) { g_upload_state.active = 0u; g_upload_state.expected_samples = 0u; g_upload_state.written_samples = 0u; } static void ad9102_start_output(void) { HAL_GPIO_WritePin(AD9102_TRIG_GPIO_Port, AD9102_TRIG_Pin, GPIO_PIN_SET); ad9102_write_reg(AD9102_REG_PAT_STATUS, AD9102_PAT_STATUS_RUN); ad9102_write_reg(AD9102_REG_RAMUPDATE, 0x0001u); for (volatile uint32_t delay_counter = 0u; delay_counter < 1000u; ++delay_counter) { } HAL_GPIO_WritePin(AD9102_TRIG_GPIO_Port, AD9102_TRIG_Pin, GPIO_PIN_RESET); } static void ad9102_configure_sram_playback(uint16_t sample_count, uint8_t hold_cycles) { uint16_t pat_timebase; uint32_t pat_period; if (sample_count < 2u) { sample_count = 2u; } if (sample_count > AD9102_SRAM_MAX_SAMPLE_COUNT) { sample_count = AD9102_SRAM_MAX_SAMPLE_COUNT; } if (hold_cycles == 0u) { hold_cycles = AD9102_SRAM_DEFAULT_HOLD; } if (hold_cycles > 0x0Fu) { hold_cycles = 0x0Fu; } pat_timebase = (uint16_t)(((uint16_t)(hold_cycles & 0x0Fu) << 8) | ((AD9102_SRAM_PAT_PERIOD_BASE_DEFAULT & 0x0Fu) << 4) | (AD9102_SRAM_START_DELAY_BASE_DEFAULT & 0x0Fu)); pat_period = (uint32_t)sample_count * (uint32_t)(hold_cycles & 0x0Fu); if (pat_period == 0u) { pat_period = sample_count; } if (pat_period > 0xFFFFu) { pat_period = 0xFFFFu; } ad9102_write_reg_table(g_ad9102_example2_regval, AD9102_REG_COUNT); ad9102_stop_output(); ad9102_write_reg(AD9102_REG_WAV_CONFIG, AD9102_EX2_WAV_CONFIG); ad9102_write_reg(AD9102_REG_SAW_CONFIG, AD9102_EX2_SAW_CONFIG); ad9102_write_reg(AD9102_REG_DAC_PAT, AD9102_EX2_DAC_PAT); ad9102_write_reg(AD9102_REG_PAT_TIMEBASE, pat_timebase); ad9102_write_reg(AD9102_REG_PAT_PERIOD, (uint16_t)pat_period); ad9102_write_reg(AD9102_REG_PAT_TYPE, 0x0000u); ad9102_write_reg(AD9102_REG_START_DLY, AD9102_SRAM_START_DLY_DEFAULT); ad9102_write_reg(AD9102_REG_START_ADDR, 0x0000u); ad9102_write_reg(AD9102_REG_STOP_ADDR, (uint16_t)((sample_count - 1u) << 4)); ad9102_write_reg(AD9102_REG_RAMUPDATE, 0x0001u); } static void ad9102_load_sram_ramp(uint16_t sample_count, uint8_t triangle_mode, uint16_t amplitude) { uint16_t sample_index; if (sample_count < 2u) { sample_count = 2u; } if (sample_count > AD9102_SRAM_MAX_SAMPLE_COUNT) { sample_count = AD9102_SRAM_MAX_SAMPLE_COUNT; } if (amplitude > AD9102_SRAM_DEFAULT_AMPLITUDE) { amplitude = AD9102_SRAM_DEFAULT_AMPLITUDE; } ad9102_write_reg(AD9102_REG_PAT_STATUS, 0x0004u); for (sample_index = 0u; sample_index < sample_count; ++sample_index) { int32_t value; int32_t min_value = -(int32_t)amplitude; int32_t max_value = (int32_t)amplitude; int32_t span = max_value - min_value; if (triangle_mode != 0u) { uint16_t half = sample_count / 2u; if (half == 0u) { half = 1u; } if (sample_index < half) { uint16_t denominator = (half > 1u) ? (uint16_t)(half - 1u) : 1u; value = min_value + (span * (int32_t)sample_index) / (int32_t)denominator; } else { uint16_t tail = (uint16_t)(sample_count - half); uint16_t denominator = (tail > 1u) ? (uint16_t)(tail - 1u) : 1u; value = max_value - (span * (int32_t)(sample_index - half)) / (int32_t)denominator; } } else { uint16_t denominator = (sample_count > 1u) ? (uint16_t)(sample_count - 1u) : 1u; value = min_value + (span * (int32_t)sample_index) / (int32_t)denominator; } if (value < AD9102_SRAM_RAMP_MIN) { value = AD9102_SRAM_RAMP_MIN; } else if (value > AD9102_SRAM_RAMP_MAX) { value = AD9102_SRAM_RAMP_MAX; } ad9102_write_reg((uint16_t)(AD9102_REG_SRAM_DATA_BASE + sample_index), (uint16_t)(((uint16_t)((int16_t)value) & 0x3FFFu) << 2)); } ad9102_write_reg(AD9102_REG_PAT_STATUS, 0x0000u); } void ad9102_init(void) { HAL_GPIO_WritePin(AD9102_CS_GPIO_Port, AD9102_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(AD9102_RESET_GPIO_Port, AD9102_RESET_Pin, GPIO_PIN_RESET); for (volatile uint32_t delay_counter = 0u; delay_counter < 1000u; ++delay_counter) { } HAL_GPIO_WritePin(AD9102_RESET_GPIO_Port, AD9102_RESET_Pin, GPIO_PIN_SET); ad9102_write_reg_table(g_ad9102_example4_regval, AD9102_REG_COUNT); ad9102_write_reg(AD9102_REG_PAT_STATUS, 0x0000u); ad9102_write_reg(AD9102_REG_RAMUPDATE, 0x0001u); HAL_GPIO_WritePin(AD9102_TRIG_GPIO_Port, AD9102_TRIG_Pin, GPIO_PIN_SET); ad9102_reset_upload_state(); } void ad9102_stop_output(void) { ad9102_write_reg(AD9102_REG_PAT_STATUS, 0x0000u); HAL_GPIO_WritePin(AD9102_TRIG_GPIO_Port, AD9102_TRIG_Pin, GPIO_PIN_SET); } uint16_t ad9102_apply_saw(uint8_t saw_type, uint8_t enabled, uint8_t saw_step, uint8_t pat_period_base, uint16_t pat_period) { uint16_t saw_config; uint16_t pat_timebase; ad9102_reset_upload_state(); if (enabled == 0u) { ad9102_stop_output(); return ad9102_read_reg(AD9102_REG_PAT_STATUS); } if (saw_step == 0u) { saw_step = AD9102_SAW_STEP_DEFAULT; } else if (saw_step > 63u) { saw_step = 63u; } if (pat_period == 0u) { pat_period = AD9102_PAT_PERIOD_DEFAULT; } saw_config = (uint16_t)(((uint16_t)(saw_step & 0x3Fu) << 2) | ((uint16_t)(saw_type & 0x3u))); pat_timebase = (uint16_t)(((AD9102_PAT_TIMEBASE_HOLD_DEFAULT & 0x0Fu) << 8) | ((pat_period_base & 0x0Fu) << 4) | (AD9102_START_DELAY_BASE_DEFAULT & 0x0Fu)); ad9102_write_reg(AD9102_REG_WAV_CONFIG, AD9102_EX4_WAV_CONFIG); ad9102_write_reg(AD9102_REG_SAW_CONFIG, saw_config); ad9102_write_reg(AD9102_REG_PAT_TIMEBASE, pat_timebase); ad9102_write_reg(AD9102_REG_PAT_PERIOD, pat_period); ad9102_write_reg(AD9102_REG_PAT_TYPE, 0x0000u); ad9102_start_output(); return ad9102_read_reg(AD9102_REG_PAT_STATUS); } uint16_t ad9102_apply_generated_sram(uint8_t enabled, uint16_t sample_count, uint8_t hold_cycles, uint8_t triangle_mode, uint16_t amplitude) { ad9102_reset_upload_state(); if (sample_count == 0u) { sample_count = AD9102_SRAM_DEFAULT_SAMPLE_COUNT; } if (sample_count < 2u) { sample_count = 2u; } if (sample_count > AD9102_SRAM_MAX_SAMPLE_COUNT) { sample_count = AD9102_SRAM_MAX_SAMPLE_COUNT; } if (hold_cycles == 0u) { hold_cycles = AD9102_SRAM_DEFAULT_HOLD; } if (hold_cycles > 0x0Fu) { hold_cycles = 0x0Fu; } if (amplitude > AD9102_SRAM_DEFAULT_AMPLITUDE) { amplitude = AD9102_SRAM_DEFAULT_AMPLITUDE; } ad9102_configure_sram_playback(sample_count, hold_cycles); ad9102_load_sram_ramp(sample_count, triangle_mode, amplitude); if (enabled != 0u) { ad9102_start_output(); } else { ad9102_stop_output(); } return ad9102_read_reg(AD9102_REG_PAT_STATUS); } bool ad9102_begin_custom_upload(uint16_t sample_count) { if ((sample_count < 2u) || (sample_count > AD9102_SRAM_MAX_SAMPLE_COUNT)) { return false; } ad9102_stop_output(); ad9102_reset_upload_state(); ad9102_configure_sram_playback(sample_count, AD9102_SRAM_DEFAULT_HOLD); ad9102_write_reg(AD9102_REG_PAT_STATUS, 0x0004u); g_upload_state.expected_samples = sample_count; g_upload_state.written_samples = 0u; g_upload_state.active = 1u; return true; } bool ad9102_write_custom_chunk(const uint16_t *samples, uint16_t chunk_count) { uint16_t index; if ((samples == NULL) || (g_upload_state.active == 0u)) { return false; } if ((chunk_count == 0u) || (chunk_count > AD9102_WAVE_MAX_CHUNK_SAMPLES)) { return false; } if (((uint32_t)g_upload_state.written_samples + (uint32_t)chunk_count) > (uint32_t)g_upload_state.expected_samples) { return false; } for (index = 0u; index < chunk_count; ++index) { int16_t sample = (int16_t)samples[index]; if ((sample < AD9102_SRAM_RAMP_MIN) || (sample > AD9102_SRAM_RAMP_MAX)) { return false; } ad9102_write_reg((uint16_t)(AD9102_REG_SRAM_DATA_BASE + g_upload_state.written_samples + index), (uint16_t)(((uint16_t)sample & 0x3FFFu) << 2)); } g_upload_state.written_samples = (uint16_t)(g_upload_state.written_samples + chunk_count); return true; } uint16_t ad9102_commit_custom_upload(bool *out_ok) { uint16_t pat_status; if (out_ok != NULL) { *out_ok = false; } if ((g_upload_state.active == 0u) || (g_upload_state.expected_samples < 2u) || (g_upload_state.written_samples != g_upload_state.expected_samples)) { ad9102_cancel_custom_upload(); return ad9102_read_reg(AD9102_REG_PAT_STATUS); } ad9102_write_reg(AD9102_REG_PAT_STATUS, 0x0000u); ad9102_write_reg(AD9102_REG_START_ADDR, 0x0000u); ad9102_write_reg(AD9102_REG_STOP_ADDR, (uint16_t)((g_upload_state.expected_samples - 1u) << 4)); ad9102_write_reg(AD9102_REG_RAMUPDATE, 0x0001u); ad9102_start_output(); pat_status = ad9102_read_reg(AD9102_REG_PAT_STATUS); ad9102_reset_upload_state(); if (out_ok != NULL) { *out_ok = true; } return pat_status; } void ad9102_cancel_custom_upload(void) { if (g_upload_state.active != 0u) { ad9102_stop_output(); } ad9102_reset_upload_state(); } uint8_t ad9102_check_saw_configuration(uint16_t pat_status, uint8_t expect_run, uint8_t saw_type, uint8_t saw_step, uint8_t pat_period_base, uint16_t pat_period) { uint16_t spiconfig = ad9102_read_reg(AD9102_REG_SPICONFIG); uint16_t power_config = ad9102_read_reg(AD9102_REG_POWERCONFIG); uint16_t clock_config = ad9102_read_reg(AD9102_REG_CLOCKCONFIG); uint16_t config_error = ad9102_read_reg(AD9102_REG_CFG_ERROR); uint16_t pat_timebase = (uint16_t)(((AD9102_PAT_TIMEBASE_HOLD_DEFAULT & 0x0Fu) << 8) | ((pat_period_base & 0x0Fu) << 4) | (AD9102_START_DELAY_BASE_DEFAULT & 0x0Fu)); uint16_t expected_saw; uint8_t ok = 1u; if (saw_step == 0u) { saw_step = AD9102_SAW_STEP_DEFAULT; } if (saw_step > 63u) { saw_step = 63u; } if (pat_period == 0u) { pat_period = AD9102_PAT_PERIOD_DEFAULT; } expected_saw = (uint16_t)(((uint16_t)(saw_step & 0x3Fu) << 2) | ((uint16_t)(saw_type & 0x3u))); if (spiconfig != 0x0000u) { ok = 0u; } if (power_config & ((1u << 8) | (1u << 7) | (1u << 6) | (1u << 5) | (1u << 3))) { ok = 0u; } if (clock_config & ((1u << 11) | (1u << 7) | (1u << 6) | (1u << 5))) { ok = 0u; } if (config_error & 0x003Fu) { ok = 0u; } if ((expect_run != 0u) && ((pat_status & AD9102_PAT_STATUS_RUN) == 0u)) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_WAV_CONFIG) != AD9102_EX4_WAV_CONFIG) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_PAT_TIMEBASE) != pat_timebase) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_PAT_PERIOD) != pat_period) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_PAT_TYPE) != 0x0000u) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_SAW_CONFIG) != expected_saw) { ok = 0u; } return (ok != 0u) ? 0u : 1u; } uint8_t ad9102_check_sram_configuration(uint16_t pat_status, uint8_t expect_run, uint16_t sample_count, uint8_t hold_cycles) { uint16_t spiconfig = ad9102_read_reg(AD9102_REG_SPICONFIG); uint16_t power_config = ad9102_read_reg(AD9102_REG_POWERCONFIG); uint16_t clock_config = ad9102_read_reg(AD9102_REG_CLOCKCONFIG); uint16_t config_error = ad9102_read_reg(AD9102_REG_CFG_ERROR); uint16_t pat_timebase; uint32_t pat_period; uint16_t stop_address; uint8_t ok = 1u; if (sample_count == 0u) { sample_count = AD9102_SRAM_DEFAULT_SAMPLE_COUNT; } if (sample_count < 2u) { sample_count = 2u; } if (sample_count > AD9102_SRAM_MAX_SAMPLE_COUNT) { sample_count = AD9102_SRAM_MAX_SAMPLE_COUNT; } if (hold_cycles == 0u) { hold_cycles = AD9102_SRAM_DEFAULT_HOLD; } if (hold_cycles > 0x0Fu) { hold_cycles = 0x0Fu; } pat_timebase = (uint16_t)(((uint16_t)(hold_cycles & 0x0Fu) << 8) | ((AD9102_SRAM_PAT_PERIOD_BASE_DEFAULT & 0x0Fu) << 4) | (AD9102_SRAM_START_DELAY_BASE_DEFAULT & 0x0Fu)); pat_period = (uint32_t)sample_count * (uint32_t)(hold_cycles & 0x0Fu); if (pat_period == 0u) { pat_period = sample_count; } if (pat_period > 0xFFFFu) { pat_period = 0xFFFFu; } stop_address = (uint16_t)((sample_count - 1u) << 4); if (spiconfig != 0x0000u) { ok = 0u; } if (power_config & ((1u << 8) | (1u << 7) | (1u << 6) | (1u << 5) | (1u << 3))) { ok = 0u; } if (clock_config & ((1u << 11) | (1u << 7) | (1u << 6) | (1u << 5))) { ok = 0u; } if (config_error & 0x003Fu) { ok = 0u; } if ((expect_run != 0u) && ((pat_status & AD9102_PAT_STATUS_RUN) == 0u)) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_WAV_CONFIG) != AD9102_EX2_WAV_CONFIG) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_PAT_TIMEBASE) != pat_timebase) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_PAT_PERIOD) != (uint16_t)pat_period) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_PAT_TYPE) != 0x0000u) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_START_ADDR) != 0x0000u) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_STOP_ADDR) != stop_address) { ok = 0u; } if (ad9102_read_reg(AD9102_REG_DAC_PAT) != AD9102_EX2_DAC_PAT) { ok = 0u; } return (ok != 0u) ? 0u : 1u; }