]> git.gag.com Git - fw/altos/commitdiff
altos: Add telemega test for seeed
authorKeith Packard <keithp@keithp.com>
Tue, 28 Jan 2025 19:37:40 +0000 (11:37 -0800)
committerKeith Packard <keithp@keithp.com>
Tue, 28 Jan 2025 19:39:16 +0000 (11:39 -0800)
This runs the existing POST as well as validating flash size, battery
voltage, GPS receiver, accel range and baro range.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/kernel/ao_config.c
src/telemega-v7.0-seeed/.gitignore [new file with mode: 0644]
src/telemega-v7.0-seeed/ao_pins.h [new file with mode: 0644]
src/telemega-v7.0-seeed/ao_telemega_seeed.c [new file with mode: 0644]
src/telemega-v7.0-seeed/flash-loader/ao_pins.h [new file with mode: 0644]

index 565ac61e450e6d6a567975761e0b4fcb02bf2b4d..4883e7cfa9821d4ef590698f391b6c956054b815 100644 (file)
@@ -56,6 +56,10 @@ uint8_t ao_force_freq;
 #define AO_CONFIG_DEFAULT_PYRO_TIME    AO_MS_TO_TICKS(50)
 #define AO_CONFIG_DEFAULT_RADIO_10MW   0
 #define AO_CONFIG_DEFAULT_REPORT_FEET  0
+#ifndef AO_CONFIG_DEFAULT_ACCEL_PLUS_G
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G 0
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G        0
+#endif
 #if HAS_CONFIG_SAVE
 #ifndef USE_INTERNAL_FLASH
 #error Please define USE_INTERNAL_FLASH
@@ -155,8 +159,8 @@ _ao_config_get(void)
                        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;
+                       ao_config.accel_plus_g = AO_CONFIG_DEFAULT_ACCEL_PLUS_G;
+                       ao_config.accel_minus_g = AO_CONFIG_DEFAULT_ACCEL_MINUS_G;
                }
                /* Fixups for minor version 3 */
 #if HAS_RADIO
