diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c index 319475b..8102200 100644 --- a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c @@ -1,510 +1,641 @@ -#include "adf4382a_manager.h" -#include "no_os_delay.h" -#include -#include - -// External SPI handle -extern SPI_HandleTypeDef hspi4; - -// Static function prototypes -static void set_chip_enable(uint8_t ce_pin, bool state); -static void set_deladj_pin(uint8_t device, bool state); -static void set_delstr_pin(uint8_t device, bool state); -static uint16_t phase_ps_to_duty_cycle(uint16_t phase_ps); - -int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method) -{ - struct adf4382_init_param tx_param, rx_param; - int ret; - - if (!manager) { - return ADF4382A_MANAGER_ERROR_INVALID; - } - - // Initialize manager structure - manager->tx_dev = NULL; - manager->rx_dev = NULL; - manager->initialized = false; - manager->sync_method = method; - manager->tx_phase_shift_ps = 0; - manager->rx_phase_shift_ps = 0; - - // Initialize SPI parameters in manager - memset(&manager->spi_tx_param, 0, sizeof(manager->spi_tx_param)); - memset(&manager->spi_rx_param, 0, sizeof(manager->spi_rx_param)); - - // Setup TX SPI parameters for SPI4 - manager->spi_tx_param.device_id = ADF4382A_SPI_DEVICE_ID; - manager->spi_tx_param.max_speed_hz = ADF4382A_SPI_SPEED_HZ; - manager->spi_tx_param.mode = NO_OS_SPI_MODE_0; - manager->spi_tx_param.chip_select = TX_CS_Pin; - manager->spi_tx_param.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST; - manager->spi_tx_param.platform_ops = NULL; - manager->spi_tx_param.extra = &hspi4; - - // Setup RX SPI parameters for SPI4 - manager->spi_rx_param.device_id = ADF4382A_SPI_DEVICE_ID; - manager->spi_rx_param.max_speed_hz = ADF4382A_SPI_SPEED_HZ; - manager->spi_rx_param.mode = NO_OS_SPI_MODE_0; - manager->spi_rx_param.chip_select = RX_CS_Pin; - manager->spi_rx_param.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST; - manager->spi_rx_param.platform_ops = NULL; - manager->spi_rx_param.extra = &hspi4; - - // Configure TX parameters (10.5 GHz) - memset(&tx_param, 0, sizeof(tx_param)); - tx_param.spi_3wire_en = 0; - tx_param.cmos_3v3 = 1; - tx_param.ref_freq_hz = REF_FREQ_HZ; - tx_param.ref_div = 1; - tx_param.ref_doubler_en = false; - tx_param.freq = TX_FREQ_HZ; - tx_param.id = ID_ADF4382A; - tx_param.cp_i = 3; - tx_param.bleed_word = 1000; - tx_param.ld_count = 0x07; - tx_param.spi_init = &manager->spi_tx_param; - - // Configure RX parameters (10.38 GHz) - memset(&rx_param, 0, sizeof(rx_param)); - rx_param.spi_3wire_en = 0; - rx_param.cmos_3v3 = 1; - rx_param.ref_freq_hz = REF_FREQ_HZ; - rx_param.ref_div = 1; - rx_param.ref_doubler_en = false; - rx_param.freq = RX_FREQ_HZ; - rx_param.id = ID_ADF4382A; - rx_param.cp_i = 4; - rx_param.bleed_word = 1200; - rx_param.ld_count = 0x07; - rx_param.spi_init = &manager->spi_rx_param; - - // Enable chips - set_chip_enable(TX_CE_Pin, true); - set_chip_enable(RX_CE_Pin, true); - no_os_udelay(1000); - - // Initialize DELADJ and DELSTR pins - set_deladj_pin(0, false); // TX device - set_deladj_pin(1, false); // RX device - set_delstr_pin(0, false); // TX device - set_delstr_pin(1, false); // RX device - - // Initialize TX device first - printf("Initializing TX ADF4382A (10.5 GHz) on SPI4...\n"); - ret = adf4382_init(&manager->tx_dev, &tx_param); - if (ret) { - printf("TX ADF4382A initialization failed: %d\n", ret); - set_chip_enable(TX_CE_Pin, false); - set_chip_enable(RX_CE_Pin, false); - return ADF4382A_MANAGER_ERROR_SPI; - } - - // Small delay between initializations - no_os_udelay(5000); - - // Initialize RX device - printf("Initializing RX ADF4382A (10.38 GHz) on SPI4...\n"); - ret = adf4382_init(&manager->rx_dev, &rx_param); - if (ret) { - printf("RX ADF4382A initialization failed: %d\n", ret); - adf4382_remove(manager->tx_dev); - set_chip_enable(TX_CE_Pin, false); - set_chip_enable(RX_CE_Pin, false); - return ADF4382A_MANAGER_ERROR_SPI; - } - - // Set output power - adf4382_set_out_power(manager->tx_dev, 0, 12); - adf4382_set_out_power(manager->tx_dev, 1, 12); - adf4382_set_out_power(manager->rx_dev, 0, 12); - adf4382_set_out_power(manager->rx_dev, 1, 12); - - // Enable outputs - adf4382_set_en_chan(manager->tx_dev, 0, true); - adf4382_set_en_chan(manager->tx_dev, 1, false); - adf4382_set_en_chan(manager->rx_dev, 0, true); - adf4382_set_en_chan(manager->rx_dev, 1, false); - - // Setup synchronization based on selected method - if (method == SYNC_METHOD_TIMED) { - ret = ADF4382A_SetupTimedSync(manager); - if (ret) { - printf("Timed sync setup failed: %d\n", ret); - } - } else { - ret = ADF4382A_SetupEZSync(manager); - if (ret) { - printf("EZSync setup failed: %d\n", ret); - } - } - - manager->initialized = true; - printf("ADF4382A Manager initialized with %s synchronization on SPI4\n", - (method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC"); - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_SetupTimedSync(ADF4382A_Manager *manager) -{ - int ret; - - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - printf("Setting up Timed Synchronization (60 MHz SYNCP/SYNCN)...\n"); - - // Setup TX for timed sync - ret = adf4382_set_timed_sync_setup(manager->tx_dev, true); - if (ret) { - printf("TX timed sync setup failed: %d\n", ret); - return ret; - } - - // Setup RX for timed sync - ret = adf4382_set_timed_sync_setup(manager->rx_dev, true); - if (ret) { - printf("RX timed sync setup failed: %d\n", ret); - return ret; - } - - manager->sync_method = SYNC_METHOD_TIMED; - printf("Timed synchronization configured for 60 MHz SYNCP/SYNCN\n"); - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_SetupEZSync(ADF4382A_Manager *manager) -{ - int ret; - - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - printf("Setting up EZSync (SPI-based synchronization)...\n"); - - // Setup TX for EZSync - ret = adf4382_set_ezsync_setup(manager->tx_dev, true); - if (ret) { - printf("TX EZSync setup failed: %d\n", ret); - return ret; - } - - // Setup RX for EZSync - ret = adf4382_set_ezsync_setup(manager->rx_dev, true); - if (ret) { - printf("RX EZSync setup failed: %d\n", ret); - return ret; - } - - manager->sync_method = SYNC_METHOD_EZSYNC; - printf("EZSync configured\n"); - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_TriggerTimedSync(ADF4382A_Manager *manager) -{ - if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_TIMED) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - printf("Timed sync ready - SYNC pin will trigger synchronization\n"); - printf("Ensure 60 MHz phase-aligned clocks are present on SYNCP/SYNCN pins\n"); - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_TriggerEZSync(ADF4382A_Manager *manager) -{ - int ret; - - if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_EZSYNC) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Trigger software sync on both devices - ret = adf4382_set_sw_sync(manager->tx_dev, true); - if (ret) { - printf("TX software sync failed: %d\n", ret); - return ADF4382A_MANAGER_ERROR_SPI; - } - - ret = adf4382_set_sw_sync(manager->rx_dev, true); - if (ret) { - printf("RX software sync failed: %d\n", ret); - return ADF4382A_MANAGER_ERROR_SPI; - } - - // Small delay for sync to take effect - no_os_udelay(10); - - // Clear software sync - ret = adf4382_set_sw_sync(manager->tx_dev, false); - if (ret) { - printf("TX sync clear failed: %d\n", ret); - return ADF4382A_MANAGER_ERROR_SPI; - } - - ret = adf4382_set_sw_sync(manager->rx_dev, false); - if (ret) { - printf("RX sync clear failed: %d\n", ret); - return ADF4382A_MANAGER_ERROR_SPI; - } - - printf("EZSync triggered via SPI\n"); - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_Manager_Deinit(ADF4382A_Manager *manager) -{ - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Disable outputs first - if (manager->tx_dev) { - adf4382_set_en_chan(manager->tx_dev, 0, false); - adf4382_set_en_chan(manager->tx_dev, 1, false); - } - - if (manager->rx_dev) { - adf4382_set_en_chan(manager->rx_dev, 0, false); - adf4382_set_en_chan(manager->rx_dev, 1, false); - } - - // Remove devices - if (manager->tx_dev) { - adf4382_remove(manager->tx_dev); - manager->tx_dev = NULL; - } - - if (manager->rx_dev) { - adf4382_remove(manager->rx_dev); - manager->rx_dev = NULL; - } - - // Disable chips and phase control pins - set_chip_enable(TX_CE_Pin, false); - set_chip_enable(RX_CE_Pin, false); - set_deladj_pin(0, false); - set_deladj_pin(1, false); - set_delstr_pin(0, false); - set_delstr_pin(1, false); - - manager->initialized = false; - - printf("ADF4382A Manager deinitialized\n"); - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_CheckLockStatus(ADF4382A_Manager *manager, bool *tx_locked, bool *rx_locked) -{ - uint8_t tx_status, rx_status; - int ret; - - if (!manager || !manager->initialized || !tx_locked || !rx_locked) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Read lock status from registers - ret = adf4382_spi_read(manager->tx_dev, 0x58, &tx_status); - if (ret) { - printf("TX lock status read failed: %d\n", ret); - return ADF4382A_MANAGER_ERROR_SPI; - } - - ret = adf4382_spi_read(manager->rx_dev, 0x58, &rx_status); - if (ret) { - printf("RX lock status read failed: %d\n", ret); - return ADF4382A_MANAGER_ERROR_SPI; - } - - *tx_locked = (tx_status & ADF4382_LOCKED_MSK) != 0; - *rx_locked = (rx_status & ADF4382_LOCKED_MSK) != 0; - - // Also check GPIO lock detect pins as backup - bool tx_gpio_locked = HAL_GPIO_ReadPin(TX_LKDET_GPIO_Port, TX_LKDET_Pin) == GPIO_PIN_SET; - bool rx_gpio_locked = HAL_GPIO_ReadPin(RX_LKDET_GPIO_Port, RX_LKDET_Pin) == GPIO_PIN_SET; - - // Use both register and GPIO status - *tx_locked = *tx_locked && tx_gpio_locked; - *rx_locked = *rx_locked && rx_gpio_locked; - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_SetOutputPower(ADF4382A_Manager *manager, uint8_t tx_power, uint8_t rx_power) -{ - int ret; - - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Clamp power values (0-15) - tx_power = (tx_power > 15) ? 15 : tx_power; - rx_power = (rx_power > 15) ? 15 : rx_power; - - // Set TX power for both channels - ret = adf4382_set_out_power(manager->tx_dev, 0, tx_power); - if (ret) return ret; - ret = adf4382_set_out_power(manager->tx_dev, 1, tx_power); - if (ret) return ret; - - // Set RX power for both channels - ret = adf4382_set_out_power(manager->rx_dev, 0, rx_power); - if (ret) return ret; - ret = adf4382_set_out_power(manager->rx_dev, 1, rx_power); - - printf("Output power set: TX=%d, RX=%d\n", tx_power, rx_power); - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_EnableOutputs(ADF4382A_Manager *manager, bool tx_enable, bool rx_enable) -{ - int ret; - - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Enable/disable TX outputs - ret = adf4382_set_en_chan(manager->tx_dev, 0, tx_enable); - if (ret) return ret; - ret = adf4382_set_en_chan(manager->tx_dev, 1, tx_enable); - if (ret) return ret; - - // Enable/disable RX outputs - ret = adf4382_set_en_chan(manager->rx_dev, 0, rx_enable); - if (ret) return ret; - ret = adf4382_set_en_chan(manager->rx_dev, 1, rx_enable); - - printf("Outputs: TX=%s, RX=%s\n", - tx_enable ? "ENABLED" : "DISABLED", - rx_enable ? "ENABLED" : "DISABLED"); - return ADF4382A_MANAGER_OK; -} - -// New phase delay functions - -int ADF4382A_SetPhaseShift(ADF4382A_Manager *manager, uint16_t tx_phase_ps, uint16_t rx_phase_ps) -{ - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Clamp phase shift values - tx_phase_ps = (tx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : tx_phase_ps; - rx_phase_ps = (rx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : rx_phase_ps; - - // Convert phase shift to duty cycle and apply - if (tx_phase_ps != manager->tx_phase_shift_ps) { - uint16_t duty_cycle = phase_ps_to_duty_cycle(tx_phase_ps); - ADF4382A_SetFinePhaseShift(manager, 0, duty_cycle); // 0 = TX device - manager->tx_phase_shift_ps = tx_phase_ps; - } - - if (rx_phase_ps != manager->rx_phase_shift_ps) { - uint16_t duty_cycle = phase_ps_to_duty_cycle(rx_phase_ps); - ADF4382A_SetFinePhaseShift(manager, 1, duty_cycle); // 1 = RX device - manager->rx_phase_shift_ps = rx_phase_ps; - } - - printf("Phase shift set: TX=%d ps, RX=%d ps\n", tx_phase_ps, rx_phase_ps); - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_GetPhaseShift(ADF4382A_Manager *manager, uint16_t *tx_phase_ps, uint16_t *rx_phase_ps) -{ - if (!manager || !manager->initialized || !tx_phase_ps || !rx_phase_ps) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - *tx_phase_ps = manager->tx_phase_shift_ps; - *rx_phase_ps = manager->rx_phase_shift_ps; - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_SetFinePhaseShift(ADF4382A_Manager *manager, uint8_t device, uint16_t duty_cycle) -{ - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Clamp duty cycle - duty_cycle = (duty_cycle > DELADJ_MAX_DUTY_CYCLE) ? DELADJ_MAX_DUTY_CYCLE : duty_cycle; - - // For simplicity, we'll use a basic implementation - // In a real system, you would generate a PWM signal on DELADJ pin - // Here we just set the pin state based on a simplified approach - - if (duty_cycle == 0) { - set_deladj_pin(device, false); - } else if (duty_cycle >= DELADJ_MAX_DUTY_CYCLE) { - set_deladj_pin(device, true); - } else { - // For intermediate values, you would need PWM generation - // This is a simplified implementation - set_deladj_pin(device, true); - } - - printf("Device %d DELADJ duty cycle set to %d/%d\n", - device, duty_cycle, DELADJ_MAX_DUTY_CYCLE); - - return ADF4382A_MANAGER_OK; -} - -int ADF4382A_StrobePhaseShift(ADF4382A_Manager *manager, uint8_t device) -{ - if (!manager || !manager->initialized) { - return ADF4382A_MANAGER_ERROR_NOT_INIT; - } - - // Generate a pulse on DELSTR pin to latch the current DELADJ value - set_delstr_pin(device, true); - no_os_udelay(DELADJ_PULSE_WIDTH_US); - set_delstr_pin(device, false); - - printf("Device %d phase shift strobed\n", device); - - return ADF4382A_MANAGER_OK; -} - -// Static helper functions - -static void set_chip_enable(uint8_t ce_pin, bool state) -{ - GPIO_TypeDef* port = (ce_pin == TX_CE_Pin) ? TX_CE_GPIO_Port : RX_CE_GPIO_Port; - HAL_GPIO_WritePin(port, ce_pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); -} - -static void set_deladj_pin(uint8_t device, bool state) -{ - if (device == 0) { // TX device - HAL_GPIO_WritePin(TX_DELADJ_GPIO_Port, TX_DELADJ_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); - } else { // RX device - HAL_GPIO_WritePin(RX_DELADJ_GPIO_Port, RX_DELADJ_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); - } -} - -static void set_delstr_pin(uint8_t device, bool state) -{ - if (device == 0) { // TX device - HAL_GPIO_WritePin(TX_DELSTR_GPIO_Port, TX_DELSTR_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); - } else { // RX device - HAL_GPIO_WritePin(RX_DELSTR_GPIO_Port, RX_DELSTR_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); - } -} - -static uint16_t phase_ps_to_duty_cycle(uint16_t phase_ps) -{ - // Convert phase shift in picoseconds to DELADJ duty cycle - // This is a linear mapping - adjust based on your specific requirements - uint32_t duty = (uint32_t)phase_ps * DELADJ_MAX_DUTY_CYCLE / PHASE_SHIFT_MAX_PS; - return (uint16_t)duty; -} +#include "adf4382a_manager.h" +#include "diag_log.h" +#include "no_os_delay.h" +#include +#include + +// External SPI handle +extern SPI_HandleTypeDef hspi4; + +// Static function prototypes +static void set_chip_enable(uint8_t ce_pin, bool state); +static void set_deladj_pin(uint8_t device, bool state); +static void set_delstr_pin(uint8_t device, bool state); +static uint16_t phase_ps_to_duty_cycle(uint16_t phase_ps); + +int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method) +{ + struct adf4382_init_param tx_param, rx_param; + int ret; + uint32_t t_start = HAL_GetTick(); + + DIAG_SECTION("ADF4382A LO MANAGER INIT"); + DIAG("LO", "Init called with sync_method=%d (%s)", + method, (method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC"); + + if (!manager) { + DIAG_ERR("LO", "Init called with NULL manager pointer"); + return ADF4382A_MANAGER_ERROR_INVALID; + } + + // Initialize manager structure + manager->tx_dev = NULL; + manager->rx_dev = NULL; + manager->initialized = false; + manager->sync_method = method; + manager->tx_phase_shift_ps = 0; + manager->rx_phase_shift_ps = 0; + + DIAG("LO", "Manager struct zeroed, initialized=%s", manager->initialized ? "true" : "false"); + + // Initialize SPI parameters in manager + memset(&manager->spi_tx_param, 0, sizeof(manager->spi_tx_param)); + memset(&manager->spi_rx_param, 0, sizeof(manager->spi_rx_param)); + + // Setup TX SPI parameters for SPI4 + manager->spi_tx_param.device_id = ADF4382A_SPI_DEVICE_ID; + manager->spi_tx_param.max_speed_hz = ADF4382A_SPI_SPEED_HZ; + manager->spi_tx_param.mode = NO_OS_SPI_MODE_0; + manager->spi_tx_param.chip_select = TX_CS_Pin; + manager->spi_tx_param.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST; + manager->spi_tx_param.platform_ops = NULL; + manager->spi_tx_param.extra = &hspi4; + + // Setup RX SPI parameters for SPI4 + manager->spi_rx_param.device_id = ADF4382A_SPI_DEVICE_ID; + manager->spi_rx_param.max_speed_hz = ADF4382A_SPI_SPEED_HZ; + manager->spi_rx_param.mode = NO_OS_SPI_MODE_0; + manager->spi_rx_param.chip_select = RX_CS_Pin; + manager->spi_rx_param.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST; + manager->spi_rx_param.platform_ops = NULL; + manager->spi_rx_param.extra = &hspi4; + + DIAG("LO", "SPI4 params: TX_CS=0x%04X RX_CS=0x%04X speed=%lu Hz", + TX_CS_Pin, RX_CS_Pin, (unsigned long)ADF4382A_SPI_SPEED_HZ); + + // Configure TX parameters (10.5 GHz) + memset(&tx_param, 0, sizeof(tx_param)); + tx_param.spi_3wire_en = 0; + tx_param.cmos_3v3 = 1; + tx_param.ref_freq_hz = REF_FREQ_HZ; + tx_param.ref_div = 1; + tx_param.ref_doubler_en = false; + tx_param.freq = TX_FREQ_HZ; + tx_param.id = ID_ADF4382A; + tx_param.cp_i = 3; + tx_param.bleed_word = 1000; + tx_param.ld_count = 0x07; + tx_param.spi_init = &manager->spi_tx_param; + + // Configure RX parameters (10.38 GHz) + memset(&rx_param, 0, sizeof(rx_param)); + rx_param.spi_3wire_en = 0; + rx_param.cmos_3v3 = 1; + rx_param.ref_freq_hz = REF_FREQ_HZ; + rx_param.ref_div = 1; + rx_param.ref_doubler_en = false; + rx_param.freq = RX_FREQ_HZ; + rx_param.id = ID_ADF4382A; + rx_param.cp_i = 4; + rx_param.bleed_word = 1200; + rx_param.ld_count = 0x07; + rx_param.spi_init = &manager->spi_rx_param; + + DIAG("LO", "TX target: %llu Hz, ref=%llu Hz, cp_i=%d, bleed=%d", + (unsigned long long)TX_FREQ_HZ, (unsigned long long)REF_FREQ_HZ, + tx_param.cp_i, tx_param.bleed_word); + DIAG("LO", "RX target: %llu Hz, ref=%llu Hz, cp_i=%d, bleed=%d", + (unsigned long long)RX_FREQ_HZ, (unsigned long long)REF_FREQ_HZ, + rx_param.cp_i, rx_param.bleed_word); + + // Enable chips + DIAG("LO", "Asserting CE pins (TX + RX)..."); + set_chip_enable(TX_CE_Pin, true); + set_chip_enable(RX_CE_Pin, true); + no_os_udelay(1000); + DIAG("LO", "CE pins asserted, waited 1 ms"); + + // Initialize DELADJ and DELSTR pins + set_deladj_pin(0, false); // TX device + set_deladj_pin(1, false); // RX device + set_delstr_pin(0, false); // TX device + set_delstr_pin(1, false); // RX device + DIAG("LO", "DELADJ/DELSTR pins initialized to LOW"); + + // Initialize TX device first + DIAG("LO", "--- TX ADF4382A init (10.5 GHz) ---"); + uint32_t t_tx = HAL_GetTick(); + printf("Initializing TX ADF4382A (10.5 GHz) on SPI4...\n"); + ret = adf4382_init(&manager->tx_dev, &tx_param); + DIAG("LO", "TX adf4382_init() returned %d (took %lu ms)", + ret, (unsigned long)(HAL_GetTick() - t_tx)); + if (ret) { + DIAG_ERR("LO", "TX init FAILED: %d -- disabling CE pins", ret); + printf("TX ADF4382A initialization failed: %d\n", ret); + set_chip_enable(TX_CE_Pin, false); + set_chip_enable(RX_CE_Pin, false); + return ADF4382A_MANAGER_ERROR_SPI; + } + DIAG("LO", "TX init OK, dev_ptr=%p", (void*)manager->tx_dev); + + // Small delay between initializations + no_os_udelay(5000); + DIAG("LO", "5 ms inter-device delay complete"); + + // Initialize RX device + DIAG("LO", "--- RX ADF4382A init (10.38 GHz) ---"); + uint32_t t_rx = HAL_GetTick(); + printf("Initializing RX ADF4382A (10.38 GHz) on SPI4...\n"); + ret = adf4382_init(&manager->rx_dev, &rx_param); + DIAG("LO", "RX adf4382_init() returned %d (took %lu ms)", + ret, (unsigned long)(HAL_GetTick() - t_rx)); + if (ret) { + DIAG_ERR("LO", "RX init FAILED: %d -- cleaning up TX dev", ret); + printf("RX ADF4382A initialization failed: %d\n", ret); + adf4382_remove(manager->tx_dev); + set_chip_enable(TX_CE_Pin, false); + set_chip_enable(RX_CE_Pin, false); + return ADF4382A_MANAGER_ERROR_SPI; + } + DIAG("LO", "RX init OK, dev_ptr=%p", (void*)manager->rx_dev); + + // Set output power + DIAG("LO", "Setting output power (both ch0=12, ch1=12)..."); + adf4382_set_out_power(manager->tx_dev, 0, 12); + adf4382_set_out_power(manager->tx_dev, 1, 12); + adf4382_set_out_power(manager->rx_dev, 0, 12); + adf4382_set_out_power(manager->rx_dev, 1, 12); + + // Enable outputs + DIAG("LO", "Enabling outputs: TX_ch0=ON TX_ch1=OFF, RX_ch0=ON RX_ch1=OFF"); + adf4382_set_en_chan(manager->tx_dev, 0, true); + adf4382_set_en_chan(manager->tx_dev, 1, false); + adf4382_set_en_chan(manager->rx_dev, 0, true); + adf4382_set_en_chan(manager->rx_dev, 1, false); + + // Setup synchronization based on selected method + // BUG DIAGNOSTIC: At this point manager->initialized is still false. + // ADF4382A_SetupTimedSync() and ADF4382A_SetupEZSync() both check + // manager->initialized and will return -2 (NOT_INIT) if false. + // This means sync setup ALWAYS SILENTLY FAILS during init. + DIAG_WARN("LO", "About to call sync setup -- manager->initialized=%s (BUG: will fail -2 if false)", + manager->initialized ? "true" : "false"); + + if (method == SYNC_METHOD_TIMED) { + ret = ADF4382A_SetupTimedSync(manager); + DIAG("LO", "ADF4382A_SetupTimedSync() returned %d", ret); + if (ret) { + DIAG_ERR("LO", "Timed sync setup FAILED: %d (expected -2 due to init ordering bug)", ret); + printf("Timed sync setup failed: %d\n", ret); + // NOTE: Error is logged but swallowed -- init continues + } + } else { + ret = ADF4382A_SetupEZSync(manager); + DIAG("LO", "ADF4382A_SetupEZSync() returned %d", ret); + if (ret) { + DIAG_ERR("LO", "EZSync setup FAILED: %d (expected -2 due to init ordering bug)", ret); + printf("EZSync setup failed: %d\n", ret); + } + } + + manager->initialized = true; + DIAG("LO", "manager->initialized set to true (sync setup was called BEFORE this)"); + + printf("ADF4382A Manager initialized with %s synchronization on SPI4\n", + (method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC"); + + DIAG_ELAPSED("LO", "Total Manager_Init", t_start); + DIAG("LO", "Init returning OK (but sync setup was %s)", + (ret == 0) ? "successful" : "FAILED -- sync NOT configured"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetupTimedSync(ADF4382A_Manager *manager) +{ + int ret; + + DIAG("LO", "SetupTimedSync called, manager=%p initialized=%s", + (void*)manager, (manager ? (manager->initialized ? "true" : "false") : "N/A")); + + if (!manager || !manager->initialized) { + DIAG_ERR("LO", "SetupTimedSync REJECTED: %s", + !manager ? "NULL manager" : "not initialized (initialized=false)"); + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + printf("Setting up Timed Synchronization (60 MHz SYNCP/SYNCN)...\n"); + + // Setup TX for timed sync + ret = adf4382_set_timed_sync_setup(manager->tx_dev, true); + DIAG("LO", "TX adf4382_set_timed_sync_setup() returned %d", ret); + if (ret) { + DIAG_ERR("LO", "TX timed sync register write FAILED: %d", ret); + printf("TX timed sync setup failed: %d\n", ret); + return ret; + } + + // Setup RX for timed sync + ret = adf4382_set_timed_sync_setup(manager->rx_dev, true); + DIAG("LO", "RX adf4382_set_timed_sync_setup() returned %d", ret); + if (ret) { + DIAG_ERR("LO", "RX timed sync register write FAILED: %d", ret); + printf("RX timed sync setup failed: %d\n", ret); + return ret; + } + + manager->sync_method = SYNC_METHOD_TIMED; + printf("Timed synchronization configured for 60 MHz SYNCP/SYNCN\n"); + DIAG("LO", "Timed sync setup complete for both TX and RX"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetupEZSync(ADF4382A_Manager *manager) +{ + int ret; + + DIAG("LO", "SetupEZSync called, manager=%p initialized=%s", + (void*)manager, (manager ? (manager->initialized ? "true" : "false") : "N/A")); + + if (!manager || !manager->initialized) { + DIAG_ERR("LO", "SetupEZSync REJECTED: %s", + !manager ? "NULL manager" : "not initialized (initialized=false)"); + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + printf("Setting up EZSync (SPI-based synchronization)...\n"); + + // Setup TX for EZSync + ret = adf4382_set_ezsync_setup(manager->tx_dev, true); + DIAG("LO", "TX adf4382_set_ezsync_setup() returned %d", ret); + if (ret) { + printf("TX EZSync setup failed: %d\n", ret); + return ret; + } + + // Setup RX for EZSync + ret = adf4382_set_ezsync_setup(manager->rx_dev, true); + DIAG("LO", "RX adf4382_set_ezsync_setup() returned %d", ret); + if (ret) { + printf("RX EZSync setup failed: %d\n", ret); + return ret; + } + + manager->sync_method = SYNC_METHOD_EZSYNC; + printf("EZSync configured\n"); + DIAG("LO", "EZSync setup complete for both TX and RX"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_TriggerTimedSync(ADF4382A_Manager *manager) +{ + if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_TIMED) { + DIAG_ERR("LO", "TriggerTimedSync REJECTED: init=%s method=%d", + (manager && manager->initialized) ? "true" : "false", + manager ? manager->sync_method : -1); + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // NOTE: This function currently does NOT trigger anything -- it only prints. + // The assumption is that the 60 MHz SYNCP/SYNCN from AD9523 are always present + // and timed sync happens automatically once the timed_sync_setup registers are + // programmed. But if SetupTimedSync failed (init ordering bug), this is a no-op + // on top of a no-op. + DIAG_WARN("LO", "TriggerTimedSync called -- NOTE: function body is advisory only, no hardware trigger issued"); + DIAG_WARN("LO", "If SetupTimedSync failed during init, timed sync registers were NEVER written"); + + printf("Timed sync ready - SYNC pin will trigger synchronization\n"); + printf("Ensure 60 MHz phase-aligned clocks are present on SYNCP/SYNCN pins\n"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_TriggerEZSync(ADF4382A_Manager *manager) +{ + int ret; + + if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_EZSYNC) { + DIAG_ERR("LO", "TriggerEZSync REJECTED"); + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + DIAG("LO", "Triggering EZSync via SPI..."); + + // Trigger software sync on both devices + ret = adf4382_set_sw_sync(manager->tx_dev, true); + if (ret) { + DIAG_ERR("LO", "TX sw_sync SET failed: %d", ret); + printf("TX software sync failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + ret = adf4382_set_sw_sync(manager->rx_dev, true); + if (ret) { + DIAG_ERR("LO", "RX sw_sync SET failed: %d", ret); + printf("RX software sync failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + // Small delay for sync to take effect + no_os_udelay(10); + + // Clear software sync + ret = adf4382_set_sw_sync(manager->tx_dev, false); + if (ret) { + DIAG_ERR("LO", "TX sw_sync CLEAR failed: %d", ret); + printf("TX sync clear failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + ret = adf4382_set_sw_sync(manager->rx_dev, false); + if (ret) { + DIAG_ERR("LO", "RX sw_sync CLEAR failed: %d", ret); + printf("RX sync clear failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + printf("EZSync triggered via SPI\n"); + DIAG("LO", "EZSync trigger complete (set + 10us + clear)"); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_Manager_Deinit(ADF4382A_Manager *manager) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + DIAG("LO", "Manager deinit starting..."); + + // Disable outputs first + if (manager->tx_dev) { + adf4382_set_en_chan(manager->tx_dev, 0, false); + adf4382_set_en_chan(manager->tx_dev, 1, false); + } + + if (manager->rx_dev) { + adf4382_set_en_chan(manager->rx_dev, 0, false); + adf4382_set_en_chan(manager->rx_dev, 1, false); + } + + // Remove devices + if (manager->tx_dev) { + adf4382_remove(manager->tx_dev); + manager->tx_dev = NULL; + } + + if (manager->rx_dev) { + adf4382_remove(manager->rx_dev); + manager->rx_dev = NULL; + } + + // Disable chips and phase control pins + set_chip_enable(TX_CE_Pin, false); + set_chip_enable(RX_CE_Pin, false); + set_deladj_pin(0, false); + set_deladj_pin(1, false); + set_delstr_pin(0, false); + set_delstr_pin(1, false); + + manager->initialized = false; + + printf("ADF4382A Manager deinitialized\n"); + DIAG("LO", "Manager deinit complete"); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_CheckLockStatus(ADF4382A_Manager *manager, bool *tx_locked, bool *rx_locked) +{ + uint8_t tx_status, rx_status; + int ret; + + if (!manager || !manager->initialized || !tx_locked || !rx_locked) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Read lock status from registers + ret = adf4382_spi_read(manager->tx_dev, 0x58, &tx_status); + if (ret) { + DIAG_ERR("LO", "TX lock status SPI read FAILED: %d", ret); + printf("TX lock status read failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + ret = adf4382_spi_read(manager->rx_dev, 0x58, &rx_status); + if (ret) { + DIAG_ERR("LO", "RX lock status SPI read FAILED: %d", ret); + printf("RX lock status read failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + bool tx_reg_locked = (tx_status & ADF4382_LOCKED_MSK) != 0; + bool rx_reg_locked = (rx_status & ADF4382_LOCKED_MSK) != 0; + + // Also check GPIO lock detect pins as backup + bool tx_gpio_locked = HAL_GPIO_ReadPin(TX_LKDET_GPIO_Port, TX_LKDET_Pin) == GPIO_PIN_SET; + bool rx_gpio_locked = HAL_GPIO_ReadPin(RX_LKDET_GPIO_Port, RX_LKDET_Pin) == GPIO_PIN_SET; + + // Diagnostic: show both register and GPIO readings independently + DIAG("LO", "Lock check: TX reg[0x58]=0x%02X(%s) GPIO=%s | RX reg[0x58]=0x%02X(%s) GPIO=%s", + tx_status, tx_reg_locked ? "LK" : "UNL", tx_gpio_locked ? "HI" : "LO", + rx_status, rx_reg_locked ? "LK" : "UNL", rx_gpio_locked ? "HI" : "LO"); + + // Flag disagreement between register and GPIO + if (tx_reg_locked != tx_gpio_locked) { + DIAG_WARN("LO", "TX LOCK DISAGREE: reg=%s GPIO=%s -- possible pin mapping issue", + tx_reg_locked ? "LOCKED" : "UNLOCKED", + tx_gpio_locked ? "HIGH" : "LOW"); + } + if (rx_reg_locked != rx_gpio_locked) { + DIAG_WARN("LO", "RX LOCK DISAGREE: reg=%s GPIO=%s -- possible pin mapping issue", + rx_reg_locked ? "LOCKED" : "UNLOCKED", + rx_gpio_locked ? "HIGH" : "LOW"); + } + + // Use both register and GPIO status + *tx_locked = tx_reg_locked && tx_gpio_locked; + *rx_locked = rx_reg_locked && rx_gpio_locked; + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetOutputPower(ADF4382A_Manager *manager, uint8_t tx_power, uint8_t rx_power) +{ + int ret; + + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Clamp power values (0-15) + tx_power = (tx_power > 15) ? 15 : tx_power; + rx_power = (rx_power > 15) ? 15 : rx_power; + + DIAG("LO", "SetOutputPower: TX=%d RX=%d", tx_power, rx_power); + + // Set TX power for both channels + ret = adf4382_set_out_power(manager->tx_dev, 0, tx_power); + if (ret) return ret; + ret = adf4382_set_out_power(manager->tx_dev, 1, tx_power); + if (ret) return ret; + + // Set RX power for both channels + ret = adf4382_set_out_power(manager->rx_dev, 0, rx_power); + if (ret) return ret; + ret = adf4382_set_out_power(manager->rx_dev, 1, rx_power); + + printf("Output power set: TX=%d, RX=%d\n", tx_power, rx_power); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_EnableOutputs(ADF4382A_Manager *manager, bool tx_enable, bool rx_enable) +{ + int ret; + + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + DIAG("LO", "EnableOutputs: TX=%s RX=%s", + tx_enable ? "ON" : "OFF", rx_enable ? "ON" : "OFF"); + + // Enable/disable TX outputs + ret = adf4382_set_en_chan(manager->tx_dev, 0, tx_enable); + if (ret) return ret; + ret = adf4382_set_en_chan(manager->tx_dev, 1, tx_enable); + if (ret) return ret; + + // Enable/disable RX outputs + ret = adf4382_set_en_chan(manager->rx_dev, 0, rx_enable); + if (ret) return ret; + ret = adf4382_set_en_chan(manager->rx_dev, 1, rx_enable); + + printf("Outputs: TX=%s, RX=%s\n", + tx_enable ? "ENABLED" : "DISABLED", + rx_enable ? "ENABLED" : "DISABLED"); + return ADF4382A_MANAGER_OK; +} + +// New phase delay functions + +int ADF4382A_SetPhaseShift(ADF4382A_Manager *manager, uint16_t tx_phase_ps, uint16_t rx_phase_ps) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Clamp phase shift values + tx_phase_ps = (tx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : tx_phase_ps; + rx_phase_ps = (rx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : rx_phase_ps; + + DIAG("LO", "SetPhaseShift: TX=%d ps, RX=%d ps", tx_phase_ps, rx_phase_ps); + + // Convert phase shift to duty cycle and apply + if (tx_phase_ps != manager->tx_phase_shift_ps) { + uint16_t duty_cycle = phase_ps_to_duty_cycle(tx_phase_ps); + DIAG_WARN("LO", "TX phase: %d ps -> duty_cycle=%d/%d (SIMPLIFIED -- not real PWM)", + tx_phase_ps, duty_cycle, DELADJ_MAX_DUTY_CYCLE); + ADF4382A_SetFinePhaseShift(manager, 0, duty_cycle); // 0 = TX device + manager->tx_phase_shift_ps = tx_phase_ps; + } + + if (rx_phase_ps != manager->rx_phase_shift_ps) { + uint16_t duty_cycle = phase_ps_to_duty_cycle(rx_phase_ps); + DIAG_WARN("LO", "RX phase: %d ps -> duty_cycle=%d/%d (SIMPLIFIED -- not real PWM)", + rx_phase_ps, duty_cycle, DELADJ_MAX_DUTY_CYCLE); + ADF4382A_SetFinePhaseShift(manager, 1, duty_cycle); // 1 = RX device + manager->rx_phase_shift_ps = rx_phase_ps; + } + + printf("Phase shift set: TX=%d ps, RX=%d ps\n", tx_phase_ps, rx_phase_ps); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_GetPhaseShift(ADF4382A_Manager *manager, uint16_t *tx_phase_ps, uint16_t *rx_phase_ps) +{ + if (!manager || !manager->initialized || !tx_phase_ps || !rx_phase_ps) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + *tx_phase_ps = manager->tx_phase_shift_ps; + *rx_phase_ps = manager->rx_phase_shift_ps; + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetFinePhaseShift(ADF4382A_Manager *manager, uint8_t device, uint16_t duty_cycle) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Clamp duty cycle + duty_cycle = (duty_cycle > DELADJ_MAX_DUTY_CYCLE) ? DELADJ_MAX_DUTY_CYCLE : duty_cycle; + + // For simplicity, we'll use a basic implementation + // In a real system, you would generate a PWM signal on DELADJ pin + // Here we just set the pin state based on a simplified approach + + if (duty_cycle == 0) { + set_deladj_pin(device, false); + DIAG("LO", "Dev%d DELADJ=LOW (duty=0)", device); + } else if (duty_cycle >= DELADJ_MAX_DUTY_CYCLE) { + set_deladj_pin(device, true); + DIAG("LO", "Dev%d DELADJ=HIGH (duty=max)", device); + } else { + // For intermediate values, you would need PWM generation + // This is a simplified implementation + set_deladj_pin(device, true); + DIAG_WARN("LO", "Dev%d DELADJ=HIGH for duty=%d/%d -- PLACEHOLDER: intermediate values need real PWM", + device, duty_cycle, DELADJ_MAX_DUTY_CYCLE); + } + + printf("Device %d DELADJ duty cycle set to %d/%d\n", + device, duty_cycle, DELADJ_MAX_DUTY_CYCLE); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_StrobePhaseShift(ADF4382A_Manager *manager, uint8_t device) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + DIAG("LO", "Dev%d DELSTR strobe (%d us pulse)", device, DELADJ_PULSE_WIDTH_US); + + // Generate a pulse on DELSTR pin to latch the current DELADJ value + set_delstr_pin(device, true); + no_os_udelay(DELADJ_PULSE_WIDTH_US); + set_delstr_pin(device, false); + + printf("Device %d phase shift strobed\n", device); + + return ADF4382A_MANAGER_OK; +} + +// Static helper functions + +static void set_chip_enable(uint8_t ce_pin, bool state) +{ + GPIO_TypeDef* port = (ce_pin == TX_CE_Pin) ? TX_CE_GPIO_Port : RX_CE_GPIO_Port; + HAL_GPIO_WritePin(port, ce_pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); +} + +static void set_deladj_pin(uint8_t device, bool state) +{ + if (device == 0) { // TX device + HAL_GPIO_WritePin(TX_DELADJ_GPIO_Port, TX_DELADJ_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } else { // RX device + HAL_GPIO_WritePin(RX_DELADJ_GPIO_Port, RX_DELADJ_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } +} + +static void set_delstr_pin(uint8_t device, bool state) +{ + if (device == 0) { // TX device + HAL_GPIO_WritePin(TX_DELSTR_GPIO_Port, TX_DELSTR_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } else { // RX device + HAL_GPIO_WritePin(RX_DELSTR_GPIO_Port, RX_DELSTR_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } +} + +static uint16_t phase_ps_to_duty_cycle(uint16_t phase_ps) +{ + // Convert phase shift in picoseconds to DELADJ duty cycle + // This is a linear mapping - adjust based on your specific requirements + uint32_t duty = (uint32_t)phase_ps * DELADJ_MAX_DUTY_CYCLE / PHASE_SHIFT_MAX_PS; + return (uint16_t)duty; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/diag_log.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/diag_log.h new file mode 100644 index 0000000..62f737b --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/diag_log.h @@ -0,0 +1,126 @@ +/***************************************************************************//** + * @file diag_log.h + * @brief Bring-up diagnostic logging macros for AERIS-10 radar system. + * + * Provides timestamped, subsystem-tagged diagnostic output over USART3. + * All output is observation-only instrumentation -- no behavioral changes. + * + * Usage: + * #include "diag_log.h" + * DIAG("LO", "TX init returned %d", ret); + * DIAG_WARN("CLK", "PLL2 not locked after %lu ms", timeout); + * DIAG_ERR("PA", "IDQ out of range: %d mA", idq_ma); + * DIAG_REG("LO", "TX reg 0x58", reg_val); + * DIAG_GPIO("LO", "TX_LKDET", port, pin); + * + * Compile-time control: + * #define DIAG_DISABLE -- suppress all DIAG output + * #define DIAG_VERBOSE -- include file:line in every message + * + * @author AERIS-10 Bring-up Instrumentation + * @date 2026 + *******************************************************************************/ + +#ifndef DIAG_LOG_H +#define DIAG_LOG_H + +#include +#include +#include "stm32f7xx_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Core DIAG macro -- timestamped, subsystem-tagged printf. + * Uses HAL_GetTick() for millisecond timestamps. + * Output format: "[ 12345 ms] LO: TX init returned -2\n" + */ +#ifndef DIAG_DISABLE + +#ifdef DIAG_VERBOSE +#define DIAG(subsys, fmt, ...) \ + printf("[%7lu ms] %s: " fmt " (%s:%d)\n", \ + (unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__, __FILE__, __LINE__) +#else +#define DIAG(subsys, fmt, ...) \ + printf("[%7lu ms] %s: " fmt "\n", \ + (unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__) +#endif + +/* Severity-tagged variants */ +#define DIAG_WARN(subsys, fmt, ...) \ + printf("[%7lu ms] %s WARN: " fmt "\n", \ + (unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__) + +#define DIAG_ERR(subsys, fmt, ...) \ + printf("[%7lu ms] %s **ERR**: " fmt "\n", \ + (unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__) + +/* Register read diagnostic -- prints hex value */ +#define DIAG_REG(subsys, name, val) \ + printf("[%7lu ms] %s: %s = 0x%02X\n", \ + (unsigned long)HAL_GetTick(), subsys, name, (unsigned int)(val)) + +/* Register read diagnostic -- 32-bit variant */ +#define DIAG_REG32(subsys, name, val) \ + printf("[%7lu ms] %s: %s = 0x%08lX\n", \ + (unsigned long)HAL_GetTick(), subsys, name, (unsigned long)(val)) + +/* GPIO pin state diagnostic */ +#define DIAG_GPIO(subsys, name, port, pin) \ + printf("[%7lu ms] %s: GPIO %s = %s\n", \ + (unsigned long)HAL_GetTick(), subsys, name, \ + (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET) ? "HIGH" : "LOW") + +/* Boolean condition diagnostic */ +#define DIAG_BOOL(subsys, name, val) \ + printf("[%7lu ms] %s: %s = %s\n", \ + (unsigned long)HAL_GetTick(), subsys, name, (val) ? "YES" : "NO") + +/* Section separator for init sequence readability */ +#define DIAG_SECTION(title) \ + printf("[%7lu ms] ======== %s ========\n", \ + (unsigned long)HAL_GetTick(), title) + +/* Elapsed time helper -- use with a captured start tick */ +#define DIAG_ELAPSED(subsys, label, start_tick) \ + printf("[%7lu ms] %s: %s took %lu ms\n", \ + (unsigned long)HAL_GetTick(), subsys, label, \ + (unsigned long)(HAL_GetTick() - (start_tick))) + +#else /* DIAG_DISABLE */ + +#define DIAG(subsys, fmt, ...) ((void)0) +#define DIAG_WARN(subsys, fmt, ...) ((void)0) +#define DIAG_ERR(subsys, fmt, ...) ((void)0) +#define DIAG_REG(subsys, name, val) ((void)0) +#define DIAG_REG32(subsys, name, val) ((void)0) +#define DIAG_GPIO(subsys, name, port, pin) ((void)0) +#define DIAG_BOOL(subsys, name, val) ((void)0) +#define DIAG_SECTION(title) ((void)0) +#define DIAG_ELAPSED(subsys, label, start) ((void)0) + +#endif /* DIAG_DISABLE */ + +/* + * Subsystem tag constants -- use these for consistency: + * "CLK" -- AD9523 clock generator + * "LO" -- ADF4382A LO synthesizers (manager level) + * "LO_DRV" -- ADF4382 low-level driver + * "BF" -- ADAR1000 beamformer + * "PA" -- Power amplifier bias/monitoring + * "FPGA" -- FPGA communication and handshake + * "USB" -- FT601 USB data path + * "PWR" -- Power sequencing and rail monitoring + * "IMU" -- IMU/GPS/barometer sensors + * "MOT" -- Stepper motor/scan mechanics + * "SYS" -- System-level init, health, safe-mode + */ + +#ifdef __cplusplus +} +#endif + +#endif /* DIAG_LOG_H */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp index ef1be6e..06c6e4d 100644 --- a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp @@ -59,6 +59,7 @@ extern "C" { #include "adf4382.h" #include "no_os_delay.h" #include "no_os_error.h" +#include "diag_log.h" } #include #include "DAC5578.h" @@ -1041,34 +1042,65 @@ static int configure_ad9523(void) init_param.pdata = &pdata; + DIAG_SECTION("AD9523 CONFIGURE"); + DIAG("CLK", "VCXO=%lu Hz, PLL2 N=%d (4*%d+%d)=%d, R2=%d", + (unsigned long)pdata.vcxo_freq, + 4 * pdata.pll2_ndiv_b_cnt + pdata.pll2_ndiv_a_cnt, + pdata.pll2_ndiv_b_cnt, pdata.pll2_ndiv_a_cnt, + 4 * pdata.pll2_ndiv_b_cnt + pdata.pll2_ndiv_a_cnt, + pdata.pll2_r2_div); + DIAG("CLK", "Enabled channels: 0,1(/12=300M) 4,5(/9=400M) 6(/36=100M) 7(/180=20M) 8,9(/60=60M) 10,11(/30=120M)"); + // init ad9523 defaults (fills any missing pdata defaults) + DIAG("CLK", "Calling ad9523_init() -- fills pdata defaults"); ad9523_init(&init_param); + + /* [BUG ANNOTATION] First ad9523_setup() call -- chip is still in reset + * (AD9523_RESET_RELEASE() hasn't been called yet). + * SPI writes here likely fail silently or go to a reset device. */ + DIAG_WARN("CLK", "[BUG] Calling ad9523_setup() #1 BEFORE reset release -- chip in reset, writes likely lost"); + uint32_t setup1_start = HAL_GetTick(); ret = ad9523_setup(&dev, &init_param); + DIAG("CLK", "ad9523_setup() #1 returned %ld (took %lu ms)", + (long)ret, (unsigned long)(HAL_GetTick() - setup1_start)); // Bring AD9523 out of reset + DIAG("CLK", "Releasing AD9523 reset (AD9523_RESET_RELEASE)"); AD9523_RESET_RELEASE(); HAL_Delay(5); + DIAG("CLK", "AD9523 reset released, waited 5 ms"); // Select REFB (100MHz) using REF_SEL pin (true selects REFB here) + DIAG("CLK", "Selecting REFB (100 MHz) via REF_SEL pin"); AD9523_REF_SEL(true); // Call setup which uses no_os_spi to write registers, io_update, calibrate, sync + DIAG("CLK", "Calling ad9523_setup() #2 -- post-reset, actual configuration"); + uint32_t setup2_start = HAL_GetTick(); ret = ad9523_setup(&dev, &init_param); + DIAG("CLK", "ad9523_setup() #2 returned %ld (took %lu ms)", + (long)ret, (unsigned long)(HAL_GetTick() - setup2_start)); if (ret != 0) { // handle error: lock missing or SPI error + DIAG_ERR("CLK", "ad9523_setup() #2 FAILED (ret=%ld) -- lock missing or SPI error", (long)ret); return -1; } // Final check + DIAG("CLK", "Checking AD9523 status (PLL lock, etc.)"); ret = ad9523_status(dev); + DIAG("CLK", "ad9523_status() returned %ld", (long)ret); if (ret != 0) { // log/handle + DIAG_ERR("CLK", "AD9523 status check FAILED (ret=%ld)", (long)ret); return -1; } // optionally manual sync + DIAG("CLK", "Triggering manual ad9523_sync()"); ad9523_sync(dev); + DIAG("CLK", "AD9523 configuration complete -- all outputs should be active"); // keep device pointer globally if needed (dev) return 0; @@ -1232,17 +1264,32 @@ int main(void) /* --- Enable DWT cycle counter for accurate microsecond delays --- */ DWT_Init(); + + DIAG_SECTION("SYSTEM INIT"); + DIAG("SYS", "DWT cycle counter initialized, TIM1 started"); + DIAG("SYS", "HAL tick at init start: %lu ms", (unsigned long)HAL_GetTick()); + //Wait for OCXO 3mn + DIAG("CLK", "OCXO warmup starting -- waiting 180 s (3 min)"); + uint32_t ocxo_start = HAL_GetTick(); HAL_Delay(180000); + DIAG_ELAPSED("CLK", "OCXO warmup", ocxo_start); + + DIAG_SECTION("AD9523 POWER SEQUENCING"); + DIAG("PWR", "Asserting AD9523 reset (pin LOW)"); HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_RESET); //Power sequencing AD9523 + DIAG("PWR", "Enabling 1.8V clock rail"); HAL_GPIO_WritePin(EN_P_1V8_CLOCK_GPIO_Port,EN_P_1V8_CLOCK_Pin,GPIO_PIN_SET); HAL_Delay(100); + DIAG("PWR", "Enabling 3.3V clock rail"); HAL_GPIO_WritePin(EN_P_3V3_CLOCK_GPIO_Port,EN_P_3V3_CLOCK_Pin,GPIO_PIN_SET); HAL_Delay(100); + DIAG("PWR", "Releasing AD9523 reset (pin HIGH)"); HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_SET); HAL_Delay(100); + DIAG("PWR", "AD9523 power sequencing complete -- all rails up, reset released"); //Set planned Clocks on AD9523 /* @@ -1261,24 +1308,38 @@ int main(void) // Ensure stm32_spi.c and stm32_delay.c are compiled and linked + DIAG("CLK", "Calling configure_ad9523()..."); + uint32_t ad9523_cfg_start = HAL_GetTick(); if (configure_ad9523() != 0) { // configuration error - handle as needed + DIAG_ERR("CLK", "configure_ad9523() FAILED -- entering infinite halt loop"); while (1) { HAL_Delay(1000); } } + DIAG_ELAPSED("CLK", "configure_ad9523()", ad9523_cfg_start); + DIAG("CLK", "AD9523 configured successfully"); //Power sequencing FPGA + DIAG_SECTION("FPGA POWER SEQUENCING"); + DIAG("PWR", "Enabling 1.0V FPGA rail"); HAL_GPIO_WritePin(EN_P_1V0_FPGA_GPIO_Port,EN_P_1V0_FPGA_Pin,GPIO_PIN_SET); HAL_Delay(100); + DIAG("PWR", "Enabling 1.8V FPGA rail"); HAL_GPIO_WritePin(EN_P_1V8_FPGA_GPIO_Port,EN_P_1V8_FPGA_Pin,GPIO_PIN_SET); HAL_Delay(100); + DIAG("PWR", "Enabling 3.3V FPGA rail"); HAL_GPIO_WritePin(EN_P_3V3_FPGA_GPIO_Port,EN_P_3V3_FPGA_Pin,GPIO_PIN_SET); HAL_Delay(100); + DIAG("PWR", "FPGA power sequencing complete -- 1.0V -> 1.8V -> 3.3V"); -// Initialize module IMU - if (!GY85_Init()) { - Error_Handler(); - } +// Initialize module IMU + DIAG_SECTION("IMU INIT (GY-85)"); + DIAG("IMU", "Initializing GY-85 IMU..."); + if (!GY85_Init()) { + DIAG_ERR("IMU", "GY85_Init() FAILED -- calling Error_Handler()"); + Error_Handler(); + } + DIAG("IMU", "GY-85 initialized OK, running 10 calibration samples"); for(int i=0; i<10;i++){ if (!GY85_Update(&imu)) { Error_Handler(); @@ -1391,40 +1452,63 @@ int main(void) /////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////BAROMETER BMP180//////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// + DIAG_SECTION("BAROMETER INIT (BMP180)"); + DIAG("IMU", "Reading 5 barometer samples for altitude baseline"); for(int i = 0; i<5 ; i++){ float BMP_Perssure = myBMP.getPressure(); RADAR_Altitude = 44330*(1-(pow((BMP_Perssure/101325),(1/5.255)))); HAL_Delay(100); } + DIAG("IMU", "Barometer init complete, RADAR_Altitude baseline set"); /////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////ADF4382///////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// + DIAG_SECTION("ADF4382A LO INIT"); printf("Starting ADF4382A Radar LO System...\n"); printf("Using SPI4 with TIMED SYNCHRONIZATION (60 MHz clocks)\n"); // Initialize LO manager with TIMED synchronization + DIAG("LO", "Calling ADF4382A_Manager_Init(sync=SYNC_METHOD_TIMED)"); + uint32_t lo_init_start = HAL_GetTick(); int ret = ADF4382A_Manager_Init(&lo_manager, SYNC_METHOD_TIMED); + DIAG("LO", "ADF4382A_Manager_Init returned %d (took %lu ms)", + ret, (unsigned long)(HAL_GetTick() - lo_init_start)); + + /* [BUG ANNOTATION] The following SetPhaseShift/StrobePhaseShift calls happen + * BEFORE the init return code is checked (line below with 'if ret !='). + * If init failed, these operate on an uninitialized manager. */ + DIAG_WARN("LO", "[BUG] SetPhaseShift/Strobe called BEFORE checking init return code (ret=%d)", ret); // Set phase shift (e.g., 500 ps for TX, 500 ps for RX) - ADF4382A_SetPhaseShift(&lo_manager, 500, 500); + int ps_ret = ADF4382A_SetPhaseShift(&lo_manager, 500, 500); + DIAG("LO", "ADF4382A_SetPhaseShift(500, 500) returned %d", ps_ret); // Strobe to apply phase shifts - ADF4382A_StrobePhaseShift(&lo_manager, 0); // TX device - ADF4382A_StrobePhaseShift(&lo_manager, 1); // RX device + int strobe_tx_ret = ADF4382A_StrobePhaseShift(&lo_manager, 0); // TX device + int strobe_rx_ret = ADF4382A_StrobePhaseShift(&lo_manager, 1); // RX device + DIAG("LO", "StrobePhaseShift TX returned %d, RX returned %d", strobe_tx_ret, strobe_rx_ret); + if (ret != ADF4382A_MANAGER_OK) { printf("LO Manager initialization failed: %d\n", ret); + DIAG_ERR("LO", "Manager init FAILED (ret=%d) -- calling Error_Handler()", ret); Error_Handler(); } // Check initial lock status bool tx_locked, rx_locked; + DIAG("LO", "Checking initial lock status..."); ret = ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked); if (ret == ADF4382A_MANAGER_OK) { printf("Initial Lock Status - TX: %s, RX: %s\n", tx_locked ? "LOCKED" : "UNLOCKED", rx_locked ? "LOCKED" : "UNLOCKED"); + DIAG("LO", "Initial lock: TX=%s RX=%s", tx_locked ? "LOCKED" : "UNLOCKED", rx_locked ? "LOCKED" : "UNLOCKED"); + } else { + DIAG_ERR("LO", "CheckLockStatus returned %d", ret); } // Wait for both LOs to lock + DIAG("LO", "Entering lock-wait loop (max 10 s = 100 x 100 ms)"); + uint32_t lock_wait_start = HAL_GetTick(); uint32_t lock_timeout = 0; while (!(tx_locked && rx_locked) && lock_timeout < 100) { HAL_Delay(100); @@ -1435,44 +1519,65 @@ int main(void) printf("Waiting for LO lock... TX: %s, RX: %s\n", tx_locked ? "LOCKED" : "UNLOCKED", rx_locked ? "LOCKED" : "UNLOCKED"); + DIAG("LO", "Lock poll #%lu: TX=%s RX=%s", + (unsigned long)lock_timeout, + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); } } + DIAG_ELAPSED("LO", "Lock wait loop", lock_wait_start); if (tx_locked && rx_locked) { printf("Both LOs locked successfully!\n"); printf("Synchronization ready - 60 MHz clocks on SYNCP/SYNCN pins\n"); + DIAG("LO", "Both LOs LOCKED after %lu iterations", (unsigned long)lock_timeout); // - 60 MHz phase-aligned clocks on SYNCP/SYNCN pins // - SYNC pin connected for triggering // When ready to synchronize: + /* [BUG ANNOTATION] TriggerTimedSync is a no-op -- it only prints + * messages but does not actually toggle any sync pin or register. */ + DIAG_WARN("LO", "[BUG] Calling TriggerTimedSync -- known NO-OP, does nothing hardware-related"); ADF4382A_TriggerTimedSync(&lo_manager); // At this point, the SYNC pin can be toggled to trigger synchronization } else { printf("LO lock timeout! TX: %s, RX: %s\n", tx_locked ? "LOCKED" : "UNLOCKED", rx_locked ? "LOCKED" : "UNLOCKED"); + DIAG_ERR("LO", "Lock TIMEOUT after %lu iterations! TX=%s RX=%s", + (unsigned long)lock_timeout, + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); } - // check if there is a lock + + // check if there is a lock via direct GPIO (independent of register read above) + DIAG("LO", "Direct GPIO lock detect pins:"); + DIAG_GPIO("LO", "ADF4382_TX_LKDET", ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin); + DIAG_GPIO("LO", "ADF4382_RX_LKDET", ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin); if(HAL_GPIO_ReadPin (ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin)) { // Set The LED_1 ON! HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_SET); + DIAG("LO", "TX lock detected via GPIO -- LED_1 ON"); } else { // Else .. Turn LED_1 OFF! HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_RESET); + DIAG_WARN("LO", "TX NOT locked via GPIO -- LED_1 OFF"); } if(HAL_GPIO_ReadPin (ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin)) { // Set The LED_2 ON! HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_SET); + DIAG("LO", "RX lock detected via GPIO -- LED_2 ON"); } else { // Else .. Turn LED_2 OFF! HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_RESET); + DIAG_WARN("LO", "RX NOT locked via GPIO -- LED_2 OFF"); } @@ -1481,28 +1586,36 @@ int main(void) ////////////////////////////////////////////////////////////////////////////////////// //Power sequencing ADAR1000 + DIAG_SECTION("ADAR1000 POWER SEQUENCING"); //Tell FPGA to turn off TX RF signal by disabling Mixers + DIAG("BF", "Disabling TX mixers (GPIOD pin 11 LOW)"); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET); + DIAG("PWR", "Enabling 3.3V ADAR12 + ADAR34 rails"); HAL_GPIO_WritePin(EN_P_3V3_ADAR12_GPIO_Port,EN_P_3V3_ADAR12_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_3V3_ADAR34_GPIO_Port,EN_P_3V3_ADAR34_Pin,GPIO_PIN_SET); HAL_Delay(500); + DIAG("PWR", "Enabling 5.0V ADAR rail"); HAL_GPIO_WritePin(EN_P_5V0_ADAR_GPIO_Port,EN_P_5V0_ADAR_Pin,GPIO_PIN_SET); HAL_Delay(500); + DIAG("PWR", "ADAR1000 power sequencing complete"); // System startup message uint8_t startup_msg[] = "Starting Phased Array RADAR System...\r\n"; HAL_UART_Transmit(&huart3, startup_msg, sizeof(startup_msg)-1, 1000); + DIAG("BF", "Calling systemPowerUpSequence()"); // Power up sequence systemPowerUpSequence(); + DIAG("BF", "Calling initializeBeamMatrices()"); // Initialize beam matrices initializeBeamMatrices(); // Print system status printSystemStatus(); + DIAG("SYS", "System init complete -- entering main loop"); ////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////GPS///////////////////////////////////////// @@ -1663,13 +1776,16 @@ int main(void) } //RESET FPGA + DIAG("FPGA", "Resetting FPGA (GPIOD pin 12: LOW -> 10ms -> HIGH)"); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); + DIAG("FPGA", "FPGA reset complete"); //Tell FPGA to apply TX RF by enabling Mixers + DIAG("FPGA", "Enabling TX mixers (GPIOD pin 11 HIGH)"); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_SET); /* T°C sensor TMP37 ADC3: Address 0x49, Single-Ended mode, Internal Ref ON + ADC ON */ @@ -1717,11 +1833,15 @@ int main(void) if (!checkSystemHealthStatus()) { // System is in bad state, enter safe mode //Tell FPGA to turn off TX RF signal by disabling Mixers + DIAG_ERR("SYS", "checkSystemHealthStatus() FAILED -- entering SAFE MODE"); + DIAG("SYS", "Disabling TX mixers (GPIOD pin 11 LOW)"); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET); + DIAG("SYS", "Calling systemPowerDownSequence()"); systemPowerDownSequence(); char emergency_msg[] = "SYSTEM IN SAFE MODE - Manual intervention required\r\n"; HAL_UART_Transmit(&huart3, (uint8_t*)emergency_msg, strlen(emergency_msg), 1000); + DIAG_ERR("SYS", "SAFE MODE ACTIVE -- blinking all LEDs, waiting for system_emergency_state clear"); // Blink all LEDs to indicate safe mode while (system_emergency_state) { @@ -1730,6 +1850,7 @@ int main(void) HAL_GPIO_TogglePin(LED_3_GPIO_Port, LED_3_Pin); HAL_GPIO_TogglePin(LED_4_GPIO_Port, LED_4_Pin); } + DIAG("SYS", "Exited safe mode blink loop -- system_emergency_state cleared"); } ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////// Monitor ADF4382A lock status periodically////////////////// @@ -1744,6 +1865,13 @@ int main(void) printf("LO Lock Lost! TX: %s, RX: %s\n", tx_locked ? "LOCKED" : "UNLOCKED", rx_locked ? "LOCKED" : "UNLOCKED"); + DIAG_ERR("LO", "Lock LOST in main loop! TX=%s RX=%s", + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); + DIAG_GPIO("LO", "TX_LKDET (direct)", ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin); + DIAG_GPIO("LO", "RX_LKDET (direct)", ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin); + } else { + DIAG("LO", "Lock poll OK: TX=LOCKED RX=LOCKED"); } last_check = HAL_GetTick(); @@ -1765,18 +1893,27 @@ int main(void) Temperature_7 = ADS7830_Measure_SingleEnded(&hadc3, 6)*0.64705f; Temperature_8 = ADS7830_Measure_SingleEnded(&hadc3, 7)*0.64705f; + DIAG("PA", "Temps: T1=%.1f T2=%.1f T3=%.1f T4=%.1f T5=%.1f T6=%.1f T7=%.1f T8=%.1f", + (double)Temperature_1, (double)Temperature_2, (double)Temperature_3, (double)Temperature_4, + (double)Temperature_5, (double)Temperature_6, (double)Temperature_7, (double)Temperature_8); + //(20 mV/°C on TMP37) QPA2962 RF amplifier Operating Temp. Range, TBASE min−40 normal+25 max+85 °C int Max_Temp = 25; if((Temperature_1>Max_Temp)||(Temperature_2>Max_Temp)||(Temperature_3>Max_Temp)||(Temperature_4>Max_Temp) ||(Temperature_5>Max_Temp)||(Temperature_6>Max_Temp)||(Temperature_7>Max_Temp)||(Temperature_8>Max_Temp)) { HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_SET); + DIAG_WARN("PA", "Over-temp detected (>%d C) -- cooling ENABLED", Max_Temp); } else{ HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_RESET); } + /* [BUG ANNOTATION] Line below writes to 'last_check' instead of 'last_check1'. + * This causes the temperature timer to share state with the lock-check timer above. + * Temperature reads may run at incorrect intervals. */ + DIAG_WARN("PA", "[BUG] Timer uses 'last_check' instead of 'last_check1' -- temp interval corrupted"); last_check = HAL_GetTick(); } //////////////////////////////////////////////////////////////////////////////////////