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, &register_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, &register_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, &register_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