mirror of
https://github.com/greatscottgadgets/hackrf.git
synced 2026-03-02 21:45:37 +01:00
New method to test RTC oscillator.
This commit is contained in:
@@ -150,6 +150,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
|
||||
#endif
|
||||
usb_vendor_request_read_selftest,
|
||||
usb_vendor_request_adc_read,
|
||||
usb_vendor_request_test_rtc_osc,
|
||||
};
|
||||
|
||||
static const uint32_t vendor_request_handler_count =
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <usb_queue.h>
|
||||
#include <libopencm3/lpc43xx/creg.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
#include "usb_api_selftest.h"
|
||||
#include "selftest.h"
|
||||
#include "platform_detect.h"
|
||||
@@ -122,3 +124,61 @@ usb_request_status_t usb_vendor_request_read_selftest(
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_test_rtc_osc(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint16_t count;
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
enum {
|
||||
START_32KHZ_OSCILLATOR,
|
||||
START_FREQ_MONITOR,
|
||||
READ_FREQ_MONITOR,
|
||||
STOP_32KHZ_OSCILLATOR,
|
||||
} step = endpoint->setup.index;
|
||||
|
||||
switch (step) {
|
||||
case START_32KHZ_OSCILLATOR:
|
||||
// Enable 32kHz oscillator
|
||||
CREG_CREG0 &= ~(CREG_CREG0_PD32KHZ | CREG_CREG0_RESET32KHZ);
|
||||
CREG_CREG0 |= CREG_CREG0_EN32KHZ;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case START_FREQ_MONITOR:
|
||||
// Start counting cycles with frequency monitor
|
||||
CGU_FREQ_MON = CGU_FREQ_MON_RCNT(511) |
|
||||
CGU_FREQ_MON_CLK_SEL(CGU_SRC_32K);
|
||||
CGU_FREQ_MON |= CGU_FREQ_MON_MEAS_MASK;
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case READ_FREQ_MONITOR:
|
||||
if (~(CGU_FREQ_MON & CGU_FREQ_MON_MEAS_MASK)) {
|
||||
// Measurement completed.
|
||||
count = (CGU_FREQ_MON & CGU_FREQ_MON_FCNT_MASK) >>
|
||||
CGU_FREQ_MON_FCNT_SHIFT;
|
||||
} else {
|
||||
// Measurement failed to complete.
|
||||
count = 0;
|
||||
}
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
&count,
|
||||
sizeof(count),
|
||||
NULL,
|
||||
NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case STOP_32KHZ_OSCILLATOR:
|
||||
// Disable 32kHz oscillator
|
||||
CREG_CREG0 &= ~CREG_CREG0_EN32KHZ;
|
||||
CREG_CREG0 |= (CREG_CREG0_PD32KHZ | CREG_CREG0_RESET32KHZ);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,8 @@ usb_request_status_t usb_vendor_request_read_selftest(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
|
||||
usb_request_status_t usb_vendor_request_test_rtc_osc(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
|
||||
#endif // __USB_API_SELFTEST_H
|
||||
|
||||
@@ -609,6 +609,7 @@ static struct option long_options[] = {
|
||||
{"ui", required_argument, 0, 'u'},
|
||||
{"leds", required_argument, 0, 'l'},
|
||||
{"selftest", no_argument, 0, 't'},
|
||||
{"rtc-osc", no_argument, 0, 'o'},
|
||||
{"adc", required_argument, 0, 'a'},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
@@ -647,6 +648,7 @@ int main(int argc, char** argv)
|
||||
bool set_narrowband = false;
|
||||
bool set_fpga_bitstream = false;
|
||||
bool read_selftest = false;
|
||||
bool test_rtc_osc = false;
|
||||
bool read_adc = false;
|
||||
|
||||
int result = hackrf_init();
|
||||
@@ -660,7 +662,7 @@ int main(int argc, char** argv)
|
||||
while ((opt = getopt_long(
|
||||
argc,
|
||||
argv,
|
||||
"n:rw:d:cmsfg1:2:C:N:P:ST:R:h?u:l:ta:",
|
||||
"n:rw:d:cmsfg1:2:C:N:P:ST:R:h?u:l:ta:o",
|
||||
long_options,
|
||||
&option_index)) != EOF) {
|
||||
switch (opt) {
|
||||
@@ -767,6 +769,9 @@ int main(int argc, char** argv)
|
||||
case 't':
|
||||
read_selftest = true;
|
||||
break;
|
||||
case 'o':
|
||||
test_rtc_osc = true;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
read_adc = true;
|
||||
@@ -812,7 +817,8 @@ int main(int argc, char** argv)
|
||||
|
||||
if (!(write || read || dump_config || dump_state || set_tx_limit ||
|
||||
set_rx_limit || set_ui || set_leds || set_p1 || set_p2 || set_clkin ||
|
||||
set_narrowband || set_fpga_bitstream || read_selftest || read_adc)) {
|
||||
set_narrowband || set_fpga_bitstream || read_selftest || test_rtc_osc ||
|
||||
read_adc)) {
|
||||
fprintf(stderr, "Specify read, write, or config option.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
@@ -820,7 +826,8 @@ int main(int argc, char** argv)
|
||||
|
||||
if (part == PART_NONE && !set_ui && !dump_state && !set_tx_limit &&
|
||||
!set_rx_limit && !set_leds && !set_p1 && !set_p2 && !set_clkin &&
|
||||
!set_narrowband && !set_fpga_bitstream && !read_selftest && !read_adc) {
|
||||
!set_narrowband && !set_fpga_bitstream && !read_selftest && !test_rtc_osc &&
|
||||
!read_adc) {
|
||||
fprintf(stderr, "Specify a part to read, write, or print config from.\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
@@ -973,6 +980,18 @@ int main(int argc, char** argv)
|
||||
printf("%s", selftest.msg);
|
||||
}
|
||||
|
||||
if (test_rtc_osc) {
|
||||
bool pass;
|
||||
result = hackrf_test_rtc_osc(device, &pass);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
printf("hackrf_test_rtc_osc() failed: %s (%d)\n",
|
||||
hackrf_error_name(result),
|
||||
result);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("RTC test result: %s\n", pass ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
if (read_adc) {
|
||||
uint16_t value;
|
||||
result = hackrf_read_adc(device, adc_channel, &value);
|
||||
|
||||
@@ -110,6 +110,7 @@ typedef enum {
|
||||
HACKRF_VENDOR_REQUEST_CLKIN_CTRL = 55,
|
||||
HACKRF_VENDOR_REQUEST_READ_SELFTEST = 56,
|
||||
HACKRF_VENDOR_REQUEST_READ_ADC = 57,
|
||||
HACKRF_VENDOR_REQUEST_TEST_RTC_OSC = 58,
|
||||
} hackrf_vendor_request;
|
||||
|
||||
#define USB_CONFIG_STANDARD 0x1
|
||||
@@ -1245,6 +1246,110 @@ int ADDCALL hackrf_read_selftest(hackrf_device* device, hackrf_selftest* selftes
|
||||
}
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_test_rtc_osc(hackrf_device* device, bool* pass)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0109);
|
||||
|
||||
int result;
|
||||
|
||||
enum {
|
||||
START_32KHZ_OSCILLATOR,
|
||||
START_FREQ_MONITOR,
|
||||
READ_FREQ_MONITOR,
|
||||
STOP_32KHZ_OSCILLATOR,
|
||||
} step;
|
||||
|
||||
// Enable 32kHz oscillator
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_TEST_RTC_OSC,
|
||||
0,
|
||||
START_32KHZ_OSCILLATOR,
|
||||
NULL,
|
||||
0,
|
||||
1000);
|
||||
|
||||
if (result < 0) {
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
}
|
||||
|
||||
// Wait 1s for oscillator startup
|
||||
#ifdef _WIN32
|
||||
Sleep(1000);
|
||||
#else
|
||||
usleep(1000000);
|
||||
#endif
|
||||
|
||||
// Start frequency monitor
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_TEST_RTC_OSC,
|
||||
0,
|
||||
START_FREQ_MONITOR,
|
||||
NULL,
|
||||
0,
|
||||
1000);
|
||||
|
||||
if (result < 0) {
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
}
|
||||
|
||||
// Wait for frequency monitor result
|
||||
#ifdef _WIN32
|
||||
Sleep(1);
|
||||
#else
|
||||
usleep(1000);
|
||||
#endif
|
||||
|
||||
// Read frequency monitor result
|
||||
uint16_t count = 0;
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_TEST_RTC_OSC,
|
||||
0,
|
||||
READ_FREQ_MONITOR,
|
||||
(unsigned char*) &count,
|
||||
sizeof(count),
|
||||
1000);
|
||||
|
||||
if (result < sizeof(count)) {
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
// Disable 32kHz oscillator
|
||||
result = libusb_control_transfer(
|
||||
device->usb_device,
|
||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_RECIPIENT_DEVICE,
|
||||
HACKRF_VENDOR_REQUEST_TEST_RTC_OSC,
|
||||
0,
|
||||
STOP_32KHZ_OSCILLATOR,
|
||||
NULL,
|
||||
0,
|
||||
1000);
|
||||
|
||||
if (result < 0) {
|
||||
last_libusb_error = result;
|
||||
return HACKRF_ERROR_LIBUSB;
|
||||
}
|
||||
|
||||
*pass = true;
|
||||
} else {
|
||||
*pass = false;
|
||||
}
|
||||
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
|
||||
int ADDCALL hackrf_read_adc(hackrf_device* device, uint8_t adc_channel, uint16_t* value)
|
||||
{
|
||||
USB_API_REQUIRED(device, 0x0109);
|
||||
|
||||
@@ -1354,6 +1354,16 @@ extern ADDAPI int ADDCALL hackrf_read_selftest(
|
||||
hackrf_device* device,
|
||||
hackrf_selftest* value);
|
||||
|
||||
/**
|
||||
* Test the RTC oscillator on the device
|
||||
*
|
||||
* @param[in] device device to query
|
||||
* @param[out] pass RTC oscillator test result
|
||||
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
|
||||
* @ingroup debug
|
||||
*/
|
||||
extern ADDAPI int ADDCALL hackrf_test_rtc_osc(hackrf_device* device, bool* pass);
|
||||
|
||||
/**
|
||||
* Read a value from an ADC channel
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user