Merge branch 'branch-1.8' into debian
authorBdale Garbee <bdale@gag.com>
Sun, 5 Aug 2018 03:24:13 +0000 (11:24 +0800)
committerBdale Garbee <bdale@gag.com>
Sun, 5 Aug 2018 03:24:13 +0000 (11:24 +0800)
136 files changed:
ChangeLog
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java
altoslib/AltosAccelCal.java
altoslib/AltosCalData.java
altoslib/AltosConfigData.java
altoslib/AltosDebug.java
altoslib/AltosFlightSeries.java
altoslib/AltosFlightStats.java
altoslib/AltosHexfile.java
altoslib/AltosIMU.java
altoslib/AltosIdleFetch.java
altoslib/AltosLib.java
altoslib/AltosLink.java
altoslib/AltosPyro.java
altoslib/AltosRomconfig.java
altosui/AltosConfigFCUI.java
altosui/AltosConfigPyroUI.java
altosuilib/AltosFlashUI.java
ao-bringup/turnon_chaoskey
ao-bringup/turnon_telegps
ao-bringup/turnon_telelco [new file with mode: 0755]
ao-bringup/turnon_telemega
ao-bringup/turnon_telemetrum
ao-bringup/turnon_telemini
ao-tools/ao-chaosread/ao-chaosread.1
ao-tools/ao-chaosread/ao-chaosread.c
ao-tools/ao-dumplog/ao-dumplog.c
configure.ac
doc/Makefile
doc/RELNOTES
doc/altusmetrum-docinfo.xml
doc/config-device.inc
doc/easymini-release-notes.inc
doc/intro.inc
doc/load-maps.inc
doc/pyro-channels.inc
doc/release-notes-1.8.6.inc [new file with mode: 0644]
doc/release-notes.inc
doc/telegps-release-notes.inc
micropeak/MicroData.java
src/Makefile
src/chaoskey-v1.0/Makefile
src/chaoskey-v1.0/ao_chaoskey.c
src/chaoskey-v1.0/ao_pins.h
src/drivers/ao_button.c
src/drivers/ao_cc1120.c
src/drivers/ao_lco.c
src/drivers/ao_lco.h
src/drivers/ao_lco_bits.c [new file with mode: 0644]
src/drivers/ao_lco_cmd.c
src/drivers/ao_lco_two.c
src/drivers/ao_pad.c
src/drivers/ao_quadrature.c
src/fox1ihu/.gitignore [new file with mode: 0644]
src/fox1ihu/Makefile [new file with mode: 0644]
src/fox1ihu/ao_fox1ihu.c [new file with mode: 0644]
src/fox1ihu/ao_pins.h [new file with mode: 0644]
src/fox1ihu/flash-loader/Makefile [new file with mode: 0644]
src/fox1ihu/flash-loader/ao_pins.h [new file with mode: 0644]
src/kernel/ao_flash_readout.c [new file with mode: 0644]
src/kernel/ao_flash_readout.h [new file with mode: 0644]
src/kernel/ao_flight.c
src/kernel/ao_flight.h
src/kernel/ao_kalman.c
src/kernel/ao_product.c
src/kernel/ao_pyro.c
src/kernel/ao_sample.c
src/kernel/ao_sample.h
src/kernel/ao_usb.h
src/mpusb-v3.0/.gitignore [new file with mode: 0644]
src/mpusb-v3.0/Makefile [new file with mode: 0644]
src/mpusb-v3.0/ao_mpusb.c [new file with mode: 0644]
src/mpusb-v3.0/ao_pins.h [new file with mode: 0644]
src/mpusb-v3.0/flash-loader/.gitignore [new file with mode: 0644]
src/mpusb-v3.0/flash-loader/Makefile [new file with mode: 0644]
src/mpusb-v3.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/product/ao_flash_pins.h
src/stm-demo/Makefile
src/stm-demo/ao_demo.c
src/stm-demo/ao_pins.h
src/stm/ao_adc_single.h [new file with mode: 0644]
src/stm/ao_adc_single_stm.c [new file with mode: 0644]
src/stm/ao_arch.h
src/stm/ao_led.c
src/stm/ao_romconfig.c
src/stm/ao_timer.c
src/stm/ao_usb_stm.c
src/stm/stm32l.h
src/stmf0/ao_arch_funcs.h
src/stmf0/ao_flash_loader_stm.c
src/stmf0/ao_interrupt.c
src/stmf0/ao_usb_stm.c
src/telefire-v0.1/ao_pins.h
src/telefire-v0.2/ao_pins.h
src/telefireeight-v1.0/.gitignore [new file with mode: 0644]
src/telefireeight-v1.0/Makefile [new file with mode: 0644]
src/telefireeight-v1.0/ao_pins.h [new file with mode: 0644]
src/telefireeight-v1.0/ao_telefireeight.c [new file with mode: 0644]
src/telefireeight-v1.0/flash-loader/.gitignore [new file with mode: 0644]
src/telefireeight-v1.0/flash-loader/Makefile [new file with mode: 0644]
src/telefireeight-v1.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telefiretwo-v0.1/ao_pins.h
src/telelco-v0.2-cc1200/Makefile [new file with mode: 0644]
src/telelco-v0.2-cc1200/ao_pins.h [new file with mode: 0644]
src/telelco-v0.2-cc1200/ao_telelco.c [new file with mode: 0644]
src/telelco-v0.2-cc1200/flash-loader/.gitignore [new file with mode: 0644]
src/telelco-v0.2-cc1200/flash-loader/Makefile [new file with mode: 0644]
src/telelco-v0.2-cc1200/flash-loader/ao_pins.h [new file with mode: 0644]
src/telelco-v0.2/Makefile
src/telelco-v0.2/ao_pins.h
src/telelco-v0.3/Makefile
src/telelco-v0.3/ao_pins.h
src/telelco-v2.0/.gitignore [new file with mode: 0644]
src/telelco-v2.0/Makefile [new file with mode: 0644]
src/telelco-v2.0/ao_lco_v2.c [new file with mode: 0644]
src/telelco-v2.0/ao_pins.h [new file with mode: 0644]
src/telelco-v2.0/ao_telelco.c [new file with mode: 0644]
src/telelco-v2.0/flash-loader/.gitignore [new file with mode: 0644]
src/telelco-v2.0/flash-loader/Makefile [new file with mode: 0644]
src/telelco-v2.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/telelcotwo-v0.1/Makefile
src/telelcotwo-v0.1/ao_pins.h
src/test/ao_flight_test.c
src/test/plottest
src/tmgps-v2.0/.gitignore [new file with mode: 0644]
src/tmgps-v2.0/Makefile [new file with mode: 0644]
src/tmgps-v2.0/ao_pins.h [new file with mode: 0644]
src/tmgps-v2.0/ao_tmgps.c [new file with mode: 0644]
src/vidtime/.gitignore [new file with mode: 0644]
src/vidtime/Makefile [new file with mode: 0644]
src/vidtime/ao_pins.h [new file with mode: 0644]
src/vidtime/ao_vidtime.c [new file with mode: 0644]
src/vidtime/flash-loader/.gitignore [new file with mode: 0644]
src/vidtime/flash-loader/Makefile [new file with mode: 0644]
src/vidtime/flash-loader/ao_pins.h [new file with mode: 0644]

index 90220e0de1c7021b1cb705bde660a455796bd859..e25234b26d884b8137c855465a9a7ab474904dc4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+commit d8627bb7b46fc991786835afa38cd720e9e75812
+Merge: 59e23c27 8830fbc9
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Aug 5 11:21:37 2018 +0800
+
+    Merge branch 'master' into branch-1.8
+
+commit 8830fbc99565f753c0ae1f3d9f4b079860c2634a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 5 11:13:23 2018 +0800
+
+    Update docs for 1.8.6
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d57c78dde3c6e61576a4769b0e0fae7e88c107d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 5 11:09:34 2018 +0800
+
+    altos: Add separate 'ao_launch_tick'. Use in pyro and lockout.
+    
+    Prior to this, there was only ao_boost_tick, which got reset at each
+    motor burn start. That meant there wasn't any way to measure total
+    flight time for pyro channels and 'apogee lockout' was based on time
+    since most recent motor start instead of total flight time.
+    
+    Now pyro channels and apogee lockout both use total flight time, while
+    motor burn length still uses time since most recent motor burn start
+    (as it should).
+    
+    Docs and UI updated to use 'launch' instead of 'boost' to try and make
+    the change clear.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9dfbf0103a649816e98d5511b1d6bbbfc93f6632
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 5 09:03:35 2018 +0800
+
+    altos/plottest: Make linewidth bigger
+    
+    1-pixel lines are harsh in 2018
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 50c6d796e0dbb69289f95c826e6b542e538fc5de
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 5 08:45:30 2018 +0800
+
+    altos/stm-demo: Set up for dumping eeprom
+    
+    This is used to dump an eeprom wired to the stm demo board.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 327b765962d397efd4c45b6209c9225a4d23ba1d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 5 08:44:04 2018 +0800
+
+    altos: Change 'after motor' pyro check to be >= instead of ==
+    
+    This makes after motor stay valid even if further motors burn.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a90d205d41cb4f9f8e669473247786a23a678368
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 5 08:43:06 2018 +0800
+
+    ao-tools/ao-dumplog: Dump entire eeprom contents
+    
+    This gets the eeprom size from the device and uses that to dump the
+    whole thing.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08e7fdb9f2db4b54279c0c5b18735aa1d5abc19e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 4 20:25:58 2018 -0700
+
+    altoslib: Make stop_remote delay depend on the data rate
+    
+    It takes longer to flush commands at 2400 baud, so wait longer when
+    disabling remote mode.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 323a79e6ed3dfdd2afadfc2a464bb0610380b03b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 4 16:08:31 2018 -0700
+
+    altos: Fetch current quadrature status at startup time
+    
+    This avoids having the state appear to change the first time we look
+    at the device.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ad9d6677231ccbfa09a528387f306f5364f9d608
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 4 12:34:38 2018 -0700
+
+    altos: Make fewer LCO variables public
+    
+    The lco common code doesn't need to share its internal values with the
+    world; make most of them static.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 38fb80e5e6af87f8c734448e4aa69b2c39854903
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 4 11:58:40 2018 -0700
+
+    altos: Make LCO search directly drive pad/box displays
+    
+    Don't use ao_lco_show as that has other logic too.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2214ad7c0f268be76c0b027eef9d1dc406f23b28
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 4 11:27:31 2018 -0700
+
+    altos: Fix LCO display while searching
+    
+    Use lower level functions to control the display more directly
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3b53a69e47816ee987a409b05a6b0b47891ca816
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 4 11:18:12 2018 -0700
+
+    altos: Fix telelcotwo build for new ao_lco_bits.c file
+    
+    Lots of code motion; shouldn't have any functional changes.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 71a51b4857f5bd49c0cba2578fb54b1d5b2c738b
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jul 4 12:13:38 2018 -0600
+
+    add telefireeight-v1.0 to products built by default in src/Makefile
+
+commit 81355cd08a22502d47637f2505b6089d226d0889
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 3 01:06:09 2018 -0700
+
+    altos: A bit more LCO code sharing
+    
+    Missed drag race pad toggling in ao_lco_v2.c
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 55f817d6ff1a524434fe41ba83e42b8008989cac
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 3 01:01:05 2018 -0700
+
+    altos: Build telelco-v2.0 by default
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c48d4b60da8b23bf358e6c14d7332d3a360c2d2f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 3 01:00:15 2018 -0700
+
+    altos: Share common LCO functions in ao_lco_bits.c
+    
+    Move common code out of ao_lco.c and ao_lco_v2.c into a shared file,
+    ao_lco_bits.c. Update ao_lco.h to include shared functions.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e56e1dc20b3bf18073766da4e26e97d9e1d419fc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 2 14:21:48 2018 -0700
+
+    altos/test: Compute and show height error tracker in ao_flight_test
+    
+    Enable the computation of ao_error_h_sq_avg in ao_flight_test even
+    when an accelerometer is present to allow review of that data.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c263fde769da380d55d223cebe3c9b6e8f19cb29
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jul 2 14:20:39 2018 -0700
+
+    altosuilib: Split cc1111 vs arm telefire/telemini for flashing
+    
+    Only older telefire and telemini boards had cc1111 processors and need
+    pair-programming.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8794920328c8311372f83e4e5656ce14c7f8336b
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Jul 1 14:50:26 2018 -0600
+
+    add a turnon script for TeleLCO v2.0
+
+commit 655fd8e1490b70061cd81edf1d019e0469843688
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 18 10:53:35 2018 -0700
+
+    altos/telelco-v2.0: Do all drag race beeping from the beeping thread
+    
+    Instead of starting the beep from the calling thread, just update some
+    state and poke the beeping thread.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9ece56e3ad76af6ae623ad7a6782c0c933839be8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 12:35:23 2018 -0700
+
+    altos/ao_pad: Move LED test to the monitor task
+    
+    It sets the LEDs, so it's best to not start doing that until we've
+    tested them.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cef5a5725e3bf2c17965599bd76eb93cb05a0f80
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 12:30:09 2018 -0700
+
+    altos/ao_pad: Turn on all LEDs for a moment at power up
+    
+    Allow validation of all LED connections.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 731ba39a22719a8c431eb63895cd8ba553975114
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 12:29:36 2018 -0700
+
+    altos/ao_pad: Use AO_LED_TYPE for computing active LEDs.
+    
+    instead of uint8_t
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 42ee832368f6ff796444823d53935d824acd329a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 12:28:51 2018 -0700
+
+    altos/stm: Let products override AO_LED_TYPE for stm processors
+    
+    No need requiring it to be uint16_t
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c2d9f13a97d45b7dbe2cb47b563aea59ec725bb1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 01:36:00 2018 -0700
+
+    Bump version to 1.8.6
+    
+    Prepare for release.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 290506129fb6cb664da3a5e3ca450a0dcdff0398
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 01:20:01 2018 -0700
+
+    altos/telelco-v2.0: Fix AO_ADC_DUMP
+    
+    Was printing p.v_batt instead of (p)->v_batt. I don't know why the
+    former even worked.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 291bcd751991960ae3dad8c6523323fdcbafa16d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 16 23:50:11 2018 -0700
+
+    altos/telelco-v0.2-cc1200: Add build for NAR hacked TeleLCO v0.2 board
+    
+    This has the CC1120 replaced with a CC1200, but with 32MHz xtals
+    instead of 40MHz on the radio chip.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 16482bf5d63eafc5256f14a218d3a374f6584e0a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 16 23:51:26 2018 -0700
+
+    altos/driver: Improve quadrature debouncing for mechanical encoders
+    
+    Track state of encoder better and only bump values when the full
+    motion is detected (all four states).
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit abac6c59d6b004d52a7b782865d2d987732cd61e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 00:17:29 2018 -0700
+
+    altos/telelco-v0: Test display, show batt voltage at boot
+    
+    Just like telelco v2
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 96835cc841ff7afad0b4d2fe4b63f26b951da122
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Jun 17 00:19:37 2018 -0700
+
+    ao-bringup: Find dfu-util in $PATH for chaoskey
+    
+    In case it's not in /usr/bin
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7821e341a7cf55e32b926eb4474220dabb6eeb81
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 16 23:47:42 2018 -0700
+
+    altos/stm: Define ADC channels for TEMP and V_REF
+    
+    These are fixed at 16 and 17.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5c465b0049659246908b15be68806b1390e8ebe5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 16 23:47:15 2018 -0700
+
+    altos/stm: Remove unused ADC names from ao_adc_single_stm.c
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5d9881547706b49cc22b98cc5c94e01e8a7f5181
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu May 31 22:45:49 2018 -0700
+
+    altos/telelco: Remove STATIC_TEST code from stand-alone LCO boxes
+    
+    This command conflicts with the 'debug' command in these devices and
+    so wasn't usable anyways.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f755181fd3ec82d7644591e2ed4b99a244acfd6e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu May 31 22:42:13 2018 -0700
+
+    altos/telelco-v2.0: Test displays at power on
+    
+    At boot, light up all LEDS and LCD segments for a second to let the
+    user verify that things are working correctly.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 99642f9c4f89aa5577376a9cd118e7cff26e2762
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu May 31 22:39:45 2018 -0700
+
+    altos/telefire*: Do voltage tests in decivolts instead of ADC units
+    
+    This requires that each pad device specify the ADC reference voltage
+    and all relevant voltage divider resistor values explicitly so that
+    the ADC values can be converted to decivolts and compared with one
+    another. This should be easier to understand in the future when
+    reading the code.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ab22c56ca02db87a84b6950c024a90b086f5ce28
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu May 31 16:24:33 2018 -0700
+
+    altos/telefireeight-v1.0: Fix ADC definitions
+    
+    Was missing all of the GPIO configuration bits, which probably meant
+    the ADCs were returning garbage values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 82ed4f5c45b1a9f114577a59fac546c81d69f810
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed May 30 11:38:24 2018 -0700
+
+    altoslib: Revert field name changes for accel cal values
+    
+    These names get written in the JSON part of all .eeprom files, so we
+    can't change the names or the values won't be read and written correctly.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 484ffebc54048bbe276e0e2c0e2ab52c6a1761c1
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 19:19:43 2018 -0700
+
+    altos/telelco-v2.0: Set HAS_ADC_SINGLE to enable HSI timer
+    
+    The ADC unit requires the HSI timer to run, so make sure it's enabled
+    for this device.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 16971e550d1018fb6acf3fee3c56098f5ba9921e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 19:18:48 2018 -0700
+
+    altos/stm: Enable HSI timer when HAS_ADC_SINGLE is set
+    
+    The ADC unit always uses the HSI timer.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 42a261a56606be69b5fb90fd6017c70a1e5d72dd
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 16:10:51 2018 -0700
+
+    altos/telelco-v2.0: Display local batt voltage at startup
+    
+    Show the battery voltage for a second at startup.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3fb27f0ab7163c96945a60fd406e5423552206a2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 16:09:19 2018 -0700
+
+    altos/stm: Add polling ADC sampler API
+    
+    This just fetches ADC values on demand instead of loading them
+    periodically into a ring buffer from the timer interrupt.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dbeb9b91a48418c5bc9f6edccaef20c3ef77d45d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 15:12:26 2018 -0700
+
+    altos/telelco-v2.0: Change drag race selected/no-continutity pattern
+    
+    Make it turn on at the same time as the pads with continuity, but turn
+    off sooner
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eb31a40b3499287e0a52324a9adc3728883ed957
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 15:07:06 2018 -0700
+
+    altos/telelco-v2.0: Add debug output for pad voltage display
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 29f9880f7b09bc135d34bf0dcb221bdede7726b3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 14:54:47 2018 -0700
+
+    altos/telelco-v2.0: A bit fancier with the drag-mode LED show
+    
+    Continutity leds now show whether the pad is included in the drag race
+    *and* the continutity using four different patterns:
+    
+    Drag select & igniter present:          long on, short off
+    Drag select & igniter missing:          short on, long off
+    Not select & igniter present:           solid on
+    Not select & igniter missing:           solid off
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 98ea690cc7514f43254f3a6c72668c11820f657c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 14:41:51 2018 -0700
+
+    altos/telelco-v2.0: Fix button names and pin mappings. Add drag LED.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b1f1a4513391aa595eb64552f2aa4cfedd0cc0ff
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 14:35:18 2018 -0700
+
+    altos/telelco-v2.0: Mixed up the select_button pin (is E0, was set to E13)
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2c94ba66d5b4c99b43ab965331bf1faa270a9768
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 14:26:47 2018 -0700
+
+    altos/telelco-v2.0: Only look at drag select presses, not releases
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a26cf26e3416b1982abec249678a32a420bf8809
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 14:26:12 2018 -0700
+
+    altos/telelco-v2.0: Use single-step quadrature code
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ccad6e970c5c7416561443f1e6e2fa8f80698957
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 14:15:34 2018 -0700
+
+    altos/driver: Add support for one-step-per-click quadrature encoder
+    
+    The mechanical encoders go through all four steps per click while the
+    optical ones have a single step per click. Support both kinds.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f172b139ddc3fcc17cf89b57e5126264c0faa45e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 13:08:33 2018 -0700
+
+    altos/telelco-v2.0: Reduce quadrature debounce time
+    
+    The optical encoders shouldn't bounce at all; let's try a minimal value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a4dbc940cc6c8ff5565e8af21f2dcb4ae090380c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 13:07:06 2018 -0700
+
+    altos/drivers: Make quadrature debounce longer by default. Fix state tracking
+    
+    This increases the default debounce time for quadrature encoders to
+    30ms, which cleans up the mechanical encoders on TeleLCO v0.2. Also
+    change state tracking to explicitly check for expected state values to
+    avoid mis-triggering.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7e2a2849f58e98adc1114bb8f3a6319408d93691
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 12:06:41 2018 -0700
+
+    altos/telelco-v2.0: Only switch encoder mode on push, not release
+    
+    Was not checking event value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 863a9d523b26a8a5f8fbd5b516bd7dd914ee079e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 11:23:03 2018 -0700
+
+    altos/ao_button.c: Support up to 16 buttons
+    
+    TeleLCO v2.0 has more than 4
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eb70e334ffc77e737bb21ab3fe777a982d80ee3b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 28 11:12:36 2018 -0700
+
+    altos/telelco-v2: Change select button to alternate box/pad mode
+    
+    Instead of a three-way, just make the select button two-way and have
+    the arming switch disable it.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14fa6cee857918966740d05c4ed13b1a79db3caa
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 21 22:36:35 2018 -0700
+
+    altos: Add TeleFireEight v1.0 product
+    
+    Eight pyro channel version of the TeleFire boards.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e272f6a66881b6904037ee7b1afeb9a8a3ec5b2a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 21 22:32:38 2018 -0700
+
+    altos/drivers: Pads with multi-port firing and pad selector DIP switch
+    
+    TeleFire 8 scrambles GPIOs to make layout cleaner, placing the 8
+    firing outputs across two GPIO ports.
+    
+    We're also adding an 8-unit selector for box number so that boards can
+    be re-configured in the field. These override any ROM-configuration
+    value; you can select the rom value by setting all switches to 'off'.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 85a8846a423ce2d15815466564fb589bb553c742
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed May 16 22:03:25 2018 -0700
+
+    altos/stm: Add per-LED port/pin mode in LED code
+    
+    If you've got a complicated LED pin arrangement, you can ask for each
+    one to be configured separately, instead of using groups in a couple
+    of GPIO registers. The code isn't as efficient this way, but at least
+    it's easy to read.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 96ee5257068a988db10097af8df72b0008bce978
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed May 16 22:02:11 2018 -0700
+
+    altos: Add TeleLCO v2.0 product
+    
+    New LCO design with a single rotary knob and lots more buttons.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5a26df7db9453bf0596f729a23efb90e5e8a63c7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed May 16 22:05:26 2018 -0700
+
+    altos/vidtime: Check for value change in normal code, not irq
+    
+    This makes sure each value change is reported to the user.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 06dac6551418ba817798c187f198b9b00c1dda74
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 11:26:42 2018 -0700
+
+    altos: add 'vidtime', a simple brightness monitor
+    
+    This is a testing tool for video refresh tracking. It uses the mpusb
+    v3.0 hardware and monitors the phototransistor value, sending 0 or 1
+    to the USB port when the value changes.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1f56dc30a31e3d5c833f73ec9cd31f548a80e154
+Merge: feb881a2 71acc79f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 09:53:52 2018 -0700
+
+    Merge branch 'mpusb'
+
+commit 71acc79f8e828d56296db282c72cf4492a8aa4f4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 09:43:27 2018 -0700
+
+    altos/mpusb-v3.0: Make it compile again
+    
+    A few things have changed since this code was written.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bc70f92966221f941b96177b401744a7aca24814
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 09:42:28 2018 -0700
+
+    altos/stmf0: leave ao_power_gpio names undefined without power management
+    
+    Should make it more obvious at compile time that you've done something wrong.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5ddd4e10bd8ddb4a00a0ccd8982db3311ec5a9e7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 20 00:00:07 2016 -0800
+
+    altos: Add µPusb v3.0 project
+    
+    This replaces the ft230 with a stm32f04, saving a bit of BOM
+    and giving us control over the firmware.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit feb881a24250bd7e71ec8ccef0099d4b4a0df519
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 08:58:21 2018 -0700
+
+    doc: Update pyro channel info to reflect UI changes
+    
+    Use the new naming in the UI. Add lots more comments about how things work.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7b11a34bb031035883bac97952e5ca6db0684e33
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 08:56:32 2018 -0700
+
+    altos/test: Replace state name with 10* state value in test log. Fix raw speed
+    
+    Using a state value means we can plot state changes along with the
+    rest of the graph. Raw speed (simple integrated acceleration) was
+    busted; mostly needing to skip the first accel sample.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cc83d57454ed07e4828b4413e5af6ae2ecfe2e5a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 08:51:36 2018 -0700
+
+    altos: Eliminate height requirement for coast detect
+    
+    We had required a minimum altitude of 100m to transition from boost to
+    coast. With small motors in a heavy multi-staged rocket, this can fail
+    to detect coast in time to light the second motor.
+    
+    Also, this would fail to deploy recovery systems if the flight failed
+    before reaching 100m.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 49aafcbb6c0f3ecda4b668776be74a04a5654377
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon May 7 08:50:33 2018 -0700
+
+    Update version to 1.8.5.2
+    
+    Shipped some bits to Fred Taverni to test eliminating the altitude
+    requirement for boost detect as he stages so low.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ab65e9f257493da5282d8933d8f0dcb716c1f41f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:16:25 2018 -0700
+
+    ao-chaosread: Add support for the new flash endpoint in chaoskey
+    
+    This adds support for endpoint 0x87, which streams the contents of the
+    onboard flash to the host for firmware verification.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bea42e45952df85d61428662caefbb100465a585
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:13:02 2018 -0700
+
+    altos/chaoskey-v1.0: Add endpoint for reading flash contents
+    
+    This creates another IN endpoint which provides the contents of flash
+    for validation of the firmware load on the host.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4451f7b6bade66775a197b93c6e70ba15f1826ce
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:11:48 2018 -0700
+
+    altos/stmf0: Fix up USB debug code
+    
+    At least make it compile. In this configuration, it's dumping out IN3
+    endpoint register values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a06c283c358455008cd1e5376ccc0b6f72c7ac87
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:11:02 2018 -0700
+
+    altos/stmf0: Add IN3 alternate endpoint support
+    
+    This adds the code necessary to drive another IN endpoint.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b15549d8c5277ba3aa425e232473a17dc136e5a4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:09:22 2018 -0700
+
+    altos/stmf0: Toggle IN2 SW_BUF bit when sending data
+    
+    This tells the hardware we're done writing data to the second input
+    buffer and allows it to be switched from NAK to VALID.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8efe0d40deded973f08f63eb650a036f9e24d2fb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:17:32 2018 -0700
+
+    altos/kernel: Add USB descriptors for IN3
+    
+    This adds the necessary descriptor information to support another IN
+    endpoint for applications.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f282b802d2f5a0da56bb8245169c46a16b2eed71
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun May 6 21:06:31 2018 -0700
+
+    altos/kernel: Define usb IN2/IN3 functions
+    
+    These are putchar and flush functions that are used when sending data
+    to the additional IN2 and IN3 endpoints.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 257350e1a3e4ba2048e80d30a4a0454eb65d4a26
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue May 1 23:47:27 2018 -0700
+
+    ao-bringup/turnon_telemini: Skip DFU if no DFU device is present
+    
+    This skips running dfu-util to load the bootloader if there isn't a
+    suitable DFU device listed in the system, which allows an
+    already-flashed device to be run through the same script.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08e543cd8b761e4cbbfa97404fcd5394f65a0e9e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue May 1 23:44:00 2018 -0700
+
+    altos/stmf0: Set 0x0 mapping to Main Flash for boot loader
+    
+    When DFU finishes loading firmware and jumps to the application, it
+    leaves the mapping of addresses starting at 0x0 set to System flash,
+    which prevents the boot loader from receiving interrupts and requires
+    a power cycle during flash & cal.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 980e3dc43ac4712680a370756e5112e9f330aa9a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue May 1 23:36:57 2018 -0700
+
+    altos/stmf0: whitespace fix
+    
+    Trailing whitespace.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 772b5f1cb625fba1396a57b47498ef805ae1a9a8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue May 1 23:36:16 2018 -0700
+
+    altos/stmf0: Change tests for AO_BOOT_CHAIN and AO_BOOT_PIN to #if
+    
+    Were #ifdef, which meant that #define AO_BOOT_PIN 0 didn't work right.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 312f303be7f2a641020903ed2daccb8a4d67ec42
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 28 12:03:10 2018 -0700
+
+    altoslib: Fix Idle Monitor on TeleMega v3
+    
+    The new IMU includes a mag sensor, and there's no separate mag sensor.
+    
+    Add support for reading the mag sensor values from the IMU, separate
+    out v3 from previous TeleMega versions so that the code can stop
+    trying to read the mag sensor.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0dfaecc25a12da57248541a66dd5118161616cce
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 21 16:16:18 2018 -0700
+
+    altos/fox1ihu: Pull down radio control pin in flash loader
+    
+    Ensures that the radio is powered down while in the flash loader.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8025b98420f16730e5e6e45114cbdbbf88f7a748
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:16:41 2015 -0700
+
+    Remove ao_radio_cal from stm products without radios
+    
+    Products without a radio don't need this value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c408c773793b5a5685d95c11ba6f710200505c25
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue May 6 00:38:33 2014 -0600
+
+    had the sense backwards .. presence of 'attached' should put us in the loader
+
+commit 9003147a89074f8d991d1707f307fd4e41435aa3
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon May 5 17:32:22 2014 -0600
+
+    move signal that forces flash-loader on to PB8, active high
+
+commit ddf70e806f894707613830fd64e21b5bb8f19972
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 27 00:36:36 2013 -0700
+
+    altos: Build fox1ihu by default
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6247e0c81084b59365ceca0ced33d2db92a72444
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Feb 1 00:06:30 2014 -0800
+
+    altos/fox: Enable system timer in flash loader and prod watchdog with it
+    
+    This makes it possible to reflash the board without needing to disable
+    the watchdog.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 04aa1dfa7918dcf4eea9ec4cef5a31ac2a61a00d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jan 31 22:39:58 2014 -0800
+
+    altos/fox: Update ADC to fox-1 IHU Revision 2
+    
+    Change ADC pin definitions to match new hardware.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54da028c492464802b048cb949d392cd83994e75
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Jan 31 17:44:45 2014 -0800
+
+    altos/fox: Transition to current altos build environment
+    
+    Fix the library usage, use $(LIBS) instead of $(SAT_CLIB) -lgcc
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ca58096665fc1a11ca5683f0e6aafaf3e153af37
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 28 00:42:31 2013 -0700
+
+    altos/fox: update product name to show v2, enable watchdog by default
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e79202f95f0e5b4a01da31d3742a775bea62cc92
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 28 00:05:39 2013 -0700
+
+    altos/fox: Run app when PD6 is low
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 36cf713ead58a52539c87de764b022ba0dcde27d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 27 16:06:48 2013 -0700
+
+    altos/fox: Add fox1ihu flash loader
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4c37ccc63d37ff0a4382f6812060d3c5fd4b6cfb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 25 21:25:12 2013 -0700
+
+    altos/fox: Add MRAM and SD card drivers
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f517aa5e042af8dd7fd36be47e4b196f212e79b0
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Mar 21 10:16:35 2013 -0700
+
+    altos/fox: Enable M25 driver for MRAM.
+    
+    The M25 driver can also talk to the MRAM chip, with a few adjustments
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0c969910a516c018e64eaa73cdbe4bc2f979835
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Mar 21 09:49:15 2013 -0700
+
+    altos/fox: Add watchdog timer
+    
+    Runs at 25Hz, can be enabled and disabled via the command line
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6adf9d2a17d701ed0ceb742f322fa72723149980
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 23 21:37:24 2013 -0800
+
+    altos/fox: Turn on all of the fox lights
+    
+    Fox has two red and two green LEDs
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 524afb040aa34d93abae7d04afa1df7a626f9877
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 23 21:36:18 2013 -0800
+
+    altos/fox: Provide names for fox ADC channels
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8b783887d7f136d3a389316545b74f4755e43eb4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 23 21:05:26 2013 -0800
+
+    altos/fox: Fix up Fox ADC bits
+    
+    Update to current schematic
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff2330a7fedfa7f6be3502ad0d591ab9e5ddddc6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 23 20:48:04 2013 -0800
+
+    altos/fox: Initialize FOX adc
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fbf01178e560d8a36916e295d7bdb0b0e98d2b02
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jan 23 21:45:28 2013 -0700
+
+    altos/fox: rename fox product
+    
+    It's Fox1IHU-v1 now
+
+commit 23ba75c3c2ddde65dc543b52cd87b8a1433c5024
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jan 23 19:03:26 2013 -0800
+
+    altos/fox: Add fox1ihu bringup firmware
+    
+    Firmware capable of testing fox1ihu hardware
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8612c1287a1c458a17f33af1d679d30a13dea772
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 26 17:24:51 2018 -0700
+
+    altoslib: Fix data fetching during flashing of cc1111-based devices
+    
+    We want to get enough information about the target device to verify
+    that the new firmware matches, so fetch 512 bytes instead of just
+    barely enough to cover the romconfig data.
+    
+    Also catch out-of-bounds accesses and handle them, in case even this
+    large array isn't enough.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eee9f6128da146b0e9c711d49b2a3eb49a95aaf3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 26 16:30:54 2018 -0700
+
+    altoslib: Keep config data accel cal in antenna up form.
+    
+    Instead of letting the accel cal data live in whatever form it was
+    fetched in, keep it in antenna up form and provide it in whatever
+    orientation is necessary.
+    
+    This fixes bugs in changing pad configuration where the accel cal values
+    from the old orientation would get used in the new orientation and
+    wreck them.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b3474fb33a58e78b3b8f36958dd44768e49f3edc
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Apr 25 23:07:46 2018 -0700
+
+    altoslib: Flush settings restoration commands after accel cal
+    
+    To avoid mangling settings when the user doesn't 'save' things,
+    restore the original accel cal values and orientation after finishing
+    accelerometer calibration.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d691170a96545a9e57aad454de87541cea8c292
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 22 20:02:04 2018 -0700
+
+    altoslib: Remove ascending/descending from pyro config
+    
+    Ascending and descending don't add any functionality and can confuse
+    people. Clears pyro configuration value when ascending or descending were
+    selected in the configuration so that the user knows to reset the
+    channel from scratch.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57218127ee39724e985fefcf203991401f01cc84
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Apr 22 20:01:01 2018 -0700
+
+    altoslib: Clarify terms in Mega pyro config
+    
+    Suggestions from Bob Brown et al
+    
+    Speed -> ascent rate
+    Height -> height above ground
+    Acceleration -> Vertical acceleration
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 06ca18ee67f80a9d1e25799930aca59e99e32d7f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 21 16:22:16 2018 -0700
+
+    Set version to 1.8.5.1
+    
+    Firmware has changed
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b47796991cb6c2edb85f9201a53515b4dd28b946
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 15 22:52:35 2014 -0700
+
+    altos/flash-loader: On STM, don't include ao_usb_disable
+    
+    This saves a bit of space, keeping the flash loader under 4k on fox
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b478d3c3569d2f9df50b0030197468d14af67688
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 21 16:17:26 2018 -0700
+
+    altos: Use max of 64 previous orient values when checking pyro limits
+    
+    Instead of checking just a single measurement to see if the
+    orientation is outside of the desired limits, use the maximum of 64
+    previous values to that rapidly changing orientation won't
+    accidentally enable a pyro channel if sampled at the 'wrong time'.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a414a32f86c9d8a2c5f576898c0f0dc75263ff85
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Apr 21 16:14:39 2018 -0700
+
+    altos/stm: Simplify ao_usb_write a bit
+    
+    Remove unnecessary 'offset' param (was always passed zero). This also
+    makes some code conditional on that value no longer necessary.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1569b23b2f139e3840ec145f4eef45f36fc4939a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Apr 16 09:46:22 2018 -0700
+
+    doc: add release check for altusmetrum-docinfo.xml copyright
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d5c038473d56ebbe61b8a71b5eb28d03385f8c48
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Apr 16 09:45:35 2018 -0700
+
+    altosdroid: Attempt to avoid some reported altosdroid crashes
+    
+    Just looking at stack traces, maybe these changes will avoid some problems?
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 110e4818b85781c33d683b7b7e7f2864a1223c5c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Apr 5 16:41:20 2018 -0700
+
+    micropeak: Make reported 'max height' value show filtered max height
+    
+    MicroPeak tries to filter out bogus pressure data so that the value
+    reported on the LED is reasonable. We want to report that same value
+    in the UI, which means replacing the normal mechanism for computing
+    max height from the time series of height data with the value computed
+    from the saved minimum pressure value recorded in the device.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 20dc0e6c8e365c1f4188189d506163d589c3bade
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Apr 22 19:00:03 2018 -0600
+
+    add a warning about Google limiting per-day access until/unless we pay
+
+commit 0b58d3067d994319b73c2bd15817f6922257ece2
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sat Mar 31 17:44:18 2018 -0600
+
+    another second seems to help on the very slow Acer laptop
+
+commit 865364d2738ae0b79a390eab62a5ddac1e890c71
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Mar 23 17:35:47 2018 -0600
+
+    altos: Hack up code for TeleMetrum to make it just a tracker
+    
+    Support for a failed TeleMetrum device that uses just the GPS receiver
+    and radio to create a TeleGPS-compatible device called 'tmgps'.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 58eda1736d8cffa6e3b5afce6f5faabbb179045e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Mar 23 17:34:23 2018 -0600
+
+    altos/ao_cc1120: Only call ao_packet_slave_stop when HAS_SLAVE
+    
+    Don't try to disable packet slave mode when the product doesn't
+    support packet slave mode.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 49fd1fe435b116665b41722c7d14878a62bb3311
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Tue Mar 20 18:25:43 2018 -0600
+
+    add a paragraph to the intro pointing to the altusmetrum email list
+
+commit 59e23c27c2a85d7d748223e444b24d19937afe47
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Sun Mar 18 15:49:07 2018 -0600
+
+    preparing to release 1.8.5
+
 commit 7b614380f307cb5e27f2a05281bc76c4ace93334
 Merge: 16a9d861 39023ed6
 Author: Bdale Garbee <bdale@gag.com>
