1 /*
2 * Copyright 2013/2014 Benjamin Vernoux <bvernoux@airspy.com>
3 *
4 * This file is part of AirSpy (based on HackRF project).
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <airspy.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <getopt.h>
28
29 #ifndef bool
30 typedef int bool;
31 #define true 1
32 #define false 0
33 #endif
34
35 #define REGISTER_NUM_MIN (0)
36 #define REGISTER_NUM_MAX (31)
37
usage()38 static void usage() {
39 printf("Usage:\n");
40 printf("\t-n, --register <n>: set register <n>[%d,%d] for subsequent read/write operations\n", REGISTER_NUM_MIN, REGISTER_NUM_MAX);
41 printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
42 printf("\t-w, --write <v>: write register specified by last -n argument with value <v>[0,255]\n");
43 printf("\t-c, --config: configure registers to r820t default mode for test\n");
44 printf("\t[-s serial_number_64bits]: Open board with specified 64bits serial number.\n");
45 printf("\nExamples:\n");
46 printf("\t<command> -n 12 -r # reads from register 12\n");
47 printf("\t<command> -r # reads all registers\n");
48 printf("\t<command> -n 10 -w 22 # writes register 10 with 22 decimal\n");
49 }
50
51 static struct option long_options[] = {
52 { "register", required_argument, 0, 'n' },
53 { "write", required_argument, 0, 'w' },
54 { "read", no_argument, 0, 'r' },
55 { "config", no_argument, 0, 'c' },
56 { 0, 0, 0, 0 },
57 };
58
parse_u8(char * const s,uint8_t * const value)59 int parse_u8(char* const s, uint8_t* const value) {
60 char* s_end = s;
61 const long int long_value = strtol(s, &s_end, 10);
62 if( (s != s_end) && (*s_end == 0) ) {
63 if((long_value >=0 ) && (long_value < 256)) {
64 *value = (uint8_t)long_value;
65 return AIRSPY_SUCCESS;
66 } else {
67 return AIRSPY_ERROR_INVALID_PARAM;
68 }
69 } else {
70 return AIRSPY_ERROR_INVALID_PARAM;
71 }
72 }
73
parse_u64(char * s,uint64_t * const value)74 int parse_u64(char* s, uint64_t* const value) {
75 uint_fast8_t base = 10;
76 char* s_end;
77 uint64_t u64_value;
78
79 if( strlen(s) > 2 ) {
80 if( s[0] == '0' ) {
81 if( (s[1] == 'x') || (s[1] == 'X') ) {
82 base = 16;
83 s += 2;
84 } else if( (s[1] == 'b') || (s[1] == 'B') ) {
85 base = 2;
86 s += 2;
87 }
88 }
89 }
90
91 s_end = s;
92 u64_value = strtoull(s, &s_end, base);
93 if( (s != s_end) && (*s_end == 0) ) {
94 *value = u64_value;
95 return AIRSPY_SUCCESS;
96 } else {
97 return AIRSPY_ERROR_INVALID_PARAM;
98 }
99 }
100
dump_register(struct airspy_device * device,const uint8_t register_number)101 int dump_register(struct airspy_device* device, const uint8_t register_number)
102 {
103 uint8_t register_value;
104 int result = airspy_r820t_read(device, register_number, ®ister_value);
105
106 if( result == AIRSPY_SUCCESS ) {
107 printf("[%3d] -> 0x%02X\n", register_number, register_value);
108 } else {
109 printf("airspy_r820t_read() failed: %s (%d)\n", airspy_error_name(result), result);
110 }
111
112 return result;
113 }
114
dump_registers(struct airspy_device * device)115 int dump_registers(struct airspy_device* device)
116 {
117 uint8_t register_number;
118 int result = AIRSPY_SUCCESS;
119
120 for(register_number=0; register_number<32; register_number++)
121 {
122 result = dump_register(device, register_number);
123 if( result != AIRSPY_SUCCESS ) {
124 break;
125 }
126 }
127
128 return result;
129 }
130
write_register(struct airspy_device * device,const uint8_t register_number,const uint8_t register_value)131 int write_register(struct airspy_device* device, const uint8_t register_number, const uint8_t register_value)
132 {
133 int result = AIRSPY_SUCCESS;
134 result = airspy_r820t_write(device, register_number, register_value);
135
136 if( result == AIRSPY_SUCCESS ) {
137 printf("0x%02X -> [%3d]\n", register_value, register_number);
138 } else {
139 printf("airspy_r820t_write() failed: %s (%d)\n", airspy_error_name(result), result);
140 }
141
142 return result;
143 }
144
145 #define CONF_R820T_START_REG (5)
146 uint8_t conf_r820t[] =
147 {
148 0x12, 0x32, 0x75, /* 05 to 07 */
149 0xc0, 0x40, 0xd6, 0x6c, /* 08 to 11 */
150 0x40, 0x63, 0x75, 0x68, /* 12 to 15 */
151 0x6c, 0x83, 0x80, 0x00, /* 16 to 19 */
152 0x0f, 0x00, 0xc0, 0x30, /* 20 to 23 */
153 0x48, 0xcc, 0x60, 0x00, /* 24 to 27 */
154 0x54, 0xae, 0x4a, 0xc0 /* 28 to 31 */
155 };
156
configure_registers(struct airspy_device * device)157 int configure_registers(struct airspy_device* device)
158 {
159 int i, j;
160 uint8_t register_number;
161 uint8_t register_value;
162 int result = AIRSPY_SUCCESS;
163
164 j=0;
165 for(i=0; i<sizeof(conf_r820t); i++)
166 {
167 register_number = i + CONF_R820T_START_REG;
168 register_value = conf_r820t[j];
169 j++;
170 result = airspy_r820t_write(device, register_number, register_value);
171 if( result == AIRSPY_SUCCESS )
172 {
173 printf("0x%02X -> [%3d]\n", register_value, register_number);
174 } else {
175 printf("airspy_r820t_write() failed: %s (%d)\n", airspy_error_name(result), result);
176 return result;
177 }
178 }
179 return result;
180 }
181
182 #define REGISTER_INVALID 255
183 bool serial_number = false;
184 uint64_t serial_number_val;
185
main(int argc,char ** argv)186 int main(int argc, char** argv) {
187 int opt;
188 uint8_t register_number = REGISTER_INVALID;
189 uint8_t register_value;
190 struct airspy_device* device = NULL;
191 int option_index;
192 uint32_t serial_number_msb_val;
193 uint32_t serial_number_lsb_val;
194 int result;
195
196 option_index = 0;
197 while( (opt = getopt_long(argc, argv, "cn:rw:s:", long_options, &option_index)) != EOF )
198 {
199 switch( opt ) {
200
201 case 's':
202 serial_number = true;
203 result = parse_u64(optarg, &serial_number_val);
204 serial_number_msb_val = (uint32_t)(serial_number_val >> 32);
205 serial_number_lsb_val = (uint32_t)(serial_number_val & 0xFFFFFFFF);
206 printf("Board serial number to open: 0x%08X%08X\n", serial_number_msb_val, serial_number_lsb_val);
207 break;
208 }
209 }
210
211 result = airspy_init();
212 if( result ) {
213 printf("airspy_init() failed: %s (%d)\n", airspy_error_name(result), result);
214 return EXIT_FAILURE;
215 }
216
217 if(serial_number == true)
218 {
219 result = airspy_open_sn(&device, serial_number_val);
220 if( result != AIRSPY_SUCCESS ) {
221 printf("airspy_open_sn() failed: %s (%d)\n", airspy_error_name(result), result);
222 usage();
223 airspy_exit();
224 return EXIT_FAILURE;
225 }
226 }else
227 {
228 result = airspy_open(&device);
229 if( result != AIRSPY_SUCCESS ) {
230 printf("airspy_open() failed: %s (%d)\n", airspy_error_name(result), result);
231 usage();
232 airspy_exit();
233 return EXIT_FAILURE;
234 }
235 }
236
237 result = AIRSPY_ERROR_OTHER;
238 option_index = 0;
239 optind = 0;
240 while( (opt = getopt_long(argc, argv, "cn:rw:", long_options, &option_index)) != EOF )
241 {
242 switch( opt ) {
243 case 'n':
244 result = parse_u8(optarg, ®ister_number);
245 if((result != AIRSPY_SUCCESS) || (register_number > REGISTER_NUM_MAX))
246 {
247 register_number = REGISTER_INVALID;
248 printf("Error parameter -n shall be between %d and %d\n", REGISTER_NUM_MIN, REGISTER_NUM_MAX);
249 result = AIRSPY_ERROR_OTHER;
250 }
251 break;
252
253 case 'w':
254 result = parse_u8(optarg, ®ister_value);
255 if( result == AIRSPY_SUCCESS ) {
256 result = write_register(device, register_number, register_value);
257 }else
258 {
259 printf("Error parameter -w shall be between 0 and 255\n");
260 result = AIRSPY_ERROR_OTHER;
261 }
262 break;
263
264 case 'r':
265 if( register_number == REGISTER_INVALID ) {
266 result = dump_registers(device);
267 } else {
268 result = dump_register(device, register_number);
269 }
270 break;
271
272 case 'c':
273 result = configure_registers(device);
274 break;
275 }
276
277 if( result != AIRSPY_SUCCESS )
278 {
279 break;
280 }
281 }
282
283 if( result != AIRSPY_SUCCESS )
284 {
285 usage();
286 }
287
288 result = airspy_close(device);
289 if( result ) {
290 printf("airspy_close() failed: %s (%d)\n", airspy_error_name(result), result);
291 airspy_exit();
292 return EXIT_FAILURE;
293 }
294
295 airspy_exit();
296
297 return 0;
298 }
299
300