Merge branch 'branch-1.9' into debian
authorBdale Garbee <bdale@gag.com>
Wed, 30 Sep 2020 06:19:12 +0000 (00:19 -0600)
committerBdale Garbee <bdale@gag.com>
Wed, 30 Sep 2020 06:19:12 +0000 (00:19 -0600)
189 files changed:
ChangeLog
Releasing
altosdroid/Makefile.am
altoslib/AltosConfigData.java
altoslib/AltosHexfile.java
altoslib/AltosIdleFetch.java
altoslib/AltosLink.java
altoslib/AltosPreferences.java
altoslib/AltosRomconfig.java
altosui/AltosConfigFCUI.java
altosui/AltosConfigPyroUI.java
altosui/AltosConfigTDUI.java
altosui/AltosFlightUI.java
altosui/AltosIdleMonitorUI.java
altosui/AltosIgniteUI.java
altosui/AltosLaunchUI.java
altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub
altosui/Instdrv/NSIS/Includes/java.nsh
altosui/Makefile.am
altosui/altos-windows.nsi.in
altosui/ask-pass [new file with mode: 0755]
altosui/install-macosx
altosuilib/AltosBTManage.java
altosuilib/AltosConfigFreqUI.java
altosuilib/AltosEepromMonitorUI.java
altosuilib/AltosFlashUI.java
altosuilib/AltosRomconfigUI.java
altosuilib/AltosScanUI.java
altosuilib/AltosUIAccelCal.java
altosuilib/AltosUIConfigure.java
altosuilib/AltosUIDialog.java
altosuilib/AltosUIFrame.java
altosuilib/AltosUIMapPreload.java
altosuilib/AltosUIPreferences.java
altosuilib/AltosUSBDevice.java
ao-bringup/turnon_telebt
ao-bringup/turnon_telemega_v1.0
ao-bringup/turnon_telemega_v3.0
ao-tools/ao-eeprom/ao-eeprom.c
configure.ac
doc/Makefile.am
doc/RELNOTES
doc/config-device.inc
doc/easymini-outline.txt
doc/easymini-release-notes.inc
doc/release-notes-1.9.5.inc [new file with mode: 0644]
doc/release-notes.inc
doc/telegps-release-notes.inc
doc/telelaunch-configuration.inc
doc/updating-firmware.inc
libaltos/Makefile-standalone
libaltos/libaltos.dylib
libaltos/libaltos_darwin.c
libaltos/libaltos_windows.c
micropeak/Makefile.am
micropeak/MicroData.java
micropeak/MicroDownload.java
micropeak/MicroFile.java
micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub
micropeak/MicroPeak.java
micropeak/MicroSave.java
micropeak/MicroSerial.java
src/Makefile
src/attiny/ao_arch.h
src/attiny/ao_arch_funcs.h
src/attiny/ao_clock.c
src/avr/ao_arch.h
src/cortexelf-v1/ao_pins.h
src/drivers/ao_adxl375.c
src/drivers/ao_bmx160.c
src/drivers/ao_cc1120.c
src/drivers/ao_cc115l.c
src/drivers/ao_cc1200.c
src/drivers/ao_companion.c
src/drivers/ao_led.c
src/drivers/ao_m25.c
src/drivers/ao_mma655x.c
src/drivers/ao_mpu6000.c
src/drivers/ao_mpu9250.c
src/drivers/ao_ms5607.c
src/drivers/ao_rn4678.c
src/easymega-v1.0/ao_pins.h
src/easymega-v2.0/ao_pins.h
src/easymega-v3.0/ao_pins.h
src/easymini-v1.0/ao_pins.h
src/easymini-v2.0/ao_pins.h
src/easytimer-v1/ao_pins.h
src/fox1ihu/ao_pins.h
src/kernel/ao.h
src/kernel/ao_beep.h
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_flight.c
src/kernel/ao_ignite.c
src/kernel/ao_led.h
src/kernel/ao_log_micro.c
src/kernel/ao_log_micro.h
src/kernel/ao_notask.c
src/kernel/ao_notask.h
src/kernel/ao_pyro.c
src/kernel/ao_storage.c
src/kernel/ao_storage.h
src/kernel/ao_task.c
src/kernel/ao_task.h
src/lpc/ao_arch.h
src/lpc/ao_arch_funcs.h
src/lpc/ao_beep_lpc.c
src/lpc/ao_led_lpc.c
src/lpc/ao_timer_lpc.c
src/micropeak-v2.0/Makefile
src/micropeak-v2.0/ao_micro.c [new file with mode: 0644]
src/micropeak-v2.0/ao_micropeak.c
src/micropeak-v2.0/ao_pins.h
src/micropeak-v2.0/micropeak.ld
src/mpusb-v3.0/Makefile
src/mpusb-v3.0/ao_pins.h
src/product/ao_flash_pins.h
src/product/ao_flash_task.c
src/stm-flash/ao_pins.h
src/stm-vga/ao_pins.h
src/stm/ao_arch_funcs.h
src/stm/ao_beep_stm.c
src/stm/ao_led_stm.c
src/stm/ao_spi_stm.c
src/stm/ao_timer.c
src/stm32f4/ao_arch.h
src/stm32f4/ao_arch_funcs.h
src/stm32f4/ao_interrupt.c
src/stm32f4/ao_timer.c
src/stm32l0/Makefile-flash.defs [new file with mode: 0644]
src/stm32l0/Makefile-stm32l0.defs [new file with mode: 0644]
src/stm32l0/Makefile.defs [new file with mode: 0644]
src/stm32l0/altos.ld [new file with mode: 0644]
src/stm32l0/ao_adc_stm32l0.c [new file with mode: 0644]
src/stm32l0/ao_adc_stm32l0.h [new file with mode: 0644]
src/stm32l0/ao_arch.h [new file with mode: 0644]
src/stm32l0/ao_arch_funcs.h [new file with mode: 0644]
src/stm32l0/ao_dma_stm32l0.c [new file with mode: 0644]
src/stm32l0/ao_exti.h [new file with mode: 0644]
src/stm32l0/ao_exti_stm.c [new file with mode: 0644]
src/stm32l0/ao_flash.h [new file with mode: 0644]
src/stm32l0/ao_flash_stm32l0.c [new file with mode: 0644]
src/stm32l0/ao_interrupt.c [new file with mode: 0644]
src/stm32l0/ao_lpuart.h [new file with mode: 0644]
src/stm32l0/ao_lpuart_stm.c [new file with mode: 0644]
src/stm32l0/ao_pwm_stm.c [new file with mode: 0644]
src/stm32l0/ao_serial_stm.c [new file with mode: 0644]
src/stm32l0/ao_spi_stm32l0.c [new file with mode: 0644]
src/stm32l0/ao_timer.c [new file with mode: 0644]
src/stm32l0/stm32l0.h [new file with mode: 0644]
src/stm32l0/stm32l0.ld [new file with mode: 0644]
src/stmf0/ao_arch_funcs.h
src/stmf0/ao_beep_stm.c
src/stmf0/ao_interrupt.c
src/stmf0/ao_led_stmf0.c
src/stmf0/ao_timer.c
src/teleballoon-v2.0/ao_pins.h
src/telebt-v3.0/ao_pins.h
src/telebt-v4.0/ao_pins.h
src/teledongle-v3.0/ao_pins.h
src/telefireeight-v1.0/ao_pins.h
src/telefireeight-v2.0/ao_pins.h
src/telefireone-v1.0/ao_pins.h
src/telefireone-v2.0/ao_pins.h
src/telefiretwo-v0.1/ao_pins.h
src/telefiretwo-v0.2/ao_pins.h
src/telegps-v0.1/ao_pins.h
src/telegps-v0.3/ao_pins.h
src/telegps-v1.0/ao_pins.h
src/telegps-v2.0/ao_pins.h
src/telelco-v0.2-cc1200/ao_pins.h
src/telelco-v0.3/ao_pins.h
src/telelco-v2.0/ao_pins.h
src/telelcotwo-v0.1/ao_pins.h
src/telemega-v0.1/ao_pins.h
src/telemega-v1.0/ao_pins.h
src/telemega-v2.0/ao_pins.h
src/telemega-v3.0/ao_pins.h
src/telemega-v4.0/ao_pins.h
src/telemetrum-v2.0/ao_pins.h
src/telemetrum-v3.0/ao_pins.h
src/telemini-v3.0/ao_pins.h
src/telestatic-v3.0/ao_pins.h
src/test/ao_micropeak_test.c
src/tmgps-v2.0/ao_pins.h
src/vidtime/ao_pins.h
telegps/Makefile.am
telegps/TeleGPS.app/Contents/MacOS/JavaApplicationStub
telegps/TeleGPSConfigUI.java

index 139409b0c5be1bbe5092e80775162d29d30cb5d7..39adbf91d39a690a0bcb0e831450fc58faecf00a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,761 @@
+commit f763dfe6a684a16ec40503149adefdc074a63ad0
+Merge: bfe338d1 a1779f94
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Sep 30 00:17:03 2020 -0600
+
+    Merge branch 'master' into branch-1.9
+
+commit a1779f9442787dbd5c40edbb476e6b765392196e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 29 20:10:38 2020 -0700
+
+    Version 1.9.5
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 67e8e9b5b51e259eda4a669de527111851bab78f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 29 22:02:56 2020 -0700
+
+    altosui: Work around lack of actual USB product names on Windows
+    
+    Windows doesn't provide an API to get the USB product name for
+    attached devices, it only provides the name listed in the .inf file
+    for each vid/pid. This means that you get 'TeleMega', or 'TeleMega
+    can't isolate the list to the correct version.
+    
+    With this fix, at least the '#2' is stripped off, and the matching
+    code restricts itself to showing only TeleMega files instead of all
+    filenames starting with 'tele'.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9bee7d9b6be861909d8c89767f6eabf007f76612
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 29 20:08:31 2020 -0700
+
+    altosdroid: Copy generated .apks to bin directory
+    
+    This places them in the same location as the previous build system.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1fa1ba86f6e6e4ff469f0680cdbc39bc806474a4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Sep 25 20:06:18 2020 -0700
+
+    doc: Add 1.9.5 release notes
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2d239b9bf600fac46717980f45de3ca7a242236f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 1 18:47:23 2020 -0700
+
+    altoslib: Print more helpful debug messages when checking rom version
+    
+    Make sure success and failure include enough info to debug what
+    happened.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5bdc63a2086c1ffd4c34c9a503af638a47a1d98b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Sep 1 18:31:03 2020 -0700
+
+    libaltos: Update to support Mac OS X 10.15 (catalina)
+    
+    They decided to break device names reported by USB for some reason,
+    but at least the real names are still available under a different
+    name.
+    
+    Also updated the Makefile-standalone to work on my current box;
+    presumably the next time I build this I'll have to update again...
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 583a749724700845d2d3552a0d3a759f16b25cfe
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 31 20:52:43 2020 -0700
+
+    macosx: Update macosx install script
+    
+    Use dialog engine to monitor progress and get sudo password
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ffbd99545ca0462161c24e0ed86978544f2c28f6
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 31 15:08:08 2020 -0700
+
+    altosuilib: Make dialogs mostly scrollable
+    
+    When screens are too small, some dialogs aren't usable. Fix that by
+    wrapping them all with a scrollable pane.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 521dc6dbf9aa5f7aad7829cd98a815031725ac24
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 31 15:07:13 2020 -0700
+
+    windows: Point windows users at adoptopenjdk.net by default
+    
+    This gives them a free software java which works fine with altosui.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7fc37f145a6ec3f913e908b6500d1e2c6dd405c8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 31 15:05:41 2020 -0700
+
+    macosx: Hack JavaApplicationStub to set freetype properties
+    
+    Set the FREETYPE_PROPERTIES environment variable to revert to
+    non-fuzzy text.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 075999e274dd1815b15c0d717d1af4e7717e5da9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 31 15:03:57 2020 -0700
+
+    altoslib: Set default logging directory to $HOME/AltusMetrum
+    
+    Change from ~/TeleMetrum
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4e07392c65ec512e3309d89c7465c1406a941b66
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Aug 31 15:01:18 2020 -0700
+
+    libaltos: Map generic windows device names to actual names
+    
+    When we signed the .ini file for our windows 'driver', IDs 28 and 2c
+    hadn't been assigned to EasyMega and EasyMotor, so that file has
+    generic 'AltusMetrum28' and 'AltusMetrum2c' instead. Updating that
+    file is 'hard', so just map the names in the driver instead.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d298df9e4cf945f3d0dfdb583af07e498c685a0
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Fri Sep 18 11:38:06 2020 -0600
+
+    docs: add explicit admonition about avoiding 'c f' when configuring TeleLaunch
+
+commit 95b31cb200d59917fd3ad03c5c3a0ad99c8a140d
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Fri Sep 18 11:34:56 2020 -0600
+
+    docs: fix horrible typo in TeleLaunch configuration section
+
+commit 23e148bb3379969935bcbbbeb6c8dc66c0474f6d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 23 15:34:26 2020 -0700
+
+    altosuilib: Allow config to be missing in rom config dialog
+    
+    If the configuration data can't be fetched from the target board, it
+    will be missing while building the dialog box. Deal with that.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2289fd36f7ba76692fe07d2ebc8d7eda33750180
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 23 15:32:57 2020 -0700
+
+    altoslib: Deal with reflashing EasyMega boards with ancient firmware
+    
+    Ancient EasyMega firmware included radio calibration data in the
+    romconfig bits, which has since been removed. That means the config
+    data from those boards will be at a different location than current
+    firmware. Deal with that by poking around in firmware looking for
+    valid bits.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 335e40873c238a67cea2c63d62b73fd9d29e94d2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 23 10:55:30 2020 -0700
+
+    doc: Fix spelling error in updating-firmware section.
+    
+    Thanks to Timothy Dixon for catching this (copy-and-pasted many times)
+    typo -- could sequentially -> count sequentially.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c1b754c12ac32ed38a561d8b35dcbdf82beea896
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 23 10:53:25 2020 -0700
+
+    altosui: Improve configuration save feedback
+    
+    Mark window title as (modified) with any unsaved changes. Disable the
+    'Save' button while the save is happening. Wait for the re-load of
+    configuration values before clearing the '(modified)' state. This lets
+    you see when the flight computer has accepted the updated values.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 10a10667a28f82c24d895e44617e68c7c1848c45
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 23 10:51:00 2020 -0700
+
+    altoslib: Improve configuration performance over remote link
+    
+    Avoid re-setting dongle radio parameters when they haven't changed
+    during device configuration setting. This avoids flipping back and
+    forth from remote to local mode three times during config save.
+    
+    Wait for remote end to say 'Saved' before dropping radio link. This
+    ensures that the remote end actually gets the save command before the
+    link is terminated.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b3297909e58a2709d340f65181c22ef82341afb9
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Aug 19 14:38:04 2020 -0600
+
+    fix broken TeleBT turnon script
+
+commit f82e0c5e3a3b3a505e35df23301cdc7dd4b1a869
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 21:51:39 2020 -0700
+
+    altoslib: Flush output when disabling remote
+    
+    This speeds up sending data to the other end.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 783a541d661f24f2df1dee86bad2e47950bee9da
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 21:50:38 2020 -0700
+
+    altoslib: Don't fetch config data for every idle status
+    
+    This makes fetching data during idle monitor much faster, especially
+    now that fetching the list of stored flights takes so long.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bbd052c0ad5b99673cf583198e50e6ed351fdfb7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 21:49:37 2020 -0700
+
+    altos: Allow multiple manual firing of main/drogue channels
+    
+    Reset the 'fired' status so that you can trigger these multiple times
+    without needing to reboot.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f3c8946d992889edabffbab40aead578963de75f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 21:48:09 2020 -0700
+
+    altos: Don't report inhibited pyro channels as fired
+    
+    Inhibiting channels happens when the channel conditions change during
+    the delay period and was done by marking them as already fired. This
+    worked, but the log file would then indicate that the channel had
+    fired when in fact it was inhibited instead. Separate out the inhibited status
+    so that the correct data appears in the log.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 38db8202a4d6ab90305768410f1a37106cc95794
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:20:59 2020 -0700
+
+    micropeak: Add support for MicroPeak v2.0
+    
+    MicroPeak v2.0 sends a 'unique id' with the log data; capture that and
+    included it in the file name.
+    
+    MicroPeak v2.0 can be directly connected to the host using the ÂµP I/O
+    board. Handle that case by sending the 'l' command which will cause
+    the device to dump the log.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0743e7213729df629aea90b3a5dc904fe397b5cb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:19:28 2020 -0700
+
+    micropeak: Fix top-level window building
+    
+    The menu wasn't actually working, and the application would randomly
+    start at the wrong size or crash.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7dd23ac750226746f340df64107dab84cd7ea113
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:18:10 2020 -0700
+
+    micropeak: Check for empty data when fetching log
+    
+    Don't pop up the graph window and don't save data from an erased
+    device.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 838d359ed8676f056fe487dad3dfbec34bd65009
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:16:55 2020 -0700
+
+    altos/mpusb-v3.0: Make this build again
+    
+    It's not built by default and the requirements in the Makefile have
+    changed.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 52eaf4a2480ac0fd367978e423e2f252949f978b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:15:32 2020 -0700
+
+    altos/micropeak-v2.0: Functionally complete.
+    
+    Get flight mode working correctly.
+    Offer log dumping from serial link.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 999b3598019c75d77af6ab40c1942a7d57a2ec3c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:13:50 2020 -0700
+
+    altos: Add MicroPeak v2.0 support to ao_log_micro
+    
+    Support 4-byte sample count (required for stm32l0 flash storage
+    limitations).
+    
+    Mix in log ID on-the-fly so that erased flash parts still report
+    device type.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 476fd2f2c23da427b6b2a68f7d285767a924041e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:12:22 2020 -0700
+
+    altos/stm32l0: Big update in functionality
+    
+    Fix baud rate setting in LPUART
+    Add code to turn everything off.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7b1f4177d42e5e951a7db4289c847d355a785c2a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Aug 6 11:05:03 2020 -0700
+
+    altos: Remove support for !HAS_TASK_QUEUE
+    
+    This uses a bit more memory, but the amount can be controlled by
+    setting the size of the sleep hash table, which makes this fit on even
+    the smaller devices like the early EasyMini boards.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a6baf04bae3fe6a6b3da2f456419732ffeb4d056
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 18:17:07 2020 -0700
+
+    altos: Remove ao_led_toggle API from general code
+    
+    The generic implementation would need to record LED status as it
+    cannot be read back from the device on most hardware. Just get rid of
+    it and let attiny keep its implementation (which does work).
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0385d7d68c51e05f5b555749ccc20e3c7c202370
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 18:15:47 2020 -0700
+
+    ao-tools: Add TeleGPS log parsing to ao-eeprom
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9df66f7589b663899e2c729b884eed4b64e5d4da
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Aug 6 10:44:49 2020 -0700
+
+    altos: add noreturn attribute to ao_panic
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 33ea5b3658377cea325db285a3e457724f660384
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Aug 5 22:32:14 2020 -0700
+
+    altos/stm32l0: Add LPUART driver
+    
+    This is a simpler UART which micropeak has connected to the LED and
+    we'll use for transmitting the log on power up
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 980d54134bedb64d506c0702f09b4d5277000848
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Aug 5 17:17:47 2020 -0700
+
+    altos/stm32l0: Provide ao_spi_speed inline as per new clocking API
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2cd7ecf437bec322e6a201992d0404f31207bd68
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:22:21 2020 -0700
+
+    altos/micropeak-v2.0: Finish hardware bring-up
+    
+    All of the hardware is working:
+    
+     * serial
+     * SPI
+     * ms56067
+     * ADC
+     * flash
+     * clocking
+     * timer
+    
+    Now we just need an application
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 845b51d09a6a6f257aebb6db202b12ee1fa9ed7e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:21:57 2020 -0700
+
+    altos/stm32l0: Add adc and flash drivers
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d2b750a04bbaf428a38fd95891a7ce1cc7d3d2f3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:21:26 2020 -0700
+
+    altos/stm32l0: Remove some unused code in ao_timer.c
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9dea51ca2174d86d5ab4a8a27179519b34869a36
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:20:56 2020 -0700
+
+    altos/stm32l0: Remove some unused code in USART driver
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit db7bf095dfa75858eb12328f104051ea1686e1d5
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:20:26 2020 -0700
+
+    altos/stm32l0: Get exti working
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e58d08a93818b3d60746f0f17b34e96fbf8ba0e3
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:19:47 2020 -0700
+
+    altos/stm32l0: Get SPI driver working
+    
+    This isn't using DMA, but it seems to work now.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b0c4df25a0c419eeb53e0e241489c0bd6bee04ef
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:19:11 2020 -0700
+
+    altos/stm32l0: Some device addrs were wrong
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3df505b02fb7d4ba2d40351e658931b02425b74f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:18:27 2020 -0700
+
+    altos/stm32l0: More DMA fixes
+    
+    This code still doesn't work, but it should be closer'
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1e1a84e9ea21ef6037a2127098499e294d293fa8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:17:03 2020 -0700
+
+    altos: Micropeak v2.0 doesn't have a flash loader anymore
+    
+    The current version doesn't have USB, so the existing flash loader
+    protocol won't work anyways.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0375e9840ea1bcc486b56ccb3aaace57875312a7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:16:28 2020 -0700
+
+    altos/ao_storage: Allow apps to #define storage parameters
+    
+    This avoids placing them in RAM.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 45b00da14ea814cf8f14dcb2cfaccaddd0fbb38d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:15:28 2020 -0700
+
+    altos/ao_storage: allow erased byte value to be set by application
+    
+    External flash is usually 0xff for erased bytes, but other memory may
+    use different values
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6b4da0492c6d9066c8a118fba9b8ffca02fa84ba
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jun 23 16:15:14 2020 -0700
+
+    remove ao_delay_until from ao.h
+
+commit 48bc180211f226b0406aae28a85d5e5ee77455a2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 22 17:42:03 2020 -0700
+
+    altos: Add ao_delay_until to ao_notask
+    
+    Used on micropeak
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b4a31f4bba8edee32d4f41780bd62bcfa064f20a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jun 22 17:41:11 2020 -0700
+
+    altos: Move empty ao_mutex_get/put to ao_notask.h
+    
+    Make it work on any no-task project.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7cd8e0aca8ea42a5ff077971e439b0816608b324
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 20 15:15:35 2020 -0700
+
+    altos: Declare ao_delay_until API in ao.h
+    
+    This uses AO_TICK_TYPE which isn't defined until we get to ao.h
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eea198932b8f12d4729f6138a40489d954d6f93a
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 20 15:14:26 2020 -0700
+
+    altos: Switch micropeak v2.0 to stm32l0
+    
+    The stm32f042 takes too much power for micropeak. Try the stm32l0
+    instead.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d907b0fe40d31995848e5b207009ba230da2e36e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 20 15:13:09 2020 -0700
+
+    altos: Add initial stm32l0 support
+    
+    A low-power cortex M0 chip for MicroPeak v2.0
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8a9273162b7016afc29f4c98fc3b66324d4c85b
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jun 20 15:00:28 2020 -0700
+
+    altos: Fix a bunch of time variables to be AO_TICK_TYPE
+    
+    The default tick type is now 32 bits, so all of these
+    variables were mis-typed at 16 bits.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 304dbcbff72c6fa66c71224ecf98ec55447ffff7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Fri Aug 7 20:08:34 2020 -0700
+
+    altos/stm: Fix stack validation code
+    
+    This is not included by default, and broke at some point.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff3a2de3223f5cf3fd87f40cd9961e2c2890a867
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Mon Aug 3 12:43:22 2020 -0600
+
+    doc: EasyMotor and EasyTimer have the same mounting geometry as EasyMini
+
+commit 21da942560863ed191953e1af2fbca66bcc29fb8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 2 17:29:44 2020 -0700
+
+    altos/stmf0, stm32f0: Call ao_boot_chain to start application
+    
+    This used to be done inside ao_boot_check_chain or ao_boot_check_pin,
+    but it made more sense to have it done in _start instead. stm and lpc
+    were adjusted, but stmf0 and stm32f4 were missed.
+    
+    This caused boards using this process to wedge in the boot loader.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6b5e5899d174466552a34a4d8574f0439776240d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sun Aug 2 13:31:58 2020 -0700
+
+    altosui: Re-set pad orientation labels after product name is set
+    
+    We don't know what product is being configured until after we query
+    the configuration, which means we need to re-set the orientation label
+    once that has been fetched.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 341157c7415fcf879696c9d8167722a0c5ff264c
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 29 10:53:39 2020 -0700
+
+    altos: Use new ao_spi_speed inline to set SPI speeds using spec'd frequencies
+    
+    Instead of hand-adjusting SPI speeds for each driver and product based
+    on processor supported rates, create an inline function that takes the
+    maximum frequency supported by the device and maps that to a value
+    supported by the SoC. This ensures that we don't accidentally drive devices
+    faster than they want (as could happen with AO_SPI_SPEED_FAST), but do go
+    as fast as possible in every configuration. Using an inline function means
+    the value is computed at compile time.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 202166275ba5220db54f63dcd9366e9115d09c0d
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 28 23:44:33 2020 -0700
+
+    altos: Support flash parts > 8MB
+    
+    The number of sectors (64kB) units in the connected flash
+    part can be larger than 255, so switch from 8-bits to 32-bits for
+    holding this value.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c56bcc315ac29d001e62859b61ede890a8b7c64f
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 28 23:43:04 2020 -0700
+
+    altos: Protect shared storage_data with mutex
+    
+    As storage_data is shared between all threads, protect it
+    with a mutex to avoid collisions.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8a24d37e40210b1fb5cdab944c3a6d9ae4e144d7
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue Jul 28 23:40:36 2020 -0700
+
+    altos/stm: Increase MISO DMA priority to very high
+    
+    We're still losing incoming bytes in full duplex mode.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3058ecdeafdee959b1103965f3df4ffcd59683e4
+Merge: 0a53faa8 8ec51d69
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jul 22 15:23:02 2020 -0600
+
+    Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit 0a53faa8173565b1277d1a35c60022de567c2dce
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Wed Jul 22 15:22:21 2020 -0600
+
+    ao-bringup: ensure TeleMega turnon scripts are using the right test versions
+
+commit 8ec51d698921d07c394e6e0e48ac5d587f70ece8
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 22 09:04:30 2020 -0700
+
+    altos: Add 'booster' mode for dual-deploy igniters
+    
+    Booster mode triggers the 'main' channel at first motor burnout
+    allowing the use of a simple flight computer in the booster while
+    providing both a separation charge and an apogee event for recovery.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d0c0dec140b8fa847704c9a22a39d254445188b9
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 22 08:57:05 2020 -0700
+
+    altos: Use state transitions to directly drive igniters
+    
+    Instead of a separate igniter API, have the igniter code monitor
+    flight state changes to trigger igniter events. This simplifes the
+    code while allowing further changes in the igniter code.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6ff8e55581ca85b9cc892806a2481d57a65e8bae
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jul 22 08:56:10 2020 -0700
+
+    Releasing: save .map files too
+    
+    These are useful to debug issues with linker scripts or library problems
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4c5942fb082811f136322ec26de615cdb7e17580
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 16 10:23:34 2020 -0700
+
+    Add support for TLS if needed
+    
+    Define USE_TLS if you want TLS support from altos.
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8066ce73d96f85efe7f5e51b1576b5fd0ff9565e
+Author: Keith Packard <keithp@keithp.com>
+Date:   Thu Jul 16 09:29:52 2020 -0700
+
+    altosui: Spurious ; in altos-windows.nsi.in kept out TM v3.0 ihx
+    
+    Looks like a semicolon got stuck in this file, which commented out the
+    TeleMetrum v3.0 firmware from being included in the windows build
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bfe338d11965d2d1715bdd81d92ef32f1b5ff9fa
+Author: Bdale Garbee <bdale@gag.com>
+Date:   Thu Jul 2 20:21:19 2020 -0600
+
+    releasing 1.9.4
+
 commit 8359fcc23a93a37ee3aee4c5d2ef183f18ea3f27
 Merge: b95d6674 9b62f683
 Author: Bdale Garbee <bdale@gag.com>
index 223a14d3c902407478c3f6627deb3865e09a18ae..e9ceb4084162203a1213a9b443b34074b1e2c2c3 100644 (file)
--- a/Releasing
+++ b/Releasing
@@ -101,40 +101,40 @@ These are Bdale's notes on how to do a release.
 
        - store a stable copy of ARM binaries for production use
 
-       cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin} \
-          src/easymega-v1.0/{*.elf,*.ihx} \
-          src/easymega-v2.0/{*.elf,*.ihx} \
-          src/easymini-v1.0/{*.elf,*.ihx} \
-          src/easymini-v2.0/{*.elf,*.ihx} \
-          src/easytimer-v1/{*.elf,*.ihx} \
-          src/telebt-v3.0/{*.elf,*.ihx} \
-          src/telebt-v4.0/{*.elf,*.ihx} \
-          src/teledongle-v3.0/{*.elf,*.ihx} \
-          src/telegps-v1.0/{*.elf,*.ihx} \
-          src/telegps-v2.0/{*.elf,*.ihx} \
-          src/telemega-v[1-4].0/{*.elf,*.ihx} \
-          src/telemetrum-v2.0/{*.elf,*.ihx} \
-          src/telemetrum-v3.0/{*.elf,*.ihx} \
-          src/telemini-v3.0/{*.elf,*.ihx} \
-          src/telelco-v2.0/{*.elf,*.ihx} \
-          src/telefireeight-v1.0/{*.elf,*.ihx} \
-          src/telefireeight-v2.0/{*.elf,*.ihx} \
+       cp src/chaoskey-v1.0/{*.elf,*.ihx,*.bin,*.map} \
+          src/easymega-v1.0/{*.elf,*.ihx,*.map} \
+          src/easymega-v2.0/{*.elf,*.ihx,*.map} \
+          src/easymini-v1.0/{*.elf,*.ihx,*.map} \
+          src/easymini-v2.0/{*.elf,*.ihx,*.map} \
+          src/easytimer-v1/{*.elf,*.ihx,*.map} \
+          src/telebt-v3.0/{*.elf,*.ihx,*.map} \
+          src/telebt-v4.0/{*.elf,*.ihx,*.map} \
+          src/teledongle-v3.0/{*.elf,*.ihx,*.map} \
+          src/telegps-v1.0/{*.elf,*.ihx,*.map} \
+          src/telegps-v2.0/{*.elf,*.ihx,*.map} \
+          src/telemega-v[1-4].0/{*.elf,*.ihx,*.map} \
+          src/telemetrum-v2.0/{*.elf,*.ihx,*.map} \
+          src/telemetrum-v3.0/{*.elf,*.ihx,*.map} \
+          src/telemini-v3.0/{*.elf,*.ihx,*.map} \
+          src/telelco-v2.0/{*.elf,*.ihx,*.map} \
+          src/telefireeight-v1.0/{*.elf,*.ihx,*.map} \
+          src/telefireeight-v2.0/{*.elf,*.ihx,*.map} \
           ~/altusmetrumllc/Binaries/
-       cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin} \
+       cp src/chaoskey-v1.0/flash-loader/{*.elf,*.bin,*.map} \
           src/easymega-v1.0/flash-loader/*.elf \
           src/easymega-v2.0/flash-loader/*.elf \
           src/easymini-v1.0/flash-loader/*.elf \
-          src/easymini-v2.0/flash-loader/{*.elf,*.bin} \
-          src/easytimer-v1/flash-loader/{*.elf,*.bin} \
+          src/easymini-v2.0/flash-loader/{*.elf,*.bin,*.map} \
+          src/easytimer-v1/flash-loader/{*.elf,*.bin,*.map} \
           src/telebt-v3.0/flash-loader/*.elf \
-          src/telebt-v4.0/flash-loader/{*.elf,*.bin} \
+          src/telebt-v4.0/flash-loader/{*.elf,*.bin,*.map} \
           src/teledongle-v3.0/flash-loader/*.elf \
           src/telegps-v1.0/flash-loader/*.elf \
-          src/telegps-v2.0/flash-loader/{*.elf,*.bin} \
+          src/telegps-v2.0/flash-loader/{*.elf,*.bin,*.map} \
           src/telemega-v[1-4].0/flash-loader/*.elf \
           src/telemetrum-v2.0/flash-loader/*.elf \
           src/telemetrum-v3.0/flash-loader/*.elf \
-          src/telemini-v3.0/flash-loader/{*.elf,*.bin} \
+          src/telemini-v3.0/flash-loader/{*.elf,*.bin,*.map} \
           src/telelco-v2.0/flash-loader/*.elf \
           src/telefireeight-v1.0/flash-loader/*.elf \
           src/telefireeight-v2.0/flash-loader/*.elf \
index 7fb16404d776cc27a681ee6a87ed7bc183c2b92c..f9f69662b9e25541ff0a9b65a1c1307170f3141b 100644 (file)
@@ -3,8 +3,10 @@ REL_APK=app/build/outputs/apk/release/app-release.apk
 
 if ANDROID
 all_target=$(DBG_APK)
+all_target += bin/AltosDroid-debug.apk
 if ANDROID_RELEASE
 all_target+=$(REL_APK)
+all_target += bin/AltosDroid-release.apk
 endif
 else
 all_target=
@@ -53,6 +55,14 @@ SRC=$(JAVA_SRC) $(DRAWABLES) $(RES)
 
 all: $(all_target)
 
+bin/AltosDroid-debug.apk: $(DBG_APK)
+       mkdir -p bin
+       cp $^ $@
+
+bin/AltosDroid-release.apk: $(REL_APK)
+       mkdir -p bin
+       cp $^ $@
+
 .NOTPARALLEL:
 
 $(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR)
index 5d58566ecb3dc0b9836e1bd676a5857f04a1cde1..83f3ca07a55dfd35b3541dc70e6c239ae0203ec3 100644 (file)
@@ -796,33 +796,28 @@ public class AltosConfigData {
                                                        has_setting,
                                                        radio_calibration);
                        /* When remote, reset the dongle frequency at the same time */
-                       if (remote) {
-                               link.flush_output();
+                       if (remote && frequency != link.frequency) {
                                link.stop_remote();
                                link.set_radio_frequency(frequency);
-                               link.flush_output();
                                link.start_remote();
                        }
                }
 
                if (telemetry_rate != AltosLib.MISSING) {
                        link.printf("c T %d\n", telemetry_rate);
-                       if (remote) {
-                               link.flush_output();
+                       if (remote && telemetry_rate != link.telemetry_rate) {
                                link.stop_remote();
                                link.set_telemetry_rate(telemetry_rate);
-                               link.flush_output();
                                link.start_remote();
                        }
                }
 
                if (callsign != null) {
                        link.printf("c c %s\n", callsign);
-                       if (remote) {
-                               link.flush_output();
+                       if (remote && !callsign.equals(link.callsign)) {
+                               System.out.printf("changing link callsign from %s to %s\n", link.callsign, callsign);
                                link.stop_remote();
                                link.set_callsign(callsign);
-                               link.flush_output();
                                link.start_remote();
                        }
                }
@@ -882,7 +877,7 @@ public class AltosConfigData {
                /* UI doesn't support accel cal */
 
                link.printf("c w\n");
-               link.flush_output();
+               read_link(link, "Saved");
        }
 
        public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException {
index 14f660a0bbcb0c4d38f406d31d2029d3fea3c711..718826001755a0dedf1a1b9725b94a30e3fcf7f4 100644 (file)
@@ -287,6 +287,8 @@ public class AltosHexfile {
                return null;
        }
 
+       private static final int look_around[] = { 0, -2, 2, -4, 4 };
+
        private long find_usb_descriptors() {
                AltosHexsym     usb_descriptors = lookup_symbol("ao_usb_descriptors");
                long            a;
@@ -294,24 +296,22 @@ public class AltosHexfile {
                if (usb_descriptors == null)
                        return -1;
 
-               try {
-                       /* The address of this has moved depending on
-                        * padding in the linker script. Look forward
-                        * and backwards two bytes to see if we can find it
-                        */
-                       a = usb_descriptors.address;
-
-                       if (get_u8(a) == 0x12 && get_u8(a+1) == AO_USB_DESC_DEVICE)
-                               return a;
-                       else if (get_u8(a+1) == 0x12 && get_u8(a+3) == AO_USB_DESC_DEVICE)
-                               return a + 2;
-                       else if (get_u8(a-2) == 0x12 && get_u8(a-1) == AO_USB_DESC_DEVICE)
-                               return a - 2;
+               /* The address of this has moved depending on padding
+                * in the linker script and romconfig symbols. Look
+                * forward and backwards two and four bytes to see if
+                * we can find it
+                */
+               a = usb_descriptors.address;
 
-                       return -1;
-               } catch (ArrayIndexOutOfBoundsException ae) {
-                       return -1;
+               for (int look : look_around) {
+                       try {
+                               if (get_u8(a + look) == 0x12 && get_u8(a + look + 1) == AO_USB_DESC_DEVICE)
+                                       return a;
+                       } catch (ArrayIndexOutOfBoundsException ae) {
+                               continue;
+                       }
                }
+               return -1;
        }
 
        public AltosUsbId find_usb_id() {
index ca3e33eb244ffc91d47a4a035a8ffad5a9e5e668..1ac075e394c13b01b03658c1a26857dbf053aac4 100644 (file)
@@ -227,7 +227,7 @@ public class AltosIdleFetch implements AltosDataProvider {
                try {
                        boolean matched = false;
                        /* Fetch config data from remote */
-                       AltosConfigData config_data = new AltosConfigData(link);
+                       AltosConfigData config_data = link.config_data();
                        listener.set_state(AltosLib.ao_flight_stateless);
                        for (AltosIdler idler : idlers) {
                                if (idler.matches(config_data)) {
index 9946b83586f18d082268fb86a0761da1ac92f7f9..b713b3dcc9cfebfb0bffc7f145c216b9aea0be79 100644 (file)
@@ -539,6 +539,7 @@ public abstract class AltosLink implements Runnable {
                if (debug)
                        System.out.printf("stop remote\n");
                try {
+                       flush_output();
                        flush_input();
                } finally {
                        printf ("~\n");
index 00b4c4b30829e3cbd9b774283bba8efba4efab4c..2fda9621e70c0fd09b3c4dc8ff278050a03ad936 100644 (file)
@@ -72,8 +72,8 @@ public class AltosPreferences {
        /* Launcher channel preference name */
        public final static String launcherChannelPreference = "LAUNCHER-CHANNEL";
 
-       /* Default logdir is ~/TeleMetrum */
-       public final static String logdirName = "TeleMetrum";
+       /* Default logdir is ~/AltusMetrum */
+       public final static String logdirName = "AltusMetrum";
 
        /* Log directory */
        public static File logdir;
index d868b9aa444cfc488476ea7b244de71e24053691..670946582386a3f5412e6881a006bab840aeca46 100644 (file)
@@ -28,6 +28,7 @@ public class AltosRomconfig implements AltosUnitInfoListener {
        public int      check;
        public int      serial_number;
        public int      radio_calibration;
+       public int      address_offset;
        public AltosUsbId       usb_id;
        public String           usb_product;
 
@@ -46,9 +47,9 @@ public class AltosRomconfig implements AltosUnitInfoListener {
                return (int) (find_address(hexfile, name, len) - hexfile.address);
        }
 
-       static int get_int(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol {
+       static private int get_int(AltosHexfile hexfile, String name, int len, int adjust) throws AltosNoSymbol {
                byte[] bytes = hexfile.data;
-               int start = (int) find_offset(hexfile, name, len);
+               int start = (int) find_offset(hexfile, name, len) + adjust;
 
                int     v = 0;
                int     o = 0;
@@ -142,33 +143,46 @@ public class AltosRomconfig implements AltosUnitInfoListener {
                }
        }
 
+       static final int adjust_rom[] = { 0, -4, 4 };
+
        public AltosRomconfig(AltosHexfile hexfile) {
                try {
-                       version = get_int(hexfile, ao_romconfig_version, 2);
-                       check = get_int(hexfile, ao_romconfig_check, 2);
-                       if (check == (~version & 0xffff)) {
-                               switch (version) {
-                               case 2:
-                               case 1:
-                                       serial_number = get_int(hexfile, ao_serial_number, 2);
-                                       try {
-                                               radio_calibration = get_int(hexfile, ao_radio_cal, 4);
-                                       } catch (AltosNoSymbol missing) {
-                                               radio_calibration = 0;
-                                       }
-
-                                       valid = true;
-
-                                       /* XXX TeleBT v4.0 units originally shipped without RF calibration programmed. Go fetch
-                                        * the correct value from the web site
-                                        */
-                                       if (serial_number == 2584 ||
-                                           (3686 <= serial_number && serial_number <= 3938 && radio_calibration == 5695485))
-                                       {
-                                               fetch_radio_cal();
+                       for (int adjust : adjust_rom) {
+                               try {
+                                       version = get_int(hexfile, ao_romconfig_version, 2, adjust);
+                                       check = get_int(hexfile, ao_romconfig_check, 2, adjust);
+                                       if (check == (~version & 0xffff)) {
+                                               System.out.printf("adjust %d version %x check %x success\n", adjust, version, check);
+                                               switch (version) {
+                                               case 2:
+                                               case 1:
+                                                       serial_number = get_int(hexfile, ao_serial_number, 2, adjust);
+                                                       try {
+                                                               radio_calibration = get_int(hexfile, ao_radio_cal, 4, adjust);
+                                                       } catch (AltosNoSymbol missing) {
+                                                               radio_calibration = 0;
+                                                       }
+
+                                                       valid = true;
+
+                                                       /* XXX TeleBT v4.0 units originally shipped without RF calibration programmed. Go fetch
+                                                        * the correct value from the web site
+                                                        */
+                                                       if (serial_number == 2584 ||
+                                                           (3686 <= serial_number && serial_number <= 3938 && radio_calibration == 5695485))
+                                                       {
+                                                               fetch_radio_cal();
+                                                       }
+
+                                                       break;
+                                               }
+                                               break;
+                                       } else {
+                                               System.out.printf("adjust %d version %x check %x fail\n", adjust, version, check);
                                        }
-
-                                       break;
+                               } catch (ArrayIndexOutOfBoundsException aie) {
+                                       System.out.printf("adjust %d out of bounds\n", adjust);
+                                       continue;
                                }
                        }
                        usb_id = hexfile.find_usb_id();
index 8df3c022a398c3067a7222768befb981ad5ff0d0..278d3fea167f076bf0dac50f886f5b94d2040dfd 100644 (file)
@@ -97,6 +97,8 @@ public class AltosConfigFCUI
 
        ActionListener          listener;
 
+       static final String     title = "Configure Flight Computer";
+
        static String[]         main_deploy_values_m = {
                "100", "150", "200", "250", "300", "350",
                "400", "450", "500"
@@ -119,6 +121,7 @@ public class AltosConfigFCUI
                "Dual Deploy",
                "Redundant Apogee",
                "Redundant Main",
+               "Separation & Apogee",
        };
 
        static String[]         aprs_interval_values = {
@@ -310,6 +313,22 @@ public class AltosConfigFCUI
                }
        }
 
+       void set_pad_orientation_values() {
+               String [] new_values;
+               if (has_radio())
+                       new_values = pad_orientation_values_radio;
+               else
+                       new_values = pad_orientation_values_no_radio;
+               if (new_values != pad_orientation_values) {
+                       int id = pad_orientation_value.getSelectedIndex();
+                       pad_orientation_value.removeAllItems();
+                       pad_orientation_values = new_values;
+                       for (int i = 0; i < new_values.length; i++)
+                               pad_orientation_value.addItem(pad_orientation_values[i]);
+                       pad_orientation_value.setSelectedIndex(id);
+               }
+       }
+
        void set_accel_tool_tips() {
                if (accel_plus_value.isVisible()) {
                        accel_plus_value.setToolTipText("Pad acceleration value in flight orientation");
@@ -329,7 +348,7 @@ public class AltosConfigFCUI
 
        /* Build the UI using a grid bag */
        public AltosConfigFCUI(JFrame in_owner, boolean remote) {
-               super (in_owner, "Configure Flight Computer", false);
+               super (in_owner, title, false);
 
                owner = in_owner;
                GridBagConstraints c;
@@ -338,7 +357,8 @@ public class AltosConfigFCUI
                Insets il = new Insets(4,4,4,4);
                Insets ir = new Insets(4,4,4,4);
 
-               pane = getContentPane();
+               pane = getScrollablePane();
+
                pane.setLayout(new GridBagLayout());
 
                /* Product */
@@ -787,10 +807,7 @@ public class AltosConfigFCUI
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
                c.ipady = 5;
-               if (has_radio())
-                       pad_orientation_values = pad_orientation_values_radio;
-               else
-                       pad_orientation_values = pad_orientation_values_no_radio;
+               pad_orientation_values = pad_orientation_values_no_radio;
 
                pad_orientation_value = new JComboBox<String>(pad_orientation_values);
                pad_orientation_value.setEditable(false);
@@ -1030,11 +1047,13 @@ public class AltosConfigFCUI
 
        public void set_dirty() {
                dirty = true;
+               setTitle(title + " (modified)");
                save.setEnabled(true);
        }
 
        public void set_clean() {
                dirty = false;
+               setTitle(title);
                save.setEnabled(false);
        }
 
@@ -1062,13 +1081,13 @@ public class AltosConfigFCUI
                if (cmd.equals("Close") || cmd.equals("Reboot"))
                        if (!check_dirty(cmd))
                                return;
+               if (cmd.equals("Save"))
+                       save.setEnabled(false);
                listener.actionPerformed(e);
                if (cmd.equals("Close") || cmd.equals("Reboot")) {
                        setVisible(false);
                        dispose();
                }
-               if (cmd.equals("Save") || cmd.equals("Reset"))
-                       set_clean();
        }
 
        /* ItemListener interface method */
@@ -1101,6 +1120,7 @@ public class AltosConfigFCUI
                set_pad_orientation_tool_tip();
                set_accel_tool_tips();
                set_flight_log_max_tool_tip();
+               set_pad_orientation_values();
        }
 
        public void set_version(String version) {
index 309bb8ee80c7c35fdbdbfe096926423157d3cdba..2b01cee877509d95564de9217776f850af7afb70 100644 (file)
@@ -386,7 +386,7 @@ public class AltosConfigPyroUI
 
                GridBagConstraints      c;
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                int     nrow = 0;
index 0fdf4449938a06cabc7eaaf5e5383e409e800747..b2e8e8030f36be542525a474074f68e7b8c42113 100644 (file)
@@ -82,7 +82,7 @@ public class AltosConfigTDUI
                Insets il = new Insets(4,4,4,4);
                Insets ir = new Insets(4,4,4,4);
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                /* Product */
index 608042a544947e05521e8213987a071d2c15fd42..a2d0c3645b898daadb7f7c00e10d141e9aabe45d 100644 (file)
@@ -186,7 +186,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
                voice = in_voice;
                reader = in_reader;
 
-               bag = getContentPane();
+               bag = getScrollablePane();
                bag.setLayout(new GridBagLayout());
 
                setTitle(String.format("AltOS %s", reader.name));
index 26bc06e40f648ba4aa8df345826d685c4fe57106..50994bb27293d55c71e3af9b5311339a49b4ffc6 100644 (file)
@@ -226,7 +226,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl
                /* We let the user set the freq/callsign, so don't bother with the cancel dialog */
                link.set_cancel_enable(false);
 
-               bag = getContentPane();
+               bag = getScrollablePane();
                bag.setLayout(new GridBagLayout());
 
                setTitle(String.format("AltOS %s", device.toShortString()));
index 0d848ab86fea079e2c39780f9eecf03533b678e6..8256722a513269405ece3db08e16b5c7d8c0a5ca 100644 (file)
@@ -65,7 +65,7 @@ public class AltosIgniteUI
                }
 
                Igniter(AltosIgniteUI ui, String label, String name, int y) {
-                       Container               pane = getContentPane();
+                       Container               pane = getScrollablePane();
                        GridBagConstraints      c = new GridBagConstraints();
                        Insets                  i = new Insets(4,4,4,4);
 
@@ -388,7 +388,7 @@ public class AltosIgniteUI
        private void make_ui() {
                group = new ButtonGroup();
 
-               Container               pane = getContentPane();
+               Container               pane = getScrollablePane();
 
                GridBagConstraints      c = new GridBagConstraints();
                Insets                  i = new Insets(4,4,4,4);
index 875b786e7c77e6fdb295b26644b05f433ca3079a..6615063badd39bb12f5cb3594312e8a1aeb63e49 100644 (file)
@@ -393,7 +393,7 @@ public class AltosLaunchUI
                if (!open())
                        return;
 
-               Container               pane = getContentPane();
+               Container               pane = getScrollablePane();
                GridBagConstraints      c = new GridBagConstraints();
                Insets                  i = new Insets(4,4,4,4);
 
@@ -510,4 +510,4 @@ public class AltosLaunchUI
 
                setVisible(true);
        }
-}
\ No newline at end of file
+}
index 16966918da4e3f715b18f4e71db0714ebb17f56e..145a260ba76c07cfcb7dffb469b6191049f4d556 100755 (executable)
@@ -1,4 +1,16 @@
 #!/bin/bash
+#
+# Fix fonts. I don't know why the getting the
+# basename of the app set to . matters, but it does
+#
+case "$0" in
+    /*)
+        cd `dirname "$0"`
+        ./`basename "$0"` "$@"
+        exit $?
+        ;;
+esac
+export FREETYPE_PROPERTIES=truetype:interpreter-version=35
 ##################################################################################
 #                                                                                #
 # universalJavaApplicationStub                                                   #
index 8e0e208aea668333b2c70b7bacf04ab474f25d99..c7ec9ca9d08d70b2b129753efb6b6a3688048207 100644 (file)
@@ -150,7 +150,7 @@ var quit
 var skip
 
 Function GetJRE
-  ${OpenURL} "java.com"
+  ${OpenURL} "adoptopenjdk.net"
   MessageBox MB_OK "Click OK to continue after completing the Java Install."
 FunctionEnd
 
index b172b0227603f235f3d11b9188ba82a4ce18e152..6d4ed1bca79e4bfb5b4a150390f104f2f23c4e9c 100644 (file)
@@ -183,7 +183,7 @@ LINUX_FILES=$(FAT_FILES) $(LINUX_LIBS) $(FIRMWARE) $(DOC) $(desktop_file).in $(L
 LINUX_EXTRA=altosui-fat
 
 MACOSX_INFO_PLIST=Info.plist
-MACOSX_INSTALL=install-macosx
+MACOSX_INSTALL=install-macosx ask-pass
 MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(DOC) ReadMe-Mac.rtf $(MACOSX_ICONS) $(MACOSX_INSTALL)
 MACOSX_EXTRA=$(FIRMWARE)
 
index fa803c5fc566a5851f262aff271a5a2dd785d74d..6d4876720980e523d624910fb163dec83a09ebd8 100644 (file)
@@ -121,7 +121,7 @@ Section "Firmware"
        SetOutPath $INSTDIR
 
        File "../src/telemetrum-v2.0/telemetrum-v2.0-${VERSION}.ihx"
-;      File "../src/telemetrum-v3.0/telemetrum-v3.0-${VERSION}.ihx"
+       File "../src/telemetrum-v3.0/telemetrum-v3.0-${VERSION}.ihx"
        File "../src/telemini-v3.0/telemini-v3.0-${VERSION}.ihx"
        File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
        File "../src/telegps-v2.0/telegps-v2.0-${VERSION}.ihx"
diff --git a/altosui/ask-pass b/altosui/ask-pass
new file mode 100755 (executable)
index 0000000..605ccb7
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+osascript -e 'display dialog "Password:" with hidden answer default answer "" with title "Password for '$USER'"' -e 'text returned of result'
index aebfd5276d58fbab1162b513f38979005c805912..8f0067e5a030190d3fbb25656a8338361a4b57bf 100755 (executable)
@@ -1,9 +1,47 @@
-#!/bin/sh
+#!/bin/bash
+
+JVM=/Library/Java/JavaVirtualMachines
 dir=`dirname "$0"`
+
+case `id -u` in
+    0)
+    ;;
+    *)
+       SUDO_ASKPASS="${dir}/ask-pass" sudo -A "$0" "$@"
+       exit 0
+       ;;
+esac
+
+# Check for java
+if ls "$JVM" | grep -q adopt; then
+    echo "Adopt OpenJDK already present"
+else
+    open https://adoptopenjdk.net/
+    osascript -e 'display dialog "Install Java from https://adoptopenjdk.net then click Continue" buttons {"Continue"} default button 1 with title "Install Java"' >/dev/null
+fi
+
 cd "$dir"
-mkdir -p ~/Applications/AltOS
-find ~/Applications/AltOS -type d -print0 | xargs -0 chmod +w
-cp -f -a * ~/Applications/AltOS
-cd ~/Applications/AltOS
-chmod +w *
-xattr -c *
+LIBRARY=/Library/AltusMetrum
+APPLICATIONS=/Applications
+INSTALLED=
+for file in *; do
+    echo 'Installing' "$file"
+    case "$file" in
+       *.app)
+           mkdir -p "${APPLICATIONS}"
+           if [ -d "${APPLICATIONS}/${file}" ]; then
+               rm -rf "${APPLICATIONS}/${file}"
+           fi
+           cp -a "$file" "${APPLICATIONS}/${file}"
+           chmod -R +w "${APPLICATIONS}/${file}"
+           xattr -rc "${APPLICATIONS}/${file}"
+           APP=`basename "$file" .app`
+           INSTALLED="${INSTALLED} ${APP}"
+           ;;
+       *)
+           mkdir -p "${LIBRARY}"
+           cp -a "$file" "${LIBRARY}"
+           ;;
+    esac
+done
+osascript -e 'display dialog "Installation of'"${INSTALLED}"' complete" with title "Installation Complete" buttons {"OK"} default button 1' >/dev/null
index 1726190d58bbdb7b20751bf784643ac260b4775e..37e820b62389178207a08a7fdd1d447839df91fa 100644 (file)
@@ -219,7 +219,7 @@ public class AltosBTManage extends AltosUIDialog implements ActionListener, Iter
 
                found_devices = new LinkedBlockingQueue<AltosBTDevice>();
 
-               Container pane = getContentPane();
+               Container pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                GridBagConstraints c = new GridBagConstraints();
index d24480b33fb7869d37632fd3c5dd95f18db16e74..49fe6b40b48900b6726b756f9be714897ddace3c 100644 (file)
@@ -67,7 +67,7 @@ class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
                got_ok = false;
                frame = in_frame;
 
-               Container pane = getContentPane();
+               Container pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                GridBagConstraints c = new GridBagConstraints();
@@ -302,7 +302,7 @@ public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener {
 
                frequencies = new FrequencyList(in_frequencies);
 
-               Container pane = getContentPane();
+               Container pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                GridBagConstraints c = new GridBagConstraints();
index 7da9786cce698bc510ecd14c66669b92a2d107a4..90ce58ac0208f66850c6c3698c2a3613fb363717 100644 (file)
@@ -56,7 +56,7 @@ public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMo
                Insets il = new Insets(4,4,4,4);
                Insets ir = new Insets(4,4,4,4);
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                c = new GridBagConstraints();
index fd84f921c5d75a5fb0249133321ad0ffd98af247..6b78aea7f69a2706a3e2d439159ec2ecfe42a6f5 100644 (file)
@@ -131,7 +131,7 @@ public class AltosFlashUI
                Insets il = new Insets(4,4,4,4);
                Insets ir = new Insets(4,4,4,4);
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                c = new GridBagConstraints();
@@ -208,9 +208,18 @@ public class AltosFlashUI
 
                public AltosHexfileFilter(String usb_product) {
                        int l;
+                       int dash;
 
                        /* Trim off any trailing variants (1.0a vs 1.0) */
-                       for (l = usb_product.length(); l > 0; l--) {
+                       for (dash = usb_product.length(); dash > 0; dash--) {
+                               char c = usb_product.charAt(dash-1);
+                               if (c == '-')
+                                       break;
+                       }
+                       if (dash == 0)
+                               dash = usb_product.length();
+
+                       for (l = usb_product.length(); l > dash; l--) {
                                char c = usb_product.charAt(l-1);
                                if (c < 'a' || 'z' < c)
                                        break;
@@ -637,7 +646,7 @@ public class AltosFlashUI
                        super(in_owner, "Open Flash Target Device", true);
                        owner = in_owner;
 
-                       Container               pane = getContentPane();
+                       Container               pane = getScrollablePane();
                        GridBagConstraints      c = new GridBagConstraints();
                        Insets                  i = new Insets(4,4,4,4);
 
index a25c39c468796637a479356de689100ad2bbde9d..44d3a9f8a685687212aee908c7cbf1a94daadfe4 100644 (file)
@@ -51,7 +51,7 @@ public class AltosRomconfigUI
                Insets il = new Insets(4,4,4,4);
                Insets ir = new Insets(4,4,4,4);
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                int y = 0;
@@ -74,7 +74,10 @@ public class AltosRomconfigUI
                c.weightx = 1;
                c.anchor = GridBagConstraints.LINE_START;
                c.insets = ir;
-               product_value = new JLabel(config.usb_product);
+               String product = "unknown";
+               if (config != null)
+                       product = config.usb_product;
+               product_value = new JLabel(product);
                pane.add(product_value, c);
 
                y++;
index a09142e53406dc0fc7bd0d5a241a71d0c8aa306d..4ec858fa89de9e399921190f6d038286499a488e 100644 (file)
@@ -470,7 +470,7 @@ public class AltosScanUI
                if (!open())
                        return;
 
-               Container               pane = getContentPane();
+               Container               pane = getScrollablePane();
                GridBagConstraints      c = new GridBagConstraints();
                Insets                  i = new Insets(4,4,4,4);
 
index 7ca8ea8292fb589f36a0c9a810024cc23ba5243d..94d80193c2d1b5dbbcc6cffb0cbd7b4aed677729 100644 (file)
@@ -164,7 +164,7 @@ public class AltosUIAccelCal
                this.link = link;
                this.config_values = config_values;
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                GridBagConstraints c = new GridBagConstraints();
index 8ee89dd4400a72a47b9cb459a57af70888e7f76e..09e7daaab595f73cb257e85921f4f32a2e841d81 100644 (file)
@@ -260,7 +260,7 @@ public class AltosUIConfigure
                super(in_owner, name, false);
 
                owner = in_owner;
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                row = 0;
index 34bd50d80ecf82ffaec1156aab534362abaa345e..be883a1479baa48fe486c8bd1f01a554394640d1 100644 (file)
@@ -30,6 +30,30 @@ class AltosUIDialogListener extends WindowAdapter {
 
 public class AltosUIDialog extends JDialog implements AltosUIListener {
 
+       private Container scrollPane;
+
+       public Container getScrollablePane() {
+               if (scrollPane == null) {
+                       Container content = super.getContentPane();
+                       /* Create a container to hold the dialog contents */
+                       scrollPane = new Container();
+
+                       /* Make an opaque box to use the right color */
+                       Box box = new Box(BoxLayout.X_AXIS);
+                       box.add(scrollPane);
+                       box.setOpaque(true);
+
+                       /* Create a scrollpane to hold the box */
+                       JScrollPane scroll = new JScrollPane();
+                       JViewport view = scroll.getViewport();
+                       view.add(box);
+
+                       /* Add the scroll pane to the top level */
+                       content.add(scroll);
+               }
+               return (Container) scrollPane;
+       }
+
        public void ui_changed(String look_and_feel) {
                SwingUtilities.updateComponentTreeUI(this);
                this.pack();
index 71e16e1d372ec00820938b73197aa77380a58a5f..f701ce7afa0d1b8243a1736dfecb470ae64f0e69 100644 (file)
@@ -41,6 +41,30 @@ public class AltosUIFrame extends JFrame implements AltosUIListener, AltosPositi
                this.pack();
        }
 
+       private Container scrollPane;
+
+       public Container getScrollablePane() {
+               if (scrollPane == null) {
+                       Container content = super.getContentPane();
+                       /* Create a container to hold the dialog contents */
+                       scrollPane = new Container();
+
+                       /* Make an opaque box to use the right color */
+                       Box box = new Box(BoxLayout.X_AXIS);
+                       box.add(scrollPane);
+                       box.setOpaque(true);
+
+                       /* Create a scrollpane to hold the box */
+                       JScrollPane scroll = new JScrollPane();
+                       JViewport view = scroll.getViewport();
+                       view.add(box);
+
+                       /* Add the scroll pane to the top level */
+                       content.add(scroll);
+               }
+               return (Container) scrollPane;
+       }
+
        static String[] altos_icon_names = {
                "/altusmetrum-altosui-16.png",
                "/altusmetrum-altosui-32.png",
index 31c8ed1b8abc9911df9ef2d77a3807b616039916..9ba273553885242686840c1f74230ba5798dc400 100644 (file)
@@ -336,7 +336,7 @@ public class AltosUIMapPreload extends AltosUIFrame implements ActionListener, I
        public AltosUIMapPreload(AltosUIFrame in_owner) {
                owner = in_owner;
 
-               Container               pane = getContentPane();
+               Container               pane = getScrollablePane();
                GridBagConstraints      c = new GridBagConstraints();
                Insets                  i = new Insets(4,4,4,4);
 
index 7e3178d8dd887a926ebc28d127e084801b91d056..c40903ced0c37c590214b11d764af264bde8714e 100644 (file)
@@ -129,18 +129,23 @@ public class AltosUIPreferences extends AltosPreferences {
                        backend.putInt(fontSizePreference, font_size);
                        flush_preferences();
                        AltosUILib.set_fonts(font_size);
-                       for (AltosFontListener l : font_listeners)
+                       for (AltosFontListener l : font_listeners) {
+                               System.out.printf("notifying %s of font size change\n", l);
                                l.font_size_changed(font_size);
+                       }
+                       System.out.printf("all fonts changed\n");
                }
        }
 
        public static void register_font_listener(AltosFontListener l) {
+               System.out.printf("register font listener\n");
                synchronized (backend) {
                        font_listeners.add(l);
                }
        }
 
        public static void unregister_font_listener(AltosFontListener l) {
+               System.out.printf("unregister font listener\n");
                synchronized (backend) {
                        font_listeners.remove(l);
                }
index 50ec4c03bc843399d380df97b6645926d9c6fd83..585bd7740d293b1b256c408d6c5d32a31912c1cd 100644 (file)
@@ -26,7 +26,7 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
 
        public String toString() {
                String  name = getName();
-               if (name == null)
+               if (name == null || "".equals(name))
                        name = "Altus Metrum";
                return String.format("%-20.20s %4d %s",
                                     name, getSerial(), getPath());
@@ -34,7 +34,7 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
 
        public String toShortString() {
                String  name = getName();
-               if (name == null)
+               if (name == null || "".equals(name))
                        name = "Altus Metrum";
                return String.format("%s %d %s",
                                     name, getSerial(), getPath());
index 3e9fddaa4da8203bf26350cf266b9730ccb02a14..af72bab869575ed650f26a74ec633356c9bcaf2b 100755 (executable)
@@ -66,12 +66,8 @@ esac
 
 CALFILE=cal-$SERIAL.txt
 
-echo 'E 0' > $dev
-
 ../ao-tools/ao-cal-freq/ao-cal-freq --nosave --output=$CALFILE --tty=$dev
 
-# echo 'E 1' > $dev
-
 CAL_VALUE=`cat $CALFILE`
 echo $SERIAL","$CAL_VALUE >> cal_values
 echo "Reflashing with calibration: $CAL_VALUE"
index 7b95bf20fb9eb4ea756564b439061a8f4517b6fb..a8fb8c862b1dbc4742c8f127a1884c98faa6086f 100755 (executable)
@@ -58,6 +58,6 @@ SERIAL=$SERIAL ./cal-freq $dev
 
 echo 'E 1' > $dev
 
-./test-telemega
+./test-telemega-v1.0
 
 exit $?
index 1fce345ac8d305e274eefd7839017bf0c450385b..272a69d7536b17f6789fa040d87d70767080c02a 100755 (executable)
@@ -76,6 +76,6 @@ done
 
 echo 'E 1' > $dev
 
-./test-telemega
+./test-telemega-v3.0
 
 exit $?
index 2f0762420432fece69f082c618a6a0a20b296bbf..90055d783160a4aa1517bc7c3881decfc97dd6f7 100644 (file)
@@ -636,7 +636,43 @@ main (int argc, char **argv)
                                        break;
                                case AO_LOG_FORMAT_TELEGPS:
                                        log_gps = (struct ao_log_gps *) &eeprom->data[pos];
-                                       (void) log_gps;
+                                       switch (log_gps->type) {
+                                       case AO_LOG_GPS_TIME:
+                                               printf(" lat %10.7f Â° lon %10.7f Â° alt %8d m",
+                                                      log_gps->u.gps.latitude / 10000000.0,
+                                                      log_gps->u.gps.longitude/ 10000000.0,
+                                                      (int32_t) (log_gps->u.gps.altitude_low |
+                                                                 (log_gps->u.gps.altitude_high << 16)));
+                                               printf(" time %02d:%02d:%02d %04d-%02d-%02d flags %02x",
+                                                      log_gps->u.gps.hour,
+                                                      log_gps->u.gps.minute,
+                                                      log_gps->u.gps.second,
+                                                      log_gps->u.gps.year + 2000,
+                                                      log_gps->u.gps.month,
+                                                      log_gps->u.gps.day,
+                                                      log_gps->u.gps.flags);
+                                               printf(" course %3d ground_speed %5u climb_rate %6d pdop %3d hdop %3d vdop %3d mode %3d",
+                                                      log_gps->u.gps.course,
+                                                      log_gps->u.gps.ground_speed,
+                                                      log_gps->u.gps.climb_rate,
+                                                      log_gps->u.gps.pdop,
+                                                      log_gps->u.gps.hdop,
+                                                      log_gps->u.gps.vdop,
+                                                      log_gps->u.gps.mode);
+                                               break;
+                                       case AO_LOG_GPS_SAT:
+                                               printf(" channels %2d",
+                                                      log_gps->u.gps_sat.channels);
+                                               for (i = 0; i < 12; i++) {
+                                                       printf(" svid %3d c_n %2d",
+                                                              log_gps->u.gps_sat.sats[i].svid,
+                                                              log_gps->u.gps_sat.sats[i].c_n);
+                                               }
+                                               break;
+                                       default:
+                                               printf (" unknown");
+                                               break;
+                                       }
                                        break;
                                case AO_LOG_FORMAT_DETHERM:
                                        break;
index 8a0377676d15bbad868f47f853c37f2e12f7a8c2..bd3d51cd511f30685b9130a739055089bec81d74 100644 (file)
@@ -18,13 +18,13 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([altos], 1.9.4)
+AC_INIT([altos], 1.9.5)
 ANDROID_VERSION=27
 AC_CONFIG_SRCDIR([src/kernel/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
-RELEASE_DATE=2020-07-02
+RELEASE_DATE=2020-09-29
 AC_SUBST(RELEASE_DATE)
 
 DOC_DATE=`LC_ALL=C date -d $RELEASE_DATE +'%d %b %Y'`
index e56e2a55bcfbb9a1a4626517549323cc1347b397..165317e2ff0f351016ecf0dadb5a197d8543fbb7 100644 (file)
@@ -17,6 +17,7 @@ FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
 endif
 
 RELNOTES_INC=\
+       release-notes-1.9.5.inc \
        release-notes-1.9.4.inc \
        release-notes-1.9.3.inc \
        release-notes-1.9.2.inc \
index 066283c32a8380cef9beac537e641a2bb9473a17..7541b844408aaea79d8a03c5b54e0bd9ab239d97 100644 (file)
@@ -1,6 +1,6 @@
 Creating documentation for a new release of AltOS
 
-* Write release notes in release-notes-${version}.inc. Add to Makefile
+* Write release notes in release-notes-${version}.inc.
 
 * Make sure that doc/altusmetrum.txt has the right copyright year
 
index 15f9129e4d0dd55cbc5a459909aae2030de38e4a..a533ca82213debb5455671d278192640ac3d4bed 100644 (file)
@@ -171,6 +171,10 @@ ifdef::altusmetrum[]
                is fired first, followed after a two second
                delay by the 'main' channel.
 
+               Separation & Apogee::
+               This fires the 'main' channel when the first motor
+               burns out and fires the 'apogee' charge at apogee.
+
        ifdef::telemetrum,telemega,easymega,easytimer[]
        ==== Pad Orientation
 
index c4b1baa597f9b7621493300fa4a259f4b9af522f..eac1c4afa14d7f38c0961ef2e31333589e555160 100644 (file)
@@ -1,10 +1,10 @@
 :notitle:
 :doctype: article
 
-== EasyMini Outline and Hole Pattern
+== EasyMini/EasyMotor/EasyTimer Outline and Hole Pattern
        This image, when printed, provides a precise template for the
-       mounting holes in EasyMini.  EasyMini has overall dimensions
-       of 0.800 x 1.500 inches, and the mounting holes are sized for
-       use with 4-40 or M3 screws.
+       mounting holes in EasyMini, EasyMotor, and EasyTimer.  Each of 
+       these products has overall dimensions of 0.800 x 1.500 inches, 
+       and the mounting holes are sized for use with 4-40 or M3 screws.
 
        image::easymini.svg[align="center"]
index 990ee69f52fb0d2baf67580541ad67b5dbae5ddd..66544c1513e90c5c90232f8de754360623f88957 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.5.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.4.adoc[]
 
diff --git a/doc/release-notes-1.9.5.inc b/doc/release-notes-1.9.5.inc
new file mode 100644 (file)
index 0000000..220caaa
--- /dev/null
@@ -0,0 +1,45 @@
+= Release Notes for Version 1.9.5
+include::release-head.adoc[]
+:doctype: article
+
+       Version 1.9.5
+
+       == AltOS
+
+       * Add Booster mode for all dual-deploy altimeters. Select
+         "Separation & Apogee" mode in AltosUI to fire the 'main'
+         channel at first motor burnout and the 'apogee' channel at
+         apogee.
+
+       * Improve reliability of stm32l firmware under heavy
+         load. This was found using Monitor Idle on TeleMega with all
+         flash slots full of data which would occasionally lock up.
+
+       * Fix orientation label in AltosUI for devices with
+         radios. This makes the orientation say 'Antenna up' and
+         'Antenna Down' for TeleMetrum and TeleMega again.
+
+       * Fix log data for pyro channels which were inhibited (often
+         because of a tilt limit). They used to report 'fired' as
+         soon as they were inhibited, which was misleading. Now they
+         never report as having been fired.
+
+       * Allow Igniter Test to fire each igniter more than once.
+
+       == AltosUI
+
+       * Improve performance of Monitor Idle mode by sending less data for each
+         update.
+
+       * Improve Mac OS X install scripts so that they work on
+          Catalina. This involves sending the user to get Java from
+          the AdoptOpenJDK project which provides a version that works
+          with Java applications.
+
+       * Make larger dialogs scrollable for use on smaller screens.
+
+       * Fix troubles re-flashing EasyMega boards running older
+          firmware.
+
+       * Add TeleMetrum v3.0 firmware to the Windows
+          AltosUI packages.
index 160128b2f0df1822f96d80748bc79366cd33a5db..917753f46f041dce2675fc6be70e0e4742c7e9e2 100644 (file)
@@ -1,5 +1,9 @@
 [appendix]
 == Release Notes
+       :leveloffset: 2
+       include::release-notes-1.9.5.adoc[]
+
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.4.adoc[]
 
index 8b315ccb6156d8780188922b62f6a3128af49f56..30e8f73b7c319a0bd5266f8fd753a3194cc26eca 100644 (file)
@@ -1,15 +1,17 @@
 [appendix]
 == Release Notes
        :leveloffset: 2
-       include::release-notes-1.9.4.adoc[]
+       include::release-notes-1.9.5.adoc[]
 
        <<<<
+       :leveloffset: 2
+       include::release-notes-1.9.4.adoc[]
 
+       <<<<
        :leveloffset: 2
        include::release-notes-1.9.3.adoc[]
 
        <<<<
-
        :leveloffset: 2
        include::release-notes-1.9.1.adoc[]
 
index f5199cc4820b53772e7c0ad4eac552742d150222..0317613cae8340033759a4d5c9554bad10f52241 100644 (file)
                memory.  For example, the default 435.750 MHz would be 
                configured using
 
-                       c f 435750 +
+                       c F 435750
                        c w
 
+               Note that the 'f' parameter is a frequency calibration value
+               that you really, really, really don't want to change.  So, 
+               please be careful to make sure you use capital 'F', not lower
+               case 'f' when changing the operating frequency!
 
        === Callsign
 
index 1999a9c77e6a2557458fc97aa07a5888d18d664b..b9216a2235288d58a8c50705d18b40a6b9b2101c 100644 (file)
@@ -84,7 +84,7 @@
 
                        Connect pin 6 and pin 1 of the companion
                        connector. Pin 1 can be identified by the square pad
-                       around it, and then the pins could sequentially across
+                       around it, and then the pins count sequentially across
                        the board. Be very careful to *not* short pin 8 to
                        anything as that is connected directly to the
                        battery. Pin 7 carries 3.3V and the board will crash
@@ -97,7 +97,7 @@
 
                        Connect pin 6 and pin 1 of the companion
                        connector. Pin 1 can be identified by the square pad
-                       around it, and then the pins could sequentially across
+                       around it, and then the pins count sequentially across
                        the board. Be very careful to *not* short pin 8 to
                        anything as that is connected directly to the
                        battery. Pin 7 carries 3.3V and the board will crash
                        Connect pin 5 and pin 1 of the debug connector, which
                        is the six holes next to the beeper. Pin 1 can be
                        identified by the square pad around it, and then the
-                       pins could sequentially across the board, making Pin 5
+                       pins count sequentially across the board, making Pin 5
                        the one on the other end of the row.
                        endif::easytimer[]
 
 
                        Connect pin 6 and pin 1 of the companion
                        connector. Pin 1 can be identified by the square pad
-                       around it, and then the pins could sequentially across
+                       around it, and then the pins count sequentially across
                        the board. Be very careful to *not* short pin 8 to
                        anything as that is connected directly to the
                        battery. Pin 7 carries 3.3V and the board will crash
                        Connect pin 6 and pin 1 of the debug connector, which
                        is the six holes next to the beeper. Pin 1 can be
                        identified by the square pad around it, and then the
-                       pins could sequentially across the board, making Pin 6
+                       pins count sequentially across the board, making Pin 6
                        the one on the other end of the row.
                        endif::easymini[]
 
index 1430aacb2fb07cdd65d1be3a56ececd3096edb8e..77c7cca514f1e6196288eefbd5d6372821bc00a8 100644 (file)
@@ -33,12 +33,12 @@ OS_SRCS=libaltos_posix.c libaltos_darwin.c
 #      -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
 #      -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
 
-XCODE=/Applications/Xcode-beta.app
-SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
+XCODE=/Applications/Xcode.app
+SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk
 MINVERSION=10.5
 
 OS_LIB_CFLAGS=\
-       -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 -isysroot $(SDK) \
+       -DDARWIN -DPOSIX_TTY -arch x86_64 -isysroot $(SDK) \
        -mmacosx-version-min=10.5 \
        -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
        -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
index c18493ea7836aca971c0f9ebe8b3b04b1b8d85de..0d5b9c46309e1ec164fbe924bb3921b099bb8013 100755 (executable)
Binary files a/libaltos/libaltos.dylib and b/libaltos/libaltos.dylib differ
index c6b6355f870fb9e1cf33fbedb96dc93ea65fe6f0..794c021500e8673c237297c0677f224fcc15a4a1 100644 (file)
@@ -192,7 +192,8 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
                if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
                    get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
                    get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
-                   get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
+                   (get_string (usb_device, CFSTR("kUSBProductString"), device->name, sizeof (device->name)) ||
+                    get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name))) &&
                    get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
                        device->serial = atoi(serial_string);
                        IOObjectRelease(object);
index 03c2958f52bc1a63b1a0dc71c01eb43a82472e8a..162c85bab8fa6aa658479017bb920395fb678e8a 100644 (file)
@@ -131,6 +131,15 @@ altos_ftdi_list_start(void)
        return list;
 }
 
+static struct {
+       char    *windows;
+       char    *real;
+} name_map[] = {
+       { .windows = "AltusMetrum28", .real = "EasyMega" },
+       { .windows = "AltusMetrum2c", .real = "EasyMotor" },
+       { 0, 0 },
+};
+
 PUBLIC int
 altos_list_next(struct altos_list *list, struct altos_device *device)
 {
@@ -148,6 +157,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
        DWORD           friendlyname_len;
        char            instanceid[1024];
        DWORD           instanceid_len;
+       int             i;
 
        dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
        while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
@@ -230,6 +240,16 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
                        altos_set_last_windows_error();
                        continue;
                }
+               for (i = 0; name_map[i].windows; i++)
+                       if (!strcmp(name_map[i].windows, friendlyname)) {
+                               strcpy(friendlyname, name_map[i].real);
+                               break;
+                       }
+
+               char *space = strchr(friendlyname, ' ');
+               if  (space)
+                       *space = '\0';
+
                device->vendor = vid;
                device->product = pid;
                device->serial = serial;
index 23ec077ec4cda796c35f9b4d4970c2ec93621465..816dd4b3414ede0dae87e02efb540f57fd07f208 100644 (file)
@@ -137,7 +137,7 @@ MACOSX_DRIVERS=$(MACOSX_DRIVER_1) $(MACOSX_DRIVER_0)
 
 MACOSX_INFO_PLIST=Info.plist
 MACOSX_README=ReadMe-Mac.rtf
-MACOSX_INSTALL=../altosui/install-macosx
+MACOSX_INSTALL=../altosui/install-macosx ../altosui/ask-pass
 MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVERS) $(MACOSX_README) $(DOC) $(MACOSX_ICONS) $(MACOSX_INSTALL)
 
 $(MACOSX_DRIVER_0):
index 4a795dffa2337edd97c2dc8a8c3f9bd0b0671a55..359ccd7aea592bced582a440e87d8f3f6d66a02c 100644 (file)
@@ -34,8 +34,10 @@ public class MicroData {
 
        private double          time_step;
        private ArrayList<Integer>      bytes;
+       public int              nsamples;
        public int              log_id;
        String                  name;
+       String                  unique_id;
 
        public static final int LOG_ID_MICROPEAK = 0;
        public static final int LOG_ID_MICROKITE = 1;
@@ -134,6 +136,21 @@ public class MicroData {
                return v;
        }
 
+       private String get_line(InputStream f) throws IOException, FileEndedException, NonHexcharException {
+               int c;
+               StringBuffer line = new StringBuffer();
+
+               do {
+                       c = f.read();
+               } while (Character.isWhitespace(c));
+
+               do {
+                       line.append((char) c);
+                       c = f.read();
+               } while (!Character.isWhitespace(c));
+               return new String(line);
+       }
+
        private int swap16(int i) {
                return ((i << 8) & 0xff00) | ((i >> 8) & 0xff);
        }
@@ -277,10 +294,14 @@ public class MicroData {
                        file_crc = 0xffff;
                        ground_pressure = get_32(f);
                        min_pressure = get_32(f);
-                       int nsamples = get_16(f);
+                       nsamples = get_16(f);
 
                        log_id = nsamples >> 12;
                        nsamples &= 0xfff;
+                       if (log_id == LOG_ID_MICROPEAK2) {
+                               int nsamples_high = get_16(f);
+                               nsamples |= (nsamples_high << 12);
+                       }
 
                        cal_data.set_ground_pressure(ground_pressure);
 
@@ -328,6 +349,15 @@ public class MicroData {
                                flight_series.set_pressure(cur);
                        }
 
+                       int current_crc = swap16(~file_crc & 0xffff);
+                       int crc = get_16(f);
+
+                       crc_valid = crc == current_crc;
+
+                       if (log_id == LOG_ID_MICROPEAK2) {
+                               unique_id = get_line(f);
+                       }
+
                        flight_series.finish();
 
                        /* Build states */
@@ -335,8 +365,10 @@ public class MicroData {
                        flight_series.set_time(0);
                        flight_series.set_state(AltosLib.ao_flight_boost);
 
-                       flight_series.set_time(flight_series.speed_series.max().time);
-                       flight_series.set_state(AltosLib.ao_flight_coast);
+                       if (flight_series.speed_series != null && flight_series.speed_series.max() != null) {
+                               flight_series.set_time(flight_series.speed_series.max().time);
+                               flight_series.set_state(AltosLib.ao_flight_coast);
+                       }
 
                        flight_series.set_time(flight_series.height_series.max().time);
                        flight_series.set_state(AltosLib.ao_flight_drogue);
@@ -351,10 +383,6 @@ public class MicroData {
 
                        flight_stats = new AltosFlightStats(flight_series);
 
-                       int current_crc = swap16(~file_crc & 0xffff);
-                       int crc = get_16(f);
-
-                       crc_valid = crc == current_crc;
 
                } catch (FileEndedException fe) {
                        throw new IOException("File Ended Unexpectedly");
index 1ede2d9a78989dd14f8599d098191807bdbe7026..7e3d1e593dfc6658d737902ec5546afecdffb905 100644 (file)
@@ -64,21 +64,27 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
        }
 
        private void done_internal() {
-               setVisible(false);
-               dispose();
-
                if (data != null && data.crc_valid) {
-                       status_value.setText("Received MicroPeak Data");
-                       owner = owner.SetData(data);
-                       MicroSave save = new MicroSave(owner, data);
-                       if (save.runDialog())
-                               owner.SetName(data.name);
+                       if (data.nsamples == 0) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             "No Flight Data Present",
+                                                             "Empty Log",
+                                                             JOptionPane.WARNING_MESSAGE);
+                       } else {
+                               status_value.setText("Received MicroPeak Data");
+                               owner = owner.SetData(data);
+                               MicroSave save = new MicroSave(owner, data);
+                               if (save.runDialog())
+                                       owner.SetName(data.name);
+                       }
                } else {
                        JOptionPane.showMessageDialog(owner,
                                                      "Download Failed",
                                                      "Flight data corrupted",
                                                      JOptionPane.ERROR_MESSAGE);
                }
+               setVisible(false);
+               dispose();
        }
 
        public void drain_queue() {
@@ -152,6 +158,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
                                } catch (MicroData.NonHexcharException nhe) {
                                }
                        }
+                       write_thread.join();
                } catch (FileNotFoundException fe) {
                } catch (IOException ioe) {
                } catch (InterruptedException ie) {
@@ -162,6 +169,25 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
        }
 
        Thread  serial_thread;
+       Thread  write_thread;
+
+       public class SerialWriter implements Runnable {
+               MicroSerial serial;
+
+               public void run () {
+                       try {
+                               Thread.sleep(100);
+                               serial.write('l');
+                               serial.write('\n');
+                               serial.flush();
+                       } catch (InterruptedException ie) {
+                       }
+               }
+
+               public SerialWriter(MicroSerial serial) {
+                       this.serial = serial;
+               }
+       }
 
        public void start() {
                try {
@@ -172,6 +198,10 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
                }
                serial_thread = new Thread(this);
                serial_thread.start();
+
+               SerialWriter writer = new SerialWriter(serial);
+               write_thread = new Thread(writer);
+               write_thread.start();
        }
 
        public void actionPerformed(ActionEvent ae) {
@@ -194,7 +224,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList
                this.owner = owner;
                this.device = device;
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                c = new GridBagConstraints();
index cea41c41374d8690af1649b8fcbc3678850f6cd3..f75cd1c3cf30156e05e00f04ac5ec6c9139d9d4b 100644 (file)
@@ -25,22 +25,29 @@ import org.altusmetrum.altosuilib_14.*;
 
 public class MicroFile {
 
-       public static File make(File directory, int year, int month, int day) {
+       public static File make(MicroData data, File directory, int year, int month, int day) {
+               String unique = "";
+               if (data != null && data.unique_id != null)
+                       unique = String.format("-%s", data.unique_id);
                for (int sequence = 1;; sequence++) {
-                       String s = String.format("%04d-%02d-%02d-flight-%03d.mpd",
-                                                year, month, day, sequence);
+                       String s = String.format("%04d-%02d-%02d%s-flight-%03d.mpd",
+                                                year, month, day, unique, sequence);
                        File file = new File(directory, s);
                        if (!file.exists())
                                return file;
                }
        }
 
-       public static File make(File directory) {
+       public static File make(MicroData data, File directory) {
                Calendar        cal = Calendar.getInstance();
-               return make(directory, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
+               return make(data, directory, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
+       }
+
+       public static File make(MicroData data) {
+               return make(data, AltosUIPreferences.logdir());
        }
 
        public static File make() {
-               return make(AltosUIPreferences.logdir());
+               return make(null);
        }
-}
\ No newline at end of file
+}
index 16966918da4e3f715b18f4e71db0714ebb17f56e..145a260ba76c07cfcb7dffb469b6191049f4d556 100755 (executable)
@@ -1,4 +1,16 @@
 #!/bin/bash
+#
+# Fix fonts. I don't know why the getting the
+# basename of the app set to . matters, but it does
+#
+case "$0" in
+    /*)
+        cd `dirname "$0"`
+        ./`basename "$0"` "$@"
+        exit $?
+        ;;
+esac
+export FREETYPE_PROPERTIES=truetype:interpreter-version=35
 ##################################################################################
 #                                                                                #
 # universalJavaApplicationStub                                                   #
index eb08c5527a3516edcbc12e6efd403f983ebe405e..7d3e20d8d1a4f308692ebe9158582a370aa408be 100644 (file)
@@ -37,8 +37,30 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
        MicroData       data;
        Container       container;
        JTabbedPane     pane;
+       JMenuBar        menu_bar;
        static int      number_of_windows;
 
+       /* File menu */
+       final static String     open_command = "open";
+       final static String     save_command = "save";
+       final static String     export_command = "export";
+       final static String     preferences_command = "preferences";
+       final static String     close_command = "close";
+       final static String     exit_command = "exit";
+
+       static final String[][] file_menu_entries = new String[][] {
+               { "Open",               open_command },
+               { "Save a Copy",        save_command },
+               { "Export Data",        export_command },
+               { "Preferences",        preferences_command },
+               { "Close",              close_command },
+               { "Exit",               exit_command },
+       };
+
+       /* Download menu */
+       final static String     download_command = "download";
+       final static String     download_label = "Download";
+
        MicroPeak SetData(MicroData data) {
                MicroPeak       mp = this;
                if (this.data != null) {
@@ -174,20 +196,20 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
        }
 
        public void actionPerformed(ActionEvent ev) {
-               if ("Exit".equals(ev.getActionCommand()))
-                       System.exit(0);
-               else if ("Close".equals(ev.getActionCommand()))
-                       Close();
-               else if ("Open".equals(ev.getActionCommand()))
+               if (open_command.equals(ev.getActionCommand()))
                        SelectFile();
-               else if ("Download".equals(ev.getActionCommand()))
-                       DownloadData();
-               else if ("Export".equals(ev.getActionCommand()))
+               else if (save_command.equals(ev.getActionCommand()))
+                       Save();
+               else if (export_command.equals(ev.getActionCommand()))
                        Export();
-               else if ("Preferences".equals(ev.getActionCommand()))
+               else if (preferences_command.equals(ev.getActionCommand()))
                        Preferences();
-               else if ("Save a Copy".equals(ev.getActionCommand()))
-                       Save();
+               else if (close_command.equals(ev.getActionCommand()))
+                       Close();
+               else if (exit_command.equals(ev.getActionCommand()))
+                       System.exit(0);
+               else if (download_command.equals(ev.getActionCommand()))
+                       DownloadData();
        }
 
        public void itemStateChanged(ItemEvent e) {
@@ -225,6 +247,29 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                return 1.0;
        }
 
+       private void add_menu(JMenu menu, String label, String action) {
+               JMenuItem       item = new JMenuItem(label);
+               menu.add(item);
+               item.addActionListener(this);
+               item.setActionCommand(action);
+       }
+
+
+       private JMenu make_menu(String label, String[][] items) {
+               JMenu   menu = new JMenu(label);
+               for (int i = 0; i < items.length; i++) {
+                       if (MAC_OS_X) {
+                               if (items[i][1].equals("exit"))
+                                       continue;
+                               if (items[i][1].equals("preferences"))
+                                       continue;
+                       }
+                       add_menu(menu, items[i][0], items[i][1]);
+               }
+               menu_bar.add(menu);
+               return menu;
+       }
+
        public MicroPeak() {
 
                ++number_of_windows;
@@ -238,43 +283,15 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
 
                setTitle("MicroPeak");
 
-               JMenuBar menuBar = new JMenuBar();
-               setJMenuBar(menuBar);
-
-               JMenu fileMenu = new JMenu("File");
-               menuBar.add(fileMenu);
-
-               JMenuItem openAction = new JMenuItem("Open");
-               fileMenu.add(openAction);
-               openAction.addActionListener(this);
-
-               JMenuItem downloadAction = new JMenuItem("Download");
-               fileMenu.add(downloadAction);
-               downloadAction.addActionListener(this);
-
-               JMenuItem saveAction = new JMenuItem("Save a Copy");
-               fileMenu.add(saveAction);
-               saveAction.addActionListener(this);
-
-               JMenuItem exportAction = new JMenuItem("Export");
-               fileMenu.add(exportAction);
-               exportAction.addActionListener(this);
-
-               JMenuItem preferencesAction = new JMenuItem("Preferences");
-               fileMenu.add(preferencesAction);
-               preferencesAction.addActionListener(this);
-
-               JMenuItem closeAction = new JMenuItem("Close");
-               fileMenu.add(closeAction);
-               closeAction.addActionListener(this);
+               menu_bar = new JMenuBar();
+               setJMenuBar(menu_bar);
 
-               JMenuItem exitAction = new JMenuItem("Exit");
-               fileMenu.add(exitAction);
-               exitAction.addActionListener(this);
+               JMenu file_menu = make_menu("File", file_menu_entries);
 
-               JButton downloadButton = new JButton ("Download");
-               downloadButton.addActionListener(this);
-               menuBar.add(downloadButton);
+               JButton download_button = new JButton (download_label);
+               download_button.setActionCommand(download_command);
+               download_button.addActionListener(this);
+               menu_bar.add(download_button);
 
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                addWindowListener(new WindowAdapter() {
@@ -303,12 +320,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene
                container.validate();
                doLayout();
                validate();
-               Insets i = getInsets();
-               Dimension ps = pane.getPreferredSize();
-               ps.width += i.left + i.right;
-               ps.height += i.top + i.bottom;
-//             setPreferredSize(ps);
-               setSize(ps);
+               pack();
                setVisible(true);
        }
 
index b45cd834d3a2c1c1ae557323b8aced57bc9b9020..f6e2ed2a2e1743e67eb38cfcb9b7a9e2ed2ad4fb 100644 (file)
@@ -72,7 +72,7 @@ public class MicroSave extends JFileChooser {
                                                                      JOptionPane.YES_NO_OPTION);
                                if (r != JOptionPane.YES_OPTION)
                                        continue;
-                                                             
+
                                if (!file.canWrite()) {
                                        JOptionPane.showMessageDialog(frame,
                                                                      String.format("\"%s\" is not writable",
@@ -104,6 +104,6 @@ public class MicroSave extends JFileChooser {
                setFileFilter(new FileNameExtensionFilter("MicroPeak data file",
                                                          "mpd"));
                setCurrentDirectory(AltosUIPreferences.last_logdir());
-               setSelectedFile(MicroFile.make());
+               setSelectedFile(MicroFile.make(data));
        }
 }
index 57fb30db90766fbb06d85e08b382ebaee4846dc3..c688242874837c2c60c9093191e3d847e920867a 100644 (file)
@@ -28,6 +28,8 @@ public class MicroSerial extends InputStream {
        private MicroSerialLog  log;
 
        public int read() {
+               if (file == null)
+                       return -1;
                int     c = libaltos.altos_getchar(file, 0);
                if (Thread.interrupted())
                        return -1;
@@ -40,6 +42,14 @@ public class MicroSerial extends InputStream {
                return c;
        }
 
+       public void write(char c) {
+               libaltos.altos_putchar(file, c);
+       }
+
+       public void flush() {
+               libaltos.altos_flush(file);
+       }
+
        public void close() {
                if (file != null) {
                        libaltos.altos_close(file);
index 7d683d8c6d9c5879bb4050ad07d6f9c6d5ecf633..3443ec8ac394cbd5f630f7d678e23f5dc9239189 100644 (file)
@@ -49,7 +49,7 @@ ARMM0DIRS=\
        chaoskey-v1.0 chaoskey-v1.0/flash-loader \
        telemini-v3.0 telemini-v3.0/flash-loader \
        easymini-v2.0 easymini-v2.0/flash-loader \
-       micropeak-v2.0 micropeak-v2.0/flash-loader
+       micropeak-v2.0
 
 AVRDIRS=\
        micropeak microkite microsplash
index 5550eb447e101f3fa724120bf634053ca1b28540..1a2bd34be251472563faeaf1e206da07f525cd9d 100644 (file)
 #define ao_arch_block_interrupts()     cli()
 #define ao_arch_release_interrupts()   sei()
 
-#define ao_mutex_get(m)
-#define ao_mutex_put(m)
-
 void
-ao_delay_until(uint16_t target);
+ao_delay_until(AO_TICK_TYPE target);
 
 /* We can't hit 100 Hz, but we can hit 125 */
 #define AO_HERTZ       125
index 69b259d9419c34b6c8c24951605f03a8a82dc070..e51f456b5965594aa4f075257109d8d292bcef79 100644 (file)
@@ -121,3 +121,5 @@ extern void ao_report_altitude(void);
 
 void ao_delay_us(uint16_t us);
 
+void
+ao_led_toggle(uint8_t colors);
index 2ac0500b217f307466fd8be143eae566969eac89..0669585082bec63d74f2b9585b421756302d303c 100644 (file)
@@ -31,7 +31,7 @@ ISR(TIMER1_COMPA_vect)
 AO_TICK_TYPE
 ao_time(void)
 {
-       uint16_t        r;
+       AO_TICK_TYPE    r;
 
        cli();
        r = ao_tick_count;
@@ -127,7 +127,7 @@ void ao_delay_us(uint16_t us)
 }
 
 void
-ao_delay_until(uint16_t target)
+ao_delay_until(AO_TICK_TYPE target)
 {
        cli();
        ao_wakeup_count = target;
@@ -137,7 +137,7 @@ ao_delay_until(uint16_t target)
 }
 
 void
-ao_delay(uint16_t ticks)
+ao_delay(AO_TICK_TYPE ticks)
 {
        ao_delay_until(ao_time() + ticks);
 }
index d3454f917fc6f75aa32d5879d2d3d9a4cf821198..a8fa85836489513a00625fc3f194341644012c37 100644 (file)
@@ -78,9 +78,8 @@ extern uint8_t        ao_cpu_sleep_disable;
 
 #define ao_arch_task_globals   uint8_t ao_cpu_sleep_disable;
 
-#define ao_arch_init_stack(task, start) \
+#define ao_arch_init_stack(task, sp, start)                            \
        do {                                                            \
-               uint8_t         *sp = task->stack8 + AO_STACK_SIZE - 1; \
                uint16_t        a = (uint16_t) start;                   \
                int             i;                                      \
                                                                        \
index c2bbf2d2f2a1b4dd00d9ba766e450a4f7a95f275..2a94d968a3ea4d8f0a4177f1ca4ed6aa4413da3d 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index dca2213b1ba94cb3b111a19ed81301c6e1cf8450..c7cf78af7d8f7940c985a10c2171630a6c606d77 100644 (file)
@@ -26,6 +26,8 @@
 #define PRINTD(l,...)
 #endif
 
+#define AO_ADXL375_SPI_SPEED   ao_spi_speed(5000000)
+
 struct ao_adxl375_sample       ao_adxl375_current;
 
 static void
index c3922b60651130a6dcccaef19bf302b0a755c787..427a081bc36e21db5e56a65e92101225f0690517 100644 (file)
@@ -24,7 +24,9 @@ static uint8_t        ao_bmx160_configured;
 
 static struct ao_bmm150_trim ao_bmm150_trim;
 
-#define ao_bmx160_spi_get()    ao_spi_get(AO_BMX160_SPI_BUS, AO_SPI_SPEED_8MHz)
+#define AO_BMX160_SPI_SPEED    ao_spi_speed(10000000)
+
+#define ao_bmx160_spi_get()    ao_spi_get(AO_BMX160_SPI_BUS, AO_BMX160_SPI_SPEED)
 #define ao_bmx160_spi_put()    ao_spi_put(AO_BMX160_SPI_BUS)
 
 #define ao_bmx160_spi_start()  ao_spi_set_cs(AO_BMX160_SPI_CS_PORT,    \
index b1a1377875c0d17be8c9c65185e89bbdd8b35fbc..1ebc0ea20bc9afcda54969bd3b944aebeee316cc 100644 (file)
@@ -42,8 +42,10 @@ extern const uint32_t        ao_radio_cal;
 
 #define FOSC   32000000
 
-#define ao_radio_try_select(task_id)   ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id)
-#define ao_radio_select()      ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)
+#define AO_CC1120_SPI_SPEED    ao_spi_speed(6100000)   /* 6.1MHz max with 32MHz osc */
+
+#define ao_radio_try_select(task_id)   ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_CC1120_SPI_SPEED, task_id)
+#define ao_radio_select()      ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_CC1120_SPI_SPEED)
 #define ao_radio_deselect()    ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
 #define ao_radio_spi_start_bytes()     ao_spi_start_bytes(AO_CC1120_SPI_BUS)
 #define ao_radio_spi_stop_bytes()      ao_spi_stop_bytes(AO_CC1120_SPI_BUS)
index 2b5fd3fd9313ffaf636b78649752ed74a42a05f3..dc8e9ff315ad303df49ee0b1ccc151767e8c842e 100644 (file)
@@ -39,6 +39,8 @@ static uint8_t ao_radio_abort;                /* radio operation should abort */
 
 #define FOSC   26000000
 
+#define AO_CC115L_SPI_SPEED    ao_spi_speed(6500000)   /* for back-to-back access */
+
 #define ao_radio_select()      ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_CC115L_SPI_SPEED)
 #define ao_radio_deselect()    ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS)
 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS)
index 105e0d50a80aa072a2147248d1cf57edd4a0e8e2..3ccf121f1a1f3301f0b2e720d2308e78febb5be9 100644 (file)
@@ -51,9 +51,7 @@ extern const uint32_t ao_radio_cal;
 #define FOSC   40000000
 #endif
 
-#ifndef AO_CC1200_SPI_SPEED
-#error AO_CC1200_SPI_SPEED undefined
-#endif
+#define AO_CC1200_SPI_SPEED    ao_spi_speed(7700000)   /* 7.7MHz max for extended memory reads */
 
 #define ao_radio_select()      ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_CC1200_SPI_SPEED)
 #define ao_radio_deselect()    ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
index d6fbb6b7480de528c322eac0f778a671b9d44d85..093356a59981ecdea92b82927f3ac919f1a1facf 100644 (file)
 #error HAS_COMPANION not set in ao_companion.c
 #endif
 
+#define AO_COMPANION_SPI_SPEED ao_spi_speed(200000)
+
 #define COMPANION_SELECT()     do {                    \
                ao_spi_get_bit(AO_COMPANION_CS_PORT,    \
                               AO_COMPANION_CS_PIN,     \
                               AO_COMPANION_SPI_BUS,    \
-                              AO_SPI_SPEED_200kHz);    \
+                              AO_COMPANION_SPI_SPEED); \
        } while (0)
 
 #define COMPANION_DESELECT()   do {                    \
index 899bee74915e0be87330b4892bb62cd15a5dfc31..b32034e7d3f2f0903a03751e7c8210ffc17462ef 100644 (file)
@@ -147,15 +147,6 @@ ao_led_set(AO_LED_TYPE colors)
                ao_gpio_set(ao_leds[i].port, ao_leds[i].pin, (colors >> i) & 1);
 }
 
-void
-ao_led_toggle(AO_LED_TYPE colors)
-{
-       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, ~ao_gpio_get(ao_leds[i].port, ao_leds[i].pin));
-}
-
 void
 ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) 
 {
index ca0615e7c5b75e30c8e1eb0b50f98d741977f2e7..2e4cbedf989d23991c54245b6a6a18d392e2d1b1 100644 (file)
@@ -82,11 +82,11 @@ uint16_t    ao_storage_unit;
  */
 
 #if M25_MAX_CHIPS > 1
-static uint8_t ao_m25_size[M25_MAX_CHIPS];     /* number of sectors in each chip */
+static uint32_t ao_m25_size[M25_MAX_CHIPS];    /* number of sectors in each chip */
 static ao_port_t ao_m25_pin[M25_MAX_CHIPS];    /* chip select pin for each chip */
 static uint8_t ao_m25_numchips;                        /* number of chips detected */
 #endif
-static uint8_t ao_m25_total;                   /* total sectors available */
+static uint32_t ao_m25_total;                  /* total sectors available */
 static ao_port_t ao_m25_wip;                   /* write in progress */
 
 static uint8_t ao_m25_mutex;
@@ -101,12 +101,14 @@ static uint8_t ao_m25_mutex;
 
 static uint8_t ao_m25_instruction[4];
 
-#define M25_SELECT(cs)         ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS, AO_SPI_SPEED_FAST)
+#define AO_M25_SPI_SPEED       ao_spi_speed(10000000)  /* this seems like a reasonable minimum speed to require */
+
+#define M25_SELECT(cs)         ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS,AO_M25_SPI_SPEED)
 #define M25_DESELECT(cs)       ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS)
 
 #define M25_BLOCK_SHIFT                        16
 #define M25_BLOCK                      65536L
-#define M25_POS_TO_SECTOR(pos)         ((uint8_t) ((pos) >> M25_BLOCK_SHIFT))
+#define M25_POS_TO_SECTOR(pos)         ((uint32_t) ((pos) >> M25_BLOCK_SHIFT))
 #define M25_SECTOR_TO_POS(sector)      (((uint32_t) (sector)) << M25_BLOCK_SHIFT)
 
 /*
@@ -146,7 +148,7 @@ ao_m25_write_enable(ao_port_t cs)
 /*
  * Returns the number of 64kB sectors
  */
-static uint8_t
+static uint32_t
 ao_m25_read_capacity(ao_port_t cs)
 {
        uint8_t capacity;
@@ -172,7 +174,7 @@ ao_m25_set_address(uint32_t pos)
 {
        ao_port_t       mask;
 #if M25_MAX_CHIPS > 1
-       uint8_t size;
+       uint32_t        size;
        uint8_t         chip;
 
        for (chip = 0; chip < ao_m25_numchips; chip++) {
@@ -204,7 +206,8 @@ static uint8_t
 ao_m25_scan(void)
 {
 #if M25_MAX_CHIPS > 1
-       uint8_t pin, size;
+       uint8_t pin;
+       uint32_t size;
 #endif
 
        if (ao_m25_total)
@@ -344,12 +347,12 @@ ao_storage_device_info(void)
        ao_mutex_put(&ao_m25_mutex);
 
 #if M25_MAX_CHIPS > 1
-       printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total);
+       printf ("Detected chips %d size %ld\n", ao_m25_numchips, ao_m25_total);
        for (chip = 0; chip < ao_m25_numchips; chip++)
                printf ("Flash chip %d select %02x size %d\n",
                        chip, ao_m25_pin[chip], ao_m25_size[chip]);
 #else
-       printf ("Detected chips 1 size %d\n", ao_m25_total);
+       printf ("Detected chips 1 size %ld\n", ao_m25_total);
 #endif
 
 #if M25_DEBUG
index 4c24e98b71c1e432883f32703a90e2f569d16ce8..7736a0f89c4889d49cb3a86a31667fb226d56794 100644 (file)
 #define PRINTD(l,...) 
 #endif
 
+#define AO_MMA655X_SPI_SPEED   ao_spi_speed(8333333)   /* 120ns clock period */
+
 static void
 ao_mma655x_start(void) {
        ao_spi_get_bit(AO_MMA655X_CS_PORT,
                       AO_MMA655X_CS_PIN,
                       AO_MMA655X_SPI_INDEX,
-                      AO_SPI_SPEED_FAST);
+                      AO_MMA655X_SPI_SPEED);
 }
 
 static void
index c894239ec0e54ae0934781886c44a759e8bcc38b..7c9d6b6bffaa343469576c4429bf4d883fad69d5 100644 (file)
@@ -32,7 +32,9 @@ static uint8_t        ao_mpu6000_configured;
 
 #if AO_MPU6000_SPI
 
-#define ao_mpu6000_spi_get()   ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz)
+#define AO_MPU6000_SPI_SPEED   ao_spi_speed(1000000)   /* 1Mhz for all register access */
+
+#define ao_mpu6000_spi_get()   ao_spi_get(AO_MPU6000_SPI_BUS, AO_MPU6000_SPI_SPEED)
 #define ao_mpu6000_spi_put()   ao_spi_put(AO_MPU6000_SPI_BUS)
 
 #define ao_mpu6000_spi_start()         ao_spi_set_cs(AO_MPU6000_SPI_CS_PORT,   \
@@ -383,7 +385,7 @@ ao_mpu6000_init(void)
         */
 
        ao_cur_task = &ao_mpu6000_task;
-       ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz);
+       ao_mpu6000_spi_get();
        ao_cur_task = NULL;
 #endif
 
index 0597a81c57fbc8677bc64d93002db7d0d0ca88b5..09b65bfa749c8cd7de7b1e5f6ff712d5cc602c74 100644 (file)
@@ -35,7 +35,7 @@ static uint8_t        ao_mpu9250_configured;
 #if AO_MPU9250_SPI
 
 #ifndef AO_MPU9250_SPI_SPEED
-#define AO_MPU9250_SPI_SPEED   AO_SPI_SPEED_1MHz
+#define AO_MPU9250_SPI_SPEED   ao_spi_speed(1000000)   /* 1MHz max SCLK */
 #endif
 
 #define ao_mpu9250_spi_get()   ao_spi_get(AO_MPU9250_SPI_BUS, AO_MPU9250_SPI_SPEED)
index 1ebba3e9c6f99ccfb0fd7a7bbebd42b1e7da2c58..c5e733a46e6bf4dacca71dd40ba9e581cd745d90 100644 (file)
@@ -25,9 +25,7 @@
 struct ao_ms5607_prom  ao_ms5607_prom;
 static uint8_t         ms5607_configured;
 
-#ifndef AO_MS5607_SPI_SPEED
-#define AO_MS5607_SPI_SPEED    AO_SPI_SPEED_FAST
-#endif
+#define AO_MS5607_SPI_SPEED    ao_spi_speed(20000000)
 
 static void
 ao_ms5607_start(void) {
index 4d13decc46ec271bb9fff384ad937c6db8b79bd6..3983dc941598ff6e584d1e53e8b688323e7a7dd5 100644 (file)
@@ -350,11 +350,10 @@ ao_bt_panic(int where)
 {
        int i;
        for (;;) {
-               for (i = 0; i < 50; i++) {
-                       ao_led_toggle(AO_BT_LED);
+               for (i = 0; i < 25; i++) {
+                       ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(10));
                        ao_delay(AO_MS_TO_TICKS(10));
                }
-               ao_led_off(AO_BT_LED);
                ao_delay(AO_MS_TO_TICKS(500));
                for (i = 0; i < where; i++) {
                        ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(200));
@@ -548,7 +547,10 @@ ao_rn_factory(void)
                v = 1-v;
                ao_delay(AO_MS_TO_TICKS(50));
                ao_gpio_set(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, v);
-               ao_led_toggle(AO_BT_LED);
+               if (v)
+                       ao_led_on(AO_BT_LED);
+               else
+                       ao_led_off(AO_BT_LED);
        }
 
        /* And let P3_1 float again */
index bfa777c66401466a9348abd6f7a2c1da4687bc84..d16843d62cf345903eca1516961bc8b4ed25c058 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index 399654f0ed6f598ed1fa9fb2f5559436181724c4..a3d04da52d008a5746fafd07e8ddffa361c118a2 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 16MHz High speed external crystal */
 #define AO_HSE                 16000000
@@ -324,7 +323,6 @@ struct ao_adc {
 #define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
 #define AO_ADXL375_CS_PORT     (&stm_gpioc)
 #define AO_ADXL375_CS_PIN      12
-#define AO_ADXL375_SPI_SPEED   AO_SPI_SPEED_4MHz
 
 #define AO_ADXL375_INT1_PORT   (&stm_gpiob)
 #define AO_ADXL375_INT1_PIN    8
index fa810fdae4efde8be69f5768d4e2cf21b73670b7..863909d553342c140f56f823835893cbbb8ccdb8 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 16MHz High speed external crystal */
 #define AO_HSE                 16000000
@@ -324,7 +323,6 @@ struct ao_adc {
 #define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
 #define AO_ADXL375_CS_PORT     (&stm_gpioc)
 #define AO_ADXL375_CS_PIN      12
-#define AO_ADXL375_SPI_SPEED   AO_SPI_SPEED_4MHz
 
 #define AO_ADXL375_INT1_PORT   (&stm_gpiob)
 #define AO_ADXL375_INT1_PIN    8
index 201b913edd1e981532b7513d0f8eb72ec24e26c8..ef8cba2d43307a85af5602c19cb85602e73f8461 100644 (file)
@@ -19,7 +19,9 @@
 #define HAS_BEEP               1
 #define HAS_BATTERY_REPORT     1
 
-#define AO_STACK_SIZE  376
+#define AO_STACK_SIZE          360
+#define SLEEP_HASH_SIZE                3
+#define AO_NUM_TASKS           6
 
 #define IS_FLASH_LOADER        0
 
@@ -93,6 +95,7 @@
 #define USE_INTERNAL_FLASH     0
 #define HAS_IGNITE             1
 #define HAS_IGNITE_REPORT      1
+#define SLEEP_HASH_SIZE                3
 
 #define AO_DATA_RING           16
 
index 38d463100d3fd14d767bd7caf81bce52be7e31f7..ba5749e94c35e25b25ef541b132ebf994f0bddb7 100644 (file)
@@ -93,7 +93,6 @@
 #define AO_MS5607_MISO_PIN     6
 #define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO_PIN)
 #define AO_MS5607_SPI_INDEX    AO_SPI_1_PA5_PA6_PA7
-#define AO_MS5607_SPI_SPEED    AO_SPI_SPEED_12MHz
 
 #define AO_DATA_RING           64
 
index 3ceb49f3c73a79f17e8a223dfe250f71d0ed2ed2..1169a2830be8839e7017f8dfc137364c5c1ca561 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 16MHz High speed external crystal */
 #define AO_HSE                 16000000
index b5dd7283748084cb3dc0e7788bcc447415aa49b1..34fdefe66484ae87d281b95ed2e24b9e90b49273 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index fb7af24dac350c717c8620e425ce81bd1a6644f8..5df4903cdd0084c7a977ccb19c2ebb76d2587c01 100644 (file)
@@ -42,6 +42,11 @@ extern char ao_getchar(void);
 
 typedef AO_PORT_TYPE ao_port_t;
 
+#ifndef AO_TICK_TYPE
+#define AO_TICK_TYPE uint32_t
+#define AO_TICK_SIGNED int32_t
+#endif
+
 #if HAS_TASK
 #include <ao_task.h>
 #else
@@ -81,7 +86,7 @@ typedef AO_PORT_TYPE ao_port_t;
 
 /* Stop the operating system, beeping and blinking the reason */
 void
-ao_panic(uint8_t reason);
+ao_panic(uint8_t reason) __attribute__((noreturn));
 
 /*
  * ao_romconfig.c
@@ -100,11 +105,6 @@ extern AO_ROMCONFIG_SYMBOL uint32_t ao_radio_cal;
  * ao_timer.c
  */
 
-#ifndef AO_TICK_TYPE
-#define AO_TICK_TYPE   uint32_t
-#define AO_TICK_SIGNED int32_t
-#endif
-
 extern volatile AO_TICK_TYPE ao_tick_count;
 
 /* Our timer runs at 100Hz */
@@ -124,7 +124,7 @@ ao_time_ns(void);
 
 /* Suspend the current task until ticks time has passed */
 void
-ao_delay(uint16_t ticks);
+ao_delay(AO_TICK_TYPE ticks);
 
 /* Set the ADC interval */
 void
@@ -749,9 +749,6 @@ enum ao_igniter {
        ao_igniter_main = 1
 };
 
-void
-ao_ignite(enum ao_igniter igniter);
-
 enum ao_igniter_status {
        ao_igniter_unknown,     /* unknown status (ambiguous voltage) */
        ao_igniter_ready,       /* continuity detected */
index fdc150f1bbb56148b2d126520105913bb134e344..8c5d53435254df11e78ad3c311c6c04fc4de1d3b 100644 (file)
@@ -85,7 +85,7 @@ ao_beep(uint8_t beep);
 
 /* Turn on the beeper for the specified time */
 void
-ao_beep_for(uint8_t beep, uint16_t ticks);
+ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks);
 
 /* Initialize the beeper */
 void
index 217b0ab1a8cd5145dbc6470f2c95bede280144f1..24eb79d9aaeba53b2fe2db62d93929569e5633d3 100644 (file)
@@ -1039,7 +1039,7 @@ const struct ao_config_var ao_config_vars[] = {
          ao_config_log_set,            ao_config_log_show },
 #endif
 #if HAS_IGNITE
-       { "i <0 dual, 1 apogee, 2 main>\0Igniter mode",
+       { "i <0 dual, 1 apogee, 2 main, 3 booster>\0Igniter mode",
          ao_config_ignite_mode_set,    ao_config_ignite_mode_show },
 #endif
 #if HAS_AES
index 87509dff8df1e94d8b8b15866a5845d021c264c0..3cfd0d0731574c71599c5946e012a6f0d6c642bc 100644 (file)
@@ -139,6 +139,7 @@ extern uint32_t     ao_send_radio_setting;
 #define AO_IGNITE_MODE_DUAL            0
 #define AO_IGNITE_MODE_APOGEE          1
 #define AO_IGNITE_MODE_MAIN            2
+#define AO_IGNITE_MODE_BOOSTER         3
 
 #define AO_RADIO_ENABLE_CORE           1
 #define AO_RADIO_DISABLE_TELEMETRY     2
index c5069158a61cc603914566a4917608a54a300be3..2142546c9b0737b186cca6f6dce65fa51c8e30ec 100644 (file)
@@ -222,6 +222,8 @@ ao_flight(void)
                                )
                        {
                                ao_flight_state = ao_flight_boost;
+                               ao_wakeup(&ao_flight_state);
+
                                ao_launch_tick = ao_boost_tick = ao_sample_tick;
 
                                /* start logging data */
@@ -242,8 +244,6 @@ ao_flight(void)
                                ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING;
                                ao_wakeup(&ao_gps_new);
 #endif
-
-                               ao_wakeup(&ao_flight_state);
                        }
                        break;
                case ao_flight_boost:
@@ -278,8 +278,8 @@ ao_flight(void)
 #else
                                ao_flight_state = ao_flight_coast;
 #endif
-                               ++ao_motor_number;
                                ao_wakeup(&ao_flight_state);
+                               ++ao_motor_number;
                        }
                        break;
 #if HAS_ACCEL && HAS_BARO
@@ -327,11 +327,9 @@ ao_flight(void)
 #endif
                                )
                        {
-#if HAS_IGNITE
-                               /* ignite the drogue charge */
-                               ao_ignite(ao_igniter_drogue);
-#endif
-
+                               /* enter drogue state */
+                               ao_flight_state = ao_flight_drogue;
+                               ao_wakeup(&ao_flight_state);
 #if HAS_TELEMETRY
                                /* slow down the telemetry system */
                                ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
@@ -339,10 +337,6 @@ ao_flight(void)
                                /* Turn the RDF beacon back on */
                                ao_rdf_set(1);
 #endif
-
-                               /* and enter drogue state */
-                               ao_flight_state = ao_flight_drogue;
-                               ao_wakeup(&ao_flight_state);
                        }
                        else
 #else /* not HAS_BARO */
@@ -362,12 +356,11 @@ ao_flight(void)
                                    ao_interval_max_accel_through - ao_interval_min_accel_through <= ao_data_accel_to_sample(MAX_QUIET_ACCEL))
                                {
                                        ao_flight_state = ao_flight_landed;
+                                       ao_wakeup(&ao_flight_state);
 #if HAS_ADC
                                        /* turn off the ADC capture */
                                        ao_timer_set_adc_interval(0);
 #endif
-
-                                       ao_wakeup(&ao_flight_state);
                                }
 
                                /* Reset interval values */
@@ -410,9 +403,8 @@ ao_flight(void)
                         */
                        if (ao_height <= ao_config.main_deploy)
                        {
-#if HAS_IGNITE
-                               ao_ignite(ao_igniter_main);
-#endif
+                               ao_flight_state = ao_flight_main;
+                               ao_wakeup(&ao_flight_state);
 
                                /*
                                 * Start recording min/max height
@@ -423,9 +415,6 @@ ao_flight(void)
                                ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
 
                                ao_interval_min_height = ao_interval_max_height = ao_avg_height;
-
-                               ao_flight_state = ao_flight_main;
-                               ao_wakeup(&ao_flight_state);
                        }
                        break;
 
@@ -445,13 +434,11 @@ ao_flight(void)
                                if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4))
                                {
                                        ao_flight_state = ao_flight_landed;
-
+                                       ao_wakeup(&ao_flight_state);
 #if HAS_ADC
                                        /* turn off the ADC capture */
                                        ao_timer_set_adc_interval(0);
 #endif
-
-                                       ao_wakeup(&ao_flight_state);
                                }
                                ao_interval_min_height = ao_interval_max_height = ao_avg_height;
                                ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
index 71c99a614352d928aaa34d5e4d9dd863c18e66b8..e4e4843e1cb8383ba1597699988fc0c67a57bf6f 100644 (file)
 #if HAS_IGNITE
 struct ao_ignition ao_ignition[2];
 
-void
-ao_ignite(enum ao_igniter igniter)
-{
-       ao_arch_block_interrupts();
-       ao_ignition[igniter].request = 1;
-       ao_wakeup(&ao_ignition);
-       ao_arch_release_interrupts();
-}
-
 #ifndef AO_SENSE_DROGUE
 #define AO_SENSE_DROGUE(p)     ((p)->adc.sense_d)
 #define AO_SENSE_MAIN(p)       ((p)->adc.sense_m)
@@ -86,9 +77,9 @@ ao_igniter_status(enum ao_igniter igniter)
 static void
 ao_igniter_fire(enum ao_igniter igniter)
 {
-       ao_ignition[igniter].firing = 1;
-       switch(ao_config.ignite_mode) {
-       case AO_IGNITE_MODE_DUAL:
+       if (!ao_ignition[igniter].fired) {
+               ao_ignition[igniter].firing = 1;
+               ao_ignition[igniter].fired = 1;
                switch (igniter) {
                case ao_igniter_drogue:
                        AO_IGNITER_SET_DROGUE(1);
@@ -101,58 +92,47 @@ ao_igniter_fire(enum ao_igniter igniter)
                        AO_IGNITER_SET_MAIN(0);
                        break;
                }
-               break;
-       case AO_IGNITE_MODE_APOGEE:
-               switch (igniter) {
-               case ao_igniter_drogue:
-                       AO_IGNITER_SET_DROGUE(1);
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_SET_DROGUE(0);
-                       ao_delay(AO_IGNITER_CHARGE_TIME);
-                       AO_IGNITER_SET_MAIN(1);
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_SET_MAIN(0);
-                       break;
-               default:
-                       break;
-               }
-               break;
-       case AO_IGNITE_MODE_MAIN:
-               switch (igniter) {
-               case ao_igniter_main:
-                       AO_IGNITER_SET_DROGUE(1);
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_SET_DROGUE(0);
-                       ao_delay(AO_IGNITER_CHARGE_TIME);
-                       AO_IGNITER_SET_MAIN(1);
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_SET_MAIN(0);
-                       break;
-               default:
-                       break;
-               }
-               break;
+               ao_ignition[igniter].firing = 0;
+               ao_delay(AO_IGNITER_CHARGE_TIME);
        }
-       ao_ignition[igniter].firing = 0;
 }
 
 static void
 ao_igniter(void)
 {
-       enum ao_igniter igniter;
-
        ao_config_get();
        for (;;) {
-               ao_sleep(&ao_ignition);
-               for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) {
-                       if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) {
-                               if (igniter == ao_igniter_drogue && ao_config.apogee_delay)
-                                       ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay));
-
-                               ao_igniter_fire(igniter);
-                               ao_delay(AO_IGNITER_CHARGE_TIME);
-                               ao_ignition[igniter].fired = 1;
+               /* Wait for flight state change */
+               ao_sleep(&ao_flight_state);
+
+               /* Fire any igniters that are supposed to be triggered
+                * in this new state
+                */
+               switch(ao_config.ignite_mode) {
+               case AO_IGNITE_MODE_DUAL:
+                       if (ao_flight_drogue <= ao_flight_state && ao_flight_state < ao_flight_landed)
+                               ao_igniter_fire(ao_igniter_drogue);
+                       if (ao_flight_main <= ao_flight_state && ao_flight_state < ao_flight_landed)
+                               ao_igniter_fire(ao_igniter_main);
+                       break;
+               case AO_IGNITE_MODE_APOGEE:
+                       if (ao_flight_drogue <= ao_flight_state && ao_flight_state < ao_flight_landed) {
+                               ao_igniter_fire(ao_igniter_drogue);
+                               ao_igniter_fire(ao_igniter_main);
                        }
+                       break;
+               case AO_IGNITE_MODE_MAIN:
+                       if (ao_flight_main <= ao_flight_state && ao_flight_state < ao_flight_landed) {
+                               ao_igniter_fire(ao_igniter_drogue);
+                               ao_igniter_fire(ao_igniter_main);
+                       }
+                       break;
+               case AO_IGNITE_MODE_BOOSTER:
+                       if (ao_flight_fast <= ao_flight_state && ao_flight_state < ao_flight_landed)
+                               ao_igniter_fire(ao_igniter_main);
+                       if (ao_flight_drogue <= ao_flight_state && ao_flight_state < ao_flight_landed)
+                               ao_igniter_fire(ao_igniter_drogue);
+                       break;
                }
        }
 }
@@ -168,10 +148,12 @@ ao_ignite_manual(void)
        ao_cmd_white();
 #if HAS_IGNITE
        if (ao_cmd_lex_c == 'm' && ao_match_word("main")) {
+               ao_ignition[ao_igniter_main].fired = 0;
                ao_igniter_fire(ao_igniter_main);
                return;
        }
        if (ao_cmd_lex_c == 'd' && ao_match_word("drogue")) {
+               ao_ignition[ao_igniter_drogue].fired = 0;
                ao_igniter_fire(ao_igniter_drogue);
                return;
        }
index b770381f7efb8aea3dcb379a5cb0981800788328..60c2d41fd10e05dbce1a7f405c020b79c76a1d91 100644 (file)
@@ -45,10 +45,6 @@ ao_led_set(AO_LED_TYPE colors);
 void
 ao_led_set_mask(AO_LED_TYPE colors, AO_LED_TYPE mask);
 
-/* Toggle the specified LEDs */
-void
-ao_led_toggle(AO_LED_TYPE colors);
-
 /* Turn on the specified LEDs for the indicated interval */
 void
 ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks);
index d6f9c5a84e85c480549fef6621793796819e2dc9..1cb03715b23eb284573e5e5ba6e22ff1e7c90b8d 100644 (file)
 #include <ao.h>
 #include <ao_micropeak.h>
 #include <ao_log_micro.h>
-#ifndef ao_async_byte
+#ifndef LOG_MICRO_ASYNC
+#define LOG_MICRO_ASYNC 1
+#endif
+#if LOG_MICRO_ASYNC
 #include <ao_async.h>
 #else
 #include <ao_serial.h>
 #endif
 #include <ao_storage.h>
 
-static uint16_t ao_log_offset = STARTING_LOG_OFFSET;
+static N_SAMPLES_TYPE ao_log_offset = STARTING_LOG_OFFSET;
 
-#define AO_LOG_ID_SHIFT        12
-#define AO_LOG_ID_MASK ((1 << AO_LOG_ID_SHIFT) - 1)
 
 void
 ao_log_micro_save(void)
 {
-       uint16_t        n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t);
+       N_SAMPLES_TYPE  n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t);
 
-#if AO_LOG_ID
-       n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT;
-#endif
        ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground));
        ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min));
        ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
@@ -88,24 +86,26 @@ ao_log_hex_nibble(uint8_t b)
                ao_async_byte('a' - 10 + b);
 }
 
-static void
+void
 ao_log_hex(uint8_t b)
 {
        ao_log_hex_nibble(b>>4);
        ao_log_hex_nibble(b&0xf);
 }
 
-static void
+void
 ao_log_newline(void)
 {
        ao_async_byte('\r');
        ao_async_byte('\n');
 }
 
+#define MAX_N_SAMPLES  ((MAX_LOG_OFFSET - STARTING_LOG_OFFSET) / 2)
+
 void
 ao_log_micro_dump(void)
 {
-       uint16_t        n_samples;
+       N_SAMPLES_TYPE  n_samples;
        uint16_t        nbytes;
        uint8_t         byte;
        uint16_t        b;
@@ -113,12 +113,24 @@ ao_log_micro_dump(void)
 
        ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
 
-       if (n_samples == 0xffff)
+       if (n_samples == (N_SAMPLES_TYPE) (~0))
                n_samples = 0;
+       nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples;
+
+       /*
+        * Rewrite n_samples so that it includes the log ID value with
+        * 32-bit n_samples split into two chunks
+        */
+       if (sizeof (n_samples) > 2) {
+               N_SAMPLES_TYPE  n_samples_low;
+               N_SAMPLES_TYPE  n_samples_high;
+               n_samples_low = n_samples & ((1 << AO_LOG_ID_SHIFT) - 1);
+               n_samples_high = (n_samples - n_samples_low) << AO_LOG_ID_WIDTH;
+               n_samples = n_samples_low | n_samples_high;
+       }
 #if AO_LOG_ID
-       n_samples &= AO_LOG_ID_MASK;
+       n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT;
 #endif
-       nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples;
        ao_async_start();
        ao_async_byte('M');
        ao_async_byte('P');
@@ -126,6 +138,11 @@ ao_log_micro_dump(void)
                if ((b & 0xf) == 0)
                        ao_log_newline();
                ao_eeprom_read(b, &byte, 1);
+#if AO_LOG_ID
+               if (N_SAMPLES_OFFSET <= b && b < (N_SAMPLES_OFFSET + sizeof(n_samples))) {
+                       byte = n_samples >> ((b - N_SAMPLES_OFFSET) << 3);
+               }
+#endif
                ao_log_hex(byte);
                crc = ao_log_micro_crc(crc, byte);
        }
index f0243028adc1a22a5686f518cffc994eead7dac4..f4870c71371d0192b6771d1f5d458a8d72035769 100644 (file)
 #ifndef _AO_LOG_MICRO_H_
 #define _AO_LOG_MICRO_H_
 
+#ifndef N_SAMPLES_TYPE
+#define N_SAMPLES_TYPE uint16_t
+#endif
+
 #define PA_GROUND_OFFSET       0
 #define PA_MIN_OFFSET          4
 #define N_SAMPLES_OFFSET       8
-#define STARTING_LOG_OFFSET    10
+#define STARTING_LOG_OFFSET    (N_SAMPLES_OFFSET + sizeof (N_SAMPLES_TYPE))
 #ifndef MAX_LOG_OFFSET
 #define MAX_LOG_OFFSET         512
 #endif
 
+#define AO_LOG_ID_SHIFT        12
+#define AO_LOG_ID_WIDTH        4
+#define AO_LOG_ID_MASK (((1 << AO_LOG_ID_WIDTH) - 1) << AO_LOG_ID_SHIFT);
+
+void
+ao_log_hex(uint8_t b);
+
+void
+ao_log_newline(void);
+
 void
 ao_log_micro_save(void);
 
index a5bdc8a7c65e5d81dbc6e0ad8b7bcf9ff54261d8..8c5743fdecd0a0a1f7ae62c528e32d27c98a138b 100644 (file)
@@ -41,17 +41,20 @@ ao_sleep(void *wchan)
 
 #if HAS_AO_DELAY
 void
-ao_delay(uint16_t ticks)
+ao_delay_until(AO_TICK_TYPE target)
 {
-       AO_TICK_TYPE    target;
-
-       if (!ticks)
-               ticks = 1;
-       target = ao_tick_count + ticks;
-       do {
-               ao_sleep(&ao_time);
-       } while ((int16_t) (target - ao_tick_count) > 0);
+       ao_arch_block_interrupts();
+       while ((int16_t) (target - ao_tick_count) > 0)
+               ao_sleep((void *) &ao_tick_count);
+       ao_arch_release_interrupts();
 }
+
+void
+ao_delay(AO_TICK_TYPE ticks)
+{
+       ao_delay_until(ao_time() + ticks);
+}
+
 #endif
 
 void
index ce622b630e7d92f834fa78883749f178faa2992a..f698a4ee2426014985a32e45e526afbf39556980 100644 (file)
 #ifndef _AO_NOTASK_H_
 #define _AO_NOTASK_H_
 
+void
+ao_delay_until(AO_TICK_TYPE target);
+
 uint8_t
 ao_sleep(void *wchan);
 
 void
 ao_wakeup(void *wchan);
 
+static inline void ao_mutex_get(uint8_t *m) {(void) m;}
+static inline void ao_mutex_put(uint8_t *m) {(void) m;}
+
 #endif /* _AO_NOTASK_H_ */
index 30d1518f051701146b8e96a95a74d7715a685ee5..80e1980ebf28b8204b10be3d2f5090017f2db43b 100644 (file)
@@ -69,6 +69,7 @@ ao_pyro_print_status(void)
 #endif
 
 uint16_t       ao_pyro_fired;
+uint16_t       ao_pyro_inhibited;
 
 #ifndef PYRO_DBG
 #define PYRO_DBG       0
@@ -274,9 +275,9 @@ ao_pyro_check(void)
        for (p = 0; p < AO_PYRO_NUM; p++) {
                pyro = &ao_config.pyro[p];
 
-               /* Ignore igniters which have already fired
+               /* Ignore igniters which have already fired or inhibited
                 */
-               if (ao_pyro_fired & (1 << p))
+               if ((ao_pyro_fired|ao_pyro_inhibited) & (1 << p))
                        continue;
 
                /* Ignore disabled igniters
@@ -308,10 +309,10 @@ ao_pyro_check(void)
 
                        /* Check to make sure the required conditions
                         * remain valid. If not, inhibit the channel
-                        * by setting the fired bit
+                        * by setting the inhibited bit
                         */
                        if (!ao_pyro_ready(pyro)) {
-                               ao_pyro_fired |= (1 << p);
+                               ao_pyro_inhibited |= (1 << p);
                                continue;
                        }
 
index ca5fcb464d9129508098394870b2568bdb724be9..213ec2d6872825cda21173ff15a13bfd8d6a5a6b 100644 (file)
@@ -22,6 +22,7 @@
 #define AO_STORAGE_DATA_SIZE   128
 
 static uint8_t storage_data[AO_STORAGE_DATA_SIZE];
+static uint8_t storage_mutex;
 
 uint8_t
 ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len)
@@ -85,28 +86,41 @@ ao_storage_write(ao_pos_t pos, void *v_buf, uint16_t len)
        return 1;
 }
 
+#ifndef AO_STORAGE_ERASED_BYTE
+#define AO_STORAGE_ERASED_BYTE 0xff
+#endif
+
 uint8_t
 ao_storage_is_erased(uint32_t pos)
 {
        uint32_t        read_pos;
        uint32_t        read_len;
        uint32_t        i;
+       uint8_t         ret = 1;
 
+       ao_storage_setup();
+       ao_mutex_get(&storage_mutex);
        read_pos = pos;
        read_len = ao_storage_block;
        while (read_len) {
                uint32_t this_time = AO_STORAGE_DATA_SIZE;
                if (this_time > read_len)
                        this_time = read_len;
-               if (!ao_storage_read(read_pos, storage_data, this_time))
-                       return 0;
+               if (!ao_storage_read(read_pos, storage_data, this_time)) {
+                       ret = 0;
+                       goto done;
+               }
                for (i = 0; i < this_time; i++)
-                       if (storage_data[i] != 0xff)
-                               return 0;
+                       if (storage_data[i] != AO_STORAGE_ERASED_BYTE) {
+                               ret = 0;
+                               goto done;
+                       }
                read_pos += this_time;
                read_len -= this_time;
        }
-       return 1;
+done:
+       ao_mutex_put(&storage_mutex);
+       return ret;
 }
 
 uint8_t
@@ -144,25 +158,29 @@ static void
 ao_storage_dump(void) 
 {
        uint32_t block;
-       uint8_t i, j;
+       uint8_t i, j, k;
 
        block = ao_cmd_hex();
        if (ao_cmd_status != ao_cmd_success)
                return;
-       for (i = 0; ; i += 8) {
+       ao_mutex_get(&storage_mutex);
+       for (i = 0; ; i += AO_STORAGE_DATA_SIZE) {
                if (ao_storage_read((block << 8) + i,
                                    storage_data,
-                                   8)) {
-                       ao_cmd_put16((uint16_t) i);
-                       for (j = 0; j < 8; j++) {
-                               putchar(' ');
-                               ao_cmd_put8(storage_data[j]);
+                                   AO_STORAGE_DATA_SIZE)) {
+                       for (k = 0; k < AO_STORAGE_DATA_SIZE; k += 8) {
+                               ao_cmd_put16((uint16_t) i + k);
+                               for (j = 0; j < 8; j++) {
+                                       putchar(' ');
+                                       ao_cmd_put8(storage_data[k + j]);
+                               }
+                               putchar ('\n');
                        }
-                       putchar ('\n');
                }
-               if (i == 248)
+               if (i == 256 - AO_STORAGE_DATA_SIZE)
                        break;
        }
+       ao_mutex_put(&storage_mutex);
 }
 
 #if HAS_STORAGE_DEBUG
index 1c5867e09eed3e9dc78f79a9a00490d488c3d9a4..026074b5d2db4c2bd30768a2e1fcd2de780bc636 100644 (file)
 typedef ao_storage_pos_t ao_pos_t;
 
 /* Total bytes of available storage */
+#ifndef ao_storage_total
 extern ao_pos_t        ao_storage_total;
+#endif
 
 /* Block size - device is erased in these units. At least 256 bytes */
+#ifndef ao_storage_block
 extern ao_pos_t        ao_storage_block;
+#endif
 
 #ifndef USE_STORAGE_CONFIG
 #define USE_STORAGE_CONFIG 1
@@ -50,7 +54,9 @@ extern ao_pos_t       ao_storage_config;
 #endif
 
 /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
+#ifndef ao_storage_unit
 extern uint16_t ao_storage_unit;
+#endif
 
 /* Initialize above values. Can only be called once the OS is running */
 void
index 0bc85d40aad2dc86c2df71ee884fb313733fbcb7..dd278bde064740f3ed0ac1a6ef11d90ccb85ab7c 100644 (file)
 #if HAS_STACK_GUARD
 #include <ao_mpu.h>
 #endif
+#include <picotls.h>
 
 #define DEBUG  0
 
-#define AO_NO_TASK_INDEX       0xff
-
 struct ao_task * ao_tasks[AO_NUM_TASKS];
 uint8_t ao_num_tasks;
 struct ao_task *ao_cur_task;
 
-#if !HAS_TASK_QUEUE
-static uint8_t ao_cur_task_index;
-#endif
-
 #ifdef ao_arch_task_globals
 ao_arch_task_globals
 #endif
@@ -61,16 +56,16 @@ static inline void ao_check_stack(void) {
 #define ao_task_irq_check()
 #endif
 
-#if HAS_TASK_QUEUE
-
+#ifndef SLEEP_HASH_SIZE
 #define SLEEP_HASH_SIZE        17
+#endif
 
 static struct ao_list  run_queue;
 static struct ao_list  alarm_queue;
 static struct ao_list  ao_sleep_queue[SLEEP_HASH_SIZE];
 
 static void
-ao_task_to_run_queue(struct ao_task *task)
+_ao_task_to_run_queue(struct ao_task *task)
 {
        ao_task_irq_check();
        ao_list_del(&task->queue);
@@ -84,7 +79,7 @@ ao_task_sleep_queue(void *wchan)
 }
 
 static void
-ao_task_to_sleep_queue(struct ao_task *task, void *wchan)
+_ao_task_to_sleep_queue(struct ao_task *task, void *wchan)
 {
        ao_task_irq_check();
        ao_list_del(&task->queue);
@@ -125,10 +120,10 @@ ao_task_validate_alarm_queue(void)
 #define ao_task_validate_alarm_queue()
 #endif
 
-uint16_t       ao_task_alarm_tick;
+AO_TICK_TYPE   ao_task_alarm_tick;
 
 static void
-ao_task_to_alarm_queue(struct ao_task *task)
+_ao_task_to_alarm_queue(struct ao_task *task)
 {
        struct ao_task  *alarm;
        ao_task_irq_check();
@@ -146,7 +141,7 @@ ao_task_to_alarm_queue(struct ao_task *task)
 }
 
 static void
-ao_task_from_alarm_queue(struct ao_task *task)
+_ao_task_from_alarm_queue(struct ao_task *task)
 {
        ao_task_irq_check();
        ao_list_del(&task->alarm_queue);
@@ -173,17 +168,17 @@ ao_task_exit_queue(struct ao_task *task)
 }
 
 void
-ao_task_check_alarm(uint16_t tick)
+ao_task_alarm(AO_TICK_TYPE tick)
 {
        struct ao_task  *alarm, *next;
 
        ao_arch_critical(
                ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) {
-                       if ((int16_t) (tick - alarm->alarm) < 0)
+                       if ((AO_TICK_SIGNED) (tick - alarm->alarm) < 0)
                                break;
                        alarm->alarm = 0;
-                       ao_task_from_alarm_queue(alarm);
-                       ao_task_to_run_queue(alarm);
+                       _ao_task_from_alarm_queue(alarm);
+                       _ao_task_to_run_queue(alarm);
                });
 }
 
@@ -287,7 +282,20 @@ ao_task_validate(void)
 }
 #endif /* DEBUG */
 
-#endif /* HAS_TASK_QUEUE */
+static inline void *
+ao_stack_top(struct ao_task *task)
+{
+       uint8_t *top = &task->stack8[AO_STACK_SIZE];
+
+       /* Subtract off the TLS space, but keep the resulting
+        * stack 8-byte aligned
+        */
+#if USE_TLS
+       return top - ((_tls_size() + 7) & ~3);
+#else
+       return top;
+#endif
+}
 
 void
 ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name) 
@@ -310,12 +318,14 @@ ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name)
         * Construct a stack frame so that it will 'return'
         * to the start of the task
         */
-       ao_arch_init_stack(task, task_func);
-       ao_arch_critical(
-#if HAS_TASK_QUEUE
-               ao_task_init_queue(task);
-               ao_task_to_run_queue(task);
+       uint32_t *sp = ao_stack_top(task);
+#if USE_TLS
+       _init_tls(sp);
 #endif
+       ao_arch_init_stack(task, sp, task_func);
+       ao_task_init_queue(task);
+       ao_arch_critical(
+               _ao_task_to_run_queue(task);
                ao_tasks[ao_num_tasks] = task;
                ao_num_tasks++;
                );
@@ -323,38 +333,25 @@ ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name)
 
 uint8_t        ao_task_minimize_latency;
 
-/* Task switching function. This must not use any stack variables */
+/* Task switching function. */
 void
-ao_yield(void) ao_arch_naked_define
+ao_yield(void)
 {
-       ao_arch_save_regs();
-
-#if HAS_TASK_QUEUE
-       if (ao_cur_task == NULL)
-               ao_cur_task = ao_tasks[ao_num_tasks-1];
-#else
-       if (ao_cur_task_index == AO_NO_TASK_INDEX)
-               ao_cur_task_index = ao_num_tasks-1;
-#endif
-       else
+       if (ao_cur_task)
        {
 #if HAS_SAMPLE_PROFILE
-               uint16_t        tick = ao_sample_profile_timer_value();
-               uint16_t        run = tick - ao_cur_task->start;
+               AO_TICK_TYPE    tick = ao_sample_profile_timer_value();
+               AO_TICK_TYPE    run = tick - ao_cur_task->start;
                if (run > ao_cur_task->max_run)
                        ao_cur_task->max_run = run;
                ++ao_cur_task->yields;
 #endif
+               ao_arch_save_regs();
                ao_arch_save_stack();
        }
 
        ao_arch_isr_stack();
-#if !HAS_TASK_QUEUE
-       if (ao_task_minimize_latency)
-               ao_arch_release_interrupts();
-       else
-#endif
-               ao_arch_block_interrupts();
+       ao_arch_block_interrupts();
 
 #if AO_CHECK_STACK
        in_yield = 1;
@@ -362,12 +359,11 @@ ao_yield(void) ao_arch_naked_define
        /* Find a task to run. If there isn't any runnable task,
         * this loop will run forever, which is just fine
         */
-#if HAS_TASK_QUEUE
        /* If the current task is running, move it to the
         * end of the queue to allow other tasks a chance
         */
-       if (ao_cur_task->wchan == NULL)
-               ao_task_to_run_queue(ao_cur_task);
+       if (ao_cur_task && ao_cur_task->wchan == NULL)
+               _ao_task_to_run_queue(ao_cur_task);
        for (;;) {
                ao_arch_memory_barrier();
                if (!ao_list_is_empty(&run_queue))
@@ -380,31 +376,6 @@ ao_yield(void) ao_arch_naked_define
                        ao_arch_wait_interrupt();
        }
        ao_cur_task = ao_list_first_entry(&run_queue, struct ao_task, queue);
-#else
-       {
-               uint8_t ao_last_task_index = ao_cur_task_index;
-               for (;;) {
-                       ++ao_cur_task_index;
-                       if (ao_cur_task_index == ao_num_tasks)
-                               ao_cur_task_index = 0;
-
-                       ao_cur_task = ao_tasks[ao_cur_task_index];
-
-                       /* Check for ready task */
-                       if (ao_cur_task->wchan == NULL)
-                               break;
-
-                       /* Check if the alarm is set for a time which has passed */
-                       if (ao_cur_task->alarm &&
-                           (int16_t) (ao_time() - ao_cur_task->alarm) >= 0)
-                               break;
-
-                       /* Wait for interrupts when there's nothing ready */
-                       if (ao_cur_task_index == ao_last_task_index && !ao_task_minimize_latency)
-                               ao_arch_wait_interrupt();
-               }
-       }
-#endif
 #if HAS_SAMPLE_PROFILE
        ao_cur_task->start = ao_sample_profile_timer_value();
 #endif
@@ -413,6 +384,9 @@ ao_yield(void) ao_arch_naked_define
 #endif
 #if AO_CHECK_STACK
        in_yield = 0;
+#endif
+#if USE_TLS
+       _set_tls(ao_stack_top(ao_cur_task));
 #endif
        ao_arch_restore_stack();
 }
@@ -420,15 +394,10 @@ ao_yield(void) ao_arch_naked_define
 uint8_t
 ao_sleep(void *wchan)
 {
-#if HAS_TASK_QUEUE
-       uint32_t flags;
-       flags = ao_arch_irqsave();
-#endif
-       ao_cur_task->wchan = wchan;
-#if HAS_TASK_QUEUE
-       ao_task_to_sleep_queue(ao_cur_task, wchan);
-       ao_arch_irqrestore(flags);
-#endif
+       ao_arch_critical(
+               ao_cur_task->wchan = wchan;
+               _ao_task_to_sleep_queue(ao_cur_task, wchan);
+               );
        ao_yield();
        if (ao_cur_task->wchan) {
                ao_cur_task->wchan = NULL;
@@ -442,7 +411,6 @@ void
 ao_wakeup(void *wchan) 
 {
        ao_validate_cur_stack();
-#if HAS_TASK_QUEUE
        struct ao_task  *sleep, *next;
        struct ao_list  *sleep_queue;
        uint32_t        flags;
@@ -454,52 +422,33 @@ ao_wakeup(void *wchan)
        ao_list_for_each_entry_safe(sleep, next, sleep_queue, struct ao_task, queue) {
                if (sleep->wchan == wchan) {
                        sleep->wchan = NULL;
-                       ao_task_to_run_queue(sleep);
+                       _ao_task_to_run_queue(sleep);
                }
        }
        ao_arch_irqrestore(flags);
-#else
-       {
-       uint8_t i;
-       for (i = 0; i < ao_num_tasks; i++)
-               if (ao_tasks[i]->wchan == wchan)
-                       ao_tasks[i]->wchan = NULL;
-       }
-#endif
        ao_check_stack();
 }
 
 uint8_t
-ao_sleep_for(void *wchan, uint16_t timeout)
+ao_sleep_for(void *wchan, AO_TICK_TYPE timeout)
 {
        uint8_t ret;
        if (timeout) {
-#if HAS_TASK_QUEUE
-               uint32_t flags;
-               flags = ao_arch_irqsave();
-#endif
-               /* Make sure we sleep *at least* delay ticks, which means adding
-                * one to account for the fact that we may be close to the next tick
-                */
-               if (!(ao_cur_task->alarm = ao_time() + timeout + 1))
-                       ao_cur_task->alarm = 1;
-#if HAS_TASK_QUEUE
-               ao_task_to_alarm_queue(ao_cur_task);
-               ao_arch_irqrestore(flags);
-#endif
+               ao_arch_critical(
+                       /* Make sure we sleep *at least* delay ticks, which means adding
+                        * one to account for the fact that we may be close to the next tick
+                        */
+                       if (!(ao_cur_task->alarm = ao_time() + timeout + 1))
+                               ao_cur_task->alarm = 1;
+                       _ao_task_to_alarm_queue(ao_cur_task);
+                       );
        }
        ret = ao_sleep(wchan);
        if (timeout) {
-#if HAS_TASK_QUEUE
-               uint32_t flags;
-
-               flags = ao_arch_irqsave();
-#endif
-               ao_cur_task->alarm = 0;
-#if HAS_TASK_QUEUE
-               ao_task_from_alarm_queue(ao_cur_task);
-               ao_arch_irqrestore(flags);
-#endif
+               ao_arch_critical(
+                       ao_cur_task->alarm = 0;
+                       _ao_task_from_alarm_queue(ao_cur_task);
+                       );
        }
        return ret;
 }
@@ -507,7 +456,7 @@ ao_sleep_for(void *wchan, uint16_t timeout)
 static uint8_t ao_forever;
 
 void
-ao_delay(uint16_t ticks)
+ao_delay(AO_TICK_TYPE ticks)
 {
        if (!ticks)
                ticks = 1;
@@ -519,21 +468,17 @@ ao_exit(void)
 {
        uint8_t i;
        ao_arch_block_interrupts();
-       ao_num_tasks--;
-#if HAS_TASK_QUEUE
        for (i = 0; i < ao_num_tasks; i++)
                if (ao_tasks[i] == ao_cur_task)
                        break;
        ao_task_exit_queue(ao_cur_task);
-#else
-       i = ao_cur_task_index;
-       ao_cur_task_index = AO_NO_TASK_INDEX;
-#endif
+       /* Remove task from list */
+       ao_num_tasks--;
        for (; i < ao_num_tasks; i++)
                ao_tasks[i] = ao_tasks[i+1];
        ao_cur_task = NULL;
        ao_yield();
-       /* we'll never get back here */
+       __builtin_unreachable();
 }
 
 #if HAS_TASK_INFO
@@ -542,7 +487,7 @@ ao_task_info(void)
 {
        uint8_t         i;
        struct ao_task *task;
-       uint16_t        now = ao_time();
+       AO_TICK_TYPE    now = ao_time();
 
        for (i = 0; i < ao_num_tasks; i++) {
                task = ao_tasks[i];
@@ -552,7 +497,7 @@ ao_task_info(void)
                       task->alarm ? (int16_t) (task->alarm - now) : 9999,
                       task->name);
        }
-#if HAS_TASK_QUEUE && DEBUG
+#if DEBUG
        ao_task_validate();
 #endif
 }
@@ -561,9 +506,6 @@ ao_task_info(void)
 void
 ao_start_scheduler(void)
 {
-#if !HAS_TASK_QUEUE
-       ao_cur_task_index = AO_NO_TASK_INDEX;
-#endif
        ao_cur_task = NULL;
 #if HAS_ARCH_START_SCHEDULER
        ao_arch_start_scheduler();
index 03b629693c0e44baa9ba61a24caa39edc6d61ff4..beb4da30e5ad7d799b3780017b805e692c34d656 100644 (file)
@@ -18,9 +18,8 @@
 
 #ifndef _AO_TASK_H_
 #define _AO_TASK_H_
-#if HAS_TASK_QUEUE
+
 #include <ao_list.h>
-#endif
 
 #ifndef HAS_TASK_INFO
 #define HAS_TASK_INFO 1
@@ -38,7 +37,7 @@
 /* An AltOS task */
 struct ao_task {
        void *wchan;                    /* current wait channel (NULL if running) */
-       uint16_t alarm;                 /* abort ao_sleep time */
+       AO_TICK_TYPE alarm;             /* abort ao_sleep time */
        uint16_t task_id;               /* unique id */
        /* Saved stack pointer */
        union {
@@ -46,10 +45,8 @@ struct ao_task {
                uint8_t         *sp8;
        };
        const char *name;               /* task name */
-#if HAS_TASK_QUEUE
        struct ao_list  queue;
        struct ao_list  alarm_queue;
-#endif
        /* Provide both 32-bit and 8-bit stacks */
        union {
                uint32_t stack32[AO_STACK_SIZE>>2];
@@ -67,8 +64,6 @@ struct ao_task {
 #define AO_NUM_TASKS           16      /* maximum number of tasks */
 #endif
 
-#define AO_NO_TASK             0       /* no task id */
-
 extern struct ao_task * ao_tasks[AO_NUM_TASKS];
 extern uint8_t ao_num_tasks;
 extern struct ao_task *ao_cur_task;
@@ -96,7 +91,7 @@ ao_sleep(void *wchan);
  *  1 on alarm
  */
 uint8_t
-ao_sleep_for(void *wchan, uint16_t timeout);
+ao_sleep_for(void *wchan, AO_TICK_TYPE timeout);
 
 /* Wake all tasks sleeping on wchan */
 void
@@ -105,7 +100,7 @@ ao_wakeup(void *wchan);
 #if 0
 /* set an alarm to go off in 'delay' ticks */
 void
-ao_alarm(uint16_t delay);
+ao_alarm(AO_TICK_TYPE delay);
 
 /* Clear any pending alarm */
 void
@@ -120,16 +115,24 @@ ao_yield(void) ao_arch_naked_declare;
 void
 ao_add_task(struct ao_task * task, void (*start)(void), const char *name);
 
-#if HAS_TASK_QUEUE
 /* Called on timer interrupt to check alarms */
-extern uint16_t        ao_task_alarm_tick;
+extern AO_TICK_TYPE            ao_task_alarm_tick;
+extern volatile AO_TICK_TYPE   ao_tick_count;
+
 void
-ao_task_check_alarm(uint16_t tick);
+ao_task_alarm(AO_TICK_TYPE tick);
+
+static inline void
+ao_task_check_alarm(void) {
+#if HAS_TASK
+       if ((AO_TICK_SIGNED) (ao_tick_count - ao_task_alarm_tick) >= 0)
+               ao_task_alarm(ao_tick_count);
 #endif
+}
 
 /* Terminate the current task */
 void
-ao_exit(void);
+ao_exit(void) __attribute__ ((noreturn));
 
 /* Dump task info to console */
 void
@@ -139,11 +142,7 @@ ao_task_info(void);
 void
 ao_start_scheduler(void) __attribute__((noreturn));
 
-#if HAS_TASK_QUEUE
 void
 ao_task_init(void);
-#else
-#define ao_task_init()
-#endif
 
 #endif
index c638aa22b9658846a0a4319daec94b377706b6d4..eedac777a46fae6a010a09ba04aaba6098c5b231 100644 (file)
@@ -103,18 +103,28 @@ ao_serial_init(void);
 
 /* SPI definitions */
 
-#define AO_SPI_SPEED_12MHz             4
-#define AO_SPI_SPEED_8MHz              6
-#define AO_SPI_SPEED_6MHz              8
-#define AO_SPI_SPEED_4MHz              12
-#define AO_SPI_SPEED_2MHz              24
-#define AO_SPI_SPEED_1MHz              48
-#define AO_SPI_SPEED_500kHz            96
-#define AO_SPI_SPEED_250kHz            192
-#define AO_SPI_SPEED_125kHz            384
-#define AO_SPI_SPEED_62500Hz           768
-
-#define AO_SPI_SPEED_FAST      AO_SPI_SPEED_12MHz
+#define _AO_SPI_SPEED_12MHz            4
+#define _AO_SPI_SPEED_8MHz             6
+#define _AO_SPI_SPEED_6MHz             8
+#define _AO_SPI_SPEED_4MHz             12
+#define _AO_SPI_SPEED_2MHz             24
+#define _AO_SPI_SPEED_1MHz             48
+#define _AO_SPI_SPEED_500kHz           96
+#define _AO_SPI_SPEED_250kHz           192
+#define _AO_SPI_SPEED_125kHz           384
+#define _AO_SPI_SPEED_62500Hz          768
+
+static inline uint32_t
+ao_spi_speed(uint32_t hz)
+{
+       if (hz >= 4000000) return _AO_SPI_SPEED_4MHz;
+       if (hz >= 2000000) return _AO_SPI_SPEED_2MHz;
+       if (hz >= 1000000) return _AO_SPI_SPEED_1MHz;
+       if (hz >=  500000) return _AO_SPI_SPEED_500kHz;
+       if (hz >=  250000) return _AO_SPI_SPEED_250kHz;
+       if (hz >=  125000) return _AO_SPI_SPEED_125kHz;
+       return _AO_SPI_SPEED_62500Hz;
+}
 
 #define AO_BOOT_APPLICATION_BASE       ((uint32_t *) 0x00001000)
 #define AO_BOOT_APPLICATION_BOUND      ((uint32_t *) (0x00000000 + 32 * 1024))
index 1368f7e5e883ad4b8c94adf626d9d85db7657b67..e0280e76466a2f6e4a1752478b828c743de33e6d 100644 (file)
@@ -107,9 +107,8 @@ ao_arch_memory_barrier(void) {
 
 #if HAS_TASK
 static inline void
-ao_arch_init_stack(struct ao_task *task, void *start)
+ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start)
 {
-       uint32_t        *sp = &task->stack32[AO_STACK_SIZE >> 2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
index eab86ee644ebe44b92e6deee77828dc5809bc661..ab06ef48776be45260add4fe20242114b1ba5f6c 100644 (file)
@@ -59,7 +59,7 @@ ao_beep(uint8_t beep)
 }
 
 void
-ao_beep_for(uint8_t beep, uint16_t ticks) 
+ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks) 
 {
        ao_beep(beep);
        ao_delay(ticks);
index 46bf0495988dfa82446ab7a49cb8b43cd4cdbc15..3747df973f2ec74f1f7f289dc2b82c1028304c01 100644 (file)
@@ -42,12 +42,6 @@ ao_led_set(AO_PORT_TYPE colors)
        ao_led_on(on);
 }
 
-void
-ao_led_toggle(AO_PORT_TYPE colors)
-{
-       lpc_gpio.pin[LED_PORT] ^= colors;
-}
-
 void
 ao_led_for(AO_PORT_TYPE colors, AO_TICK_TYPE ticks) 
 {
index 62b16318107f74fc354783ab8520390ac54d524b..a334ee0d286f8b78fa57ed5a80720545d52e795c 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <ao.h>
+#include <ao_task.h>
 
 #define AO_SYSTICK     (AO_LPC_SYSCLK / 2)
 
@@ -53,10 +54,7 @@ void lpc_systick_isr(void)
 {
        if (lpc_systick.csr & (1 << LPC_SYSTICK_CSR_COUNTFLAG)) {
                ++ao_tick_count;
-#if HAS_TASK_QUEUE
-               if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
-                       ao_task_check_alarm((uint16_t) ao_tick_count);
-#endif
+               ao_task_check_alarm();
 #if AO_DATA_ALL
                if (++ao_data_count == ao_data_interval) {
                        ao_data_count = 0;
index 5949ec0963f63324a5c87f6d97bd3c931ff874e6..a662e49b16e61f1b87ab9e8efd535c3fc4227264 100644 (file)
@@ -3,7 +3,7 @@
 #
 #
 
-include ../stmf0/Makefile.defs
+include ../stm32l0/Makefile.defs
 
 PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
 PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX)
@@ -14,35 +14,6 @@ MICRO_SRC=\
        ao_microflight.c \
        ao_microkalman.c
 
-ALTOS_SRC = \
-       ao_micropeak.c \
-       ao_spi_stm.c \
-       ao_dma_stm.c \
-       ao_led_stmf0.c \
-       ao_timer.c \
-       ao_ms5607.c \
-       ao_exti_stm.c \
-       ao_convert_pa.c \
-       ao_romconfig.c \
-       ao_product.c \
-       ao_panic.c \
-       ao_stdio.c \
-       ao_serial_stm.c \
-       ao_usb_stm.c \
-       ao_mutex.c \
-       ao_interrupt.c \
-       ao_cmd.c \
-       ao_config.c \
-       ao_task.c \
-       ao_data.c \
-       ao_boot_chain.c \
-       ao_microflight.c \
-       ao_report_micro.c \
-       ao_storage_stm.c \
-       ao_storage.c \
-       ao_log_micro.c \
-       ao_microkalman.c
-
 INC=\
        ao.h \
        ao_pins.h \
@@ -52,15 +23,40 @@ INC=\
        ao_ms5607.h \
        ao_log_micro.h \
        ao_micropeak.h \
+       ao_lpuart.h \
        altitude-pa.h \
        ao_product.h \
-       stm32f0.h
+       stm32l0.h
+
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_panic.c \
+       ao_micro.c \
+       ao_report_micro.c \
+       ao_stdio.c \
+       ao_notask.c \
+       ao_serial_stm.c \
+       ao_lpuart_stm.c \
+       ao_timer.c \
+       ao_spi_stm32l0.c \
+       ao_adc_stm32l0.c \
+       ao_ms5607.c \
+       ao_exti_stm.c \
+       ao_convert_pa.c \
+       ao_led.c \
+       ao_cmd.c \
+       ao_product.c \
+       ao_romconfig.c \
+       ao_flash_stm32l0.c \
+       ao_microflight.c \
+       ao_log_micro.c \
+       ao_microkalman.c
 
 IDPRODUCT=0x14
 PRODUCT=MicroPeak-v2.0
 PRODUCT_DEF=-DMICROPEAK
 
-CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS)
+CFLAGS = $(PRODUCT_DEF) $(STML0_CFLAGS) -Wl,--gc-sections -ffunction-sections -fdata-sections
 
 PROGNAME=micropeak-v2.0
 PROG=$(PROGNAME)-$(VERSION).elf
@@ -71,7 +67,7 @@ OBJ=$(SRC:.c=.o)
 
 all: $(PROG) $(HEX)
 
-LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stmf0 -Tmicropeak.ld -n
+LDFLAGS=-nostartfiles $(CFLAGS) -L$(TOPDIR)/stm32l0 -Taltos.ld -n
 
 $(PROG): Makefile $(OBJ) micropeak.ld
        $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS) -Wl,-Map=$(PROGNAME)-$(VERSION).map
diff --git a/src/micropeak-v2.0/ao_micro.c b/src/micropeak-v2.0/ao_micro.c
new file mode 100644 (file)
index 0000000..5a21d65
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright Â© 2020 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_micropeak.h>
+#include <ao_adc_stm32l0.h>
+#include <ao_report_micro.h>
+#include <ao_log_micro.h>
+
+uint32_t       pa;
+alt_t          ground_alt, max_alt;
+alt_t          ao_max_height;
+
+static void
+ao_msi_init(void)
+{
+       uint32_t icscr = stm_rcc.icscr;
+
+       /* Set MSI clock to desired range */
+       icscr &= ~(STM_RCC_ICSCR_MSIRANGE_MASK << STM_RCC_ICSCR_MSIRANGE);
+       icscr |= (AO_MSI_RANGE << STM_RCC_ICSCR_MSIRANGE);
+       stm_rcc.icscr = icscr;
+
+       /* Set vcore to 1.2V */
+       uint32_t cr = stm_pwr.cr;
+       cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS);
+       cr |= (STM_PWR_CR_VOS_1_2 << STM_PWR_CR_VOS);
+       stm_pwr.cr = cr;
+}
+
+void
+ao_pa_get(void)
+{
+       static struct ao_ms5607_value   value;
+
+       ao_ms5607_sample(&ao_ms5607_current);
+       ao_ms5607_convert(&ao_ms5607_current, &value);
+       pa = value.pres;
+}
+
+static void
+ao_compute_height(void)
+{
+       ground_alt = ao_pa_to_altitude(pa_ground);
+       max_alt = ao_pa_to_altitude(pa_min);
+       ao_max_height = max_alt - ground_alt;
+}
+
+static void
+ao_pips(void)
+{
+       uint8_t i;
+       for (i = 0; i < 5; i++) {
+               ao_led_on(AO_LED_REPORT);
+               ao_delay(AO_MS_TO_TICKS(80));
+               ao_led_off(AO_LED_REPORT);
+               ao_delay(AO_MS_TO_TICKS(80));
+       }
+       ao_delay(AO_MS_TO_TICKS(200));
+}
+
+static void
+power_down(void)
+{
+       ao_timer_stop();
+       for(;;) {
+               /*
+                * Table 40, entering standby mode
+                *
+                * SLEEPDEEP = 1 in M0 SCR
+                * PDDS = 1
+                * WUF = 0
+                */
+               stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN);
+               stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+               stm_scb.scr |= ((1 << STM_SCB_SCR_SLEEPDEEP) |
+                               (1 << STM_SCB_SCR_SLEEPONEXIT));
+               stm_pwr.cr |= (1 << STM_PWR_CR_PDDS);
+               stm_pwr.csr &= ~(1 << STM_PWR_CSR_WUF);
+               ao_arch_wait_interrupt();
+       }
+}
+
+static bool log_stdout;
+
+static void
+log_micro_dump(void)
+{
+       int i;
+       if (!log_stdout) {
+               ao_led_off(AO_LED_REPORT);
+               ao_lpuart1_enable();
+       }
+       ao_log_micro_dump();
+       for (i = 0; i < 4; i++)
+               ao_async_byte(stm_device_id.lot_num_0_3[i]);
+       for (i = 0; i < 3; i++)
+               ao_async_byte(stm_device_id.lot_num_4_6[i]);
+       ao_async_byte('-');
+       ao_log_hex(stm_device_id.waf_num);
+       ao_async_byte('-');
+       for (i = 0; i < 4; i++)
+               ao_log_hex(stm_device_id.unique_id[i]);
+       ao_log_newline();
+       if (!log_stdout)
+               ao_lpuart1_disable();
+}
+
+static void
+log_erase(void)
+{
+       uint32_t        pos;
+
+       for (pos = 0; pos < ao_storage_total; pos += STM_FLASH_PAGE_SIZE)
+       {
+               if (!ao_storage_device_is_erased(pos))
+                       ao_storage_device_erase(pos);
+       }
+}
+
+static void
+flight_mode(void)
+{
+       /* Give the person a second to get their finger out of the way */
+       ao_delay(AO_MS_TO_TICKS(1000));
+
+       ao_log_micro_restore();
+       ao_compute_height();
+       ao_report_altitude();
+       ao_pips();
+       log_micro_dump();
+#if BOOST_DELAY        
+       ao_delay(BOOST_DELAY);
+#endif
+       log_erase();
+       ao_microflight();
+       ao_log_micro_save();
+       ao_compute_height();
+       ao_report_altitude();
+       power_down();
+}
+
+void ao_async_byte(char c)
+{
+       if (log_stdout)
+               putchar(c);
+       else
+               ao_lpuart1_putchar(c);
+}
+
+static void
+log_micro_dump_uart(void)
+{
+       log_stdout = true;
+       log_micro_dump();
+       log_stdout = false;
+}
+
+static void
+log_erase_cmd(void)
+{
+       ao_cmd_white();
+       if (!ao_match_word("DoIt"))
+               return;
+       log_erase();
+}
+
+const struct ao_cmds ao_micro_cmds[] = {
+       { log_micro_dump_uart, "l\0Dump log" },
+       { flight_mode, "F\0Flight mode" },
+       { power_down, "S\0Standby" },
+       { log_erase_cmd, "z <key>\0Erase. <key> is doit with D&I" },
+       {}
+};
+
+static void
+cmd_mode(void)
+{
+       ao_serial_init();
+       ao_cmd_init();
+       ao_cmd_register(ao_micro_cmds);
+       ao_cmd();
+}
+
+int
+main(void)
+{
+       ao_msi_init();
+       ao_led_init();
+       ao_timer_init();
+       ao_spi_init();
+       ao_ms5607_init();
+       ao_ms5607_setup();
+
+       /* Check the power supply voltage; it'll be 3.3V if
+        * the I/O board is connected
+        */
+       uint16_t vref = ao_adc_read_vref();
+
+       uint32_t vdda = 3 * stm_vrefint_cal.vrefint_cal * 1000 / vref;
+
+       /* Power supply > 3.25V means we're on USB power */
+       if (vdda > 3250) {
+               cmd_mode();
+       } else {
+               flight_mode();
+       }
+}
index a4de48543a70d2cbf24dbad2f184fd73f2cc4870..c6c1e221880c0fc38e158e15dbcb4b36bb66ed5a 100644 (file)
@@ -56,7 +56,7 @@ ao_pips(void)
 }
 
 void
-ao_delay_until(uint16_t target) {
+ao_delay_until(AO_TICK_TYPE target) {
        int16_t delay = target - ao_time();
        if (delay > 0) {
                ao_sleep_for(ao_delay_until, delay);
@@ -145,10 +145,10 @@ ao_battery_fini(void)
        stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_ADCEN);
 }
 
-static uint16_t
+static AO_TICK_TYPE
 ao_battery_voltage(void)
 {
-       uint16_t        vrefint;
+       AO_TICK_TYPE    vrefint;
 
        ao_battery_init();
 
@@ -212,7 +212,7 @@ ao_show_bat(void)
 uint8_t
 ao_log_present(void)
 {
-       uint16_t        n_samples;
+       AO_TICK_TYPE    n_samples;
 
        ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
 
index d3bd22814a46f0264669237de7c06bf2beb87efb..951083bd19ea2d7aca468088880faae5ef24596c 100644 (file)
 
 extern uint8_t ao_on_battery;
 
-#define AO_SYSCLK      (ao_on_battery ? STM_HSI_FREQ : 48000000)
+#define HAS_TASK       0
 
-#define LED_PORT_ENABLE        STM_RCC_AHBENR_IOPAEN
-#define LED_PORT       (&stm_gpioa)
-#define LED_PIN_ORANGE 2
-#define AO_LED_ORANGE  (1 << LED_PIN_ORANGE)
+#define AO_SYSCLK      STM_MSI_FREQ_524288
+#define AO_MSI_RANGE   STM_RCC_ICSCR_MSIRANGE_524288
+
+#define LED_0_PORT     (&stm_gpioa)
+#define LED_0_PIN      1
+#define AO_LED_ORANGE  (1 << 0)
 #define AO_LED_REPORT  AO_LED_ORANGE
 #define AO_LED_PANIC   AO_LED_ORANGE
 
@@ -33,32 +35,28 @@ extern uint8_t ao_on_battery;
 
 #define AO_POWER_MANAGEMENT    0
 
-/* 48MHz clock based on USB */
-#define AO_HSI48       1
-/* Need HSI running to flash */
-#define AO_NEED_HSI    1
-
-/* HCLK = 12MHz usb / 2MHz battery */
-#define AO_AHB_PRESCALER       (ao_on_battery ? 16 : 1)
-#define AO_RCC_CFGR_HPRE_DIV   (ao_on_battery ? STM_RCC_CFGR_HPRE_DIV_16 : STM_RCC_CFGR_HPRE_DIV_1)
+/* HCLK = MSI (2.097MHz) */
+#define AO_AHB_PRESCALER       (1)
+#define AO_RCC_CFGR_HPRE_DIV   (STM_RCC_CFGR_HPRE_DIV_1)
 
-/* APB = 12MHz usb / 2MHz battery */
-#define AO_APB_PRESCALER       (ao_on_battery ? 2 : 1)
-#define AO_RCC_CFGR_PPRE_DIV   (ao_on_battery ? STM_RCC_CFGR_PPRE_DIV_2 : STM_RCC_CFGR_PPRE_DIV_1)
-
-#define HAS_USB                        1
-#define AO_PA11_PA12_RMP       1
+/* APB = MSI */
+#define AO_APB1_PRESCALER      (1)
+#define AO_APB2_PRESCALER      (1)
+#define AO_RCC_CFGR_PPRE_DIV   (STM_RCC_CFGR_PPRE_DIV_1)
 
 #define PACKET_HAS_SLAVE       0
 #define HAS_SERIAL_1           0
 #define HAS_SERIAL_2           1
-#define USE_SERIAL_2_STDIN     0
+#define USE_SERIAL_2_STDIN     1
 #define USE_SERIAL_2_FLOW      0
 #define USE_SERIAL_2_SW_FLOW   0
-#define SERIAL_2_PA2_PA3       1
-#define SERIAL_2_PA14_PA15     0
-#define USE_SERIAL2_FLOW       0
-#define USE_SERIAL2_SW_FLOW    0
+#define SERIAL_2_PA9_PA10      1
+
+#define HAS_LPUART_1           1
+#define LPUART_1_PA0_PA1       1
+#define USE_LPUART_1_STDIN     0
+#define USE_LPUART_1_FLOW      0
+#define USE_LPUART_1_SW_FLOW   0
 
 #define IS_FLASH_LOADER                0
 
@@ -109,9 +107,8 @@ typedef int32_t alt_t;
 
 #define AO_ALT_VALUE(x)                ((x) * (alt_t) 10)
 
-#define AO_DATA_RING           32
-
 #define HAS_ADC                        0
+#define HAS_AO_DELAY           1
 
 static inline void
 ao_power_off(void) __attribute((noreturn));
@@ -124,24 +121,16 @@ ao_power_off(void) {
 
 extern alt_t ao_max_height;
 
-void ao_delay_until(uint16_t target);
-
-#define ao_async_stop() do {                                   \
-               ao_serial2_drain();                             \
-               stm_moder_set(&stm_gpioa, 2, STM_MODER_OUTPUT); \
-               ao_serial_shutdown();                           \
-       } while (0)
+#define ao_async_stop()
+#define ao_async_start()
 
-#define ao_async_start() do {                                          \
-               ao_serial_init();                                       \
-               stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE);      \
-               ao_delay(AO_MS_TO_TICKS(100));                          \
-       } while (0)
+#define LOG_MICRO_ASYNC 0
 
-#define ao_async_byte(b) ao_serial2_putchar((char) (b))
+void ao_async_byte(char c);
 
-#define ao_eeprom_read(pos, ptr, size) ao_storage_read(pos, ptr, size)
-#define ao_eeprom_write(pos, ptr, size) ao_storage_write(pos, ptr, size)
+#define ao_eeprom_read(pos, ptr, size) ao_storage_device_read(pos, ptr, size)
+#define ao_eeprom_write(pos, ptr, size) ao_storage_device_write(pos, ptr, size)
+#define N_SAMPLES_TYPE uint32_t
 #define MAX_LOG_OFFSET ao_storage_total
 #define ao_storage_log_max ao_storage_total
 
@@ -151,4 +140,6 @@ extern uint32_t __flash_end__[];
 #define AO_BOOT_APPLICATION_BOUND      ((uint32_t *) __flash__)
 #define USE_STORAGE_CONFIG     0
 
+#define HAS_STORAGE_DEBUG 1
+
 #endif /* _AO_PINS_H_ */
index b4e06a877708bd7cbdbe446b4262a5b1d5265856..93536c48967bb37aea03c89201c791f08c59e62f 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-__flash = 0x08001000;
-__flash_size = 22K;
+__flash = 0x08000000;
+__flash_size = 10K;
 __flash__ = __flash + __flash_size;
 __flash_end__ = __flash__ + 6K;
 __ram = 0x20000000;
-__ram_size = 6K;
+__ram_size = 2K;
 __stack_size = 512;
 
-INCLUDE registers.ld
 INCLUDE picolibc.ld
index c09eedcf4c0eddcb0c083572c01d4e3208669018..63ab485956b01671c5823c242e76106da52a23c9 100644 (file)
@@ -49,11 +49,8 @@ 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) > $@
+$(PROG): Makefile $(OBJ)
+       $(call quiet,CC) $(LDFLAGS) -o $(PROG) $(OBJ) $(LIBS)
 
 $(OBJ): $(INC)
 
index 3e79aad3d2ffd7f4fd778c151ccd81016bb16ba2..54ff374c5ed5d30b0b03f06c1f8692de8c58e54e 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 #define IS_FLASH_LOADER        0
 
index 019b542529807103d8a16b09c82a1bd227630504..cf6299ca18afee1876e524e5b2bbd43114481766 100644 (file)
@@ -21,8 +21,6 @@
 
 /* Common definitions for the USB flash loader */
 
-#define HAS_TASK_QUEUE         0
-
 #define HAS_USB                        1
 #define USE_USB_STDIO          0
 #define HAS_USB_DISABLE                0
index a680ca181e7afd2771bc35f3d71ddab91fe3cbe8..bbd5675a1528ff7708bd38b8abc7d5380c47fbe6 100644 (file)
@@ -26,6 +26,7 @@ void
 ao_panic(uint8_t reason)
 {
        (void) reason;
+       for (;;);
 }
 
 void
index 853b6841fca83f612d2e805f56e2affb4d31dcbb..268cf2f206dc07714238634e27cb4cd96f85fc7e 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         0
 
 /* Bridge SB17 on the board and use the MCO from the other chip */
 #define AO_HSE         8000000
index 8503c4fd2eebade428b724ecd10260fd3bfce0bf..93264031dd7a427f03ee6addbae83b4dae2efd27 100644 (file)
@@ -71,7 +71,6 @@
 #define HAS_USB                        1
 #define HAS_BEEP               0
 #define PACKET_HAS_SLAVE       0
-#define HAS_TASK_QUEUE         1
 
 #define CONSOLE_STDIN          1
 
index ad46ef32babf9fd52b0f9d58f08fd09e6f534275..083f7a2beb7ad394e57c200d9b1f13dd2ff5f020 100644 (file)
 
 /* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
 
-#define AO_SPI_SPEED_8MHz      STM_SPI_CR1_BR_PCLK_2
-#define AO_SPI_SPEED_4MHz      STM_SPI_CR1_BR_PCLK_4
-#define AO_SPI_SPEED_2MHz      STM_SPI_CR1_BR_PCLK_8
-#define AO_SPI_SPEED_1MHz      STM_SPI_CR1_BR_PCLK_16
-#define AO_SPI_SPEED_500kHz    STM_SPI_CR1_BR_PCLK_32
-#define AO_SPI_SPEED_250kHz    STM_SPI_CR1_BR_PCLK_64
-#define AO_SPI_SPEED_125kHz    STM_SPI_CR1_BR_PCLK_128
-#define AO_SPI_SPEED_62500Hz   STM_SPI_CR1_BR_PCLK_256
+//#define AO_SPI_SPEED_8MHz    STM_SPI_CR1_BR_PCLK_2   /* too fast to use safely */
+#define _AO_SPI_SPEED_4MHz     STM_SPI_CR1_BR_PCLK_4
+#define _AO_SPI_SPEED_2MHz     STM_SPI_CR1_BR_PCLK_8
+#define _AO_SPI_SPEED_1MHz     STM_SPI_CR1_BR_PCLK_16
+#define _AO_SPI_SPEED_500kHz   STM_SPI_CR1_BR_PCLK_32
+#define _AO_SPI_SPEED_250kHz   STM_SPI_CR1_BR_PCLK_64
+#define _AO_SPI_SPEED_125kHz   STM_SPI_CR1_BR_PCLK_128
+#define _AO_SPI_SPEED_62500Hz  STM_SPI_CR1_BR_PCLK_256
 
-#define AO_SPI_SPEED_FAST      AO_SPI_SPEED_8MHz
-
-/* Companion bus wants something no faster than 200kHz */
-
-#define AO_SPI_SPEED_200kHz    AO_SPI_SPEED_125kHz
+static inline uint32_t
+ao_spi_speed(uint32_t hz)
+{
+       if (hz >= 4000000) return _AO_SPI_SPEED_4MHz;
+       if (hz >= 2000000) return _AO_SPI_SPEED_2MHz;
+       if (hz >= 1000000) return _AO_SPI_SPEED_1MHz;
+       if (hz >=  500000) return _AO_SPI_SPEED_500kHz;
+       if (hz >=  250000) return _AO_SPI_SPEED_250kHz;
+       if (hz >=  125000) return _AO_SPI_SPEED_125kHz;
+       return _AO_SPI_SPEED_62500Hz;
+}
 
 #define AO_SPI_CPOL_BIT                4
 #define AO_SPI_CPHA_BIT                5
@@ -151,8 +157,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
 void
 ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
 
-extern uint16_t        ao_spi_speed[STM_NUM_SPI];
-
 void
 ao_spi_init(void);
 
@@ -473,9 +477,8 @@ ao_arch_irq_check(void) {
 
 #if HAS_TASK
 static inline void
-ao_arch_init_stack(struct ao_task *task, void *start)
+ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start)
 {
-       uint32_t        *sp = &task->stack32[AO_STACK_SIZE>>2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
@@ -559,8 +562,8 @@ ao_validate_cur_stack(void)
 
        asm("mrs %0,psp" : "=&r" (psp));
        if (ao_cur_task &&
-           psp <= ao_cur_task->stack &&
-           psp >= ao_cur_task->stack - 256)
+           (psp <= ao_cur_task->stack8 ||
+            psp >= ao_cur_task->stack8 + AO_STACK_SIZE))
                ao_panic(AO_PANIC_STACK);
 }
 #endif
index 2bcd684909af1fccfe843fd9655dee4e586d53e0..12d2b0b6439eed06dacc5085d2c81a9f205be883 100644 (file)
@@ -148,7 +148,7 @@ ao_beep(uint8_t beep)
 }
 
 void
-ao_beep_for(uint8_t beep, uint16_t ticks)
+ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks)
 {
        ao_beep(beep);
        ao_delay(ticks);
index ed4ec1610de3dde8e645725d851231a4b1051671..7f40eaca301ceaafbcf0ddf410464cb82337ac7c 100644 (file)
@@ -68,24 +68,6 @@ ao_led_set(AO_LED_TYPE colors)
        ao_led_on(on);
 }
 
-void
-ao_led_toggle(AO_LED_TYPE colors)
-{
-#ifdef LED_PORT
-       LED_PORT->odr ^= (colors & LEDS_AVAILABLE);
-#else
-#ifdef LED_PORT_0
-       LED_PORT_0->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
-#endif
-#ifdef LED_PORT_1
-       LED_PORT_1->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
-#endif
-#ifdef LED_PORT_2
-       LED_PORT_2->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_2_MASK) << LED_PORT_2_SHIFT;
-#endif
-#endif
-}
-
 void
 ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) 
 {
index 1a04a2899a825afa758726d5625d3c11a7536c34..0215f03ebd6a56bf173c16e16e8c0a53cd008955 100644 (file)
@@ -116,7 +116,7 @@ ao_spi_set_dma_miso(uint8_t id, void *data, uint16_t len, uint32_t minc)
                            data,
                            len,
                            (0 << STM_DMA_CCR_MEM2MEM) |
-                           (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_PL_VERY_HIGH << STM_DMA_CCR_PL) |
                            (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
                            (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
                            (minc << STM_DMA_CCR_MINC) |
index d00deffab2161b80e0333f6524567deefdb87052..0d81b5de47e6170fccfe160f34a90f4f9c1fa97b 100644 (file)
@@ -67,10 +67,7 @@ void stm_systick_isr(void)
 #if HAS_TICK
                ++ao_tick_count;
 #endif
-#if HAS_TASK_QUEUE
-               if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
-                       ao_task_check_alarm((uint16_t) ao_tick_count);
-#endif
+               ao_task_check_alarm();
 #if AO_DATA_ALL
                if (++ao_data_count == ao_data_interval) {
                        ao_data_count = 0;
index 7dd4c80d79266b00856f43677a5fe1cfc04f476f..6d75f1885f3a36e4a33c2a2cb9844008e983bc89 100644 (file)
 #define AO_STACK_SIZE  2048
 #endif
 
-#ifndef HAS_TASK_QUEUE
-#define HAS_TASK_QUEUE 1
-#endif
-
 #define AO_STACK_ALIGNMENT __attribute__ ((aligned(8)))
 
 #define AO_PORT_TYPE   uint16_t
index 6fa654973842877a59325e94cd3a991e6d1750d0..74f4021b070854cf9dd0e0f10f55e03ba6b96823 100644 (file)
@@ -82,9 +82,8 @@ ao_arch_irq_check(void) {
 
 #if HAS_TASK
 static inline void
-ao_arch_init_stack(struct ao_task *task, void *start)
+ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start)
 {
-       uint32_t        *sp = &task->stack32[AO_STACK_SIZE>>2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
index 24f56abc5e730f90d0288fe1704e30f96cd3ef4d..20577b14e4c3b8262b83795de1cf6985ee308c0e 100644 (file)
@@ -45,8 +45,11 @@ void start(void)
 #ifdef AO_BOOT_CHAIN
        if (ao_boot_check_chain()) {
 #ifdef AO_BOOT_PIN
-               ao_boot_check_pin();
+               if (ao_boot_check_pin())
 #endif
+               {
+                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+               }
        }
 #endif
        /* Enable FPU */
index fb83db003aa46085f37a3b294e2da02402dc49b3..999b587f3e7933862bbad0f72e783e15f3c11dee 100644 (file)
@@ -47,10 +47,7 @@ void stm_systick_isr(void)
 #if HAS_TICK
                ++ao_tick_count;
 #endif
-#if HAS_TASK_QUEUE
-               if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
-                       ao_task_check_alarm((uint16_t) ao_tick_count);
-#endif
+               ao_task_check_alarm();
 #if AO_DATA_ALL
                if (++ao_data_count == ao_data_interval) {
                        ao_data_count = 0;
diff --git a/src/stm32l0/Makefile-flash.defs b/src/stm32l0/Makefile-flash.defs
new file mode 100644 (file)
index 0000000..08a4b17
--- /dev/null
@@ -0,0 +1,58 @@
+include $(TOPDIR)/stm/Makefile-stm.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_flash_pins.h \
+       ao_flash_stm_pins.h \
+       ao_flash_task.h \
+       ao_pins.h \
+       ao_product.h \
+       Makefile
+
+#
+# Common AltOS sources
+#
+SRC = \
+       ao_interrupt.c \
+       ao_romconfig.c \
+       ao_boot_chain.c \
+       ao_boot_pin.c \
+       ao_product.c \
+       ao_notask.c \
+       ao_timer.c \
+       ao_usb_stm.c \
+       ao_flash_stm.c \
+       ao_flash_task.c \
+       ao_flash_loader_stm.c
+
+OBJ=$(SRC:.c=.o)
+
+PRODUCT=AltosFlash
+PRODUCT_DEF=-DALTOS_FLASH
+IDPRODUCT=0x000a
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS)
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos-loader.ld -n
+
+PROGNAME=altos-flash
+PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+
+$(PROG): Makefile $(OBJ) altos-loader.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+all: $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/stm32l0/Makefile-stm32l0.defs b/src/stm32l0/Makefile-stm32l0.defs
new file mode 100644 (file)
index 0000000..1eab283
--- /dev/null
@@ -0,0 +1,16 @@
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+# Disable floating-point support in printf to save space
+
+PICOLIBC_PRINTF_CFLAGS = -DPICOLIBC_INTEGER_PRINTF_SCANF
+
+include $(TOPDIR)/Makefile.defs
+
+vpath % $(TOPDIR)/stm32l0:$(AO_VPATH)
+
+CC=$(ARM_CC)
+
+STML0_CFLAGS=-mlittle-endian -mcpu=cortex-m0 -mthumb \
+       -I$(TOPDIR)/stm32l0 $(AO_CFLAGS) $(PICOLIBC_CFLAGS)
diff --git a/src/stm32l0/Makefile.defs b/src/stm32l0/Makefile.defs
new file mode 100644 (file)
index 0000000..911d8dc
--- /dev/null
@@ -0,0 +1,7 @@
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/stm32l0/Makefile-stm32l0.defs
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stm32l0 -Taltos.ld
diff --git a/src/stm32l0/altos.ld b/src/stm32l0/altos.ld
new file mode 100644 (file)
index 0000000..5c9688e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+__flash   = 0x08000000;
+__flash_size = 12k;
+__storage = __flash + __flash_size;
+__storage_size = 16k - __flash_size;
+__ram     = 0x20000000;
+__ram_size = 2k;
+__stack_size = 512;
+
+PROVIDE(__storage = __storage);
+PROVIDE(__storage_size = __storage_size);
+
+INCLUDE picolibc.ld
+INCLUDE stm32l0.ld
diff --git a/src/stm32l0/ao_adc_stm32l0.c b/src/stm32l0/ao_adc_stm32l0.c
new file mode 100644 (file)
index 0000000..a7af0a0
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright Â© 2020 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_adc_stm32l0.h>
+
+void
+ao_adc_init(void)
+{
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN);
+
+       /* Configure */
+       stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) |                             /* analog watchdog channel 0 */
+                        (0 << STM_ADC_CFGR1_AWDEN) |                             /* Disable analog watchdog */
+                        (0 << STM_ADC_CFGR1_AWDSGL) |                            /* analog watchdog on all channels */
+                        (0 << STM_ADC_CFGR1_DISCEN) |                            /* Not discontinuous mode. All channels converted with one trigger */
+                        (0 << STM_ADC_CFGR1_AUTOOFF) |                           /* Leave ADC running */
+                        (1 << STM_ADC_CFGR1_WAIT) |                              /* Wait for data to be read before next conversion */
+                        (0 << STM_ADC_CFGR1_CONT) |                              /* only one set of conversions per trigger */
+                        (1 << STM_ADC_CFGR1_OVRMOD) |                            /* overwrite on overrun */
+                        (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) |   /* SW trigger */
+                        (0 << STM_ADC_CFGR1_ALIGN) |                             /* Align to LSB */
+                        (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) |            /* 12 bit resolution */
+                        (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) |    /* scan 0 .. n */
+                        (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | /* one set of conversions then stop */
+                        (0 << STM_ADC_CFGR1_DMAEN));                             /* disable DMA */
+
+       /* Set the clock */
+       stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE;
+
+       /* Shortest sample time */
+       stm_adc.smpr = STM_ADC_SMPR_SMP_71_5 << STM_ADC_SMPR_SMP;
+
+#define AO_ADC_LFMEN   (AO_SYSCLK < 3500000)
+
+       stm_adc.ccr = ((AO_ADC_LFMEN << STM_ADC_CCR_LFMEN) |
+                      (0 << STM_ADC_CCR_VLCDEN) |
+                      (0 << STM_ADC_CCR_TSEN) |
+                      (0 << STM_ADC_CCR_VREFEN));
+
+       /* Calibrate. This also enables the ADC vreg */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
+       while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0)
+               ;
+
+       /* Enable */
+       stm_adc.isr = (1 << STM_ADC_ISR_ADRDY); /* Clear ADRDY bit */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
+       while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0)
+               ;
+}
+
+static void
+ao_adc_shutdown(void)
+{
+       /* Disable ADC */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADDIS);
+       while ((stm_adc.cr & (1 << STM_ADC_CR_ADEN)) != 0)
+               ;
+
+       /* Clear ADRDY bit */
+       stm_adc.isr = (1 << STM_ADC_ISR_ADRDY);
+
+       /* Disable ADC vreg */
+       stm_adc.cr &= ~(1 << STM_ADC_CR_ADVREGEN);
+
+       /* Disable ADC clocks */
+       stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_ADCEN);
+}
+
+uint16_t
+ao_adc_read_vref(void)
+{
+       uint16_t value;
+
+       ao_adc_init();
+
+       /* Turn on voltage reference */
+       stm_adc.ccr |= (1 << STM_ADC_CCR_VREFEN);
+
+       /* Select VREF */
+       stm_adc.chselr = (1 << STM_ADC_CHSEL_VREF);
+
+       /* Start conversion */
+       stm_adc.cr |= (1 << STM_ADC_CR_ADSTART);
+
+       /* Wait for conversion complete */
+       while ((stm_adc.isr & (1 << STM_ADC_ISR_EOC)) == 0)
+               ;
+
+       /* Fetch result */
+       value = stm_adc.dr;
+
+       ao_adc_shutdown();
+       return value;
+}
diff --git a/src/stm32l0/ao_adc_stm32l0.h b/src/stm32l0/ao_adc_stm32l0.h
new file mode 100644 (file)
index 0000000..8dd4c47
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright Â© 2020 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.
+ */
+
+#pragma once
+
+uint16_t
+ao_adc_read_vref(void);
diff --git a/src/stm32l0/ao_arch.h b/src/stm32l0/ao_arch.h
new file mode 100644 (file)
index 0000000..542d2ee
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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_ARCH_H_
+#define _AO_ARCH_H_
+
+#include <stdio.h>
+#include <stm32l0.h>
+
+/*
+ * STM32L0 definitions and code fragments for AltOS
+ */
+
+#ifndef AO_STACK_SIZE
+#define AO_STACK_SIZE  256
+#endif
+
+#define HAS_USB                0
+
+#define AO_PORT_TYPE   uint16_t
+
+/* Various definitions to make GCC look more like SDCC */
+
+#define ao_arch_naked_declare  __attribute__((naked))
+#define ao_arch_naked_define
+#define __interrupt(n)
+#define __at(n)
+
+#define ao_arch_reboot() \
+       (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \
+                         (1 << STM_SCB_AIRCR_SYSRESETREQ)))
+
+#define ao_arch_nop()          asm("nop")
+
+#define ao_arch_interrupt(n)   /* nothing */
+
+/*
+ * ao_romconfig.c
+ */
+
+#define AO_ROMCONFIG_SYMBOL __attribute__((section(".romconfig"))) const
+
+#ifndef AO_SYSCLK
+#if AO_HSE
+#define AO_PLLSRC      AO_HSE
+#else
+#define AO_PLLSRC      STM_HSI_FREQ
+#endif
+
+#define AO_PLLVCO      (AO_PLLSRC * AO_PLLMUL)
+#define AO_SYSCLK      (AO_PLLVCO / AO_PLLDIV)
+#endif
+
+#define AO_HCLK                (AO_SYSCLK / AO_AHB_PRESCALER)
+#define AO_FCLK                AO_HCLK
+#define AO_PCLK1       (AO_HCLK / AO_APB1_PRESCALER)
+#define AO_PCLK2       (AO_HCLK / AO_APB2_PRESCALER)
+#define AO_SYSTICK     (AO_HCLK / 8)
+
+#if AO_APB1_PRESCALER == 1
+#define AO_TIM23467_CLK                AO_PCLK1
+#else
+#define AO_TIM23467_CLK                (2 * AO_PCLK1)
+#endif
+
+#if AO_APB2_PRESCALER == 1
+#define AO_TIM91011_CLK                AO_PCLK2
+#else
+#define AO_TIM91011_CLK                (2 * AO_PCLK2)
+#endif
+
+/* The stm32l implements only 4 bits of the priority fields */
+
+#if AO_NONMASK_INTERRUPT
+#define AO_STM_NVIC_NONMASK_PRIORITY   0x00
+
+/* Set the basepri register to this value to mask all
+ * non-maskable priorities
+ */
+#define AO_STM_NVIC_BASEPRI_MASK       0x10
+#endif
+
+#define AO_STM_NVIC_HIGH_PRIORITY      0x40
+#define AO_STM_NVIC_MED_PRIORITY       0x80
+#define AO_STM_NVIC_LOW_PRIORITY       0xC0
+#define AO_STM_NVIC_CLOCK_PRIORITY     0xf0
+
+void ao_lcd_stm_init(void);
+
+void ao_lcd_font_init(void);
+
+void ao_lcd_font_string(char *s);
+
+extern const uint32_t  ao_radio_cal;
+
+void
+ao_adc_init(void);
+
+/* ADC maximum reported value */
+#define AO_ADC_MAX                     4095
+
+#define HAS_BOOT_LOADER                        0
+
+#ifndef AO_LED_TYPE
+#define AO_LED_TYPE uint16_t
+#endif
+
+void
+ao_timer_stop(void);
+
+#endif /* _AO_ARCH_H_ */
+
+
diff --git a/src/stm32l0/ao_arch_funcs.h b/src/stm32l0/ao_arch_funcs.h
new file mode 100644 (file)
index 0000000..297bd66
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * 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_ARCH_FUNCS_H_
+#define _AO_ARCH_FUNCS_H_
+
+/* ao_spi_stm.c
+ */
+
+/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+
+#define _AO_SPI_SPEED_8MHz     STM_SPI_CR1_BR_PCLK_2
+#define _AO_SPI_SPEED_4MHz     STM_SPI_CR1_BR_PCLK_4
+#define _AO_SPI_SPEED_2MHz     STM_SPI_CR1_BR_PCLK_8
+#define _AO_SPI_SPEED_1MHz     STM_SPI_CR1_BR_PCLK_16
+#define _AO_SPI_SPEED_500kHz   STM_SPI_CR1_BR_PCLK_32
+#define _AO_SPI_SPEED_250kHz   STM_SPI_CR1_BR_PCLK_64
+#define _AO_SPI_SPEED_125kHz   STM_SPI_CR1_BR_PCLK_128
+#define _AO_SPI_SPEED_62500Hz  STM_SPI_CR1_BR_PCLK_256
+
+/* Companion bus wants something no faster than 200kHz */
+
+static inline uint32_t
+ao_spi_speed(uint32_t hz)
+{
+       if (hz >= 4000000) return _AO_SPI_SPEED_4MHz;
+       if (hz >= 2000000) return _AO_SPI_SPEED_2MHz;
+       if (hz >= 1000000) return _AO_SPI_SPEED_1MHz;
+       if (hz >=  500000) return _AO_SPI_SPEED_500kHz;
+       if (hz >=  250000) return _AO_SPI_SPEED_250kHz;
+       if (hz >=  125000) return _AO_SPI_SPEED_125kHz;
+       return _AO_SPI_SPEED_62500Hz;
+}
+
+#define AO_SPI_CPOL_BIT                4
+#define AO_SPI_CPHA_BIT                5
+
+#define AO_SPI_CONFIG_1                0x00
+#define AO_SPI_1_CONFIG_PA5_PA6_PA7    AO_SPI_CONFIG_1
+
+#define AO_SPI_CONFIG_2                0x04
+#define AO_SPI_1_CONFIG_PA12_PA13_PA14 AO_SPI_CONFIG_2
+#define AO_SPI_2_CONFIG_PD1_PD3_PD4    AO_SPI_CONFIG_2
+
+#define AO_SPI_CONFIG_3                0x08
+#define AO_SPI_1_CONFIG_PB3_PB4_PB5    AO_SPI_CONFIG_3
+
+#define AO_SPI_CONFIG_NONE     0x0c
+
+#define AO_SPI_INDEX_MASK      0x01
+#define AO_SPI_CONFIG_MASK     0x0c
+
+#define AO_SPI_1_PA5_PA6_PA7   (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7)
+#define AO_SPI_1_PA12_PA13_PA14        (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA12_PA13_PA14)
+#define AO_SPI_1_PB3_PB4_PB5   (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5)
+
+#define AO_SPI_2_PB13_PB14_PB15        (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15)
+#define AO_SPI_2_PD1_PD3_PD4   (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4)
+
+#define AO_SPI_INDEX(id)       ((id) & AO_SPI_INDEX_MASK)
+#define AO_SPI_CONFIG(id)      ((id) & AO_SPI_CONFIG_MASK)
+#define AO_SPI_PIN_CONFIG(id)  ((id) & (AO_SPI_INDEX_MASK | AO_SPI_CONFIG_MASK))
+#define AO_SPI_CPOL(id)                ((uint32_t) (((id) >> AO_SPI_CPOL_BIT) & 1))
+#define AO_SPI_CPHA(id)                ((uint32_t) (((id) >> AO_SPI_CPHA_BIT) & 1))
+
+#define AO_SPI_MAKE_MODE(pol,pha)      (((pol) << AO_SPI_CPOL_BIT) | ((pha) << AO_SPI_CPHA_BIT))
+#define AO_SPI_MODE_0          AO_SPI_MAKE_MODE(0,0)
+#define AO_SPI_MODE_1          AO_SPI_MAKE_MODE(0,1)
+#define AO_SPI_MODE_2          AO_SPI_MAKE_MODE(1,0)
+#define AO_SPI_MODE_3          AO_SPI_MAKE_MODE(1,1)
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id);
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed);
+
+void
+ao_spi_put(uint8_t spi_index);
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_start_bytes(uint8_t spi_index);
+
+void
+ao_spi_stop_bytes(uint8_t spi_index);
+
+static inline void
+ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+       struct stm_spi  *stm_spi = &stm_spi1;
+       (void) spi_index;
+
+       while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)))
+               ;
+       stm_spi->dr = byte;
+       while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE)))
+               ;
+       (void) stm_spi->dr;
+}
+
+static inline uint8_t
+ao_spi_recv_byte(uint8_t spi_index)
+{
+       struct stm_spi  *stm_spi = &stm_spi1;
+       (void) spi_index;
+
+       while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)))
+               ;
+       stm_spi->dr = 0xff;
+       while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE)))
+               ;
+       return stm_spi->dr;
+}
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_init(void);
+
+#define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16)
+#define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask))
+
+#define ao_spi_get_mask(reg,mask,bus, speed) do {              \
+               ao_spi_get(bus, speed);                         \
+               ao_spi_set_cs(reg,mask);                        \
+       } while (0)
+
+static inline uint8_t
+ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id)
+{
+       if (!ao_spi_try_get(bus, speed, task_id))
+               return 0;
+       ao_spi_set_cs(reg, mask);
+       return 1;
+}
+
+#define ao_spi_put_mask(reg,mask,bus) do {     \
+               ao_spi_clr_cs(reg,mask);        \
+               ao_spi_put(bus);                \
+       } while (0)
+
+#define ao_spi_get_bit(reg,bit,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
+#define ao_spi_put_bit(reg,bit,bus) ao_spi_put_mask(reg,(1<<bit),bus)
+
+#define ao_enable_port(port) do {                                      \
+               if ((port) == &stm_gpioa)                               \
+                       stm_rcc.iopenr |= (1 << STM_RCC_IOPENR_IOPAEN); \
+               else if ((port) == &stm_gpiob)                          \
+                       stm_rcc.iopenr |= (1 << STM_RCC_IOPENR_IOPBEN); \
+               else if ((port) == &stm_gpioc)                          \
+                       stm_rcc.iopenr |= (1 << STM_RCC_IOPENR_IOPCEN); \
+               else if ((port) == &stm_gpiod)                          \
+                       stm_rcc.iopenr |= (1 << STM_RCC_IOPENR_IOPDEN); \
+               else if ((port) == &stm_gpioe)                          \
+                       stm_rcc.iopenr |= (1 << STM_RCC_IOPENR_IOPEEN); \
+               else if ((port) == &stm_gpioh)                          \
+                       stm_rcc.iopenr |= (1 << STM_RCC_IOPENR_IOPHEN); \
+       } while (0)
+
+#define ao_disable_port(port) do {                                     \
+               if ((port) == &stm_gpioa)                               \
+                       stm_rcc.iopenr &= ~(1 << STM_RCC_IOPENR_IOPAEN); \
+               else if ((port) == &stm_gpiob)                          \
+                       stm_rcc.iopenr &= ~(1 << STM_RCC_IOPENR_IOPBEN); \
+               else if ((port) == &stm_gpioc)                          \
+                       stm_rcc.iopenr &= ~(1 << STM_RCC_IOPENR_IOPCEN); \
+               else if ((port) == &stm_gpiod)                          \
+                       stm_rcc.iopenr &= ~(1 << STM_RCC_IOPENR_IOPDEN); \
+               else if ((port) == &stm_gpioe)                          \
+                       stm_rcc.iopenr &= ~(1 << STM_RCC_IOPENR_IOPEEN); \
+               else if ((port) == &stm_gpioh)                          \
+                       stm_rcc.iopenr &= ~(1 << STM_RCC_IOPENR_IOPHEN); \
+       } while (0)
+
+
+#define ao_gpio_set(port, bit, v) stm_gpio_set(port, bit, v)
+
+#define ao_gpio_get(port, bit) stm_gpio_get(port, bit)
+
+#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits)
+
+#define ao_gpio_set_mask(port, bits, mask) stm_gpio_set_mask(port, bits, mask)
+
+#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits);
+
+#define ao_gpio_get_all(port) stm_gpio_get_all(port)
+
+#define ao_enable_output(port,bit,v) do {                      \
+               ao_enable_port(port);                           \
+               ao_gpio_set(port, bit, v);                      \
+               stm_moder_set(port, bit, STM_MODER_OUTPUT);\
+       } while (0)
+
+#define ao_enable_output_mask(port,bits,mask) do {             \
+               ao_enable_port(port);                           \
+               ao_gpio_set_mask(port, bits, mask);             \
+               ao_set_output_mask(port, mask);                 \
+       } while (0)
+
+#define AO_OUTPUT_PUSH_PULL    STM_OTYPER_PUSH_PULL
+#define AO_OUTPUT_OPEN_DRAIN   STM_OTYPER_OPEN_DRAIN
+
+#define ao_gpio_set_output_mode(port,bit,mode) \
+       stm_otyper_set(port, pin, mode)
+
+#define ao_gpio_set_mode(port,bit,mode) do {                           \
+               if (mode == AO_EXTI_MODE_PULL_UP)                       \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP);    \
+               else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN);  \
+               else                                                    \
+                       stm_pupdr_set(port, bit, STM_PUPDR_NONE);       \
+       } while (0)
+
+#define ao_gpio_set_mode_mask(port,mask,mode) do {                     \
+               if (mode == AO_EXTI_MODE_PULL_UP)                       \
+                       stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_UP); \
+               else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
+                       stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_DOWN); \
+               else                                                    \
+                       stm_pupdr_set_mask(port, mask, STM_PUPDR_NONE); \
+       } while (0)
+
+#define ao_set_input(port, bit) do {                           \
+               stm_moder_set(port, bit, STM_MODER_INPUT);      \
+       } while (0)
+
+#define ao_set_output(port, bit, v) do {                       \
+               ao_gpio_set(port, bit, v);                      \
+               stm_moder_set(port, bit, STM_MODER_OUTPUT);     \
+       } while (0)
+
+#define ao_set_output_mask(port, mask) do {                    \
+               stm_moder_set_mask(port, mask, STM_MODER_OUTPUT);       \
+       } while (0)
+
+#define ao_set_input_mask(port, mask) do {                             \
+               stm_moder_set_mask(port, mask, STM_MODER_INPUT);        \
+       } while (0)
+
+#define ao_enable_input(port,bit,mode) do {                            \
+               ao_enable_port(port);                                   \
+               ao_set_input(port, bit);                                \
+               ao_gpio_set_mode(port, bit, mode);                      \
+       } while (0)
+
+#define ao_enable_input_mask(port,mask,mode) do {      \
+               ao_enable_port(port);                   \
+               ao_gpio_set_mode_mask(port, mask, mode);        \
+               ao_set_input_mask(port, mask);          \
+       } while (0)
+
+#define _ao_enable_cs(port, bit) do {                          \
+               stm_gpio_set((port), bit, 1);                   \
+               stm_moder_set((port), bit, STM_MODER_OUTPUT);   \
+       } while (0)
+
+#define ao_enable_cs(port,bit) do {                            \
+               ao_enable_port(port);                           \
+               _ao_enable_cs(port, bit);                       \
+       } while (0)
+
+#define ao_spi_init_cs(port, mask) do {                                \
+               ao_enable_port(port);                           \
+               if ((mask) & 0x0001) _ao_enable_cs(port, 0);    \
+               if ((mask) & 0x0002) _ao_enable_cs(port, 1);    \
+               if ((mask) & 0x0004) _ao_enable_cs(port, 2);    \
+               if ((mask) & 0x0008) _ao_enable_cs(port, 3);    \
+               if ((mask) & 0x0010) _ao_enable_cs(port, 4);    \
+               if ((mask) & 0x0020) _ao_enable_cs(port, 5);    \
+               if ((mask) & 0x0040) _ao_enable_cs(port, 6);    \
+               if ((mask) & 0x0080) _ao_enable_cs(port, 7);    \
+               if ((mask) & 0x0100) _ao_enable_cs(port, 8);    \
+               if ((mask) & 0x0200) _ao_enable_cs(port, 9);    \
+               if ((mask) & 0x0400) _ao_enable_cs(port, 10);\
+               if ((mask) & 0x0800) _ao_enable_cs(port, 11);\
+               if ((mask) & 0x1000) _ao_enable_cs(port, 12);\
+               if ((mask) & 0x2000) _ao_enable_cs(port, 13);\
+               if ((mask) & 0x4000) _ao_enable_cs(port, 14);\
+               if ((mask) & 0x8000) _ao_enable_cs(port, 15);\
+       } while (0)
+
+/* ao_dma_stm.c
+ */
+
+extern uint8_t ao_dma_done[STM_NUM_DMA];
+
+void
+ao_dma_set_transfer(uint8_t            index,
+                   volatile void       *peripheral,
+                   void                *memory,
+                   uint16_t            count,
+                   uint32_t            ccr);
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int index));
+
+void
+ao_dma_start(uint8_t index);
+
+void
+ao_dma_done_transfer(uint8_t index);
+
+void
+ao_dma_alloc(uint8_t index, uint8_t cselr);
+
+void
+ao_dma_init(void);
+
+/* ao_i2c_stm.c */
+
+void
+ao_i2c_get(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_start(uint8_t i2c_index, uint16_t address);
+
+void
+ao_i2c_put(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+uint8_t
+ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+void
+ao_i2c_init(void);
+
+#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_SW_FLOW 1
+#else
+#define HAS_SERIAL_SW_FLOW 0
+#endif
+
+#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_HW_FLOW 1
+#else
+#define HAS_SERIAL_HW_FLOW 0
+#endif
+
+/* ao_serial_stm.c */
+struct ao_stm_usart {
+       struct ao_fifo          rx_fifo;
+       struct ao_fifo          tx_fifo;
+       struct stm_usart        *reg;
+       uint8_t                 tx_running;
+       uint8_t                 draining;
+#if HAS_SERIAL_SW_FLOW
+       /* RTS - 0 if we have FIFO space, 1 if not
+        * CTS - 0 if we can send, 0 if not
+        */
+       struct stm_gpio         *gpio_rts;
+       struct stm_gpio         *gpio_cts;
+       uint8_t                 pin_rts;
+       uint8_t                 pin_cts;
+       uint8_t                 rts;
+#endif
+};
+
+#include <ao_lpuart.h>
+
+void
+ao_debug_out(char c);
+
+#if HAS_SERIAL_1
+extern struct ao_stm_usart     ao_stm_usart1;
+#endif
+
+#if HAS_SERIAL_2
+extern struct ao_stm_usart     ao_stm_usart2;
+#endif
+
+#if HAS_SERIAL_3
+extern struct ao_stm_usart     ao_stm_usart3;
+#endif
+
+#define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
+
+typedef uint32_t       ao_arch_irq_t;
+
+static inline void
+ao_arch_block_interrupts(void) {
+#ifdef AO_NONMASK_INTERRUPTS
+       asm("msr basepri,%0" : : "r" (AO_STM_NVIC_BASEPRI_MASK));
+#else
+       asm("cpsid i");
+#endif
+}
+
+static inline void
+ao_arch_release_interrupts(void) {
+#ifdef AO_NONMASK_INTERRUPTS
+       asm("msr basepri,%0" : : "r" (0x0));
+#else
+       asm("cpsie i");
+#endif
+}
+
+static inline uint32_t
+ao_arch_irqsave(void) {
+       uint32_t        val;
+#ifdef AO_NONMASK_INTERRUPTS
+       asm("mrs %0,basepri" : "=r" (val));
+#else
+       asm("mrs %0,primask" : "=r" (val));
+#endif
+       ao_arch_block_interrupts();
+       return val;
+}
+
+static inline void
+ao_arch_irqrestore(uint32_t basepri) {
+#ifdef AO_NONMASK_INTERRUPTS
+       asm("msr basepri,%0" : : "r" (basepri));
+#else
+       asm("msr primask,%0" : : "r" (basepri));
+#endif
+}
+
+static inline void
+ao_arch_memory_barrier(void) {
+       asm volatile("" ::: "memory");
+}
+
+static inline void
+ao_arch_irq_check(void) {
+#ifdef AO_NONMASK_INTERRUPTS
+       uint32_t        basepri;
+       asm("mrs %0,basepri" : "=r" (basepri));
+       if (basepri == 0)
+               ao_panic(AO_PANIC_IRQ);
+#else
+       uint32_t        primask;
+       asm("mrs %0,primask" : "=r" (primask));
+       if ((primask & 1) == 0)
+               ao_panic(AO_PANIC_IRQ);
+#endif
+}
+
+#if HAS_TASK
+static inline void
+ao_arch_init_stack(struct ao_task *task, void *start)
+{
+       uint32_t        *sp = &task->stack32[AO_STACK_SIZE >> 2];
+       uint32_t        a = (uint32_t) start;
+       int             i;
+
+       /* Return address (goes into LR) */
+       ARM_PUSH32(sp, a);
+
+       /* Clear register values r0-r7 */
+       i = 8;
+       while (i--)
+               ARM_PUSH32(sp, 0);
+
+       /* APSR */
+       ARM_PUSH32(sp, 0);
+
+       /* PRIMASK with interrupts enabled */
+       ARM_PUSH32(sp, 0);
+
+       task->sp32 = sp;
+}
+
+static inline void ao_arch_save_regs(void) {
+       /* Save general registers */
+       asm("push {r0-r7,lr}\n");
+
+       /* Save APSR */
+       asm("mrs r0,apsr");
+       asm("push {r0}");
+
+       /* Save PRIMASK */
+       asm("mrs r0,primask");
+       asm("push {r0}");
+}
+
+static inline void ao_arch_save_stack(void) {
+       uint32_t        *sp;
+       asm("mov %0,sp" : "=&r" (sp) );
+       ao_cur_task->sp32 = (sp);
+}
+
+static inline void ao_arch_restore_stack(void) {
+       /* Switch stacks */
+       asm("mov sp, %0" : : "r" (ao_cur_task->sp32) );
+
+       /* Restore PRIMASK */
+       asm("pop {r0}");
+       asm("msr primask,r0");
+
+       /* Restore APSR */
+       asm("pop {r0}");
+       asm("msr apsr_nczvq,r0");
+
+       /* Restore general registers */
+       asm("pop {r0-r7,pc}\n");
+}
+
+#ifndef HAS_SAMPLE_PROFILE
+#define HAS_SAMPLE_PROFILE 0
+#endif
+
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK    1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+       uint8_t         *psp;
+
+       asm("mrs %0,psp" : "=&r" (psp));
+       if (ao_cur_task &&
+           psp <= ao_cur_task->stack &&
+           psp >= ao_cur_task->stack - 256)
+               ao_panic(AO_PANIC_STACK);
+}
+#endif
+
+#if !HAS_SAMPLE_PROFILE
+#define HAS_ARCH_START_SCHEDULER       1
+
+static inline void ao_arch_start_scheduler(void) {
+       uint32_t        sp;
+       uint32_t        control;
+
+       asm("mrs %0,msp" : "=&r" (sp));
+       asm("msr psp,%0" : : "r" (sp));
+       asm("mrs %0,control" : "=r" (control));
+       control |= (1 << 1);
+       asm("msr control,%0" : : "r" (control));
+       asm("isb");
+}
+#endif
+
+#define ao_arch_isr_stack()
+
+#endif
+
+static inline void
+ao_arch_wait_interrupt(void) {
+#ifdef AO_NONMASK_INTERRUPTS
+       asm(
+           "dsb\n"                     /* Serialize data */
+           "isb\n"                     /* Serialize instructions */
+           "cpsid i\n"                 /* Block all interrupts */
+           "msr basepri,%0\n"          /* Allow all interrupts through basepri */
+           "wfi\n"                     /* Wait for an interrupt */
+           "cpsie i\n"                 /* Allow all interrupts */
+           "msr basepri,%1\n"          /* Block interrupts through basepri */
+           : : "r" (0), "r" (AO_STM_NVIC_BASEPRI_MASK));
+#else
+       asm("\twfi\n");
+       ao_arch_release_interrupts();
+       ao_arch_block_interrupts();
+#endif
+}
+
+#define ao_arch_critical(b) do {                       \
+               uint32_t __mask = ao_arch_irqsave();    \
+               do { b } while (0);                     \
+               ao_arch_irqrestore(__mask);             \
+       } while (0)
+
+void start(void);
+
+bool
+ao_storage_device_is_erased(uint32_t pos);
+
+#endif /* _AO_ARCH_FUNCS_H_ */
diff --git a/src/stm32l0/ao_dma_stm32l0.c b/src/stm32l0/ao_dma_stm32l0.c
new file mode 100644 (file)
index 0000000..d32844c
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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"
+
+#define NUM_DMA        7
+
+struct ao_dma_config {
+       void            (*isr)(int index);
+};
+
+uint8_t ao_dma_done[NUM_DMA];
+
+static struct ao_dma_config ao_dma_config[NUM_DMA];
+static uint8_t ao_dma_allocated[NUM_DMA];
+static uint8_t ao_dma_mutex[NUM_DMA];
+static uint8_t ao_dma_active;
+
+#ifndef LEAVE_DMA_ON
+static uint8_t ao_dma_active;
+#endif
+
+#define ch_mask(id)    (STM_DMA_ISR_MASK << STM_DMA_ISR(id))
+
+static void
+ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
+       /* Get channel interrupt bits */
+       uint32_t        isr = stm_dma1.isr & mask;
+       uint8_t         index;
+
+       /* Ack them */
+       stm_dma1.ifcr = isr;
+       for (index = low_index; index <= high_index; index++) {
+               if (isr & ch_mask(index)) {
+                       if (ao_dma_config[index].isr)
+                               (*ao_dma_config[index].isr)(index);
+                       else {
+                               ao_dma_done[index] = 1;
+                               ao_wakeup(&ao_dma_done[index]);
+                       }
+               }
+       }
+}
+
+void stm_dma1_channel1_isr(void) {
+       ao_dma_isr(STM_DMA_INDEX(1),
+                  STM_DMA_INDEX(1),
+                  ch_mask(STM_DMA_INDEX(1)));
+}
+
+void stm_dma1_channel3_2_isr(void) {
+       ao_dma_isr(STM_DMA_INDEX(2),
+                  STM_DMA_INDEX(3),
+                  ch_mask(STM_DMA_INDEX(2)) |
+                  ch_mask(STM_DMA_INDEX(3)));
+}
+
+void stm_dma1_channel7_4_isr(void) {
+       ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(7),
+                  ch_mask(STM_DMA_INDEX(4)) |
+                  ch_mask(STM_DMA_INDEX(5)) |
+                  ch_mask(STM_DMA_INDEX(6)) |
+                  ch_mask(STM_DMA_INDEX(7)));
+}
+
+void
+ao_dma_set_transfer(uint8_t            index,
+                   volatile void       *peripheral,
+                   void                *memory,
+                   uint16_t            count,
+                   uint32_t            ccr)
+{
+       if (ao_dma_allocated[index]) {
+               if (ao_dma_mutex[index])
+                       ao_panic(AO_PANIC_DMA);
+               ao_dma_mutex[index] = 0xff;
+       } else
+               ao_mutex_get(&ao_dma_mutex[index]);
+#ifndef LEAVE_DMA_ON
+       ao_arch_critical(
+               if (ao_dma_active++ == 0)
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
+               );
+#endif
+       stm_dma1.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+       stm_dma1.channel[index].cndtr = count;
+       stm_dma1.channel[index].cpar = peripheral;
+       stm_dma1.channel[index].cmar = memory;
+       ao_dma_config[index].isr = NULL;
+}
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int))
+{
+       ao_dma_config[index].isr = isr;
+}
+
+void
+ao_dma_start(uint8_t index)
+{
+       ao_dma_done[index] = 0;
+       stm_dma1.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
+}
+
+void
+ao_dma_done_transfer(uint8_t index)
+{
+       stm_dma1.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+#ifndef LEAVE_DMA_ON
+       ao_arch_critical(
+               if (--ao_dma_active == 0)
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN);
+               );
+#endif
+       if (ao_dma_allocated[index])
+               ao_dma_mutex[index] = 0;
+       else
+               ao_mutex_put(&ao_dma_mutex[index]);
+}
+
+void
+ao_dma_alloc(uint8_t index, uint8_t cselr)
+{
+       if (ao_dma_allocated[index])
+               ao_panic(AO_PANIC_DMA);
+       ao_dma_allocated[index] = 1;
+
+       int shift = (index << 2);
+       uint32_t mask = ~(0xf << shift);
+       stm_dma1.cselr = (stm_dma1.cselr & mask) | (cselr << shift);
+}
+
+#if DEBUG
+void
+ao_dma_dump_cmd(void)
+{
+       int i;
+
+#ifndef LEAVE_DMA_ON
+       ao_arch_critical(
+               if (ao_dma_active++ == 0)
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
+               );
+#endif
+       printf ("isr %08x ifcr%08x\n", stm_dma1.isr, stm_dma1.ifcr);
+       for (i = 0; i < NUM_DMA; i++)
+               printf("%d: done %d allocated %d mutex %2d ccr %04x cndtr %04x cpar %08x cmar %08x isr %08x\n",
+                      i,
+                      ao_dma_done[i],
+                      ao_dma_allocated[i],
+                      ao_dma_mutex[i],
+                      stm_dma1.channel[i].ccr,
+                      stm_dma1.channel[i].cndtr,
+                      stm_dma1.channel[i].cpar,
+                      stm_dma1.channel[i].cmar,
+                      ao_dma_config[i].isr);
+#ifndef LEAVE_DMA_ON
+       ao_arch_critical(
+               if (--ao_dma_active == 0)
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN);
+               );
+#endif
+}
+
+static const struct ao_cmds ao_dma_cmds[] = {
+       { ao_dma_dump_cmd,      "D\0Dump DMA status" },
+       { 0, NULL }
+};
+#endif
+
+void
+ao_dma_init(void)
+{
+       int     index;
+
+#ifdef LEAVE_DMA_ON
+       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
+#endif
+       for (index = 0; index < STM_NUM_DMA; index++) {
+               stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index);
+               stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index,
+                                     AO_STM_NVIC_MED_PRIORITY);
+               ao_dma_allocated[index] = 0;
+               ao_dma_mutex[index] = 0;
+       }
+#if DEBUG
+       ao_cmd_register(&ao_dma_cmds[0]);
+#endif
+}
diff --git a/src/stm32l0/ao_exti.h b/src/stm32l0/ao_exti.h
new file mode 100644 (file)
index 0000000..1d19a48
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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_EXTI_H_
+#define _AO_EXTI_H_
+
+#define AO_EXTI_MODE_RISING    1
+#define AO_EXTI_MODE_FALLING   2
+#define AO_EXTI_MODE_PULL_NONE 0
+#define AO_EXTI_MODE_PULL_UP   4
+#define AO_EXTI_MODE_PULL_DOWN 8
+#define AO_EXTI_PRIORITY_LOW   16
+#define AO_EXTI_PRIORITY_MED   0
+#define AO_EXTI_PRIORITY_HIGH  32
+#define AO_EXTI_PIN_NOCONFIGURE        64
+
+void
+ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void));
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void));
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin);
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin);
+
+void
+ao_exti_init(void);
+
+#endif /* _AO_EXTI_H_ */
diff --git a/src/stm32l0/ao_exti_stm.c b/src/stm32l0/ao_exti_stm.c
new file mode 100644 (file)
index 0000000..d808d1e
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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_exti.h>
+
+static void    (*ao_exti_callback[16])(void);
+
+uint32_t       ao_last_exti;
+
+static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
+       uint16_t        pending = (ao_last_exti = stm_exti.pr) & mask;
+       uint8_t         pin;
+       static uint16_t last_mask;
+       static uint8_t  last_pin;
+
+       if (pending == last_mask) {
+               stm_exti.pr = last_mask;
+               (*ao_exti_callback[last_pin])();
+               return;
+       }
+       stm_exti.pr = pending;
+       for (pin = first; pin <= last; pin++)
+               if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
+                       last_mask = (1 << pin);
+                       last_pin = pin;
+                       (*ao_exti_callback[pin])();
+               }
+}
+
+void stm_exti1_0_isr(void) { ao_exti_range_isr(0, 1, 0x3); }
+void stm_exti3_2_isr(void) { ao_exti_range_isr(2, 3, 0xc); }
+void stm_exti15_4_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+       uint32_t        mask = 1 << pin;
+       uint8_t         irq;
+       uint8_t         prio;
+
+       ao_exti_callback[pin] = callback;
+
+       /* configure gpio to interrupt routing */
+       stm_exticr_set(gpio, pin);
+
+#if 0
+       if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
+               uint32_t        pupdr;
+               /* configure pin as input, setting selected pull-up/down mode */
+               stm_moder_set(gpio, pin, STM_MODER_INPUT);
+               switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
+               case 0:
+               default:
+                       pupdr  = STM_PUPDR_NONE;
+                       break;
+               case AO_EXTI_MODE_PULL_UP:
+                       pupdr = STM_PUPDR_PULL_UP;
+                       break;
+               case AO_EXTI_MODE_PULL_DOWN:
+                       pupdr = STM_PUPDR_PULL_DOWN;
+                       break;
+               }
+               stm_pupdr_set(gpio, pin, pupdr);
+       }
+#endif
+
+       /* Set interrupt mask and rising/falling mode */
+       stm_exti.imr &= ~mask;
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+
+       if (pin <= 1)
+               irq = STM_ISR_EXTI1_0_POS;
+       else if (2 <= pin && pin <= 3)
+               irq = STM_ISR_EXTI3_2_POS;
+       else
+               irq = STM_ISR_EXTI15_4_POS;
+
+       /* Set priority */
+       prio = AO_STM_NVIC_MED_PRIORITY;
+       if (mode & AO_EXTI_PRIORITY_LOW)
+               prio = AO_STM_NVIC_LOW_PRIORITY;
+       else if (mode & AO_EXTI_PRIORITY_HIGH)
+               prio = AO_STM_NVIC_HIGH_PRIORITY;
+
+       stm_nvic_set_priority(irq, prio);
+       stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+       (void) gpio;
+
+       uint32_t        mask = 1 << pin;
+
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+}
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)(void)) {
+       (void) gpio;
+       ao_exti_callback[pin] = callback;
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+       uint32_t        mask = (1 << pin);
+       (void) gpio;
+       stm_exti.pr = mask;
+       stm_exti.imr |= mask;
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+       uint32_t        mask = (1 << pin);
+       (void) gpio;
+       stm_exti.imr &= ~mask;
+       stm_exti.pr = mask;
+}
+
+void
+ao_exti_init(void)
+{
+}
diff --git a/src/stm32l0/ao_flash.h b/src/stm32l0/ao_flash.h
new file mode 100644 (file)
index 0000000..274d6fe
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright Â© 2020 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_FLASH_H_
+#define _AO_FLASH_H_
+
+void
+ao_flash_erase_page(uint32_t *page);
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src);
+
+#endif /* _AO_FLASH_H_ */
diff --git a/src/stm32l0/ao_flash_stm32l0.c b/src/stm32l0/ao_flash_stm32l0.c
new file mode 100644 (file)
index 0000000..ba32744
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright Â© 2020 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_flash.h>
+
+static uint8_t
+ao_flash_pecr_is_locked(void)
+{
+       return (stm_flash.pecr & (1 << STM_FLASH_PECR_PE_LOCK)) != 0;
+}
+
+static uint8_t
+ao_flash_pgr_is_locked(void)
+{
+       return (stm_flash.pecr & (1 << STM_FLASH_PECR_PRG_LOCK)) != 0;
+}
+
+static void
+ao_flash_pecr_unlock(void)
+{
+       if (!ao_flash_pecr_is_locked())
+               return;
+
+       /* Unlock Data EEPROM and FLASH_PECR register */
+       stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1;
+       stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2;
+       if (ao_flash_pecr_is_locked())
+               ao_panic(AO_PANIC_FLASH);
+}
+
+static void
+ao_flash_pgr_unlock(void)
+{
+       if (!ao_flash_pgr_is_locked())
+               return;
+
+       /* Unlock program memory */
+       stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY1;
+       stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY2;
+       if (ao_flash_pgr_is_locked())
+               ao_panic(AO_PANIC_FLASH);
+}
+
+static void
+ao_flash_lock(void)
+{
+       stm_flash.pecr |= (1 << STM_FLASH_PECR_OPT_LOCK) | (1 << STM_FLASH_PECR_PRG_LOCK) | (1 << STM_FLASH_PECR_PE_LOCK);
+}
+
+static void
+ao_flash_wait_bsy(void)
+{
+       while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+               ;
+}
+
+static void __attribute__ ((section(".sdata2.flash"), noinline))
+_ao_flash_erase_page(uint32_t *page)
+{
+       stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG);
+
+       *page = 0x00000000;
+
+       ao_flash_wait_bsy();
+}
+
+void
+ao_flash_erase_page(uint32_t *page)
+{
+       ao_arch_block_interrupts();
+       ao_flash_pecr_unlock();
+       ao_flash_pgr_unlock();
+
+       _ao_flash_erase_page(page);
+
+       ao_flash_lock();
+       ao_arch_release_interrupts();
+}
+
+#if 0
+static void __attribute__ ((section(".sdata2.flash"), noinline))
+_ao_flash_half_page(uint32_t *dst, uint32_t *src)
+{
+       uint8_t         i;
+
+       stm_flash.pecr |= (1 << STM_FLASH_PECR_FPRG);
+       stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG);
+
+       ao_flash_wait_bsy();
+
+       for (i = 0; i < 32; i++) {
+               *dst++ = *src++;
+       }
+
+       while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+               ;
+}
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src)
+{
+       uint8_t         h;
+
+       ao_flash_erase_page(page);
+
+       ao_arch_block_interrupts();
+       ao_flash_pecr_unlock();
+       ao_flash_pgr_unlock();
+       for (h = 0; h < 2; h++) {
+               _ao_flash_half_page(page, src);
+               page += 32;
+               src += 32;
+       }
+       ao_flash_lock();
+       ao_arch_release_interrupts();
+}
+#endif
+
+static ao_pos_t        write_pos;
+static uint8_t write_pending;
+static union {
+       uint32_t        u32;
+       uint8_t         u8[4];
+} write_buf;
+
+void
+ao_storage_flush(void)
+{
+       if (write_pending) {
+               ao_flash_pecr_unlock();
+               ao_flash_pgr_unlock();
+               __storage[write_pos] = write_buf.u32;
+               ao_flash_lock();
+               write_pending = 0;
+       }
+}
+
+/* Read data within a storage unit */
+uint8_t
+ao_storage_device_read(ao_pos_t pos, void *buf, uint16_t len)
+{
+       memcpy(buf, ((uint8_t *) __storage) + pos, len);
+       return 1;
+}
+
+static void
+flash_write_select(ao_pos_t pos)
+{
+       /* Flush any pending writes to another word */
+       if (write_pending) {
+               if (pos == write_pos)
+                       return;
+               __storage[write_pos] = write_buf.u32;
+               write_pending = 0;
+       }
+       write_pos = pos;
+}
+
+/* Write data within a storage unit */
+uint8_t
+ao_storage_device_write(ao_pos_t pos, void *buf, uint16_t len)
+{
+       uint8_t *b8 = buf;
+
+       ao_flash_pecr_unlock();
+       ao_flash_pgr_unlock();
+       while (len) {
+               ao_pos_t        this_pos = pos >> 2;
+
+               flash_write_select(this_pos);
+
+               /* Update write buffer with new contents */
+               int this_word = 4 - (pos & 3);
+               if (this_word > len)
+                       this_word = len;
+               memcpy(&write_buf.u8[pos & 3], b8, this_word);
+               pos += this_word;
+               len -= this_word;
+               b8 += this_word;
+
+               /* If we filled the buffer, flush it out */
+               if ((pos & 3) == 0) {
+                       __storage[write_pos] = write_buf.u32;
+               } else {
+                       write_pending = 1;
+               }
+       }
+       ao_flash_lock();
+       return 1;
+}
+
+bool
+ao_storage_device_is_erased(uint32_t pos)
+{
+       uint8_t *m = ((uint8_t *) __storage) + pos;
+       uint32_t i;
+
+       for (i = 0; i < STM_FLASH_PAGE_SIZE; i++)
+               if (*m++ != AO_STORAGE_ERASED_BYTE)
+                       return false;
+       return true;
+}
+
+/* Erase device from pos through pos + ao_storage_block */
+uint8_t
+ao_storage_device_erase(uint32_t pos)
+{
+       ao_flash_erase_page(__storage + (pos >> 2));
+       return 1;
+}
diff --git a/src/stm32l0/ao_interrupt.c b/src/stm32l0/ao_interrupt.c
new file mode 100644 (file)
index 0000000..47effe5
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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 <string.h>
+#include <ao_boot.h>
+
+/* Interrupt functions */
+
+void stm_halt_isr(void)
+{
+       ao_panic(AO_PANIC_CRASH);
+}
+
+void stm_ignore_isr(void)
+{
+}
+
+void _start(void);
+
+#define STRINGIFY(x) #x
+
+#define isr(name) \
+       void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
+       _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr))
+
+#define isr_halt(name) \
+       void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
+       _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr))
+
+isr(nmi)
+isr_halt(hardfault)
+isr_halt(memmanage)
+isr_halt(busfault)
+isr_halt(usagefault)
+isr(svc)
+isr(debugmon)
+isr(pendsv)
+isr(systick)
+isr(wwdg)
+isr(pvd)
+isr(rtc)
+isr(flash)
+isr(rcc_crs)
+isr(exti1_0)
+isr(exti3_2)
+isr(exti15_4)
+isr(dma1_channel1)
+isr(dma1_channel3_2)
+isr(dma1_channel7_4)
+isr(adc_comp)
+isr(lptim1)
+isr(usart4_usart5)
+isr(tim2)
+isr(tim3)
+isr(tim4)
+isr(tim6)
+isr(tim7)
+isr(tim21)
+isr(i2c3)
+isr(tim22)
+isr(i2c1)
+isr(i2c2)
+isr(spi1)
+isr(spi2)
+isr(usart1)
+isr(usart2)
+isr(usart3)
+isr(lpuart1_aes)
+
+#define i(addr,name)   [(addr)/4] = stm_ ## name ## _isr
+
+extern char __stack[];
+void _start(void) __attribute__((__noreturn__));
+void main(void) __attribute__((__noreturn__));
+
+__attribute__ ((section(".init")))
+const void *const __interrupt_vector[] = {
+       [0] = &__stack,
+       [1] = _start,
+       i(0x08, nmi),
+       i(0x0c, hardfault),
+       i(0x2c, svc),
+       i(0x38, pendsv),
+       i(0x3c, systick),
+       i(0x40, wwdg),
+       i(0x44, pvd),
+       i(0x48, rtc),
+       i(0x4c, flash),
+       i(0x50, rcc_crs),
+       i(0x54, exti1_0),
+       i(0x58, exti3_2),
+       i(0x5c, exti15_4),
+       i(0x64, dma1_channel1),
+       i(0x68, dma1_channel3_2),
+       i(0x6c, dma1_channel7_4),
+       i(0x70, adc_comp),
+       i(0x74, lptim1),
+       i(0x78, usart4_usart5),
+       i(0x7c, tim2),
+       i(0x80, tim3),
+       i(0x84, tim6),
+       i(0x88, tim7),
+       i(0x90, tim21),
+       i(0x94, i2c3),
+       i(0x98, tim22),
+       i(0x9c, i2c1),
+       i(0xa0, i2c2),
+       i(0xa4, spi1),
+       i(0xa8, spi2),
+       i(0xac, usart1),
+       i(0xb0, usart2),
+       i(0xb4, lpuart1_aes),
+};
+
+extern char __data_source[];
+extern char __data_start[];
+extern char __data_size[];
+extern char __bss_start[];
+extern char __bss_size[];
+
+void _start(void)
+{
+#ifdef AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+               if (ao_boot_check_pin())
+#endif
+               {
+                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+               }
+       }
+#endif
+       memcpy(__data_start, __data_source, (uintptr_t) __data_size);
+       memset(__bss_start, '\0', (uintptr_t) __bss_size);
+
+       main();
+}
diff --git a/src/stm32l0/ao_lpuart.h b/src/stm32l0/ao_lpuart.h
new file mode 100644 (file)
index 0000000..567eda7
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright Â© 2020 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.
+ */
+
+char
+ao_lpuart1_getchar(void);
+
+void
+ao_lpuart1_putchar(char c);
+
+int
+_ao_lpuart1_pollchar(void);
+
+void
+ao_lpuart1_drain(void);
+
+void
+ao_lpuart1_set_speed(uint8_t speed);
+
+void
+ao_lpuart1_enable(void);
+
+void
+ao_lpuart1_disable(void);
diff --git a/src/stm32l0/ao_lpuart_stm.c b/src/stm32l0/ao_lpuart_stm.c
new file mode 100644 (file)
index 0000000..c4a23f5
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright Â© 2020 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_exti.h>
+#include <ao_lpuart.h>
+
+struct ao_stm_lpuart {
+       struct ao_fifo          rx_fifo;
+       struct ao_fifo          tx_fifo;
+       struct stm_lpuart       *reg;
+       uint8_t                 tx_running;
+       uint8_t                 draining;
+#if HAS_SERIAL_SW_FLOW
+       /* RTS - 0 if we have FIFO space, 1 if not
+        * CTS - 0 if we can send, 0 if not
+        */
+       struct stm_gpio         *gpio_rts;
+       struct stm_gpio         *gpio_cts;
+       uint8_t                 pin_rts;
+       uint8_t                 pin_cts;
+       uint8_t                 rts;
+#endif
+};
+
+static int
+_ao_lpuart_tx_start(struct ao_stm_lpuart *lpuart)
+{
+       if (!ao_fifo_empty(lpuart->tx_fifo)) {
+#if HAS_LPUART_SW_FLOW
+               if (lpuart->gpio_cts && ao_gpio_get(lpuart->gpio_cts, lpuart->pin_cts) == 1) {
+                       ao_exti_enable(lpuart->gpio_cts, lpuart->pin_cts);
+                       return 0;
+               }
+#endif
+               if (lpuart->reg->isr & (1 << STM_LPUART_ISR_TXE))
+               {
+                       lpuart->tx_running = 1;
+                       lpuart->reg->cr1 |= (1 << STM_LPUART_CR1_TXEIE) | (1 << STM_LPUART_CR1_TCIE);
+                       ao_fifo_remove(lpuart->tx_fifo, lpuart->reg->tdr);
+                       ao_wakeup(&lpuart->tx_fifo);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+#if HAS_LPUART_SW_FLOW
+static void
+_ao_lpuart_cts(struct ao_stm_lpuart *lpuart)
+{
+       if (_ao_lpuart_tx_start(lpuart))
+               ao_exti_disable(lpuart->gpio_cts, lpuart->pin_cts);
+}
+#endif
+
+static void
+_ao_lpuart_rx(struct ao_stm_lpuart *lpuart, int is_stdin)
+{
+       if (lpuart->reg->isr & (1 << STM_LPUART_ISR_RXNE)) {
+               lpuart->reg->icr = (1 << STM_LPUART_ICR_ORECF);
+               if (!ao_fifo_full(lpuart->rx_fifo)) {
+                       ao_fifo_insert(lpuart->rx_fifo, lpuart->reg->rdr);
+                       ao_wakeup(&lpuart->rx_fifo);
+                       if (is_stdin)
+                               ao_wakeup(&ao_stdin_ready);
+#if HAS_LPUART_SW_FLOW
+                       /* If the fifo is nearly full, turn off RTS and wait
+                        * for it to drain a bunch
+                        */
+                       if (lpuart->gpio_rts && ao_fifo_mostly(lpuart->rx_fifo)) {
+                               ao_gpio_set(lpuart->gpio_rts, lpuart->pin_rts, 1);
+                               lpuart->rts = 0;
+                       }
+#endif
+               } else {
+                       lpuart->reg->cr1 &= ~(1 << STM_LPUART_CR1_RXNEIE);
+               }
+       }
+}
+
+static void
+ao_lpuart_isr(struct ao_stm_lpuart *lpuart, int is_stdin)
+{
+       _ao_lpuart_rx(lpuart, is_stdin);
+
+       if (!_ao_lpuart_tx_start(lpuart))
+               lpuart->reg->cr1 &= ~(1<< STM_LPUART_CR1_TXEIE);
+
+       if (lpuart->reg->isr & (1 << STM_LPUART_ISR_TC)) {
+               lpuart->tx_running = 0;
+               lpuart->reg->cr1 &= ~(1 << STM_LPUART_CR1_TCIE);
+               if (lpuart->draining) {
+                       lpuart->draining = 0;
+                       ao_wakeup(&lpuart->tx_fifo);
+               }
+       }
+}
+
+static int
+_ao_lpuart_pollchar(struct ao_stm_lpuart *lpuart)
+{
+       int     c;
+
+       if (ao_fifo_empty(lpuart->rx_fifo))
+               c = AO_READ_AGAIN;
+       else {
+               uint8_t u;
+               ao_fifo_remove(lpuart->rx_fifo,u);
+               if ((lpuart->reg->cr1 & (1 << STM_LPUART_CR1_RXNEIE)) == 0) {
+                       if (ao_fifo_barely(lpuart->rx_fifo))
+                               lpuart->reg->cr1 |= (1 << STM_LPUART_CR1_RXNEIE);
+               }
+#if HAS_LPUART_SW_FLOW
+               /* If we've cleared RTS, check if there's space now and turn it back on */
+               if (lpuart->gpio_rts && lpuart->rts == 0 && ao_fifo_barely(lpuart->rx_fifo)) {
+                       ao_gpio_set(lpuart->gpio_rts, lpuart->pin_rts, 0);
+                       lpuart->rts = 1;
+               }
+#endif
+               c = u;
+       }
+       return c;
+}
+
+static char
+ao_lpuart_getchar(struct ao_stm_lpuart *lpuart)
+{
+       int c;
+       ao_arch_block_interrupts();
+       while ((c = _ao_lpuart_pollchar(lpuart)) == AO_READ_AGAIN)
+               ao_sleep(&lpuart->rx_fifo);
+       ao_arch_release_interrupts();
+       return (char) c;
+}
+
+#if 0
+static inline uint8_t
+_ao_lpuart_sleep_for(struct ao_stm_lpuart *lpuart, uint16_t timeout)
+{
+       return ao_sleep_for(&lpuart->rx_fifo, timeout);
+}
+#endif
+
+static void
+ao_lpuart_putchar(struct ao_stm_lpuart *lpuart, char c)
+{
+       ao_arch_block_interrupts();
+       while (ao_fifo_full(lpuart->tx_fifo))
+               ao_sleep(&lpuart->tx_fifo);
+       ao_fifo_insert(lpuart->tx_fifo, c);
+       _ao_lpuart_tx_start(lpuart);
+       ao_arch_release_interrupts();
+}
+
+static void
+ao_lpuart_drain(struct ao_stm_lpuart *lpuart)
+{
+       ao_arch_block_interrupts();
+       while (!ao_fifo_empty(lpuart->tx_fifo) || lpuart->tx_running) {
+               lpuart->draining = 1;
+               ao_sleep(&lpuart->tx_fifo);
+       }
+       ao_arch_release_interrupts();
+}
+
+extern const uint32_t ao_usart_speeds[];
+
+static void
+ao_lpuart_set_speed(struct ao_stm_lpuart *lpuart, uint8_t speed)
+{
+       if (speed > AO_SERIAL_SPEED_115200)
+               return;
+       lpuart->reg->brr = 256 * AO_PCLK1 / ao_usart_speeds[speed];
+}
+
+static void
+ao_lpuart_enable(struct ao_stm_lpuart *lpuart, int hw_flow)
+{
+       lpuart->reg->cr1 = ((0 << STM_LPUART_CR1_M1) |
+                          (0 << STM_LPUART_CR1_DEAT) |
+                          (0 << STM_LPUART_CR1_DEDT) |
+                          (0 << STM_LPUART_CR1_CMIE) |
+                          (0 << STM_LPUART_CR1_MME) |
+                          (0 << STM_LPUART_CR1_M0) |
+                          (0 << STM_LPUART_CR1_WAKE) |
+                          (0 << STM_LPUART_CR1_PCE) |
+                          (0 << STM_LPUART_CR1_PS) |
+                          (0 << STM_LPUART_CR1_PEIE) |
+                          (0 << STM_LPUART_CR1_TXEIE) |
+                          (0 << STM_LPUART_CR1_TCIE) |
+                          (1 << STM_LPUART_CR1_RXNEIE) |
+                          (0 << STM_LPUART_CR1_IDLEIE) |
+                          (1 << STM_LPUART_CR1_TE) |
+                          (1 << STM_LPUART_CR1_RE) |
+                          (0 << STM_LPUART_CR1_UESM) |
+                          (0 << STM_LPUART_CR1_UE));
+
+       lpuart->reg->cr2 = ((0 << STM_LPUART_CR2_ADD) |
+                          (0 << STM_LPUART_CR2_MSBFIRST) |
+                          (0 << STM_LPUART_CR2_DATAINV) |
+                          (0 << STM_LPUART_CR2_TXINV) |
+                          (0 << STM_LPUART_CR2_RXINV) |
+                          (0 << STM_LPUART_CR2_SWAP) |
+                          (0 << STM_LPUART_CR2_STOP) |
+                          (0 << STM_LPUART_CR2_ADDM7));
+
+       uint32_t cr3 = ((0 << STM_LPUART_CR3_UCESM) |
+                       (0 << STM_LPUART_CR3_WUFIE) |
+                       (0 << STM_LPUART_CR3_WUS) |
+                       (0 << STM_LPUART_CR3_DEP) |
+                       (0 << STM_LPUART_CR3_DEM) |
+                       (0 << STM_LPUART_CR3_DDRE) |
+                       (0 << STM_LPUART_CR3_OVRDIS) |
+                       (0 << STM_LPUART_CR3_CTSIE) |
+                       (0 << STM_LPUART_CR3_CTSE) |
+                       (0 << STM_LPUART_CR3_RTSE) |
+                       (0 << STM_LPUART_CR3_DMAT) |
+                       (0 << STM_LPUART_CR3_DMAR) |
+                       (0 << STM_LPUART_CR3_HDSEL) |
+                       (0 << STM_LPUART_CR3_EIE));
+
+       if (hw_flow)
+               cr3 |= ((1 << STM_LPUART_CR3_CTSE) |
+                       (1 << STM_LPUART_CR3_RTSE));
+
+       lpuart->reg->cr3 = cr3;
+
+       /* Pick a 9600 baud rate */
+       ao_lpuart_set_speed(lpuart, AO_SERIAL_SPEED_9600);
+
+       /* Enable the lpuart */
+       lpuart->reg->cr1 |= (1 << STM_LPUART_CR1_UE);
+}
+
+static void
+ao_lpuart_disable(struct ao_stm_lpuart *lpuart)
+{
+       ao_lpuart_drain(lpuart);
+       lpuart->reg->cr1 = 0;
+}
+
+#if HAS_LPUART_1
+
+struct ao_stm_lpuart ao_stm_lpuart1;
+
+void stm_lpuart1_aes_isr(void) {
+       ao_lpuart_isr(&ao_stm_lpuart1, USE_LPUART_1_STDIN);
+}
+
+char
+ao_lpuart1_getchar(void)
+{
+       return ao_lpuart_getchar(&ao_stm_lpuart1);
+}
+
+void
+ao_lpuart1_putchar(char c)
+{
+       ao_lpuart_putchar(&ao_stm_lpuart1, c);
+}
+
+int
+_ao_lpuart1_pollchar(void)
+{
+       return _ao_lpuart_pollchar(&ao_stm_lpuart1);
+}
+
+void
+ao_lpuart1_drain(void)
+{
+       ao_lpuart_drain(&ao_stm_lpuart1);
+}
+
+void
+ao_lpuart1_set_speed(uint8_t speed)
+{
+       ao_lpuart_drain(&ao_stm_lpuart1);
+       ao_lpuart_set_speed(&ao_stm_lpuart1, speed);
+}
+
+#endif /* HAS_LPUART_1 */
+
+#if HAS_LPUART_SW_FLOW
+static void
+ao_lpuart_set_sw_rts_cts(struct ao_stm_lpuart *lpuart,
+                        void (*isr)(void),
+                        struct stm_gpio *port_rts,
+                        int pin_rts,
+                        struct stm_gpio *port_cts,
+                        int pin_cts)
+{
+       /* Pull RTS low to note that there's space in the FIFO
+        */
+       ao_enable_output(port_rts, pin_rts, 0);
+       lpuart->gpio_rts = port_rts;
+       lpuart->pin_rts = pin_rts;
+       lpuart->rts = 1;
+
+       ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+       lpuart->gpio_cts = port_cts;
+       lpuart->pin_cts = pin_cts;
+}
+#endif
+
+void
+ao_lpuart1_enable(void)
+{
+       /*
+        *      TX      RX
+        *      PA1     PA0
+        *      PA2     PA3
+        *      PA4     PA3
+        *      PA14    PA13
+        *      PB6     PB7
+        */
+
+#ifdef HAS_LPUART_1
+       /* Clock source defaults to PCLK1, so just leave it */
+
+# if LPUART_1_PA0_PA1
+       ao_enable_port(&stm_gpioa);
+       stm_afr_set(&stm_gpioa, 0, STM_AFR_AF6);
+       stm_afr_set(&stm_gpioa, 1, STM_AFR_AF6);
+# else
+#  error "No LPUART_1 port configuration specified"
+# endif
+       /* Enable LPUART */
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_LPUART1EN);
+
+       ao_stm_lpuart1.reg = &stm_lpuart1;
+       ao_lpuart_enable(&ao_stm_lpuart1, USE_LPUART_1_FLOW && !USE_LPUART_1_SW_FLOW);
+
+       stm_nvic_set_enable(STM_ISR_LPUART1_AES_POS);
+       stm_nvic_set_priority(STM_ISR_LPUART1_AES_POS, 4);
+# if USE_LPUART_1_STDIN && !DELAY_LPUART_1_STDIN
+       ao_add_stdio(_ao_lpuart1_pollchar,
+                    ao_lpuart1_putchar,
+                    NULL);
+# endif
+#endif
+}
+
+void
+ao_lpuart1_disable(void)
+{
+       /* Stop LPUART */
+       ao_lpuart_disable(&ao_stm_lpuart1);
+
+       /* Disable interrupts */
+       stm_nvic_clear_enable(STM_ISR_LPUART1_AES_POS);
+
+       /* Remap pins to GPIO use */
+# if LPUART_1_PA0_PA1
+       stm_moder_set(&stm_gpioa, 0, STM_MODER_INPUT);
+       stm_moder_set(&stm_gpioa, 1, STM_MODER_OUTPUT);
+# else
+#  error "No LPUART_1 port configuration specified"
+# endif
+
+       /* Disable LPUART */
+       stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_LPUART1EN);
+}
diff --git a/src/stm32l0/ao_pwm_stm.c b/src/stm32l0/ao_pwm_stm.c
new file mode 100644 (file)
index 0000000..341f888
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright Â© 2015 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_pwm.h"
+
+static uint8_t pwm_running;
+
+static uint16_t        pwm_value[NUM_PWM];
+
+static void
+ao_pwm_up(void)
+{
+       if (pwm_running++ == 0) {
+               struct stm_tim234       *tim = &AO_PWM_TIMER;
+
+               tim->ccr1 = 0;
+               tim->ccr2 = 0;
+               tim->ccr3 = 0;
+               tim->ccr4 = 0;
+               tim->arr = PWM_MAX - 1; /* turn on the timer */
+               tim->cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
+                           (0 << STM_TIM234_CR1_ARPE) |
+                           (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
+                           (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) |
+                           (0 << STM_TIM234_CR1_OPM) |
+                           (0 << STM_TIM234_CR1_URS) |
+                           (0 << STM_TIM234_CR1_UDIS) |
+                           (1 << STM_TIM234_CR1_CEN));
+
+               /* Set the timer running */
+               tim->egr = (1 << STM_TIM234_EGR_UG);
+       }
+}
+
+static void
+ao_pwm_down(void)
+{
+       if (--pwm_running == 0) {
+               struct stm_tim234       *tim = &AO_PWM_TIMER;
+
+               tim->arr = 0;
+               tim->cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
+                           (0 << STM_TIM234_CR1_ARPE) |
+                           (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
+                           (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) |
+                           (0 << STM_TIM234_CR1_OPM) |
+                           (0 << STM_TIM234_CR1_URS) |
+                           (0 << STM_TIM234_CR1_UDIS) |
+                           (0 << STM_TIM234_CR1_CEN));
+
+               /* Stop the timer */
+               tim->egr = (1 << STM_TIM234_EGR_UG);
+       }
+}
+
+void
+ao_pwm_set(uint8_t pwm, uint16_t value)
+{
+       struct stm_tim234       *tim = &AO_PWM_TIMER;
+
+       if (value > PWM_MAX)
+               value = PWM_MAX;
+       if (value != 0) {
+               if (pwm_value[pwm] == 0)
+                       ao_pwm_up();
+       }
+       switch (pwm) {
+       case 0:
+               tim->ccr1 = value;
+               break;
+       case 1:
+               tim->ccr2 = value;
+               break;
+       case 2:
+               tim->ccr3 = value;
+               break;
+       case 3:
+               tim->ccr4 = value;
+               break;
+       }
+       if (value == 0) {
+               if (pwm_value[pwm] != 0)
+                       ao_pwm_down();
+       }
+       pwm_value[pwm] = value;
+}
+
+static void
+ao_pwm_cmd(void)
+{
+       uint8_t ch;
+       uint16_t val;
+
+       ch = ao_cmd_decimal();
+       val = ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+
+       printf("Set channel %d to %d\n", ch, val);
+       ao_pwm_set(ch, val);
+}
+
+static const struct ao_cmds ao_pwm_cmds[] = {
+       { ao_pwm_cmd,   "P <ch> <val>\0Set PWM ch to val" },
+       { 0, NULL },
+};
+
+void
+ao_pwm_init(void)
+{
+       struct stm_tim234       *tim = &AO_PWM_TIMER;
+
+       stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE);
+
+       tim->cr1 = 0;
+       tim->psc = AO_PWM_TIMER_SCALE - 1;
+       tim->cnt = 0;
+       tim->ccer = ((1 << STM_TIM234_CCER_CC1E) |
+                    (0 << STM_TIM234_CCER_CC1P) |
+                    (1 << STM_TIM234_CCER_CC2E) |
+                    (0 << STM_TIM234_CCER_CC2P) |
+                    (1 << STM_TIM234_CCER_CC3E) |
+                    (0 << STM_TIM234_CCER_CC3P) |
+                    (1 << STM_TIM234_CCER_CC4E) |
+                    (0 << STM_TIM234_CCER_CC4P));
+
+       tim->ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |
+                     (STM_TIM234_CCMR1_OC2M_PWM_MODE_1 << STM_TIM234_CCMR1_OC2M) |
+                     (0 << STM_TIM234_CCMR1_OC2PE) |
+                     (0 << STM_TIM234_CCMR1_OC2FE) |
+                     (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) |
+
+                     (0 << STM_TIM234_CCMR1_OC1CE) |
+                     (STM_TIM234_CCMR1_OC1M_PWM_MODE_1 << STM_TIM234_CCMR1_OC1M) |
+                     (0 << STM_TIM234_CCMR1_OC1PE) |
+                     (0 << STM_TIM234_CCMR1_OC1FE) |
+                     (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
+
+
+       tim->ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) |
+                     (STM_TIM234_CCMR2_OC4M_PWM_MODE_1 << STM_TIM234_CCMR2_OC4M) |
+                     (0 << STM_TIM234_CCMR2_OC4PE) |
+                     (0 << STM_TIM234_CCMR2_OC4FE) |
+                     (STM_TIM234_CCMR2_CC4S_OUTPUT << STM_TIM234_CCMR2_CC4S) |
+
+                     (0 << STM_TIM234_CCMR2_OC3CE) |
+                     (STM_TIM234_CCMR2_OC3M_PWM_MODE_1 << STM_TIM234_CCMR2_OC3M) |
+                     (0 << STM_TIM234_CCMR2_OC3PE) |
+                     (0 << STM_TIM234_CCMR2_OC3FE) |
+                     (STM_TIM234_CCMR2_CC3S_OUTPUT << STM_TIM234_CCMR2_CC3S));
+       tim->egr = 0;
+
+       tim->sr = 0;
+       tim->dier = 0;
+       tim->smcr = 0;
+       tim->cr2 = ((0 << STM_TIM234_CR2_TI1S) |
+                   (STM_TIM234_CR2_MMS_RESET<< STM_TIM234_CR2_MMS) |
+                   (0 << STM_TIM234_CR2_CCDS));
+
+       stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF2);
+       stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_40MHz);
+#if NUM_PWM > 1
+       stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF2);
+       stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_40MHz);
+#endif
+#if NUM_PWM > 2
+       stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF2);
+       stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_40MHz);
+#endif
+#if NUM_PWM > 3
+       stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF2);
+       stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_40MHz);
+#endif
+       ao_cmd_register(&ao_pwm_cmds[0]);
+}
diff --git a/src/stm32l0/ao_serial_stm.c b/src/stm32l0/ao_serial_stm.c
new file mode 100644 (file)
index 0000000..ac745d9
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Copyright Â© 2020 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_exti.h>
+
+static int
+_ao_usart_tx_start(struct ao_stm_usart *usart)
+{
+       if (!ao_fifo_empty(usart->tx_fifo)) {
+#if HAS_SERIAL_SW_FLOW
+               if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts) == 1) {
+                       ao_exti_enable(usart->gpio_cts, usart->pin_cts);
+                       return 0;
+               }
+#endif
+               if (usart->reg->isr & (1 << STM_USART_ISR_TXE))
+               {
+                       usart->tx_running = 1;
+                       usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE);
+                       ao_fifo_remove(usart->tx_fifo, usart->reg->tdr);
+                       ao_wakeup(&usart->tx_fifo);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+#if HAS_SERIAL_SW_FLOW
+static void
+_ao_usart_cts(struct ao_stm_usart *usart)
+{
+       if (_ao_usart_tx_start(usart))
+               ao_exti_disable(usart->gpio_cts, usart->pin_cts);
+}
+#endif
+
+static void
+_ao_usart_rx(struct ao_stm_usart *usart, int is_stdin)
+{
+       if (usart->reg->isr & (1 << STM_USART_ISR_RXNE)) {
+               usart->reg->icr = (1 << STM_USART_ICR_ORECF);
+               if (!ao_fifo_full(usart->rx_fifo)) {
+                       ao_fifo_insert(usart->rx_fifo, usart->reg->rdr);
+                       ao_wakeup(&usart->rx_fifo);
+                       if (is_stdin)
+                               ao_wakeup(&ao_stdin_ready);
+#if HAS_SERIAL_SW_FLOW
+                       /* If the fifo is nearly full, turn off RTS and wait
+                        * for it to drain a bunch
+                        */
+                       if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) {
+                               ao_gpio_set(usart->gpio_rts, usart->pin_rts, 1);
+                               usart->rts = 0;
+                       }
+#endif
+               } else {
+                       usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE);
+               }
+       }
+}
+
+static void
+ao_usart_isr(struct ao_stm_usart *usart, int is_stdin)
+{
+       _ao_usart_rx(usart, is_stdin);
+
+       if (!_ao_usart_tx_start(usart))
+               usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE);
+
+       if (usart->reg->isr & (1 << STM_USART_ISR_TC)) {
+               usart->tx_running = 0;
+               usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE);
+               if (usart->draining) {
+                       usart->draining = 0;
+                       ao_wakeup(&usart->tx_fifo);
+               }
+       }
+}
+
+static int
+_ao_usart_pollchar(struct ao_stm_usart *usart)
+{
+       int     c;
+
+       if (ao_fifo_empty(usart->rx_fifo))
+               c = AO_READ_AGAIN;
+       else {
+               uint8_t u;
+               ao_fifo_remove(usart->rx_fifo,u);
+               if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) {
+                       if (ao_fifo_barely(usart->rx_fifo))
+                               usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE);
+               }
+#if HAS_SERIAL_SW_FLOW
+               /* If we've cleared RTS, check if there's space now and turn it back on */
+               if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) {
+                       ao_gpio_set(usart->gpio_rts, usart->pin_rts, 0);
+                       usart->rts = 1;
+               }
+#endif
+               c = u;
+       }
+       return c;
+}
+
+static char
+ao_usart_getchar(struct ao_stm_usart *usart)
+{
+       int c;
+       ao_arch_block_interrupts();
+       while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN)
+               ao_sleep(&usart->rx_fifo);
+       ao_arch_release_interrupts();
+       return (char) c;
+}
+
+#if 0
+static inline uint8_t
+_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)
+{
+       return ao_sleep_for(&usart->rx_fifo, timeout);
+}
+#endif
+
+static void
+ao_usart_putchar(struct ao_stm_usart *usart, char c)
+{
+       ao_arch_block_interrupts();
+       while (ao_fifo_full(usart->tx_fifo))
+               ao_sleep(&usart->tx_fifo);
+       ao_fifo_insert(usart->tx_fifo, c);
+       _ao_usart_tx_start(usart);
+       ao_arch_release_interrupts();
+}
+
+#if 0
+static void
+ao_usart_drain(struct ao_stm_usart *usart)
+{
+       ao_arch_block_interrupts();
+       while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) {
+               usart->draining = 1;
+               ao_sleep(&usart->tx_fifo);
+       }
+       ao_arch_release_interrupts();
+}
+#endif
+
+const uint32_t ao_usart_speeds[] = {
+       [AO_SERIAL_SPEED_4800] = 4800,
+       [AO_SERIAL_SPEED_9600] = 9600,
+       [AO_SERIAL_SPEED_19200] = 19200,
+       [AO_SERIAL_SPEED_57600] = 57600,
+       [AO_SERIAL_SPEED_115200] = 115200,
+};
+
+static void
+ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
+{
+       if (speed > AO_SERIAL_SPEED_115200)
+               return;
+       usart->reg->brr = AO_PCLK2 / ao_usart_speeds[speed];
+}
+
+static void
+ao_usart_init(struct ao_stm_usart *usart, int hw_flow)
+{
+       usart->reg->cr1 = ((0 << STM_USART_CR1_M1) |
+                          (0 << STM_USART_CR1_EOBIE) |
+                          (0 << STM_USART_CR1_RTOIE) |
+                          (0 << STM_USART_CR1_DEAT) |
+                          (0 << STM_USART_CR1_DEDT) |
+                          (0 << STM_USART_CR1_OVER8) |
+                          (0 << STM_USART_CR1_CMIE) |
+                          (0 << STM_USART_CR1_MME) |
+                          (0 << STM_USART_CR1_M0) |
+                          (0 << STM_USART_CR1_WAKE) |
+                          (0 << STM_USART_CR1_PCE) |
+                          (0 << STM_USART_CR1_PS) |
+                          (0 << STM_USART_CR1_PEIE) |
+                          (0 << STM_USART_CR1_TXEIE) |
+                          (0 << STM_USART_CR1_TCIE) |
+                          (1 << STM_USART_CR1_RXNEIE) |
+                          (0 << STM_USART_CR1_IDLEIE) |
+                          (1 << STM_USART_CR1_TE) |
+                          (1 << STM_USART_CR1_RE) |
+                          (0 << STM_USART_CR1_UESM) |
+                          (0 << STM_USART_CR1_UE));
+
+       usart->reg->cr2 = ((0 << STM_USART_CR2_ADD) |
+                          (0 << STM_USART_CR2_RTOEN) |
+                          (0 << STM_USART_CR2_ABRMOD) |
+                          (0 << STM_USART_CR2_ABREN) |
+                          (0 << STM_USART_CR2_MSBFIRST) |
+                          (0 << STM_USART_CR2_DATAINV) |
+                          (0 << STM_USART_CR2_TXINV) |
+                          (0 << STM_USART_CR2_RXINV) |
+                          (0 << STM_USART_CR2_SWAP) |
+                          (0 << STM_USART_CR2_LINEN) |
+                          (0 << STM_USART_CR2_STOP) |
+                          (0 << STM_USART_CR2_CLKEN) |
+                          (0 << STM_USART_CR2_CPOL) |
+                          (0 << STM_USART_CR2_CHPA) |
+                          (0 << STM_USART_CR2_LBCL) |
+                          (0 << STM_USART_CR2_LBDIE) |
+                          (0 << STM_USART_CR2_LBDL) |
+                          (0 << STM_USART_CR2_ADDM7));
+
+       uint32_t cr3 = ((0 << STM_USART_CR3_WUFIE) |
+                       (0 << STM_USART_CR3_WUS) |
+                       (0 << STM_USART_CR3_SCARCNT) |
+                       (0 << STM_USART_CR3_DEP) |
+                       (0 << STM_USART_CR3_DEM) |
+                       (0 << STM_USART_CR3_DDRE) |
+                       (0 << STM_USART_CR3_OVRDIS) |
+                       (0 << STM_USART_CR3_ONEBIT) |
+                       (0 << STM_USART_CR3_CTIIE) |
+                       (0 << STM_USART_CR3_CTSE) |
+                       (0 << STM_USART_CR3_RTSE) |
+                       (0 << STM_USART_CR3_DMAT) |
+                       (0 << STM_USART_CR3_DMAR) |
+                       (0 << STM_USART_CR3_SCEN) |
+                       (0 << STM_USART_CR3_NACK) |
+                       (0 << STM_USART_CR3_HDSEL) |
+                       (0 << STM_USART_CR3_IRLP) |
+                       (0 << STM_USART_CR3_IREN) |
+                       (0 << STM_USART_CR3_EIE));
+
+       if (hw_flow)
+               cr3 |= ((1 << STM_USART_CR3_CTSE) |
+                       (1 << STM_USART_CR3_RTSE));
+
+       usart->reg->cr3 = cr3;
+
+       /* Pick a 9600 baud rate */
+       ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
+
+       /* Enable the usart */
+       usart->reg->cr1 |= (1 << STM_USART_CR1_UE);
+}
+
+#if HAS_SERIAL_1
+
+struct ao_stm_usart ao_stm_usart1;
+
+void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); }
+
+char
+ao_serial1_getchar(void)
+{
+       return ao_usart_getchar(&ao_stm_usart1);
+}
+
+void
+ao_serial1_putchar(char c)
+{
+       ao_usart_putchar(&ao_stm_usart1, c);
+}
+
+int
+_ao_serial1_pollchar(void)
+{
+       return _ao_usart_pollchar(&ao_stm_usart1);
+}
+
+#if 0
+uint8_t
+_ao_serial1_sleep_for(uint16_t timeout)
+{
+       return _ao_usart_sleep_for(&ao_stm_usart1, timeout);
+}
+#endif
+
+#if 0
+void
+ao_serial1_drain(void)
+{
+       ao_usart_drain(&ao_stm_usart1);
+}
+
+void
+ao_serial1_set_speed(uint8_t speed)
+{
+       ao_usart_drain(&ao_stm_usart1);
+       ao_usart_set_speed(&ao_stm_usart1, speed);
+}
+#endif
+#endif /* HAS_SERIAL_1 */
+
+#if HAS_SERIAL_2
+
+struct ao_stm_usart ao_stm_usart2;
+
+void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); }
+
+char
+ao_serial2_getchar(void)
+{
+       return ao_usart_getchar(&ao_stm_usart2);
+}
+
+void
+ao_serial2_putchar(char c)
+{
+       ao_usart_putchar(&ao_stm_usart2, c);
+}
+
+int
+_ao_serial2_pollchar(void)
+{
+       return _ao_usart_pollchar(&ao_stm_usart2);
+}
+
+#if 0
+uint8_t
+_ao_serial2_sleep_for(uint16_t timeout)
+{
+       return _ao_usart_sleep_for(&ao_stm_usart2, timeout);
+}
+
+void
+ao_serial2_drain(void)
+{
+       ao_usart_drain(&ao_stm_usart2);
+}
+
+void
+ao_serial2_set_speed(uint8_t speed)
+{
+       ao_usart_drain(&ao_stm_usart2);
+       ao_usart_set_speed(&ao_stm_usart2, speed);
+}
+#endif
+
+#if USE_SERIAL_2_FLOW && USE_SERIAL_2_SW_FLOW
+void
+ao_serial2_cts(void)
+{
+       _ao_usart_cts(&ao_stm_usart2);
+}
+#endif
+
+#endif /* HAS_SERIAL_2 */
+
+#if HAS_SERIAL_SW_FLOW
+static void
+ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
+                        void (*isr)(void),
+                        struct stm_gpio *port_rts,
+                        int pin_rts,
+                        struct stm_gpio *port_cts,
+                        int pin_cts)
+{
+       /* Pull RTS low to note that there's space in the FIFO
+        */
+       ao_enable_output(port_rts, pin_rts, 0);
+       usart->gpio_rts = port_rts;
+       usart->pin_rts = pin_rts;
+       usart->rts = 1;
+
+       ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+       usart->gpio_cts = port_cts;
+       usart->pin_cts = pin_cts;
+}
+#endif
+
+#if 0
+void
+ao_serial_shutdown(void)
+{
+# if SERIAL_2_PA2_PA3
+       stm_moder_set(&stm_gpioa, 2, STM_MODER_INPUT);
+       stm_moder_set(&stm_gpioa, 3, STM_MODER_INPUT);
+# elif SERIAL_2_PA9_PA10
+       stm_moder_set(&stm_gpioa, 9, STM_MODER_INPUT);
+       stm_moder_set(&stm_gpioa, 10, STM_MODER_INPUT);
+# elif SERIAL_2_PA14_PA15
+       stm_moder_set(&stm_gpioa, 14, STM_MODER_INPUT);
+       stm_moder_set(&stm_gpioa, 15, STM_MODER_INPUT);
+# elif SERIAL_2_PB6_PB7
+       stm_moder_set(&stm_gpiob, 6, STM_MODER_INPUT);
+       stm_moder_set(&stm_gpiob, 7, STM_MODER_INPUT);
+#endif
+#if HAS_SERIAL_1
+       stm_rcc.apb2enr &= ~(1 << STM_RCC_APB2ENR_USART1EN);
+#endif
+#if HAS_SERIAL_2
+       stm_nvic_set_disable(STM_ISR_USART2_POS);
+       stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USART2EN);
+#endif
+}
+#endif
+
+void
+ao_serial_init(void)
+{
+#if HAS_SERIAL_1
+#endif
+
+#if HAS_SERIAL_2
+       /*
+        *      TX      RX
+        *      PA2     PA3
+        *      PA9     PA10
+        *      PA14    PA15
+        *      PB6     PB7
+        */
+
+# if SERIAL_2_PA2_PA3
+       ao_enable_port(&stm_gpioa);
+       stm_afr_set(&stm_gpioa, 2, STM_AFR_AF4);
+       stm_afr_set(&stm_gpioa, 3, STM_AFR_AF4);
+# elif SERIAL_2_PA9_PA10
+       ao_enable_port(&stm_gpioa);
+       stm_afr_set(&stm_gpioa, 9, STM_AFR_AF4);
+       stm_afr_set(&stm_gpioa, 10, STM_AFR_AF4);
+# elif SERIAL_2_PA14_PA15
+       ao_enable_port(&stm_gpioa);
+       stm_afr_set(&stm_gpioa, 14, STM_AFR_AF4);
+       stm_afr_set(&stm_gpioa, 15, STM_AFR_AF4);
+# elif SERIAL_2_PB6_PB7
+       ao_enable_port(&stm_gpiob);
+       stm_afr_set(&stm_gpiob, 6, STM_AFR_AF0);
+       stm_afr_set(&stm_gpiob, 7, STM_AFR_AF0);
+# else
+#  error "No SERIAL_2 port configuration specified"
+# endif
+       /* Enable USART */
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN);
+
+       ao_stm_usart2.reg = &stm_usart2;
+       ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW);
+
+       stm_nvic_set_enable(STM_ISR_USART2_POS);
+       stm_nvic_set_priority(STM_ISR_USART2_POS, 4);
+# if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN
+       ao_add_stdio(_ao_serial2_pollchar,
+                    ao_serial2_putchar,
+                    NULL);
+# endif
+#endif
+}
diff --git a/src/stm32l0/ao_spi_stm32l0.c b/src/stm32l0/ao_spi_stm32l0.c
new file mode 100644 (file)
index 0000000..b8831d5
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Copyright Â© 2020 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>
+
+static uint8_t         ao_spi_mutex;
+static uint8_t         ao_spi_pin_config;
+
+#define AO_DMA_SPI1_RX_INDEX   STM_DMA_INDEX(2)
+#define AO_DMA_SPI1_RX_CSELR   STM_DMA_CSELR_C2S_SPI1_RX
+#define AO_DMA_SPI1_TX_INDEX   STM_DMA_INDEX(3)
+#define AO_DMA_SPI1_TX_CSELR   STM_DMA_CSELR_C3S_SPI1_TX
+
+#if 0
+static uint8_t spi_dev_null;
+
+static void
+ao_spi_set_dma_mosi(uint8_t id, const void *data, uint16_t len, uint32_t minc)
+{
+       (void) id;
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       ao_dma_set_transfer(AO_DMA_SPI1_TX_INDEX,
+                           &stm_spi->dr,
+                           (void *) data,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (minc << STM_DMA_CCR_MINC) |
+                           (0 << STM_DMA_CCR_PINC) |
+                           (0 << STM_DMA_CCR_CIRC) |
+                           (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
+}
+
+static void
+ao_spi_set_dma_miso(uint8_t id, void *data, uint16_t len, uint32_t minc)
+{
+       (void) id;
+       uint8_t miso_dma_index = STM_DMA_INDEX(2);
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       ao_dma_set_transfer(miso_dma_index,
+                           &stm_spi->dr,
+                           data,
+                           len,
+                           (0 << STM_DMA_CCR_MEM2MEM) |
+                           (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
+                           (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+                           (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+                           (minc << 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));
+}
+
+static void
+ao_spi_run(uint8_t id, uint8_t which, uint16_t len)
+{
+       (void) id;
+       uint8_t mosi_dma_index = STM_DMA_INDEX(3);
+       uint8_t miso_dma_index = STM_DMA_INDEX(2);
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (1 << STM_SPI_CR2_TXDMAEN) |
+                       (1 << STM_SPI_CR2_RXDMAEN));
+
+       ao_dma_start(miso_dma_index);
+       ao_dma_start(mosi_dma_index);
+
+       ao_arch_critical(
+               while (!ao_dma_done[miso_dma_index])
+                       ao_sleep(&ao_dma_done[miso_dma_index]);
+               );
+
+       while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
+       while (stm_spi->sr & (1 << STM_SPI_SR_BSY));
+
+       stm_spi->cr2 = 0;
+
+       ao_dma_done_transfer(mosi_dma_index);
+       ao_dma_done_transfer(miso_dma_index);
+}
+#endif
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
+{
+       (void) spi_index;
+#if 0
+       /* Set up the transmit DMA to deliver data */
+       ao_spi_set_dma_mosi(id, block, len, 1);
+
+       /* Set up the receive DMA -- when this is done, we know the SPI unit
+        * is idle. Without this, we'd have to poll waiting for the BSY bit to
+        * be cleared
+        */
+       ao_spi_set_dma_miso(id, &spi_dev_null, len, 0);
+
+       ao_spi_run(id, 1, len);
+#else
+       const uint8_t *bytes = block;
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       while (len--) {
+               while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
+               stm_spi->dr = *bytes++;
+               while ((stm_spi->sr & (1 << STM_SPI_SR_RXNE)) == 0);
+               (void) stm_spi->dr;
+       }
+#endif
+}
+
+#if 0
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+       uint8_t id = AO_SPI_INDEX(spi_index);
+
+       /* Set up the transmit DMA to deliver data */
+       ao_spi_set_dma_mosi(id, &value, len, 0);
+
+       /* Set up the receive DMA -- when this is done, we know the SPI unit
+        * is idle. Without this, we'd have to poll waiting for the BSY bit to
+        * be cleared
+        */
+       ao_spi_set_dma_miso(id, &spi_dev_null, len, 0);
+
+       ao_spi_run(id, 3, len);
+}
+
+void
+ao_spi_start_bytes(uint8_t spi_index)
+{
+       (void) spi_index;
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (0 << STM_SPI_CR2_TXDMAEN) |
+                       (0 << STM_SPI_CR2_RXDMAEN));
+}
+
+void
+ao_spi_stop_bytes(uint8_t spi_index)
+{
+       (void) spi_index;
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+               ;
+       while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+               ;
+       /* Clear the OVR flag */
+       (void) stm_spi->dr;
+       (void) stm_spi->sr;
+       stm_spi->cr2 = 0;
+}
+
+void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
+{
+       (void) spi_index;
+       const uint8_t   *b = block;
+       struct stm_spi  *stm_spi = &stm_spi1;
+
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (0 << STM_SPI_CR2_TXDMAEN) |
+                       (0 << STM_SPI_CR2_RXDMAEN));
+       while (len--) {
+               while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+               stm_spi->dr = *b++;
+       }
+       while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+               ;
+       while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+               ;
+       /* Clear the OVR flag */
+       (void) stm_spi->dr;
+       (void) stm_spi->sr;
+}
+#endif
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
+{
+       (void) spi_index;
+#if 0
+
+       spi_dev_null = 0xff;
+
+       /* Set up transmit DMA to make the SPI hardware actually run */
+       ao_spi_set_dma_mosi(id, &spi_dev_null, len, 0);
+
+       /* Set up the receive DMA to capture data */
+       ao_spi_set_dma_miso(id, block, len, 1);
+
+       ao_spi_run(id, 9, len);
+#else
+       uint8_t *bytes = block;
+       struct stm_spi *stm_spi = &stm_spi1;
+
+       while (len--) {
+               while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
+               stm_spi->dr = 0xff;
+               while ((stm_spi->sr & (1 << STM_SPI_SR_RXNE)) == 0);
+               *bytes++ = stm_spi->dr;
+       }
+#endif
+}
+
+#if 0
+void
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+
+       /* Set up transmit DMA to send data */
+       ao_spi_set_dma_mosi(id, out, len, 1);
+
+       /* Set up the receive DMA to capture data */
+       ao_spi_set_dma_miso(id, in, len, 1);
+
+       ao_spi_run(id, 11, len);
+}
+#endif
+
+static void
+ao_spi_disable_pin_config(uint8_t spi_pin_config)
+{
+       /* Disable current config
+        */
+       switch (spi_pin_config) {
+       case AO_SPI_1_PA5_PA6_PA7:
+               stm_gpio_set(&stm_gpioa, 5, 1);
+               stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+               stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+               stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
+               break;
+       case AO_SPI_1_PA12_PA13_PA14:
+               stm_gpio_set(&stm_gpioa, 13, 1);
+               stm_moder_set(&stm_gpioa, 13, STM_MODER_OUTPUT);        /* clk */
+               stm_moder_set(&stm_gpioa, 12, STM_MODER_OUTPUT);        /* mosi */
+               stm_moder_set(&stm_gpioa, 14, STM_MODER_INPUT);         /* miso */
+               break;
+       case AO_SPI_1_PB3_PB4_PB5:
+               stm_gpio_set(&stm_gpiob, 3, 1);
+               stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+               stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+               stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+               break;
+       }
+}
+
+static void
+ao_spi_enable_pin_config(uint8_t spi_pin_config)
+{
+       /* Enable new config
+        */
+       switch (spi_pin_config) {
+       case AO_SPI_1_PA5_PA6_PA7:
+               stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0);
+               stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0);
+               stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0);
+               break;
+       case AO_SPI_1_PA12_PA13_PA14:
+               stm_afr_set(&stm_gpioe, 12, STM_AFR_AF0);       /* yes, AF0 */
+               stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
+               stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
+               break;
+       case AO_SPI_1_PB3_PB4_PB5:
+               stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0);
+               stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0);
+               stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0);
+               break;
+       }
+}
+
+static void
+ao_spi_config(uint8_t spi_index, uint32_t speed)
+{
+       uint8_t         spi_pin_config = AO_SPI_PIN_CONFIG(spi_index);
+       struct stm_spi  *stm_spi = &stm_spi1;
+
+       if (spi_pin_config != ao_spi_pin_config) {
+
+               /* Disable old config
+                */
+               ao_spi_disable_pin_config(ao_spi_pin_config);
+
+               /* Enable new config
+                */
+               ao_spi_enable_pin_config(spi_pin_config);
+
+               /* Remember current config
+                */
+               ao_spi_pin_config = spi_pin_config;
+       }
+
+       /* Turn the SPI transceiver on and set the mode */
+       stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |           /* Three wire mode */
+                       (0 << STM_SPI_CR1_BIDIOE) |
+                       (0 << STM_SPI_CR1_CRCEN) |              /* CRC disabled */
+                       (0 << STM_SPI_CR1_CRCNEXT) |
+                       (0 << STM_SPI_CR1_DFF) |
+                       (0 << STM_SPI_CR1_RXONLY) |
+                       (1 << STM_SPI_CR1_SSM) |                /* Software SS handling */
+                       (1 << STM_SPI_CR1_SSI) |                /*  ... */
+                       (0 << STM_SPI_CR1_LSBFIRST) |           /* Big endian */
+                       (1 << STM_SPI_CR1_SPE) |                /* Enable SPI unit */
+                       (speed << STM_SPI_CR1_BR) |             /* baud rate to pclk/4 */
+                       (1 << STM_SPI_CR1_MSTR) |
+                       (AO_SPI_CPOL(spi_index) << STM_SPI_CR1_CPOL) |  /* Format */
+                       (AO_SPI_CPHA(spi_index) << STM_SPI_CR1_CPHA));
+}
+
+#if HAS_TASK
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
+{
+       uint8_t         id = AO_SPI_INDEX(spi_index);
+
+       if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
+               return 0;
+       ao_spi_config(spi_index, speed);
+       return 1;
+}
+#endif
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
+{
+       (void) spi_index;
+
+       ao_mutex_get(&ao_spi_mutex);
+       ao_spi_config(spi_index, speed);
+}
+
+void
+ao_spi_put(uint8_t spi_index)
+{
+       (void) spi_index;
+       struct stm_spi  *stm_spi = &stm_spi1;
+
+       stm_spi->cr1 = 0;
+       ao_mutex_put(&ao_spi_mutex);
+}
+
+static void
+ao_spi_channel_init(uint8_t spi_index)
+{
+       (void) spi_index;
+       struct stm_spi  *stm_spi = &stm_spi1;
+
+       ao_spi_disable_pin_config(AO_SPI_PIN_CONFIG(spi_index));
+
+       stm_spi->cr1 = 0;
+       stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+                       (0 << STM_SPI_CR2_RXNEIE) |
+                       (0 << STM_SPI_CR2_ERRIE) |
+                       (0 << STM_SPI_CR2_SSOE) |
+                       (0 << STM_SPI_CR2_TXDMAEN) |
+                       (0 << STM_SPI_CR2_RXDMAEN));
+
+       /* Clear any pending data and error flags */
+       (void) stm_spi->dr;
+       (void) stm_spi->sr;
+}
+
+#if DEBUG
+void
+ao_spi_dump_cmd(void)
+{
+       int s;
+
+       for (s = 0; s < 64; s++) {
+               int i = (spi_task_index + s) & 63;
+               if (spi_tasks[i].which) {
+                       int t;
+                       const char *name = "(none)";
+                       for (t = 0; t < ao_num_tasks; t++)
+                               if (ao_tasks[t]->task_id == spi_tasks[i].task) {
+                                       name = ao_tasks[t]->name;
+                                       break;
+                               }
+                       printf("%2d: %5d task %2d which %2d len %5d %s\n",
+                              s,
+                              spi_tasks[i].tick,
+                              spi_tasks[i].task,
+                              spi_tasks[i].which,
+                              spi_tasks[i].len,
+                              name);
+               }
+       }
+       for (s = 0; s < STM_NUM_SPI; s++) {
+               struct stm_spi *spi = ao_spi_stm_info[s].stm_spi;
+
+               printf("%1d: mutex %2d index %3d miso dma %3d mosi dma %3d",
+                      s, ao_spi_mutex[s], ao_spi_index[s],
+                      ao_spi_stm_info[s].miso_dma_index,
+                      ao_spi_stm_info[s].mosi_dma_index);
+               printf(" cr1 %04x cr2 %02x sr %03x\n",
+                      spi->cr1, spi->cr2, spi->sr);
+       }
+
+}
+
+static const struct ao_cmds ao_spi_cmds[] = {
+       { ao_spi_dump_cmd,      "S\0Dump SPI status" },
+       { 0, NULL }
+};
+#endif
+
+void
+ao_spi_init(void)
+{
+#if HAS_SPI_1
+# if SPI_1_PA5_PA6_PA7
+       ao_enable_port(&stm_gpioa);
+       stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
+# endif
+# if SPI_1_PB3_PB4_PB5
+       ao_enable_port(&stm_gpiob);
+       stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
+# endif
+# if SPI_1_PE13_PE14_PE15
+       ao_enable_port(&stm_gpioe);
+       stm_ospeedr_set(&stm_gpioe, 13, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpioe, 14, SPI_1_OSPEEDR);
+       stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR);
+# endif
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
+       ao_spi_pin_config = AO_SPI_CONFIG_NONE;
+       ao_spi_channel_init(0);
+#if 0
+       ao_dma_alloc(AO_DMA_SPI1_RX_INDEX, AO_DMA_SPI1_RX_CSELR);
+       ao_dma_alloc(AO_DMA_SPI1_TX_INDEX, AO_DMA_SPI1_TX_CSELR);
+#endif
+#endif
+
+#if HAS_SPI_2
+# if SPI_2_PB13_PB14_PB15
+       ao_enable_port(&stm_gpiob);
+       stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
+# define HAS_SPI_2_CONFIG 1
+# endif
+# if SPI_2_PD1_PD3_PD4
+       ao_enable_port(&stm_gpiod);
+       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
+       stm_ospeedr_set(&stm_gpiod, 1, SPI_2_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiod, 3, SPI_2_OSPEEDR);
+       stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR);
+# define HAS_SPI_2_CONFIG 1
+# endif
+# ifndef HAS_SPI_2_CONFIG 1
+       #error "no config for SPI2"
+# endif
+       stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+       ao_spi_pin_config[1] = AO_SPI_CONFIG_NONE;
+       ao_spi_channel_init(1);
+       ao_dma_alloc(AO_DMA_SPI2_RX_INDEX, AO_DMA_SPI2_RX_CSELR);
+       ao_dma_alloc(AO_DMA_SPI2_TX_INDEX, AO_DMA_SPI2_TX_CSELR);
+#endif
+#if DEBUG
+       ao_cmd_register(&ao_spi_cmds[0]);
+#endif
+}
diff --git a/src/stm32l0/ao_timer.c b/src/stm32l0/ao_timer.c
new file mode 100644 (file)
index 0000000..8919333
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright Â© 2020 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_task.h>
+#if HAS_FAKE_FLIGHT
+#include <ao_fake_flight.h>
+#endif
+
+#ifndef HAS_TICK
+#define HAS_TICK 1
+#endif
+
+#if HAS_TICK
+volatile AO_TICK_TYPE ao_tick_count;
+
+AO_TICK_TYPE
+ao_time(void)
+{
+       return ao_tick_count;
+}
+
+#if 0
+uint64_t
+ao_time_ns(void)
+{
+       AO_TICK_TYPE    before, after;
+       uint32_t        cvr;
+
+       do {
+               before = ao_tick_count;
+               cvr = stm_systick.cvr;
+               after = ao_tick_count;
+       } while (before != after);
+
+       return (uint64_t) after * (1000000000ULL / AO_HERTZ) +
+               (uint64_t) cvr * (1000000000ULL / AO_SYSTICK);
+}
+#endif
+
+#if AO_DATA_ALL
+volatile uint8_t       ao_data_interval = 1;
+volatile uint8_t       ao_data_count;
+#endif
+
+void stm_systick_isr(void)
+{
+       if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
+               ++ao_tick_count;
+               ao_task_check_alarm();
+#if AO_DATA_ALL
+               if (++ao_data_count == ao_data_interval) {
+                       ao_data_count = 0;
+#if HAS_ADC
+#if HAS_FAKE_FLIGHT
+                       if (ao_fake_flight_active)
+                               ao_fake_flight_poll();
+                       else
+#endif
+                               ao_adc_poll();
+#endif
+#if (AO_DATA_ALL & ~(AO_DATA_ADC))
+                       ao_wakeup((void *) &ao_data_count);
+#endif
+               }
+#endif
+#ifdef AO_TIMER_HOOK
+               AO_TIMER_HOOK;
+#endif
+       }
+}
+
+#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1)
+
+void
+ao_timer_init(void)
+{
+       stm_systick.csr = 0;
+       stm_systick.rvr = SYSTICK_RELOAD;
+       stm_systick.cvr = 0;
+       stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) |
+                          (1 << STM_SYSTICK_CSR_TICKINT) |
+                          (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE));
+}
+
+void
+ao_timer_stop(void)
+{
+       stm_systick.csr = 0;
+}
+
+#endif
diff --git a/src/stm32l0/stm32l0.h b/src/stm32l0/stm32l0.h
new file mode 100644 (file)
index 0000000..90f070c
--- /dev/null
@@ -0,0 +1,2145 @@
+/*
+ * 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 _STM32L0_H_
+#define _STM32L0_H_
+
+#include <stdint.h>
+
+typedef volatile uint32_t      vuint32_t;
+typedef volatile uint16_t      vuint16_t;
+typedef volatile void *                vvoid_t;
+
+struct stm_gpio {
+       vuint32_t       moder;
+       vuint32_t       otyper;
+       vuint32_t       ospeedr;
+       vuint32_t       pupdr;
+
+       vuint32_t       idr;
+       vuint32_t       odr;
+       vuint32_t       bsrr;
+       vuint32_t       lckr;
+
+       vuint32_t       afrl;
+       vuint32_t       afrh;
+       vuint32_t       brr;
+};
+
+#define STM_MODER_SHIFT(pin)           ((pin) << 1)
+#define STM_MODER_MASK                 3
+#define STM_MODER_INPUT                        0
+#define STM_MODER_OUTPUT               1
+#define STM_MODER_ALTERNATE            2
+#define STM_MODER_ANALOG               3
+
+static inline void
+stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+       gpio->moder = ((gpio->moder &
+                       ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) |
+                      value << STM_MODER_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_spread_mask(uint16_t mask) {
+       uint32_t m = mask;
+
+       /* 0000000000000000mmmmmmmmmmmmmmmm */
+       m = (m & 0xff) | ((m & 0xff00) << 8);
+       /* 00000000mmmmmmmm00000000mmmmmmmm */
+       m = (m & 0x000f000f) | ((m & 0x00f000f0) << 4);
+       /* 0000mmmm0000mmmm0000mmmm0000mmmm */
+       m = (m & 0x03030303) | ((m & 0x0c0c0c0c) << 2);
+       /* 00mm00mm00mm00mm00mm00mm00mm00mm */
+       m = (m & 0x11111111) | ((m & 0x22222222) << 2);
+       /* 0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m */
+       return m;
+}
+
+static inline void
+stm_moder_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) {
+       uint32_t        bits32 = stm_spread_mask(mask);
+       uint32_t        mask32 = 3 * bits32;
+       uint32_t        value32 = (value & 3) * bits32;
+
+       gpio->moder = ((gpio->moder & ~mask32) | value32);
+}
+
+static inline uint32_t
+stm_moder_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK;
+}
+
+#define STM_OTYPER_SHIFT(pin)          (pin)
+#define STM_OTYPER_MASK                        1
+#define STM_OTYPER_PUSH_PULL           0
+#define STM_OTYPER_OPEN_DRAIN          1
+
+static inline void
+stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+       gpio->otyper = ((gpio->otyper &
+                        ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) |
+                       value << STM_OTYPER_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_otyper_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK;
+}
+
+#define STM_OSPEEDR_SHIFT(pin)         ((pin) << 1)
+#define STM_OSPEEDR_MASK               3
+#define STM_OSPEEDR_LOW                        0
+#define STM_OSPEEDR_MEDIUM             1
+#define STM_OSPEEDR_HIGH               2
+#define STM_OSPEEDR_VERY_HIGH          3
+
+static inline void
+stm_ospeedr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+       gpio->ospeedr = ((gpio->ospeedr &
+                       ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) |
+                      value << STM_OSPEEDR_SHIFT(pin));
+}
+
+static inline void
+stm_ospeedr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) {
+       uint32_t        bits32 = stm_spread_mask(mask);
+       uint32_t        mask32 = 3 * bits32;
+       uint32_t        value32 = (value & 3) * bits32;
+
+       gpio->ospeedr = ((gpio->ospeedr & ~mask32) | value32);
+}
+
+static inline uint32_t
+stm_ospeedr_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK;
+}
+
+#define STM_PUPDR_SHIFT(pin)           ((pin) << 1)
+#define STM_PUPDR_MASK                 3
+#define STM_PUPDR_NONE                 0
+#define STM_PUPDR_PULL_UP              1
+#define STM_PUPDR_PULL_DOWN            2
+#define STM_PUPDR_RESERVED             3
+
+static inline void
+stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+       gpio->pupdr = ((gpio->pupdr &
+                       ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) |
+                      value << STM_PUPDR_SHIFT(pin));
+}
+
+static inline void
+stm_pupdr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) {
+       uint32_t        bits32 = stm_spread_mask(mask);
+       uint32_t        mask32 = 3 * bits32;
+       uint32_t        value32 = (value & 3) * bits32;
+
+       gpio->pupdr = (gpio->pupdr & ~mask32) | value32;
+}
+
+static inline uint32_t
+stm_pupdr_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK;
+}
+
+#define STM_AFR_SHIFT(pin)             ((pin) << 2)
+#define STM_AFR_MASK                   0xf
+#define STM_AFR_AF0                    0x0
+#define STM_AFR_AF1                    0x1
+#define STM_AFR_AF2                    0x2
+#define STM_AFR_AF3                    0x3
+#define STM_AFR_AF4                    0x4
+#define STM_AFR_AF5                    0x5
+#define STM_AFR_AF6                    0x6
+#define STM_AFR_AF7                    0x7
+#define STM_AFR_AF8                    0x8
+#define STM_AFR_AF9                    0x9
+#define STM_AFR_AF10                   0xa
+#define STM_AFR_AF11                   0xb
+#define STM_AFR_AF12                   0xc
+#define STM_AFR_AF13                   0xd
+#define STM_AFR_AF14                   0xe
+#define STM_AFR_AF15                   0xf
+
+static inline void
+stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+       /*
+        * Set alternate pin mode too
+        */
+       stm_moder_set(gpio, pin, STM_MODER_ALTERNATE);
+       if (pin < 8)
+               gpio->afrl = ((gpio->afrl &
+                              ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) |
+                             value << STM_AFR_SHIFT(pin));
+       else {
+               pin -= 8;
+               gpio->afrh = ((gpio->afrh &
+                              ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) |
+                             value << STM_AFR_SHIFT(pin));
+       }
+}
+       
+static inline uint32_t
+stm_afr_get(struct stm_gpio *gpio, int pin) {
+       if (pin < 8)
+               return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK;
+       else {
+               pin -= 8;
+               return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK;
+       }
+}
+
+static inline void
+stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {
+       /* Use the bit set/reset register to do this atomically */
+       gpio->bsrr = value ? (1 << pin) : (1 << (pin + 16));
+}
+
+static inline void
+stm_gpio_set_mask(struct stm_gpio *gpio, uint16_t bits, uint16_t mask) {
+       /* Use the bit set/reset register to do this atomically */
+       gpio->bsrr = ((uint32_t) (~bits & mask) << 16) | ((uint32_t) (bits & mask));
+}
+
+static inline void
+stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) {
+       gpio->bsrr = bits;
+}
+
+static inline void
+stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) {
+       gpio->bsrr = ((uint32_t) bits) << 16;
+}
+
+static inline uint8_t
+stm_gpio_get(struct stm_gpio *gpio, int pin) {
+       return (gpio->idr >> pin) & 1;
+}
+
+static inline uint16_t
+stm_gpio_get_all(struct stm_gpio *gpio) {
+       return gpio->idr;
+}
+
+/*
+ * We can't define these in registers.ld or our fancy
+ * ao_enable_gpio macro will expand into a huge pile of code
+ * as the compiler won't do correct constant folding and
+ * dead-code elimination
+ */
+
+extern struct stm_gpio stm_gpioa;
+extern struct stm_gpio stm_gpiob;
+extern struct stm_gpio stm_gpioc;
+extern struct stm_gpio stm_gpiod;
+extern struct stm_gpio stm_gpioe;
+extern struct stm_gpio stm_gpioh;
+
+#define stm_gpiob  (*((struct stm_gpio *) 0x50000400))
+#define stm_gpioa  (*((struct stm_gpio *) 0x50000000))
+
+struct stm_usart {
+       vuint32_t       cr1;    /* control register 1 */
+       vuint32_t       cr2;    /* control register 2 */
+       vuint32_t       cr3;    /* control register 3 */
+       vuint32_t       brr;    /* baud rate register */
+
+       vuint32_t       gtpr;   /* guard time and prescaler */
+       vuint32_t       rtor;   /* receiver timeout register */
+       vuint32_t       rqr;    /* request register */
+       vuint32_t       isr;    /* interrupt and status register */
+
+       vuint32_t       icr;    /* interrupt flag clear register */
+       vuint32_t       rdr;    /* receive data register */
+       vuint32_t       tdr;    /* transmit data register */
+};
+
+#define STM_USART_CR1_M1       28
+#define STM_USART_CR1_EOBIE    27
+#define STM_USART_CR1_RTOIE    26
+#define STM_USART_CR1_DEAT     21
+#define STM_USART_CR1_DEDT     16
+#define STM_USART_CR1_OVER8    15
+#define STM_USART_CR1_CMIE     14
+#define STM_USART_CR1_MME      13
+#define STM_USART_CR1_M0       12
+#define STM_USART_CR1_WAKE     11
+#define STM_USART_CR1_PCE      10
+#define STM_USART_CR1_PS       9
+#define STM_USART_CR1_PEIE     8
+#define STM_USART_CR1_TXEIE    7
+#define STM_USART_CR1_TCIE     6
+#define STM_USART_CR1_RXNEIE   5
+#define STM_USART_CR1_IDLEIE   4
+#define STM_USART_CR1_TE       3
+#define STM_USART_CR1_RE       2
+#define STM_USART_CR1_UESM     1
+#define STM_USART_CR1_UE       0
+
+#define STM_USART_CR2_ADD      24
+#define STM_USART_CR2_RTOEN    23
+#define STM_USART_CR2_ABRMOD   21
+#define STM_USART_CR2_ABREN    20
+#define STM_USART_CR2_MSBFIRST 19
+#define STM_USART_CR2_DATAINV  18
+#define STM_USART_CR2_TXINV    17
+#define STM_USART_CR2_RXINV    16
+#define STM_USART_CR2_SWAP     15
+#define STM_USART_CR2_LINEN    14
+#define STM_USART_CR2_STOP     12
+#define STM_USART_CR2_CLKEN    11
+#define STM_USART_CR2_CPOL     10
+#define STM_USART_CR2_CHPA     9
+#define STM_USART_CR2_LBCL     8
+#define STM_USART_CR2_LBDIE    6
+#define STM_USART_CR2_LBDL     5
+#define STM_USART_CR2_ADDM7    4
+
+#define STM_USART_CR3_WUFIE    22
+#define STM_USART_CR3_WUS      20
+#define STM_USART_CR3_SCARCNT  17
+#define STM_USART_CR3_DEP      15
+#define STM_USART_CR3_DEM      14
+#define STM_USART_CR3_DDRE     13
+#define STM_USART_CR3_OVRDIS   12
+#define STM_USART_CR3_ONEBIT   11
+#define STM_USART_CR3_CTIIE    10
+#define STM_USART_CR3_CTSE     9
+#define STM_USART_CR3_RTSE     8
+#define STM_USART_CR3_DMAT     7
+#define STM_USART_CR3_DMAR     6
+#define STM_USART_CR3_SCEN     5
+#define STM_USART_CR3_NACK     4
+#define STM_USART_CR3_HDSEL    3
+#define STM_USART_CR3_IRLP     2
+#define STM_USART_CR3_IREN     1
+#define STM_USART_CR3_EIE      0
+
+#define STM_USART_GTPR_GT      8
+#define STM_USART_GTPR_PSC     0
+
+#define STM_USART_RQR_TXFRQ    4
+#define STM_USART_RQR_RXFRQ    3
+#define STM_USART_RQR_MMRQ     2
+#define STM_USART_RQR_SBKRQ    1
+#define STM_USART_RQR_ABRRQ    0
+
+#define STM_USART_ISR_REACK    22
+#define STM_USART_ISR_TEACK    21
+#define STM_USART_ISR_WUF      20
+#define STM_USART_ISR_RWU      19
+#define STM_USART_ISR_SBKF     18
+#define STM_USART_ISR_CMF      17
+#define STM_USART_ISR_BUSY     16
+#define STM_USART_ISR_ABRF     15
+#define STM_USART_ISR_ABRE     14
+#define STM_USART_ISR_EOBF     12
+#define STM_USART_ISR_RTOF     11
+#define STM_USART_ISR_CTS      10
+#define STM_USART_ISR_CTSIF    9
+#define STM_USART_ISR_LBDF     8
+#define STM_USART_ISR_TXE      7
+#define STM_USART_ISR_TC       6
+#define STM_USART_ISR_RXNE     5
+#define STM_USART_ISR_IDLE     4
+#define STM_USART_ISR_ORE      3
+#define STM_USART_ISR_NF       2
+#define STM_USART_ISR_FE       1
+#define STM_USART_ISR_PE       0
+
+#define STM_USART_ICR_WUCF     20
+#define STM_USART_ICR_CMCF     17
+#define STM_USART_ICR_EOBCF    12
+#define STM_USART_ICR_RTOCF    11
+#define STM_USART_ICR_CTSCF    9
+#define STM_USART_ICR_LBDCF    8
+#define STM_USART_ICR_TCCF     6
+#define STM_USART_ICR_IDLECF   4
+#define STM_USART_ICR_ORECF    3
+#define STM_USART_ICR_NCF      2
+#define STM_USART_ICR_FECF     1
+#define STM_USART_ICR_PECF     0
+
+extern struct stm_usart        stm_usart1;
+extern struct stm_usart stm_usart2;
+#define stm_usart1 (*((struct stm_usart *) 0x40013800))
+#define stm_usart2 (*((struct stm_usart *) 0x40004400))
+
+struct stm_lpuart {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       cr3;
+       vuint32_t       brr;
+
+       uint32_t        unused_10;
+       uint32_t        unused_14;
+       vuint32_t       rqr;
+       vuint32_t       isr;
+
+       vuint32_t       icr;
+       vuint32_t       rdr;
+       vuint32_t       tdr;
+};
+extern struct stm_lpuart stm_lpuart1;
+
+#define stm_lpuart1 (*((struct stm_lpuart *) 0x40004800))
+
+#define STM_LPUART_CR1_M1      28
+#define STM_LPUART_CR1_DEAT    21
+#define STM_LPUART_CR1_DEDT    16
+#define STM_LPUART_CR1_CMIE    14
+#define STM_LPUART_CR1_MME     13
+#define STM_LPUART_CR1_M0      12
+#define STM_LPUART_CR1_WAKE    11
+#define STM_LPUART_CR1_PCE     10
+#define STM_LPUART_CR1_PS      9
+#define STM_LPUART_CR1_PEIE    8
+#define STM_LPUART_CR1_TXEIE   7
+#define STM_LPUART_CR1_TCIE    6
+#define STM_LPUART_CR1_RXNEIE  5
+#define STM_LPUART_CR1_IDLEIE  4
+#define STM_LPUART_CR1_TE      3
+#define STM_LPUART_CR1_RE      2
+#define STM_LPUART_CR1_UESM    1
+#define STM_LPUART_CR1_UE      0
+
+#define STM_LPUART_CR2_ADD     24
+#define STM_LPUART_CR2_MSBFIRST        19
+#define STM_LPUART_CR2_DATAINV 18
+#define STM_LPUART_CR2_TXINV   17
+#define STM_LPUART_CR2_RXINV   16
+#define STM_LPUART_CR2_SWAP    15
+#define STM_LPUART_CR2_STOP    12
+#define STM_LPUART_CR2_ADDM7   4
+
+#define STM_LPUART_CR3_UCESM   23
+#define STM_LPUART_CR3_WUFIE   22
+#define STM_LPUART_CR3_WUS     20
+#define STM_LPUART_CR3_DEP     15
+#define STM_LPUART_CR3_DEM     14
+#define STM_LPUART_CR3_DDRE    13
+#define STM_LPUART_CR3_OVRDIS  12
+#define STM_LPUART_CR3_CTSIE   10
+#define STM_LPUART_CR3_CTSE    9
+#define STM_LPUART_CR3_RTSE    8
+#define STM_LPUART_CR3_DMAT    7
+#define STM_LPUART_CR3_DMAR    6
+#define STM_LPUART_CR3_HDSEL   3
+#define STM_LPUART_CR3_EIE     0
+
+#define STM_LPUART_RQR_RXFRQ   3
+#define STM_LPUART_RQR_MMRQ    2
+#define STM_LPUART_RQR_SBKRQ   1
+
+#define STM_LPUART_ISR_REACK   22
+#define STM_LPUART_ISR_TEACK   21
+#define STM_LPUART_ISR_WUF     20
+#define STM_LPUART_ISR_RWU     19
+#define STM_LPUART_ISR_SBKF    18
+#define STM_LPUART_ISR_CMF     17
+#define STM_LPUART_ISR_BUSY    16
+#define STM_LPUART_ISR_CTS     10
+#define STM_LPUART_ISR_CTSIF   9
+#define STM_LPUART_ISR_TXE     7
+#define STM_LPUART_ISR_TC      6
+#define STM_LPUART_ISR_RXNE    5
+#define STM_LPUART_ISR_IDLE    4
+#define STM_LPUART_ISR_ORE     3
+#define STM_LPUART_ISR_NF      2
+#define STM_LPUART_ISR_FE      1
+#define STM_LPUART_ISR_PE      1
+
+#define STM_LPUART_ICR_WUCF    20
+#define STM_LPUART_ICR_CMCF    17
+#define STM_LPUART_ICR_CTSCF   9
+#define STM_LPUART_ICR_TCCF    6
+#define STM_LPUART_ICR_IDLECF  4
+#define STM_LPUART_ICR_ORECF   3
+#define STM_LPUART_ICR_NCF     2
+#define STM_LPUART_ICR_FECF    1
+#define STM_LPUART_ICR_PECF    0
+
+struct stm_tim {
+};
+
+extern struct stm_tim stm_tim9;
+
+struct stm_tim1011 {
+       vuint32_t       cr1;
+       uint32_t        unused_4;
+       vuint32_t       smcr;
+       vuint32_t       dier;
+       vuint32_t       sr;
+       vuint32_t       egr;
+       vuint32_t       ccmr1;
+       uint32_t        unused_1c;
+       vuint32_t       ccer;
+       vuint32_t       cnt;
+       vuint32_t       psc;
+       vuint32_t       arr;
+       uint32_t        unused_30;
+       vuint32_t       ccr1;
+       uint32_t        unused_38;
+       uint32_t        unused_3c;
+       uint32_t        unused_40;
+       uint32_t        unused_44;
+       uint32_t        unused_48;
+       uint32_t        unused_4c;
+       vuint32_t       or;
+};
+
+extern struct stm_tim1011 stm_tim10;
+extern struct stm_tim1011 stm_tim11;
+
+#define STM_TIM1011_CR1_CKD    8
+#define  STM_TIM1011_CR1_CKD_1         0
+#define  STM_TIM1011_CR1_CKD_2         1
+#define  STM_TIM1011_CR1_CKD_4         2
+#define  STM_TIM1011_CR1_CKD_MASK      3
+#define STM_TIM1011_CR1_ARPE   7
+#define STM_TIM1011_CR1_URS    2
+#define STM_TIM1011_CR1_UDIS   1
+#define STM_TIM1011_CR1_CEN    0
+
+#define STM_TIM1011_SMCR_ETP   15
+#define STM_TIM1011_SMCR_ECE   14
+#define STM_TIM1011_SMCR_ETPS  12
+#define  STM_TIM1011_SMCR_ETPS_OFF     0
+#define  STM_TIM1011_SMCR_ETPS_2       1
+#define  STM_TIM1011_SMCR_ETPS_4       2
+#define  STM_TIM1011_SMCR_ETPS_8       3
+#define  STM_TIM1011_SMCR_ETPS_MASK    3
+#define STM_TIM1011_SMCR_ETF   8
+#define  STM_TIM1011_SMCR_ETF_NONE             0
+#define  STM_TIM1011_SMCR_ETF_CK_INT_2         1
+#define  STM_TIM1011_SMCR_ETF_CK_INT_4         2
+#define  STM_TIM1011_SMCR_ETF_CK_INT_8         3
+#define  STM_TIM1011_SMCR_ETF_DTS_2_6          4
+#define  STM_TIM1011_SMCR_ETF_DTS_2_8          5
+#define  STM_TIM1011_SMCR_ETF_DTS_4_6          6
+#define  STM_TIM1011_SMCR_ETF_DTS_4_8          7
+#define  STM_TIM1011_SMCR_ETF_DTS_8_6          8
+#define  STM_TIM1011_SMCR_ETF_DTS_8_8          9
+#define  STM_TIM1011_SMCR_ETF_DTS_16_5         10
+#define  STM_TIM1011_SMCR_ETF_DTS_16_6         11
+#define  STM_TIM1011_SMCR_ETF_DTS_16_8         12
+#define  STM_TIM1011_SMCR_ETF_DTS_32_5         13
+#define  STM_TIM1011_SMCR_ETF_DTS_32_6         14
+#define  STM_TIM1011_SMCR_ETF_DTS_32_8         15
+#define  STM_TIM1011_SMCR_ETF_MASK             15
+
+#define STM_TIM1011_DIER_CC1E  1
+#define STM_TIM1011_DIER_UIE   0
+
+#define STM_TIM1011_SR_CC1OF   9
+#define STM_TIM1011_SR_CC1IF   1
+#define STM_TIM1011_SR_UIF     0
+
+#define STM_TIM1011_EGR_CC1G   1
+#define STM_TIM1011_EGR_UG     0
+
+#define STM_TIM1011_CCMR1_OC1CE        7
+#define STM_TIM1011_CCMR1_OC1M 4
+#define  STM_TIM1011_CCMR1_OC1M_FROZEN                 0
+#define  STM_TIM1011_CCMR1_OC1M_SET_1_ACTIVE_ON_MATCH  1
+#define  STM_TIM1011_CCMR1_OC1M_SET_1_INACTIVE_ON_MATCH        2
+#define  STM_TIM1011_CCMR1_OC1M_TOGGLE                 3
+#define  STM_TIM1011_CCMR1_OC1M_FORCE_INACTIVE         4
+#define  STM_TIM1011_CCMR1_OC1M_FORCE_ACTIVE           5
+#define  STM_TIM1011_CCMR1_OC1M_PWM_MODE_1             6
+#define  STM_TIM1011_CCMR1_OC1M_PWM_MODE_2             7
+#define  STM_TIM1011_CCMR1_OC1M_MASK                   7
+#define STM_TIM1011_CCMR1_OC1PE        3
+#define STM_TIM1011_CCMR1_OC1FE        2
+#define STM_TIM1011_CCMR1_CC1S 0
+#define  STM_TIM1011_CCMR1_CC1S_OUTPUT                 0
+#define  STM_TIM1011_CCMR1_CC1S_INPUT_TI1              1
+#define  STM_TIM1011_CCMR1_CC1S_INPUT_TI2              2
+#define  STM_TIM1011_CCMR1_CC1S_INPUT_TRC              3
+#define  STM_TIM1011_CCMR1_CC1S_MASK                   3
+
+#define  STM_TIM1011_CCMR1_IC1F_NONE           0
+#define  STM_TIM1011_CCMR1_IC1F_CK_INT_2       1
+#define  STM_TIM1011_CCMR1_IC1F_CK_INT_4       2
+#define  STM_TIM1011_CCMR1_IC1F_CK_INT_8       3
+#define  STM_TIM1011_CCMR1_IC1F_DTS_2_6                4
+#define  STM_TIM1011_CCMR1_IC1F_DTS_2_8                5
+#define  STM_TIM1011_CCMR1_IC1F_DTS_4_6                6
+#define  STM_TIM1011_CCMR1_IC1F_DTS_4_8                7
+#define  STM_TIM1011_CCMR1_IC1F_DTS_8_6                8
+#define  STM_TIM1011_CCMR1_IC1F_DTS_8_8                9
+#define  STM_TIM1011_CCMR1_IC1F_DTS_16_5       10
+#define  STM_TIM1011_CCMR1_IC1F_DTS_16_6       11
+#define  STM_TIM1011_CCMR1_IC1F_DTS_16_8       12
+#define  STM_TIM1011_CCMR1_IC1F_DTS_32_5       13
+#define  STM_TIM1011_CCMR1_IC1F_DTS_32_6       14
+#define  STM_TIM1011_CCMR1_IC1F_DTS_32_8       15
+#define  STM_TIM1011_CCMR1_IC1F_MASK           15
+#define STM_TIM1011_CCMR1_IC1PSC       2
+#define  STM_TIM1011_CCMR1_IC1PSC_1            0
+#define  STM_TIM1011_CCMR1_IC1PSC_2            1
+#define  STM_TIM1011_CCMR1_IC1PSC_4            2
+#define  STM_TIM1011_CCMR1_IC1PSC_8            3
+#define  STM_TIM1011_CCMR1_IC1PSC_MASK         3
+#define STM_TIM1011_CCMR1_CC1S         0
+
+#define STM_TIM1011_CCER_CC1NP         3
+#define STM_TIM1011_CCER_CC1P          1
+#define STM_TIM1011_CCER_CC1E          0
+
+#define STM_TIM1011_OR_TI1_RMP_RI      3
+#define STM_TIM1011_ETR_RMP            2
+#define STM_TIM1011_TI1_RMP            0
+#define  STM_TIM1011_TI1_RMP_GPIO              0
+#define  STM_TIM1011_TI1_RMP_LSI               1
+#define  STM_TIM1011_TI1_RMP_LSE               2
+#define  STM_TIM1011_TI1_RMP_RTC               3
+#define  STM_TIM1011_TI1_RMP_MASK              3
+
+struct stm_rcc {
+       vuint32_t       cr;
+       vuint32_t       icscr;
+       uint32_t        unused08;
+       vuint32_t       cfgr;
+
+       vuint32_t       cier;
+       vuint32_t       cifr;
+       vuint32_t       cicr;
+       vuint32_t       iopstr;
+
+       vuint32_t       ahbrstr;
+       vuint32_t       apb2rstr;
+       vuint32_t       apb1rstr;
+       vuint32_t       iopenr;
+
+       vuint32_t       ahbenr;
+       vuint32_t       apb2enr;
+       vuint32_t       apb1enr;
+       vuint32_t       iopsmen;
+
+       vuint32_t       ahbsmenr;
+       vuint32_t       apb2smenr;
+       vuint32_t       apb1smenr;
+       vuint32_t       ccipr;
+
+       vuint32_t       csr;
+};
+
+extern struct stm_rcc stm_rcc;
+
+/* Nominal high speed internal oscillator frequency is 16MHz */
+#define STM_HSI_FREQ           16000000
+#define STM_MSI_FREQ_65536     65536
+#define STM_MSI_FREQ_131072    131072
+#define STM_MSI_FREQ_262144    262144
+#define STM_MSI_FREQ_524288    524288
+#define STM_MSI_FREQ_1048576   1048576
+#define STM_MSI_FREQ_2097152   2097152
+#define STM_MSI_FREQ_4194304   4194304
+
+#define STM_RCC_CR_RTCPRE      (29)
+#define  STM_RCC_CR_RTCPRE_HSE_DIV_2   0
+#define  STM_RCC_CR_RTCPRE_HSE_DIV_4   1
+#define  STM_RCC_CR_RTCPRE_HSE_DIV_8   2
+#define  STM_RCC_CR_RTCPRE_HSE_DIV_16  3
+#define  STM_RCC_CR_RTCPRE_HSE_MASK    3
+
+#define STM_RCC_CR_CSSON       (28)
+#define STM_RCC_CR_PLLRDY      (25)
+#define STM_RCC_CR_PLLON       (24)
+#define STM_RCC_CR_HSEBYP      (18)
+#define STM_RCC_CR_HSERDY      (17)
+#define STM_RCC_CR_HSEON       (16)
+#define STM_RCC_CR_MSIRDY      (9)
+#define STM_RCC_CR_MSION       (8)
+#define STM_RCC_CR_HSIRDY      (1)
+#define STM_RCC_CR_HSION       (0)
+
+#define STM_RCC_ICSCR_HSI16CAL 0
+#define STM_RCC_ICSCR_HSI16TRIM        8
+#define STM_RCC_ICSCR_MSIRANGE 13
+#define  STM_RCC_ICSCR_MSIRANGE_65536  0
+#define  STM_RCC_ICSCR_MSIRANGE_131072
+#define  STM_RCC_ICSCR_MSIRANGE_262144 2
+#define  STM_RCC_ICSCR_MSIRANGE_524288 3
+#define  STM_RCC_ICSCR_MSIRANGE_1048576        4
+#define  STM_RCC_ICSCR_MSIRANGE_2097152        5
+#define  STM_RCC_ICSCR_MSIRANGE_4194304        6
+#define  STM_RCC_ICSCR_MSIRANGE_MASK   0x7
+#define STM_RCC_ICSCR_MSICAL   16
+#define STM_RCC_ICSCR_MSITRIM  24
+
+#define STM_RCC_CFGR_MCOPRE    (28)
+#define  STM_RCC_CFGR_MCOPRE_DIV_1     0
+#define  STM_RCC_CFGR_MCOPRE_DIV_2     1
+#define  STM_RCC_CFGR_MCOPRE_DIV_4     2
+#define  STM_RCC_CFGR_MCOPRE_DIV_8     3
+#define  STM_RCC_CFGR_MCOPRE_DIV_16    4
+#define  STM_RCC_CFGR_MCOPRE_MASK      7
+
+#define STM_RCC_CFGR_MCOSEL    (24)
+#define  STM_RCC_CFGR_MCOSEL_DISABLE   0
+#define  STM_RCC_CFGR_MCOSEL_SYSCLK    1
+#define  STM_RCC_CFGR_MCOSEL_HSI       2
+#define  STM_RCC_CFGR_MCOSEL_MSI       3
+#define  STM_RCC_CFGR_MCOSEL_HSE       4
+#define  STM_RCC_CFGR_MCOSEL_PLL       5
+#define  STM_RCC_CFGR_MCOSEL_LSI       6
+#define  STM_RCC_CFGR_MCOSEL_LSE       7
+#define  STM_RCC_CFGR_MCOSEL_MASK      7
+
+#define STM_RCC_CFGR_PLLDIV    (22)
+#define  STM_RCC_CFGR_PLLDIV_2         1
+#define  STM_RCC_CFGR_PLLDIV_3         2
+#define  STM_RCC_CFGR_PLLDIV_4         3
+#define  STM_RCC_CFGR_PLLDIV_MASK      3
+
+#define STM_RCC_CFGR_PLLMUL    (18)
+#define  STM_RCC_CFGR_PLLMUL_3         0
+#define  STM_RCC_CFGR_PLLMUL_4         1
+#define  STM_RCC_CFGR_PLLMUL_6         2
+#define  STM_RCC_CFGR_PLLMUL_8         3
+#define  STM_RCC_CFGR_PLLMUL_12                4
+#define  STM_RCC_CFGR_PLLMUL_16                5
+#define  STM_RCC_CFGR_PLLMUL_24                6
+#define  STM_RCC_CFGR_PLLMUL_32                7
+#define  STM_RCC_CFGR_PLLMUL_48                8
+#define  STM_RCC_CFGR_PLLMUL_MASK      0xf
+
+#define STM_RCC_CFGR_PLLSRC    (16)
+
+#define STM_RCC_CFGR_PPRE2     (11)
+#define  STM_RCC_CFGR_PPRE2_DIV_1      0
+#define  STM_RCC_CFGR_PPRE2_DIV_2      4
+#define  STM_RCC_CFGR_PPRE2_DIV_4      5
+#define  STM_RCC_CFGR_PPRE2_DIV_8      6
+#define  STM_RCC_CFGR_PPRE2_DIV_16     7
+#define  STM_RCC_CFGR_PPRE2_MASK       7
+
+#define STM_RCC_CFGR_PPRE1     (8)
+#define  STM_RCC_CFGR_PPRE1_DIV_1      0
+#define  STM_RCC_CFGR_PPRE1_DIV_2      4
+#define  STM_RCC_CFGR_PPRE1_DIV_4      5
+#define  STM_RCC_CFGR_PPRE1_DIV_8      6
+#define  STM_RCC_CFGR_PPRE1_DIV_16     7
+#define  STM_RCC_CFGR_PPRE1_MASK       7
+
+#define STM_RCC_CFGR_HPRE      (4)
+#define  STM_RCC_CFGR_HPRE_DIV_1       0
+#define  STM_RCC_CFGR_HPRE_DIV_2       8
+#define  STM_RCC_CFGR_HPRE_DIV_4       9
+#define  STM_RCC_CFGR_HPRE_DIV_8       0xa
+#define  STM_RCC_CFGR_HPRE_DIV_16      0xb
+#define  STM_RCC_CFGR_HPRE_DIV_64      0xc
+#define  STM_RCC_CFGR_HPRE_DIV_128     0xd
+#define  STM_RCC_CFGR_HPRE_DIV_256     0xe
+#define  STM_RCC_CFGR_HPRE_DIV_512     0xf
+#define  STM_RCC_CFGR_HPRE_MASK                0xf
+
+#define STM_RCC_CFGR_SWS       (2)
+#define  STM_RCC_CFGR_SWS_MSI          0
+#define  STM_RCC_CFGR_SWS_HSI          1
+#define  STM_RCC_CFGR_SWS_HSE          2
+#define  STM_RCC_CFGR_SWS_PLL          3
+#define  STM_RCC_CFGR_SWS_MASK         3
+
+#define STM_RCC_CFGR_SW                (0)
+#define  STM_RCC_CFGR_SW_MSI           0
+#define  STM_RCC_CFGR_SW_HSI           1
+#define  STM_RCC_CFGR_SW_HSE           2
+#define  STM_RCC_CFGR_SW_PLL           3
+#define  STM_RCC_CFGR_SW_MASK          3
+
+#define STM_RCC_IOPENR_IOPAEN          0
+#define STM_RCC_IOPENR_IOPBEN          1
+#define STM_RCC_IOPENR_IOPCEN          2
+#define STM_RCC_IOPENR_IOPDEN          3
+#define STM_RCC_IOPENR_IOPEEN          4
+#define STM_RCC_IOPENR_IOPHEN          7
+
+#define STM_RCC_AHBENR_DMA1EN          0
+#define STM_RCC_AHBENR_MIFEN           8
+#define STM_RCC_AHBENR_CRCEN           12
+#define STM_RCC_AHBENR_CRYPEN          24
+
+#define STM_RCC_APB2ENR_DBGEN          (22)
+#define STM_RCC_APB2ENR_USART1EN       (14)
+#define STM_RCC_APB2ENR_SPI1EN         (12)
+#define STM_RCC_APB2ENR_ADCEN          (9)
+#define STM_RCC_APB2ENR_FWEN           (7)
+#define STM_RCC_APB2ENR_TIM22EN                (5)
+#define STM_RCC_APB2ENR_TIM21EN                (2)
+#define STM_RCC_APB2ENR_SYSCFGEN       (0)
+
+#define STM_RCC_APB1ENR_LPTIM1EN       31
+#define STM_RCC_APB1ENR_I2C3EN         30
+#define STM_RCC_APB1ENR_PWREN          28
+#define STM_RCC_APB1ENR_I2C2EN         22
+#define STM_RCC_APB1ENR_I2C1EN         21
+#define STM_RCC_APB1ENR_USART5EN       20
+#define STM_RCC_APB1ENR_USART4EN       19
+#define STM_RCC_APB1ENR_LPUART1EN      18
+#define STM_RCC_APB1ENR_USART2EN       17
+#define STM_RCC_APB1ENR_SPI2EN         14
+#define STM_RCC_APB1ENR_WWDGEN         11
+#define STM_RCC_APB1ENR_TIM7EN         5
+#define STM_RCC_APB1ENR_TIM6EN         4
+#define STM_RCC_APB1ENR_TIM3EN         1
+#define STM_RCC_APB1ENR_TIM2EN         0
+
+#define STM_RCC_CCIPR_LPTIM1SEL                18
+#define STM_RCC_CCIPR_I2C3SEL          16
+#define STM_RCC_CCIPR_I2C1SEL          12
+#define STM_RCC_CCIPR_LPUART1SEL       10
+#define  STM_RCC_CCIPR_LPUART1SEL_APB          0
+#define  STM_RCC_CCIPR_LPUART1SEL_SYSTEM       1
+#define  STM_RCC_CCIPR_LPUART1SEL_HSI16                2
+#define  STM_RCC_CCIPR_LPUART1SEL_LSE          3
+#define STM_RCC_CCIPR_USART2SEL                2
+#define STM_RCC_CCIPR_USART1SEL                0
+
+#define STM_RCC_CSR_LPWRRSTF           (31)
+#define STM_RCC_CSR_WWDGRSTF           (30)
+#define STM_RCC_CSR_IWDGRSTF           (29)
+#define STM_RCC_CSR_SFTRSTF            (28)
+#define STM_RCC_CSR_PORRSTF            (27)
+#define STM_RCC_CSR_PINRSTF            (26)
+#define STM_RCC_CSR_OBLRSTF            (25)
+#define STM_RCC_CSR_RMVF               (24)
+#define STM_RCC_CSR_RTFRST             (23)
+#define STM_RCC_CSR_RTCEN              (22)
+#define STM_RCC_CSR_RTCSEL             (16)
+
+#define  STM_RCC_CSR_RTCSEL_NONE               0
+#define  STM_RCC_CSR_RTCSEL_LSE                        1
+#define  STM_RCC_CSR_RTCSEL_LSI                        2
+#define  STM_RCC_CSR_RTCSEL_HSE                        3
+#define  STM_RCC_CSR_RTCSEL_MASK               3
+
+#define STM_RCC_CSR_LSEBYP             (10)
+#define STM_RCC_CSR_LSERDY             (9)
+#define STM_RCC_CSR_LSEON              (8)
+#define STM_RCC_CSR_LSIRDY             (1)
+#define STM_RCC_CSR_LSION              (0)
+
+struct stm_pwr {
+       vuint32_t       cr;
+       vuint32_t       csr;
+};
+
+extern struct stm_pwr stm_pwr;
+
+
+#define STM_PWR_CR_LPDS                16
+#define STM_PWR_CR_LPRUN       14
+#define STM_PWR_CR_DS_EE_KOFF  13
+#define STM_PWR_CR_VOS         11
+#define  STM_PWR_CR_VOS_1_8            1
+#define  STM_PWR_CR_VOS_1_5            2
+#define  STM_PWR_CR_VOS_1_2            3
+#define  STM_PWR_CR_VOS_MASK           3
+#define STM_PWR_CR_FWU         10
+#define STM_PWR_CR_ULP         9
+#define STM_PWR_CR_DBP         8
+#define STM_PWR_CR_PLS         5
+#define  STM_PWR_CR_PLS_1_9    0
+#define  STM_PWR_CR_PLS_2_1    1
+#define  STM_PWR_CR_PLS_2_3    2
+#define  STM_PWR_CR_PLS_2_5    3
+#define  STM_PWR_CR_PLS_2_7    4
+#define  STM_PWR_CR_PLS_2_9    5
+#define  STM_PWR_CR_PLS_3_1    6
+#define  STM_PWR_CR_PLS_EXT    7
+#define  STM_PWR_CR_PLS_MASK   7
+#define STM_PWR_CR_PVDE                4
+#define STM_PWR_CR_CSBF                3
+#define STM_PWR_CR_CWUF                2
+#define STM_PWR_CR_PDDS                1
+#define STM_PWR_CR_LPSDSR      0
+
+#define STM_PWR_CSR_EWUP3      (10)
+#define STM_PWR_CSR_EWUP2      (9)
+#define STM_PWR_CSR_EWUP1      (8)
+#define STM_PWR_CSR_REGLPF     (5)
+#define STM_PWR_CSR_VOSF       (4)
+#define STM_PWR_CSR_VREFINTRDYF        (3)
+#define STM_PWR_CSR_PVDO       (2)
+#define STM_PWR_CSR_SBF                (1)
+#define STM_PWR_CSR_WUF                (0)
+
+struct stm_tim67 {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       uint32_t        _unused_08;
+       vuint32_t       dier;
+
+       vuint32_t       sr;
+       vuint32_t       egr;
+       uint32_t        _unused_18;
+       uint32_t        _unused_1c;
+
+       uint32_t        _unused_20;
+       vuint32_t       cnt;
+       vuint32_t       psc;
+       vuint32_t       arr;
+};
+
+extern struct stm_tim67 stm_tim6;
+
+#define STM_TIM67_CR1_ARPE     (7)
+#define STM_TIM67_CR1_OPM      (3)
+#define STM_TIM67_CR1_URS      (2)
+#define STM_TIM67_CR1_UDIS     (1)
+#define STM_TIM67_CR1_CEN      (0)
+
+#define STM_TIM67_CR2_MMS      (4)
+#define  STM_TIM67_CR2_MMS_RESET       0
+#define  STM_TIM67_CR2_MMS_ENABLE      1
+#define  STM_TIM67_CR2_MMS_UPDATE      2
+#define  STM_TIM67_CR2_MMS_MASK                7
+
+#define STM_TIM67_DIER_UDE     (8)
+#define STM_TIM67_DIER_UIE     (0)
+
+#define STM_TIM67_SR_UIF       (0)
+
+#define STM_TIM67_EGR_UG       (0)
+
+struct stm_lcd {
+       vuint32_t       cr;
+       vuint32_t       fcr;
+       vuint32_t       sr;
+       vuint32_t       clr;
+       uint32_t        unused_0x10;
+       vuint32_t       ram[8*2];
+};
+
+extern struct stm_lcd stm_lcd;
+
+#define STM_LCD_CR_MUX_SEG             (7)
+
+#define STM_LCD_CR_BIAS                        (5)
+#define  STM_LCD_CR_BIAS_1_4           0
+#define  STM_LCD_CR_BIAS_1_2           1
+#define  STM_LCD_CR_BIAS_1_3           2
+#define  STM_LCD_CR_BIAS_MASK          3
+
+#define STM_LCD_CR_DUTY                        (2)
+#define  STM_LCD_CR_DUTY_STATIC                0
+#define  STM_LCD_CR_DUTY_1_2           1
+#define  STM_LCD_CR_DUTY_1_3           2
+#define  STM_LCD_CR_DUTY_1_4           3
+#define  STM_LCD_CR_DUTY_1_8           4
+#define  STM_LCD_CR_DUTY_MASK          7
+
+#define STM_LCD_CR_VSEL                        (1)
+#define STM_LCD_CR_LCDEN               (0)
+
+#define STM_LCD_FCR_PS                 (22)
+#define  STM_LCD_FCR_PS_1              0x0
+#define  STM_LCD_FCR_PS_2              0x1
+#define  STM_LCD_FCR_PS_4              0x2
+#define  STM_LCD_FCR_PS_8              0x3
+#define  STM_LCD_FCR_PS_16             0x4
+#define  STM_LCD_FCR_PS_32             0x5
+#define  STM_LCD_FCR_PS_64             0x6
+#define  STM_LCD_FCR_PS_128            0x7
+#define  STM_LCD_FCR_PS_256            0x8
+#define  STM_LCD_FCR_PS_512            0x9
+#define  STM_LCD_FCR_PS_1024           0xa
+#define  STM_LCD_FCR_PS_2048           0xb
+#define  STM_LCD_FCR_PS_4096           0xc
+#define  STM_LCD_FCR_PS_8192           0xd
+#define  STM_LCD_FCR_PS_16384          0xe
+#define  STM_LCD_FCR_PS_32768          0xf
+#define  STM_LCD_FCR_PS_MASK           0xf
+
+#define STM_LCD_FCR_DIV                        (18)
+#define STM_LCD_FCR_DIV_16             0x0
+#define STM_LCD_FCR_DIV_17             0x1
+#define STM_LCD_FCR_DIV_18             0x2
+#define STM_LCD_FCR_DIV_19             0x3
+#define STM_LCD_FCR_DIV_20             0x4
+#define STM_LCD_FCR_DIV_21             0x5
+#define STM_LCD_FCR_DIV_22             0x6
+#define STM_LCD_FCR_DIV_23             0x7
+#define STM_LCD_FCR_DIV_24             0x8
+#define STM_LCD_FCR_DIV_25             0x9
+#define STM_LCD_FCR_DIV_26             0xa
+#define STM_LCD_FCR_DIV_27             0xb
+#define STM_LCD_FCR_DIV_28             0xc
+#define STM_LCD_FCR_DIV_29             0xd
+#define STM_LCD_FCR_DIV_30             0xe
+#define STM_LCD_FCR_DIV_31             0xf
+#define STM_LCD_FCR_DIV_MASK           0xf
+
+#define STM_LCD_FCR_BLINK              (16)
+#define  STM_LCD_FCR_BLINK_DISABLE             0
+#define  STM_LCD_FCR_BLINK_SEG0_COM0           1
+#define  STM_LCD_FCR_BLINK_SEG0_COMALL         2
+#define  STM_LCD_FCR_BLINK_SEGALL_COMALL       3
+#define  STM_LCD_FCR_BLINK_MASK                        3
+
+#define STM_LCD_FCR_BLINKF             (13)
+#define  STM_LCD_FCR_BLINKF_8                  0
+#define  STM_LCD_FCR_BLINKF_16                 1
+#define  STM_LCD_FCR_BLINKF_32                 2
+#define  STM_LCD_FCR_BLINKF_64                 3
+#define  STM_LCD_FCR_BLINKF_128                        4
+#define  STM_LCD_FCR_BLINKF_256                        5
+#define  STM_LCD_FCR_BLINKF_512                        6
+#define  STM_LCD_FCR_BLINKF_1024               7
+#define  STM_LCD_FCR_BLINKF_MASK               7
+
+#define STM_LCD_FCR_CC                 (10)
+#define  STM_LCD_FCR_CC_MASK                   7
+
+#define STM_LCD_FCR_DEAD               (7)
+#define  STM_LCD_FCR_DEAD_MASK                 7
+
+#define STM_LCD_FCR_PON                        (4)
+#define  STM_LCD_FCR_PON_MASK                  7
+
+#define STM_LCD_FCR_UDDIE              (3)
+#define STM_LCD_FCR_SOFIE              (1)
+#define STM_LCD_FCR_HD                 (0)
+
+#define STM_LCD_SR_FCRSF               (5)
+#define STM_LCD_SR_RDY                 (4)
+#define STM_LCD_SR_UDD                 (3)
+#define STM_LCD_SR_UDR                 (2)
+#define STM_LCD_SR_SOF                 (1)
+#define STM_LCD_SR_ENS                 (0)
+
+#define STM_LCD_CLR_UDDC               (3)
+#define STM_LCD_CLR_SOFC               (1)
+
+/* The SYSTICK starts at 0xe000e010 */
+
+struct stm_systick {
+       vuint32_t       csr;
+       vuint32_t       rvr;
+       vuint32_t       cvr;
+       vuint32_t       calib;
+};
+
+extern struct stm_systick stm_systick;
+
+#define STM_SYSTICK_CSR_ENABLE         0
+#define STM_SYSTICK_CSR_TICKINT                1
+#define STM_SYSTICK_CSR_CLKSOURCE      2
+#define  STM_SYSTICK_CSR_CLKSOURCE_HCLK_8              0
+#define  STM_SYSTICK_CSR_CLKSOURCE_HCLK                        1
+#define STM_SYSTICK_CSR_COUNTFLAG      16
+
+/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */
+
+struct stm_nvic {
+       vuint32_t       iser;           /* 0x000 0xe000e100 Set Enable Register */
+
+       uint8_t         _unused020[0x080 - 0x004];
+
+       vuint32_t       icer;           /* 0x080 0xe000e180 Clear Enable Register */
+
+       uint8_t         _unused0a0[0x100 - 0x084];
+
+       vuint32_t       ispr;           /* 0x100 0xe000e200 Set Pending Register */
+
+       uint8_t         _unused120[0x180 - 0x104];
+
+       vuint32_t       icpr;           /* 0x180 0xe000e280 Clear Pending Register */
+
+       uint8_t         _unused1a0[0x300 - 0x184];
+
+       vuint32_t       ipr[8];         /* 0x300 0xe000e400 Priority Register */
+};
+
+extern struct stm_nvic stm_nvic;
+
+#define IRQ_MASK(irq)  (1 << (irq))
+#define IRQ_BOOL(v,irq)        (((v) >> (irq)) & 1)
+
+static inline void
+stm_nvic_set_enable(int irq) {
+       stm_nvic.iser = IRQ_MASK(irq);
+}
+
+static inline void
+stm_nvic_clear_enable(int irq) {
+       stm_nvic.icer = IRQ_MASK(irq);
+}
+
+static inline int
+stm_nvic_enabled(int irq) {
+       return IRQ_BOOL(stm_nvic.iser, irq);
+}
+
+static inline void
+stm_nvic_set_pending(int irq) {
+       stm_nvic.ispr = IRQ_MASK(irq);
+}
+
+static inline void
+stm_nvic_clear_pending(int irq) {
+       stm_nvic.icpr = IRQ_MASK(irq);
+}
+
+static inline int
+stm_nvic_pending(int irq) {
+       return IRQ_BOOL(stm_nvic.ispr, irq);
+}
+
+#define IRQ_PRIO_REG(irq)      ((irq) >> 2)
+#define IRQ_PRIO_BIT(irq)      (((irq) & 3) << 3)
+#define IRQ_PRIO_MASK(irq)     (0xff << IRQ_PRIO_BIT(irq))
+
+static inline void
+stm_nvic_set_priority(int irq, uint8_t prio) {
+       int             n = IRQ_PRIO_REG(irq);
+       uint32_t        v;
+
+       v = stm_nvic.ipr[n];
+       v &= ~IRQ_PRIO_MASK(irq);
+       v |= (prio) << IRQ_PRIO_BIT(irq);
+       stm_nvic.ipr[n] = v;
+}
+
+static inline uint8_t
+stm_nvic_get_priority(int irq) {
+       return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
+}
+
+struct stm_scb {
+       vuint32_t       cpuid;
+       vuint32_t       icsr;
+       vuint32_t       vtor;
+       vuint32_t       aircr;
+
+       vuint32_t       scr;
+       vuint32_t       ccr;
+       vuint32_t       shpr1;
+       vuint32_t       shpr2;
+
+       vuint32_t       shpr3;
+       vuint32_t       shcrs;
+       vuint32_t       cfsr;
+       vuint32_t       hfsr;
+
+       uint32_t        unused_30;
+       vuint32_t       mmfar;
+       vuint32_t       bfar;
+};
+
+extern struct stm_scb stm_scb;
+
+#define STM_SCB_AIRCR_VECTKEY          16
+#define  STM_SCB_AIRCR_VECTKEY_KEY             0x05fa
+#define STM_SCB_AIRCR_PRIGROUP         8
+#define STM_SCB_AIRCR_SYSRESETREQ      2
+#define STM_SCB_AIRCR_VECTCLRACTIVE    1
+#define STM_SCB_AIRCR_VECTRESET                0
+
+#define STM_SCB_SCR_SVONPEND           4
+#define STM_SCB_SCR_SLEEPDEEP          2
+#define STM_SCB_SCR_SLEEPONEXIT                1
+
+struct stm_mpu {
+       vuint32_t       typer;
+       vuint32_t       cr;
+       vuint32_t       rnr;
+       vuint32_t       rbar;
+
+       vuint32_t       rasr;
+       vuint32_t       rbar_a1;
+       vuint32_t       rasr_a1;
+       vuint32_t       rbar_a2;
+       vuint32_t       rasr_a2;
+       vuint32_t       rbar_a3;
+       vuint32_t       rasr_a3;
+};
+
+extern struct stm_mpu stm_mpu;
+
+#define STM_MPU_TYPER_IREGION  16
+#define  STM_MPU_TYPER_IREGION_MASK    0xff
+#define STM_MPU_TYPER_DREGION  8
+#define  STM_MPU_TYPER_DREGION_MASK    0xff
+#define STM_MPU_TYPER_SEPARATE 0
+
+#define STM_MPU_CR_PRIVDEFENA  2
+#define STM_MPU_CR_HFNMIENA    1
+#define STM_MPU_CR_ENABLE      0
+
+#define STM_MPU_RNR_REGION     0
+#define STM_MPU_RNR_REGION_MASK                0xff
+
+#define STM_MPU_RBAR_ADDR      5
+#define STM_MPU_RBAR_ADDR_MASK         0x7ffffff
+
+#define STM_MPU_RBAR_VALID     4
+#define STM_MPU_RBAR_REGION    0
+#define STM_MPU_RBAR_REGION_MASK       0xf
+
+#define STM_MPU_RASR_XN                28
+#define STM_MPU_RASR_AP                24
+#define  STM_MPU_RASR_AP_NONE_NONE     0
+#define  STM_MPU_RASR_AP_RW_NONE       1
+#define  STM_MPU_RASR_AP_RW_RO         2
+#define  STM_MPU_RASR_AP_RW_RW         3
+#define  STM_MPU_RASR_AP_RO_NONE       5
+#define  STM_MPU_RASR_AP_RO_RO         6
+#define  STM_MPU_RASR_AP_MASK          7
+#define STM_MPU_RASR_TEX       19
+#define  STM_MPU_RASR_TEX_MASK         7
+#define STM_MPU_RASR_S         18
+#define STM_MPU_RASR_C         17
+#define STM_MPU_RASR_B         16
+#define STM_MPU_RASR_SRD       8
+#define  STM_MPU_RASR_SRD_MASK         0xff
+#define STM_MPU_RASR_SIZE      1
+#define  STM_MPU_RASR_SIZE_MASK                0x1f
+#define STM_MPU_RASR_ENABLE    0
+
+#define isr_decl(name) void stm_ ## name ## _isr(void)
+
+isr_decl(halt);
+isr_decl(ignore);
+
+isr_decl(nmi);
+isr_decl(hardfault);
+isr_decl(usagefault);
+isr_decl(svc);
+isr_decl(debugmon);
+isr_decl(pendsv);
+isr_decl(systick);
+isr_decl(wwdg);
+isr_decl(pvd);
+isr_decl(rtc);
+isr_decl(flash);
+isr_decl(rcc_crs);
+isr_decl(exti1_0);
+isr_decl(exti3_2);
+isr_decl(exti15_4);
+isr_decl(dma1_channel1);
+isr_decl(dma1_channel3_2);
+isr_decl(dma1_channel7_4);
+isr_decl(adc_comp);
+isr_decl(lptim1);
+isr_decl(usart4_usart5);
+isr_decl(tim2);
+isr_decl(tim3);
+isr_decl(tim4);
+isr_decl(tim6);
+isr_decl(tim7);
+isr_decl(tim21);
+isr_decl(i2c3);
+isr_decl(tim22);
+isr_decl(i2c1);
+isr_decl(i2c2);
+isr_decl(spi1);
+isr_decl(spi2);
+isr_decl(usart1);
+isr_decl(usart2);
+isr_decl(usart3);
+isr_decl(lpuart1_aes);
+
+#undef isr_decl
+
+#define STM_ISR_WWDG_POS               0
+#define STM_ISR_PVD_POS                        1
+#define STM_ISR_RTC_POS                        2
+#define STM_ISR_FLASH_POS              3
+#define STM_ISR_RCC_CRS_POS            4
+#define STM_ISR_EXTI1_0_POS            5
+#define STM_ISR_EXTI3_2_POS            6
+#define STM_ISR_EXTI15_4_POS           7
+#define STM_ISR_DMA1_CHANNEL1_POS      9
+#define STM_ISR_DMA1_CHANNEL3_2_POS    10
+#define STM_ISR_DMA1_CHANNEL7_4_POS    11
+#define STM_ISR_ADC_COMP_POS           12
+#define STM_ISR_LPTIM1_POS             13
+#define STM_ISR_USART4_USART5_POS      14
+#define STM_ISR_TIM2_POS               15
+#define STM_ISR_TIM3_POS               16
+#define STM_ISR_TIM6_POS               17
+#define STM_ISR_TIM7_POS               18
+#define STM_ISR_TIM21_POS              20
+#define STM_ISR_I2C3_POS               21
+#define STM_ISR_TIM22_POS              22
+#define STM_ISR_I2C1_POS               23
+#define STM_ISR_I2C2_POS               24
+#define STM_ISR_SPI1_POS               25
+#define STM_ISR_SPI2_POS               26
+#define STM_ISR_USART1_POS             27
+#define STM_ISR_USART2_POS             28
+#define STM_ISR_LPUART1_AES_POS                29
+
+struct stm_syscfg {
+       vuint32_t       memrmp;
+       vuint32_t       pmc;
+       vuint32_t       exticr[4];
+};
+
+extern struct stm_syscfg stm_syscfg;
+
+#define STM_SYSCFG_MEMRMP_MEM_MODE     0
+#define  STM_SYSCFG_MEMRMP_MEM_MODE_MAIN_FLASH         0
+#define  STM_SYSCFG_MEMRMP_MEM_MODE_SYSTEM_FLASH       1
+#define  STM_SYSCFG_MEMRMP_MEM_MODE_SRAM               3
+#define  STM_SYSCFG_MEMRMP_MEM_MODE_MASK               3
+
+#define STM_SYSCFG_PMC_USB_PU          0
+
+#define STM_SYSCFG_EXTICR_PA           0
+#define STM_SYSCFG_EXTICR_PB           1
+#define STM_SYSCFG_EXTICR_PC           2
+#define STM_SYSCFG_EXTICR_PD           3
+#define STM_SYSCFG_EXTICR_PE           4
+#define STM_SYSCFG_EXTICR_PH           5
+
+static inline void
+stm_exticr_set(struct stm_gpio *gpio, int pin) {
+       uint8_t reg = pin >> 2;
+       uint8_t shift = (pin & 3) << 2;
+       uint8_t val = 0;
+
+       /* Enable SYSCFG */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN);
+
+       if (gpio == &stm_gpioa)
+               val = STM_SYSCFG_EXTICR_PA;
+       else if (gpio == &stm_gpiob)
+               val = STM_SYSCFG_EXTICR_PB;
+       else if (gpio == &stm_gpioc)
+               val = STM_SYSCFG_EXTICR_PC;
+       else if (gpio == &stm_gpiod)
+               val = STM_SYSCFG_EXTICR_PD;
+       else if (gpio == &stm_gpioe)
+               val = STM_SYSCFG_EXTICR_PE;
+
+       stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
+}
+
+struct stm_dma_channel {
+       vuint32_t       ccr;
+       vuint32_t       cndtr;
+       vvoid_t         cpar;
+       vvoid_t         cmar;
+       vuint32_t       reserved;
+};
+
+#define STM_NUM_DMA    7
+
+struct stm_dma {
+       vuint32_t               isr;
+       vuint32_t               ifcr;
+       struct stm_dma_channel  channel[STM_NUM_DMA];
+       uint8_t                 unused94[0xa8 - 0x94];
+       vuint32_t               cselr;
+};
+
+extern struct stm_dma stm_dma1;
+#define stm_dma1 (*(struct stm_dma *) 0x40020000)
+
+/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh)
+ */
+
+#define STM_DMA_INDEX(channel)         ((channel) - 1)
+
+#define STM_DMA_ISR(index)             ((index) << 2)
+#define STM_DMA_ISR_MASK                       0xf
+#define STM_DMA_ISR_TEIF                       3
+#define STM_DMA_ISR_HTIF                       2
+#define STM_DMA_ISR_TCIF                       1
+#define STM_DMA_ISR_GIF                                0
+
+#define STM_DMA_IFCR(index)            ((index) << 2)
+#define STM_DMA_IFCR_MASK                      0xf
+#define STM_DMA_IFCR_CTEIF                     3
+#define STM_DMA_IFCR_CHTIF                     2
+#define STM_DMA_IFCR_CTCIF                     1
+#define STM_DMA_IFCR_CGIF                      0
+
+#define STM_DMA_CCR_MEM2MEM            (14)
+
+#define STM_DMA_CCR_PL                 (12)
+#define  STM_DMA_CCR_PL_LOW                    (0)
+#define  STM_DMA_CCR_PL_MEDIUM                 (1)
+#define  STM_DMA_CCR_PL_HIGH                   (2)
+#define  STM_DMA_CCR_PL_VERY_HIGH              (3)
+#define  STM_DMA_CCR_PL_MASK                   (3)
+
+#define STM_DMA_CCR_MSIZE              (10)
+#define  STM_DMA_CCR_MSIZE_8                   (0)
+#define  STM_DMA_CCR_MSIZE_16                  (1)
+#define  STM_DMA_CCR_MSIZE_32                  (2)
+#define  STM_DMA_CCR_MSIZE_MASK                        (3)
+
+#define STM_DMA_CCR_PSIZE              (8)
+#define  STM_DMA_CCR_PSIZE_8                   (0)
+#define  STM_DMA_CCR_PSIZE_16                  (1)
+#define  STM_DMA_CCR_PSIZE_32                  (2)
+#define  STM_DMA_CCR_PSIZE_MASK                        (3)
+
+#define STM_DMA_CCR_MINC               (7)
+#define STM_DMA_CCR_PINC               (6)
+#define STM_DMA_CCR_CIRC               (5)
+#define STM_DMA_CCR_DIR                        (4)
+#define  STM_DMA_CCR_DIR_PER_TO_MEM            0
+#define  STM_DMA_CCR_DIR_MEM_TO_PER            1
+#define STM_DMA_CCR_TEIE               (3)
+#define STM_DMA_CCR_HTIE               (2)
+#define STM_DMA_CCR_TCIE               (1)
+#define STM_DMA_CCR_EN                 (0)
+
+#define STM_DMA_CSELR_C7S_SPI2_TX              0x2
+#define STM_DMA_CSELR_C7S_USART2_TX            0x4
+#define STM_DMA_CSELR_C7S_LPUART1_TX           0x5
+#define STM_DMA_CSELR_C7S_I2C1_RX              0x6
+#define STM_DMA_CSELR_C7S_TIM2_CH2_TIM2_CH4    0x8
+#define STM_DMA_CSELR_C7S_USART4_TX            0xc
+#define STM_DMA_CSELR_C7S_USART5_TX            0xd
+
+#define STM_DMA_CSELR_C6S_SPI2_RX              0x2
+#define STM_DMA_CSELR_C6S_USART2_RX            0x4
+#define STM_DMA_CSELR_C6S_LPUART1_RX           0x5
+#define STM_DMA_CSELR_C6S_I2C1_TX              0x6
+#define STM_DMA_CSELR_C6S_TIM3_TRIG            0xa
+#define STM_DMA_CSELR_C6S_USART4_RX            0xc
+#define STM_DMA_CSELR_C6S_USART5_RX            0xd
+
+#define STM_DMA_CSELR_C5S_SPI2_TX              0x2
+#define STM_DMA_CSELR_C5S_USART1_RX            0x3
+#define STM_DMA_CSELR_C5S_USART2_RX            0x4
+#define STM_DMA_CSELR_C5S_I2C2_RX              0x7
+#define STM_DMA_CSELR_C5S_TIM2_CH1             0x8
+#define STM_DMA_CSELR_C5S_TIM3_CH1             0xa
+#define STM_DMA_CSELR_C5S_AES_IN               0xb
+#define STM_DMA_CSELR_C5S_I2C3_RX              0xe
+
+#define STM_DMA_CSELR_C4S_SPI2_RX              0x2
+#define STM_DMA_CSELR_C4S_USART1_TX            0x3
+#define STM_DMA_CSELR_C4S_USART2_TX            0x4
+#define STM_DMA_CSELR_C4S_I2C2_TX              0x7
+#define STM_DMA_CSELR_C4S_TIM2_CH4             0x8
+#define STM_DMA_CSELR_C4S_I2C3_TX              0xe
+#define STM_DMA_CSELR_C4S_TIM7_UP              0xf
+
+#define STM_DMA_CSELR_C3S_SPI1_TX              0x1
+#define STM_DMA_CSELR_C3S_USART1_RX            0x3
+#define STM_DMA_CSELR_C3S_LPUART1_RX           0x5
+#define STM_DMA_CSELR_C3S_I2C1_RX              0x6
+#define STM_DMA_CSELR_C3S_TIM2_CH2             0x8
+#define STM_DMA_CSELR_C3S_TIM4_CH4_TIM4_UP     0xa
+#define STM_DMA_CSELR_C3S_AES_OUT              0xb
+#define STM_DMA_CSELR_C3S_USART4_TX            0xc
+#define STM_DMA_CSELR_C3S_USART5_TX            0xd
+#define STM_DMA_CSELR_C3S_I2C3_RX              0xe
+
+#define STM_DMA_CSELR_C2S_ADC                  0x0
+#define STM_DMA_CSELR_C2S_SPI1_RX              0x1
+#define STM_DMA_CSELR_C2S_USART1_TX            0x3
+#define STM_DMA_CSELR_C2S_LPUART1_TX           0x5
+#define STM_DMA_CSELR_C2S_I2C1_TX              0x6
+#define STM_DMA_CSELR_C2S_TIM2_UP              0x8
+#define STM_DMA_CSELR_C2S_TIM6_UP              0x9
+#define STM_DMA_CSELR_C2S_TIM3_CH3             0xa
+#define STM_DMA_CSELR_C2S_AES_OUT              0xb
+#define STM_DMA_CSELR_C2S_USART4_RX            0xc
+#define STM_DMA_CSELR_C2S_USART5_RX            0xd
+#define STM_DMA_CSELR_C2S_I2C3_TX              0xe
+
+#define STM_DMA_CSELR_C1S_ADC                  0x0
+#define STM_DMA_CSELR_C1S_TIM2_CH3             0x8
+#define STM_DMA_CSELR_C1S_AES_IN               0xb
+
+#define STM_NUM_SPI    1
+
+struct stm_spi {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       sr;
+       vuint32_t       dr;
+       vuint32_t       crcpr;
+       vuint32_t       rxcrcr;
+       vuint32_t       txcrcr;
+};
+
+extern struct stm_spi stm_spi1;
+#define stm_spi1 (*(struct stm_spi *) 0x40013000)
+
+/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh)
+ */
+
+#define STM_SPI_INDEX(channel)         ((channel) - 1)
+
+#define STM_SPI_CR1_BIDIMODE           15
+#define STM_SPI_CR1_BIDIOE             14
+#define STM_SPI_CR1_CRCEN              13
+#define STM_SPI_CR1_CRCNEXT            12
+#define STM_SPI_CR1_DFF                        11
+#define STM_SPI_CR1_RXONLY             10
+#define STM_SPI_CR1_SSM                        9
+#define STM_SPI_CR1_SSI                        8
+#define STM_SPI_CR1_LSBFIRST           7
+#define STM_SPI_CR1_SPE                        6
+#define STM_SPI_CR1_BR                 3
+#define  STM_SPI_CR1_BR_PCLK_2                 0
+#define  STM_SPI_CR1_BR_PCLK_4                 1
+#define  STM_SPI_CR1_BR_PCLK_8                 2
+#define  STM_SPI_CR1_BR_PCLK_16                        3
+#define  STM_SPI_CR1_BR_PCLK_32                        4
+#define  STM_SPI_CR1_BR_PCLK_64                        5
+#define  STM_SPI_CR1_BR_PCLK_128               6
+#define  STM_SPI_CR1_BR_PCLK_256               7
+#define  STM_SPI_CR1_BR_MASK                   7
+
+#define STM_SPI_CR1_MSTR               2
+#define STM_SPI_CR1_CPOL               1
+#define STM_SPI_CR1_CPHA               0
+
+#define STM_SPI_CR2_TXEIE      7
+#define STM_SPI_CR2_RXNEIE     6
+#define STM_SPI_CR2_ERRIE      5
+#define STM_SPI_CR2_SSOE       2
+#define STM_SPI_CR2_TXDMAEN    1
+#define STM_SPI_CR2_RXDMAEN    0
+
+#define STM_SPI_SR_FRE         8
+#define STM_SPI_SR_BSY         7
+#define STM_SPI_SR_OVR         6
+#define STM_SPI_SR_MODF                5
+#define STM_SPI_SR_CRCERR      4
+#define STM_SPI_SR_UDR         3
+#define STM_SPI_SR_CHSIDE      2
+#define STM_SPI_SR_TXE         1
+#define STM_SPI_SR_RXNE                0
+
+struct stm_adc {
+       vuint32_t       isr;
+       vuint32_t       ier;
+       vuint32_t       cr;
+       vuint32_t       cfgr1;
+
+       vuint32_t       cfgr2;
+       vuint32_t       smpr;
+       vuint32_t       r_18;
+       vuint32_t       r_1c;
+
+       vuint32_t       tr;
+       vuint32_t       r_24;
+       vuint32_t       chselr;
+       vuint32_t       r_2c;
+
+       vuint32_t       r_30[4];
+
+       vuint32_t       dr;
+
+       uint8_t         r_44[0xb4 - 0x44];
+
+       vuint32_t       calfact;
+
+       uint8_t         r_b8[0x308 - 0xb8];
+       vuint32_t       ccr;
+};
+
+extern struct stm_adc stm_adc;
+#define stm_adc (*(struct stm_adc *) 0x40012400)
+
+#define STM_ADC_ISR_AWD                7
+#define STM_ADC_ISR_OVR                4
+#define STM_ADC_ISR_EOSEQ      3
+#define STM_ADC_ISR_EOC                2
+#define STM_ADC_ISR_EOSMP      1
+#define STM_ADC_ISR_ADRDY      0
+
+#define STM_ADC_IER_AWDIE      7
+#define STM_ADC_IER_OVRIE      4
+#define STM_ADC_IER_EOSEQIE    3
+#define STM_ADC_IER_EOCIE      2
+#define STM_ADC_IER_EOSMPIE    1
+#define STM_ADC_IER_ADRDYIE    0
+
+#define STM_ADC_CR_ADCAL       31
+#define STM_ADC_CR_ADVREGEN    28
+#define STM_ADC_CR_ADSTP       4
+#define STM_ADC_CR_ADSTART     2
+#define STM_ADC_CR_ADDIS       1
+#define STM_ADC_CR_ADEN                0
+
+#define STM_ADC_CFGR1_AWDCH    26
+#define STM_ADC_CFGR1_AWDEN    23
+#define STM_ADC_CFGR1_AWDSGL   22
+#define STM_ADC_CFGR1_DISCEN   16
+#define STM_ADC_CFGR1_AUTOOFF  15
+#define STM_ADC_CFGR1_WAIT     14
+#define STM_ADC_CFGR1_CONT     13
+#define STM_ADC_CFGR1_OVRMOD   12
+#define STM_ADC_CFGR1_EXTEN    10
+#define  STM_ADC_CFGR1_EXTEN_DISABLE   0
+#define  STM_ADC_CFGR1_EXTEN_RISING    1
+#define  STM_ADC_CFGR1_EXTEN_FALLING   2
+#define  STM_ADC_CFGR1_EXTEN_BOTH      3
+#define  STM_ADC_CFGR1_EXTEN_MASK      3
+
+#define STM_ADC_CFGR1_EXTSEL   6
+#define STM_ADC_CFGR1_ALIGN    5
+#define STM_ADC_CFGR1_RES      3
+#define  STM_ADC_CFGR1_RES_12          0
+#define  STM_ADC_CFGR1_RES_10          1
+#define  STM_ADC_CFGR1_RES_8           2
+#define  STM_ADC_CFGR1_RES_6           3
+#define  STM_ADC_CFGR1_RES_MASK                3
+#define STM_ADC_CFGR1_SCANDIR  2
+#define  STM_ADC_CFGR1_SCANDIR_UP      0
+#define  STM_ADC_CFGR1_SCANDIR_DOWN    1
+#define STM_ADC_CFGR1_DMACFG   1
+#define  STM_ADC_CFGR1_DMACFG_ONESHOT  0
+#define  STM_ADC_CFGR1_DMACFG_CIRCULAR 1
+#define STM_ADC_CFGR1_DMAEN    0
+
+#define STM_ADC_CFGR2_CKMODE   30
+#define  STM_ADC_CFGR2_CKMODE_ADCCLK   0
+#define  STM_ADC_CFGR2_CKMODE_PCLK_2   1
+#define  STM_ADC_CFGR2_CKMODE_PCLK_4   2
+#define  STM_ADC_CFGR2_CKMODE_PCLK     3
+
+#define STM_ADC_SMPR_SMP       0
+#define  STM_ADC_SMPR_SMP_1_5          0
+#define  STM_ADC_SMPR_SMP_7_5          1
+#define  STM_ADC_SMPR_SMP_13_5         2
+#define  STM_ADC_SMPR_SMP_28_5         3
+#define  STM_ADC_SMPR_SMP_41_5         4
+#define  STM_ADC_SMPR_SMP_55_5         5
+#define  STM_ADC_SMPR_SMP_71_5         6
+#define  STM_ADC_SMPR_SMP_239_5                7
+
+#define STM_ADC_TR_HT          16
+#define STM_ADC_TR_LT          0
+
+#define STM_ADC_CCR_LFMEN      25
+#define STM_ADC_CCR_VLCDEN     24
+#define STM_ADC_CCR_TSEN       23
+#define STM_ADC_CCR_VREFEN     22
+#define STM_ADC_CCR_PRESC      18
+
+#define STM_ADC_CHSEL_TEMP     18
+#define STM_ADC_CHSEL_VREF     17
+#define STM_ADC_CHSEL_VLCD     16
+
+struct stm_cal {
+       uint16_t        ts_cal_cold;    /* 30°C */
+       uint16_t        vrefint_cal;
+       uint16_t        unused_c0;
+       uint16_t        ts_cal_hot;     /* 110°C */
+};
+
+extern struct stm_cal  stm_cal;
+
+#define stm_temp_cal_cold      30
+#define stm_temp_cal_hot       110
+
+struct stm_dbg_mcu {
+       uint32_t        idcode;
+};
+
+extern struct stm_dbg_mcu      stm_dbg_mcu;
+
+static inline uint16_t
+stm_dev_id(void) {
+       return stm_dbg_mcu.idcode & 0xfff;
+}
+
+struct stm_flash_size {
+       uint16_t        f_size;
+};
+
+extern struct stm_flash_size   stm_flash_size_reg;
+#define stm_flash_size_reg     (*((struct stm_flash_size *) 0x1ff8007c))
+
+/* Returns flash size in bytes */
+extern uint32_t
+stm_flash_size(void);
+
+struct stm_device_id {
+       char            lot_num_4_6[3];
+       uint8_t         waf_num;
+       char            lot_num_0_3[4];
+       uint8_t         unique_id[4];
+};
+
+extern struct stm_device_id    stm_device_id;
+#define stm_device_id  (*((struct stm_device_id *) 0x1ff80050))
+
+#define STM_NUM_I2C    2
+
+#define STM_I2C_INDEX(channel) ((channel) - 1)
+
+struct stm_i2c {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       oar1;
+       vuint32_t       oar2;
+       vuint32_t       dr;
+       vuint32_t       sr1;
+       vuint32_t       sr2;
+       vuint32_t       ccr;
+       vuint32_t       trise;
+};
+
+extern struct stm_i2c stm_i2c1, stm_i2c2;
+
+#define STM_I2C_CR1_SWRST      15
+#define STM_I2C_CR1_ALERT      13
+#define STM_I2C_CR1_PEC                12
+#define STM_I2C_CR1_POS                11
+#define STM_I2C_CR1_ACK                10
+#define STM_I2C_CR1_STOP       9
+#define STM_I2C_CR1_START      8
+#define STM_I2C_CR1_NOSTRETCH  7
+#define STM_I2C_CR1_ENGC       6
+#define STM_I2C_CR1_ENPEC      5
+#define STM_I2C_CR1_ENARP      4
+#define STM_I2C_CR1_SMBTYPE    3
+#define STM_I2C_CR1_SMBUS      1
+#define STM_I2C_CR1_PE         0
+
+#define STM_I2C_CR2_LAST       12
+#define STM_I2C_CR2_DMAEN      11
+#define STM_I2C_CR2_ITBUFEN    10
+#define STM_I2C_CR2_ITEVTEN    9
+#define STM_I2C_CR2_ITERREN    8
+#define STM_I2C_CR2_FREQ       0
+#define  STM_I2C_CR2_FREQ_2_MHZ                2
+#define  STM_I2C_CR2_FREQ_4_MHZ                4
+#define  STM_I2C_CR2_FREQ_8_MHZ                8
+#define  STM_I2C_CR2_FREQ_16_MHZ       16
+#define  STM_I2C_CR2_FREQ_24_MHZ       24
+#define  STM_I2C_CR2_FREQ_32_MHZ       32
+#define  STM_I2C_CR2_FREQ_MASK         0x3f
+
+#define STM_I2C_SR1_SMBALERT   15
+#define STM_I2C_SR1_TIMEOUT    14
+#define STM_I2C_SR1_PECERR     12
+#define STM_I2C_SR1_OVR                11
+#define STM_I2C_SR1_AF         10
+#define STM_I2C_SR1_ARLO       9
+#define STM_I2C_SR1_BERR       8
+#define STM_I2C_SR1_TXE                7
+#define STM_I2C_SR1_RXNE       6
+#define STM_I2C_SR1_STOPF      4
+#define STM_I2C_SR1_ADD10      3
+#define STM_I2C_SR1_BTF                2
+#define STM_I2C_SR1_ADDR       1
+#define STM_I2C_SR1_SB         0
+
+#define STM_I2C_SR2_PEC                8
+#define  STM_I2C_SR2_PEC_MASK  0xff00
+#define STM_I2C_SR2_DUALF      7
+#define STM_I2C_SR2_SMBHOST    6
+#define STM_I2C_SR2_SMBDEFAULT 5
+#define STM_I2C_SR2_GENCALL    4
+#define STM_I2C_SR2_TRA                2
+#define STM_I2C_SR2_BUSY               1
+#define STM_I2C_SR2_MSL                0
+
+#define STM_I2C_CCR_FS         15
+#define STM_I2C_CCR_DUTY       14
+#define STM_I2C_CCR_CCR                0
+#define  STM_I2C_CCR_MASK      0x7ff
+
+struct stm_tim234 {
+       vuint32_t       cr1;
+       vuint32_t       cr2;
+       vuint32_t       smcr;
+       vuint32_t       dier;
+
+       vuint32_t       sr;
+       vuint32_t       egr;
+       vuint32_t       ccmr1;
+       vuint32_t       ccmr2;
+
+       vuint32_t       ccer;
+       vuint32_t       cnt;
+       vuint32_t       psc;
+       vuint32_t       arr;
+
+       uint32_t        reserved_30;
+       vuint32_t       ccr1;
+       vuint32_t       ccr2;
+       vuint32_t       ccr3;
+
+       vuint32_t       ccr4;
+       uint32_t        reserved_44;
+       vuint32_t       dcr;
+       vuint32_t       dmar;
+
+       uint32_t        reserved_50;
+};
+
+extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
+
+#define STM_TIM234_CR1_CKD     8
+#define  STM_TIM234_CR1_CKD_1          0
+#define  STM_TIM234_CR1_CKD_2          1
+#define  STM_TIM234_CR1_CKD_4          2
+#define  STM_TIM234_CR1_CKD_MASK       3
+#define STM_TIM234_CR1_ARPE    7
+#define STM_TIM234_CR1_CMS     5
+#define  STM_TIM234_CR1_CMS_EDGE       0
+#define  STM_TIM234_CR1_CMS_CENTER_1   1
+#define  STM_TIM234_CR1_CMS_CENTER_2   2
+#define  STM_TIM234_CR1_CMS_CENTER_3   3
+#define  STM_TIM234_CR1_CMS_MASK       3
+#define STM_TIM234_CR1_DIR     4
+#define  STM_TIM234_CR1_DIR_UP         0
+#define  STM_TIM234_CR1_DIR_DOWN       1
+#define STM_TIM234_CR1_OPM     3
+#define STM_TIM234_CR1_URS     2
+#define STM_TIM234_CR1_UDIS    1
+#define STM_TIM234_CR1_CEN     0
+
+#define STM_TIM234_CR2_TI1S    7
+#define STM_TIM234_CR2_MMS     4
+#define  STM_TIM234_CR2_MMS_RESET              0
+#define  STM_TIM234_CR2_MMS_ENABLE             1
+#define  STM_TIM234_CR2_MMS_UPDATE             2
+#define  STM_TIM234_CR2_MMS_COMPARE_PULSE      3
+#define  STM_TIM234_CR2_MMS_COMPARE_OC1REF     4
+#define  STM_TIM234_CR2_MMS_COMPARE_OC2REF     5
+#define  STM_TIM234_CR2_MMS_COMPARE_OC3REF     6
+#define  STM_TIM234_CR2_MMS_COMPARE_OC4REF     7
+#define  STM_TIM234_CR2_MMS_MASK               7
+#define STM_TIM234_CR2_CCDS    3
+
+#define STM_TIM234_SMCR_ETP    15
+#define STM_TIM234_SMCR_ECE    14
+#define STM_TIM234_SMCR_ETPS   12
+#define  STM_TIM234_SMCR_ETPS_OFF              0
+#define  STM_TIM234_SMCR_ETPS_DIV_2            1
+#define  STM_TIM234_SMCR_ETPS_DIV_4            2
+#define  STM_TIM234_SMCR_ETPS_DIV_8            3
+#define  STM_TIM234_SMCR_ETPS_MASK             3
+#define STM_TIM234_SMCR_ETF    8
+#define  STM_TIM234_SMCR_ETF_NONE              0
+#define  STM_TIM234_SMCR_ETF_INT_N_2           1
+#define  STM_TIM234_SMCR_ETF_INT_N_4           2
+#define  STM_TIM234_SMCR_ETF_INT_N_8           3
+#define  STM_TIM234_SMCR_ETF_DTS_2_N_6         4
+#define  STM_TIM234_SMCR_ETF_DTS_2_N_8         5
+#define  STM_TIM234_SMCR_ETF_DTS_4_N_6         6
+#define  STM_TIM234_SMCR_ETF_DTS_4_N_8         7
+#define  STM_TIM234_SMCR_ETF_DTS_8_N_6         8
+#define  STM_TIM234_SMCR_ETF_DTS_8_N_8         9
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_5                10
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_6                11
+#define  STM_TIM234_SMCR_ETF_DTS_16_N_8                12
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_5                13
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_6                14
+#define  STM_TIM234_SMCR_ETF_DTS_32_N_8                15
+#define  STM_TIM234_SMCR_ETF_MASK              15
+#define STM_TIM234_SMCR_MSM    7
+#define STM_TIM234_SMCR_TS     4
+#define  STM_TIM234_SMCR_TS_ITR0               0
+#define  STM_TIM234_SMCR_TS_ITR1               1
+#define  STM_TIM234_SMCR_TS_ITR2               2
+#define  STM_TIM234_SMCR_TS_ITR3               3
+#define  STM_TIM234_SMCR_TS_TI1F_ED            4
+#define  STM_TIM234_SMCR_TS_TI1FP1             5
+#define  STM_TIM234_SMCR_TS_TI2FP2             6
+#define  STM_TIM234_SMCR_TS_ETRF               7
+#define  STM_TIM234_SMCR_TS_MASK               7
+#define STM_TIM234_SMCR_OCCS   3
+#define STM_TIM234_SMCR_SMS    0
+#define  STM_TIM234_SMCR_SMS_DISABLE           0
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_1    1
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_2    2
+#define  STM_TIM234_SMCR_SMS_ENCODER_MODE_3    3
+#define  STM_TIM234_SMCR_SMS_RESET_MODE                4
+#define  STM_TIM234_SMCR_SMS_GATED_MODE                5
+#define  STM_TIM234_SMCR_SMS_TRIGGER_MODE      6
+#define  STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK    7
+#define  STM_TIM234_SMCR_SMS_MASK              7
+
+#define STM_TIM234_DIER_TDE            14
+#define STM_TIM234_DIER_CC4DE          12
+#define STM_TIM234_DIER_CC3DE          11
+#define STM_TIM234_DIER_CC2DE          10
+#define STM_TIM234_DIER_CC1DE          9
+#define STM_TIM234_DIER_UDE            8
+
+#define STM_TIM234_DIER_TIE            6
+#define STM_TIM234_DIER_CC4IE          4
+#define STM_TIM234_DIER_CC3IE          3
+#define STM_TIM234_DIER_CC2IE          2
+#define STM_TIM234_DIER_CC1IE          1
+#define STM_TIM234_DIER_UIE            0
+
+#define STM_TIM234_SR_CC4OF    12
+#define STM_TIM234_SR_CC3OF    11
+#define STM_TIM234_SR_CC2OF    10
+#define STM_TIM234_SR_CC1OF    9
+#define STM_TIM234_SR_TIF      6
+#define STM_TIM234_SR_CC4IF    4
+#define STM_TIM234_SR_CC3IF    3
+#define STM_TIM234_SR_CC2IF    2
+#define STM_TIM234_SR_CC1IF    1
+#define STM_TIM234_SR_UIF      0
+
+#define STM_TIM234_EGR_TG      6
+#define STM_TIM234_EGR_CC4G    4
+#define STM_TIM234_EGR_CC3G    3
+#define STM_TIM234_EGR_CC2G    2
+#define STM_TIM234_EGR_CC1G    1
+#define STM_TIM234_EGR_UG      0
+
+#define STM_TIM234_CCMR1_OC2CE 15
+#define STM_TIM234_CCMR1_OC2M  12
+#define  STM_TIM234_CCMR1_OC2M_FROZEN                  0
+#define  STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR1_OC2M_TOGGLE                  3
+#define  STM_TIM234_CCMR1_OC2M_FORCE_LOW               4
+#define  STM_TIM234_CCMR1_OC2M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR1_OC2M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR1_OC2M_MASK                    7
+#define STM_TIM234_CCMR1_OC2PE 11
+#define STM_TIM234_CCMR1_OC2FE 10
+#define STM_TIM234_CCMR1_CC2S  8
+#define  STM_TIM234_CCMR1_CC2S_OUTPUT                  0
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TI2               1
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TI1               2
+#define  STM_TIM234_CCMR1_CC2S_INPUT_TRC               3
+#define  STM_TIM234_CCMR1_CC2S_MASK                    3
+
+#define STM_TIM234_CCMR1_OC1CE 7
+#define STM_TIM234_CCMR1_OC1M  4
+#define  STM_TIM234_CCMR1_OC1M_FROZEN                  0
+#define  STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR1_OC1M_TOGGLE                  3
+#define  STM_TIM234_CCMR1_OC1M_FORCE_LOW               4
+#define  STM_TIM234_CCMR1_OC1M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR1_OC1M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR1_OC1M_MASK                    7
+#define STM_TIM234_CCMR1_OC1PE 3
+#define STM_TIM234_CCMR1_OC1FE 2
+#define STM_TIM234_CCMR1_CC1S  0
+#define  STM_TIM234_CCMR1_CC1S_OUTPUT                  0
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TI1               1
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TI2               2
+#define  STM_TIM234_CCMR1_CC1S_INPUT_TRC               3
+#define  STM_TIM234_CCMR1_CC1S_MASK                    3
+
+#define STM_TIM234_CCMR1_IC2F  12
+#define  STM_TIM234_CCMR1_IC2F_NONE                    0
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_2              1
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_4              2
+#define  STM_TIM234_CCMR1_IC2F_CK_INT_N_8              3
+#define  STM_TIM234_CCMR1_IC2F_DTS_2_N_6               4
+#define  STM_TIM234_CCMR1_IC2F_DTS_2_N_8               5
+#define  STM_TIM234_CCMR1_IC2F_DTS_4_N_6               6
+#define  STM_TIM234_CCMR1_IC2F_DTS_4_N_8               7
+#define  STM_TIM234_CCMR1_IC2F_DTS_8_N_6               8
+#define  STM_TIM234_CCMR1_IC2F_DTS_8_N_8               9
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_5              10
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_6              11
+#define  STM_TIM234_CCMR1_IC2F_DTS_16_N_8              12
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_5              13
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_6              14
+#define  STM_TIM234_CCMR1_IC2F_DTS_32_N_8              15
+#define STM_TIM234_CCMR1_IC2PSC        10
+#define  STM_TIM234_CCMR1_IC2PSC_NONE                  0
+#define  STM_TIM234_CCMR1_IC2PSC_2                     1
+#define  STM_TIM234_CCMR1_IC2PSC_4                     2
+#define  STM_TIM234_CCMR1_IC2PSC_8                     3
+#define STM_TIM234_CCMR1_IC1F  4
+#define  STM_TIM234_CCMR1_IC1F_NONE                    0
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_2              1
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_4              2
+#define  STM_TIM234_CCMR1_IC1F_CK_INT_N_8              3
+#define  STM_TIM234_CCMR1_IC1F_DTS_2_N_6               4
+#define  STM_TIM234_CCMR1_IC1F_DTS_2_N_8               5
+#define  STM_TIM234_CCMR1_IC1F_DTS_4_N_6               6
+#define  STM_TIM234_CCMR1_IC1F_DTS_4_N_8               7
+#define  STM_TIM234_CCMR1_IC1F_DTS_8_N_6               8
+#define  STM_TIM234_CCMR1_IC1F_DTS_8_N_8               9
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_5              10
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_6              11
+#define  STM_TIM234_CCMR1_IC1F_DTS_16_N_8              12
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_5              13
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_6              14
+#define  STM_TIM234_CCMR1_IC1F_DTS_32_N_8              15
+#define STM_TIM234_CCMR1_IC1PSC        2
+#define  STM_TIM234_CCMR1_IC1PSC_NONE                  0
+#define  STM_TIM234_CCMR1_IC1PSC_2                     1
+#define  STM_TIM234_CCMR1_IC1PSC_4                     2
+#define  STM_TIM234_CCMR1_IC1PSC_8                     3
+
+#define STM_TIM234_CCMR2_OC4CE 15
+#define STM_TIM234_CCMR2_OC4M  12
+#define  STM_TIM234_CCMR2_OC4M_FROZEN                  0
+#define  STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR2_OC4M_TOGGLE                  3
+#define  STM_TIM234_CCMR2_OC4M_FORCE_LOW               4
+#define  STM_TIM234_CCMR2_OC4M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR2_OC4M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR2_OC4M_MASK                    7
+#define STM_TIM234_CCMR2_OC4PE 11
+#define STM_TIM234_CCMR2_OC4FE 10
+#define STM_TIM234_CCMR2_CC4S  8
+#define  STM_TIM234_CCMR2_CC4S_OUTPUT                  0
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TI4               1
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TI3               2
+#define  STM_TIM234_CCMR2_CC4S_INPUT_TRC               3
+#define  STM_TIM234_CCMR2_CC4S_MASK                    3
+
+#define STM_TIM234_CCMR2_OC3CE 7
+#define STM_TIM234_CCMR2_OC3M  4
+#define  STM_TIM234_CCMR2_OC3M_FROZEN                  0
+#define  STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH       1
+#define  STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH                2
+#define  STM_TIM234_CCMR2_OC3M_TOGGLE                  3
+#define  STM_TIM234_CCMR2_OC3M_FORCE_LOW               4
+#define  STM_TIM234_CCMR2_OC3M_FORCE_HIGH              5
+#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_1              6
+#define  STM_TIM234_CCMR2_OC3M_PWM_MODE_2              7
+#define  STM_TIM234_CCMR2_OC3M_MASK                    7
+#define STM_TIM234_CCMR2_OC3PE 3
+#define STM_TIM234_CCMR2_OC3FE 2
+#define STM_TIM234_CCMR2_CC3S  0
+#define  STM_TIM234_CCMR2_CC3S_OUTPUT                  0
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TI3               1
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TI4               2
+#define  STM_TIM234_CCMR2_CC3S_INPUT_TRC               3
+#define  STM_TIM234_CCMR2_CC3S_MASK                    3
+
+#define STM_TIM234_CCER_CC4NP  15
+#define STM_TIM234_CCER_CC4P   13
+#define  STM_TIM234_CCER_CC4P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC4P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC4E   12
+#define STM_TIM234_CCER_CC3NP  11
+#define STM_TIM234_CCER_CC3P   9
+#define  STM_TIM234_CCER_CC3P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC3P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC3E   8
+#define STM_TIM234_CCER_CC2NP  7
+#define STM_TIM234_CCER_CC2P   5
+#define  STM_TIM234_CCER_CC2P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC2P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC2E   4
+#define STM_TIM234_CCER_CC1NP  3
+#define STM_TIM234_CCER_CC1P   1
+#define  STM_TIM234_CCER_CC1P_ACTIVE_HIGH      0
+#define  STM_TIM234_CCER_CC1P_ACTIVE_LOW       1
+#define STM_TIM234_CCER_CC1E   0
+
+struct stm_exti {
+       vuint32_t       imr;
+       vuint32_t       emr;
+       vuint32_t       rtsr;
+       vuint32_t       ftsr;
+
+       vuint32_t       swier;
+       vuint32_t       pr;
+};
+
+extern struct stm_exti stm_exti;
+#define stm_exti (*(struct stm_exti *) 0x40010400)
+
+struct stm_vrefint_cal {
+       vuint16_t       vrefint_cal;
+};
+
+extern struct stm_vrefint_cal stm_vrefint_cal;
+#define stm_vrefint_cal (*(struct stm_vrefint_cal *) 0x1ff80078)
+
+/* Flash interface */
+
+struct stm_flash {
+       vuint32_t       acr;
+       vuint32_t       pecr;
+       vuint32_t       pdkeyr;
+       vuint32_t       pekeyr;
+
+       vuint32_t       prgkeyr;
+       vuint32_t       optkeyr;
+       vuint32_t       sr;
+       vuint32_t       obr;
+
+       vuint32_t       wrpr;
+};
+
+
+extern uint32_t __storage[], __storage_size[];
+
+#define STM_FLASH_PAGE_SIZE    128
+
+#define ao_storage_unit                128
+#define ao_storage_total       ((uintptr_t) __storage_size)
+#define ao_storage_block       STM_FLASH_PAGE_SIZE
+#define AO_STORAGE_ERASED_BYTE 0x00
+
+extern struct stm_flash        stm_flash;
+
+#define STM_FLASH_ACR_PRE_READ (6)
+#define STM_FLASH_ACR_DISAB_BUF        (5)
+#define STM_FLASH_ACR_RUN_PD   (4)
+#define STM_FLASH_ACR_SLEEP_PD (3)
+#define STM_FLASH_ACR_PRFEN    (1)
+#define STM_FLASH_ACR_LATENCY  (0)
+
+#define STM_FLASH_PECR_NZDISABLE       23
+#define STM_FLASH_PECR_OBL_LAUNCH      18
+#define STM_FLASH_PECR_ERRIE           17
+#define STM_FLASH_PECR_EOPIE           16
+#define STM_FLASH_PECR_PARRALELLBANK   15
+#define STM_FLASH_PECR_FPRG            10
+#define STM_FLASH_PECR_ERASE           9
+#define STM_FLASH_PECR_FIX             8
+#define STM_FLASH_PECR_DATA            4
+#define STM_FLASH_PECR_PROG            3
+#define STM_FLASH_PECR_OPT_LOCK                2
+#define STM_FLASH_PECR_PRG_LOCK                1
+#define STM_FLASH_PECR_PE_LOCK         0
+
+#define STM_FLASH_SR_OPTVERR           11
+#define STM_FLASH_SR_SIZERR            10
+#define STM_FLASH_SR_PGAERR            9
+#define STM_FLASH_SR_WRPERR            8
+#define STM_FLASH_SR_READY             3
+#define STM_FLASH_SR_ENDHV             2
+#define STM_FLASH_SR_EOP               1
+#define STM_FLASH_SR_BSY               0
+
+#define STM_FLASH_OPTKEYR_OPTKEY1 0xFBEAD9C8
+#define STM_FLASH_OPTKEYR_OPTKEY2 0x24252627
+
+#define STM_FLASH_PEKEYR_PEKEY1        0x89ABCDEF
+#define STM_FLASH_PEKEYR_PEKEY2 0x02030405
+
+#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF
+#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516
+
+#endif /* _STM32L0_H_ */
diff --git a/src/stm32l0/stm32l0.ld b/src/stm32l0/stm32l0.ld
new file mode 100644 (file)
index 0000000..e266e9a
--- /dev/null
@@ -0,0 +1,58 @@
+/* IOPORT */
+stm_gpioh  = 0x50001c00;
+stm_gpioe  = 0x50001000;
+stm_gpiod  = 0x50000c00;
+stm_gpioc  = 0x50000800;
+stm_gpiob  = 0x50000400;
+stm_gpioa  = 0x50000000;
+
+/* AHB */
+stm_aes    = 0x40026000;
+stm_crc    = 0x40023000;
+stm_flash  = 0x40022000;
+stm_rcc    = 0x40021000;
+stm_dma1   = 0x40020000;
+
+/* APB2 */
+stm_dbg    = 0x40015800;
+stm_usart1 = 0x40013800;
+stm_spi1   = 0x40013000;
+stm_adc    = 0x40012400;
+stm_firewall = 0x40011c00;
+stm_tim22  = 0x40011400;
+stm_tim21  = 0x40010800;
+stm_exti   = 0x40010400;
+stm_syscfg = 0x40010000;
+stm_comp   = 0x40010000;
+
+/* APB1 */
+stm_lptim1 = 0x40007c00;
+stm_i2c3   = 0x40007800;
+stm_pwr    = 0x40007000;
+stm_i2c2   = 0x40005800;
+stm_i2c1   = 0x40005400;
+stm_usart5 = 0x40005000;
+stm_usart4 = 0x40004c00;
+stm_lpuart1 = 0x40004800;
+stm_usart2 = 0x40004400;
+stm_spi2   = 0x40003800;
+stm_iwdg   = 0x40003000;
+stm_wwdg   = 0x40002c00;
+stm_rtc    = 0x40002800;
+stm_timer7 = 0x40001400;
+stm_timer6 = 0x40001000;
+stm_timer3 = 0x40000400;
+stm_timer2 = 0x40000000;
+
+/* ARM */
+stm_systick = 0xe000e010;
+
+stm_nvic   = 0xe000e100;
+
+stm_scb    = 0xe000ed00;
+
+stm_mpu    = 0xe000ed90;
+
+/* ID registers */
+stm_flash_size = 0x1ff8007c;
+stm_device_id = 0x1ff80050;
index 591ca8a07576fb01a2888754d5f372fc9ab0ac47..defe259896e67b4eaf0f78ae0be48808dddcbede 100644 (file)
 
 /* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */
 
-#define AO_SPI_SPEED_24MHz     STM_SPI_CR1_BR_PCLK_2
-#define AO_SPI_SPEED_12MHz     STM_SPI_CR1_BR_PCLK_4
-#define AO_SPI_SPEED_6MHz      STM_SPI_CR1_BR_PCLK_8
-#define AO_SPI_SPEED_3MHz      STM_SPI_CR1_BR_PCLK_16
-#define AO_SPI_SPEED_1500kHz   STM_SPI_CR1_BR_PCLK_32
-#define AO_SPI_SPEED_750kHz    STM_SPI_CR1_BR_PCLK_64
-#define AO_SPI_SPEED_375kHz    STM_SPI_CR1_BR_PCLK_128
-#define AO_SPI_SPEED_187500Hz  STM_SPI_CR1_BR_PCLK_256
+#define _AO_SPI_SPEED_24MHz    STM_SPI_CR1_BR_PCLK_2
+#define _AO_SPI_SPEED_12MHz    STM_SPI_CR1_BR_PCLK_4
+#define _AO_SPI_SPEED_6MHz     STM_SPI_CR1_BR_PCLK_8
+#define _AO_SPI_SPEED_3MHz     STM_SPI_CR1_BR_PCLK_16
+#define _AO_SPI_SPEED_1500kHz  STM_SPI_CR1_BR_PCLK_32
+#define _AO_SPI_SPEED_750kHz   STM_SPI_CR1_BR_PCLK_64
+#define _AO_SPI_SPEED_375kHz   STM_SPI_CR1_BR_PCLK_128
+#define _AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256
 
-#define AO_SPI_SPEED_FAST      AO_SPI_SPEED_24MHz
-
-/* Companion bus wants something no faster than 200kHz */
-
-#define AO_SPI_SPEED_200kHz    AO_SPI_SPEED_187500Hz
+static inline uint32_t
+ao_spi_speed(uint32_t hz)
+{
+       if (hz >=24000000) return _AO_SPI_SPEED_24MHz;
+       if (hz >=12000000) return _AO_SPI_SPEED_12MHz;
+       if (hz >= 6000000) return _AO_SPI_SPEED_6MHz;
+       if (hz >= 3000000) return _AO_SPI_SPEED_3MHz;
+       if (hz >= 1500000) return _AO_SPI_SPEED_1500kHz;
+       if (hz >=  750000) return _AO_SPI_SPEED_750kHz;
+       if (hz >=  375000) return _AO_SPI_SPEED_375kHz;
+       return _AO_SPI_SPEED_187500Hz;
+}
 
 #define AO_SPI_CONFIG_1                0x00
 #define AO_SPI_1_CONFIG_PA5_PA6_PA7    AO_SPI_CONFIG_1
@@ -141,8 +148,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
 void
 ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index);
 
-extern uint16_t        ao_spi_speed[STM_NUM_SPI];
-
 void
 ao_spi_init(void);
 
@@ -387,9 +392,8 @@ ao_arch_memory_barrier(void) {
 
 #if HAS_TASK
 static inline void
-ao_arch_init_stack(struct ao_task *task, void *start)
+ao_arch_init_stack(struct ao_task *task, uint32_t *sp, void *start)
 {
-       uint32_t        *sp = &task->stack32[AO_STACK_SIZE >> 2];
        uint32_t        a = (uint32_t) start;
        int             i;
 
index 31af7f4a00ab74d19fc2fa2a54808ba286630b87..39022da16d4fd36e48300c0573ee8894af7b04ec 100644 (file)
@@ -376,7 +376,7 @@ ao_beep(uint8_t beep)
 }
 
 void
-ao_beep_for(uint8_t beep, uint16_t ticks) 
+ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks) 
 {
        ao_beep(beep);
        ao_delay(ticks);
index 3d7dc7a82c653e2eff6be3327b4edd252ae6ad88..3ef51dfa63fddbe78185e181ae8a1baf6b5d8977 100644 (file)
@@ -186,8 +186,11 @@ void _start(void)
 #if AO_BOOT_CHAIN
        if (ao_boot_check_chain()) {
 #if AO_BOOT_PIN
-               ao_boot_check_pin();
+               if (ao_boot_check_pin())
 #endif
+               {
+                       ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+               }
        }
 #endif
        /* Turn on syscfg */
index 1564535e8ec0a61c6c5df27f5347186d7d2d36c0..63593aff039c6153da468cc4bc154451621fc581 100644 (file)
@@ -58,21 +58,6 @@ ao_led_set(AO_LED_TYPE colors)
        ao_led_on(on);
 }
 
-void
-ao_led_toggle(AO_LED_TYPE colors)
-{
-#ifdef LED_PORT
-       LED_PORT->odr ^= (colors & LEDS_AVAILABLE);
-#else
-#ifdef LED_PORT_0
-       LED_PORT_0->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
-#endif
-#ifdef LED_PORT_1
-       LED_PORT_1->odr ^= ((colors & LEDS_AVAILABLE) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
-#endif
-#endif
-}
-
 void
 ao_led_for(AO_LED_TYPE colors, AO_TICK_TYPE ticks) 
 {
index be333754cfa37298d669f57572eb4783d4999093..b0b6ec0a07e878d5f6c5dab4658468f7588c5f1f 100644 (file)
@@ -60,10 +60,7 @@ void stm_systick_isr(void)
 {
        if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
                ++ao_tick_count;
-#if HAS_TASK_QUEUE
-               if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
-                       ao_task_check_alarm((uint16_t) ao_tick_count);
-#endif
+               ao_task_check_alarm();
 #if AO_DATA_ALL
                if (++ao_data_count == ao_data_interval) {
                        ao_data_count = 0;
index cb0ec838e3bb90c9244297bd0d0e5b559a523967..6b006307545fe4d3625837301fec1b860ba37ce8 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index 62dddf2a2f8fa7da5ab1acfe9716aaa48196f97a..d71f265501dbeeef35551cc3f1100673c5151c8d 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
@@ -198,7 +197,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN   10
 #define AO_CC1200_SPI_BUS      AO_SPI_1_PA5_PA6_PA7
 #define AO_CC1200_SPI          stm_spi1
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index f3d70d1ad31eb1e81f698345a7aa349d48af152e..1b4efdd3dfbc2e485db85d37dfc229ac44aee507 100644 (file)
@@ -40,7 +40,6 @@
 #define AO_PA11_PA12_RMP       0
 
 #define IS_FLASH_LOADER        0
-#define HAS_TASK_QUEUE         1
 
 /*
  * Serial ports
@@ -272,7 +271,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN   11
 #define AO_CC1200_SPI_BUS      AO_SPI_1_PA5_PA6_PA7
 #define AO_CC1200_SPI          stm_spi1
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_6MHz
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (10)
index be710aef3ca17a10458822e30ce8ddac68a11dfe..5641462a3dcc5c485521bdb3935c93818405a191 100644 (file)
@@ -23,7 +23,6 @@
 
 #define AO_STACK_SIZE  320
 
-#define HAS_TASK_QUEUE         1
 
 #define IS_FLASH_LOADER        0
 
@@ -96,7 +95,6 @@
 #define AO_CC1200_SPI_CS_PIN   3
 #define AO_CC1200_SPI_BUS      0
 #define AO_CC1200_SPI          0
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_8MHz
 
 #define AO_CC1200_INT_PORT     0
 #define AO_CC1200_INT_PIN      2
index c15e06bf1e4adf70167cf06315b09443f443d1c9..b1952278815d98dd2ecc18e92fa4e4dc7d896826 100644 (file)
 #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)
index 046514b42e64204528c1bf297216e2b10e304191..a71eb441046a6ca1891fc580016c6d6fb19a3797 100644 (file)
@@ -88,7 +88,6 @@
 #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)
index cd8eb65861d3b4b7d8bc460a3fa489524c1246fd..9d43c2c23e1be832a42f28c307e3802b86a43eec 100644 (file)
 #define AO_CC1200_SPI_CS_PIN   7
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index 8025ace6a660c239872db4e0a02909c0495c1f78..3b76cccfa475d17d148b9c023a46da366778be94 100644 (file)
 #define AO_CC1200_SPI_CS_PIN   3
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index dedd0fad3ece4345d47e0c35f665518a6965e739..a3bc0a8565ae83dddc99ee15722416a88f574d5f 100644 (file)
 #define AO_CC1200_SPI_CS_PIN   7
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index 01faace2dfad944deff3825f8a5a9fc546c9ad69..e04c4fd793ae6f093db91762b9c394fc4487dcd4 100644 (file)
 #define AO_CC1200_SPI_CS_PIN   7
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index 5afc9498c7d22bcdd01d1032ba85e86a5cf602b1..ff04a04465dc599a51cd333b9b87b634ed10f038 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
 #define AO_CC115L_SPI_CS_PIN   12
 #define AO_CC115L_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC115L_SPI          stm_spi2
-#define AO_CC115L_SPI_SPEED    AO_SPI_SPEED_4MHz
 
 #define AO_CC115L_FIFO_INT_GPIO_IOCFG  CC115L_IOCFG2
 #define AO_CC115L_FIFO_INT_PORT                (&stm_gpioa)
index 873474bbab3ac074a8aefd4389c2a1139c54cbfc..e22331d14061fbaf8b8bbb9d459005fb7caf2242 100644 (file)
@@ -96,7 +96,6 @@
 #define AO_CC115L_SPI_CS_PORT  0
 #define AO_CC115L_SPI_CS_PIN   3
 #define AO_CC115L_SPI_BUS      0
-#define AO_CC115L_SPI_SPEED    AO_SPI_SPEED_6MHz
 
 #define AO_CC115L_FIFO_INT_GPIO_IOCFG  CC115L_IOCFG2
 #define AO_CC115L_FIFO_INT_PORT                0
index f3bdc0ac73f135360baaa9a5ae047dfded1b2f11..fbc767393fdd4d5c0f0460348f5272a0136e888d 100644 (file)
@@ -98,7 +98,6 @@
 #define AO_CC115L_SPI_CS_PORT  0
 #define AO_CC115L_SPI_CS_PIN   3
 #define AO_CC115L_SPI_BUS      0
-#define AO_CC115L_SPI_SPEED    AO_SPI_SPEED_6MHz
 
 #define AO_CC115L_FIFO_INT_GPIO_IOCFG  CC115L_IOCFG2
 #define AO_CC115L_FIFO_INT_PORT                0
index a2e812fa51f5570762b07d0e1c8b16004ea0c9b1..5c6aee0e302e3615a7b06d53354d17019e37d5f9 100644 (file)
@@ -158,7 +158,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN    1
 #define AO_CC1200_SPI_BUS       AO_SPI_1_PA5_PA6_PA7
 #define AO_CC1200_SPI           stm_spi1
-#define AO_CC1200_SPI_SPEED     AO_SPI_SPEED_6MHz
 
 #define AO_CC1200_INT_PORT              (&stm_gpioa)
 #define AO_CC1200_INT_PIN               4
index f3850ebd199c231d3b375988dd706ac0ab0955e1..b434e7cb4b374aac2fb79ff90f13cc63ee31673e 100644 (file)
@@ -95,7 +95,6 @@
 #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)
index c806268f7964991429d72f8204dc691f66c4e1a5..de89d746a41bb55e35c036e3cba74d91c9e9cf07 100644 (file)
@@ -95,7 +95,6 @@
 #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)
index e06633145fe7a1dc097c5d4e4d13a3bc6d2749c5..bfbda42381ade84c51347df56a753dc527c3074a 100644 (file)
@@ -93,7 +93,6 @@
 #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)
index 3ef88c7476a93ae742e790fc137a855a4ed2cebf..cf93976e43e32f3a2e457350cd557dfc4a8fa282 100644 (file)
@@ -94,7 +94,6 @@
 #define AO_CC1200_SPI_CS_PIN   7
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index 0208fafa37cae69916683e5326bff7ad0c14f0e7..ea450354e4a6161bbd58393a25e99072d21cc3cd 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index a154225ec77d68bb907a96fef8fd456c3e5d46d8..fa953460ede8992d26d2e7857014e3d9c2ef3934 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index ba302c7409a2683c27bee0db87ce4ec36b1e2ebb..4f3b73f7d4d3d75cbff63895122481e717e6933b 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
@@ -311,7 +310,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN   5
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpioe)
 #define AO_CC1200_INT_PIN              1
index ce22390785a1c03a8097de26a422cc3e252cfa67..29b5cc1d3163d7535926d7fd5411ea4bc80d30c8 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
@@ -311,7 +310,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN   5
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpioe)
 #define AO_CC1200_INT_PIN              1
index 84af615c00a89fa9ef7301c17c93d644df1b5d3e..fdf290716c041b0804fd617b8b066749288eb70b 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
@@ -306,7 +305,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN   5
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpioe)
 #define AO_CC1200_INT_PIN              1
@@ -351,7 +349,6 @@ struct ao_adc {
 #define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
 #define AO_ADXL375_CS_PORT     (&stm_gpiod)
 #define AO_ADXL375_CS_PIN      4
-#define AO_ADXL375_SPI_SPEED   AO_SPI_SPEED_4MHz
 
 #define AO_ADXL375_AXIS                x
 #define AO_ADXL375_INVERT      1
index e8c97ff4270461a4c3a7299202b47663250828a0..aa49483e8ee580fb8570965bfcb58d1dd6b76ace 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index 68bec1be3f789066f031121b983f5d2454a39d70..a1d4aa28edb3378a1d8e7db4ae4cfb745566d635 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
@@ -260,7 +259,6 @@ struct ao_adc {
 #define AO_CC1200_SPI_CS_PIN   2
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpioa)
 #define AO_CC1200_INT_PIN              (3)
@@ -283,7 +281,6 @@ struct ao_adc {
 #define AO_ADXL375_SPI_INDEX   (AO_SPI_1_PB3_PB4_PB5 | AO_SPI_MODE_3)
 #define AO_ADXL375_CS_PORT     (&stm_gpiob)
 #define AO_ADXL375_CS_PIN      9
-#define AO_ADXL375_SPI_SPEED   AO_SPI_SPEED_4MHz
 
 #define AO_ADXL375_AXIS                x
 #define AO_ADXL375_INVERT      1
index ae8534b9c3fbaf56ef3545f42dcaf6296273da3d..a734ff0aaaa1f139c48729edc8b52e107db9a31b 100644 (file)
 #define AO_MS5607_MISO_PIN     4
 #define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO_PIN)
 #define AO_MS5607_SPI_INDEX    AO_SPI_1_PB3_PB4_PB5
-#define AO_MS5607_SPI_SPEED    AO_SPI_SPEED_12MHz
 
 /* CC1200 */
 
 #define AO_CC1200_SPI_CS_PIN   0
 #define AO_CC1200_SPI_BUS      AO_SPI_1_PA5_PA6_PA7
 #define AO_CC1200_SPI          stm_spi1
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_12MHz
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              1
index aad17664bde320fd49357177b06c7c0fe6ebeb8c..866206ce28661538f7fdf4faf1294579f759b7fa 100644 (file)
 #define AO_CC1200_SPI_CS_PIN   3
 #define AO_CC1200_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 #define AO_CC1200_SPI          stm_spi2
-#define AO_CC1200_SPI_SPEED    AO_SPI_SPEED_FAST
 
 #define AO_CC1200_INT_PORT             (&stm_gpiob)
 #define AO_CC1200_INT_PIN              (11)
index 059c22843d2fd138c1a668b5196c1ff14204b811..952460d0c2831c2daf12808037ffa947ee019171 100644 (file)
@@ -46,10 +46,10 @@ static void ao_led_on(uint8_t led) {
 static void ao_led_off(uint8_t led) {
 }
 
-static void ao_delay_until(uint16_t target) {
+static void ao_delay_until(AO_TICK_TYPE target) {
 }
 
-static uint16_t ao_time(void) {
+static AO_TICK_TYPE ao_time(void) {
        return 0;
 }
 
@@ -57,7 +57,7 @@ static uint16_t ao_time(void) {
 #include "ao_microkalman.c"
 #include "ao_convert_pa.c"
 
-uint16_t       now;
+AO_TICK_TYPE   now;
 uint8_t                running;
 
 void ao_log_micro_data() {
index b4dcc10c33889913478dc987ba9a06f6d8986467..dd030eeea0982480dffc32fe216c84cf6c1ba5d7 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 /* 8MHz High speed external crystal */
 #define AO_HSE                 8000000
index fe9d3879e8be58f8f53a58141b3a5a547b5ea3e5..649d52a79b3ee5682c193c9ea5e84e199c3895b5 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef _AO_PINS_H_
 #define _AO_PINS_H_
 
-#define HAS_TASK_QUEUE         1
 
 #define IS_FLASH_LOADER        0
 
index 0e75abf1480996fadb88763f938a99d4d4173a2f..26e5dfb82d79ca1b7bcc4cc2a0f5e3c55268fd51 100644 (file)
@@ -153,7 +153,7 @@ LINUX_EXTRA=telegps-fat $(desktop_file).in
 
 MACOSX_INFO_PLIST=Info.plist
 MACOSX_README=ReadMe-Mac.rtf
-MACOSX_INSTALL=../altosui/install-macosx
+MACOSX_INSTALL=../altosui/install-macosx ../altosui/ask-pass
 MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_README) $(DOC) $(MACOSX_ICONS) $(MACOSX_INSTALL)
 MACOSX_EXTRA=$(FIRMWARE)
 
index 16966918da4e3f715b18f4e71db0714ebb17f56e..145a260ba76c07cfcb7dffb469b6191049f4d556 100755 (executable)
@@ -1,4 +1,16 @@
 #!/bin/bash
+#
+# Fix fonts. I don't know why the getting the
+# basename of the app set to . matters, but it does
+#
+case "$0" in
+    /*)
+        cd `dirname "$0"`
+        ./`basename "$0"` "$@"
+        exit $?
+        ;;
+esac
+export FREETYPE_PROPERTIES=truetype:interpreter-version=35
 ##################################################################################
 #                                                                                #
 # universalJavaApplicationStub                                                   #
index 7c5d186e9864728f5b959b69e594e21c69314768..465916ec81ea0c2efebdc26cef86f9ede96c81f9 100644 (file)
@@ -211,7 +211,7 @@ public class TeleGPSConfigUI
                Insets il = new Insets(4,4,4,4);
                Insets ir = new Insets(4,4,4,4);
 
-               pane = getContentPane();
+               pane = getScrollablePane();
                pane.setLayout(new GridBagLayout());
 
                /* Product */