index 71309897b6751b4bb71878f37e82be88ca759583..ec73f5e3c4ba5f102278719b7ec20ee4a3283ec9 100644 (file)
@@ -63,7 +63,10 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen
                        show(last_telem_state, last_state, last_from_receiver, last_receiver);
                } else
                        ft.hide(this);
-               ft.commitAllowingStateLoss();
+               try {
+                       ft.commitAllowingStateLoss();
+               } catch (IllegalStateException ie) {
+               }
        }
 
        @Override
index d970fc4f2f3b65de920ac67c551ae4df47556b59..6c2d9d7ae9eefc9758c85361cbf631e7f3569662 100644 (file)
@@ -256,6 +256,12 @@ public class SetupActivity extends Activity {
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
 
+               AltosDebug.init(this);
+               AltosDebug.debug("+++ ON CREATE +++");
+
+               // Initialise preferences
+               AltosDroidPreferences.init(this);
+
                // Setup the window
                requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
                setContentView(R.layout.setup);
index 03d9fbf27def2bc70aa75ffb99326798f814465c..f98090efaec35edcfe452b00acf4ef65f16302a4 100644 (file)
@@ -174,22 +174,23 @@ public class AltosAccelCal implements Runnable {
                                if (worked)
                                        new_config = new AltosConfigData(link);
                        } finally {
+                               int plus = config_data.accel_cal_plus(config_data.pad_orientation);
+                               int minus = config_data.accel_cal_minus(config_data.pad_orientation);
                                System.out.printf("Restore orientation %d +g %d -g %d\n",
                                                  config_data.pad_orientation,
-                                                 config_data.accel_cal_plus,
-                                                 config_data.accel_cal_minus);
-                               if (config_data.pad_orientation != AltosLib.MISSING && config_data.pad_orientation != 0)
+                                                 plus, minus);
+                               if (config_data.pad_orientation != AltosLib.MISSING)
                                        link.printf("c o %d\n", config_data.pad_orientation);
-                               if (config_data.accel_cal_plus != AltosLib.MISSING && config_data.accel_cal_minus != AltosLib.MISSING)
-                                       link.printf("c a %d %d\n",
-                                                   config_data.accel_cal_plus, config_data.accel_cal_minus);
+                               if (plus != AltosLib.MISSING && minus != AltosLib.MISSING)
+                                       link.printf("c a %d %d\n", plus, minus);
+                               link.flush_output();
                                stop_link();
                        }
                        if (new_config != null) {
-                               System.out.printf("*** +1g %d -1g %d\n",
-                                                 new_config.accel_cal_plus,
-                                                 new_config.accel_cal_minus);
-                               listener.cal_done(this, new_config.accel_cal_plus, new_config.accel_cal_minus);
+                               int plus = new_config.accel_cal_plus(AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP);
+                               int minus = new_config.accel_cal_minus(AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP);
+                               System.out.printf("*** +1g %d -1g %d\n", plus, minus);
+                               listener.cal_done(this, plus, minus);
                                if (!wait_signal())
                                        throw new InterruptedException("aborted");
                        } else
