HTime Tool Source

  1/*
  2 * Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
  3 * Copyright 2012 Jared Boone <jared@sharebrained.com>
  4 * Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
  5 * Copyright 2017 Dominic Spill <dominicgs@gmail.com>
  6 * Copyright 2025 Fabrizio Pollastri <mxgbot@gmail.com>
  7 *
  8 * This file is part of HackRF.
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2, or (at your option)
 13 * any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; see the file COPYING.  If not, write to
 22 * the Free Software Foundation, Inc., 51 Franklin Street,
 23 * Boston, MA 02110-1301, USA.
 24 */
 25
 26#include <hackrf.h>
 27
 28#include <stdio.h>
 29#include <string.h>
 30#include <stdlib.h>
 31#include <getopt.h>
 32
 33//#ifndef bool
 34//typedef int bool;
 35//	#define true  1
 36//	#define false 0
 37//#endif
 38
 39int parse_int(char* s, uint32_t* const value)
 40{
 41	uint_fast8_t base = 10;
 42	char* s_end;
 43	long long_value;
 44
 45	if (strlen(s) > 2) {
 46		if (s[0] == '0') {
 47			if ((s[1] == 'x') || (s[1] == 'X')) {
 48				base = 16;
 49				s += 2;
 50			} else if ((s[1] == 'b') || (s[1] == 'B')) {
 51				base = 2;
 52				s += 2;
 53			}
 54		}
 55	}
 56
 57	s_end = s;
 58	long_value = strtol(s, &s_end, base);
 59	if ((s != s_end) && (*s_end == 0)) {
 60		*value = (uint32_t) long_value;
 61		return HACKRF_SUCCESS;
 62	} else {
 63		return HACKRF_ERROR_INVALID_PARAM;
 64	}
 65}
 66
 67int parse_double(char* s, double* const double_value)
 68{
 69	char* s_end;
 70
 71	s_end = s + strlen(s);
 72	*double_value = strtof(s, &s_end);
 73	if ((s != s_end) && (*s_end == 0)) {
 74		return HACKRF_SUCCESS;
 75	} else {
 76		return HACKRF_ERROR_INVALID_PARAM;
 77	}
 78}
 79
 80static void usage()
 81{
 82	printf("Manage HTime for HackRF: ticks, seconds, A/D trigger, clocks.\n");
 83	printf("\nUsage:\n");
 84	printf("\t-h, --help: this help\n");
 85	printf("\t-d, --divisor <v>: set divisor to <v> val next pps\n");
 86	printf("\t-D, --Divisor <v>: set divisor to <v> val for one pps\n");
 87	printf("\t-f, --set_clk_freq <v>: set sync clock freq to <v>\n");
 88	printf("\t-k, --ticks : read ticks counter now\n");
 89	printf("\t-K, --Ticks : set ticks counter now\n");
 90	printf("\t-r, --trig_delay <v>: set trig delay to <v> val next pps\n");
 91	printf("\t-s, --seconds <v>: set seconds counter now to <v> value\n");
 92	printf("\t-S, --Seconds <v>: as -s but in sync to next pps\n");
 93	printf("\t-t, --get_seconds: read seconds counter now\n");
 94	printf("\t-y, --mcu_clk_sync <0/1>: enable/disable mcu clock sync\n");
 95	printf("\nExamples:\n");
 96	printf("\thackrf_time -s 1234     # set seconds counter to 1234 now\n");
 97	printf("\thackrf_time -y 1        # enable MCU sync mode\n");
 98
 99	printf("\nv0.1.0 20250215 F.P. <mxgbot@gmail.com>\n");
100}
101
102static struct option long_options[] = {
103	{"help", no_argument, 0, 'h'},
104	{"divisor", required_argument, 0, 'd'},
105	{"Divisor", required_argument, 0, 'D'},
106	{"set_clk_freq", required_argument, 0, 'f'},
107	{"ticks", no_argument, 0, 'k'},
108	{"Ticks", required_argument, 0, 'K'},
109	{"trig_delay", required_argument, 0, 'r'},
110	{"seconds", required_argument, 0, 's'},
111	{"Seconds", required_argument, 0, 'S'},
112	{"get_seconds", no_argument, 0, 't'},
113	{"mcu_clk_sync", required_argument, 0, 'y'},
114	{0, 0, 0, 0}};
115
116int main(int argc, char** argv)
117{
118	int opt;
119	hackrf_device* device = NULL;
120	int option_index = 0;
121	const char* serial_number = NULL;
122
123	uint32_t divisor;
124	uint32_t trig_delay;
125	int64_t seconds;
126	uint32_t ticks;
127	uint32_t value;
128	double frequency;
129
130	if (argc > 1)
131		opt = getopt_long(
132			argc,
133			argv,
134			"hd:D:f:kK:r:s:S:ty:",
135			long_options,
136			&option_index);
137	else {
138		usage();
139		return 0;
140	}
141
142	int result = hackrf_init();
143	if (result) {
144		printf("hackrf_init() failed: %s (%d)\n",
145		       hackrf_error_name(result),
146		       result);
147		return EXIT_FAILURE;
148	}
149
150	result = hackrf_open_by_serial(serial_number, &device);
151	if (result) {
152		printf("hackrf_open() failed: %s (%d)\n",
153		       hackrf_error_name(result),
154		       result);
155		return EXIT_FAILURE;
156	}
157
158	switch (opt) {
159	case 'd':
160		result = parse_int(optarg, &value);
161		if (result) {
162			printf("invalid divisor value. Int required'\n");
163			return EXIT_FAILURE;
164		}
165		divisor = value;
166		result = hackrf_time_set_divisor_next_pps(device, divisor);
167		if (result) {
168			printf("divisor next pps setting failed: %s (%d)\n",
169			       hackrf_error_name(result),
170			       result);
171			return EXIT_FAILURE;
172		}
173		break;
174
175	case 'D':
176		result = parse_int(optarg, &value);
177		if (result) {
178			printf("invalid divisor value. Int required'\n");
179			return EXIT_FAILURE;
180		}
181		divisor = value;
182		result = hackrf_time_set_divisor_one_pps(device, divisor);
183		if (result) {
184			printf("divisor one pps setting failed: %s (%d)\n",
185			       hackrf_error_name(result),
186			       result);
187			return EXIT_FAILURE;
188		}
189		break;
190
191	case 'f':
192		result = parse_double(optarg, &frequency);
193		if (result) {
194			printf("invalid frequency value. Double required'\n");
195			return EXIT_FAILURE;
196		}
197		result = hackrf_time_set_clk_freq(device, frequency);
198		if (result) {
199			printf("clock frequency setting failed: %s (%d)\n",
200			       hackrf_error_name(result),
201			       result);
202			return EXIT_FAILURE;
203		}
204		break;
205
206	case 'k':
207		result = hackrf_time_get_ticks_now(device, &ticks);
208		if (result) {
209			printf("ticks reading failed: %s (%d)\n",
210			       hackrf_error_name(result),
211			       result);
212			return EXIT_FAILURE;
213		}
214		printf("tick counter: %d\n", ticks);
215		break;
216
217	case 'K':
218		result = hackrf_time_set_ticks_now(device, ticks);
219		if (result) {
220			printf("tick setting failed: %s (%d)\n",
221			       hackrf_error_name(result),
222			       result);
223			return EXIT_FAILURE;
224		}
225		break;
226
227	case 'r':
228		result = parse_int(optarg, &value);
229		if (result) {
230			printf("invalid delay value. Int required'\n");
231			return EXIT_FAILURE;
232		}
233		trig_delay = value;
234		result = hackrf_time_set_trig_delay_next_pps(device, trig_delay);
235		if (result) {
236			printf("trigger delay setting failed: %s (%d)\n",
237			       hackrf_error_name(result),
238			       result);
239			return EXIT_FAILURE;
240		}
241		break;
242
243	case 's':
244		result = parse_int(optarg, &value);
245		if (result) {
246			printf("invalid second value. Int required'\n");
247			return EXIT_FAILURE;
248		}
249		seconds = value;
250		result = hackrf_time_set_seconds_now(device, seconds);
251		if (result) {
252			printf("second setting failed: %s (%d)\n",
253			       hackrf_error_name(result),
254			       result);
255			return EXIT_FAILURE;
256		}
257		break;
258
259	case 'S':
260		result = parse_int(optarg, &value);
261		if (result) {
262			printf("invalid second value. Int required'\n");
263			return EXIT_FAILURE;
264		}
265		seconds = value;
266		result = hackrf_time_set_seconds_next_pps(device, seconds);
267		if (result) {
268			printf("second setting at next pps failed: %s (%d)\n",
269			       hackrf_error_name(result),
270			       result);
271			return EXIT_FAILURE;
272		}
273		break;
274
275	case 't':
276		result = hackrf_time_get_seconds_now(device, &seconds);
277		if (result) {
278			printf("seconds reading failed: %s (%d)\n",
279			       hackrf_error_name(result),
280			       result);
281			return EXIT_FAILURE;
282		}
283		printf("second counter: %ld\n", seconds);
284		break;
285
286	case 'y':
287		result = parse_int(optarg, &value);
288		if (result) {
289			printf("invalid enable value. Int required'\n");
290			return EXIT_FAILURE;
291		}
292		result = hackrf_time_set_mcu_clk_sync(device, value);
293		if (result) {
294			printf("seconds setting at next pps failed: %s (%d)\n",
295			       hackrf_error_name(result),
296			       result);
297			return EXIT_FAILURE;
298		}
299		break;
300
301	case 'h':
302	case '?':
303		usage();
304		return EXIT_SUCCESS;
305	default:
306		fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
307		usage();
308		return EXIT_FAILURE;
309	}
310
311	if (result != HACKRF_SUCCESS) {
312		printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
313		usage();
314		return EXIT_FAILURE;
315	}
316
317	result = hackrf_close(device);
318	if (result) {
319		printf("hackrf_close() failed: %s (%d)\n",
320		       hackrf_error_name(result),
321		       result);
322		return EXIT_FAILURE;
323	}
324
325	hackrf_exit();
326	return EXIT_SUCCESS;
327}

HTime documentation by Fabrizio Pollastri is licensed under CC BY-SA 4.0