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