index 03e2cbd72e17793aabf277fbc408188940b73fae..5bc6c4fd5b51299db71f92c868d22caa73d34988 100644 (file)
@@ -397,7 +397,7 @@ public class AltosCalData {
                set_flight_params(config_data.apogee_delay / ticks_per_sec, config_data.apogee_lockout / ticks_per_sec);
                set_pad_orientation(config_data.pad_orientation);
                set_product(config_data.product);
-               set_accel_plus_minus(config_data.accel_cal_plus, config_data.accel_cal_minus);
+               set_accel_plus_minus(config_data.accel_cal_plus(config_data.pad_orientation), config_data.accel_cal_minus(config_data.pad_orientation));
                set_accel_zero(config_data.accel_zero_along, config_data.accel_zero_across, config_data.accel_zero_through);
                set_ms5607(config_data.ms5607);
                try {
index dc036867047cf278432aa99b7b35be0ccb244d6f..8d0bb47938f056dec65127f5b732d90b268fdb95 100644 (file)
@@ -22,6 +22,7 @@ import java.util.*;
 import java.text.*;
 import java.util.concurrent.*;
 
+/* Don't change the field names in this structure; they're part of all .eeprom files */
 public class AltosConfigData {
 
        /* Version information */
@@ -53,6 +54,8 @@ public class AltosConfigData {
 
        /* HAS_ACCEL */
        public int      accel_cal_plus, accel_cal_minus;
+       private int     accel_cal_plus_cooked, accel_cal_minus_cooked;
+       private boolean accel_cal_adjusted;
        public int      pad_orientation;
 
        /* HAS_LOG */
@@ -186,6 +189,23 @@ public class AltosConfigData {
                }
        }
 
+       public int invert_accel_value(int value) {
+               if (value == AltosLib.MISSING)
+                       return AltosLib.MISSING;
+
+               switch (log_format) {
+               case AltosLib.AO_LOG_FORMAT_FULL:
+                       return 0x7fff - value;
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+               case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+               case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
+                       return 4095 - value;
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
        public boolean has_monitor_battery() {
                if (product.startsWith("TeleBT"))
                        return true;
@@ -252,9 +272,12 @@ public class AltosConfigData {
                radio_setting = AltosLib.MISSING;
                telemetry_rate = AltosLib.MISSING;
 
+               accel_cal_plus_cooked = AltosLib.MISSING;
+               accel_cal_minus_cooked = AltosLib.MISSING;
                accel_cal_plus = AltosLib.MISSING;
                accel_cal_minus = AltosLib.MISSING;
                pad_orientation = AltosLib.MISSING;
+               accel_cal_adjusted = false;
 
                flight_log_max = AltosLib.MISSING;
                log_fixed = AltosLib.MISSING;
@@ -285,6 +308,59 @@ public class AltosConfigData {
                accel_zero_through = AltosLib.MISSING;
        }
 
+       /* Return + accel calibration relative to a specific pad orientation */
+       public int accel_cal_plus(int pad_orientation) {
+               adjust_accel_cal();
+               switch (pad_orientation) {
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                       return accel_cal_plus_cooked;
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                       return invert_accel_value(accel_cal_minus_cooked);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       /* Return - accel calibration relative to a specific pad orientation */
+       public int accel_cal_minus(int pad_orientation) {
+               adjust_accel_cal();
+               switch (pad_orientation) {
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                       return accel_cal_minus_cooked;
+               case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                       return invert_accel_value(accel_cal_plus_cooked);
+               default:
+                       return AltosLib.MISSING;
+               }
+       }
+
+       /* Once we have all of the values from the config data, compute the
+        * accel cal values relative to Antenna Up orientation.
+        */
+       private void adjust_accel_cal() {
+               if (!accel_cal_adjusted &&
+                   pad_orientation != AltosLib.MISSING &&
+                   accel_cal_plus != AltosLib.MISSING &&
+                   accel_cal_minus != AltosLib.MISSING &&
+                   log_format != AltosLib.AO_LOG_FORMAT_UNKNOWN)
+               {
+                       switch (pad_orientation) {
+                       case AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP:
+                               accel_cal_plus_cooked = accel_cal_plus;
+                               accel_cal_minus_cooked = accel_cal_minus;
+                               accel_cal_adjusted = true;
+                               break;
+                       case AltosLib.AO_PAD_ORIENTATION_ANTENNA_DOWN:
+                               accel_cal_plus_cooked = invert_accel_value(accel_cal_minus);
+                               accel_cal_minus_cooked = invert_accel_value(accel_cal_plus);
+                               accel_cal_adjusted = true;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
        public void parse_line(String line) {
 
                /* Version replies */
@@ -351,6 +427,7 @@ public class AltosConfigData {
                                if (bits.length >= 6) {
                                        accel_cal_plus = Integer.parseInt(bits[3]);
                                        accel_cal_minus = Integer.parseInt(bits[5]);
+                                       accel_cal_adjusted = false;
                                }
                        }
                } catch (Exception e) {}
@@ -414,6 +491,9 @@ public class AltosConfigData {
                                }
                        }
                } catch (Exception e) {}
+
+               /* Fix accel cal as soon as all of the necessary values appear */
+               adjust_accel_cal();
        }
 
        public AltosConfigData() {
@@ -525,11 +605,11 @@ public class AltosConfigData {
                if (pad_orientation != AltosLib.MISSING)
                        pad_orientation = source.pad_orientation();
 
-               if (accel_cal_plus != AltosLib.MISSING)
-                       accel_cal_plus = source.accel_cal_plus();
+               if (accel_cal_plus_cooked != AltosLib.MISSING)
+                       accel_cal_plus_cooked = source.accel_cal_plus();
 
-               if (accel_cal_minus != AltosLib.MISSING)
-                       accel_cal_minus = source.accel_cal_minus();
+               if (accel_cal_minus_cooked != AltosLib.MISSING)
+                       accel_cal_minus_cooked = source.accel_cal_minus();
 
                /* HAS_LOG */
                if (flight_log_max != AltosLib.MISSING)
@@ -598,7 +678,8 @@ public class AltosConfigData {
                dest.set_flight_log_max(flight_log_max);
                dest.set_ignite_mode(ignite_mode);
                dest.set_pad_orientation(pad_orientation);
-               dest.set_accel_cal(accel_cal_plus, accel_cal_minus);
+               dest.set_accel_cal(accel_cal_plus(AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP),
+                                  accel_cal_minus(AltosLib.AO_PAD_ORIENTATION_ANTENNA_UP));
                dest.set_callsign(callsign);
                if (npyro != AltosLib.MISSING)
                        dest.set_pyros(pyros);
@@ -676,10 +757,13 @@ public class AltosConfigData {
                        link.printf("c e %d\n", radio_enable);
 
                /* HAS_ACCEL */
+               /* set orientation first so that we know how to set the accel cal */
                if (pad_orientation != AltosLib.MISSING)
                        link.printf("c o %d\n", pad_orientation);
-               if (accel_cal_plus != AltosLib.MISSING && accel_cal_minus != AltosLib.MISSING)
-                       link.printf("c a %d %d\n", accel_cal_plus, accel_cal_minus);
+               int plus = accel_cal_plus(pad_orientation);
+               int minus = accel_cal_minus(pad_orientation);
+               if (plus != AltosLib.MISSING && minus != AltosLib.MISSING)
+                       link.printf("c a %d %d\n", plus, minus);
 
                /* HAS_LOG */
                if (flight_log_max != 0)
index 24a2593303c0f4bc16bbee37debaf73527208d83..a44eb12fc002fd93589ce4278b16c2ee26a5ce3f 100644 (file)
@@ -264,8 +264,8 @@ public class AltosDebug {
 
        public AltosRomconfig romconfig() throws InterruptedException {
                try {
-                       byte[] bytes = read_memory(0xa0, 10);
-                       AltosHexfile hexfile = new AltosHexfile (bytes, 0xa0);
+                       byte[] bytes = read_memory(0x00, 0x200);
+                       AltosHexfile hexfile = new AltosHexfile (bytes, 0x00);
                        return new AltosRomconfig(hexfile);
                } catch (IOException ie) {
                }
index d130d3adcfa6ae6ca41f38da645c060fbf046b41..182bdd19bd511fdcc8533147719c346ffe566c1a 100644 (file)
@@ -257,6 +257,15 @@ public class AltosFlightSeries extends AltosDataListener {
 
        public AltosTimeSeries height_series;
 
+       public double max_height = AltosLib.MISSING;
+
+       public  void set_min_pressure(double pa) {
+               double ground_altitude = cal_data().ground_altitude;
+               if (ground_altitude != AltosLib.MISSING)
+                       max_height = AltosConvert.pressure_to_altitude(pa) -
+                               ground_altitude;
+       }
+
        public static final String height_name = "Height";
 
        public  void set_pressure(double pa) {
index 6bb835810b6183b8d885d95629e782b6ce8c10c8..2760321d0940685ca20a5ea910db20efa9455f95 100644 (file)
@@ -266,8 +266,8 @@ public class AltosFlightStats {
                        }
                }
 
-               max_height = AltosLib.MISSING;
-               if (series.height_series != null)
+               max_height = series.max_height;
+               if (max_height == AltosLib.MISSING && series.height_series != null)
                        max_height = series.height_series.max().value;
                max_gps_height = AltosLib.MISSING;
                if (series.gps_height != null) {
index 6aa98383e9fc38d92d93b928a97d4990c6fc8258..f2ab4bead5c3883dd8cd1e16d5020b8cf63eb484 100644 (file)
@@ -294,15 +294,19 @@ public class AltosHexfile {
                if (usb_descriptors == null)
                        return -1;
 
-               /* Walk the descriptors looking for the device */
-               a = usb_descriptors.address;
-               while (get_u8(a+1) != AO_USB_DESC_DEVICE) {
-                       int delta = get_u8(a);
-                       a += delta;
-                       if (delta == 0 || a >= max_address)
-                               return -1;
+               try {
+                       /* Walk the descriptors looking for the device */
+                       a = usb_descriptors.address;
+                       while (get_u8(a+1) != AO_USB_DESC_DEVICE) {
+                               int delta = get_u8(a);
+                               a += delta;
+                               if (delta == 0 || a >= max_address)
+                                       return -1;
+                       }
+                       return a;
+               } catch (ArrayIndexOutOfBoundsException ae) {
+                       return -1;
                }
-               return a;
        }
 
        public AltosUsbId find_usb_id() {
index ba6f1a82584089c46a643d4e67d03af691ce39aa..df81c9ddea979a3b56fb2ca91760c33aa9204afb 100644 (file)
@@ -22,13 +22,17 @@ import java.util.concurrent.*;
 import java.io.*;
 
 public class AltosIMU implements Cloneable {
-       public int              accel_x;
-       public int              accel_y;
-       public int              accel_z;
+       public int              accel_x = AltosLib.MISSING;
+       public int              accel_y = AltosLib.MISSING;
+       public int              accel_z = AltosLib.MISSING;
 
-       public int              gyro_x;
-       public int              gyro_y;
-       public int              gyro_z;
+       public int              gyro_x = AltosLib.MISSING;
+       public int              gyro_y = AltosLib.MISSING;
+       public int              gyro_z = AltosLib.MISSING;
+
+       public int              mag_x = AltosLib.MISSING;
+       public int              mag_y = AltosLib.MISSING;
+       public int              mag_z = AltosLib.MISSING;
 
        public static final double      counts_per_g = 2048.0;
 
@@ -58,6 +62,11 @@ public class AltosIMU implements Cloneable {
                        gyro_y = Integer.parseInt(items[6]);
                        gyro_z = Integer.parseInt(items[7]);
                }
+               if (items.length >= 12) {
+                       mag_x = Integer.parseInt(items[9]);
+                       mag_y = Integer.parseInt(items[10]);
+                       mag_z = Integer.parseInt(items[11]);
+               }
                return true;
        }
 
@@ -71,6 +80,11 @@ public class AltosIMU implements Cloneable {
                n.gyro_x = gyro_x;
                n.gyro_y = gyro_y;
                n.gyro_z = gyro_z;
+
+               n.mag_x = mag_x;
+               n.mag_y = mag_y;
+               n.mag_z = mag_z;
+
                return n;
        }
 
@@ -86,6 +100,11 @@ public class AltosIMU implements Cloneable {
                                listener.set_accel_ground(imu.accel_y,
                                                          imu.accel_x,
                                                          imu.accel_z);
+                               if (imu.mag_x != AltosLib.MISSING) {
+                                       listener.set_mag(cal_data.mag_along(imu.mag_y),
+                                                        cal_data.mag_across(imu.mag_x),
+                                                        cal_data.mag_through(imu.mag_z));
+                               }
                        }
                } catch (TimeoutException te) {
                }
@@ -99,6 +118,10 @@ public class AltosIMU implements Cloneable {
                gyro_x = AltosLib.MISSING;
                gyro_y = AltosLib.MISSING;
                gyro_z = AltosLib.MISSING;
+
+               mag_x = AltosLib.MISSING;
+               mag_y = AltosLib.MISSING;
+               mag_z = AltosLib.MISSING;
        }
 
        public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException {
index 058df0a1a246db3455e4f4877b05df0f8ff241fa..88a5dab4eafd4885ff36abe7d8914a1e1a80df72 100644 (file)
@@ -133,12 +133,30 @@ public class AltosIdleFetch implements AltosDataProvider {
                               AltosIdler.idle_ms5607,
                               AltosIdler.idle_sensor_metrum),
 
-               new AltosIdler("TeleMega",
+               new AltosIdler("TeleMega-v0",
                               AltosIdler.idle_gps,
                               AltosIdler.idle_mma655x,
                               AltosIdler.idle_ms5607,
                               AltosIdler.idle_imu, AltosIdler.idle_mag,
                               AltosIdler.idle_sensor_mega),
+               new AltosIdler("TeleMega-v1",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_mma655x,
+                              AltosIdler.idle_ms5607,
+                              AltosIdler.idle_imu, AltosIdler.idle_mag,
+                              AltosIdler.idle_sensor_mega),
+               new AltosIdler("TeleMega-v2",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_mma655x,
+                              AltosIdler.idle_ms5607,
+                              AltosIdler.idle_imu, AltosIdler.idle_mag,
+                              AltosIdler.idle_sensor_mega),
+               new AltosIdler("TeleMega-v3",
+                              AltosIdler.idle_gps,
+                              AltosIdler.idle_mma655x,
+                              AltosIdler.idle_ms5607,
+                              AltosIdler.idle_imu,
+                              AltosIdler.idle_sensor_mega),
                new AltosIdler("EasyMega",
                               AltosIdler.idle_mma655x,
                               AltosIdler.idle_ms5607,
index c25a6273136c095b5b945fe71946631a7d393b25..7d2b68e0bfe94d56788f06ca9a4e2d7f51168aef 100644 (file)
@@ -348,6 +348,9 @@ public class AltosLib {
        public static final int AO_GPS_NUM_SAT_SHIFT = 0;
        public static final int AO_GPS_NUM_SAT_MASK = 0xf;
 
+       public static final int AO_PAD_ORIENTATION_ANTENNA_UP = 0;
+       public static final int AO_PAD_ORIENTATION_ANTENNA_DOWN = 1;
+
        public static final int AO_LOG_FORMAT_UNKNOWN = 0;
        public static final int AO_LOG_FORMAT_FULL = 1;
        public static final int AO_LOG_FORMAT_TINY = 2;
index 829a1a63f90070d88baa4cb2659da0bb35f90825..3ad3489173e149557c7d0caf437eae9ab8bfdf93 100644 (file)
@@ -339,9 +339,22 @@ public abstract class AltosLink implements Runnable {
 
 
        public void flush_input() throws InterruptedException {
-               if (remote)
-                       flush_input(500);
-               else
+               if (remote) {
+                       int timeout = 500;
+                       switch (telemetry_rate) {
+                       case AltosLib.ao_telemetry_rate_38400:
+                       default:
+                               timeout = 500;
+                               break;
+                       case AltosLib.ao_telemetry_rate_9600:
+                               timeout = 1000;
+                               break;
+                       case AltosLib.ao_telemetry_rate_2400:
+                               timeout = 2000;
+                               break;
+                       }
+                       flush_input(timeout);
+               } else
                        flush_input(100);
        }
 
index 0ea3bfc13ccacdf950b204b452e98ef84d5f248c..fea4fd5955f7f03d87aa926034b8f294b7df90b2 100644 (file)
@@ -29,24 +29,24 @@ public class AltosPyro {
        public static final int pyro_accel_greater              = 0x00000002;
        public static final String pyro_accel_less_string       = "a<";
        public static final String pyro_accel_greater_string    = "a>";
-       public static final String pyro_accel_less_name         = "Acceleration less than";
-       public static final String pyro_accel_greater_name      = "Acceleration greater than";
+       public static final String pyro_accel_less_name         = "Vertical acceleration less than";
+       public static final String pyro_accel_greater_name      = "Vertical acceleration greater than";
        public static final double pyro_accel_scale             = 16.0;
 
        public static final int pyro_speed_less                 = 0x00000004;
        public static final int pyro_speed_greater              = 0x00000008;
        public static final String pyro_speed_less_string       = "s<";
        public static final String pyro_speed_greater_string    = "s>";
-       public static final String pyro_speed_less_name         = "Speed less than";
-       public static final String pyro_speed_greater_name      = "Speed greater than";
+       public static final String pyro_speed_less_name         = "Ascent rate less than";
+       public static final String pyro_speed_greater_name      = "Ascent rate greater than";
        public static final double pyro_speed_scale             = 16.0;
 
        public static final int pyro_height_less                = 0x00000010;
        public static final int pyro_height_greater             = 0x00000020;
        public static final String pyro_height_less_string      = "h<";
        public static final String pyro_height_greater_string   = "h>";
-       public static final String pyro_height_less_name        = "Height less than";
-       public static final String pyro_height_greater_name     = "Height greater than";
+       public static final String pyro_height_less_name        = "Height above pad less than";
+       public static final String pyro_height_greater_name     = "Height above pad greater than";
        public static final double pyro_height_scale            = 1.0;
 
        public static final int pyro_orient_less                = 0x00000040;
@@ -61,8 +61,8 @@ public class AltosPyro {
        public static final int pyro_time_greater               = 0x00000200;
        public static final String pyro_time_less_string        = "t<";
        public static final String pyro_time_greater_string     = "t>";
-       public static final String pyro_time_less_name          = "Time since boost less than (s)";
-       public static final String pyro_time_greater_name       = "Time since boost greater than (s)";
+       public static final String pyro_time_less_name          = "Time since launch less than (s)";
+       public static final String pyro_time_greater_name       = "Time since launch greater than (s)";
        public static final double pyro_time_scale              = 100.0;
 
        public static final int pyro_ascending                  = 0x00000400;
@@ -90,7 +90,10 @@ public class AltosPyro {
        public static final String pyro_state_greater_or_equal_name     = "Flight state after";
        public static final double pyro_state_scale             = 1.0;
 
+       public static final int pyro_deprecate                  = pyro_ascending | pyro_descending;
+
        public static final int pyro_all                        = 0x0000ffff;
+       public static final int pyro_all_useful                 = pyro_all ^ pyro_deprecate;
 
        public static final int pyro_no_value                   = (pyro_ascending |
                                                                   pyro_descending);
index 1fbb411540c534601631735949c7cddc55b3489b..44a3fa6097fc8d376394824614cab76edd493c81 100644 (file)
@@ -35,12 +35,12 @@ public class AltosRomconfig {
                        System.out.printf("no symbol %s\n", name);
                        throw new AltosNoSymbol(name);
                }
-               if (hexfile.address <= symbol.address && symbol.address + len < hexfile.max_address) {
+               if (hexfile.address <= symbol.address && symbol.address + len <= hexfile.max_address) {
                        System.out.printf("%s: %x\n", name, symbol.address);
                        return symbol.address;
                }
-               System.out.printf("invalid symbol addr %x range is %x - %x\n",
-                                 symbol.address, hexfile.address, hexfile.max_address);
+               System.out.printf("invalid symbol addr %x len %d range is %x - %x\n",
+                                 symbol.address, len, hexfile.address, hexfile.max_address);
                throw new AltosNoSymbol(name);
        }
 
index 1e875dec1aa9b490622fd0d2d371f306b43f0936..9bd265f096f92c67900b47d454c1b18454972434 100644 (file)
@@ -440,7 +440,7 @@ public class AltosConfigFCUI
                apogee_lockout_value.setEditable(true);
                apogee_lockout_value.addItemListener(this);
                pane.add(apogee_lockout_value, c);
-               apogee_lockout_value.setToolTipText("Time after boost while apogee detection is locked out");
+               apogee_lockout_value.setToolTipText("Time after launch while apogee detection is locked out");
                row++;
 
                /* Frequency */
index cd887c00c8cadd43ee74d414cad65ed4f8c1c44d..62c434ac72c71cd29ff582629cd2f8a2263b073d 100644 (file)
@@ -186,8 +186,17 @@ public class AltosConfigPyroUI
 
                public void set(AltosPyro pyro) {
                        int row = 0;
+                       if ((pyro.flags & AltosPyro.pyro_deprecate) != 0) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             String.format("Pyro settings “Ascending” and “Descending” are deprecated.\n" +
+                                                                           "Clearing %s configuration.", AltosLib.igniter_name(pyro.channel)),
+                                                             "Deprecated Pyro Settings",
+                                                             JOptionPane.ERROR_MESSAGE);
+                               pyro.flags = 0;
+                               owner.set_dirty();
+                       }
                        for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
-                               if ((AltosPyro.pyro_all & flag) != 0) {
+                               if ((AltosPyro.pyro_all_useful & flag) != 0) {
                                        items[row].set((pyro.flags & flag) != 0,
                                                       pyro.get_value(flag));
                                        row++;
@@ -200,7 +209,7 @@ public class AltosConfigPyroUI
 
                        int row = 0;
                        for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
-                               if ((AltosPyro.pyro_all & flag) != 0) {
+                               if ((AltosPyro.pyro_all_useful & flag) != 0) {
                                        if (items[row].enabled()) {
                                                try {
                                                p.flags |= flag;
@@ -220,7 +229,7 @@ public class AltosConfigPyroUI
                public void units_changed(boolean imperial_units) {
                        int row = 0;
                        for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
-                               if ((AltosPyro.pyro_all & flag) != 0) {
+                               if ((AltosPyro.pyro_all_useful & flag) != 0) {
                                        items[row].units_changed(imperial_units);
                                        row++;
                                }
@@ -233,7 +242,7 @@ public class AltosConfigPyroUI
 
                        int     nrow = 0;
                        for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
-                               if ((flag & AltosPyro.pyro_all) != 0)
+                               if ((flag & AltosPyro.pyro_all_useful) != 0)
                                        nrow++;
 
                        items = new PyroItem[nrow];
@@ -251,7 +260,7 @@ public class AltosConfigPyroUI
                        y++;
 
                        for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
-                               if ((flag & AltosPyro.pyro_all) != 0) {
+                               if ((flag & AltosPyro.pyro_all_useful) != 0) {
                                        items[row] = new PyroItem(ui, flag, x, y + row);
                                        row++;
                                }
@@ -336,10 +345,12 @@ public class AltosConfigPyroUI
                        columns[c].units_changed(imperial_units);
                int r = 0;
                for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
-                       String n = AltosPyro.pyro_to_name(flag);
-                       if (n != null) {
-                               labels[r].setText(n);
-                               r++;
+                       if ((flag & AltosPyro.pyro_all_useful) != 0) {
+                               String n = AltosPyro.pyro_to_name(flag);
+                               if (n != null) {
+                                       labels[r].setText(n);
+                                       r++;
+                               }
                        }
                }
        }
@@ -380,7 +391,7 @@ public class AltosConfigPyroUI
 
                int     nrow = 0;
                for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
-                       if ((flag & AltosPyro.pyro_all) != 0)
+                       if ((flag & AltosPyro.pyro_all_useful) != 0)
                                nrow++;
 
                labels = new JLabel[nrow];
@@ -390,18 +401,20 @@ public class AltosConfigPyroUI
                for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
                        String  n;
 
-                       n = AltosPyro.pyro_to_name(flag);
-                       if (n != null) {
-                               c = new GridBagConstraints();
-                               c.gridx = 0; c.gridy = row;
-                               c.gridwidth = 1;
-                               c.fill = GridBagConstraints.NONE;
-                               c.anchor = GridBagConstraints.LINE_START;
-                               c.insets = il;
-                               JLabel label = new JLabel(n);
-                               pane.add(label, c);
-                               labels[row-1] = label;
-                               row++;
+                       if ((flag & AltosPyro.pyro_all_useful) != 0) {
+                               n = AltosPyro.pyro_to_name(flag);
+                               if (n != null) {
+                                       c = new GridBagConstraints();
+                                       c.gridx = 0; c.gridy = row;
+                                       c.gridwidth = 1;
+                                       c.fill = GridBagConstraints.NONE;
+                                       c.anchor = GridBagConstraints.LINE_START;
+                                       c.insets = il;
+                                       JLabel label = new JLabel(n);
+                                       pane.add(label, c);
+                                       labels[row-1] = label;
+                                       row++;
+                               }
                        }
                }
 
index c717e47c1840a30cc07c3d8e50830e9896a2f6fa..802e8eb3ca764a30589ecff335ad45d73ff90fdb 100644 (file)
@@ -59,10 +59,10 @@ public class AltosFlashUI
                "teleballoon",
                "telebt-v1",
                "teledongle-v0",
-               "telefire",
+               "telefire-v0",
                "telemetrum-v0",
                "telemetrum-v1",
-               "telemini",
+               "telemini-v1",
                "telenano",
                "teleshield",
                "teleterra"
@@ -72,10 +72,11 @@ public class AltosFlashUI
                "TeleBalloon",
                "TeleBT-v1",
                "TeleDongle-v0",
+               "TeleFire-v0",
                "TeleFire",
                "TeleMetrum-v0",
                "TeleMetrum-v1",
-               "TeleMini",
+               "TeleMini-v1",
                "TeleNano",
                "TeleShield",
                "TeleTerra"
index d710e5ff19a89fda20da27b6f86c47372cf4f137..9ad809122bd847139239ebc77d10b56a1886c96f 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
-if [ -x /usr/bin/dfu-util ]; then
-    DFU_UTIL=/usr/bin/dfu-util
+if [ -x `which dfu-util` ]; then
+    DFU_UTIL=`which dfu-util`
 else
     echo "Can't find dfu-util! Aborting."
     exit 1
@@ -33,7 +33,7 @@ $DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || true
 
 #$USBLOAD --serial=1 $ALTOS_FILE || exit 1
 
-sleep 1
+sleep 3
 
 ./test-chaoskey
 
index 48af692a2f9a02103f3a078105a63919ad144a77..5e4cd616f007c175ccf55c436ecbbe02dc13ef57 100755 (executable)
@@ -49,9 +49,9 @@ esac
 FLASH_FILE=$REPO/loaders/telegps-v2.0-altos-flash-*.bin
 ALTOS_FILE=$REPO/telegps-v2.0-*.elf
 
-$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE 
+$DFU_UTIL -v -v -R -a 0 -s 0x08000000:leave -D $FLASH_FILE 
 
-sleep 2
+sleep 3
 
 $USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
 
diff --git a/ao-bringup/turnon_telelco b/ao-bringup/turnon_telelco
new file mode 100755 (executable)
index 0000000..dafa213
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+if [ -x /usr/bin/ao-flash-stm ]; then
+       FLASH_STM=/usr/bin/ao-flash-stm
+else
+       echo "Can't find ao-flash-stm!  Aborting."
+       exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+       USBLOAD=/usr/bin/ao-usbload
+else
+       echo "Can't find ao-usbload!  Aborting."
+       exit 1
+fi
+
+VERSION=2.0
+REPO=~/altusmetrumllc/Binaries
+PRODUCT=TeleLCO
+
+echo "$PRODUCT v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2018 by Bdale Garbee.  Released under GPL v3"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+
+case $# in
+    1)
+       SERIAL="$1"
+       echo "$PRODUCT-$VERSION serial number: $SERIAL" 
+       ;;
+    0)
+       echo -n "$PRODUCT-$VERSION serial number: "
+       read SERIAL
+       ;;
+    *)
+       echo "Usage: $0 <serial-number>" 1>&2
+       exit 1;
+       ;;
+esac
+
+echo $FLASH_STM
+
+$FLASH_STM $REPO/loaders/telelco-v$VERSION*.elf 
+
+sleep 3
+
+$USBLOAD --serial=$SERIAL --force $REPO/telelco-v$VERSION*.elf || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/'"$PRODUCT-v$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+       echo "$PRODUCT"' found on $dev'
+       ;;
+*)
+       echo 'No '"$PRODUCT-v$VERSION"' found'
+       exit 1
+       ;;
+esac
+
+echo 'E 0' > $dev
+
+SERIAL=$SERIAL ./cal-freq $dev
+
+echo 'E 1' > $dev
+
+echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+echo "\007"
+
+exit $?
index 497767888c0b8b325bb76be87e5a59606123f138..1fce345ac8d305e274eefd7839017bf0c450385b 100755 (executable)
@@ -46,7 +46,7 @@ echo $FLASH_STM
 
 $FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf 
 
-sleep 5
+sleep 3
 
 $USBLOAD --serial=$SERIAL --force $REPO/telemega-v$VERSION*.elf || exit 1
 
index d40be953c4cb012bfe30eec44cb4846ff6e7ee12..dd30378a01a649eeead9db44e6d9e8c39571326a 100755 (executable)
@@ -46,7 +46,7 @@ echo $FLASH_STM
 
 $FLASH_STM ~/altusmetrumllc/Binaries/loaders/telemetrum-v$VERSION-*.elf || exit 1
 
-sleep 2
+sleep 3
 
 $USBLOAD --serial=$SERIAL ~/altusmetrumllc/Binaries/telemetrum-v$VERSION-*.elf || exit 1
 
index 23031481dac46aa2c5f79d5589767c5f6e683f43..678251f48d8caf5a0b0dba23d48ac7688a786027 100755 (executable)
@@ -45,9 +45,11 @@ ALTOS_FILE=~/altusmetrumllc/Binaries/telemini-v$VERSION-*.elf
 #FLASH_FILE=../src/telemini-v3.0/flash-loader/telemini-v$VERSION-altos-flash-*.bin
 #ALTOS_FILE=../src/telemini-v3.0/telemini-v$VERSION-*.elf
 
-$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1
+if lsusb -d 0483:df11 | grep -q STM; then
+    $DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1
 
-sleep 2
+    sleep 2
+fi
 
 $USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1
 
index e6ed2fac64443bd21d3cd9942c650ca0b70b49c9..94ca5ce9e0fc06d543415dc3b75aadb220325daf 100644 (file)
@@ -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.
index 8a814a009ed7b20b405877431a334d6918c03a73..5c0de1257fbded71cda28e0d7dbaaf2fcffaba7c 100644 (file)
@@ -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;
index 6d4fa5bfb0cd56a13b02f48265adcd7801288602..41d0ac102d27d86cb24e433bdde9b9441bb6f740 100644 (file)
@@ -90,6 +90,8 @@ main (int argc, char **argv)
        int             any_valid;
        int             invalid;
        char            serial_line[8192];
+       unsigned        storage_size;
+       int             blocks;
 
        while ((c = getopt_long(argc, argv, "T:D:C:R", options, NULL)) != -1) {
                switch (c) {
@@ -140,10 +142,21 @@ main (int argc, char **argv)
                cc_usb_close(cc);
                exit(1);
        }
-       printf ("Serial number: %d\n", serial_number);
+       cc_usb_printf(cc, "f\n");
+       storage_size = 0;
+       for (;;) {
+               cc_usb_getline(cc, line, sizeof(line));
+               if (sscanf(line, "Storage size: %u", &storage_size) == 1)
+                       break;
+       }
+       printf ("Serial number: %d Storage size: %u\n", serial_number, storage_size);
+       if (storage_size)
+               blocks = storage_size / 256;
+       else
+               blocks = 511;
        done = 0;
        column = 0;
-       for (block = 0; !done && block < 511; block++) {
+       for (block = 0; !done && block < blocks; block++) {
                cc_usb_printf(cc, "e %x\n", block);
                if (column == 64) {
                        putchar('\n');
index 82e0f3d03966aeca5e1f14cdcbec485e82f264f8..c5de6a5d5beda38dea77df3f4c2ccd18d86ffaa0 100644 (file)
@@ -18,13 +18,13 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.8.5)
+AC_INIT([altos], 1.8.6)
 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-06-17
 AC_SUBST(RELEASE_DATE)
 
 VERSION_DASH=`echo $VERSION | sed 's/\./-/g'`
index efa7f9d37c75e56534ebf788803336e5fcc12375..3661a6d64264a11f9338c39222f21b3f2ee0b981 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 RELNOTES_INC=\
+       release-notes-1.8.6.inc \
        release-notes-1.8.5.inc \
        release-notes-1.8.4.inc \
        release-notes-1.8.3.inc \
index c3980882bb718cb5bb2b485f8ff877cad8394811..748d2b5b428539355fa329a244b3eab6c2d85c68 100644 (file)
@@ -1,5 +1,9 @@
 Creating documentation for a new release of AltOS
 
+* Make sure that doc/altusmetrum-docinfo.xml has the right copyright 
+  year, and add release to the revision history at the front (release 
+  notes will be pulled in by release-notes.inc)
+
 * Write release notes in release-notes-${version}.inc. Add to
   Makefile
 
index 3ea79f8b27b1a51abcbda9f283b339061ea7b41f..7b696b97e9bba1104fc97ba9b72c174447a6ba5e 100644 (file)
 </legalnotice>
 <revhistory>
   <?dbhtml filename="altusmetrum-revhistory.html"?>
+  <revision>
+    <revnumber>1.8.6</revnumber>
+    <date>6 Aug 2018</date>
+    <revremark>
+      Various pyro channel configuration updates.
+    </revremark>
+  </revision>
+  <revision>
+    <revnumber>1.8.5</revnumber>
+    <date>18 Mar 2018</date>
+    <revremark>
+      Minor ground station software updates.
+    </revremark>
+  </revision>
   <revision>
     <revnumber>1.8.4</revnumber>
     <date>20 Dec 2017</date>
index 99d5c008861fd4e48abfe589c0641448b87e4fa1..0ca6afff10e296d89e035402e67baf41e3d9ac18 100644 (file)
@@ -23,7 +23,7 @@ ifdef::altusmetrum[]
 
        ==== Apogee Lockout
 
-               Apogee lockout is the number of seconds after boost
+               Apogee lockout is the number of seconds after launch
                where the flight computer will not fire the apogee
                charge, even if the rocket appears to be at
                apogee. This is often called 'Mach Delay', as it is
@@ -35,6 +35,12 @@ ifdef::altusmetrum[]
                pressure increase, and so this setting should be left
                at the default value of zero to disable it.
 
+               [WARNING]
+               Firmware versions older than 1.8.6 have a
+               bug which resets the time since launch to zero each
+               time a motor starts burning. Update firmware to get
+               the correct behavior.
+
 endif::altusmetrum[]
 
 ifdef::radio[]
index 2d289b1264af872a8f46a26b9c1ba1f8505c63ee..425236efb2a1362c532218df179a05205a48aea4 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.8.6.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.8.5.raw[]
 
index 6b0cd31872f08b7704d41a8fea0f358c6d01ef36..bff009c0c087166bdda1a06445096e1de15c8232 100644 (file)
@@ -7,6 +7,16 @@
        we also hope to empower you to take as active a role in our collective
        future as you wish!
 
+       Our goal is to include in this document all of the information required
+       to successfully configure and use Altus Metrum products.  But 
+       documentation is a lot like software in that it can contain "bugs",
+       and can probably always be improved!  If you have questions that 
+       aren't answered in this manual, or just need a little help figuring
+       things out, we strongly suggest joining the Altus Metrum user email
+       list, which you can do by visiting 
+       https://lists.gag.com/mailman/listinfo/altusmetrum.  There's a lot
+       of useful information in the mailing list archives!
+
        The first device created for our community was TeleMetrum, a dual
        deploy altimeter with fully integrated GPS and radio telemetry
        as standard features, and a “companion interface” that will
index e7717d89e2cbb5fd86e4e8d3cda71dfafcb671a9..ccab47954df196807fe3e8fac848cd301d877131 100644 (file)
@@ -5,7 +5,11 @@
 
        Before heading out to a new launch site, you can use
        this to load satellite images in case you don't have
-       internet connectivity at the site.
+       internet connectivity at the site.  Try not to wait
+       until the last minute, though, particularly if you're
+       heading to a major launch.  If too many people are 
+       all trying to download map data at once, Google may
+       limit access until the next day.
 
        There's a drop-down menu of launch sites we know
        about; if your favorites aren't there, please let us
index 3b9185445c40e910651a03fe70a5a29b2386e668..ab5baef0e37cc68d7bca8c24e59a22c28d9bd0a1 100644 (file)
@@ -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]
   ====
@@ -47,45 +42,70 @@ pad and initialize the system.
   of less than that value.
   ====
 
-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.
+Flight Time:: Time since launch. 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.
+[WARNING]
+Firmware versions older than 1.8.6 have a bug which resets the time
+since launch to zero each time a motor starts burning. Update firmware
+to get the correct behavior.
 
-Descending:: A simple test saying whether the rocket is going down 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 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.
+launches. As of version 1.8.6 firmware, this checks to make sure at
+least this many motors have burned. Before version 1.8.6, this checked
+to make sure that exactly this many motors had burned.
 
-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/doc/release-notes-1.8.6.inc b/doc/release-notes-1.8.6.inc
new file mode 100644 (file)
index 0000000..1467977
--- /dev/null
@@ -0,0 +1,33 @@
+= Release Notes for Version 1.8.6
+:toc!:
+:doctype: article
+
+       Version 1.8.6
+
+       == AltOS
+
+       * Use maximum of 64 previous tilt values in pyro tilt tests
+       
+       * Eliminate 100m height requirement for coast detection
+
+       * Change After Motor pyro check to be >= instead of ==
+
+       * Change Time since Boost to be Time since launch.
+
+       == AltosUI, TeleGPS
+
+       * Clarify pyro test phrasing
+
+       * Remove ascending/descending from pyro config UI
+
+       * Fix accel calibration in Antenna Down mode
+
+       * Add mag sensor reporting for TeleMega v3 idle monitoring.
+
+       * Fix radio parameter saving at 2400 bps telmetry rate.
+
+       == MicroPeak
+
+       * Report altimeter-recorded maximum height value
+
+       
index b7c7f5a7a0dc5786375320f35ca61ffb4276337f..693699dfd73af2106260acae29ffa704ce404194 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.8.6.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.8.5.raw[]
 
index f451c2c844787c7949c954a4d98b69157292ccaf..9c1353f8413287fe724052175bfc163ee5961bbd 100644 (file)
@@ -1,6 +1,10 @@
 [appendix]
 == Release Notes
 
+       :leveloffset: 2
+       include::release-notes-1.8.6.raw[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.8.5.raw[]
 
index 70492a07abbebf5e95eaf4ac128ba1f03227590c..6a9adf3ff32a5427b6a10c43ab18646a52d45433 100644 (file)
@@ -345,6 +345,8 @@ public class MicroData {
                        flight_series.set_time(cal_data.time());
                        flight_series.set_state(AltosLib.ao_flight_landed);
 
+                       flight_series.set_min_pressure(min_pressure);
+
                        flight_series.finish();
 
                        flight_stats = new AltosFlightStats(flight_series);
index 8420b37648c0ec0f6175396e3031f8f8549502f9..0dafb5ec701879ff86288833cdd738f5c1f2cbc7 100644 (file)
@@ -25,6 +25,7 @@ SDCCDIRS=\
        telerepeat-v1.0
 
 ARMM3DIRS=\
+       fox1ihu fox1ihu/flash-loader \
        easymega-v1.0 easymega-v1.0/flash-loader \
        telemega-v0.1 telemega-v0.1/flash-loader \
        telemega-v1.0 telemega-v1.0/flash-loader \
@@ -36,13 +37,16 @@ ARMM3DIRS=\
        telegps-v1.0 telegps-v1.0/flash-loader \
        telegps-v2.0 telegps-v2.0/flash-loader \
        telelco-v0.2 telelco-v0.2/flash-loader \
+       telelco-v0.2-cc1200 telelco-v0.2-cc1200/flash-loader \
        telelco-v0.3 telelco-v0.3/flash-loader \
+       telelco-v2.0 telelco-v2.0/flash-loader \
        teledongle-v3.0 teledongle-v3.0/flash-loader \
        teleballoon-v2.0 \
        telebt-v3.0 telebt-v3.0/flash-loader \
        telebt-v4.0 telebt-v4.0/flash-loader \
        telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \
        telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \
+       telefireeight-v1.0 telefireeight-v1.0/flash-loader 
 
 ARMM0DIRS=\
        easymini-v1.0 easymini-v1.0/flash-loader \
index dea5b483f5158e719cf63dcf0d49c018f5e67fef..c6cf45bd348e2203dc778cbaec325c5c17879afa 100644 (file)
@@ -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
 
index c3acd441c637c77f2357f01a24d11e74dc434020..1165e4540fbe5e445a1e7aa32ef54681d76ae262 100644 (file)
@@ -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();
 
index f2c46d8b409193a84156975326f25011f8c98869..22861d9d1e8636e665ba706518532d9c568fb632 100644 (file)
@@ -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)
index 07e92c670f3a1c590aed332b875d3f8fc66e46b3..f6a9676bc481ad934b6d794625092a84f531f5d0 100644 (file)
@@ -68,6 +68,39 @@ _ao_button_get(uint8_t b)
 #endif
 #if AO_BUTTON_COUNT > 4
        case 4: return ao_button_value(4);
+#endif
+#if AO_BUTTON_COUNT > 5
+       case 5: return ao_button_value(5);
+#endif
+#if AO_BUTTON_COUNT > 6
+       case 6: return ao_button_value(6);
+#endif
+#if AO_BUTTON_COUNT > 7
+       case 7: return ao_button_value(7);
+#endif
+#if AO_BUTTON_COUNT > 8
+       case 8: return ao_button_value(8);
+#endif
+#if AO_BUTTON_COUNT > 9
+       case 9: return ao_button_value(9);
+#endif
+#if AO_BUTTON_COUNT > 10
+       case 10: return ao_button_value(10);
+#endif
+#if AO_BUTTON_COUNT > 11
+       case 11: return ao_button_value(11);
+#endif
+#if AO_BUTTON_COUNT > 12
+       case 12: return ao_button_value(12);
+#endif
+#if AO_BUTTON_COUNT > 13
+       case 13: return ao_button_value(13);
+#endif
+#if AO_BUTTON_COUNT > 14
+       case 14: return ao_button_value(14);
+#endif
+#if AO_BUTTON_COUNT > 15
+       case 15: return ao_button_value(15);
 #endif
        }
        return 0;
@@ -144,4 +177,40 @@ ao_button_init(void)
 #if AO_BUTTON_COUNT > 4
        init(4);
 #endif
+#if AO_BUTTON_COUNT > 5
+       init(5);
+#endif
+#if AO_BUTTON_COUNT > 6
+       init(6);
+#endif
+#if AO_BUTTON_COUNT > 7
+       init(7);
+#endif
+#if AO_BUTTON_COUNT > 8
+       init(8);
+#endif
+#if AO_BUTTON_COUNT > 9
+       init(9);
+#endif
+#if AO_BUTTON_COUNT > 10
+       init(10);
+#endif
+#if AO_BUTTON_COUNT > 11
+       init(11);
+#endif
+#if AO_BUTTON_COUNT > 12
+       init(12);
+#endif
+#if AO_BUTTON_COUNT > 13
+       init(13);
+#endif
+#if AO_BUTTON_COUNT > 14
+       init(14);
+#endif
+#if AO_BUTTON_COUNT > 15
+       init(15);
+#endif
+#if AO_BUTTON_COUNT > 16
+       #error too many buttons
+#endif
 }
index efe5f996acaaaa157d42397ad9f2bf313554368e..2f091485a24721e09f80cd972f8dd32c3d8fcc9b 100644 (file)
@@ -1447,7 +1447,9 @@ ao_radio_test_recv(void)
 static void
 ao_radio_aprs(void)
 {
+#if PACKET_HAS_SLAVE
        ao_packet_slave_stop();
+#endif
        ao_aprs_send();
 }
 #endif
index e1806ca394f95815c84838b3f4fafdefd07d9538..e892c8c045d3ad584edfc87c5149750f4935f7bf 100644 (file)
 #include <ao_quadrature.h>
 #include <ao_lco_func.h>
 #include <ao_radio_cmac.h>
-
-#define DEBUG  1
-
-#if DEBUG
-static uint8_t ao_lco_debug;
-#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
-#else
-#define PRINTD(...) 
+#if HAS_ADC_SINGLE
+#include <ao_adc_single.h>
 #endif
 
 #define AO_LCO_PAD_DIGIT       0
@@ -40,32 +34,16 @@ static uint8_t      ao_lco_debug;
 #define AO_LCO_DRAG_RACE_START_TIME    AO_SEC_TO_TICKS(5)
 #define AO_LCO_DRAG_RACE_STOP_TIME     AO_SEC_TO_TICKS(2)
 
-#define AO_LCO_VALID_LAST      1
-#define AO_LCO_VALID_EVER      2
-
-static uint8_t ao_lco_min_box, ao_lco_max_box;
-static uint8_t ao_lco_selected[AO_PAD_MAX_BOXES];
-static uint8_t ao_lco_valid[AO_PAD_MAX_BOXES];
-static uint8_t ao_lco_channels[AO_PAD_MAX_BOXES];
-static uint16_t        ao_lco_tick_offset[AO_PAD_MAX_BOXES];
+#define AO_LCO_BOX_DRAG                0x1000
 
 /* UI values */
-static uint8_t ao_lco_armed;
-static uint8_t ao_lco_firing;
 static uint16_t        ao_lco_fire_tick;
 static uint8_t ao_lco_fire_down;
-static uint8_t ao_lco_drag_race;
-static uint8_t ao_lco_pad;
-static int16_t ao_lco_box;
-
-#define AO_LCO_BOX_DRAG                0x1000
-
-static struct ao_pad_query     ao_pad_query;
 
 static uint8_t ao_lco_display_mutex;
 
-static void
-ao_lco_set_pad(uint8_t pad)
+void
+ao_lco_show_pad(uint8_t pad)
 {
        ao_mutex_get(&ao_lco_display_mutex);
        ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4));
@@ -89,8 +67,8 @@ ao_lco_set_pad(uint8_t pad)
                                 (0 << 5) |     \
                                 (0 << 6))
 
-static void
-ao_lco_set_box(uint16_t box)
+void
+ao_lco_show_box(uint16_t box)
 {
        ao_mutex_get(&ao_lco_display_mutex);
        if (box == AO_LCO_BOX_DRAG) {
@@ -104,7 +82,7 @@ ao_lco_set_box(uint16_t box)
 }
 
 static void
-ao_lco_set_voltage(uint16_t decivolts)
+ao_lco_show_voltage(uint16_t decivolts)
 {
        uint8_t tens, ones, tenths;
 
@@ -118,27 +96,21 @@ ao_lco_set_voltage(uint16_t decivolts)
        ao_mutex_put(&ao_lco_display_mutex);
 }
 
-static void
-ao_lco_set_display(void)
+void
+ao_lco_show(void)
 {
-       if (ao_lco_pad == 0 && ao_lco_box != AO_LCO_BOX_DRAG) {
-               ao_lco_set_voltage(ao_pad_query.battery);
+       if (ao_lco_pad == AO_LCO_PAD_VOLTAGE && ao_lco_box != AO_LCO_BOX_DRAG) {
+               ao_lco_show_voltage(ao_pad_query.battery);
        } else {
                if (ao_lco_box == AO_LCO_BOX_DRAG)
-                       ao_lco_set_pad(ao_lco_drag_race);
+                       ao_lco_show_pad(ao_lco_drag_race);
                else
-                       ao_lco_set_pad(ao_lco_pad);
-               ao_lco_set_box(ao_lco_box);
+                       ao_lco_show_pad(ao_lco_pad);
+               ao_lco_show_box(ao_lco_box);
        }
 }
 
-#define MASK_SIZE(n)   (((n) + 7) >> 3)
-#define MASK_ID(n)     ((n) >> 3)
-#define MASK_SHIFT(n)  ((n) & 7)
-
-static uint8_t ao_lco_box_mask[MASK_SIZE(AO_PAD_MAX_BOXES)];
-
-static uint8_t
+uint8_t
 ao_lco_box_present(uint16_t box)
 {
        if (box == AO_LCO_BOX_DRAG)
@@ -146,117 +118,11 @@ ao_lco_box_present(uint16_t box)
 
        if (box >= AO_PAD_MAX_BOXES)
                return 0;
-       return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1;
-}
-
-static uint8_t
-ao_lco_pad_present(uint8_t box, uint8_t pad)
-{
-       /* voltage measurement is always valid */
-       if (pad == 0)
-               return 1;
-       if (!ao_lco_channels[box])
-               return 0;
-       if (pad > AO_PAD_MAX_CHANNELS)
-               return 0;
-       return (ao_lco_channels[box] >> (pad - 1)) & 1;
-}
-
-static uint8_t
-ao_lco_pad_first(uint8_t box)
-{
-       uint8_t pad;
-
-       for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++)
-               if (ao_lco_pad_present(box, pad))
-                       return pad;
-       return 0;
+       return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1;
 }
 
 static struct ao_task  ao_lco_drag_task;
 static uint8_t         ao_lco_drag_active;
-static uint8_t         ao_lco_drag_beep_count;
-static uint8_t         ao_lco_drag_beep_on;
-static uint16_t                ao_lco_drag_beep_time;
-static uint16_t                ao_lco_drag_warn_time;
-
-#define AO_LCO_DRAG_BEEP_TIME  AO_MS_TO_TICKS(50)
-#define AO_LCO_DRAG_WARN_TIME  AO_SEC_TO_TICKS(5)
-
-static void
-ao_lco_drag_beep_start(void)
-{
-       ao_beep(AO_BEEP_HIGH);
-       PRINTD("beep start\n");
-       ao_lco_drag_beep_on = 1;
-       ao_lco_drag_beep_time = ao_time() + AO_LCO_DRAG_BEEP_TIME;
-}
-
-static void
-ao_lco_drag_beep_stop(void)
-{
-       ao_beep(0);
-       PRINTD("beep stop\n");
-       ao_lco_drag_beep_on = 0;
-       if (ao_lco_drag_beep_count) {
-               --ao_lco_drag_beep_count;
-               if (ao_lco_drag_beep_count)
-                       ao_lco_drag_beep_time = ao_time() + AO_LCO_DRAG_BEEP_TIME;
-       }
-}
-
-static void
-ao_lco_drag_beep(uint8_t beeps)
-{
-       PRINTD("beep %d\n", beeps);
-       if (!ao_lco_drag_beep_count)
-               ao_lco_drag_beep_start();
-       ao_lco_drag_beep_count += beeps;
-}
-
-static uint16_t
-ao_lco_drag_beep_check(uint16_t now, uint16_t delay)
-{
-       PRINTD("beep check count %d delta %d\n",
-              ao_lco_drag_beep_count,
-              (int16_t) (now - ao_lco_drag_beep_time));
-       if (ao_lco_drag_beep_count) {
-               if ((int16_t) (now - ao_lco_drag_beep_time) >= 0) {
-                       if (ao_lco_drag_beep_on)
-                               ao_lco_drag_beep_stop();
-                       else
-                               ao_lco_drag_beep_start();
-               }
-       }
-
-       if (ao_lco_drag_beep_count) {
-               if (delay > AO_LCO_DRAG_BEEP_TIME)
-                       delay = AO_LCO_DRAG_BEEP_TIME;
-       }
-       return delay;
-}
-
-static void
-ao_lco_drag_enable(void)
-{
-       PRINTD("Drag enable\n");
-       ao_lco_drag_race = 1;
-       memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
-       ao_lco_drag_beep(5);
-       ao_lco_set_display();
-       ao_lco_fire_down = 0;
-}
-
-static void
-ao_lco_drag_disable(void)
-{
-       PRINTD("Drag disable\n");
-       ao_lco_drag_race = 0;
-       memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
-       ao_lco_drag_beep(2);
-       ao_lco_set_display();
-       ao_lco_fire_down = 0;
-}
 
 static uint16_t
 ao_lco_drag_button_check(uint16_t now, uint16_t delay)
@@ -269,13 +135,17 @@ ao_lco_drag_button_check(uint16_t now, uint16_t delay)
         */
        if (ao_lco_fire_down) {
                if (ao_lco_drag_race) {
-                       if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME)
+                       if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_STOP_TIME) {
                                ao_lco_drag_disable();
+                               ao_lco_fire_down = 0;
+                       }
                        else
                                button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_STOP_TIME - now;
                } else {
-                       if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_START_TIME)
+                       if ((int16_t) (now - ao_lco_fire_tick) >= AO_LCO_DRAG_RACE_START_TIME) {
                                ao_lco_drag_enable();
+                               ao_lco_fire_down = 0;
+                       }
                        else
                                button_delay = ao_lco_fire_tick + AO_LCO_DRAG_RACE_START_TIME - now;
                }
@@ -285,35 +155,20 @@ ao_lco_drag_button_check(uint16_t now, uint16_t delay)
        return delay;
 }
 
-static uint16_t
-ao_lco_drag_warn_check(uint16_t now, uint16_t delay)
-{
-       uint16_t        warn_delay = ~0;
-
-       if (ao_lco_drag_race) {
-               if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) {
-                       ao_lco_drag_beep(1);
-                       ao_lco_drag_warn_time = now + AO_LCO_DRAG_WARN_TIME;
-               }
-               warn_delay = ao_lco_drag_warn_time - now;
-       }
-       if (delay > warn_delay)
-               delay = warn_delay;
-       return delay;
-}
-
 static void
 ao_lco_drag_monitor(void)
 {
        uint16_t        delay = ~0;
        uint16_t        now;
 
+       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
        for (;;) {
-               PRINTD("Drag monitor active %d delay %d\n", ao_lco_drag_active, delay);
+               PRINTD("Drag monitor count %d active %d delay %d\n",
+                      ao_lco_drag_beep_count, ao_lco_drag_active, delay);
                if (delay == (uint16_t) ~0)
-                       ao_sleep(&ao_lco_drag_active);
+                       ao_sleep(&ao_lco_drag_beep_count);
                else
-                       ao_sleep_for(&ao_lco_drag_active, delay);
+                       ao_sleep_for(&ao_lco_drag_beep_count, delay);
 
                delay = ~0;
                if (!ao_lco_drag_active)
@@ -332,14 +187,34 @@ ao_lco_drag_monitor(void)
        }
 }
 
+static void
+ao_lco_step_box(int8_t dir)
+{
+       int16_t new_box = ao_lco_box;
+       do {
+               if (new_box == AO_LCO_BOX_DRAG) {
+                       if (dir < 0)
+                               new_box = ao_lco_max_box;
+                       else
+                               new_box = ao_lco_min_box;
+               } else {
+                       new_box += dir;
+                       if (new_box > ao_lco_max_box)
+                               new_box = AO_LCO_BOX_DRAG;
+                       else if (new_box < ao_lco_min_box)
+                               new_box = AO_LCO_BOX_DRAG;
+               }
+               if (new_box == ao_lco_box)
+                       break;
+       } while (!ao_lco_box_present(new_box));
+       ao_lco_set_box(new_box);
+}
+
 static void
 ao_lco_input(void)
 {
        static struct ao_event  event;
-       int8_t          dir, new_pad;
-       int16_t         new_box;
 
-       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
        for (;;) {
                ao_event_get(&event);
                PRINTD("event type %d unit %d value %d\n",
@@ -348,106 +223,38 @@ ao_lco_input(void)
                case AO_EVENT_QUADRATURE:
                        switch (event.unit) {
                        case AO_QUADRATURE_PAD:
-                               if (!ao_lco_armed) {
-                                       dir = (int8_t) event.value;
-                                       new_pad = ao_lco_pad;
-                                       do {
-                                               new_pad += dir;
-                                               if (new_pad > AO_PAD_MAX_CHANNELS)
-                                                       new_pad = 0;
-                                               if (new_pad < 0)
-                                                       new_pad = AO_PAD_MAX_CHANNELS;
-                                               if (new_pad == ao_lco_pad)
-                                                       break;
-                                       } while (!ao_lco_pad_present(ao_lco_box, new_pad));
-                                       if (new_pad != ao_lco_pad) {
-                                               ao_lco_pad = new_pad;
-                                               ao_lco_set_display();
-                                       }
-                               }
+                               if (!ao_lco_armed)
+                                       ao_lco_step_pad((int8_t) event.value);
                                break;
                        case AO_QUADRATURE_BOX:
-                               if (!ao_lco_armed) {
-                                       dir = (int8_t) event.value;
-                                       new_box = ao_lco_box;
-                                       do {
-                                               if (new_box == AO_LCO_BOX_DRAG) {
-                                                       if (dir < 0)
-                                                               new_box = ao_lco_max_box;
-                                                       else
-                                                               new_box = ao_lco_min_box;
-                                               } else {
-                                                       new_box += dir;
-                                                       if (new_box > ao_lco_max_box)
-                                                               new_box = AO_LCO_BOX_DRAG;
-                                                       else if (new_box < ao_lco_min_box)
-                                                               new_box = AO_LCO_BOX_DRAG;
-                                               }
-                                               if (new_box == ao_lco_box)
-                                                       break;
-                                       } while (!ao_lco_box_present(new_box));
-                                       if (ao_lco_box != new_box) {
-                                               ao_lco_box = new_box;
-                                               ao_lco_pad = 1;
-                                               if (ao_lco_box != AO_LCO_BOX_DRAG)
-                                                       ao_lco_channels[ao_lco_box] = 0;
-                                               ao_lco_set_display();
-                                       }
-                               }
+                               if (!ao_lco_armed)
+                                       ao_lco_step_box((int8_t) event.value);
                                break;
                        }
                        break;
                case AO_EVENT_BUTTON:
                        switch (event.unit) {
                        case AO_BUTTON_ARM:
-                               ao_lco_armed = event.value;
-                               PRINTD("Armed %d\n", ao_lco_armed);
-                               if (ao_lco_armed) {
-                                       if (ao_lco_drag_race) {
-                                               uint8_t box;
-
-                                               for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) {
-                                                       if (ao_lco_selected[box]) {
-                                                               ao_wakeup(&ao_lco_armed);
-                                                               break;
-                                                       }
-                                               }
-                                       } else {
-                                               memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
-                                               if (ao_lco_pad != 0 && ao_lco_box != AO_LCO_BOX_DRAG)
-                                                       ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1));
-                                               else
-                                                       ao_lco_armed = 0;
-                                       }
-                               }
-                               ao_wakeup(&ao_lco_armed);
+                               ao_lco_set_armed(event.value);
                                break;
                        case AO_BUTTON_FIRE:
                                if (ao_lco_armed) {
                                        ao_lco_fire_down = 0;
-                                       ao_lco_firing = event.value;
-                                       PRINTD("Firing %d\n", ao_lco_firing);
-                                       ao_wakeup(&ao_lco_armed);
+                                       ao_lco_set_firing(event.value);
                                } else {
                                        if (event.value) {
                                                if (ao_lco_box == AO_LCO_BOX_DRAG) {
                                                        ao_lco_fire_down = 1;
                                                        ao_lco_fire_tick = ao_time();
                                                        ao_lco_drag_active = 1;
+                                                       ao_wakeup(&ao_lco_drag_beep_count);
+                                               } else {
+                                                       ao_lco_toggle_drag();
                                                }
-                                               if (ao_lco_drag_race) {
-                                                       if (ao_lco_pad != 0 && ao_lco_box != AO_LCO_BOX_DRAG) {
-                                                               ao_lco_selected[ao_lco_box] ^= (1 << (ao_lco_pad - 1));
-                                                               PRINTD("Toggle box %d pad %d (pads now %x) to drag race\n",
-                                                                      ao_lco_pad, ao_lco_box, ao_lco_selected[ao_lco_box]);
-                                                               ao_lco_drag_beep(ao_lco_pad);
-                                                       }
-                                               }
-                                               ao_wakeup(&ao_lco_drag_active);
                                        } else {
                                                ao_lco_fire_down = 0;
                                                if (ao_lco_drag_active)
-                                                       ao_wakeup(&ao_lco_drag_active);
+                                                       ao_wakeup(&ao_lco_drag_beep_count);
                                        }
                                }
                                break;
@@ -457,188 +264,36 @@ ao_lco_input(void)
        }
 }
 
-static AO_LED_TYPE     continuity_led[AO_LED_CONTINUITY_NUM] = {
-#ifdef AO_LED_CONTINUITY_0
-       AO_LED_CONTINUITY_0,
-#endif
-#ifdef AO_LED_CONTINUITY_1
-       AO_LED_CONTINUITY_1,
-#endif
-#ifdef AO_LED_CONTINUITY_2
-       AO_LED_CONTINUITY_2,
-#endif
-#ifdef AO_LED_CONTINUITY_3
-       AO_LED_CONTINUITY_3,
-#endif
-#ifdef AO_LED_CONTINUITY_4
-       AO_LED_CONTINUITY_4,
-#endif
-#ifdef AO_LED_CONTINUITY_5
-       AO_LED_CONTINUITY_5,
-#endif
-#ifdef AO_LED_CONTINUITY_6
-       AO_LED_CONTINUITY_6,
-#endif
-#ifdef AO_LED_CONTINUITY_7
-       AO_LED_CONTINUITY_7,
-#endif
-};
-
-static uint8_t
-ao_lco_get_channels(uint8_t box, struct ao_pad_query *query)
-{
-       int8_t                  r;
-
-       r = ao_lco_query(box, query, &ao_lco_tick_offset[box]);
-       if (r == AO_RADIO_CMAC_OK) {
-               ao_lco_channels[box] = query->channels;
-               ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
-       } else
-               ao_lco_valid[box] &= ~AO_LCO_VALID_LAST;
-       PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]);
-       ao_wakeup(&ao_pad_query);
-       return ao_lco_valid[box];
-}
-
-static void
-ao_lco_update(void)
-{
-       if (ao_lco_box != AO_LCO_BOX_DRAG) {
-               uint8_t previous_valid = ao_lco_valid[ao_lco_box];
-
-               if (ao_lco_get_channels(ao_lco_box, &ao_pad_query) & AO_LCO_VALID_LAST) {
-                       if (!(previous_valid & AO_LCO_VALID_EVER)) {
-                               if (ao_lco_pad != 0)
-                                       ao_lco_pad = ao_lco_pad_first(ao_lco_box);
-                               ao_lco_set_display();
-                       }
-                       if (ao_lco_pad == 0)
-                               ao_lco_set_display();
-               }
-       }
-}
-
-static void
-ao_lco_box_reset_present(void)
-{
-       ao_lco_min_box = 0xff;
-       ao_lco_max_box = 0x00;
-       memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask));
-}
-
-static void
-ao_lco_box_set_present(uint8_t box)
-{
-       if (box < ao_lco_min_box)
-               ao_lco_min_box = box;
-       if (box > ao_lco_max_box)
-               ao_lco_max_box = box;
-       if (box >= AO_PAD_MAX_BOXES)
-               return;
-       ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box);
-}
-
+/*
+ * Light up everything for a second at power on to let the user
+ * visually inspect the system for correct operation
+ */
 static void
-ao_lco_search(void)
+ao_lco_display_test()
 {
-       int8_t          r;
-       int8_t          try;
-       uint8_t         box;
-       uint8_t         boxes = 0;
-
-       ao_lco_box_reset_present();
-       ao_lco_set_pad(0);
-       for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
-               if ((box % 10) == 0)
-                       ao_lco_set_box(box);
-               for (try = 0; try < 3; try++) {
-                       ao_lco_tick_offset[box] = 0;
-                       r = ao_lco_query(box, &ao_pad_query, &ao_lco_tick_offset[box]);
-                       PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]);
-                       if (r == AO_RADIO_CMAC_OK) {
-                               ++boxes;
-                               ao_lco_box_set_present(box);
-                               ao_lco_set_pad(boxes % 10);
-                               ao_delay(AO_MS_TO_TICKS(30));
-                               break;
-                       }
-               }
-       }
-       if (ao_lco_min_box <= ao_lco_max_box)
-               ao_lco_box = ao_lco_min_box;
-       else
-               ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0;
-       memset(ao_lco_valid, 0, sizeof (ao_lco_valid));
-       memset(ao_lco_channels, 0, sizeof (ao_lco_channels));
-       ao_lco_pad = 1;
-       ao_lco_set_display();
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, 8 | 0x10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 8 | 0x10);
+       ao_mutex_put(&ao_lco_display_mutex);
+       ao_led_on(LEDS_AVAILABLE);
+       ao_delay(AO_MS_TO_TICKS(1000));
+       ao_led_off(LEDS_AVAILABLE);
 }
 
+#if HAS_ADC_SINGLE
 static void
-ao_lco_igniter_status(void)
+ao_lco_batt_voltage(void)
 {
-       uint8_t         c;
-       uint8_t         t = 0;
-
-       for (;;) {
-               ao_sleep(&ao_pad_query);
-               PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_box == AO_LCO_BOX_DRAG ? -1 : ao_lco_valid[ao_lco_box]);
-               if (ao_lco_box == AO_LCO_BOX_DRAG) {
-                       ao_led_off(AO_LED_RED|AO_LED_GREEN|AO_LED_AMBER);
-                       for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
-                               ao_led_off(continuity_led[c]);
-               } else {
-                       if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) {
-                               ao_led_on(AO_LED_RED);
-                               ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
-                               continue;
-                       }
-                       if (ao_radio_cmac_rssi < -90) {
-                               ao_led_on(AO_LED_AMBER);
-                               ao_led_off(AO_LED_RED|AO_LED_GREEN);
-                       } else {
-                               ao_led_on(AO_LED_GREEN);
-                               ao_led_off(AO_LED_RED|AO_LED_AMBER);
-                       }
-                       if (ao_pad_query.arm_status)
-                               ao_led_on(AO_LED_REMOTE_ARM);
-                       else
-                               ao_led_off(AO_LED_REMOTE_ARM);
-
-                       for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
-                               uint8_t status;
+       struct ao_adc   packet;
+       int16_t         decivolt;
 
-                               if (ao_lco_drag_race) {
-                                       if (ao_lco_selected[ao_lco_box] & (1 << c) && t)
-                                               ao_led_on(continuity_led[c]);
-                                       else
-                                               ao_led_off(continuity_led[c]);
-                               } else {
-                                       if (ao_pad_query.channels & (1 << c))
-                                               status = ao_pad_query.igniter_status[c];
-                                       else
-                                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
-                                       if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
-                                               ao_led_on(continuity_led[c]);
-                                       else
-                                               ao_led_off(continuity_led[c]);
-                               }
-                       }
-                       t = 1-t;
-               }
-       }
-}
-
-static void
-ao_lco_arm_warn(void)
-{
-       for (;;) {
-               while (!ao_lco_armed)
-                       ao_sleep(&ao_lco_armed);
-               ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
-               ao_delay(AO_MS_TO_TICKS(200));
-       }
+       ao_adc_single_get(&packet);
+       decivolt = ao_battery_decivolt(packet.v_batt);
+       ao_lco_show_voltage(decivolt);
+       ao_delay(AO_MS_TO_TICKS(1000));
 }
+#endif
 
 static struct ao_task ao_lco_input_task;
 static struct ao_task ao_lco_monitor_task;
@@ -646,43 +301,18 @@ static struct ao_task ao_lco_arm_warn_task;
 static struct ao_task ao_lco_igniter_status_task;
 
 static void
-ao_lco_monitor(void)
+ao_lco_main(void)
 {
-       uint16_t                delay;
-       uint8_t                 box;
-
+       ao_lco_display_test();
+#if HAS_ADC_SINGLE
+       ao_lco_batt_voltage();
+#endif
        ao_lco_search();
        ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
        ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
        ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
        ao_add_task(&ao_lco_drag_task, ao_lco_drag_monitor, "drag race");
-       for (;;) {
-               PRINTD("monitor armed %d firing %d\n",
-                      ao_lco_armed, ao_lco_firing);
-
-               if (ao_lco_armed && ao_lco_firing) {
-                       ao_lco_ignite(AO_PAD_FIRE);
-               } else {
-                       ao_lco_update();
-                       if (ao_lco_armed) {
-                               for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) {
-                                       if (ao_lco_selected[box]) {
-                                               PRINTD("Arming box %d pads %x\n",
-                                                      box, ao_lco_selected[box]);
-                                               if (ao_lco_valid[box] & AO_LCO_VALID_EVER) {
-                                                       ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]);
-                                                       ao_delay(AO_MS_TO_TICKS(10));
-                                               }
-                                       }
-                               }
-                       }
-               }
-               if (ao_lco_armed && ao_lco_firing)
-                       delay = AO_MS_TO_TICKS(100);
-               else
-                       delay = AO_SEC_TO_TICKS(1);
-               ao_sleep_for(&ao_lco_armed, delay);
-       }
+       ao_lco_monitor();
 }
 
 #if DEBUG
@@ -704,7 +334,7 @@ __code struct ao_cmds ao_lco_cmds[] = {
 void
 ao_lco_init(void)
 {
-       ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor");
+       ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
 #if DEBUG
        ao_cmd_register(&ao_lco_cmds[0]);
 #endif
index 5721eed539044ab02e897526083dcd439aad533d..2958fbccc33cae7ec874b1edfaa66dc63e5f4aaf 100644 (file)
 #ifndef _AO_LCO_H_
 #define _AO_LCO_H_
 
+#include <ao_lco_func.h>
+
+#ifndef AO_LCO_DRAG
+#define AO_LCO_DRAG    1
+#endif
+
+#define DEBUG  1
+
+#if DEBUG
+extern uint8_t ao_lco_debug;
+#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(...) 
+#endif
+
+#if AO_LCO_DRAG
+extern uint8_t ao_lco_drag_race;       /* TRUE when drag race mode enabled */
+#endif
+
+extern uint8_t ao_lco_pad;             /* Currently selected pad */
+extern int16_t ao_lco_box;             /* Currently selected box */
+
+extern uint8_t ao_lco_armed;           /* armed mode active */
+extern uint8_t ao_lco_firing;          /* fire button pressed */
+
+extern struct ao_pad_query     ao_pad_query;   /* Last received QUERY from pad */
+
+#define AO_LCO_PAD_VOLTAGE     0               /* Pad number to show box voltage */
+
+extern uint8_t ao_lco_min_box, ao_lco_max_box;
+
+#define AO_LCO_MASK_SIZE(n)    (((n) + 7) >> 3)
+#define AO_LCO_MASK_ID(n)      ((n) >> 3)
+#define AO_LCO_MASK_SHIFT(n)   ((n) & 7)
+
+extern uint8_t ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)];
+
+/*
+ * Shared functions
+ */
+
+void
+ao_lco_igniter_status(void);
+
+void
+ao_lco_update(void);
+
+uint8_t
+ao_lco_pad_present(uint8_t box, uint8_t pad);
+
+uint8_t
+ao_lco_pad_first(uint8_t box);
+
+void
+ao_lco_set_pad(uint8_t new_pad);
+
+void
+ao_lco_step_pad(int8_t dir);
+
+void
+ao_lco_set_box(uint16_t new_box);
+
+void
+ao_lco_set_armed(uint8_t armed);
+
+void
+ao_lco_set_firing(uint8_t firing);
+
+void
+ao_lco_toggle_drag(void);
+
+void
+ao_lco_search(void);
+
+void
+ao_lco_monitor(void);
+
+extern uint8_t                 ao_lco_drag_beep_count;
+
+/* enable drag race mode */
+void
+ao_lco_drag_enable(void);
+
+/* disable drag race mode */
+void
+ao_lco_drag_disable(void);
+
+/* Handle drag beeps, return new delay */
+uint16_t
+ao_lco_drag_beep_check(uint16_t now, uint16_t delay);
+
+/* Check if it's time to beep during drag race. Return new delay */
+uint16_t
+ao_lco_drag_warn_check(uint16_t now, uint16_t delay);
+
+/* Request 'beeps' additional drag race beeps */
+void
+ao_lco_drag_add_beeps(uint8_t beeps);
+
+/* task function for beeping while arm is active */
+void
+ao_lco_arm_warn(void);
+
+/*
+ * Provided by the hw-specific driver code
+ */
+
+void
+ao_lco_show_pad(uint8_t pad);
+
+void
+ao_lco_show_box(uint16_t box);
+
+void
+ao_lco_show(void);
+
 void
 ao_lco_init(void);
 
+uint8_t
+ao_lco_box_present(uint16_t box);
+
 #endif /* _AO_LCO_H_ */
diff --git a/src/drivers/ao_lco_bits.c b/src/drivers/ao_lco_bits.c
new file mode 100644 (file)
index 0000000..6e50e44
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+ * 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_lco.h>
+#include <ao_radio_cmac.h>
+
+uint8_t                ao_lco_debug;
+
+uint8_t                ao_lco_pad;
+int16_t                ao_lco_box;
+
+uint8_t                ao_lco_armed;                                   /* arm active */
+uint8_t                ao_lco_firing;                                  /* fire active */
+
+uint8_t                ao_lco_min_box, ao_lco_max_box;
+
+#if AO_LCO_DRAG
+uint8_t                ao_lco_drag_race;
+#endif
+
+struct ao_pad_query    ao_pad_query;                           /* latest query response */
+
+static uint8_t         ao_lco_channels[AO_PAD_MAX_BOXES];      /* pad channels available on each box */
+static uint16_t                ao_lco_tick_offset[AO_PAD_MAX_BOXES];   /* offset from local to remote tick count */
+static uint8_t         ao_lco_selected[AO_PAD_MAX_BOXES];      /* pads selected to fire */
+
+#define AO_LCO_VALID_LAST      1
+#define AO_LCO_VALID_EVER      2
+
+static uint8_t         ao_lco_valid[AO_PAD_MAX_BOXES];         /* AO_LCO_VALID bits per box */
+
+static const AO_LED_TYPE       continuity_led[AO_LED_CONTINUITY_NUM] = {
+#ifdef AO_LED_CONTINUITY_0
+       AO_LED_CONTINUITY_0,
+#endif
+#ifdef AO_LED_CONTINUITY_1
+       AO_LED_CONTINUITY_1,
+#endif
+#ifdef AO_LED_CONTINUITY_2
+       AO_LED_CONTINUITY_2,
+#endif
+#ifdef AO_LED_CONTINUITY_3
+       AO_LED_CONTINUITY_3,
+#endif
+#ifdef AO_LED_CONTINUITY_4
+       AO_LED_CONTINUITY_4,
+#endif
+#ifdef AO_LED_CONTINUITY_5
+       AO_LED_CONTINUITY_5,
+#endif
+#ifdef AO_LED_CONTINUITY_6
+       AO_LED_CONTINUITY_6,
+#endif
+#ifdef AO_LED_CONTINUITY_7
+       AO_LED_CONTINUITY_7,
+#endif
+};
+
+/* Set LEDs to match remote box status */
+void
+ao_lco_igniter_status(void)
+{
+       uint8_t         c;
+       uint8_t         t = 0;
+
+       for (;;) {
+#if AO_LCO_DRAG
+               if (ao_lco_drag_race)
+                       ao_sleep_for(&ao_pad_query, AO_MS_TO_TICKS(50));
+               else
+#endif
+                       ao_sleep(&ao_pad_query);
+               PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid[ao_lco_box]);
+               if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST)) {
+                       ao_led_on(AO_LED_RED);
+                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
+                       continue;
+               }
+               if (ao_radio_cmac_rssi < -90) {
+                       ao_led_on(AO_LED_AMBER);
+                       ao_led_off(AO_LED_RED|AO_LED_GREEN);
+               } else {
+                       ao_led_on(AO_LED_GREEN);
+                       ao_led_off(AO_LED_RED|AO_LED_AMBER);
+               }
+               if (ao_pad_query.arm_status)
+                       ao_led_on(AO_LED_REMOTE_ARM);
+               else
+                       ao_led_off(AO_LED_REMOTE_ARM);
+
+               for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
+                       uint8_t status;
+
+                       if (ao_pad_query.channels & (1 << c))
+                               status = ao_pad_query.igniter_status[c];
+                       else
+                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+
+#if AO_LCO_DRAG
+                       if (ao_lco_drag_race && (ao_lco_selected[ao_lco_box] & (1 << c))) {
+                               uint8_t on = 0;
+                               if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) {
+                                       if (t)
+                                               on = 1;
+                               } else {
+                                       if (t == 1)
+                                               on = 1;
+                               }
+                               if (on)
+                                       ao_led_on(continuity_led[c]);
+                               else
+                                       ao_led_off(continuity_led[c]);
+                       } else
+#endif
+                       {
+                               if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+                                       ao_led_on(continuity_led[c]);
+                               else
+                                       ao_led_off(continuity_led[c]);
+                       }
+               }
+               t = (t + 1) & 3;
+       }
+}
+
+uint8_t
+ao_lco_pad_present(uint8_t box, uint8_t pad)
+{
+       /* voltage measurement is always valid */
+       if (pad == AO_LCO_PAD_VOLTAGE)
+               return 1;
+       if (!ao_lco_channels[box])
+               return 0;
+       if (pad > AO_PAD_MAX_CHANNELS)
+               return 0;
+       return (ao_lco_channels[box] >> (pad - 1)) & 1;
+}
+
+uint8_t
+ao_lco_pad_first(uint8_t box)
+{
+       uint8_t pad;
+
+       for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++)
+               if (ao_lco_pad_present(box, pad))
+                       return pad;
+       return 0;
+}
+
+static uint8_t
+ao_lco_get_channels(uint8_t box, struct ao_pad_query *query)
+{
+       int8_t                  r;
+
+       r = ao_lco_query(box, query, &ao_lco_tick_offset[box]);
+       if (r == AO_RADIO_CMAC_OK) {
+               ao_lco_channels[box] = query->channels;
+               ao_lco_valid[box] = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
+       } else
+               ao_lco_valid[box] &= ~AO_LCO_VALID_LAST;
+       PRINTD("ao_lco_get_channels(%d) rssi %d valid %d ret %d offset %d\n", box, ao_radio_cmac_rssi, ao_lco_valid[box], r, ao_lco_tick_offset[box]);
+       ao_wakeup(&ao_pad_query);
+       return ao_lco_valid[box];
+}
+
+void
+ao_lco_update(void)
+{
+       uint8_t previous_valid = ao_lco_valid[ao_lco_box];
+
+       if (ao_lco_get_channels(ao_lco_box, &ao_pad_query) & AO_LCO_VALID_LAST) {
+               if (!(previous_valid & AO_LCO_VALID_EVER)) {
+                       if (ao_lco_pad != AO_LCO_PAD_VOLTAGE)
+                               ao_lco_set_pad(ao_lco_pad_first(ao_lco_box));
+               }
+               if (ao_lco_pad == AO_LCO_PAD_VOLTAGE)
+                       ao_lco_show();
+       }
+}
+
+uint8_t        ao_lco_box_mask[AO_LCO_MASK_SIZE(AO_PAD_MAX_BOXES)];
+
+static void
+ao_lco_box_reset_present(void)
+{
+       ao_lco_min_box = 0xff;
+       ao_lco_max_box = 0x00;
+       memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask));
+}
+
+static void
+ao_lco_box_set_present(uint8_t box)
+{
+       if (box < ao_lco_min_box)
+               ao_lco_min_box = box;
+       if (box > ao_lco_max_box)
+               ao_lco_max_box = box;
+       if (box >= AO_PAD_MAX_BOXES)
+               return;
+       ao_lco_box_mask[AO_LCO_MASK_ID(box)] |= 1 << AO_LCO_MASK_SHIFT(box);
+}
+
+void
+ao_lco_set_pad(uint8_t new_pad)
+{
+       ao_lco_pad = new_pad;
+       ao_lco_show();
+}
+
+void
+ao_lco_set_box(uint16_t new_box)
+{
+       ao_lco_box = new_box;
+       if (ao_lco_box < AO_PAD_MAX_BOXES)
+               ao_lco_channels[ao_lco_box] = 0;
+       ao_lco_pad = 1;
+       ao_lco_show();
+}
+
+void
+ao_lco_step_pad(int8_t dir)
+{
+       int8_t  new_pad;
+
+       new_pad = ao_lco_pad;
+       do {
+               new_pad += dir;
+               if (new_pad > AO_PAD_MAX_CHANNELS)
+                       new_pad = AO_LCO_PAD_VOLTAGE;
+               if (new_pad < 0)
+                       new_pad = AO_PAD_MAX_CHANNELS;
+               if (new_pad == ao_lco_pad)
+                       break;
+       } while (!ao_lco_pad_present(ao_lco_box, new_pad));
+       ao_lco_set_pad(new_pad);
+}
+
+void
+ao_lco_set_armed(uint8_t armed)
+{
+       ao_lco_armed = armed;
+       PRINTD("Armed %d\n", ao_lco_armed);
+       if (ao_lco_armed) {
+#if AO_LCO_DRAG
+               if (ao_lco_drag_race) {
+                       uint8_t box;
+
+                       for (box = ao_lco_min_box; box <= ao_lco_max_box; box++)
+                               if (ao_lco_selected[box])
+                                       break;
+                       if (box > ao_lco_max_box)
+                               ao_lco_armed = 0;
+               } else
+#endif
+               {
+                       memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
+                       if (ao_lco_pad != 0)
+                               ao_lco_selected[ao_lco_box] = (1 << (ao_lco_pad - 1));
+                       else
+                               ao_lco_armed = 0;
+               }
+       }
+       ao_wakeup(&ao_lco_armed);
+}
+
+void
+ao_lco_set_firing(uint8_t firing)
+{
+       ao_lco_firing = firing;
+       PRINTD("Firing %d\n", ao_lco_firing);
+       ao_wakeup(&ao_lco_armed);
+}
+
+void
+ao_lco_search(void)
+{
+       int8_t          r;
+       int8_t          try;
+       uint8_t         box;
+       uint8_t         boxes = 0;
+
+       ao_lco_box_reset_present();
+       ao_lco_show_box(0);
+       ao_lco_show_pad(0);
+       for (box = 0; box < AO_PAD_MAX_BOXES; box++) {
+               if ((box % 10) == 0)
+                       ao_lco_show_box(box);
+               for (try = 0; try < 3; try++) {
+                       ao_lco_tick_offset[box] = 0;
+                       r = ao_lco_query(box, &ao_pad_query, &ao_lco_tick_offset[box]);
+                       PRINTD("box %d result %d offset %d\n", box, r, ao_lco_tick_offset[box]);
+                       if (r == AO_RADIO_CMAC_OK) {
+                               ++boxes;
+                               ao_lco_box_set_present(box);
+                               ao_lco_show_pad(boxes % 10);
+                               ao_delay(AO_MS_TO_TICKS(30));
+                               break;
+                       }
+               }
+       }
+       if (ao_lco_min_box <= ao_lco_max_box)
+               ao_lco_box = ao_lco_min_box;
+       else
+               ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0;
+       memset(ao_lco_valid, 0, sizeof (ao_lco_valid));
+       memset(ao_lco_channels, 0, sizeof (ao_lco_channels));
+       ao_lco_set_box(ao_lco_min_box);
+}
+
+void
+ao_lco_monitor(void)
+{
+       uint16_t                delay;
+       uint8_t                 box;
+
+       for (;;) {
+               PRINTD("monitor armed %d firing %d\n",
+                      ao_lco_armed, ao_lco_firing);
+
+               if (ao_lco_armed && ao_lco_firing) {
+                       ao_lco_ignite(AO_PAD_FIRE);
+               } else {
+                       ao_lco_update();
+                       if (ao_lco_armed) {
+                               for (box = ao_lco_min_box; box <= ao_lco_max_box; box++) {
+                                       if (ao_lco_selected[box]) {
+                                               PRINTD("Arming box %d pads %x\n",
+                                                      box, ao_lco_selected[box]);
+                                               if (ao_lco_valid[box] & AO_LCO_VALID_EVER) {
+                                                       ao_lco_arm(box, ao_lco_selected[box], ao_lco_tick_offset[box]);
+                                                       ao_delay(AO_MS_TO_TICKS(10));
+                                               }
+                                       }
+                               }
+                       }
+               }
+               if (ao_lco_armed && ao_lco_firing)
+                       delay = AO_MS_TO_TICKS(100);
+               else
+                       delay = AO_SEC_TO_TICKS(1);
+               ao_sleep_for(&ao_lco_armed, delay);
+       }
+}
+
+#if AO_LCO_DRAG
+
+uint8_t                        ao_lco_drag_beep_count;
+static uint8_t         ao_lco_drag_beep_on;
+static uint16_t                ao_lco_drag_beep_time;
+static uint16_t                ao_lco_drag_warn_time;
+
+#define AO_LCO_DRAG_BEEP_TIME  AO_MS_TO_TICKS(50)
+#define AO_LCO_DRAG_WARN_TIME  AO_SEC_TO_TICKS(5)
+
+/* Request 'beeps' additional drag race beeps */
+void
+ao_lco_drag_add_beeps(uint8_t beeps)
+{
+       PRINTD("beep %d\n", beeps);
+       if (ao_lco_drag_beep_count == 0)
+               ao_lco_drag_beep_time = ao_time();
+       ao_lco_drag_beep_count += beeps;
+       ao_wakeup(&ao_lco_drag_beep_count);
+}
+
+/* Toggle current pad in drag set */
+void
+ao_lco_toggle_drag(void)
+{
+       if (ao_lco_drag_race && ao_lco_pad != AO_LCO_PAD_VOLTAGE) {
+               ao_lco_selected[ao_lco_box] ^= (1 << (ao_lco_pad - 1));
+               PRINTD("Toggle box %d pad %d (pads now %x) to drag race\n",
+                      ao_lco_pad, ao_lco_box, ao_lco_selected[ao_lco_box]);
+               ao_lco_drag_add_beeps(ao_lco_pad);
+       }
+}
+
+/* Check whether it's time to change the beeper status, then either
+ * turn it on or off as necessary and bump the remaining beep counts
+ */
+
+uint16_t
+ao_lco_drag_beep_check(uint16_t now, uint16_t delay)
+{
+       PRINTD("beep check count %d delta %d\n",
+              ao_lco_drag_beep_count,
+              (int16_t) (now - ao_lco_drag_beep_time));
+       if (ao_lco_drag_beep_count) {
+               if ((int16_t) (now - ao_lco_drag_beep_time) >= 0) {
+                       if (ao_lco_drag_beep_on) {
+                               ao_beep(0);
+                               PRINTD("beep stop\n");
+                               ao_lco_drag_beep_on = 0;
+                               if (ao_lco_drag_beep_count) {
+                                       --ao_lco_drag_beep_count;
+                                       if (ao_lco_drag_beep_count)
+                                               ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME;
+                               }
+                       } else {
+                               ao_beep(AO_BEEP_HIGH);
+                               PRINTD("beep start\n");
+                               ao_lco_drag_beep_on = 1;
+                               ao_lco_drag_beep_time = now + AO_LCO_DRAG_BEEP_TIME;
+                       }
+               }
+       }
+
+       if (ao_lco_drag_beep_count) {
+               uint16_t beep_delay = 0;
+
+               if (ao_lco_drag_beep_time > now)
+                       beep_delay = ao_lco_drag_beep_time - now;
+
+               if (delay > beep_delay)
+                       delay = beep_delay;
+       }
+       return delay;
+}
+
+void
+ao_lco_drag_enable(void)
+{
+       if (!ao_lco_drag_race) {
+               PRINTD("Drag enable\n");
+               ao_lco_drag_race = 1;
+               memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
+#ifdef AO_LED_DRAG
+               ao_led_on(AO_LED_DRAG);
+#endif
+               ao_lco_drag_add_beeps(5);
+               ao_lco_show();
+       }
+}
+
+void
+ao_lco_drag_disable(void)
+{
+       if (ao_lco_drag_race) {
+               PRINTD("Drag disable\n");
+               ao_lco_drag_race = 0;
+#ifdef AO_LED_DRAG
+               ao_led_off(AO_LED_DRAG);
+#endif
+               memset(ao_lco_selected, 0, sizeof (ao_lco_selected));
+               ao_lco_drag_add_beeps(2);
+               ao_lco_show();
+       }
+}
+
+/* add a beep if it's time to warn the user that drag race mode is
+ * active
+ */
+
+uint16_t
+ao_lco_drag_warn_check(uint16_t now, uint16_t delay)
+{
+       if (ao_lco_drag_race) {
+               uint16_t        warn_delay;
+
+               if ((int16_t) (now - ao_lco_drag_warn_time) >= 0) {
+                       ao_lco_drag_add_beeps(1);
+                       ao_lco_drag_warn_time = now + AO_LCO_DRAG_WARN_TIME;
+               }
+               warn_delay = ao_lco_drag_warn_time - now;
+               if (delay > warn_delay)
+                       delay = warn_delay;
+       }
+       return delay;
+}
+#endif /* AO_LCO_DRAG */
+
+/* task function for beeping while arm is active */
+void
+ao_lco_arm_warn(void)
+{
+       for (;;) {
+               while (!ao_lco_armed) {
+#ifdef AO_LED_FIRE
+                       ao_led_off(AO_LED_FIRE);
+#endif
+                       ao_sleep(&ao_lco_armed);
+               }
+#ifdef AO_LED_FIRE
+               ao_led_on(AO_LED_FIRE);
+#endif
+               ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+               ao_delay(AO_MS_TO_TICKS(200));
+       }
+}
index 8de21fb6702075e25317dfb891e50223fa517122..dba9a76aedcc344bc0b819f38405d86259690b34 100644 (file)
 #include <ao_lco_func.h>
 #include <ao_radio_cmac.h>
 
+#ifndef HAS_STATIC_TEST
+#define HAS_STATIC_TEST        1
+#endif
+
 static __pdata uint16_t        lco_box;
 static __pdata uint8_t lco_channels;
 static __pdata uint16_t        tick_offset;
@@ -150,6 +154,7 @@ lco_fire_cmd(void) __reentrant
        }
 }
 
