diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 161e74ec..05a63506 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -130,6 +130,40 @@ void rffc5071_setup(rffc5071_driver_t* const drv) rffc5071_regs_commit(drv); } +void rffc5071_lock_test(rffc5071_driver_t* const drv) +{ + bool lock = false; + + for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { + // Tune to 100MHz. + rffc5071_set_frequency(drv, 100000000); + + // Wait 1ms. + delay_us_at_mhz(1000, 204); + + // Check for lock. + lock = rffc5071_check_lock(drv); + + selftest.mixer_locks[i] = lock; + } + + // The last attempt must be successful. + if (!lock) { + selftest.report.pass = false; + } +} + +bool rffc5071_check_lock(rffc5071_driver_t* const drv) +{ +#ifdef PRALINE + return gpio_read(drv->gpio_ld); +#else + set_RFFC5071_READSEL(drv, 0b0001); + rffc5071_regs_commit(drv); + return !!(rffc5071_reg_read(drv, RFFC5071_READBACK_REG) & 0x8000); +#endif +} + static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { (void) drv; diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 1586e285..164f6324 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -44,6 +44,7 @@ typedef struct { /* Initialize chip. Call _setup() externally, as it calls _init(). */ extern void rffc5071_init(rffc5071_driver_t* const drv); extern void rffc5071_setup(rffc5071_driver_t* const drv); +extern void rffc5071_lock_test(rffc5071_driver_t* const drv); /* Read a register via SPI. Save a copy to memory and return * value. Discard any uncommited changes and mark CLEAN. */ @@ -73,5 +74,6 @@ extern void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t); #ifdef PRALINE extern bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state); #endif +extern bool rffc5071_check_lock(rffc5071_driver_t* const drv); #endif // __RFFC5071_H diff --git a/firmware/common/selftest.h b/firmware/common/selftest.h index 0e57d626..86ee2213 100644 --- a/firmware/common/selftest.h +++ b/firmware/common/selftest.h @@ -25,6 +25,8 @@ #include #include +#define NUM_LOCK_ATTEMPTS 3 + enum { FAILED = 0, PASSED = 1, @@ -36,6 +38,9 @@ typedef uint8_t test_result_t; typedef struct { uint16_t mixer_id; +#ifndef RAD1O + bool mixer_locks[NUM_LOCK_ATTEMPTS]; +#endif #ifdef PRALINE uint16_t max2831_mux_rssi_1; uint16_t max2831_mux_temp; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index a3f38149..0b5d303a 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -338,6 +338,10 @@ int main(void) rf_path_init(&rf_path); +#ifndef RAD1O + rffc5071_lock_test(&mixer); +#endif + #ifdef PRALINE fpga_if_xcvr_selftest(); #endif diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index 1bafbe00..16a1cff4 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -83,6 +83,17 @@ void generate_selftest_report(void) append(&s, &c, itoa(selftest.mixer_id >> 3, 10)); append(&s, &c, ", Rev: "); append(&s, &c, itoa(selftest.mixer_id & 0x7, 10)); + append(&s, &c, ", Locks: "); + bool lock; + for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { + lock = selftest.mixer_locks[i]; + append(&s, &c, itoa(lock, 2)); + } + if (lock) { + append(&s, &c, " (PASS)"); + } else { + append(&s, &c, " (FAIL)"); + } append(&s, &c, "\n"); #endif append(&s, &c, "Clock: Si5351");