AC_PREREQ(2.57)
AC_INIT([altos], 1.3.2.1)
-AC_CONFIG_SRCDIR([src/core/ao.h])
+AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
# AltOS build
#
#
-vpath % ..:../core:../product:../drivers:../avr
+vpath % ..:../kernel:../product:../drivers:../avr
vpath make-altitude ..
vpath make-kalman ..
vpath kalman.5c ../kalman
MCU=atmega32u4
PRODUCT_DEF=-DAVR_DEMO
IDPRODUCT=0x000a
-CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I..
+CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../kernel -I..
CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues
NICKLE=nickle
CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE)
-CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../drivers -I../product
+CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../kernel -I../cc1111 -I../drivers -I../product
CODESIZE ?= 0x8000
+++ /dev/null
-/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/
-#define NALT 129
-#define ALT_FRAC_BITS 8
- 15835, /* 10.56 kPa 0.000% */
- 15332, /* 11.42 kPa 0.781% */
- 14868, /* 12.29 kPa 1.563% */
- 14435, /* 13.16 kPa 2.344% */
- 14030, /* 14.02 kPa 3.125% */
- 13649, /* 14.90 kPa 3.906% */
- 13290, /* 15.76 kPa 4.688% */
- 12950, /* 16.63 kPa 5.469% */
- 12627, /* 17.50 kPa 6.250% */
- 12320, /* 18.37 kPa 7.031% */
- 12027, /* 19.24 kPa 7.813% */
- 11747, /* 20.10 kPa 8.594% */
- 11479, /* 20.97 kPa 9.375% */
- 11222, /* 21.84 kPa 10.156% */
- 10975, /* 22.71 kPa 10.938% */
- 10736, /* 23.58 kPa 11.719% */
- 10504, /* 24.44 kPa 12.500% */
- 10278, /* 25.31 kPa 13.281% */
- 10059, /* 26.18 kPa 14.063% */
- 9846, /* 27.05 kPa 14.844% */
- 9638, /* 27.91 kPa 15.625% */
- 9435, /* 28.78 kPa 16.406% */
- 9237, /* 29.65 kPa 17.188% */
- 9044, /* 30.52 kPa 17.969% */
- 8855, /* 31.39 kPa 18.750% */
- 8670, /* 32.26 kPa 19.531% */
- 8490, /* 33.13 kPa 20.313% */
- 8313, /* 33.99 kPa 21.094% */
- 8140, /* 34.86 kPa 21.875% */
- 7970, /* 35.73 kPa 22.656% */
- 7803, /* 36.60 kPa 23.438% */
- 7640, /* 37.47 kPa 24.219% */
- 7480, /* 38.33 kPa 25.000% */
- 7322, /* 39.20 kPa 25.781% */
- 7168, /* 40.07 kPa 26.563% */
- 7016, /* 40.94 kPa 27.344% */
- 6867, /* 41.80 kPa 28.125% */
- 6720, /* 42.67 kPa 28.906% */
- 6575, /* 43.54 kPa 29.688% */
- 6433, /* 44.41 kPa 30.469% */
- 6294, /* 45.28 kPa 31.250% */
- 6156, /* 46.15 kPa 32.031% */
- 6020, /* 47.01 kPa 32.813% */
- 5887, /* 47.88 kPa 33.594% */
- 5755, /* 48.75 kPa 34.375% */
- 5625, /* 49.62 kPa 35.156% */
- 5497, /* 50.49 kPa 35.938% */
- 5371, /* 51.35 kPa 36.719% */
- 5247, /* 52.22 kPa 37.500% */
- 5124, /* 53.09 kPa 38.281% */
- 5003, /* 53.96 kPa 39.063% */
- 4883, /* 54.83 kPa 39.844% */
- 4765, /* 55.69 kPa 40.625% */
- 4648, /* 56.56 kPa 41.406% */
- 4533, /* 57.43 kPa 42.188% */
- 4419, /* 58.30 kPa 42.969% */
- 4307, /* 59.17 kPa 43.750% */
- 4196, /* 60.03 kPa 44.531% */
- 4086, /* 60.90 kPa 45.313% */
- 3977, /* 61.77 kPa 46.094% */
- 3870, /* 62.63 kPa 46.875% */
- 3764, /* 63.51 kPa 47.656% */
- 3659, /* 64.38 kPa 48.438% */
- 3555, /* 65.24 kPa 49.219% */
- 3453, /* 66.11 kPa 50.000% */
- 3351, /* 66.98 kPa 50.781% */
- 3250, /* 67.85 kPa 51.563% */
- 3151, /* 68.72 kPa 52.344% */
- 3052, /* 69.58 kPa 53.125% */
- 2955, /* 70.45 kPa 53.906% */
- 2858, /* 71.32 kPa 54.688% */
- 2763, /* 72.19 kPa 55.469% */
- 2668, /* 73.06 kPa 56.250% */
- 2574, /* 73.92 kPa 57.031% */
- 2482, /* 74.79 kPa 57.813% */
- 2390, /* 75.66 kPa 58.594% */
- 2298, /* 76.52 kPa 59.375% */
- 2208, /* 77.40 kPa 60.156% */
- 2119, /* 78.26 kPa 60.938% */
- 2030, /* 79.13 kPa 61.719% */
- 1942, /* 80.00 kPa 62.500% */
- 1855, /* 80.87 kPa 63.281% */
- 1769, /* 81.74 kPa 64.063% */
- 1683, /* 82.60 kPa 64.844% */
- 1598, /* 83.47 kPa 65.625% */
- 1514, /* 84.34 kPa 66.406% */
- 1430, /* 85.21 kPa 67.188% */
- 1347, /* 86.08 kPa 67.969% */
- 1265, /* 86.94 kPa 68.750% */
- 1184, /* 87.81 kPa 69.531% */
- 1103, /* 88.68 kPa 70.313% */
- 1023, /* 89.55 kPa 71.094% */
- 943, /* 90.41 kPa 71.875% */
- 864, /* 91.28 kPa 72.656% */
- 786, /* 92.15 kPa 73.438% */
- 708, /* 93.02 kPa 74.219% */
- 631, /* 93.89 kPa 75.000% */
- 554, /* 94.76 kPa 75.781% */
- 478, /* 95.63 kPa 76.563% */
- 403, /* 96.49 kPa 77.344% */
- 328, /* 97.36 kPa 78.125% */
- 254, /* 98.23 kPa 78.906% */
- 180, /* 99.10 kPa 79.688% */
- 106, /* 99.97 kPa 80.469% */
- 34, /* 100.83 kPa 81.250% */
- -39, /* 101.70 kPa 82.031% */
- -111, /* 102.57 kPa 82.813% */
- -182, /* 103.44 kPa 83.594% */
- -253, /* 104.30 kPa 84.375% */
- -323, /* 105.17 kPa 85.156% */
- -393, /* 106.04 kPa 85.938% */
- -462, /* 106.91 kPa 86.719% */
- -531, /* 107.78 kPa 87.500% */
- -600, /* 108.65 kPa 88.281% */
- -668, /* 109.51 kPa 89.063% */
- -736, /* 110.38 kPa 89.844% */
- -803, /* 111.25 kPa 90.625% */
- -870, /* 112.12 kPa 91.406% */
- -936, /* 112.99 kPa 92.188% */
- -1002, /* 113.85 kPa 92.969% */
- -1068, /* 114.72 kPa 93.750% */
- -1133, /* 115.59 kPa 94.531% */
- -1198, /* 116.46 kPa 95.313% */
- -1262, /* 117.33 kPa 96.094% */
- -1326, /* 118.19 kPa 96.875% */
- -1389, /* 119.06 kPa 97.656% */
- -1453, /* 119.93 kPa 98.438% */
- -1516, /* 120.80 kPa 99.219% */
- -1578, /* 121.67 kPa 100.000% */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_H_
-#define _AO_H_
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <ao_pins.h>
-#include <ao_arch.h>
-
-#define TRUE 1
-#define FALSE 0
-
-/* Convert a __data pointer into an __xdata pointer */
-#ifndef DATA_TO_XDATA
-#define DATA_TO_XDATA(a) (a)
-#endif
-#ifndef PDATA_TO_XDATA
-#define PDATA_TO_XDATA(a) (a)
-#endif
-#ifndef CODE_TO_XDATA
-#define CODE_TO_XDATA(a) (a)
-#endif
-
-#ifndef HAS_TASK
-#define HAS_TASK 1
-#endif
-
-#ifndef AO_PORT_TYPE
-#define AO_PORT_TYPE uint8_t
-#endif
-
-typedef AO_PORT_TYPE ao_port_t;
-
-#if HAS_TASK
-#include <ao_task.h>
-#else
-#include <ao_notask.h>
-#endif
-
-/*
- * ao_panic.c
- */
-
-#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */
-#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */
-#define AO_PANIC_MUTEX 3 /* Mis-using mutex API */
-#define AO_PANIC_EE 4 /* Mis-using eeprom API */
-#define AO_PANIC_LOG 5 /* Failing to read/write log data */
-#define AO_PANIC_CMD 6 /* Too many command sets registered */
-#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */
-#define AO_PANIC_REBOOT 8 /* Reboot failed */
-#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */
-#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */
-#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */
-#define AO_PANIC_STACK 12 /* Stack overflow */
-#define AO_PANIC_SPI 13 /* SPI communication failure */
-#define AO_PANIC_CRASH 14 /* Processor crashed */
-#define AO_PANIC_BUFIO 15 /* Mis-using bufio API */
-#define AO_PANIC_EXTI 16 /* Mis-using exti API */
-#define AO_PANIC_FAST_TIMER 17 /* Mis-using fast timer API */
-#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */
-#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */
-#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */
-#define AO_PANIC_SELF_TEST_MS5607 0x40 | 4 /* Self test failure */
-
-/* Stop the operating system, beeping and blinking the reason */
-void
-ao_panic(uint8_t reason);
-
-/*
- * ao_timer.c
- */
-
-#ifndef AO_TICK_TYPE
-#define AO_TICK_TYPE uint16_t
-#define AO_TICK_SIGNED int16_t
-#endif
-
-extern volatile __data AO_TICK_TYPE ao_tick_count;
-
-/* Our timer runs at 100Hz */
-#ifndef AO_HERTZ
-#define AO_HERTZ 100
-#endif
-#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ))
-#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ)
-
-/* Returns the current time in ticks */
-AO_TICK_TYPE
-ao_time(void);
-
-/* Suspend the current task until ticks time has passed */
-void
-ao_delay(uint16_t ticks);
-
-/* Set the ADC interval */
-void
-ao_timer_set_adc_interval(uint8_t interval);
-
-/* Timer interrupt */
-void
-ao_timer_isr(void) ao_arch_interrupt(9);
-
-/* Initialize the timer */
-void
-ao_timer_init(void);
-
-/* Initialize the hardware clock. Must be called first */
-void
-ao_clock_init(void);
-
-/*
- * ao_mutex.c
- */
-
-#ifndef ao_mutex_get
-void
-ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
-
-void
-ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant;
-#endif
-
-/*
- * ao_cmd.c
- */
-
-enum ao_cmd_status {
- ao_cmd_success = 0,
- ao_cmd_lex_error = 1,
- ao_cmd_syntax_error = 2,
-};
-
-extern __pdata uint16_t ao_cmd_lex_i;
-extern __pdata uint32_t ao_cmd_lex_u32;
-extern __pdata char ao_cmd_lex_c;
-extern __pdata enum ao_cmd_status ao_cmd_status;
-
-void
-ao_put_string(__code char *s);
-
-void
-ao_cmd_lex(void);
-
-void
-ao_cmd_put8(uint8_t v);
-
-void
-ao_cmd_put16(uint16_t v);
-
-uint8_t
-ao_cmd_is_white(void);
-
-void
-ao_cmd_white(void);
-
-int8_t
-ao_cmd_hexchar(char c);
-
-void
-ao_cmd_hexbyte(void);
-
-void
-ao_cmd_hex(void);
-
-void
-ao_cmd_decimal(void) __reentrant;
-
-/* Read a single hex nibble off stdin. */
-uint8_t
-ao_getnibble(void);
-
-uint8_t
-ao_match_word(__code char *word);
-
-struct ao_cmds {
- void (*func)(void);
- __code char *help;
-};
-
-void
-ao_cmd_register(const __code struct ao_cmds *cmds);
-
-void
-ao_cmd_init(void);
-
-#if HAS_CMD_FILTER
-/*
- * Provided by an external module to filter raw command lines
- */
-uint8_t
-ao_cmd_filter(void);
-#endif
-
-/*
- * Various drivers
- */
-#if HAS_ADC
-#include <ao_adc.h>
-#endif
-
-#if HAS_BEEP
-#include <ao_beep.h>
-#endif
-
-#if LEDS_AVAILABLE
-#include <ao_led.h>
-#endif
-
-#if HAS_USB
-#include <ao_usb.h>
-#endif
-
-#if HAS_EEPROM
-#include <ao_storage.h>
-#endif
-
-#if HAS_LOG
-#include <ao_log.h>
-#endif
-
-#if HAS_FLIGHT
-#include <ao_flight.h>
-#include <ao_sample.h>
-#endif
-
-/*
- * ao_report.c
- */
-
-#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5)
-#define AO_RDF_LENGTH_MS 500
-#define AO_RDF_CONTINUITY_MS 32
-#define AO_RDF_CONTINUITY_PAUSE 96
-#define AO_RDF_CONTINUITY_TOTAL ((AO_RDF_CONTINUITY_PAUSE + AO_RDF_CONTINUITY_MS) * 3 + AO_RDF_CONTINUITY_PAUSE)
-
-/* This assumes that we're generating a 1kHz tone, which
- * modulates the carrier at 2kbps, or 250kBps
- */
-#define AO_MS_TO_RDF_LEN(ms) ((ms) / 4)
-
-#define AO_RADIO_RDF_LEN AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)
-#define AO_RADIO_CONT_TONE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_MS)
-#define AO_RADIO_CONT_PAUSE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_PAUSE)
-#define AO_RADIO_CONT_TOTAL_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_TOTAL)
-
-/* returns a value 0-3 to indicate igniter continuity */
-uint8_t
-ao_report_igniter(void);
-
-void
-ao_report_init(void);
-
-/*
- * ao_convert.c
- *
- * Given raw data, convert to SI units
- */
-
-/* pressure from the sensor to altitude in meters */
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant;
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant;
-
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant;
-
-/*
- * ao_convert_pa.c
- *
- * Convert between pressure in Pa and altitude in meters
- */
-
-#include <ao_data.h>
-
-alt_t
-ao_pa_to_altitude(int32_t pa);
-
-int32_t
-ao_altitude_to_pa(alt_t alt);
-
-#if HAS_DBG
-#include <ao_dbg.h>
-#endif
-
-#if HAS_SERIAL_0 || HAS_SERIAL_1 || HAS_SERIAL_2 || HAS_SERIAL_3
-#include <ao_serial.h>
-#endif
-
-/*
- * ao_convert_volt.c
- *
- * Convert ADC readings to decivolts
- */
-
-int16_t
-ao_battery_decivolt(int16_t adc);
-
-int16_t
-ao_ignite_decivolt(int16_t adc);
-
-/*
- * ao_spi_slave.c
- */
-
-uint8_t
-ao_spi_slave_recv(void *buf, uint16_t len);
-
-void
-ao_spi_slave_send(void *buf, uint16_t len);
-
-void
-ao_spi_slave_init(void);
-
-/* This must be defined by the product; it will get called when chip
- * select goes low, at which point it should use ao_spi_read and
- * ao_spi_write to deal with the request
- */
-
-void
-ao_spi_slave(void);
-
-#include <ao_telemetry.h>
-/*
- * ao_gps.c
- */
-
-#define AO_GPS_NUM_SAT_MASK (0xf << 0)
-#define AO_GPS_NUM_SAT_SHIFT (0)
-
-#define AO_GPS_VALID (1 << 4)
-#define AO_GPS_RUNNING (1 << 5)
-#define AO_GPS_DATE_VALID (1 << 6)
-#define AO_GPS_COURSE_VALID (1 << 7)
-
-#define AO_GPS_NEW_DATA 1
-#define AO_GPS_NEW_TRACKING 2
-
-extern __xdata uint8_t ao_gps_new;
-extern __pdata uint16_t ao_gps_tick;
-extern __xdata uint8_t ao_gps_mutex;
-extern __xdata struct ao_telemetry_location ao_gps_data;
-extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data;
-
-struct ao_gps_orig {
- uint8_t year;
- uint8_t month;
- uint8_t day;
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
- uint8_t flags;
- int32_t latitude; /* degrees * 10⁷ */
- int32_t longitude; /* degrees * 10⁷ */
- int16_t altitude; /* m */
- uint16_t ground_speed; /* cm/s */
- uint8_t course; /* degrees / 2 */
- uint8_t hdop; /* * 5 */
- int16_t climb_rate; /* cm/s */
- uint16_t h_error; /* m */
- uint16_t v_error; /* m */
-};
-
-struct ao_gps_sat_orig {
- uint8_t svid;
- uint8_t c_n_1;
-};
-
-#define AO_MAX_GPS_TRACKING 12
-
-struct ao_gps_tracking_orig {
- uint8_t channels;
- struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING];
-};
-
-void
-ao_gps(void);
-
-void
-ao_gps_print(__xdata struct ao_gps_orig *gps_data);
-
-void
-ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data);
-
-void
-ao_gps_show(void) __reentrant;
-
-void
-ao_gps_init(void);
-
-/*
- * ao_gps_report.c
- */
-
-void
-ao_gps_report(void);
-
-void
-ao_gps_report_init(void);
-
-/*
- * ao_gps_report_mega.c
- */
-
-void
-ao_gps_report_mega(void);
-
-void
-ao_gps_report_mega_init(void);
-
-/*
- * ao_telemetry_orig.c
- */
-
-#if LEGACY_MONITOR
-struct ao_adc_orig {
- uint16_t tick; /* tick when the sample was read */
- int16_t accel; /* accelerometer */
- int16_t pres; /* pressure sensor */
- int16_t temp; /* temperature sensor */
- int16_t v_batt; /* battery voltage */
- int16_t sense_d; /* drogue continuity sense */
- int16_t sense_m; /* main continuity sense */
-};
-
-struct ao_telemetry_orig {
- uint16_t serial;
- uint16_t flight;
- uint8_t flight_state;
- int16_t accel;
- int16_t ground_accel;
- union {
- struct {
- int16_t speed;
- int16_t unused;
- } k;
- int32_t flight_vel;
- } u;
- int16_t height;
- int16_t ground_pres;
- int16_t accel_plus_g;
- int16_t accel_minus_g;
- struct ao_adc_orig adc;
- struct ao_gps_orig gps;
- char callsign[AO_MAX_CALLSIGN];
- struct ao_gps_tracking_orig gps_tracking;
-};
-
-struct ao_telemetry_tiny {
- uint16_t serial;
- uint16_t flight;
- uint8_t flight_state;
- int16_t height; /* AGL in meters */
- int16_t speed; /* in m/s * 16 */
- int16_t accel; /* in m/s² * 16 */
- int16_t ground_pres; /* sensor units */
- struct ao_adc adc; /* raw ADC readings */
- char callsign[AO_MAX_CALLSIGN];
-};
-
-struct ao_telemetry_orig_recv {
- struct ao_telemetry_orig telemetry_orig;
- int8_t rssi;
- uint8_t status;
-};
-
-struct ao_telemetry_tiny_recv {
- struct ao_telemetry_tiny telemetry_tiny;
- int8_t rssi;
- uint8_t status;
-};
-
-#endif /* LEGACY_MONITOR */
-
-/* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method
- * for reporting RSSI. So, now we use these values everywhere
- */
-#define AO_RSSI_FROM_RADIO(radio) ((int16_t) ((int8_t) (radio) >> 1) - 74)
-#define AO_RADIO_FROM_RSSI(rssi) (((int8_t) (rssi) + 74) << 1)
-
-/*
- * ao_radio_recv tacks on rssi and status bytes
- */
-
-struct ao_telemetry_raw_recv {
- uint8_t packet[AO_MAX_TELEMETRY + 2];
-};
-
-/* Set delay between telemetry reports (0 to disable) */
-
-#ifdef AO_SEND_ALL_BARO
-#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(100)
-#else
-#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000)
-#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000)
-#endif
-
-void
-ao_telemetry_set_interval(uint16_t interval);
-
-void
-ao_rdf_set(uint8_t rdf);
-
-void
-ao_telemetry_init(void);
-
-void
-ao_telemetry_orig_init(void);
-
-void
-ao_telemetry_tiny_init(void);
-
-/*
- * ao_radio.c
- */
-
-extern __xdata uint8_t ao_radio_dma;
-
-extern __xdata int8_t ao_radio_rssi;
-
-#ifdef PKT_APPEND_STATUS_1_CRC_OK
-#define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK
-#else
-#include <ao_fec.h>
-#define AO_RADIO_STATUS_CRC_OK AO_FEC_DECODE_CRC_OK
-#endif
-
-#ifndef HAS_RADIO_RECV
-#define HAS_RADIO_RECV HAS_RADIO
-#endif
-#ifndef HAS_RADIO_XMIT
-#define HAS_RADIO_XMIT HAS_RADIO
-#endif
-
-void
-ao_radio_general_isr(void) ao_arch_interrupt(16);
-
-#if HAS_RADIO_XMIT
-void
-ao_radio_send(const __xdata void *d, uint8_t size) __reentrant;
-#endif
-
-#if HAS_RADIO_RECV
-uint8_t
-ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) __reentrant;
-
-void
-ao_radio_recv_abort(void);
-#endif
-
-void
-ao_radio_test(uint8_t on);
-
-typedef int16_t (*ao_radio_fill_func)(uint8_t *buffer, int16_t len);
-
-void
-ao_radio_send_aprs(ao_radio_fill_func fill);
-
-/*
- * ao_radio_pa
- */
-
-#if HAS_RADIO_AMP
-void
-ao_radio_pa_on(void);
-
-void
-ao_radio_pa_off(void);
-
-void
-ao_radio_pa_init(void);
-#else
-#define ao_radio_pa_on()
-#define ao_radio_pa_off()
-#define ao_radio_pa_init()
-#endif
-
-/*
- * Compute the packet length as follows:
- *
- * 2000 bps (for a 1kHz tone)
- * so, for 'ms' milliseconds, we need
- * 2 * ms bits, or ms / 4 bytes
- */
-
-void
-ao_radio_rdf(void);
-
-void
-ao_radio_continuity(uint8_t c);
-
-void
-ao_radio_rdf_abort(void);
-
-void
-ao_radio_init(void);
-
-/*
- * ao_monitor.c
- */
-
-#if HAS_MONITOR
-
-extern const char const * const ao_state_names[];
-
-#define AO_MONITOR_RING 8
-
-union ao_monitor {
- struct ao_telemetry_raw_recv raw;
- struct ao_telemetry_all_recv all;
-#if LEGACY_MONITOR
- struct ao_telemetry_orig_recv orig;
- struct ao_telemetry_tiny_recv tiny;
-#endif
-};
-
-extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING];
-
-#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1))
-
-extern __data uint8_t ao_monitoring;
-extern __data uint8_t ao_monitor_head;
-
-void
-ao_monitor(void);
-
-#define AO_MONITORING_OFF 0
-#define AO_MONITORING_ORIG 1
-
-void
-ao_monitor_set(uint8_t monitoring);
-
-void
-ao_monitor_disable(void);
-
-void
-ao_monitor_enable(void);
-
-void
-ao_monitor_init(void) __reentrant;
-
-#endif
-
-/*
- * ao_stdio.c
- */
-
-#define AO_READ_AGAIN (-1)
-
-struct ao_stdio {
- int (*_pollchar)(void); /* Called with interrupts blocked */
- void (*putchar)(char c) __reentrant;
- void (*flush)(void);
- uint8_t echo;
-};
-
-extern __xdata struct ao_stdio ao_stdios[];
-extern __pdata int8_t ao_cur_stdio;
-extern __pdata int8_t ao_num_stdios;
-
-void
-flush(void);
-
-extern __xdata uint8_t ao_stdin_ready;
-
-uint8_t
-ao_echo(void);
-
-int8_t
-ao_add_stdio(int (*pollchar)(void),
- void (*putchar)(char) __reentrant,
- void (*flush)(void)) __reentrant;
-
-/*
- * ao_ignite.c
- */
-
-enum ao_igniter {
- ao_igniter_drogue = 0,
- ao_igniter_main = 1
-};
-
-void
-ao_ignite(enum ao_igniter igniter);
-
-enum ao_igniter_status {
- ao_igniter_unknown, /* unknown status (ambiguous voltage) */
- ao_igniter_ready, /* continuity detected */
- ao_igniter_active, /* igniter firing */
- ao_igniter_open, /* open circuit detected */
-};
-
-struct ao_ignition {
- uint8_t request;
- uint8_t fired;
- uint8_t firing;
-};
-
-extern __code char * __code ao_igniter_status_names[];
-
-extern __xdata struct ao_ignition ao_ignition[2];
-
-enum ao_igniter_status
-ao_igniter_status(enum ao_igniter igniter);
-
-extern __pdata uint8_t ao_igniter_present;
-
-void
-ao_ignite_set_pins(void);
-
-void
-ao_igniter_init(void);
-
-/*
- * ao_config.c
- */
-
-#if AO_PYRO_NUM
-#include <ao_pyro.h>
-#endif
-
-#if HAS_FORCE_FREQ
-/*
- * Set this to force the frequency to 434.550MHz
- */
-extern __xdata uint8_t ao_force_freq;
-#endif
-
-#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 15
-
-#define AO_AES_LEN 16
-
-extern __xdata uint8_t ao_config_aes_seq;
-
-struct ao_config {
- uint8_t major;
- uint8_t minor;
- uint16_t main_deploy;
- int16_t accel_plus_g; /* changed for minor version 2 */
- uint8_t _legacy_radio_channel;
- char callsign[AO_MAX_CALLSIGN + 1];
- uint8_t apogee_delay; /* minor version 1 */
- int16_t accel_minus_g; /* minor version 2 */
- uint32_t radio_cal; /* minor version 3 */
- uint32_t flight_log_max; /* minor version 4 */
- uint8_t ignite_mode; /* minor version 5 */
- uint8_t pad_orientation; /* minor version 6 */
- uint32_t radio_setting; /* minor version 7 */
- uint8_t radio_enable; /* minor version 8 */
- uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */
- uint32_t frequency; /* minor version 10 */
- uint16_t apogee_lockout; /* minor version 11 */
-#if AO_PYRO_NUM
- struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */
-#endif
- uint16_t aprs_interval; /* minor version 13 */
-#if HAS_RADIO_POWER
- uint8_t radio_power; /* minor version 14 */
-#endif
-#if HAS_RADIO_AMP
- uint8_t radio_amp; /* minor version 14 */
-#endif
-#if HAS_GYRO
- int16_t accel_zero_along; /* minor version 15 */
- int16_t accel_zero_across; /* minor version 15 */
- int16_t accel_zero_through; /* minor version 15 */
-#endif
-};
-
-#define AO_IGNITE_MODE_DUAL 0
-#define AO_IGNITE_MODE_APOGEE 1
-#define AO_IGNITE_MODE_MAIN 2
-
-#define AO_RADIO_ENABLE_CORE 1
-#define AO_RADIO_DISABLE_TELEMETRY 2
-#define AO_RADIO_DISABLE_RDF 4
-
-#define AO_PAD_ORIENTATION_ANTENNA_UP 0
-#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1
-
-extern __xdata struct ao_config ao_config;
-
-#define AO_CONFIG_MAX_SIZE 128
-
-void
-_ao_config_edit_start(void);
-
-void
-_ao_config_edit_finish(void);
-
-void
-ao_config_get(void);
-
-void
-ao_config_put(void);
-
-void
-ao_config_set_radio(void);
-
-void
-ao_config_init(void);
-
-/*
- * ao_rssi.c
- */
-
-void
-ao_rssi_set(int rssi_value);
-
-void
-ao_rssi_init(uint8_t rssi_led);
-
-/*
- * ao_product.c
- *
- * values which need to be defined for
- * each instance of a product
- */
-
-extern const char ao_version[];
-extern const char ao_manufacturer[];
-extern const char ao_product[];
-
-/*
- * Fifos
- */
-
-#define AO_FIFO_SIZE 32
-
-struct ao_fifo {
- uint8_t insert;
- uint8_t remove;
- char fifo[AO_FIFO_SIZE];
-};
-
-#define ao_fifo_insert(f,c) do { \
- (f).fifo[(f).insert] = (c); \
- (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \
-} while(0)
-
-#define ao_fifo_remove(f,c) do {\
- c = (f).fifo[(f).remove]; \
- (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \
-} while(0)
-
-#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
-#define ao_fifo_empty(f) ((f).insert == (f).remove)
-
-#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE
-#include <ao_packet.h>
-#endif
-
-#if HAS_BTM
-#include <ao_btm.h>
-#endif
-
-#if HAS_COMPANION
-#include <ao_companion.h>
-#endif
-
-#if HAS_LCD
-#include <ao_lcd.h>
-#endif
-
-#if HAS_AES
-#include <ao_aes.h>
-#endif
-
-/* ao_launch.c */
-
-struct ao_launch_command {
- uint16_t tick;
- uint16_t serial;
- uint8_t cmd;
- uint8_t channel;
- uint16_t unused;
-};
-
-#define AO_LAUNCH_QUERY 1
-
-struct ao_launch_query {
- uint16_t tick;
- uint16_t serial;
- uint8_t channel;
- uint8_t valid;
- uint8_t arm_status;
- uint8_t igniter_status;
-};
-
-#define AO_LAUNCH_ARM 2
-#define AO_LAUNCH_FIRE 3
-
-void
-ao_launch_init(void);
-
-/*
- * ao_log_single.c
- */
-
-#define AO_LOG_TELESCIENCE_START ((uint8_t) 's')
-#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd')
-
-#define AO_LOG_TELESCIENCE_NUM_ADC 12
-
-struct ao_log_telescience {
- uint8_t type;
- uint8_t csum;
- uint16_t tick;
- uint16_t tm_tick;
- uint8_t tm_state;
- uint8_t unused;
- uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC];
-};
-
-#define AO_LOG_SINGLE_SIZE 32
-
-union ao_log_single {
- struct ao_log_telescience telescience;
- union ao_telemetry_all telemetry;
- uint8_t bytes[AO_LOG_SINGLE_SIZE];
-};
-
-extern __xdata union ao_log_single ao_log_single_write_data;
-extern __xdata union ao_log_single ao_log_single_read_data;
-
-void
-ao_log_single_extra_query(void);
-
-void
-ao_log_single_list(void);
-
-void
-ao_log_single_main(void);
-
-uint8_t
-ao_log_single_write(void);
-
-uint8_t
-ao_log_single_read(uint32_t pos);
-
-void
-ao_log_single_start(void);
-
-void
-ao_log_single_stop(void);
-
-void
-ao_log_single_restart(void);
-
-void
-ao_log_single_set(void);
-
-void
-ao_log_single_delete(void);
-
-void
-ao_log_single_init(void);
-
-void
-ao_log_single(void);
-
-/*
- * ao_pyro_slave.c
- */
-
-#define AO_TELEPYRO_NUM_ADC 9
-
-#ifndef ao_xmemcpy
-#define ao_xmemcpy(d,s,c) memcpy(d,s,c)
-#define ao_xmemset(d,v,c) memset(d,v,c)
-#define ao_xmemcmp(d,s,c) memcmp(d,s,c)
-#endif
-
-/*
- * ao_terraui.c
- */
-
-void
-ao_terraui_init(void);
-
-/*
- * ao_battery.c
- */
-
-#ifdef BATTERY_PIN
-void
-ao_battery_isr(void) ao_arch_interrupt(1);
-
-uint16_t
-ao_battery_get(void);
-
-void
-ao_battery_init(void);
-#endif /* BATTERY_PIN */
-
-/*
- * ao_sqrt.c
- */
-
-uint32_t
-ao_sqrt(uint32_t op);
-
-/*
- * ao_freq.c
- */
-
-int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant;
-
-/*
- * ao_ms5607.c
- */
-
-void ao_ms5607_init(void);
-
-#include <ao_arch_funcs.h>
-
-#endif /* _AO_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_ADC_H_
-#define _AO_ADC_H_
-
-#include <ao_data.h>
-
-/* Trigger a conversion sequence (called from the timer interrupt) */
-void
-ao_adc_poll(void);
-
-/* Suspend the current task until another A/D sample is converted */
-void
-ao_adc_sleep(void);
-
-/* Initialize the A/D converter */
-void
-ao_adc_init(void);
-
-#endif /* _AO_ADC_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_AES_H_
-#define _AO_AES_H_
-
-/* ao_aes.c */
-
-extern __xdata uint8_t ao_aes_mutex;
-
-/* AES keys and blocks are 128 bits */
-
-enum ao_aes_mode {
- ao_aes_mode_cbc_mac
-};
-
-#if HAS_AES
-#ifdef SDCC
-void
-ao_aes_isr(void) __interrupt 4;
-#endif
-#endif
-
-void
-ao_aes_set_mode(enum ao_aes_mode mode);
-
-void
-ao_aes_set_key(__xdata uint8_t *in);
-
-void
-ao_aes_zero_iv(void);
-
-void
-ao_aes_run(__xdata uint8_t *in,
- __xdata uint8_t *out);
-
-void
-ao_aes_init(void);
-
-#endif /* _AO_AES_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#endif
-
-#ifndef HAS_ACCEL
-#error Please define HAS_ACCEL
-#endif
-
-#ifndef HAS_GPS
-#error Please define HAS_GPS
-#endif
-
-#ifndef HAS_USB
-#error Please define HAS_USB
-#endif
-
-#if HAS_SENSOR_ERRORS
-/* Any sensor can set this to mark the flight computer as 'broken' */
-__xdata uint8_t ao_sensor_errors;
-#endif
-
-__pdata uint16_t ao_motor_number; /* number of motors burned so far */
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state ao_flight_state; /* current flight state */
-
-__pdata uint8_t ao_flight_force_idle;
-
-void
-ao_flight(void)
-{
- ao_sample_init();
- ao_flight_state = ao_flight_startup;
- for (;;) {
-
- /*
- * Process ADC samples, just looping
- * until the sensors are calibrated.
- */
- if (!ao_sample())
- continue;
-
- switch (ao_flight_state) {
- case ao_flight_startup:
-
- /* Check to see what mode we should go to.
- * - Invalid mode if accel cal appears to be out
- * - pad mode if we're upright,
- * - idle mode otherwise
- */
- if (!ao_flight_force_idle)
- {
- /* Set pad mode - we can fly! */
- ao_flight_state = ao_flight_pad;
-#if HAS_USB
- /* Disable the USB controller in flight mode
- * to save power
- */
- if (!ao_usb_running)
- ao_usb_disable();
-#endif
-
- /* Disable packet mode in pad state */
- ao_packet_slave_stop();
-
- /* Turn on telemetry system */
- ao_rdf_set(1);
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_BALLOON);
-
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
- } else {
- /* Set idle mode */
- ao_flight_state = ao_flight_idle;
-
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
- }
- /* wakeup threads due to state change */
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-
- break;
- case ao_flight_pad:
-
- /* pad to coast:
- *
- * barometer: > 20m vertical motion
- */
- if (ao_height > AO_M_TO_HEIGHT(20))
- {
- ao_flight_state = ao_flight_drogue;
-
- /* start logging data */
- ao_log_start();
-
-#if HAS_GPS
- /* Record current GPS position by waking up GPS log tasks */
- ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING;
- ao_wakeup(&ao_gps_new);
-#endif
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
- default:
- break;
- }
- }
-}
-
-static __xdata struct ao_task flight_task;
-
-void
-ao_flight_init(void)
-{
- ao_flight_state = ao_flight_startup;
- ao_add_task(&flight_task, ao_flight, "flight");
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_BEEP_H_
-#define _AO_BEEP_H_
-
-/*
- * ao_beep.c
- */
-
-/*
- * Various pre-defined beep frequencies
- *
- * frequency = 1/2 (24e6/32) / beep
- */
-
-#define AO_BEEP_LOW 150 /* 2500Hz */
-#define AO_BEEP_MID 94 /* 3989Hz */
-#define AO_BEEP_HIGH 75 /* 5000Hz */
-#define AO_BEEP_OFF 0 /* off */
-
-#define AO_BEEP_g 240 /* 1562.5Hz */
-#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */
-#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */
-#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */
-#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */
-#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */
-#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */
-#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */
-#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */
-#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */
-#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */
-#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */
-#define AO_BEEP_gg 120 /* 3125Hz */
-#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */
-#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */
-#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */
-#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */
-#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */
-#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */
-#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */
-#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */
-#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */
-#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */
-#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */
-#define AO_BEEP_ggg 60 /* 6250Hz */
-
-/* Set the beeper to the specified tone */
-void
-ao_beep(uint8_t beep);
-
-/* Turn on the beeper for the specified time */
-void
-ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant;
-
-/* Initialize the beeper */
-void
-ao_beep_init(void);
-
-#endif /* _AO_BEEP_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_BTM_H_
-#define _AO_BTM_H_
-
-/* ao_btm.c */
-
-/* If bt_link is on P2, this interrupt is shared by USB, so the USB
- * code calls this function. Otherwise, it's a regular ISR.
- */
-
-void
-ao_btm_isr(void)
-#if BT_LINK_ON_P1
- __interrupt 15
-#endif
- ;
-void
-ao_btm_init(void);
-
-#endif /* _AO_BTM_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_task.h"
-
-__pdata uint16_t ao_cmd_lex_i;
-__pdata uint32_t ao_cmd_lex_u32;
-__pdata char ao_cmd_lex_c;
-__pdata enum ao_cmd_status ao_cmd_status;
-
-#define CMD_LEN 48
-
-static __xdata char cmd_line[CMD_LEN];
-static __pdata uint8_t cmd_len;
-static __pdata uint8_t cmd_i;
-
-void
-ao_put_string(__code char *s)
-{
- char c;
- while ((c = *s++))
- putchar(c);
-}
-
-static void
-backspace(void)
-{
- ao_put_string ("\010 \010");
-}
-
-static void
-readline(void)
-{
- char c;
- if (ao_echo())
- ao_put_string("> ");
- cmd_len = 0;
- for (;;) {
- flush();
- c = getchar();
- /* backspace/delete */
- if (c == '\010' || c == '\177') {
- if (cmd_len != 0) {
- if (ao_echo())
- backspace();
- --cmd_len;
- }
- continue;
- }
-
- /* ^U */
- if (c == '\025') {
- while (cmd_len != 0) {
- if (ao_echo())
- backspace();
- --cmd_len;
- }
- continue;
- }
-
- /* map CR to NL */
- if (c == '\r')
- c = '\n';
-
- if (c == '\n') {
- if (ao_echo())
- putchar('\n');
- break;
- }
-
- if (cmd_len >= CMD_LEN - 2)
- continue;
- cmd_line[cmd_len++] = c;
- if (ao_echo())
- putchar(c);
- }
- cmd_line[cmd_len++] = '\n';
- cmd_line[cmd_len++] = '\0';
- cmd_i = 0;
-}
-
-void
-ao_cmd_lex(void)
-{
- ao_cmd_lex_c = '\n';
- if (cmd_i < cmd_len)
- ao_cmd_lex_c = cmd_line[cmd_i++];
-}
-
-static void
-putnibble(uint8_t v)
-{
- if (v < 10)
- putchar(v + '0');
- else
- putchar(v + ('a' - 10));
-}
-
-uint8_t
-ao_getnibble(void)
-{
- char c;
-
- c = getchar();
- if ('0' <= c && c <= '9')
- return c - '0';
- if ('a' <= c && c <= 'f')
- return c - ('a' - 10);
- if ('A' <= c && c <= 'F')
- return c - ('A' - 10);
- ao_cmd_status = ao_cmd_lex_error;
- return 0;
-}
-
-void
-ao_cmd_put16(uint16_t v)
-{
- ao_cmd_put8(v >> 8);
- ao_cmd_put8(v);
-}
-
-void
-ao_cmd_put8(uint8_t v)
-{
- putnibble((v >> 4) & 0xf);
- putnibble(v & 0xf);
-}
-
-uint8_t
-ao_cmd_is_white(void)
-{
- return ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t';
-}
-
-void
-ao_cmd_white(void)
-{
- while (ao_cmd_is_white())
- ao_cmd_lex();
-}
-
-int8_t
-ao_cmd_hexchar(char c)
-{
- if ('0' <= c && c <= '9')
- return (c - '0');
- if ('a' <= c && c <= 'f')
- return (c - 'a' + 10);
- if ('A' <= c && c <= 'F')
- return (c - 'A' + 10);
- return -1;
-}
-
-void
-ao_cmd_hexbyte(void)
-{
- uint8_t i;
- int8_t n;
-
- ao_cmd_lex_i = 0;
- ao_cmd_white();
- for (i = 0; i < 2; i++) {
- n = ao_cmd_hexchar(ao_cmd_lex_c);
- if (n < 0) {
- ao_cmd_status = ao_cmd_syntax_error;
- break;
- }
- ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n;
- ao_cmd_lex();
- }
-}
-
-void
-ao_cmd_hex(void)
-{
- __pdata uint8_t r = ao_cmd_lex_error;
- int8_t n;
-
- ao_cmd_lex_i = 0;
- ao_cmd_white();
- for(;;) {
- n = ao_cmd_hexchar(ao_cmd_lex_c);
- if (n < 0)
- break;
- ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n;
- r = ao_cmd_success;
- ao_cmd_lex();
- }
- if (r != ao_cmd_success)
- ao_cmd_status = r;
-}
-
-void
-ao_cmd_decimal(void) __reentrant
-{
- uint8_t r = ao_cmd_lex_error;
-
- ao_cmd_lex_u32 = 0;
- ao_cmd_white();
- for(;;) {
- if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
- ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0');
- else
- break;
- r = ao_cmd_success;
- ao_cmd_lex();
- }
- if (r != ao_cmd_success)
- ao_cmd_status = r;
- ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32;
-}
-
-uint8_t
-ao_match_word(__code char *word)
-{
- while (*word) {
- if (ao_cmd_lex_c != *word) {
- ao_cmd_status = ao_cmd_syntax_error;
- return 0;
- }
- word++;
- ao_cmd_lex();
- }
- return 1;
-}
-
-static void
-echo(void)
-{
- ao_cmd_hex();
- if (ao_cmd_status == ao_cmd_success)
- ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0;
-}
-
-static void
-ao_reboot(void)
-{
- ao_cmd_white();
- if (!ao_match_word("eboot"))
- return;
- /* Delay waiting for the packet master to be turned off
- * so that we don't end up back in idle mode because we
- * received a packet after boot.
- */
- flush();
- ao_delay(AO_SEC_TO_TICKS(1));
- ao_arch_reboot();
- ao_panic(AO_PANIC_REBOOT);
-}
-
-#ifndef HAS_VERSION
-#define HAS_VERSION 1
-#endif
-
-#if HAS_VERSION
-static void
-version(void)
-{
- printf("manufacturer %s\n"
- "product %s\n"
- "serial-number %u\n"
-#if HAS_FLIGHT
- "current-flight %u\n"
-#endif
-#if HAS_LOG
- "log-format %u\n"
-#endif
- , ao_manufacturer
- , ao_product
- , ao_serial_number
-#if HAS_FLIGHT
- , ao_flight_number
-#endif
-#if HAS_LOG
- , ao_log_format
-#endif
- );
- printf("software-version %s\n", ao_version);
-}
-#endif
-
-#ifndef NUM_CMDS
-#define NUM_CMDS 11
-#endif
-
-static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]);
-static __pdata uint8_t ao_ncmds;
-
-static void
-help(void)
-{
- __pdata uint8_t cmds;
- __pdata uint8_t cmd;
- __code struct ao_cmds * __pdata cs;
- __code const char *h;
- uint8_t e;
-
- for (cmds = 0; cmds < ao_ncmds; cmds++) {
- cs = ao_cmds[cmds];
- for (cmd = 0; cs[cmd].func; cmd++) {
- h = cs[cmd].help;
- ao_put_string(h);
- e = strlen(h);
- h += e + 1;
- e = 45 - e;
- while (e--)
- putchar(' ');
- ao_put_string(h);
- putchar('\n');
- }
- }
-}
-
-static void
-report(void)
-{
- switch(ao_cmd_status) {
- case ao_cmd_lex_error:
- case ao_cmd_syntax_error:
- puts("Syntax error");
- ao_cmd_status = 0;
- default:
- break;
- }
-}
-
-void
-ao_cmd_register(__code struct ao_cmds *cmds)
-{
- if (ao_ncmds >= NUM_CMDS)
- ao_panic(AO_PANIC_CMD);
- ao_cmds[ao_ncmds++] = cmds;
-}
-
-void
-ao_cmd(void)
-{
- __pdata char c;
- uint8_t cmd, cmds;
- __code struct ao_cmds * __xdata cs;
- void (*__xdata func)(void);
-
- for (;;) {
- readline();
- ao_cmd_lex();
- ao_cmd_white();
- c = ao_cmd_lex_c;
- ao_cmd_lex();
- if (c == '\r' || c == '\n')
- continue;
- func = (void (*)(void)) NULL;
- for (cmds = 0; cmds < ao_ncmds; cmds++) {
- cs = ao_cmds[cmds];
- for (cmd = 0; cs[cmd].func; cmd++)
- if (cs[cmd].help[0] == c) {
- func = cs[cmd].func;
- break;
- }
- if (func)
- break;
- }
- if (func)
- (*func)();
- else
- ao_cmd_status = ao_cmd_syntax_error;
- report();
- }
-}
-
-#if HAS_BOOT_LOADER
-
-#include <ao_boot.h>
-
-static void
-ao_loader(void)
-{
- flush();
- ao_boot_loader();
-}
-#endif
-
-__xdata struct ao_task ao_cmd_task;
-
-__code struct ao_cmds ao_base_cmds[] = {
- { help, "?\0Help" },
-#if HAS_TASK_INFO
- { ao_task_info, "T\0Tasks" },
-#endif
- { echo, "E <0 off, 1 on>\0Echo" },
- { ao_reboot, "r eboot\0Reboot" },
-#if HAS_VERSION
- { version, "v\0Version" },
-#endif
-#if HAS_BOOT_LOADER
- { ao_loader, "X\0Switch to boot loader" },
-#endif
- { 0, NULL },
-};
-
-void
-ao_cmd_init(void)
-{
- ao_cmd_register(&ao_base_cmds[0]);
- ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_COMPANION_H_
-#define _AO_COMPANION_H_
-
-/* ao_companion.c */
-
-#define AO_COMPANION_SETUP 1
-#define AO_COMPANION_FETCH 2
-#define AO_COMPANION_NOTIFY 3
-
-struct ao_companion_command {
- uint8_t command;
- uint8_t flight_state;
- uint16_t tick;
- uint16_t serial;
- uint16_t flight;
- int16_t accel;
- int16_t speed;
- int16_t height;
- int16_t motor_number;
-};
-
-struct ao_companion_setup {
- uint16_t board_id;
- uint16_t board_id_inverse;
- uint8_t update_period;
- uint8_t channels;
-};
-
-extern __pdata uint8_t ao_companion_running;
-extern __xdata uint8_t ao_companion_mutex;
-extern __xdata struct ao_companion_command ao_companion_command;
-extern __xdata struct ao_companion_setup ao_companion_setup;
-extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS];
-
-void
-ao_companion_init(void);
-
-#endif /* _AO_COMPANION_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_log.h"
-#include <ao_config.h>
-#if HAS_FLIGHT
-#include <ao_sample.h>
-#include <ao_data.h>
-#endif
-
-__xdata struct ao_config ao_config;
-__pdata uint8_t ao_config_loaded;
-__pdata uint8_t ao_config_dirty;
-__xdata uint8_t ao_config_mutex;
-
-#ifndef AO_CONFIG_DEFAULT_APRS_INTERVAL
-#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0
-#endif
-#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250
-#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0
-#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL"
-#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
-#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
-#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL
-#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP
-#if HAS_EEPROM
-#ifndef USE_INTERNAL_FLASH
-#error Please define USE_INTERNAL_FLASH
-#endif
-#endif
-#ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX
-#if USE_INTERNAL_FLASH
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config
-#else
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024)
-#endif
-#endif
-#ifndef AO_CONFIG_DEFAULT_RADIO_POWER
-#define AO_CONFIG_DEFAULT_RADIO_POWER 0x60
-#endif
-#define AO_CONFIG_DEFAULT_RADIO_AMP 0
-
-#if HAS_EEPROM
-static void
-_ao_config_put(void)
-{
- ao_config_setup();
- ao_config_erase();
- ao_config_write(0, &ao_config, sizeof (ao_config));
-#if HAS_FLIGHT
- ao_log_write_erase(0);
-#endif
- ao_config_flush();
-}
-
-void
-ao_config_put(void)
-{
- ao_mutex_get(&ao_config_mutex);
- _ao_config_put();
- ao_mutex_put(&ao_config_mutex);
-}
-#endif
-
-#if HAS_RADIO
-void
-ao_config_set_radio(void)
-{
- ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal);
-}
-#endif /* HAS_RADIO */
-
-static void
-_ao_config_get(void)
-{
- uint8_t minor;
-
- if (ao_config_loaded)
- return;
-#if HAS_EEPROM
- /* Yes, I know ao_storage_read calls ao_storage_setup,
- * but ao_storage_setup *also* sets ao_storage_config, which we
- * need before calling ao_storage_read here
- */
- ao_config_setup();
- ao_config_read(0, &ao_config, sizeof (ao_config));
-#endif
- if (ao_config.major != AO_CONFIG_MAJOR) {
- ao_config.major = AO_CONFIG_MAJOR;
- ao_config.minor = 0;
-
- /* Version 0 stuff */
- ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
- ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
- ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN),
- sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
- ao_config._legacy_radio_channel = 0;
- }
- minor = ao_config.minor;
- if (minor != AO_CONFIG_MINOR) {
- /* Fixups for minor version 1 */
- if (minor < 1)
- ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
- /* Fixups for minor version 2 */
- if (minor < 2) {
- ao_config.accel_plus_g = 0;
- ao_config.accel_minus_g = 0;
- }
- /* Fixups for minor version 3 */
-#if HAS_RADIO
- if (minor < 3)
- ao_config.radio_cal = ao_radio_cal;
-#endif
- /* Fixups for minor version 4 */
-#if HAS_FLIGHT
- if (minor < 4)
- ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX;
-#endif
- /* Fixupes for minor version 5 */
- if (minor < 5)
- ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE;
- if (minor < 6)
- ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION;
- if (minor < 8)
- ao_config.radio_enable = AO_RADIO_ENABLE_CORE;
- if (minor < 9)
- ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN);
- if (minor < 10)
- ao_config.frequency = 434550 + ao_config._legacy_radio_channel * 100;
- if (minor < 11)
- ao_config.apogee_lockout = 0;
-#if AO_PYRO_NUM
- if (minor < 12)
- memset(&ao_config.pyro, '\0', sizeof (ao_config.pyro));
-#endif
- if (minor < 13)
- ao_config.aprs_interval = AO_CONFIG_DEFAULT_APRS_INTERVAL;
-#if HAS_RADIO_POWER
- if (minor < 14)
- ao_config.radio_power = AO_CONFIG_DEFAULT_RADIO_POWER;
- #endif
-#if HAS_RADIO_AMP
- if (minor < 14)
- ao_config.radio_amp = AO_CONFIG_DEFAULT_RADIO_AMP;
-#endif
-#if HAS_GYRO
- if (minor < 15) {
- ao_config.accel_zero_along = 0;
- ao_config.accel_zero_across = 0;
- ao_config.accel_zero_through = 0;
-
- /* Reset the main accel offsets to force
- * re-calibration
- */
- ao_config.accel_plus_g = 0;
- ao_config.accel_minus_g = 0;
- }
-#endif
- ao_config.minor = AO_CONFIG_MINOR;
- ao_config_dirty = 1;
- }
-#if HAS_RADIO
-#if HAS_FORCE_FREQ
- if (ao_force_freq) {
- ao_config.frequency = 434550;
- ao_config.radio_cal = ao_radio_cal;
- ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN),
- sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
- }
-#endif
- ao_config_set_radio();
-#endif
- ao_config_loaded = 1;
-}
-
-void
-_ao_config_edit_start(void)
-{
- ao_mutex_get(&ao_config_mutex);
- _ao_config_get();
-}
-
-void
-_ao_config_edit_finish(void)
-{
- ao_config_dirty = 1;
- ao_mutex_put(&ao_config_mutex);
-}
-
-void
-ao_config_get(void)
-{
- _ao_config_edit_start();
- ao_mutex_put(&ao_config_mutex);
-}
-
-void
-ao_config_callsign_show(void)
-{
- printf ("Callsign: \"%s\"\n", ao_config.callsign);
-}
-
-void
-ao_config_callsign_set(void) __reentrant
-{
- uint8_t c;
- static __xdata char callsign[AO_MAX_CALLSIGN + 1];
-
- ao_xmemset(callsign, '\0', sizeof callsign);
- ao_cmd_white();
- c = 0;
- while (ao_cmd_lex_c != '\n') {
- if (c < AO_MAX_CALLSIGN)
- callsign[c++] = ao_cmd_lex_c;
- else
- ao_cmd_status = ao_cmd_lex_error;
- ao_cmd_lex();
- }
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_xmemcpy(&ao_config.callsign, &callsign,
- AO_MAX_CALLSIGN + 1);
- _ao_config_edit_finish();
-}
-
-#if HAS_RADIO
-
-void
-ao_config_frequency_show(void) __reentrant
-{
- printf("Frequency: %ld\n",
- ao_config.frequency);
-}
-
-void
-ao_config_frequency_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.frequency = ao_cmd_lex_u32;
- ao_config_set_radio();
- _ao_config_edit_finish();
-#if HAS_RADIO_RECV
- ao_radio_recv_abort();
-#endif
-}
-#endif
-
-#if HAS_FLIGHT
-
-void
-ao_config_main_deploy_show(void) __reentrant
-{
- printf("Main deploy: %d meters\n",
- ao_config.main_deploy);
-}
-
-void
-ao_config_main_deploy_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.main_deploy = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#if HAS_ACCEL
-void
-ao_config_accel_calibrate_show(void) __reentrant
-{
- printf("Accel cal +1g: %d -1g: %d\n",
- ao_config.accel_plus_g, ao_config.accel_minus_g);
-#if HAS_GYRO
- printf ("IMU cal along %d across %d through %d\n",
- ao_config.accel_zero_along,
- ao_config.accel_zero_across,
- ao_config.accel_zero_through);
-#endif
-}
-
-#define ACCEL_CALIBRATE_SAMPLES 1024
-#define ACCEL_CALIBRATE_SHIFT 10
-
-#if HAS_GYRO
-static int16_t accel_cal_along;
-static int16_t accel_cal_across;
-static int16_t accel_cal_through;
-#endif
-
-static int16_t
-ao_config_accel_calibrate_auto(char *orientation) __reentrant
-{
- uint16_t i;
- int32_t accel_total;
- uint8_t cal_data_ring;
-#if HAS_GYRO
- int32_t accel_along_total = 0;
- int32_t accel_across_total = 0;
- int32_t accel_through_total = 0;
-#endif
-
- printf("Orient antenna %s and press a key...", orientation);
- flush();
- (void) getchar();
- puts("\r\n"); flush();
- puts("Calibrating..."); flush();
- i = ACCEL_CALIBRATE_SAMPLES;
- accel_total = 0;
- cal_data_ring = ao_sample_data;
- while (i) {
- ao_sleep(DATA_TO_XDATA(&ao_sample_data));
- while (i && cal_data_ring != ao_sample_data) {
- accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]);
-#if HAS_GYRO
- accel_along_total += (int32_t) ao_data_along(&ao_data_ring[cal_data_ring]);
- accel_across_total += (int32_t) ao_data_across(&ao_data_ring[cal_data_ring]);
- accel_through_total += (int32_t) ao_data_through(&ao_data_ring[cal_data_ring]);
-#endif
- cal_data_ring = ao_data_ring_next(cal_data_ring);
- i--;
- }
- }
-#if HAS_GYRO
- accel_cal_along = accel_along_total >> ACCEL_CALIBRATE_SHIFT;
- accel_cal_across = accel_across_total >> ACCEL_CALIBRATE_SHIFT;
- accel_cal_through = accel_through_total >> ACCEL_CALIBRATE_SHIFT;
-#endif
- return accel_total >> ACCEL_CALIBRATE_SHIFT;
-}
-
-void
-ao_config_accel_calibrate_set(void) __reentrant
-{
- int16_t up, down;
-#if HAS_GYRO
- int16_t accel_along_up = 0, accel_along_down = 0;
- int16_t accel_across_up = 0, accel_across_down = 0;
- int16_t accel_through_up = 0, accel_through_down = 0;
-#endif
-
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- if (ao_cmd_lex_i == 0) {
- up = ao_config_accel_calibrate_auto("up");
-#if HAS_GYRO
- accel_along_up = accel_cal_along;
- accel_across_up = accel_cal_across;
- accel_through_up = accel_cal_through;
-#endif
- down = ao_config_accel_calibrate_auto("down");
-#if HAS_GYRO
- accel_along_down = accel_cal_along;
- accel_across_down = accel_cal_across;
- accel_through_down = accel_cal_through;
-#endif
- } else {
- up = ao_cmd_lex_i;
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- down = ao_cmd_lex_i;
- }
- if (up >= down) {
- printf("Invalid accel: up (%d) down (%d)\n",
- up, down);
- return;
- }
- _ao_config_edit_start();
- ao_config.accel_plus_g = up;
- ao_config.accel_minus_g = down;
-#if HAS_GYRO
- if (ao_cmd_lex_i == 0) {
- ao_config.accel_zero_along = (accel_along_up + accel_along_down) / 2;
- ao_config.accel_zero_across = (accel_across_up + accel_across_down) / 2;
- ao_config.accel_zero_through = (accel_through_up + accel_through_down) / 2;
- }
-#endif
- _ao_config_edit_finish();
-}
-#endif /* HAS_ACCEL */
-
-void
-ao_config_apogee_delay_show(void) __reentrant
-{
- printf("Apogee delay: %d seconds\n",
- ao_config.apogee_delay);
-}
-
-void
-ao_config_apogee_delay_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.apogee_delay = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-void
-ao_config_apogee_lockout_show(void) __reentrant
-{
- printf ("Apogee lockout: %d seconds\n",
- ao_config.apogee_lockout);
-}
-
-void
-ao_config_apogee_lockout_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.apogee_lockout = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#endif /* HAS_FLIGHT */
-
-#if HAS_RADIO
-void
-ao_config_radio_cal_show(void) __reentrant
-{
- printf("Radio cal: %ld\n", ao_config.radio_cal);
-}
-
-void
-ao_config_radio_cal_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_cal = ao_cmd_lex_u32;
- ao_config_set_radio();
- _ao_config_edit_finish();
-}
-#endif
-
-#if HAS_LOG
-void
-ao_config_log_show(void) __reentrant
-{
- printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
-}
-
-void
-ao_config_log_set(void) __reentrant
-{
- uint16_t block = (uint16_t) (ao_storage_block >> 10);
- uint16_t log_max = (uint16_t) (ao_storage_log_max >> 10);
-
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- if (ao_log_present())
- printf("Storage must be empty before changing log size\n");
- else if (block > 1024 && (ao_cmd_lex_i & (block - 1)))
- printf("Flight log size must be multiple of %d kB\n", block);
- else if (ao_cmd_lex_i > log_max)
- printf("Flight log max %d kB\n", log_max);
- else {
- _ao_config_edit_start();
- ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;
- _ao_config_edit_finish();
- }
-}
-#endif /* HAS_LOG */
-
-#if HAS_IGNITE
-void
-ao_config_ignite_mode_show(void) __reentrant
-{
- printf("Ignite mode: %d\n", ao_config.ignite_mode);
-}
-
-void
-ao_config_ignite_mode_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.ignite_mode = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-#endif
-
-#if HAS_ACCEL
-void
-ao_config_pad_orientation_show(void) __reentrant
-{
- printf("Pad orientation: %d\n", ao_config.pad_orientation);
-}
-
-#ifndef AO_ACCEL_INVERT
-#define AO_ACCEL_INVERT 0x7fff
-#endif
-
-void
-ao_config_pad_orientation_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_cmd_lex_i &= 1;
- if (ao_config.pad_orientation != ao_cmd_lex_i) {
- int16_t t;
- t = ao_config.accel_plus_g;
- ao_config.accel_plus_g = AO_ACCEL_INVERT - ao_config.accel_minus_g;
- ao_config.accel_minus_g = AO_ACCEL_INVERT - t;
- }
- ao_config.pad_orientation = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-#endif
-
-#if HAS_RADIO
-void
-ao_config_radio_enable_show(void) __reentrant
-{
- printf("Radio enable: %d\n", ao_config.radio_enable);
-}
-
-void
-ao_config_radio_enable_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_enable = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-#endif /* HAS_RADIO */
-
-#if HAS_AES
-
-__xdata uint8_t ao_config_aes_seq = 1;
-
-void
-ao_config_key_show(void) __reentrant
-{
- uint8_t i;
- printf("AES key: ");
- for (i = 0; i < AO_AES_LEN; i++)
- printf ("%02x", ao_config.aes_key[i]);
- printf("\n");
-}
-
-void
-ao_config_key_set(void) __reentrant
-{
- uint8_t i;
-
- _ao_config_edit_start();
- for (i = 0; i < AO_AES_LEN; i++) {
- ao_cmd_hexbyte();
- if (ao_cmd_status != ao_cmd_success)
- break;
- ao_config.aes_key[i] = ao_cmd_lex_i;
- }
- ++ao_config_aes_seq;
- _ao_config_edit_finish();
-}
-#endif
-
-#if HAS_APRS
-
-void
-ao_config_aprs_show(void)
-{
- printf ("APRS interval: %d\n", ao_config.aprs_interval);
-}
-
-void
-ao_config_aprs_set(void)
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.aprs_interval = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#endif /* HAS_APRS */
-
-#if HAS_RADIO_AMP
-
-void
-ao_config_radio_amp_show(void)
-{
- printf ("Radio amp setting: %d\n", ao_config.radio_amp);
-}
-
-void
-ao_config_radio_amp_set(void)
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_amp = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#endif
-
-#if HAS_RADIO_POWER
-
-void
-ao_config_radio_power_show(void)
-{
- printf ("Radio power setting: %d\n", ao_config.radio_power);
-}
-
-void
-ao_config_radio_power_set(void)
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- _ao_config_edit_start();
- ao_config.radio_power = ao_cmd_lex_i;
- _ao_config_edit_finish();
-}
-
-#endif
-
-struct ao_config_var {
- __code char *str;
- void (*set)(void) __reentrant;
- void (*show)(void) __reentrant;
-};
-
-static void
-ao_config_help(void) __reentrant;
-
-static void
-ao_config_show(void) __reentrant;
-
-#if HAS_EEPROM
-static void
-ao_config_save(void) __reentrant;
-#endif
-
-__code struct ao_config_var ao_config_vars[] = {
-#if HAS_FLIGHT
- { "m <meters>\0Main deploy (m)",
- ao_config_main_deploy_set, ao_config_main_deploy_show, },
- { "d <delay>\0Apogee delay (s)",
- ao_config_apogee_delay_set, ao_config_apogee_delay_show },
- { "L <seconds>\0Apogee detect lockout (s)",
- ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, },
-#endif /* HAS_FLIGHT */
-#if HAS_RADIO
- { "F <freq>\0Frequency (kHz)",
- ao_config_frequency_set, ao_config_frequency_show },
- { "c <call>\0Callsign (8 char max)",
- ao_config_callsign_set, ao_config_callsign_show },
- { "e <0 disable, 1 enable>\0Enable telemetry and RDF",
- ao_config_radio_enable_set, ao_config_radio_enable_show },
- { "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
- ao_config_radio_cal_set, ao_config_radio_cal_show },
-#if HAS_RADIO_POWER
- { "p <setting>\0Radio power setting (0-255)",
- ao_config_radio_power_set, ao_config_radio_power_show },
-#endif
-#if HAS_RADIO_AMP
- { "d <setting>\0Radio amplifier setting (0-3)",
- ao_config_radio_amp_set, ao_config_radio_amp_show },
-#endif
-#endif /* HAS_RADIO */
-#if HAS_ACCEL
- { "a <+g> <-g>\0Accel calib (0 for auto)",
- ao_config_accel_calibrate_set,ao_config_accel_calibrate_show },
- { "o <0 antenna up, 1 antenna down>\0Set pad orientation",
- ao_config_pad_orientation_set,ao_config_pad_orientation_show },
-#endif /* HAS_ACCEL */
-#if HAS_LOG
- { "l <size>\0Flight log size (kB)",
- ao_config_log_set, ao_config_log_show },
-#endif
-#if HAS_IGNITE
- { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode",
- ao_config_ignite_mode_set, ao_config_ignite_mode_show },
-#endif
-#if HAS_AES
- { "k <32 hex digits>\0Set AES encryption key",
- ao_config_key_set, ao_config_key_show },
-#endif
-#if AO_PYRO_NUM
- { "P <n,?>\0Configure pyro channels",
- ao_pyro_set, ao_pyro_show },
-#endif
-#if HAS_APRS
- { "A <secs>\0APRS packet interval (0 disable)",
- ao_config_aprs_set, ao_config_aprs_show },
-#endif
- { "s\0Show",
- ao_config_show, 0 },
-#if HAS_EEPROM
- { "w\0Write to eeprom",
- ao_config_save, 0 },
-#endif
- { "?\0Help",
- ao_config_help, 0 },
- { 0, 0, 0 }
-};
-
-void
-ao_config_set(void)
-{
- char c;
- uint8_t cmd;
-
- ao_cmd_white();
- c = ao_cmd_lex_c;
- ao_cmd_lex();
- for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
- if (ao_config_vars[cmd].str[0] == c) {
- (*ao_config_vars[cmd].set)();
- return;
- }
- ao_cmd_status = ao_cmd_syntax_error;
-}
-
-static void
-ao_config_help(void) __reentrant
-{
- uint8_t cmd;
- for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
- printf("%-20s %s\n",
- ao_config_vars[cmd].str,
- ao_config_vars[cmd].str+1+
- strlen(ao_config_vars[cmd].str));
-}
-
-static void
-ao_config_show(void) __reentrant
-{
- uint8_t cmd;
- ao_config_get();
- printf("Config version: %d.%d\n",
- ao_config.major, ao_config.minor);
- for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
- if (ao_config_vars[cmd].show)
- (*ao_config_vars[cmd].show)();
-#if HAS_MS5607
- ao_ms5607_info();
-#endif
-}
-
-#if HAS_EEPROM
-static void
-ao_config_save(void) __reentrant
-{
- uint8_t saved = 0;
- ao_mutex_get(&ao_config_mutex);
- if (ao_config_dirty) {
- _ao_config_put();
- ao_config_dirty = 0;
- saved = 1;
- }
- ao_mutex_put(&ao_config_mutex);
- if (saved)
- puts("Saved");
- else
- puts("Nothing to save");
-}
-#endif
-
-__code struct ao_cmds ao_config_cmds[] = {
- { ao_config_set, "c <var> <value>\0Set config (? for help, s to show)" },
- { 0, NULL },
-};
-
-void
-ao_config_init(void)
-{
- ao_cmd_register(&ao_config_cmds[0]);
-}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_CONFIG_H_
-#define _AO_CONFIG_H_
-
-#ifndef USE_STORAGE_CONFIG
-#define USE_STORAGE_CONFIG 1
-#endif
-
-#ifndef USE_EEPROM_CONFIG
-#define USE_EEPROM_CONFIG 0
-#endif
-
-#if USE_STORAGE_CONFIG
-
-#include <ao_storage.h>
-
-#define ao_config_setup() ao_storage_setup()
-#define ao_config_erase() ao_storage_erase(ao_storage_config)
-#define ao_config_write(pos,bytes, len) ao_storage_write(ao_storage_config+(pos), bytes, len)
-#define ao_config_read(pos,bytes, len) ao_storage_read(ao_storage_config+(pos), bytes, len)
-#define ao_config_flush() ao_storage_flush()
-
-#endif
-
-#if USE_EEPROM_CONFIG
-
-#include <ao_eeprom.h>
-
-#define ao_config_setup()
-#define ao_config_erase()
-#define ao_config_write(pos,bytes, len) ao_eeprom_write(pos, bytes, len)
-#define ao_config_read(pos,bytes, len) ao_eeprom_read(pos, bytes, len)
-#define ao_config_flush()
-
-#endif
-
-#endif /* _AO_CONFIG_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST)
-#include "ao.h"
-#endif
-
-static const int16_t altitude_table[] = {
-#include "altitude.h"
-};
-
-#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
-#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1)
-
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant
-{
- uint8_t o;
- int16_t part;
-
- if (pres < 0)
- pres = 0;
- o = pres >> ALT_FRAC_BITS;
- part = pres & ALT_FRAC_MASK;
-
- return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) +
- (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS;
-}
-
-#if AO_NEED_ALTITUDE_TO_PRES
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
-{
- int16_t span, sub_span;
- uint8_t l, h, m;
- int32_t pres;
-
- l = 0;
- h = NALT - 1;
- while ((h - l) != 1) {
- m = (l + h) >> 1;
- if (altitude_table[m] < alt)
- h = m;
- else
- l = m;
- }
- span = altitude_table[l] - altitude_table[h];
- sub_span = altitude_table[l] - alt;
- pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span;
- if (pres > 32767)
- pres = 32767;
- if (pres < 0)
- pres = 0;
- return (int16_t) pres;
-}
-#endif
-
-#if 0
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant
-{
- int16_t ret;
-
- /* Output voltage at 0°C = 0.755V
- * Coefficient = 0.00247V/°C
- * Reference voltage = 1.25V
- *
- * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
- * = (value - 19791.268) / 32768 * 1.25 / 0.00247
- * ≃ (value - 19791) * 1012 / 65536
- */
- ret = ((temp - 19791) * 1012L) >> 16;
- return ret;
-}
-#endif
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST)
-#include "ao.h"
-#endif
-
-#ifndef AO_CONST_ATTRIB
-#define AO_CONST_ATTRIB
-#endif
-
-static const alt_t altitude_table[] AO_CONST_ATTRIB = {
-#include "altitude-pa.h"
-};
-
-#ifndef FETCH_ALT
-#define FETCH_ALT(o) altitude_table[o]
-#endif
-
-#define ALT_SCALE (1 << ALT_SHIFT)
-#define ALT_MASK (ALT_SCALE - 1)
-
-alt_t
-ao_pa_to_altitude(int32_t pa)
-{
- int16_t o;
- int16_t part;
- int32_t low, high;
-
- if (pa < 0)
- pa = 0;
- if (pa > 120000L)
- pa = 120000L;
- o = pa >> ALT_SHIFT;
- part = pa & ALT_MASK;
-
- low = (int32_t) FETCH_ALT(o) * (ALT_SCALE - part);
- high = (int32_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1);
- return (low + high) >> ALT_SHIFT;
-}
-
-#ifdef AO_CONVERT_TEST
-int32_t
-ao_altitude_to_pa(int32_t alt)
-{
- int32_t span, sub_span;
- uint16_t l, h, m;
- int32_t pa;
-
- l = 0;
- h = NALT - 1;
- while ((h - l) != 1) {
- m = (l + h) >> 1;
- if (altitude_table[m] < alt)
- h = m;
- else
- l = m;
- }
- span = altitude_table[l] - altitude_table[h];
- sub_span = altitude_table[l] - alt;
- pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span;
- if (pa > 120000)
- pa = 120000;
- if (pa < 0)
- pa = 0;
- return pa;
-}
-#endif
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <stdint.h>
-#define AO_CONVERT_TEST
-typedef int32_t alt_t;
-#include "ao_host.h"
-#include "ao_convert_pa.c"
-
-#define STEP_P 1
-#define STEP_A 1
-
-static inline int i_abs(int i) { return i < 0 ? -i : i; }
-
-int
-main (int argc, char **argv)
-{
- int i;
- int32_t p_to_a, p_to_a_to_p;
- int32_t a_to_p, a_to_p_to_a;
- int max_p_error = 0, max_p_error_p = -1;
- int max_a_error = 0, max_a_error_a = -1;
- int p_error;
- int a_error;
- int ret = 0;
-
- for (i = 0; i < 120000 + STEP_P; i += STEP_P) {
- if (i > 120000)
- i = 120000;
- p_to_a = ao_pa_to_altitude(i);
- p_to_a_to_p = ao_altitude_to_pa(p_to_a);
- p_error = i_abs(p_to_a_to_p - i);
- if (p_error > max_p_error) {
- max_p_error = p_error;
- max_p_error_p = i;
- }
-// printf ("pa %d alt %d pa %d\n",
-// i, p_to_a, p_to_a_to_p);
- }
- for (i = -1450; i < 40000 + STEP_A; i += STEP_A) {
- a_to_p = ao_altitude_to_pa(i);
- a_to_p_to_a = ao_pa_to_altitude(a_to_p);
- a_error = i_abs(a_to_p_to_a - i);
- if (a_error > max_a_error) {
- max_a_error = a_error;
- max_a_error_a = i;
- }
-// printf ("alt %d pa %d alt %d\n",
-// i, a_to_p, a_to_p_to_a);
- }
- if (max_p_error > 2) {
- printf ("max p error %d at %d\n", max_p_error,
- max_p_error_p);
- ret++;
- }
- if (max_a_error > 1) {
- printf ("max a error %d at %d\n", max_a_error,
- max_a_error_a);
- ret++;
- }
- return ret;
-}
+++ /dev/null
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <stdint.h>
-#define AO_CONVERT_TEST
-#define AO_NEED_ALTITUDE_TO_PRES 1
-#include "ao_host.h"
-#include "ao_convert.c"
-
-#define STEP 1
-
-static inline int i_abs(int i) { return i < 0 ? -i : i; }
-
-int main (int argc, char **argv)
-{
- int i;
- int16_t p_to_a, p_to_a_to_p;
- int16_t a_to_p, a_to_p_to_a;
- int max_p_error = 0, max_p_error_p = -1;
- int max_a_error = 0, max_a_error_a = -1;
- int p_error;
- int a_error;
- int ret = 0;
-
- for (i = 0; i < 32767 + STEP; i += STEP) {
- if (i > 32767)
- i = 32767;
- p_to_a = ao_pres_to_altitude(i);
- p_to_a_to_p = ao_altitude_to_pres(p_to_a);
- p_error = i_abs(p_to_a_to_p - i);
- if (p_error > max_p_error) {
- max_p_error = p_error;
- max_p_error_p = i;
- }
-// printf ("pres %d alt %d pres %d\n",
-// i, p_to_a, p_to_a_to_p);
- }
- for (i = -1578; i < 15835 + STEP; i += STEP) {
- if (i > 15835)
- i = 15835;
- a_to_p = ao_altitude_to_pres(i);
- a_to_p_to_a = ao_pres_to_altitude(a_to_p);
- a_error = i_abs(a_to_p_to_a - i);
- if (a_error > max_a_error) {
- max_a_error = a_error;
- max_a_error_a = i;
- }
-// printf ("alt %d pres %d alt %d\n",
-// i, a_to_p, a_to_p_to_a);
- }
- if (max_p_error > 2) {
- printf ("max p error %d at %d\n", max_p_error,
- max_p_error_p);
- ret++;
- }
- if (max_a_error > 1) {
- printf ("max a error %d at %d\n", max_a_error,
- max_a_error_a);
- ret++;
- }
- return ret;
-}
+++ /dev/null
-/*
- * Copyright © 2014 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#define scale(v,p,m) ((int32_t) (v) * (AO_ADC_REFERENCE_DV * ((p) + (m))) / (AO_ADC_MAX * (m)))
-
-int16_t
-ao_battery_decivolt(int16_t adc)
-{
- return scale(adc, AO_BATTERY_DIV_PLUS, AO_BATTERY_DIV_MINUS);
-}
-
-int16_t
-ao_ignite_decivolt(int16_t adc)
-{
- return scale(adc, AO_IGNITE_DIV_PLUS, AO_IGNITE_DIV_MINUS);
-}
-
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-#include <ao_data.h>
-
-volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING];
-volatile __data uint8_t ao_data_head;
-volatile __data uint8_t ao_data_present;
-
-#ifndef ao_data_count
-void
-ao_data_get(__xdata struct ao_data *packet)
-{
-#if HAS_FLIGHT
- uint8_t i = ao_data_ring_prev(ao_sample_data);
-#else
- uint8_t i = ao_data_ring_prev(ao_data_head);
-#endif
- memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));
-}
-#endif
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_DATA_H_
-#define _AO_DATA_H_
-
-#define GRAVITY 9.80665
-
-#if HAS_ADC
-#define AO_DATA_ADC (1 << 0)
-#else
-#define AO_DATA_ADC 0
-#endif
-
-#if HAS_MS5607
-#include <ao_ms5607.h>
-#define AO_DATA_MS5607 (1 << 1)
-#else
-#define AO_DATA_MS5607 0
-#endif
-
-#if HAS_MPU6000
-#include <ao_mpu6000.h>
-#define AO_DATA_MPU6000 (1 << 2)
-#else
-#define AO_DATA_MPU6000 0
-#endif
-
-#if HAS_HMC5883
-#include <ao_hmc5883.h>
-#define AO_DATA_HMC5883 (1 << 3)
-#else
-#define AO_DATA_HMC5883 0
-#endif
-
-#if HAS_MMA655X
-#include <ao_mma655x.h>
-#define AO_DATA_MMA655X (1 << 4)
-#else
-#define AO_DATA_MMA655X 0
-#endif
-
-#ifdef AO_DATA_RING
-
-#define AO_DATA_ALL (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X)
-
-struct ao_data {
- uint16_t tick;
-#if HAS_ADC
- struct ao_adc adc;
-#endif
-#if HAS_MS5607
- struct ao_ms5607_sample ms5607_raw;
- struct ao_ms5607_value ms5607_cooked;
-#endif
-#if HAS_MPU6000
- struct ao_mpu6000_sample mpu6000;
-#if !HAS_MMA655X
- int16_t z_accel;
-#endif
-#endif
-#if HAS_HMC5883
- struct ao_hmc5883_sample hmc5883;
-#endif
-#if HAS_MMA655X
- uint16_t mma655x;
-#endif
-};
-
-#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1))
-#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1))
-
-/* Get a copy of the last complete sample set */
-void
-ao_data_get(__xdata struct ao_data *packet);
-
-extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING];
-extern volatile __data uint8_t ao_data_head;
-extern volatile __data uint8_t ao_data_present;
-extern volatile __data uint8_t ao_data_count;
-
-/*
- * Mark a section of data as ready, check for data complete
- */
-#define AO_DATA_PRESENT(bit) (ao_data_present |= (bit))
-
-/*
- * Wait until it is time to write a sensor sample; this is
- * signaled by the timer tick
- */
-#define AO_DATA_WAIT() do { \
- ao_sleep(DATA_TO_XDATA ((void *) &ao_data_count)); \
- } while (0)
-
-#endif /* AO_DATA_RING */
-
-#if !HAS_BARO && HAS_MS5607
-
-/* Either an MS5607 or an MS5611 hooked to a SPI port
- */
-
-#define HAS_BARO 1
-
-typedef int32_t pres_t;
-
-#ifndef AO_ALT_TYPE
-#define AO_ALT_TYPE int32_t
-#endif
-
-typedef AO_ALT_TYPE alt_t;
-
-#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked)
-
-#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres)
-#define ao_data_temp(packet) ((packet)->ms5607_cooked.temp)
-
-#define pres_to_altitude(p) ao_pa_to_altitude(p)
-
-#endif
-
-#if !HAS_BARO && HAS_ADC
-
-#define HAS_BARO 1
-
-typedef int16_t pres_t;
-typedef int16_t alt_t;
-
-#define ao_data_pres(packet) ((packet)->adc.pres)
-#define ao_data_temp(packet) ((packet)->adc.temp)
-#define pres_to_altitude(p) ao_pres_to_altitude(p)
-#define ao_data_pres_cook(p)
-
-#endif
-
-#if !HAS_BARO
-typedef int16_t alt_t;
-#endif
-
-/*
- * Need a few macros to pull data from the sensors:
- *
- * ao_data_accel_sample - pull raw sensor and convert to normalized values
- * ao_data_accel - pull normalized value (lives in the same memory)
- * ao_data_set_accel - store normalized value back in the sensor location
- * ao_data_accel_invert - flip rocket ends for positive acceleration
- */
-
-#if HAS_ACCEL
-
-/* This section is for an analog accelerometer hooked to one of the ADC pins. As
- * those are 5V parts, this also requires that the 5V supply be hooked to to anothe ADC
- * pin so that the both can be measured to correct for changes between the 3.3V and 5V rails
- */
-
-typedef int16_t accel_t;
-#define ao_data_accel(packet) ((packet)->adc.accel)
-#define ao_data_set_accel(packet, a) ((packet)->adc.accel = (a))
-#define ao_data_accel_invert(a) (0x7fff -(a))
-
-/*
- * Ok, the math here is a bit tricky.
- *
- * ao_sample_accel: ADC output for acceleration
- * ao_accel_ref: ADC output for the 5V reference.
- * ao_cook_accel: Corrected acceleration value
- * Vcc: 3.3V supply to the CC1111
- * Vac: 5V supply to the accelerometer
- * accel: input voltage to accelerometer ADC pin
- * ref: input voltage to 5V reference ADC pin
- *
- *
- * Measured acceleration is ratiometric to Vcc:
- *
- * ao_sample_accel accel
- * ------------ = -----
- * 32767 Vcc
- *
- * Measured 5v reference is also ratiometric to Vcc:
- *
- * ao_accel_ref ref
- * ------------ = -----
- * 32767 Vcc
- *
- *
- * ao_accel_ref = 32767 * (ref / Vcc)
- *
- * Acceleration is measured ratiometric to the 5V supply,
- * so what we want is:
- *
- * ao_cook_accel accel
- * ------------- = -----
- * 32767 ref
- *
- *
- * accel Vcc
- * = ----- * ---
- * Vcc ref
- *
- * ao_sample_accel 32767
- * = ------------ * ------------
- * 32767 ao_accel_ref
- *
- * Multiply through by 32767:
- *
- * ao_sample_accel * 32767
- * ao_cook_accel = --------------------
- * ao_accel_ref
- *
- * Now, the tricky part. Getting this to compile efficiently
- * and keeping all of the values in-range.
- *
- * First off, we need to use a shift of 16 instead of * 32767 as SDCC
- * does the obvious optimizations for byte-granularity shifts:
- *
- * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref
- *
- * Next, lets check our input ranges:
- *
- * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion)
- * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff)
- *
- * Plugging in our input ranges, we get an output range of 0 - 0x12490,
- * which is 17 bits. That won't work. If we take the accel ref and shift
- * by a bit, we'll change its range:
- *
- * 0xe000 <= ao_accel_ref<<1 <= 0xfffe
- *
- * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1)
- *
- * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It
- * is, however, one bit too large for our signed computations. So, we
- * take the result and shift that by a bit:
- *
- * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1
- *
- * This finally creates an output range of 0 - 0x4924. As the ADC only
- * provides 11 bits of data, we haven't actually lost any precision,
- * just dropped a bit of noise off the low end.
- */
-
-#if HAS_ACCEL_REF
-
-#define ao_data_accel_cook(packet) \
- ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1)
-
-#else
-
-#define ao_data_accel_cook(packet) ((packet)->adc.accel)
-
-#endif /* HAS_ACCEL_REF */
-
-#endif /* HAS_ACCEL */
-
-#if !HAS_ACCEL && HAS_MMA655X
-
-#define HAS_ACCEL 1
-
-typedef int16_t accel_t;
-
-/* MMA655X is hooked up so that positive values represent negative acceleration */
-
-#define AO_ACCEL_INVERT 4095
-
-#define ao_data_accel(packet) ((packet)->mma655x)
-#if AO_MMA655X_INVERT
-#define ao_data_accel_cook(packet) (AO_ACCEL_INVERT - (packet)->mma655x)
-#else
-#define ao_data_accel_cook(packet) ((packet)->mma655x)
-#endif
-#define ao_data_set_accel(packet, accel) ((packet)->mma655x = (accel))
-#define ao_data_accel_invert(accel) (AO_ACCEL_INVERT - (accel))
-
-#endif
-
-#if !HAS_ACCEL && HAS_MPU6000
-
-#define HAS_ACCEL 1
-
-#define AO_ACCEL_INVERT 0
-
-typedef int16_t accel_t;
-
-/* MPU6000 is hooked up so that positive y is positive acceleration */
-#define ao_data_accel(packet) ((packet)->z_accel)
-#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y)
-#define ao_data_set_accel(packet, accel) ((packet)->z_accel = (accel))
-#define ao_data_accel_invert(a) (-(a))
-
-#endif
-
-#if !HAS_GYRO && HAS_MPU6000
-
-#define HAS_GYRO 1
-
-typedef int16_t gyro_t; /* in raw sample units */
-typedef int16_t angle_t; /* in degrees */
-
-/* Y axis is aligned with the direction of motion (along) */
-/* X axis is aligned in the other board axis (across) */
-/* Z axis is aligned perpendicular to the board (through) */
-
-#define ao_data_along(packet) ((packet)->mpu6000.accel_y)
-#define ao_data_across(packet) ((packet)->mpu6000.accel_x)
-#define ao_data_through(packet) ((packet)->mpu6000.accel_z)
-
-#define ao_data_roll(packet) ((packet)->mpu6000.gyro_y)
-#define ao_data_pitch(packet) ((packet)->mpu6000.gyro_x)
-#define ao_data_yaw(packet) ((packet)->mpu6000.gyro_z)
-
-#endif
-
-#if !HAS_MAG && HAS_HMC5883
-
-#define HAS_MAG 1
-
-typedef int16_t ao_mag_t; /* in raw sample units */
-
-#define ao_data_mag_along(packet) ((packet)->hmc5883.x)
-#define ao_data_mag_across(packet) ((packet)->hmc5883.y)
-#define ao_data_mag_through(packet) ((packet)->hmc5883.z)
-
-#endif
-
-#endif /* _AO_DATA_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_DBG_H_
-#define _AO_DBG_H_
-
-/*
- * ao_dbg.c
- *
- * debug another telemetrum board
- */
-
-/* Send a byte to the dbg target */
-void
-ao_dbg_send_byte(uint8_t byte);
-
-/* Receive a byte from the dbg target */
-uint8_t
-ao_dbg_recv_byte(void);
-
-/* Start a bulk transfer to/from dbg target memory */
-void
-ao_dbg_start_transfer(uint16_t addr);
-
-/* End a bulk transfer to/from dbg target memory */
-void
-ao_dbg_end_transfer(void);
-
-/* Write a byte to dbg target memory */
-void
-ao_dbg_write_byte(uint8_t byte);
-
-/* Read a byte from dbg target memory */
-uint8_t
-ao_dbg_read_byte(void);
-
-/* Enable dbg mode, switching use of the pins */
-void
-ao_dbg_debug_mode(void);
-
-/* Reset the dbg target */
-void
-ao_dbg_reset(void);
-
-void
-ao_dbg_init(void);
-
-#endif /* _AO_DBG_H_ */
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-#include <ao_debounce.h>
-#include <ao_fast_timer.h>
-
-static uint8_t ao_debounce_initialized;
-static uint8_t ao_debounce_running;
-static struct ao_debounce *ao_debounce;
-
-static uint8_t values[64];
-static uint8_t n;
-
-#define d_step(n) (((n) + 1) & 63)
-
-static void
-_ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
-{
- if (value != debounce->value) {
- values[n] = value;
- n = (n + 1) & 63;
- debounce->value = value;
- debounce->_set(debounce, value);
- }
- _ao_debounce_stop(debounce);
-}
-
-void
-ao_debounce_dump(void)
-{
- uint8_t s;
-
- for (s = 0; s < n; s++) {
- printf ("%d: %d\n",
- s, values[s]);
- }
- n = 0;
-}
-
-/*
- * Get the current value, set the result when we've
- * reached the debounce count limit
- */
-static void
-_ao_debounce_check(struct ao_debounce *debounce)
-{
- uint8_t next = debounce->_get(debounce);
-
- if (next == debounce->current) {
- if (debounce->count < debounce->hold) {
- if (++debounce->count == debounce->hold)
- _ao_debounce_set(debounce, debounce->current);
- }
- } else {
- debounce->count = 0;
- debounce->current = next;
- }
-}
-
-static void
-_ao_debounce_isr(void)
-{
- struct ao_debounce *debounce, *next;
-
- for (debounce = ao_debounce; debounce; debounce = next) {
- next = debounce->next;
- _ao_debounce_check(debounce);
- }
-}
-
-static void
-ao_debounce_on(void)
-{
- ao_fast_timer_on(_ao_debounce_isr);
-}
-
-static void
-ao_debounce_off(void)
-{
- ao_fast_timer_off(_ao_debounce_isr);
-}
-
-/*
- * Start monitoring one pin
- */
-void
-_ao_debounce_start(struct ao_debounce *debounce)
-{
- uint32_t m;
-
- m = ao_arch_irqsave();
- if (!debounce->running) {
- debounce->running = 1;
-
- /* Reset the counter */
- debounce->count = 0;
-
- /* Link into list */
- debounce->next = ao_debounce;
- ao_debounce = debounce;
-
- /* Make sure the timer is running */
- if (!ao_debounce_running++)
- ao_debounce_on();
-
- /* And go check the current value */
- _ao_debounce_check(debounce);
- }
- ao_arch_irqrestore(m);
-}
-
-/*
- * Stop monitoring one pin
- */
-void
-_ao_debounce_stop(struct ao_debounce *debounce)
-{
- struct ao_debounce **prev;
- uint32_t m;
-
- m = ao_arch_irqsave();
- if (debounce->running) {
- debounce->running = 0;
-
- /* Unlink */
- for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) {
- if (*prev == debounce) {
- *prev = debounce->next;
- break;
- }
- }
- debounce->next = NULL;
-
- /* Turn off the timer if possible */
- if (!--ao_debounce_running)
- ao_debounce_off();
- }
- ao_arch_irqrestore(m);
-}
-
-void
-ao_debounce_init(void)
-{
- if (ao_debounce_initialized)
- return;
- ao_debounce_initialized = 1;
- ao_fast_timer_init();
-}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_DEBOUNCE_H_
-#define _AO_DEBOUNCE_H_
-
-struct ao_debounce {
- struct ao_debounce *next;
-
- /* time that pin value must be stable before accepting */
- uint8_t hold;
-
- /* last value reported to app; don't report it twice */
- uint8_t value;
-
- /* current value received from pins */
- uint8_t current;
-
- /* current count of intervals pin value has been stable */
- uint8_t count;
-
- /* This pin is running */
- uint8_t running;
-
- /* Get the current pin value */
- uint8_t (*_get)(struct ao_debounce *debounce);
-
- /* The stable value has changed */
- void (*_set)(struct ao_debounce *debounce, uint8_t value);
-};
-
-static inline void
-ao_debounce_config(struct ao_debounce *debounce,
- uint8_t (*_get)(struct ao_debounce *debounce),
- void (*_set)(struct ao_debounce *debounce, uint8_t value),
- uint8_t hold)
-{
- debounce->next = 0;
- debounce->hold = hold;
- debounce->value = 0xff;
- debounce->current = 0xff;
- debounce->count = 0;
- debounce->running = 0;
- debounce->_get = _get;
- debounce->_set = _set;
-}
-
-void
-_ao_debounce_start(struct ao_debounce *debounce);
-
-void
-_ao_debounce_stop(struct ao_debounce *debounce);
-
-void
-ao_debounce_init(void);
-
-void
-ao_debounce_dump(void);
-
-#endif /* _AO_DEBOUNCE_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/*
- * For hardware without eeprom, the config code still
- * wants to call these functions
- */
-uint8_t
-ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
-{
- (void) buf;
- (void) len;
- return 1;
-}
-
-uint8_t
-ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
-{
- ao_xmemset(buf, '\0', len);
- return 1;
-}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_EEPROM_H_
-#define _AO_EEPROM_H_
-
-extern const ao_pos_t ao_eeprom_total;
-
-/*
- * Write to eeprom
- */
-
-uint8_t
-ao_eeprom_write(ao_pos_t pos32, __xdata void *v, uint16_t len);
-
-/*
- * Read from eeprom
- */
-uint8_t
-ao_eeprom_read(ao_pos_t pos, __xdata void *v, uint16_t len);
-
-/*
- * Initialize eeprom
- */
-
-void
-ao_eeprom_init(void);
-
-#endif /* _AO_EEPROM_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_FEC_H_
-#define _AO_FEC_H_
-
-#include <stdint.h>
-
-#define AO_FEC_CRC_INIT 0xffff
-#define AO_FEC_TRELLIS_TERMINATOR 0x0b
-#define AO_FEC_PREPARE_EXTRA 4
-
-extern const uint8_t ao_fec_whiten_table[];
-
-#if AO_FEC_DEBUG
-void
-ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name);
-#endif
-
-static inline uint16_t
-ao_fec_crc_byte(uint8_t byte, uint16_t crc)
-{
- uint8_t bit;
-
- for (bit = 0; bit < 8; bit++) {
- if (((crc & 0x8000) >> 8) ^ (byte & 0x80))
- crc = (crc << 1) ^ 0x8005;
- else
- crc = (crc << 1);
- byte <<= 1;
- }
- return crc;
-}
-
-uint16_t
-ao_fec_crc(const uint8_t *bytes, uint8_t len);
-
-/*
- * 'len' is the length of the original data; 'bytes'
- * must be four bytes longer than that, and the first
- * two after 'len' must be the received crc
- */
-uint8_t
-ao_fec_check_crc(const uint8_t *bytes, uint8_t len);
-
-/*
- * Compute CRC, whiten, convolve and interleave data. 'out' must be (len + 4) * 2 bytes long
- */
-uint8_t
-ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out);
-
-/*
- * Decode data. 'in' is one byte per bit, soft decision
- * 'out' must be len/8 bytes long
- */
-
-#define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */
-
-#define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */
-
-uint8_t
-ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void));
-
-/*
- * Interleave data packed in bytes. 'out' must be 'len' bytes long.
- */
-uint16_t
-ao_fec_interleave_bytes(uint8_t *in, uint16_t len, uint8_t *out);
-
-#endif /* _AO_FEC_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao_fec.h>
-#include <stdio.h>
-
-#ifdef TELEMEGA
-#include <ao.h>
-#endif
-
-#if AO_PROFILE
-#include <ao_profile.h>
-
-uint32_t ao_fec_decode_start, ao_fec_decode_end;
-#endif
-
-/*
- * byte order repeats through 3 2 1 0
- *
- * bit-pair order repeats through
- *
- * 1/0 3/2 5/4 7/6
- *
- * So, the over all order is:
- *
- * 3,1/0 2,1/0 1,1/0 0,1/0
- * 3,3/2 2,3/2 1,3/2 0,3/2
- * 3,5/4 2,5/4 1,5/4 0,5/4
- * 3,7/6 2,7/6 1,7/6 0,7/6
- *
- * The raw bit order is thus
- *
- * 1e/1f 16/17 0e/0f 06/07
- * 1c/1d 14/15 0c/0d 04/05
- * 1a/1b 12/13 0a/0b 02/03
- * 18/19 10/11 08/09 00/01
- */
-
-static const uint8_t ao_interleave_order[] = {
- 0x1e, 0x16, 0x0e, 0x06,
- 0x1c, 0x14, 0x0c, 0x04,
- 0x1a, 0x12, 0x0a, 0x02,
- 0x18, 0x10, 0x08, 0x00
-};
-
-static inline uint16_t ao_interleave_index(uint16_t i) {
- return (i & ~0x1e) | ao_interleave_order[(i & 0x1e) >> 1];
-}
-
-#define NUM_STATE 8
-#define NUM_HIST 24
-
-typedef uint32_t bits_t;
-
-#define V_0 0xff
-#define V_1 0x00
-
-/*
- * These are just the 'zero' states; the 'one' states mirror them
- */
-static const uint8_t ao_fec_decode_table[NUM_STATE*2] = {
- V_0, V_0, /* 000 */
- V_0, V_1, /* 001 */
- V_1, V_1, /* 010 */
- V_1, V_0, /* 011 */
- V_1, V_1, /* 100 */
- V_1, V_0, /* 101 */
- V_0, V_0, /* 110 */
- V_0, V_1 /* 111 */
-};
-
-static inline uint8_t
-ao_next_state(uint8_t state, uint8_t bit)
-{
- return ((state << 1) | bit) & 0x7;
-}
-
-/*
- * 'in' is 8-bits per symbol soft decision data
- * 'len' is input byte length. 'out' must be
- * 'len'/16 bytes long
- */
-
-uint8_t
-ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void))
-{
- static uint32_t cost[2][NUM_STATE]; /* path cost */
- static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */
-
- uint16_t i; /* input byte index */
- uint16_t b; /* encoded symbol index (bytes/2) */
- uint16_t o; /* output bit index */
- uint8_t p; /* previous cost/bits index */
- uint8_t n; /* next cost/bits index */
- uint8_t state; /* state index */
- const uint8_t *whiten = ao_fec_whiten_table;
- uint16_t interleave; /* input byte array index */
- uint8_t s0, s1;
- uint16_t avail;
- uint16_t crc = AO_FEC_CRC_INIT;
-#if AO_PROFILE
- uint32_t start_tick;
-#endif
-
- p = 0;
- for (state = 0; state < NUM_STATE; state++) {
- cost[0][state] = 0x7fffffff;
- bits[0][state] = 0;
- }
- cost[0][0] = 0;
-
- if (callback)
- avail = 0;
- else
- avail = len;
-
-#if AO_PROFILE
- if (!avail) {
- avail = callback();
- if (!avail)
- return 0;
- }
- start_tick = ao_profile_tick();
-#endif
- o = 0;
- for (i = 0; i < len; i += 2) {
- b = i/2;
- n = p ^ 1;
-
- if (!avail) {
- avail = callback();
- if (!avail)
- return 0;
- }
-
- /* Fetch one pair of input bytes, de-interleaving
- * the input.
- */
- interleave = ao_interleave_index(i);
- s0 = in[interleave];
- s1 = in[interleave+1];
-
- avail -= 2;
-
- /* Compute path costs and accumulate output bit path
- * for each state and encoded bit value. Unrolling
- * this loop is worth about > 30% performance boost.
- * Decoding 76-byte remote access packets is reduced
- * from 14.700ms to 9.3ms. Redoing the loop to
- * directly compare the two pasts for each future state
- * reduces this down to 5.7ms
- */
-
- /* Ok, of course this is tricky, it's optimized.
- *
- * First, it's important to realize that we have 8
- * states representing the combinations of the three
- * most recent bits from the encoder. Flipping any
- * of these three bits flips both output bits.
- *
- * 'state<<1' represents the target state for a new
- * bit value of 0. '(state<<1)+1' represents the
- * target state for a new bit value of 1.
- *
- * 'state' is the previous state with an oldest bit
- * value of 0. 'state + 4' is the previous state with
- * an oldest bit value of 1. These two states will
- * either lead to 'state<<1' or '(state<<1)+1', depending
- * on whether the next encoded bit was a zero or a one.
- *
- * m0 and m1 are the cost of coming to 'state<<1' from
- * one of the two possible previous states 'state' and
- * 'state + 4'.
- *
- * Because we know the expected values of each
- * received bit are flipped between these two previous
- * states:
- *
- * bitcost(state+4) = 510 - bitcost(state)
- *
- * With those two total costs in hand, we then pick
- * the lower as the cost of the 'state<<1', and compute
- * the path of bits leading to that state.
- *
- * Then, do the same for '(state<<1) + 1'. This time,
- * instead of computing the m0 and m1 values from
- * scratch, because the only difference is that we're
- * expecting a one bit instead of a zero bit, we just
- * flip the bitcost values around to match the
- * expected transmitted bits with some tricky
- * arithmetic which is equivalent to:
- *
- * m0 = cost[p][state] + (510 - bitcost);
- * m1 = cost[p][state+4] + bitcost
- *
- * Then, the lowest cost and bit trace of the new state
- * is saved.
- */
-
-#define DO_STATE(state) { \
- uint32_t bitcost; \
- \
- uint32_t m0; \
- uint32_t m1; \
- uint32_t bit; \
- \
- bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \
- (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)|1])); \
- \
- m0 = cost[p][state] + bitcost; \
- m1 = cost[p][state+4] + (510 - bitcost); \
- bit = m0 > m1; \
- cost[n][state<<1] = bit ? m1 : m0; \
- bits[n][state<<1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \
- \
- m0 -= (bitcost+bitcost-510); \
- m1 += (bitcost+bitcost-510); \
- bit = m0 > m1; \
- cost[n][(state<<1)+1] = bit ? m1 : m0; \
- bits[n][(state<<1)+1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \
- }
-
- DO_STATE(0);
- DO_STATE(1);
- DO_STATE(2);
- DO_STATE(3);
-
-#if 0
- printf ("bit %3d symbol %2x %2x:", i/2, s0, s1);
- for (state = 0; state < NUM_STATE; state++) {
- printf (" %8u(%08x)", cost[n][state], bits[n][state]);
- }
- printf ("\n");
-#endif
- p = n;
-
- /* A loop is needed to handle the last output byte. It
- * won't have any bits of future data to perform full
- * error correction, but we might as well give the
- * best possible answer anyways.
- */
- while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) {
-
- /* Compute number of bits to the end of the
- * last full byte of data. This is generally
- * NUM_HIST, unless we've reached
- * the end of the input, in which case
- * it will be seven.
- */
- int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */
- uint32_t min_cost; /* lowest cost */
- uint8_t min_state; /* lowest cost state */
- uint8_t byte;
-
- /* Find the best fit at the current point
- * of the decode.
- */
- min_cost = cost[p][0];
- min_state = 0;
- for (state = 1; state < NUM_STATE; state++) {
- if (cost[p][state] < min_cost) {
- min_cost = cost[p][state];
- min_state = state;
- }
- }
-
- /* The very last byte of data has the very last bit
- * of data left in the state value; just smash the
- * bits value in place and reset the 'dist' from
- * -1 to 0 so that the full byte is read out
- */
- if (dist < 0) {
- bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1);
- dist = 0;
- }
-
-#if 0
- printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n",
- i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten);
-#endif
- byte = (bits[p][min_state] >> dist) ^ *whiten++;
- *out++ = byte;
- if (out_len > 2)
- crc = ao_fec_crc_byte(byte, crc);
-
- if (!--out_len) {
- if ((out[-2] == (uint8_t) (crc >> 8)) &&
- out[-1] == (uint8_t) crc)
- out[-1] = AO_FEC_DECODE_CRC_OK;
- else
- out[-1] = 0;
- out[-2] = 0;
- goto done;
- }
- o += 8;
- }
- }
-done:
-#if AO_PROFILE
- ao_fec_decode_start = start_tick;
- ao_fec_decode_end = ao_profile_tick();
-#endif
- return 1;
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao_fec.h>
-#include <stdio.h>
-
-#if AO_FEC_DEBUG
-void
-ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name)
-{
- uint16_t i;
-
- printf ("%s (%d):", name, len);
- for (i = 0; i < len; i++) {
- if ((i & 7) == 0)
- printf ("\n\t%02x:", i);
- printf(" %02x", bytes[i]);
- }
- printf ("\n");
-}
-#endif
-
-uint16_t
-ao_fec_crc(const uint8_t *bytes, uint8_t len)
-{
- uint16_t crc = AO_FEC_CRC_INIT;
-
- while (len--)
- crc = ao_fec_crc_byte(*bytes++, crc);
- return crc;
-}
-
-/*
- * len is the length of the data; the crc will be
- * the fist two bytes after that
- */
-
-uint8_t
-ao_fec_check_crc(const uint8_t *bytes, uint8_t len)
-{
- uint16_t computed_crc = ao_fec_crc(bytes, len);
- uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]);
-
- return computed_crc == received_crc;
-}
-
-/*
- * Compute CRC and trellis-terminator/interleave-pad bytes
- */
-static uint8_t
-ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra)
-{
- uint16_t crc = ao_fec_crc (in, len);
- uint8_t i = 0;
- uint8_t num_fec;
-
- /* Append CRC */
- extra[i++] = crc >> 8;
- extra[i++] = crc;
-
- /* Append FEC -- 1 byte if odd, two bytes if even */
- num_fec = 2 - (i & 1);
- while (num_fec--)
- extra[i++] = AO_FEC_TRELLIS_TERMINATOR;
- return i;
-}
-
-const uint8_t ao_fec_whiten_table[] = {
-#include "ao_whiten.h"
-};
-
-static const uint8_t ao_fec_encode_table[16] = {
-/* next 0 1 state */
- 0, 3, /* 000 */
- 1, 2, /* 001 */
- 3, 0, /* 010 */
- 2, 1, /* 011 */
- 3, 0, /* 100 */
- 2, 1, /* 101 */
- 0, 3, /* 110 */
- 1, 2 /* 111 */
-};
-
-uint8_t
-ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out)
-{
- uint8_t extra[AO_FEC_PREPARE_EXTRA];
- uint8_t extra_len;
- uint32_t encode, interleave;
- uint8_t pair, byte, bit;
- uint16_t fec = 0;
- const uint8_t *whiten = ao_fec_whiten_table;
-
- extra_len = ao_fec_prepare(in, len, extra);
- for (pair = 0; pair < len + extra_len; pair += 2) {
- encode = 0;
- for (byte = 0; byte < 2; byte++) {
- if (pair + byte == len)
- in = extra;
- fec |= *in++ ^ *whiten++;
- for (bit = 0; bit < 8; bit++) {
- encode = encode << 2 | ao_fec_encode_table[fec >> 7];
- fec = (fec << 1) & 0x7ff;
- }
- }
-
- interleave = 0;
- for (bit = 0; bit < 4 * 4; bit++) {
- uint8_t byte_shift = (bit & 0x3) << 3;
- uint8_t bit_shift = (bit & 0xc) >> 1;
-
- interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3);
- }
- *out++ = interleave >> 24;
- *out++ = interleave >> 16;
- *out++ = interleave >> 8;
- *out++ = interleave >> 0;
- }
- return (len + extra_len) * 2;
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#include <ao_log.h>
-#endif
-
-#if HAS_MPU6000
-#include <ao_quaternion.h>
-#endif
-
-#ifndef HAS_ACCEL
-#error Please define HAS_ACCEL
-#endif
-
-#ifndef HAS_GPS
-#error Please define HAS_GPS
-#endif
-
-#ifndef HAS_USB
-#error Please define HAS_USB
-#endif
-
-#ifndef HAS_TELEMETRY
-#define HAS_TELEMETRY HAS_RADIO
-#endif
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state ao_flight_state; /* current flight state */
-__pdata uint16_t ao_boost_tick; /* time of launch detect */
-__pdata uint16_t ao_motor_number; /* number of motors burned so far */
-
-#if HAS_SENSOR_ERRORS
-/* Any sensor can set this to mark the flight computer as 'broken' */
-__xdata uint8_t ao_sensor_errors;
-#endif
-
-/*
- * track min/max data over a long interval to detect
- * resting
- */
-static __data uint16_t ao_interval_end;
-static __data int16_t ao_interval_min_height;
-static __data int16_t ao_interval_max_height;
-#if HAS_ACCEL
-static __data int16_t ao_coast_avg_accel;
-#endif
-
-__pdata uint8_t ao_flight_force_idle;
-
-/* We also have a clock, which can be used to sanity check things in
- * case of other failures
- */
-
-#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15)
-
-/* Landing is detected by getting constant readings from both pressure and accelerometer
- * for a fairly long time (AO_INTERVAL_TICKS)
- */
-#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10)
-
-#define abs(a) ((a) < 0 ? -(a) : (a))
-
-void
-ao_flight(void)
-{
- ao_sample_init();
- ao_flight_state = ao_flight_startup;
- for (;;) {
-
- /*
- * Process ADC samples, just looping
- * until the sensors are calibrated.
- */
- if (!ao_sample())
- continue;
-
- switch (ao_flight_state) {
- case ao_flight_startup:
-
- /* Check to see what mode we should go to.
- * - Invalid mode if accel cal appears to be out
- * - pad mode if we're upright,
- * - idle mode otherwise
- */
-#if HAS_ACCEL
- if (ao_config.accel_plus_g == 0 ||
- ao_config.accel_minus_g == 0 ||
- ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
- ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP ||
- ao_ground_height < -1000 ||
- ao_ground_height > 7000)
- {
- /* Detected an accel value outside -1.5g to 1.5g
- * (or uncalibrated values), so we go into invalid mode
- */
- ao_flight_state = ao_flight_invalid;
-
-#if HAS_RADIO && PACKET_HAS_SLAVE
- /* Turn on packet system in invalid mode on TeleMetrum */
- ao_packet_slave_start();
-#endif
- } else
-#endif
- if (!ao_flight_force_idle
-#if HAS_ACCEL
- && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP
-#endif
- )
- {
- /* Set pad mode - we can fly! */
- ao_flight_state = ao_flight_pad;
-#if HAS_USB && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE
- /* Disable the USB controller in flight mode
- * to save power
- */
- ao_usb_disable();
-#endif
-
-#if !HAS_ACCEL && PACKET_HAS_SLAVE
- /* Disable packet mode in pad state on TeleMini */
- ao_packet_slave_stop();
-#endif
-
-#if HAS_TELEMETRY
- /* Turn on telemetry system */
- ao_rdf_set(1);
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
-#endif
-#if AO_LED_RED
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
-#endif
- } else {
- /* Set idle mode */
- ao_flight_state = ao_flight_idle;
-#if HAS_SENSOR_ERRORS
- if (ao_sensor_errors)
- ao_flight_state = ao_flight_invalid;
-#endif
-
-#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE
- /* Turn on packet system in idle mode on TeleMetrum */
- ao_packet_slave_start();
-#endif
-
-#if AO_LED_RED
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
-#endif
- }
- /* wakeup threads due to state change */
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-
- break;
- case ao_flight_pad:
-
- /* pad to boost:
- *
- * barometer: > 20m vertical motion
- * OR
- * accelerometer: > 2g AND velocity > 5m/s
- *
- * The accelerometer should always detect motion before
- * the barometer, but we use both to make sure this
- * transition is detected. If the device
- * doesn't have an accelerometer, then ignore the
- * speed and acceleration as they are quite noisy
- * on the pad.
- */
- if (ao_height > AO_M_TO_HEIGHT(20)
-#if HAS_ACCEL
- || (ao_accel > AO_MSS_TO_ACCEL(20) &&
- ao_speed > AO_MS_TO_SPEED(5))
-#endif
- )
- {
- ao_flight_state = ao_flight_boost;
- ao_boost_tick = ao_sample_tick;
-
- /* start logging data */
- ao_log_start();
-
-#if HAS_TELEMETRY
- /* Increase telemetry rate */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);
-
- /* disable RDF beacon */
- ao_rdf_set(0);
-#endif
-
-#if HAS_GPS
- /* Record current GPS position by waking up GPS log tasks */
- ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING;
- ao_wakeup(&ao_gps_new);
-#endif
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
- case ao_flight_boost:
-
- /* boost to fast:
- *
- * accelerometer: start to fall at > 1/4 G
- * OR
- * time: boost for more than 15 seconds
- *
- * Detects motor burn out by the switch from acceleration to
- * deceleration, or by waiting until the maximum burn duration
- * (15 seconds) has past.
- */
- if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) ||
- (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX)
- {
-#if HAS_ACCEL
- ao_flight_state = ao_flight_fast;
- ao_coast_avg_accel = ao_accel;
-#else
- ao_flight_state = ao_flight_coast;
-#endif
- ++ao_motor_number;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
-#if HAS_ACCEL
- case ao_flight_fast:
- /*
- * This is essentially the same as coast,
- * but the barometer is being ignored as
- * it may be unreliable.
- */
- if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED))
- {
- ao_flight_state = ao_flight_coast;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- } else
- goto check_re_boost;
- break;
-#endif
- case ao_flight_coast:
-
- /*
- * By customer request - allow the user
- * to lock out apogee detection for a specified
- * number of seconds.
- */
- if (ao_config.apogee_lockout) {
- if ((ao_sample_tick - ao_boost_tick) <
- AO_SEC_TO_TICKS(ao_config.apogee_lockout))
- break;
- }
-
- /* apogee detect: coast to drogue deploy:
- *
- * speed: < 0
- *
- * Also make sure the model altitude is tracking
- * the measured altitude reasonably closely; otherwise
- * we're probably transsonic.
- */
- if (ao_speed < 0
-#if !HAS_ACCEL
- && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)
-#endif
- )
- {
-#if HAS_IGNITE
- /* ignite the drogue charge */
- ao_ignite(ao_igniter_drogue);
-#endif
-
-#if HAS_TELEMETRY
- /* slow down the telemetry system */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
-
- /* Turn the RDF beacon back on */
- ao_rdf_set(1);
-#endif
-
- /* and enter drogue state */
- ao_flight_state = ao_flight_drogue;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
-#if HAS_ACCEL
- else {
- check_re_boost:
- ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6);
- if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) {
- ao_boost_tick = ao_sample_tick;
- ao_flight_state = ao_flight_boost;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- }
-#endif
-
- break;
- case ao_flight_drogue:
-
- /* drogue to main deploy:
- *
- * barometer: reach main deploy altitude
- *
- * Would like to use the accelerometer for this test, but
- * the orientation of the flight computer is unknown after
- * drogue deploy, so we ignore it. Could also detect
- * high descent rate using the pressure sensor to
- * recognize drogue deploy failure and eject the main
- * at that point. Perhaps also use the drogue sense lines
- * to notice continutity?
- */
- if (ao_height <= ao_config.main_deploy)
- {
-#if HAS_IGNITE
- ao_ignite(ao_igniter_main);
-#endif
-
- /*
- * Start recording min/max height
- * to figure out when the rocket has landed
- */
-
- /* initialize interval values */
- ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
-
- ao_interval_min_height = ao_interval_max_height = ao_avg_height;
-
- ao_flight_state = ao_flight_main;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
-
- /* fall through... */
- case ao_flight_main:
-
- /* main to land:
- *
- * barometer: altitude stable
- */
-
- if (ao_avg_height < ao_interval_min_height)
- ao_interval_min_height = ao_avg_height;
- if (ao_avg_height > ao_interval_max_height)
- ao_interval_max_height = ao_avg_height;
-
- if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
- if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4))
- {
- ao_flight_state = ao_flight_landed;
-
- /* turn off the ADC capture */
- ao_timer_set_adc_interval(0);
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- ao_interval_min_height = ao_interval_max_height = ao_avg_height;
- ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
- }
- break;
-#if HAS_FLIGHT_DEBUG
- case ao_flight_test:
-#if HAS_GYRO
- printf ("angle %4d pitch %7d yaw %7d roll %7d\n",
- ao_sample_orient,
- ((ao_sample_pitch << 9) - ao_ground_pitch) >> 9,
- ((ao_sample_yaw << 9) - ao_ground_yaw) >> 9,
- ((ao_sample_roll << 9) - ao_ground_roll) >> 9);
-#endif
- flush();
- break;
-#endif /* HAS_FLIGHT_DEBUG */
- default:
- break;
- }
- }
-}
-
-#if HAS_FLIGHT_DEBUG
-static inline int int_part(int16_t i) { return i >> 4; }
-static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; }
-
-static void
-ao_flight_dump(void)
-{
-#if HAS_ACCEL
- int16_t accel;
-
- accel = ((ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale) >> 16;
-#endif
-
- printf ("sample:\n");
- printf (" tick %d\n", ao_sample_tick);
- printf (" raw pres %d\n", ao_sample_pres);
-#if HAS_ACCEL
- printf (" raw accel %d\n", ao_sample_accel);
-#endif
- printf (" ground pres %d\n", ao_ground_pres);
- printf (" ground alt %d\n", ao_ground_height);
-#if HAS_ACCEL
- printf (" raw accel %d\n", ao_sample_accel);
- printf (" groundaccel %d\n", ao_ground_accel);
- printf (" accel_2g %d\n", ao_accel_2g);
-#endif
-
- printf (" alt %d\n", ao_sample_alt);
- printf (" height %d\n", ao_sample_height);
-#if HAS_ACCEL
- printf (" accel %d.%02d\n", int_part(accel), frac_part(accel));
-#endif
-
-
- printf ("kalman:\n");
- printf (" height %d\n", ao_height);
- printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed));
- printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel));
- printf (" max_height %d\n", ao_max_height);
- printf (" avg_height %d\n", ao_avg_height);
- printf (" error_h %d\n", ao_error_h);
- printf (" error_avg %d\n", ao_error_h_sq_avg);
-}
-
-static void
-ao_gyro_test(void)
-{
- ao_flight_state = ao_flight_test;
- ao_getchar();
- ao_flight_state = ao_flight_idle;
-}
-
-uint8_t ao_orient_test;
-
-static void
-ao_orient_test_select(void)
-{
- ao_orient_test = !ao_orient_test;
-}
-
-__code struct ao_cmds ao_flight_cmds[] = {
- { ao_flight_dump, "F\0Dump flight status" },
- { ao_gyro_test, "G\0Test gyro code" },
- { ao_orient_test_select,"O\0Test orientation code" },
- { 0, NULL },
-};
-#endif
-
-static __xdata struct ao_task flight_task;
-
-void
-ao_flight_init(void)
-{
- ao_flight_state = ao_flight_startup;
-#if HAS_FLIGHT_DEBUG
- ao_cmd_register(&ao_flight_cmds[0]);
-#endif
- ao_add_task(&flight_task, ao_flight, "flight");
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_FLIGHT_H_
-#define _AO_FLIGHT_H_
-
-
-/*
- * ao_flight.c
- */
-
-enum ao_flight_state {
- ao_flight_startup = 0,
- ao_flight_idle = 1,
- ao_flight_pad = 2,
- ao_flight_boost = 3,
- ao_flight_fast = 4,
- ao_flight_coast = 5,
- ao_flight_drogue = 6,
- ao_flight_main = 7,
- ao_flight_landed = 8,
- ao_flight_invalid = 9,
- ao_flight_test = 10
-};
-
-extern __pdata enum ao_flight_state ao_flight_state;
-extern __pdata uint16_t ao_boost_tick;
-extern __pdata uint16_t ao_motor_number;
-
-#if HAS_IMU || HAS_MMA655X
-#define HAS_SENSOR_ERRORS 1
-#endif
-
-#if HAS_SENSOR_ERRORS
-extern __xdata uint8_t ao_sensor_errors;
-#endif
-
-extern __pdata uint16_t ao_launch_time;
-extern __pdata uint8_t ao_flight_force_idle;
-
-/* Flight thread */
-void
-ao_flight(void);
-
-/* Initialize flight thread */
-void
-ao_flight_init(void);
-
-/*
- * ao_flight_nano.c
- */
-
-void
-ao_flight_nano_init(void);
-
-#endif /* _AO_FLIGHT_H_ */
+++ /dev/null
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state ao_flight_state; /* current flight state */
-__pdata uint16_t ao_launch_tick; /* time of launch detect */
-
-/*
- * track min/max data over a long interval to detect
- * resting
- */
-__pdata uint16_t ao_interval_end;
-__pdata alt_t ao_interval_min_height;
-__pdata alt_t ao_interval_max_height;
-
-__pdata uint8_t ao_flight_force_idle;
-
-/* Landing is detected by getting constant readings from both pressure and accelerometer
- * for a fairly long time (AO_INTERVAL_TICKS)
- */
-#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5)
-
-static void
-ao_flight_nano(void)
-{
- ao_sample_init();
- ao_flight_state = ao_flight_startup;
-
- for (;;) {
- /*
- * Process ADC samples, just looping
- * until the sensors are calibrated.
- */
- if (!ao_sample())
- continue;
-
- switch (ao_flight_state) {
- case ao_flight_startup:
- if (ao_flight_force_idle) {
- /* Set idle mode */
- ao_flight_state = ao_flight_idle;
- } else {
- ao_flight_state = ao_flight_pad;
- /* Disable packet mode in pad state */
- ao_packet_slave_stop();
-
- /* Turn on telemetry system */
- ao_rdf_set(1);
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
- }
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
-
- /* wakeup threads due to state change */
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- break;
- case ao_flight_pad:
- if (ao_height> AO_M_TO_HEIGHT(20)) {
- ao_flight_state = ao_flight_drogue;
- ao_launch_tick = ao_sample_tick;
-
- /* start logging data */
- ao_log_start();
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
- case ao_flight_drogue:
- /* drogue/main to land:
- *
- * barometer: altitude stable
- */
-
- if (ao_height < ao_interval_min_height)
- ao_interval_min_height = ao_height;
- if (ao_height > ao_interval_max_height)
- ao_interval_max_height = ao_height;
-
- if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
- if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5))
- {
- ao_flight_state = ao_flight_landed;
-
- /* turn off the ADC capture */
- ao_timer_set_adc_interval(0);
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- ao_interval_min_height = ao_interval_max_height = ao_height;
- ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
- }
- break;
- }
- }
-}
-
-static __xdata struct ao_task flight_task;
-
-void
-ao_flight_nano_init(void)
-{
- ao_flight_state = ao_flight_startup;
- ao_add_task(&flight_task, ao_flight_nano, "flight");
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-
-/*
- * The provided 'calibration' value is
- * that needed to tune the radio to precisely 434550kHz.
- * Use that to 'walk' to the target frequency by following
- * a 'bresenham' line from 434550kHz to the target
- * frequency, and updating the radio setting along the way
- */
-
-int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant
-{
- static __pdata int32_t set;
- static __pdata uint8_t neg;
- static __pdata int32_t error;
-
- set = 0;
- neg = 0;
- error = -434550 / 2;
-
- if ((freq -= 434550) < 0) {
- neg = 1;
- freq = -freq;
- }
- for (;;) {
- if (error > 0) {
- error -= 434550;
- set++;
- } else {
- error += cal;
- if (--freq < 0)
- break;
- }
- }
- if (neg)
- set = -set;
- return cal + set;
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_GPS_TEST
-#include "ao.h"
-#endif
-#include "ao_telem.h"
-
-void
-ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
-{
- char state;
-
- if (gps_data->flags & AO_GPS_VALID)
- state = AO_TELEM_GPS_STATE_LOCKED;
- else if (gps_data->flags & AO_GPS_RUNNING)
- state = AO_TELEM_GPS_STATE_UNLOCKED;
- else
- state = AO_TELEM_GPS_STATE_ERROR;
- printf(AO_TELEM_GPS_STATE " %c "
- AO_TELEM_GPS_NUM_SAT " %d ",
- state,
- (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
- if (!(gps_data->flags & AO_GPS_VALID))
- return;
- printf(AO_TELEM_GPS_LATITUDE " %ld "
- AO_TELEM_GPS_LONGITUDE " %ld "
- AO_TELEM_GPS_ALTITUDE " %d ",
- (long) gps_data->latitude,
- (long) gps_data->longitude,
- gps_data->altitude);
-
- if (gps_data->flags & AO_GPS_DATE_VALID)
- printf(AO_TELEM_GPS_YEAR " %d "
- AO_TELEM_GPS_MONTH " %d "
- AO_TELEM_GPS_DAY " %d ",
- gps_data->year,
- gps_data->month,
- gps_data->day);
-
- printf(AO_TELEM_GPS_HOUR " %d "
- AO_TELEM_GPS_MINUTE " %d "
- AO_TELEM_GPS_SECOND " %d ",
- gps_data->hour,
- gps_data->minute,
- gps_data->second);
-
- printf(AO_TELEM_GPS_HDOP " %d ",
- gps_data->hdop * 2);
-
- if (gps_data->flags & AO_GPS_COURSE_VALID) {
- printf(AO_TELEM_GPS_HERROR " %d "
- AO_TELEM_GPS_VERROR " %d "
- AO_TELEM_GPS_VERTICAL_SPEED " %d "
- AO_TELEM_GPS_HORIZONTAL_SPEED " %d "
- AO_TELEM_GPS_COURSE " %d ",
- gps_data->h_error,
- gps_data->v_error,
- gps_data->climb_rate,
- gps_data->ground_speed,
- (int) gps_data->course * 2);
- }
-}
-
-void
-ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant
-{
- uint8_t c, n, v;
- __xdata struct ao_gps_sat_orig *sat;
-
- n = gps_tracking_data->channels;
- if (n == 0)
- return;
-
- sat = gps_tracking_data->sats;
- v = 0;
- for (c = 0; c < n; c++) {
- if (sat->svid)
- v++;
- sat++;
- }
-
- printf (AO_TELEM_SAT_NUM " %d ",
- v);
-
- sat = gps_tracking_data->sats;
- v = 0;
- for (c = 0; c < n; c++) {
- if (sat->svid) {
- printf (AO_TELEM_SAT_SVID "%d %d "
- AO_TELEM_SAT_C_N_0 "%d %d ",
- v, sat->svid,
- v, sat->c_n_1);
- v++;
- }
- sat++;
- }
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_gps_report(void)
-{
- static __xdata struct ao_log_record gps_log;
- static __xdata struct ao_telemetry_location gps_data;
- static __xdata struct ao_telemetry_satellite gps_tracking_data;
- uint8_t date_reported = 0;
- uint8_t new;
-
- for (;;) {
- while ((new = ao_gps_new) == 0)
- ao_sleep(&ao_gps_new);
- ao_mutex_get(&ao_gps_mutex);
- if (new & AO_GPS_NEW_DATA)
- ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
- if (new & AO_GPS_NEW_TRACKING)
- ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
- ao_gps_new = 0;
- ao_mutex_put(&ao_gps_mutex);
-
- if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) {
- gps_log.tick = ao_gps_tick;
- gps_log.type = AO_LOG_GPS_TIME;
- gps_log.u.gps_time.hour = gps_data.hour;
- gps_log.u.gps_time.minute = gps_data.minute;
- gps_log.u.gps_time.second = gps_data.second;
- gps_log.u.gps_time.flags = gps_data.flags;
- ao_log_data(&gps_log);
- gps_log.type = AO_LOG_GPS_LAT;
- gps_log.u.gps_latitude = gps_data.latitude;
- ao_log_data(&gps_log);
- gps_log.type = AO_LOG_GPS_LON;
- gps_log.u.gps_longitude = gps_data.longitude;
- ao_log_data(&gps_log);
- gps_log.type = AO_LOG_GPS_ALT;
- gps_log.u.gps_altitude.altitude = gps_data.altitude;
- gps_log.u.gps_altitude.unused = 0xffff;
- ao_log_data(&gps_log);
- if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
- gps_log.type = AO_LOG_GPS_DATE;
- gps_log.u.gps_date.year = gps_data.year;
- gps_log.u.gps_date.month = gps_data.month;
- gps_log.u.gps_date.day = gps_data.day;
- gps_log.u.gps_date.extra = 0;
- date_reported = ao_log_data(&gps_log);
- }
- }
- if (new & AO_GPS_NEW_TRACKING) {
- uint8_t c, n;
-
- if ((n = gps_tracking_data.channels) != 0) {
- gps_log.type = AO_LOG_GPS_SAT;
- for (c = 0; c < n; c++)
- if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid))
- {
- gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1;
- ao_log_data(&gps_log);
- }
- }
- }
- }
-}
-
-__xdata struct ao_task ao_gps_report_task;
-
-void
-ao_gps_report_init(void)
-{
- ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report");
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_log.h"
-
-void
-ao_gps_report_mega(void)
-{
- static __xdata struct ao_log_mega gps_log;
- static __xdata struct ao_telemetry_location gps_data;
- static __xdata struct ao_telemetry_satellite gps_tracking_data;
- uint8_t new;
- uint8_t c, n, i;
-
- for (;;) {
- while (!(new = ao_gps_new))
- ao_sleep(&ao_gps_new);
- ao_mutex_get(&ao_gps_mutex);
- if (new & AO_GPS_NEW_DATA)
- ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
- if (new & AO_GPS_NEW_TRACKING)
- ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
- ao_gps_new = 0;
- ao_mutex_put(&ao_gps_mutex);
-
- if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) {
- gps_log.tick = ao_gps_tick;
- gps_log.type = AO_LOG_GPS_TIME;
- gps_log.u.gps.latitude = gps_data.latitude;
- gps_log.u.gps.longitude = gps_data.longitude;
- gps_log.u.gps.altitude = gps_data.altitude;
-
- gps_log.u.gps.hour = gps_data.hour;
- gps_log.u.gps.minute = gps_data.minute;
- gps_log.u.gps.second = gps_data.second;
- gps_log.u.gps.flags = gps_data.flags;
- gps_log.u.gps.year = gps_data.year;
- gps_log.u.gps.month = gps_data.month;
- gps_log.u.gps.day = gps_data.day;
- gps_log.u.gps.course = gps_data.course;
- gps_log.u.gps.ground_speed = gps_data.ground_speed;
- gps_log.u.gps.climb_rate = gps_data.climb_rate;
- gps_log.u.gps.pdop = gps_data.pdop;
- gps_log.u.gps.hdop = gps_data.hdop;
- gps_log.u.gps.vdop = gps_data.vdop;
- gps_log.u.gps.mode = gps_data.mode;
- ao_log_mega(&gps_log);
- }
- if ((new & AO_GPS_NEW_TRACKING) && (n = gps_tracking_data.channels) != 0) {
- gps_log.tick = ao_gps_tick;
- gps_log.type = AO_LOG_GPS_SAT;
- i = 0;
- for (c = 0; c < n; c++)
- if ((gps_log.u.gps_sat.sats[i].svid = gps_tracking_data.sats[c].svid))
- {
- gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1;
- i++;
- if (i >= 12)
- break;
- }
- gps_log.u.gps_sat.channels = i;
- ao_log_mega(&gps_log);
- }
- }
-}
-
-__xdata struct ao_task ao_gps_report_mega_task;
-
-void
-ao_gps_report_mega_init(void)
-{
- ao_add_task(&ao_gps_report_mega_task,
- ao_gps_report_mega,
- "gps_report");
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_log.h"
-
-void
-ao_gps_report_metrum(void)
-{
- static __xdata struct ao_log_metrum gps_log;
- static __xdata struct ao_telemetry_location gps_data;
- static __xdata struct ao_telemetry_satellite gps_tracking_data;
- uint8_t c, n, i;
- uint8_t svid;
- uint8_t new;
-
- for (;;) {
- while (!(new = ao_gps_new))
- ao_sleep(&ao_gps_new);
- ao_mutex_get(&ao_gps_mutex);
- if (new & AO_GPS_NEW_DATA)
- ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
- if (new & AO_GPS_NEW_TRACKING)
- ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
- ao_gps_new = 0;
- ao_mutex_put(&ao_gps_mutex);
-
- if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) {
- gps_log.tick = ao_gps_tick;
- gps_log.type = AO_LOG_GPS_POS;
- gps_log.u.gps.latitude = gps_data.latitude;
- gps_log.u.gps.longitude = gps_data.longitude;
- gps_log.u.gps.altitude = gps_data.altitude;
- ao_log_metrum(&gps_log);
-
- gps_log.type = AO_LOG_GPS_TIME;
- gps_log.u.gps_time.hour = gps_data.hour;
- gps_log.u.gps_time.minute = gps_data.minute;
- gps_log.u.gps_time.second = gps_data.second;
- gps_log.u.gps_time.flags = gps_data.flags;
- gps_log.u.gps_time.year = gps_data.year;
- gps_log.u.gps_time.month = gps_data.month;
- gps_log.u.gps_time.day = gps_data.day;
- ao_log_metrum(&gps_log);
- }
-
- if ((new & AO_GPS_NEW_TRACKING) && (n = gps_tracking_data.channels)) {
- gps_log.type = AO_LOG_GPS_SAT;
- gps_log.tick = ao_gps_tick;
- i = 0;
- for (c = 0; c < n; c++) {
- svid = gps_tracking_data.sats[c].svid;
- if (svid != 0) {
- if (i == 4) {
- gps_log.u.gps_sat.channels = i;
- gps_log.u.gps_sat.more = 1;
- ao_log_metrum(&gps_log);
- i = 0;
- }
- gps_log.u.gps_sat.sats[i].svid = svid;
- gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1;
- i++;
- }
- }
- if (i) {
- gps_log.u.gps_sat.channels = i;
- gps_log.u.gps_sat.more = 0;
- ao_log_metrum(&gps_log);
- }
- }
- }
-}
-
-__xdata struct ao_task ao_gps_report_metrum_task;
-
-void
-ao_gps_report_metrum_init(void)
-{
- ao_add_task(&ao_gps_report_metrum_task,
- ao_gps_report_metrum,
- "gps_report");
-}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_GPS_TEST
-#include <ao.h>
-#endif
-
-void
-ao_gps_show(void) __reentrant
-{
- uint8_t i;
- ao_mutex_get(&ao_gps_mutex);
- printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day);
- printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
- printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude);
- printf ("Alt: %d\n", ao_gps_data.altitude);
- printf ("Flags: 0x%x\n", ao_gps_data.flags);
- printf ("Sats: %d", ao_gps_tracking_data.channels);
- for (i = 0; i < ao_gps_tracking_data.channels; i++)
- printf (" %d %d",
- ao_gps_tracking_data.sats[i].svid,
- ao_gps_tracking_data.sats[i].c_n_1);
- printf ("\ndone\n");
- ao_mutex_put(&ao_gps_mutex);
-}
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define _GNU_SOURCE
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define AO_ADC_RING 64
-#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1))
-#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1))
-
-/*
- * One set of samples read from the A/D converter
- */
-struct ao_adc {
- uint16_t tick; /* tick when the sample was read */
- int16_t accel; /* accelerometer */
- int16_t pres; /* pressure sensor */
- int16_t temp; /* temperature sensor */
- int16_t v_batt; /* battery voltage */
- int16_t sense_d; /* drogue continuity sense */
- int16_t sense_m; /* main continuity sense */
-};
-
-#define __pdata
-#define __data
-#define __xdata
-#define __code
-#define __reentrant
-
-#define DATA_TO_XDATA(a) (a)
-#define PDATA_TO_XDATA(a) (a)
-#define CODE_TO_XDATA(a) (a)
-
-enum ao_flight_state {
- ao_flight_startup = 0,
- ao_flight_idle = 1,
- ao_flight_pad = 2,
- ao_flight_boost = 3,
- ao_flight_fast = 4,
- ao_flight_coast = 5,
- ao_flight_drogue = 6,
- ao_flight_main = 7,
- ao_flight_landed = 8,
- ao_flight_invalid = 9
-};
-
-struct ao_adc ao_adc_ring[AO_ADC_RING];
-uint8_t ao_adc_head;
-
-#define ao_led_on(l)
-#define ao_led_off(l)
-#define ao_timer_set_adc_interval(i)
-#define ao_wakeup(wchan) ao_dump_state(wchan)
-#define ao_cmd_register(c)
-#define ao_usb_disable()
-#define ao_telemetry_set_interval(x)
-#define ao_delay(x)
-
-enum ao_igniter {
- ao_igniter_drogue = 0,
- ao_igniter_main = 1
-};
-
-void
-ao_ignite(enum ao_igniter igniter)
-{
- printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main");
-}
-
-struct ao_task {
- int dummy;
-};
-
-#define ao_add_task(t,f,n)
-
-#define ao_log_start()
-#define ao_log_stop()
-
-#define AO_MS_TO_TICKS(ms) ((ms) / 10)
-#define AO_SEC_TO_TICKS(s) ((s) * 100)
-
-#define AO_FLIGHT_TEST
-
-struct ao_adc ao_adc_static;
-
-FILE *emulator_in;
-
-void
-ao_dump_state(void *wchan);
-
-void
-ao_sleep(void *wchan);
-
-const char const * const ao_state_names[] = {
- "startup", "idle", "pad", "boost", "fast",
- "coast", "drogue", "main", "landed", "invalid"
-};
-
-struct ao_cmds {
- void (*func)(void);
- const char *help;
-};
-
-
-struct ao_config {
- uint16_t main_deploy;
- int16_t accel_zero_g;
-};
-
-#define ao_config_get()
-
-struct ao_config ao_config = { 250, 16000 };
-
-#define ao_xmemcpy(d,s,c) memcpy(d,s,c)
-#define ao_xmemset(d,v,c) memset(d,v,c)
-#define ao_xmemcmp(d,s,c) memcmp(d,s,c)
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include <ao_data.h>
-#if AO_PYRO_NUM
-#include <ao_pyro.h>
-#endif
-
-#if HAS_IGNITE
-__xdata struct ao_ignition ao_ignition[2];
-
-void
-ao_ignite(enum ao_igniter igniter)
-{
- ao_arch_block_interrupts();
- ao_ignition[igniter].request = 1;
- ao_wakeup(&ao_ignition);
- ao_arch_release_interrupts();
-}
-
-#ifndef AO_SENSE_DROGUE
-#define AO_SENSE_DROGUE(p) ((p)->adc.sense_d)
-#define AO_SENSE_MAIN(p) ((p)->adc.sense_m)
-#endif
-
-enum ao_igniter_status
-ao_igniter_status(enum ao_igniter igniter)
-{
- __xdata struct ao_data packet;
- __pdata int16_t value;
- __pdata uint8_t request, firing, fired;
-
- ao_arch_critical(
- ao_data_get(&packet);
- request = ao_ignition[igniter].request;
- fired = ao_ignition[igniter].fired;
- firing = ao_ignition[igniter].firing;
- );
- if (firing || (request && !fired))
- return ao_igniter_active;
-
- value = (AO_IGNITER_CLOSED>>1);
- switch (igniter) {
- case ao_igniter_drogue:
- value = AO_SENSE_DROGUE(&packet);
- break;
- case ao_igniter_main:
- value = AO_SENSE_MAIN(&packet);
- break;
- }
- if (value < AO_IGNITER_OPEN)
- return ao_igniter_open;
- else if (value > AO_IGNITER_CLOSED)
- return ao_igniter_ready;
- else
- return ao_igniter_unknown;
-}
-
-#ifndef AO_IGNITER_SET_DROGUE
-#define AO_IGNITER_SET_DROGUE(v) AO_IGNITER_DROGUE = (v)
-#define AO_IGNITER_SET_MAIN(v) AO_IGNITER_MAIN = (v)
-#endif
-
-#ifndef AO_IGNITER_FIRE_TIME
-#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50)
-#endif
-
-#ifndef AO_IGNITER_CHARGE_TIME
-#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000)
-#endif
-
-void
-ao_igniter_fire(enum ao_igniter igniter)
-{
- ao_ignition[igniter].firing = 1;
- switch(ao_config.ignite_mode) {
- case AO_IGNITE_MODE_DUAL:
- switch (igniter) {
- case ao_igniter_drogue:
- AO_IGNITER_SET_DROGUE(1);
- ao_delay(AO_IGNITER_FIRE_TIME);
- AO_IGNITER_SET_DROGUE(0);
- break;
- case ao_igniter_main:
- AO_IGNITER_SET_MAIN(1);
- ao_delay(AO_IGNITER_FIRE_TIME);
- AO_IGNITER_SET_MAIN(0);
- break;
- }
- break;
- case AO_IGNITE_MODE_APOGEE:
- switch (igniter) {
- case ao_igniter_drogue:
- AO_IGNITER_SET_DROGUE(1);
- ao_delay(AO_IGNITER_FIRE_TIME);
- AO_IGNITER_SET_DROGUE(0);
- ao_delay(AO_IGNITER_CHARGE_TIME);
- AO_IGNITER_SET_MAIN(1);
- ao_delay(AO_IGNITER_FIRE_TIME);
- AO_IGNITER_SET_MAIN(0);
- break;
- default:
- break;
- }
- break;
- case AO_IGNITE_MODE_MAIN:
- switch (igniter) {
- case ao_igniter_main:
- AO_IGNITER_SET_DROGUE(1);
- ao_delay(AO_IGNITER_FIRE_TIME);
- AO_IGNITER_SET_DROGUE(0);
- ao_delay(AO_IGNITER_CHARGE_TIME);
- AO_IGNITER_SET_MAIN(1);
- ao_delay(AO_IGNITER_FIRE_TIME);
- AO_IGNITER_SET_MAIN(0);
- break;
- default:
- break;
- }
- break;
- }
- ao_ignition[igniter].firing = 0;
-}
-
-void
-ao_igniter(void)
-{
- __xdata enum ao_igniter igniter;
-
- ao_config_get();
- for (;;) {
- ao_sleep(&ao_ignition);
- for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) {
- if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) {
- if (igniter == ao_igniter_drogue && ao_config.apogee_delay)
- ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay));
-
- ao_igniter_fire(igniter);
- ao_delay(AO_IGNITER_CHARGE_TIME);
- ao_ignition[igniter].fired = 1;
- }
- }
- }
-}
-
-#endif
-
-void
-ao_ignite_manual(void)
-{
- ao_cmd_white();
- if (!ao_match_word("DoIt"))
- return;
- ao_cmd_white();
-#if HAS_IGNITE
- if (ao_cmd_lex_c == 'm' && ao_match_word("main")) {
- ao_igniter_fire(ao_igniter_main);
- return;
- }
- if (ao_cmd_lex_c == 'd' && ao_match_word("drogue")) {
- ao_igniter_fire(ao_igniter_drogue);
- return;
- }
-#endif
-#if AO_PYRO_NUM
- if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') {
- ao_pyro_manual(ao_cmd_lex_c - '0');
- return;
- }
-#endif
- ao_cmd_status = ao_cmd_syntax_error;
-}
-
-__code char * __code ao_igniter_status_names[] = {
- "unknown", "ready", "active", "open"
-};
-
-#if HAS_IGNITE
-void
-ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant
-{
- enum ao_igniter_status status = ao_igniter_status(igniter);
- printf("Igniter: %6s Status: %s\n",
- name,
- ao_igniter_status_names[status]);
-}
-#endif
-
-void
-ao_ignite_test(void)
-{
-#if HAS_IGNITE
- ao_ignite_print_status(ao_igniter_drogue, "drogue");
- ao_ignite_print_status(ao_igniter_main, "main");
-#endif
-#if AO_PYRO_NUM
- ao_pyro_print_status();
-#endif
-}
-
-__code struct ao_cmds ao_ignite_cmds[] = {
- { ao_ignite_manual, "i <key> {main|drogue}\0Fire igniter. <key> is doit with D&I" },
- { ao_ignite_test, "t\0Test igniter" },
- { 0, NULL },
-};
-
-#if HAS_IGNITE
-__xdata struct ao_task ao_igniter_task;
-
-void
-ao_ignite_set_pins(void)
-{
- ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, 0);
- ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, 0);
-}
-#endif
-
-void
-ao_igniter_init(void)
-{
-#if HAS_IGNITE
- ao_ignite_set_pins();
- ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
-#endif
- ao_cmd_register(&ao_ignite_cmds[0]);
-}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao_int64.h>
-
-__pdata ao_int64_t *__data ao_64r, *__data ao_64a, *__data ao_64b;
-
-void ao_plus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR {
- __LOCAL uint32_t t;
-
- r->high = a->high + b->high;
- t = a->low + b->low;
- if (t < a->low)
- r->high++;
- r->low = t;
-}
-
-void ao_minus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR {
- __LOCAL uint32_t t;
-
- r->high = a->high - b->high;
- t = a->low - b->low;
- if (t > a->low)
- r->high--;
- r->low = t;
-}
-
-void ao_rshift64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, uint8_t d) __FATTR {
- if (d < 32) {
- r->low = a->low >> d;
- if (d)
- r->low |= a->high << (32 - d);
- r->high = (int32_t) a->high >> d;
- } else {
- d &= 0x1f;
- r->low = (int32_t) a->high >> d;
- r->high = 0;
- }
-}
-
-void ao_lshift64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, uint8_t d) __FATTR {
- if (d < 32) {
- r->high = a->high << d;
- if (d)
- r->high |= a->low >> (32 - d);
- r->low = a->low << d;
- } else {
- d &= 0x1f;
- r->high = a->low << d;
- r->low = 0;
- }
-}
-
-static void ao_umul64_32_32(__ARG ao_int64_t *r, uint32_t a, uint32_t b) __reentrant {
- __LOCAL uint32_t s;
- __LOCAL ao_int64_t t;
- r->low = (uint32_t) (uint16_t) a * (uint16_t) b;
- r->high = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) (b >> 16);
-
- s = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) b;
-
- t.high = s >> 16;
- t.low = s << 16;
- ao_plus64(r, r, &t);
-
- s = (uint32_t) (uint16_t) a * (uint16_t) (b >> 16);
-
- t.high = s >> 16;
- t.low = s << 16;
- ao_plus64(r, r, &t);
-}
-
-void ao_neg64(__pdata ao_int64_t *r, __pdata ao_int64_t *a) __FATTR {
- r->high = ~a->high;
- if (!(r->low = ~a->low + 1))
- r->high++;
-}
-
-void ao_mul64_32_32(__ARG ao_int64_t *r, int32_t a, int32_t b) __FATTR {
- uint8_t negative = 0;
-
- if (a < 0) {
- a = -a;
- ++negative;
- }
- if (b < 0) {
- b = -b;
- --negative;
- }
- ao_umul64_32_32(r, a, b);
- if (negative)
- ao_neg64(r, r);
-}
-
-static void ao_umul64(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG ao_int64_t *b) __reentrant {
- __LOCAL ao_int64_t r2, r3;
-
- ao_umul64_32_32(&r2, a->high, b->low);
- ao_umul64_32_32(&r3, a->low, b->high);
- ao_umul64_32_32(r, a->low, b->low);
-
- r->high += r2.low + r3.low;
-}
-
-static __ARG ao_int64_t ap, bp;
-
-void ao_mul64(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG ao_int64_t *b) __FATTR {
- uint8_t negative = 0;
-
- if (ao_int64_negativep(a)) {
- ao_neg64(&ap, a);
- a = ≈
- ++negative;
- }
- if (ao_int64_negativep(b)) {
- ao_neg64(&bp, b);
- b = &bp;
- --negative;
- }
- ao_umul64(r, a, b);
- if (negative)
- ao_neg64(r, r);
-}
-
-static void ao_umul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, uint16_t b) __reentrant {
- __LOCAL uint32_t h;
-
- h = a->high * b;
- ao_umul64_32_32(r, a->low, b);
- r->high += h;
-}
-
-void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b) __FATTR {
- uint8_t negative = 0;
-
- if ((int32_t) a->high < 0) {
- ao_neg64(&ap, a);
- a = ≈
- negative++;
- } else
- ao_umul64_64_16(r, a, b);
- if (negative)
- ao_neg64(r, r);
-}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_INT64_H_
-#define _AO_INT64_H_
-
-#include <stdint.h>
-
-typedef struct {
- uint32_t high;
- uint32_t low;
-} ao_int64_t;
-
-#define __FATTR
-#define __ARG __pdata
-#define __LOCAL static __pdata
-
-void ao_plus64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, __pdata ao_int64_t *ao_64b) __FATTR;
-void ao_minus64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, __pdata ao_int64_t *ao_64b) __FATTR;
-void ao_neg64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a) __FATTR;
-void ao_rshift64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, uint8_t d) __FATTR;
-void ao_lshift64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, uint8_t d) __FATTR;
-void ao_mul64_32_32(__ARG ao_int64_t *r, __ARG int32_t a, __ARG int32_t b) __FATTR;
-void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b) __FATTR;
-void ao_mul64(__ARG ao_int64_t * __ARG r, __ARG ao_int64_t * __ARG a, __ARG ao_int64_t *__ARG b) __FATTR;
-
-#define ao_int64_init32(r, a) (((r)->high = 0), (r)->low = (a))
-#define ao_int64_init64(r, a, b) (((r)->high = (a)), (r)->low = (b))
-
-#define ao_cast64(a) (((int64_t) (a)->high << 32) | (a)->low)
-
-#define ao_int64_negativep(a) (((int32_t) (a)->high) < 0)
-
-#endif /* _AO_INT64_H_ */
+++ /dev/null
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#include "ao_flight.h"
-#endif
-
-#include "ao_sample.h"
-#include "ao_kalman.h"
-
-
-static __pdata int32_t ao_k_height;
-static __pdata int32_t ao_k_speed;
-static __pdata int32_t ao_k_accel;
-
-#define AO_K_STEP_100 to_fix16(0.01)
-#define AO_K_STEP_2_2_100 to_fix16(0.00005)
-
-#define AO_K_STEP_10 to_fix16(0.1)
-#define AO_K_STEP_2_2_10 to_fix16(0.005)
-
-#define AO_K_STEP_1 to_fix16(1)
-#define AO_K_STEP_2_2_1 to_fix16(0.5)
-
-__pdata int16_t ao_height;
-__pdata int16_t ao_speed;
-__pdata int16_t ao_accel;
-__xdata int16_t ao_max_height;
-static __pdata int32_t ao_avg_height_scaled;
-__xdata int16_t ao_avg_height;
-
-__pdata int16_t ao_error_h;
-__pdata int16_t ao_error_h_sq_avg;
-
-#if HAS_ACCEL
-__pdata int16_t ao_error_a;
-#endif
-
-static void
-ao_kalman_predict(void)
-{
-#ifdef AO_FLIGHT_TEST
- if (ao_sample_tick - ao_sample_prev_tick > 50) {
- ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 +
- (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
- ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1;
-
- return;
- }
- if (ao_sample_tick - ao_sample_prev_tick > 5) {
- ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 +
- (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
- ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10;
-
- return;
- }
- if (ao_flight_debug) {
- printf ("predict speed %g + (%g * %g) = %g\n",
- ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0,
- (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
- }
-#endif
- ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 +
- (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
- ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100;
-}
-
-static void
-ao_kalman_err_height(void)
-{
- int16_t e;
- int16_t height_distrust;
-#if HAS_ACCEL
- int16_t speed_distrust;
-#endif
-
- ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16);
-
- e = ao_error_h;
- if (e < 0)
- e = -e;
- if (e > 127)
- e = 127;
-#if HAS_ACCEL
- ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2;
- ao_error_h_sq_avg += (e * e) >> 2;
-#else
- ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4;
- ao_error_h_sq_avg += (e * e) >> 4;
-#endif
-
- if (ao_flight_state >= ao_flight_drogue)
- return;
- height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT;
-#if HAS_ACCEL
- /* speed is stored * 16, but we need to ramp between 200 and 328, so
- * we want to multiply by 2. The result is a shift by 3.
- */
- speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1);
- if (speed_distrust <= 0)
- speed_distrust = 0;
- else if (speed_distrust > height_distrust)
- height_distrust = speed_distrust;
-#endif
- if (height_distrust > 0) {
-#ifdef AO_FLIGHT_TEST
- int old_ao_error_h = ao_error_h;
-#endif
- if (height_distrust > 0x100)
- height_distrust = 0x100;
- ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8);
-#ifdef AO_FLIGHT_TEST
- if (ao_flight_debug) {
- printf("over height %g over speed %g distrust: %g height: error %d -> %d\n",
- (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT),
- (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0,
- height_distrust / 256.0,
- old_ao_error_h, ao_error_h);
- }
-#endif
- }
-}
-
-static void
-ao_kalman_correct_baro(void)
-{
- ao_kalman_err_height();
-#ifdef AO_FLIGHT_TEST
- if (ao_sample_tick - ao_sample_prev_tick > 50) {
- ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h;
- ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h;
- ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h;
- return;
- }
- if (ao_sample_tick - ao_sample_prev_tick > 5) {
- ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h;
- ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h;
- ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h;
- return;
- }
-#endif
- ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h;
- ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h;
- ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h;
-}
-
-#if HAS_ACCEL
-
-static void
-ao_kalman_err_accel(void)
-{
- int32_t accel;
-
- accel = (ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale;
-
- /* Can't use ao_accel here as it is the pre-prediction value still */
- ao_error_a = (accel - ao_k_accel) >> 16;
-}
-
-#ifndef FORCE_ACCEL
-static void
-ao_kalman_correct_both(void)
-{
- ao_kalman_err_height();
- ao_kalman_err_accel();
-
-#ifdef AO_FLIGHT_TEST
- if (ao_sample_tick - ao_sample_prev_tick > 50) {
- if (ao_flight_debug) {
- printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
- ao_k_speed / (65536.0 * 16.0),
- (double) ao_error_h, AO_BOTH_K10_1 / 65536.0,
- (double) ao_error_a, AO_BOTH_K11_1 / 65536.0,
- (ao_k_speed +
- (int32_t) AO_BOTH_K10_1 * ao_error_h +
- (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
- }
- ao_k_height +=
- (int32_t) AO_BOTH_K00_1 * ao_error_h +
- (int32_t) AO_BOTH_K01_1 * ao_error_a;
- ao_k_speed +=
- (int32_t) AO_BOTH_K10_1 * ao_error_h +
- (int32_t) AO_BOTH_K11_1 * ao_error_a;
- ao_k_accel +=
- (int32_t) AO_BOTH_K20_1 * ao_error_h +
- (int32_t) AO_BOTH_K21_1 * ao_error_a;
- return;
- }
- if (ao_sample_tick - ao_sample_prev_tick > 5) {
- if (ao_flight_debug) {
- printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
- ao_k_speed / (65536.0 * 16.0),
- (double) ao_error_h, AO_BOTH_K10_10 / 65536.0,
- (double) ao_error_a, AO_BOTH_K11_10 / 65536.0,
- (ao_k_speed +
- (int32_t) AO_BOTH_K10_10 * ao_error_h +
- (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
- }
- ao_k_height +=
- (int32_t) AO_BOTH_K00_10 * ao_error_h +
- (int32_t) AO_BOTH_K01_10 * ao_error_a;
- ao_k_speed +=
- (int32_t) AO_BOTH_K10_10 * ao_error_h +
- (int32_t) AO_BOTH_K11_10 * ao_error_a;
- ao_k_accel +=
- (int32_t) AO_BOTH_K20_10 * ao_error_h +
- (int32_t) AO_BOTH_K21_10 * ao_error_a;
- return;
- }
- if (ao_flight_debug) {
- printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
- ao_k_speed / (65536.0 * 16.0),
- (double) ao_error_h, AO_BOTH_K10_100 / 65536.0,
- (double) ao_error_a, AO_BOTH_K11_100 / 65536.0,
- (ao_k_speed +
- (int32_t) AO_BOTH_K10_100 * ao_error_h +
- (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
- }
-#endif
- ao_k_height +=
- (int32_t) AO_BOTH_K00_100 * ao_error_h +
- (int32_t) AO_BOTH_K01_100 * ao_error_a;
- ao_k_speed +=
- (int32_t) AO_BOTH_K10_100 * ao_error_h +
- (int32_t) AO_BOTH_K11_100 * ao_error_a;
- ao_k_accel +=
- (int32_t) AO_BOTH_K20_100 * ao_error_h +
- (int32_t) AO_BOTH_K21_100 * ao_error_a;
-}
-
-#else
-
-static void
-ao_kalman_correct_accel(void)
-{
- ao_kalman_err_accel();
-
- if (ao_sample_tick - ao_sample_prev_tick > 5) {
- ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a;
- ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a;
- ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a;
- return;
- }
- ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a;
- ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a;
- ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a;
-}
-
-#endif /* else FORCE_ACCEL */
-#endif /* HAS_ACCEL */
-
-void
-ao_kalman(void)
-{
- ao_kalman_predict();
-#if HAS_ACCEL
- if (ao_flight_state <= ao_flight_coast) {
-#ifdef FORCE_ACCEL
- ao_kalman_correct_accel();
-#else
- ao_kalman_correct_both();
-#endif
- } else
-#endif
- ao_kalman_correct_baro();
- ao_height = from_fix(ao_k_height);
- ao_speed = from_fix(ao_k_speed);
- ao_accel = from_fix(ao_k_accel);
- if (ao_height > ao_max_height)
- ao_max_height = ao_height;
- ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height;
-#ifdef AO_FLIGHT_TEST
- if (ao_sample_tick - ao_sample_prev_tick > 50)
- ao_avg_height = (ao_avg_height_scaled + 1) >> 1;
- else if (ao_sample_tick - ao_sample_prev_tick > 5)
- ao_avg_height = (ao_avg_height_scaled + 7) >> 4;
- else
-#endif
- ao_avg_height = (ao_avg_height_scaled + 63) >> 7;
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_LCD_H_
-#define _AO_LCD_H_
-
-/* ao_lcd.c */
-
-void
-ao_lcd_putchar(uint8_t d);
-
-void
-ao_lcd_putstring(char *string);
-
-void
-ao_lcd_contrast_set(uint8_t contrast);
-
-void
-ao_lcd_clear(void);
-
-void
-ao_lcd_cursor_on(void);
-
-void
-ao_lcd_cursor_off(void);
-
-#define AO_LCD_ADDR(row,col) ((row << 6) | (col))
-
-void
-ao_lcd_goto(uint8_t addr);
-
-void
-ao_lcd_start(void);
-
-void
-ao_lcd_init(void);
-
-/* ao_lcd_port.c */
-
-void
-ao_lcd_port_put_nibble(uint8_t rs, uint8_t d);
-
-void
-ao_lcd_port_init(void);
-
-#endif /* _AO_LCD_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_LED_H_
-#define _AO_LED_H_
-
-/*
- * ao_led.c
- */
-
-#define AO_LED_NONE 0
-
-#ifndef AO_LED_TYPE
-#define AO_LED_TYPE uint8_t
-#endif
-
-/* Turn on the specified LEDs */
-void
-ao_led_on(AO_LED_TYPE colors);
-
-/* Turn off the specified LEDs */
-void
-ao_led_off(AO_LED_TYPE colors);
-
-/* Set all of the LEDs to the specified state */
-void
-ao_led_set(AO_LED_TYPE colors);
-
-/* Set all LEDs in 'mask' to the specified state */
-void
-ao_led_set_mask(uint8_t colors, uint8_t mask);
-
-/* Toggle the specified LEDs */
-void
-ao_led_toggle(AO_LED_TYPE colors);
-
-/* Turn on the specified LEDs for the indicated interval */
-void
-ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant;
-
-/* Initialize the LEDs */
-void
-ao_led_init(AO_LED_TYPE enable);
-
-#endif /* _AO_LED_H_ */
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_LIST_H_
-#define _AO_LIST_H_
-
-#include <stddef.h>
-
-struct ao_list {
- struct ao_list *next, *prev;
-};
-
-static inline void
-ao_list_init(struct ao_list *list)
-{
- list->next = list->prev = list;
-}
-
-static inline void
-__ao_list_add(struct ao_list *list, struct ao_list *prev, struct ao_list *next)
-{
- next->prev = list;
- list->next = next;
- list->prev = prev;
- prev->next = list;
-}
-
-/**
- * Insert a new element after the given list head. The new element does not
- * need to be initialised as empty list.
- * The list changes from:
- * head → some element → ...
- * to
- * head → new element → older element → ...
- *
- * Example:
- * struct foo *newfoo = malloc(...);
- * ao_list_add(&newfoo->entry, &bar->list_of_foos);
- *
- * @param entry The new element to prepend to the list.
- * @param head The existing list.
- */
-static inline void
-ao_list_insert(struct ao_list *entry, struct ao_list *head)
-{
- __ao_list_add(entry, head, head->next);
-}
-
-/**
- * Append a new element to the end of the list given with this list head.
- *
- * The list changes from:
- * head → some element → ... → lastelement
- * to
- * head → some element → ... → lastelement → new element
- *
- * Example:
- * struct foo *newfoo = malloc(...);
- * ao_list_append(&newfoo->entry, &bar->list_of_foos);
- *
- * @param entry The new element to prepend to the list.
- * @param head The existing list.
- */
-static inline void
-ao_list_append(struct ao_list *entry, struct ao_list *head)
-{
- __ao_list_add(entry, head->prev, head);
-}
-
-static inline void
-__ao_list_del(struct ao_list *prev, struct ao_list *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * Remove the element from the list it is in. Using this function will reset
- * the pointers to/from this element so it is removed from the list. It does
- * NOT free the element itself or manipulate it otherwise.
- *
- * Using ao_list_del on a pure list head (like in the example at the top of
- * this file) will NOT remove the first element from
- * the list but rather reset the list as empty list.
- *
- * Example:
- * ao_list_del(&foo->entry);
- *
- * @param entry The element to remove.
- */
-static inline void
-ao_list_del(struct ao_list *entry)
-{
- __ao_list_del(entry->prev, entry->next);
- ao_list_init(entry);
-}
-
-/**
- * Check if the list is empty.
- *
- * Example:
- * ao_list_is_empty(&bar->list_of_foos);
- *
- * @return True if the list contains one or more elements or False otherwise.
- */
-static inline uint8_t
-ao_list_is_empty(struct ao_list *head)
-{
- return head->next == head;
-}
-
-/**
- * Returns a pointer to the container of this list element.
- *
- * Example:
- * struct foo* f;
- * f = container_of(&foo->entry, struct foo, entry);
- * assert(f == foo);
- *
- * @param ptr Pointer to the struct ao_list.
- * @param type Data type of the list element.
- * @param member Member name of the struct ao_list field in the list element.
- * @return A pointer to the data struct containing the list head.
- */
-#define ao_container_of(ptr, type, member) \
- ((type *)((char *)(ptr) - offsetof(type, member)))
-
-/**
- * Alias of ao_container_of
- */
-#define ao_list_entry(ptr, type, member) \
- ao_container_of(ptr, type, member)
-
-/**
- * Retrieve the first list entry for the given list pointer.
- *
- * Example:
- * struct foo *first;
- * first = ao_list_first_entry(&bar->list_of_foos, struct foo, list_of_foos);
- *
- * @param ptr The list head
- * @param type Data type of the list element to retrieve
- * @param member Member name of the struct ao_list field in the list element.
- * @return A pointer to the first list element.
- */
-#define ao_list_first_entry(ptr, type, member) \
- ao_list_entry((ptr)->next, type, member)
-
-/**
- * Retrieve the last list entry for the given listpointer.
- *
- * Example:
- * struct foo *first;
- * first = ao_list_last_entry(&bar->list_of_foos, struct foo, list_of_foos);
- *
- * @param ptr The list head
- * @param type Data type of the list element to retrieve
- * @param member Member name of the struct ao_list field in the list element.
- * @return A pointer to the last list element.
- */
-#define ao_list_last_entry(ptr, type, member) \
- ao_list_entry((ptr)->prev, type, member)
-
-/**
- * Loop through the list given by head and set pos to struct in the list.
- *
- * Example:
- * struct foo *iterator;
- * ao_list_for_each_entry(iterator, &bar->list_of_foos, entry) {
- * [modify iterator]
- * }
- *
- * This macro is not safe for node deletion. Use ao_list_for_each_entry_safe
- * instead.
- *
- * @param pos Iterator variable of the type of the list elements.
- * @param head List head
- * @param member Member name of the struct ao_list in the list elements.
- *
- */
-#define ao_list_for_each_entry(pos, head, type, member) \
- for (pos = ao_container_of((head)->next, type, member); \
- &pos->member != (head); \
- pos = ao_container_of(pos->member.next, type, member))
-
-/**
- * Loop through the list, keeping a backup pointer to the element. This
- * macro allows for the deletion of a list element while looping through the
- * list.
- *
- * See ao_list_for_each_entry for more details.
- */
-#define ao_list_for_each_entry_safe(pos, tmp, head, type, member) \
- for ((pos = ao_container_of((head)->next, type, member)), \
- (tmp = ao_container_of(pos->member.next, type, member)); \
- &pos->member != (head); \
- (pos = tmp), (tmp = ao_container_of(pos->member.next, type, member)))
-
-#endif /* _AO_LIST_H_ */
+++ /dev/null
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include <ao_log.h>
-#include <ao_config.h>
-
-__pdata uint32_t ao_log_current_pos;
-__pdata uint32_t ao_log_end_pos;
-__pdata uint32_t ao_log_start_pos;
-__xdata uint8_t ao_log_running;
-__pdata enum ao_flight_state ao_log_state;
-__xdata uint16_t ao_flight_number;
-
-void
-ao_log_flush(void)
-{
- ao_storage_flush();
-}
-
-/*
- * When erasing a flight log, make sure the config block
- * has an up-to-date version of the current flight number
- */
-
-struct ao_log_erase {
- uint8_t unused;
- uint16_t flight;
-};
-
-static __xdata struct ao_log_erase erase;
-
-#define LOG_MAX_ERASE 16
-
-static uint32_t
-ao_log_erase_pos(uint8_t i)
-{
- return i * sizeof (struct ao_log_erase) + AO_CONFIG_MAX_SIZE;
-}
-
-void
-ao_log_write_erase(uint8_t pos)
-{
- erase.unused = 0x00;
- erase.flight = ao_flight_number;
- ao_config_write(ao_log_erase_pos(pos), &erase, sizeof (erase));
- ao_config_flush();
-}
-
-static void
-ao_log_read_erase(uint8_t pos)
-{
- ao_config_read(ao_log_erase_pos(pos), &erase, sizeof (erase));
-}
-
-
-static void
-ao_log_erase_mark(void)
-{
- uint8_t i;
-
- for (i = 0; i < LOG_MAX_ERASE; i++) {
- ao_log_read_erase(i);
- if (erase.unused == 0 && erase.flight == ao_flight_number)
- return;
- if (erase.unused == 0xff) {
- ao_log_write_erase(i);
- return;
- }
- }
- ao_config_put();
-}
-
-static uint8_t
-ao_log_slots()
-{
- return (uint8_t) (ao_storage_log_max / ao_config.flight_log_max);
-}
-
-uint32_t
-ao_log_pos(uint8_t slot)
-{
- return ((slot) * ao_config.flight_log_max);
-}
-
-static uint16_t
-ao_log_max_flight(void)
-{
- uint8_t log_slot;
- uint8_t log_slots;
- uint16_t log_flight;
- uint16_t max_flight = 0;
-
- /* Scan the log space looking for the biggest flight number */
- log_slots = ao_log_slots();
- for (log_slot = 0; log_slot < log_slots; log_slot++) {
- log_flight = ao_log_flight(log_slot);
- if (!log_flight)
- continue;
- if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0)
- max_flight = log_flight;
- }
- return max_flight;
-}
-
-void
-ao_log_scan(void) __reentrant
-{
- uint8_t log_slot;
- uint8_t log_slots;
- uint8_t log_want;
-
- ao_config_get();
-
- ao_flight_number = ao_log_max_flight();
- if (ao_flight_number)
- if (++ao_flight_number == 0)
- ao_flight_number = 1;
-
- /* Now look through the log of flight numbers from erase operations and
- * see if the last one is bigger than what we found above
- */
- for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) {
- ao_log_read_erase(log_slot);
- if (erase.unused == 0) {
- if (ao_flight_number == 0 ||
- (int16_t) (erase.flight - ao_flight_number) > 0)
- ao_flight_number = erase.flight;
- break;
- }
- }
- if (ao_flight_number == 0)
- ao_flight_number = 1;
-
- /* With a flight number in hand, find a place to write a new log,
- * use the target flight number to index the available log slots so
- * that we write logs to each spot about the same number of times.
- */
-
- /* Find a log slot for the next flight, if available */
- ao_log_current_pos = ao_log_end_pos = 0;
- log_slots = ao_log_slots();
- log_want = (ao_flight_number - 1) % log_slots;
- log_slot = log_want;
- do {
- if (ao_log_flight(log_slot) == 0) {
- ao_log_current_pos = ao_log_pos(log_slot);
- ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
- break;
- }
- if (++log_slot >= log_slots)
- log_slot = 0;
- } while (log_slot != log_want);
-
- ao_wakeup(&ao_flight_number);
-}
-
-void
-ao_log_start(void)
-{
- /* start logging */
- ao_log_running = 1;
- ao_wakeup(&ao_log_running);
-}
-
-void
-ao_log_stop(void)
-{
- ao_log_running = 0;
- ao_log_flush();
-}
-
-uint8_t
-ao_log_present(void)
-{
- return ao_log_max_flight() != 0;
-}
-
-uint8_t
-ao_log_full(void)
-{
- return ao_log_current_pos == ao_log_end_pos;
-}
-
-#if HAS_ADC
-static __xdata struct ao_task ao_log_task;
-#endif
-
-void
-ao_log_list(void) __reentrant
-{
- uint8_t slot;
- uint8_t slots;
- uint16_t flight;
-
- slots = ao_log_slots();
- for (slot = 0; slot < slots; slot++)
- {
- flight = ao_log_flight(slot);
- if (flight)
- printf ("flight %d start %x end %x\n",
- flight,
- (uint16_t) (ao_log_pos(slot) >> 8),
- (uint16_t) (ao_log_pos(slot+1) >> 8));
- }
- printf ("done\n");
-}
-
-void
-ao_log_delete(void) __reentrant
-{
- uint8_t slot;
- uint8_t slots;
-
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
-
- slots = ao_log_slots();
- /* Look for the flight log matching the requested flight */
- if (ao_cmd_lex_i) {
- for (slot = 0; slot < slots; slot++) {
- if (ao_log_flight(slot) == ao_cmd_lex_i) {
- ao_log_erase_mark();
- ao_log_current_pos = ao_log_pos(slot);
- ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
- while (ao_log_current_pos < ao_log_end_pos) {
- uint8_t i;
- static __xdata uint8_t b;
-
- /*
- * Check to see if we've reached the end of
- * the used memory to avoid re-erasing the same
- * memory over and over again
- */
- for (i = 0; i < 16; i++) {
- if (ao_storage_read(ao_log_current_pos + i, &b, 1))
- if (b != 0xff)
- break;
- }
- if (i == 16)
- break;
- ao_storage_erase(ao_log_current_pos);
- ao_log_current_pos += ao_storage_block;
- }
- puts("Erased");
- return;
- }
- }
- }
- printf("No such flight: %d\n", ao_cmd_lex_i);
-}
-
-__code struct ao_cmds ao_log_cmds[] = {
- { ao_log_list, "l\0List logs" },
- { ao_log_delete, "d <flight-number>\0Delete flight" },
- { 0, NULL },
-};
-
-void
-ao_log_init(void)
-{
- ao_log_running = 0;
-
- /* For now, just log the flight starting at the begining of eeprom */
- ao_log_state = ao_flight_invalid;
-
- ao_cmd_register(&ao_log_cmds[0]);
-
-#ifndef HAS_ADC
-#error Define HAS_ADC for ao_log.c
-#endif
-#if HAS_ADC
- /* Create a task to log events to eeprom */
- ao_add_task(&ao_log_task, ao_log, "log");
-#endif
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_LOG_H_
-#define _AO_LOG_H_
-
-#include <ao_flight.h>
-
-/*
- * ao_log.c
- */
-
-/* We record flight numbers in the first record of
- * the log. Tasks may wait for this to be initialized
- * by sleeping on this variable.
- */
-extern __xdata uint16_t ao_flight_number;
-
-extern __pdata uint32_t ao_log_current_pos;
-extern __pdata uint32_t ao_log_end_pos;
-extern __pdata uint32_t ao_log_start_pos;
-extern __xdata uint8_t ao_log_running;
-extern __pdata enum ao_flight_state ao_log_state;
-
-/* required functions from the underlying log system */
-
-#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */
-#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */
-#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */
-#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */
-#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */
-#define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */
-#define AO_LOG_FORMAT_EASYMINI 6 /* 16-byte MS5607 baro only, 3.0V supply */
-#define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */
-#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */
-#define AO_LOG_FORMAT_NONE 127 /* No log at all */
-
-extern __code uint8_t ao_log_format;
-
-/* Return the flight number from the given log slot, 0 if none */
-uint16_t
-ao_log_flight(uint8_t slot);
-
-/* Flush the log */
-void
-ao_log_flush(void);
-
-/* Logging thread main routine */
-void
-ao_log(void);
-
-/* functions provided in ao_log.c */
-
-/* Figure out the current flight number */
-void
-ao_log_scan(void) __reentrant;
-
-/* Return the position of the start of the given log slot */
-uint32_t
-ao_log_pos(uint8_t slot);
-
-/* Start logging to eeprom */
-void
-ao_log_start(void);
-
-/* Stop logging */
-void
-ao_log_stop(void);
-
-/* Initialize the logging system */
-void
-ao_log_init(void);
-
-/* Write out the current flight number to the erase log */
-void
-ao_log_write_erase(uint8_t pos);
-
-/* Returns true if there are any logs stored in eeprom */
-uint8_t
-ao_log_present(void);
-
-/* Returns true if there is no more storage space available */
-uint8_t
-ao_log_full(void);
-
-/*
- * ao_log_big.c
- */
-
-/*
- * The data log is recorded in the eeprom as a sequence
- * of data packets.
- *
- * Each packet starts with a 4-byte header that has the
- * packet type, the packet checksum and the tick count. Then
- * they all contain 2 16 bit values which hold packet-specific
- * data.
- *
- * For each flight, the first packet
- * is FLIGHT packet, indicating the serial number of the
- * device and a unique number marking the number of flights
- * recorded by this device.
- *
- * During flight, data from the accelerometer and barometer
- * are recorded in SENSOR packets, using the raw 16-bit values
- * read from the A/D converter.
- *
- * Also during flight, but at a lower rate, the deployment
- * sensors are recorded in DEPLOY packets. The goal here is to
- * detect failure in the deployment circuits.
- *
- * STATE packets hold state transitions as the flight computer
- * transitions through different stages of the flight.
- */
-#define AO_LOG_FLIGHT 'F'
-#define AO_LOG_SENSOR 'A'
-#define AO_LOG_TEMP_VOLT 'T'
-#define AO_LOG_DEPLOY 'D'
-#define AO_LOG_STATE 'S'
-#define AO_LOG_GPS_TIME 'G'
-#define AO_LOG_GPS_LAT 'N'
-#define AO_LOG_GPS_LON 'W'
-#define AO_LOG_GPS_ALT 'H'
-#define AO_LOG_GPS_SAT 'V'
-#define AO_LOG_GPS_DATE 'Y'
-#define AO_LOG_GPS_POS 'P'
-
-#define AO_LOG_POS_NONE (~0UL)
-
-struct ao_log_record {
- char type; /* 0 */
- uint8_t csum; /* 1 */
- uint16_t tick; /* 2 */
- union {
- struct {
- int16_t ground_accel; /* 4 */
- uint16_t flight; /* 6 */
- } flight;
- struct {
- int16_t accel; /* 4 */
- int16_t pres; /* 6 */
- } sensor;
- struct {
- int16_t temp;
- int16_t v_batt;
- } temp_volt;
- struct {
- int16_t drogue;
- int16_t main;
- } deploy;
- struct {
- uint16_t state;
- uint16_t reason;
- } state;
- struct {
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
- uint8_t flags;
- } gps_time;
- int32_t gps_latitude;
- int32_t gps_longitude;
- struct {
- int16_t altitude;
- uint16_t unused;
- } gps_altitude;
- struct {
- uint16_t svid;
- uint8_t unused;
- uint8_t c_n;
- } gps_sat;
- struct {
- uint8_t year;
- uint8_t month;
- uint8_t day;
- uint8_t extra;
- } gps_date;
- struct {
- uint16_t d0;
- uint16_t d1;
- } anon;
- } u;
-};
-
-struct ao_log_mega {
- char type; /* 0 */
- uint8_t csum; /* 1 */
- uint16_t tick; /* 2 */
- union { /* 4 */
- /* AO_LOG_FLIGHT */
- struct {
- uint16_t flight; /* 4 */
- int16_t ground_accel; /* 6 */
- uint32_t ground_pres; /* 8 */
- int16_t ground_accel_along; /* 16 */
- int16_t ground_accel_across; /* 12 */
- int16_t ground_accel_through; /* 14 */
- int16_t ground_roll; /* 18 */
- int16_t ground_pitch; /* 20 */
- int16_t ground_yaw; /* 22 */
- } flight; /* 24 */
- /* AO_LOG_STATE */
- struct {
- uint16_t state;
- uint16_t reason;
- } state;
- /* AO_LOG_SENSOR */
- struct {
- uint32_t pres; /* 4 */
- uint32_t temp; /* 8 */
- int16_t accel_x; /* 12 */
- int16_t accel_y; /* 14 */
- int16_t accel_z; /* 16 */
- int16_t gyro_x; /* 18 */
- int16_t gyro_y; /* 20 */
- int16_t gyro_z; /* 22 */
- int16_t mag_x; /* 24 */
- int16_t mag_y; /* 26 */
- int16_t mag_z; /* 28 */
- int16_t accel; /* 30 */
- } sensor; /* 32 */
- /* AO_LOG_TEMP_VOLT */
- struct {
- int16_t v_batt; /* 4 */
- int16_t v_pbatt; /* 6 */
- int16_t n_sense; /* 8 */
- int16_t sense[10]; /* 10 */
- uint16_t pyro; /* 30 */
- } volt; /* 32 */
- /* AO_LOG_GPS_TIME */
- struct {
- int32_t latitude; /* 4 */
- int32_t longitude; /* 8 */
- int16_t altitude; /* 12 */
- uint8_t hour; /* 14 */
- uint8_t minute; /* 15 */
- uint8_t second; /* 16 */
- uint8_t flags; /* 17 */
- uint8_t year; /* 18 */
- uint8_t month; /* 19 */
- uint8_t day; /* 20 */
- uint8_t course; /* 21 */
- uint16_t ground_speed; /* 22 */
- int16_t climb_rate; /* 24 */
- uint8_t pdop; /* 26 */
- uint8_t hdop; /* 27 */
- uint8_t vdop; /* 28 */
- uint8_t mode; /* 29 */
- } gps; /* 30 */
- /* AO_LOG_GPS_SAT */
- struct {
- uint16_t channels; /* 4 */
- struct {
- uint8_t svid;
- uint8_t c_n;
- } sats[12]; /* 6 */
- } gps_sat; /* 30 */
- } u;
-};
-
-struct ao_log_metrum {
- char type; /* 0 */
- uint8_t csum; /* 1 */
- uint16_t tick; /* 2 */
- union { /* 4 */
- /* AO_LOG_FLIGHT */
- struct {
- uint16_t flight; /* 4 */
- int16_t ground_accel; /* 6 */
- uint32_t ground_pres; /* 8 */
- uint32_t ground_temp; /* 12 */
- } flight; /* 16 */
- /* AO_LOG_STATE */
- struct {
- uint16_t state; /* 4 */
- uint16_t reason; /* 6 */
- } state; /* 8 */
- /* AO_LOG_SENSOR */
- struct {
- uint32_t pres; /* 4 */
- uint32_t temp; /* 8 */
- int16_t accel; /* 12 */
- } sensor; /* 14 */
- /* AO_LOG_TEMP_VOLT */
- struct {
- int16_t v_batt; /* 4 */
- int16_t sense_a; /* 6 */
- int16_t sense_m; /* 8 */
- } volt; /* 10 */
- /* AO_LOG_GPS_POS */
- struct {
- int32_t latitude; /* 4 */
- int32_t longitude; /* 8 */
- int16_t altitude; /* 12 */
- } gps; /* 14 */
- /* AO_LOG_GPS_TIME */
- struct {
- uint8_t hour; /* 4 */
- uint8_t minute; /* 5 */
- uint8_t second; /* 6 */
- uint8_t flags; /* 7 */
- uint8_t year; /* 8 */
- uint8_t month; /* 9 */
- uint8_t day; /* 10 */
- uint8_t pad; /* 11 */
- } gps_time; /* 12 */
- /* AO_LOG_GPS_SAT (up to three packets) */
- struct {
- uint8_t channels; /* 4 */
- uint8_t more; /* 5 */
- struct {
- uint8_t svid;
- uint8_t c_n;
- } sats[4]; /* 6 */
- } gps_sat; /* 14 */
- uint8_t raw[12]; /* 4 */
- } u; /* 16 */
-};
-
-struct ao_log_mini {
- char type; /* 0 */
- uint8_t csum; /* 1 */
- uint16_t tick; /* 2 */
- union { /* 4 */
- /* AO_LOG_FLIGHT */
- struct {
- uint16_t flight; /* 4 */
- uint16_t r6;
- uint32_t ground_pres; /* 8 */
- } flight;
- /* AO_LOG_STATE */
- struct {
- uint16_t state; /* 4 */
- uint16_t reason; /* 6 */
- } state;
- /* AO_LOG_SENSOR */
- struct {
- uint8_t pres[3]; /* 4 */
- uint8_t temp[3]; /* 7 */
- int16_t sense_a; /* 10 */
- int16_t sense_m; /* 12 */
- int16_t v_batt; /* 14 */
- } sensor; /* 16 */
- } u; /* 16 */
-}; /* 16 */
-
-#define ao_log_pack24(dst,value) do { \
- (dst)[0] = (value); \
- (dst)[1] = (value) >> 8; \
- (dst)[2] = (value) >> 16; \
- } while (0)
-
-/* Write a record to the eeprom log */
-uint8_t
-ao_log_data(__xdata struct ao_log_record *log) __reentrant;
-
-uint8_t
-ao_log_mega(__xdata struct ao_log_mega *log) __reentrant;
-
-uint8_t
-ao_log_metrum(__xdata struct ao_log_metrum *log) __reentrant;
-
-uint8_t
-ao_log_mini(__xdata struct ao_log_mini *log) __reentrant;
-
-void
-ao_log_flush(void);
-
-void
-ao_gps_report_metrum_init(void);
-
-#endif /* _AO_LOG_H_ */
+++ /dev/null
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static __xdata uint8_t ao_log_mutex;
-static __xdata struct ao_log_record log;
-
-__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL;
-
-static uint8_t
-ao_log_csum(__xdata uint8_t *b) __reentrant
-{
- uint8_t sum = 0x5a;
- uint8_t i;
-
- for (i = 0; i < sizeof (struct ao_log_record); i++)
- sum += *b++;
- return -sum;
-}
-
-uint8_t
-ao_log_data(__xdata struct ao_log_record *log) __reentrant
-{
- uint8_t wrote = 0;
- /* set checksum */
- log->csum = 0;
- log->csum = ao_log_csum((__xdata uint8_t *) log);
- ao_mutex_get(&ao_log_mutex); {
- if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
- ao_log_stop();
- if (ao_log_running) {
- wrote = 1;
- ao_storage_write(ao_log_current_pos,
- log,
- sizeof (struct ao_log_record));
- ao_log_current_pos += sizeof (struct ao_log_record);
- }
- } ao_mutex_put(&ao_log_mutex);
- return wrote;
-}
-
-static uint8_t
-ao_log_dump_check_data(void)
-{
- if (ao_log_csum((uint8_t *) &log) != 0)
- return 0;
- return 1;
-}
-
-static __data uint8_t ao_log_data_pos;
-
-/* a hack to make sure that ao_log_records fill the eeprom block in even units */
-typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ;
-
-#ifndef AO_SENSOR_INTERVAL_ASCENT
-#define AO_SENSOR_INTERVAL_ASCENT 1
-#define AO_SENSOR_INTERVAL_DESCENT 10
-#define AO_OTHER_INTERVAL 32
-#endif
-
-void
-ao_log(void)
-{
- __pdata uint16_t next_sensor, next_other;
-
- ao_storage_setup();
-
- ao_log_scan();
-
- while (!ao_log_running)
- ao_sleep(&ao_log_running);
-
- log.type = AO_LOG_FLIGHT;
- log.tick = ao_sample_tick;
-#if HAS_ACCEL
- log.u.flight.ground_accel = ao_ground_accel;
-#endif
- log.u.flight.flight = ao_flight_number;
- ao_log_data(&log);
-
- /* Write the whole contents of the ring to the log
- * when starting up.
- */
- ao_log_data_pos = ao_data_ring_next(ao_sample_data);
- next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick;
- ao_log_state = ao_flight_startup;
- for (;;) {
- /* Write samples to EEPROM */
- while (ao_log_data_pos != ao_sample_data) {
- log.tick = ao_data_ring[ao_log_data_pos].tick;
- if ((int16_t) (log.tick - next_sensor) >= 0) {
- log.type = AO_LOG_SENSOR;
- log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel;
- log.u.sensor.pres = ao_data_ring[ao_log_data_pos].adc.pres;
- ao_log_data(&log);
- if (ao_log_state <= ao_flight_coast)
- next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
- else
- next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT;
- }
- if ((int16_t) (log.tick - next_other) >= 0) {
- log.type = AO_LOG_TEMP_VOLT;
- log.u.temp_volt.temp = ao_data_ring[ao_log_data_pos].adc.temp;
- log.u.temp_volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
- ao_log_data(&log);
- log.type = AO_LOG_DEPLOY;
- log.u.deploy.drogue = ao_data_ring[ao_log_data_pos].adc.sense_d;
- log.u.deploy.main = ao_data_ring[ao_log_data_pos].adc.sense_m;
- ao_log_data(&log);
- next_other = log.tick + AO_OTHER_INTERVAL;
- }
- ao_log_data_pos = ao_data_ring_next(ao_log_data_pos);
- }
- /* Write state change to EEPROM */
- if (ao_flight_state != ao_log_state) {
- ao_log_state = ao_flight_state;
- log.type = AO_LOG_STATE;
- log.tick = ao_sample_tick;
- log.u.state.state = ao_log_state;
- log.u.state.reason = 0;
- ao_log_data(&log);
-
- if (ao_log_state == ao_flight_landed)
- ao_log_stop();
- }
-
- /* Wait for a while */
- ao_delay(AO_MS_TO_TICKS(100));
-
- /* Stop logging when told to */
- while (!ao_log_running)
- ao_sleep(&ao_log_running);
- }
-}
-
-uint16_t
-ao_log_flight(uint8_t slot)
-{
- if (!ao_storage_read(ao_log_pos(slot),
- &log,
- sizeof (struct ao_log_record)))
- return 0;
-
- if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT)
- return log.u.flight.flight;
- return 0;
-}
+++ /dev/null
-/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include <ao_log.h>
-#include <ao_data.h>
-#include <ao_flight.h>
-
-static __xdata uint8_t ao_log_mutex;
-static __xdata struct ao_log_mega log;
-
-__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMEGA;
-
-static uint8_t
-ao_log_csum(__xdata uint8_t *b) __reentrant
-{
- uint8_t sum = 0x5a;
- uint8_t i;
-
- for (i = 0; i < sizeof (struct ao_log_mega); i++)
- sum += *b++;
- return -sum;
-}
-
-uint8_t
-ao_log_mega(__xdata struct ao_log_mega *log) __reentrant
-{
- uint8_t wrote = 0;
- /* set checksum */
- log->csum = 0;
- log->csum = ao_log_csum((__xdata uint8_t *) log);
- ao_mutex_get(&ao_log_mutex); {
- if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
- ao_log_stop();
- if (ao_log_running) {
- wrote = 1;
- ao_storage_write(ao_log_current_pos,
- log,
- sizeof (struct ao_log_mega));
- ao_log_current_pos += sizeof (struct ao_log_mega);
- }
- } ao_mutex_put(&ao_log_mutex);
- return wrote;
-}
-
-static uint8_t
-ao_log_dump_check_data(void)
-{
- if (ao_log_csum((uint8_t *) &log) != 0)
- return 0;
- return 1;
-}
-
-#if HAS_ADC
-static __data uint8_t ao_log_data_pos;
-
-/* a hack to make sure that ao_log_megas fill the eeprom block in even units */
-typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_mega))] ;
-
-#ifndef AO_SENSOR_INTERVAL_ASCENT
-#define AO_SENSOR_INTERVAL_ASCENT 1
-#define AO_SENSOR_INTERVAL_DESCENT 10
-#define AO_OTHER_INTERVAL 32
-#endif
-
-void
-ao_log(void)
-{
- __pdata uint16_t next_sensor, next_other;
- uint8_t i;
-
- ao_storage_setup();
-
- ao_log_scan();
-
- while (!ao_log_running)
- ao_sleep(&ao_log_running);
-
-#if HAS_FLIGHT
- log.type = AO_LOG_FLIGHT;
- log.tick = ao_sample_tick;
-#if HAS_ACCEL
- log.u.flight.ground_accel = ao_ground_accel;
-#endif
-#if HAS_GYRO
- log.u.flight.ground_accel_along = ao_ground_accel_along;
- log.u.flight.ground_accel_across = ao_ground_accel_across;
- log.u.flight.ground_accel_through = ao_ground_accel_through;
- log.u.flight.ground_pitch = ao_ground_pitch;
- log.u.flight.ground_yaw = ao_ground_yaw;
- log.u.flight.ground_roll = ao_ground_roll;
-#endif
- log.u.flight.ground_pres = ao_ground_pres;
- log.u.flight.flight = ao_flight_number;
- ao_log_mega(&log);
-#endif
-
- /* Write the whole contents of the ring to the log
- * when starting up.
- */
- ao_log_data_pos = ao_data_ring_next(ao_data_head);
- next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick;
- ao_log_state = ao_flight_startup;
- for (;;) {
- /* Write samples to EEPROM */
- while (ao_log_data_pos != ao_data_head) {
- log.tick = ao_data_ring[ao_log_data_pos].tick;
- if ((int16_t) (log.tick - next_sensor) >= 0) {
- log.type = AO_LOG_SENSOR;
-#if HAS_MS5607
- log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres;
- log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp;
-#endif
-#if HAS_MPU6000
- log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x;
- log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y;
- log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z;
- log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x;
- log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y;
- log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z;
-#endif
-#if HAS_HMC5883
- log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x;
- log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y;
- log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z;
-#endif
- log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]);
- ao_log_mega(&log);
- if (ao_log_state <= ao_flight_coast)
- next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
- else
- next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT;
- }
- if ((int16_t) (log.tick - next_other) >= 0) {
- log.type = AO_LOG_TEMP_VOLT;
- log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
- log.u.volt.v_pbatt = ao_data_ring[ao_log_data_pos].adc.v_pbatt;
- log.u.volt.n_sense = AO_ADC_NUM_SENSE;
- for (i = 0; i < AO_ADC_NUM_SENSE; i++)
- log.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i];
- log.u.volt.pyro = ao_pyro_fired;
- ao_log_mega(&log);
- next_other = log.tick + AO_OTHER_INTERVAL;
- }
- ao_log_data_pos = ao_data_ring_next(ao_log_data_pos);
- }
-#if HAS_FLIGHT
- /*&nb