+#if HAS_STATIC_TEST
 static void
 lco_static_cmd(void) __reentrant
 {
@@ -182,6 +187,7 @@ lco_static_cmd(void) __reentrant
                ao_delay(AO_MS_TO_TICKS(100));
        }
 }
+#endif
 
 static void
 lco_arm_cmd(void) __reentrant
@@ -208,18 +214,21 @@ lco_ignite_cmd(void) __reentrant
 }
 
 
+#if HAS_STATIC_TEST
 static void
 lco_endstatic_cmd(void) __reentrant
 {
        lco_ignite(AO_PAD_ENDSTATIC);
 }
+#endif
 
 static __code struct ao_cmds ao_lco_cmds[] = {
        { lco_report_cmd,       "l <box> <channel>\0Get remote status" },
        { lco_fire_cmd,         "F <box> <channel> <secs>\0Fire remote igniters" },
-       { lco_fire_cmd,         "F <box> <channel> <secs>\0Fire remote igniters" },
+#if HAS_STATIC_TEST
        { lco_static_cmd,       "S <box> <channel> <secs>\0Initiate static test" },
        { lco_endstatic_cmd,    "D\0End static test (and download someday)" },
+#endif
        { lco_arm_cmd,          "a <box> <channel>\0Arm remote igniter" },
        { lco_ignite_cmd,       "i <box> <channel>\0Pulse remote igniter" },
        { 0, NULL },
index e2f867454c5183e1f63cb30d212681093110c438..6f2d81ffbfbbef2233a0642dc4c597644056e453 100644 (file)
 #include <ao_lco_func.h>
 #include <ao_radio_cmac.h>
 
-#define DEBUG  1
-
-#if DEBUG
-static uint8_t ao_lco_debug;
-#define DEBUG_EVENT    1
-#define DEBUG_STATUS   2
-#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
-#else
-#define PRINTD(l,...)
-#endif
-
-#define AO_LCO_VALID_LAST      1
-#define AO_LCO_VALID_EVER      2
-
 static uint8_t ao_lco_suspended;
-static uint8_t ao_lco_valid;
-static uint8_t ao_lco_channels;
-static uint16_t        ao_lco_tick_offset;
-
-/* UI values */
-static uint8_t ao_lco_armed;
-static uint8_t ao_lco_firing;
-static uint8_t ao_lco_box;
-
-static struct ao_pad_query     ao_pad_query;
-
-/* TeleFireTwo boxes have a single pad */
-#define ao_lco_pad     0
-
-static void
-ao_lco_set_box(int box)
-{
-       ao_lco_box = ao_config.pad_box + box;
-       ao_lco_valid = 0;
-       ao_lco_armed = 0;
-       ao_wakeup(&ao_lco_armed);
-}
-
-static void
-ao_lco_set_armed(int armed)
-{
-       uint8_t bit = (1 << ao_lco_pad);
-
-       if (armed) {
-               ao_lco_armed = bit;
-       } else {
-               ao_lco_armed = 0;
-       }
-       PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_armed 0x%x\n",
-              ao_lco_pad, bit, armed, ao_lco_armed);
-       ao_wakeup(&ao_lco_armed);
-}
 
 static void
 ao_lco_suspend(void)
 {
        if (!ao_lco_suspended) {
-               PRINTD(DEBUG_EVENT, "suspend\n");
+               PRINTD("suspend\n");
                ao_lco_suspended = 1;
                ao_lco_armed = 0;
                ao_wakeup(&ao_pad_query);
@@ -96,6 +45,23 @@ ao_lco_wakeup(void)
        }
 }
 
+void
+ao_lco_show_pad(uint8_t pad)
+{
+       (void) pad;
+}
+
+void
+ao_lco_show_box(uint16_t box)
+{
+       (void) box;
+}
+
+void
+ao_lco_show(void)
+{
+}
+
 static void
 ao_lco_input(void)
 {
@@ -113,23 +79,21 @@ ao_lco_input(void)
                        ao_event_get(&event);
                }
                ao_lco_wakeup();
-               PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
+               PRINTD("event type %d unit %d value %d\n",
                       event.type, event.unit, event.value);
                switch (event.type) {
                case AO_EVENT_BUTTON:
                        switch (event.unit) {
                        case AO_BUTTON_BOX:
                                ao_lco_set_box(event.value);
+                               ao_lco_set_armed(0);
                                break;
                        case AO_BUTTON_ARM:
                                ao_lco_set_armed(event.value);
                                break;
                        case AO_BUTTON_FIRE:
-                               if (ao_lco_armed) {
-                                       ao_lco_firing = event.value;
-                                       PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
-                                       ao_wakeup(&ao_lco_armed);
-                               }
+                               if (ao_lco_armed)
+                                       ao_lco_set_firing(event.value);
                                break;
                        }
                        break;
@@ -137,140 +101,14 @@ ao_lco_input(void)
        }
 }
 
-static AO_LED_TYPE     continuity_led[AO_LED_CONTINUITY_NUM] = {
-#ifdef AO_LED_CONTINUITY_0
-       AO_LED_CONTINUITY_0,
-#endif
-#ifdef AO_LED_CONTINUITY_1
-       AO_LED_CONTINUITY_1,
-#endif
-#ifdef AO_LED_CONTINUITY_2
-       AO_LED_CONTINUITY_2,
-#endif
-#ifdef AO_LED_CONTINUITY_3
-       AO_LED_CONTINUITY_3,
-#endif
-#ifdef AO_LED_CONTINUITY_4
-       AO_LED_CONTINUITY_4,
-#endif
-#ifdef AO_LED_CONTINUITY_5
-       AO_LED_CONTINUITY_5,
-#endif
-#ifdef AO_LED_CONTINUITY_6
-       AO_LED_CONTINUITY_6,
-#endif
-#ifdef AO_LED_CONTINUITY_7
-       AO_LED_CONTINUITY_7,
-#endif
-};
-
-static uint8_t
-ao_lco_get_channels(void)
-{
-       int8_t                  r;
-
-       r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
-       if (r == AO_RADIO_CMAC_OK) {
-               ao_lco_channels = ao_pad_query.channels;
-               ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
-       } else
-               ao_lco_valid &= ~AO_LCO_VALID_LAST;
-       PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset);
-       ao_wakeup(&ao_pad_query);
-       return ao_lco_valid;
-}
-
-static void
-ao_lco_igniter_status(void)
-{
-       uint8_t         c;
-       uint8_t         t = 0;
-
-       for (;;) {
-               uint8_t all_status;
-               ao_sleep(&ao_pad_query);
-               while (ao_lco_suspended) {
-                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM);
-                       for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
-                               ao_led_off(continuity_led[c]);
-                       ao_sleep(&ao_lco_suspended);
-               }
-               PRINTD(DEBUG_STATUS, "RSSI %d VALID %d channels %d arm_status %d\n",
-                      ao_radio_cmac_rssi, ao_lco_valid,
-                      ao_lco_channels, ao_pad_query.arm_status);
-               if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
-                       ao_led_on(AO_LED_RED);
-                       ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
-                       memset(&ao_pad_query, '\0', sizeof (ao_pad_query));
-               } else if (ao_radio_cmac_rssi < -90) {
-                       ao_led_on(AO_LED_AMBER);
-                       ao_led_off(AO_LED_RED|AO_LED_GREEN);
-               } else {
-                       ao_led_on(AO_LED_GREEN);
-                       ao_led_off(AO_LED_RED|AO_LED_AMBER);
-               }
-               if (ao_pad_query.arm_status)
-                       ao_led_on(AO_LED_REMOTE_ARM);
-               else
-                       ao_led_off(AO_LED_REMOTE_ARM);
-
-               all_status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
-               for (c = 0; c < 8; c++) {
-                       if (ao_pad_query.channels & (1 << c)) {
-                               uint8_t status = ao_pad_query.igniter_status[c];
-                               if (status > all_status)
-                                       all_status = status;
-                               PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
-                       }
-               }
-               for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
-                       uint8_t on = 0;
-                       if (c == (ao_lco_box - ao_config.pad_box) % AO_LED_CONTINUITY_NUM) {
-                               switch (all_status) {
-                               case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN:
-                                       on = 1;
-                                       break;
-                               case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED:
-                               case AO_PAD_IGNITER_STATUS_UNKNOWN:
-                                       on = t & 1;
-                               }
-                       }
-                       if (on)
-                               ao_led_on(continuity_led[c]);
-                       else
-                               ao_led_off(continuity_led[c]);
-               }
-               t = 1-t;
-       }
-}
-
-static void
-ao_lco_arm_warn(void)
-{
-       int     i;
-       for (;;) {
-               while (ao_lco_suspended)
-                       ao_sleep(&ao_lco_suspended);
-               while (!ao_lco_armed)
-                       ao_sleep(&ao_lco_armed);
-               for (i = 0; i < ao_lco_armed; i++) {
-                       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100));
-                       ao_delay(AO_MS_TO_TICKS(100));
-               }
-               ao_delay(AO_MS_TO_TICKS(300));
-       }
-}
-
 static struct ao_task ao_lco_input_task;
 static struct ao_task ao_lco_monitor_task;
 static struct ao_task ao_lco_arm_warn_task;
 static struct ao_task ao_lco_igniter_status_task;
 
 static void
-ao_lco_monitor(void)
+ao_lco_main(void)
 {
-       uint16_t                delay;
-
        ao_config_get();
        ao_lco_set_box(ao_button_get(AO_BUTTON_BOX));
        ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
@@ -279,33 +117,7 @@ ao_lco_monitor(void)
        ao_led_on(~0);
        ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
        ao_led_off(~0);
-       for (;;) {
-               while (ao_lco_suspended)
-                       ao_sleep(&ao_lco_suspended);
-
-               PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
-                      ao_lco_armed, ao_lco_firing);
-
-               if (ao_lco_armed && ao_lco_firing) {
-                       ao_lco_ignite(AO_PAD_FIRE);
-               } else {
-                       ao_lco_get_channels();
-                       if (ao_lco_armed) {
-                               PRINTD(DEBUG_STATUS, "Arming pads %x\n",
-                                      ao_lco_armed);
-                               if (ao_lco_valid & AO_LCO_VALID_EVER) {
-                                       ao_lco_arm(ao_lco_box, ao_lco_armed, ao_lco_tick_offset);
-                                       ao_delay(AO_MS_TO_TICKS(10));
-                               }
-                       }
-               }
-               if (ao_lco_armed && ao_lco_firing)
-                       delay = AO_MS_TO_TICKS(100);
-               else {
-                       delay = AO_SEC_TO_TICKS(1);
-               }
-               ao_sleep_for(&ao_lco_armed, delay);
-       }
+       ao_lco_monitor();
 }
 
 #if DEBUG
