altos/stm32f4: Wrong value for CK48MSEL_PLL_Q
[fw/altos] / altoslib / AltosPreferences.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 package org.altusmetrum.altoslib_13;
20
21 import java.io.*;
22 import java.util.*;
23 import java.text.*;
24
25 public class AltosPreferences {
26         public static AltosPreferencesBackend backend = null;
27
28         /* logdir preference name */
29         public final static String logdirPreference = "LOGDIR";
30
31         /* channel preference name */
32         public final static String channelPreferenceFormat = "CHANNEL-%d";
33
34         /* frequency preference name */
35         public final static String frequencyPreferenceFormat = "FREQUENCY-%d";
36
37         /* telemetry format preference name */
38         public final static String telemetryPreferenceFormat = "TELEMETRY-%d";
39
40         /* telemetry rate format preference name */
41         public final static String telemetryRatePreferenceFormat = "RATE-%d";
42
43         /* log file format preference name */
44         public final static String logfilePreferenceFormat = "LOGFILE-%d";
45
46         /* state preference name */
47         public final static String statePreferenceHead = "STATE-";
48         public final static String statePreferenceFormat = "STATE-%d";
49         public final static String statePreferenceLatest = "STATE-LATEST";
50
51         /* voice preference name */
52         public final static String voicePreference = "VOICE";
53
54         /* callsign preference name */
55         public final static String callsignPreference = "CALLSIGN";
56
57         /* firmware directory preference name */
58         public final static String firmwaredirPreference = "FIRMWARE";
59
60         /* serial debug preference name */
61         public final static String serialDebugPreference = "SERIAL-DEBUG";
62
63         /* scanning telemetry preferences name */
64         public final static String scanningTelemetryPreference = "SCANNING-TELEMETRY";
65
66         /* scanning telemetry rate preferences name */
67         public final static String scanningTelemetryRatePreference = "SCANNING-RATE";
68
69         /* Launcher serial preference name */
70         public final static String launcherSerialPreference = "LAUNCHER-SERIAL";
71
72         /* Launcher channel preference name */
73         public final static String launcherChannelPreference = "LAUNCHER-CHANNEL";
74
75         /* Default logdir is ~/TeleMetrum */
76         public final static String logdirName = "TeleMetrum";
77
78         /* Log directory */
79         public static File logdir;
80
81         /* Last log directory - use this next time we open or save something */
82         public static File last_logdir;
83
84         /* Map directory -- hangs of logdir */
85         public static File mapdir;
86
87         /* Frequency (map serial to frequency) */
88         public static Hashtable<Integer, Double> frequencies;
89
90         /* Telemetry (map serial to telemetry format) */
91         public static Hashtable<Integer, Integer> telemetries;
92
93         /* Telemetry rate (map serial to telemetry format) */
94         public static Hashtable<Integer, Integer> telemetry_rates;
95
96         /* Log file (map serial to logfile name) */
97         public static Hashtable<Integer, File> logfiles;
98
99         /* Voice preference */
100         public static boolean voice;
101
102         /* Callsign preference */
103         public static String callsign;
104
105         /* Firmware directory */
106         public static File firmwaredir;
107
108         /* Scanning telemetry */
109         public static int scanning_telemetry;
110
111         public static int scanning_telemetry_rate;
112
113         /* List of frequencies */
114         public final static String common_frequencies_node_name = "COMMON-FREQUENCIES";
115         public static AltosFrequency[] common_frequencies;
116
117         public final static String      frequency_count = "COUNT";
118         public final static String      frequency_format = "FREQUENCY-%d";
119         public final static String      description_format = "DESCRIPTION-%d";
120         public final static String      frequenciesPreference = "FREQUENCIES-1";
121
122         /* Units preference */
123
124         public final static String      unitsPreference = "IMPERIAL-UNITS";
125
126         /* Maps cache size preference name */
127         final static String mapCachePreference = "MAP-CACHE";
128
129         static LinkedList<AltosMapCacheListener> map_cache_listeners;
130
131         public static int map_cache = 9;
132
133         final static String mapTypePreference = "MAP-TYPE";
134         static int      map_type;
135
136         public static AltosFrequency[] load_common_frequencies() {
137                 AltosFrequency[] frequencies = null;
138
139                 try {
140                         AltosJson json = AltosJson.fromString(backend.getString(frequenciesPreference,
141                                                                                 null));
142                         frequencies = (AltosFrequency[]) json.make((new AltosFrequency[1]).getClass());
143                 } catch (Exception e) {
144                 }
145
146                 if (frequencies == null) {
147                         if (backend.nodeExists(common_frequencies_node_name)) {
148                                 AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
149                                 int             count = node.getInt(frequency_count, 0);
150
151                                 if (count > 0) {
152                                         frequencies = new AltosFrequency[count];
153                                         for (int i = 0; i < count; i++) {
154                                                 double  frequency;
155                                                 String  description;
156
157                                                 frequency = node.getDouble(String.format(frequency_format, i), 0.0);
158                                                 description = node.getString(String.format(description_format, i), null);
159                                                 frequencies[i] = new AltosFrequency(frequency, description);
160                                         }
161                                 }
162                         }
163                 }
164
165                 if (frequencies == null) {
166                         frequencies = new AltosFrequency[10];
167                         for (int i = 0; i < 10; i++) {
168                                 frequencies[i] = new AltosFrequency(434.550 + i * .1,
169                                                                            String.format("Channel %d", i));
170                         }
171                 }
172                 return frequencies;
173         }
174
175         public static void save_common_frequencies() {
176                 AltosJson       json = new AltosJson(common_frequencies);
177                 backend.putString(frequenciesPreference, json.toString());
178                 flush_preferences();
179         }
180
181         public static int launcher_serial;
182
183         public static int launcher_channel;
184
185         public static void init(AltosPreferencesBackend in_backend) {
186
187                 if (backend != null)
188                         return;
189
190                 backend = in_backend;
191
192                 /* Initialize logdir from preferences */
193                 String logdir_string = backend.getString(logdirPreference, null);
194                 if (logdir_string != null)
195                         logdir = new File(logdir_string);
196                 else {
197                         logdir = new File(backend.homeDirectory(), logdirName);
198                         if (!logdir.exists())
199                                 logdir.mkdirs();
200                 }
201                 mapdir = new File(logdir, "maps");
202                 if (!mapdir.exists())
203                         mapdir.mkdirs();
204
205                 frequencies = new Hashtable<Integer, Double>();
206
207                 telemetries = new Hashtable<Integer,Integer>();
208
209                 telemetry_rates = new Hashtable<Integer,Integer>();
210
211                 logfiles = new Hashtable<Integer,File>();
212
213                 voice = backend.getBoolean(voicePreference, true);
214
215                 callsign = backend.getString(callsignPreference,"N0CALL");
216
217                 scanning_telemetry = backend.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard));
218
219                 scanning_telemetry_rate = backend.getInt(scanningTelemetryRatePreference,(1 << AltosLib.ao_telemetry_rate_38400));
220
221                 launcher_serial = backend.getInt(launcherSerialPreference, 0);
222
223                 launcher_channel = backend.getInt(launcherChannelPreference, 0);
224
225                 String firmwaredir_string = backend.getString(firmwaredirPreference, null);
226                 if (firmwaredir_string != null)
227                         firmwaredir = new File(firmwaredir_string);
228                 else
229                         firmwaredir = null;
230
231                 common_frequencies = load_common_frequencies();
232
233                 AltosConvert.imperial_units = backend.getBoolean(unitsPreference, false);
234
235                 map_cache = backend.getInt(mapCachePreference, 9);
236                 map_cache_listeners = new LinkedList<AltosMapCacheListener>();
237                 map_type = backend.getInt(mapTypePreference, AltosMap.maptype_hybrid);
238         }
239
240         public static void flush_preferences() {
241                 backend.flush();
242         }
243
244         public static void set_logdir(File new_logdir) {
245                 synchronized (backend) {
246                         logdir = new_logdir;
247                         mapdir = new File(logdir, "maps");
248                         if (!mapdir.exists())
249                                 mapdir.mkdirs();
250                         backend.putString(logdirPreference, logdir.getPath());
251                         flush_preferences();
252                 }
253         }
254
255         public static File logdir() {
256                 synchronized (backend) {
257                         return logdir;
258                 }
259         }
260
261         public static File last_logdir() {
262                 synchronized (backend) {
263                         if (last_logdir == null)
264                                 last_logdir = logdir;
265                         return last_logdir;
266                 }
267         }
268
269         public static void set_last_logdir(File file) {
270                 synchronized(backend) {
271                         if (file != null && !file.isDirectory())
272                                 file = file.getParentFile();
273                         if (file == null)
274                                 file = new File(".");
275                         last_logdir = file;
276                 }
277         }
278
279         public static File mapdir() {
280                 synchronized (backend) {
281                         return mapdir;
282                 }
283         }
284
285         public static void set_frequency(int serial, double new_frequency) {
286                 synchronized (backend) {
287                         frequencies.put(serial, new_frequency);
288                         backend.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency);
289                         flush_preferences();
290                 }
291         }
292
293         public static double frequency(int serial) {
294                 synchronized (backend) {
295                         if (frequencies.containsKey(serial))
296                                 return frequencies.get(serial);
297                         double frequency = backend.getDouble(String.format(frequencyPreferenceFormat, serial), 0);
298                         if (frequency == 0.0) {
299                                 int channel = backend.getInt(String.format(channelPreferenceFormat, serial), 0);
300                                 frequency = AltosConvert.radio_channel_to_frequency(channel);
301                         }
302                         frequencies.put(serial, frequency);
303                         return frequency;
304                 }
305         }
306
307         public static void set_telemetry(int serial, int new_telemetry) {
308                 synchronized (backend) {
309                         telemetries.put(serial, new_telemetry);
310                         backend.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry);
311                         flush_preferences();
312                 }
313         }
314
315         public static int telemetry(int serial) {
316                 synchronized (backend) {
317                         if (telemetries.containsKey(serial))
318                                 return telemetries.get(serial);
319                         int telemetry = backend.getInt(String.format(telemetryPreferenceFormat, serial),
320                                                    AltosLib.ao_telemetry_standard);
321                         telemetries.put(serial, telemetry);
322                         return telemetry;
323                 }
324         }
325
326         public static void set_telemetry_rate(int serial, int new_telemetry_rate) {
327                 synchronized (backend) {
328                         telemetry_rates.put(serial, new_telemetry_rate);
329                         backend.putInt(String.format(telemetryRatePreferenceFormat, serial), new_telemetry_rate);
330                         flush_preferences();
331                 }
332         }
333
334         public static int telemetry_rate(int serial) {
335                 synchronized (backend) {
336                         if (telemetry_rates.containsKey(serial))
337                                 return telemetry_rates.get(serial);
338                         int telemetry_rate = backend.getInt(String.format(telemetryRatePreferenceFormat, serial),
339                                                             AltosLib.ao_telemetry_rate_38400);
340                         telemetry_rates.put(serial, telemetry_rate);
341                         return telemetry_rate;
342                 }
343         }
344
345         public static void set_logfile(int serial, File new_logfile) {
346                 synchronized(backend) {
347                         logfiles.put(serial, new_logfile);
348                         backend.putString(String.format(logfilePreferenceFormat, serial), new_logfile.getPath());
349                         flush_preferences();
350                 }
351         }
352
353         public static File logfile(int serial) {
354                 synchronized(backend) {
355                         if (logfiles.containsKey(serial))
356                                 return logfiles.get(serial);
357                         String logfile_string = backend.getString(String.format(logfilePreferenceFormat, serial), null);
358                         if (logfile_string == null)
359                                 return null;
360                         File logfile = new File(logfile_string);
361                         logfiles.put(serial, logfile);
362                         return logfile;
363                 }
364         }
365
366         public static void set_state(AltosState state, int serial) {
367
368                 synchronized(backend) {
369                         backend.putJson(String.format(statePreferenceFormat, serial), new AltosJson(state));
370                         backend.putInt(statePreferenceLatest, serial);
371                         flush_preferences();
372                 }
373         }
374
375         public static ArrayList<Integer> list_states() {
376                 String[]                keys = backend.keys();
377                 ArrayList<Integer>      states = new ArrayList<Integer>();
378
379                 for (String key : keys) {
380                         if (key.startsWith(statePreferenceHead)) {
381                                 try {
382                                         int serial = AltosParse.parse_int(key.substring(statePreferenceHead.length()));
383                                         states.add(serial);
384                                 } catch (ParseException pe) {
385                                 }
386                         }
387                 }
388                 return states;
389         }
390
391         public static void remove_state(int serial) {
392                 synchronized(backend) {
393                         backend.remove(String.format(statePreferenceFormat, serial));
394                         flush_preferences();
395                 }
396         }
397
398         public static int latest_state() {
399                 int     latest = 0;
400                 synchronized (backend) {
401                         latest = backend.getInt(statePreferenceLatest, 0);
402                 }
403                 return latest;
404         }
405
406         public static AltosState state(int serial) {
407                 synchronized(backend) {
408                         try {
409                                 AltosJson json = backend.getJson(String.format(statePreferenceFormat, serial));
410                                 if (json != null)
411                                         return (AltosState) (json.make(AltosState.class));
412                         } catch (Exception e) {
413                         }
414                         return null;
415                 }
416         }
417
418         public static void set_scanning_telemetry(int new_scanning_telemetry) {
419                 synchronized (backend) {
420                         scanning_telemetry = new_scanning_telemetry;
421                         backend.putInt(scanningTelemetryPreference, scanning_telemetry);
422                         flush_preferences();
423                 }
424         }
425
426         public static int scanning_telemetry() {
427                 synchronized (backend) {
428                         return scanning_telemetry;
429                 }
430         }
431
432         public static void set_scanning_telemetry_rate(int new_scanning_telemetry_rate) {
433                 synchronized (backend) {
434                         scanning_telemetry_rate = new_scanning_telemetry_rate;
435                         backend.putInt(scanningTelemetryRatePreference, scanning_telemetry_rate);
436                         flush_preferences();
437                 }
438         }
439
440         public static int scanning_telemetry_rate() {
441                 synchronized(backend) {
442                         return scanning_telemetry_rate;
443                 }
444         }
445
446         public static void set_voice(boolean new_voice) {
447                 synchronized (backend) {
448                         voice = new_voice;
449                         backend.putBoolean(voicePreference, voice);
450                         flush_preferences();
451                 }
452         }
453
454         public static boolean voice() {
455                 synchronized (backend) {
456                         return voice;
457                 }
458         }
459
460         public static void set_callsign(String new_callsign) {
461                 synchronized(backend) {
462                         callsign = new_callsign;
463                         backend.putString(callsignPreference, callsign);
464                         flush_preferences();
465                 }
466         }
467
468         public static String callsign() {
469                 synchronized(backend) {
470                         return callsign;
471                 }
472         }
473
474         public static void set_firmwaredir(File new_firmwaredir) {
475                 synchronized (backend) {
476                         firmwaredir = new_firmwaredir;
477                         backend.putString(firmwaredirPreference, firmwaredir.getPath());
478                         flush_preferences();
479                 }
480         }
481
482         public static File firmwaredir() {
483                 synchronized (backend) {
484                         return firmwaredir;
485                 }
486         }
487
488         public static void set_launcher_serial(int new_launcher_serial) {
489                 synchronized (backend) {
490                         launcher_serial = new_launcher_serial;
491                         backend.putInt(launcherSerialPreference, launcher_serial);
492                         flush_preferences();
493                 }
494         }
495
496         public static int launcher_serial() {
497                 synchronized (backend) {
498                         return launcher_serial;
499                 }
500         }
501
502         public static void set_launcher_channel(int new_launcher_channel) {
503                 synchronized (backend) {
504                         launcher_channel = new_launcher_channel;
505                         backend.putInt(launcherChannelPreference, launcher_channel);
506                         flush_preferences();
507                 }
508         }
509
510         public static int launcher_channel() {
511                 synchronized (backend) {
512                         return launcher_channel;
513                 }
514         }
515
516         public static AltosPreferencesBackend bt_devices() {
517                 synchronized (backend) {
518                         return backend.node("bt_devices");
519                 }
520         }
521
522         public static AltosFrequency[] common_frequencies() {
523                 synchronized (backend) {
524                         return common_frequencies;
525                 }
526         }
527
528         public static void set_common_frequencies(AltosFrequency[] frequencies) {
529                 synchronized(backend) {
530                         common_frequencies = frequencies;
531
532                         save_common_frequencies();
533                 }
534         }
535
536         public static void add_common_frequency(AltosFrequency frequency) {
537                 AltosFrequency[]        old_frequencies = common_frequencies();
538                 AltosFrequency[]        new_frequencies = new AltosFrequency[old_frequencies.length + 1];
539                 int                     i;
540
541                 for (i = 0; i < old_frequencies.length; i++) {
542                         if (frequency.frequency == old_frequencies[i].frequency)
543                                 return;
544                         if (frequency.frequency < old_frequencies[i].frequency)
545                                 break;
546                         new_frequencies[i] = old_frequencies[i];
547                 }
548                 new_frequencies[i] = frequency;
549                 for (; i < old_frequencies.length; i++)
550                         new_frequencies[i+1] = old_frequencies[i];
551                 set_common_frequencies(new_frequencies);
552         }
553
554         static LinkedList<AltosUnitsListener> units_listeners;
555
556         public static boolean imperial_units() {
557                 synchronized(backend) {
558                         return AltosConvert.imperial_units;
559                 }
560         }
561
562         public static void set_imperial_units(boolean imperial_units) {
563                 synchronized (backend) {
564                         AltosConvert.imperial_units = imperial_units;
565                         backend.putBoolean(unitsPreference, imperial_units);
566                         flush_preferences();
567                 }
568                 if (units_listeners != null) {
569                         for (AltosUnitsListener l : units_listeners) {
570                                 l.units_changed(imperial_units);
571                         }
572                 }
573         }
574
575         public static void register_units_listener(AltosUnitsListener l) {
576                 synchronized(backend) {
577                         if (units_listeners == null)
578                                 units_listeners = new LinkedList<AltosUnitsListener>();
579                         units_listeners.add(l);
580                 }
581         }
582
583         public static void unregister_units_listener(AltosUnitsListener l) {
584                 synchronized(backend) {
585                         units_listeners.remove(l);
586                 }
587         }
588
589
590         public static void register_map_cache_listener(AltosMapCacheListener l) {
591                 synchronized(backend) {
592                         map_cache_listeners.add(l);
593                 }
594         }
595
596         public static void unregister_map_cache_listener(AltosMapCacheListener l) {
597                 synchronized (backend) {
598                         map_cache_listeners.remove(l);
599                 }
600         }
601
602         public static void set_map_cache(int new_map_cache) {
603                 synchronized(backend) {
604                         map_cache = new_map_cache;
605                         backend.putInt(mapCachePreference, map_cache);
606                         flush_preferences();
607                         for (AltosMapCacheListener l: map_cache_listeners)
608                                 l.map_cache_changed(map_cache);
609                 }
610         }
611
612         public static int map_cache() {
613                 synchronized(backend) {
614                         return map_cache;
615                 }
616         }
617
618         static LinkedList<AltosMapTypeListener> map_type_listeners;
619
620         public static void set_map_type(int map_type) {
621                 synchronized(backend) {
622                         AltosPreferences.map_type = map_type;
623                         backend.putInt(mapTypePreference, map_type);
624                         flush_preferences();
625                 }
626                 if (map_type_listeners != null) {
627                         for (AltosMapTypeListener l : map_type_listeners) {
628                                 l.map_type_changed(map_type);
629                         }
630                 }
631         }
632
633         public static int map_type() {
634                 synchronized(backend) {
635                         return map_type;
636                 }
637         }
638
639         public static void register_map_type_listener(AltosMapTypeListener l) {
640                 synchronized(backend) {
641                         if (map_type_listeners == null)
642                                 map_type_listeners = new LinkedList<AltosMapTypeListener>();
643                         map_type_listeners.add(l);
644                 }
645         }
646
647         public static void unregister_map_type_listener(AltosMapTypeListener l) {
648                 synchronized(backend) {
649                         map_type_listeners.remove(l);
650                 }
651         }
652 }