diff options
-rw-r--r-- | ao-tools/ao-chaosread/ao-chaosread.1 | 6 | ||||
-rw-r--r-- | ao-tools/ao-chaosread/ao-chaosread.c | 9 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | doc/pyro-channels.inc | 92 | ||||
-rw-r--r-- | src/chaoskey-v1.0/Makefile | 4 | ||||
-rw-r--r-- | src/chaoskey-v1.0/ao_chaoskey.c | 2 | ||||
-rw-r--r-- | src/chaoskey-v1.0/ao_pins.h | 4 | ||||
-rw-r--r-- | src/kernel/ao_flash_readout.c | 50 | ||||
-rw-r--r-- | src/kernel/ao_flash_readout.h | 20 | ||||
-rw-r--r-- | src/kernel/ao_flight.c | 4 | ||||
-rw-r--r-- | src/kernel/ao_product.c | 14 | ||||
-rw-r--r-- | src/kernel/ao_usb.h | 21 | ||||
-rw-r--r-- | src/stmf0/ao_usb_stm.c | 162 | ||||
-rw-r--r-- | src/test/ao_flight_test.c | 13 | ||||
-rwxr-xr-x | src/test/plottest | 4 |
15 files changed, 349 insertions, 60 deletions
diff --git a/ao-tools/ao-chaosread/ao-chaosread.1 b/ao-tools/ao-chaosread/ao-chaosread.1 index e6ed2fac..94ca5ce9 100644 --- a/ao-tools/ao-chaosread/ao-chaosread.1 +++ b/ao-tools/ao-chaosread/ao-chaosread.1 @@ -47,6 +47,12 @@ from the noise source. .TP \-r | --raw Read raw data from the noise source. This is the default. +.TP +\-f | --flash +Read the contents of flash memory on the device. This loops through +flash memory, so you can read the contents more than once, but there's +no way to reset the pointer back to the start other than making sure +you read the whole contents. .SH USAGE .I ao-chaosread reads noise data. diff --git a/ao-tools/ao-chaosread/ao-chaosread.c b/ao-tools/ao-chaosread/ao-chaosread.c index 8a814a00..5c0de125 100644 --- a/ao-tools/ao-chaosread/ao-chaosread.c +++ b/ao-tools/ao-chaosread/ao-chaosread.c @@ -174,6 +174,7 @@ chaoskey_close(struct chaoskey *ck) #define COOKED_ENDPOINT 0x85 #define RAW_ENDPOINT 0x86 +#define FLASH_ENDPOINT 0x87 int chaoskey_read(struct chaoskey *ck, int endpoint, void *buffer, int len) @@ -208,12 +209,13 @@ static const struct option options[] = { { .name = "bytes", .has_arg = 0, .val = 'b' }, { .name = "cooked", .has_arg = 0, .val = 'c' }, { .name = "raw", .has_arg = 0, .val = 'r' }, + { .name = "flash", .has_arg = 0, .val = 'f' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]] [--infinite] [--bytes] [--cooked] [--raw]\n", program); + fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]] [--infinite] [--bytes] [--cooked] [--raw] [--flash]\n", program); exit(1); } @@ -233,7 +235,7 @@ main (int argc, char **argv) int bytes = 0; int endpoint = RAW_ENDPOINT; - while ((c = getopt_long(argc, argv, "s:l:ibcr", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "s:l:ibcrf", options, NULL)) != -1) { switch (c) { case 's': serial = optarg; @@ -262,6 +264,9 @@ main (int argc, char **argv) case 'r': endpoint = RAW_ENDPOINT; break; + case 'f': + endpoint = FLASH_ENDPOINT; + break; default: usage(argv[0]); break; diff --git a/configure.ac b/configure.ac index 5f70ced5..9b0a3cef 100644 --- a/configure.ac +++ b/configure.ac @@ -18,13 +18,13 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.8.5.1) +AC_INIT([altos], 1.8.5.2) ANDROID_VERSION=17 AC_CONFIG_SRCDIR([src/kernel/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -RELEASE_DATE=2018-03-17 +RELEASE_DATE=2018-04-26 AC_SUBST(RELEASE_DATE) VERSION_DASH=`echo $VERSION | sed 's/\./-/g'` diff --git a/doc/pyro-channels.inc b/doc/pyro-channels.inc index 3b918544..7fd06412 100644 --- a/doc/pyro-channels.inc +++ b/doc/pyro-channels.inc @@ -1,33 +1,28 @@ -Acceleration:: Select a value, and then choose -whether acceleration should be above or below -that value. Acceleration is positive upwards, -so accelerating towards the ground would -produce negative numbers. Acceleration during -descent is noisy and inaccurate, so be careful -when using it during these phases of the -flight. - -Vertical speed:: Select a value, and then -choose whether vertical speed should be above -or below that value. Speed is positive -upwards, so moving towards the ground would -produce negative numbers. Speed during descent -is a bit noisy and so be careful when using it +Vertical Acceleration:: Select a value, and then choose whether +acceleration away from the ground should be above or below that +value. Acceleration is positive upwards, so accelerating towards the +ground would produce negative numbers. Acceleration during descent is +noisy and inaccurate, so be careful when using it during these phases +of the flight. + +Ascent rate:: Select a value, and then choose whether ascent rate +should be above or below that value. Ascent rate is positive upwards, +so moving towards the ground would produce negative numbers. Ascent +rate during descent is a bit noisy and so be careful when using it during these phases of the flight. -Height:: Select a value, and then choose -whether the height above the launch pad should -be above or below that value. +Height above pad:: Select a value, and then choose whether the height +above the launch pad should be above or below that value. -Orientation:: TeleMega and EasyMega contain a -3-axis gyroscope and accelerometer which is -used to measure the current angle. Note that -this angle is not the change in angle from the -launch pad, but rather absolute relative to -gravity; the 3-axis accelerometer is used to -compute the angle of the rocket on the launch -pad and initialize the system. +Orientation:: TeleMega and EasyMega contain a 3-axis gyroscope and +accelerometer which is used to compute the orientation of the +rocket. A record of orientations over the last 0.64 seconds is kept +and the largest value within this period is compared with the +specified value. Note that the tilt angle is not the change in angle +from the launch pad, but rather absolute relative to gravity—the +3-axis accelerometer is used to compute the angle of the rocket on the +launch pad and initialize the system. [NOTE] ==== @@ -51,41 +46,60 @@ Flight Time:: Time since boost was detected. Select a value and choose whether to activate the pyro channel before or after that amount of time. -Ascending:: A simple test saying whether the rocket is going up or -not. This is exactly equivalent to testing whether the speed is > 0. +Ascending:: A deprecated configuration value which was the same as +setting Ascent rate > 0. Existing configurations using this will be +cleared and must be reconfigured by the user. -Descending:: A simple test saying whether the rocket is going down or -not. This is exactly equivalent to testing whether the speed is < 0. +Descending:: A deprecated configuration value which was the same as +setting Ascent rate < 0. Existing configurations using this will be +cleared and must be reconfigured by the user. After Motor:: The flight software counts each time the rocket starts accelerating and then decelerating (presumably due to a motor or motors burning). Use this value for multi-staged or multi-airstart launches. -Delay:: This value doesn't perform any checks, instead it inserts a -delay between the time when the other parameters become true and when -the pyro channel is activated. +Delay:: Once the other parameters all become true, a timer is +started for the specified amount of time. While the timer is running, +the other parameters are checked repeatedly and if any of them become +false, then the pyro channel is disabled and will not fire. If the +timer expires and all of the other parameters have remained true for +the entire time, then the pyro channel is fired. Flight State:: The flight software tracks the flight through a sequence of states: * Boost. The motor has lit and the rocket is - accelerating upwards. + accelerating upwards. Ascent rate will be greater than zero. + Vertical acceleration will be greater than zero. * Fast. The motor has burned out and the rocket is decelerating, but it is going - faster than 200m/s. + faster than 200m/s. Ascent rate will be greater than zero. Vertical + acceleration will be less than zero. * Coast. The rocket is still moving upwards - and decelerating, but the speed is less - than 200m/s. + and decelerating, but the Ascent rate is less + than 200m/s. Ascent rate will greater than zero. Vertical + acceleration will be less than zero. * Drogue. The rocket has reached apogee and is heading back down, but is above the - configured Main altitude. + configured Main altitude. Ascent rate will be less than zero during + this state. Vertical acceleration will be negative until the rocket + reaches a terminal descent rate, at which point Vertical + acceleration will be zero. Both Ascent rate and Vertical + acceleration are very noisy in this state, so be careful when + trying to use them to control pyro channels. * Main. The rocket is still descending, and - is below the Main altitude + is below the Main altitude. Ascent rate will be less than zero + during this state. Vertical acceleration may be briefly less than + zero as the rocket slows from drogue descent to main descent, but + it will settle down to a zero value once the rocket has reached the + terminal velocity under the main chute. Ascent rate and Vertical + acceleration should be much less noisy once the main chute has + deployed. * Landed. The rocket is no longer moving. diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile index dea5b483..c6cf45bd 100644 --- a/src/chaoskey-v1.0/Makefile +++ b/src/chaoskey-v1.0/Makefile @@ -14,6 +14,7 @@ INC = \ ao_task.h \ ao_adc_fast.h \ ao_power.h \ + ao_flash_readout.h \ ao_crc.h \ stm32f0.h @@ -34,6 +35,7 @@ ALTOS_SRC = \ ao_boot_chain.c \ ao_usb_stm.c \ ao_trng_send.c \ + ao_flash_readout.c \ ao_task.c \ ao_power.c \ ao_gpio.c \ @@ -84,7 +86,7 @@ check: $(METAINFO) distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx *.bin rm -f ao_product.h rm -f *.cab diff --git a/src/chaoskey-v1.0/ao_chaoskey.c b/src/chaoskey-v1.0/ao_chaoskey.c index c3acd441..1165e454 100644 --- a/src/chaoskey-v1.0/ao_chaoskey.c +++ b/src/chaoskey-v1.0/ao_chaoskey.c @@ -20,6 +20,7 @@ #include <ao_adc_fast.h> #include <ao_crc.h> #include <ao_trng_send.h> +#include <ao_flash_readout.h> void main(void) { @@ -30,6 +31,7 @@ void main(void) ao_dma_init(); ao_adc_init(); ao_crc_init(); + ao_flash_readout_init(); ao_usb_init(); diff --git a/src/chaoskey-v1.0/ao_pins.h b/src/chaoskey-v1.0/ao_pins.h index f2c46d8b..22861d9d 100644 --- a/src/chaoskey-v1.0/ao_pins.h +++ b/src/chaoskey-v1.0/ao_pins.h @@ -50,6 +50,7 @@ #define AO_USB_HAS_OUT 0 #define AO_USB_HAS_IN 1 #define AO_USB_HAS_IN2 1 +#define AO_USB_HAS_IN3 1 #define AO_USB_HAS_INT 0 #define AO_USB_SELF_POWER 0 #define AO_USB_DEVICE_ID_SERIAL 1 @@ -58,6 +59,9 @@ #define IS_FLASH_LOADER 0 +#define AO_FLASH_READOUT 1 +#define ao_flash_readout_putchar(c) ao_usb_putchar3(c) + /* ADC */ #define AO_ADC_PIN0_PORT (&stm_gpioa) diff --git a/src/kernel/ao_flash_readout.c b/src/kernel/ao_flash_readout.c new file mode 100644 index 00000000..46b5ba7a --- /dev/null +++ b/src/kernel/ao_flash_readout.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2018 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. + */ + +#include <ao.h> +#include <ao_usb.h> +#include <ao_flash_readout.h> + +#ifndef AO_FLASH_READOUT_BASE +#define AO_FLASH_READOUT_BASE AO_BOOT_LOADER_BASE +#define AO_FLASH_READOUT_BOUND AO_BOOT_APPLICATION_BOUND +#endif + +static void +ao_flash_readout(void) +{ + uint8_t *base = (uint8_t *) AO_FLASH_READOUT_BASE; + uint8_t *bound = (uint8_t *) AO_FLASH_READOUT_BOUND; + uint8_t *p = base; + + for (;;) { + ao_arch_block_interrupts(); + while (!ao_usb_running) { + p = base; + ao_sleep(&ao_usb_running); + } + ao_arch_release_interrupts(); + ao_flash_readout_putchar(*p++); + if (p == bound) + p = base; + } +} + +static struct ao_task ao_flash_readout_task; + +void +ao_flash_readout_init(void) +{ + ao_add_task(&ao_flash_readout_task, ao_flash_readout, "flash_readout"); +} diff --git a/src/kernel/ao_flash_readout.h b/src/kernel/ao_flash_readout.h new file mode 100644 index 00000000..5eee53cc --- /dev/null +++ b/src/kernel/ao_flash_readout.h @@ -0,0 +1,20 @@ +/* + * Copyright © 2018 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. + */ + +#ifndef _AO_FLASH_READOUT_H_ +#define _AO_FLASH_READOUT_H_ + +void ao_flash_readout_init(void); + +#endif /* _AO_FLASH_READOUT_H_ */ diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index cb02c454..7b3cb9fa 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -233,7 +233,7 @@ ao_flight(void) * 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)) || + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5)) || (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) { #if HAS_ACCEL @@ -310,7 +310,7 @@ ao_flight(void) #if HAS_ACCEL else { check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + ao_coast_avg_accel = ao_coast_avg_accel + ((ao_accel - ao_coast_avg_accel) >> 5); if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { ao_boost_tick = ao_sample_tick; ao_flight_state = ao_flight_boost; diff --git a/src/kernel/ao_product.c b/src/kernel/ao_product.c index c4df9f26..4c2d83ef 100644 --- a/src/kernel/ao_product.c +++ b/src/kernel/ao_product.c @@ -55,7 +55,7 @@ const char ao_product[] = AO_iProduct_STRING; #define HEADER_LEN 9 #define CONTROL_CLASS_LEN 35 -#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2) +#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2 + 7 * AO_USB_HAS_IN3) #define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN) #define NUM_INTERFACES (AO_USB_HAS_INT + 1) @@ -141,7 +141,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = AO_USB_DESC_INTERFACE, AO_USB_HAS_INT, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ - AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2, /* bNumEndPoints */ + AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2 + AO_USB_HAS_IN3, /* bNumEndPoints */ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */ 0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceProtocol */ @@ -177,6 +177,16 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x00, /* bInterval */ #endif +#if AO_USB_HAS_IN3 + /* Data EP in 3 */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_IN3_EP|0x80, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ +#endif + /* String descriptors */ 0x04, AO_USB_DESC_STRING, diff --git a/src/kernel/ao_usb.h b/src/kernel/ao_usb.h index 936d939b..40516de1 100644 --- a/src/kernel/ao_usb.h +++ b/src/kernel/ao_usb.h @@ -41,7 +41,23 @@ ao_usb_pollchar(void); void ao_usb_flush(void); +#if AO_USB_HAS_IN2 +void +ao_usb_flush2(void); + +void +ao_usb_putchar2(char c); +#endif + +#if AO_USB_HAS_IN3 +void +ao_usb_flush3(void); + +void +ao_usb_putchar3(char c); +#endif /* Enable the USB controller */ + void ao_usb_enable(void); @@ -107,6 +123,7 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #define AO_USB_OUT_EP 4 #define AO_USB_IN_EP 5 #define AO_USB_IN2_EP 6 +#define AO_USB_IN3_EP 7 #endif #ifndef AO_USB_HAS_OUT @@ -125,6 +142,10 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #define AO_USB_HAS_IN2 0 #endif +#ifndef AO_USB_HAS_IN3 +#define AO_USB_HAS_IN3 0 +#endif + /* * USB bulk packets can only come in 8, 16, 32 and 64 * byte sizes, so we'll use 64 for everything diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index 483d2419..c4860d8e 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -113,6 +113,12 @@ static uint8_t ao_usb_in_tx2_which; static uint8_t ao_usb_tx2_count; #endif +#if AO_USB_HAS_IN3 +static uint16_t ao_usb_in_tx3_offset; +static uint8_t ao_usb_in_tx3_which; +static uint8_t ao_usb_tx3_count; +#endif + /* * End point register indices */ @@ -122,6 +128,7 @@ static uint8_t ao_usb_tx2_count; #define AO_USB_OUT_EPR 2 #define AO_USB_IN_EPR 3 #define AO_USB_IN2_EPR 4 +#define AO_USB_IN3_EPR 5 /* Marks when we don't need to send an IN packet. * This happens only when the last IN packet is not full, @@ -146,6 +153,16 @@ static uint16_t in2_count; static uint8_t ao_usb_in2_flushed; #endif +#if AO_USB_HAS_IN3 +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t ao_usb_in3_pending; +static uint16_t in3_count; +static uint8_t ao_usb_in3_flushed; +#endif + /* Marks when an OUT packet has been received by the hardware * but not pulled to the shadow buffer. */ @@ -423,6 +440,11 @@ ao_usb_alloc_buffers(void) ao_usb_in_tx2_offset = sram_addr; sram_addr += AO_USB_IN_SIZE * 2; #endif +#if AO_USB_HAS_IN3 + sram_addr += (sram_addr & 1); + ao_usb_in_tx3_offset = sram_addr; + sram_addr += AO_USB_IN_SIZE * 2; +#endif } static void @@ -558,6 +580,25 @@ ao_usb_set_configuration(void) ao_usb_in_tx2_which = 0; #endif +#if AO_USB_HAS_IN3 + /* Set up the IN3 end point */ + stm_usb_bdt[AO_USB_IN3_EPR].double_tx[0].addr = ao_usb_in_tx3_offset; + stm_usb_bdt[AO_USB_IN3_EPR].double_tx[0].count = 0; + stm_usb_bdt[AO_USB_IN3_EPR].double_tx[1].addr = ao_usb_in_tx3_offset + AO_USB_IN_SIZE; + stm_usb_bdt[AO_USB_IN3_EPR].double_tx[1].count = 0; + + ao_usb_init_ep(AO_USB_IN3_EPR, + AO_USB_IN3_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK, + STM_USB_EPR_EP_KIND_DBL_BUF, + 0, 1); + + /* First transmit data goes to buffer 0 */ + ao_usb_in_tx3_which = 0; +#endif + ao_usb_in_flushed = 0; ao_usb_in_pending = 0; ao_wakeup(&ao_usb_in_pending); @@ -567,6 +608,12 @@ ao_usb_set_configuration(void) ao_wakeup(&ao_usb_in2_pending); #endif +#if AO_USB_HAS_IN3 + ao_usb_in3_flushed = 0; + ao_usb_in3_pending = 0; + ao_wakeup(&ao_usb_in3_pending); +#endif + ao_usb_out_avail = 0; ao_usb_configuration = 0; @@ -996,6 +1043,16 @@ stm_usb_isr(void) } break; #endif +#if AO_USB_HAS_IN3 + case AO_USB_IN3_EPR: + ++in3_count; + _tx_dbg1("TX3 ISR", epr); + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in3_pending = 0; + ao_wakeup(&ao_usb_in3_pending); + } + break; +#endif case AO_USB_INT_EPR: #if USB_STATUS ++int_count; @@ -1132,6 +1189,9 @@ _ao_usb_in2_send(void) /* Toggle our usage */ ao_usb_in_tx2_which = 1 - ao_usb_in_tx2_which; + /* Toggle the SW_BUF flag */ + _ao_usb_toggle_dtog(AO_USB_IN2_EPR, 1, 0); + /* Mark the outgoing buffer as valid */ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID); @@ -1199,6 +1259,94 @@ ao_usb_putchar2(char c) } #endif +#if AO_USB_HAS_IN3 +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in3_send(void) +{ + _tx_dbg0("in3_send start"); + debug ("send3 %d\n", ao_usb_tx3_count); + while (ao_usb_in3_pending) + ao_sleep(&ao_usb_in3_pending); + ao_usb_in3_pending = 1; + if (ao_usb_tx3_count != AO_USB_IN_SIZE) + ao_usb_in3_flushed = 1; + stm_usb_bdt[AO_USB_IN3_EPR].double_tx[ao_usb_in_tx3_which].count = ao_usb_tx3_count; + ao_usb_tx3_count = 0; + + /* Toggle our usage */ + ao_usb_in_tx3_which = 1 - ao_usb_in_tx3_which; + + /* Toggle the SW_BUF flag */ + _ao_usb_toggle_dtog(AO_USB_IN3_EPR, 1, 0); + + /* Mark the outgoing buffer as valid */ + _ao_usb_set_stat_tx(AO_USB_IN3_EPR, STM_USB_EPR_STAT_TX_VALID); + + _tx_dbg0("in3_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in3_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx3_count < AO_USB_IN_SIZE) + break; + + _tx_dbg0("in3_wait top"); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in3_pending) + ao_sleep(&ao_usb_in3_pending); + _tx_dbg0("in_wait bottom"); + } +} + +void +ao_usb_flush3(void) +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + ao_arch_block_interrupts(); + while (!ao_usb_in3_flushed) { + _tx_dbg0("flush3 top"); + _ao_usb_in3_send(); + _tx_dbg0("flush3 end"); + } + ao_arch_release_interrupts(); +} + +void +ao_usb_putchar3(char c) +{ + if (!ao_usb_running) + return; + + ao_arch_block_interrupts(); + _ao_usb_in3_wait(); + + ao_usb_in3_flushed = 0; + ao_usb_tx_byte(ao_usb_in_tx3_offset + AO_USB_IN_SIZE * ao_usb_in_tx3_which + ao_usb_tx3_count++, c); + + /* Send the packet when full */ + if (ao_usb_tx3_count == AO_USB_IN_SIZE) { + _tx_dbg0("putchar3 full"); + _ao_usb_in3_send(); + _tx_dbg0("putchar3 flushed"); + } + ao_arch_release_interrupts(); +} +#endif + #if AO_USB_HAS_OUT static void _ao_usb_out_recv(void) @@ -1541,9 +1689,9 @@ struct ao_usb_dbg { #endif }; -#define NUM_USB_DBG 128 +#define NUM_USB_DBG 16 -struct ao_usb_dbg dbg[128]; +struct ao_usb_dbg dbg[NUM_USB_DBG]; int dbg_i; static void _dbg(int line, char *msg, uint32_t value) @@ -1555,11 +1703,11 @@ static void _dbg(int line, char *msg, uint32_t value) asm("mrs %0,primask" : "=&r" (primask)); dbg[dbg_i].primask = primask; #if TX_DBG - dbg[dbg_i].in_count = in_count; - dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR]; - dbg[dbg_i].in_pending = ao_usb_in_pending; - dbg[dbg_i].tx_count = ao_usb_tx_count; - dbg[dbg_i].in_flushed = ao_usb_in_flushed; + dbg[dbg_i].in_count = in3_count; + dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN3_EPR].r; + dbg[dbg_i].in_pending = ao_usb_in3_pending; + dbg[dbg_i].tx_count = ao_usb_tx3_count; + dbg[dbg_i].in_flushed = ao_usb_in3_flushed; #endif #if RX_DBG dbg[dbg_i].rx_count = ao_usb_rx_count; diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 2d862f82..8fe3b5df 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -504,7 +504,7 @@ ao_insert(void) ao_data_ring[ao_data_head] = ao_data_static; if (ao_flight_state != ao_flight_startup) { #if HAS_ACCEL - double accel = ((ao_flight_ground_accel - ao_data_accel_cook(&ao_data_static)) * GRAVITY * 2.0) / + double accel = ((ao_flight_ground_accel - ao_data_accel(&ao_data_static)) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); #else double accel = 0.0; @@ -515,7 +515,12 @@ ao_insert(void) tick_offset = -ao_data_static.tick; if ((prev_tick - ao_data_static.tick) > 0x400) tick_offset += 65536; - simple_speed += accel * (ao_data_static.tick - prev_tick) / 100.0; + if (prev_tick) { + int ticks = ao_data_static.tick - prev_tick; + if (ticks < 0) + ticks += 65536; + simple_speed += accel * ticks / 100.0; + } prev_tick = ao_data_static.tick; time = (double) (ao_data_static.tick + tick_offset) / 100; @@ -653,7 +658,7 @@ ao_insert(void) #if 1 printf("%7.2f height %8.2f accel %8.3f accel_speed %8.3f " - "state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d" + "state %d k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d" #if TELEMEGA " angle %5d " "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d " @@ -663,7 +668,7 @@ ao_insert(void) height, accel, simple_speed > -100.0 ? simple_speed : -100.0, - ao_state_names[ao_flight_state], + ao_flight_state * 10, ao_k_height / 65536.0, ao_k_speed / 65536.0 / 16.0, ao_k_accel / 65536.0 / 16.0, diff --git a/src/test/plottest b/src/test/plottest index 95337f10..e427604a 100755 --- a/src/test/plottest +++ b/src/test/plottest @@ -1,4 +1,5 @@ gnuplot -persist << EOF +set title "$1" set ylabel "altitude (m)" set y2label "velocity (m/s), acceleration(m/s²)" set xlabel "time (s)" @@ -13,5 +14,6 @@ plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ "$1" using 1:15 with lines axes x1y2 title "accel",\ "$1" using 1:19 with lines axes x1y1 title "drogue",\ "$1" using 1:21 with lines axes x1y1 title "main",\ -"$1" using 1:23 with lines axes x1y1 title "error" +"$1" using 1:23 with lines axes x1y1 title "error",\ +"$1" using 1:9 with lines axes x1y2 title "state" EOF |