@@ -326,7 +138,7 @@ __code struct ao_cmds ao_lco_cmds[] = {
 void
 ao_lco_init(void)
 {
-       ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor");
+       ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
 #if DEBUG
        ao_cmd_register(&ao_lco_cmds[0]);
 #endif
index 16b4ae60eb19e4d8ee23eff06f930a8fc12828a3..c6efc311fd9e8ea2cd29828206f28218dbc0305a 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <ao.h>
+#include <ao_exti.h>
 #include <ao_pad.h>
 #include <ao_74hc165.h>
 #include <ao_radio_cmac.h>
@@ -69,10 +70,20 @@ ao_strobe(uint8_t v)
 #endif
 }
 
+#ifdef AO_PAD_PORT_0
+#define pins_pad(pad)  (*((AO_PAD_ ## pad ## _PORT) == AO_PAD_PORT_0 ? (&pins0) : (&pins1)))
+#else
+#define pins_pad(pad)  pins0
+#define AO_PAD_PORT_0 AO_PAD_PORT
+#endif
+
 static void
 ao_pad_run(void)
 {
-       AO_PORT_TYPE    pins;
+       AO_PORT_TYPE    pins0;
+#ifdef AO_PAD_PORT_1
+       AO_PORT_TYPE    pins1;
+#endif
 
        for (;;) {
                while (!ao_pad_ignite)
@@ -80,58 +91,116 @@ ao_pad_run(void)
                /*
                 * Actually set the pad bits
                 */
-               pins = 0;
+               pins0 = 0;
+#ifdef AO_PAD_PORT_1
+               pins1 = 0;
+#endif
 #if AO_PAD_NUM > 0
                if (ao_pad_ignite & (1 << 0))
-                       pins |= (1 << AO_PAD_PIN_0);
+                       pins_pad(0) |= (1 << AO_PAD_PIN_0);
 #endif
 #if AO_PAD_NUM > 1
                if (ao_pad_ignite & (1 << 1))
-                       pins |= (1 << AO_PAD_PIN_1);
+                       pins_pad(1) |= (1 << AO_PAD_PIN_1);
 #endif
 #if AO_PAD_NUM > 2
                if (ao_pad_ignite & (1 << 2))
-                       pins |= (1 << AO_PAD_PIN_2);
+                       pins_pad(2) |= (1 << AO_PAD_PIN_2);
 #endif
 #if AO_PAD_NUM > 3
                if (ao_pad_ignite & (1 << 3))
-                       pins |= (1 << AO_PAD_PIN_3);
+                       pins_pad(3) |= (1 << AO_PAD_PIN_3);
+#endif
+#if AO_PAD_NUM > 4
+               if (ao_pad_ignite & (1 << 4))
+                       pins_pad(4) |= (1 << AO_PAD_PIN_4);
+#endif
+#if AO_PAD_NUM > 5
+               if (ao_pad_ignite & (1 << 5))
+                       pins_pad(5) |= (1 << AO_PAD_PIN_5);
+#endif
+#if AO_PAD_NUM > 6
+               if (ao_pad_ignite & (1 << 6))
+                       pins_pad(6) |= (1 << AO_PAD_PIN_6);
+#endif
+#if AO_PAD_NUM > 7
+               if (ao_pad_ignite & (1 << 7))
+                       pins_pad(7) |= (1 << AO_PAD_PIN_7);
+#endif
+#ifdef AO_PAD_PORT_1
+               PRINTD("ignite pins 0x%x 0x%x\n", pins0, pins1);
+               ao_gpio_set_bits(AO_PAD_PORT_0, pins0);
+               ao_gpio_set_bits(AO_PAD_PORT_1, pins1);
+#else
+               PRINTD("ignite pins 0x%x\n", pins0);
+               ao_gpio_set_bits(AO_PAD_PORT_0, pins0);
 #endif
-               PRINTD("ignite pins 0x%x\n", pins);
-               ao_gpio_set_bits(AO_PAD_PORT, pins);
                while (ao_pad_ignite) {
                        ao_pad_ignite = 0;
 
                        ao_delay(AO_PAD_FIRE_TIME);
                }
-               ao_gpio_clr_bits(AO_PAD_PORT, pins);
-               PRINTD("turn off pins 0x%x\n", pins);
+#ifdef AO_PAD_PORT_1
+               ao_gpio_clr_bits(AO_PAD_PORT_0, pins0);
+               ao_gpio_clr_bits(AO_PAD_PORT_1, pins1);
+               PRINTD("turn off pins 0x%x 0x%x\n", pins0, pins1);
+#else
+               ao_gpio_set_bits(AO_PAD_PORT_0, pins0);
+               PRINTD("turn off pins 0x%x\n", pins0);
+#endif
        }
 }
 
 #define AO_PAD_ARM_SIREN_INTERVAL      200
 
-#ifndef AO_PYRO_R_PYRO_SENSE
-#define AO_PYRO_R_PYRO_SENSE   100
-#define AO_PYRO_R_SENSE_GND    27
-#define AO_FIRE_R_POWER_FET    100
-#define AO_FIRE_R_FET_SENSE    100
-#define AO_FIRE_R_SENSE_GND    27
-#endif
+/* Resistor values needed for various voltage test ratios:
+ *
+ *     Net names involved:
+ *
+ *     V_BATT          Battery power, after the initial power switch
+ *     V_PYRO          Pyro power, after the pyro power switch (and initial power switch)
+ *     PYRO_SENSE      ADC input to sense V_PYRO voltage
+ *     BATT_SENSE      ADC input to sense V_BATT voltage
+ *     IGNITER         FET output to pad (the other pad lead hooks to V_PYRO)
+ *     IGNITER_SENSE   ADC input to sense igniter voltage
+ *
+ *     AO_PAD_R_V_BATT_BATT_SENSE      Resistor from battery rail to battery sense input
+ *     AO_PAD_R_BATT_SENSE_GND         Resistor from battery sense input to ground
+ *
+ *     AO_PAD_R_V_BATT_V_PYRO          Resistor from battery rail to pyro rail
+ *     AO_PAD_R_V_PYRO_PYRO_SENSE      Resistor from pyro rail to pyro sense input
+ *     AO_PAD_R_PYRO_SENSE_GND         Resistor from pyro sense input to ground
+ *
+ *     AO_PAD_R_V_PYRO_IGNITER         Optional resistors from pyro rail to FET igniter output
+ *     AO_PAD_R_IGNITER_IGNITER_SENSE  Resistors from FET igniter output to igniter sense ADC inputs
+ *     AO_PAD_R_IGNITER_SENSE_GND      Resistors from igniter sense ADC inputs to ground
+ */
+
+int16_t
+ao_pad_decivolt(int16_t adc, int16_t r_plus, int16_t r_minus)
+{
+       int32_t mul = (int32_t) AO_ADC_REFERENCE_DV * (r_plus + r_minus);
+       int32_t div = (int32_t) AO_ADC_MAX * r_minus;
+       return ((int32_t) adc * mul + mul/2) / div;
+}
 
 static void
 ao_pad_monitor(void)
 {
        uint8_t                 c;
        uint8_t                 sample;
-       __pdata uint8_t         prev = 0, cur = 0;
+       __pdata AO_LED_TYPE     prev = 0, cur = 0;
        __pdata uint8_t         beeping = 0;
        __xdata volatile struct ao_data *packet;
        __pdata uint16_t        arm_beep_time = 0;
 
        sample = ao_data_head;
+       ao_led_set(LEDS_AVAILABLE);
+       ao_delay(AO_MS_TO_TICKS(1000));
+       ao_led_set(0);
        for (;;) {
                __pdata int16_t                 pyro;
+
                ao_arch_critical(
                        while (sample == ao_data_head)
                                ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
@@ -141,28 +210,18 @@ ao_pad_monitor(void)
                packet = &ao_data_ring[sample];
                sample = ao_data_ring_next(sample);
 
-               pyro = packet->adc.pyro;
-
-#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \
-                                           (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX)))
-
+               /* Reply battery voltage */
+               query.battery = ao_pad_decivolt(packet->adc.batt, AO_PAD_R_V_BATT_BATT_SENSE, AO_PAD_R_BATT_SENSE_GND);
 
-#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \
-                                           (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))
+               /* Current pyro voltage */
+               pyro = ao_pad_decivolt(packet->adc.pyro,
+                                      AO_PAD_R_V_PYRO_PYRO_SENSE,
+                                      AO_PAD_R_PYRO_SENSE_GND);
 
-               /* convert ADC value to voltage in tenths, then add .2 for the diode drop */
-               query.battery = (packet->adc.batt + 96) / 192 + 2;
                cur = 0;
-               if (pyro > VOLTS_TO_PYRO(10)) {
+               if (pyro > query.battery * 7 / 8) {
                        query.arm_status = AO_PAD_ARM_STATUS_ARMED;
                        cur |= AO_LED_ARMED;
-#if AO_FIRE_R_POWER_FET
-               } else if (pyro > VOLTS_TO_PYRO(5)) {
-                       if ((ao_time() % 100) < 50)
-                               cur |= AO_LED_ARMED;
-                       query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
-                       arm_beep_time = 0;
-#endif
                } else {
                        query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
                        arm_beep_time = 0;
@@ -175,54 +234,50 @@ ao_pad_monitor(void)
                        cur |= AO_LED_GREEN;
 
                for (c = 0; c < AO_PAD_NUM; c++) {
-                       int16_t         sense = packet->adc.sense[c];
+                       int16_t         sense = ao_pad_decivolt(packet->adc.sense[c],
+                                                               AO_PAD_R_IGNITER_IGNITER_SENSE,
+                                                               AO_PAD_R_IGNITER_SENSE_GND);
                        uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN;
 
                        /*
-                        *      pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20
-                        *      v_pyro = pyro * 127 / 27
+                        *      Here's the resistor stack on each
+                        *      igniter channel. Note that
+                        *      AO_PAD_R_V_PYRO_IGNITER is optional
                         *
-                        *              v_pyro \
-                        *      100k            igniter
-                        *              output /
-                        *      100k           \
-                        *              sense   relay
-                        *      27k            /
-                        *              gnd ---
+                        *                                      v_pyro \
+                        *      AO_PAD_R_V_PYRO_IGNITER                 igniter
+                        *                                      output /
+                        *      AO_PAD_R_IGNITER_IGNITER_SENSE         \
+                        *                                      sense   relay
+                        *      AO_PAD_R_IGNITER_SENSE_GND             /
+                        *                                      gnd ---
                         *
-                        *              v_pyro \
-                        *      200k            igniter
-                        *              output /
-                        *      200k           \
-                        *              sense   relay
-                        *      22k            /
-                        *              gnd ---
-                        *
-                        *      If the relay is closed, then sense will be 0
-                        *      If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
-                        *      If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
                         */
 
-#if AO_FIRE_R_POWER_FET
+#ifdef AO_PAD_R_V_PYRO_IGNITER
                        if (sense <= pyro / 8) {
+                               /* close to zero → relay is closed */
                                status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
                                if ((ao_time() % 100) < 50)
                                        cur |= AO_LED_CONTINUITY(c);
-                       } else
-                       if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
-                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
-                       else if (pyro / 8 * 7 <= sense) {
-                               status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
-                               cur |= AO_LED_CONTINUITY(c);
-                       }
-#else
-                       if (sense >= pyro / 8 * 5) {
-                               status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
-                               cur |= AO_LED_CONTINUITY(c);
-                       } else {
-                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
                        }
+                       else
 #endif
+                       {
+                               if (sense >= (pyro * 7) / 8) {
+
+                                       /* sense close to pyro voltage; igniter is good
+                                        */
+                                       status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+                                       cur |= AO_LED_CONTINUITY(c);
+                               } else {
+
+                                       /* relay not shorted (if we can tell),
+                                        * and igniter not obviously present
+                                        */
+                                       status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+                               }
+                       }
                        query.igniter_status[c] = status;
                }
                if (cur != prev) {
@@ -284,6 +339,23 @@ ao_pad_read_box(void)
 }
 #endif
 
+#ifdef AO_PAD_SELECTOR_PORT
+static int ao_pad_read_box(void) {
+       AO_PORT_TYPE    value = ao_gpio_get_all(AO_PAD_SELECTOR_PORT);
+       unsigned        pin;
+       int             select = 1;
+
+       for (pin = 0; pin < sizeof (AO_PORT_TYPE) * 8; pin++) {
+               if (AO_PAD_SELECTOR_PINS & (1 << pin)) {
+                       if ((value & (1 << pin)) == 0)
+                               return select;
+                       select++;
+               }
+       }
+       return ao_config.pad_box;
+}
+#else
+
 #if HAS_FIXED_PAD_BOX
 #define ao_pad_read_box()      ao_config.pad_box
 #endif
@@ -292,6 +364,8 @@ ao_pad_read_box(void)
 #define ao_pad_read_box()      PAD_BOX
 #endif
 
+#endif
+
 static void
 ao_pad(void)
 {
@@ -299,7 +373,6 @@ ao_pad(void)
        int8_t  ret;
 
        ao_pad_box = 0;
-       ao_led_set(0);
        for (;;) {
                FLUSHD();
                while (ao_pad_disabled)
@@ -497,20 +570,51 @@ __code struct ao_cmds ao_pad_cmds[] = {
        { 0, NULL }
 };
 
+#ifndef AO_PAD_PORT_1
+#define AO_PAD_0_PORT  AO_PAD_PORT
+#define AO_PAD_1_PORT  AO_PAD_PORT
+#define AO_PAD_2_PORT  AO_PAD_PORT
+#define AO_PAD_3_PORT  AO_PAD_PORT
+#define AO_PAD_4_PORT  AO_PAD_PORT
+#define AO_PAD_5_PORT  AO_PAD_PORT
+#define AO_PAD_6_PORT  AO_PAD_PORT
+#define AO_PAD_7_PORT  AO_PAD_PORT
+#endif
+
 void
 ao_pad_init(void)
 {
+#ifdef AO_PAD_SELECTOR_PORT
+       unsigned pin;
+
+       for (pin = 0; pin < sizeof (AO_PORT_TYPE) * 8; pin++) {
+               if (AO_PAD_SELECTOR_PINS & (1 << pin))
+                       ao_enable_input(AO_PAD_SELECTOR_PORT, pin, AO_EXTI_MODE_PULL_UP);
+       }
+#endif
 #if AO_PAD_NUM > 0
-       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0);
+       ao_enable_output(AO_PAD_0_PORT, AO_PAD_PIN_0, AO_PAD_0, 0);
 #endif
 #if AO_PAD_NUM > 1
-       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0);
+       ao_enable_output(AO_PAD_1_PORT, AO_PAD_PIN_1, AO_PAD_1, 0);
 #endif
 #if AO_PAD_NUM > 2
-       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0);
+       ao_enable_output(AO_PAD_2_PORT, AO_PAD_PIN_2, AO_PAD_2, 0);
 #endif
 #if AO_PAD_NUM > 3
-       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0);
+       ao_enable_output(AO_PAD_3_PORT, AO_PAD_PIN_3, AO_PAD_3, 0);
+#endif
+#if AO_PAD_NUM > 4
+       ao_enable_output(AO_PAD_4_PORT, AO_PAD_PIN_4, AO_PAD_4, 0);
+#endif
+#if AO_PAD_NUM > 5
+       ao_enable_output(AO_PAD_5_PORT, AO_PAD_PIN_5, AO_PAD_5, 0);
+#endif
+#if AO_PAD_NUM > 5
+       ao_enable_output(AO_PAD_6_PORT, AO_PAD_PIN_6, AO_PAD_6, 0);
+#endif
+#if AO_PAD_NUM > 7
+       ao_enable_output(AO_PAD_7_PORT, AO_PAD_PIN_7, AO_PAD_7, 0);
 #endif
 #ifdef AO_STROBE
        ao_enable_output(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, 0);
index deecfb79422b9c2980507a0a00e9eb3344b64842..250e035fc3171f167c438da9ef92ba35e8668cd5 100644 (file)
 #include <ao_event.h>
 
 __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
+#ifndef AO_QUADRATURE_SINGLE_CODE
+static int8_t ao_quadrature_step[AO_QUADRATURE_COUNT];
+#endif
+
 static uint8_t  ao_quadrature_state[AO_QUADRATURE_COUNT];
 
 struct ao_debounce {
@@ -39,20 +43,25 @@ static struct ao_debounce ao_debounce_state[AO_QUADRATURE_COUNT][2];
 #define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN
 #define isr(q)  ao_quadrature_isr_ ## q
 
-#define DEBOUNCE       10
+#ifndef AO_QUADRATURE_DEBOUNCE
+#error must define AO_QUADRATURE_DEBOUNCE
+#endif
 
 static uint8_t
 ao_debounce(uint8_t cur, struct ao_debounce *debounce)
 {
-       if (cur == debounce->state)
-               debounce->count = 0;
-       else {
-               if (++debounce->count == DEBOUNCE) {
-                       debounce->state = cur;
-                       debounce->count = 0;
-               }
+#if AO_QUADRATURE_DEBOUNCE > 0
+       if (debounce->count > 0) {
+               debounce->count--;
+       } else if (cur != debounce->state) {
+               debounce->state = cur;
+               debounce->count = AO_QUADRATURE_DEBOUNCE;
        }
        return debounce->state;
+#else
+       (void) debounce;
+       return cur;
+#endif
 }
 
 static uint16_t
@@ -70,8 +79,21 @@ ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b, struct a
 #define _ao_quadrature_get(q)  ao_quadrature_read(port(q), bita(q), bitb(q), ao_debounce_state[q])
 
 static void
-_ao_quadrature_queue(uint8_t q, int8_t step)
+_ao_quadrature_step(uint8_t q, int8_t step)
 {
+#ifndef AO_QUADRATURE_SINGLE_CODE
+       ao_quadrature_step[q] += step;
+       if (ao_quadrature_state[q] != 0)
+               return;
+       if (ao_quadrature_step[q] >= 4) {
+               ao_quadrature_step[q] = 0;
+               step = 1;
+       } else if (ao_quadrature_step[q] <= -4) {
+               ao_quadrature_step[q] = 0;
+               step = -1;
+       } else
+               return;
+#endif
        ao_quadrature_count[q] += step;
 #if AO_EVENT
        ao_event_put_isr(AO_EVENT_QUADRATURE, q, step);
@@ -79,17 +101,29 @@ _ao_quadrature_queue(uint8_t q, int8_t step)
        ao_wakeup(&ao_quadrature_count[q]);
 }
 
+static const struct {
+       uint8_t prev, next;
+} ao_quadrature_steps[4] = {
+       [0] { .prev = 2, .next = 1 },
+       [1] { .prev = 0, .next = 3 },
+       [3] { .prev = 1, .next = 2 },
+       [2] { .prev = 3, .next = 0 },
+};
+
 static void
-_ao_quadrature_set(uint8_t q, uint8_t new) {
-       uint8_t old = ao_quadrature_state[q];
-
-       if (old != new && new == 0) {
-               if (old & 2)
-                       _ao_quadrature_queue(q, 1);
-               else if (old & 1)
-                       _ao_quadrature_queue(q, -1);
-       }
+_ao_quadrature_set(uint8_t q, uint8_t new)
+{
+       uint8_t old;
+
+       ao_arch_block_interrupts();
+       old = ao_quadrature_state[q];
        ao_quadrature_state[q] = new;
+       ao_arch_release_interrupts();
+
+       if (new == ao_quadrature_steps[old].next)
+               _ao_quadrature_step(q, 1);
+       else if (new == ao_quadrature_steps[old].prev)
+               _ao_quadrature_step(q, -1);
 }
 
 static void
@@ -103,6 +137,14 @@ ao_quadrature_isr(void)
 #endif
 }
 
+static void
+_ao_quadrature_start_one(uint8_t q, uint8_t new)
+{
+       ao_arch_block_interrupts();
+       ao_quadrature_state[q] = new;
+       ao_arch_release_interrupts();
+}
+
 int32_t
 ao_quadrature_poll(uint8_t q)
 {
@@ -124,21 +166,32 @@ ao_quadrature_test(void)
        uint8_t q;
        int32_t c;
        uint8_t s;
+#ifndef AO_QUADRATURE_SINGLE_CODE
+       int8_t t = 0;
+#endif
 
        ao_cmd_decimal();
        q = ao_cmd_lex_i;
-       if (q >= AO_QUADRATURE_COUNT) {
+       if (q >= AO_QUADRATURE_COUNT)
                ao_cmd_status = ao_cmd_syntax_error;
+       if (ao_cmd_status != ao_cmd_success)
                return;
-       }
 
        c = -10000;
        s = 0;
        while (ao_quadrature_count[q] != 10) {
                if (ao_quadrature_count[q] != c ||
-                   ao_quadrature_state[q] != s) {
+#ifndef AO_QUADRATURE_SINGLE_CODE
+                   ao_quadrature_step[q] != t ||
+#endif
+                   ao_quadrature_state[q] != s)
+               {
                        c = ao_quadrature_count[q];
                        s = ao_quadrature_state[q];
+#ifndef AO_QUADRATURE_SINGLE_CODE
+                       t = ao_quadrature_step[q];
+                       printf("step %3d ", t);
+#endif
                        printf ("count %3d state %2x\n", c, s);
                        flush();
                }
@@ -160,9 +213,10 @@ static const struct ao_cmds ao_quadrature_cmds[] = {
        { 0, NULL }
 };
 
-#define init(q) do {                                   \
-               ao_enable_input(port(q), bita(q), 0);   \
-               ao_enable_input(port(q), bitb(q), 0);   \
+#define init(q) do {                                                   \
+               ao_enable_input(port(q), bita(q), 0);                   \
+               ao_enable_input(port(q), bitb(q), 0);                   \
+               _ao_quadrature_start_one(q, _ao_quadrature_get(q));     \
        } while (0)
 
 void
diff --git a/src/fox1ihu/.gitignore b/src/fox1ihu/.gitignore
new file mode 100644 (file)
index 0000000..538cf8b
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+fox1ihu-*.elf
diff --git a/src/fox1ihu/Makefile b/src/fox1ihu/Makefile
new file mode 100644 (file)
index 0000000..e3226a2
--- /dev/null
@@ -0,0 +1,89 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_watchdog.h \
+       ao_storage.h \
+       ao_task.h \
+       stm32l.h \
+       ao_sdcard.h \
+       ao_bufio.h \
+       ao_fat.h \
+       Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#      ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_adc_stm.c \
+       ao_data.c \
+       ao_storage.c \
+       ao_mr25.c \
+       ao_sdcard.c \
+       ao_bufio.c \
+       ao_fat.c \
+       ao_watchdog.c
+
+PRODUCT=Fox1IHU-v2
+PRODUCT_DEF=-DFOX
+IDPRODUCT=0x0024
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=fox1ihu-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_fox1ihu.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/fox1ihu/ao_fox1ihu.c b/src/fox1ihu/ao_fox1ihu.c
new file mode 100644 (file)
index 0000000..2e1a2fd
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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_exti.h>
+#include <ao_watchdog.h>
+#include <ao_storage.h>
+#include <ao_fat.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+       
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED|AO_LED_GREEN|AO_LED_RED_2|AO_LED_GREEN_2);
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_adc_init();
+
+       ao_cmd_init();
+
+       ao_usb_init();
+
+       ao_storage_init();
+
+       ao_watchdog_init();
+
+       ao_fat_init();
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/fox1ihu/ao_pins.h b/src/fox1ihu/ao_pins.h
new file mode 100644 (file)
index 0000000..b5dd728
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+/* 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           1
+#define USE_SERIAL_1_STDIN     0
+#define SERIAL_1_PB6_PB7       0
+#define SERIAL_1_PA9_PA10      1
+
+#define HAS_SERIAL_2           0
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       0
+#define SERIAL_2_PD5_PD6       0
+
+#define HAS_SERIAL_3           0
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     0
+#define SERIAL_3_PC10_PC11     1
+#define SERIAL_3_PD8_PD9       0
+
+#define HAS_EEPROM             0
+#define USE_INTERNAL_FLASH     0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_RADIO              0
+#define HAS_TELEMETRY          0
+
+#define HAS_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   1       /* */
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+#define HAS_STORAGE_DEBUG      1
+
+#define SPI_2_PORT             (&stm_gpiob)
+#define SPI_2_SCK_PIN          13
+#define SPI_2_MISO_PIN         14
+#define SPI_2_MOSI_PIN         15
+
+#define HAS_I2C_1              1
+#define I2C_1_PB6_PB7          1
+#define I2C_1_PB8_PB9          0
+
+#define HAS_I2C_2              1
+#define I2C_2_PB10_PB11                1
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_0_ENABLE      STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0             (&stm_gpioc)
+#define LED_PORT_0_MASK                (0xff)
+#define LED_PORT_0_SHIFT       0
+#define LED_PIN_RED            6
+#define LED_PIN_GREEN          7
+#define LED_PIN_RED_2          8
+#define LED_PIN_GREEN_2                9
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+#define AO_LED_RED_2           (1 << LED_PIN_RED_2)
+#define AO_LED_GREEN_2         (1 << LED_PIN_GREEN_2)
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN | AO_LED_RED_2 | AO_LED_GREEN_2)
+
+#define HAS_GPS                        0
+#define HAS_FLIGHT             0
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           1
+#define HAS_LOG                        0
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+
+struct ao_adc {
+       int16_t                 tx_pa_current;  /* 0 ADC_IN0 */
+       int16_t                 tx_temp;        /* 1 ADC_IN1 */
+       int16_t                 exp4_temp;      /* 2 ADC_IN2 */
+       int16_t                 rx_temp;        /* 3 ADC_IN3 */
+       int16_t                 tx_analog_1;    /* 4 ADC_IN4 */
+       int16_t                 sense_batt;     /* 5 ADC_IN5 */
+       int16_t                 rx_analog_1;    /* 6 ADC_IN6 */
+       int16_t                 rx_rssi;        /* 7 ADC_IN8 */
+       int16_t                 rx_cd;          /* 8 ADC_IN9 */
+       int16_t                 ant_sense_1;    /* 9 ADC_IN10 */
+       int16_t                 ant_sense_2;    /* 10 ADC_IN11 */
+       int16_t                 gyro_x_1;       /* 11 ADC_IN12 */
+       int16_t                 gyro_z_1;       /* 12 ADC_IN13 */
+       int16_t                 gyro_vref_1;    /* 13 ADC_IN24 */
+       int16_t                 gyro_x_2;       /* 14 ADC_IN14 */
+       int16_t                 gyro_z_2;       /* 15 ADC_IN15 */
+       int16_t                 gyro_vref_2;    /* 16 ADC_IN25 */
+};
+
+#define AO_ADC_TX_PA_CURRENT           0
+#define AO_ADC_TX_PA_CURRENT_PORT      (&stm_gpioa)
+#define AO_ADC_TX_PA_CURRENT_PIN       0
+
+#define AO_ADC_TX_TEMP                 1
+#define AO_ADC_TX_TEMP_PORT            (&stm_gpioa)
+#define AO_ADC_TX_TEMP_PIN             1
+
+#define AO_ADC_EXP4_TEMP               2
+#define AO_ADC_EXP4_TEMP_PORT          (&stm_gpioa)
+#define AO_ADC_EXP4_TEMP_PIN           2
+
+#define AO_ADC_RX_TEMP                 3
+#define AO_ADC_RX_TEMP_PORT            (&stm_gpioa)
+#define AO_ADC_RX_TEMP_PIN             3
+
+#define AO_ADC_TX_ANALOG_1             4
+#define AO_ADC_TX_ANALOG_1_PORT                (&stm_gpioa)
+#define AO_ADC_TX_ANALOG_1_PIN         4
+
+#define AO_ADC_SENSE_BATT              5
+#define AO_ADC_SENSE_BATT_PORT         (&stm_gpioa)
+#define AO_ADC_SENSE_BATT_PIN          5
+
+#define AO_ADC_RX_ANALOG_1             6
+#define AO_ADC_RX_ANALOG_1_PORT                (&stm_gpioa)
+#define AO_ADC_RX_ANALOG_1_PIN         6
+
+#define AO_ADC_RX_RSSI                 8
+#define AO_ADC_RX_RSSI_PORT            (&stm_gpiob)
+#define AO_ADC_RX_RSSI_PIN             0
+
+#define AO_ADC_RX_CD                   9
+#define AO_ADC_RX_CD_PORT              (&stm_gpiob)
+#define AO_ADC_RX_CD_PIN               1
+
+#define AO_ADC_ANT_SENSE_1             10
+#define AO_ADC_ANT_SENSE_1_PORT                (&stm_gpioc)
+#define AO_ADC_ANT_SENSE_1_PIN         0
+
+#define AO_ADC_ANT_SENSE_2             11
+#define AO_ADC_ANT_SENSE_2_PORT                (&stm_gpioc)
+#define AO_ADC_ANT_SENSE_2_PIN         1
+
+#define AO_ADC_GYRO_X_1                        12
+#define AO_ADC_GYRO_X_1_PORT           (&stm_gpioc)
+#define AO_ADC_GYRO_X_1_PIN            2
+
+#define AO_ADC_GYRO_Z_1                        13
+#define AO_ADC_GYRO_Z_1_PORT           (&stm_gpioc)
+#define AO_ADC_GYRO_Z_1_PIN            3
+
+#define AO_ADC_GYRO_VREF_1             24
+#define AO_ADC_GYRO_VREF_1_PORT                (&stm_gpioe)
+#define AO_ADC_GYRO_VREF_1_PIN         9
+
+#define AO_ADC_GYRO_X_2                        14
+#define AO_ADC_GYRO_X_2_PORT           (&stm_gpioc)
+#define AO_ADC_GYRO_X_2_PIN            4
+
+#define AO_ADC_GYRO_Z_2                        15
+#define AO_ADC_GYRO_Z_2_PORT           (&stm_gpioc)
+#define AO_ADC_GYRO_Z_2_PIN            5
+
+#define AO_ADC_GYRO_VREF_2             25
+#define AO_ADC_GYRO_VREF_2_PORT                (&stm_gpioe)
+#define AO_ADC_GYRO_VREF_2_PIN         10
+
+#define AO_ADC_TEMP                    16
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOCEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOEEN))
+
+#define AO_NUM_ADC_PIN         (17)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_TX_PA_CURRENT_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_TX_PA_CURRENT_PIN
+#define AO_ADC_PIN1_PORT       AO_ADC_TX_TEMP_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_TX_TEMP_PIN
+#define AO_ADC_PIN2_PORT       AO_ADC_EXP4_TEMP_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_EXP4_TEMP_PIN
+#define AO_ADC_PIN3_PORT       AO_ADC_RX_TEMP_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_RX_TEMP_PIN
+#define AO_ADC_PIN4_PORT       AO_ADC_TX_ANALOG_1_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_TX_ANALOG_1_PIN
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_BATT_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_BATT_PIN
+#define AO_ADC_PIN6_PORT       AO_ADC_RX_ANALOG_1_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_RX_ANALOG_1_PIN
+#define AO_ADC_PIN7_PORT       AO_ADC_RX_RSSI_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_RX_RSSI_PIN
+#define AO_ADC_PIN8_PORT       AO_ADC_RX_CD_PORT
+#define AO_ADC_PIN8_PIN                AO_ADC_RX_CD_PIN
+#define AO_ADC_PIN9_PORT       AO_ADC_ANT_SENSE_1_PORT
+#define AO_ADC_PIN9_PIN                AO_ADC_ANT_SENSE_1_PIN
+#define AO_ADC_PIN10_PORT      AO_ADC_ANT_SENSE_2_PORT
+#define AO_ADC_PIN10_PIN       AO_ADC_ANT_SENSE_2_PIN
+#define AO_ADC_PIN11_PORT      AO_ADC_GYRO_X_1_PORT
+#define AO_ADC_PIN11_PIN       AO_ADC_GYRO_X_1_PIN
+#define AO_ADC_PIN12_PORT      AO_ADC_GYRO_Z_1_PORT
+#define AO_ADC_PIN12_PIN       AO_ADC_GYRO_Z_1_PIN
+#define AO_ADC_PIN13_PORT      AO_ADC_GYRO_VREF_1_PORT
+#define AO_ADC_PIN13_PIN       AO_ADC_GYRO_VREF_1_PIN
+#define AO_ADC_PIN14_PORT      AO_ADC_GYRO_X_2_PORT
+#define AO_ADC_PIN14_PIN       AO_ADC_GYRO_X_2_PIN
+#define AO_ADC_PIN15_PORT      AO_ADC_GYRO_Z_2_PORT
+#define AO_ADC_PIN15_PIN       AO_ADC_GYRO_Z_2_PIN
+#define AO_ADC_PIN16_PORT      AO_ADC_GYRO_VREF_2_PORT
+#define AO_ADC_PIN16_PIN       AO_ADC_GYRO_VREF_2_PIN
+
+#define AO_NUM_ADC             (AO_NUM_ADC_PIN + 1)    /* Add internal temp sensor */
+
+#define AO_ADC_SQ1             AO_ADC_TX_PA_CURRENT
+#define AO_ADC_SQ1_NAME                "tx_pa_current"
+#define AO_ADC_SQ2             AO_ADC_TX_TEMP
+#define AO_ADC_SQ2_NAME                "tx_temp"
+#define AO_ADC_SQ3             AO_ADC_EXP4_TEMP
+#define AO_ADC_SQ3_NAME                "expr_temp"
+#define AO_ADC_SQ4             AO_ADC_RX_TEMP
+#define AO_ADC_SQ4_NAME                "rx_temp"
+#define AO_ADC_SQ5             AO_ADC_TX_ANALOG_1
+#define AO_ADC_SQ5_NAME                "tx_analog_1"
+#define AO_ADC_SQ6             AO_ADC_SENSE_BATT
+#define AO_ADC_SQ6_NAME                "sense_batt"
+#define AO_ADC_SQ7             AO_ADC_RX_ANALOG_1
+#define AO_ADC_SQ7_NAME                "rx_analog_1"
+#define AO_ADC_SQ8             AO_ADC_RX_RSSI
+#define AO_ADC_SQ8_NAME                "rx_rssi"
+#define AO_ADC_SQ9             AO_ADC_RX_CD
+#define AO_ADC_SQ9_NAME                "rx_cd"
+#define AO_ADC_SQ10            AO_ADC_ANT_SENSE_1
+#define AO_ADC_SQ10_NAME       "ant_sense_1"
+#define AO_ADC_SQ11            AO_ADC_ANT_SENSE_2
+#define AO_ADC_SQ11_NAME       "ant_sense_2"
+#define AO_ADC_SQ12            AO_ADC_GYRO_X_1
+#define AO_ADC_SQ12_NAME       "gyro_x_1"
+#define AO_ADC_SQ13            AO_ADC_GYRO_Z_1
+#define AO_ADC_SQ13_NAME       "gyro_z_1"
+#define AO_ADC_SQ14            AO_ADC_GYRO_VREF_1
+#define AO_ADC_SQ14_NAME       "gyro_vref_1"
+#define AO_ADC_SQ15            AO_ADC_GYRO_X_2
+#define AO_ADC_SQ15_NAME       "gyro_x_2"
+#define AO_ADC_SQ16            AO_ADC_GYRO_Z_2
+#define AO_ADC_SQ16_NAME       "gyro_z_2"
+#define AO_ADC_SQ17            AO_ADC_GYRO_VREF_2
+#define AO_ADC_SQ17_NAME       "gyro_vref_2"
+#define AO_ADC_SQ18            AO_ADC_TEMP
+#define AO_ADC_SQ18_NAME       "temp"
+
+/* Watchdog timer */
+
+#define AO_WATCHDOG_INTERVAL   AO_MS_TO_TICKS(40)
+#define AO_WATCHDOG_PORT       (&stm_gpiod)
+#define AO_WATCHDOG_BIT                3
+
+/* MRAM device */
+
+#define AO_MR25_SPI_CS_PORT    (&stm_gpiod)
+#define AO_MR25_SPI_CS_PIN     0
+#define AO_MR25_SPI_BUS                AO_SPI_2_PB13_PB14_PB15
+
+/* SD card */
+
+#define AO_SDCARD_SPI_CS_PORT  (&stm_gpiod)
+#define AO_SDCARD_SPI_CS_PIN   1
+#define AO_SDCARD_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_SDCARD_SPI_PORT     (&stm_gpiob)
+#define AO_SDCARD_SPI_SCK_PIN  13
+#define AO_SDCARD_SPI_MISO_PIN 14
+#define AO_SDCARD_SPI_MOSI_PIN 15
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/fox1ihu/flash-loader/Makefile b/src/fox1ihu/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..454bc6f
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=fox1ihu
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/fox1ihu/flash-loader/ao_pins.h b/src/fox1ihu/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..19f29b0
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE         8000000
+
+#define AO_WATCHDOG_PORT       (&stm_gpiod)
+#define AO_WATCHDOG_PORT_BIT   (1 << STM_RCC_AHBENR_GPIODEN)
+#define AO_WATCHDOG_BIT                3
+#define AO_WATCHDOG_VALUE      0
+
+#define AO_RADIO_CONTROL_PORT          (&stm_gpioe)
+#define AO_RADIO_CONTROL_PORT_BIT      (1 << STM_RCC_AHBENR_GPIOEEN)
+#define AO_RADIO_CONTROL_BIT           12
+#define AO_RADIO_CONTROL_VALUE         1
+
+#define AO_FLASH_LOADER_INIT do {                                      \
+               stm_rcc.ahbenr |= AO_WATCHDOG_PORT_BIT | AO_RADIO_CONTROL_PORT_BIT; \
+                                                                       \
+               stm_gpio_set(AO_WATCHDOG_PORT, AO_WATCHDOG_BIT, AO_WATCHDOG_VALUE); \
+               stm_moder_set(AO_WATCHDOG_PORT, AO_WATCHDOG_BIT, STM_MODER_OUTPUT); \
+                                                                       \
+               stm_gpio_set(AO_RADIO_CONTROL_PORT, AO_RADIO_CONTROL_BIT, AO_RADIO_CONTROL_VALUE); \
+               stm_moder_set(AO_RADIO_CONTROL_PORT, AO_RADIO_CONTROL_BIT, STM_MODER_OUTPUT); \
+       } while (0)
+
+#define AO_TIMER_HOOK  do {                                            \
+               AO_WATCHDOG_PORT->odr ^= (1 << AO_WATCHDOG_BIT);        \
+       } while (0)
+
+#define HAS_TICK               1
+#include <ao_flash_stm_pins.h>
+
+/* Attached signal, PB8 */
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpiob
+#define AO_BOOT_APPLICATION_PIN                8
+#define AO_BOOT_APPLICATION_VALUE      0
+#define AO_BOOT_APPLICATION_MODE       0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/kernel/ao_flash_readout.c b/src/kernel/ao_flash_readout.c
new file mode 100644 (file)
index 0000000..46b5ba7
--- /dev/null
@@ -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 (file)
index 0000000..5eee53c
--- /dev/null
@@ -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_ */
index cb02c4549ee20564981f8fafa7c2072b1bdd1b65..c2700d20bddb41801bacb0d560291a50aaad4bb0 100644 (file)
@@ -48,7 +48,8 @@
 /* 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_boost_tick;          /* time of most recent boost detect */
+__pdata uint16_t               ao_launch_tick;         /* time of first boost detect */
 __pdata uint16_t               ao_motor_number;        /* number of motors burned so far */
 
 #if HAS_SENSOR_ERRORS
