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