1 //  soft66.c   V0.1
2 //  Linrad's 'host control' routines for Soft66 series SDR receivers
3 //  Uses libsoft66 by Thomas Horsten <thomas@horsten.com>
4 //
5 //  There is currently no provision for listing devices or
6 //  selecting one based on serial number, although the library
7 //  supports these features. Instead you can set the environment
8 //  variable SOFT66_SERIAL to the correct serial number and
9 //  the correct one will be opened.
10 //
11 //  Expect more features to be added, this is a raw first cut,
12 //  just to get frequency control!
13 //
14 //  This code is based on si570.c which in turn is based on
15 //  ausbsoftrock.c by Andrew Nilsson (andrew.nilsson@gmail.com),
16 //  powerSwitch.c by Christian Starkjohann,
17 //  and usbtemp.c by Mathias Dalheimer of Objective Development Software GmbH (2005)
18 //  (see http://www.obdev.at/products/vusb/index.html )
19 //
20 //  Use at your own risk and enjoy
21 //  Thomas
22 //
23 //  UPDATE HISTORY
24 //  06 November 2010	Created
25 
26 #include "loadusb.h"
27 #include "uidef.h"
28 #include "screendef.h"
29 #include "fft1def.h"
30 #include <string.h>
31 
32 
33 #if OSNUM == OSNUM_WINDOWS
34 #include <windows.h>
35 #ifdef interface
36 #undef interface
37 #endif
38 #endif
39 
40 
41 
42 
43 #define SOFT66_SERIAL_ENV "SOFT66_SERIAL"
44 #define SOFT66_VID_ENV "SOFT66_VID"
45 #define SOFT66_PID_ENV "SOFT66_PID"
46 
47 #define SOFT66_VID_DEFAULT 0x0403
48 #define SOFT66_PID_DEFAULT 0x6001
49 
50 
51 enum soft66_model {
52 	SOFT66_MODEL_UNKNOWN = 0x0,
53 	SOFT66_MODEL_SOFT66ADD = 0x1,
54 };
55 
56 struct soft66_context {
57 	int model;
58 	unsigned int chipid;
59 	unsigned int freq_min;
60 	unsigned int freq_max;
61 	unsigned int mclk;
62 
63 	struct ftdi_context *ftdi;
64 };
65 
66 
67 //struct soft66_context *soft66_new(void);
68 typedef struct soft66_context* (*p_soft66_new)(void);
69 typedef void (*p_soft66_free)(struct soft66_context *ctx);
70 typedef int (*p_soft66_set_frequency)(struct soft66_context *ctx, int freq, int noreset);
71 typedef int (*p_soft66_open_device)(struct soft66_context *ctx,
72                                        int vid, int pid, const char *serial);
73 p_soft66_new soft66_new;
74 p_soft66_set_frequency soft66_set_frequency;
75 p_soft66_open_device soft66_open_device;
76 p_soft66_free soft66_free;
77 
78 int soft66_library_flag;
79 
80 
81 
82 #define MAX_SOFT66_PARM            1
83 
84 static char *soft66_parfil_name="par_soft66";
85 static char *soft66_parm_text[MAX_SOFT66_PARM]={"Power down on exit"
86 };
87 
88 typedef struct {
89 	int PowerDownOnExit;
90 }P_SOFT66;
91 P_SOFT66 soft66;
92 struct soft66_context *soft66_handle = NULL;
93 int soft66_needs_reset = 0;
94 
95 #if(OSNUM == OSNUM_WINDOWS)
96 #include <windows.h>
97 HANDLE soft66_libhandle;
98 
load_soft66_library(void)99 void load_soft66_library(void)
100 {
101 int info;
102 if(soft66_library_flag)return;
103 info=0;
104 soft66_libhandle=LoadLibrary("soft66.dll");
105 if(!soft66_libhandle)goto soft66_load_error;
106 info=1;
107 soft66_new=(p_soft66_new)GetProcAddress(soft66_libhandle, "soft66_new");
108 if(!soft66_new)goto soft66_sym_error;
109 soft66_set_frequency=(p_soft66_set_frequency)
110                         GetProcAddress(soft66_libhandle, "soft66_set_frequency");
111 if(!soft66_set_frequency)goto soft66_sym_error;
112 soft66_open_device=(p_soft66_open_device)
113                             GetProcAddress(soft66_libhandle, "soft66_open_device");
114 if(!soft66_open_device)goto soft66_sym_error;
115 soft66_free=(p_soft66_free)GetProcAddress(soft66_libhandle, "soft66_free");
116 if(!soft66_free)goto soft66_sym_error;
117 soft66_library_flag=TRUE;
118 if(!soft66_new)goto soft66_sym_error;
119 return;
120 soft66_sym_error:;
121 FreeLibrary(soft66_libhandle);
122 soft66_load_error:;
123 library_error_screen("soft66.dll",info);
124 }
125 
unload_soft66_library(void)126 void unload_soft66_library(void)
127 {
128 if(!soft66_library_flag)return;
129 FreeLibrary(soft66_libhandle);
130 soft66_library_flag=FALSE;
131 }
132 #endif
133 
134 
135 #if(OSNUM == OSNUM_LINUX)
136 #include <dlfcn.h>
137 void *soft66_libhandle;
138 
load_soft66_library(void)139 void load_soft66_library(void)
140 {
141 int info;
142 info=0;
143 if(soft66_library_flag)return;
144 soft66_libhandle=dlopen(SOFT66_LIBNAME, RTLD_LAZY);
145 if(!soft66_libhandle)goto soft66_load_error;
146 info=1;
147 soft66_new=(p_soft66_new)dlsym(soft66_libhandle, "soft66_new");
148 if(dlerror() != 0)goto soft66_sym_error;
149 soft66_set_frequency=(p_soft66_set_frequency)
150                         dlsym(soft66_libhandle, "soft66_set_frequency");
151 soft66_open_device=(p_soft66_open_device)
152                             dlsym(soft66_libhandle, "soft66_open_device");
153 soft66_free=(p_soft66_free)dlsym(soft66_libhandle, "soft66_free");
154 soft66_library_flag=TRUE;
155 return;
156 soft66_sym_error:;
157 dlclose(soft66_libhandle);
158 soft66_load_error:;
159 library_error_screen(SOFT66_LIBNAME,info);
160 }
161 
unload_soft66_library(void)162 void unload_soft66_library(void)
163 {
164 if(!soft66_library_flag)return;
165 dlclose(soft66_libhandle);
166 soft66_library_flag=FALSE;
167 }
168 #endif
169 
170 
171 
set_default_parameters(void)172 static void set_default_parameters(void)
173 {
174 // SET DEFAULTS VALUES FOR Soft66
175 	soft66.PowerDownOnExit =0;
176 }
177 
read_par_soft66_file(void)178 static void read_par_soft66_file(void)
179 {
180 	int errcod;
181 	errcod=read_sdrpar(soft66_parfil_name, MAX_SOFT66_PARM,
182 			   soft66_parm_text, (int*)((void*)&soft66));
183 	if (errcod != 0)
184 	{
185 		FILE *soft66_file;
186 		int *sdr_pi,i;
187 		soft66_file=fopen(soft66_parfil_name,"w");
188 		set_default_parameters();
189 		sdr_pi=(int*)(&soft66);
190 		for(i=0; i<MAX_SOFT66_PARM; i++)
191 		{
192 			fprintf(soft66_file,"%s [%d]\n",soft66_parm_text[i],sdr_pi[i]);
193 		}
194 		parfile_end(soft66_file);
195 	}
196 }
197 
save_par_soft66_file(void)198 static void save_par_soft66_file(void)
199 {
200 	FILE *soft66_file;
201 	int *sdr_pi,i;
202 	soft66_file=fopen(soft66_parfil_name,"w");
203 	sdr_pi=(int*)(&soft66);
204 	for(i=0; i<MAX_SOFT66_PARM; i++)
205 	{
206 		fprintf(soft66_file,"%s [%d]\n",soft66_parm_text[i],sdr_pi[i]);
207 	}
208 	parfile_end(soft66_file);
209 }
210 
Soft66OpenDevice(void)211 static int Soft66OpenDevice(void)
212 {
213 	int r;
214 	struct soft66_context *ctx = soft66_new();
215 	read_par_soft66_file();
216 	if (!ctx)
217 		return -1;
218 	r = soft66_open_device(ctx, 0, 0, NULL);
219 	if (r < 0) {
220 		soft66_free(ctx);
221 		ctx = NULL;
222 	}
223 	soft66_needs_reset = 1;
224 	soft66_handle = ctx;
225 	return r;
226 return 0;
227 }
228 /*
229 static int Soft66CloseDevice(void)
230 {
231 	if (soft66_handle)
232 		soft66_free(soft66_handle);
233 	soft66_handle = NULL;
234 	soft66_needs_reset = 0;
235 	return 0;
236 }
237 */
setFreqByValue(unsigned int frequency)238 static int setFreqByValue(unsigned int frequency)
239 {
240 	int r;
241 	if (!soft66_handle) {
242 		r = Soft66OpenDevice();
243 		if (r<0)
244 			return r;
245 	}
246 
247 	r = soft66_set_frequency(soft66_handle, frequency, soft66_needs_reset);
248 	//printf("sfbv: %d (%d)\n", frequency, soft66_needs_reset);
249 	if (r < 0)
250 		printf("soft66.c: Error when setting frequency %d, returncode=%i\n",frequency,r);
251 	soft66_needs_reset = 0;
252 	return r;
253 }
254 
soft66_setup(void)255 void soft66_setup(void)
256 {
257 char s[160];
258 int  retval;
259 int  line;
260 load_soft66_library();
261 if(!soft66_library_flag)return;
262 start_setup:
263 clear_screen();
264 settextcolor(14);
265 lir_text(2,1,"CURRENT SETUP FOR 'SOFT66 USB DEVICE' ");
266 settextcolor(7);
267 line= 4;
268 read_par_soft66_file();
269 retval=Soft66OpenDevice();
270 if(retval == 0)
271   {
272   settextcolor(10);
273   sprintf(s,"Soft66 Model: %d", soft66_handle->model);
274   lir_text(38,line,s);
275   settextcolor(7);
276   line+=2;
277   }
278 else
279   {
280   settextcolor(12);
281   sprintf(s,"Could not open device, probably not connected");
282   lir_text(58,line,s);
283   settextcolor(7);
284   line+=2;
285   }
286 sprintf(s,"Soft66 power down on exit = ");
287 lir_text(2,line,s);
288 settextcolor(10);
289 sprintf(s,"%i",soft66.PowerDownOnExit);
290 lir_text(38,line,s);
291 settextcolor(7);
292 line+=6;
293 lir_text(2,line,"A = Enable automatic power-down.");
294 line++;
295 lir_text(2,line,"B = Disable automatic power-down.");
296 line++;
297 line++;
298 lir_text(2,line,"X = Exit.");
299 setup_menu:;
300 await_processed_keyboard();
301 if(kill_all_flag)return;
302 switch(lir_inkey)
303   {
304   case 'A':
305   soft66.PowerDownOnExit=0;
306   save_par_soft66_file();
307   goto start_setup;
308 
309   case 'B':
310   soft66.PowerDownOnExit=0;
311   save_par_soft66_file();
312   goto start_setup;
313 
314   case 'X':
315   unload_soft66_library();
316   return;
317 
318   default:
319   goto setup_menu;
320   }
321 }
322 
soft66_rx_freq_control(void)323 void soft66_rx_freq_control(void)
324 {
325 	int  retval;
326 	int f;
327 
328 	fg.passband_direction=1;
329 	fft1_direction = fg.passband_direction;
330 	fg.passband_increment=0.050;
331 
332 	if (!soft66_handle) {
333 		retval=Soft66OpenDevice();
334 		if(retval != 0 ) printf("soft66.c: Could not find Soft66 device\n");
335 		return;
336 	}
337 
338 	if (fg.passband_center*1000000.0 < soft66_handle->freq_min )
339 	{
340 		fg.passband_center = soft66_handle->freq_min/1000000.0;
341 	} else if (fg.passband_center*1000000.0 > soft66_handle->freq_max )
342 	{
343 		fg.passband_center = soft66_handle->freq_max/1000000.0;
344 	}
345 	f = (int)(fg.passband_center*1000000.0);
346 	//f = (int)(fg.passband_center*1000000.0);
347 	retval=setFreqByValue(f);
348 	if (retval < 0 )
349 	{
350 		if(retval != 0 ) printf("soft66.c: Could not set frequency\n");
351 	}
352 }
353