@@ -199,7 +200,7 @@ ao_flight(void)
                                )
                        {
                                ao_flight_state = ao_flight_boost;
-                               ao_boost_tick = ao_sample_tick;
+                               ao_launch_tick = ao_boost_tick = ao_sample_tick;
 
                                /* start logging data */
                                ao_log_start();
@@ -233,7 +234,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
@@ -269,7 +270,7 @@ ao_flight(void)
                         * number of seconds.
                         */
                        if (ao_config.apogee_lockout) {
-                               if ((int16_t) (ao_sample_tick - ao_boost_tick) <
+                               if ((int16_t) (ao_sample_tick - ao_launch_tick) <
                                    AO_SEC_TO_TICKS(ao_config.apogee_lockout))
                                        break;
                        }
@@ -310,7 +311,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;
index 6894fe59815a0fa01edb9b4edba123bc7ecfa2e9..005c7e8459ad0be8a6bf2f909ce64aa7f7cac03b 100644 (file)
@@ -40,6 +40,7 @@ enum ao_flight_state {
 
 extern __pdata enum ao_flight_state    ao_flight_state;
 extern __pdata uint16_t                        ao_boost_tick;
+extern __pdata uint16_t                        ao_launch_tick;
 extern __pdata uint16_t                        ao_motor_number;
 
 #if HAS_IMU || HAS_MMA655X
index ac41085df8166db526d26c0d5a95f5f750360056..e4cc6d4b9f73676fbc93b750ececfad91b2ed332 100644 (file)
@@ -45,7 +45,11 @@ static __pdata ao_k_t                ao_avg_height_scaled;
 __xdata ao_v_t                 ao_avg_height;
 
 __pdata ao_v_t                 ao_error_h;
-#if !HAS_ACCEL
+#if !HAS_ACCEL || AO_FLIGHT_TEST
+#define AO_ERROR_H_SQ_AVG      1
+#endif
+
+#if AO_ERROR_H_SQ_AVG
 __pdata ao_v_t                 ao_error_h_sq_avg;
 #endif
 
@@ -85,7 +89,7 @@ ao_kalman_predict(void)
 static void
 ao_kalman_err_height(void)
 {
-#if !HAS_ACCEL
+#if AO_ERROR_H_SQ_AVG
        ao_v_t  e;
 #endif
        ao_v_t height_distrust;
@@ -95,7 +99,7 @@ ao_kalman_err_height(void)
 
        ao_error_h = ao_sample_height - (ao_v_t) (ao_k_height >> 16);
 
-#if !HAS_ACCEL
+#if AO_ERROR_H_SQ_AVG
        e = ao_error_h;
        if (e < 0)
                e = -e;
index c4df9f264aa6f0d284ddb53e26896f4535cf2c16..4c2d83efcaba5ebb3bc224c5bae5261c28f17460 100644 (file)
@@ -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,
index e5c30eec42da6e1504880684f773da59760bd482..527112acfbfcbc1332464966f95ed5c47cbfac54 100644 (file)
@@ -81,6 +81,19 @@ int pyro_dbg;
 #define DBG(...)
 #endif
 
+static angle_t
+ao_sample_max_orient(void)
+{
+       uint8_t i;
+       angle_t max = ao_sample_orients[0];
+
+       for (i = 1; i < AO_NUM_ORIENT; i++) {
+               angle_t a = ao_sample_orients[i];
+               if (a > max)
+                       max = a;
+       }
+       return max;
+}
 /*
  * Given a pyro structure, figure out
  * if the current flight state satisfies all
@@ -90,6 +103,9 @@ static uint8_t
 ao_pyro_ready(struct ao_pyro *pyro)
 {
        enum ao_pyro_flag flag, flags;
+#if HAS_GYRO
+       angle_t max_orient;
+#endif
 
        flags = pyro->flags;
        while (flags != ao_pyro_none) {
@@ -130,26 +146,28 @@ ao_pyro_ready(struct ao_pyro *pyro)
 
 #if HAS_GYRO
                case ao_pyro_orient_less:
-                       if (ao_sample_orient <= pyro->orient_less)
+                       max_orient = ao_sample_max_orient();
+                       if (max_orient <= pyro->orient_less)
                                continue;
-                       DBG("orient %d > %d\n", ao_sample_orient, pyro->orient_less);
+                       DBG("orient %d > %d\n", max_orient, pyro->orient_less);
                        break;
                case ao_pyro_orient_greater:
-                       if (ao_sample_orient >= pyro->orient_greater)
+                       max_orient = ao_sample_max_orient();
+                       if (max_orient >= pyro->orient_greater)
                                continue;
-                       DBG("orient %d < %d\n", ao_sample_orient, pyro->orient_greater);
+                       DBG("orient %d < %d\n", max_orient, pyro->orient_greater);
                        break;
 #endif
 
                case ao_pyro_time_less:
-                       if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less)
+                       if ((int16_t) (ao_time() - ao_launch_tick) <= pyro->time_less)
                                continue;
-                       DBG("time %d > %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_less);
+                       DBG("time %d > %d\n", (int16_t)(ao_time() - ao_launch_tick), pyro->time_less);
                        break;
                case ao_pyro_time_greater:
-                       if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater)
+                       if ((int16_t) (ao_time() - ao_launch_tick) >= pyro->time_greater)
                                continue;
-                       DBG("time %d < %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_greater);
+                       DBG("time %d < %d\n", (int16_t)(ao_time() - ao_launch_tick), pyro->time_greater);
                        break;
 
                case ao_pyro_ascending:
@@ -164,7 +182,7 @@ ao_pyro_ready(struct ao_pyro *pyro)
                        break;
 
                case ao_pyro_after_motor:
-                       if (ao_motor_number == pyro->motor)
+                       if (ao_motor_number >= pyro->motor)
                                continue;
                        DBG("motor %d != %d\n", ao_motor_number, pyro->motor);
                        break;
index 61519478a2a2c6ab1df8f36c7db14869e37fe20c..f8012e3455c48f8bf0b81888f2621366cd0e32ac 100644 (file)
@@ -50,6 +50,8 @@ __pdata gyro_t                ao_sample_roll;
 __pdata gyro_t         ao_sample_pitch;
 __pdata gyro_t         ao_sample_yaw;
 __pdata angle_t                ao_sample_orient;
+__pdata angle_t                ao_sample_orients[AO_NUM_ORIENT];
+__pdata uint8_t                ao_sample_orient_pos;
 #endif
 
 __data uint8_t         ao_sample_data;
@@ -115,6 +117,53 @@ ao_sample_preflight_add(void)
        ++nsamples;
 }
 
+#if HAS_GYRO
+static void
+ao_sample_set_all_orients(void)
+{
+       int i;
+       for (i = 0; i < AO_NUM_ORIENT; i++)
+               ao_sample_orients[i] = ao_sample_orient;
+       ao_sample_orient_pos = 0;
+}
+
+static void
+ao_sample_set_one_orient(void)
+{
+       ao_sample_orients[ao_sample_orient_pos] = ao_sample_orient;
+       ao_sample_orient_pos = (ao_sample_orient_pos + 1) % AO_NUM_ORIENT;
+}
+
+static void
+ao_sample_compute_orient(void)
+{
+       /* Compute pitch angle from vertical by taking the pad
+        * orientation vector and rotating it by the current total
+        * rotation value. That will be a unit vector pointing along
+        * the airframe axis. The Z value will be the cosine of the
+        * change in the angle from vertical since boost.
+        *
+        * rot = ao_rotation * vertical * ao_rotation°
+        * rot = ao_rotation * (0,0,0,1) * ao_rotation°
+        *     = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z
+        *
+        *     = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r)
+        *     = a.z² - a.y² - a.x² + a.r²
+        *
+        * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation°
+        *     = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z
+        *
+        *     = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r)
+        *     = -a.z² + a.y² + a.x² - a.r²
+        */
+
+       float rotz;
+       rotz = ao_rotation.z * ao_rotation.z - ao_rotation.y * ao_rotation.y - ao_rotation.x * ao_rotation.x + ao_rotation.r * ao_rotation.r;
+
+       ao_sample_orient = acosf(rotz) * (float) (180.0/M_PI);
+}
+#endif /* HAS_GYRO */
+
 static void
 ao_sample_preflight_set(void)
 {
@@ -138,7 +187,7 @@ ao_sample_preflight_set(void)
        ao_sample_pitch_sum = 0;
        ao_sample_yaw_sum = 0;
        ao_sample_roll_sum = 0;
-       ao_sample_orient = 0;
+       ao_sample_set_all_orients();
 
        struct ao_quaternion    orient;
 
@@ -168,6 +217,9 @@ ao_sample_preflight_set(void)
        if (ao_orient_test)
                printf("\n\treset\n");
 #endif 
+
+       ao_sample_compute_orient();
+       ao_sample_set_all_orients();
 #endif
        nsamples = 0;
 }
@@ -195,31 +247,6 @@ ao_sample_rotate(void)
        /* And normalize to make sure it remains a unit vector */
        ao_quaternion_normalize(&ao_rotation, &ao_rotation);
 
-       /* Compute pitch angle from vertical by taking the pad
-        * orientation vector and rotating it by the current total
-        * rotation value. That will be a unit vector pointing along
-        * the airframe axis. The Z value will be the cosine of the
-        * change in the angle from vertical since boost.
-        *
-        * rot = ao_rotation * vertical * ao_rotation°
-        * rot = ao_rotation * (0,0,0,1) * ao_rotation°
-        *     = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z
-        *
-        *     = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r)
-        *     = a.z² - a.y² - a.x² + a.r²
-        *
-        * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation°
-        *     = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z
-        *
-        *     = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r)
-        *     = -a.z² + a.y² + a.x² - a.r²
-        */
-
-       float rotz;
-       rotz = ao_rotation.z * ao_rotation.z - ao_rotation.y * ao_rotation.y - ao_rotation.x * ao_rotation.x + ao_rotation.r * ao_rotation.r;
-
-       ao_sample_orient = acosf(rotz) * (float) (180.0/M_PI);
-
 #if HAS_FLIGHT_DEBUG
        if (ao_orient_test) {
                printf ("rot %d %d %d orient %d     \r",
@@ -229,7 +256,8 @@ ao_sample_rotate(void)
                        ao_sample_orient);
        }
 #endif
-
+       ao_sample_compute_orient();
+       ao_sample_set_one_orient();
 }
 #endif
 
@@ -367,6 +395,7 @@ ao_sample_init(void)
        ao_sample_yaw = 0;
        ao_sample_roll = 0;
        ao_sample_orient = 0;
+       ao_sample_set_all_orients();
 #endif
        ao_sample_data = ao_data_head;
        ao_preflight = TRUE;
index fbef031d46129ab1039b186b7a3885144969e10d..5ae389bec7c636e4356b1d0c4042fd7fee5e25b0 100644 (file)
@@ -146,7 +146,10 @@ extern __pdata accel_t     ao_sample_accel_through;
 extern __pdata gyro_t  ao_sample_roll;
 extern __pdata gyro_t  ao_sample_pitch;
 extern __pdata gyro_t  ao_sample_yaw;
+#define AO_NUM_ORIENT  64
 extern __pdata angle_t ao_sample_orient;
+extern __pdata angle_t ao_sample_orients[AO_NUM_ORIENT];
+extern __pdata uint8_t ao_sample_orient_pos;
 #endif
 
 void ao_sample_init(void);
index 936d939bdd4fde1e92ae90ad9a499ae7457a3975..40516de10340ffa439f606a2292e776c25ca0d55 100644 (file)
@@ -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/mpusb-v3.0/.gitignore b/src/mpusb-v3.0/.gitignore
new file mode 100644 (file)
index 0000000..7c1cb59
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+mpusb-v3.0-*
diff --git a/src/mpusb-v3.0/Makefile b/src/mpusb-v3.0/Makefile
new file mode 100644 (file)
index 0000000..9615674
--- /dev/null
@@ -0,0 +1,68 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       ao_whiten.h \
+       stm32f0.h \
+       Makefile
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_dma_stm.c \
+       ao_task.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_usb_stm.c \
+       ao_power.c \
+       ao_gpio.c \
+       ao_serial_stm.c
+
+PRODUCT=MicroPeakUSB-v3.0
+PRODUCT_DEF=-DMPUSB
+IDPRODUCT=0x002b
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g
+
+PROGNAME=mpusb-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_mpusb.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/mpusb-v3.0/ao_mpusb.c b/src/mpusb-v3.0/ao_mpusb.c
new file mode 100644 (file)
index 0000000..dc30e19
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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_serial.h>
+
+static struct ao_task ao_report_task;
+
+static void
+ao_report(void)
+{
+       int     c;
+       ao_up_set_speed(AO_SERIAL_SPEED_9600);
+       for (;;) {
+               ao_arch_block_interrupts();
+               c = _ao_up_pollchar();
+               ao_arch_release_interrupts();
+               if (c == AO_READ_AGAIN) {
+                       flush();
+                       c = ao_up_getchar();
+               }
+               putchar(c);
+       }
+}
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_task_init();
+
+       ao_timer_init();
+
+       ao_serial_init();
+
+       ao_dma_init();
+
+       ao_cmd_init();
+
+       ao_usb_init();
+
+       ao_add_task(&ao_report_task, ao_report, "report");
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/mpusb-v3.0/ao_pins.h b/src/mpusb-v3.0/ao_pins.h
new file mode 100644 (file)
index 0000000..3e79aad
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+/* Using TeleMetrum v1.9 board */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+#define IS_FLASH_LOADER        0
+
+#define AO_POWER_MANAGEMENT    1
+
+/* 48MHz clock based on USB */
+#define AO_HSI48       1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_EEPROM             0
+#define USE_INTERNAL_FLASH     0
+#define USE_STORAGE_CONFIG     0
+#define USE_EEPROM_CONFIG      0
+
+#define HAS_BEEP               0
+
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#define HAS_SPI_0              0
+
+#define LOW_LEVEL_DEBUG                0
+
+#define HAS_SERIAL_2           1
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       1
+#define SERIAL_2_SWAP          0
+#define USE_SERIAL_2_FLOW      0
+#define USE_SERIAL_2_SW_FLOW   0
+
+#define ao_up_getchar          ao_serial2_getchar
+#define ao_up_putchar          ao_serial2_putchar
+#define _ao_up_pollchar                _ao_serial2_pollchar
+#define ao_up_set_speed                ao_serial2_set_speed
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/mpusb-v3.0/flash-loader/.gitignore b/src/mpusb-v3.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..1f8b354
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+mpusb*
diff --git a/src/mpusb-v3.0/flash-loader/Makefile b/src/mpusb-v3.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..8d0f9e4
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# AltOS flash loader build
+#
+
+TOPDIR=../..
+HARDWARE=mpusb-v3.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/mpusb-v3.0/flash-loader/ao_pins.h b/src/mpusb-v3.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..7feb936
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Debug port PA15 (pin 23) */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       (stm_gpioa)
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#endif /* _AO_PINS_H_ */
index ff8d3273c03147c038a781e4144f3904295b5c06..019b542529807103d8a16b09c82a1bd227630504 100644 (file)
@@ -25,6 +25,7 @@
 
 #define HAS_USB                        1
 #define USE_USB_STDIO          0
+#define HAS_USB_DISABLE                0
 #define HAS_BEEP               0
 #define HAS_TASK               0
 #define HAS_ECHO               0
index 869fb32fd4010d71a5c63135f643b7bdc51087a4..d4569c1a9b80539074976472e451096a4320a919 100644 (file)
@@ -30,6 +30,8 @@ ALTOS_SRC = \
        ao_lcd_stm.c \
        ao_lcd_font.c \
        ao_mutex.c \
+       ao_storage.c \
+       ao_m25.c \
        ao_dma_stm.c \
        ao_spi_stm.c \
        ao_adc_stm.c \
index db432c2ae91a6f257a6a02847aa88f02c868e7ff..f6c8e3df83f0dafa48b40ed03be9b528ac9e6bc9 100644 (file)
@@ -223,11 +223,12 @@ main(void)
        ao_cmd_init();
 //     ao_lcd_stm_init();
 //     ao_lcd_font_init();
-//     ao_spi_init();
+       ao_spi_init();
 //     ao_i2c_init();
 //     ao_exti_init();
 //     ao_quadrature_init();
 //     ao_button_init();
+       ao_storage_init();
 
 //     ao_timer_set_adc_interval(100);
 
index 233537dffdcb765d9de35033c62ad11adc2b8a04..2b4c5ab0f31a70766e33badbba78bfd3d2136182 100644 (file)
 #define SERIAL_3_PC10_PC11     0
 #define SERIAL_3_PD8_PD9       1
 
-#define HAS_SPI_1              1
+#define HAS_SPI_1              0
 #define SPI_1_PB3_PB4_PB5      1
 #define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
 
-#define HAS_SPI_2              0
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion, Radio */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
 
 #define HAS_USB                        1
 #define HAS_BEEP               0
@@ -200,4 +203,11 @@ struct ao_adc {
 #define AO_TICK_TYPE           uint32_t
 #define AO_TICK_SIGNED         int32_t
 
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK     (1 << 12)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEMEGA
+
 #endif /* _AO_PINS_H_ */
diff --git a/src/stm/ao_adc_single.h b/src/stm/ao_adc_single.h
new file mode 100644 (file)
index 0000000..f9d953c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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_ADC_SINGLE_H_
+#define _AO_ADC_SINGLE_H_
+
+void
+ao_adc_single_get(struct ao_adc *packet);
+
+void
+ao_adc_single_init(void);
+
+#endif /* _AO_ADC_SINGLE_H_ */
diff --git a/src/stm/ao_adc_single_stm.c b/src/stm/ao_adc_single_stm.c
new file mode 100644 (file)
index 0000000..8a7fda4
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * 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; 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_data.h>
+
+static uint8_t                 ao_adc_ready;
+
+#define AO_ADC_CR2_VAL         ((0 << STM_ADC_CR2_SWSTART) |           \
+                                (STM_ADC_CR2_EXTEN_DISABLE << STM_ADC_CR2_EXTEN) | \
+                                (0 << STM_ADC_CR2_EXTSEL) |            \
+                                (0 << STM_ADC_CR2_JWSTART) |           \
+                                (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \
+                                (0 << STM_ADC_CR2_JEXTSEL) |           \
+                                (0 << STM_ADC_CR2_ALIGN) |             \
+                                (0 << STM_ADC_CR2_EOCS) |              \
+                                (1 << STM_ADC_CR2_DDS) |               \
+                                (1 << STM_ADC_CR2_DMA) |               \
+                                (STM_ADC_CR2_DELS_UNTIL_READ << STM_ADC_CR2_DELS) | \
+                                (0 << STM_ADC_CR2_CONT) |              \
+                                (1 << STM_ADC_CR2_ADON))
+
+/*
+ * Callback from DMA ISR
+ *
+ * Shut down DMA engine, signal anyone waiting
+ */
+static void ao_adc_done(int index)
+{
+       (void) index;
+       ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
+       ao_adc_ready = 1;
+       ao_wakeup((void *) &ao_adc_ready);
+}
+
+/*
+ * Start the ADC sequence using the DMA engine
+ */
+static void
+ao_adc_poll(struct ao_adc *packet)
+{
+       ao_adc_ready = 0;
+       stm_adc.sr = 0;
+       ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1),
+                           &stm_adc.dr,
+                           (void *) packet,
+                           AO_NUM_ADC,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) |
+                           (1 << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+       ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done);
+       ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
+
+       stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART);
+}
+
+/*
+ * Fetch a copy of the most recent ADC data
+ */
+void
+ao_adc_single_get(struct ao_adc *packet)
+{
+       ao_adc_poll(packet);
+       ao_arch_block_interrupts();
+       while (!ao_adc_ready)
+               ao_sleep(&ao_adc_ready);
+       ao_arch_release_interrupts();
+}
+
+static void
+ao_adc_dump(void)
+{
+       struct ao_adc   packet;
+       ao_adc_single_get(&packet);
+       AO_ADC_DUMP(&packet);
+}
+
+__code struct ao_cmds ao_adc_cmds[] = {
+       { ao_adc_dump,  "a\0Display current ADC values" },
+       { 0, NULL },
+};
+
+void
+ao_adc_single_init(void)
+{
+#ifdef AO_ADC_PIN0_PORT
+       stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR;
+#endif
+
+#ifdef AO_ADC_PIN0_PORT
+       stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN1_PORT
+       stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN2_PORT
+       stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN3_PORT
+       stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN4_PORT
+       stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN5_PORT
+       stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN6_PORT
+       stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN7_PORT
+       stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN8_PORT
+       stm_moder_set(AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN9_PORT
+       stm_moder_set(AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN10_PORT
+       stm_moder_set(AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN11_PORT
+       stm_moder_set(AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN12_PORT
+       stm_moder_set(AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN13_PORT
+       stm_moder_set(AO_ADC_PIN13_PORT, AO_ADC_PIN13_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN14_PORT
+       stm_moder_set(AO_ADC_PIN14_PORT, AO_ADC_PIN14_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN15_PORT
+       stm_moder_set(AO_ADC_PIN15_PORT, AO_ADC_PIN15_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN16_PORT
+       stm_moder_set(AO_ADC_PIN16_PORT, AO_ADC_PIN16_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN17_PORT
+       stm_moder_set(AO_ADC_PIN17_PORT, AO_ADC_PIN17_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN18_PORT
+       stm_moder_set(AO_ADC_PIN18_PORT, AO_ADC_PIN18_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN19_PORT
+       stm_moder_set(AO_ADC_PIN19_PORT, AO_ADC_PIN19_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN20_PORT
+       stm_moder_set(AO_ADC_PIN20_PORT, AO_ADC_PIN20_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN21_PORT
+       stm_moder_set(AO_ADC_PIN21_PORT, AO_ADC_PIN21_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN22_PORT
+       stm_moder_set(AO_ADC_PIN22_PORT, AO_ADC_PIN22_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN23_PORT
+       stm_moder_set(AO_ADC_PIN23_PORT, AO_ADC_PIN23_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN24_PORT
+       #error "Too many ADC ports"
+#endif
+
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN);
+
+       /* Turn off ADC during configuration */
+       stm_adc.cr2 = 0;
+
+       stm_adc.cr1 = ((0 << STM_ADC_CR1_OVRIE ) |
+                      (STM_ADC_CR1_RES_12 << STM_ADC_CR1_RES ) |
+                      (0 << STM_ADC_CR1_AWDEN ) |
+                      (0 << STM_ADC_CR1_JAWDEN ) |
+                      (0 << STM_ADC_CR1_PDI ) |
+                      (0 << STM_ADC_CR1_PDD ) |
+                      (0 << STM_ADC_CR1_DISCNUM ) |
+                      (0 << STM_ADC_CR1_JDISCEN ) |
+                      (0 << STM_ADC_CR1_DISCEN ) |
+                      (0 << STM_ADC_CR1_JAUTO ) |
+                      (0 << STM_ADC_CR1_AWDSGL ) |
+                      (1 << STM_ADC_CR1_SCAN ) |
+                      (0 << STM_ADC_CR1_JEOCIE ) |
+                      (0 << STM_ADC_CR1_AWDIE ) |
+                      (0 << STM_ADC_CR1_EOCIE ) |
+                      (0 << STM_ADC_CR1_AWDCH ));
+
+       /* 384 cycle sample time for everyone */
+       stm_adc.smpr1 = 0x3ffff;
+       stm_adc.smpr2 = 0x3fffffff;
+       stm_adc.smpr3 = 0x3fffffff;
+
+       stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20);
+       stm_adc.sqr2 = 0;
+       stm_adc.sqr3 = 0;
+       stm_adc.sqr4 = 0;
+       stm_adc.sqr5 = 0;
+#if AO_NUM_ADC > 0
+       stm_adc.sqr5 |= (AO_ADC_SQ1 << 0);
+#endif
+#if AO_NUM_ADC > 1
+       stm_adc.sqr5 |= (AO_ADC_SQ2 << 5);
+#endif
+#if AO_NUM_ADC > 2
+       stm_adc.sqr5 |= (AO_ADC_SQ3 << 10);
+#endif
+#if AO_NUM_ADC > 3
+       stm_adc.sqr5 |= (AO_ADC_SQ4 << 15);
+#endif
+#if AO_NUM_ADC > 4
+       stm_adc.sqr5 |= (AO_ADC_SQ5 << 20);
+#endif
+#if AO_NUM_ADC > 5
+       stm_adc.sqr5 |= (AO_ADC_SQ6 << 25);
+#endif
+#if AO_NUM_ADC > 6
+       stm_adc.sqr4 |= (AO_ADC_SQ7 << 0);
+#endif
+#if AO_NUM_ADC > 7
+       stm_adc.sqr4 |= (AO_ADC_SQ8 << 5);
+#endif
+#if AO_NUM_ADC > 8
+       stm_adc.sqr4 |= (AO_ADC_SQ9 << 10);
+#endif
+#if AO_NUM_ADC > 9
+       stm_adc.sqr4 |= (AO_ADC_SQ10 << 15);
+#endif
+#if AO_NUM_ADC > 10
+       stm_adc.sqr4 |= (AO_ADC_SQ11 << 20);
+#endif
+#if AO_NUM_ADC > 11
+       stm_adc.sqr4 |= (AO_ADC_SQ12 << 25);
+#endif
+#if AO_NUM_ADC > 12
+       stm_adc.sqr3 |= (AO_ADC_SQ13 << 0);
+#endif
+#if AO_NUM_ADC > 13
+       stm_adc.sqr3 |= (AO_ADC_SQ14 << 5);
+#endif
+#if AO_NUM_ADC > 14
+       stm_adc.sqr3 |= (AO_ADC_SQ15 << 10);
+#endif
+#if AO_NUM_ADC > 15
+       stm_adc.sqr3 |= (AO_ADC_SQ16 << 15);
+#endif
+#if AO_NUM_ADC > 16
+       stm_adc.sqr3 |= (AO_ADC_SQ17 << 20);
+#endif
+#if AO_NUM_ADC > 17
+       stm_adc.sqr3 |= (AO_ADC_SQ18 << 25);
+#endif
+#if AO_NUM_ADC > 18
+#error "need to finish stm_adc.sqr settings"
+#endif
+
+       /* Turn ADC on */
+       stm_adc.cr2 = AO_ADC_CR2_VAL;
+
+       /* Wait for ADC to be ready */
+       while (!(stm_adc.sr & (1 << STM_ADC_SR_ADONS)))
+               ;
+
+#ifndef HAS_ADC_TEMP
+#error Please define HAS_ADC_TEMP
+#endif
+#if HAS_ADC_TEMP
+       stm_adc.ccr = ((1 << STM_ADC_CCR_TSVREFE));
+#else
+       stm_adc.ccr = 0;
+#endif
+       /* Clear any stale status bits */
+       stm_adc.sr = 0;
+
+       ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
+
+       ao_cmd_register(&ao_adc_cmds[0]);
+}
index 5f033b66219e36719164e7864b8e4121977b8934..679dba4499623d33f57671830287a7073b0180f2 100644 (file)
@@ -30,8 +30,6 @@
 #define AO_STACK_SIZE  512
 #endif
 
-#define AO_LED_TYPE    uint16_t
-
 #ifndef AO_TICK_TYPE
 #define AO_TICK_TYPE   uint16_t
 #define AO_TICK_SIGNED int16_t
@@ -153,6 +151,10 @@ ao_adc_init();
 #define AO_BOOT_LOADER_BASE            ((uint32_t *) 0x08000000)
 #define HAS_BOOT_LOADER                        1
 
+#ifndef AO_LED_TYPE
+#define AO_LED_TYPE uint16_t
+#endif
+
 #endif /* _AO_ARCH_H_ */
 
 
index 0f39befb9426843f1f63d260ff9c77509b187351..a7033dbba5eb02136065d87f9aef8f7e5c2c11d6 100644 (file)
 
 #include "ao.h"
 
-__pdata uint16_t ao_led_enable;
+#if LED_PER_LED
+static const struct {
+       struct stm_gpio *port;
+       uint16_t        pin;
+} ao_leds[] = {
+#ifdef LED_0_PORT
+    [0] { LED_0_PORT, LED_0_PIN },
+#endif
+#ifdef LED_1_PORT
+    [1] { LED_1_PORT, LED_1_PIN },
+#endif
+#ifdef LED_2_PORT
+    [2] { LED_2_PORT, LED_2_PIN },
+#endif
+#ifdef LED_3_PORT
+    [3] { LED_3_PORT, LED_3_PIN },
+#endif
+#ifdef LED_4_PORT
+    [4] { LED_4_PORT, LED_4_PIN },
+#endif
+#ifdef LED_5_PORT
+    [5] { LED_5_PORT, LED_5_PIN },
+#endif
+#ifdef LED_6_PORT
+    [6] { LED_6_PORT, LED_6_PIN },
+#endif
+#ifdef LED_7_PORT
+    [7] { LED_7_PORT, LED_7_PIN },
+#endif
+#ifdef LED_8_PORT
+    [8] { LED_8_PORT, LED_8_PIN },
+#endif
+#ifdef LED_9_PORT
+    [9] { LED_9_PORT, LED_9_PIN },
+#endif
+#ifdef LED_10_PORT
+    [10] { LED_10_PORT, LED_10_PIN },
+#endif
+#ifdef LED_11_PORT
+    [11] { LED_11_PORT, LED_11_PIN },
+#endif
+#ifdef LED_12_PORT
+    [12] { LED_12_PORT, LED_12_PIN },
+#endif
+#ifdef LED_13_PORT
+    [13] { LED_13_PORT, LED_13_PIN },
+#endif
+#ifdef LED_14_PORT
+    [14] { LED_14_PORT, LED_14_PIN },
+#endif
+#ifdef LED_15_PORT
+    [15] { LED_15_PORT, LED_15_PIN },
+#endif
+};
+#define N_LED  (sizeof (ao_leds)/sizeof(ao_leds[0]))
+#endif
+static AO_LED_TYPE ao_led_enable;
 
 void
-ao_led_on(uint16_t colors)
+ao_led_on(AO_LED_TYPE colors)
 {
+#ifdef LED_PER_LED
+       AO_LED_TYPE i;
+       for (i = 0; i < N_LED; i++)
+               if (colors & (1 << i))
+                       ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, foo, 1);
+#else
 #ifdef LED_PORT
        LED_PORT->bsrr = (colors & ao_led_enable);
 #else
@@ -33,11 +95,18 @@ ao_led_on(uint16_t colors)
        LED_PORT_1->bsrr = ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
 #endif
 #endif
+#endif
 }
 
 void
-ao_led_off(uint16_t colors)
+ao_led_off(AO_LED_TYPE colors)
 {
+#ifdef LED_PER_LED
+       AO_LED_TYPE i;
+       for (i = 0; i < N_LED; i++)
+               if (colors & (1 << i))
+                       ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, foo, 0);
+#else
 #ifdef LED_PORT
        LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16;
 #else
@@ -48,21 +117,28 @@ ao_led_off(uint16_t colors)
        LED_PORT_1->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_1_MASK) << (LED_PORT_1_SHIFT + 16);
 #endif
 #endif
+#endif
 }
 
 void
-ao_led_set(uint16_t colors)
+ao_led_set(AO_LED_TYPE colors)
 {
-       uint16_t        on = colors & ao_led_enable;
-       uint16_t        off = ~colors & ao_led_enable;
+       AO_LED_TYPE     on = colors & ao_led_enable;
+       AO_LED_TYPE     off = ~colors & ao_led_enable;
 
        ao_led_off(off);
        ao_led_on(on);
 }
 
 void
-ao_led_toggle(uint16_t colors)
+ao_led_toggle(AO_LED_TYPE colors)
 {
+#ifdef LED_PER_LED
+       AO_LED_TYPE i;
+       for (i = 0; i < N_LED; i++)
+               if (colors & (1 << i))
+                       ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, foo, ~ao_gpio_get(ao_leds[i].port, ao_leds[i].pin, foo));
+#else
 #ifdef LED_PORT
        LED_PORT->odr ^= (colors & ao_led_enable);
 #else
@@ -73,10 +149,11 @@ ao_led_toggle(uint16_t colors)
        LED_PORT_1->odr ^= ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
 #endif
 #endif
+#endif
 }
 
 void
-ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
+ao_led_for(AO_LED_TYPE colors, AO_LED_TYPE ticks) __reentrant
 {
        ao_led_on(colors);
        ao_delay(ticks);
@@ -89,11 +166,15 @@ ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
        } while (0)
 
 void
-ao_led_init(uint16_t enable)
+ao_led_init(AO_LED_TYPE enable)
 {
-       int     bit;
+       AO_LED_TYPE     bit;
 
        ao_led_enable = enable;
+#if LED_PER_LED
+       for (bit = 0; bit < N_LED; bit++)
+               ao_enable_output(ao_leds[bit].port, ao_leds[bit].pin, foo, 0);
+#else
 #ifdef LED_PORT
        stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE);
        LED_PORT->odr &= ~enable;
@@ -106,6 +187,10 @@ ao_led_init(uint16_t enable)
        stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE);
        LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
 #endif
+#ifdef LED_PORT_2
+       stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE);
+       LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
 #endif
        for (bit = 0; bit < 16; bit++) {
                if (enable & (1 << bit)) {
@@ -120,7 +205,12 @@ ao_led_init(uint16_t enable)
                        if (LED_PORT_1_MASK & (1 << bit))
                                init_led_pin(LED_PORT_1, bit + LED_PORT_1_SHIFT);
 #endif
+#ifdef LED_PORT_2
+                       if (LED_PORT_2_MASK & (1 << bit))
+                               init_led_pin(LED_PORT_2, bit + LED_PORT_2_SHIFT);
+#endif
 #endif
                }
        }
+#endif
 }
index 9d5fd6fb8616391d0a0c1b348e2d83c83283d120..63a48becd4b05cd17f236252e1e6a53bb4a264de 100644 (file)
@@ -24,5 +24,6 @@ AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0;
 #ifndef AO_RADIO_CAL_DEFAULT
 #define AO_RADIO_CAL_DEFAULT 0x01020304
 #endif
+#if HAS_RADIO
 AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT;
-
+#endif
index 1576a6c91f78e38132b119b025415e0c112a3970..7b526902169abc46cbb2f7bc61fbcab8e525c293 100644 (file)
@@ -149,7 +149,7 @@ ao_clock_init(void)
 #define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK       (0 << STM_RCC_CFGR_PLLSRC)
 #endif
 
-#if !AO_HSE || HAS_ADC
+#if !AO_HSE || HAS_ADC || HAS_ADC_SINGLE
        /* Enable HSI RC clock 16MHz */
        stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
        while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
index 595bddac29c0618f35e8063c5a29dff2530314c7..b06814d23184fcf992b7df4fc880fd598986c31c 100644 (file)
@@ -446,15 +446,11 @@ ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset)
 }
 
 static void
-ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes)
+ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t bytes)
 {
+       uint16_t offset = 0;
        if (!bytes)
                return;
-       if (offset & 1) {
-               debug_data (" %02x", src[0]);
-               ao_usb_write_byte(*src++, base, offset++);
-               bytes--;
-       }
        while (bytes >= 2) {
                debug_data (" %02x %02x", src[0], src[1]);
                ao_usb_write_short((src[1] << 8) | src[0], base, offset);
@@ -531,7 +527,7 @@ ao_usb_ep0_flush(void)
        ao_usb_ep0_in_len -= this_len;
 
        debug_data ("Flush EP0 len %d:", this_len);
-       ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len);
+       ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len);
        debug_data ("\n");
        ao_usb_ep0_in_data += this_len;
 
@@ -850,7 +846,7 @@ _ao_usb_in_send(void)
        ao_usb_in_pending = 1;
        if (ao_usb_tx_count != AO_USB_IN_SIZE)
                ao_usb_in_flushed = 1;
-       ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count);
+       ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count);
        ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count;
        ao_usb_tx_count = 0;
        _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
@@ -974,6 +970,11 @@ ao_usb_getchar(void)
        return c;
 }
 
+#ifndef HAS_USB_DISABLE
+#define HAS_USB_DISABLE 1
+#endif
+
+#if HAS_USB_DISABLE
 void
 ao_usb_disable(void)
 {
@@ -991,6 +992,7 @@ ao_usb_disable(void)
        stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN);
        ao_arch_release_interrupts();
 }
+#endif
 
 void
 ao_usb_enable(void)
