2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
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.
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.
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.
21 #include <ao_config.h>
23 #include <ao_sample.h>
30 #include <ao_tracker.h>
33 struct ao_config ao_config;
34 uint8_t ao_config_loaded;
35 uint8_t ao_config_dirty;
36 uint8_t ao_config_mutex;
39 uint8_t ao_force_freq;
42 #ifndef HAS_CONFIG_SAVE
43 #define HAS_CONFIG_SAVE HAS_EEPROM
46 #ifndef AO_CONFIG_DEFAULT_APRS_INTERVAL
47 #define AO_CONFIG_DEFAULT_APRS_INTERVAL 0
49 #define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250
50 #define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0
51 #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL"
52 #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
53 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
54 #define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL
55 #define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP
56 #define AO_CONFIG_DEFAULT_PYRO_TIME AO_MS_TO_TICKS(50)
57 #define AO_CONFIG_DEFAULT_RADIO_10MW 0
58 #define AO_CONFIG_DEFAULT_REPORT_FEET 0
60 #ifndef USE_INTERNAL_FLASH
61 #error Please define USE_INTERNAL_FLASH
65 #ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX
66 # if FLIGHT_LOG_APPEND
67 # define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_log_max
69 # if USE_INTERNAL_FLASH
70 # define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config
72 # define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024)
77 #ifndef AO_CONFIG_DEFAULT_RADIO_POWER
78 #define AO_CONFIG_DEFAULT_RADIO_POWER 0x60
80 #define AO_CONFIG_DEFAULT_RADIO_AMP 0
81 #define AO_CONFIG_DEFAULT_APRS_SSID ((uint8_t) (ao_serial_number % 10))
82 #define AO_CONFIG_DEFAULT_RADIO_RATE AO_RADIO_RATE_38400
90 ao_config_write(0, &ao_config, sizeof (ao_config));
91 #if HAS_FLIGHT && HAS_LOG
92 ao_log_write_erase(0);
100 ao_mutex_get(&ao_config_mutex);
102 ao_mutex_put(&ao_config_mutex);
108 #if HAS_RADIO_FORWARD
109 uint32_t ao_send_radio_setting;
113 ao_config_set_radio(void)
115 ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal);
116 #if HAS_RADIO_FORWARD
117 ao_send_radio_setting = ao_freq_to_set(ao_config.send_frequency, ao_config.radio_cal);
120 #endif /* HAS_RADIO */
127 if (ao_config_loaded)
130 /* Yes, I know ao_storage_read calls ao_storage_setup,
131 * but ao_storage_setup *also* sets ao_storage_config, which we
132 * need before calling ao_storage_read here
135 ao_config_read(0, &ao_config, sizeof (ao_config));
137 if (ao_config.major != AO_CONFIG_MAJOR) {
138 ao_config.major = AO_CONFIG_MAJOR;
141 /* Version 0 stuff */
142 ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
143 memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
144 memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
145 sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
146 ao_config._legacy_radio_channel = 0;
148 minor = ao_config.minor;
149 if (minor != AO_CONFIG_MINOR) {
151 ao_pyro_update_version();
153 /* Fixups for minor version 1 */
155 ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
156 /* Fixups for minor version 2 */
158 ao_config.accel_plus_g = 0;
159 ao_config.accel_minus_g = 0;
161 /* Fixups for minor version 3 */
164 ao_config.radio_cal = ao_radio_cal;
166 /* Fixups for minor version 4 */
169 ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX;
171 /* Fixupes for minor version 5 */
173 ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE;
175 ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION;
177 ao_config.radio_enable = AO_RADIO_ENABLE_CORE;
179 memset(&ao_config.aes_key, '\0', AO_AES_LEN);
181 ao_config.frequency = 434550U + ao_config._legacy_radio_channel * 100U;
183 ao_config.apogee_lockout = 0;
186 memset(&ao_config.pyro, '\0', sizeof (ao_config.pyro));
189 ao_config.aprs_interval = AO_CONFIG_DEFAULT_APRS_INTERVAL;
192 ao_config.radio_power = AO_CONFIG_DEFAULT_RADIO_POWER;
196 ao_config.radio_amp = AO_CONFIG_DEFAULT_RADIO_AMP;
200 ao_config.accel_zero_along = 0;
201 ao_config.accel_zero_across = 0;
202 ao_config.accel_zero_through = 0;
204 /* Reset the main accel offsets to force
207 ao_config.accel_plus_g = 0;
208 ao_config.accel_minus_g = 0;
213 ao_config.mid_beep = AO_BEEP_MID_DEFAULT;
217 ao_config.tracker_motion = AO_TRACKER_MOTION_DEFAULT;
218 ao_config.tracker_interval = AO_TRACKER_INTERVAL_DEFAULT;
223 ao_config.pyro_time = AO_CONFIG_DEFAULT_PYRO_TIME;
227 ao_config.aprs_ssid = AO_CONFIG_DEFAULT_APRS_SSID;
231 ao_config.radio_rate = AO_CONFIG_DEFAULT_RADIO_RATE;
233 #if HAS_RADIO_FORWARD
235 ao_config.send_frequency = 434550;
239 ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
241 #if HAS_FIXED_PAD_BOX
243 ao_config.pad_box = 1;
245 ao_config.pad_idle = 120;
249 ao_config.aprs_offset = 0;
253 ao_config.radio_10mw = AO_CONFIG_DEFAULT_RADIO_10MW;
256 ao_config.report_feet = AO_CONFIG_DEFAULT_REPORT_FEET;
257 ao_config.minor = AO_CONFIG_MINOR;
263 ao_config.frequency = 434550;
264 ao_config.radio_cal = ao_radio_cal;
266 ao_config.radio_rate = AO_CONFIG_DEFAULT_RADIO_RATE;
268 memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
269 sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
272 ao_config_set_radio();
274 ao_config_loaded = 1;
278 _ao_config_edit_start(void)
280 ao_mutex_get(&ao_config_mutex);
285 _ao_config_edit_finish(void)
288 ao_mutex_put(&ao_config_mutex);
294 _ao_config_edit_start();
295 ao_mutex_put(&ao_config_mutex);
301 ao_config_callsign_show(void)
303 printf ("Callsign: \"%s\"\n", ao_config.callsign);
307 ao_config_callsign_set(void)
310 static char callsign[AO_MAX_CALLSIGN + 1];
312 memset(callsign, '\0', sizeof callsign);
315 while (ao_cmd_lex_c != '\n') {
316 if (c < AO_MAX_CALLSIGN)
317 callsign[c++] = ao_cmd_lex_c;
319 ao_cmd_status = ao_cmd_lex_error;
322 if (ao_cmd_status != ao_cmd_success)
324 _ao_config_edit_start();
325 memcpy(&ao_config.callsign, &callsign,
326 AO_MAX_CALLSIGN + 1);
327 _ao_config_edit_finish();
331 ao_config_frequency_show(void)
333 printf("Frequency: %ld\n",
334 ao_config.frequency);
338 ao_config_frequency_set(void)
340 uint32_t r = ao_cmd_decimal();
341 if (ao_cmd_status != ao_cmd_success)
343 _ao_config_edit_start();
344 ao_config.frequency = r;
345 ao_config_set_radio();
346 _ao_config_edit_finish();
348 ao_radio_recv_abort();
354 #if HAS_RADIO_FORWARD
356 ao_config_send_frequency_show(void)
358 printf("Send frequency: %ld\n",
359 ao_config.send_frequency);
363 ao_config_send_frequency_set(void)
366 if (ao_cmd_status != ao_cmd_success)
368 _ao_config_edit_start();
369 ao_config.send_frequency = ao_cmd_lex_u32;
370 ao_config_set_radio();
371 _ao_config_edit_finish();
373 ao_radio_recv_abort();
384 ao_config_main_deploy_show(void)
386 printf("Main deploy: %d meters\n",
387 ao_config.main_deploy);
391 ao_config_main_deploy_set(void)
393 uint32_t r = ao_cmd_decimal();
394 if (ao_cmd_status != ao_cmd_success)
396 _ao_config_edit_start();
397 ao_config.main_deploy = (uint16_t) r;
398 _ao_config_edit_finish();
405 ao_config_accel_calibrate_show(void)
407 printf("Accel cal +1g: %d -1g: %d\n",
408 ao_config.accel_plus_g, ao_config.accel_minus_g);
410 printf ("IMU cal along %d across %d through %d\n",
411 ao_config.accel_zero_along,
412 ao_config.accel_zero_across,
413 ao_config.accel_zero_through);
417 #define ACCEL_CALIBRATE_SAMPLES 1024
418 #define ACCEL_CALIBRATE_SHIFT 10
421 static int16_t accel_cal_along;
422 static int16_t accel_cal_across;
423 static int16_t accel_cal_through;
427 ao_config_accel_calibrate_auto(char *orientation)
431 uint8_t cal_data_ring;
433 int32_t accel_along_total = 0;
434 int32_t accel_across_total = 0;
435 int32_t accel_through_total = 0;
438 printf("Orient antenna %s and press a key...", orientation);
441 puts("\r\n"); flush();
442 puts("Calibrating..."); flush();
443 i = ACCEL_CALIBRATE_SAMPLES;
445 cal_data_ring = ao_sample_data;
447 ao_sleep(&ao_sample_data);
448 while (i && cal_data_ring != ao_sample_data) {
449 accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]);
451 accel_along_total += (int32_t) ao_data_along(&ao_data_ring[cal_data_ring]);
452 accel_across_total += (int32_t) ao_data_across(&ao_data_ring[cal_data_ring]);
453 accel_through_total += (int32_t) ao_data_through(&ao_data_ring[cal_data_ring]);
455 cal_data_ring = ao_data_ring_next(cal_data_ring);
460 accel_cal_along = (int16_t) (accel_along_total >> ACCEL_CALIBRATE_SHIFT);
461 accel_cal_across = (int16_t) (accel_across_total >> ACCEL_CALIBRATE_SHIFT);
462 accel_cal_through = (int16_t) (accel_through_total >> ACCEL_CALIBRATE_SHIFT);
464 return (int16_t) (accel_total >> ACCEL_CALIBRATE_SHIFT);
468 ao_config_accel_calibrate_set(void)
473 int16_t accel_along_up = 0, accel_along_down = 0;
474 int16_t accel_across_up = 0, accel_across_down = 0;
475 int16_t accel_through_up = 0, accel_through_down = 0;
478 up = (int16_t) ao_cmd_decimal();
479 if (ao_cmd_status != ao_cmd_success)
481 down = (int16_t) ao_cmd_decimal();
482 auto_cal = (up == 0 && ao_cmd_status != ao_cmd_success);
483 ao_cmd_status = ao_cmd_success;
485 up = ao_config_accel_calibrate_auto("up");
487 accel_along_up = accel_cal_along;
488 accel_across_up = accel_cal_across;
489 accel_through_up = accel_cal_through;
491 down = ao_config_accel_calibrate_auto("down");
493 accel_along_down = accel_cal_along;
494 accel_across_down = accel_cal_across;
495 accel_through_down = accel_cal_through;
499 printf("Invalid accel: up (%d) down (%d)\n",
503 _ao_config_edit_start();
504 ao_config.accel_plus_g = up;
505 ao_config.accel_minus_g = down;
508 ao_config.accel_zero_along = (int16_t) ((accel_along_up + accel_along_down) / 2);
509 ao_config.accel_zero_across = (int16_t) ((accel_across_up + accel_across_down) / 2);
510 ao_config.accel_zero_through = (int16_t) ((accel_through_up + accel_through_down) / 2);
514 v = (int16_t) ao_cmd_decimal();
515 if (ao_cmd_status == ao_cmd_success) {
516 ao_config.accel_zero_along = v;
517 v = (int16_t) ao_cmd_decimal();
518 if (ao_cmd_status == ao_cmd_success) {
519 ao_config.accel_zero_across = v;
520 v = (int16_t) ao_cmd_decimal();
521 if (ao_cmd_status == ao_cmd_success)
522 ao_config.accel_zero_through = v;
527 _ao_config_edit_finish();
529 #endif /* HAS_ACCEL */
533 ao_config_apogee_delay_show(void)
535 printf("Apogee delay: %d seconds\n",
536 ao_config.apogee_delay);
540 ao_config_apogee_delay_set(void)
542 uint32_t r = ao_cmd_decimal();
543 if (ao_cmd_status != ao_cmd_success)
546 ao_cmd_status = ao_cmd_lex_error;
549 _ao_config_edit_start();
550 ao_config.apogee_delay = (uint8_t) r;
551 _ao_config_edit_finish();
555 ao_config_apogee_lockout_show(void)
557 printf ("Apogee lockout: %d seconds\n",
558 ao_config.apogee_lockout);
562 ao_config_apogee_lockout_set(void)
564 uint32_t r = ao_cmd_decimal();
565 if (ao_cmd_status != ao_cmd_success)
568 ao_cmd_status = ao_cmd_lex_error;
571 _ao_config_edit_start();
572 ao_config.apogee_lockout = (uint16_t) r;
573 _ao_config_edit_finish();
577 #endif /* HAS_FLIGHT */
581 ao_config_radio_cal_show(void)
583 printf("Radio cal: %ld\n", ao_config.radio_cal);
587 ao_config_radio_cal_set(void)
589 uint32_t r = ao_cmd_decimal();
590 if (ao_cmd_status != ao_cmd_success)
592 _ao_config_edit_start();
593 ao_config.radio_cal = r;
594 ao_config_set_radio();
595 _ao_config_edit_finish();
601 #ifndef HAS_TELEMETRY
602 #error Please define HAS_TELEMETRY
606 ao_config_radio_rate_show(void)
608 printf("Telemetry rate: %d\n", ao_config.radio_rate);
612 ao_config_radio_rate_set(void)
614 uint32_t r = ao_cmd_decimal();
615 if (ao_cmd_status != ao_cmd_success)
617 if (AO_RADIO_RATE_MAX < r) {
618 ao_cmd_status = ao_cmd_lex_error;
621 _ao_config_edit_start();
622 ao_config.radio_rate = (uint8_t) r;
623 _ao_config_edit_finish();
625 ao_telemetry_reset_interval();
628 ao_radio_recv_abort();
636 ao_config_log_show(void)
638 printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
639 #if FLIGHT_LOG_APPEND
640 printf("Log fixed: 1\n");
644 #if FLIGHT_LOG_APPEND && HAS_CONFIG_SAVE
646 ao_config_log_fix_append(void)
648 _ao_config_edit_start();
649 ao_config.flight_log_max = ao_storage_log_max;
650 _ao_config_edit_finish();
651 ao_mutex_get(&ao_config_mutex);
654 ao_mutex_put(&ao_config_mutex);
659 ao_config_log_set(void)
661 #if FLIGHT_LOG_APPEND
662 printf("Flight log fixed size %u kB\n", (unsigned) (ao_storage_log_max >> 10));
666 r = ao_cmd_decimal();
667 if (ao_cmd_status != ao_cmd_success)
670 if (ao_log_present()) {
671 if (r != ao_config.flight_log_max)
672 printf("Storage must be empty before changing log size\n");
675 if (r > ao_storage_log_max) {
676 printf("Flight log max %u kB\n", (unsigned) (ao_storage_log_max >> 10));
679 _ao_config_edit_start();
680 ao_config.flight_log_max = r & ~(ao_storage_block - 1);
681 _ao_config_edit_finish();
688 ao_config_ignite_mode_show(void)
690 printf("Ignite mode: %d\n", ao_config.ignite_mode);
694 ao_config_ignite_mode_set(void)
696 uint32_t r = ao_cmd_decimal();
697 if (ao_cmd_status != ao_cmd_success)
699 _ao_config_edit_start();
700 ao_config.ignite_mode = (uint8_t) r;
701 _ao_config_edit_finish();
707 ao_config_pad_orientation_show(void)
709 printf("Pad orientation: %d\n", ao_config.pad_orientation);
713 ao_config_pad_orientation_set(void)
715 uint8_t r = ao_cmd_decimal() & 1;
716 if (ao_cmd_status != ao_cmd_success)
718 _ao_config_edit_start();
719 if (ao_config.pad_orientation != r) {
721 t = ao_config.accel_plus_g;
722 ao_config.accel_plus_g = ao_data_accel_invert(ao_config.accel_minus_g);
723 ao_config.accel_minus_g = ao_data_accel_invert(t);
725 ao_config.pad_orientation = r;
726 _ao_config_edit_finish();
732 ao_config_radio_enable_show(void)
734 printf("Radio enable: %d\n", ao_config.radio_enable);
738 ao_config_radio_enable_set(void)
740 uint32_t r = ao_cmd_decimal();
741 if (ao_cmd_status != ao_cmd_success)
743 _ao_config_edit_start();
744 ao_config.radio_enable = r != 0;
745 _ao_config_edit_finish();
746 #if HAS_TELEMETRY && HAS_RADIO_RATE
747 ao_telemetry_reset_interval();
750 #endif /* HAS_RADIO */
754 uint8_t ao_config_aes_seq = 1;
757 ao_config_key_show(void)
761 for (i = 0; i < AO_AES_LEN; i++)
762 printf ("%02x", ao_config.aes_key[i]);
767 ao_config_key_set(void)
771 _ao_config_edit_start();
772 for (i = 0; i < AO_AES_LEN; i++) {
773 uint8_t b = ao_cmd_hexbyte();
774 if (ao_cmd_status != ao_cmd_success)
776 ao_config.aes_key[i] = b;
779 _ao_config_edit_finish();
786 ao_config_aprs_show(void)
788 printf ("APRS interval: %d\n", ao_config.aprs_interval);
792 ao_config_aprs_set(void)
794 uint32_t r = ao_cmd_decimal();
795 if (ao_cmd_status != ao_cmd_success)
797 _ao_config_edit_start();
798 ao_config.aprs_interval = (uint16_t) r;
799 _ao_config_edit_finish();
800 ao_telemetry_reset_interval();
804 ao_config_aprs_offset_show(void)
806 printf ("APRS offset: %d\n", ao_config.aprs_offset);
810 ao_config_aprs_offset_set(void)
812 uint32_t r = ao_cmd_decimal();
813 if (ao_cmd_status != ao_cmd_success)
815 _ao_config_edit_start();
816 ao_config.aprs_offset = (uint8_t) r;
817 _ao_config_edit_finish();
818 ao_telemetry_reset_interval();
821 #endif /* HAS_APRS */
826 ao_config_radio_amp_show(void)
828 printf ("Radio amp setting: %d\n", ao_config.radio_amp);
832 ao_config_radio_amp_set(void)
834 uint16_t r = ao_cmd_decimal();
835 if (ao_cmd_status != ao_cmd_success)
837 _ao_config_edit_start();
838 ao_config.radio_amp = r;
839 _ao_config_edit_finish();
847 ao_config_radio_power_show(void)
849 printf ("Radio power setting: %d\n", ao_config.radio_power);
853 ao_config_radio_power_set(void)
855 uint16_t r = ao_cmd_decimal();
856 if (ao_cmd_status != ao_cmd_success)
858 _ao_config_edit_start();
859 ao_config.radio_power = r;
860 _ao_config_edit_finish();
868 ao_config_radio_10mw_show(void)
870 printf ("Radio 10mw limit: %d\n", ao_config.radio_10mw);
874 ao_config_radio_10mw_set(void)
876 uint32_t r = ao_cmd_decimal();
877 if (ao_cmd_status != ao_cmd_success)
879 _ao_config_edit_start();
880 ao_config.radio_10mw = !!r;
881 _ao_config_edit_finish();
887 ao_config_report_feet_show(void)
889 printf ("Report in feet: %d\n", ao_config.report_feet);
893 ao_config_report_feet_set(void)
895 uint32_t r = ao_cmd_decimal();
896 if (ao_cmd_status != ao_cmd_success)
898 _ao_config_edit_start();
899 ao_config.report_feet = !!r;
900 _ao_config_edit_finish();
906 ao_config_beep_show(void)
908 printf ("Beeper setting: %d\n", ao_config.mid_beep);
912 ao_config_beep_set(void)
914 uint32_t r = ao_cmd_decimal();
915 if (ao_cmd_status != ao_cmd_success)
917 _ao_config_edit_start();
918 ao_config.mid_beep = (uint8_t) r;
919 _ao_config_edit_finish();
925 ao_config_tracker_show(void)
927 printf ("Tracker setting: %d %d\n",
928 ao_config.tracker_motion,
929 ao_config.tracker_interval);
933 ao_config_tracker_set(void)
937 m = (uint16_t) ao_cmd_decimal();
938 if (ao_cmd_status != ao_cmd_success)
940 i = (uint8_t) ao_cmd_decimal();
941 if (ao_cmd_status != ao_cmd_success)
943 _ao_config_edit_start();
944 ao_config.tracker_motion = m;
945 ao_config.tracker_interval = i;
946 _ao_config_edit_finish();
948 ao_telemetry_reset_interval();
951 #endif /* HAS_TRACKER */
955 ao_config_pyro_time_show(void)
957 printf ("Pyro time: %d\n", ao_config.pyro_time);
961 ao_config_pyro_time_set(void)
963 uint32_t r = ao_cmd_decimal();
964 if (ao_cmd_status != ao_cmd_success)
966 _ao_config_edit_start();
967 ao_config.pyro_time = (uint16_t) r;
968 _ao_config_edit_finish();
974 ao_config_aprs_ssid_show(void)
976 printf ("APRS SSID: %d\n",
977 ao_config.aprs_ssid);
981 ao_config_aprs_ssid_set(void)
983 uint32_t r = ao_cmd_decimal();
984 if (ao_cmd_status != ao_cmd_success)
987 ao_cmd_status = ao_cmd_lex_error;
990 _ao_config_edit_start();
991 ao_config.aprs_ssid = (uint8_t) r;
992 _ao_config_edit_finish();
996 ao_config_aprs_format_set(void)
998 uint32_t r = ao_cmd_decimal();
999 if (ao_cmd_status != ao_cmd_success)
1001 _ao_config_edit_start();
1002 ao_config.aprs_format = r != 0;
1003 _ao_config_edit_finish();
1007 ao_config_aprs_format_show(void)
1009 printf ("APRS format: %d\n", ao_config.aprs_format);
1011 #endif /* HAS_APRS */
1013 #if HAS_FIXED_PAD_BOX
1015 ao_config_pad_box_show(void)
1017 printf ("Pad box: %d\n", ao_config.pad_box);
1021 ao_config_pad_box_set(void)
1023 uint32_t r = ao_cmd_decimal();
1024 if (ao_cmd_status != ao_cmd_success)
1026 _ao_config_edit_start();
1027 ao_config.pad_box = (uint8_t) r;
1028 _ao_config_edit_finish();
1032 ao_config_pad_idle_show(void)
1034 printf ("Idle timeout: %d\n", ao_config.pad_idle);
1038 ao_config_pad_idle_set(void)
1040 uint32_t r = ao_cmd_decimal();
1041 if (ao_cmd_status != ao_cmd_success)
1043 _ao_config_edit_start();
1044 ao_config.pad_idle = (uint8_t) r;
1045 _ao_config_edit_finish();
1049 struct ao_config_var {
1056 ao_config_help(void);
1059 ao_config_show(void);
1063 ao_config_save(void);
1066 const struct ao_config_var ao_config_vars[] = {
1067 #if HAS_FLIGHT && HAS_BARO
1068 { "m <meters>\0Main deploy (m)",
1069 ao_config_main_deploy_set, ao_config_main_deploy_show, },
1070 { "d <delay>\0Apogee delay (s)",
1071 ao_config_apogee_delay_set, ao_config_apogee_delay_show },
1072 { "L <seconds>\0Apogee detect lockout (s)",
1073 ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, },
1074 #endif /* HAS_FLIGHT */
1076 { "F <freq>\0Frequency (kHz)",
1077 ao_config_frequency_set, ao_config_frequency_show },
1078 #if HAS_RADIO_FORWARD
1079 { "R <freq>\0Repeater output frequency (kHz)",
1080 ao_config_send_frequency_set, ao_config_send_frequency_show },
1082 { "c <call>\0Callsign (8 char max)",
1083 ao_config_callsign_set, ao_config_callsign_show },
1084 { "e <0 disable, 1 enable>\0Enable telemetry and RDF",
1085 ao_config_radio_enable_set, ao_config_radio_enable_show },
1086 { "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
1087 ao_config_radio_cal_set, ao_config_radio_cal_show },
1089 { "T <rate>\0Telemetry rate (0=38.4, 1=9.6, 2=2.4)",
1090 ao_config_radio_rate_set, ao_config_radio_rate_show },
1093 { "p <setting>\0Radio power setting (0-255)",
1094 ao_config_radio_power_set, ao_config_radio_power_show },
1097 { "d <setting>\0Radio amplifier setting (0-3)",
1098 ao_config_radio_amp_set, ao_config_radio_amp_show },
1100 #endif /* HAS_RADIO */
1102 { "a <+g> <-g>\0Accel calib (0 for auto)",
1103 ao_config_accel_calibrate_set,ao_config_accel_calibrate_show },
1104 { "o <0 antenna up, 1 antenna down>\0Pad orientation",
1105 ao_config_pad_orientation_set,ao_config_pad_orientation_show },
1106 #endif /* HAS_ACCEL */
1108 { "l <size>\0Flight log size (kB)",
1109 ao_config_log_set, ao_config_log_show },
1112 { "i <0 dual, 1 apogee, 2 main, 3 booster>\0Igniter mode",
1113 ao_config_ignite_mode_set, ao_config_ignite_mode_show },
1116 { "k <32 hex digits>\0AES encryption key",
1117 ao_config_key_set, ao_config_key_show },
1120 { "P <n,?>\0Pyro channels",
1121 ao_pyro_set, ao_pyro_show },
1122 { "I <ticks>\0Pyro firing time",
1123 ao_config_pyro_time_set, ao_config_pyro_time_show },
1126 { "A <secs>\0APRS packet interval (0 disable)",
1127 ao_config_aprs_set, ao_config_aprs_show },
1130 { "b <val>\0Beeper tone (freq = 1/2 (24e6/32) / beep",
1131 ao_config_beep_set, ao_config_beep_show },
1134 { "t <motion> <interval>\0Tracker configuration",
1135 ao_config_tracker_set, ao_config_tracker_show },
1138 { "S <ssid>\0Set APRS SSID (0-15)",
1139 ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
1140 { "C <0 compressed, 1 uncompressed>\0APRS format",
1141 ao_config_aprs_format_set, ao_config_aprs_format_show },
1142 { "O <aprs-offset>\0APRS Offset from top of minute",
1143 ao_config_aprs_offset_set, ao_config_aprs_offset_show },
1145 #if HAS_FIXED_PAD_BOX
1146 { "B <box>\0Set pad box (1-99)",
1147 ao_config_pad_box_set, ao_config_pad_box_show },
1148 { "i <seconds>\0Set idle timeout (0 disable)",
1149 ao_config_pad_idle_set, ao_config_pad_idle_show },
1152 { "p <0 no limit, 1 limit>\0Limit radio power to 10mW",
1153 ao_config_radio_10mw_set, ao_config_radio_10mw_show },
1155 { "u <0 meters, 1 feet>\0Units to report height after landing",
1156 ao_config_report_feet_set, ao_config_report_feet_show },
1158 ao_config_show, 0 },
1160 { "w\0Write to eeprom",
1161 ao_config_save, 0 },
1164 ao_config_help, 0 },
1177 for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
1178 if (ao_config_vars[cmd].str[0] == c) {
1179 (*ao_config_vars[cmd].set)();
1182 ao_cmd_status = ao_cmd_syntax_error;
1186 ao_config_help(void)
1189 for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
1190 printf("%-20s %s\n",
1191 ao_config_vars[cmd].str,
1192 ao_config_vars[cmd].str+1+
1193 strlen(ao_config_vars[cmd].str));
1197 ao_config_show(void)
1201 printf("Config version: %d.%d\n",
1202 ao_config.major, ao_config.minor);
1203 for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
1204 if (ao_config_vars[cmd].show)
1205 (*ao_config_vars[cmd].show)();
1213 ao_config_save(void)
1216 ao_mutex_get(&ao_config_mutex);
1217 if (ao_config_dirty) {
1219 ao_config_dirty = 0;
1222 ao_mutex_put(&ao_config_mutex);
1226 puts("Nothing to save");
1230 const struct ao_cmds ao_config_cmds[] = {
1231 { ao_config_set, "c <var> <value>\0Set config (? for help, s to show)" },
1236 ao_config_init(void)
1238 ao_cmd_register(&ao_config_cmds[0]);