1 /*
2 *
3 * NMEA library
4 * URL: http://nmea.sourceforge.net
5 * Author: Tim (xtimor@gmail.com)
6 * Licence: http://www.gnu.org/licenses/lgpl.html
7 * $Id: generator.c 17 2008-03-11 11:56:11Z xtimor $
8 *
9 */
10
11 #include "nmea/gmath.h"
12 #include "nmea/generate.h"
13 #include "nmea/generator.h"
14 #include "nmea/context.h"
15
16 #include <string.h>
17 #include <stdlib.h>
18
19 #if defined(NMEA_WIN) && defined(_MSC_VER)
20 # pragma warning(disable: 4100) /* unreferenced formal parameter */
21 #endif
22
nmea_random(double min,double max)23 double nmea_random(double min, double max)
24 {
25 static double rand_max = RAND_MAX;
26 double rand_val = rand();
27 double bounds = max - min;
28 return min + (rand_val * bounds) / rand_max;
29 }
30
31 /*
32 * low level
33 */
34
nmea_gen_init(nmeaGENERATOR * gen,nmeaINFO * info)35 int nmea_gen_init(nmeaGENERATOR *gen, nmeaINFO *info)
36 {
37 int RetVal = 1; int smask = info->smask;
38 nmeaGENERATOR *igen = gen;
39
40 nmea_zero_INFO(info);
41 info->smask = smask;
42
43 info->lat = NMEA_DEF_LAT;
44 info->lon = NMEA_DEF_LON;
45
46 while(RetVal && igen)
47 {
48 if(igen->init_call)
49 RetVal = (*igen->init_call)(igen, info);
50 igen = igen->next;
51 }
52
53 return RetVal;
54 }
55
nmea_gen_loop(nmeaGENERATOR * gen,nmeaINFO * info)56 int nmea_gen_loop(nmeaGENERATOR *gen, nmeaINFO *info)
57 {
58 int RetVal = 1;
59
60 if(gen->loop_call)
61 RetVal = (*gen->loop_call)(gen, info);
62
63 if(RetVal && gen->next)
64 RetVal = nmea_gen_loop(gen->next, info);
65
66 return RetVal;
67 }
68
nmea_gen_reset(nmeaGENERATOR * gen,nmeaINFO * info)69 int nmea_gen_reset(nmeaGENERATOR *gen, nmeaINFO *info)
70 {
71 int RetVal = 1;
72
73 if(gen->reset_call)
74 RetVal = (*gen->reset_call)(gen, info);
75
76 return RetVal;
77 }
78
nmea_gen_destroy(nmeaGENERATOR * gen)79 void nmea_gen_destroy(nmeaGENERATOR *gen)
80 {
81 if(gen->next)
82 {
83 nmea_gen_destroy(gen->next);
84 gen->next = 0;
85 }
86
87 if(gen->destroy_call)
88 (*gen->destroy_call)(gen);
89
90 free(gen);
91 }
92
nmea_gen_add(nmeaGENERATOR * to,nmeaGENERATOR * gen)93 void nmea_gen_add(nmeaGENERATOR *to, nmeaGENERATOR *gen)
94 {
95 if(to->next)
96 nmea_gen_add(to->next, gen);
97 else
98 to->next = gen;
99 }
100
nmea_generate_from(char * buff,int buff_sz,nmeaINFO * info,nmeaGENERATOR * gen,int generate_mask)101 int nmea_generate_from(
102 char *buff, int buff_sz,
103 nmeaINFO *info,
104 nmeaGENERATOR *gen,
105 int generate_mask
106 )
107 {
108 int retval;
109
110 if(0 != (retval = nmea_gen_loop(gen, info)))
111 retval = nmea_generate(buff, buff_sz, info, generate_mask);
112
113 return retval;
114 }
115
116 /*
117 * NOISE generator
118 */
119
nmea_igen_noise_init(nmeaGENERATOR * gen,nmeaINFO * info)120 int nmea_igen_noise_init(nmeaGENERATOR *gen, nmeaINFO *info)
121 {
122 return 1;
123 }
124
nmea_igen_noise_loop(nmeaGENERATOR * gen,nmeaINFO * info)125 int nmea_igen_noise_loop(nmeaGENERATOR *gen, nmeaINFO *info)
126 {
127 int it;
128 int in_use;
129
130 info->sig = (int)nmea_random(1, 3);
131 info->PDOP = nmea_random(0, 9);
132 info->HDOP = nmea_random(0, 9);
133 info->VDOP = nmea_random(0, 9);
134 info->fix = (int)nmea_random(2, 3);
135 info->lat = nmea_random(0, 100);
136 info->lon = nmea_random(0, 100);
137 info->speed = nmea_random(0, 100);
138 info->direction = nmea_random(0, 360);
139 info->declination = nmea_random(0, 360);
140 info->elv = (int)nmea_random(-100, 100);
141
142 info->satinfo.inuse = 0;
143 info->satinfo.inview = 0;
144
145 for(it = 0; it < 12; ++it)
146 {
147 info->satinfo.sat[it].id = it;
148 info->satinfo.sat[it].in_use = in_use = (int)nmea_random(0, 3);
149 info->satinfo.sat[it].elv = (int)nmea_random(0, 90);
150 info->satinfo.sat[it].azimuth = (int)nmea_random(0, 359);
151 info->satinfo.sat[it].sig = (int)(in_use?nmea_random(40, 99):nmea_random(0, 40));
152
153 if(in_use)
154 info->satinfo.inuse++;
155 if(info->satinfo.sat[it].sig > 0)
156 info->satinfo.inview++;
157 }
158
159 return 1;
160 }
161
nmea_igen_noise_reset(nmeaGENERATOR * gen,nmeaINFO * info)162 int nmea_igen_noise_reset(nmeaGENERATOR *gen, nmeaINFO *info)
163 {
164 return 1;
165 }
166
167 /*
168 * STATIC generator
169 */
170
nmea_igen_static_loop(nmeaGENERATOR * gen,nmeaINFO * info)171 int nmea_igen_static_loop(nmeaGENERATOR *gen, nmeaINFO *info)
172 {
173 nmea_time_now(&info->utc);
174 return 1;
175 };
176
nmea_igen_static_reset(nmeaGENERATOR * gen,nmeaINFO * info)177 int nmea_igen_static_reset(nmeaGENERATOR *gen, nmeaINFO *info)
178 {
179 info->satinfo.inuse = 4;
180 info->satinfo.inview = 4;
181
182 info->satinfo.sat[0].id = 1;
183 info->satinfo.sat[0].in_use = 1;
184 info->satinfo.sat[0].elv = 50;
185 info->satinfo.sat[0].azimuth = 0;
186 info->satinfo.sat[0].sig = 99;
187
188 info->satinfo.sat[1].id = 2;
189 info->satinfo.sat[1].in_use = 1;
190 info->satinfo.sat[1].elv = 50;
191 info->satinfo.sat[1].azimuth = 90;
192 info->satinfo.sat[1].sig = 99;
193
194 info->satinfo.sat[2].id = 3;
195 info->satinfo.sat[2].in_use = 1;
196 info->satinfo.sat[2].elv = 50;
197 info->satinfo.sat[2].azimuth = 180;
198 info->satinfo.sat[2].sig = 99;
199
200 info->satinfo.sat[3].id = 4;
201 info->satinfo.sat[3].in_use = 1;
202 info->satinfo.sat[3].elv = 50;
203 info->satinfo.sat[3].azimuth = 270;
204 info->satinfo.sat[3].sig = 99;
205
206 return 1;
207 }
208
nmea_igen_static_init(nmeaGENERATOR * gen,nmeaINFO * info)209 int nmea_igen_static_init(nmeaGENERATOR *gen, nmeaINFO *info)
210 {
211 info->sig = 3;
212 info->fix = 3;
213
214 nmea_igen_static_reset(gen, info);
215
216 return 1;
217 }
218
219 /*
220 * SAT_ROTATE generator
221 */
222
nmea_igen_rotate_loop(nmeaGENERATOR * gen,nmeaINFO * info)223 int nmea_igen_rotate_loop(nmeaGENERATOR *gen, nmeaINFO *info)
224 {
225 int it;
226 int count = info->satinfo.inview;
227 double deg = 360 / (count?count:1);
228 double srt = (count?(info->satinfo.sat[0].azimuth):0) + 5;
229
230 nmea_time_now(&info->utc);
231
232 for(it = 0; it < count; ++it)
233 {
234 info->satinfo.sat[it].azimuth =
235 (int)((srt >= 360)?srt - 360:srt);
236 srt += deg;
237 }
238
239 return 1;
240 };
241
nmea_igen_rotate_reset(nmeaGENERATOR * gen,nmeaINFO * info)242 int nmea_igen_rotate_reset(nmeaGENERATOR *gen, nmeaINFO *info)
243 {
244 int it;
245 double deg = 360 / 8;
246 double srt = 0;
247
248 info->satinfo.inuse = 8;
249 info->satinfo.inview = 8;
250
251 for(it = 0; it < info->satinfo.inview; ++it)
252 {
253 info->satinfo.sat[it].id = it + 1;
254 info->satinfo.sat[it].in_use = 1;
255 info->satinfo.sat[it].elv = 5;
256 info->satinfo.sat[it].azimuth = (int)srt;
257 info->satinfo.sat[it].sig = 80;
258 srt += deg;
259 }
260
261 return 1;
262 }
263
nmea_igen_rotate_init(nmeaGENERATOR * gen,nmeaINFO * info)264 int nmea_igen_rotate_init(nmeaGENERATOR *gen, nmeaINFO *info)
265 {
266 info->sig = 3;
267 info->fix = 3;
268
269 nmea_igen_rotate_reset(gen, info);
270
271 return 1;
272 }
273
274 /*
275 * POS_RANDMOVE generator
276 */
277
nmea_igen_pos_rmove_init(nmeaGENERATOR * gen,nmeaINFO * info)278 int nmea_igen_pos_rmove_init(nmeaGENERATOR *gen, nmeaINFO *info)
279 {
280 info->sig = 3;
281 info->fix = 3;
282 info->direction = info->declination = 0;
283 info->speed = 20;
284 return 1;
285 }
286
nmea_igen_pos_rmove_loop(nmeaGENERATOR * gen,nmeaINFO * info)287 int nmea_igen_pos_rmove_loop(nmeaGENERATOR *gen, nmeaINFO *info)
288 {
289 nmeaPOS crd;
290
291 info->direction += nmea_random(-10, 10);
292 info->speed += nmea_random(-2, 3);
293
294 if(info->direction < 0)
295 info->direction = 359 + info->direction;
296 if(info->direction > 359)
297 info->direction -= 359;
298
299 if(info->speed > 40)
300 info->speed = 40;
301 if(info->speed < 1)
302 info->speed = 1;
303
304 nmea_info2pos(info, &crd);
305 nmea_move_horz(&crd, &crd, info->direction, info->speed / 3600);
306 nmea_pos2info(&crd, info);
307
308 info->declination = info->direction;
309
310 return 1;
311 };
312
nmea_igen_pos_rmove_destroy(nmeaGENERATOR * gen)313 int nmea_igen_pos_rmove_destroy(nmeaGENERATOR *gen)
314 {
315 return 1;
316 };
317
318 /*
319 * generator create
320 */
321
__nmea_create_generator(int type,nmeaINFO * info)322 nmeaGENERATOR * __nmea_create_generator(int type, nmeaINFO *info)
323 {
324 nmeaGENERATOR *gen = 0;
325
326 switch(type)
327 {
328 case NMEA_GEN_NOISE:
329 if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
330 nmea_error("Insufficient memory!");
331 else
332 {
333 memset(gen, 0, sizeof(nmeaGENERATOR));
334 gen->init_call = &nmea_igen_noise_init;
335 gen->loop_call = &nmea_igen_noise_loop;
336 gen->reset_call = &nmea_igen_noise_reset;
337 }
338 break;
339 case NMEA_GEN_STATIC:
340 case NMEA_GEN_SAT_STATIC:
341 if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
342 nmea_error("Insufficient memory!");
343 else
344 {
345 memset(gen, 0, sizeof(nmeaGENERATOR));
346 gen->init_call = &nmea_igen_static_init;
347 gen->loop_call = &nmea_igen_static_loop;
348 gen->reset_call = &nmea_igen_static_reset;
349 }
350 break;
351 case NMEA_GEN_SAT_ROTATE:
352 if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
353 nmea_error("Insufficient memory!");
354 else
355 {
356 memset(gen, 0, sizeof(nmeaGENERATOR));
357 gen->init_call = &nmea_igen_rotate_init;
358 gen->loop_call = &nmea_igen_rotate_loop;
359 gen->reset_call = &nmea_igen_rotate_reset;
360 }
361 break;
362 case NMEA_GEN_POS_RANDMOVE:
363 if(0 == (gen = malloc(sizeof(nmeaGENERATOR))))
364 nmea_error("Insufficient memory!");
365 else
366 {
367 memset(gen, 0, sizeof(nmeaGENERATOR));
368 gen->init_call = &nmea_igen_pos_rmove_init;
369 gen->loop_call = &nmea_igen_pos_rmove_loop;
370 gen->destroy_call = &nmea_igen_pos_rmove_destroy;
371 }
372 break;
373 case NMEA_GEN_ROTATE:
374 gen = __nmea_create_generator(NMEA_GEN_SAT_ROTATE, info);
375 nmea_gen_add(gen, __nmea_create_generator(NMEA_GEN_POS_RANDMOVE, info));
376 break;
377 };
378
379 return gen;
380 }
381
nmea_create_generator(int type,nmeaINFO * info)382 nmeaGENERATOR * nmea_create_generator(int type, nmeaINFO *info)
383 {
384 nmeaGENERATOR *gen = __nmea_create_generator(type, info);
385
386 if(gen)
387 nmea_gen_init(gen, info);
388
389 return gen;
390 }
391
nmea_destroy_generator(nmeaGENERATOR * gen)392 void nmea_destroy_generator(nmeaGENERATOR *gen)
393 {
394 nmea_gen_destroy(gen);
395 }
396
397 #if defined(NMEA_WIN) && defined(_MSC_VER)
398 # pragma warning(default: 4100)
399 #endif
400