index 201f4f36647c4b5722cd9dfc5ab785065788c72a..1da817e7a0db36267524bbf2b6dbf33cf80c4bb3 100644 (file)
@@ -1454,6 +1454,9 @@ struct stm_adc {
 
 extern struct stm_adc stm_adc;
 
+#define STM_ADC_SQ_TEMP                16
+#define STM_ADC_SQ_V_REF       17
+
 #define STM_ADC_SR_JCNR                9
 #define STM_ADC_SR_RCNR                8
 #define STM_ADC_SR_ADONS       6
index 56a3bc75e0a38dfa84f6772609e49d23b2cc2179..96c033f9712ce379f481c43d4fe621e52f663e2d 100644 (file)
@@ -171,10 +171,12 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
 #define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
 #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
 
+#if AO_POWER_MANAGEMENT
 extern struct ao_power ao_power_gpioa;
 extern struct ao_power ao_power_gpiob;
 extern struct ao_power ao_power_gpioc;
 extern struct ao_power ao_power_gpiof;
+#endif
 
 static inline void ao_enable_port(struct stm_gpio *port)
 {
index a8d1701b318dbead80640f393daeed3cc3f024cb..18bf272c6476e0557f92d1fd65dcc1c371b42089 100644 (file)
@@ -34,7 +34,7 @@ main(void)
 
 #ifdef AO_FLASH_LOADER_INIT
        AO_FLASH_LOADER_INIT;
-#endif 
+#endif
        ao_flash_task();
        return 0;
 }
index fcd330f1b5aafc6620075ecfad98ad40a3be6aa6..a67f6f1a26e2f4fb4dcef390d9bc6db7d6d99ded 100644 (file)
@@ -69,20 +69,24 @@ stm_flash_size(void) {
 
 void start(void)
 {
-#ifdef AO_BOOT_CHAIN
+#if AO_BOOT_CHAIN
        if (ao_boot_check_chain()) {
-#ifdef AO_BOOT_PIN
+#if AO_BOOT_PIN
                ao_boot_check_pin();
 #endif
        }
 #endif
-#if RELOCATE_INTERRUPT
        /* Turn on syscfg */
        stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
 
+#if RELOCATE_INTERRUPT
        memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
        stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
                (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
+#else
+       /* Switch to Main Flash mode (DFU loader leaves us in System mode) */
+       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
+               (STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH << STM_SYSCFG_CFGR1_MEM_MODE);
 #endif
        memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
        memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
index bf08abc169dac58e74da45f81ab2ea1f64c5277e..c4860d8e063a02ca6c85366acc29ac9eb0393799 100644 (file)
@@ -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;
 
@@ -995,6 +1042,16 @@ stm_usb_isr(void)
                                ao_wakeup(&ao_usb_in2_pending);
                        }
                        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
@@ -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)
@@ -1447,7 +1595,7 @@ ao_usb_enable(void)
 
        ao_arch_release_interrupts();
 
-       for (t = 0; t < 1000; t++)
+       for (t = 0; t < 50000; t++)
                ao_arch_nop();
 
        /* Enable USB pull-up */
@@ -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;
index ee0ca7166c3639d45d22c54cc97c212bd7e839d9..8266589e254845f6ee2ad20fd7a77aa3ec119dd2 100644 (file)
 #define AO_STROBE_PIN          1
 #define AO_STROBE              P1_1
 
-/* test these values with real igniters */
-#define AO_PAD_RELAY_CLOSED    3524
-#define AO_PAD_NO_IGNITER      16904
-#define AO_PAD_GOOD_IGNITER    22514
+#define AO_ADC_REFERENCE_DV    33
+#define AO_PAD_R_V_BATT_BATT_SENSE     100
+#define AO_PAD_R_BATT_SENSE_GND                27
+
+#define AO_PAD_R_V_BATT_V_PYRO         100
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     100
+#define AO_PAD_R_PYRO_SENSE_GND                27
+
+#define AO_PAD_R_V_PYRO_IGNITER                100
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 100
+#define AO_PAD_R_IGNITER_SENSE_GND     27
 
 #define AO_PAD_ADC_PYRO                4
 #define AO_PAD_ADC_BATT                5
index 4faeb65f83ea0ce34fd37dbd4cf4a1bed6be5a70..65f5bdcc17f1f4e3aa1da412e911e78b3ebf704f 100644 (file)
 #define AO_STROBE              P2_4
 
 /* test these values with real igniters */
-#define AO_PAD_RELAY_CLOSED    3524
-#define AO_PAD_NO_IGNITER      16904
-#define AO_PAD_GOOD_IGNITER    22514
-
 #define AO_PAD_ADC_PYRO                4
 #define AO_PAD_ADC_BATT                5
 
 #define AO_ADC_FIRST_PIN       0
 
+#define AO_ADC_REFERENCE_DV    33
+#define AO_PAD_R_V_BATT_BATT_SENSE     100
+#define AO_PAD_R_BATT_SENSE_GND                27
+
+#define AO_PAD_R_V_BATT_V_PYRO         100
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     100
+#define AO_PAD_R_PYRO_SENSE_GND                27
+
+#define AO_PAD_R_V_PYRO_IGNITER                100
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 100
+#define AO_PAD_R_IGNITER_SENSE_GND     27
+
+
 struct ao_adc {
        int16_t         sense[AO_PAD_NUM];
        int16_t         pyro;
diff --git a/src/telefireeight-v1.0/.gitignore b/src/telefireeight-v1.0/.gitignore
new file mode 100644 (file)
index 0000000..22f7e9e
--- /dev/null
@@ -0,0 +1,2 @@
+telefireeight-*
+ao_product.h
diff --git a/src/telefireeight-v1.0/Makefile b/src/telefireeight-v1.0/Makefile
new file mode 100644 (file)
index 0000000..200c315
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pad.h \
+       ao_product.h \
+       ao_radio_spi.h \
+       ao_radio_cmac.h \
+       ao_cc1200_CC1200.h \
+       ao_cc1200.h \
+       stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_adc_stm.c \
+       ao_data.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_cc1200.c \
+       ao_radio_cmac.c \
+       ao_aes.c \
+       ao_aes_tables.c \
+       ao_pad.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+       ao_telefireeight.c
+
+PRODUCT=TeleFireEight-v1.0
+PRODUCT_DEF=-DTELEFIREEIGHT_V_1_0
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefireeight-v1.0
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
diff --git a/src/telefireeight-v1.0/ao_pins.h b/src/telefireeight-v1.0/ao_pins.h
new file mode 100644 (file)
index 0000000..15e1fa1
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * 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; 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_
+
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+#define HAS_FLIGHT             0
+#define HAS_USB                        1
+#define HAS_BEEP               0
+#define HAS_GPS                        0
+#define HAS_SERIAL_1           0
+#define HAS_ADC                        1
+#define HAS_DBG                        0
+#define HAS_EEPROM             1
+#define HAS_LOG                        0
+#define HAS_PAD                        1
+#define USE_INTERNAL_FLASH     1
+#define IGNITE_ON_P0           0
+#define PACKET_HAS_MASTER      0
+#define PACKET_HAS_SLAVE       0
+#define AO_DATA_RING           32
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_AES                        1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC         40000000
+
+/* 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_SPI_1              1
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   1
+#define SPI_1_GPIO             (&stm_gpioe)
+#define SPI_1_SCK              13
+#define SPI_1_MISO             14
+#define SPI_1_MOSI             15
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              0
+#define SPI_2_PB13_PB14_PB15   0
+#define SPI_2_PD1_PD3_PD4      0
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define FAST_TIMER_FREQ                10000   /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpioe)
+#define AO_CC1200_SPI_CS_PIN   11
+#define AO_CC1200_SPI_BUS      AO_SPI_1_PE13_PE14_PE15
+#define AO_CC1200_SPI          stm_spi1
+#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
+
+#define AO_CC1200_INT_PORT     (&stm_gpioe)
+#define AO_CC1200_INT_PIN      (12)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define LED_PER_LED            1
+#define LED_TYPE               uint16_t
+
+/* Continuity leds 1-8 */
+#define LED_0_PORT             (&stm_gpiob)
+#define LED_0_PIN              13
+#define LED_1_PORT             (&stm_gpiob)
+#define LED_1_PIN              12
+#define LED_2_PORT             (&stm_gpiob)
+#define LED_2_PIN              11
+#define LED_3_PORT             (&stm_gpiob)
+#define LED_3_PIN              10
+#define LED_4_PORT             (&stm_gpioc)
+#define LED_4_PIN              9
+#define LED_5_PORT             (&stm_gpioa)
+#define LED_5_PIN              8
+#define LED_6_PORT             (&stm_gpioa)
+#define LED_6_PIN              9
+#define LED_7_PORT             (&stm_gpioa)
+#define LED_7_PIN              10
+
+#define LED_PIN_CONTINUITY_0   0
+#define LED_PIN_CONTINUITY_1   1
+#define LED_PIN_CONTINUITY_2   2
+#define LED_PIN_CONTINUITY_3   3
+#define LED_PIN_CONTINUITY_4   4
+#define LED_PIN_CONTINUITY_5   5
+#define LED_PIN_CONTINUITY_6   6
+#define LED_PIN_CONTINUITY_7   7
+
+/* ARM */
+#define LED_8_PORT             (&stm_gpioe)
+#define LED_8_PIN              3
+
+#define LED_PIN_ARMED          8
+
+/* RF good/marginal/poor */
+#define LED_9_PORT             (&stm_gpioe)
+#define LED_9_PIN              4
+#define LED_10_PORT            (&stm_gpioe)
+#define LED_10_PIN             5
+#define LED_11_PORT            (&stm_gpioe)
+#define LED_11_PIN             6
+
+#define LED_PIN_GREEN          9
+#define LED_PIN_AMBER          10
+#define LED_PIN_RED            11
+
+#define AO_LED_CONTINUITY(c)   (1 << (c))
+#define AO_LED_CONTINUITY_MASK (0xff)
+
+#define AO_LED_ARMED           (1 << LED_PIN_ARMED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+#define AO_LED_AMBER           (1 << LED_PIN_AMBER)
+#define AO_LED_RED             (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE         (0xfff)
+
+/* Alarm A */
+#define AO_SIREN
+#define AO_SIREN_PORT          (&stm_gpiod)
+#define AO_SIREN_PIN           10
+
+/* Alarm B */
+#define AO_STROBE
+#define AO_STROBE_PORT         (&stm_gpiod)
+#define AO_STROBE_PIN          11
+
+/* Pad selector is on PD0-7 */
+
+#define HAS_FIXED_PAD_BOX      1
+#define AO_PAD_SELECTOR_PORT   (&stm_gpiod)
+#define AO_PAD_SELECTOR_PINS   (0xff)
+
+#define SPI_CONST      0x00
+
+#define AO_PAD_NUM             8
+#define        AO_PAD_PORT_0           (&stm_gpiod)
+#define        AO_PAD_PORT_1           (&stm_gpiob)
+
+#define AO_PAD_PIN_0           9
+#define AO_PAD_0_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_0     3
+#define AO_ADC_SENSE_PAD_0_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_0_PIN 3
+
+#define AO_PAD_PIN_1           8
+#define AO_PAD_1_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_1     2
+#define AO_ADC_SENSE_PAD_1_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_1_PIN 2
+
+#define AO_PAD_PIN_2           15
+#define AO_PAD_2_PORT          (&stm_gpiob)
+#define AO_ADC_SENSE_PAD_2     1
+#define AO_ADC_SENSE_PAD_2_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_2_PIN 1
+
+#define AO_PAD_PIN_3           14
+#define AO_PAD_3_PORT          (&stm_gpiob)
+#define AO_ADC_SENSE_PAD_3     0
+#define AO_ADC_SENSE_PAD_3_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_3_PIN 0
+
+#define AO_PAD_PIN_4           12
+#define AO_PAD_4_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_4     7
+#define AO_ADC_SENSE_PAD_4_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_4_PIN 7
+
+#define AO_PAD_PIN_5           13
+#define AO_PAD_5_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_5     6
+#define AO_ADC_SENSE_PAD_5_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_5_PIN 6
+
+#define AO_PAD_PIN_6           14
+#define AO_PAD_6_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_6     5
+#define AO_ADC_SENSE_PAD_6_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_6_PIN 5
+
+#define AO_PAD_PIN_7           15
+#define AO_PAD_7_PORT          (&stm_gpiod)
+#define AO_ADC_SENSE_PAD_7     4
+#define AO_ADC_SENSE_PAD_7_PORT        (&stm_gpioa)
+#define AO_ADC_SENSE_PAD_7_PIN 4
+
+#define AO_ADC_PYRO            8
+#define AO_ADC_PYRO_PORT       (&stm_gpiob)
+#define AO_ADC_PYRO_PIN                0
+
+#define AO_ADC_BATT            15
+#define AO_ADC_BATT_PORT       (&stm_gpioc)
+#define AO_ADC_BATT_PIN                5
+
+#define AO_ADC_PIN0_PORT       AO_ADC_SENSE_PAD_0_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_SENSE_PAD_0_PIN
+
+#define AO_ADC_PIN1_PORT       AO_ADC_SENSE_PAD_1_PORT
+#define AO_ADC_PIN1_PIN                AO_ADC_SENSE_PAD_1_PIN
+
+#define AO_ADC_PIN2_PORT       AO_ADC_SENSE_PAD_2_PORT
+#define AO_ADC_PIN2_PIN                AO_ADC_SENSE_PAD_2_PIN
+
+#define AO_ADC_PIN3_PORT       AO_ADC_SENSE_PAD_3_PORT
+#define AO_ADC_PIN3_PIN                AO_ADC_SENSE_PAD_3_PIN
+
+#define AO_ADC_PIN4_PORT       AO_ADC_SENSE_PAD_4_PORT
+#define AO_ADC_PIN4_PIN                AO_ADC_SENSE_PAD_4_PIN
+
+#define AO_ADC_PIN5_PORT       AO_ADC_SENSE_PAD_5_PORT
+#define AO_ADC_PIN5_PIN                AO_ADC_SENSE_PAD_5_PIN
+
+#define AO_ADC_PIN6_PORT       AO_ADC_SENSE_PAD_6_PORT
+#define AO_ADC_PIN6_PIN                AO_ADC_SENSE_PAD_6_PIN
+
+#define AO_ADC_PIN7_PORT       AO_ADC_SENSE_PAD_7_PORT
+#define AO_ADC_PIN7_PIN                AO_ADC_SENSE_PAD_7_PIN
+
+#define AO_ADC_PIN8_PORT       AO_ADC_PYRO_PORT
+#define AO_ADC_PIN8_PIN                AO_ADC_PYRO_PIN
+
+#define AO_ADC_PIN9_PORT       AO_ADC_BATT_PORT
+#define AO_ADC_PIN9_PIN                AO_ADC_BATT_PIN
+
+#define AO_PAD_ALL_CHANNELS    (0xff)
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED    3524
+#define AO_PAD_NO_IGNITER      16904
+#define AO_PAD_GOOD_IGNITER    22514
+
+#define AO_ADC_FIRST_PIN       0
+
+#define AO_NUM_ADC             10
+
+#define AO_ADC_SQ1             AO_ADC_SENSE_PAD_0
+#define AO_ADC_SQ2             AO_ADC_SENSE_PAD_1
+#define AO_ADC_SQ3             AO_ADC_SENSE_PAD_2
+#define AO_ADC_SQ4             AO_ADC_SENSE_PAD_3
+#define AO_ADC_SQ5             AO_ADC_SENSE_PAD_4
+#define AO_ADC_SQ6             AO_ADC_SENSE_PAD_5
+#define AO_ADC_SQ7             AO_ADC_SENSE_PAD_6
+#define AO_ADC_SQ8             AO_ADC_SENSE_PAD_7
+#define AO_ADC_SQ9             AO_ADC_PYRO
+#define AO_ADC_SQ10            AO_ADC_BATT
+
+#define AO_ADC_REFERENCE_DV    33
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOBEN) | \
+                                (1 << STM_RCC_AHBENR_GPIOCEN))
+
+
+#define AO_PAD_R_V_BATT_BATT_SENSE     200
+#define AO_PAD_R_BATT_SENSE_GND                22
+
+#define AO_PAD_R_V_BATT_V_PYRO         200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     200
+#define AO_PAD_R_PYRO_SENSE_GND                22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 200
+#define AO_PAD_R_IGNITER_SENSE_GND     22
+
+#define HAS_ADC_TEMP           0
+
+struct ao_adc {
+       int16_t         sense[AO_PAD_NUM];
+       int16_t         pyro;
+       int16_t         batt;
+};
+
+#define AO_ADC_DUMP(p)                                                 \
+       printf ("tick: %5u "                                            \
+               "0: %5d 1: %5d 2: %5d 3: %5d "                          \
+               "4: %5d 5: %5d 6: %5d 7: %5d "                          \
+               "pyro: %5d batt: %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.sense[6],                                      \
+               (p)->adc.sense[7],                                      \
+               (p)->adc.pyro,                                          \
+               (p)->adc.batt)
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telefireeight-v1.0/ao_telefireeight.c b/src/telefireeight-v1.0/ao_telefireeight.c
new file mode 100644 (file)
index 0000000..bdcf321
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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; 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_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+
+       ao_task_init();
+
+       ao_timer_init();
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       ao_cmd_init();
+
+       ao_adc_init();
+
+       ao_eeprom_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_pad_init();
+
+//     ao_radio_cmac_cmd_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/telefireeight-v1.0/flash-loader/.gitignore b/src/telefireeight-v1.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..65fe7ea
--- /dev/null
@@ -0,0 +1,2 @@
+*.elf
+*.ihx
diff --git a/src/telefireeight-v1.0/flash-loader/Makefile b/src/telefireeight-v1.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..baf0e3f
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefireeight-v1.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telefireeight-v1.0/flash-loader/ao_pins.h b/src/telefireeight-v1.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..889feef
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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; 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 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioe
+#define AO_BOOT_APPLICATION_PIN                2
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 1e5c0d09bac5c943979c0341b37431e32532faa2..dedd0fad3ece4345d47e0c35f665518a6965e739 100644 (file)
 
 #define HAS_ADC_TEMP           0
 
+#define AO_ADC_REFERENCE_DV    33
+
+#define AO_PAD_R_V_BATT_BATT_SENSE     200
+#define AO_PAD_R_BATT_SENSE_GND                22
+
+#define AO_PAD_R_V_BATT_V_PYRO         200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     200
+#define AO_PAD_R_PYRO_SENSE_GND                22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 200
+#define AO_PAD_R_IGNITER_SENSE_GND     22
+
 struct ao_adc {
        int16_t         sense[AO_PAD_NUM];
        int16_t         pyro;
diff --git a/src/telelco-v0.2-cc1200/Makefile b/src/telelco-v0.2-cc1200/Makefile
new file mode 100644 (file)
index 0000000..4ccf494
--- /dev/null
@@ -0,0 +1,109 @@
+#
+# AltOS build for TeleLCO
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_companion.h \
+       ao_data.h \
+       ao_sample.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_seven_segment.h \
+       ao_lco.h \
+       ao_lco_cmd.h \
+       ao_lco_func.h \
+       ao_radio_spi.h \
+       ao_radio_cmac.h \
+       ao_cc1200_CC1200.h \
+       ao_cc1200.h \
+       stm32l.h
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_adc_single_stm.c \
+       ao_convert_volt.c \
+       ao_fast_timer.c \
+       ao_lcd_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_cc1200.c \
+       ao_radio_cmac.c \
+       ao_aes.c \
+       ao_aes_tables.c \
+       ao_fec_tx.c \
+       ao_fec_rx.c \
+       ao_seven_segment.c \
+       ao_quadrature.c \
+       ao_button.c \
+       ao_event.c \
+       ao_lco.c \
+       ao_lco_bits.c \
+       ao_lco_cmd.c \
+       ao_lco_func.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT=TeleLCO-v0.2
+PRODUCT_DEF=-DTELELCO
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telelco-v0.2
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telelco.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+../altitude.h: make-altitude
+       nickle $< > $@
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telelco-v0.2-cc1200/ao_pins.h b/src/telelco-v0.2-cc1200/ao_pins.h
new file mode 100644 (file)
index 0000000..bc325e0
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * 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; 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_
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC         32000000
+
+/* 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_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+#define HAS_AES                        1
+#define HAS_STATIC_TEST                0
+
+
+#define HAS_SPI_1              0
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+
+#define HAS_SPI_2              1       /* CC1120 */
+#define SPI_2_PB13_PB14_PB15   0
+#define SPI_2_PD1_PD3_PD4      1
+#define SPI_2_GPIO             (&stm_gpiod)
+#define SPI_2_SCK              1
+#define SPI_2_MISO             3
+#define SPI_2_MOSI             4
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define FAST_TIMER_FREQ                10000   /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpiod)
+#define AO_CC1200_SPI_CS_PIN   0
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PD1_PD3_PD4
+#define AO_CC1200_SPI          stm_spi2
+#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
+
+#define AO_CC1200_INT_PORT             (&stm_gpioc)
+#define AO_CC1200_INT_PIN              (15)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT               (&stm_gpioc)
+#define LED_PIN_RED            7
+#define LED_PIN_AMBER          8
+#define LED_PIN_GREEN          9
+#define LED_PIN_CONTINUITY_3   10
+#define LED_PIN_CONTINUITY_2   11
+#define LED_PIN_CONTINUITY_1   12
+#define LED_PIN_CONTINUITY_0   13
+#define LED_PIN_REMOTE_ARM     14
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_AMBER           (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+#define AO_LED_CONTINUITY_3    (1 << LED_PIN_CONTINUITY_3)
+#define AO_LED_CONTINUITY_2    (1 << LED_PIN_CONTINUITY_2)
+#define AO_LED_CONTINUITY_1    (1 << LED_PIN_CONTINUITY_1)
+#define AO_LED_CONTINUITY_0    (1 << LED_PIN_CONTINUITY_0)
+
+#define AO_LED_CONTINUITY_NUM  4
+
+#define AO_LED_REMOTE_ARM      (1 << LED_PIN_REMOTE_ARM)
+
+#define LEDS_AVAILABLE         (AO_LED_RED |           \
+                                AO_LED_AMBER |         \
+                                AO_LED_GREEN |         \
+                                AO_LED_CONTINUITY_3 |  \
+                                AO_LED_CONTINUITY_2 |  \
+                                AO_LED_CONTINUITY_1 |  \
+                                AO_LED_CONTINUITY_0 |  \
+                                AO_LED_REMOTE_ARM)
+
+/* LCD displays */
+
+#define LCD_DEBUG              0
+#define SEVEN_SEGMENT_DEBUG    0
+
+#define AO_LCD_STM_SEG_ENABLED_0 (             \
+               (1 << 0) | /* PA1 */            \
+               (1 << 1) | /* PA2 */            \
+               (1 << 2) | /* PA3 */            \
+               (1 << 3) | /* PA6 */            \
+               (1 << 4) | /* PA7 */            \
+               (1 << 5) | /* PB0 */            \
+               (1 << 6) | /* PB1 */            \
+               (1 << 7) | /* PB3 */            \
+               (1 << 8) | /* PB4 */            \
+               (1 << 9) | /* PB5 */            \
+               (1 << 10) | /* PB10 */          \
+               (1 << 11) | /* PB11 */          \
+               (1 << 12) | /* PB12 */          \
+               (1 << 13) | /* PB13 */          \
+               (1 << 14) | /* PB14 */          \
+               (1 << 15) | /* PB15 */          \
+               (1 << 16) | /* PB8 */           \
+               (1 << 17) | /* PA15 */          \
+               (1 << 18) | /* PC0 */           \
+               (1 << 19) | /* PC1 */           \
+               (1 << 20) | /* PC2 */           \
+               (1 << 21) | /* PC3 */           \
+               (1 << 22) | /* PC4 */           \
+               (1 << 23) | /* PC5 */           \
+               (0 << 24) | /* PC6 */           \
+               (0 << 25) | /* PC7 */           \
+               (0 << 26) | /* PC8 */           \
+               (0 << 27) | /* PC9 */           \
+               (0 << 28) | /* PC10 or PD8 */   \
+               (0 << 29) | /* PC11 or PD9 */   \
+               (0 << 30) | /* PC12 or PD10 */  \
+               (0 << 31))  /* PD2 or PD11 */
+
+#define AO_LCD_STM_SEG_ENABLED_1 (             \
+               (0 << 0) | /* PD12 */           \
+               (0 << 1) | /* PD13 */           \
+               (0 << 2) | /* PD14 */           \
+               (0 << 3) | /* PD15 */           \
+               (0 << 4) | /* PE0 */            \
+               (0 << 5) | /* PE1 */            \
+               (0 << 6) | /* PE2 */            \
+               (0 << 7))  /* PE3 */
+
+#define AO_LCD_STM_COM_ENABLED (               \
+               (1 << 0) | /* PA8 */            \
+               (0 << 1) | /* PA9 */            \
+               (0 << 2) | /* PA10 */           \
+               (0 << 3) | /* PB9 */            \
+               (0 << 4) | /* PC10 */           \
+               (0 << 5) | /* PC11 */           \
+               (0 << 6)) /* PC12 */
+
+#define AO_LCD_28_ON_C 0
+
+#define AO_LCD_DUTY    STM_LCD_CR_DUTY_STATIC
+
+#define AO_LCD_PER_DIGIT       1
+
+#define AO_LCD_DIGITS          3
+#define AO_LCD_SEGMENTS                8
+
+#define AO_SEGMENT_MAP {                       \
+               /* pad segments */              \
+               { 0, 14 },                      \
+               { 0, 13 },                      \
+               { 0, 15 },                      \
+               { 0, 17 },                      \
+               { 0, 16 },                      \
+               { 0, 8 },                       \
+               { 0, 9 },                       \
+               { 0, 7 },                       \
+               /* box1 segments */             \
+               { 0, 10 },                      \
+               { 0, 6 },                       \
+               { 0, 11 },                      \
+               { 0, 12 },                      \
+               { 0, 21 },                      \
+               { 0, 19 },                      \
+               { 0, 20 },                      \
+               { 0, 18 },                      \
+               /* box0 segments */             \
+               { 0, 22 },                      \
+               { 0, 4 },                       \
+               { 0, 23 },                      \
+               { 0, 5 },                       \
+               { 0, 3 },                       \
+               { 0, 1 },                       \
+               { 0, 2 },                       \
+               { 0, 0 },                       \
+}
+
+/*
+ * Use event queue for input devices
+ */
+
+#define AO_EVENT               1
+
+/*
+ * Knobs
+ */
+
+#define AO_QUADRATURE_COUNT    2
+
+#define AO_QUADRATURE_0_PORT   &stm_gpioe
+#define AO_QUADRATURE_0_A      3
+#define AO_QUADRATURE_0_B      2
+
+#define AO_QUADRATURE_PAD      0
+
+#define AO_QUADRATURE_1_PORT   &stm_gpioe
+#define AO_QUADRATURE_1_A      1
+#define AO_QUADRATURE_1_B      0
+
+#define AO_QUADRATURE_BOX      1
+#define AO_QUADRATURE_DEBOUNCE 10
+
+/*
+ * Buttons
+ */
+
+#define AO_BUTTON_COUNT                2
+#define AO_BUTTON_MODE         AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT       &stm_gpioe
+#define AO_BUTTON_0            4
+
+#define AO_BUTTON_ARM          0
+
+#define AO_BUTTON_1_PORT       &stm_gpioe
+#define AO_BUTTON_1            5
+
+#define AO_BUTTON_FIRE         1
+
+/* ADC */
+
+#define HAS_ADC_SINGLE         1
+#define HAS_BATTERY_REPORT     1
+
+struct ao_adc {
+       int16_t         v_batt;
+       int16_t         temp;
+       int16_t         v_ref;
+};
+
+#if HAS_ADC_SINGLE
+#define AO_ADC_DUMP(p) \
+       printf("batt: %5d temp: %5d v_ref: %5d\n", \
+              (p)->v_batt, (p)->temp, (p)->v_ref)
+#endif
+#if HAS_ADC
+#define AO_ADC_DUMP(p) \
+       printf("%5d: batt: %5d temp %5d v_ref %5d\n", \
+              (p)->tick, (p)->adc.v_batt, (p)->adc.temp, (p)->adc.v_ref)
+#endif
+
+#define HAS_ADC_TEMP           1
+
+#define AO_ADC_V_BATT          0
+#define AO_ADC_V_BATT_PORT     (&stm_gpioa)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_RCC_AHBENR      (1 << STM_RCC_AHBENR_GPIOAEN)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
+
+#define AO_ADC_SQ1             AO_ADC_V_BATT
+#define AO_ADC_SQ2             STM_ADC_SQ_TEMP
+#define AO_ADC_SQ3             STM_ADC_SQ_V_REF
+
+#define AO_NUM_ADC             3
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    15      /* 15k */
+#define AO_BATTERY_DIV_MINUS   27      /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telelco-v0.2-cc1200/ao_telelco.c b/src/telelco-v0.2-cc1200/ao_telelco.c
new file mode 100644 (file)
index 0000000..3266da0
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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; 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_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_pyro.h>
+#include <ao_aes.h>
+#include <ao_seven_segment.h>
+#include <ao_quadrature.h>
+#include <ao_button.h>
+#include <ao_lco.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+#if HAS_ADC_SINGLE
+#include <ao_adc_single.h>
+#endif
+#if HAS_ADC
+#include <ao_adc.h>
+#endif
+
+int
+main(void)
+{
+       ao_clock_init();
+       ao_task_init();
+       ao_timer_init();
+       ao_dma_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_GREEN);
+
+
+       ao_spi_init();
+       ao_exti_init();
+
+       ao_beep_init();
+       ao_cmd_init();
+
+       ao_lcd_stm_init();
+       ao_seven_segment_init();
+       ao_quadrature_init();
+       ao_button_init();
+
+       ao_adc_single_init();
+
+       ao_eeprom_init();
+
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+
+       ao_lco_init();
+       ao_lco_cmd_init();
+//     ao_radio_cmac_cmd_init();
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telelco-v0.2-cc1200/flash-loader/.gitignore b/src/telelco-v0.2-cc1200/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..a32ec26
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telelco*.elf
diff --git a/src/telelco-v0.2-cc1200/flash-loader/Makefile b/src/telelco-v0.2-cc1200/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..679e61b
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telelco-v0.2
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telelco-v0.2-cc1200/flash-loader/ao_pins.h b/src/telelco-v0.2-cc1200/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..72f840c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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; 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 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Arm switch. Press at power on to get boot loader */
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioe
+#define AO_BOOT_APPLICATION_PIN                4
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 8c1ced6c035d44a75db7e9b293f03d194adf4b59..8279cac1fd81ec7090e4e187eb4938ae794bf1a7 100644 (file)
@@ -64,6 +64,7 @@ ALTOS_SRC = \
        ao_button.c \
        ao_event.c \
        ao_lco.c \
+       ao_lco_bits.c \
        ao_lco_cmd.c \
        ao_lco_func.c \
        ao_radio_cmac_cmd.c
index b90fca8b7bcdd4b38cadfeaf18bd3878bc868fee..f0da4fe448a9625d79d37ed54dfbef585630eea3 100644 (file)
 #define AO_QUADRATURE_1_B      0
 
 #define AO_QUADRATURE_BOX      1
+#define AO_QUADRATURE_DEBOUNCE 10
 
 /*
  * Buttons
index 0bb0f9dc94816bb2878586bd970085eb3b5415dc..c2592bf86e3c1b7a3781c3a9537982227f6a8b56 100644 (file)
@@ -65,6 +65,7 @@ ALTOS_SRC = \
        ao_button.c \
        ao_event.c \
        ao_lco.c \
+       ao_lco_bits.c \
        ao_lco_cmd.c \
        ao_lco_func.c \
        ao_radio_cmac_cmd.c
index dd4aaafbbdd8b3b7c8ee4101f38d9841ce062789..6023739cb182f7d5e38ad5b5e726cb1e967bd5d9 100644 (file)
@@ -54,6 +54,8 @@
 #define HAS_RADIO_RATE         1
 #define HAS_TELEMETRY          0
 #define HAS_AES                        1
+#define HAS_STATIC_TEST                0
+
 
 #define HAS_SPI_1              0
 #define SPI_1_PA5_PA6_PA7      0
 #define AO_QUADRATURE_1_B      0
 
 #define AO_QUADRATURE_BOX      1
+#define AO_QUADRATURE_DEBOUNCE 10
 
 /*
  * Buttons
diff --git a/src/telelco-v2.0/.gitignore b/src/telelco-v2.0/.gitignore
new file mode 100644 (file)
index 0000000..a32ec26
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telelco*.elf
diff --git a/src/telelco-v2.0/Makefile b/src/telelco-v2.0/Makefile
new file mode 100644 (file)
index 0000000..43295fd
--- /dev/null
@@ -0,0 +1,106 @@
+#
+# AltOS build for TeleLCO v2.0
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_companion.h \
+       ao_data.h \
+       ao_sample.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_seven_segment.h \
+       ao_lco.h \
+       ao_lco_cmd.h \
+       ao_lco_func.h \
+       ao_radio_spi.h \
+       ao_radio_cmac.h \
+       ao_cc1200_CC1200.h \
+       ao_cc1200.h \
+       stm32l.h
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_beep_stm.c \
+       ao_eeprom_stm.c \
+       ao_adc_single_stm.c \
+       ao_convert_volt.c \
+       ao_fast_timer.c \
+       ao_lcd_stm.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_cc1200.c \
+       ao_radio_cmac.c \
+       ao_aes.c \
+       ao_aes_tables.c \
+       ao_fec_tx.c \
+       ao_fec_rx.c \
+       ao_seven_segment.c \
+       ao_quadrature.c \
+       ao_button.c \
+       ao_event.c \
+       ao_lco_bits.c \
+       ao_lco_v2.c \
+       ao_lco_cmd.c \
+       ao_lco_func.c \
+       ao_radio_cmac_cmd.c
+
+PRODUCT=TeleLCO-v2.0
+PRODUCT_DEF=-DTELELCO
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telelco-v2.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telelco.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/telelco-v2.0/ao_lco_v2.c b/src/telelco-v2.0/ao_lco_v2.c
new file mode 100644 (file)
index 0000000..a9933d5
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * 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; 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_lco.h>
+#include <ao_event.h>
+#include <ao_seven_segment.h>
+#include <ao_quadrature.h>
+#include <ao_radio_cmac.h>
+#include <ao_adc_single.h>
+
+#define AO_LCO_PAD_DIGIT       0
+#define AO_LCO_BOX_DIGIT_1     1
+#define AO_LCO_BOX_DIGIT_10    2
+
+#define AO_LCO_DRAG_RACE_START_TIME    AO_SEC_TO_TICKS(5)
+#define AO_LCO_DRAG_RACE_STOP_TIME     AO_SEC_TO_TICKS(2)
+
+/* UI values */
+static uint8_t ao_lco_select_mode;
+#define AO_LCO_SELECT_PAD      0
+#define AO_LCO_SELECT_BOX      1
+
+static uint8_t ao_lco_display_mutex;
+
+void
+ao_lco_show_pad(uint8_t pad)
+{
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad | (ao_lco_drag_race << 4));
+       ao_mutex_put(&ao_lco_display_mutex);
+}
+
+#define SEVEN_SEGMENT_d                ((0 << 0) |     \
+                                (0 << 1) |     \
+                                (1 << 2) |     \
+                                (1 << 3) |     \
+                                (1 << 4) |     \
+                                (1 << 5) |     \
+                                (1 << 6))
+
+
+#define SEVEN_SEGMENT_r                ((0 << 0) |     \
+                                (0 << 1) |     \
+                                (0 << 2) |     \
+                                (1 << 3) |     \
+                                (1 << 4) |     \
+                                (0 << 5) |     \
+                                (0 << 6))
+
+void
+ao_lco_show_box(uint16_t box)
+{
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10 | (ao_lco_drag_race << 4));
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10 | (ao_lco_drag_race << 4));
+       ao_mutex_put(&ao_lco_display_mutex);
+}
+
+static void
+ao_lco_show_voltage(uint16_t decivolts)
+{
+       uint8_t tens, ones, tenths;
+
+       PRINTD("voltage %d\n", decivolts);
+       tenths = decivolts % 10;
+       ones = (decivolts / 10) % 10;
+       tens = (decivolts / 100) % 10;
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_PAD_DIGIT, tenths);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ones | 0x10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, tens);
+       ao_mutex_put(&ao_lco_display_mutex);
+}
+
+void
+ao_lco_show(void)
+{
+       if (ao_lco_pad == AO_LCO_PAD_VOLTAGE) {
+               ao_lco_show_voltage(ao_pad_query.battery);
+       } else {
+               ao_lco_show_pad(ao_lco_pad);
+               ao_lco_show_box(ao_lco_box);
+       }
+}
+
+uint8_t
+ao_lco_box_present(uint16_t box)
+{
+       if (box >= AO_PAD_MAX_BOXES)
+               return 0;
+       return (ao_lco_box_mask[AO_LCO_MASK_ID(box)] >> AO_LCO_MASK_SHIFT(box)) & 1;
+}
+
+static void
+ao_lco_set_select(void)
+{
+       if (ao_lco_armed) {
+               ao_led_off(AO_LED_PAD);
+               ao_led_off(AO_LED_BOX);
+       } else {
+               switch (ao_lco_select_mode) {
+               case AO_LCO_SELECT_PAD:
+                       ao_led_off(AO_LED_BOX);
+                       ao_led_on(AO_LED_PAD);
+                       break;
+               case AO_LCO_SELECT_BOX:
+                       ao_led_off(AO_LED_PAD);
+                       ao_led_on(AO_LED_BOX);
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+static void
+ao_lco_step_box(int8_t dir)
+{
+       int16_t new_box = ao_lco_box;
+
+       do {
+               new_box += dir;
+               if (new_box > ao_lco_max_box)
+                       new_box = ao_lco_min_box;
+               else if (new_box < ao_lco_min_box)
+                       new_box = ao_lco_max_box;
+               if (new_box == ao_lco_box)
+                       break;
+       } while (!ao_lco_box_present(new_box));
+       ao_lco_set_box(new_box);
+}
+
+static struct ao_task  ao_lco_drag_task;
+
+static void
+ao_lco_drag_monitor(void)
+{
+       uint16_t        delay = ~0;
+       uint16_t        now;
+
+       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+       for (;;) {
+               PRINTD("Drag monitor count %d delay %d\n", ao_lco_drag_beep_count, delay);
+               if (delay == (uint16_t) ~0)
+                       ao_sleep(&ao_lco_drag_beep_count);
+               else
+                       ao_sleep_for(&ao_lco_drag_beep_count, delay);
+
+               delay = ~0;
+               now = ao_time();
+               delay = ao_lco_drag_warn_check(now, delay);
+               delay = ao_lco_drag_beep_check(now, delay);
+       }
+}
+
+static void
+ao_lco_input(void)
+{
+       static struct ao_event  event;
+
+       for (;;) {
+               ao_event_get(&event);
+               PRINTD("event type %d unit %d value %d\n",
+                      event.type, event.unit, event.value);
+               switch (event.type) {
+               case AO_EVENT_QUADRATURE:
+                       switch (event.unit) {
+                       case AO_QUADRATURE_SELECT:
+                               if (!ao_lco_armed) {
+                                       switch (ao_lco_select_mode) {
+                                       case AO_LCO_SELECT_PAD:
+                                               ao_lco_step_pad((int8_t) event.value);
+                                               break;
+                                       case AO_LCO_SELECT_BOX:
+                                               ao_lco_step_box((int8_t) event.value);
+                                               break;
+                                       default:
+                                               break;
+                                       }
+                               }
+                               break;
+                       }
+                       break;
+               case AO_EVENT_BUTTON:
+                       switch (event.unit) {
+                       case AO_BUTTON_ARM:
+                               ao_lco_set_armed(event.value);
+                               ao_lco_set_select();
+                               break;
+                       case AO_BUTTON_FIRE:
+                               if (ao_lco_armed)
+                                       ao_lco_set_firing(event.value);
+                               break;
+                       case AO_BUTTON_DRAG_SELECT:
+                               if (event.value)
+                                       ao_lco_toggle_drag();
+                               break;
+                       case AO_BUTTON_DRAG_MODE:
+                               if (event.value)
+                                       ao_lco_drag_enable();
+                               else
+                                       ao_lco_drag_disable();
+                               break;
+                       case AO_BUTTON_ENCODER_SELECT:
+                               if (event.value) {
+                                       if (!ao_lco_armed) {
+                                               ao_lco_select_mode = 1 - ao_lco_select_mode;
+                                               ao_lco_set_select();
+                                       }
+                               }
+                               break;
+                       }
+                       break;
+               }
+       }
+}
+
+/*
+ * Light up everything for a second at power on to let the user
+ * visually inspect the system for correct operation
+ */
+static void
+ao_lco_display_test()
+{
+       ao_mutex_get(&ao_lco_display_mutex);
+       ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, 8 | 0x10);
+       ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 8 | 0x10);
+       ao_mutex_put(&ao_lco_display_mutex);
+       ao_led_on(LEDS_AVAILABLE);
+       ao_delay(AO_MS_TO_TICKS(1000));
+       ao_led_off(LEDS_AVAILABLE);
+}
+
+static void
+ao_lco_batt_voltage(void)
+{
+       struct ao_adc   packet;
+       int16_t         decivolt;
+
+       ao_adc_single_get(&packet);
+       decivolt = ao_battery_decivolt(packet.v_batt);
+       ao_lco_show_voltage(decivolt);
+       ao_delay(AO_MS_TO_TICKS(1000));
+}
+
+static struct ao_task ao_lco_input_task;
+static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_arm_warn_task;
+static struct ao_task ao_lco_igniter_status_task;
+
+static void
+ao_lco_main(void)
+{
+       ao_lco_display_test();
+       ao_lco_batt_voltage();
+       ao_lco_search();
+       ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
+       ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
+       ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
+       ao_add_task(&ao_lco_drag_task, ao_lco_drag_monitor, "drag race");
+       ao_lco_monitor();
+}
+
+#if DEBUG
+void
+ao_lco_set_debug(void)
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status == ao_cmd_success)
+               ao_lco_debug = ao_cmd_lex_i != 0;
+}
+
+__code struct ao_cmds ao_lco_cmds[] = {
+       { ao_lco_set_debug,     "D <0 off, 1 on>\0Debug" },
+       { ao_lco_search,        "s\0Search for pad boxes" },
+       { 0, NULL }
+};
+#endif
+
+void
+ao_lco_init(void)
+{
+       ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
+#if DEBUG
+       ao_cmd_register(&ao_lco_cmds[0]);
+#endif
+}
diff --git a/src/telelco-v2.0/ao_pins.h b/src/telelco-v2.0/ao_pins.h
new file mode 100644 (file)
index 0000000..95998dc
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * 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; 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_
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC         40000000
+
+/* 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_EEPROM             1
+#define USE_INTERNAL_FLASH     1
+#define USE_EEPROM_CONFIG      1
+#define USE_STORAGE_CONFIG     0
+#define HAS_USB                        1
+#define HAS_BEEP               1
+#define HAS_RADIO              1
+#define HAS_RADIO_RATE         1
+#define HAS_TELEMETRY          0
+#define HAS_AES                        1
+#define HAS_STATIC_TEST                0
+
+#define HAS_SPI_1              0
+#define SPI_1_PA5_PA6_PA7      0
+#define SPI_1_PB3_PB4_PB5      0
+#define SPI_1_PE13_PE14_PE15   0
+
+#define HAS_SPI_2              1       /* CC1200 */
+#define SPI_2_PB13_PB14_PB15   0
+#define SPI_2_PD1_PD3_PD4      1
+#define SPI_2_GPIO             (&stm_gpiod)
+#define SPI_2_SCK              1
+#define SPI_2_MISO             3
+#define SPI_2_MOSI             4
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1              0
+
+#define HAS_I2C_2              0
+
+#define PACKET_HAS_SLAVE       0
+#define PACKET_HAS_MASTER      0
+
+#define FAST_TIMER_FREQ                10000   /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT   5695733
+
+#define AO_CC1200_SPI_CS_PORT  (&stm_gpiod)
+#define AO_CC1200_SPI_CS_PIN   0
+#define AO_CC1200_SPI_BUS      AO_SPI_2_PD1_PD3_PD4
+#define AO_CC1200_SPI          stm_spi2
+#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
+
+#define AO_CC1200_INT_PORT             (&stm_gpiod)
+#define AO_CC1200_INT_PIN              (5)
+
+#define AO_CC1200_INT_GPIO     2
+#define AO_CC1200_INT_GPIO_IOCFG       CC1200_IOCFG2
+
+#define LOW_LEVEL_DEBUG                0
+
+#define LED_PER_LED            1
+#define LED_TYPE               uint16_t
+
+#define LED_ENABLE_BITS                ((1 << STM_RCC_AHBENR_GPIOAEN) |        \
+                                (1 << STM_RCC_AHBENR_GPIOCEN) |        \
+                                (1 << STM_RCC_AHBENR_GPIODEN) |        \
+                                (1 << STM_RCC_AHBENR_GPIOEEN))
+
+/* PC7 - PC9, LED 0 - 2 */
+#define LED_0_PORT             (&stm_gpioc)
+#define LED_0_PIN              7
+#define LED_1_PORT             (&stm_gpioc)
+#define LED_1_PIN              8
+#define LED_2_PORT             (&stm_gpioc)
+#define LED_2_PIN              9
+
+/* PD8 - PD10, LED 3 - 5 */
+#define LED_3_PORT             (&stm_gpiod)
+#define LED_3_PIN              8
+#define LED_4_PORT             (&stm_gpiod)
+#define LED_4_PIN              9
+#define LED_5_PORT             (&stm_gpiod)
+#define LED_5_PIN              10
+
+/* PE2 - PE11 (not PE6), LED 6-14 */
+#define LED_6_PORT             (&stm_gpioe)
+#define LED_6_PIN              2
+#define LED_7_PORT             (&stm_gpioe)
+#define LED_7_PIN              3
+#define LED_8_PORT             (&stm_gpioe)
+#define LED_8_PIN              4
+#define LED_9_PORT             (&stm_gpioe)
+#define LED_9_PIN              5
+#define LED_10_PORT            (&stm_gpioe)
+#define LED_10_PIN             7
+#define LED_11_PORT            (&stm_gpioe)
+#define LED_11_PIN             8
+#define LED_12_PORT            (&stm_gpioe)
+#define LED_12_PIN             9
+#define LED_13_PORT            (&stm_gpioe)
+#define LED_13_PIN             10
+#define LED_14_PORT            (&stm_gpioe)
+#define LED_14_PIN             11
+
+/* PA5, LED 15 */
+#define LED_15_PORT            (&stm_gpioa)
+#define LED_15_PIN             5
+
+#define LED_PIN_RED            0
+#define LED_PIN_AMBER          1
+#define LED_PIN_GREEN          2
+#define LED_PIN_BOX            3
+#define LED_PIN_PAD            4
+#define LED_PIN_DRAG           5
+#define LED_PIN_CONTINUITY_7   6
+#define LED_PIN_CONTINUITY_6   7
+#define LED_PIN_CONTINUITY_5   8
+#define LED_PIN_CONTINUITY_4   9
+#define LED_PIN_CONTINUITY_3   10
+#define LED_PIN_CONTINUITY_2   11
+#define LED_PIN_CONTINUITY_1   12
+#define LED_PIN_CONTINUITY_0   13
+#define LED_PIN_REMOTE_ARM     14
+#define LED_PIN_FIRE           15
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_AMBER           (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+#define AO_LED_BOX             (1 << LED_PIN_BOX)
+#define AO_LED_PAD             (1 << LED_PIN_PAD)
+#define AO_LED_DRAG            (1 << LED_PIN_DRAG)
+#define AO_LED_CONTINUITY_7    (1 << LED_PIN_CONTINUITY_7)
+#define AO_LED_CONTINUITY_6    (1 << LED_PIN_CONTINUITY_6)
+#define AO_LED_CONTINUITY_5    (1 << LED_PIN_CONTINUITY_5)
+#define AO_LED_CONTINUITY_4    (1 << LED_PIN_CONTINUITY_4)
+#define AO_LED_CONTINUITY_3    (1 << LED_PIN_CONTINUITY_3)
+#define AO_LED_CONTINUITY_2    (1 << LED_PIN_CONTINUITY_2)
+#define AO_LED_CONTINUITY_1    (1 << LED_PIN_CONTINUITY_1)
+#define AO_LED_CONTINUITY_0    (1 << LED_PIN_CONTINUITY_0)
+#define AO_LED_CONTINUITY_NUM  8
+#define AO_LED_REMOTE_ARM      (1 << LED_PIN_REMOTE_ARM)
+#define AO_LED_FIRE            (1 << LED_PIN_FIRE)
+
+#define LEDS_AVAILABLE         (AO_LED_RED |           \
+                                AO_LED_AMBER |         \
+                                AO_LED_GREEN |         \
+                                AO_LED_BOX |           \
+                                AO_LED_PAD |           \
+                                AO_LED_DRAG |          \
+                                AO_LED_CONTINUITY_7 |  \
+                                AO_LED_CONTINUITY_6 |  \
+                                AO_LED_CONTINUITY_5 |  \
+                                AO_LED_CONTINUITY_4 |  \
+                                AO_LED_CONTINUITY_3 |  \
+                                AO_LED_CONTINUITY_2 |  \
+                                AO_LED_CONTINUITY_1 |  \
+                                AO_LED_CONTINUITY_0 |  \
+                                AO_LED_REMOTE_ARM |    \
+                                AO_LED_FIRE)
+
+/* LCD displays */
+
+#define LCD_DEBUG              0
+#define SEVEN_SEGMENT_DEBUG    0
+
+#define AO_LCD_STM_SEG_ENABLED_0 (             \
+               (1 << 0) | /* PA1 */            \
+               (1 << 1) | /* PA2 */            \
+               (1 << 2) | /* PA3 */            \
+               (1 << 3) | /* PA6 */            \
+               (1 << 4) | /* PA7 */            \
+               (1 << 5) | /* PB0 */            \
+               (1 << 6) | /* PB1 */            \
+               (1 << 7) | /* PB3 */            \
+               (1 << 8) | /* PB4 */            \
+               (1 << 9) | /* PB5 */            \
+               (1 << 10) | /* PB10 */          \
+               (1 << 11) | /* PB11 */          \
+               (1 << 12) | /* PB12 */          \
+               (1 << 13) | /* PB13 */          \
+               (1 << 14) | /* PB14 */          \
+               (1 << 15) | /* PB15 */          \
+               (1 << 16) | /* PB8 */           \
+               (1 << 17) | /* PA15 */          \
+               (1 << 18) | /* PC0 */           \
+               (1 << 19) | /* PC1 */           \
+               (1 << 20) | /* PC2 */           \
+               (1 << 21) | /* PC3 */           \
+               (1 << 22) | /* PC4 */           \
+               (1 << 23) | /* PC5 */           \
+               (0 << 24) | /* PC6 */           \
+               (0 << 25) | /* PC7 */           \
+               (0 << 26) | /* PC8 */           \
+               (0 << 27) | /* PC9 */           \
+               (0 << 28) | /* PC10 or PD8 */   \
+               (0 << 29) | /* PC11 or PD9 */   \
+               (0 << 30) | /* PC12 or PD10 */  \
+               (0 << 31))  /* PD2 or PD11 */
+
+#define AO_LCD_STM_SEG_ENABLED_1 (             \
+               (0 << 0) | /* PD12 */           \
+               (0 << 1) | /* PD13 */           \
+               (0 << 2) | /* PD14 */           \
+               (0 << 3) | /* PD15 */           \
+               (0 << 4) | /* PE0 */            \
+               (0 << 5) | /* PE1 */            \
+               (0 << 6) | /* PE2 */            \
+               (0 << 7))  /* PE3 */
+
+#define AO_LCD_STM_COM_ENABLED (               \
+               (1 << 0) | /* PA8 */            \
+               (0 << 1) | /* PA9 */            \
+               (0 << 2) | /* PA10 */           \
+               (0 << 3) | /* PB9 */            \
+               (0 << 4) | /* PC10 */           \
+               (0 << 5) | /* PC11 */           \
+               (0 << 6)) /* PC12 */
+
+#define AO_LCD_28_ON_C 0
+
+#define AO_LCD_DUTY    STM_LCD_CR_DUTY_STATIC
+
+#define AO_LCD_PER_DIGIT       1
+
+#define AO_LCD_DIGITS          3
+#define AO_LCD_SEGMENTS                8
+
+#define AO_SEGMENT_MAP {                       \
+               /* pad segments */              \
+               { 0, 14 },                      \
+               { 0, 13 },                      \
+               { 0, 15 },                      \
+               { 0, 17 },                      \
+               { 0, 16 },                      \
+               { 0, 8 },                       \
+               { 0, 9 },                       \
+               { 0, 7 },                       \
+               /* box1 segments */             \
+               { 0, 10 },                      \
+               { 0, 6 },                       \
+               { 0, 11 },                      \
+               { 0, 12 },                      \
+               { 0, 21 },                      \
+               { 0, 19 },                      \
+               { 0, 20 },                      \
+               { 0, 18 },                      \
+               /* box0 segments */             \
+               { 0, 22 },                      \
+               { 0, 4 },                       \
+               { 0, 23 },                      \
+               { 0, 5 },                       \
+               { 0, 3 },                       \
+               { 0, 1 },                       \
+               { 0, 2 },                       \
+               { 0, 0 },                       \
+}
+
+/*
+ * Use event queue for input devices
+ */
+
+#define AO_EVENT               1
+
+/*
+ * Knobs
+ */
+
+#define AO_QUADRATURE_COUNT    1
+#define AO_QUADRATURE_DEBOUNCE 0
+#define AO_QUADRATURE_SINGLE_CODE      1
+
+#define AO_QUADRATURE_0_PORT   &stm_gpioe
+#define AO_QUADRATURE_0_A      15
+#define AO_QUADRATURE_0_B      14
+
+#define AO_QUADRATURE_SELECT   0
+
+/*
+ * Buttons
+ */
+
+#define AO_BUTTON_COUNT                9
+#define AO_BUTTON_MODE         AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_DRAG_MODE    0
+#define AO_BUTTON_0_PORT       &stm_gpioe
+#define AO_BUTTON_0            1
+
+#define AO_BUTTON_DRAG_SELECT  1
+#define AO_BUTTON_1_PORT       &stm_gpioe
+#define AO_BUTTON_1            0
+
+#define AO_BUTTON_SPARE1               2
+#define AO_BUTTON_2_PORT       &stm_gpiob
+#define AO_BUTTON_2            9
+
+#define AO_BUTTON_SPARE2       3
+#define AO_BUTTON_3_PORT       &stm_gpiob
+#define AO_BUTTON_3            7
+
+#define AO_BUTTON_SPARE3               4
+#define AO_BUTTON_4_PORT       &stm_gpiob
+#define AO_BUTTON_4            6
+
+#define AO_BUTTON_ARM          5
+#define AO_BUTTON_5_PORT       &stm_gpioe
+#define AO_BUTTON_5            12
+
+#define AO_BUTTON_FIRE         6
+#define AO_BUTTON_6_PORT       &stm_gpioa
+#define AO_BUTTON_6            4
+
+#define AO_BUTTON_SPARE4       7
+#define AO_BUTTON_7_PORT       &stm_gpiod
+#define AO_BUTTON_7            11
+
+#define AO_BUTTON_ENCODER_SELECT       8
+#define AO_BUTTON_8_PORT       &stm_gpioe
+#define AO_BUTTON_8            13
+
+/* ADC */
+
+struct ao_adc {
+       int16_t         v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("batt: %5d\n", (p)->v_batt)
+
+#define HAS_ADC_SINGLE         1
+#define HAS_ADC_TEMP           0
+#define HAS_BATTERY_REPORT     1
+
+#define AO_ADC_V_BATT          0
+#define AO_ADC_V_BATT_PORT     (&stm_gpioa)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_RCC_AHBENR      (1 << STM_RCC_AHBENR_GPIOAEN)
+
+#define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
+
+#define AO_ADC_SQ1             AO_ADC_V_BATT
+
+#define AO_NUM_ADC             1
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    15      /* 15k */
+#define AO_BATTERY_DIV_MINUS   27      /* 27k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/telelco-v2.0/ao_telelco.c b/src/telelco-v2.0/ao_telelco.c
new file mode 100644 (file)
index 0000000..9693c65
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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; 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_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_pyro.h>
+#include <ao_aes.h>
+#include <ao_seven_segment.h>
+#include <ao_quadrature.h>
+#include <ao_button.h>
+#include <ao_lco.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+#include <ao_adc_single.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+       
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_GREEN);
+       ao_task_init();
+
+       ao_timer_init();
+
+       ao_spi_init();
+       ao_dma_init();
+       ao_exti_init();
+       ao_adc_single_init();
+
+       ao_beep_init();
+       ao_cmd_init();
+
+       ao_lcd_stm_init();
+       ao_seven_segment_init();
+       ao_quadrature_init();
+       ao_button_init();
+
+       ao_eeprom_init();
+       
+       ao_radio_init();
+
+       ao_usb_init();
+
+       ao_config_init();
+       
+       ao_lco_init();
+       ao_lco_cmd_init();
+//     ao_radio_cmac_cmd_init();
+       
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/telelco-v2.0/flash-loader/.gitignore b/src/telelco-v2.0/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..a32ec26
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+telelco*.elf
diff --git a/src/telelco-v2.0/flash-loader/Makefile b/src/telelco-v2.0/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..b4ec2da
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telelco-v2.0
+include $(TOPDIR)/stm/Makefile-flash.defs
diff --git a/src/telelco-v2.0/flash-loader/ao_pins.h b/src/telelco-v2.0/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..2292f03
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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; 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 8MHz */
+#define AO_HSE         8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Drag race select button. Press at power on to get boot loader */
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       stm_gpioe
+#define AO_BOOT_APPLICATION_PIN                0
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
index 42188bb2632d5017cc1d4bbeee263102bff37489..c68f3eb5dd1dae776b262b0458e12c9b861573b0 100644 (file)
@@ -58,6 +58,7 @@ ALTOS_SRC = \
        ao_button.c \
        ao_event.c \
        ao_lco_two.c \
+       ao_lco_bits.c \
        ao_lco_func.c \
        ao_lco_cmd.c \
        ao_radio_cmac_cmd.c
index 60e94c67eac90136988365ccc4bdd7c15c3cc4b4..1941e03d7468c2aa9ea5f032be97ea2ba3c9f5b9 100644 (file)
                                 AO_LED_CONTINUITY_0 |  \
                                 AO_LED_REMOTE_ARM)
 
+#define AO_LCO_DRAG            0
+
 /*
  * Use event queue for input devices
  */
index 2d862f82a944f5663281273bbcf52b1c45b859a7..746a681463ab4d2238f3f457c3470b9e15fcc07b 100644 (file)
@@ -305,7 +305,7 @@ struct ao_task {
 #define AO_MS_TO_TICKS(ms)     ((ms) / 10)
 #define AO_SEC_TO_TICKS(s)     ((s) * 100)
 
-#define AO_FLIGHT_TEST
+#define AO_FLIGHT_TEST 1
 
 int    ao_flight_debug;
 
@@ -438,10 +438,6 @@ static uint16_t    pyros_fired;
 static struct ao_mpu6000_sample        ao_ground_mpu6000;
 #endif
 
-#if HAS_ACCEL
-int ao_error_h_sq_avg;
-#endif
-
 void
 ao_test_exit(void)
 {
@@ -504,7 +500,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 +511,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 +654,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 +664,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,
index 95337f10eca7be43ea1f28bb05b202a4715c9d73..5b30cfa546923713c8273b1842ba644bff293f1e 100755 (executable)
@@ -1,17 +1,33 @@
+#!/bin/bash
+
+LINEWIDTH=2
+
 gnuplot -persist << EOF
+set title "$1"
 set ylabel "altitude (m)"
 set y2label "velocity (m/s), acceleration(m/s²)"
 set xlabel "time (s)"
 set xtics border out nomirror
 set ytics border out nomirror
 set y2tics border out nomirror
-plot "$1" using 1:3 with lines axes x1y1 title "raw height",\
-"$1" using 1:5 with lines axes x1y2 title "raw accel",\
-"$1" using 1:7 with lines axes x1y2 title "accel speed",\
-"$1" using 1:11 with lines axes x1y1 title "height",\
-"$1" using 1:13 with lines axes x1y2 title "speed",\
-"$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"
+set style line 1 linewidth $LINEWIDTH
+set style line 2 linewidth $LINEWIDTH
+set style line 3 linewidth $LINEWIDTH
+set style line 4 linewidth $LINEWIDTH
+set style line 5 linewidth $LINEWIDTH
+set style line 6 linewidth $LINEWIDTH
+set style line 7 linewidth $LINEWIDTH dashtype 2
+set style line 8 linewidth $LINEWIDTH dashtype 2
+set style line 9 linewidth $LINEWIDTH dashtype 2
+set style line 10 linewidth $LINEWIDTH dashtype 2
+plot "$1" using 1:3 with lines axes x1y1 title "raw height" ls 1,\
+"$1" using 1:5 with lines axes x1y2 title "raw accel" ls 2,\
+"$1" using 1:7 with lines axes x1y2 title "accel speed" ls 3,\
+"$1" using 1:11 with lines axes x1y1 title "height" ls 4,\
+"$1" using 1:13 with lines axes x1y2 title "speed" ls 5,\
+"$1" using 1:15 with lines axes x1y2 title "accel" ls 6,\
+"$1" using 1:19 with lines axes x1y1 title "drogue" ls 7,\
+"$1" using 1:21 with lines axes x1y1 title "main" ls 8,\
+"$1" using 1:23 with lines axes x1y1 title "error" ls 9,\
+"$1" using 1:9 with lines axes x1y2 title "state" ls 10
 EOF
diff --git a/src/tmgps-v2.0/.gitignore b/src/tmgps-v2.0/.gitignore
new file mode 100644 (file)
index 0000000..611e845
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+tmgps-*.elf
diff --git a/src/tmgps-v2.0/Makefile b/src/tmgps-v2.0/Makefile
new file mode 100644 (file)
index 0000000..9e3965c
--- /dev/null
@@ -0,0 +1,117 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_companion.h \
+       ao_data.h \
+       ao_sample.h \
+       ao_pins.h \
+       ao_kalman.h \
+       ao_product.h \
+       ao_cc1120_CC1120.h \
+       ao_profile.h \
+       ao_task.h \
+       ao_whiten.h \
+       ao_sample_profile.h \
+       ao_mpu.h \
+       stm32l.h \
+       Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+#      ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+MATH_SRC=\
+       ef_log.c
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_config.c \
+       ao_task.c \
+       ao_led.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_serial_stm.c \
+       ao_gps_ublox.c \
+       ao_gps_show.c \
+       ao_freq.c \
+       ao_dma_stm.c \
+       ao_spi_stm.c \
+       ao_cc1120.c \
+       ao_fec_tx.c \
+       ao_fec_rx.c \
+       ao_data.c \
+       ao_adc_stm.c \
+       ao_storage.c \
+       ao_m25.c \
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_eeprom_stm.c \
+       ao_convert_volt.c \
+       ao_log.c \
+       ao_log_gps.c \
+       ao_distance.c \
+       ao_sqrt.c \
+       ao_tracker.c \
+       ao_telemetry.c \
+       ao_aprs.c \
+       $(MATH_SRC) \
+       $(PROFILE) \
+       $(SAMPLE_PROFILE) \
+       $(STACK_GUARD)
+
+PRODUCT=TMGPS-v2.0
+PRODUCT_DEF=-DTMGPS_V_2_0
+IDPRODUCT=0x0025
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=tmgps-v2.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_tmgps.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+../altitude-pa.h: make-altitude-pa
+       nickle $< > $@
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/tmgps-v2.0/ao_pins.h b/src/tmgps-v2.0/ao_pins.h
new file mode 100644 (file)
index 0000000..b4dcc10
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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; 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_
+
+#define HAS_TASK_QUEUE         1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE                 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL              12
+#define AO_RCC_CFGR_PLLMUL     (STM_RCC_CFGR_PLLMUL_12)
+
+/* 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      1
+
+#define HAS_SERIAL_2           0
+#define USE_SERIAL_2_STDIN     0
+#define SERIAL_2_PA2_PA3       0
+#define SERIAL_2_PD5_PD6       0
+
+#define HAS_SERIAL_3           1
+#define USE_SERIAL_3_STDIN     0
+#define SERIAL_3_PB10_PB11     1
+#define SERIAL_3_PC10_PC11     0
+#define SERIAL_3_PD8_PD9       0
+
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       (512 * 1024)
+#define AO_CONFIG_MAX_SIZE                     1024
+#define LOG_ERASE_MARK                         0x55
+#define LOG_MAX_ERASE                          128
+
+#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               0
+#define HAS_RADIO              1
+#define HAS_TELEMETRY          1
+#define HAS_RDF                        1
+#define HAS_APRS               1
+#define HAS_COMPANION          0
+
+#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   0
+#define SPI_1_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2              1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion, Radio */
+#define SPI_2_PD1_PD3_PD4      0
+#define SPI_2_OSPEEDR          STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT             (&stm_gpiob)
+#define SPI_2_SCK_PIN          13
+#define SPI_2_MISO_PIN         14
+#define SPI_2_MOSI_PIN         15
+
+#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       0
+#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            14
+#define LED_PIN_GREEN          15
+#define AO_LED_RED             (1 << LED_PIN_RED)
+#define AO_LED_GREEN           (1 << LED_PIN_GREEN)
+
+#define AO_LED_PANIC   AO_LED_RED
+#define AO_LED_GPS_LOCK        AO_LED_GREEN
+
+#define LEDS_AVAILABLE         (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS                        1
+#define HAS_FLIGHT             0
+#define HAS_ADC                        1
+#define HAS_ADC_TEMP           0
+#define HAS_LOG                        1
+#define HAS_TRACKER            1
+#define LOG_ADC                        0
+#define AO_LOG_FORMAT                          AO_LOG_FORMAT_TELEGPS
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING           32
+#define AO_ADC_NUM_SENSE       2
+
+struct ao_adc {
+       int16_t                 v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+       printf("tick: %5u batt: %5d\n", \
+              (p)->tick, \
+              (p)->adc.v_batt);
+
+#define AO_ADC_V_BATT          8
+#define AO_ADC_V_BATT_PORT     (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN      0
+
+#define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOBEN))
+
+#define AO_NUM_ADC_PIN         1
+
+#define AO_ADC_PIN0_PORT       AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN                AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC             (AO_NUM_ADC_PIN)
+
+#define AO_ADC_SQ1             AO_ADC_V_BATT
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS    56      /* 5.6k */
+#define AO_BATTERY_DIV_MINUS   100     /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV    33
+
+/*
+ * GPS
+ */
+
+#define AO_SERIAL_SPEED_UBLOX  AO_SERIAL_SPEED_9600
+
+#define ao_gps_getchar         ao_serial3_getchar
+#define ao_gps_putchar         ao_serial3_putchar
+#define ao_gps_set_speed       ao_serial3_set_speed
+#define ao_gps_fifo            (ao_stm_usart3.rx_fifo)
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS          1
+#define AO_M25_SPI_CS_PORT     (&stm_gpiob)
+#define AO_M25_SPI_CS_MASK     (1 << 8)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * Radio (cc1120)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT   0x6ca333
+
+#define AO_FEC_DEBUG           0
+#define AO_CC1120_SPI_CS_PORT  (&stm_gpioa)
+#define AO_CC1120_SPI_CS_PIN   2
+#define AO_CC1120_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1120_SPI          stm_spi2
+
+#define AO_CC1120_INT_PORT             (&stm_gpioa)
+#define AO_CC1120_INT_PIN              (3)
+#define AO_CC1120_MCU_WAKEUP_PORT      (&stm_gpioa)
+#define AO_CC1120_MCU_WAKEUP_PIN       (4)
+
+#define AO_CC1120_INT_GPIO     2
+#define AO_CC1120_INT_GPIO_IOCFG       CC1120_IOCFG2
+
+#define AO_CC1120_MARC_GPIO    3
+#define AO_CC1120_MARC_GPIO_IOCFG      CC1120_IOCFG3
+
+#define HAS_BOOT_RADIO         0
+
+#define NUM_CMDS               16
+
+/*
+ * 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
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/tmgps-v2.0/ao_tmgps.c b/src/tmgps-v2.0/ao_tmgps.c
new file mode 100644 (file)
index 0000000..cbd58eb
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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; 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_log.h>
+#include <ao_exti.h>
+#include <ao_tracker.h>
+#include <ao_eeprom.h>
+#include <ao_profile.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
+
+int
+main(void)
+{
+       ao_clock_init();
+
+#if HAS_STACK_GUARD
+       ao_mpu_init();
+#endif
+
+       ao_task_init();
+       ao_cmd_init();
+       ao_config_init();
+
+       /* Turn on all of the LEDs to test them */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(LEDS_AVAILABLE);
+
+       /* Internal systems */
+       ao_timer_init();
+       ao_dma_init();
+       ao_exti_init();
+
+       /* SoC hardware */
+       ao_spi_init();
+       ao_adc_init();
+       ao_serial_init();
+       ao_usb_init();
+       ao_eeprom_init();
+
+       /* External hardware */
+       ao_storage_init();
+       ao_radio_init();
+       ao_gps_init();
+
+       /* Services */
+       ao_log_init();
+       ao_telemetry_init();
+       ao_tracker_init();
+
+#if AO_PROFILE
+       ao_profile_init();
+#endif
+#if HAS_SAMPLE_PROFILE
+       ao_sample_profile_init();
+#endif
+       ao_led_off(LEDS_AVAILABLE);
+
+       ao_start_scheduler();
+       return 0;
+}
diff --git a/src/vidtime/.gitignore b/src/vidtime/.gitignore
new file mode 100644 (file)
index 0000000..471b7fd
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+vidtime-*
diff --git a/src/vidtime/Makefile b/src/vidtime/Makefile
new file mode 100644 (file)
index 0000000..327614b
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_boot.h \
+       ao_pins.h \
+       ao_product.h \
+       ao_task.h \
+       stm32f0.h \
+       Makefile
+
+ALTOS_SRC = \
+       ao_boot_chain.c \
+       ao_interrupt.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_cmd.c \
+       ao_dma_stm.c \
+       ao_exti_stm.c \
+       ao_task.c \
+       ao_stdio.c \
+       ao_panic.c \
+       ao_timer.c \
+       ao_mutex.c \
+       ao_usb_stm.c
+
+PRODUCT=VidTime
+PRODUCT_DEF=-DVIDTIME
+IDPRODUCT=0x002b
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g
+
+PROGNAME=vidtime-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_vidtime.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/vidtime/ao_pins.h b/src/vidtime/ao_pins.h
new file mode 100644 (file)
index 0000000..fe9d387
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE         1
+
+#define IS_FLASH_LOADER        0
+
+#define AO_POWER_MANAGEMENT    0
+
+/* 48MHz clock based on USB */
+#define AO_HSI48       1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_EEPROM             0
+#define USE_INTERNAL_FLASH     0
+#define USE_STORAGE_CONFIG     0
+#define USE_EEPROM_CONFIG      0
+
+#define HAS_BEEP               0
+
+#define HAS_USB                        1
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#define HAS_SPI_0              0
+
+#define AO_SENSOR_PORT         (&stm_gpioa)
+#define AO_SENSOR_PIN          3
+
+#define LOW_LEVEL_DEBUG                0
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/vidtime/ao_vidtime.c b/src/vidtime/ao_vidtime.c
new file mode 100644 (file)
index 0000000..1b9b9e1
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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_exti.h>
+
+static uint8_t sensor_value;
+static uint8_t vidtime_monitor;
+
+static void
+vidtime(void)
+{
+       uint8_t old = 0, got;
+
+       ao_exti_enable(AO_SENSOR_PORT, AO_SENSOR_PIN);
+       for (;;) {
+               while (!vidtime_monitor)
+                       ao_sleep(&vidtime_monitor);
+               while ((got = sensor_value) == old)
+                       ao_sleep(&sensor_value);
+               printf("%d\n", got);
+               flush();
+               old = got;
+       }
+}
+
+static void
+sensor_interrupt(void)
+{
+       sensor_value = ao_gpio_get(AO_SENSOR_PORT, AO_SENSOR_PIN, foo);
+       ao_wakeup(&sensor_value);
+}
+
+static struct ao_task  vidtime_task;
+
+static void
+ao_init_vidtime(void)
+{
+       ao_enable_port(AO_SENSOR_PORT);
+       ao_exti_setup(AO_SENSOR_PORT, AO_SENSOR_PIN,
+                     AO_EXTI_MODE_RISING|
+                     AO_EXTI_MODE_FALLING|
+                     AO_EXTI_MODE_PULL_NONE|
+                     AO_EXTI_PRIORITY_MED,
+                     sensor_interrupt);
+       ao_add_task(&vidtime_task, vidtime, "vidtime");
+}
+
+static void
+ao_set_vidtime(void)
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status == ao_cmd_success) {
+               vidtime_monitor = ao_cmd_lex_i != 0;
+               ao_wakeup(&vidtime_monitor);
+       }
+}
+
+const struct ao_cmds   ao_vidtime_cmds[] = {
+       { ao_set_vidtime, "V <0 off, 1 on>\0Enable/disable timing monitor" },
+       { 0, NULL }
+};
+
+void main(void)
+{
+       ao_clock_init();
+
+       ao_task_init();
+
+       ao_timer_init();
+
+       ao_dma_init();
+
+       ao_init_vidtime();
+
+       ao_usb_init();
+
+       ao_cmd_init();
+
+       ao_cmd_register(&ao_vidtime_cmds[0]);
+
+       ao_start_scheduler();
+}
diff --git a/src/vidtime/flash-loader/.gitignore b/src/vidtime/flash-loader/.gitignore
new file mode 100644 (file)
index 0000000..05f1a4d
--- /dev/null
@@ -0,0 +1,2 @@
+ao_product.h
+vidtime*
diff --git a/src/vidtime/flash-loader/Makefile b/src/vidtime/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..57c65b5
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# AltOS flash loader build
+#
+
+TOPDIR=../..
+HARDWARE=vidtime-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
diff --git a/src/vidtime/flash-loader/ao_pins.h b/src/vidtime/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..7feb936
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Debug port PA15 (pin 23) */
+
+#define AO_BOOT_PIN                    1
+#define AO_BOOT_APPLICATION_GPIO       (stm_gpioa)
+#define AO_BOOT_APPLICATION_PIN                15
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define AO_USB_DIRECTIO                0
+#define AO_PA11_PA12_RMP       1
+
+#endif /* _AO_PINS_H_ */