diff --git a/src/telemega-v7.0-seeed/.gitignore b/src/telemega-v7.0-seeed/.gitignore
new file mode 100644 (file)
index 0000000..e67759a
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telemega-*.elf
diff --git a/src/telemega-v7.0-seeed/ao_pins.h b/src/telemega-v7.0-seeed/ao_pins.h
new file mode 100644 (file)
index 0000000..32e8fce
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Copyright © 2017 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+
+/* 16MHz High speed external crystal */
+#define AO_HSE                 16000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              6
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_6)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV              3
+#define AO_RCC_CFGR_PLLDIV     (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER      2
+#define AO_RCC_CFGR_PPRE1_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER      2
+#define AO_RCC_CFGR_PPRE2_DIV  STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1           0
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      0
+
+#define HAS_SERIAL_2           1
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       1
+#define SERIAL_2_PD5_PD6       0
+#define USE_SERIAL_2_FLOW      0
+#define USE_SERIAL_2_SW_FLOW   0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     0
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define ao_gps_getchar         ao_serial2_getchar
+#define ao_gps_putchar         ao_serial2_putchar
+#define ao_gps_set_speed       ao_serial2_set_speed
+#define ao_gps_fifo            (ao_stm_usart2.rx_fifo)
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (1024 * 1024)
+#define AO_CONFIG_DEFAULT_ACCEL_PLUS_G         -20
+#define AO_CONFIG_DEFAULT_ACCEL_MINUS_G                20
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA_6
+#define AO_LOG_NORMALIZED                      1
+
+#define HAS_EEPROM             1
+#define USE_INTERNAL_FLASH     0
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define BEEPER_TIMER           3
+#define BEEPER_CHANNEL         2
+#define BEEPER_PORT            (&stm_gpioe)
+#define BEEPER_PIN             4
+#define HAS_BATTERY_REPORT     1
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_APRS               1
+#define HAS_COMPANION          1
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
+#define SPI_1_PB3_PB4_PB5      1       /* Accelerometer */
+#define SPI_1_PE13_PE14_PE15   1       /* MPU6000 */
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+//#define MMC5983_I2C          1
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
+#ifndef MMC5983_I2C
+#define SPI_2_PD1_PD3_PD4      1       /* MMC5983 */
+#endif
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+#define I2C_1_PB8_PB9          0
+
+#define HAS_I2C_2              0
+#define I2C_2_PB10_PB11                0
+
+#define PACKET_HAS_SLAVE       1
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT               (&stm_gpioc)
+#define LED_PIN_RED            8
+#define LED_PIN_GREEN          9
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             1
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        1
+
+/*
+ * Igniter
+ */
+
+#define HAS_IGNITE             1
+#define HAS_IGNITE_REPORT      1
+
+#define AO_SENSE_PYRO(p,n)     ((p)->adc.sense[n])
+#define AO_SENSE_DROGUE(p)     ((p)->adc.sense[4])
+#define AO_SENSE_MAIN(p)       ((p)->adc.sense[5])
+#define AO_IGNITER_CLOSED      400
+#define AO_IGNITER_OPEN                60
+
+/* Pyro A */
+#define AO_PYRO_PORT_0 (&stm_gpiod)
+#define AO_PYRO_PIN_0  6
+
+/* Pyro B */
+#define AO_PYRO_PORT_1 (&stm_gpiod)
+#define AO_PYRO_PIN_1  7
+
+/* Pyro C */
+#define AO_PYRO_PORT_2 (&stm_gpioe)
+#define AO_PYRO_PIN_2  3
+
+/* Pyro D */
+#define AO_PYRO_PORT_3 (&stm_gpioe)
+#define AO_PYRO_PIN_3  2
+
+/* Drogue */
+#define AO_IGNITER_DROGUE_PORT (&stm_gpioe)
+#define AO_IGNITER_DROGUE_PIN  6
+
+/* Main */
+#define AO_IGNITER_MAIN_PORT   (&stm_gpioe)
+#define AO_IGNITER_MAIN_PIN    5
+
+/* Number of general purpose pyro channels available */
+#define AO_PYRO_NUM    4
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       6
+
+struct ao_adc {
+       int16_t                 sense[AO_ADC_NUM_SENSE];
+       int16_t                 v_batt;
+       int16_t                 v_pbatt;
+       int16_t                 temp;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5lu A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \
+              (p)->tick, \
+              (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \
+              (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \
+              (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp)
+
+#define AO_ADC_SENSE_A         0
+#define AO_ADC_SENSE_A_PORT    (&stm_gpioa)
+#define AO_ADC_SENSE_A_PIN     0
+
+#define AO_ADC_SENSE_B         1
+#define AO_ADC_SENSE_B_PORT    (&stm_gpioa)
+#define AO_ADC_SENSE_B_PIN     1
+
+#define AO_ADC_SENSE_C         24
+#define AO_ADC_SENSE_C_PORT    (&stm_gpioe)
+#define AO_ADC_SENSE_C_PIN     9
+
+#define AO_ADC_SENSE_D         25
+#define AO_ADC_SENSE_D_PORT    (&stm_gpioe)
+#define AO_ADC_SENSE_D_PIN     10
+
+#define AO_ADC_SENSE_DROGUE    4
+#define AO_ADC_SENSE_DROGUE_PORT       (&stm_gpioa)
+#define AO_ADC_SENSE_DROGUE_PIN        4
+
+#define AO_ADC_SENSE_MAIN      22
+#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe)
+#define AO_ADC_SENSE_MAIN_PIN  7
+
+#define AO_ADC_V_BATT          8
+#define AO_ADC_V_BATT_PORT     (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_V_PBATT         9
+#define AO_ADC_V_PBATT_PORT    (&stm_gpiob)
+#define AO_ADC_V_PBATT_PIN     1
+
+#define AO_ADC_TEMP            16
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOEEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN         (AO_ADC_NUM_SENSE + 2)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_A_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_A_PIN
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_B_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_B_PIN
+#define AO_ADC_PIN2_PORT       AO_ADC_SENSE_C_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_SENSE_C_PIN
+#define AO_ADC_PIN3_PORT       AO_ADC_SENSE_D_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_SENSE_D_PIN
+#define AO_ADC_PIN4_PORT       AO_ADC_SENSE_DROGUE_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_SENSE_DROGUE_PIN
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_MAIN_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_MAIN_PIN
+#define AO_ADC_PIN6_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_V_BATT_PIN
+#define AO_ADC_PIN7_PORT       AO_ADC_V_PBATT_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_V_PBATT_PIN
+
+#define AO_NUM_ADC             (AO_ADC_NUM_SENSE + 3)
+
+#define AO_ADC_SQ1             AO_ADC_SENSE_A
+#define AO_ADC_SQ2             AO_ADC_SENSE_B
+#define AO_ADC_SQ3             AO_ADC_SENSE_C
+#define AO_ADC_SQ4             AO_ADC_SENSE_D
+#define AO_ADC_SQ5             AO_ADC_SENSE_DROGUE
+#define AO_ADC_SQ6             AO_ADC_SENSE_MAIN
+#define AO_ADC_SQ7             AO_ADC_V_BATT
+#define AO_ADC_SQ8             AO_ADC_V_PBATT
+#define AO_ADC_SQ9             AO_ADC_TEMP
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * Voltage divider on ADC pyro battery sampler
+ */
+#define AO_PYRO_BATTERY_DIV_PLUS       100     /* 100k */
+#define AO_PYRO_BATTERY_DIV_MINUS      12      /* 12k */
+
+/*
+ * Voltage divider on ADC igniter samplers
+ */
+#define AO_IGNITE_DIV_PLUS     100     /* 100k */
+#define AO_IGNITE_DIV_MINUS    12      /* 12k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * Pressure sensor settings
+ */
+#define HAS_MS5607             1
+#define HAS_MS5611             0
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_CS_PORT      (&stm_gpioc)
+#define AO_MS5607_CS_PIN       4
+#define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS)
+#define AO_MS5607_MISO_PORT    (&stm_gpioa)
+#define AO_MS5607_MISO_PIN     6
+#define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO)
+#define AO_MS5607_SPI_INDEX    AO_SPI_1_PA5_PA6_PA7
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpiod)
+#define AO_M25_SPI_CS_MASK     (1 << 10)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN   5
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI          stm_spi2
+
+#define AO_CC1200_INT_PORT             (&stm_gpiob)
+#define AO_CC1200_INT_PIN              11
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define AO_CC1200_MARC_GPIO    3
+#define AO_CC1200_MARC_GPIO_IOCFG      CC1200_IOCFG3
+
+#define HAS_BOOT_RADIO         0
+
+
+/*
+ *
+ * Here are the required sensor signs:
+ *
+ * +along      nose up
+ * +across     USB down
+ * +through    TH down
+ *
+ * With the board aligned to have positive accel for the relevant
+ * axis, looking down from above we have:
+ *
+ * +roll       counter clockwise (nose up)
+ * +pitch      counter clockwise (USB down)
+ * +yaw                counter clockwise (TH down)
+ */
+
+/*
+ * On TMega v6, bmi088 pin 1 (NE corner of chip) is placed towards the
+ * USB and antenna edges of the board. Relative to bmi088 specs, to
+ * get the above values, we need to flip the Y axis, assigning values
+ * as follows:
+ *
+ *     +along          +X      +roll   +X
+ *     +across         -Y      +pitch  -Y
+ *     +through        +Z      +yaw    +Z
+ */
+
+#define HAS_BMI088             1
+#define AO_BMI088_SPI_BUS      AO_SPI_1_PE13_PE14_PE15
+#define AO_BMI088_ACC_CS_PORT  (&stm_gpioc)
+#define AO_BMI088_ACC_CS_PIN   14
+#define AO_BMI088_GYR_CS_PORT  (&stm_gpioc)
+#define AO_BMI088_GYR_CS_PIN   13
+#define HAS_IMU                        1
+
+#define ao_bmi088_along(m)     ((m)->acc.x)
+#define ao_bmi088_across(m)    (-(m)->acc.y)
+#define ao_bmi088_through(m)   ((m)->acc.z)
+
+#define ao_bmi088_roll(m)      ((m)->gyr.x)
+#define ao_bmi088_pitch(m)     (-(m)->gyr.y)
+#define ao_bmi088_yaw(m)       ((m)->gyr.z)
+
+#define ao_data_along(packet)  ao_bmi088_along(&(packet)->bmi088)
+#define ao_data_across(packet) ao_bmi088_across(&(packet)->bmi088)
+#define ao_data_through(packet)        ao_bmi088_through(&(packet)->bmi088)
+
+#define ao_data_roll(packet)   ao_bmi088_roll(&(packet)->bmi088)
+#define ao_data_pitch(packet)  ao_bmi088_pitch(&(packet)->bmi088)
+#define ao_data_yaw(packet)    ao_bmi088_yaw(&(packet)->bmi088)
+
+/*
+ * MMC5983
+ *
+ *     pin 1 NE corner of chip
+ *
+ *     +along          -Y
+ *     +across         +X
+ *     +through        -Z
+ */
+
+#define HAS_MMC5983            1
+#define AO_MMC5983_INT_PORT    (&stm_gpiod)
+#define AO_MMC5983_INT_PIN     5
+#define AO_MMC5983_SPI_CLK_PORT        (&stm_gpiod)
+#define AO_MMC5983_SPI_CLK_PIN 1
+#define AO_MMC5983_SPI_MISO_PORT       (&stm_gpiod)
+#define AO_MMC5983_SPI_MISO_PIN        3
+#define AO_MMC5983_SPI_MOSI_PORT       (&stm_gpiod)
+#define AO_MMC5983_SPI_MOSI_PIN        4
+#define AO_MMC5983_SPI_INDEX   (AO_SPI_2_PD1_PD3_PD4 | AO_SPI_MODE_3)
+#define AO_MMC5983_SPI_CS_PORT (&stm_gpioa)
+#define AO_MMC5983_SPI_CS_PIN  15
+
+#define ao_mmc5983_along(m)            (-(m)->y)
+#define ao_mmc5983_across(m)           ((m)->x)
+#define ao_mmc5983_through(m)          (-(m)->z)
+
+#define ao_data_mag_along(packet)      ao_mmc5983_along(&(packet)->mmc5983)
+#define ao_data_mag_across(packet)     ao_mmc5983_across(&(packet)->mmc5983)
+#define ao_data_mag_through(packet)    ao_mmc5983_through(&(packet)->mmc5983)
+
+/*
+ * ADXL375
+ *
+ * pin 1 NW corner of chip
+ *
+ *     +along          +X
+ *     +across         +Y
+ *     +through        +Z
+ */
+
+#define HAS_ADXL375            1
+#define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
+#define AO_ADXL375_CS_PORT     (&stm_gpioc)
+#define AO_ADXL375_CS_PIN      0
+
+#define AO_ADXL375_AXIS                x
+#define AO_ADXL375_INVERT      1
+
+#define NUM_CMDS               16
+
+/*
+ * Companion
+ */
+
+#define AO_COMPANION_CS_PORT   (&stm_gpiob)
+#define AO_COMPANION_CS_PIN_0  (6)
+#define AO_COMPANION_CS_PIN    AO_COMPANION_CS_PIN_0
+#define AO_COMPANION_CS_PIN_1  (7)
+#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Monitor
+ */
+
+#define HAS_MONITOR            0
+#define LEGACY_MONITOR         0
+#define HAS_MONITOR_PUT                1
+#define AO_MONITOR_LED         0
+#define HAS_RSSI               0
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE             0
+#endif
+
+/*
+ * PWM output
+ */
+
+#define NUM_PWM                        4
+#define PWM_MAX                        20000
+#define AO_PWM_TIMER           stm_tim4
+#define AO_PWM_TIMER_ENABLE    STM_RCC_APB1ENR_TIM4EN
+#define AO_PWM_TIMER_SCALE     32
+
+#define AO_PWM_0_GPIO          (&stm_gpiod)
+#define AO_PWM_0_PIN           12
+
+#define AO_PWM_1_GPIO          (&stm_gpiod)
+#define AO_PWM_1_PIN           13
+
+#define AO_PWM_2_GPIO          (&stm_gpiod)
+#define AO_PWM_2_PIN           15
+
+#define AO_PWM_3_GPIO          (&stm_gpiod)
+#define AO_PWM_3_PIN           14
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telemega-v7.0-seeed/ao_telemega_seeed.c b/src/telemega-v7.0-seeed/ao_telemega_seeed.c
new file mode 100644 (file)
index 0000000..8e47958
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2021 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_bmi088.h>
+#include <ao_mmc5983.h>
+#include <ao_adxl375.h>
+#include <ao_log.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_eeprom.h>
+#include <ao_i2c_bit.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+#include <ao_pwm.h>
+
+#define AO_FAIL_FLASH  1
+#define AO_FAIL_ADC    2
+#define AO_FAIL_GPS    3
+#define AO_FAIL_RADIO  4
+#define AO_FAIL_ACCEL  5
+#define AO_FAIL_BARO   6
+#define AO_FAIL_IMU    7
+#define AO_FAIL_MAG    8
+#define AO_FAIL_RANGE  9
+
+static void
+ao_validate(void)
+{
+       static struct ao_telemetry_location     gps_data;
+       static struct ao_telemetry_satellite    gps_tracking_data;
+       uint8_t new;
+       uint8_t data;
+       int16_t decivolt;
+       AO_TICK_TYPE    gps_start;
+
+       ao_config_get();
+       /* Check the flash part */
+       ao_storage_setup();
+       if (ao_storage_total != 8 * 1024 * 1024)
+               ao_panic(AO_FAIL_FLASH);
+
+       /* Check the battery voltage */
+       data = ao_data_head;
+       do {
+               ao_sleep((void *) &ao_data_head);
+       } while (ao_data_head == data);
+       decivolt = ao_battery_decivolt(ao_data_ring[data].adc.v_batt);
+       if (decivolt < 35 || 55 < decivolt)
+               ao_panic(AO_FAIL_ADC);
+
+       /* Check to make sure GPS data is being received */
+       gps_start = ao_time();
+       for (;;) {
+               while ((new = ao_gps_new) == 0)
+                       ao_sleep_for(&ao_gps_new, AO_SEC_TO_TICKS(1));
+               ao_mutex_get(&ao_gps_mutex);
+               if (new & AO_GPS_NEW_DATA)
+                       memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+               if (new & AO_GPS_NEW_TRACKING)
+                       memcpy(&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) {
+                       if (gps_data.flags & AO_GPS_RUNNING)
+                               break;
+               }
+               if ((AO_TICK_SIGNED) (ao_time() - gps_start) > (AO_TICK_SIGNED) AO_SEC_TO_TICKS(10))
+                       ao_panic(AO_FAIL_GPS);
+       }
+
+       if (!ao_radio_post())
+               ao_panic(AO_FAIL_RADIO);
+
+       ao_sample_init();
+       ao_flight_state = ao_flight_startup;
+       for (;;) {
+
+               /*
+                * Process ADC samples, just looping
+                * until the sensors are calibrated.
+                */
+               if (ao_sample())
+                       break;
+       }
+
+       if (ao_sensor_errors & AO_DATA_MS5607)
+               ao_panic(AO_FAIL_BARO);
+       if (ao_sensor_errors & AO_DATA_BMI088)
+               ao_panic(AO_FAIL_IMU);
+       if (ao_sensor_errors & AO_DATA_MMC5983)
+               ao_panic(AO_FAIL_MAG);
+       if (ao_sensor_errors & AO_DATA_ADXL375)
+               ao_panic(AO_FAIL_ACCEL);
+       if (ao_sensor_errors)
+               ao_panic(AO_FAIL_RANGE);
+
+       /* Check ground accel value to make sure it's somewhat valid */
+       if (ao_ground_accel < (accel_t) AO_CONFIG_DEFAULT_ACCEL_PLUS_G - ACCEL_NOSE_UP ||
+           ao_ground_accel > (accel_t) AO_CONFIG_DEFAULT_ACCEL_MINUS_G + ACCEL_NOSE_UP) {
+               ao_panic(AO_FAIL_ACCEL);
+       }
+       if (ao_ground_height < -1000 || ao_ground_height > 7000)
+               ao_panic(AO_FAIL_BARO);
+
+       ao_led_on(LEDS_AVAILABLE);
+       ao_beep_for(AO_BEEP_MID_DEFAULT, AO_MS_TO_TICKS(100));
+
+       ao_exit();
+}
+
+struct ao_task ao_validate_task;
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_serial_init();
+       ao_led_init();
+       ao_led_off(LEDS_AVAILABLE);
+       ao_timer_init();
+
+       ao_spi_init();
+#ifdef MMC5983_I2C
+       ao_i2c_bit_init();
+#endif
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+#if HAS_BEEP
+       ao_beep_init();
+#endif
+       ao_cmd_init();
+
+       ao_ms5607_init();
+       ao_bmi088_init();
+       ao_mmc5983_init();
+       ao_adxl375_init();
+
+       ao_eeprom_init();
+       ao_storage_init();
+
+       ao_usb_init();
+       ao_gps_init();
+
+       ao_radio_init();
+       ao_igniter_init();
+       ao_pyro_init();
+
+       ao_config_init();
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+
+       ao_pwm_init();
+
+       ao_add_task(&ao_validate_task, ao_validate, "validate");
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telemega-v7.0-seeed/flash-loader/ao_pins.h b/src/telemega-v7.0-seeed/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..46ba162
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2021 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 16MHz */
+#define AO_HSE         16000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Companion port cs_companion0 PB6 */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                6
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */