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
 34typedef int bool;
 35	#define true 1
 36	#define false 0
 37#endif
 38
 39
 40int parse_int(char* s, uint32_t* const value)
 41{
 42	uint_fast8_t base = 10;
 43	char* s_end;
 44	long long_value;
 45
 46	if (strlen(s) > 2) {
 47		if (s[0] == '0') {
 48			if ((s[1] == 'x') || (s[1] == 'X')) {
 49				base = 16;
 50				s += 2;
 51			} else if ((s[1] == 'b') || (s[1] == 'B')) {
 52				base = 2;
 53				s += 2;
 54			}
 55		}
 56	}
 57
 58	s_end = s;
 59	long_value = strtol(s, &s_end, base);
 60	if ((s != s_end) && (*s_end == 0)) {
 61		*value = (uint32_t) long_value;
 62		return HACKRF_SUCCESS;
 63	} else {
 64		return HACKRF_ERROR_INVALID_PARAM;
 65	}
 66}
 67
 68
 69int parse_double(char* s, double* const double_value)
 70{
 71	char* s_end;
 72
 73	s_end = s + strlen(s);
 74	*double_value = strtof(s, &s_end);
 75	if ((s != s_end) && (*s_end == 0)) {
 76		return HACKRF_SUCCESS;
 77	} else {
 78		return HACKRF_ERROR_INVALID_PARAM;
 79	}
 80}
 81
 82
 83static void usage()
 84{
 85	printf("Manage HTime for HackRF: ticks, seconds, A/D trigger, clocks.\n");
 86	printf("\nUsage:\n");
 87	printf("\t-h, --help: this help\n");
 88	printf("\t-d, --divisor <v>: set divisor to <v> val next pps\n");
 89	printf("\t-D, --Divisor <v>: set divisor to <v> val for one pps\n");
 90	printf("\t-f, --set_clk_freq <v>: set sync clock freq to <v>\n");
 91	printf("\t-k, --ticks : read ticks counter now\n");
 92	printf("\t-K, --Ticks : set ticks counter now\n");
 93	printf("\t-r, --trig_delay <v>: set trig delay to <v> val next pps\n");
 94	printf("\t-s, --seconds <v>: set seconds counter now to <v> value\n");
 95	printf("\t-S, --Seconds <v>: as -s but in sync to next pps\n");
 96	printf("\t-t, --get_seconds: read seconds counter now\n");
 97	printf("\t-y, --mcu_clk_sync <0/1>: enable/disable mcu clock sync\n");
 98	printf("\nExamples:\n");
 99	printf("\thackrf_time -s 1234     # set seconds counter to 1234 now\n");
100	printf("\thackrf_time -y 1        # enable MCU sync mode\n");
101
102	printf("\nv0.1.0 20250215 F.P. <mxgbot@gmail.com>\n");
103}
104
105
106static struct option long_options[] = {
107    {"help", no_argument, 0, 'h'},
108	{"divisor", required_argument, 0, 'd'},
109	{"Divisor", required_argument, 0, 'D'},
110	{"set_clk_freq", required_argument, 0, 'f'},
111	{"ticks", no_argument, 0, 'k'},
112	{"Ticks", required_argument, 0, 'K'},
113	{"trig_delay", required_argument, 0, 'r'},
114	{"seconds", required_argument, 0, 's'},
115	{"Seconds", required_argument, 0, 'S'},
116	{"get_seconds", no_argument, 0, 't'},
117	{"mcu_clk_sync", required_argument, 0, 'y'},
118    {0, 0, 0, 0}
119};
120
121
122int main(int argc, char** argv)
123{
124	int opt;
125	hackrf_device* device = NULL;
126	int option_index = 0;
127	const char* serial_number = NULL;
128
129	uint32_t divisor;
130	uint32_t trig_delay;
131	int64_t seconds;
132	uint32_t ticks;
133	uint32_t value;
134	double frequency;
135
136	if (argc > 1)
137		opt = getopt_long(argc,argv,"hd:D:f:kK:r:s:S:ty:",long_options,
138				&option_index);
139	else {
140		usage();
141		return 0;
142	}
143
144	int result = hackrf_init();
145	if (result) {
146		printf("hackrf_init() failed: %s (%d)\n",
147		       hackrf_error_name(result),
148		       result);
149		return EXIT_FAILURE;
150	}
151
152	result = hackrf_open_by_serial(serial_number, &device);
153	if (result) {
154		printf("hackrf_open() failed: %s (%d)\n",
155		       hackrf_error_name(result),
156		       result);
157		return EXIT_FAILURE;
158	}
159
160	switch (opt) {
161
162        case 'd':
163            result = parse_int(optarg,&value);
164			if (result){
165				printf("invalid divisor value. Int required'\n");
166				return EXIT_FAILURE;
167			}
168			divisor = value;
169			result = hackrf_time_set_divisor_next_pps(device,divisor);
170			if (result) {
171				printf("divisor next pps setting failed: %s (%d)\n",
172                    hackrf_error_name(result),result);
173				return EXIT_FAILURE;
174			}
175			break;
176
177
178		case 'D':
179			result = parse_int(optarg,&value);
180			if (result){
181				printf("invalid divisor value. Int required'\n");
182				return EXIT_FAILURE;
183			}
184			divisor = value;
185			result = hackrf_time_set_divisor_one_pps(device,divisor);
186			if (result) {
187				printf("divisor one pps setting failed: %s (%d)\n",
188                 	hackrf_error_name(result),result);
189				return EXIT_FAILURE;
190			}
191			break;
192
193
194		case 'f':
195			result = parse_double(optarg,&frequency);
196			if (result) { 
197				printf("invalid frequency value. Double required'\n");
198				return EXIT_FAILURE;
199			}
200			result = hackrf_time_set_clk_freq(device,frequency);
201			if (result) {
202				printf("clock frequency setting failed: %s (%d)\n",
203                    hackrf_error_name(result),result);
204				return EXIT_FAILURE;
205			}
206			break;
207
208
209		case 'k':
210			result = hackrf_time_get_ticks_now(device,&ticks);
211            if (result) {
212                printf("ticks reading failed: %s (%d)\n",
213                    hackrf_error_name(result),result);
214                return EXIT_FAILURE;
215			}
216			printf("tick counter: %d\n",ticks);
217			break;
218
219
220		case 'K':
221			result = hackrf_time_set_ticks_now(device,ticks);
222                if (result) {
223                    printf("tick setting failed: %s (%d)\n",
224                        hackrf_error_name(result),result);
225                    return EXIT_FAILURE;
226			}
227			break;
228
229
230		case 'r':
231			result = parse_int(optarg,&value);
232			if (result){
233				printf("invalid delay value. Int required'\n");
234				return EXIT_FAILURE;
235			}
236			trig_delay = value;
237			result = hackrf_time_set_trig_delay_next_pps(device,
238				trig_delay);
239			if (result) {
240				printf("trigger delay setting failed: %s (%d)\n",
241                	hackrf_error_name(result),result);
242				return EXIT_FAILURE;
243			}
244			break;
245
246
247		case 's':
248			result = parse_int(optarg,&value);
249			if (result){
250				printf("invalid second value. Int required'\n");
251				return EXIT_FAILURE;
252			}
253			seconds = value;
254			result = hackrf_time_set_seconds_now(device,seconds);
255			if (result) {
256				printf("second setting failed: %s (%d)\n",
257                   	hackrf_error_name(result),result);
258				return EXIT_FAILURE;
259			}
260			break;
261
262
263		case 'S':
264			result = parse_int(optarg,&value);
265			if (result){
266				printf("invalid second value. Int required'\n");
267				return EXIT_FAILURE;
268			}
269			seconds = value;
270			result = hackrf_time_set_seconds_next_pps(device,seconds);
271			if (result) {
272			  printf("second setting at next pps failed: %s (%d)\n",
273                  hackrf_error_name(result),result);
274			  return EXIT_FAILURE;
275			}
276			break;
277
278
279		case 't':
280			result = hackrf_time_get_seconds_now(device,&seconds);
281			if (result) {
282			  printf("seconds reading failed: %s (%d)\n",
283                  hackrf_error_name(result),result);
284			  return EXIT_FAILURE;
285			}
286			printf("second counter: %ld\n",seconds);
287			break;
288
289
290		case 'y':
291			result = parse_int(optarg,&value);
292			if (result){
293				printf("invalid enable value. Int required'\n");
294				return EXIT_FAILURE;
295			}
296			result = hackrf_time_set_mcu_clk_sync(device,value);
297			if (result) {
298			  printf("seconds setting at next pps failed: %s (%d)\n",
299                  hackrf_error_name(result),result);
300			  return EXIT_FAILURE;
301			}
302			break;
303
304
305		case 'h':
306		case '?':
307			usage();
308			return EXIT_SUCCESS;
309		default:
310			fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
311			usage();
312			return EXIT_FAILURE;
313		}
314
315		if (result != HACKRF_SUCCESS) {
316			printf("argument error: %s (%d)\n",
317			    hackrf_error_name(result),result);
318			usage();
319			return EXIT_FAILURE;
320	}
321
322	result = hackrf_close(device);
323	if (result) {
324		printf("hackrf_close() failed: %s (%d)\n",
325		    hackrf_error_name(result),result);
326		return EXIT_FAILURE;
327	}
328
329	hackrf_exit();
330	return EXIT_SUCCESS;
331}

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