altos: Restructure altos build to prepare for multi-arch support
authorKeith Packard <keithp@keithp.com>
Fri, 26 Aug 2011 03:43:44 +0000 (20:43 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 26 Aug 2011 03:49:11 +0000 (20:49 -0700)
Split out sources into separate directories:

core: architecture and product independent bits
cc1111: cc1111-specific code
drivers: architecture independent drivers
product: product-specific sources and Makefile fragments
util: scripts for building stuff

This should have no effect on the built products, but testing is encouraged

Signed-off-by: Keith Packard <keithp@keithp.com>
190 files changed:
configure.ac
src/25lc1024.h [deleted file]
src/Makefile
src/Makefile.proto [deleted file]
src/_bp.c [deleted file]
src/altitude.h [deleted file]
src/ao-make-product.5c [deleted file]
src/ao.h [deleted file]
src/ao_adc.c [deleted file]
src/ao_adc_fake.c [deleted file]
src/ao_beep.c [deleted file]
src/ao_btm.c [deleted file]
src/ao_cmd.c [deleted file]
src/ao_companion.c [deleted file]
src/ao_config.c [deleted file]
src/ao_convert.c [deleted file]
src/ao_convert_test.c [deleted file]
src/ao_dbg.c [deleted file]
src/ao_dma.c [deleted file]
src/ao_ee.c [deleted file]
src/ao_ee_fake.c [deleted file]
src/ao_flash.c [deleted file]
src/ao_flight.c [deleted file]
src/ao_flight_nano.c [deleted file]
src/ao_flight_test.c [deleted file]
src/ao_gps_print.c [deleted file]
src/ao_gps_report.c [deleted file]
src/ao_gps_sirf.c [deleted file]
src/ao_gps_skytraq.c [deleted file]
src/ao_gps_test.c [deleted file]
src/ao_gps_test_skytraq.c [deleted file]
src/ao_host.h [deleted file]
src/ao_ignite.c [deleted file]
src/ao_intflash.c [deleted file]
src/ao_kalman.c [deleted file]
src/ao_led.c [deleted file]
src/ao_log.c [deleted file]
src/ao_log_big.c [deleted file]
src/ao_log_telem.c [deleted file]
src/ao_log_tiny.c [deleted file]
src/ao_m25.c [deleted file]
src/ao_main.c [deleted file]
src/ao_monitor.c [deleted file]
src/ao_mutex.c [deleted file]
src/ao_packet.c [deleted file]
src/ao_packet_master.c [deleted file]
src/ao_packet_slave.c [deleted file]
src/ao_panic.c [deleted file]
src/ao_pins.h [deleted file]
src/ao_product.c [deleted file]
src/ao_radio.c [deleted file]
src/ao_reboot.c [deleted file]
src/ao_report.c [deleted file]
src/ao_romconfig.c [deleted file]
src/ao_rssi.c [deleted file]
src/ao_sample.c [deleted file]
src/ao_serial.c [deleted file]
src/ao_spi.c [deleted file]
src/ao_state.c [deleted file]
src/ao_stdio.c [deleted file]
src/ao_storage.c [deleted file]
src/ao_task.c [deleted file]
src/ao_telebt.c [deleted file]
src/ao_teledongle.c [deleted file]
src/ao_telem.h [deleted file]
src/ao_telemetrum.c [deleted file]
src/ao_telemetry.c [deleted file]
src/ao_telemini.c [deleted file]
src/ao_telenano.c [deleted file]
src/ao_teleterra.c [deleted file]
src/ao_test.c [deleted file]
src/ao_tidongle.c [deleted file]
src/ao_timer.c [deleted file]
src/ao_usb.c [deleted file]
src/ao_usb.h [deleted file]
src/at45db161d.h [deleted file]
src/cc1111.h [deleted file]
src/cc1111/Makefile.cc1111 [new file with mode: 0644]
src/cc1111/_bp.c [new file with mode: 0644]
src/cc1111/ao_adc.c [new file with mode: 0644]
src/cc1111/ao_beep.c [new file with mode: 0644]
src/cc1111/ao_dbg.c [new file with mode: 0644]
src/cc1111/ao_dma.c [new file with mode: 0644]
src/cc1111/ao_ignite.c [new file with mode: 0644]
src/cc1111/ao_intflash.c [new file with mode: 0644]
src/cc1111/ao_led.c [new file with mode: 0644]
src/cc1111/ao_packet.c [new file with mode: 0644]
src/cc1111/ao_packet_master.c [new file with mode: 0644]
src/cc1111/ao_packet_slave.c [new file with mode: 0644]
src/cc1111/ao_radio.c [new file with mode: 0644]
src/cc1111/ao_reboot.c [new file with mode: 0644]
src/cc1111/ao_romconfig.c [new file with mode: 0644]
src/cc1111/ao_serial.c [new file with mode: 0644]
src/cc1111/ao_spi.c [new file with mode: 0644]
src/cc1111/ao_timer.c [new file with mode: 0644]
src/cc1111/ao_usb.c [new file with mode: 0644]
src/cc1111/ao_usb.h [new file with mode: 0644]
src/cc1111/cc1111.h [new file with mode: 0644]
src/check-stack [deleted file]
src/core/altitude.h [new file with mode: 0644]
src/core/ao.h [new file with mode: 0644]
src/core/ao_cmd.c [new file with mode: 0644]
src/core/ao_config.c [new file with mode: 0644]
src/core/ao_convert.c [new file with mode: 0644]
src/core/ao_convert_test.c [new file with mode: 0644]
src/core/ao_ee_fake.c [new file with mode: 0644]
src/core/ao_flight.c [new file with mode: 0644]
src/core/ao_flight_nano.c [new file with mode: 0644]
src/core/ao_gps_print.c [new file with mode: 0644]
src/core/ao_gps_report.c [new file with mode: 0644]
src/core/ao_host.h [new file with mode: 0644]
src/core/ao_kalman.c [new file with mode: 0644]
src/core/ao_log.c [new file with mode: 0644]
src/core/ao_log_big.c [new file with mode: 0644]
src/core/ao_log_telem.c [new file with mode: 0644]
src/core/ao_log_tiny.c [new file with mode: 0644]
src/core/ao_monitor.c [new file with mode: 0644]
src/core/ao_mutex.c [new file with mode: 0644]
src/core/ao_panic.c [new file with mode: 0644]
src/core/ao_pins.h [new file with mode: 0644]
src/core/ao_product.c [new file with mode: 0644]
src/core/ao_report.c [new file with mode: 0644]
src/core/ao_rssi.c [new file with mode: 0644]
src/core/ao_sample.c [new file with mode: 0644]
src/core/ao_state.c [new file with mode: 0644]
src/core/ao_stdio.c [new file with mode: 0644]
src/core/ao_storage.c [new file with mode: 0644]
src/core/ao_task.c [new file with mode: 0644]
src/core/ao_telem.h [new file with mode: 0644]
src/core/ao_telemetry.c [new file with mode: 0644]
src/drivers/ao_25lc1024.c [new file with mode: 0644]
src/drivers/ao_25lc1024.h [new file with mode: 0644]
src/drivers/ao_at45db161d.c [new file with mode: 0644]
src/drivers/ao_at45db161d.h [new file with mode: 0644]
src/drivers/ao_btm.c [new file with mode: 0644]
src/drivers/ao_companion.c [new file with mode: 0644]
src/drivers/ao_gps_sirf.c [new file with mode: 0644]
src/drivers/ao_gps_skytraq.c [new file with mode: 0644]
src/drivers/ao_m25.c [new file with mode: 0644]
src/gps-cksum [deleted file]
src/make-altitude [deleted file]
src/make-kalman [deleted file]
src/product/Makefile.telebt [new file with mode: 0644]
src/product/Makefile.teledongle [new file with mode: 0644]
src/product/Makefile.telemetrum [new file with mode: 0644]
src/product/Makefile.telemini [new file with mode: 0644]
src/product/Makefile.telenano [new file with mode: 0644]
src/product/ao_telebt.c [new file with mode: 0644]
src/product/ao_teledongle.c [new file with mode: 0644]
src/product/ao_telemetrum.c [new file with mode: 0644]
src/product/ao_telemini.c [new file with mode: 0644]
src/product/ao_telenano.c [new file with mode: 0644]
src/product/ao_teleterra.c [new file with mode: 0644]
src/product/ao_test.c [new file with mode: 0644]
src/product/ao_tidongle.c [new file with mode: 0644]
src/sirf-cksum [deleted file]
src/skytraq-cksum [deleted file]
src/telebt-v0.0/Makefile
src/telebt-v0.0/Makefile.defs [deleted file]
src/telebt-v0.1/Makefile
src/telebt-v0.1/Makefile.defs [deleted file]
src/teledongle-v0.1/Makefile
src/teledongle-v0.1/Makefile.defs [deleted file]
src/teledongle-v0.2/Makefile
src/teledongle-v0.2/Makefile.defs [deleted file]
src/telemetrum-v0.1-sirf/Makefile
src/telemetrum-v0.1-sirf/Makefile.defs [deleted file]
src/telemetrum-v0.1-sky/Makefile
src/telemetrum-v0.1-sky/Makefile.defs [deleted file]
src/telemetrum-v1.0/Makefile
src/telemetrum-v1.0/Makefile.defs [deleted file]
src/telemetrum-v1.1/Makefile
src/telemetrum-v1.1/Makefile.defs [deleted file]
src/telemini-v1.0/Makefile
src/telemini-v1.0/Makefile.defs [deleted file]
src/telenano-v0.1/Makefile
src/telenano-v0.1/Makefile.defs [deleted file]
src/test/Makefile
src/test/ao_flight_test.c [new file with mode: 0644]
src/test/ao_gps_test.c [new file with mode: 0644]
src/test/ao_gps_test_skytraq.c [new file with mode: 0644]
src/tidongle/Makefile
src/tidongle/Makefile.defs [deleted file]
src/util/ao-make-product.5c [new file with mode: 0644]
src/util/check-stack [new file with mode: 0755]
src/util/gps-cksum [new file with mode: 0755]
src/util/make-altitude [new file with mode: 0644]
src/util/make-kalman [new file with mode: 0644]
src/util/sirf-cksum [new file with mode: 0755]
src/util/skytraq-cksum [new file with mode: 0644]

index f9002508ec4199cd5bec5b8f0838191cfe0e6358..da9d99916234e60a22a5a4c3cd5636d62c3085a5 100644 (file)
@@ -19,7 +19,7 @@ dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
 AC_INIT([altos], 1.0)
-AC_CONFIG_SRCDIR([src/ao.h])
+AC_CONFIG_SRCDIR([src/core/ao.h])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
diff --git a/src/25lc1024.h b/src/25lc1024.h
deleted file mode 100644 (file)
index 44e5238..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */
-
-#ifndef _25LC1024_H_
-#define _25LC1024_H_
-
-#define EE_READ                0x03
-#define EE_WRITE       0x02
-#define EE_WREN                0x06
-#define EE_WRDI                0x04
-#define EE_RDSR                0x05
-#define EE_WRSR                0x01
-#define EE_PE          0x42
-#define EE_SE          0xd8
-#define EE_CE          0xc7
-#define EE_RDID                0xab
-#define EE_DPD         0xb9
-
-#define EE_STATUS_WIP  (1 << 0)
-#define EE_STATUS_WEL  (1 << 1)
-#define EE_STATUS_BP0  (1 << 2)
-#define EE_STATUS_BP1  (1 << 3)
-#define EE_STATUS_WPEN (1 << 7)
-
-#endif /* _25LC1024_H_ */
index 018f0c5c1f7c46300729661f86362e36dff9a26c..4e40c2bf3dc2021830a141be598d34260b3c9eac 100644 (file)
@@ -2,7 +2,13 @@
 # AltOS build
 #
 #
-CC=sdcc
+
+vpath make-altitude util
+vpath make-kalman util
+vpath kalman.5c kalman
+vpath kalman_filter.5c kalman
+vpath load_csv.5c kalman
+vpath matrix.5c kalman
 
 include Version
 
@@ -14,7 +20,7 @@ SUBDIRS=\
        telemetrum-v0.1-sky telemetrum-v0.1-sirf \
        tidongle test
 
-all: all-recursive
+all: all-local all-recursive
 
 RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive
 
@@ -27,8 +33,21 @@ $(RECURSIVE_TARGETS):
 
 distclean:     clean
 
-clean: clean-recursive
+clean: clean-local clean-recursive
 
 install: install-recursive
 
 uninstall:
+
+all-recursive: all-local
+
+all-local: altitude.h ao_kalman.h
+
+altitude.h: make-altitude
+       nickle $< > $@
+
+ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
+       sh $< kalman > $@
+
+clean-local:
+       rm -f altitude.h ao_kalman.h
\ No newline at end of file
diff --git a/src/Makefile.proto b/src/Makefile.proto
deleted file mode 100644 (file)
index 8f98d35..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-#
-# AltOS build
-#
-#
-vpath %.c ..
-vpath %.h ..
-vpath make-altitude ..
-vpath make-kalman ..
-vpath kalman.5c ../kalman
-vpath kalman_filter.5c ../kalman
-vpath load_csv.5c ../kalman
-vpath matrix.5c ../kalman
-vpath ao-make-product.5c ..
-
-CC=sdcc
-
-ifndef VERSION
-include ../Version
-endif
-
-CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE)
-
-CODESIZE ?= 0x8000
-
-LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \
-       --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff
-
-INC = \
-       ao.h \
-       ao_pins.h \
-       cc1111.h \
-       altitude.h \
-       ao_kalman.h \
-       25lc1024.h
-
-#
-# Common AltOS sources
-#
-ALTOS_SRC = \
-       ao_cmd.c \
-       ao_dma.c \
-       ao_mutex.c \
-       ao_panic.c \
-       ao_task.c \
-       ao_timer.c \
-       ao_romconfig.c \
-       _bp.c
-
-#
-# Shared AltOS drivers
-#
-ALTOS_DRIVER_SRC = \
-       ao_config.c \
-       ao_led.c \
-       ao_radio.c \
-       ao_stdio.c
-
-BEEP_DRIVER_SRC = \
-       ao_beep.c
-
-USB_DRIVER_SRC = \
-       ao_usb.c
-
-TELE_COMMON_SRC = \
-       ao_packet.c
-
-#
-# Receiver code
-#
-TELE_RECEIVER_SRC =\
-       ao_monitor.c \
-       ao_gps_print.c \
-       ao_packet_master.c \
-       ao_state.c \
-       ao_rssi.c
-
-#
-# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle)
-#
-
-TELE_DRIVER_SRC = \
-       ao_convert.c
-
-#
-# Serial port driver
-#
-SERIAL_DRIVER_SRC = \
-       ao_serial.c
-
-#
-# Spi bus driver
-#
-SPI_DRIVER_SRC = \
-       ao_spi.c
-
-#
-# Debug dongle driver (only on TI)
-#
-DBG_SRC = \
-       ao_dbg.c
-
-#
-# Drivers only on TeleMetrum
-#
-TM_DRIVER_SRC = \
-       ao_adc.c \
-       ao_gps_report.c \
-       ao_ignite.c \
-       ao_packet_slave.c \
-       $(BEEP_DRIVER_SRC) \
-       $(USB_DRIVER_SRC)
-
-#
-# 25LC1024 driver source
-EE_DRIVER_SRC = \
-       ao_storage.c \
-       ao_ee.c
-
-#
-# AT45DB161D driver source
-
-FLASH_DRIVER_SRC = \
-       ao_storage.c \
-       ao_flash.c
-
-#
-# Numonyx M25P80 driver source
-#
-
-M25_DRIVER_SRC = \
-       ao_storage.c \
-       ao_m25.c
-
-#
-# SiRF driver source
-#
-SIRF_DRIVER_SRC = \
-       ao_gps_sirf.c
-
-#
-# Skytraq driver source
-#
-SKY_DRIVER_SRC = \
-       ao_gps_skytraq.c
-
-
-#
-# BTM-182 driver source
-#
-BTM_DRIVER_SRC = \
-       ao_btm.c
-
-#
-# Companion port driver source
-#
-COMPANION_SRC = \
-       ao_companion.c
-
-#
-# Tasks run on TeleMetrum
-#
-TM_TASK_SRC = \
-       ao_flight.c \
-       ao_sample.c \
-       ao_kalman.c \
-       ao_log.c \
-       ao_log_big.c \
-       ao_report.c \
-       ao_telemetry.c
-
-TM_MAIN_SRC = \
-       ao_telemetrum.c
-
-#
-# Base sources for TeleMetrum
-#
-TM_BASE_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_DRIVER_SRC) \
-       $(SERIAL_DRIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(TM_DRIVER_SRC) \
-       $(TM_TASK_SRC) \
-       $(TM_MAIN_SRC)
-
-#
-# Sources for TeleMini
-TMINI_DRIVER_SRC = \
-       ao_adc.c \
-       ao_ignite.c \
-       ao_config.c \
-       ao_storage.c \
-       ao_packet_slave.c \
-       ao_intflash.c
-
-TMINI_TASK_SRC = \
-       ao_flight.c \
-       ao_sample.c \
-       ao_kalman.c \
-       ao_log.c \
-       ao_log_tiny.c \
-       ao_report.c \
-       ao_telemetry.c
-
-TMINI_MAIN_SRC = \
-       ao_telemini.c
-
-TMINI_BASE_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_DRIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(TMINI_DRIVER_SRC) \
-       $(TMINI_TASK_SRC) \
-       $(TMINI_MAIN_SRC)
-
-#
-# Sources for TeleNano
-TNANO_DRIVER_SRC = \
-       ao_adc.c \
-       ao_config.c \
-       ao_storage.c \
-       ao_packet_slave.c \
-       ao_intflash.c
-
-TNANO_TASK_SRC = \
-       ao_flight_nano.c \
-       ao_sample.c \
-       ao_kalman.c \
-       ao_log.c \
-       ao_log_tiny.c \
-       ao_report.c \
-       ao_telemetry.c
-
-TNANO_MAIN_SRC = \
-       ao_telenano.c
-
-TNANO_BASE_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_DRIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(TNANO_DRIVER_SRC) \
-       $(TNANO_TASK_SRC) \
-       $(TNANO_MAIN_SRC)
-
-#
-# Sources for TeleBluetooth
-#
-
-TBT_MAIN_SRC = \
-       ao_telebt.c
-
-TBT_BASE_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_RECEIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(SERIAL_DRIVER_SRC) \
-       $(USB_DRIVER_SRC) \
-       $(BTM_DRIVER_SRC) \
-       $(DBG_SRC) \
-       $(TBT_MAIN_SRC)
-
-TBT_V_0_1_SRC = \
-       $(TBT_BASE_SRC) \
-       $(SPI_DRIVER_SRC) \
-       $(M25_DRIVER_SRC) \
-       $(BEEP_DRIVER_SRC) \
-       ao_log_telem.c
-
-#
-# TI Dongle sources
-#
-TI_MAIN_SRC = \
-       ao_tidongle.c
-
-#
-# All sources for the TI debug dongle
-#
-TI_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_RECEIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(USB_DRIVER_SRC) \
-       $(TI_MAIN_SRC) \
-       $(DBG_SRC)
-
-TT_MAIN_SRC = \
-       ao_teleterra.c
-#
-# All sources for TeleTerra
-#
-TT_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_RECEIVER_SRC) \
-       $(TELE_DRIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(USB_DRIVER_SRC) \
-       $(TT_MAIN_SRC)
-
-
-#
-# Sources for TeleDongle
-#
-
-TD_MAIN_SRC = \
-       ao_teledongle.c
-
-TD_SRC = \
-       $(ALTOS_SRC) \
-       $(ALTOS_DRIVER_SRC) \
-       $(TELE_RECEIVER_SRC) \
-       $(TELE_COMMON_SRC) \
-       $(USB_DRIVER_SRC) \
-       $(TD_MAIN_SRC)
-
-include Makefile.defs
-
-CFLAGS += $(PRODUCT_DEF) -I.
-
-NICKLE=nickle
-CHECK_STACK=sh ../check-stack
-
-REL=$(SRC:.c=.rel) ao_product.rel
-ADB=$(REL:.rel=.adb)
-ASM=$(REL:.rel=.asm)
-LNK=$(REL:.rel=.lnk)
-LST=$(REL:.rel=.lst)
-RST=$(REL:.rel=.rst)
-SYM=$(REL:.rel=.sym)
-
-PCDB=$(PROG:.ihx=.cdb)
-PLNK=$(PROG:.ihx=.lnk)
-PMAP=$(PROG:.ihx=.map)
-PMEM=$(PROG:.ihx=.mem)
-PAOM=$(PROG:.ihx=)
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf "  $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-%.rel : %.c $(INC)
-       $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $<
-
-all: ../$(PROG)
-
-../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto
-       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
-       $(call quiet,CHECK_STACK) ../ao.h $(PMEM)
-
-../altitude.h: make-altitude
-       nickle $< > $@
-
-../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
-       sh $< > $@
-
-ao_product.h: ao-make-product.5c ../Version
-       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-$(REL): ao_product.h
-
-distclean:     clean
-
-clean:
-       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
-       rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
-       rm -f ao_product.h
-       rm -f ../$(PROG)
-
-install:
-
-uninstall:
diff --git a/src/_bp.c b/src/_bp.c
deleted file mode 100644 (file)
index 6bf135b..0000000
--- a/src/_bp.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-------------------------------------------------------------------------
-
-  _bp.c :- just declares bp as a variable
-
-             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
-
-   This library is free software; you can redistribute it and/or modify it
-   under the terms of the GNU Library General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any
-   later version.
-
-   This library 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 Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-   In other words, you are welcome to use, share and improve this program.
-   You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!
--------------------------------------------------------------------------*/
-
-__data unsigned char bp ;
diff --git a/src/altitude.h b/src/altitude.h
deleted file mode 100644 (file)
index a278bbc..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*max error 3.197865153490684 at   0.782%. Average error 0.260150920474668*/
-#define NALT 129
-#define ALT_FRAC_BITS 8
-    15835, /*  10.56 kPa   0.000% */
-    15332, /*  11.42 kPa   0.781% */
-    14868, /*  12.29 kPa   1.563% */
-    14435, /*  13.16 kPa   2.344% */
-    14030, /*  14.02 kPa   3.125% */
-    13649, /*  14.90 kPa   3.906% */
-    13290, /*  15.76 kPa   4.688% */
-    12950, /*  16.63 kPa   5.469% */
-    12627, /*  17.50 kPa   6.250% */
-    12320, /*  18.37 kPa   7.031% */
-    12027, /*  19.24 kPa   7.813% */
-    11747, /*  20.10 kPa   8.594% */
-    11479, /*  20.97 kPa   9.375% */
-    11222, /*  21.84 kPa  10.156% */
-    10975, /*  22.71 kPa  10.938% */
-    10736, /*  23.58 kPa  11.719% */
-    10504, /*  24.44 kPa  12.500% */
-    10278, /*  25.31 kPa  13.281% */
-    10059, /*  26.18 kPa  14.063% */
-     9846, /*  27.05 kPa  14.844% */
-     9638, /*  27.91 kPa  15.625% */
-     9435, /*  28.78 kPa  16.406% */
-     9237, /*  29.65 kPa  17.188% */
-     9044, /*  30.52 kPa  17.969% */
-     8855, /*  31.39 kPa  18.750% */
-     8670, /*  32.26 kPa  19.531% */
-     8490, /*  33.13 kPa  20.313% */
-     8313, /*  33.99 kPa  21.094% */
-     8140, /*  34.86 kPa  21.875% */
-     7970, /*  35.73 kPa  22.656% */
-     7803, /*  36.60 kPa  23.438% */
-     7640, /*  37.47 kPa  24.219% */
-     7480, /*  38.33 kPa  25.000% */
-     7322, /*  39.20 kPa  25.781% */
-     7168, /*  40.07 kPa  26.563% */
-     7016, /*  40.94 kPa  27.344% */
-     6867, /*  41.80 kPa  28.125% */
-     6720, /*  42.67 kPa  28.906% */
-     6575, /*  43.54 kPa  29.688% */
-     6433, /*  44.41 kPa  30.469% */
-     6294, /*  45.28 kPa  31.250% */
-     6156, /*  46.15 kPa  32.031% */
-     6020, /*  47.01 kPa  32.813% */
-     5887, /*  47.88 kPa  33.594% */
-     5755, /*  48.75 kPa  34.375% */
-     5625, /*  49.62 kPa  35.156% */
-     5497, /*  50.49 kPa  35.938% */
-     5371, /*  51.35 kPa  36.719% */
-     5247, /*  52.22 kPa  37.500% */
-     5124, /*  53.09 kPa  38.281% */
-     5003, /*  53.96 kPa  39.063% */
-     4883, /*  54.83 kPa  39.844% */
-     4765, /*  55.69 kPa  40.625% */
-     4648, /*  56.56 kPa  41.406% */
-     4533, /*  57.43 kPa  42.188% */
-     4419, /*  58.30 kPa  42.969% */
-     4307, /*  59.17 kPa  43.750% */
-     4196, /*  60.03 kPa  44.531% */
-     4086, /*  60.90 kPa  45.313% */
-     3977, /*  61.77 kPa  46.094% */
-     3870, /*  62.63 kPa  46.875% */
-     3764, /*  63.51 kPa  47.656% */
-     3659, /*  64.38 kPa  48.438% */
-     3555, /*  65.24 kPa  49.219% */
-     3453, /*  66.11 kPa  50.000% */
-     3351, /*  66.98 kPa  50.781% */
-     3250, /*  67.85 kPa  51.563% */
-     3151, /*  68.72 kPa  52.344% */
-     3052, /*  69.58 kPa  53.125% */
-     2955, /*  70.45 kPa  53.906% */
-     2858, /*  71.32 kPa  54.688% */
-     2763, /*  72.19 kPa  55.469% */
-     2668, /*  73.06 kPa  56.250% */
-     2574, /*  73.92 kPa  57.031% */
-     2482, /*  74.79 kPa  57.813% */
-     2390, /*  75.66 kPa  58.594% */
-     2298, /*  76.52 kPa  59.375% */
-     2208, /*  77.40 kPa  60.156% */
-     2119, /*  78.26 kPa  60.938% */
-     2030, /*  79.13 kPa  61.719% */
-     1942, /*  80.00 kPa  62.500% */
-     1855, /*  80.87 kPa  63.281% */
-     1769, /*  81.74 kPa  64.063% */
-     1683, /*  82.60 kPa  64.844% */
-     1598, /*  83.47 kPa  65.625% */
-     1514, /*  84.34 kPa  66.406% */
-     1430, /*  85.21 kPa  67.188% */
-     1347, /*  86.08 kPa  67.969% */
-     1265, /*  86.94 kPa  68.750% */
-     1184, /*  87.81 kPa  69.531% */
-     1103, /*  88.68 kPa  70.313% */
-     1023, /*  89.55 kPa  71.094% */
-      943, /*  90.41 kPa  71.875% */
-      864, /*  91.28 kPa  72.656% */
-      786, /*  92.15 kPa  73.438% */
-      708, /*  93.02 kPa  74.219% */
-      631, /*  93.89 kPa  75.000% */
-      554, /*  94.76 kPa  75.781% */
-      478, /*  95.63 kPa  76.563% */
-      403, /*  96.49 kPa  77.344% */
-      328, /*  97.36 kPa  78.125% */
-      254, /*  98.23 kPa  78.906% */
-      180, /*  99.10 kPa  79.688% */
-      106, /*  99.97 kPa  80.469% */
-       34, /* 100.83 kPa  81.250% */
-      -39, /* 101.70 kPa  82.031% */
-     -111, /* 102.57 kPa  82.813% */
-     -182, /* 103.44 kPa  83.594% */
-     -253, /* 104.30 kPa  84.375% */
-     -323, /* 105.17 kPa  85.156% */
-     -393, /* 106.04 kPa  85.938% */
-     -462, /* 106.91 kPa  86.719% */
-     -531, /* 107.78 kPa  87.500% */
-     -600, /* 108.65 kPa  88.281% */
-     -668, /* 109.51 kPa  89.063% */
-     -736, /* 110.38 kPa  89.844% */
-     -803, /* 111.25 kPa  90.625% */
-     -870, /* 112.12 kPa  91.406% */
-     -936, /* 112.99 kPa  92.188% */
-    -1002, /* 113.85 kPa  92.969% */
-    -1068, /* 114.72 kPa  93.750% */
-    -1133, /* 115.59 kPa  94.531% */
-    -1198, /* 116.46 kPa  95.313% */
-    -1262, /* 117.33 kPa  96.094% */
-    -1326, /* 118.19 kPa  96.875% */
-    -1389, /* 119.06 kPa  97.656% */
-    -1453, /* 119.93 kPa  98.438% */
-    -1516, /* 120.80 kPa  99.219% */
-    -1578, /* 121.67 kPa 100.000% */
diff --git a/src/ao-make-product.5c b/src/ao-make-product.5c
deleted file mode 100644 (file)
index 5f2eb8e..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/bin/sh
-
-autoimport ParseArgs;
-
-void
-write_ucs2(string a, string description)
-{
-       int len = String::length(a);
-
-       printf("/* %s */\n", description);
-       printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2);
-       printf("#define AO_%s_STRING \"%s\"\n", description, a);
-       printf("#define AO_%s_UCS2", description);
-       for (int i = 0; i < len; i++) {
-               int     c = a[i];
-               if (i > 0)
-                       printf(",");
-               if (0x20 <= c && c < 128)
-                       printf(" '%c', 0", c);
-               else
-                       printf(" LE_WORD(0x%04x),", c);
-       }
-       printf("\n\n");
-}
-
-void
-write_string(string a, string description)
-{
-       printf ("/* %s */\n", description);
-       printf ("#define AO_%s_STRING \"%s\"\n", description, a);
-}
-
-void
-write_int(int a, string description)
-{
-       printf ("/* %s */\n", description);
-       printf ("#define AO_%s_NUMBER %d\n\n", description, a);
-}
-
-void
-write_hex(int a, string description)
-{
-       printf ("/* %s */\n", description);
-       printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a);
-}
-
-string manufacturer = "altusmetrum.org";
-string product = "TeleMetrum";
-string version = "0.0";
-int serial = 1;
-int user_argind = 0;
-int id_product = 0x000a;
-
-argdesc argd = {
-       .args = {
-               {
-                       .var = { .arg_string = &manufacturer },
-                       .abbr = 'm',
-                       .name = "manufacturer",
-                       .expr_name = "manf",
-                       .desc = "Manufacturer name." },
-               {
-                       .var = { .arg_string = &product },
-                       .abbr = 'p',
-                       .name = "product",
-                       .expr_name = "prod",
-                       .desc = "Product name." },
-               {
-                       .var = { .arg_int = &id_product },
-                       .abbr = 'i',
-                       .name = "id_product",
-                       .expr_name = "id_p",
-                       .desc = "Product ID." },
-               {
-                       .var = { .arg_int = &serial },
-                       .abbr = 's',
-                       .name = "serial",
-                       .expr_name = "number",
-                       .desc = "Serial number." },
-               {
-                       .var = { .arg_string = &version },
-                       .abbr = 'v',
-                       .name = "version",
-                       .expr_name = "string",
-                       .desc = "Program version." },
-       },
-       .prog_name = "usb descriptors",
-};
-
-void
-main()
-{
-       string[dim(argv)-1] nargv = {[n] = argv[n+1]};
-       parseargs(&argd, &nargv);
-       write_ucs2(manufacturer, "iManufacturer");
-       write_ucs2(product, "iProduct");
-       write_ucs2(sprintf("%06d", serial), "iSerial");
-       write_int(serial, "iSerial");
-       write_hex(id_product, "idProduct");
-       write_string(version, "iVersion");
-}
-
-main();
diff --git a/src/ao.h b/src/ao.h
deleted file mode 100644 (file)
index 8ac9ac3..0000000
--- a/src/ao.h
+++ /dev/null
@@ -1,1610 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_H_
-#define _AO_H_
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include "cc1111.h"
-#include "ao_pins.h"
-
-#define TRUE 1
-#define FALSE 0
-
-/* Convert a __data pointer into an __xdata pointer */
-#define DATA_TO_XDATA(a)       ((void __xdata *) ((uint8_t) (a) | 0xff00))
-
-/* Stack runs from above the allocated __data space to 0xfe, which avoids
- * writing to 0xff as that triggers the stack overflow indicator
- */
-#define AO_STACK_START 0x90
-#define AO_STACK_END   0xfe
-#define AO_STACK_SIZE  (AO_STACK_END - AO_STACK_START + 1)
-
-/* An AltOS task */
-struct ao_task {
-       __xdata void *wchan;            /* current wait channel (NULL if running) */
-       uint16_t alarm;                 /* abort ao_sleep time */
-       uint8_t stack_count;            /* amount of saved stack */
-       uint8_t task_id;                /* unique id */
-       __code char *name;              /* task name */
-       uint8_t stack[AO_STACK_SIZE];   /* saved stack */
-};
-
-extern __xdata struct ao_task *__data ao_cur_task;
-
-#define AO_NUM_TASKS           16      /* maximum number of tasks */
-#define AO_NO_TASK             0       /* no task id */
-
-/*
- ao_task.c
- */
-
-/* Suspend the current task until wchan is awoken.
- * returns:
- *  0 on normal wake
- *  1 on alarm
- */
-uint8_t
-ao_sleep(__xdata void *wchan);
-
-/* Wake all tasks sleeping on wchan */
-void
-ao_wakeup(__xdata void *wchan);
-
-/* set an alarm to go off in 'delay' ticks */
-void
-ao_alarm(uint16_t delay);
-
-/* Yield the processor to another task */
-void
-ao_yield(void) __naked;
-
-/* Add a task to the run queue */
-void
-ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant;
-
-/* Terminate the current task */
-void
-ao_exit(void);
-
-/* Dump task info to console */
-void
-ao_task_info(void);
-
-/* Start the scheduler. This will not return */
-void
-ao_start_scheduler(void);
-
-/*
- * ao_panic.c
- */
-
-#define AO_PANIC_NO_TASK       1       /* AO_NUM_TASKS is not large enough */
-#define AO_PANIC_DMA           2       /* Attempt to start DMA while active */
-#define AO_PANIC_MUTEX         3       /* Mis-using mutex API */
-#define AO_PANIC_EE            4       /* Mis-using eeprom API */
-#define AO_PANIC_LOG           5       /* Failing to read/write log data */
-#define AO_PANIC_CMD           6       /* Too many command sets registered */
-#define AO_PANIC_STDIO         7       /* Too many stdio handlers registered */
-#define AO_PANIC_REBOOT                8       /* Reboot failed */
-#define AO_PANIC_FLASH         9       /* Invalid flash part (or wrong blocksize) */
-#define AO_PANIC_USB           10      /* Trying to send USB packet while busy */
-#define AO_PANIC_BT            11      /* Communications with bluetooth device failed */
-
-/* Stop the operating system, beeping and blinking the reason */
-void
-ao_panic(uint8_t reason);
-
-/*
- * ao_timer.c
- */
-
-/* Our timer runs at 100Hz */
-#define AO_HERTZ               100
-#define AO_MS_TO_TICKS(ms)     ((ms) / (1000 / AO_HERTZ))
-#define AO_SEC_TO_TICKS(s)     ((s) * AO_HERTZ)
-
-/* Returns the current time in ticks */
-uint16_t
-ao_time(void);
-
-/* Suspend the current task until ticks time has passed */
-void
-ao_delay(uint16_t ticks);
-
-/* Set the ADC interval */
-void
-ao_timer_set_adc_interval(uint8_t interval) __critical;
-
-/* Timer interrupt */
-void
-ao_timer_isr(void) __interrupt 9;
-
-/* Initialize the timer */
-void
-ao_timer_init(void);
-
-/* Initialize the hardware clock. Must be called first */
-void
-ao_clock_init(void);
-
-/*
- * One set of samples read from the A/D converter or telemetry
- */
-struct ao_adc {
-       uint16_t        tick;           /* tick when the sample was read */
-       int16_t         accel;          /* accelerometer */
-       int16_t         pres;           /* pressure sensor */
-       int16_t         temp;           /* temperature sensor */
-       int16_t         v_batt;         /* battery voltage */
-       int16_t         sense_d;        /* drogue continuity sense */
-       int16_t         sense_m;        /* main continuity sense */
-};
-
-#ifndef HAS_ADC
-#error Please define HAS_ADC
-#endif
-
-#if HAS_ADC
-
-#if HAS_ACCEL
-#ifndef HAS_ACCEL_REF
-#error Please define HAS_ACCEL_REF
-#endif
-#else
-#define HAS_ACCEL_REF 0
-#endif
-
-/*
- * ao_adc.c
- */
-
-#define AO_ADC_RING    32
-#define ao_adc_ring_next(n)    (((n) + 1) & (AO_ADC_RING - 1))
-#define ao_adc_ring_prev(n)    (((n) - 1) & (AO_ADC_RING - 1))
-
-
-/*
- * A/D data is stored in a ring, with the next sample to be written
- * at ao_adc_head
- */
-extern volatile __xdata struct ao_adc  ao_adc_ring[AO_ADC_RING];
-extern volatile __data uint8_t         ao_adc_head;
-#if HAS_ACCEL_REF
-extern volatile __xdata uint16_t       ao_accel_ref[AO_ADC_RING];
-#endif
-
-/* Trigger a conversion sequence (called from the timer interrupt) */
-void
-ao_adc_poll(void);
-
-/* Suspend the current task until another A/D sample is converted */
-void
-ao_adc_sleep(void);
-
-/* Get a copy of the last complete A/D sample set */
-void
-ao_adc_get(__xdata struct ao_adc *packet);
-
-/* The A/D interrupt handler */
-
-void
-ao_adc_isr(void) __interrupt 1;
-
-/* Initialize the A/D converter */
-void
-ao_adc_init(void);
-
-#endif /* HAS_ADC */
-
-/*
- * ao_beep.c
- */
-
-/*
- * Various pre-defined beep frequencies
- *
- * frequency = 1/2 (24e6/32) / beep
- */
-
-#define AO_BEEP_LOW    150     /* 2500Hz */
-#define AO_BEEP_MID    94      /* 3989Hz */
-#define AO_BEEP_HIGH   75      /* 5000Hz */
-#define AO_BEEP_OFF    0       /* off */
-
-#define AO_BEEP_g      240     /* 1562.5Hz */
-#define AO_BEEP_gs     227     /* 1652Hz (1655Hz) */
-#define AO_BEEP_aa     214     /* 1752Hz (1754Hz) */
-#define AO_BEEP_bbf    202     /* 1856Hz (1858Hz) */
-#define AO_BEEP_bb     190     /* 1974Hz (1969Hz) */
-#define AO_BEEP_cc     180     /* 2083Hz (2086Hz) */
-#define AO_BEEP_ccs    170     /* 2205Hz (2210Hz) */
-#define AO_BEEP_dd     160     /* 2344Hz (2341Hz) */
-#define AO_BEEP_eef    151     /* 2483Hz (2480Hz) */
-#define AO_BEEP_ee     143     /* 2622Hz (2628Hz) */
-#define AO_BEEP_ff     135     /* 2778Hz (2784Hz) */
-#define AO_BEEP_ffs    127     /* 2953Hz (2950Hz) */
-#define AO_BEEP_gg     120     /* 3125Hz */
-#define AO_BEEP_ggs    113     /* 3319Hz (3311Hz) */
-#define AO_BEEP_aaa    107     /* 3504Hz (3508Hz) */
-#define AO_BEEP_bbbf   101     /* 3713Hz (3716Hz) */
-#define AO_BEEP_bbb    95      /* 3947Hz (3937Hz) */
-#define AO_BEEP_ccc    90      /* 4167Hz (4171Hz) */
-#define AO_BEEP_cccs   85      /* 4412Hz (4419Hz) */
-#define AO_BEEP_ddd    80      /* 4688Hz (4682Hz) */
-#define AO_BEEP_eeef   76      /* 4934Hz (4961Hz) */
-#define AO_BEEP_eee    71      /* 5282Hz (5256Hz) */
-#define AO_BEEP_fff    67      /* 5597Hz (5568Hz) */
-#define AO_BEEP_fffs   64      /* 5859Hz (5899Hz) */
-#define AO_BEEP_ggg    60      /* 6250Hz */
-
-/* Set the beeper to the specified tone */
-void
-ao_beep(uint8_t beep);
-
-/* Turn on the beeper for the specified time */
-void
-ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant;
-
-/* Initialize the beeper */
-void
-ao_beep_init(void);
-
-/*
- * ao_led.c
- */
-
-#define AO_LED_NONE    0
-
-/* Turn on the specified LEDs */
-void
-ao_led_on(uint8_t colors);
-
-/* Turn off the specified LEDs */
-void
-ao_led_off(uint8_t colors);
-
-/* Set all of the LEDs to the specified state */
-void
-ao_led_set(uint8_t colors);
-
-/* Toggle the specified LEDs */
-void
-ao_led_toggle(uint8_t colors);
-
-/* Turn on the specified LEDs for the indicated interval */
-void
-ao_led_for(uint8_t colors, uint16_t ticks) __reentrant;
-
-/* Initialize the LEDs */
-void
-ao_led_init(uint8_t enable);
-
-/*
- * ao_romconfig.c
- */
-
-#define AO_ROMCONFIG_VERSION   2
-
-extern __code __at (0x00a0) uint16_t ao_romconfig_version;
-extern __code __at (0x00a2) uint16_t ao_romconfig_check;
-extern __code __at (0x00a4) uint16_t ao_serial_number;
-extern __code __at (0x00a6) uint32_t ao_radio_cal;
-
-#ifndef HAS_USB
-#error Please define HAS_USB
-#endif
-
-#if HAS_USB
-extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
-#endif
-
-/*
- * ao_usb.c
- */
-
-/* Put one character to the USB output queue */
-void
-ao_usb_putchar(char c);
-
-/* Get one character from the USB input queue */
-char
-ao_usb_getchar(void);
-
-/* Poll for a charcter on the USB input queue.
- * returns AO_READ_AGAIN if none are available
- */
-char
-ao_usb_pollchar(void);
-
-/* Flush the USB output queue */
-void
-ao_usb_flush(void);
-
-#if HAS_USB
-/* USB interrupt handler */
-void
-ao_usb_isr(void) __interrupt 6;
-#endif
-
-/* Enable the USB controller */
-void
-ao_usb_enable(void);
-
-/* Disable the USB controller */
-void
-ao_usb_disable(void);
-
-/* Initialize the USB system */
-void
-ao_usb_init(void);
-
-/*
- * ao_cmd.c
- */
-
-enum ao_cmd_status {
-       ao_cmd_success = 0,
-       ao_cmd_lex_error = 1,
-       ao_cmd_syntax_error = 2,
-};
-
-extern __pdata uint16_t ao_cmd_lex_i;
-extern __pdata uint32_t ao_cmd_lex_u32;
-extern __pdata char    ao_cmd_lex_c;
-extern __pdata enum ao_cmd_status ao_cmd_status;
-
-void
-ao_cmd_lex(void);
-
-void
-ao_cmd_put8(uint8_t v);
-
-void
-ao_cmd_put16(uint16_t v);
-
-void
-ao_cmd_white(void);
-
-void
-ao_cmd_hex(void);
-
-void
-ao_cmd_decimal(void);
-
-uint8_t
-ao_match_word(__code char *word);
-
-struct ao_cmds {
-       void            (*func)(void);
-       __code char     *help;
-};
-
-void
-ao_cmd_register(__code struct ao_cmds *cmds);
-
-void
-ao_cmd_init(void);
-
-#if HAS_CMD_FILTER
-/*
- * Provided by an external module to filter raw command lines
- */
-uint8_t
-ao_cmd_filter(void);
-#endif
-
-/*
- * ao_dma.c
- */
-
-/* Allocate a DMA channel. the 'done' parameter will be set when the
- * dma is finished and will be used to wakeup any waiters
- */
-
-uint8_t
-ao_dma_alloc(__xdata uint8_t * done);
-
-/* Setup a DMA channel */
-void
-ao_dma_set_transfer(uint8_t id,
-                   void __xdata *srcaddr,
-                   void __xdata *dstaddr,
-                   uint16_t count,
-                   uint8_t cfg0,
-                   uint8_t cfg1);
-
-/* Start a DMA channel */
-void
-ao_dma_start(uint8_t id);
-
-/* Manually trigger a DMA channel */
-void
-ao_dma_trigger(uint8_t id);
-
-/* Abort a running DMA transfer */
-void
-ao_dma_abort(uint8_t id);
-
-/* DMA interrupt routine */
-void
-ao_dma_isr(void) __interrupt 8;
-
-/*
- * ao_mutex.c
- */
-
-void
-ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
-
-void
-ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant;
-
-/*
- * Storage interface, provided by one of the eeprom or flash
- * drivers
- */
-
-/* Total bytes of available storage */
-extern __pdata uint32_t        ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-extern __pdata uint32_t        ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-extern __pdata uint32_t        ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-extern __pdata uint16_t ao_storage_unit;
-
-#define AO_STORAGE_ERASE_LOG   (ao_storage_config + AO_CONFIG_MAX_SIZE)
-
-/* Initialize above values. Can only be called once the OS is running */
-void
-ao_storage_setup(void) __reentrant;
-
-/* Write data. Returns 0 on failure, 1 on success */
-uint8_t
-ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Read data. Returns 0 on failure, 1 on success */
-uint8_t
-ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Erase a block of storage. This always clears ao_storage_block bytes */
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant;
-
-/* Flush any pending writes to stable storage */
-void
-ao_storage_flush(void) __reentrant;
-
-/* Initialize the storage code */
-void
-ao_storage_init(void);
-
-/*
- * Low-level functions wrapped by ao_storage.c
- */
-
-/* Read data within a storage unit */
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Write data within a storage unit */
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
-
-/* Initialize low-level device bits */
-void
-ao_storage_device_init(void);
-
-/* Print out information about flash chips */
-void
-ao_storage_device_info(void) __reentrant;
-
-/*
- * ao_log.c
- */
-
-/* We record flight numbers in the first record of
- * the log. Tasks may wait for this to be initialized
- * by sleeping on this variable.
- */
-extern __xdata uint16_t ao_flight_number;
-
-extern __pdata uint32_t ao_log_current_pos;
-extern __pdata uint32_t ao_log_end_pos;
-extern __pdata uint32_t ao_log_start_pos;
-extern __xdata uint8_t ao_log_running;
-extern __pdata enum flight_state ao_log_state;
-
-/* required functions from the underlying log system */
-
-#define AO_LOG_FORMAT_UNKNOWN          0       /* unknown; altosui will have to guess */
-#define AO_LOG_FORMAT_FULL             1       /* 8 byte typed log records */
-#define AO_LOG_FORMAT_TINY             2       /* two byte state/baro records */
-#define AO_LOG_FORMAT_TELEMETRY                3       /* 32 byte ao_telemetry records */
-#define AO_LOG_FORMAT_TELESCIENCE      4       /* 32 byte typed telescience records */
-#define AO_LOG_FORMAT_NONE             127     /* No log at all */
-
-extern __code uint8_t ao_log_format;
-
-/* Return the flight number from the given log slot, 0 if none */
-uint16_t
-ao_log_flight(uint8_t slot);
-
-/* Flush the log */
-void
-ao_log_flush(void);
-
-/* Logging thread main routine */
-void
-ao_log(void);
-
-/* functions provided in ao_log.c */
-
-/* Figure out the current flight number */
-void
-ao_log_scan(void) __reentrant;
-
-/* Return the position of the start of the given log slot */
-uint32_t
-ao_log_pos(uint8_t slot);
-
-/* Start logging to eeprom */
-void
-ao_log_start(void);
-
-/* Stop logging */
-void
-ao_log_stop(void);
-
-/* Initialize the logging system */
-void
-ao_log_init(void);
-
-/* Write out the current flight number to the erase log */
-void
-ao_log_write_erase(uint8_t pos);
-
-/* Returns true if there are any logs stored in eeprom */
-uint8_t
-ao_log_present(void);
-
-/* Returns true if there is no more storage space available */
-uint8_t
-ao_log_full(void);
-
-/*
- * ao_log_big.c
- */
-
-/*
- * The data log is recorded in the eeprom as a sequence
- * of data packets.
- *
- * Each packet starts with a 4-byte header that has the
- * packet type, the packet checksum and the tick count. Then
- * they all contain 2 16 bit values which hold packet-specific
- * data.
- *
- * For each flight, the first packet
- * is FLIGHT packet, indicating the serial number of the
- * device and a unique number marking the number of flights
- * recorded by this device.
- *
- * During flight, data from the accelerometer and barometer
- * are recorded in SENSOR packets, using the raw 16-bit values
- * read from the A/D converter.
- *
- * Also during flight, but at a lower rate, the deployment
- * sensors are recorded in DEPLOY packets. The goal here is to
- * detect failure in the deployment circuits.
- *
- * STATE packets hold state transitions as the flight computer
- * transitions through different stages of the flight.
- */
-#define AO_LOG_FLIGHT          'F'
-#define AO_LOG_SENSOR          'A'
-#define AO_LOG_TEMP_VOLT       'T'
-#define AO_LOG_DEPLOY          'D'
-#define AO_LOG_STATE           'S'
-#define AO_LOG_GPS_TIME                'G'
-#define AO_LOG_GPS_LAT         'N'
-#define AO_LOG_GPS_LON         'W'
-#define AO_LOG_GPS_ALT         'H'
-#define AO_LOG_GPS_SAT         'V'
-#define AO_LOG_GPS_DATE                'Y'
-
-#define AO_LOG_POS_NONE                (~0UL)
-
-struct ao_log_record {
-       char                    type;
-       uint8_t                 csum;
-       uint16_t                tick;
-       union {
-               struct {
-                       int16_t         ground_accel;
-                       uint16_t        flight;
-               } flight;
-               struct {
-                       int16_t         accel;
-                       int16_t         pres;
-               } sensor;
-               struct {
-                       int16_t         temp;
-                       int16_t         v_batt;
-               } temp_volt;
-               struct {
-                       int16_t         drogue;
-                       int16_t         main;
-               } deploy;
-               struct {
-                       uint16_t        state;
-                       uint16_t        reason;
-               } state;
-               struct {
-                       uint8_t         hour;
-                       uint8_t         minute;
-                       uint8_t         second;
-                       uint8_t         flags;
-               } gps_time;
-               int32_t         gps_latitude;
-               int32_t         gps_longitude;
-               struct {
-                       int16_t         altitude;
-                       uint16_t        unused;
-               } gps_altitude;
-               struct {
-                       uint16_t        svid;
-                       uint8_t         unused;
-                       uint8_t         c_n;
-               } gps_sat;
-               struct {
-                       uint8_t         year;
-                       uint8_t         month;
-                       uint8_t         day;
-                       uint8_t         extra;
-               } gps_date;
-               struct {
-                       uint16_t        d0;
-                       uint16_t        d1;
-               } anon;
-       } u;
-};
-
-/* Write a record to the eeprom log */
-uint8_t
-ao_log_data(__xdata struct ao_log_record *log) __reentrant;
-
-/*
- * ao_flight.c
- */
-
-enum ao_flight_state {
-       ao_flight_startup = 0,
-       ao_flight_idle = 1,
-       ao_flight_pad = 2,
-       ao_flight_boost = 3,
-       ao_flight_fast = 4,
-       ao_flight_coast = 5,
-       ao_flight_drogue = 6,
-       ao_flight_main = 7,
-       ao_flight_landed = 8,
-       ao_flight_invalid = 9
-};
-
-extern __pdata enum ao_flight_state    ao_flight_state;
-
-extern __pdata uint16_t                        ao_launch_time;
-extern __pdata uint8_t                 ao_flight_force_idle;
-
-/* Flight thread */
-void
-ao_flight(void);
-
-/* Initialize flight thread */
-void
-ao_flight_init(void);
-
-/*
- * ao_flight_nano.c
- */
-
-void
-ao_flight_nano_init(void);
-
-/*
- * ao_sample.c
- */
-
-/*
- * Barometer calibration
- *
- * We directly sample the barometer. The specs say:
- *
- * Pressure range: 15-115 kPa
- * Voltage at 115kPa: 2.82
- * Output scale: 27mV/kPa
- *
- * If we want to detect launch with the barometer, we need
- * a large enough bump to not be fooled by noise. At typical
- * launch elevations (0-2000m), a 200Pa pressure change cooresponds
- * to about a 20m elevation change. This is 5.4mV, or about 3LSB.
- * As all of our calculations are done in 16 bits, we'll actually see a change
- * of 16 times this though
- *
- * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa
- */
-
-/* Accelerometer calibration
- *
- * We're sampling the accelerometer through a resistor divider which
- * consists of 5k and 10k resistors. This multiplies the values by 2/3.
- * That goes into the cc1111 A/D converter, which is running at 11 bits
- * of precision with the bits in the MSB of the 16 bit value. Only positive
- * values are used, so values should range from 0-32752 for 0-3.3V. The
- * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what
- * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV,
- * for a final computation of:
- *
- * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g
- *
- * Zero g was measured at 16000 (we would expect 16384).
- * Note that this value is only require to tell if the
- * rocket is standing upright. Once that is determined,
- * the value of the accelerometer is averaged for 100 samples
- * to find the resting accelerometer value, which is used
- * for all further flight computations
- */
-
-#define GRAVITY 9.80665
-
-/*
- * Above this height, the baro sensor doesn't work
- */
-#define AO_MAX_BARO_HEIGHT     12000
-
-/*
- * Above this speed, baro measurements are unreliable
- */
-#define AO_MAX_BARO_SPEED      200
-
-#define ACCEL_NOSE_UP  (ao_accel_2g >> 2)
-
-/*
- * Speed and acceleration are scaled by 16 to provide a bit more
- * resolution while still having reasonable range. Note that this
- * limits speed to 2047m/s (around mach 6) and acceleration to
- * 2047m/s² (over 200g)
- */
-
-#define AO_M_TO_HEIGHT(m)      ((int16_t) (m))
-#define AO_MS_TO_SPEED(ms)     ((int16_t) ((ms) * 16))
-#define AO_MSS_TO_ACCEL(mss)   ((int16_t) ((mss) * 16))
-
-extern __pdata uint16_t        ao_sample_tick;         /* time of last data */
-extern __pdata int16_t ao_sample_pres;         /* most recent pressure sensor reading */
-extern __pdata int16_t ao_sample_alt;          /* MSL of ao_sample_pres */
-extern __pdata int16_t ao_sample_height;       /* AGL of ao_sample_pres */
-extern __data uint8_t  ao_sample_adc;          /* Ring position of last processed sample */
-
-#if HAS_ACCEL
-extern __pdata int16_t ao_sample_accel;        /* most recent accel sensor reading */
-#endif
-
-extern __pdata int16_t ao_ground_pres;         /* startup pressure */
-extern __pdata int16_t ao_ground_height;       /* MSL of ao_ground_pres */
-
-#if HAS_ACCEL
-extern __pdata int16_t ao_ground_accel;        /* startup acceleration */
-extern __pdata int16_t         ao_accel_2g;            /* factory accel calibration */
-extern __pdata int32_t ao_accel_scale;         /* sensor to m/s² conversion */
-#endif
-
-void ao_sample_init(void);
-
-/* returns FALSE in preflight mode, TRUE in flight mode */
-uint8_t ao_sample(void);
-
-/*
- * ao_kalman.c
- */
-
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
-#define from_fix(x)    ((x) >> 16)
-
-extern __pdata int16_t                 ao_height;      /* meters */
-extern __pdata int16_t                 ao_speed;       /* m/s * 16 */
-extern __pdata int16_t                 ao_accel;       /* m/s² * 16 */
-extern __pdata int16_t                 ao_max_height;  /* max of ao_height */
-extern __pdata int16_t                 ao_avg_height;  /* running average of height */
-
-extern __pdata int16_t                 ao_error_h;
-extern __pdata int16_t                 ao_error_h_sq_avg;
-
-#if HAS_ACCEL
-extern __pdata int16_t                 ao_error_a;
-#endif
-
-void ao_kalman(void);
-
-/*
- * ao_report.c
- */
-
-void
-ao_report_init(void);
-
-/*
- * ao_convert.c
- *
- * Given raw data, convert to SI units
- */
-
-/* pressure from the sensor to altitude in meters */
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant;
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant;
-
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant;
-
-/*
- * ao_dbg.c
- *
- * debug another telemetrum board
- */
-
-/* Send a byte to the dbg target */
-void
-ao_dbg_send_byte(uint8_t byte);
-
-/* Receive a byte from the dbg target */
-uint8_t
-ao_dbg_recv_byte(void);
-
-/* Start a bulk transfer to/from dbg target memory */
-void
-ao_dbg_start_transfer(uint16_t addr);
-
-/* End a bulk transfer to/from dbg target memory */
-void
-ao_dbg_end_transfer(void);
-
-/* Write a byte to dbg target memory */
-void
-ao_dbg_write_byte(uint8_t byte);
-
-/* Read a byte from dbg target memory */
-uint8_t
-ao_dbg_read_byte(void);
-
-/* Enable dbg mode, switching use of the pins */
-void
-ao_dbg_debug_mode(void);
-
-/* Reset the dbg target */
-void
-ao_dbg_reset(void);
-
-void
-ao_dbg_init(void);
-
-/*
- * ao_serial.c
- */
-
-#ifndef HAS_SERIAL_1
-#error Please define HAS_SERIAL_1
-#endif
-
-#if HAS_SERIAL_1
-#ifndef USE_SERIAL_STDIN
-#error Please define USE_SERIAL_STDIN
-#endif
-
-void
-ao_serial_rx1_isr(void) __interrupt 3;
-
-void
-ao_serial_tx1_isr(void) __interrupt 14;
-
-char
-ao_serial_getchar(void) __critical;
-
-#if USE_SERIAL_STDIN
-char
-ao_serial_pollchar(void) __critical;
-
-void
-ao_serial_set_stdin(uint8_t stdin);
-#endif
-
-void
-ao_serial_putchar(char c) __critical;
-
-void
-ao_serial_drain(void) __critical;
-
-#define AO_SERIAL_SPEED_4800   0
-#define AO_SERIAL_SPEED_9600   1
-#define AO_SERIAL_SPEED_19200  2
-#define AO_SERIAL_SPEED_57600  3
-
-void
-ao_serial_set_speed(uint8_t speed);
-
-void
-ao_serial_init(void);
-#endif
-
-/*
- * ao_spi.c
- */
-
-extern __xdata uint8_t ao_spi_mutex;
-
-#define ao_spi_get_mask(reg,mask) do {\
-       ao_mutex_get(&ao_spi_mutex); \
-       (reg) &= ~(mask); \
-       } while (0)
-
-#define ao_spi_put_mask(reg,mask) do { \
-       (reg) |= (mask); \
-       ao_mutex_put(&ao_spi_mutex); \
-       } while (0)
-
-#define ao_spi_get_bit(bit) do {\
-       ao_mutex_get(&ao_spi_mutex); \
-       (bit) = 0; \
-       } while (0)
-
-#define ao_spi_put_bit(bit) do { \
-       (bit) = 1; \
-       ao_mutex_put(&ao_spi_mutex); \
-       } while (0)
-
-/*
- * The SPI mutex must be held to call either of these
- * functions -- this mutex covers the entire SPI operation,
- * from chip select low to chip select high
- */
-
-void
-ao_spi_send(void __xdata *block, uint16_t len) __reentrant;
-
-void
-ao_spi_recv(void __xdata *block, uint16_t len) __reentrant;
-
-void
-ao_spi_init(void);
-
-/*
- * ao_telemetry.c
- */
-#define AO_MAX_CALLSIGN                        8
-#define AO_MAX_VERSION                 8
-#define AO_MAX_TELEMETRY               128
-
-struct ao_telemetry_generic {
-       uint16_t        serial;         /* 0 */
-       uint16_t        tick;           /* 2 */
-       uint8_t         type;           /* 4 */
-       uint8_t         payload[27];    /* 5 */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01
-#define AO_TELEMETRY_SENSOR_TELEMINI   0x02
-#define AO_TELEMETRY_SENSOR_TELENANO   0x03
-
-struct ao_telemetry_sensor {
-       uint16_t        serial;         /*  0 */
-       uint16_t        tick;           /*  2 */
-       uint8_t         type;           /*  4 */
-
-       uint8_t         state;          /*  5 flight state */
-       int16_t         accel;          /*  6 accelerometer (TM only) */
-       int16_t         pres;           /*  8 pressure sensor */
-       int16_t         temp;           /* 10 temperature sensor */
-       int16_t         v_batt;         /* 12 battery voltage */
-       int16_t         sense_d;        /* 14 drogue continuity sense (TM/Tm) */
-       int16_t         sense_m;        /* 16 main continuity sense (TM/Tm) */
-
-       int16_t         acceleration;   /* 18 m/s² * 16 */
-       int16_t         speed;          /* 20 m/s * 16 */
-       int16_t         height;         /* 22 m */
-
-       int16_t         ground_pres;    /* 24 average pres on pad */
-       int16_t         ground_accel;   /* 26 average accel on pad */
-       int16_t         accel_plus_g;   /* 28 accel calibration at +1g */
-       int16_t         accel_minus_g;  /* 30 accel calibration at -1g */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_CONFIGURATION     0x04
-
-struct ao_telemetry_configuration {
-       uint16_t        serial;                         /*  0 */
-       uint16_t        tick;                           /*  2 */
-       uint8_t         type;                           /*  4 */
-
-       uint8_t         device;                         /*  5 device type */
-       uint16_t        flight;                         /*  6 flight number */
-       uint8_t         config_major;                   /*  8 Config major version */
-       uint8_t         config_minor;                   /*  9 Config minor version */
-       uint16_t        apogee_delay;                   /* 10 Apogee deploy delay in seconds */
-       uint16_t        main_deploy;                    /* 12 Main deploy alt in meters */
-       uint16_t        flight_log_max;                 /* 14 Maximum flight log size in kB */
-       char            callsign[AO_MAX_CALLSIGN];      /* 16 Radio operator identity */
-       char            version[AO_MAX_VERSION];        /* 24 Software version */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_LOCATION          0x05
-
-#define AO_GPS_MODE_NOT_VALID          'N'
-#define AO_GPS_MODE_AUTONOMOUS         'A'
-#define AO_GPS_MODE_DIFFERENTIAL       'D'
-#define AO_GPS_MODE_ESTIMATED          'E'
-#define AO_GPS_MODE_MANUAL             'M'
-#define AO_GPS_MODE_SIMULATED          'S'
-
-struct ao_telemetry_location {
-       uint16_t        serial;         /*  0 */
-       uint16_t        tick;           /*  2 */
-       uint8_t         type;           /*  4 */
-
-       uint8_t         flags;          /*  5 Number of sats and other flags */
-       int16_t         altitude;       /*  6 GPS reported altitude (m) */
-       int32_t         latitude;       /*  8 latitude (degrees * 10⁷) */
-       int32_t         longitude;      /* 12 longitude (degrees * 10⁷) */
-       uint8_t         year;           /* 16 (- 2000) */
-       uint8_t         month;          /* 17 (1-12) */
-       uint8_t         day;            /* 18 (1-31) */
-       uint8_t         hour;           /* 19 (0-23) */
-       uint8_t         minute;         /* 20 (0-59) */
-       uint8_t         second;         /* 21 (0-59) */
-       uint8_t         pdop;           /* 22 (m * 5) */
-       uint8_t         hdop;           /* 23 (m * 5) */
-       uint8_t         vdop;           /* 24 (m * 5) */
-       uint8_t         mode;           /* 25 */
-       uint16_t        ground_speed;   /* 26 cm/s */
-       int16_t         climb_rate;     /* 28 cm/s */
-       uint8_t         course;         /* 30 degrees / 2 */
-       uint8_t         unused[1];      /* 31 */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_SATELLITE         0x06
-
-struct ao_telemetry_satellite_info {
-       uint8_t         svid;
-       uint8_t         c_n_1;
-};
-
-struct ao_telemetry_satellite {
-       uint16_t                                serial;         /*  0 */
-       uint16_t                                tick;           /*  2 */
-       uint8_t                                 type;           /*  4 */
-       uint8_t                                 channels;       /*  5 number of reported sats */
-
-       struct ao_telemetry_satellite_info      sats[12];       /* 6 */
-       uint8_t                                 unused[2];      /* 30 */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_COMPANION         0x07
-
-#define AO_COMPANION_MAX_CHANNELS      12
-
-struct ao_telemetry_companion {
-       uint16_t                                serial;         /*  0 */
-       uint16_t                                tick;           /*  2 */
-       uint8_t                                 type;           /*  4 */
-       uint8_t                                 board_id;       /*  5 */
-
-       uint8_t                                 update_period;  /*  6 */
-       uint8_t                                 channels;       /*  7 */
-       uint16_t                                companion_data[AO_COMPANION_MAX_CHANNELS];      /*  8 */
-       /* 32 */
-};
-       
-union ao_telemetry_all {
-       struct ao_telemetry_generic             generic;
-       struct ao_telemetry_sensor              sensor;
-       struct ao_telemetry_configuration       configuration;
-       struct ao_telemetry_location            location;
-       struct ao_telemetry_satellite           satellite;
-       struct ao_telemetry_companion           companion;
-};
-
-/*
- * ao_gps.c
- */
-
-#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
-#define AO_GPS_NUM_SAT_SHIFT   (0)
-
-#define AO_GPS_VALID           (1 << 4)
-#define AO_GPS_RUNNING         (1 << 5)
-#define AO_GPS_DATE_VALID      (1 << 6)
-#define AO_GPS_COURSE_VALID    (1 << 7)
-
-extern __pdata uint16_t ao_gps_tick;
-extern __xdata uint8_t ao_gps_mutex;
-extern __xdata struct ao_telemetry_location ao_gps_data;
-extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data;
-
-struct ao_gps_orig {
-       uint8_t                 year;
-       uint8_t                 month;
-       uint8_t                 day;
-       uint8_t                 hour;
-       uint8_t                 minute;
-       uint8_t                 second;
-       uint8_t                 flags;
-       int32_t                 latitude;       /* degrees * 10⁷ */
-       int32_t                 longitude;      /* degrees * 10⁷ */
-       int16_t                 altitude;       /* m */
-       uint16_t                ground_speed;   /* cm/s */
-       uint8_t                 course;         /* degrees / 2 */
-       uint8_t                 hdop;           /* * 5 */
-       int16_t                 climb_rate;     /* cm/s */
-       uint16_t                h_error;        /* m */
-       uint16_t                v_error;        /* m */
-};
-
-struct ao_gps_sat_orig {
-       uint8_t         svid;
-       uint8_t         c_n_1;
-};
-
-#define AO_MAX_GPS_TRACKING    12
-
-struct ao_gps_tracking_orig {
-       uint8_t                 channels;
-       struct ao_gps_sat_orig  sats[AO_MAX_GPS_TRACKING];
-};
-
-void
-ao_gps(void);
-
-void
-ao_gps_print(__xdata struct ao_gps_orig *gps_data);
-
-void
-ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data);
-
-void
-ao_gps_init(void);
-
-/*
- * ao_gps_report.c
- */
-
-void
-ao_gps_report(void);
-
-void
-ao_gps_report_init(void);
-
-/*
- * ao_telemetry_orig.c
- */
-
-struct ao_telemetry_orig {
-       uint16_t                serial;
-       uint16_t                flight;
-       uint8_t                 flight_state;
-       int16_t                 accel;
-       int16_t                 ground_accel;
-       union {
-               struct {
-                       int16_t                 speed;
-                       int16_t                 unused;
-               } k;
-               int32_t         flight_vel;
-       } u;
-       int16_t                 height;
-       int16_t                 ground_pres;
-       int16_t                 accel_plus_g;
-       int16_t                 accel_minus_g;
-       struct ao_adc           adc;
-       struct ao_gps_orig      gps;
-       char                    callsign[AO_MAX_CALLSIGN];
-       struct ao_gps_tracking_orig     gps_tracking;
-};
-
-struct ao_telemetry_tiny {
-       uint16_t                serial;
-       uint16_t                flight;
-       uint8_t                 flight_state;
-       int16_t                 height;         /* AGL in meters */
-       int16_t                 speed;          /* in m/s * 16 */
-       int16_t                 accel;          /* in m/s² * 16 */
-       int16_t                 ground_pres;    /* sensor units */
-       struct ao_adc           adc;            /* raw ADC readings */
-       char                    callsign[AO_MAX_CALLSIGN];
-};
-
-/*
- * ao_radio_recv tacks on rssi and status bytes
- */
-
-struct ao_telemetry_raw_recv {
-       uint8_t                 packet[AO_MAX_TELEMETRY + 2];
-};
-
-struct ao_telemetry_orig_recv {
-       struct ao_telemetry_orig        telemetry_orig;
-       int8_t                          rssi;
-       uint8_t                         status;
-};
-
-struct ao_telemetry_tiny_recv {
-       struct ao_telemetry_tiny        telemetry_tiny;
-       int8_t                          rssi;
-       uint8_t                         status;
-};
-
-/* Set delay between telemetry reports (0 to disable) */
-
-#define AO_TELEMETRY_INTERVAL_PAD      AO_MS_TO_TICKS(1000)
-#define AO_TELEMETRY_INTERVAL_FLIGHT   AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_RECOVER  AO_MS_TO_TICKS(1000)
-
-void
-ao_telemetry_set_interval(uint16_t interval);
-
-void
-ao_rdf_set(uint8_t rdf);
-
-void
-ao_telemetry_init(void);
-
-void
-ao_telemetry_orig_init(void);
-
-void
-ao_telemetry_tiny_init(void);
-
-/*
- * ao_radio.c
- */
-
-extern __xdata uint8_t ao_radio_dma;
-extern __xdata uint8_t ao_radio_dma_done;
-extern __xdata uint8_t ao_radio_done;
-extern __xdata uint8_t ao_radio_mutex;
-
-void
-ao_radio_general_isr(void) __interrupt 16;
-
-void
-ao_radio_get(uint8_t len);
-
-#define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
-
-void
-ao_radio_set_packet(void);
-
-void
-ao_radio_send(__xdata void *data, uint8_t size) __reentrant;
-
-uint8_t
-ao_radio_recv(__xdata void *data, uint8_t size) __reentrant;
-
-void
-ao_radio_recv_abort(void);
-
-void
-ao_radio_rdf(int ms);
-
-void
-ao_radio_rdf_abort(void);
-
-void
-ao_radio_idle(void);
-
-void
-ao_radio_init(void);
-
-/*
- * ao_monitor.c
- */
-
-extern const char const * const ao_state_names[];
-
-void
-ao_monitor(void);
-
-#define AO_MONITORING_OFF      0
-#define AO_MONITORING_ORIG     1
-#define AO_MONITORING_TINY     2
-
-void
-ao_set_monitor(uint8_t monitoring);
-
-void
-ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant;
-
-/*
- * ao_stdio.c
- */
-
-#define AO_READ_AGAIN  ((char) -1)
-
-struct ao_stdio {
-       char    (*pollchar)(void);
-       void    (*putchar)(char c) __reentrant;
-       void    (*flush)(void);
-       uint8_t echo;
-};
-
-extern __xdata struct ao_stdio ao_stdios[];
-extern __pdata int8_t ao_cur_stdio;
-extern __pdata int8_t ao_num_stdios;
-
-void
-flush(void);
-
-extern __xdata uint8_t ao_stdin_ready;
-
-uint8_t
-ao_echo(void);
-
-int8_t
-ao_add_stdio(char (*pollchar)(void),
-            void (*putchar)(char) __reentrant,
-            void (*flush)(void)) __reentrant;
-
-/*
- * ao_ignite.c
- */
-
-enum ao_igniter {
-       ao_igniter_drogue = 0,
-       ao_igniter_main = 1
-};
-
-void
-ao_ignite(enum ao_igniter igniter);
-
-enum ao_igniter_status {
-       ao_igniter_unknown,     /* unknown status (ambiguous voltage) */
-       ao_igniter_ready,       /* continuity detected */
-       ao_igniter_active,      /* igniter firing */
-       ao_igniter_open,        /* open circuit detected */
-};
-
-enum ao_igniter_status
-ao_igniter_status(enum ao_igniter igniter);
-
-void
-ao_ignite_set_pins(void);
-
-void
-ao_igniter_init(void);
-
-/*
- * ao_config.c
- */
-
-#define AO_CONFIG_MAJOR        1
-#define AO_CONFIG_MINOR        8
-
-struct ao_config {
-       uint8_t         major;
-       uint8_t         minor;
-       uint16_t        main_deploy;
-       int16_t         accel_plus_g;           /* changed for minor version 2 */
-       uint8_t         radio_channel;
-       char            callsign[AO_MAX_CALLSIGN + 1];
-       uint8_t         apogee_delay;           /* minor version 1 */
-       int16_t         accel_minus_g;          /* minor version 2 */
-       uint32_t        radio_cal;              /* minor version 3 */
-       uint32_t        flight_log_max;         /* minor version 4 */
-       uint8_t         ignite_mode;            /* minor version 5 */
-       uint8_t         pad_orientation;        /* minor version 6 */
-       uint32_t        radio_setting;          /* minor version 7 */
-       uint8_t         radio_enable;           /* minor version 8 */
-};
-
-#define AO_IGNITE_MODE_DUAL            0
-#define AO_IGNITE_MODE_APOGEE          1
-#define AO_IGNITE_MODE_MAIN            2
-
-#define AO_PAD_ORIENTATION_ANTENNA_UP  0
-#define AO_PAD_ORIENTATION_ANTENNA_DOWN        1
-
-extern __xdata struct ao_config ao_config;
-
-#define AO_CONFIG_MAX_SIZE     128
-
-void
-ao_config_get(void);
-
-void
-ao_config_put(void);
-
-void
-ao_config_init(void);
-
-/*
- * ao_rssi.c
- */
-
-void
-ao_rssi_set(int rssi_value);
-
-void
-ao_rssi_init(uint8_t rssi_led);
-
-/*
- * ao_product.c
- *
- * values which need to be defined for
- * each instance of a product
- */
-
-extern const char ao_version[];
-extern const char ao_manufacturer[];
-extern const char ao_product[];
-
-/*
- * Fifos
- */
-
-#define AO_FIFO_SIZE   32
-
-struct ao_fifo {
-       uint8_t insert;
-       uint8_t remove;
-       char    fifo[AO_FIFO_SIZE];
-};
-
-#define ao_fifo_insert(f,c) do { \
-       (f).fifo[(f).insert] = (c); \
-       (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \
-} while(0)
-
-#define ao_fifo_remove(f,c) do {\
-       c = (f).fifo[(f).remove]; \
-       (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \
-} while(0)
-
-#define ao_fifo_full(f)                ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
-#define ao_fifo_empty(f)       ((f).insert == (f).remove)
-
-/*
- * ao_packet.c
- *
- * Packet-based command interface
- */
-
-#define AO_PACKET_MAX          64
-#define AO_PACKET_SYN          (uint8_t) 0xff
-
-struct ao_packet {
-       uint8_t         addr;
-       uint8_t         len;
-       uint8_t         seq;
-       uint8_t         ack;
-       uint8_t         d[AO_PACKET_MAX];
-       uint8_t         callsign[AO_MAX_CALLSIGN];
-};
-
-struct ao_packet_recv {
-       struct ao_packet        packet;
-       int8_t                  rssi;
-       uint8_t                 status;
-};
-
-extern __xdata struct ao_packet_recv ao_rx_packet;
-extern __xdata struct ao_packet ao_tx_packet;
-extern __xdata struct ao_task  ao_packet_task;
-extern __xdata uint8_t ao_packet_enable;
-extern __xdata uint8_t ao_packet_master_sleeping;
-extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
-
-void
-ao_packet_send(void);
-
-uint8_t
-ao_packet_recv(void);
-
-void
-ao_packet_flush(void);
-
-void
-ao_packet_putchar(char c) __reentrant;
-
-char
-ao_packet_pollchar(void) __critical;
-
-/* ao_packet_master.c */
-
-void
-ao_packet_master_init(void);
-
-/* ao_packet_slave.c */
-
-void
-ao_packet_slave_start(void);
-
-void
-ao_packet_slave_stop(void);
-
-void
-ao_packet_slave_init(uint8_t enable);
-
-/* ao_btm.c */
-
-/* If bt_link is on P2, this interrupt is shared by USB, so the USB
- * code calls this function. Otherwise, it's a regular ISR.
- */
-
-void
-ao_btm_isr(void)
-#if BT_LINK_ON_P1
-       __interrupt 15
-#endif
-       ;
-
-void
-ao_btm_init(void);
-
-/* ao_companion.c */
-
-#define AO_COMPANION_SETUP             1
-#define AO_COMPANION_FETCH             2
-#define AO_COMPANION_NOTIFY            3
-
-struct ao_companion_command {
-       uint8_t         command;
-       uint8_t         flight_state;
-       uint16_t        tick;
-       uint16_t        serial;
-       uint16_t        flight;
-};
-
-struct ao_companion_setup {
-       uint16_t        board_id;
-       uint16_t        board_id_inverse;
-       uint8_t         update_period;
-       uint8_t         channels;
-};
-
-extern __pdata uint8_t                         ao_companion_running;
-extern __xdata struct ao_companion_setup       ao_companion_setup;
-extern __xdata uint8_t                         ao_companion_mutex;
-extern __xdata uint16_t                                ao_companion_data[AO_COMPANION_MAX_CHANNELS];
-
-void
-ao_companion_init(void);
-
-#endif /* _AO_H_ */
diff --git a/src/ao_adc.c b/src/ao_adc.c
deleted file mode 100644 (file)
index 786dfd1..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_pins.h"
-
-volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING];
-#if HAS_ACCEL_REF
-volatile __xdata uint16_t      ao_accel_ref[AO_ADC_RING];
-#endif
-volatile __data uint8_t                ao_adc_head;
-
-void
-ao_adc_poll(void)
-{
-#if HAS_ACCEL_REF
-       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2;
-#else
-# ifdef TELENANO_V_0_1
-       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1;
-# else
-       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0;
-# endif
-#endif
-}
-
-void
-ao_adc_get(__xdata struct ao_adc *packet)
-{
-       uint8_t i = ao_adc_ring_prev(ao_sample_adc);
-       memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc));
-}
-
-void
-ao_adc_isr(void) __interrupt 1
-{
-       uint8_t sequence;
-       uint8_t __xdata *a;
-
-       sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT;
-#if IGNITE_ON_P2
-       /* TeleMetrum readings */
-#if HAS_ACCEL_REF
-       if (sequence == 2) {
-               a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]);
-               sequence = 0;
-       } else
-#endif
-       {
-               if (sequence == ADCCON3_ECH_TEMP)
-                       sequence = 2;
-               a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence);
-               sequence++;
-       }
-#define GOT_ADC
-       a[0] = ADCL;
-       a[1] = ADCH;
-       if (sequence < 6) {
-#if HAS_EXTERNAL_TEMP == 0
-               /* start next channel conversion */
-               /* v0.2 replaces external temp sensor with internal one */
-               if (sequence == 2)
-                       ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
-               else
-#endif
-                       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence;
-       }
-#endif
-
-#if IGNITE_ON_P0
-       /* TeleMini readings */
-       a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres);
-#ifdef TELEMINI_V_1_0
-       switch (sequence) {
-       case 0:
-               /* pressure */
-               a += 0;
-               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1;
-               break;
-       case 1:
-               /* drogue sense */
-               a += 6;
-               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2;
-               break;
-       case 2:
-               /* main sense */
-               a += 8;
-               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3;
-               break;
-       case 3:
-               /* battery */
-               a += 4;
-               sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
-               break;
-       case ADCCON3_ECH_TEMP:
-               a += 2;
-               sequence = 0;
-               break;
-       }
-#define GOT_ADC
-#endif
-#ifdef TELENANO_V_0_1
-       switch (sequence) {
-       case 1:
-               /* pressure */
-               a += 0;
-               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3;
-               break;
-       case 3:
-               /* battery */
-               a += 4;
-               sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
-               break;
-       case ADCCON3_ECH_TEMP:
-               a += 2;
-               sequence = 0;
-               break;
-       }
-#define GOT_ADC
-#endif
-       a[0] = ADCL;
-       a[1] = ADCH;
-       if (sequence) {
-               /* Start next conversion */
-               ADCCON3 = sequence;
-       }
-#endif
-#ifndef GOT_ADC
-#error No known ADC configuration set
-#endif
-
-       else {
-               /* record this conversion series */
-               ao_adc_ring[ao_adc_head].tick = ao_time();
-               ao_adc_head = ao_adc_ring_next(ao_adc_head);
-               ao_wakeup(DATA_TO_XDATA(&ao_adc_head));
-       }
-}
-
-static void
-ao_adc_dump(void) __reentrant
-{
-       static __xdata struct ao_adc    packet;
-       ao_adc_get(&packet);
-       printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n",
-              packet.tick, packet.accel, packet.pres, packet.temp,
-              packet.v_batt, packet.sense_d, packet.sense_m);
-}
-
-__code struct ao_cmds ao_adc_cmds[] = {
-       { ao_adc_dump,  "a\0Current ADC" },
-       { 0, NULL },
-};
-
-void
-ao_adc_init(void)
-{
-#if IGNITE_ON_P2
-       /* TeleMetrum configuration */
-       ADCCFG = ((1 << 0) |    /* acceleration */
-                 (1 << 1) |    /* pressure */
-#if HAS_EXTERNAL_TEMP
-                 (1 << 2) |    /* v0.1 temperature */
-#endif
-                 (1 << 3) |    /* battery voltage */
-                 (1 << 4) |    /* drogue sense */
-                 (1 << 5));    /* main sense */
-#endif
-
-#if IGNITE_ON_P0
-       /* TeleMini configuration */
-       ADCCFG = ((1 << 0) |    /* pressure */
-                 (1 << 1) |    /* drogue sense */
-                 (1 << 2) |    /* main sense */
-                 (1 << 3));    /* battery voltage */
-#endif
-
-       /* enable interrupts */
-       ADCIF = 0;
-       IEN0 |= IEN0_ADCIE;
-       ao_cmd_register(&ao_adc_cmds[0]);
-}
diff --git a/src/ao_adc_fake.c b/src/ao_adc_fake.c
deleted file mode 100644 (file)
index 6ca88d4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING];
-volatile __data uint8_t                ao_adc_head;
-
-/* Stub for systems which have no ADC */
-void
-ao_adc_poll(void)
-{
-}
diff --git a/src/ao_beep.c b/src/ao_beep.c
deleted file mode 100644 (file)
index 3642f4c..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_beep(uint8_t beep)
-{
-       if (beep == 0) {
-               P2_0 = 0;
-               P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO;
-               T4CTL = 0;
-       } else {
-               P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL;
-               T4CC0 = beep;
-               T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START;
-       }
-}
-
-void
-ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant
-{
-       ao_beep(beep);
-       ao_delay(ticks);
-       ao_beep(0);
-}
-
-void
-ao_beep_init(void)
-{
-       /* Our beeper is on P2_0, which is hooked to timer 4 using
-        * configuration alternative 2
-        */
-       P2_0 = 0;
-       P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO;
-       PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2;
-       T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE;
-}
diff --git a/src/ao_btm.c b/src/ao_btm.c
deleted file mode 100644 (file)
index 44155ec..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-int8_t                 ao_btm_stdio;
-__xdata uint8_t                ao_btm_connected;
-
-#define AO_BTM_MAX_REPLY       16
-__xdata char           ao_btm_reply[AO_BTM_MAX_REPLY];
-
-extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo;
-
-/*
- * Read a line of data from the serial port, truncating
- * it after a few characters.
- */
-
-uint8_t
-ao_btm_get_line(void)
-{
-       uint8_t ao_btm_reply_len = 0;
-       char c;
-
-       for (;;) {
-
-               while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) {
-                       if (ao_btm_reply_len < sizeof (ao_btm_reply))
-                               ao_btm_reply[ao_btm_reply_len++] = c;
-                       if (c == '\r' || c == '\n')
-                               goto done;
-               }
-               for (c = 0; c < 10; c++) {
-                       ao_delay(AO_MS_TO_TICKS(10));
-                       if (!ao_fifo_empty(ao_usart1_rx_fifo))
-                               break;
-               }
-               if (c == 10)
-                       goto done;
-       }
-done:
-       for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
-               ao_btm_reply[c++] = '\0';
-       return ao_btm_reply_len;
-}
-
-/*
- * Drain the serial port completely
- */
-void
-ao_btm_drain()
-{
-       while (ao_btm_get_line())
-               ;
-}
-
-/*
- * Set the stdio echo for the bluetooth link
- */
-void
-ao_btm_echo(uint8_t echo)
-{
-       ao_stdios[ao_btm_stdio].echo = echo;
-}
-
-/*
- * Delay between command charaters; the BT module
- * can't keep up with 57600 baud
- */
-
-void
-ao_btm_putchar(char c)
-{
-       ao_serial_putchar(c);
-       ao_delay(1);
-}
-
-/*
- * Wait for the bluetooth device to return
- * status from the previously executed command
- */
-uint8_t
-ao_btm_wait_reply(void)
-{
-       for (;;) {
-               ao_btm_get_line();
-               if (!strncmp(ao_btm_reply, "OK", 2))
-                       return 1;
-               if (!strncmp(ao_btm_reply, "ERROR", 5))
-                       return -1;
-               if (ao_btm_reply[0] == '\0')
-                       return 0;
-       }
-}
-
-void
-ao_btm_string(__code char *cmd)
-{
-       char    c;
-
-       while (c = *cmd++)
-               ao_btm_putchar(c);
-}
-
-uint8_t
-ao_btm_cmd(__code char *cmd)
-{
-       ao_btm_drain();
-       ao_btm_string(cmd);
-       return ao_btm_wait_reply();
-}
-
-uint8_t
-ao_btm_set_name(void)
-{
-       char    sn[8];
-       char    *s = sn + 8;
-       char    c;
-       int     n;
-       ao_btm_string("ATN=TeleBT-");
-       *--s = '\0';
-       *--s = '\r';
-       n = ao_serial_number;
-       do {
-               *--s = '0' + n % 10;
-       } while (n /= 10);
-       while ((c = *s++))
-               ao_btm_putchar(c);
-       return ao_btm_wait_reply();
-}
-
-uint8_t
-ao_btm_try_speed(uint8_t speed)
-{
-       ao_serial_set_speed(speed);
-       ao_btm_drain();
-       (void) ao_btm_cmd("\rATE0\rATQ0\r");
-       if (ao_btm_cmd("AT\r") == 1)
-               return 1;
-       return 0;
-}
-
-/*
- * A thread to initialize the bluetooth device and
- * hang around to blink the LED when connected
- */
-void
-ao_btm(void)
-{
-       /*
-        * Wait for the bluetooth device to boot
-        */
-       ao_delay(AO_SEC_TO_TICKS(3));
-
-#if HAS_BEEP
-       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
-#endif
-
-       /*
-        * The first time we connect, the BTM-180 comes up at 19200 baud.
-        * After that, it will remember and come up at 57600 baud. So, see
-        * if it is already running at 57600 baud, and if that doesn't work
-        * then tell it to switch to 57600 from 19200 baud.
-        */
-       while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) {
-               ao_delay(AO_SEC_TO_TICKS(1));
-               if (ao_btm_try_speed(AO_SERIAL_SPEED_19200))
-                       ao_btm_cmd("ATL4\r");
-               ao_delay(AO_SEC_TO_TICKS(1));
-       }
-
-       /* Disable echo */
-       ao_btm_cmd("ATE0\r");
-
-       /* Enable flow control */
-       ao_btm_cmd("ATC1\r");
-
-       /* Set the reported name to something we can find on the host */
-       ao_btm_set_name();
-
-       /* Turn off status reporting */
-       ao_btm_cmd("ATQ1\r");
-
-       ao_btm_stdio = ao_add_stdio(ao_serial_pollchar,
-                                   ao_serial_putchar,
-                                   NULL);
-       ao_btm_echo(0);
-
-       for (;;) {
-               while (!ao_btm_connected)
-                       ao_sleep(&ao_btm_connected);
-               while (ao_btm_connected) {
-                       ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20));
-                       ao_delay(AO_SEC_TO_TICKS(3));
-               }
-       }
-}
-
-__xdata struct ao_task ao_btm_task;
-
-#if BT_LINK_ON_P2
-#define BT_PICTL_ICON  PICTL_P2ICON
-#define BT_PIFG                P2IFG
-#define BT_PDIR                P2DIR
-#define BT_PINP                P2INP
-#define BT_IEN2_PIE    IEN2_P2IE
-#endif
-#if BT_LINK_ON_P1
-#define BT_PICTL_ICON  PICTL_P1ICON
-#define BT_PIFG                P1IFG
-#define BT_PDIR                P1DIR
-#define BT_PINP                P1INP
-#define BT_IEN2_PIE    IEN2_P1IE
-#endif
-
-void
-ao_btm_check_link() __critical
-{
-       /* Check the pin and configure the interrupt detector to wait for the
-        * pin to flip the other way
-        */
-       if (BT_LINK_PIN) {
-               ao_btm_connected = 0;
-               PICTL |= BT_PICTL_ICON;
-       } else {
-               ao_btm_connected = 1;
-               PICTL &= ~BT_PICTL_ICON;
-       }
-}
-
-void
-ao_btm_isr(void)
-#if BT_LINK_ON_P1
-       __interrupt 15
-#endif
-{
-#if BT_LINK_ON_P1
-       P1IF = 0;
-#endif
-       if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) {
-               ao_btm_check_link();
-               ao_wakeup(&ao_btm_connected);
-       }
-       BT_PIFG = 0;
-}
-
-void
-ao_btm_init (void)
-{
-       ao_serial_init();
-       ao_serial_set_speed(AO_SERIAL_SPEED_19200);
-
-#if BT_LINK_ON_P1
-       /*
-        * Configure ser reset line
-        */
-
-       P1_6 = 0;
-       P1DIR |= (1 << 6);
-#endif
-
-       /*
-        * Configure link status line
-        */
-
-       /* Set pin to input */
-       BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX);
-
-       /* Set pin to tri-state */
-       BT_PINP |= (1 << BT_LINK_PIN_INDEX);
-
-       /* Enable interrupts */
-       IEN2 |= BT_IEN2_PIE;
-
-       /* Check current pin state */
-       ao_btm_check_link();
-
-#if BT_LINK_ON_P2
-       /* Eable the pin interrupt */
-       PICTL |= PICTL_P2IEN;
-#endif
-#if BT_LINK_ON_P1
-       /* Enable pin interrupt */
-       P1IEN |= (1 << BT_LINK_PIN_INDEX);
-#endif
-
-       ao_add_task(&ao_btm_task, ao_btm, "bt");
-}
diff --git a/src/ao_cmd.c b/src/ao_cmd.c
deleted file mode 100644 (file)
index 1442ebe..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__pdata uint16_t ao_cmd_lex_i;
-__pdata uint32_t ao_cmd_lex_u32;
-__pdata char   ao_cmd_lex_c;
-__pdata enum ao_cmd_status ao_cmd_status;
-
-#define CMD_LEN        32
-
-static __xdata char    cmd_line[CMD_LEN];
-static __pdata uint8_t cmd_len;
-static __pdata uint8_t cmd_i;
-
-static void
-put_string(__code char *s)
-{
-       char    c;
-       while (c = *s++)
-               putchar(c);
-}
-
-static void
-readline(void)
-{
-       __pdata char c;
-       if (ao_echo())
-               put_string("> ");
-       cmd_len = 0;
-       for (;;) {
-               flush();
-               c = getchar();
-               /* backspace/delete */
-               if (c == '\010' || c == '\177') {
-                       if (cmd_len != 0) {
-                               if (ao_echo())
-                                       put_string("\010 \010");
-                               --cmd_len;
-                       }
-                       continue;
-               }
-
-               /* ^U */
-               if (c == '\025') {
-                       while (cmd_len != 0) {
-                               if (ao_echo())
-                                       put_string("\010 \010");
-                               --cmd_len;
-                       }
-                       continue;
-               }
-
-               /* map CR to NL */
-               if (c == '\r')
-                       c = '\n';
-
-               if (c == '\n') {
-                       if (ao_echo())
-                               putchar('\n');
-                       break;
-               }
-
-               if (cmd_len >= CMD_LEN - 2) {
-                       if (ao_echo())
-                               putchar('\007');
-                       continue;
-               }
-               cmd_line[cmd_len++] = c;
-               if (ao_echo())
-                       putchar(c);
-       }
-       cmd_line[cmd_len++] = '\n';
-       cmd_line[cmd_len++] = '\0';
-       cmd_i = 0;
-}
-
-void
-ao_cmd_lex(void)
-{
-       ao_cmd_lex_c = '\n';
-       if (cmd_i < cmd_len)
-               ao_cmd_lex_c = cmd_line[cmd_i++];
-}
-
-static void
-putnibble(uint8_t v)
-{
-       if (v < 10)
-               putchar(v + '0');
-       else
-               putchar(v + ('a' - 10));
-}
-
-void
-ao_cmd_put16(uint16_t v)
-{
-       ao_cmd_put8(v >> 8);
-       ao_cmd_put8(v);
-}
-
-void
-ao_cmd_put8(uint8_t v)
-{
-       putnibble((v >> 4) & 0xf);
-       putnibble(v & 0xf);
-}
-
-void
-ao_cmd_white(void)
-{
-       while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t')
-               ao_cmd_lex();
-}
-
-void
-ao_cmd_hex(void)
-{
-       __pdata uint8_t r = ao_cmd_lex_error;
-       uint8_t n;
-
-       ao_cmd_lex_i = 0;
-       ao_cmd_white();
-       for(;;) {
-               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
-                       n = (ao_cmd_lex_c - '0');
-               else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
-                       n = (ao_cmd_lex_c - 'a' + 10);
-               else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
-                       n = (ao_cmd_lex_c - 'A' + 10);
-               else
-                       break;
-               ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n;
-               r = ao_cmd_success;
-               ao_cmd_lex();
-       }
-       if (r != ao_cmd_success)
-               ao_cmd_status = r;
-}
-
-void
-ao_cmd_decimal(void)
-{
-       __pdata uint8_t r = ao_cmd_lex_error;
-
-       ao_cmd_lex_u32 = 0;
-       ao_cmd_white();
-       for(;;) {
-               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
-                       ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0');
-               else
-                       break;
-               r = ao_cmd_success;
-               ao_cmd_lex();
-       }
-       if (r != ao_cmd_success)
-               ao_cmd_status = r;
-       ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32;
-}
-
-uint8_t
-ao_match_word(__code char *word)
-{
-       while (*word) {
-               if (ao_cmd_lex_c != *word) {
-                       ao_cmd_status = ao_cmd_syntax_error;
-                       return 0;
-               }
-               word++;
-               ao_cmd_lex();
-       }
-       return 1;
-}
-
-static void
-eol(void)
-{
-       while (ao_cmd_lex_c != '\n')
-               ao_cmd_lex();
-}
-
-static void
-echo(void)
-{
-       ao_cmd_hex();
-       if (ao_cmd_status == ao_cmd_success)
-               ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0;
-}
-
-static void
-ao_reboot(void)
-{
-       ao_cmd_white();
-       if (!ao_match_word("eboot"))
-               return;
-       WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64;
-       ao_delay(AO_SEC_TO_TICKS(2));
-       ao_panic(AO_PANIC_REBOOT);
-}
-
-static void
-version(void)
-{
-       printf("manufacturer     %s\n", ao_manufacturer);
-       printf("product          %s\n", ao_product);
-       printf("serial-number    %u\n", ao_serial_number);
-#if HAS_EEPROM
-       printf("log-format       %u\n", ao_log_format);
-#endif
-       printf("software-version %s\n", ao_version);
-}
-
-#define NUM_CMDS       11
-
-static __code struct ao_cmds   *__xdata (ao_cmds[NUM_CMDS]);
-static __pdata uint8_t         ao_ncmds;
-
-static void
-help(void)
-{
-       register uint8_t cmds;
-       register uint8_t cmd;
-       register __code struct ao_cmds * cs;
-
-       for (cmds = 0; cmds < ao_ncmds; cmds++) {
-               cs = ao_cmds[cmds];
-               for (cmd = 0; cs[cmd].func; cmd++)
-                       printf("%-45s %s\n",
-                               cs[cmd].help,
-                               cs[cmd].help+1+strlen(cs[cmd].help));
-       }
-}
-
-static void
-report(void)
-{
-       switch(ao_cmd_status) {
-       case ao_cmd_lex_error:
-       case ao_cmd_syntax_error:
-               puts("Syntax error");
-               ao_cmd_status = 0;
-               break;
-       }
-}
-
-void
-ao_cmd_register(__code struct ao_cmds *cmds)
-{
-       if (ao_ncmds >= NUM_CMDS)
-               ao_panic(AO_PANIC_CMD);
-       ao_cmds[ao_ncmds++] = cmds;
-}
-
-void
-ao_cmd(void)
-{
-       char    c;
-       uint8_t cmd, cmds;
-       __code struct ao_cmds * __xdata cs;
-       void (*__xdata func)(void);
-
-       for (;;) {
-               readline();
-               ao_cmd_lex();
-               ao_cmd_white();
-               c = ao_cmd_lex_c;
-               ao_cmd_lex();
-               if (c == '\r' || c == '\n')
-                       continue;
-               func = (void (*)(void)) NULL;
-               for (cmds = 0; cmds < ao_ncmds; cmds++) {
-                       cs = ao_cmds[cmds];
-                       for (cmd = 0; cs[cmd].func; cmd++)
-                               if (cs[cmd].help[0] == c) {
-                                       func = cs[cmd].func;
-                                       break;
-                               }
-                       if (func)
-                               break;
-               }
-               if (func)
-                       (*func)();
-               else
-                       ao_cmd_status = ao_cmd_syntax_error;
-               report();
-       }
-}
-
-__xdata struct ao_task ao_cmd_task;
-
-__code struct ao_cmds  ao_base_cmds[] = {
-       { help,         "?\0Help" },
-       { ao_task_info, "T\0Show tasks" },
-       { echo,         "E <0 off, 1 on>\0Set echo mode" },
-       { ao_reboot,    "r eboot\0Reboot" },
-       { version,      "v\0Version" },
-       { 0,    NULL },
-};
-
-void
-ao_cmd_init(void)
-{
-       ao_cmd_register(&ao_base_cmds[0]);
-       ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
-}
diff --git a/src/ao_companion.c b/src/ao_companion.c
deleted file mode 100644 (file)
index 4c8f426..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE |          \
-                               UxGCR_CPHA_FIRST_EDGE |         \
-                               UxGCR_ORDER_MSB |               \
-                               (13 << UxGCR_BAUD_E_SHIFT)))
-
-#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE |          \
-                               UxGCR_CPHA_FIRST_EDGE |         \
-                               UxGCR_ORDER_MSB |               \
-                               (17 << UxGCR_BAUD_E_SHIFT)))
-
-#define COMPANION_SELECT()     do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0)
-#define COMPANION_DESELECT()   do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0)
-
-static __xdata struct ao_companion_command     ao_companion_command;
-__xdata struct ao_companion_setup              ao_companion_setup;
-
-__xdata uint16_t       ao_companion_data[AO_COMPANION_MAX_CHANNELS];
-__pdata uint8_t                ao_companion_running;
-__xdata uint8_t                ao_companion_mutex;
-
-static void
-ao_companion_send_command(uint8_t command)
-{
-       ao_companion_command.command = command;
-       ao_companion_command.flight_state = ao_flight_state;
-       ao_companion_command.tick = ao_time();
-       ao_companion_command.serial = ao_serial_number;
-       ao_companion_command.flight = ao_flight_number;
-       ao_spi_send(&ao_companion_command, sizeof (ao_companion_command));
-}
-
-static uint8_t
-ao_companion_get_setup(void)
-{
-       COMPANION_SELECT();
-       ao_companion_send_command(AO_COMPANION_SETUP);
-       ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup));
-       COMPANION_DESELECT();
-       return (ao_companion_setup.board_id ==
-               ~ao_companion_setup.board_id_inverse);
-}
-
-static void
-ao_companion_get_data(void)
-{
-       COMPANION_SELECT();
-       ao_companion_send_command(AO_COMPANION_FETCH);
-       ao_mutex_get(&ao_companion_mutex);
-       ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2);
-       ao_mutex_put(&ao_companion_mutex);
-       COMPANION_DESELECT();
-}
-
-static void
-ao_companion_notify(void)
-{
-       COMPANION_SELECT();
-       ao_companion_send_command(AO_COMPANION_NOTIFY);
-       COMPANION_DESELECT();
-}
-
-void
-ao_companion(void)
-{
-       uint8_t i;
-       while (!ao_flight_number)
-               ao_sleep(&ao_flight_number);
-       for (i = 0; i < 10; i++) {
-               ao_delay(AO_SEC_TO_TICKS(1));
-               if ((ao_companion_running = ao_companion_get_setup()))
-                   break;
-       }
-       while (ao_companion_running) {
-               ao_alarm(ao_companion_setup.update_period);
-               if (ao_sleep(DATA_TO_XDATA(&ao_flight_state)))
-                       ao_companion_get_data();
-               else
-                       ao_companion_notify();
-       }
-       ao_exit();
-}
-
-void
-ao_companion_status(void) __reentrant
-{
-       uint8_t i;
-       printf("Companion running: %d\n", ao_companion_running);
-       printf("device: %d\n", ao_companion_setup.board_id);
-       printf("update period: %d\n", ao_companion_setup.update_period);
-       printf("channels: %d\n", ao_companion_setup.channels);
-       printf("data:");
-       for(i = 0; i < ao_companion_setup.channels; i++)
-               printf(" %5u", ao_companion_data[i]);
-       printf("\n");
-}
-
-__code struct ao_cmds ao_companion_cmds[] = {
-       { ao_companion_status,  "L\0Companion link status" },
-       { 0, NULL },
-};
-
-static __xdata struct ao_task ao_companion_task;
-
-void
-ao_companion_init(void)
-{
-       COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */
-       COMPANION_CS_DIR |= COMPANION_CS_MASK;  /* set CS pins as outputs */
-       COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */
-
-       ao_cmd_register(&ao_companion_cmds[0]);
-       ao_add_task(&ao_companion_task, ao_companion, "companion");
-}
diff --git a/src/ao_config.c b/src/ao_config.c
deleted file mode 100644 (file)
index 0c10e60..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__xdata struct ao_config ao_config;
-__pdata uint8_t ao_config_loaded;
-__pdata uint8_t ao_config_dirty;
-__xdata uint8_t ao_config_mutex;
-
-#define AO_CONFIG_DEFAULT_MAIN_DEPLOY  250
-#define AO_CONFIG_DEFAULT_RADIO_CHANNEL        0
-#define AO_CONFIG_DEFAULT_CALLSIGN     "N0CALL"
-#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
-#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
-#define AO_CONFIG_DEFAULT_IGNITE_MODE  AO_IGNITE_MODE_DUAL
-#define AO_CONFIG_DEFAULT_PAD_ORIENTATION      AO_PAD_ORIENTATION_ANTENNA_UP
-#if HAS_EEPROM
-#ifndef USE_INTERNAL_FLASH
-#error Please define USE_INTERNAL_FLASH
-#endif
-#endif
-#if USE_INTERNAL_FLASH
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       ao_storage_config
-#else
-#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       ((uint32_t) 192 * (uint32_t) 1024)
-#endif
-
-#if HAS_EEPROM
-static void
-_ao_config_put(void)
-{
-       ao_storage_setup();
-       ao_storage_erase(ao_storage_config);
-       ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config));
-       ao_log_write_erase(0);
-       ao_storage_flush();
-}
-
-void
-ao_config_put(void)
-{
-       ao_mutex_get(&ao_config_mutex);
-       _ao_config_put();
-       ao_mutex_put(&ao_config_mutex);
-}
-#endif
-
-static void
-_ao_config_get(void)
-{
-       if (ao_config_loaded)
-               return;
-#if HAS_EEPROM
-       ao_storage_setup();
-       ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config));
-#endif
-       if (ao_config.major != AO_CONFIG_MAJOR) {
-               ao_config.major = AO_CONFIG_MAJOR;
-               ao_config.minor = 0;
-               ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
-               ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL;
-               memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
-               memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
-                      sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
-       }
-       if (ao_config.minor < AO_CONFIG_MINOR) {
-               /* Fixups for minor version 1 */
-               if (ao_config.minor < 1)
-                       ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
-               /* Fixups for minor version 2 */
-               if (ao_config.minor < 2) {
-                       ao_config.accel_plus_g = 0;
-                       ao_config.accel_minus_g = 0;
-               }
-               /* Fixups for minor version 3 */
-               if (ao_config.minor < 3)
-                       ao_config.radio_cal = ao_radio_cal;
-               /* Fixups for minor version 4 */
-               if (ao_config.minor < 4)
-                       ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX;
-               /* Fixupes for minor version 5 */
-               if (ao_config.minor < 5)
-                       ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE;
-               if (ao_config.minor < 6)
-                       ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION;
-               if (ao_config.minor < 7)
-                       ao_config.radio_setting = ao_config.radio_cal;
-               if (ao_config.minor < 8)
-                       ao_config.radio_enable = TRUE;
-               ao_config.minor = AO_CONFIG_MINOR;
-               ao_config_dirty = 1;
-       }
-       ao_config_loaded = 1;
-}
-
-static void
-_ao_config_edit_start(void)
-{
-       ao_mutex_get(&ao_config_mutex);
-       _ao_config_get();
-}
-
-static void
-_ao_config_edit_finish(void)
-{
-       ao_config_dirty = 1;
-       ao_mutex_put(&ao_config_mutex);
-}
-
-void
-ao_config_get(void)
-{
-       _ao_config_edit_start();
-       ao_mutex_put(&ao_config_mutex);
-}
-
-void
-ao_config_callsign_show(void)
-{
-       printf ("Callsign: \"%s\"\n", ao_config.callsign);
-}
-
-void
-ao_config_callsign_set(void) __reentrant
-{
-       uint8_t c;
-       static __xdata char callsign[AO_MAX_CALLSIGN + 1];
-
-       memset(callsign, '\0', sizeof callsign);
-       ao_cmd_white();
-       c = 0;
-       while (ao_cmd_lex_c != '\n') {
-               if (c < AO_MAX_CALLSIGN)
-                       callsign[c++] = ao_cmd_lex_c;
-               else
-                       ao_cmd_status = ao_cmd_lex_error;
-               ao_cmd_lex();
-       }
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       memcpy(&ao_config.callsign, &callsign,
-              AO_MAX_CALLSIGN + 1);
-       _ao_config_edit_finish();
-}
-
-void
-ao_config_radio_channel_show(void) __reentrant
-{
-       printf("Radio channel: %d\n",
-              ao_config.radio_channel);
-}
-
-void
-ao_config_radio_channel_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.radio_channel = ao_cmd_lex_i;
-       _ao_config_edit_finish();
-       ao_radio_recv_abort();
-}
-
-#if HAS_ADC
-
-void
-ao_config_main_deploy_show(void) __reentrant
-{
-       printf("Main deploy: %d meters\n",
-              ao_config.main_deploy);
-}
-
-void
-ao_config_main_deploy_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.main_deploy = ao_cmd_lex_i;
-       _ao_config_edit_finish();
-}
-
-#if HAS_ACCEL
-void
-ao_config_accel_calibrate_show(void) __reentrant
-{
-       printf("Accel cal +1g: %d -1g: %d\n",
-              ao_config.accel_plus_g, ao_config.accel_minus_g);
-}
-
-#define ACCEL_CALIBRATE_SAMPLES        1024
-#define ACCEL_CALIBRATE_SHIFT  10
-
-static int16_t
-ao_config_accel_calibrate_auto(char *orientation) __reentrant
-{
-       uint16_t        i;
-       int32_t         accel_total;
-       uint8_t         cal_adc_ring;
-
-       printf("Orient antenna %s and press a key...", orientation);
-       flush();
-       (void) getchar();
-       puts("\r\n"); flush();
-       puts("Calibrating..."); flush();
-       i = ACCEL_CALIBRATE_SAMPLES;
-       accel_total = 0;
-       cal_adc_ring = ao_sample_adc;
-       while (i) {
-               ao_sleep(DATA_TO_XDATA(&ao_sample_adc));
-               while (i && cal_adc_ring != ao_sample_adc) {
-                       accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel;
-                       cal_adc_ring = ao_adc_ring_next(cal_adc_ring);
-                       i--;
-               }
-       }
-       return accel_total >> ACCEL_CALIBRATE_SHIFT;
-}
-
-void
-ao_config_accel_calibrate_set(void) __reentrant
-{
-       int16_t up, down;
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       if (ao_cmd_lex_i == 0) {
-               up = ao_config_accel_calibrate_auto("up");
-               down = ao_config_accel_calibrate_auto("down");
-       } else {
-               up = ao_cmd_lex_i;
-               ao_cmd_decimal();
-               if (ao_cmd_status != ao_cmd_success)
-                       return;
-               down = ao_cmd_lex_i;
-       }
-       if (up >= down) {
-               printf("Invalid accel: up (%d) down (%d)\n",
-                      up, down);
-               return;
-       }
-       _ao_config_edit_start();
-       ao_config.accel_plus_g = up;
-       ao_config.accel_minus_g = down;
-       _ao_config_edit_finish();
-}
-#endif /* HAS_ACCEL */
-
-void
-ao_config_apogee_delay_show(void) __reentrant
-{
-       printf("Apogee delay: %d seconds\n",
-              ao_config.apogee_delay);
-}
-
-void
-ao_config_apogee_delay_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.apogee_delay = ao_cmd_lex_i;
-       _ao_config_edit_finish();
-}
-
-#endif /* HAS_ADC */
-
-void
-ao_config_radio_cal_show(void) __reentrant
-{
-       printf("Radio cal: %ld\n", ao_config.radio_cal);
-}
-
-void
-ao_config_radio_cal_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32;
-       _ao_config_edit_finish();
-}
-
-#if HAS_EEPROM
-void
-ao_config_log_show(void) __reentrant
-{
-       printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
-}
-
-void
-ao_config_log_set(void) __reentrant
-{
-       uint16_t        block = (uint16_t) (ao_storage_block >> 10);
-       uint16_t        config = (uint16_t) (ao_storage_config >> 10);
-
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       if (ao_log_present())
-               printf("Storage must be empty before changing log size\n");
-       else if (block > 1024 && (ao_cmd_lex_i & (block - 1)))
-               printf("Flight log size must be multiple of %d kB\n", block);
-       else if (ao_cmd_lex_i > config)
-               printf("Flight log max %d kB\n", config);
-       else {
-               _ao_config_edit_start();
-               ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;
-               _ao_config_edit_finish();
-       }
-}
-#endif /* HAS_EEPROM */
-
-#if HAS_IGNITE
-void
-ao_config_ignite_mode_show(void) __reentrant
-{
-       printf("Ignite mode: %d\n", ao_config.ignite_mode);
-}
-
-void
-ao_config_ignite_mode_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.ignite_mode = ao_cmd_lex_i;
-       _ao_config_edit_finish();
-}
-#endif
-
-#if HAS_ACCEL
-void
-ao_config_pad_orientation_show(void) __reentrant
-{
-       printf("Pad orientation: %d\n", ao_config.pad_orientation);
-}
-
-void
-ao_config_pad_orientation_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_cmd_lex_i &= 1;
-       if (ao_config.pad_orientation != ao_cmd_lex_i) {
-               uint16_t t;
-               t = ao_config.accel_plus_g;
-               ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g;
-               ao_config.accel_minus_g = 0x7fff - t;
-       }
-       ao_config.pad_orientation = ao_cmd_lex_i;
-       _ao_config_edit_finish();
-}
-#endif
-
-void
-ao_config_radio_setting_show(void) __reentrant
-{
-       printf("Radio setting: %ld\n", ao_config.radio_setting);
-}
-
-void
-ao_config_radio_setting_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.radio_setting = ao_cmd_lex_u32;
-       ao_config.radio_channel = 0;
-       _ao_config_edit_finish();
-       ao_radio_recv_abort();
-}
-
-void
-ao_config_radio_enable_show(void) __reentrant
-{
-       printf("Radio enable: %d\n", ao_config.radio_enable);
-}
-
-void
-ao_config_radio_enable_set(void) __reentrant
-{
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       _ao_config_edit_start();
-       ao_config.radio_enable = ao_cmd_lex_i;
-       _ao_config_edit_finish();
-}
-       
-struct ao_config_var {
-       __code char     *str;
-       void            (*set)(void) __reentrant;
-       void            (*show)(void) __reentrant;
-};
-
-static void
-ao_config_help(void) __reentrant;
-
-static void
-ao_config_show(void) __reentrant;
-
-static void
-ao_config_write(void) __reentrant;
-
-__code struct ao_config_var ao_config_vars[] = {
-#if HAS_ADC
-       { "m <meters>\0Main deploy (in meters)",
-         ao_config_main_deploy_set,    ao_config_main_deploy_show, },
-       { "d <delay>\0Apogee delay (in seconds)",
-         ao_config_apogee_delay_set,   ao_config_apogee_delay_show },
-#endif /* HAS_ADC */
-       { "r <channel>\0Radio channel (freq = 434.550 + chan * .1)",
-         ao_config_radio_channel_set,  ao_config_radio_channel_show },
-       { "c <call>\0Callsign (8 char max)",
-         ao_config_callsign_set,       ao_config_callsign_show },
-       { "R <setting>\0Radio freq control (freq = 434.550 * setting/cal)",
-         ao_config_radio_setting_set,  ao_config_radio_setting_show },
-       { "e <0 disable, 1 enable>\0Enable telemetry and RDF",
-         ao_config_radio_enable_set, ao_config_radio_enable_show },
-#if HAS_ACCEL
-       { "a <+g> <-g>\0Accel calib (0 for auto)",
-         ao_config_accel_calibrate_set,ao_config_accel_calibrate_show },
-#endif /* HAS_ACCEL */
-       { "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
-         ao_config_radio_cal_set,      ao_config_radio_cal_show },
-#if HAS_EEPROM
-       { "l <size>\0Flight log size in kB",
-         ao_config_log_set,            ao_config_log_show },
-#endif
-#if HAS_IGNITE
-       { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode",
-         ao_config_ignite_mode_set,    ao_config_ignite_mode_show },
-#endif
-#if HAS_ACCEL
-       { "o <0 antenna up, 1 antenna down>\0Set pad orientation",
-         ao_config_pad_orientation_set,ao_config_pad_orientation_show },
-#endif
-       { "s\0Show",
-         ao_config_show,               0 },
-#if HAS_EEPROM
-       { "w\0Write to eeprom",
-         ao_config_write,              0 },
-#endif
-       { "?\0Help",
-         ao_config_help,               0 },
-       { 0, 0, 0 }
-};
-
-void
-ao_config_set(void)
-{
-       char    c;
-       uint8_t cmd;
-       void (*__xdata func)(void) __reentrant;
-
-       ao_cmd_white();
-       c = ao_cmd_lex_c;
-       ao_cmd_lex();
-       func = 0;
-       for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
-               if (ao_config_vars[cmd].str[0] == c) {
-                       (*ao_config_vars[cmd].set)();
-                       return;
-               }
-       ao_cmd_status = ao_cmd_syntax_error;
-}
-
-static void
-ao_config_help(void) __reentrant
-{
-       uint8_t cmd;
-       for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
-               printf("%-20s %s\n",
-                      ao_config_vars[cmd].str,
-                      ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str));
-}
-
-static void
-ao_config_show(void) __reentrant
-{
-       uint8_t cmd;
-       printf("Config version: %d.%d\n",
-              ao_config.major, ao_config.minor);
-       for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
-               if (ao_config_vars[cmd].show)
-                       (*ao_config_vars[cmd].show)();
-}
-
-#if HAS_EEPROM
-static void
-ao_config_write(void) __reentrant
-{
-       uint8_t saved = 0;
-       ao_mutex_get(&ao_config_mutex);
-       if (ao_config_dirty) {
-               _ao_config_put();
-               ao_config_dirty = 0;
-               saved = 1;
-       }
-       ao_mutex_put(&ao_config_mutex);
-       if (saved)
-               puts("Saved");
-       else
-               puts("Nothing to save");
-}
-#endif
-
-__code struct ao_cmds ao_config_cmds[] = {
-       { ao_config_set,        "c <var> <value>\0Set config variable (? for help, s to show)" },
-       { 0, NULL },
-};
-
-void
-ao_config_init(void)
-{
-       ao_cmd_register(&ao_config_cmds[0]);
-}
diff --git a/src/ao_convert.c b/src/ao_convert.c
deleted file mode 100644 (file)
index 0969f10..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST)
-#include "ao.h"
-#endif
-
-static const int16_t altitude_table[] = {
-#include "altitude.h"
-};
-
-#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
-#define ALT_FRAC_MASK  (ALT_FRAC_SCALE - 1)
-
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant
-{
-       uint8_t o;
-       int16_t part;
-
-       if (pres < 0)
-               pres = 0;
-       o = pres >> ALT_FRAC_BITS;
-       part = pres & ALT_FRAC_MASK;
-
-       return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) +
-               (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS;
-}
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
-{
-       int16_t span, sub_span;
-       uint8_t l, h, m;
-       int32_t pres;
-
-       l = 0;
-       h = NALT - 1;
-       while ((h - l) != 1) {
-               m = (l + h) >> 1;
-               if (altitude_table[m] < alt)
-                       h = m;
-               else
-                       l = m;
-       }
-       span = altitude_table[l] - altitude_table[h];
-       sub_span = altitude_table[l] - alt;
-       pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span;
-       if (pres > 32767)
-               pres = 32767;
-       if (pres < 0)
-               pres = 0;
-       return (int16_t) pres;
-}
-
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant
-{
-       int16_t ret;
-
-       /* Output voltage at 0°C = 0.755V
-        * Coefficient = 0.00247V/°C
-        * Reference voltage = 1.25V
-        *
-        * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
-        *      = (value - 19791.268) / 32768 * 1.25 / 0.00247
-        *      ≃ (value - 19791) * 1012 / 65536
-        */
-       ret = ((temp - 19791) * 1012L) >> 16;
-       return ret;
-}
diff --git a/src/ao_convert_test.c b/src/ao_convert_test.c
deleted file mode 100644 (file)
index e2c28b7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <stdint.h>
-#define AO_CONVERT_TEST
-#include "ao_host.h"
-#include "ao_convert.c"
-
-#define STEP   1
-
-static inline i_abs(int i) { return i < 0 ? -i : i; }
-
-main ()
-{
-       int     i;
-       int16_t p_to_a, p_to_a_to_p;
-       int16_t a_to_p, a_to_p_to_a;
-       int max_p_error = 0, max_p_error_p = -1;
-       int max_a_error = 0, max_a_error_a = -1;
-       int p_error;
-       int a_error;
-       int ret = 0;
-
-       for (i = 0; i < 32767 + STEP; i += STEP) {
-               if (i > 32767)
-                       i = 32767;
-               p_to_a = ao_pres_to_altitude(i);
-               p_to_a_to_p = ao_altitude_to_pres(p_to_a);
-               p_error = i_abs(p_to_a_to_p - i);
-               if (p_error > max_p_error) {
-                       max_p_error = p_error;
-                       max_p_error_p = i;
-               }
-//             printf ("pres %d alt %d pres %d\n",
-//                     i, p_to_a, p_to_a_to_p);
-       }
-       for (i = -1578; i < 15835 + STEP; i += STEP) {
-               if (i > 15835)
-                       i = 15835;
-               a_to_p = ao_altitude_to_pres(i);
-               a_to_p_to_a = ao_pres_to_altitude(a_to_p);
-               a_error = i_abs(a_to_p_to_a - i);
-               if (a_error > max_a_error) {
-                       max_a_error = a_error;
-                       max_a_error_a = i;
-               }
-//             printf ("alt %d pres %d alt %d\n",
-//                     i, a_to_p, a_to_p_to_a);
-       }
-       if (max_p_error > 2) {
-               printf ("max p error %d at %d\n", max_p_error,
-                       max_p_error_p);
-               ret++;
-       }
-       if (max_a_error > 1) {
-               printf ("max a error %d at %d\n", max_a_error,
-                       max_a_error_a);
-               ret++;
-       }
-       return ret;
-}
diff --git a/src/ao_dbg.c b/src/ao_dbg.c
deleted file mode 100644 (file)
index d4c9567..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_pins.h"
-
-static void
-ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant
-{
-       DBG_PORT = (DBG_PORT & ~msk) | (val & msk);
-       _asm
-               nop
-               nop
-       _endasm;
-}
-
-void
-ao_dbg_send_byte(uint8_t byte)
-{
-       __pdata uint8_t b, d;
-
-       DBG_PORT |= DBG_DATA;
-       DBG_PORT_DIR |= DBG_DATA;
-       for (b = 0; b < 8; b++) {
-               d = 0;
-               if (byte & 0x80)
-                       d = DBG_DATA;
-               byte <<= 1;
-               ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d);
-               ao_dbg_send_bits(DBG_CLOCK|DBG_DATA,     0    |d);
-       }
-       DBG_PORT_DIR &= ~DBG_DATA;
-}
-
-uint8_t
-ao_dbg_recv_byte(void)
-{
-       __pdata uint8_t byte, b;
-
-       byte = 0;
-       for (b = 0; b < 8; b++) {
-               byte = byte << 1;
-               ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK);
-               if (DBG_DATA_PIN)
-                       byte |= 1;
-               ao_dbg_send_bits(DBG_CLOCK, 0);
-       }
-       return byte;
-}
-
-/* 8051 instructions
- */
-#define NOP                    0x00
-#define MOV_direct_data                0x75
-#define LJMP                   0x02
-#define MOV_Rn_data(n)         (0x78 | (n))
-#define DJNZ_Rn_rel(n)         (0xd8 | (n))
-#define MOV_A_direct           0xe5
-#define MOV_direct1_direct2    0x85
-#define MOV_direct_A           0xf5
-#define MOV_DPTR_data16                0x90
-#define MOV_A_data             0x74
-#define MOVX_atDPTR_A          0xf0
-#define MOVX_A_atDPTR          0xe0
-#define INC_DPTR               0xa3
-#define TRAP                   0xa5
-#define SJMP                   0x80
-#define JB                     0x20
-
-#define DEBUG_INSTR(l)         (0x54 | (l))
-
-#define SFR_PSW                        0xD0
-#define SFR_DPL0               0x82
-#define SFR_DPH0               0x83
-#define SFR_DPL1               0x84
-#define SFR_DPH1               0x85
-
-__pdata uint8_t        save_acc;
-__pdata uint8_t save_psw;
-__pdata uint8_t save_dpl0;
-__pdata uint8_t save_dph0;
-__pdata uint8_t save_dpl1;
-__pdata uint8_t save_dph1;
-
-static uint8_t
-ao_dbg_inst1(uint8_t a) __reentrant
-{
-       ao_dbg_send_byte(DEBUG_INSTR(1));
-       ao_dbg_send_byte(a);
-       return ao_dbg_recv_byte();
-}
-
-static uint8_t
-ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant
-{
-       ao_dbg_send_byte(DEBUG_INSTR(2));
-       ao_dbg_send_byte(a);
-       ao_dbg_send_byte(b);
-       return ao_dbg_recv_byte();
-}
-
-static uint8_t
-ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant
-{
-       ao_dbg_send_byte(DEBUG_INSTR(3));
-       ao_dbg_send_byte(a);
-       ao_dbg_send_byte(b);
-       ao_dbg_send_byte(c);
-       return ao_dbg_recv_byte();
-}
-
-void
-ao_dbg_start_transfer(uint16_t addr)
-{
-       save_acc  = ao_dbg_inst1(NOP);
-       save_psw  = ao_dbg_inst2(MOV_A_direct, SFR_PSW);
-       save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0);
-       save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0);
-       save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1);
-       save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1);
-       ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr);
-}
-
-void
-ao_dbg_end_transfer(void)
-{
-       ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0);
-       ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0);
-       ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1);
-       ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1);
-       ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw);
-       ao_dbg_inst2(MOV_A_data, save_acc);
-}
-
-void
-ao_dbg_write_byte(uint8_t byte)
-{
-       ao_dbg_inst2(MOV_A_data, byte);
-       ao_dbg_inst1(MOVX_atDPTR_A);
-       ao_dbg_inst1(INC_DPTR);
-}
-
-uint8_t
-ao_dbg_read_byte(void)
-{
-       ao_dbg_inst1(MOVX_A_atDPTR);
-       return ao_dbg_inst1(INC_DPTR);
-}
-
-static void
-ao_dbg_set_pins(void)
-{
-       /* Make the DBG pins GPIOs. On TeleMetrum, this will
-        * disable the SPI link, so don't expect SPI to work after
-        * using the debugger.
-        */
-       DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N);
-
-       /* make DBG_DATA tri-state */
-       DBG_PORT_INP |= DBG_DATA;
-
-       /* Raise RESET_N and CLOCK */
-       DBG_PORT |= DBG_RESET_N | DBG_CLOCK;
-
-       /* RESET_N and CLOCK are outputs now */
-       DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK;
-       DBG_PORT_DIR &= ~DBG_DATA;
-}
-
-static void
-ao_dbg_long_delay(void)
-{
-       uint8_t n;
-
-       for (n = 0; n < 20; n++)
-               _asm nop _endasm;
-}
-
-#define AO_RESET_LOW_DELAY     AO_MS_TO_TICKS(100)
-#define AO_RESET_HIGH_DELAY    AO_MS_TO_TICKS(100)
-
-void
-ao_dbg_debug_mode(void)
-{
-       ao_dbg_set_pins();
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N,     0    |DBG_DATA|    0    );
-       ao_delay(AO_RESET_LOW_DELAY);
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N,     0    |DBG_DATA|    0    );
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N,     0    |DBG_DATA|DBG_RESET_N);
-       ao_delay(AO_RESET_HIGH_DELAY);
-}
-
-void
-ao_dbg_reset(void)
-{
-       ao_dbg_set_pins();
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
-       ao_delay(AO_RESET_LOW_DELAY);
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
-       ao_dbg_long_delay();
-       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
-       ao_delay(AO_RESET_HIGH_DELAY);
-}
-
-static void
-debug_enable(void)
-{
-       ao_dbg_debug_mode();
-}
-
-static void
-debug_reset(void)
-{
-       ao_dbg_reset();
-}
-
-static void
-debug_put(void)
-{
-       for (;;) {
-               ao_cmd_white ();
-               if (ao_cmd_lex_c == '\n')
-                       break;
-               ao_cmd_hex();
-               if (ao_cmd_status != ao_cmd_success)
-                       break;
-               ao_dbg_send_byte(ao_cmd_lex_i);
-       }
-}
-
-static void
-debug_get(void)
-{
-       __pdata uint16_t count;
-       __pdata uint16_t i;
-       __pdata uint8_t byte;
-       ao_cmd_hex();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       count = ao_cmd_lex_i;
-       if (count > 256) {
-               ao_cmd_status = ao_cmd_syntax_error;
-               return;
-       }
-       for (i = 0; i < count; i++) {
-               if (i && (i & 7) == 0)
-                       putchar('\n');
-               byte = ao_dbg_recv_byte();
-               ao_cmd_put8(byte);
-               putchar(' ');
-       }
-       putchar('\n');
-}
-
-static uint8_t
-getnibble(void)
-{
-       __pdata char    c;
-
-       c = getchar();
-       if ('0' <= c && c <= '9')
-               return c - '0';
-       if ('a' <= c && c <= 'f')
-               return c - ('a' - 10);
-       if ('A' <= c && c <= 'F')
-               return c - ('A' - 10);
-       ao_cmd_status = ao_cmd_lex_error;
-       return 0;
-}
-
-static void
-debug_input(void)
-{
-       __pdata uint16_t count;
-       __pdata uint16_t addr;
-       __pdata uint8_t b;
-       __pdata uint8_t i;
-
-       ao_cmd_hex();
-       count = ao_cmd_lex_i;
-       ao_cmd_hex();
-       addr = ao_cmd_lex_i;
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       ao_dbg_start_transfer(addr);
-       i = 0;
-       while (count--) {
-               if (!(i++ & 7))
-                       putchar('\n');
-               b = ao_dbg_read_byte();
-               ao_cmd_put8(b);
-       }
-       ao_dbg_end_transfer();
-       putchar('\n');
-}
-
-static void
-debug_output(void)
-{
-       __pdata uint16_t count;
-       __pdata uint16_t addr;
-       __pdata uint8_t b;
-
-       ao_cmd_hex();
-       count = ao_cmd_lex_i;
-       ao_cmd_hex();
-       addr = ao_cmd_lex_i;
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       ao_dbg_start_transfer(addr);
-       while (count--) {
-               b = getnibble() << 4;
-               b |= getnibble();
-               if (ao_cmd_status != ao_cmd_success)
-                       return;
-               ao_dbg_write_byte(b);
-       }
-       ao_dbg_end_transfer();
-}
-
-__code struct ao_cmds ao_dbg_cmds[7] = {
-       { debug_enable, "D\0Enable debug" },
-       { debug_get,    "G <count>\0Get data" },
-       { debug_input,  "I <count> <addr>\0Input <count> at <addr>" },
-       { debug_output, "O <count> <addr>\0Output <count> at <addr>" },
-       { debug_put,    "P <byte> ...\0Put data" },
-       { debug_reset,  "R\0Reset" },
-       { 0, NULL },
-};
-
-void
-ao_dbg_init(void)
-{
-       ao_cmd_register(&ao_dbg_cmds[0]);
-}
diff --git a/src/ao_dma.c b/src/ao_dma.c
deleted file mode 100644 (file)
index 6052964..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#define NUM_DMA        5
-
-/*
- * The config address for DMA0 is programmed
- * separately from that of DMA1-4, but for simplicity,
- * we make them all contiguous.
- */
-
-static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA];
-static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA];
-static __data uint8_t ao_next_dma;
-
-uint8_t
-ao_dma_alloc(__xdata uint8_t *done)
-{
-       uint8_t id;
-
-       if (ao_next_dma == NUM_DMA)
-               ao_panic(AO_PANIC_DMA);
-       id = ao_next_dma++;
-       ao_dma_done[id] = done;
-
-       /* When the first dma object is allocated, set up the DMA
-        * controller
-        */
-       if (id == 0) {
-               DMAIRQ = 0;
-               DMAIF = 0;
-               IEN1 |= IEN1_DMAIE;
-       }
-
-       return id;
-}
-
-void
-ao_dma_set_transfer(uint8_t id,
-                   void __xdata *srcaddr,
-                   void __xdata *dstaddr,
-                   uint16_t count,
-                   uint8_t cfg0,
-                   uint8_t cfg1)
-{
-       if (DMAARM & (1 << id))
-               ao_panic(AO_PANIC_DMA);
-       ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8;
-       ao_dma_config[id].src_low = ((uint16_t) srcaddr);
-       ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8;
-       ao_dma_config[id].dst_low = ((uint16_t) dstaddr);
-       ao_dma_config[id].len_high = count >> 8;
-       ao_dma_config[id].len_low = count;
-       ao_dma_config[id].cfg0 = cfg0;
-       ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK;
-       if (id == 0) {
-               DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8;
-               DMA0CFGL = ((uint16_t) (&ao_dma_config[0]));
-       } else {
-               DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8;
-               DMA1CFGL = ((uint16_t) (&ao_dma_config[1]));
-       }
-}
-
-#define nop()  _asm nop _endasm;
-
-void
-ao_dma_start(uint8_t id)
-{
-       uint8_t mask = (1 << id);
-       DMAIRQ &= ~mask;
-       DMAARM = 0x80 | mask;
-       nop(); nop(); nop(); nop();
-       nop(); nop(); nop(); nop();
-       *(ao_dma_done[id]) = 0;
-       DMAARM = mask;
-       nop(); nop(); nop(); nop();
-       nop(); nop(); nop(); nop();
-       nop();
-}
-
-void
-ao_dma_trigger(uint8_t id)
-{
-       DMAREQ |= (1 << id);
-}
-
-void
-ao_dma_abort(uint8_t id)
-{
-       uint8_t mask = (1 << id);
-       DMAARM = 0x80 | mask;
-       DMAIRQ &= ~mask;
-}
-
-void
-ao_dma_isr(void) __interrupt 8
-{
-       uint8_t id, mask;
-
-       /* Find the first DMA channel which is done */
-       mask = 1;
-       for (id = 0; id < ao_next_dma; id++) {
-               if (DMAIRQ & mask) {
-                       /* Clear CPU interrupt flag */
-                       DMAIF = 0;
-                       /* Clear the completed ID */
-                       DMAIRQ = ~mask;
-                       *(ao_dma_done[id]) = 1;
-                       ao_wakeup(ao_dma_done[id]);
-                       break;
-               }
-               mask <<= 1;
-       }
-}
diff --git a/src/ao_ee.c b/src/ao_ee.c
deleted file mode 100644 (file)
index a2fe8dc..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "25lc1024.h"
-
-#define EE_BLOCK_SIZE  ((uint16_t) (256))
-#define EE_BLOCK_SHIFT 8
-#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024)
-
-/* Total bytes of available storage */
-__pdata uint32_t       ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-__pdata uint32_t       ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-__pdata uint32_t       ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-__pdata uint16_t       ao_storage_unit;
-
-/*
- * Using SPI on USART 0, with P1_2 as the chip select
- */
-
-#define EE_CS          P1_2
-#define EE_CS_INDEX    2
-
-static __xdata uint8_t ao_ee_mutex;
-
-#define ao_ee_delay() do { \
-       _asm nop _endasm; \
-       _asm nop _endasm; \
-       _asm nop _endasm; \
-} while(0)
-
-#define ao_ee_cs_low() ao_spi_get_bit(EE_CS)
-
-#define ao_ee_cs_high()        ao_spi_put_bit(EE_CS)
-
-struct ao_ee_instruction {
-       uint8_t instruction;
-       uint8_t address[3];
-} __xdata ao_ee_instruction;
-
-static void
-ao_ee_write_enable(void)
-{
-       ao_ee_cs_low();
-       ao_ee_instruction.instruction = EE_WREN;
-       ao_spi_send(&ao_ee_instruction, 1);
-       ao_ee_cs_high();
-}
-
-static uint8_t
-ao_ee_rdsr(void)
-{
-       ao_ee_cs_low();
-       ao_ee_instruction.instruction = EE_RDSR;
-       ao_spi_send(&ao_ee_instruction, 1);
-       ao_spi_recv(&ao_ee_instruction, 1);
-       ao_ee_cs_high();
-       return ao_ee_instruction.instruction;
-}
-
-static void
-ao_ee_wrsr(uint8_t status)
-{
-       ao_ee_cs_low();
-       ao_ee_instruction.instruction = EE_WRSR;
-       ao_ee_instruction.address[0] = status;
-       ao_spi_send(&ao_ee_instruction, 2);
-       ao_ee_cs_high();
-}
-
-#define EE_BLOCK_NONE  0xffff
-
-static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE];
-static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE;
-static __pdata uint8_t ao_ee_block_dirty;
-
-/* Write the current block to the EEPROM */
-static void
-ao_ee_write_block(void)
-{
-       uint8_t status;
-
-       status = ao_ee_rdsr();
-       if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) {
-               status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN);
-               ao_ee_wrsr(status);
-       }
-       ao_ee_write_enable();
-       ao_ee_cs_low();
-       ao_ee_instruction.instruction = EE_WRITE;
-       ao_ee_instruction.address[0] = ao_ee_block >> 8;
-       ao_ee_instruction.address[1] = ao_ee_block;
-       ao_ee_instruction.address[2] = 0;
-       ao_spi_send(&ao_ee_instruction, 4);
-       ao_spi_send(ao_ee_data, EE_BLOCK_SIZE);
-       ao_ee_cs_high();
-       for (;;) {
-               uint8_t status = ao_ee_rdsr();
-               if ((status & EE_STATUS_WIP) == 0)
-                       break;
-       }
-}
-
-/* Read the current block from the EEPROM */
-static void
-ao_ee_read_block(void)
-{
-       ao_ee_cs_low();
-       ao_ee_instruction.instruction = EE_READ;
-       ao_ee_instruction.address[0] = ao_ee_block >> 8;
-       ao_ee_instruction.address[1] = ao_ee_block;
-       ao_ee_instruction.address[2] = 0;
-       ao_spi_send(&ao_ee_instruction, 4);
-       ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE);
-       ao_ee_cs_high();
-}
-
-static void
-ao_ee_flush_internal(void)
-{
-       if (ao_ee_block_dirty) {
-               ao_ee_write_block();
-               ao_ee_block_dirty = 0;
-       }
-}
-
-static void
-ao_ee_fill(uint16_t block)
-{
-       if (block != ao_ee_block) {
-               ao_ee_flush_internal();
-               ao_ee_block = block;
-               ao_ee_read_block();
-       }
-}
-
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
-       uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
-
-       /* Transfer the data */
-       ao_mutex_get(&ao_ee_mutex); {
-               if (len != EE_BLOCK_SIZE)
-                       ao_ee_fill(block);
-               else {
-                       ao_ee_flush_internal();
-                       ao_ee_block = block;
-               }
-               memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len);
-               ao_ee_block_dirty = 1;
-       } ao_mutex_put(&ao_ee_mutex);
-       return 1;
-}
-
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
-       uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
-
-       /* Transfer the data */
-       ao_mutex_get(&ao_ee_mutex); {
-               ao_ee_fill(block);
-               memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len);
-       } ao_mutex_put(&ao_ee_mutex);
-       return 1;
-}
-
-void
-ao_storage_flush(void) __reentrant
-{
-       ao_mutex_get(&ao_ee_mutex); {
-               ao_ee_flush_internal();
-       } ao_mutex_put(&ao_ee_mutex);
-}
-
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant
-{
-       ao_mutex_get(&ao_ee_mutex); {
-               ao_ee_flush_internal();
-               ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
-               memset(ao_ee_data, 0xff, EE_BLOCK_SIZE);
-               ao_ee_block_dirty = 1;
-       } ao_mutex_put(&ao_ee_mutex);
-       return 1;
-}
-
-static void
-ee_store(void) __reentrant
-{
-}
-
-void
-ao_storage_setup(void)
-{
-       if (ao_storage_total == 0) {
-               ao_storage_total = EE_DEVICE_SIZE;
-               ao_storage_block = EE_BLOCK_SIZE;
-               ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE;
-               ao_storage_unit = EE_BLOCK_SIZE;
-       }
-}
-
-void
-ao_storage_device_info(void) __reentrant
-{
-}
-
-/*
- * To initialize the chip, set up the CS line and
- * the SPI interface
- */
-void
-ao_storage_device_init(void)
-{
-       /* set up CS */
-       EE_CS = 1;
-       P1DIR |= (1 << EE_CS_INDEX);
-       P1SEL &= ~(1 << EE_CS_INDEX);
-}
diff --git a/src/ao_ee_fake.c b/src/ao_ee_fake.c
deleted file mode 100644 (file)
index b0c1d61..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/*
- * For hardware without eeprom, the config code still
- * wants to call these functions
- */
-uint8_t
-ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
-{
-       (void) buf;
-       (void) len;
-       return 1;
-}
-
-uint8_t
-ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
-{
-       memset(buf, '\0', len);
-       return 1;
-}
diff --git a/src/ao_flash.c b/src/ao_flash.c
deleted file mode 100644 (file)
index bb40f6f..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "at45db161d.h"
-
-/* Total bytes of available storage */
-__pdata uint32_t       ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-__pdata uint32_t       ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-__pdata uint32_t       ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-__pdata uint16_t       ao_storage_unit;
-
-#define FLASH_CS               P1_1
-#define FLASH_CS_INDEX         1
-
-#define FLASH_BLOCK_SIZE_MAX   512
-
-__xdata uint8_t ao_flash_mutex;
-
-#define ao_flash_delay() do { \
-       _asm nop _endasm; \
-       _asm nop _endasm; \
-       _asm nop _endasm; \
-} while(0)
-
-#define ao_flash_cs_low()      ao_spi_get_bit(FLASH_CS)
-
-#define ao_flash_cs_high()     ao_spi_put_bit(FLASH_CS)
-
-struct ao_flash_instruction {
-       uint8_t instruction;
-       uint8_t address[3];
-} __xdata ao_flash_instruction;
-
-static void
-ao_flash_set_pagesize_512(void)
-{
-       ao_flash_cs_low();
-       ao_flash_instruction.instruction = FLASH_SET_CONFIG;
-       ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0;
-       ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1;
-       ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2;
-       ao_spi_send(&ao_flash_instruction, 4);
-       ao_flash_cs_high();
-}
-
-
-static uint8_t
-ao_flash_read_status(void)
-{
-       ao_flash_cs_low();
-       ao_flash_instruction.instruction = FLASH_READ_STATUS;
-       ao_spi_send(&ao_flash_instruction, 1);
-       ao_spi_recv(&ao_flash_instruction, 1);
-       ao_flash_cs_high();
-       return ao_flash_instruction.instruction;
-}
-
-#define FLASH_BLOCK_NONE       0xffff
-
-static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX];
-static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE;
-static __pdata uint8_t ao_flash_block_dirty;
-static __pdata uint8_t  ao_flash_write_pending;
-static __pdata uint8_t ao_flash_setup_done;
-static __pdata uint8_t ao_flash_block_shift;
-static __pdata uint16_t        ao_flash_block_size;
-static __pdata uint16_t        ao_flash_block_mask;
-
-void
-ao_storage_setup(void) __reentrant
-{
-       uint8_t status;
-
-       if (ao_flash_setup_done)
-               return;
-
-       ao_mutex_get(&ao_flash_mutex);
-       if (ao_flash_setup_done) {
-               ao_mutex_put(&ao_flash_mutex);
-               return;
-       }
-
-       /* On first use, check to see if the flash chip has
-        * been programmed to use 512 byte pages. If not, do so.
-        * And then, because the flash part must be power cycled
-        * for that change to take effect, panic.
-        */
-       status = ao_flash_read_status();
-
-       if (!(status & FLASH_STATUS_PAGESIZE_512)) {
-               ao_flash_set_pagesize_512();
-               ao_panic(AO_PANIC_FLASH);
-       }
-
-       switch (status & 0x3c) {
-
-       /* AT45DB321D */
-       case 0x34:
-               ao_flash_block_shift = 9;
-               ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024);
-               break;
-
-       /* AT45DB161D */
-       case 0x2c:
-               ao_flash_block_shift = 9;
-               ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024);
-               break;
-
-       /* AT45DB081D */
-       case 0x24:
-               ao_flash_block_shift = 8;
-               ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024);
-               break;
-
-       /* AT45DB041D */
-       case 0x1c:
-               ao_flash_block_shift = 8;
-               ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024);
-               break;
-
-       /* AT45DB021D */
-       case 0x14:
-               ao_flash_block_shift = 8;
-               ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024);
-               break;
-
-       /* AT45DB011D */
-       case 0x0c:
-               ao_flash_block_shift = 8;
-               ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024);
-               break;
-
-       default:
-               ao_panic(AO_PANIC_FLASH);
-       }
-       ao_flash_block_size = 1 << ao_flash_block_shift;
-       ao_flash_block_mask = ao_flash_block_size - 1;
-
-       ao_storage_block = ao_flash_block_size;
-       ao_storage_config = ao_storage_total - ao_storage_block;
-       ao_storage_unit = ao_flash_block_size;
-
-       ao_flash_setup_done = 1;
-       ao_mutex_put(&ao_flash_mutex);
-}
-
-static void
-ao_flash_wait_write(void)
-{
-       if (ao_flash_write_pending) {
-               for (;;) {
-                       uint8_t status = ao_flash_read_status();
-                       if ((status & FLASH_STATUS_RDY))
-                               break;
-               }
-               ao_flash_write_pending = 0;
-       }
-}
-
-/* Write the current block to the FLASHPROM */
-static void
-ao_flash_write_block(void)
-{
-       ao_flash_wait_write();
-       ao_flash_cs_low();
-       ao_flash_instruction.instruction = FLASH_WRITE;
-
-       /* 13/14 block bits + 9/8 byte bits (always 0) */
-       ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
-       ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
-       ao_flash_instruction.address[2] = 0;
-       ao_spi_send(&ao_flash_instruction, 4);
-       ao_spi_send(ao_flash_data, ao_storage_block);
-       ao_flash_cs_high();
-       ao_flash_write_pending = 1;
-}
-
-/* Read the current block from the FLASHPROM */
-static void
-ao_flash_read_block(void)
-{
-       ao_flash_wait_write();
-       ao_flash_cs_low();
-       ao_flash_instruction.instruction = FLASH_READ;
-
-       /* 13/14 block bits + 9/8 byte bits (always 0) */
-       ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
-       ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
-       ao_flash_instruction.address[2] = 0;
-       ao_spi_send(&ao_flash_instruction, 4);
-       ao_spi_recv(ao_flash_data, ao_flash_block_size);
-       ao_flash_cs_high();
-}
-
-static void
-ao_flash_flush_internal(void)
-{
-       if (ao_flash_block_dirty) {
-               ao_flash_write_block();
-               ao_flash_block_dirty = 0;
-       }
-}
-
-static void
-ao_flash_fill(uint16_t block)
-{
-       if (block != ao_flash_block) {
-               ao_flash_flush_internal();
-               ao_flash_block = block;
-               ao_flash_read_block();
-       }
-}
-
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
-       uint16_t block = (uint16_t) (pos >> ao_flash_block_shift);
-
-       /* Transfer the data */
-       ao_mutex_get(&ao_flash_mutex); {
-               if (len != ao_flash_block_size)
-                       ao_flash_fill(block);
-               else {
-                       ao_flash_flush_internal();
-                       ao_flash_block = block;
-               }
-               memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
-                      buf,
-                      len);
-               ao_flash_block_dirty = 1;
-       } ao_mutex_put(&ao_flash_mutex);
-       return 1;
-}
-
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
-       uint16_t block = (uint16_t) (pos >> ao_flash_block_shift);
-
-       /* Transfer the data */
-       ao_mutex_get(&ao_flash_mutex); {
-               ao_flash_fill(block);
-               memcpy(buf,
-                      ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
-                      len);
-       } ao_mutex_put(&ao_flash_mutex);
-       return 1;
-}
-
-void
-ao_storage_flush(void) __reentrant
-{
-       ao_mutex_get(&ao_flash_mutex); {
-               ao_flash_flush_internal();
-       } ao_mutex_put(&ao_flash_mutex);
-}
-
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant
-{
-       ao_mutex_get(&ao_flash_mutex); {
-               ao_flash_flush_internal();
-               ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift);
-               memset(ao_flash_data, 0xff, ao_flash_block_size);
-               ao_flash_block_dirty = 1;
-       } ao_mutex_put(&ao_flash_mutex);
-       return 1;
-}
-
-void
-ao_storage_device_info(void) __reentrant
-{
-       uint8_t status;
-
-       ao_storage_setup();
-       ao_mutex_get(&ao_flash_mutex); {
-               status = ao_flash_read_status();
-               printf ("Flash status: 0x%02x\n", status);
-               printf ("Flash block shift: %d\n", ao_flash_block_shift);
-               printf ("Flash block size: %d\n", ao_flash_block_size);
-               printf ("Flash block mask: %d\n", ao_flash_block_mask);
-               printf ("Flash device size: %ld\n", ao_storage_total);
-       } ao_mutex_put(&ao_flash_mutex);
-}
-
-/*
- * To initialize the chip, set up the CS line and
- * the SPI interface
- */
-void
-ao_storage_device_init(void)
-{
-       /* set up CS */
-       FLASH_CS = 1;
-       P1DIR |= (1 << FLASH_CS_INDEX);
-       P1SEL &= ~(1 << FLASH_CS_INDEX);
-}
diff --git a/src/ao_flight.c b/src/ao_flight.c
deleted file mode 100644 (file)
index 85c1825..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#endif
-
-#ifndef HAS_ACCEL
-#error Please define HAS_ACCEL
-#endif
-
-#ifndef HAS_GPS
-#error Please define HAS_GPS
-#endif
-
-#ifndef HAS_USB
-#error Please define HAS_USB
-#endif
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state   ao_flight_state;        /* current flight state */
-__pdata uint16_t               ao_launch_tick;         /* time of launch detect */
-
-/*
- * track min/max data over a long interval to detect
- * resting
- */
-__pdata uint16_t               ao_interval_end;
-__pdata int16_t                        ao_interval_min_height;
-__pdata int16_t                        ao_interval_max_height;
-__pdata uint8_t                        ao_flight_force_idle;
-
-/* We also have a clock, which can be used to sanity check things in
- * case of other failures
- */
-
-#define BOOST_TICKS_MAX        AO_SEC_TO_TICKS(15)
-
-/* Landing is detected by getting constant readings from both pressure and accelerometer
- * for a fairly long time (AO_INTERVAL_TICKS)
- */
-#define AO_INTERVAL_TICKS      AO_SEC_TO_TICKS(10)
-
-#define abs(a) ((a) < 0 ? -(a) : (a))
-
-void
-ao_flight(void)
-{
-       ao_sample_init();
-       ao_flight_state = ao_flight_startup;
-       for (;;) {
-
-               /*
-                * Process ADC samples, just looping
-                * until the sensors are calibrated.
-                */
-               if (!ao_sample())
-                       continue;
-
-               switch (ao_flight_state) {
-               case ao_flight_startup:
-
-                       /* Check to see what mode we should go to.
-                        *  - Invalid mode if accel cal appears to be out
-                        *  - pad mode if we're upright,
-                        *  - idle mode otherwise
-                        */
-#if HAS_ACCEL
-                       if (ao_config.accel_plus_g == 0 ||
-                           ao_config.accel_minus_g == 0 ||
-                           ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
-                           ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP)
-                       {
-                               /* Detected an accel value outside -1.5g to 1.5g
-                                * (or uncalibrated values), so we go into invalid mode
-                                */
-                               ao_flight_state = ao_flight_invalid;
-
-                       } else
-#endif
-                               if (!ao_flight_force_idle
-#if HAS_ACCEL
-                                   && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP
-#endif
-                                       )
-                       {
-                               /* Set pad mode - we can fly! */
-                               ao_flight_state = ao_flight_pad;
-#if HAS_USB
-                               /* Disable the USB controller in flight mode
-                                * to save power
-                                */
-                               ao_usb_disable();
-#endif
-
-                               /* Disable packet mode in pad state */
-                               ao_packet_slave_stop();
-
-                               /* Turn on telemetry system */
-                               ao_rdf_set(1);
-                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
-
-                               /* signal successful initialization by turning off the LED */
-                               ao_led_off(AO_LED_RED);
-                       } else {
-                               /* Set idle mode */
-                               ao_flight_state = ao_flight_idle;
-                               /* signal successful initialization by turning off the LED */
-                               ao_led_off(AO_LED_RED);
-                       }
-                       /* wakeup threads due to state change */
-                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-
-                       break;
-               case ao_flight_pad:
-
-                       /* pad to boost:
-                        *
-                        * barometer: > 20m vertical motion
-                        *             OR
-                        * accelerometer: > 2g AND velocity > 5m/s
-                        *
-                        * The accelerometer should always detect motion before
-                        * the barometer, but we use both to make sure this
-                        * transition is detected. If the device
-                        * doesn't have an accelerometer, then ignore the
-                        * speed and acceleration as they are quite noisy
-                        * on the pad.
-                        */
-                       if (ao_height > AO_M_TO_HEIGHT(20)
-#if HAS_ACCEL
-                           || (ao_accel > AO_MSS_TO_ACCEL(20) &&
-                               ao_speed > AO_MS_TO_SPEED(5))
-#endif
-                               )
-                       {
-                               ao_flight_state = ao_flight_boost;
-                               ao_launch_tick = ao_sample_tick;
-
-                               /* start logging data */
-                               ao_log_start();
-
-                               /* Increase telemetry rate */
-                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);
-
-                               /* disable RDF beacon */
-                               ao_rdf_set(0);
-
-#if HAS_GPS
-                               /* Record current GPS position by waking up GPS log tasks */
-                               ao_wakeup(&ao_gps_data);
-                               ao_wakeup(&ao_gps_tracking_data);
-#endif
-
-                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       }
-                       break;
-               case ao_flight_boost:
-
-                       /* boost to fast:
-                        *
-                        * accelerometer: start to fall at > 1/4 G
-                        *              OR
-                        * time: boost for more than 15 seconds
-                        *
-                        * Detects motor burn out by the switch from acceleration to
-                        * deceleration, or by waiting until the maximum burn duration
-                        * (15 seconds) has past.
-                        */
-                       if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) ||
-                           (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX)
-                       {
-#if HAS_ACCEL
-                               ao_flight_state = ao_flight_fast;
-#else
-                               ao_flight_state = ao_flight_coast;
-#endif
-                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       }
-                       break;
-#if HAS_ACCEL
-               case ao_flight_fast:
-                       /*
-                        * This is essentially the same as coast,
-                        * but the barometer is being ignored as
-                        * it may be unreliable.
-                        */
-                       if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED))
-                       {
-                               ao_flight_state = ao_flight_coast;
-                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       }
-                       break;
-#endif
-               case ao_flight_coast:
-
-                       /* apogee detect: coast to drogue deploy:
-                        *
-                        * speed: < 0
-                        *
-                        * Also make sure the model altitude is tracking
-                        * the measured altitude reasonably closely; otherwise
-                        * we're probably transsonic.
-                        */
-                       if (ao_speed < 0
-#if !HAS_ACCEL
-                           && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)
-#endif
-                               )
-                       {
-                               /* ignite the drogue charge */
-                               ao_ignite(ao_igniter_drogue);
-
-                               /* slow down the telemetry system */
-                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
-
-                               /* Turn the RDF beacon back on */
-                               ao_rdf_set(1);
-
-                               /* and enter drogue state */
-                               ao_flight_state = ao_flight_drogue;
-                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       }
-
-                       break;
-               case ao_flight_drogue:
-
-                       /* drogue to main deploy:
-                        *
-                        * barometer: reach main deploy altitude
-                        *
-                        * Would like to use the accelerometer for this test, but
-                        * the orientation of the flight computer is unknown after
-                        * drogue deploy, so we ignore it. Could also detect
-                        * high descent rate using the pressure sensor to
-                        * recognize drogue deploy failure and eject the main
-                        * at that point. Perhaps also use the drogue sense lines
-                        * to notice continutity?
-                        */
-                       if (ao_height <= ao_config.main_deploy)
-                       {
-                               ao_ignite(ao_igniter_main);
-
-                               /*
-                                * Start recording min/max height
-                                * to figure out when the rocket has landed
-                                */
-
-                               /* initialize interval values */
-                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
-
-                               ao_interval_min_height = ao_interval_max_height = ao_avg_height;
-
-                               ao_flight_state = ao_flight_main;
-                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       }
-                       break;
-
-                       /* fall through... */
-               case ao_flight_main:
-
-                       /* main to land:
-                        *
-                        * barometer: altitude stable
-                        */
-
-                       if (ao_avg_height < ao_interval_min_height)
-                               ao_interval_min_height = ao_avg_height;
-                       if (ao_avg_height > ao_interval_max_height)
-                               ao_interval_max_height = ao_avg_height;
-
-                       if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
-                               if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4))
-                               {
-                                       ao_flight_state = ao_flight_landed;
-
-                                       /* turn off the ADC capture */
-                                       ao_timer_set_adc_interval(0);
-
-                                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                               }
-                               ao_interval_min_height = ao_interval_max_height = ao_avg_height;
-                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
-                       }
-                       break;
-               case ao_flight_landed:
-                       break;
-               }
-       }
-}
-
-static __xdata struct ao_task  flight_task;
-
-void
-ao_flight_init(void)
-{
-       ao_flight_state = ao_flight_startup;
-       ao_add_task(&flight_task, ao_flight, "flight");
-}
diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c
deleted file mode 100644 (file)
index 2e332b1..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state   ao_flight_state;        /* current flight state */
-__pdata uint16_t               ao_launch_tick;         /* time of launch detect */
-
-/*
- * track min/max data over a long interval to detect
- * resting
- */
-__pdata uint16_t               ao_interval_end;
-__pdata int16_t                        ao_interval_min_height;
-__pdata int16_t                        ao_interval_max_height;
-
-__pdata uint8_t                        ao_flight_force_idle;
-
-/* Landing is detected by getting constant readings from both pressure and accelerometer
- * for a fairly long time (AO_INTERVAL_TICKS)
- */
-#define AO_INTERVAL_TICKS      AO_SEC_TO_TICKS(5)
-
-static void
-ao_flight_nano(void)
-{
-       ao_sample_init();
-       ao_flight_state = ao_flight_startup;
-
-       for (;;) {
-               /*
-                * Process ADC samples, just looping
-                * until the sensors are calibrated.
-                */
-               if (!ao_sample())
-                       continue;
-
-               switch (ao_flight_state) {
-               case ao_flight_startup:
-                       if (ao_flight_force_idle) {
-                               /* Set idle mode */
-                               ao_flight_state = ao_flight_idle;
-                       } else {
-                               ao_flight_state = ao_flight_pad;
-                               /* Disable packet mode in pad state */
-                               ao_packet_slave_stop();
-
-                               /* Turn on telemetry system */
-                               ao_rdf_set(1);
-                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
-                       }
-                       /* signal successful initialization by turning off the LED */
-                       ao_led_off(AO_LED_RED);
-
-                       /* wakeup threads due to state change */
-                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       break;
-               case ao_flight_pad:
-                       if (ao_height> AO_M_TO_HEIGHT(20)) {
-                               ao_flight_state = ao_flight_drogue;
-                               ao_launch_tick = ao_sample_tick;
-
-                               /* start logging data */
-                               ao_log_start();
-
-                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                       }
-                       break;
-               case ao_flight_drogue:
-                       /* drogue/main to land:
-                        *
-                        * barometer: altitude stable
-                        */
-
-                       if (ao_height < ao_interval_min_height)
-                               ao_interval_min_height = ao_height;
-                       if (ao_height > ao_interval_max_height)
-                               ao_interval_max_height = ao_height;
-
-                       if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
-                               if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5))
-                               {
-                                       ao_flight_state = ao_flight_landed;
-
-                                       /* turn off the ADC capture */
-                                       ao_timer_set_adc_interval(0);
-                                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
-                               }
-                               ao_interval_min_height = ao_interval_max_height = ao_height;
-                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
-                       }
-                       break;
-               }
-       }
-}
-
-static __xdata struct ao_task  flight_task;
-
-void
-ao_flight_nano_init(void)
-{
-       ao_flight_state = ao_flight_startup;
-       ao_add_task(&flight_task, ao_flight_nano, "flight");
-}
diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c
deleted file mode 100644 (file)
index 56733c8..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define _GNU_SOURCE
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <math.h>
-
-#define AO_HERTZ       100
-
-#define AO_ADC_RING    64
-#define ao_adc_ring_next(n)    (((n) + 1) & (AO_ADC_RING - 1))
-#define ao_adc_ring_prev(n)    (((n) - 1) & (AO_ADC_RING - 1))
-
-#define AO_M_TO_HEIGHT(m)      ((int16_t) (m))
-#define AO_MS_TO_SPEED(ms)     ((int16_t) ((ms) * 16))
-#define AO_MSS_TO_ACCEL(mss)   ((int16_t) ((mss) * 16))
-
-/*
- * One set of samples read from the A/D converter
- */
-struct ao_adc {
-       uint16_t        tick;           /* tick when the sample was read */
-       int16_t         accel;          /* accelerometer */
-       int16_t         pres;           /* pressure sensor */
-       int16_t         pres_real;      /* unclipped */
-       int16_t         temp;           /* temperature sensor */
-       int16_t         v_batt;         /* battery voltage */
-       int16_t         sense_d;        /* drogue continuity sense */
-       int16_t         sense_m;        /* main continuity sense */
-};
-
-#define __pdata
-#define __data
-#define __xdata
-#define __code
-#define __reentrant
-
-#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
-#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
-#define from_fix(x)    ((x) >> 16)
-
-/*
- * Above this height, the baro sensor doesn't work
- */
-#define AO_MAX_BARO_HEIGHT     12000
-#define AO_BARO_SATURATE       13000
-#define AO_MIN_BARO_VALUE      ao_altitude_to_pres(AO_BARO_SATURATE)
-
-/*
- * Above this speed, baro measurements are unreliable
- */
-#define AO_MAX_BARO_SPEED      200
-
-#define ACCEL_NOSE_UP  (ao_accel_2g >> 2)
-
-enum ao_flight_state {
-       ao_flight_startup = 0,
-       ao_flight_idle = 1,
-       ao_flight_pad = 2,
-       ao_flight_boost = 3,
-       ao_flight_fast = 4,
-       ao_flight_coast = 5,
-       ao_flight_drogue = 6,
-       ao_flight_main = 7,
-       ao_flight_landed = 8,
-       ao_flight_invalid = 9
-};
-
-extern enum ao_flight_state ao_flight_state;
-
-#define FALSE 0
-#define TRUE 1
-
-struct ao_adc ao_adc_ring[AO_ADC_RING];
-uint8_t ao_adc_head;
-int    ao_summary = 0;
-
-#define ao_led_on(l)
-#define ao_led_off(l)
-#define ao_timer_set_adc_interval(i)
-#define ao_wakeup(wchan) ao_dump_state()
-#define ao_cmd_register(c)
-#define ao_usb_disable()
-#define ao_telemetry_set_interval(x)
-#define ao_rdf_set(rdf)
-#define ao_packet_slave_start()
-#define ao_packet_slave_stop()
-
-enum ao_igniter {
-       ao_igniter_drogue = 0,
-       ao_igniter_main = 1
-};
-
-struct ao_adc ao_adc_static;
-
-int    drogue_height;
-double drogue_time;
-int    main_height;
-double main_time;
-
-int    tick_offset;
-
-static int32_t ao_k_height;
-
-void
-ao_ignite(enum ao_igniter igniter)
-{
-       double time = (double) (ao_adc_static.tick + tick_offset) / 100;
-
-       if (igniter == ao_igniter_drogue) {
-               drogue_time = time;
-               drogue_height = ao_k_height >> 16;
-       } else {
-               main_time = time;
-               main_height = ao_k_height >> 16;
-       }
-}
-
-struct ao_task {
-       int dummy;
-};
-
-#define ao_add_task(t,f,n)
-
-#define ao_log_start()
-#define ao_log_stop()
-
-#define AO_MS_TO_TICKS(ms)     ((ms) / 10)
-#define AO_SEC_TO_TICKS(s)     ((s) * 100)
-
-#define AO_FLIGHT_TEST
-
-int    ao_flight_debug;
-
-FILE *emulator_in;
-char *emulator_app;
-char *emulator_name;
-double emulator_error_max = 4;
-double emulator_height_error_max = 20; /* noise in the baro sensor */
-
-void
-ao_dump_state(void);
-
-void
-ao_sleep(void *wchan);
-
-const char const * const ao_state_names[] = {
-       "startup", "idle", "pad", "boost", "fast",
-       "coast", "drogue", "main", "landed", "invalid"
-};
-
-struct ao_cmds {
-       void            (*func)(void);
-       const char      *help;
-};
-
-#include "ao_convert.c"
-
-struct ao_config {
-       uint16_t        main_deploy;
-       int16_t         accel_plus_g;
-       int16_t         accel_minus_g;
-       uint8_t         pad_orientation;
-};
-
-#define AO_PAD_ORIENTATION_ANTENNA_UP  0
-#define AO_PAD_ORIENTATION_ANTENNA_DOWN        1
-
-#define ao_config_get()
-
-struct ao_config ao_config;
-
-#define DATA_TO_XDATA(x) (x)
-
-#define HAS_FLIGHT 1
-#define HAS_ADC 1
-#define HAS_USB 1
-#define HAS_GPS 1
-#ifndef HAS_ACCEL
-#define HAS_ACCEL 1
-#define HAS_ACCEL_REF 0
-#endif
-
-#define GRAVITY 9.80665
-extern int16_t ao_ground_accel, ao_flight_accel;
-extern int16_t ao_accel_2g;
-
-extern uint16_t        ao_sample_tick;
-
-extern int16_t ao_sample_height;
-extern int16_t ao_sample_accel;
-extern int32_t ao_accel_scale;
-extern int16_t ao_ground_height;
-extern int16_t ao_sample_alt;
-
-int ao_sample_prev_tick;
-uint16_t       prev_tick;
-
-#include "ao_kalman.c"
-#include "ao_sample.c"
-#include "ao_flight.c"
-
-#define to_double(f)   ((f) / 65536.0)
-
-static int     ao_records_read = 0;
-static int     ao_eof_read = 0;
-static int     ao_flight_ground_accel;
-static int     ao_flight_started = 0;
-static int     ao_test_max_height;
-static double  ao_test_max_height_time;
-static int     ao_test_main_height;
-static double  ao_test_main_height_time;
-static double  ao_test_landed_time;
-static double  ao_test_landed_height;
-static double  ao_test_landed_time;
-static int     landed_set;
-static double  landed_time;
-static double  landed_height;
-
-void
-ao_test_exit(void)
-{
-       double  drogue_error;
-       double  main_error;
-       double  landed_error;
-       double  landed_time_error;
-
-       if (!ao_test_main_height_time) {
-               ao_test_main_height_time = ao_test_max_height_time;
-               ao_test_main_height = ao_test_max_height;
-       }
-       drogue_error = fabs(ao_test_max_height_time - drogue_time);
-       main_error = fabs(ao_test_main_height_time - main_time);
-       landed_error = fabs(ao_test_landed_height - landed_height);
-       landed_time_error = ao_test_landed_time - landed_time;
-       if (drogue_error > emulator_error_max || main_error > emulator_error_max ||
-           landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) {
-               printf ("%s %s\n",
-                       emulator_app, emulator_name);
-               printf ("\tApogee error %g\n", drogue_error);
-               printf ("\tMain error %g\n", main_error);
-               printf ("\tLanded height error %g\n", landed_error);
-               printf ("\tLanded time error %g\n", landed_time_error);
-               printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n",
-                       ao_test_max_height, ao_test_max_height_time,
-                       ao_test_main_height, ao_test_main_height_time,
-                       ao_test_landed_height, ao_test_landed_time);
-               printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n",
-                       drogue_height, drogue_time, main_height, main_time,
-                       landed_height, landed_time);
-               exit (1);
-       }
-       exit(0);
-}
-
-void
-ao_insert(void)
-{
-       double  time;
-
-       ao_adc_ring[ao_adc_head] = ao_adc_static;
-       ao_adc_head = ao_adc_ring_next(ao_adc_head);
-       if (ao_flight_state != ao_flight_startup) {
-               double  height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height;
-               double  accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) /
-                       (ao_config.accel_minus_g - ao_config.accel_plus_g);
-
-               if (!tick_offset)
-                       tick_offset = -ao_adc_static.tick;
-               if ((prev_tick - ao_adc_static.tick) > 0x400)
-                       tick_offset += 65536;
-               prev_tick = ao_adc_static.tick;
-               time = (double) (ao_adc_static.tick + tick_offset) / 100;
-
-               if (ao_test_max_height < height) {
-                       ao_test_max_height = height;
-                       ao_test_max_height_time = time;
-                       ao_test_landed_height = height;
-                       ao_test_landed_time = time;
-               }
-               if (height > ao_config.main_deploy) {
-                       ao_test_main_height_time = time;
-                       ao_test_main_height = height;
-               }
-
-               if (ao_test_landed_height > height) {
-                       ao_test_landed_height = height;
-                       ao_test_landed_time = time;
-               }
-
-               if (ao_flight_state == ao_flight_landed && !landed_set) {
-                       landed_set = 1;
-                       landed_time = time;
-                       landed_height = height;
-               }
-
-               if (!ao_summary) {
-                       printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n",
-                              time,
-                              height,
-                              accel,
-                              ao_state_names[ao_flight_state],
-                              ao_k_height / 65536.0,
-                              ao_k_speed / 65536.0 / 16.0,
-                              ao_k_accel / 65536.0 / 16.0,
-                              ao_avg_height,
-                              drogue_height,
-                              main_height,
-                              ao_error_h_sq_avg);
-                       
-//                     if (ao_flight_state == ao_flight_landed)
-//                             ao_test_exit();
-               }
-       }
-}
-
-#define AO_MAX_CALLSIGN                        8
-#define AO_MAX_VERSION                 8
-#define AO_MAX_TELEMETRY               128
-
-struct ao_telemetry_generic {
-       uint16_t        serial;         /* 0 */
-       uint16_t        tick;           /* 2 */
-       uint8_t         type;           /* 4 */
-       uint8_t         payload[27];    /* 5 */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01
-#define AO_TELEMETRY_SENSOR_TELEMINI   0x02
-#define AO_TELEMETRY_SENSOR_TELENANO   0x03
-
-struct ao_telemetry_sensor {
-       uint16_t        serial;         /*  0 */
-       uint16_t        tick;           /*  2 */
-       uint8_t         type;           /*  4 */
-
-       uint8_t         state;          /*  5 flight state */
-       int16_t         accel;          /*  6 accelerometer (TM only) */
-       int16_t         pres;           /*  8 pressure sensor */
-       int16_t         temp;           /* 10 temperature sensor */
-       int16_t         v_batt;         /* 12 battery voltage */
-       int16_t         sense_d;        /* 14 drogue continuity sense (TM/Tm) */
-       int16_t         sense_m;        /* 16 main continuity sense (TM/Tm) */
-
-       int16_t         acceleration;   /* 18 m/s² * 16 */
-       int16_t         speed;          /* 20 m/s * 16 */
-       int16_t         height;         /* 22 m */
-
-       int16_t         ground_pres;    /* 24 average pres on pad */
-       int16_t         ground_accel;   /* 26 average accel on pad */
-       int16_t         accel_plus_g;   /* 28 accel calibration at +1g */
-       int16_t         accel_minus_g;  /* 30 accel calibration at -1g */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_CONFIGURATION     0x04
-
-struct ao_telemetry_configuration {
-       uint16_t        serial;                         /*  0 */
-       uint16_t        tick;                           /*  2 */
-       uint8_t         type;                           /*  4 */
-
-       uint8_t         device;                         /*  5 device type */
-       uint16_t        flight;                         /*  6 flight number */
-       uint8_t         config_major;                   /*  8 Config major version */
-       uint8_t         config_minor;                   /*  9 Config minor version */
-       uint16_t        apogee_delay;                   /* 10 Apogee deploy delay in seconds */
-       uint16_t        main_deploy;                    /* 12 Main deploy alt in meters */
-       uint16_t        flight_log_max;                 /* 14 Maximum flight log size in kB */
-       char            callsign[AO_MAX_CALLSIGN];      /* 16 Radio operator identity */
-       char            version[AO_MAX_VERSION];        /* 24 Software version */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_LOCATION          0x05
-
-#define AO_GPS_MODE_NOT_VALID          'N'
-#define AO_GPS_MODE_AUTONOMOUS         'A'
-#define AO_GPS_MODE_DIFFERENTIAL       'D'
-#define AO_GPS_MODE_ESTIMATED          'E'
-#define AO_GPS_MODE_MANUAL             'M'
-#define AO_GPS_MODE_SIMULATED          'S'
-
-struct ao_telemetry_location {
-       uint16_t        serial;         /*  0 */
-       uint16_t        tick;           /*  2 */
-       uint8_t         type;           /*  4 */
-
-       uint8_t         flags;          /*  5 Number of sats and other flags */
-       int16_t         altitude;       /*  6 GPS reported altitude (m) */
-       int32_t         latitude;       /*  8 latitude (degrees * 10⁷) */
-       int32_t         longitude;      /* 12 longitude (degrees * 10⁷) */
-       uint8_t         year;           /* 16 (- 2000) */
-       uint8_t         month;          /* 17 (1-12) */
-       uint8_t         day;            /* 18 (1-31) */
-       uint8_t         hour;           /* 19 (0-23) */
-       uint8_t         minute;         /* 20 (0-59) */
-       uint8_t         second;         /* 21 (0-59) */
-       uint8_t         pdop;           /* 22 (m * 5) */
-       uint8_t         hdop;           /* 23 (m * 5) */
-       uint8_t         vdop;           /* 24 (m * 5) */
-       uint8_t         mode;           /* 25 */
-       uint16_t        ground_speed;   /* 26 cm/s */
-       int16_t         climb_rate;     /* 28 cm/s */
-       uint8_t         course;         /* 30 degrees / 2 */
-       uint8_t         unused[1];      /* 31 */
-       /* 32 */
-};
-
-#define AO_TELEMETRY_SATELLITE         0x06
-
-struct ao_telemetry_satellite_info {
-       uint8_t         svid;
-       uint8_t         c_n_1;
-};
-
-struct ao_telemetry_satellite {
-       uint16_t                                serial;         /*  0 */
-       uint16_t                                tick;           /*  2 */
-       uint8_t                                 type;           /*  4 */
-       uint8_t                                 channels;       /*  5 number of reported sats */
-
-       struct ao_telemetry_satellite_info      sats[12];       /* 6 */
-       uint8_t                                 unused[2];      /* 30 */
-       /* 32 */
-};
-
-union ao_telemetry_all {
-       struct ao_telemetry_generic             generic;
-       struct ao_telemetry_sensor              sensor;
-       struct ao_telemetry_configuration       configuration;
-       struct ao_telemetry_location            location;
-       struct ao_telemetry_satellite           satellite;
-};
-
-uint16_t
-uint16(uint8_t *bytes, int off)
-{
-       off++;
-       return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8);
-}
-
-int16_t
-int16(uint8_t *bytes, int off)
-{
-       return (int16_t) uint16(bytes, off);
-}
-
-void
-ao_sleep(void *wchan)
-{
-       if (wchan == &ao_adc_head) {
-               char            type;
-               uint16_t        tick;
-               uint16_t        a, b;
-               int             ret;
-               uint8_t         bytes[1024];
-               union ao_telemetry_all  telem;
-               char            line[1024];
-               char            *saveptr;
-               char            *l;
-               char            *words[64];
-               int             nword;
-
-               for (;;) {
-                       if (ao_records_read > 2 && ao_flight_state == ao_flight_startup)
-                       {
-                               ao_adc_static.accel = ao_flight_ground_accel;
-                               ao_insert();
-                               return;
-                       }
-
-                       if (!fgets(line, sizeof (line), emulator_in)) {
-                               if (++ao_eof_read >= 1000) {
-                                       if (!ao_summary)
-                                               printf ("no more data, exiting simulation\n");
-                                       ao_test_exit();
-                               }
-                               ao_adc_static.tick += 10;
-                               ao_insert();
-                               return;
-                       }
-                       l = line;
-                       for (nword = 0; nword < 64; nword++) {
-                               words[nword] = strtok_r(l, " \t\n", &saveptr);
-                               l = NULL;
-                               if (words[nword] == NULL)
-                                       break;
-                       }
-                       if (nword == 4) {
-                               type = words[0][0];
-                               tick = strtoul(words[1], NULL, 16);
-                               a = strtoul(words[2], NULL, 16);
-                               b = strtoul(words[3], NULL, 16);
-                               if (type == 'P')
-                                       type = 'A';
-                       } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) {
-                               ao_config.accel_plus_g = atoi(words[3]);
-                               ao_config.accel_minus_g = atoi(words[5]);
-                       } else if (nword >= 4 && strcmp(words[0], "Main") == 0) {
-                               ao_config.main_deploy = atoi(words[2]);
-                       } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) {
-                               tick = atoi(words[10]);
-                               if (!ao_flight_started) {
-                                       type = 'F';
-                                       a = atoi(words[26]);
-                                       ao_flight_started = 1;
-                               } else {
-                                       type = 'A';
-                                       a = atoi(words[12]);
-                                       b = atoi(words[14]);
-                               }
-                       } else if (nword == 3 && strcmp(words[0], "BARO") == 0) {
-                               tick = strtol(words[1], NULL, 16);
-                               a = 16384 - 328;
-                               b = strtol(words[2], NULL, 10);
-                               type = 'A';
-                               if (!ao_flight_started) {
-                                       ao_flight_ground_accel = 16384 - 328;
-                                       ao_config.accel_plus_g = 16384 - 328;
-                                       ao_config.accel_minus_g = 16384 + 328;
-                                       ao_flight_started = 1;
-                               }
-                       } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) {
-                               char    *hex = words[1];
-                               char    elt[3];
-                               int     i, len;
-                               uint8_t sum;
-
-                               len = strlen(hex);
-                               if (len > sizeof (bytes) * 2) {
-                                       len = sizeof (bytes)*2;
-                                       hex[len] = '\0';
-                               }
-                               for (i = 0; i < len; i += 2) {
-                                       elt[0] = hex[i];
-                                       elt[1] = hex[i+1];
-                                       elt[2] = '\0';
-                                       bytes[i/2] = (uint8_t) strtol(elt, NULL, 16);
-                               }
-                               len = i/2;
-                               if (bytes[0] != len - 2) {
-                                       printf ("bad length %d != %d\n", bytes[0], len - 2);
-                                       continue;
-                               }
-                               sum = 0x5a;
-                               for (i = 1; i < len-1; i++)
-                                       sum += bytes[i];
-                               if (sum != bytes[len-1]) {
-                                       printf ("bad checksum\n");
-                                       continue;
-                               }
-                               if ((bytes[len-2] & 0x80) == 0) {
-                                       continue;
-                               }
-                               if (len == 36) {
-                                       memcpy(&telem, bytes + 1, 32);
-                                       tick = telem.generic.tick;
-                                       switch (telem.generic.type) {
-                                       case AO_TELEMETRY_SENSOR_TELEMETRUM:
-                                       case AO_TELEMETRY_SENSOR_TELEMINI:
-                                       case AO_TELEMETRY_SENSOR_TELENANO:
-                                               if (!ao_flight_started) {
-                                                       ao_flight_ground_accel = telem.sensor.ground_accel;
-                                                       ao_config.accel_plus_g = telem.sensor.accel_plus_g;
-                                                       ao_config.accel_minus_g = telem.sensor.accel_minus_g;
-                                                       ao_flight_started = 1;
-                                               }
-                                               type = 'A';
-                                               a = telem.sensor.accel;
-                                               b = telem.sensor.pres;
-                                               break;
-                                       }
-                               } else if (len == 99) {
-                                       ao_flight_started = 1;
-                                       tick = uint16(bytes, 21);
-                                       ao_flight_ground_accel = int16(bytes, 7);
-                                       ao_config.accel_plus_g = int16(bytes, 17);
-                                       ao_config.accel_minus_g = int16(bytes, 19);
-                                       type = 'A';
-                                       a = int16(bytes, 23);
-                                       b = int16(bytes, 25);
-                               } else if (len == 98) {
-                                       ao_flight_started = 1;
-                                       tick = uint16(bytes, 20);
-                                       ao_flight_ground_accel = int16(bytes, 6);
-                                       ao_config.accel_plus_g = int16(bytes, 16);
-                                       ao_config.accel_minus_g = int16(bytes, 18);
-                                       type = 'A';
-                                       a = int16(bytes, 22);
-                                       b = int16(bytes, 24);
-                               } else {
-                                       printf("unknown len %d\n", len);
-                                       continue;
-                               }
-                       }
-                       if (type != 'F' && !ao_flight_started)
-                               continue;
-
-                       switch (type) {
-                       case 'F':
-                               ao_flight_ground_accel = a;
-                               if (ao_config.accel_plus_g == 0) {
-                                       ao_config.accel_plus_g = a;
-                                       ao_config.accel_minus_g = a + 530;
-                               }
-                               if (ao_config.main_deploy == 0)
-                                       ao_config.main_deploy = 250;
-                               ao_flight_started = 1;
-                               break;
-                       case 'S':
-                               break;
-                       case 'A':
-                               ao_adc_static.tick = tick;
-                               ao_adc_static.accel = a;
-                               ao_adc_static.pres_real = b;
-                               if (b < AO_MIN_BARO_VALUE)
-                                       b = AO_MIN_BARO_VALUE;
-                               ao_adc_static.pres = b;
-                               ao_records_read++;
-                               ao_insert();
-                               return;
-                       case 'T':
-                               ao_adc_static.tick = tick;
-                               ao_adc_static.temp = a;
-                               ao_adc_static.v_batt = b;
-                               break;
-                       case 'D':
-                       case 'G':
-                       case 'N':
-                       case 'W':
-                       case 'H':
-                               break;
-                       }
-               }
-
-       }
-}
-#define COUNTS_PER_G 264.8
-
-void
-ao_dump_state(void)
-{
-}
-
-static const struct option options[] = {
-       { .name = "summary", .has_arg = 0, .val = 's' },
-       { .name = "debug", .has_arg = 0, .val = 'd' },
-       { 0, 0, 0, 0},
-};
-
-void run_flight_fixed(char *name, FILE *f, int summary)
-{
-       emulator_name = name;
-       emulator_in = f;
-       ao_summary = summary;
-       ao_flight_init();
-       ao_flight();
-}
-
-int
-main (int argc, char **argv)
-{
-       int     summary = 0;
-       int     c;
-       int     i;
-
-#if HAS_ACCEL
-       emulator_app="full";
-#else
-       emulator_app="baro";
-#endif
-       while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) {
-               switch (c) {
-               case 's':
-                       summary = 1;
-                       break;
-               case 'd':
-                       ao_flight_debug = 1;
-                       break;
-               }
-       }
-
-       if (optind == argc)
-               run_flight_fixed("<stdin>", stdin, summary);
-       else
-               for (i = optind; i < argc; i++) {
-                       FILE    *f = fopen(argv[i], "r");
-                       if (!f) {
-                               perror(argv[i]);
-                               continue;
-                       }
-                       run_flight_fixed(argv[i], f, summary);
-                       fclose(f);
-               }
-}
diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c
deleted file mode 100644 (file)
index fcdedd3..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_GPS_TEST
-#include "ao.h"
-#endif
-#include "ao_telem.h"
-
-void
-ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
-{
-       char    state;
-
-       if (gps_data->flags & AO_GPS_VALID)
-               state = AO_TELEM_GPS_STATE_LOCKED;
-       else if (gps_data->flags & AO_GPS_RUNNING)
-               state = AO_TELEM_GPS_STATE_UNLOCKED;
-       else
-               state = AO_TELEM_GPS_STATE_ERROR;
-       printf(AO_TELEM_GPS_STATE " %c "
-              AO_TELEM_GPS_NUM_SAT " %d ",
-              state,
-              (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
-       if (!(gps_data->flags & AO_GPS_VALID))
-               return;
-       printf(AO_TELEM_GPS_LATITUDE " %ld "
-              AO_TELEM_GPS_LONGITUDE " %ld "
-              AO_TELEM_GPS_ALTITUDE " %d ",
-              gps_data->latitude,
-              gps_data->longitude,
-              gps_data->altitude);
-
-       if (gps_data->flags & AO_GPS_DATE_VALID)
-               printf(AO_TELEM_GPS_YEAR " %d "
-                      AO_TELEM_GPS_MONTH " %d "
-                      AO_TELEM_GPS_DAY " %d ",
-                      gps_data->year,
-                      gps_data->month,
-                      gps_data->day);
-
-       printf(AO_TELEM_GPS_HOUR " %d "
-              AO_TELEM_GPS_MINUTE " %d "
-              AO_TELEM_GPS_SECOND " %d ",
-              gps_data->hour,
-              gps_data->minute,
-              gps_data->second);
-
-       printf(AO_TELEM_GPS_HDOP " %d ",
-              gps_data->hdop * 2);
-
-       if (gps_data->flags & AO_GPS_COURSE_VALID) {
-               printf(AO_TELEM_GPS_HERROR " %d "
-                      AO_TELEM_GPS_VERROR " %d "
-                      AO_TELEM_GPS_VERTICAL_SPEED " %d "
-                      AO_TELEM_GPS_HORIZONTAL_SPEED " %d "
-                      AO_TELEM_GPS_COURSE " %d ",
-                      gps_data->h_error,
-                      gps_data->v_error,
-                      gps_data->climb_rate,
-                      gps_data->ground_speed,
-                      (int) gps_data->course * 2);
-       }
-}
-
-void
-ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant
-{
-       uint8_t c, n, v;
-       __xdata struct ao_gps_sat_orig  *sat;
-
-       n = gps_tracking_data->channels;
-       if (n == 0)
-               return;
-
-       sat = gps_tracking_data->sats;
-       v = 0;
-       for (c = 0; c < n; c++) {
-               if (sat->svid)
-                       v++;
-               sat++;
-       }
-
-       printf (AO_TELEM_SAT_NUM " %d ",
-               v);
-
-       sat = gps_tracking_data->sats;
-       v = 0;
-       for (c = 0; c < n; c++) {
-               if (sat->svid) {
-                       printf (AO_TELEM_SAT_SVID "%d %d "
-                               AO_TELEM_SAT_C_N_0 "%d %d ",
-                               v, sat->svid,
-                               v, sat->c_n_1);
-                       v++;
-               }
-               sat++;
-       }
-}
diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c
deleted file mode 100644 (file)
index e57f874..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_gps_report(void)
-{
-       static __xdata struct ao_log_record             gps_log;
-       static __xdata struct ao_telemetry_location     gps_data;
-       uint8_t date_reported = 0;
-
-       for (;;) {
-               ao_sleep(&ao_gps_data);
-               ao_mutex_get(&ao_gps_mutex);
-               memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
-               ao_mutex_put(&ao_gps_mutex);
-
-               if (!(gps_data.flags & AO_GPS_VALID))
-                       continue;
-
-               gps_log.tick = ao_gps_tick;
-               gps_log.type = AO_LOG_GPS_TIME;
-               gps_log.u.gps_time.hour = gps_data.hour;
-               gps_log.u.gps_time.minute = gps_data.minute;
-               gps_log.u.gps_time.second = gps_data.second;
-               gps_log.u.gps_time.flags = gps_data.flags;
-               ao_log_data(&gps_log);
-               gps_log.type = AO_LOG_GPS_LAT;
-               gps_log.u.gps_latitude = gps_data.latitude;
-               ao_log_data(&gps_log);
-               gps_log.type = AO_LOG_GPS_LON;
-               gps_log.u.gps_longitude = gps_data.longitude;
-               ao_log_data(&gps_log);
-               gps_log.type = AO_LOG_GPS_ALT;
-               gps_log.u.gps_altitude.altitude = gps_data.altitude;
-               gps_log.u.gps_altitude.unused = 0xffff;
-               ao_log_data(&gps_log);
-               if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
-                       gps_log.type = AO_LOG_GPS_DATE;
-                       gps_log.u.gps_date.year = gps_data.year;
-                       gps_log.u.gps_date.month = gps_data.month;
-                       gps_log.u.gps_date.day = gps_data.day;
-                       gps_log.u.gps_date.extra = 0;
-                       date_reported = ao_log_data(&gps_log);
-               }
-       }
-}
-
-void
-ao_gps_tracking_report(void)
-{
-       static __xdata struct ao_log_record             gps_log;
-       static __xdata struct ao_telemetry_satellite    gps_tracking_data;
-       uint8_t c, n;
-
-       for (;;) {
-               ao_sleep(&ao_gps_tracking_data);
-               ao_mutex_get(&ao_gps_mutex);
-               gps_log.tick = ao_gps_tick;
-               memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
-               ao_mutex_put(&ao_gps_mutex);
-
-               if (!(n = gps_tracking_data.channels))
-                       continue;
-
-               gps_log.type = AO_LOG_GPS_SAT;
-               for (c = 0; c < n; c++)
-                       if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid))
-                       {
-                               gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1;
-                               ao_log_data(&gps_log);
-                       }
-       }
-}
-
-__xdata struct ao_task ao_gps_report_task;
-__xdata struct ao_task ao_gps_tracking_report_task;
-
-void
-ao_gps_report_init(void)
-{
-       ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report");
-       ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report");
-}
diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c
deleted file mode 100644 (file)
index f2abbf8..0000000
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_GPS_TEST
-#include "ao.h"
-#endif
-
-__xdata uint8_t ao_gps_mutex;
-__pdata uint16_t ao_gps_tick;
-__xdata struct ao_telemetry_location   ao_gps_data;
-__xdata struct ao_telemetry_satellite  ao_gps_tracking_data;
-
-static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n";
-
-const char ao_gps_config[] = {
-
-       0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */
-       136,                    /* mode control */
-       0, 0,                   /* reserved */
-       0,                      /* degraded mode (allow 1-SV navigation) */
-       0, 0,                   /* reserved */
-       0, 0,                   /* user specified altitude */
-       2,                      /* alt hold mode (disabled, require 3d fixes) */
-       0,                      /* alt hold source (use last computed altitude) */
-       0,                      /* reserved */
-       10,                     /* Degraded time out (10 sec) */
-       10,                     /* Dead Reckoning time out (10 sec) */
-       0,                      /* Track smoothing (disabled) */
-       0x00, 0x8e, 0xb0, 0xb3,
-
-       0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */
-       166,                    /* Set message rate */
-       2,                      /* enable/disable all messages */
-       0,                      /* message id (ignored) */
-       0,                      /* update rate (0 = disable) */
-       0, 0, 0, 0,             /* reserved */
-       0x00, 0xa8, 0xb0, 0xb3,
-
-       0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */
-       143,                    /* static navigation */
-       0,                      /* disable */
-       0x00, 0x8f, 0xb0, 0xb3,
-};
-
-#define NAV_TYPE_GPS_FIX_TYPE_MASK                     (7 << 0)
-#define NAV_TYPE_NO_FIX                                        (0 << 0)
-#define NAV_TYPE_SV_KF                                 (1 << 0)
-#define NAV_TYPE_2_SV_KF                               (2 << 0)
-#define NAV_TYPE_3_SV_KF                               (3 << 0)
-#define NAV_TYPE_4_SV_KF                               (4 << 0)
-#define NAV_TYPE_2D_LEAST_SQUARES                      (5 << 0)
-#define NAV_TYPE_3D_LEAST_SQUARES                      (6 << 0)
-#define NAV_TYPE_DR                                    (7 << 0)
-#define NAV_TYPE_TRICKLE_POWER                         (1 << 3)
-#define NAV_TYPE_ALTITUDE_HOLD_MASK                    (3 << 4)
-#define NAV_TYPE_ALTITUDE_HOLD_NONE                    (0 << 4)
-#define NAV_TYPE_ALTITUDE_HOLD_KF                      (1 << 4)
-#define NAV_TYPE_ALTITUDE_HOLD_USER                    (2 << 4)
-#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS                  (3 << 4)
-#define NAV_TYPE_DOP_LIMIT_EXCEEDED                    (1 << 6)
-#define NAV_TYPE_DGPS_APPLIED                          (1 << 7)
-#define NAV_TYPE_SENSOR_DR                             (1 << 8)
-#define NAV_TYPE_OVERDETERMINED                                (1 << 9)
-#define NAV_TYPE_DR_TIMEOUT_EXCEEDED                   (1 << 10)
-#define NAV_TYPE_FIX_MI_EDIT                           (1 << 11)
-#define NAV_TYPE_INVALID_VELOCITY                      (1 << 12)
-#define NAV_TYPE_ALTITUDE_HOLD_DISABLED                        (1 << 13)
-#define NAV_TYPE_DR_ERROR_STATUS_MASK                  (3 << 14)
-#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY              (0 << 14)
-#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS           (1 << 14)
-#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR       (2 << 14)
-#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST            (3 << 14)
-
-struct sirf_geodetic_nav_data {
-       uint16_t        nav_type;
-       uint16_t        utc_year;
-       uint8_t         utc_month;
-       uint8_t         utc_day;
-       uint8_t         utc_hour;
-       uint8_t         utc_minute;
-       uint16_t        utc_second;
-       int32_t         lat;
-       int32_t         lon;
-       int32_t         alt_msl;
-       uint16_t        ground_speed;
-       uint16_t        course;
-       int16_t         climb_rate;
-       uint32_t        h_error;
-       uint32_t        v_error;
-       uint8_t         num_sv;
-       uint8_t         hdop;
-};
-
-static __xdata struct sirf_geodetic_nav_data   ao_sirf_data;
-
-struct sirf_measured_sat_data {
-       uint8_t         svid;
-       uint8_t         c_n_1;
-};
-
-struct sirf_measured_tracker_data {
-       int16_t                         gps_week;
-       uint32_t                        gps_tow;
-       uint8_t                         channels;
-       struct sirf_measured_sat_data   sats[12];
-};
-
-static __xdata struct sirf_measured_tracker_data       ao_sirf_tracker_data;
-
-static __pdata uint16_t ao_sirf_cksum;
-static __pdata uint16_t ao_sirf_len;
-
-#define ao_sirf_byte() ((uint8_t) ao_serial_getchar())
-
-static uint8_t data_byte(void)
-{
-       uint8_t c = ao_sirf_byte();
-       --ao_sirf_len;
-       ao_sirf_cksum += c;
-       return c;
-}
-
-static char __xdata *sirf_target;
-
-static void sirf_u16(uint8_t offset)
-{
-       uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset);
-       uint16_t val;
-
-       val = data_byte() << 8;
-       val |= data_byte ();
-       *ptr = val;
-}
-
-static void sirf_u8(uint8_t offset)
-{
-       uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset);
-       uint8_t val;
-
-       val = data_byte ();
-       *ptr = val;
-}
-
-static void sirf_u32(uint8_t offset) __reentrant
-{
-       uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset);
-       uint32_t val;
-
-       val = ((uint32_t) data_byte ()) << 24;
-       val |= ((uint32_t) data_byte ()) << 16;
-       val |= ((uint32_t) data_byte ()) << 8;
-       val |= ((uint32_t) data_byte ());
-       *ptr = val;
-}
-
-static void sirf_discard(uint8_t len)
-{
-       while (len--)
-               data_byte();
-}
-
-#define SIRF_END       0
-#define SIRF_DISCARD   1
-#define SIRF_U8                2
-#define SIRF_U16       3
-#define SIRF_U32       4
-#define SIRF_U8X10     5
-
-struct sirf_packet_parse {
-       uint8_t type;
-       uint8_t offset;
-};
-
-static void
-ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant
-{
-       uint8_t i, offset, j;
-
-       sirf_target = target;
-       for (i = 0; ; i++) {
-               offset = parse[i].offset;
-               switch (parse[i].type) {
-               case SIRF_END:
-                       return;
-               case SIRF_DISCARD:
-                       sirf_discard(offset);
-                       break;
-               case SIRF_U8:
-                       sirf_u8(offset);
-                       break;
-               case SIRF_U16:
-                       sirf_u16(offset);
-                       break;
-               case SIRF_U32:
-                       sirf_u32(offset);
-                       break;
-               case SIRF_U8X10:
-                       for (j = 10; j--;)
-                               sirf_u8(offset++);
-                       break;
-               }
-       }
-}
-
-static const struct sirf_packet_parse geodetic_nav_data_packet[] = {
-       { SIRF_DISCARD, 2 },                                                    /* 1 nav valid */
-       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) },        /* 3 */
-       { SIRF_DISCARD, 6 },                                                    /* 5 week number, time of week */
-       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) },        /* 11 */
-       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) },        /* 13 */
-       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) },          /* 14 */
-       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) },         /* 15 */
-       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) },       /* 16 */
-       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) },      /* 17 */
-       { SIRF_DISCARD, 4 },    /* satellite id list */                         /* 19 */
-       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) },             /* 23 */
-       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) },             /* 27 */
-       { SIRF_DISCARD, 4 },    /* altitude from ellipsoid */                   /* 31 */
-       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) },         /* 35 */
-       { SIRF_DISCARD, 1 },    /* map datum */                                 /* 39 */
-       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) },    /* 40 */
-       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) },          /* 42 */
-       { SIRF_DISCARD, 2 },    /* magnetic variation */                        /* 44 */
-       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) },      /* 46 */
-       { SIRF_DISCARD, 2 },    /* turn rate */                                 /* 48 */
-       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) },         /* 50 */
-       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) },         /* 54 */
-       { SIRF_DISCARD, 30 },   /* time error, h_vel error, clock_bias,
-                                  clock bias error, clock drift,
-                                  clock drift error, distance,
-                                  distance error, heading error */             /* 58 */
-       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) },           /* 88 */
-       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) },             /* 89 */
-       { SIRF_DISCARD, 1 },    /* additional mode info */                      /* 90 */
-       { SIRF_END, 0 },                                                        /* 91 */
-};
-
-static void
-ao_sirf_parse_41(void) __reentrant
-{
-       ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet);
-}
-
-static const struct sirf_packet_parse measured_tracker_data_packet[] = {
-       { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) },   /* 1 week */
-       { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) },    /* 3 time of week */
-       { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) },    /* 7 channels */
-       { SIRF_END, 0 },
-};
-
-static const struct sirf_packet_parse measured_sat_data_packet[] = {
-       { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) },            /* 0 SV id */
-       { SIRF_DISCARD, 4 },                                                    /* 1 azimuth, 2 elevation, 3 state */
-       { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) },           /* C/N0 1 */
-       { SIRF_DISCARD, 9 },                                                    /* C/N0 2-10 */
-       { SIRF_END, 0 },
-};
-
-static void
-ao_sirf_parse_4(void) __reentrant
-{
-       uint8_t i;
-       ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet);
-       for (i = 0; i < 12; i++)
-               ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet);
-}
-
-static void
-ao_gps_setup(void) __reentrant
-{
-       uint8_t i, k;
-       ao_serial_set_speed(AO_SERIAL_SPEED_4800);
-       for (i = 0; i < 64; i++)
-               ao_serial_putchar(0x00);
-       for (k = 0; k < 3; k++)
-               for (i = 0; i < sizeof (ao_gps_set_nmea); i++)
-                       ao_serial_putchar(ao_gps_set_nmea[i]);
-       ao_serial_set_speed(AO_SERIAL_SPEED_57600);
-       for (i = 0; i < 64; i++)
-               ao_serial_putchar(0x00);
-}
-
-static const char ao_gps_set_message_rate[] = {
-       0xa0, 0xa2, 0x00, 0x08,
-       166,
-       0,
-};
-
-void
-ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant
-{
-       uint16_t        cksum = 0x00a6;
-       uint8_t         i;
-
-       for (i = 0; i < sizeof (ao_gps_set_message_rate); i++)
-               ao_serial_putchar(ao_gps_set_message_rate[i]);
-       ao_serial_putchar(msg);
-       ao_serial_putchar(rate);
-       cksum = 0xa6 + msg + rate;
-       for (i = 0; i < 4; i++)
-               ao_serial_putchar(0);
-       ao_serial_putchar((cksum >> 8) & 0x7f);
-       ao_serial_putchar(cksum & 0xff);
-       ao_serial_putchar(0xb0);
-       ao_serial_putchar(0xb3);
-}
-
-static const uint8_t sirf_disable[] = {
-       2,
-       9,
-       10,
-       27,
-       50,
-       52,
-};
-
-void
-ao_gps(void) __reentrant
-{
-       uint8_t i, k;
-       uint16_t cksum;
-
-       ao_gps_setup();
-       for (k = 0; k < 5; k++)
-       {
-               for (i = 0; i < sizeof (ao_gps_config); i++)
-                       ao_serial_putchar(ao_gps_config[i]);
-               for (i = 0; i < sizeof (sirf_disable); i++)
-                       ao_sirf_set_message_rate(sirf_disable[i], 0);
-               ao_sirf_set_message_rate(41, 1);
-               ao_sirf_set_message_rate(4, 1);
-       }
-       for (;;) {
-               /* Locate the begining of the next record */
-               while (ao_sirf_byte() != (uint8_t) 0xa0)
-                       ;
-               if (ao_sirf_byte() != (uint8_t) 0xa2)
-                       continue;
-
-               /* Length */
-               ao_sirf_len = ao_sirf_byte() << 8;
-               ao_sirf_len |= ao_sirf_byte();
-               if (ao_sirf_len > 1023)
-                       continue;
-
-               ao_sirf_cksum = 0;
-
-               /* message ID */
-               i = data_byte ();                                                       /* 0 */
-
-               switch (i) {
-               case 41:
-                       if (ao_sirf_len < 90)
-                               break;
-                       ao_sirf_parse_41();
-                       break;
-               case 4:
-                       if (ao_sirf_len < 187)
-                               break;
-                       ao_sirf_parse_4();
-                       break;
-               }
-               if (ao_sirf_len != 0)
-                       continue;
-
-               /* verify checksum and end sequence */
-               ao_sirf_cksum &= 0x7fff;
-               cksum = ao_sirf_byte() << 8;
-               cksum |= ao_sirf_byte();
-               if (ao_sirf_cksum != cksum)
-                       continue;
-               if (ao_sirf_byte() != (uint8_t) 0xb0)
-                       continue;
-               if (ao_sirf_byte() != (uint8_t) 0xb3)
-                       continue;
-
-               switch (i) {
-               case 41:
-                       ao_mutex_get(&ao_gps_mutex);
-                       ao_gps_tick = ao_time();
-                       ao_gps_data.hour = ao_sirf_data.utc_hour;
-                       ao_gps_data.minute = ao_sirf_data.utc_minute;
-                       ao_gps_data.second = ao_sirf_data.utc_second / 1000;
-                       ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING;
-                       if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF)
-                               ao_gps_data.flags |= AO_GPS_VALID;
-                       ao_gps_data.latitude = ao_sirf_data.lat;
-                       ao_gps_data.longitude = ao_sirf_data.lon;
-                       ao_gps_data.altitude = ao_sirf_data.alt_msl / 100;
-                       ao_gps_data.ground_speed = ao_sirf_data.ground_speed;
-                       ao_gps_data.course = ao_sirf_data.course / 200;
-                       ao_gps_data.hdop = ao_sirf_data.hdop;
-                       ao_gps_data.climb_rate = ao_sirf_data.climb_rate;
-                       ao_gps_data.flags |= AO_GPS_COURSE_VALID;
-#if 0
-                       if (ao_sirf_data.h_error > 6553500)
-                               ao_gps_data.h_error = 65535;
-                       else
-                               ao_gps_data.h_error = ao_sirf_data.h_error / 100;
-                       if (ao_sirf_data.v_error > 6553500)
-                               ao_gps_data.v_error = 65535;
-                       else
-                               ao_gps_data.v_error = ao_sirf_data.v_error / 100;
-#endif
-                       ao_mutex_put(&ao_gps_mutex);
-                       ao_wakeup(&ao_gps_data);
-                       break;
-               case 4:
-                       ao_mutex_get(&ao_gps_mutex);
-                       ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels;
-                       for (i = 0; i < 12; i++) {
-                               ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid;
-                               ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1;
-                       }
-                       ao_mutex_put(&ao_gps_mutex);
-                       ao_wakeup(&ao_gps_tracking_data);
-                       break;
-               }
-       }
-}
-
-__xdata struct ao_task ao_gps_task;
-
-void
-ao_gps_init(void)
-{
-       ao_add_task(&ao_gps_task, ao_gps, "gps");
-}
diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c
deleted file mode 100644 (file)
index 7ac2694..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_GPS_TEST
-#include "ao.h"
-#endif
-
-#define AO_GPS_LEADER          2
-
-static __code char ao_gps_header[] = "GP";
-
-__xdata uint8_t ao_gps_mutex;
-static __data char ao_gps_char;
-static __pdata uint8_t ao_gps_cksum;
-static __pdata uint8_t ao_gps_error;
-
-__pdata uint16_t ao_gps_tick;
-__xdata struct ao_telemetry_location   ao_gps_data;
-__xdata struct ao_telemetry_satellite  ao_gps_tracking_data;
-
-static __pdata uint16_t                                ao_gps_next_tick;
-static __xdata struct ao_telemetry_location    ao_gps_next;
-static __pdata uint8_t                         ao_gps_date_flags;
-static __xdata struct ao_telemetry_satellite   ao_gps_tracking_next;
-
-#define STQ_S 0xa0, 0xa1
-#define STQ_E 0x0d, 0x0a
-#define SKYTRAQ_MSG_2(id,a,b) \
-    STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E
-#define SKYTRAQ_MSG_3(id,a,b,c) \
-    STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E
-#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \
-    STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E
-#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
-    STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \
-    (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E
-
-static __code uint8_t ao_gps_config[] = {
-       SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */
-       /* gga interval */
-       /* gsa interval */
-       /* gsv interval */
-       /* gll interval */
-       /* rmc interval */
-       /* vtg interval */
-       /* zda interval */
-       /* attributes (0 = update to sram, 1 = update flash too) */
-
-       SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */
-       /* 0 = car, 1 = pedestrian */
-       /* 0 = update to sram, 1 = update sram + flash */
-};
-
-static void
-ao_gps_lexchar(void)
-{
-       if (ao_gps_error)
-               ao_gps_char = '\n';
-       else
-               ao_gps_char = ao_serial_getchar();
-       ao_gps_cksum ^= ao_gps_char;
-}
-
-void
-ao_gps_skip_field(void)
-{
-       while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n')
-               ao_gps_lexchar();
-}
-
-void
-ao_gps_skip_sep(void)
-{
-       if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*')
-               ao_gps_lexchar();
-}
-
-__pdata static uint8_t ao_gps_num_width;
-
-static int16_t
-ao_gps_decimal(uint8_t max_width)
-{
-       int16_t v;
-       __pdata uint8_t neg = 0;
-
-       ao_gps_skip_sep();
-       if (ao_gps_char == '-') {
-               neg = 1;
-               ao_gps_lexchar();
-       }
-       v = 0;
-       ao_gps_num_width = 0;
-       while (ao_gps_num_width < max_width) {
-               if (ao_gps_char < '0' || '9' < ao_gps_char)
-                       break;
-               v = v * (int16_t) 10 + ao_gps_char - '0';
-               ao_gps_num_width++;
-               ao_gps_lexchar();
-       }
-       if (neg)
-               v = -v;
-       return v;
-}
-
-static uint8_t
-ao_gps_hex(uint8_t max_width)
-{
-       uint8_t v, d;
-
-       ao_gps_skip_sep();
-       v = 0;
-       ao_gps_num_width = 0;
-       while (ao_gps_num_width < max_width) {
-               if ('0' <= ao_gps_char && ao_gps_char <= '9')
-                       d = ao_gps_char - '0';
-               else if ('A' <= ao_gps_char && ao_gps_char <= 'F')
-                       d = ao_gps_char - 'A' + 10;
-               else if ('a' <= ao_gps_char && ao_gps_char <= 'f')
-                       d = ao_gps_char - 'a' + 10;
-               else
-                       break;
-               v = (v << 4) | d;
-               ao_gps_num_width++;
-               ao_gps_lexchar();
-       }
-       return v;
-}
-
-static int32_t
-ao_gps_parse_pos(uint8_t deg_width) __reentrant
-{
-       int32_t d;
-       int32_t m;
-       int32_t f;
-
-       d = ao_gps_decimal(deg_width);
-       m = ao_gps_decimal(2);
-       if (ao_gps_char == '.') {
-               f = ao_gps_decimal(4);
-               while (ao_gps_num_width < 4) {
-                       f *= 10;
-                       ao_gps_num_width++;
-               }
-       } else {
-               f = 0;
-               if (ao_gps_char != ',')
-                       ao_gps_error = 1;
-       }
-       d = d * 10000000l;
-       m = m * 10000l + f;
-       d = d + m * 50 / 3;
-       return d;
-}
-
-static uint8_t
-ao_gps_parse_flag(char no_c, char yes_c) __reentrant
-{
-       uint8_t ret = 0;
-       ao_gps_skip_sep();
-       if (ao_gps_char == yes_c)
-               ret = 1;
-       else if (ao_gps_char == no_c)
-               ret = 0;
-       else
-               ao_gps_error = 1;
-       ao_gps_lexchar();
-       return ret;
-}
-
-static void
-ao_nmea_gga()
-{
-       uint8_t i;
-
-       /* Now read the data into the gps data record
-        *
-        * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66
-        *
-        * Essential fix data
-        *
-        *         025149.000   time (02:51:49.000 GMT)
-        *         4528.1723,N  Latitude 45°28.1723' N
-        *         12244.2480,W Longitude 122°44.2480' W
-        *         1            Fix quality:
-        *                                 0 = invalid
-        *                                 1 = GPS fix (SPS)
-        *                                 2 = DGPS fix
-        *                                 3 = PPS fix
-        *                                 4 = Real Time Kinematic
-        *                                 5 = Float RTK
-        *                                 6 = estimated (dead reckoning)
-        *                                 7 = Manual input mode
-        *                                 8 = Simulation mode
-        *         05           Number of satellites (5)
-        *         2.0          Horizontal dilution
-        *         103.5,M              Altitude, 103.5M above msl
-        *         -19.5,M              Height of geoid above WGS84 ellipsoid
-        *         ?            time in seconds since last DGPS update
-        *         0000         DGPS station ID
-        *         *66          checksum
-        */
-
-       ao_gps_next_tick = ao_time();
-       ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags;
-       ao_gps_next.hour = ao_gps_decimal(2);
-       ao_gps_next.minute = ao_gps_decimal(2);
-       ao_gps_next.second = ao_gps_decimal(2);
-       ao_gps_skip_field();    /* skip seconds fraction */
-
-       ao_gps_next.latitude = ao_gps_parse_pos(2);
-       if (ao_gps_parse_flag('N', 'S'))
-               ao_gps_next.latitude = -ao_gps_next.latitude;
-       ao_gps_next.longitude = ao_gps_parse_pos(3);
-       if (ao_gps_parse_flag('E', 'W'))
-               ao_gps_next.longitude = -ao_gps_next.longitude;
-
-       i = ao_gps_decimal(0xff);
-       if (i == 1)
-               ao_gps_next.flags |= AO_GPS_VALID;
-
-       i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT;
-       if (i > AO_GPS_NUM_SAT_MASK)
-               i = AO_GPS_NUM_SAT_MASK;
-       ao_gps_next.flags |= i;
-
-       ao_gps_lexchar();
-       i = ao_gps_decimal(0xff);
-       if (i <= 50) {
-               i = (uint8_t) 5 * i;
-               if (ao_gps_char == '.')
-                       i = (i + ((uint8_t) ao_gps_decimal(1) >> 1));
-       } else
-               i = 255;
-       ao_gps_next.hdop = i;
-       ao_gps_skip_field();
-
-       ao_gps_next.altitude = ao_gps_decimal(0xff);
-       ao_gps_skip_field();    /* skip any fractional portion */
-
-       /* Skip remaining fields */
-       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
-               ao_gps_lexchar();
-               ao_gps_skip_field();
-       }
-       if (ao_gps_char == '*') {
-               uint8_t cksum = ao_gps_cksum ^ '*';
-               if (cksum != ao_gps_hex(2))
-                       ao_gps_error = 1;
-       } else
-               ao_gps_error = 1;
-       if (!ao_gps_error) {
-               ao_mutex_get(&ao_gps_mutex);
-               ao_gps_tick = ao_gps_next_tick;
-               memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data));
-               ao_mutex_put(&ao_gps_mutex);
-               ao_wakeup(&ao_gps_data);
-       }
-}
-
-static void
-ao_nmea_gsv(void)
-{
-       char    c;
-       uint8_t i;
-       uint8_t done;
-       /* Now read the data into the GPS tracking data record
-        *
-        * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72<CR><LF>
-        *
-        * Satellites in view data
-        *
-        *      3               Total number of GSV messages
-        *      1               Sequence number of current GSV message
-        *      12              Total sats in view (0-12)
-        *      05              SVID
-        *      54              Elevation
-        *      069             Azimuth
-        *      45              C/N0 in dB
-        *      ...             other SVIDs
-        *      72              checksum
-        */
-       c = ao_gps_decimal(1);  /* total messages */
-       i = ao_gps_decimal(1);  /* message sequence */
-       if (i == 1) {
-               ao_gps_tracking_next.channels = 0;
-       }
-       done = (uint8_t) c == i;
-       ao_gps_lexchar();
-       ao_gps_skip_field();    /* sats in view */
-       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
-               i = ao_gps_tracking_next.channels;
-               c = ao_gps_decimal(2);  /* SVID */
-               if (i < AO_MAX_GPS_TRACKING)
-                       ao_gps_tracking_next.sats[i].svid = c;
-               ao_gps_lexchar();
-               ao_gps_skip_field();    /* elevation */
-               ao_gps_lexchar();
-               ao_gps_skip_field();    /* azimuth */
-               c = ao_gps_decimal(2);  /* C/N0 */
-               if (i < AO_MAX_GPS_TRACKING) {
-                       if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0)
-                               ao_gps_tracking_next.channels = i + 1;
-               }
-       }
-       if (ao_gps_char == '*') {
-               uint8_t cksum = ao_gps_cksum ^ '*';
-               if (cksum != ao_gps_hex(2))
-                       ao_gps_error = 1;
-       }
-       else
-               ao_gps_error = 1;
-       if (ao_gps_error)
-               ao_gps_tracking_next.channels = 0;
-       else if (done) {
-               ao_mutex_get(&ao_gps_mutex);
-               memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next,
-                      sizeof(ao_gps_tracking_data));
-               ao_mutex_put(&ao_gps_mutex);
-               ao_wakeup(&ao_gps_tracking_data);
-       }
-}
-
-static void
-ao_nmea_rmc(void)
-{
-       char    a, c;
-       uint8_t i;
-       /* Parse the RMC record to read out the current date */
-
-       /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61
-        *
-        * Recommended Minimum Specific GNSS Data
-        *
-        *      111636.932      UTC time 11:16:36.932
-        *      A               Data Valid (V = receiver warning)
-        *      2447.0949       Latitude
-        *      N               North/south indicator
-        *      12100.5223      Longitude
-        *      E               East/west indicator
-        *      000.0           Speed over ground
-        *      000.0           Course over ground
-        *      030407          UTC date (ddmmyy format)
-        *      A               Mode indicator:
-        *                      N = data not valid
-        *                      A = autonomous mode
-        *                      D = differential mode
-        *                      E = estimated (dead reckoning) mode
-        *                      M = manual input mode
-        *                      S = simulator mode
-        *      61              checksum
-        */
-       ao_gps_skip_field();
-       for (i = 0; i < 8; i++) {
-               ao_gps_lexchar();
-               ao_gps_skip_field();
-       }
-       a = ao_gps_decimal(2);
-       c = ao_gps_decimal(2);
-       i = ao_gps_decimal(2);
-       /* Skip remaining fields */
-       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
-               ao_gps_lexchar();
-               ao_gps_skip_field();
-       }
-       if (ao_gps_char == '*') {
-               uint8_t cksum = ao_gps_cksum ^ '*';
-               if (cksum != ao_gps_hex(2))
-                       ao_gps_error = 1;
-       } else
-               ao_gps_error = 1;
-       if (!ao_gps_error) {
-               ao_gps_next.year = i;
-               ao_gps_next.month = c;
-               ao_gps_next.day = a;
-               ao_gps_date_flags = AO_GPS_DATE_VALID;
-       }
-}
-
-#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s))
-
-static void
-ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l)
-{
-       while (l--) {
-               uint8_t c = *b++;
-               if (c == 0xa0)
-                       ao_delay(AO_MS_TO_TICKS(500));
-               ao_serial_putchar(c);
-       }
-}
-
-static void
-ao_gps_nmea_parse(void)
-{
-       uint8_t a, b, c;
-
-       ao_gps_cksum = 0;
-       ao_gps_error = 0;
-
-       for (a = 0; a < AO_GPS_LEADER; a++) {
-               ao_gps_lexchar();
-               if (ao_gps_char != ao_gps_header[a])
-                       return;
-       }
-
-       ao_gps_lexchar();
-       a = ao_gps_char;
-       ao_gps_lexchar();
-       b = ao_gps_char;
-       ao_gps_lexchar();
-       c = ao_gps_char;
-       ao_gps_lexchar();
-
-       if (ao_gps_char != ',')
-               return;
-
-       if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') {
-               ao_nmea_gga();
-       } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') {
-               ao_nmea_gsv();
-       } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') {
-               ao_nmea_rmc();
-       }
-}
-
-void
-ao_gps(void) __reentrant
-{
-       ao_serial_set_speed(AO_SERIAL_SPEED_9600);
-
-       /* give skytraq time to boot in case of cold start */
-       ao_delay(AO_MS_TO_TICKS(2000));
-
-       ao_skytraq_sendstruct(ao_gps_config);
-
-       for (;;) {
-               /* Locate the begining of the next record */
-               if (ao_serial_getchar() == '$') {
-                       ao_gps_nmea_parse();
-               }
-
-       }
-}
-
-__xdata struct ao_task ao_gps_task;
-
-static void
-gps_dump(void) __reentrant
-{
-       uint8_t i;
-       ao_mutex_get(&ao_gps_mutex);
-       printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day);
-       printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
-       printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude);
-       printf ("Alt: %d\n", ao_gps_data.altitude);
-       printf ("Flags: 0x%x\n", ao_gps_data.flags);
-       printf ("Sats: %d", ao_gps_tracking_data.channels);
-       for (i = 0; i < ao_gps_tracking_data.channels; i++)
-               printf (" %d %d",
-                       ao_gps_tracking_data.sats[i].svid,
-                       ao_gps_tracking_data.sats[i].c_n_1);
-       printf ("\ndone\n");
-       ao_mutex_put(&ao_gps_mutex);
-}
-
-__code struct ao_cmds ao_gps_cmds[] = {
-       { gps_dump,     "g\0Display GPS" },
-       { 0, NULL },
-};
-
-void
-ao_gps_init(void)
-{
-       ao_add_task(&ao_gps_task, ao_gps, "gps");
-       ao_cmd_register(&ao_gps_cmds[0]);
-}
diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c
deleted file mode 100644 (file)
index 93d7a9a..0000000
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define AO_GPS_TEST
-#include "ao_host.h"
-#include <termios.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
-#define AO_GPS_NUM_SAT_SHIFT   (0)
-
-#define AO_GPS_VALID           (1 << 4)
-#define AO_GPS_RUNNING         (1 << 5)
-#define AO_GPS_DATE_VALID      (1 << 6)
-#define AO_GPS_COURSE_VALID    (1 << 7)
-
-struct ao_gps_orig {
-       uint8_t                 year;
-       uint8_t                 month;
-       uint8_t                 day;
-       uint8_t                 hour;
-       uint8_t                 minute;
-       uint8_t                 second;
-       uint8_t                 flags;
-       int32_t                 latitude;       /* degrees * 10⁷ */
-       int32_t                 longitude;      /* degrees * 10⁷ */
-       int16_t                 altitude;       /* m */
-       uint16_t                ground_speed;   /* cm/s */
-       uint8_t                 course;         /* degrees / 2 */
-       uint8_t                 hdop;           /* * 5 */
-       int16_t                 climb_rate;     /* cm/s */
-       uint16_t                h_error;        /* m */
-       uint16_t                v_error;        /* m */
-};
-
-#define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
-#define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
-#define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
-#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE                (1 << 3)
-#define SIRF_SAT_CARRIER_PULLIN_COMPLETE       (1 << 4)
-#define SIRF_SAT_CODE_LOCKED                   (1 << 5)
-#define SIRF_SAT_ACQUISITION_FAILED            (1 << 6)
-#define SIRF_SAT_EPHEMERIS_AVAILABLE           (1 << 7)
-
-struct ao_gps_sat_orig {
-       uint8_t         svid;
-       uint8_t         c_n_1;
-};
-
-#define AO_MAX_GPS_TRACKING    12
-
-struct ao_gps_tracking_orig {
-       uint8_t                 channels;
-       struct ao_gps_sat_orig  sats[AO_MAX_GPS_TRACKING];
-};
-
-#define ao_telemetry_location ao_gps_orig
-#define ao_telemetry_satellite ao_gps_tracking_orig
-#define ao_telemetry_satellite_info ao_gps_sat_orig
-
-void
-ao_mutex_get(uint8_t *mutex)
-{
-}
-
-void
-ao_mutex_put(uint8_t *mutex)
-{
-}
-
-static int
-ao_gps_fd;
-
-static void
-ao_dbg_char(char c)
-{
-       char    line[128];
-       line[0] = '\0';
-       if (c < ' ') {
-               if (c == '\n')
-                       sprintf (line, "\n");
-               else
-                       sprintf (line, "\\%02x", ((int) c) & 0xff);
-       } else {
-               sprintf (line, "%c", c);
-       }
-       write(1, line, strlen(line));
-}
-
-#define QUEUE_LEN      4096
-
-static char    input_queue[QUEUE_LEN];
-int            input_head, input_tail;
-
-#include <sys/time.h>
-
-int
-get_millis(void)
-{
-       struct timeval  tv;
-       gettimeofday(&tv, NULL);
-       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-static void
-check_sirf_message(char *from, uint8_t *msg, int len)
-{
-       uint16_t        encoded_len, encoded_cksum;
-       uint16_t        cksum;
-       uint8_t         id;
-       int             i;
-
-       if (msg[0] != 0xa0 || msg[1] != 0xa2) {
-               printf ("bad header\n");
-               return;
-       }
-       if (len < 7) {
-               printf("short\n");
-               return;
-       }
-       if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) {
-               printf ("bad trailer\n");
-               return;
-       }
-       encoded_len = (msg[2] << 8) | msg[3];
-       id = msg[4];
-/*     printf ("%9d: %3d\n", get_millis(), id); */
-       if (encoded_len != len - 8) {
-               if (id != 52)
-                       printf ("length mismatch (got %d, wanted %d)\n",
-                               len - 8, encoded_len);
-               return;
-       }
-       encoded_cksum = (msg[len - 4] << 8) | msg[len-3];
-       cksum = 0;
-       for (i = 4; i < len - 4; i++)
-               cksum = (cksum + msg[i]) & 0x7fff;
-       if (encoded_cksum != cksum) {
-               printf ("cksum mismatch (got %04x wanted %04x)\n",
-                       cksum, encoded_cksum);
-               return;
-       }
-       id = msg[4];
-       switch (id) {
-       case 41:{
-               int     off = 4;
-
-               uint8_t         id;
-               uint16_t        nav_valid;
-               uint16_t        nav_type;
-               uint16_t        week;
-               uint32_t        tow;
-               uint16_t        year;
-               uint8_t         month;
-               uint8_t         day;
-               uint8_t         hour;
-               uint8_t         minute;
-               uint16_t        second;
-               uint32_t        sat_list;
-               int32_t         lat;
-               int32_t         lon;
-               int32_t         alt_ell;
-               int32_t         alt_msl;
-               int8_t          datum;
-               uint16_t        sog;
-               uint16_t        cog;
-               int16_t         mag_var;
-               int16_t         climb_rate;
-               int16_t         heading_rate;
-               uint32_t        h_error;
-               uint32_t        v_error;
-               uint32_t        t_error;
-               uint16_t        h_v_error;
-
-#define get_u8(u)      u = (msg[off]); off+= 1
-#define get_u16(u)     u = (msg[off] << 8) | (msg[off + 1]); off+= 2
-#define get_u32(u)     u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4
-
-               get_u8(id);
-               get_u16(nav_valid);
-               get_u16(nav_type);
-               get_u16(week);
-               get_u32(tow);
-               get_u16(year);
-               get_u8(month);
-               get_u8(day);
-               get_u8(hour);
-               get_u8(minute);
-               get_u16(second);
-               get_u32(sat_list);
-               get_u32(lat);
-               get_u32(lon);
-               get_u32(alt_ell);
-               get_u32(alt_msl);
-               get_u8(datum);
-               get_u16(sog);
-               get_u16(cog);
-               get_u16(mag_var);
-               get_u16(climb_rate);
-               get_u16(heading_rate);
-               get_u32(h_error);
-               get_u32(v_error);
-               get_u32(t_error);
-               get_u16(h_v_error);
-
-
-               printf ("Geodetic Navigation Data (41):\n");
-               printf ("\tNav valid %04x\n", nav_valid);
-               printf ("\tNav type %04x\n", nav_type);
-               printf ("\tWeek %5d", week);
-               printf (" TOW %9d", tow);
-               printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n",
-                       year, month, day,
-                       hour, minute, second / 1000.0);
-               printf ("\tsats: %08x\n", sat_list);
-               printf ("\tlat: %g", lat / 1.0e7);
-               printf (" lon: %g", lon / 1.0e7);
-               printf (" alt_ell: %g", alt_ell / 100.0);
-               printf (" alt_msll: %g", alt_msl / 100.0);
-               printf (" datum: %d\n", datum);
-               printf ("\tground speed: %g", sog / 100.0);
-               printf (" course: %g", cog / 100.0);
-               printf (" climb: %g", climb_rate / 100.0);
-               printf (" heading rate: %g\n", heading_rate / 100.0);
-               printf ("\th error: %g", h_error / 100.0);
-               printf (" v error: %g", v_error / 100.0);
-               printf (" t error: %g", t_error / 100.0);
-               printf (" h vel error: %g\n", h_v_error / 100.0);
-               break;
-       }
-       case 4: {
-               int off = 4;
-               uint8_t         id;
-               int16_t         gps_week;
-               uint32_t        gps_tow;
-               uint8_t         channels;
-               int             j, k;
-
-               get_u8(id);
-               get_u16(gps_week);
-               get_u32(gps_tow);
-               get_u8(channels);
-
-               printf ("Measured Tracker Data (4):\n");
-               printf ("GPS week: %d\n", gps_week);
-               printf ("GPS time of week: %d\n", gps_tow);
-               printf ("channels: %d\n", channels);
-               for (j = 0; j < 12; j++) {
-                       uint8_t svid, azimuth, elevation;
-                       uint16_t state;
-                       uint8_t c_n[10];
-                       get_u8(svid);
-                       get_u8(azimuth);
-                       get_u8(elevation);
-                       get_u16(state);
-                       for (k = 0; k < 10; k++) {
-                               get_u8(c_n[k]);
-                       }
-                       printf ("Sat %3d:", svid);
-                       printf (" aziumuth: %6.1f", azimuth * 1.5);
-                       printf (" elevation: %6.1f", elevation * 0.5);
-                       printf (" state: 0x%02x", state);
-                       printf (" c_n:");
-                       for (k = 0; k < 10; k++)
-                               printf(" %3d", c_n[k]);
-                       if (state & SIRF_SAT_STATE_ACQUIRED)
-                               printf(" acq,");
-                       if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID)
-                               printf(" car,");
-                       if (state & SIRF_SAT_BIT_SYNC_COMPLETE)
-                               printf(" bit,");
-                       if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE)
-                               printf(" sub,");
-                       if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE)
-                               printf(" pullin,");
-                       if (state & SIRF_SAT_CODE_LOCKED)
-                               printf(" code,");
-                       if (state & SIRF_SAT_ACQUISITION_FAILED)
-                               printf(" fail,");
-                       if (state & SIRF_SAT_EPHEMERIS_AVAILABLE)
-                               printf(" ephem,");
-                       printf ("\n");
-               }
-               break;
-       }
-       default:
-               return;
-               printf ("%s %4d:", from, encoded_len);
-               for (i = 4; i < len - 4; i++) {
-                       if (((i - 4) & 0xf) == 0)
-                               printf("\n   ");
-                       printf (" %3d", msg[i]);
-               }
-               printf ("\n");
-       }
-}
-
-static uint8_t sirf_message[4096];
-static int     sirf_message_len;
-static uint8_t sirf_in_message[4096];
-static int     sirf_in_len;
-
-char
-ao_serial_getchar(void)
-{
-       char    c;
-       uint8_t uc;
-
-       while (input_head == input_tail) {
-               for (;;) {
-                       input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN);
-                       if (input_tail < 0) {
-                               if (errno == EINTR || errno == EAGAIN)
-                                       continue;
-                               perror ("getchar");
-                               exit (1);
-                       }
-                       input_head = 0;
-                       break;
-               }
-       }
-       c = input_queue[input_head];
-       input_head = (input_head + 1) % QUEUE_LEN;
-       uc = c;
-       if (sirf_in_len || uc == 0xa0) {
-               if (sirf_in_len < 4096)
-                       sirf_in_message[sirf_in_len++] = uc;
-               if (uc == 0xb3) {
-                       check_sirf_message("recv", sirf_in_message, sirf_in_len);
-                       sirf_in_len = 0;
-               }
-       }
-       return c;
-}
-
-
-void
-ao_serial_putchar(char c)
-{
-       int     i;
-       uint8_t uc = (uint8_t) c;
-
-       if (sirf_message_len || uc == 0xa0) {
-               if (sirf_message_len < 4096)
-                       sirf_message[sirf_message_len++] = uc;
-               if (uc == 0xb3) {
-                       check_sirf_message("send", sirf_message, sirf_message_len);
-                       sirf_message_len = 0;
-               }
-       }
-       for (;;) {
-               i = write(ao_gps_fd, &c, 1);
-               if (i == 1) {
-                       if ((uint8_t) c == 0xb3 || c == '\r') {
-                               static const struct timespec delay = {
-                                       .tv_sec = 0,
-                                       .tv_nsec = 100 * 1000 * 1000
-                               };
-                               tcdrain(ao_gps_fd);
-//                             nanosleep(&delay, NULL);
-                       }
-                       break;
-               }
-               if (i < 0 && (errno == EINTR || errno == EAGAIN))
-                       continue;
-               perror("putchar");
-               exit(1);
-       }
-}
-
-#define AO_SERIAL_SPEED_4800   0
-#define AO_SERIAL_SPEED_57600  1
-
-static void
-ao_serial_set_speed(uint8_t speed)
-{
-       int     fd = ao_gps_fd;
-       struct termios  termios;
-
-       tcdrain(fd);
-       tcgetattr(fd, &termios);
-       switch (speed) {
-       case AO_SERIAL_SPEED_4800:
-               cfsetspeed(&termios, B4800);
-               break;
-       case AO_SERIAL_SPEED_57600:
-               cfsetspeed(&termios, B57600);
-               break;
-       }
-       tcsetattr(fd, TCSAFLUSH, &termios);
-       tcflush(fd, TCIFLUSH);
-}
-
-#define ao_time() 0
-
-#include "ao_gps_print.c"
-#include "ao_gps_sirf.c"
-
-void
-ao_dump_state(void *wchan)
-{
-       double  lat, lon;
-       int     i;
-       if (wchan == &ao_gps_data)
-               ao_gps_print(&ao_gps_data);
-       else
-               ao_gps_tracking_print(&ao_gps_tracking_data);
-       putchar('\n');
-       return;
-       printf ("%02d:%02d:%02d",
-               ao_gps_data.hour, ao_gps_data.minute,
-               ao_gps_data.second);
-       printf (" nsat %d %svalid",
-               ao_gps_data.flags & AO_GPS_NUM_SAT_MASK,
-               ao_gps_data.flags & AO_GPS_VALID ? "" : "not ");
-       printf (" lat %g lon %g alt %d",
-               ao_gps_data.latitude / 1.0e7,
-               ao_gps_data.longitude / 1.0e7,
-               ao_gps_data.altitude);
-       printf (" speed %g climb %g course %d",
-               ao_gps_data.ground_speed / 100.0,
-               ao_gps_data.climb_rate / 100.0,
-               ao_gps_data.course * 2);
-       printf (" hdop %g h_error %d v_error %d",
-               ao_gps_data.hdop / 5.0,
-               ao_gps_data.h_error, ao_gps_data.v_error);
-       printf("\n");
-       printf ("\t");
-       for (i = 0; i < 12; i++)
-               printf (" %2d(%02d)",
-                       ao_gps_tracking_data.sats[i].svid,
-                       ao_gps_tracking_data.sats[i].c_n_1);
-       printf ("\n");
-}
-
-int
-ao_gps_open(const char *tty)
-{
-       struct termios  termios;
-       int fd;
-
-       fd = open (tty, O_RDWR);
-       if (fd < 0)
-               return -1;
-
-       tcgetattr(fd, &termios);
-       cfmakeraw(&termios);
-       cfsetspeed(&termios, B4800);
-       tcsetattr(fd, TCSAFLUSH, &termios);
-
-       tcdrain(fd);
-       tcflush(fd, TCIFLUSH);
-       return fd;
-}
-
-#include <getopt.h>
-
-static const struct option options[] = {
-       { .name = "tty", .has_arg = 1, .val = 'T' },
-       { 0, 0, 0, 0},
-};
-
-static void usage(char *program)
-{
-       fprintf(stderr, "usage: %s [--tty <tty-name>]\n", program);
-       exit(1);
-}
-
-int
-main (int argc, char **argv)
-{
-       char    *tty = "/dev/ttyUSB0";
-       int     c;
-
-       while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) {
-               switch (c) {
-               case 'T':
-                       tty = optarg;
-                       break;
-               default:
-                       usage(argv[0]);
-                       break;
-               }
-       }
-       ao_gps_fd = ao_gps_open(tty);
-       if (ao_gps_fd < 0) {
-               perror (tty);
-               exit (1);
-       }
-       ao_gps_setup();
-       ao_gps();
-}
diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c
deleted file mode 100644 (file)
index a78fae0..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define AO_GPS_TEST
-#include "ao_host.h"
-#include <termios.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
-#define AO_GPS_NUM_SAT_SHIFT   (0)
-
-#define AO_GPS_VALID           (1 << 4)
-#define AO_GPS_RUNNING         (1 << 5)
-#define AO_GPS_DATE_VALID      (1 << 6)
-#define AO_GPS_COURSE_VALID    (1 << 7)
-
-struct ao_gps_orig {
-       uint8_t                 year;
-       uint8_t                 month;
-       uint8_t                 day;
-       uint8_t                 hour;
-       uint8_t                 minute;
-       uint8_t                 second;
-       uint8_t                 flags;
-       int32_t                 latitude;       /* degrees * 10⁷ */
-       int32_t                 longitude;      /* degrees * 10⁷ */
-       int16_t                 altitude;       /* m */
-       uint16_t                ground_speed;   /* cm/s */
-       uint8_t                 course;         /* degrees / 2 */
-       uint8_t                 hdop;           /* * 5 */
-       int16_t                 climb_rate;     /* cm/s */
-       uint16_t                h_error;        /* m */
-       uint16_t                v_error;        /* m */
-};
-
-#define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
-#define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
-#define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
-#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE                (1 << 3)
-#define SIRF_SAT_CARRIER_PULLIN_COMPLETE       (1 << 4)
-#define SIRF_SAT_CODE_LOCKED                   (1 << 5)
-#define SIRF_SAT_ACQUISITION_FAILED            (1 << 6)
-#define SIRF_SAT_EPHEMERIS_AVAILABLE           (1 << 7)
-
-struct ao_gps_sat_orig {
-       uint8_t         svid;
-       uint8_t         c_n_1;
-};
-
-#define AO_MAX_GPS_TRACKING    12
-
-struct ao_gps_tracking_orig {
-       uint8_t                 channels;
-       struct ao_gps_sat_orig  sats[AO_MAX_GPS_TRACKING];
-};
-
-#define ao_telemetry_location ao_gps_orig
-#define ao_telemetry_satellite ao_gps_tracking_orig
-#define ao_telemetry_satellite_info ao_gps_sat_orig
-
-void
-ao_mutex_get(uint8_t *mutex)
-{
-}
-
-void
-ao_mutex_put(uint8_t *mutex)
-{
-}
-
-static int
-ao_gps_fd;
-
-static void
-ao_dbg_char(char c)
-{
-       char    line[128];
-       line[0] = '\0';
-       if (c < ' ') {
-               if (c == '\n')
-                       sprintf (line, "\n");
-               else
-                       sprintf (line, "\\%02x", ((int) c) & 0xff);
-       } else {
-               sprintf (line, "%c", c);
-       }
-       write(1, line, strlen(line));
-}
-
-#define QUEUE_LEN      4096
-
-static char    input_queue[QUEUE_LEN];
-int            input_head, input_tail;
-
-#include <sys/time.h>
-
-int
-get_millis(void)
-{
-       struct timeval  tv;
-       gettimeofday(&tv, NULL);
-       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-static void
-check_skytraq_message(char *from, uint8_t *msg, int len)
-{
-       uint16_t        encoded_len, encoded_cksum;
-       uint16_t        cksum;
-       uint8_t         id;
-       int             i;
-
-//     fwrite(msg, 1, len, stdout);
-       return;
-       if (msg[0] != 0xa0 || msg[1] != 0xa2) {
-               printf ("bad header\n");
-               return;
-       }
-       if (len < 7) {
-               printf("short\n");
-               return;
-       }
-       if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) {
-               printf ("bad trailer\n");
-               return;
-       }
-       encoded_len = (msg[2] << 8) | msg[3];
-       id = msg[4];
-/*     printf ("%9d: %3d\n", get_millis(), id); */
-       if (encoded_len != len - 8) {
-               if (id != 52)
-                       printf ("length mismatch (got %d, wanted %d)\n",
-                               len - 8, encoded_len);
-               return;
-       }
-       encoded_cksum = (msg[len - 4] << 8) | msg[len-3];
-       cksum = 0;
-       for (i = 4; i < len - 4; i++)
-               cksum = (cksum + msg[i]) & 0x7fff;
-       if (encoded_cksum != cksum) {
-               printf ("cksum mismatch (got %04x wanted %04x)\n",
-                       cksum, encoded_cksum);
-               return;
-       }
-       id = msg[4];
-       switch (id) {
-       case 41:{
-               int     off = 4;
-
-               uint8_t         id;
-               uint16_t        nav_valid;
-               uint16_t        nav_type;
-               uint16_t        week;
-               uint32_t        tow;
-               uint16_t        year;
-               uint8_t         month;
-               uint8_t         day;
-               uint8_t         hour;
-               uint8_t         minute;
-               uint16_t        second;
-               uint32_t        sat_list;
-               int32_t         lat;
-               int32_t         lon;
-               int32_t         alt_ell;
-               int32_t         alt_msl;
-               int8_t          datum;
-               uint16_t        sog;
-               uint16_t        cog;
-               int16_t         mag_var;
-               int16_t         climb_rate;
-               int16_t         heading_rate;
-               uint32_t        h_error;
-               uint32_t        v_error;
-               uint32_t        t_error;
-               uint16_t        h_v_error;
-
-#define get_u8(u)      u = (msg[off]); off+= 1
-#define get_u16(u)     u = (msg[off] << 8) | (msg[off + 1]); off+= 2
-#define get_u32(u)     u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4
-
-               get_u8(id);
-               get_u16(nav_valid);
-               get_u16(nav_type);
-               get_u16(week);
-               get_u32(tow);
-               get_u16(year);
-               get_u8(month);
-               get_u8(day);
-               get_u8(hour);
-               get_u8(minute);
-               get_u16(second);
-               get_u32(sat_list);
-               get_u32(lat);
-               get_u32(lon);
-               get_u32(alt_ell);
-               get_u32(alt_msl);
-               get_u8(datum);
-               get_u16(sog);
-               get_u16(cog);
-               get_u16(mag_var);
-               get_u16(climb_rate);
-               get_u16(heading_rate);
-               get_u32(h_error);
-               get_u32(v_error);
-               get_u32(t_error);
-               get_u16(h_v_error);
-
-
-               printf ("Geodetic Navigation Data (41):\n");
-               printf ("\tNav valid %04x\n", nav_valid);
-               printf ("\tNav type %04x\n", nav_type);
-               printf ("\tWeek %5d", week);
-               printf (" TOW %9d", tow);
-               printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n",
-                       year, month, day,
-                       hour, minute, second / 1000.0);
-               printf ("\tsats: %08x\n", sat_list);
-               printf ("\tlat: %g", lat / 1.0e7);
-               printf (" lon: %g", lon / 1.0e7);
-               printf (" alt_ell: %g", alt_ell / 100.0);
-               printf (" alt_msll: %g", alt_msl / 100.0);
-               printf (" datum: %d\n", datum);
-               printf ("\tground speed: %g", sog / 100.0);
-               printf (" course: %g", cog / 100.0);
-               printf (" climb: %g", climb_rate / 100.0);
-               printf (" heading rate: %g\n", heading_rate / 100.0);
-               printf ("\th error: %g", h_error / 100.0);
-               printf (" v error: %g", v_error / 100.0);
-               printf (" t error: %g", t_error / 100.0);
-               printf (" h vel error: %g\n", h_v_error / 100.0);
-               break;
-       }
-       case 4: {
-               int off = 4;
-               uint8_t         id;
-               int16_t         gps_week;
-               uint32_t        gps_tow;
-               uint8_t         channels;
-               int             j, k;
-
-               get_u8(id);
-               get_u16(gps_week);
-               get_u32(gps_tow);
-               get_u8(channels);
-
-               printf ("Measured Tracker Data (4):\n");
-               printf ("GPS week: %d\n", gps_week);
-               printf ("GPS time of week: %d\n", gps_tow);
-               printf ("channels: %d\n", channels);
-               for (j = 0; j < 12; j++) {
-                       uint8_t svid, azimuth, elevation;
-                       uint16_t state;
-                       uint8_t c_n[10];
-                       get_u8(svid);
-                       get_u8(azimuth);
-                       get_u8(elevation);
-                       get_u16(state);
-                       for (k = 0; k < 10; k++) {
-                               get_u8(c_n[k]);
-                       }
-                       printf ("Sat %3d:", svid);
-                       printf (" aziumuth: %6.1f", azimuth * 1.5);
-                       printf (" elevation: %6.1f", elevation * 0.5);
-                       printf (" state: 0x%02x", state);
-                       printf (" c_n:");
-                       for (k = 0; k < 10; k++)
-                               printf(" %3d", c_n[k]);
-                       if (state & SIRF_SAT_STATE_ACQUIRED)
-                               printf(" acq,");
-                       if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID)
-                               printf(" car,");
-                       if (state & SIRF_SAT_BIT_SYNC_COMPLETE)
-                               printf(" bit,");
-                       if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE)
-                               printf(" sub,");
-                       if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE)
-                               printf(" pullin,");
-                       if (state & SIRF_SAT_CODE_LOCKED)
-                               printf(" code,");
-                       if (state & SIRF_SAT_ACQUISITION_FAILED)
-                               printf(" fail,");
-                       if (state & SIRF_SAT_EPHEMERIS_AVAILABLE)
-                               printf(" ephem,");
-                       printf ("\n");
-               }
-               break;
-       }
-       default:
-               return;
-               printf ("%s %4d:", from, encoded_len);
-               for (i = 4; i < len - 4; i++) {
-                       if (((i - 4) & 0xf) == 0)
-                               printf("\n   ");
-                       printf (" %3d", msg[i]);
-               }
-               printf ("\n");
-       }
-}
-
-static uint8_t skytraq_message[4096];
-static int     skytraq_message_len;
-static uint8_t skytraq_in_message[4096];
-static int     skytraq_in_len;
-
-char
-ao_serial_getchar(void)
-{
-       char    c;
-       uint8_t uc;
-
-       while (input_head == input_tail) {
-               for (;;) {
-                       input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN);
-                       if (input_tail < 0) {
-                               if (errno == EINTR || errno == EAGAIN)
-                                       continue;
-                               perror ("getchar");
-                               exit (1);
-                       }
-                       input_head = 0;
-                       break;
-               }
-       }
-       c = input_queue[input_head];
-       input_head = (input_head + 1) % QUEUE_LEN;
-       uc = c;
-//     printf ("c: %02x %c\n", uc, uc);
-       if (skytraq_in_len || uc == '$') {
-               if (skytraq_in_len < 4096)
-                       skytraq_in_message[skytraq_in_len++] = uc;
-               if (uc == 0x0a) {
-                       check_skytraq_message("recv", skytraq_in_message, skytraq_in_len);
-                       skytraq_in_len = 0;
-               }
-       }
-       return c;
-}
-
-
-void
-ao_serial_putchar(char c)
-{
-       int     i;
-       uint8_t uc = (uint8_t) c;
-
-       if (skytraq_message_len || uc == 0xa0) {
-               if (skytraq_message_len < 4096)
-                       skytraq_message[skytraq_message_len++] = uc;
-               if (uc == 0x0a) {
-                       check_skytraq_message("send", skytraq_message, skytraq_message_len);
-                       skytraq_message_len = 0;
-               }
-       }
-       for (;;) {
-               i = write(ao_gps_fd, &c, 1);
-               if (i == 1) {
-                       if ((uint8_t) c == 0xb3 || c == '\r') {
-                               static const struct timespec delay = {
-                                       .tv_sec = 0,
-                                       .tv_nsec = 100 * 1000 * 1000
-                               };
-                               tcdrain(ao_gps_fd);
-//                             nanosleep(&delay, NULL);
-                       }
-                       break;
-               }
-               if (i < 0 && (errno == EINTR || errno == EAGAIN))
-                       continue;
-               perror("putchar");
-               exit(1);
-       }
-}
-
-#define AO_SERIAL_SPEED_4800   0
-#define AO_SERIAL_SPEED_9600   1
-#define AO_SERIAL_SPEED_57600  2
-
-static void
-ao_serial_set_speed(uint8_t speed)
-{
-       int     fd = ao_gps_fd;
-       struct termios  termios;
-
-       tcdrain(fd);
-       tcgetattr(fd, &termios);
-       switch (speed) {
-       case AO_SERIAL_SPEED_4800:
-               cfsetspeed(&termios, B4800);
-               break;
-       case AO_SERIAL_SPEED_9600:
-               cfsetspeed(&termios, B38400);
-               break;
-       case AO_SERIAL_SPEED_57600:
-               cfsetspeed(&termios, B57600);
-               break;
-       }
-       tcsetattr(fd, TCSAFLUSH, &termios);
-       tcflush(fd, TCIFLUSH);
-}
-
-#define ao_time() 0
-
-#include "ao_gps_print.c"
-#include "ao_gps_skytraq.c"
-
-void
-ao_dump_state(void *wchan)
-{
-       double  lat, lon;
-       int     i;
-       if (wchan == &ao_gps_data)
-               ao_gps_print(&ao_gps_data);
-       else
-               ao_gps_tracking_print(&ao_gps_tracking_data);
-       putchar('\n');
-       return;
-}
-
-int
-ao_gps_open(const char *tty)
-{
-       struct termios  termios;
-       int fd;
-
-       fd = open (tty, O_RDWR);
-       if (fd < 0)
-               return -1;
-
-       tcgetattr(fd, &termios);
-       cfmakeraw(&termios);
-       cfsetspeed(&termios, B4800);
-       tcsetattr(fd, TCSAFLUSH, &termios);
-
-       tcdrain(fd);
-       tcflush(fd, TCIFLUSH);
-       return fd;
-}
-
-#include <getopt.h>
-
-static const struct option options[] = {
-       { .name = "tty", .has_arg = 1, .val = 'T' },
-       { 0, 0, 0, 0},
-};
-
-static void usage(char *program)
-{
-       fprintf(stderr, "usage: %s [--tty <tty-name>]\n", program);
-       exit(1);
-}
-
-int
-main (int argc, char **argv)
-{
-       char    *tty = "/dev/ttyUSB0";
-       int     c;
-
-       while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) {
-               switch (c) {
-               case 'T':
-                       tty = optarg;
-                       break;
-               default:
-                       usage(argv[0]);
-                       break;
-               }
-       }
-       ao_gps_fd = ao_gps_open(tty);
-       if (ao_gps_fd < 0) {
-               perror (tty);
-               exit (1);
-       }
-       ao_gps();
-}
diff --git a/src/ao_host.h b/src/ao_host.h
deleted file mode 100644 (file)
index 65c25fe..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define _GNU_SOURCE
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define AO_ADC_RING    64
-#define ao_adc_ring_next(n)    (((n) + 1) & (AO_ADC_RING - 1))
-#define ao_adc_ring_prev(n)    (((n) - 1) & (AO_ADC_RING - 1))
-
-/*
- * One set of samples read from the A/D converter
- */
-struct ao_adc {
-       uint16_t        tick;           /* tick when the sample was read */
-       int16_t         accel;          /* accelerometer */
-       int16_t         pres;           /* pressure sensor */
-       int16_t         temp;           /* temperature sensor */
-       int16_t         v_batt;         /* battery voltage */
-       int16_t         sense_d;        /* drogue continuity sense */
-       int16_t         sense_m;        /* main continuity sense */
-};
-
-#define __pdata
-#define __data
-#define __xdata
-#define __code
-#define __reentrant
-
-enum ao_flight_state {
-       ao_flight_startup = 0,
-       ao_flight_idle = 1,
-       ao_flight_pad = 2,
-       ao_flight_boost = 3,
-       ao_flight_fast = 4,
-       ao_flight_coast = 5,
-       ao_flight_drogue = 6,
-       ao_flight_main = 7,
-       ao_flight_landed = 8,
-       ao_flight_invalid = 9
-};
-
-struct ao_adc ao_adc_ring[AO_ADC_RING];
-uint8_t ao_adc_head;
-
-#define ao_led_on(l)
-#define ao_led_off(l)
-#define ao_timer_set_adc_interval(i)
-#define ao_wakeup(wchan) ao_dump_state(wchan)
-#define ao_cmd_register(c)
-#define ao_usb_disable()
-#define ao_telemetry_set_interval(x)
-#define ao_delay(x)
-
-enum ao_igniter {
-       ao_igniter_drogue = 0,
-       ao_igniter_main = 1
-};
-
-void
-ao_ignite(enum ao_igniter igniter)
-{
-       printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main");
-}
-
-struct ao_task {
-       int dummy;
-};
-
-#define ao_add_task(t,f,n)
-
-#define ao_log_start()
-#define ao_log_stop()
-
-#define AO_MS_TO_TICKS(ms)     ((ms) / 10)
-#define AO_SEC_TO_TICKS(s)     ((s) * 100)
-
-#define AO_FLIGHT_TEST
-
-struct ao_adc ao_adc_static;
-
-FILE *emulator_in;
-
-void
-ao_dump_state(void *wchan);
-
-void
-ao_sleep(void *wchan);
-
-const char const * const ao_state_names[] = {
-       "startup", "idle", "pad", "boost", "fast",
-       "coast", "drogue", "main", "landed", "invalid"
-};
-
-struct ao_cmds {
-       void            (*func)(void);
-       const char      *help;
-};
-
-
-struct ao_config {
-       uint16_t        main_deploy;
-       int16_t         accel_zero_g;
-};
-
-#define ao_config_get()
-
-struct ao_config ao_config = { 250, 16000 };
diff --git a/src/ao_ignite.c b/src/ao_ignite.c
deleted file mode 100644 (file)
index 5238beb..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#if IGNITE_ON_P2
-#define AO_IGNITER_DROGUE      P2_3
-#define AO_IGNITER_MAIN                P2_4
-#define AO_IGNITER_DIR         P2DIR
-#define AO_IGNITER_DROGUE_BIT  (1 << 3)
-#define AO_IGNITER_MAIN_BIT    (1 << 4)
-#endif
-
-#if IGNITE_ON_P0
-#define AO_IGNITER_DROGUE      P0_5
-#define AO_IGNITER_MAIN                P0_4
-#define AO_IGNITER_DIR         P0DIR
-#define AO_IGNITER_DROGUE_BIT  (1 << 5)
-#define AO_IGNITER_MAIN_BIT    (1 << 4)
-#endif
-
-/* test these values with real igniters */
-#define AO_IGNITER_OPEN                1000
-#define AO_IGNITER_CLOSED      7000
-#define AO_IGNITER_FIRE_TIME   AO_MS_TO_TICKS(50)
-#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000)
-
-struct ao_ignition {
-       uint8_t request;
-       uint8_t fired;
-       uint8_t firing;
-};
-
-__xdata struct ao_ignition ao_ignition[2];
-
-void
-ao_ignite(enum ao_igniter igniter) __critical
-{
-       ao_ignition[igniter].request = 1;
-       ao_wakeup(&ao_ignition);
-}
-
-enum ao_igniter_status
-ao_igniter_status(enum ao_igniter igniter)
-{
-       __xdata struct ao_adc adc;
-       __pdata int16_t value;
-       __pdata uint8_t request, firing, fired;
-
-       __critical {
-               ao_adc_get(&adc);
-               request = ao_ignition[igniter].request;
-               fired = ao_ignition[igniter].fired;
-               firing = ao_ignition[igniter].firing;
-       }
-       if (firing || (request && !fired))
-               return ao_igniter_active;
-
-       value = (AO_IGNITER_CLOSED>>1);
-       switch (igniter) {
-       case ao_igniter_drogue:
-               value = adc.sense_d;
-               break;
-       case ao_igniter_main:
-               value = adc.sense_m;
-               break;
-       }
-       if (value < AO_IGNITER_OPEN)
-               return ao_igniter_open;
-       else if (value > AO_IGNITER_CLOSED)
-               return ao_igniter_ready;
-       else
-               return ao_igniter_unknown;
-}
-
-void
-ao_igniter_fire(enum ao_igniter igniter) __critical
-{
-       ao_ignition[igniter].firing = 1;
-       switch(ao_config.ignite_mode) {
-       case AO_IGNITE_MODE_DUAL:
-               switch (igniter) {
-               case ao_igniter_drogue:
-                       AO_IGNITER_DROGUE = 1;
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_DROGUE = 0;
-                       break;
-               case ao_igniter_main:
-                       AO_IGNITER_MAIN = 1;
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_MAIN = 0;
-                       break;
-               }
-               break;
-       case AO_IGNITE_MODE_APOGEE:
-               switch (igniter) {
-               case ao_igniter_drogue:
-                       AO_IGNITER_DROGUE = 1;
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_DROGUE = 0;
-                       ao_delay(AO_IGNITER_CHARGE_TIME);
-                       AO_IGNITER_MAIN = 1;
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_MAIN = 0;
-                       break;
-               }
-               break;
-       case AO_IGNITE_MODE_MAIN:
-               switch (igniter) {
-               case ao_igniter_main:
-                       AO_IGNITER_DROGUE = 1;
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_DROGUE = 0;
-                       ao_delay(AO_IGNITER_CHARGE_TIME);
-                       AO_IGNITER_MAIN = 1;
-                       ao_delay(AO_IGNITER_FIRE_TIME);
-                       AO_IGNITER_MAIN = 0;
-                       break;
-               }
-               break;
-       }
-       ao_ignition[igniter].firing = 0;
-}
-
-void
-ao_igniter(void)
-{
-       __xdata enum ao_ignter 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;
-                       }
-               }
-       }
-}
-
-void
-ao_ignite_manual(void)
-{
-       ao_cmd_white();
-       if (!ao_match_word("DoIt"))
-               return;
-       ao_cmd_white();
-       if (ao_cmd_lex_c == 'm') {
-               if(ao_match_word("main"))
-                       ao_igniter_fire(ao_igniter_main);
-       } else {
-               if(ao_match_word("drogue"))
-                       ao_igniter_fire(ao_igniter_drogue);
-       }
-}
-
-static __code char * __code igniter_status_names[] = {
-       "unknown", "ready", "active", "open"
-};
-
-void
-ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant
-{
-       enum ao_igniter_status status = ao_igniter_status(igniter);
-       printf("Igniter: %6s Status: %s\n",
-              name,
-              igniter_status_names[status]);
-}
-
-void
-ao_ignite_test(void)
-{
-       ao_ignite_print_status(ao_igniter_drogue, "drogue");
-       ao_ignite_print_status(ao_igniter_main, "main");
-}
-
-__code struct ao_cmds ao_ignite_cmds[] = {
-       { ao_ignite_manual,     "i <key> {main|drogue}\0Fire igniter. <key> is doit with D&I" },
-       { ao_ignite_test,       "t\0Test igniter" },
-       { 0,    NULL },
-};
-
-__xdata struct ao_task ao_igniter_task;
-
-void
-ao_ignite_set_pins(void)
-{
-       AO_IGNITER_DROGUE = 0;
-       AO_IGNITER_MAIN = 0;
-       AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT;
-}
-
-void
-ao_igniter_init(void)
-{
-       ao_ignite_set_pins();
-       ao_cmd_register(&ao_ignite_cmds[0]);
-       ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
-}
diff --git a/src/ao_intflash.c b/src/ao_intflash.c
deleted file mode 100644 (file)
index d76d954..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright © 2011  Anthony Towns <aj@erisian.com.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "cc1111.h"
-
-#define ENDOFCODE  (CODESIZE)
-#define AO_INTFLASH_BLOCK      1024
-#define AO_INTFLASH_BLOCKS     ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK)
-#define AO_INTFLASH_SIZE       (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS)
-#define AO_INTFLASH_LOCATION   (0x8000 - AO_INTFLASH_SIZE)
-
-/*
- *       21000 * 24e6
- * FWT = ------------
- *           16e9
- *
- *     = 31.5
- *
- * Round up and use 32
- */
-
-#define FLASH_TIMING   0x20
-
-#if AO_INTFLASH_BLOCKS < 2
-#error "Too few pages"
-#endif
-
-#if AO_INFTLASH_LOCATION % 1024 != 0
-#error "Pages aren't aligned properly"
-#endif
-
-__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE];
-
-/* Total bytes of available storage */
-__pdata uint32_t       ao_storage_total = sizeof(ao_intflash);
-
-/* Block size - device is erased in these units. */
-__pdata uint32_t       ao_storage_block = AO_INTFLASH_BLOCK;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-__pdata uint32_t       ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. */
-__pdata uint16_t       ao_storage_unit = AO_INTFLASH_BLOCK;
-
-__xdata static uint8_t  ao_intflash_dma_done;
-static uint8_t ao_intflash_dma;
-
-/*
- * The internal flash chip is arranged in 1kB sectors; the
- * chip cannot erase in units smaller than that.
- *
- * Writing happens in units of 2 bytes and
- * can only change bits from 1 to 0. So, you can rewrite
- * the same contents, or append to an existing page easily enough
- */
-
-/*
- * Erase the specified sector
- */
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant
-{
-       uint16_t addr;
-
-       if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total)
-               return 0;
-
-       addr = ((uint16_t)(ao_intflash + pos) >> 1);
-
-       FADDRH = addr >> 8;
-       FADDRL = addr;
-
-       __critical {
-               _asm
-               .even
-               orl _FCTL, #FCTL_ERASE;         ; FCTL |=  FCTL_ERASE
-               nop                             ; Required, see datasheet.
-               _endasm;
-       }
-
-       return 1;
-}
-
-/*
- * Write to flash
- */
-
-static void
-ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant
-{
-       pos = ((uint16_t) ao_intflash + pos) >> 1;
-
-       ao_dma_set_transfer(ao_intflash_dma,
-                           d,
-                           &FWDATAXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_FLASH,
-                           DMA_CFG1_SRCINC_1 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_HIGH);
-
-       FADDRH = pos >> 8;
-       FADDRL = pos;
-
-       ao_dma_start(ao_intflash_dma);
-
-       __critical {
-               _asm
-               .even
-               orl _FCTL, #FCTL_WRITE;         ; FCTL |=  FCTL_WRITE
-               nop
-               _endasm;
-       }
-}
-
-static void
-ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant
-{
-       static __xdata uint8_t b[2];
-
-       if (pos & 1) {
-               b[0] = 0xff;
-               b[1] = byte;
-       } else {
-               b[0] = byte;
-               b[1] = 0xff;
-       }
-       ao_intflash_write_aligned(pos, b, 2);
-}
-
-uint8_t
-ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant
-{
-       uint16_t pos = pos32;
-       __xdata uint8_t *d = v;
-       uint8_t oddlen;
-
-       if (pos >= ao_storage_total || pos + len > ao_storage_total)
-               return 0;
-       if (len == 0)
-               return 1;
-
-       if (pos & 1) {
-               ao_intflash_write_byte(pos++, *d++);
-               len--;
-       }
-       oddlen = len & 1;
-       len -= oddlen;
-       if (len)
-               ao_intflash_write_aligned(pos, d, len);
-       if (oddlen)
-               ao_intflash_write_byte(pos + len, d[len]);
-
-       return 1;
-}
-
-/*
- * Read from flash
- */
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
-{
-       if (pos >= ao_storage_total || pos + len > ao_storage_total)
-               return 0;
-       memcpy(d, ao_intflash+pos, len);
-       return 1;
-}
-
-void
-ao_storage_flush(void) __reentrant
-{
-}
-
-void
-ao_storage_setup(void)
-{
-}
-
-void
-ao_storage_device_info(void) __reentrant
-{
-       printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION);
-}
-
-void
-ao_storage_device_init(void)
-{
-       ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done);
-
-       FWT = FLASH_TIMING;
-}
diff --git a/src/ao_kalman.c b/src/ao_kalman.c
deleted file mode 100644 (file)
index ee01949..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#endif
-
-#include "ao_kalman.h"
-
-static __pdata int32_t         ao_k_height;
-static __pdata int32_t         ao_k_speed;
-static __pdata int32_t         ao_k_accel;
-
-#define AO_K_STEP_100          to_fix16(0.01)
-#define AO_K_STEP_2_2_100      to_fix16(0.00005)
-
-#define AO_K_STEP_10           to_fix16(0.1)
-#define AO_K_STEP_2_2_10       to_fix16(0.005)
-
-#define AO_K_STEP_1            to_fix16(1)
-#define AO_K_STEP_2_2_1                to_fix16(0.5)
-
-__pdata int16_t                        ao_height;
-__pdata int16_t                        ao_speed;
-__pdata int16_t                        ao_accel;
-__pdata int16_t                        ao_max_height;
-static __pdata int32_t         ao_avg_height_scaled;
-__pdata int16_t                        ao_avg_height;
-
-__pdata int16_t                        ao_error_h;
-__pdata int16_t                        ao_error_h_sq_avg;
-
-#if HAS_ACCEL
-__pdata int16_t                        ao_error_a;
-#endif
-
-static void
-ao_kalman_predict(void)
-{
-#ifdef AO_FLIGHT_TEST
-       if (ao_sample_tick - ao_sample_prev_tick > 50) {
-               ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 +
-                               (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
-               ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1;
-
-               return;
-       }
-       if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 +
-                               (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
-               ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10;
-
-               return;
-       }
-       if (ao_flight_debug) {
-               printf ("predict speed %g + (%g * %g) = %g\n",
-                       ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0,
-                       (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
-       }
-#endif
-       ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 +
-                       (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
-       ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100;
-}
-
-static void
-ao_kalman_err_height(void)
-{
-       int16_t e;
-       int16_t height_distrust;
-#if HAS_ACCEL
-       int16_t speed_distrust;
-#endif
-
-       ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16);
-
-       e = ao_error_h;
-       if (e < 0)
-               e = -e;
-       if (e > 127)
-               e = 127;
-#if HAS_ACCEL
-       ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2;
-       ao_error_h_sq_avg += (e * e) >> 2;
-#else
-       ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4;
-       ao_error_h_sq_avg += (e * e) >> 4;
-#endif
-
-       if (ao_flight_state >= ao_flight_drogue)
-               return;
-       height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT;
-#if HAS_ACCEL
-       /* speed is stored * 16, but we need to ramp between 200 and 328, so
-        * we want to multiply by 2. The result is a shift by 3.
-        */
-       speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1);
-       if (speed_distrust <= 0)
-               speed_distrust = 0;
-       else if (speed_distrust > height_distrust)
-               height_distrust = speed_distrust;
-#endif
-       if (height_distrust > 0) {
-#ifdef AO_FLIGHT_TEST
-               int     old_ao_error_h = ao_error_h;
-#endif
-               if (height_distrust > 0x100)
-                       height_distrust = 0x100;
-               ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8);
-#ifdef AO_FLIGHT_TEST
-               if (ao_flight_debug) {
-                       printf("over height %g over speed %g distrust: %g height: error %d -> %d\n",
-                              (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT),
-                              (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0,
-                              height_distrust / 256.0,
-                              old_ao_error_h, ao_error_h);
-               }
-#endif
-       }
-}
-
-static void
-ao_kalman_correct_baro(void)
-{
-       ao_kalman_err_height();
-#ifdef AO_FLIGHT_TEST
-       if (ao_sample_tick - ao_sample_prev_tick > 50) {
-               ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h;
-               ao_k_speed  += (int32_t) AO_BARO_K1_1 * ao_error_h;
-               ao_k_accel  += (int32_t) AO_BARO_K2_1 * ao_error_h;
-               return;
-       }
-       if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h;
-               ao_k_speed  += (int32_t) AO_BARO_K1_10 * ao_error_h;
-               ao_k_accel  += (int32_t) AO_BARO_K2_10 * ao_error_h;
-               return;
-       }
-#endif
-       ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h;
-       ao_k_speed  += (int32_t) AO_BARO_K1_100 * ao_error_h;
-       ao_k_accel  += (int32_t) AO_BARO_K2_100 * ao_error_h;
-}
-
-#if HAS_ACCEL
-
-static void
-ao_kalman_err_accel(void)
-{
-       int32_t accel;
-
-       accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale;
-
-       /* Can't use ao_accel here as it is the pre-prediction value still */
-       ao_error_a = (accel - ao_k_accel) >> 16;
-}
-
-static void
-ao_kalman_correct_both(void)
-{
-       ao_kalman_err_height();
-       ao_kalman_err_accel();
-
-#ifdef AO_FLIGHT_TEST
-       if (ao_sample_tick - ao_sample_prev_tick > 50) {
-               if (ao_flight_debug) {
-                       printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
-                               ao_k_speed / (65536.0 * 16.0),
-                               (double) ao_error_h, AO_BOTH_K10_1 / 65536.0,
-                               (double) ao_error_a, AO_BOTH_K11_1 / 65536.0,
-                               (ao_k_speed +
-                                (int32_t) AO_BOTH_K10_1 * ao_error_h +
-                                (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
-               }
-               ao_k_height +=
-                       (int32_t) AO_BOTH_K00_1 * ao_error_h +
-                       (int32_t) AO_BOTH_K01_1 * ao_error_a;
-               ao_k_speed +=
-                       (int32_t) AO_BOTH_K10_1 * ao_error_h +
-                       (int32_t) AO_BOTH_K11_1 * ao_error_a;
-               ao_k_accel +=
-                       (int32_t) AO_BOTH_K20_1 * ao_error_h +
-                       (int32_t) AO_BOTH_K21_1 * ao_error_a;
-               return;
-       }
-       if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               if (ao_flight_debug) {
-                       printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
-                               ao_k_speed / (65536.0 * 16.0),
-                               (double) ao_error_h, AO_BOTH_K10_10 / 65536.0,
-                               (double) ao_error_a, AO_BOTH_K11_10 / 65536.0,
-                               (ao_k_speed +
-                                (int32_t) AO_BOTH_K10_10 * ao_error_h +
-                                (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
-               }
-               ao_k_height +=
-                       (int32_t) AO_BOTH_K00_10 * ao_error_h +
-                       (int32_t) AO_BOTH_K01_10 * ao_error_a;
-               ao_k_speed +=
-                       (int32_t) AO_BOTH_K10_10 * ao_error_h +
-                       (int32_t) AO_BOTH_K11_10 * ao_error_a;
-               ao_k_accel +=
-                       (int32_t) AO_BOTH_K20_10 * ao_error_h +
-                       (int32_t) AO_BOTH_K21_10 * ao_error_a;
-               return;
-       }
-       if (ao_flight_debug) {
-               printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
-                       ao_k_speed / (65536.0 * 16.0),
-                       (double) ao_error_h, AO_BOTH_K10_100 / 65536.0,
-                       (double) ao_error_a, AO_BOTH_K11_100 / 65536.0,
-                       (ao_k_speed +
-                        (int32_t) AO_BOTH_K10_100 * ao_error_h +
-                        (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
-       }
-#endif
-       ao_k_height +=
-               (int32_t) AO_BOTH_K00_100 * ao_error_h +
-               (int32_t) AO_BOTH_K01_100 * ao_error_a;
-       ao_k_speed +=
-               (int32_t) AO_BOTH_K10_100 * ao_error_h +
-               (int32_t) AO_BOTH_K11_100 * ao_error_a;
-       ao_k_accel +=
-               (int32_t) AO_BOTH_K20_100 * ao_error_h +
-               (int32_t) AO_BOTH_K21_100 * ao_error_a;
-}
-
-#ifdef FORCE_ACCEL
-static void
-ao_kalman_correct_accel(void)
-{
-       ao_kalman_err_accel();
-
-       if (ao_sample_tick - ao_sample_prev_tick > 5) {
-               ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a;
-               ao_k_speed  += (int32_t) AO_ACCEL_K1_10 * ao_error_a;
-               ao_k_accel  += (int32_t) AO_ACCEL_K2_10 * ao_error_a;
-               return;
-       }
-       ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a;
-       ao_k_speed  += (int32_t) AO_ACCEL_K1_100 * ao_error_a;
-       ao_k_accel  += (int32_t) AO_ACCEL_K2_100 * ao_error_a;
-}
-#endif
-#endif /* HAS_ACCEL */
-
-void
-ao_kalman(void)
-{
-       ao_kalman_predict();
-#if HAS_ACCEL
-       if (ao_flight_state <= ao_flight_coast) {
-#ifdef FORCE_ACCEL
-               ao_kalman_correct_accel();
-#else
-               ao_kalman_correct_both();
-#endif
-       } else
-#endif
-               ao_kalman_correct_baro();
-       ao_height = from_fix(ao_k_height);
-       ao_speed = from_fix(ao_k_speed);
-       ao_accel = from_fix(ao_k_accel);
-       if (ao_height > ao_max_height)
-               ao_max_height = ao_height;
-       ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height;
-#ifdef AO_FLIGHT_TEST
-       if (ao_sample_tick - ao_sample_prev_tick > 50)
-               ao_avg_height = (ao_avg_height_scaled + 1) >> 1;
-       else if (ao_sample_tick - ao_sample_prev_tick > 5)
-               ao_avg_height = (ao_avg_height_scaled + 7) >> 4;
-       else 
-#endif
-               ao_avg_height = (ao_avg_height_scaled + 63) >> 7;
-#ifdef AO_FLIGHT_TEST
-       ao_sample_prev_tick = ao_sample_tick;
-#endif
-}
diff --git a/src/ao_led.c b/src/ao_led.c
deleted file mode 100644 (file)
index 5beed58..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__pdata uint8_t ao_led_enable;
-
-void
-ao_led_on(uint8_t colors)
-{
-       P1 |= (colors & ao_led_enable);
-}
-
-void
-ao_led_off(uint8_t colors)
-{
-       P1 &= ~(colors & ao_led_enable);
-}
-
-void
-ao_led_set(uint8_t colors)
-{
-       P1 = (P1 & ~(ao_led_enable)) | (colors & ao_led_enable);
-}
-
-void
-ao_led_toggle(uint8_t colors)
-{
-       P1 ^= (colors & ao_led_enable);
-}
-
-void
-ao_led_for(uint8_t colors, uint16_t ticks) __reentrant
-{
-       ao_led_on(colors);
-       ao_delay(ticks);
-       ao_led_off(colors);
-}
-
-void
-ao_led_init(uint8_t enable)
-{
-       ao_led_enable = enable;
-       P1SEL &= ~enable;
-       P1 &= ~enable;
-       P1DIR |= enable;
-}
diff --git a/src/ao_log.c b/src/ao_log.c
deleted file mode 100644 (file)
index 6d3ad53..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__pdata uint32_t ao_log_current_pos;
-__pdata uint32_t ao_log_end_pos;
-__pdata uint32_t ao_log_start_pos;
-__xdata uint8_t        ao_log_running;
-__pdata enum flight_state ao_log_state;
-__xdata uint16_t ao_flight_number;
-
-__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL;
-
-void
-ao_log_flush(void)
-{
-       ao_storage_flush();
-}
-
-/*
- * When erasing a flight log, make sure the config block
- * has an up-to-date version of the current flight number
- */
-
-struct ao_log_erase {
-       uint8_t unused;
-       uint16_t flight;
-};
-
-static __xdata struct ao_log_erase erase;
-
-#define LOG_MAX_ERASE  16
-
-static uint32_t
-ao_log_erase_pos(uint8_t i)
-{
-       return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG;
-}
-
-void
-ao_log_write_erase(uint8_t pos)
-{
-       erase.unused = 0x00;
-       erase.flight = ao_flight_number;
-       ao_storage_write(ao_log_erase_pos(pos),  &erase, sizeof (erase));
-       ao_storage_flush();
-}
-
-static void
-ao_log_read_erase(uint8_t pos)
-{
-       ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase));
-}
-
-
-static void
-ao_log_erase_mark(void)
-{
-       uint8_t                         i;
-
-       for (i = 0; i < LOG_MAX_ERASE; i++) {
-               ao_log_read_erase(i);
-               if (erase.unused == 0 && erase.flight == ao_flight_number)
-                       return;
-               if (erase.unused == 0xff) {
-                       ao_log_write_erase(i);
-                       return;
-               }
-       }
-       ao_config_put();
-}
-
-static uint8_t
-ao_log_slots()
-{
-       return (uint8_t) (ao_storage_config / ao_config.flight_log_max);
-}
-
-uint32_t
-ao_log_pos(uint8_t slot)
-{
-       return ((slot) * ao_config.flight_log_max);
-}
-
-static uint16_t
-ao_log_max_flight(void)
-{
-       uint8_t         log_slot;
-       uint8_t         log_slots;
-       uint16_t        log_flight;
-       uint16_t        max_flight = 0;
-
-       /* Scan the log space looking for the biggest flight number */
-       log_slots = ao_log_slots();
-       for (log_slot = 0; log_slot < log_slots; log_slot++) {
-               log_flight = ao_log_flight(log_slot);
-               if (!log_flight)
-                       continue;
-               if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0)
-                       max_flight = log_flight;
-       }
-       return max_flight;
-}
-
-void
-ao_log_scan(void) __reentrant
-{
-       uint8_t         log_slot;
-       uint8_t         log_slots;
-       uint8_t         log_want;
-
-       ao_config_get();
-
-       ao_flight_number = ao_log_max_flight();
-       if (ao_flight_number)
-               if (++ao_flight_number == 0)
-                       ao_flight_number = 1;
-
-       /* Now look through the log of flight numbers from erase operations and
-        * see if the last one is bigger than what we found above
-        */
-       for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) {
-               ao_log_read_erase(log_slot);
-               if (erase.unused == 0) {
-                       if (ao_flight_number == 0 ||
-                           (int16_t) (erase.flight - ao_flight_number) > 0)
-                               ao_flight_number = erase.flight;
-                       break;
-               }
-       }
-       if (ao_flight_number == 0)
-               ao_flight_number = 1;
-
-       /* With a flight number in hand, find a place to write a new log,
-        * use the target flight number to index the available log slots so
-        * that we write logs to each spot about the same number of times.
-        */
-
-       /* Find a log slot for the next flight, if available */
-       ao_log_current_pos = ao_log_end_pos = 0;
-       log_slots = ao_log_slots();
-       log_want = (ao_flight_number - 1) % log_slots;
-       log_slot = log_want;
-       do {
-               if (ao_log_flight(log_slot) == 0) {
-                       ao_log_current_pos = ao_log_pos(log_slot);
-                       ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
-                       break;
-               }
-               if (++log_slot >= log_slots)
-                       log_slot = 0;
-       } while (log_slot != log_want);
-
-       ao_wakeup(&ao_flight_number);
-}
-
-void
-ao_log_start(void)
-{
-       /* start logging */
-       ao_log_running = 1;
-       ao_wakeup(&ao_log_running);
-}
-
-void
-ao_log_stop(void)
-{
-       ao_log_running = 0;
-       ao_log_flush();
-}
-
-uint8_t
-ao_log_present(void)
-{
-       return ao_log_max_flight() != 0;
-}
-
-uint8_t
-ao_log_full(void)
-{
-       return ao_log_current_pos == ao_log_end_pos;
-}
-
-static __xdata struct ao_task ao_log_task;
-
-void
-ao_log_list(void) __reentrant
-{
-       uint8_t slot;
-       uint8_t slots;
-       uint16_t flight;
-
-       slots = ao_log_slots();
-       for (slot = 0; slot < slots; slot++)
-       {
-               flight = ao_log_flight(slot);
-               if (flight)
-                       printf ("flight %d start %x end %x\n",
-                               flight,
-                               (uint16_t) (ao_log_pos(slot) >> 8),
-                               (uint16_t) (ao_log_pos(slot+1) >> 8));
-       }
-       printf ("done\n");
-}
-
-void
-ao_log_delete(void) __reentrant
-{
-       uint8_t slot;
-       uint8_t slots;
-
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-
-       slots = ao_log_slots();
-       /* Look for the flight log matching the requested flight */
-       if (ao_cmd_lex_i) {
-               for (slot = 0; slot < slots; slot++) {
-                       if (ao_log_flight(slot) == ao_cmd_lex_i) {
-                               ao_log_erase_mark();
-                               ao_log_current_pos = ao_log_pos(slot);
-                               ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
-                               while (ao_log_current_pos < ao_log_end_pos) {
-                                       uint8_t i;
-                                       static __xdata uint8_t b;
-
-                                       /*
-                                        * Check to see if we've reached the end of
-                                        * the used memory to avoid re-erasing the same
-                                        * memory over and over again
-                                        */
-                                       for (i = 0; i < 16; i++) {
-                                               if (ao_storage_read(ao_log_current_pos + i, &b, 1))
-                                                       if (b != 0xff)
-                                                               break;
-                                       }
-                                       if (i == 16)
-                                               break;
-                                       ao_storage_erase(ao_log_current_pos);
-                                       ao_log_current_pos += ao_storage_block;
-                               }
-                               puts("Erased");
-                               return;
-                       }
-               }
-       }
-       printf("No such flight: %d\n", ao_cmd_lex_i);
-}
-
-__code struct ao_cmds ao_log_cmds[] = {
-       { ao_log_list,  "l\0List flight logs" },
-       { ao_log_delete,        "d <flight-number>\0Delete flight" },
-       { 0,    NULL },
-};
-
-void
-ao_log_init(void)
-{
-       ao_log_running = 0;
-
-       /* For now, just log the flight starting at the begining of eeprom */
-       ao_log_state = ao_flight_invalid;
-
-       ao_cmd_register(&ao_log_cmds[0]);
-
-       /* Create a task to log events to eeprom */
-       ao_add_task(&ao_log_task, ao_log, "log");
-}
diff --git a/src/ao_log_big.c b/src/ao_log_big.c
deleted file mode 100644 (file)
index 74d94c4..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static __xdata uint8_t ao_log_mutex;
-static __xdata struct ao_log_record log;
-
-static uint8_t
-ao_log_csum(__xdata uint8_t *b) __reentrant
-{
-       uint8_t sum = 0x5a;
-       uint8_t i;
-
-       for (i = 0; i < sizeof (struct ao_log_record); i++)
-               sum += *b++;
-       return -sum;
-}
-
-uint8_t
-ao_log_data(__xdata struct ao_log_record *log) __reentrant
-{
-       uint8_t wrote = 0;
-       /* set checksum */
-       log->csum = 0;
-       log->csum = ao_log_csum((__xdata uint8_t *) log);
-       ao_mutex_get(&ao_log_mutex); {
-               if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
-                       ao_log_stop();
-               if (ao_log_running) {
-                       wrote = 1;
-                       ao_storage_write(ao_log_current_pos,
-                                        log,
-                                        sizeof (struct ao_log_record));
-                       ao_log_current_pos += sizeof (struct ao_log_record);
-               }
-       } ao_mutex_put(&ao_log_mutex);
-       return wrote;
-}
-
-static uint8_t
-ao_log_dump_check_data(void)
-{
-       if (ao_log_csum((uint8_t *) &log) != 0)
-               return 0;
-       return 1;
-}
-
-static __data uint8_t  ao_log_adc_pos;
-
-/* a hack to make sure that ao_log_records fill the eeprom block in even units */
-typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ;
-
-#define AO_SENSOR_INTERVAL_ASCENT      1
-#define AO_SENSOR_INTERVAL_DESCENT     10
-#define AO_OTHER_INTERVAL              32
-
-void
-ao_log(void)
-{
-       __pdata uint16_t        next_sensor, next_other;
-
-       ao_storage_setup();
-
-       ao_log_scan();
-
-       while (!ao_log_running)
-               ao_sleep(&ao_log_running);
-
-       log.type = AO_LOG_FLIGHT;
-       log.tick = ao_sample_tick;
-#if HAS_ACCEL
-       log.u.flight.ground_accel = ao_ground_accel;
-#endif
-       log.u.flight.flight = ao_flight_number;
-       ao_log_data(&log);
-
-       /* Write the whole contents of the ring to the log
-        * when starting up.
-        */
-       ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc);
-       next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick;
-       ao_log_state = ao_flight_startup;
-       for (;;) {
-               /* Write samples to EEPROM */
-               while (ao_log_adc_pos != ao_sample_adc) {
-                       log.tick = ao_adc_ring[ao_log_adc_pos].tick;
-                       if ((int16_t) (log.tick - next_sensor) >= 0) {
-                               log.type = AO_LOG_SENSOR;
-                               log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel;
-                               log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres;
-                               ao_log_data(&log);
-                               if (ao_log_state <= ao_flight_coast)
-                                       next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
-                               else
-                                       next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT;
-                       }
-                       if ((int16_t) (log.tick - next_other) >= 0) {
-                               log.type = AO_LOG_TEMP_VOLT;
-                               log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp;
-                               log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt;
-                               ao_log_data(&log);
-                               log.type = AO_LOG_DEPLOY;
-                               log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d;
-                               log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m;
-                               ao_log_data(&log);
-                               next_other = log.tick + AO_OTHER_INTERVAL;
-                       }
-                       ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos);
-               }
-               /* Write state change to EEPROM */
-               if (ao_flight_state != ao_log_state) {
-                       ao_log_state = ao_flight_state;
-                       log.type = AO_LOG_STATE;
-                       log.tick = ao_sample_tick;
-                       log.u.state.state = ao_log_state;
-                       log.u.state.reason = 0;
-                       ao_log_data(&log);
-
-                       if (ao_log_state == ao_flight_landed)
-                               ao_log_stop();
-               }
-
-               /* Wait for a while */
-               ao_delay(AO_MS_TO_TICKS(100));
-
-               /* Stop logging when told to */
-               while (!ao_log_running)
-                       ao_sleep(&ao_log_running);
-       }
-}
-
-uint16_t
-ao_log_flight(uint8_t slot)
-{
-       if (!ao_storage_read(ao_log_pos(slot),
-                            &log,
-                            sizeof (struct ao_log_record)))
-               return 0;
-
-       if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT)
-               return log.u.flight.flight;
-       return 0;
-}
diff --git a/src/ao_log_telem.c b/src/ao_log_telem.c
deleted file mode 100644 (file)
index 1b472ef..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_log_write_erase(uint8_t pos)
-{
-       (void) pos;
-}
-
-uint8_t
-ao_log_present(void)
-{
-       return 0;
-}
diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c
deleted file mode 100644 (file)
index d5a3b99..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static __data uint16_t ao_log_tiny_interval;
-
-#define AO_LOG_TINY_INTERVAL_DEFAULT   AO_MS_TO_TICKS(1000)
-#if USE_FAST_ASCENT_LOG
-#define AO_LOG_TINY_INTERVAL_ASCENT    AO_MS_TO_TICKS(100)
-#define AO_PAD_RING    8
-#else
-#define AO_LOG_TINY_INTERVAL_ASCENT    AO_LOG_TINY_INTERVAL_DEFAULT
-#define AO_PAD_RING    2
-#endif
-
-__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY;
-
-void
-ao_log_tiny_set_interval(uint16_t ticks)
-{
-       ao_log_tiny_interval = ticks;
-}
-
-
-static void ao_log_tiny_data(uint16_t d)
-{
-       if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
-               ao_log_stop();
-       if (ao_log_running) {
-               ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2);
-               ao_log_current_pos += 2;
-       }
-}
-
-static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING];
-static __pdata uint8_t ao_log_pad_ring_pos;
-
-#define ao_pad_ring_next(n)    (((n) + 1) & (AO_PAD_RING - 1))
-
-static void ao_log_tiny_queue(uint16_t d)
-{
-       ao_log_pad_ring[ao_log_pad_ring_pos] = d;
-       ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos);
-}
-
-static void ao_log_tiny_start(void)
-{
-       uint8_t         p;
-       uint16_t        d;
-
-       ao_log_tiny_data(ao_flight_number);
-       ao_log_tiny_data(ao_ground_pres);
-       p = ao_log_pad_ring_pos;
-       do {
-               d = ao_log_pad_ring[p];
-               /*
-                * ignore unwritten slots
-                */
-               if (d)
-                       ao_log_tiny_data(d);
-               p = ao_pad_ring_next(p);
-       } while (p != ao_log_pad_ring_pos);
-}
-
-void
-ao_log(void)
-{
-       uint16_t                last_time;
-       uint16_t                now;
-       enum ao_flight_state    ao_log_tiny_state;
-       int32_t                 sum;
-       int16_t                 count;
-       uint8_t                 ao_log_adc;
-       uint8_t                 ao_log_started = 0;
-
-       ao_storage_setup();
-
-       ao_log_scan();
-
-       ao_log_tiny_state = ao_flight_invalid;
-       ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
-       sum = 0;
-       count = 0;
-       ao_log_adc = ao_sample_adc;
-       last_time = ao_time();
-       for (;;) {
-
-               /*
-                * Add in pending sample data
-                */
-               ao_sleep(DATA_TO_XDATA(&ao_sample_adc));
-               while (ao_log_adc != ao_sample_adc) {
-                       sum += ao_adc_ring[ao_log_adc].pres;
-                       count++;
-                       ao_log_adc = ao_adc_ring_next(ao_log_adc);
-               }
-               if (ao_log_running) {
-                       if (!ao_log_started) {
-                               ao_log_tiny_start();
-                               ao_log_started = 1;
-                       }
-                       if (ao_flight_state != ao_log_tiny_state) {
-                               ao_log_tiny_data(ao_flight_state | 0x8000);
-                               ao_log_tiny_state = ao_flight_state;
-                               ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT;
-#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT
-                               if (ao_log_tiny_state <= ao_flight_coast)
-                                       ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
-#endif
-                               if (ao_log_tiny_state == ao_flight_landed)
-                                       ao_log_stop();
-                       }
-               }
-
-               /* Stop logging when told to */
-               if (!ao_log_running && ao_log_started)
-                       ao_exit();
-
-               /*
-                * Write out the sample when finished
-                */
-               now = ao_time();
-               if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) {
-                       count = sum / count;
-                       if (ao_log_started)
-                               ao_log_tiny_data(count);
-                       else
-                               ao_log_tiny_queue(count);
-                       sum = 0;
-                       count = 0;
-                       last_time = now;
-               }
-       }
-}
-
-uint16_t
-ao_log_flight(uint8_t slot)
-{
-       static __xdata uint16_t flight;
-
-       (void) slot;
-       ao_storage_read(0, &flight, 2);
-       if (flight == 0xffff)
-               flight = 0;
-       return flight;
-}
diff --git a/src/ao_m25.c b/src/ao_m25.c
deleted file mode 100644 (file)
index d720827..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Total bytes of available storage */
-__pdata uint32_t       ao_storage_total;
-
-/* Block size - device is erased in these units. At least 256 bytes */
-__pdata uint32_t       ao_storage_block;
-
-/* Byte offset of config block. Will be ao_storage_block bytes long */
-__pdata uint32_t       ao_storage_config;
-
-/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
-__pdata uint16_t       ao_storage_unit;
-
-/*
- * Each flash chip is arranged in 64kB sectors; the
- * chip cannot erase in units smaller than that.
- *
- * Writing happens in units of 256 byte pages and
- * can only change bits from 1 to 0. So, you can rewrite
- * the same contents, or append to an existing page easily enough
- */
-
-#define M25_WREN       0x06    /* Write Enable */
-#define M25_WRDI       0x04    /* Write Disable */
-#define M25_RDID       0x9f    /* Read Identification */
-#define M25_RDSR       0x05    /* Read Status Register */
-#define M25_WRSR       0x01    /* Write Status Register */
-#define M25_READ       0x03    /* Read Data Bytes */
-#define M25_FAST_READ  0x0b    /* Read Data Bytes at Higher Speed */
-#define M25_PP         0x02    /* Page Program */
-#define M25_SE         0xd8    /* Sector Erase */
-#define M25_BE         0xc7    /* Bulk Erase */
-#define M25_DP         0xb9    /* Deep Power-down */
-
-/* RDID response */
-#define M25_MANUF_OFFSET       0
-#define M25_MEMORY_TYPE_OFFSET 1
-#define M25_CAPACITY_OFFSET    2
-#define M25_UID_OFFSET         3
-#define M25_CFI_OFFSET         4
-#define M25_RDID_LEN           4       /* that's all we need */
-
-#define M25_CAPACITY_128KB     0x11
-#define M25_CAPACITY_256KB     0x12
-#define M25_CAPACITY_512KB     0x13
-#define M25_CAPACITY_1MB       0x14
-#define M25_CAPACITY_2MB       0x15
-
-/*
- * Status register bits
- */
-
-#define M25_STATUS_SRWD                (1 << 7)        /* Status register write disable */
-#define M25_STATUS_BP_MASK     (7 << 2)        /* Block protect bits */
-#define M25_STATUS_BP_SHIFT    (2)
-#define M25_STATUS_WEL         (1 << 1)        /* Write enable latch */
-#define M25_STATUS_WIP         (1 << 0)        /* Write in progress */
-
-/*
- * On teleterra, the m25 chip select pins are
- * wired on P0_0 through P0_3.
- */
-
-#if M25_MAX_CHIPS > 1
-static uint8_t ao_m25_size[M25_MAX_CHIPS];     /* number of sectors in each chip */
-static uint8_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 uint8_t ao_m25_wip;                     /* write in progress */
-
-static __xdata uint8_t ao_m25_mutex;
-
-/*
- * This little array is abused to send and receive data. A particular
- * caution -- the read and write addresses are written into the last
- * three bytes of the array by ao_m25_set_page_address and then the
- * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither
- * of which touch those last three bytes.
- */
-
-static __xdata uint8_t ao_m25_instruction[4];
-
-#define M25_SELECT(cs)         ao_spi_get_mask(SPI_CS_PORT,cs)
-#define M25_DESELECT(cs)       ao_spi_put_mask(SPI_CS_PORT,cs)
-
-#define M25_BLOCK_SHIFT                        16
-#define M25_BLOCK                      65536L
-#define M25_POS_TO_SECTOR(pos)         ((uint8_t) ((pos) >> M25_BLOCK_SHIFT))
-#define M25_SECTOR_TO_POS(sector)      (((uint32_t) (sector)) << M25_BLOCK_SHIFT)
-
-/*
- * Block until the specified chip is done writing
- */
-static void
-ao_m25_wait_wip(uint8_t cs)
-{
-       if (ao_m25_wip & cs) {
-               M25_SELECT(cs);
-               ao_m25_instruction[0] = M25_RDSR;
-               ao_spi_send(ao_m25_instruction, 1);
-               do {
-                       ao_spi_recv(ao_m25_instruction, 1);
-               } while (ao_m25_instruction[0] & M25_STATUS_WIP);
-               M25_DESELECT(cs);
-               ao_m25_wip &= ~cs;
-       }
-}
-
-/*
- * Set the write enable latch so that page program and sector
- * erase commands will work. Also mark the chip as busy writing
- * so that future operations will block until the WIP bit goes off
- */
-static void
-ao_m25_write_enable(uint8_t cs)
-{
-       M25_SELECT(cs);
-       ao_m25_instruction[0] = M25_WREN;
-       ao_spi_send(&ao_m25_instruction, 1);
-       M25_DESELECT(cs);
-       ao_m25_wip |= cs;
-}
-
-
-/*
- * Returns the number of 64kB sectors
- */
-static uint8_t
-ao_m25_read_capacity(uint8_t cs)
-{
-       uint8_t capacity;
-       M25_SELECT(cs);
-       ao_m25_instruction[0] = M25_RDID;
-       ao_spi_send(ao_m25_instruction, 1);
-       ao_spi_recv(ao_m25_instruction, M25_RDID_LEN);
-       M25_DESELECT(cs);
-
-       /* Check to see if the chip is present */
-       if (ao_m25_instruction[0] == 0xff)
-               return 0;
-       capacity = ao_m25_instruction[M25_CAPACITY_OFFSET];
-
-       /* Sanity check capacity number */
-       if (capacity < 0x11 || 0x1f < capacity)
-               return 0;
-       return 1 << (capacity - 0x10);
-}
-
-static uint8_t
-ao_m25_set_address(uint32_t pos)
-{
-       uint8_t chip;
-#if M25_MAX_CHIPS > 1
-       uint8_t size;
-
-       for (chip = 0; chip < ao_m25_numchips; chip++) {
-               size = ao_m25_size[chip];
-               if (M25_POS_TO_SECTOR(pos) < size)
-                       break;
-               pos -= M25_SECTOR_TO_POS(size);
-       }
-       if (chip == ao_m25_numchips)
-               return 0xff;
-
-       chip = ao_m25_pin[chip];
-#else
-       chip = M25_CS_MASK;
-#endif
-       ao_m25_wait_wip(chip);
-
-       ao_m25_instruction[1] = pos >> 16;
-       ao_m25_instruction[2] = pos >> 8;
-       ao_m25_instruction[3] = pos;
-       return chip;
-}
-
-/*
- * Scan the possible chip select lines
- * to see which flash chips are connected
- */
-static uint8_t
-ao_m25_scan(void)
-{
-#if M25_MAX_CHIPS > 1
-       uint8_t pin, size;
-#endif
-
-       if (ao_m25_total)
-               return 1;
-
-#if M25_MAX_CHIPS > 1
-       ao_m25_numchips = 0;
-       for (pin = 1; pin != 0; pin <<= 1) {
-               if (M25_CS_MASK & pin) {
-                       size = ao_m25_read_capacity(pin);
-                       if (size != 0) {
-                               ao_m25_size[ao_m25_numchips] = size;
-                               ao_m25_pin[ao_m25_numchips] = pin;
-                               ao_m25_total += size;
-                               ao_m25_numchips++;
-                       }
-               }
-       }
-#else
-       ao_m25_total = ao_m25_read_capacity(M25_CS_MASK);
-#endif
-       if (!ao_m25_total)
-               return 0;
-       ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total);
-       ao_storage_block = M25_BLOCK;
-       ao_storage_config = ao_storage_total - M25_BLOCK;
-       ao_storage_unit = 256;
-       return 1;
-}
-
-/*
- * Erase the specified sector
- */
-uint8_t
-ao_storage_erase(uint32_t pos) __reentrant
-{
-       uint8_t cs;
-
-       if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total)
-               return 0;
-
-       ao_mutex_get(&ao_m25_mutex);
-       ao_m25_scan();
-
-       cs = ao_m25_set_address(pos);
-
-       ao_m25_wait_wip(cs);
-       ao_m25_write_enable(cs);
-
-       ao_m25_instruction[0] = M25_SE;
-       M25_SELECT(cs);
-       ao_spi_send(ao_m25_instruction, 4);
-       M25_DESELECT(cs);
-       ao_m25_wip |= cs;
-
-       ao_mutex_put(&ao_m25_mutex);
-       return 1;
-}
-
-/*
- * Write to flash
- */
-uint8_t
-ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
-{
-       uint8_t cs;
-
-       if (pos >= ao_storage_total || pos + len > ao_storage_total)
-               return 0;
-
-       ao_mutex_get(&ao_m25_mutex);
-       ao_m25_scan();
-
-       cs = ao_m25_set_address(pos);
-       ao_m25_write_enable(cs);
-
-       ao_m25_instruction[0] = M25_PP;
-       M25_SELECT(cs);
-       ao_spi_send(ao_m25_instruction, 4);
-       ao_spi_send(d, len);
-       M25_DESELECT(cs);
-
-       ao_mutex_put(&ao_m25_mutex);
-       return 1;
-}
-
-/*
- * Read from flash
- */
-uint8_t
-ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
-{
-       uint8_t cs;
-
-       if (pos >= ao_storage_total || pos + len > ao_storage_total)
-               return 0;
-       ao_mutex_get(&ao_m25_mutex);
-       ao_m25_scan();
-
-       cs = ao_m25_set_address(pos);
-
-       /* No need to use the FAST_READ as we're running at only 8MHz */
-       ao_m25_instruction[0] = M25_READ;
-       M25_SELECT(cs);
-       ao_spi_send(ao_m25_instruction, 4);
-       ao_spi_recv(d, len);
-       M25_DESELECT(cs);
-
-       ao_mutex_put(&ao_m25_mutex);
-       return 1;
-}
-
-void
-ao_storage_flush(void) __reentrant
-{
-}
-
-void
-ao_storage_setup(void)
-{
-       ao_mutex_get(&ao_m25_mutex);
-       ao_m25_scan();
-       ao_mutex_put(&ao_m25_mutex);
-}
-
-void
-ao_storage_device_info(void) __reentrant
-{
-       uint8_t cs;
-#if M25_MAX_CHIPS > 1
-       uint8_t chip;
-#endif
-
-       ao_mutex_get(&ao_m25_mutex);
-       ao_m25_scan();
-       ao_mutex_put(&ao_m25_mutex);
-
-#if M25_MAX_CHIPS > 1
-       printf ("Detected chips %d size %d\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);
-#endif
-
-       printf ("Available chips:\n");
-       for (cs = 1; cs != 0; cs <<= 1) {
-               if ((M25_CS_MASK & cs) == 0)
-                       continue;
-
-               ao_mutex_get(&ao_m25_mutex);
-               M25_SELECT(cs);
-               ao_m25_instruction[0] = M25_RDID;
-               ao_spi_send(ao_m25_instruction, 1);
-               ao_spi_recv(ao_m25_instruction, M25_RDID_LEN);
-               M25_DESELECT(cs);
-
-               printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n",
-                       cs,
-                       ao_m25_instruction[M25_MANUF_OFFSET],
-                       ao_m25_instruction[M25_MEMORY_TYPE_OFFSET],
-                       ao_m25_instruction[M25_CAPACITY_OFFSET],
-                       ao_m25_instruction[M25_UID_OFFSET]);
-               ao_mutex_put(&ao_m25_mutex);
-       }
-}
-
-void
-ao_storage_device_init(void)
-{
-       /* Set up chip select wires */
-       SPI_CS_PORT |= M25_CS_MASK;     /* raise all CS pins */
-       SPI_CS_DIR |= M25_CS_MASK;      /* set CS pins as outputs */
-       SPI_CS_SEL &= ~M25_CS_MASK;     /* set CS pins as GPIO */
-}
diff --git a/src/ao_main.c b/src/ao_main.c
deleted file mode 100644 (file)
index 25acccf..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-main(void)
-{
-       ao_clock_init();
-
-       /* Turn on the red LED until the system is stable */
-       ao_led_init();
-       ao_led_on(AO_LED_RED);
-
-       ao_timer_init();
-       ao_adc_init();
-       ao_beep_init();
-       ao_cmd_init();
-       ao_ee_init();
-       ao_flight_init();
-       ao_log_init();
-       ao_report_init();
-       ao_usb_init();
-       ao_serial_init();
-       ao_gps_init();
-       ao_telemetry_init();
-       ao_radio_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_monitor.c b/src/ao_monitor.c
deleted file mode 100644 (file)
index 69eb58e..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_telem.h"
-
-#if !HAS_MONITOR
-#error Must define HAS_MONITOR to 1
-#endif
-
-__xdata uint8_t ao_monitoring;
-__pdata uint8_t ao_monitor_led;
-
-#define AO_MONITOR_RING        8
-
-__xdata union ao_monitor {
-               struct ao_telemetry_raw_recv    raw;
-               struct ao_telemetry_orig_recv   orig;
-               struct ao_telemetry_tiny_recv   tiny;
-} ao_monitor_ring[AO_MONITOR_RING];
-
-#define ao_monitor_ring_next(n)        (((n) + 1) & (AO_MONITOR_RING - 1))
-
-__data uint8_t ao_monitor_head;
-
-void
-ao_monitor_get(void)
-{
-       uint8_t size;
-
-       for (;;) {
-               switch (ao_monitoring) {
-               case 0:
-                       ao_sleep(&ao_monitoring);
-                       continue;
-               case AO_MONITORING_ORIG:
-                       size = sizeof (struct ao_telemetry_orig_recv);
-                       break;
-               case AO_MONITORING_TINY:
-                       size = sizeof (struct ao_telemetry_tiny_recv);
-                       break;
-               default:
-                       if (ao_monitoring > AO_MAX_TELEMETRY)
-                               ao_monitoring = AO_MAX_TELEMETRY;
-                       size = ao_monitoring;
-                       break;
-               }
-               if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2))
-                       continue;
-               ao_monitor_head = ao_monitor_ring_next(ao_monitor_head);
-               ao_wakeup(DATA_TO_XDATA(&ao_monitor_head));
-               ao_led_toggle(ao_monitor_led);
-       }
-}
-
-void
-ao_monitor_put(void)
-{
-       __xdata char callsign[AO_MAX_CALLSIGN+1];
-
-       uint8_t ao_monitor_tail;
-       uint8_t state;
-       uint8_t sum, byte;
-       int16_t rssi;
-       __xdata union ao_monitor        *m;
-
-#define recv_raw       ((m->raw))
-#define recv_orig      ((m->orig))
-#define recv_tiny      ((m->tiny))
-
-       ao_monitor_tail = ao_monitor_head;
-       for (;;) {
-               while (ao_monitor_tail == ao_monitor_head)
-                       ao_sleep(DATA_TO_XDATA(&ao_monitor_head));
-               m = &ao_monitor_ring[ao_monitor_tail];
-               ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail);
-               switch (ao_monitoring) {
-               case AO_MONITORING_ORIG:
-                       state = recv_orig.telemetry_orig.flight_state;
-
-                       /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */
-                       rssi = (int16_t) (recv_orig.rssi >> 1) - 74;
-                       memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN);
-                       if (state > ao_flight_invalid)
-                               state = ao_flight_invalid;
-                       if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) {
-
-                               /* General header fields */
-                               printf(AO_TELEM_VERSION " %d "
-                                      AO_TELEM_CALL " %s "
-                                      AO_TELEM_SERIAL " %d "
-                                      AO_TELEM_FLIGHT " %d "
-                                      AO_TELEM_RSSI " %d "
-                                      AO_TELEM_STATE " %s "
-                                      AO_TELEM_TICK " %d ",
-                                      AO_TELEMETRY_VERSION,
-                                      callsign,
-                                      recv_orig.telemetry_orig.serial,
-                                      recv_orig.telemetry_orig.flight,
-                                      rssi,
-                                      ao_state_names[state],
-                                      recv_orig.telemetry_orig.adc.tick);
-
-                               /* Raw sensor values */
-                               printf(AO_TELEM_RAW_ACCEL " %d "
-                                      AO_TELEM_RAW_BARO " %d "
-                                      AO_TELEM_RAW_THERMO " %d "
-                                      AO_TELEM_RAW_BATT " %d "
-                                      AO_TELEM_RAW_DROGUE " %d "
-                                      AO_TELEM_RAW_MAIN " %d ",
-                                      recv_orig.telemetry_orig.adc.accel,
-                                      recv_orig.telemetry_orig.adc.pres,
-                                      recv_orig.telemetry_orig.adc.temp,
-                                      recv_orig.telemetry_orig.adc.v_batt,
-                                      recv_orig.telemetry_orig.adc.sense_d,
-                                      recv_orig.telemetry_orig.adc.sense_m);
-
-                               /* Sensor calibration values */
-                               printf(AO_TELEM_CAL_ACCEL_GROUND " %d "
-                                      AO_TELEM_CAL_BARO_GROUND " %d "
-                                      AO_TELEM_CAL_ACCEL_PLUS " %d "
-                                      AO_TELEM_CAL_ACCEL_MINUS " %d ",
-                                      recv_orig.telemetry_orig.ground_accel,
-                                      recv_orig.telemetry_orig.ground_pres,
-                                      recv_orig.telemetry_orig.accel_plus_g,
-                                      recv_orig.telemetry_orig.accel_minus_g);
-
-                               if (recv_orig.telemetry_orig.u.k.unused == 0x8000) {
-                                       /* Kalman state values */
-                                       printf(AO_TELEM_KALMAN_HEIGHT " %d "
-                                              AO_TELEM_KALMAN_SPEED " %d "
-                                              AO_TELEM_KALMAN_ACCEL " %d ",
-                                              recv_orig.telemetry_orig.height,
-                                              recv_orig.telemetry_orig.u.k.speed,
-                                              recv_orig.telemetry_orig.accel);
-                               } else {
-                                       /* Ad-hoc flight values */
-                                       printf(AO_TELEM_ADHOC_ACCEL " %d "
-                                              AO_TELEM_ADHOC_SPEED " %ld "
-                                              AO_TELEM_ADHOC_BARO " %d ",
-                                              recv_orig.telemetry_orig.accel,
-                                              recv_orig.telemetry_orig.u.flight_vel,
-                                              recv_orig.telemetry_orig.height);
-                               }
-                               ao_gps_print(&recv_orig.telemetry_orig.gps);
-                               ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking);
-                               putchar('\n');
-                               ao_rssi_set(rssi);
-                       } else {
-                               printf("CRC INVALID RSSI %3d\n", rssi);
-                       }
-                       break;
-               case AO_MONITORING_TINY:
-                       state = recv_tiny.telemetry_tiny.flight_state;
-
-                       /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */
-                       rssi = (int16_t) (recv_tiny.rssi >> 1) - 74;
-                       memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN);
-                       if (state > ao_flight_invalid)
-                               state = ao_flight_invalid;
-                       if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) {
-                               /* General header fields */
-                               printf(AO_TELEM_VERSION " %d "
-                                      AO_TELEM_CALL " %s "
-                                      AO_TELEM_SERIAL " %d "
-                                      AO_TELEM_FLIGHT " %d "
-                                      AO_TELEM_RSSI " %d "
-                                      AO_TELEM_STATE " %s "
-                                      AO_TELEM_TICK " %d ",
-                                      AO_TELEMETRY_VERSION,
-                                      callsign,
-                                      recv_tiny.telemetry_tiny.serial,
-                                      recv_tiny.telemetry_tiny.flight,
-                                      rssi,
-                                      ao_state_names[state],
-                                      recv_tiny.telemetry_tiny.adc.tick);
-
-                               /* Raw sensor values */
-                               printf(AO_TELEM_RAW_BARO " %d "
-                                      AO_TELEM_RAW_THERMO " %d "
-                                      AO_TELEM_RAW_BATT " %d "
-                                      AO_TELEM_RAW_DROGUE " %d "
-                                      AO_TELEM_RAW_MAIN " %d ",
-                                      recv_tiny.telemetry_tiny.adc.pres,
-                                      recv_tiny.telemetry_tiny.adc.temp,
-                                      recv_tiny.telemetry_tiny.adc.v_batt,
-                                      recv_tiny.telemetry_tiny.adc.sense_d,
-                                      recv_tiny.telemetry_tiny.adc.sense_m);
-
-                               /* Sensor calibration values */
-                               printf(AO_TELEM_CAL_BARO_GROUND " %d ",
-                                      recv_tiny.telemetry_tiny.ground_pres);
-
-#if 1
-                               /* Kalman state values */
-                               printf(AO_TELEM_KALMAN_HEIGHT " %d "
-                                      AO_TELEM_KALMAN_SPEED " %d "
-                                      AO_TELEM_KALMAN_ACCEL " %d\n",
-                                      recv_tiny.telemetry_tiny.height,
-                                      recv_tiny.telemetry_tiny.speed,
-                                      recv_tiny.telemetry_tiny.accel);
-#else
-                               /* Ad-hoc flight values */
-                               printf(AO_TELEM_ADHOC_ACCEL " %d "
-                                      AO_TELEM_ADHOC_SPEED " %ld "
-                                      AO_TELEM_ADHOC_BARO " %d\n",
-                                      recv_tiny.telemetry_tiny.flight_accel,
-                                      recv_tiny.telemetry_tiny.flight_vel,
-                                      recv_tiny.telemetry_tiny.flight_pres);
-#endif
-                               ao_rssi_set(rssi);
-                       } else {
-                               printf("CRC INVALID RSSI %3d\n", rssi);
-                       }
-                       break;
-               default:
-                       printf ("TELEM %02x", ao_monitoring + 2);
-                       sum = 0x5a;
-                       for (state = 0; state < ao_monitoring + 2; state++) {
-                               byte = recv_raw.packet[state];
-                               sum += byte;
-                               printf("%02x", byte);
-                       }
-                       printf("%02x\n", sum);
-                       break;
-               }
-               ao_usb_flush();
-       }
-}
-
-__xdata struct ao_task ao_monitor_get_task;
-__xdata struct ao_task ao_monitor_put_task;
-
-void
-ao_set_monitor(uint8_t monitoring)
-{
-       if (ao_monitoring)
-               ao_radio_recv_abort();
-       ao_monitoring = monitoring;
-       ao_wakeup(&ao_monitoring);
-}
-
-static void
-set_monitor(void)
-{
-       ao_cmd_hex();
-       ao_set_monitor(ao_cmd_lex_i);
-}
-
-__code struct ao_cmds ao_monitor_cmds[] = {
-       { set_monitor,  "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" },
-       { 0,    NULL },
-};
-
-void
-ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant
-{
-       ao_monitor_led = monitor_led;
-       ao_monitoring = monitoring;
-       ao_cmd_register(&ao_monitor_cmds[0]);
-       ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get");
-       ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put");
-}
diff --git a/src/ao_mutex.c b/src/ao_mutex.c
deleted file mode 100644 (file)
index c82a7d5..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_mutex_get(__xdata uint8_t *mutex) __reentrant
-{
-       if (*mutex == ao_cur_task->task_id)
-               ao_panic(AO_PANIC_MUTEX);
-       __critical {
-               while (*mutex)
-                       ao_sleep(mutex);
-               *mutex = ao_cur_task->task_id;
-       }
-}
-
-void
-ao_mutex_put(__xdata uint8_t *mutex) __reentrant
-{
-       if (*mutex != ao_cur_task->task_id)
-               ao_panic(AO_PANIC_MUTEX);
-       __critical {
-               *mutex = 0;
-               ao_wakeup(mutex);
-       }
-}
diff --git a/src/ao_packet.c b/src/ao_packet.c
deleted file mode 100644 (file)
index f627e02..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__xdata struct ao_packet_recv ao_rx_packet;
-__xdata struct ao_packet ao_tx_packet;
-__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
-
-static __xdata char tx_data[AO_PACKET_MAX];
-static __xdata char rx_data[AO_PACKET_MAX];
-static __pdata uint8_t rx_seq;
-
-__xdata struct ao_task ao_packet_task;
-__xdata uint8_t ao_packet_enable;
-__xdata uint8_t ao_packet_master_sleeping;
-
-void
-ao_packet_send(void)
-{
-       ao_led_on(AO_LED_RED);
-       /* If any tx data is pending then copy it into the tx packet */
-       if (ao_packet_tx_used && ao_tx_packet.len == 0) {
-               memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
-               ao_tx_packet.len = ao_packet_tx_used;
-               ao_tx_packet.seq++;
-               ao_packet_tx_used = 0;
-               ao_wakeup(&tx_data);
-       }
-       ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet));
-       ao_led_off(AO_LED_RED);
-}
-
-uint8_t
-ao_packet_recv(void)
-{
-       uint8_t dma_done;
-
-#ifdef AO_LED_GREEN
-       ao_led_on(AO_LED_GREEN);
-#endif
-       dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv));
-#ifdef AO_LED_GREEN
-       ao_led_off(AO_LED_GREEN);
-#endif
-
-       /* Check to see if we got a valid packet */
-       if (!dma_done)
-               return 0;
-       if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK))
-               return 0;
-
-       /* SYN packets carry no data */
-       if (ao_rx_packet.packet.len == AO_PACKET_SYN) {
-               rx_seq = ao_rx_packet.packet.seq;
-               ao_tx_packet.seq = ao_rx_packet.packet.ack;
-               ao_tx_packet.ack = rx_seq;
-       } else if (ao_rx_packet.packet.len) {
-
-               /* Check for incoming data at the next sequence and
-                * for an empty data buffer
-                */
-               if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) &&
-                   ao_packet_rx_used == ao_packet_rx_len) {
-
-                       /* Copy data to the receive data buffer and set up the
-                        * offsets
-                        */
-                       memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
-                       ao_packet_rx_used = 0;
-                       ao_packet_rx_len = ao_rx_packet.packet.len;
-
-                       /* Mark the sequence that we've received to
-                        * let the sender know when we return a packet
-                        */
-                       rx_seq = ao_rx_packet.packet.seq;
-                       ao_tx_packet.ack = rx_seq;
-
-                       /* Poke anyone looking for received data */
-                       ao_wakeup(&ao_stdin_ready);
-               }
-       }
-
-       /* If the other side has seen the latest data we queued,
-        * wake up any task waiting to send data and let them go again
-        */
-       if (ao_rx_packet.packet.ack == ao_tx_packet.seq) {
-               ao_tx_packet.len = 0;
-               ao_wakeup(&ao_tx_packet);
-       }
-       return 1;
-}
-
-#ifndef PACKET_HAS_MASTER
-#define PACKET_HAS_MASTER 1
-#endif
-
-#if PACKET_HAS_MASTER
-void
-ao_packet_flush(void)
-{
-       /* If there is data to send, and this is the master,
-        * then poke the master to send all queued data
-        */
-       if (ao_packet_tx_used && ao_packet_master_sleeping)
-               ao_wakeup(&ao_packet_master_sleeping);
-}
-#endif /* PACKET_HAS_MASTER */
-
-void
-ao_packet_putchar(char c) __reentrant
-{
-       while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) {
-#if PACKET_HAS_MASTER
-               ao_packet_flush();
-#endif
-               ao_sleep(&tx_data);
-       }
-
-       if (ao_packet_enable)
-               tx_data[ao_packet_tx_used++] = c;
-}
-
-char
-ao_packet_pollchar(void) __critical
-{
-       if (!ao_packet_enable)
-               return AO_READ_AGAIN;
-
-       if (ao_packet_rx_used == ao_packet_rx_len)
-               return AO_READ_AGAIN;
-
-       return rx_data[ao_packet_rx_used++];
-}
diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c
deleted file mode 100644 (file)
index b0fdf5a..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static char
-ao_packet_getchar(void) __critical
-{
-       char c;
-       while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) {
-               if (!ao_packet_enable)
-                       break;
-               if (ao_packet_master_sleeping)
-                       ao_wakeup(&ao_packet_master_sleeping);
-               flush();
-               ao_sleep(&ao_stdin_ready);
-       }
-       return c;
-}
-
-static void
-ao_packet_echo(void) __reentrant
-{
-       char    c;
-       while (ao_packet_enable) {
-               c = ao_packet_getchar();
-               if (c != AO_READ_AGAIN)
-                       putchar(c);
-       }
-       ao_exit();
-}
-
-static __xdata struct ao_task  ao_packet_echo_task;
-static __xdata uint16_t                ao_packet_master_delay;
-static __xdata uint16_t                ao_packet_master_time;
-
-#define AO_PACKET_MASTER_DELAY_SHORT   AO_MS_TO_TICKS(100)
-#define AO_PACKET_MASTER_DELAY_LONG    AO_MS_TO_TICKS(1000)
-#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000)
-
-static void
-ao_packet_master_busy(void)
-{
-       ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
-       ao_packet_master_time = ao_time();
-}
-
-static void
-ao_packet_master_check_busy(void)
-{
-       int16_t idle;
-       if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT)
-               return;
-       idle = (int16_t) (ao_time() - ao_packet_master_time);
-
-       if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT)
-               ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG;
-}
-
-void
-ao_packet_master(void)
-{
-       ao_config_get();
-       ao_tx_packet.addr = ao_serial_number;
-       ao_tx_packet.len = AO_PACKET_SYN;
-       ao_packet_master_time = ao_time();
-       ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
-       while (ao_packet_enable) {
-               memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
-               ao_packet_send();
-               if (ao_tx_packet.len)
-                       ao_packet_master_busy();
-               ao_packet_master_check_busy();
-               ao_alarm(ao_packet_master_delay);
-               if (ao_packet_recv()) {
-                       /* if we can transmit data, do so */
-                       if (ao_packet_tx_used && ao_tx_packet.len == 0)
-                               continue;
-                       if (ao_rx_packet.packet.len)
-                               ao_packet_master_busy();
-                       ao_packet_master_sleeping = 1;
-                       ao_alarm(ao_packet_master_delay);
-                       ao_sleep(&ao_packet_master_sleeping);
-                       ao_packet_master_sleeping = 0;
-               }
-       }
-       ao_exit();
-}
-
-static void
-ao_packet_forward(void) __reentrant
-{
-       char c;
-       ao_packet_enable = 1;
-       ao_cmd_white();
-
-       flush();
-#if HAS_MONITOR
-       ao_set_monitor(0);
-#endif
-       ao_add_task(&ao_packet_task, ao_packet_master, "master");
-       ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo");
-       while ((c = getchar()) != '~') {
-               if (c == '\r') c = '\n';
-               ao_packet_putchar(c);
-       }
-
-       /* Wait for a second if there is any pending data */
-       for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++)
-               ao_delay(AO_MS_TO_TICKS(100));
-       ao_packet_enable = 0;
-       while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
-               ao_radio_recv_abort();
-               ao_wakeup(&ao_stdin_ready);
-               ao_delay(AO_MS_TO_TICKS(10));
-       }
-}
-
-
-
-__code struct ao_cmds ao_packet_master_cmds[] = {
-       { ao_packet_forward,    "p\0Remote packet link." },
-       { 0,    NULL },
-};
-
-void
-ao_packet_master_init(void)
-{
-       ao_cmd_register(&ao_packet_master_cmds[0]);
-}
diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c
deleted file mode 100644 (file)
index 9f14052..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-ao_packet_slave(void)
-{
-       ao_tx_packet.addr = ao_serial_number;
-       ao_tx_packet.len = AO_PACKET_SYN;
-       while (ao_packet_enable) {
-               if (ao_packet_recv()) {
-                       memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
-#if HAS_FLIGHT
-                       ao_flight_force_idle = TRUE;
-#endif
-                       ao_packet_send();
-               }
-       }
-       ao_exit();
-}
-
-void
-ao_packet_slave_start(void)
-{
-       ao_packet_enable = 1;
-       ao_add_task(&ao_packet_task, ao_packet_slave, "slave");
-}
-
-void
-ao_packet_slave_stop(void)
-{
-       if (ao_packet_enable) {
-               ao_packet_enable = 0;
-               while (ao_packet_task.wchan) {
-                       ao_radio_recv_abort();
-                       ao_delay(AO_MS_TO_TICKS(10));
-               }
-       }
-}
-
-void
-ao_packet_slave_init(uint8_t enable)
-{
-       ao_add_stdio(ao_packet_pollchar,
-                    ao_packet_putchar,
-                    NULL);
-       if (enable)
-               ao_packet_slave_start();
-}
diff --git a/src/ao_panic.c b/src/ao_panic.c
deleted file mode 100644 (file)
index fdada20..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#ifndef HAS_BEEP
-#error Please define HAS_BEEP
-#endif
-
-#if !HAS_BEEP
-#define ao_beep(x)
-#endif
-
-static void
-ao_panic_delay(uint8_t n)
-{
-       uint8_t i = 0, j = 0;
-
-       while (n--)
-               while (--j)
-                       while (--i)
-                               _asm nop _endasm;
-}
-
-void
-ao_panic(uint8_t reason)
-{
-       uint8_t n;
-
-       __critical for (;;) {
-               ao_panic_delay(20);
-               for (n = 0; n < 5; n++) {
-                       ao_led_on(AO_LED_RED);
-                       ao_beep(AO_BEEP_HIGH);
-                       ao_panic_delay(1);
-                       ao_led_off(AO_LED_RED);
-                       ao_beep(AO_BEEP_LOW);
-                       ao_panic_delay(1);
-               }
-               ao_beep(AO_BEEP_OFF);
-               ao_panic_delay(2);
-#pragma disable_warning 126
-               for (n = 0; n < reason; n++) {
-                       ao_led_on(AO_LED_RED);
-                       ao_beep(AO_BEEP_MID);
-                       ao_panic_delay(10);
-                       ao_led_off(AO_LED_RED);
-                       ao_beep(AO_BEEP_OFF);
-                       ao_panic_delay(10);
-               }
-       }
-}
diff --git a/src/ao_pins.h b/src/ao_pins.h
deleted file mode 100644 (file)
index e1f5459..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-
-#if defined(TELEMETRUM_V_1_0)
-       #define HAS_FLIGHT              1
-       #define HAS_USB                 1
-       #define HAS_BEEP                1
-       #define HAS_GPS                 1
-       #define HAS_SERIAL_1            1
-       #define HAS_ADC                 1
-       #define USE_SERIAL_STDIN        0
-       #define HAS_EEPROM              1
-       #define USE_INTERNAL_FLASH      0
-       #define HAS_DBG                 1
-       #define DBG_ON_P1               1
-       #define DBG_ON_P0               0
-       #define IGNITE_ON_P2            1
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       0
-       #define PACKET_HAS_SLAVE        1
-
-       #define HAS_COMPANION           1
-       #define COMPANION_CS_ON_P1      1
-       #define COMPANION_CS_MASK       0x4     /* CS1 is P1_2 */
-       #define COMPANION_CS            P1_2
-
-       #define AO_LED_RED              1
-       #define LEDS_AVAILABLE          (AO_LED_RED)
-       #define HAS_EXTERNAL_TEMP       0
-       #define HAS_ACCEL_REF           0
-       #define HAS_ACCEL               1
-       #define HAS_IGNITE              1
-       #define HAS_MONITOR             0
-#endif
-
-#if defined(TELEMETRUM_V_1_1)
-       #define HAS_FLIGHT              1
-       #define HAS_USB                 1
-       #define HAS_BEEP                1
-       #define HAS_GPS                 1
-       #define HAS_SERIAL_1            1
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 1
-       #define HAS_EEPROM              1
-       #define USE_INTERNAL_FLASH      0
-       #define HAS_DBG                 1
-       #define DBG_ON_P1               1
-       #define DBG_ON_P0               0
-       #define IGNITE_ON_P2            1
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       0
-       #define PACKET_HAS_SLAVE        1
-
-       #define HAS_COMPANION           1
-       #define COMPANION_CS_ON_P1      1
-       #define COMPANION_CS_MASK       0x4     /* CS1 is P1_2 */
-       #define COMPANION_CS            P1_2
-
-       #define AO_LED_RED              1
-       #define LEDS_AVAILABLE          (AO_LED_RED)
-       #define HAS_EXTERNAL_TEMP       0
-       #define HAS_ACCEL_REF           1
-       #define SPI_CS_ON_P1            1
-       #define SPI_CS_ON_P0            0
-       #define M25_CS_MASK             0x02    /* CS0 is P1_1 */
-       #define M25_MAX_CHIPS           1
-       #define HAS_ACCEL               1
-       #define HAS_IGNITE              1
-       #define HAS_MONITOR             0
-#endif
-
-#if defined(TELEDONGLE_V_0_2)
-       #define HAS_FLIGHT              0
-       #define HAS_USB                 1
-       #define HAS_BEEP                0
-       #define HAS_SERIAL_1            0
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 0
-       #define HAS_DBG                 1
-       #define HAS_EEPROM              0
-       #define DBG_ON_P1               1
-       #define DBG_ON_P0               0
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       1
-       #define PACKET_HAS_SLAVE        0
-       #define AO_LED_RED              1
-       #define AO_LED_GREEN            2
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define SPI_CS_ON_P1            1
-       #define SPI_CS_ON_P0            0
-       #define HAS_IGNITE              0
-       #define HAS_MONITOR             1
-#endif
-
-#if defined(TELEMINI_V_1_0)
-       #define HAS_FLIGHT              1
-       #define HAS_USB                 0
-       #define HAS_BEEP                0
-       #define HAS_GPS                 0
-       #define HAS_SERIAL_1            0
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 1
-       #define HAS_EEPROM              1
-       #define USE_INTERNAL_FLASH      1
-       #define HAS_DBG                 0
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            1
-       #define PACKET_HAS_MASTER       0
-       #define PACKET_HAS_SLAVE        1
-       #define USE_FAST_ASCENT_LOG     1
-
-       #define AO_LED_GREEN            1
-       #define AO_LED_RED              2
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define HAS_EXTERNAL_TEMP       0
-       #define HAS_ACCEL               0
-       #define HAS_IGNITE              1
-       #define HAS_MONITOR             0
-#endif
-
-#if defined(TELENANO_V_0_1)
-       #define HAS_FLIGHT              1
-       #define HAS_USB                 0
-       #define HAS_BEEP                0
-       #define HAS_GPS                 0
-       #define HAS_SERIAL_1            0
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 1
-       #define HAS_EEPROM              1
-       #define USE_INTERNAL_FLASH      1
-       #define HAS_DBG                 0
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            1
-       #define PACKET_HAS_MASTER       0
-       #define PACKET_HAS_SLAVE        1
-
-       #define AO_LED_GREEN            1
-       #define AO_LED_RED              2
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define HAS_EXTERNAL_TEMP       0
-       #define HAS_ACCEL               0
-       #define HAS_IGNITE              0
-       #define HAS_MONITOR             0
-#endif
-
-#if defined(TELEMETRUM_V_0_1)
-       #define HAS_FLIGHT              1
-       #define HAS_USB                 1
-       #define HAS_BEEP                1
-       #define HAS_GPS                 1
-       #define HAS_SERIAL_1            1
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 1
-       #define HAS_DBG                 0
-       #define HAS_EEPROM              1
-       #define USE_INTERNAL_FLASH      0
-       #define DBG_ON_P1               0
-       #define DBG_ON_P0               1
-       #define IGNITE_ON_P2            1
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       0
-       #define PACKET_HAS_SLAVE        1
-       #define AO_LED_RED              2
-       #define AO_LED_GREEN            1
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define HAS_EXTERNAL_TEMP       1
-       #define HAS_ACCEL_REF           0
-       #define SPI_CS_ON_P1            1
-       #define SPI_CS_ON_P0            0
-       #define HAS_ACCEL               1
-       #define HAS_IGNITE              1
-       #define HAS_MONITOR             0
-#endif
-
-#if defined(TELEDONGLE_V_0_1)
-       #define HAS_FLIGHT              0
-       #define HAS_USB                 1
-       #define HAS_BEEP                0
-       #define HAS_SERIAL_1            0
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 0
-       #define HAS_DBG                 0
-       #define HAS_EEPROM              0
-       #define DBG_ON_P1               0
-       #define DBG_ON_P0               1
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       1
-       #define PACKET_HAS_SLAVE        0
-       #define AO_LED_RED              2
-       #define AO_LED_GREEN            1
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define SPI_CS_ON_P1            0
-       #define SPI_CS_ON_P0            1
-       #define HAS_IGNITE              0
-       #define HAS_MONITOR             1
-#endif
-
-#if defined(TIDONGLE)
-       #define HAS_FLIGHT              0
-       #define HAS_USB                 1
-       #define HAS_BEEP                0
-       #define HAS_SERIAL_1            0
-       #define USE_SERIAL_STDIN        0
-       #define HAS_ADC                 0
-       #define HAS_DBG                 1
-       #define HAS_EEPROM              0
-       #define DBG_ON_P1               0
-       #define DBG_ON_P0               1
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       1
-       #define PACKET_HAS_SLAVE        0
-       #define AO_LED_RED              2
-       #define LEDS_AVAILABLE          (AO_LED_RED)
-       #define SPI_CS_ON_P1            0
-       #define SPI_CS_ON_P0            1
-       #define HAS_IGNITE              0
-       #define HAS_MONITOR             1
-#endif
-
-#if defined(TELEBT_V_0_0)
-       #define HAS_FLIGHT              0
-       #define HAS_USB                 1
-       #define HAS_BEEP                0
-       #define HAS_SERIAL_1            1
-       #define USE_SERIAL_STDIN        1
-       #define HAS_ADC                 0
-       #define HAS_DBG                 1
-       #define HAS_EEPROM              0
-       #define HAS_BTM                 1
-       #define DBG_ON_P1               0
-       #define DBG_ON_P0               1
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       1
-       #define PACKET_HAS_SLAVE        0
-       #define AO_LED_RED              2
-       #define AO_LED_GREEN            1
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define SPI_CS_ON_P1            1
-       #define SPI_CS_ON_P0            0
-       #define HAS_IGNITE              0
-       #define BT_LINK_ON_P2           1
-       #define BT_LINK_ON_P1           0
-       #define BT_LINK_PIN_INDEX       7
-       #define BT_LINK_PIN             P2_1
-       #define HAS_MONITOR             1
-#endif
-
-#if defined(TELEBT_V_0_1)
-       #define HAS_FLIGHT              0
-       #define HAS_USB                 1
-       #define HAS_BEEP                1
-       #define HAS_SERIAL_1            1
-       #define HAS_SERIAL_1_ALT_1      1
-       #define HAS_SERIAL_1_ALT_2      0
-       #define HAS_SERIAL_1_HW_FLOW    1
-       #define USE_SERIAL_STDIN        1
-       #define HAS_ADC                 0
-       #define HAS_DBG                 1
-       #define HAS_EEPROM              1
-       #define USE_INTERNAL_FLASH      0
-       #define HAS_BTM                 1
-       #define DBG_ON_P1               1
-       #define DBG_ON_P0               0
-       #define IGNITE_ON_P2            0
-       #define IGNITE_ON_P0            0
-       #define PACKET_HAS_MASTER       1
-       #define PACKET_HAS_SLAVE        0
-       #define AO_LED_RED              1
-       #define AO_LED_GREEN            2
-       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
-       #define SPI_CS_ON_P1            1
-       #define SPI_CS_ON_P0            0
-       #define M25_CS_MASK             0x04    /* CS0 is P1_2 */
-       #define M25_MAX_CHIPS           1
-       #define HAS_ACCEL               0
-       #define HAS_IGNITE              0
-       #define BT_LINK_ON_P2           0
-       #define BT_LINK_ON_P1           1
-       #define BT_LINK_PIN_INDEX       7
-       #define BT_LINK_PIN             P1_7
-       #define HAS_MONITOR             1
-#endif
-
-#if DBG_ON_P1
-
-       #define DBG_CLOCK       (1 << 4)        /* mi0 */
-       #define DBG_DATA        (1 << 5)        /* mo0 */
-       #define DBG_RESET_N     (1 << 3)        /* c0 */
-
-       #define DBG_CLOCK_PIN   (P1_4)
-       #define DBG_DATA_PIN    (P1_5)
-       #define DBG_RESET_N_PIN (P1_3)
-
-       #define DBG_PORT_NUM    1
-       #define DBG_PORT        P1
-       #define DBG_PORT_SEL    P1SEL
-       #define DBG_PORT_INP    P1INP
-       #define DBG_PORT_DIR    P1DIR
-
-#endif /* DBG_ON_P1 */
-
-#if DBG_ON_P0
-
-       #define DBG_CLOCK       (1 << 3)
-       #define DBG_DATA        (1 << 4)
-       #define DBG_RESET_N     (1 << 5)
-
-       #define DBG_CLOCK_PIN   (P0_3)
-       #define DBG_DATA_PIN    (P0_4)
-       #define DBG_RESET_N_PIN (P0_5)
-
-       #define DBG_PORT_NUM    0
-       #define DBG_PORT        P0
-       #define DBG_PORT_SEL    P0SEL
-       #define DBG_PORT_INP    P0INP
-       #define DBG_PORT_DIR    P0DIR
-
-#endif /* DBG_ON_P0 */
-
-#if COMPANION_CS_ON_P1
-       #define COMPANION_CS_PORT       P1
-       #define COMPANION_CS_SEL        P1SEL
-       #define COMPANION_CS_DIR        P1DIR
-#endif
-
-#if SPI_CS_ON_P1
-       #define SPI_CS_PORT     P1
-       #define SPI_CS_SEL      P1SEL
-       #define SPI_CS_DIR      P1DIR
-#endif
-
-#if SPI_CS_ON_P0
-       #define SPI_CS_PORT     P0
-       #define SPI_CS_SEL      P0SEL
-       #define SPI_CS_DIR      P0DIR
-#endif
-
-#ifndef IGNITE_ON_P2
-#error Please define IGNITE_ON_P2
-#endif
-
-#ifndef IGNITE_ON_P0
-#error Please define IGNITE_ON_P0
-#endif
-
-#ifndef HAS_SERIAL_1
-#error Please define HAS_SERIAL_1
-#endif
-
-#ifndef USE_SERIAL_STDIN
-#error Please define USE_SERIAL_STDIN
-#endif
-
-#ifndef HAS_ADC
-#error Please define HAS_ADC
-#endif
-
-#ifndef HAS_EEPROM
-#error Please define HAS_EEPROM
-#endif
-
-#if HAS_EEPROM
-#ifndef USE_INTERNAL_FLASH
-#error Please define USE_INTERNAL_FLASH
-#endif
-#endif
-
-#ifndef HAS_DBG
-#error Please define HAS_DBG
-#endif
-
-#ifndef HAS_IGNITE
-#error Please define HAS_IGNITE
-#endif
-
-#ifndef PACKET_HAS_MASTER
-#error Please define PACKET_HAS_MASTER
-#endif
-
-#ifndef PACKET_HAS_SLAVE
-#error Please define PACKET_HAS_SLAVE
-#endif
-
-#ifndef HAS_MONITOR
-#error Please define HAS_MONITOR
-#endif
-#endif /* _AO_PINS_H_ */
diff --git a/src/ao_product.c b/src/ao_product.c
deleted file mode 100644 (file)
index fb59580..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_product.h"
-
-/* Defines which mark this particular AltOS product */
-
-const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING;
-const char ao_manufacturer[] = AO_iManufacturer_STRING;
-const char ao_product[] = AO_iProduct_STRING;
-
-#define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
-
-#if HAS_USB
-#include "ao_usb.h"
-/* USB descriptors in one giant block of bytes */
-__code __at(0x00aa) uint8_t ao_usb_descriptors [] =
-{
-       /* Device descriptor */
-       0x12,
-       AO_USB_DESC_DEVICE,
-       LE_WORD(0x0110),        /*  bcdUSB */
-       0x02,                   /*  bDeviceClass */
-       0x00,                   /*  bDeviceSubClass */
-       0x00,                   /*  bDeviceProtocol */
-       AO_USB_CONTROL_SIZE,    /*  bMaxPacketSize */
-       LE_WORD(0xFFFE),        /*  idVendor */
-       LE_WORD(AO_idProduct_NUMBER),   /*  idProduct */
-       LE_WORD(0x0100),        /*  bcdDevice */
-       0x01,                   /*  iManufacturer */
-       0x02,                   /*  iProduct */
-       0x03,                   /*  iSerialNumber */
-       0x01,                   /*  bNumConfigurations */
-
-       /* Configuration descriptor */
-       0x09,
-       AO_USB_DESC_CONFIGURATION,
-       LE_WORD(67),            /*  wTotalLength */
-       0x02,                   /*  bNumInterfaces */
-       0x01,                   /*  bConfigurationValue */
-       0x00,                   /*  iConfiguration */
-       0xC0,                   /*  bmAttributes */
-       0x32,                   /*  bMaxPower */
-
-       /* Control class interface */
-       0x09,
-       AO_USB_DESC_INTERFACE,
-       0x00,                   /*  bInterfaceNumber */
-       0x00,                   /*  bAlternateSetting */
-       0x01,                   /*  bNumEndPoints */
-       0x02,                   /*  bInterfaceClass */
-       0x02,                   /*  bInterfaceSubClass */
-       0x01,                   /*  bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
-       0x00,                   /*  iInterface */
-
-       /* Header functional descriptor */
-       0x05,
-       CS_INTERFACE,
-       0x00,                   /*  bDescriptor SubType Header */
-       LE_WORD(0x0110),        /*  CDC version 1.1 */
-
-       /* Call management functional descriptor */
-       0x05,
-       CS_INTERFACE,
-       0x01,                   /* bDescriptor SubType Call Management */
-       0x01,                   /* bmCapabilities = device handles call management */
-       0x01,                   /* bDataInterface call management interface number */
-
-       /* ACM functional descriptor */
-       0x04,
-       CS_INTERFACE,
-       0x02,                   /* bDescriptor SubType Abstract Control Management */
-       0x02,                   /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */
-
-       /* Union functional descriptor */
-       0x05,
-       CS_INTERFACE,
-       0x06,                   /* bDescriptor SubType Union Functional descriptor */
-       0x00,                   /* bMasterInterface */
-       0x01,                   /* bSlaveInterface0 */
-
-       /* Notification EP */
-       0x07,
-       AO_USB_DESC_ENDPOINT,
-       AO_USB_INT_EP|0x80,     /* bEndpointAddress */
-       0x03,                   /* bmAttributes = intr */
-       LE_WORD(8),             /* wMaxPacketSize */
-       0x0A,                   /* bInterval */
-
-       /* Data class interface descriptor */
-       0x09,
-       AO_USB_DESC_INTERFACE,
-       0x01,                   /* bInterfaceNumber */
-       0x00,                   /* bAlternateSetting */
-       0x02,                   /* bNumEndPoints */
-       0x0A,                   /* bInterfaceClass = data */
-       0x00,                   /* bInterfaceSubClass */
-       0x00,                   /* bInterfaceProtocol */
-       0x00,                   /* iInterface */
-
-       /* Data EP OUT */
-       0x07,
-       AO_USB_DESC_ENDPOINT,
-       AO_USB_OUT_EP,          /* bEndpointAddress */
-       0x02,                   /* bmAttributes = bulk */
-       LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
-       0x00,                   /* bInterval */
-
-       /* Data EP in */
-       0x07,
-       AO_USB_DESC_ENDPOINT,
-       AO_USB_IN_EP|0x80,      /* bEndpointAddress */
-       0x02,                   /* bmAttributes = bulk */
-       LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
-       0x00,                   /* bInterval */
-
-       /* String descriptors */
-       0x04,
-       AO_USB_DESC_STRING,
-       LE_WORD(0x0409),
-
-       /* iManufacturer */
-       AO_iManufacturer_LEN,
-       AO_USB_DESC_STRING,
-       AO_iManufacturer_UCS2,
-
-       /* iProduct */
-       AO_iProduct_LEN,
-       AO_USB_DESC_STRING,
-       AO_iProduct_UCS2,
-
-       /* iSerial */
-       AO_iSerial_LEN,
-       AO_USB_DESC_STRING,
-       AO_iSerial_UCS2,
-
-       /* Terminating zero */
-       0
-};
-#endif
diff --git a/src/ao_radio.c b/src/ao_radio.c
deleted file mode 100644 (file)
index 00816b3..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Values from SmartRF® Studio for:
- *
- * Deviation:  20.507812 kHz
- * Datarate:   38.360596 kBaud
- * Modulation: GFSK
- * RF Freq:    434.549927 MHz
- * Channel:    99.975586 kHz
- * Channel:    0
- * RX filter:  93.75 kHz
- */
-
-/*
- * For IF freq of 140.62kHz, the IF value is:
- *
- * 140.62e3 / (24e6 / 2**10) = 6
- */
-
-#define IF_FREQ_CONTROL        6
-
-/*
- * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are
- *
- * BW = 24e6 / (8 * (4 + M) * 2 ** E)
- *
- * So, M = 0 and E = 3
- */
-
-#define CHANBW_M       0
-#define CHANBW_E       3
-
-/*
- * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are:
- *
- * R = (256 + M) * 2** E * 24e6 / 2**28
- *
- * So M is 163 and E is 10
- */
-
-#define DRATE_E                10
-#define DRATE_M                163
-
-/*
- * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:
- *
- * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E
- *
- * So M is 6 and E is 3
- */
-
-#define DEVIATION_M    6
-#define DEVIATION_E    3
-
-/*
- * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone),
- * so the DRATE_E and DRATE_M values are:
- *
- * M is 94 and E is 6
- *
- * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
- */
-
-#define RDF_DRATE_E    6
-#define RDF_DRATE_M    94
-#define RDF_PACKET_LEN 50
-
-/*
- * RDF deviation should match the normal NFM value of 5kHz
- *
- * M is 6 and E is 1
- *
- */
-
-#define RDF_DEVIATION_M        6
-#define RDF_DEVIATION_E        1
-
-/* This are from the table for 433MHz */
-
-#define RF_POWER_M30_DBM       0x12
-#define RF_POWER_M20_DBM       0x0e
-#define RF_POWER_M15_DBM       0x1d
-#define RF_POWER_M10_DBM       0x34
-#define RF_POWER_M5_DBM                0x2c
-#define RF_POWER_0_DBM         0x60
-#define RF_POWER_5_DBM         0x84
-#define RF_POWER_7_DBM         0xc8
-#define RF_POWER_10_DBM                0xc0
-
-#define RF_POWER               RF_POWER_10_DBM
-
-static __code uint8_t radio_setup[] = {
-       RF_PA_TABLE7_OFF,       RF_POWER,
-       RF_PA_TABLE6_OFF,       RF_POWER,
-       RF_PA_TABLE5_OFF,       RF_POWER,
-       RF_PA_TABLE4_OFF,       RF_POWER,
-       RF_PA_TABLE3_OFF,       RF_POWER,
-       RF_PA_TABLE2_OFF,       RF_POWER,
-       RF_PA_TABLE1_OFF,       RF_POWER,
-       RF_PA_TABLE0_OFF,       RF_POWER,
-
-       RF_FSCTRL1_OFF,         (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),
-       RF_FSCTRL0_OFF,         (0 << RF_FSCTRL0_FREQOFF_SHIFT),
-
-       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
-                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
-                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
-       RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
-       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
-                                RF_MDMCFG2_MOD_FORMAT_GFSK |
-                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
-       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
-                                RF_MDMCFG1_NUM_PREAMBLE_4 |
-                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
-       RF_MDMCFG0_OFF,         (17 << RF_MDMCFG0_CHANSPC_M_SHIFT),
-
-       RF_CHANNR_OFF,          0,
-
-       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
-                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
-
-       /* SmartRF says set LODIV_BUF_CURRENT_TX to 0
-        * And, we're not using power ramping, so use PA_POWER 0
-        */
-       RF_FREND0_OFF,          ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) |
-                                (0 << RF_FREND0_PA_POWER_SHIFT)),
-
-       RF_FREND1_OFF,          ((1 << RF_FREND1_LNA_CURRENT_SHIFT) |
-                                (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) |
-                                (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) |
-                                (2 << RF_FREND1_MIX_CURRENT_SHIFT)),
-
-       RF_FSCAL3_OFF,          0xE9,
-       RF_FSCAL2_OFF,          0x0A,
-       RF_FSCAL1_OFF,          0x00,
-       RF_FSCAL0_OFF,          0x1F,
-
-       RF_TEST2_OFF,           0x88,
-       RF_TEST1_OFF,           0x31,
-       RF_TEST0_OFF,           0x09,
-
-       /* default sync values */
-       RF_SYNC1_OFF,           0xD3,
-       RF_SYNC0_OFF,           0x91,
-
-       /* max packet length */
-       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
-                                PKTCTRL1_APPEND_STATUS|
-                                PKTCTRL1_ADR_CHK_NONE),
-       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_WHITE_DATA|
-                                RF_PKTCTRL0_PKT_FORMAT_NORMAL|
-                                RF_PKTCTRL0_CRC_EN|
-                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
-       RF_ADDR_OFF,            0x00,
-       RF_MCSM2_OFF,           (RF_MCSM2_RX_TIME_END_OF_PACKET),
-       RF_MCSM1_OFF,           (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING|
-                                RF_MCSM1_RXOFF_MODE_IDLE|
-                                RF_MCSM1_TXOFF_MODE_IDLE),
-       RF_MCSM0_OFF,           (RF_MCSM0_FS_AUTOCAL_FROM_IDLE|
-                                RF_MCSM0_MAGIC_3|
-                                RF_MCSM0_CLOSE_IN_RX_0DB),
-       RF_FOCCFG_OFF,          (RF_FOCCFG_FOC_PRE_K_3K,
-                                RF_FOCCFG_FOC_POST_K_PRE_K,
-                                RF_FOCCFG_FOC_LIMIT_BW_OVER_4),
-       RF_BSCFG_OFF,           (RF_BSCFG_BS_PRE_K_2K|
-                                RF_BSCFG_BS_PRE_KP_3KP|
-                                RF_BSCFG_BS_POST_KI_PRE_KI|
-                                RF_BSCFG_BS_POST_KP_PRE_KP|
-                                RF_BSCFG_BS_LIMIT_0),
-       RF_AGCCTRL2_OFF,        0x43,
-       RF_AGCCTRL1_OFF,        0x40,
-       RF_AGCCTRL0_OFF,        0x91,
-
-       RF_IOCFG2_OFF,          0x00,
-       RF_IOCFG1_OFF,          0x00,
-       RF_IOCFG0_OFF,          0x00,
-};
-
-static __code uint8_t rdf_setup[] = {
-       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
-                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
-                                (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
-       RF_MDMCFG3_OFF,         (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
-       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
-                                RF_MDMCFG2_MOD_FORMAT_GFSK |
-                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
-       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_DIS |
-                                RF_MDMCFG1_NUM_PREAMBLE_2 |
-                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
-
-       RF_DEVIATN_OFF,         ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
-                                (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
-
-       /* packet length is set in-line */
-       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
-                                PKTCTRL1_ADR_CHK_NONE),
-       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_PKT_FORMAT_NORMAL|
-                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
-};
-
-static __code uint8_t fixed_pkt_setup[] = {
-       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
-                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
-                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
-       RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
-       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
-                                RF_MDMCFG2_MOD_FORMAT_GFSK |
-                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
-       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
-                                RF_MDMCFG1_NUM_PREAMBLE_4 |
-                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
-
-       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
-                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
-
-       /* max packet length -- now set inline */
-       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
-                                PKTCTRL1_APPEND_STATUS|
-                                PKTCTRL1_ADR_CHK_NONE),
-       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_WHITE_DATA|
-                                RF_PKTCTRL0_PKT_FORMAT_NORMAL|
-                                RF_PKTCTRL0_CRC_EN|
-                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
-};
-
-__xdata uint8_t        ao_radio_dma;
-__xdata uint8_t ao_radio_dma_done;
-__xdata uint8_t ao_radio_done;
-__xdata uint8_t ao_radio_abort;
-__xdata uint8_t ao_radio_mutex;
-
-void
-ao_radio_general_isr(void) __interrupt 16
-{
-       S1CON &= ~0x03;
-       if (RFIF & RFIF_IM_TIMEOUT) {
-               ao_radio_recv_abort();
-               RFIF &= ~ RFIF_IM_TIMEOUT;
-       } else if (RFIF & RFIF_IM_DONE) {
-               ao_radio_done = 1;
-               ao_wakeup(&ao_radio_done);
-               RFIF &= ~RFIF_IM_DONE;
-       }
-}
-
-void
-ao_radio_set_packet(void)
-{
-       uint8_t i;
-       for (i = 0; i < sizeof (fixed_pkt_setup); i += 2)
-               RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1];
-}
-
-void
-ao_radio_idle(void)
-{
-       if (RF_MARCSTATE != RF_MARCSTATE_IDLE)
-       {
-               do {
-                       RFST = RFST_SIDLE;
-                       ao_yield();
-               } while (RF_MARCSTATE != RF_MARCSTATE_IDLE);
-       }
-}
-
-void
-ao_radio_get(uint8_t len)
-{
-       ao_config_get();
-       ao_mutex_get(&ao_radio_mutex);
-       ao_radio_idle();
-       RF_CHANNR = ao_config.radio_channel;
-       RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16);
-       RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8);
-       RF_FREQ0 = (uint8_t) (ao_config.radio_setting);
-       RF_PKTLEN = len;
-}
-
-
-void
-ao_radio_send(__xdata void *packet, uint8_t size) __reentrant
-{
-       ao_radio_get(size);
-       ao_radio_done = 0;
-       ao_dma_set_transfer(ao_radio_dma,
-                           packet,
-                           &RFDXADDR,
-                           size,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_RADIO,
-                           DMA_CFG1_SRCINC_1 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_HIGH);
-       ao_dma_start(ao_radio_dma);
-       RFST = RFST_STX;
-       __critical while (!ao_radio_done)
-               ao_sleep(&ao_radio_done);
-       ao_radio_put();
-}
-
-uint8_t
-ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant
-{
-       ao_radio_abort = 0;
-       ao_radio_get(size - 2);
-       ao_dma_set_transfer(ao_radio_dma,
-                           &RFDXADDR,
-                           packet,
-                           size,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_RADIO,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_1 |
-                           DMA_CFG1_PRIORITY_HIGH);
-       ao_dma_start(ao_radio_dma);
-       RFST = RFST_SRX;
-
-       /* Wait for DMA to be done, for the radio receive process to
-        * get aborted or for a receive timeout to fire
-        */
-       __critical while (!ao_radio_dma_done && !ao_radio_abort)
-                          if (ao_sleep(&ao_radio_dma_done))
-                                  break;
-
-       /* If recv was aborted, clean up by stopping the DMA engine
-        * and idling the radio
-        */
-       if (!ao_radio_dma_done) {
-               ao_dma_abort(ao_radio_dma);
-               ao_radio_idle();
-       }
-       ao_radio_put();
-       return ao_radio_dma_done;
-}
-
-/*
- * Wake up a task waiting to receive a radio packet
- * and tell them to abort the transfer
- */
-
-void
-ao_radio_recv_abort(void)
-{
-       ao_radio_abort = 1;
-       ao_wakeup(&ao_radio_dma_done);
-}
-
-__xdata ao_radio_rdf_value = 0x55;
-
-void
-ao_radio_rdf(int ms)
-{
-       uint8_t i;
-       uint8_t pkt_len;
-
-       /*
-        * Compute the packet length as follows:
-        *
-        * 2000 bps (for a 1kHz tone)
-        * so, for 'ms' milliseconds, we need
-        * 2 * ms bits, or ms / 4 bytes
-        */
-       if (ms > (255 * 4))
-               ms = 255 * 4;
-       pkt_len = ms >> 2;
-
-       ao_radio_abort = 0;
-       ao_radio_get(pkt_len);
-       ao_radio_done = 0;
-       for (i = 0; i < sizeof (rdf_setup); i += 2)
-               RF[rdf_setup[i]] = rdf_setup[i+1];
-
-       ao_dma_set_transfer(ao_radio_dma,
-                           &ao_radio_rdf_value,
-                           &RFDXADDR,
-                           pkt_len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_RADIO,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_HIGH);
-       ao_dma_start(ao_radio_dma);
-       RFST = RFST_STX;
-       __critical while (!ao_radio_done && !ao_radio_abort)
-                          ao_sleep(&ao_radio_done);
-       if (!ao_radio_done) {
-               ao_dma_abort(ao_radio_dma);
-               ao_radio_idle();
-       }
-       ao_radio_set_packet();
-       ao_radio_put();
-}
-
-void
-ao_radio_rdf_abort(void)
-{
-       ao_radio_abort = 1;
-       ao_wakeup(&ao_radio_done);
-}
-
-
-/* Output carrier */
-void
-ao_radio_test(void)
-{
-       uint8_t mode = 2;
-       static __xdata radio_on;
-       ao_cmd_white();
-       if (ao_cmd_lex_c != '\n') {
-               ao_cmd_decimal();
-               mode = (uint8_t) ao_cmd_lex_u32;
-       }
-       mode++;
-       if ((mode & 2) && !radio_on) {
-#if HAS_MONITOR
-               ao_set_monitor(0);
-#endif
-#if PACKET_HAS_SLAVE
-               ao_packet_slave_stop();
-#endif
-               ao_radio_get(0xff);
-               RFST = RFST_STX;
-               radio_on = 1;
-       }
-       if (mode == 3) {
-               printf ("Hit a character to stop..."); flush();
-               getchar();
-               putchar('\n');
-       }
-       if ((mode & 1) && radio_on) {
-               ao_radio_idle();
-               ao_radio_put();
-               radio_on = 0;
-       }
-}
-
-__code struct ao_cmds ao_radio_cmds[] = {
-       { ao_radio_test,        "C <1 start, 0 stop, none both>\0Radio carrier test" },
-       { 0,    NULL },
-};
-
-void
-ao_radio_init(void)
-{
-       uint8_t i;
-       for (i = 0; i < sizeof (radio_setup); i += 2)
-               RF[radio_setup[i]] = radio_setup[i+1];
-       ao_radio_set_packet();
-       ao_radio_dma_done = 1;
-       ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done);
-       RFIF = 0;
-       RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE;
-       IEN2 |= IEN2_RFIE;
-       ao_cmd_register(&ao_radio_cmds[0]);
-}
diff --git a/src/ao_reboot.c b/src/ao_reboot.c
deleted file mode 100644 (file)
index 8c47b89..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Use the watchdog timer to force a complete reboot
- */
-void
-ao_reboot(void)
-{
-       WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768;
-       ao_delay(AO_SEC_TO_TICKS(2));
-       ao_panic(AO_PANIC_REBOOT);
-}
diff --git a/src/ao_report.c b/src/ao_report.c
deleted file mode 100644 (file)
index 3cf558e..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#define BIT(i,x)          ((x) ? (1 << (i)) : 0)
-#define MORSE1(a)          (1 | BIT(3,a))
-#define MORSE2(a,b)        (2 | BIT(3,a) | BIT(4,b))
-#define MORSE3(a,b,c)      (3 | BIT(3,a) | BIT(4,b) | BIT(5,c))
-#define MORSE4(a,b,c,d)    (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d))
-#define MORSE5(a,b,c,d,e)  (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e))
-
-static const uint8_t flight_reports[] = {
-       MORSE3(0,0,0),          /* startup, 'S' */
-       MORSE2(0,0),            /* idle 'I' */
-       MORSE4(0,1,1,0),        /* pad 'P' */
-       MORSE4(1,0,0,0),        /* boost 'B' */
-       MORSE4(0,0,1,0),        /* fast 'F' */
-       MORSE4(1,0,1,0),        /* coast 'C' */
-       MORSE3(1,0,0),          /* drogue 'D' */
-       MORSE2(1,1),            /* main 'M' */
-       MORSE4(0,1,0,0),        /* landed 'L' */
-       MORSE4(1,0,0,1),        /* invalid 'X' */
-};
-
-#if HAS_BEEP
-#define low(time)      ao_beep_for(AO_BEEP_LOW, time)
-#define mid(time)      ao_beep_for(AO_BEEP_MID, time)
-#define high(time)     ao_beep_for(AO_BEEP_HIGH, time)
-#else
-#define low(time)      ao_led_for(AO_LED_GREEN, time)
-#define mid(time)      ao_led_for(AO_LED_RED, time)
-#define high(time)     ao_led_for(AO_LED_GREEN|AO_LED_RED, time)
-#endif
-#define pause(time)    ao_delay(time)
-
-static __pdata enum ao_flight_state ao_report_state;
-
-static void
-ao_report_beep(void) __reentrant
-{
-       uint8_t r = flight_reports[ao_flight_state];
-       uint8_t l = r & 7;
-
-       if (!r)
-               return;
-       while (l--) {
-               if (r & 8)
-                       mid(AO_MS_TO_TICKS(600));
-               else
-                       mid(AO_MS_TO_TICKS(200));
-               pause(AO_MS_TO_TICKS(200));
-               r >>= 1;
-       }
-       pause(AO_MS_TO_TICKS(400));
-}
-
-static void
-ao_report_digit(uint8_t digit) __reentrant
-{
-       if (!digit) {
-               mid(AO_MS_TO_TICKS(500));
-               pause(AO_MS_TO_TICKS(200));
-       } else {
-               while (digit--) {
-                       mid(AO_MS_TO_TICKS(200));
-                       pause(AO_MS_TO_TICKS(200));
-               }
-       }
-       pause(AO_MS_TO_TICKS(300));
-}
-
-static void
-ao_report_altitude(void)
-{
-       __pdata int16_t agl = ao_max_height;
-       __xdata uint8_t digits[10];
-       __pdata uint8_t ndigits, i;
-
-       if (agl < 0)
-               agl = 0;
-       ndigits = 0;
-       do {
-               digits[ndigits++] = agl % 10;
-               agl /= 10;
-       } while (agl);
-
-       for (;;) {
-               ao_report_beep();
-               i = ndigits;
-               do
-                       ao_report_digit(digits[--i]);
-               while (i != 0);
-               pause(AO_SEC_TO_TICKS(5));
-       }
-}
-
-#if HAS_IGNITE
-static uint8_t
-ao_report_igniter_ready(enum ao_igniter igniter)
-{
-       return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0;
-}
-
-static void
-ao_report_continuity(void) __reentrant
-{
-       uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) |
-                    (ao_report_igniter_ready(ao_igniter_main) << 1));
-       if (c) {
-               while (c--) {
-                       high(AO_MS_TO_TICKS(25));
-                       pause(AO_MS_TO_TICKS(100));
-               }
-       } else {
-               c = 10;
-               while (c--) {
-                       high(AO_MS_TO_TICKS(20));
-                       low(AO_MS_TO_TICKS(20));
-               }
-       }
-       if (ao_log_full()) {
-               pause(AO_MS_TO_TICKS(100));
-               c = 2;
-               while (c--) {
-                       low(AO_MS_TO_TICKS(100));
-                       mid(AO_MS_TO_TICKS(100));
-                       high(AO_MS_TO_TICKS(100));
-                       mid(AO_MS_TO_TICKS(100));
-               }
-       }
-       c = 50;
-       while (c-- && ao_flight_state == ao_flight_pad)
-               pause(AO_MS_TO_TICKS(100));
-}
-#endif
-
-void
-ao_report(void)
-{
-       ao_report_state = ao_flight_state;
-       for(;;) {
-               if (ao_flight_state == ao_flight_landed)
-                       ao_report_altitude();
-               ao_report_beep();
-#if HAS_IGNITE
-               if (ao_flight_state == ao_flight_idle)
-                       ao_report_continuity();
-               while (ao_flight_state == ao_flight_pad)
-                       ao_report_continuity();
-#endif
-               __critical {
-                       while (ao_report_state == ao_flight_state)
-                               ao_sleep(DATA_TO_XDATA(&ao_flight_state));
-                       ao_report_state = ao_flight_state;
-               }
-       }
-}
-
-static __xdata struct ao_task ao_report_task;
-
-void
-ao_report_init(void)
-{
-       ao_add_task(&ao_report_task, ao_report, "report");
-}
diff --git a/src/ao_romconfig.c b/src/ao_romconfig.c
deleted file mode 100644 (file)
index f3fe61b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__code __at (0x00a0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION;
-__code __at (0x00a2) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION;
-__code __at (0x00a4) uint16_t ao_serial_number = 0;
-/*
- * For 434.550MHz, the frequency value is:
- *
- * 434.550e6 / (24e6 / 2**16) = 1186611.2
- *
- * This value is stored in a const variable so that
- * ao-load can change it during programming for
- * devices that have no eeprom for config data.
- */
-__code __at (0x00a6) uint32_t ao_radio_cal = 1186611;
diff --git a/src/ao_rssi.c b/src/ao_rssi.c
deleted file mode 100644 (file)
index e3964d2..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static __xdata volatile uint16_t       ao_rssi_time;
-static __pdata volatile uint16_t       ao_rssi_delay;
-static __pdata uint8_t                 ao_rssi_led;
-
-void
-ao_rssi(void)
-{
-       for (;;) {
-               while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3))
-                       ao_sleep(&ao_rssi_time);
-               ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100));
-               ao_delay(ao_rssi_delay);
-       }
-}
-
-void
-ao_rssi_set(int rssi_value)
-{
-       if (rssi_value > 0)
-               rssi_value = 0;
-       ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5);
-       ao_rssi_time = ao_time();
-       ao_wakeup(&ao_rssi_time);
-}
-
-__xdata struct ao_task ao_rssi_task;
-
-void
-ao_rssi_init(uint8_t rssi_led)
-{
-       ao_rssi_led = rssi_led;
-       ao_rssi_delay = 0;
-       ao_add_task(&ao_rssi_task, ao_rssi, "rssi");
-}
diff --git a/src/ao_sample.c b/src/ao_sample.c
deleted file mode 100644 (file)
index b2b8e9f..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef AO_FLIGHT_TEST
-#include "ao.h"
-#endif
-
-/*
- * Current sensor values
- */
-
-__pdata uint16_t       ao_sample_tick;         /* time of last data */
-__pdata int16_t                ao_sample_pres;
-__pdata int16_t                ao_sample_alt;
-__pdata int16_t                ao_sample_height;
-#if HAS_ACCEL
-__pdata int16_t                ao_sample_accel;
-#endif
-
-__data uint8_t         ao_sample_adc;
-
-/*
- * Sensor calibration values
- */
-
-__pdata int16_t                ao_ground_pres;         /* startup pressure */
-__pdata int16_t                ao_ground_height;       /* MSL of ao_ground_pres */
-
-#if HAS_ACCEL
-__pdata int16_t                ao_ground_accel;        /* startup acceleration */
-__pdata int16_t                ao_accel_2g;            /* factory accel calibration */
-__pdata int32_t                ao_accel_scale;         /* sensor to m/s² conversion */
-#endif
-
-static __pdata uint8_t ao_preflight;           /* in preflight mode */
-
-static __pdata uint16_t        nsamples;
-__pdata int32_t ao_sample_pres_sum;
-#if HAS_ACCEL
-__pdata int32_t ao_sample_accel_sum;
-#endif
-
-static void
-ao_sample_preflight(void)
-{
-       /* startup state:
-        *
-        * Collect 512 samples of acceleration and pressure
-        * data and average them to find the resting values
-        */
-       if (nsamples < 512) {
-#if HAS_ACCEL
-               ao_sample_accel_sum += ao_sample_accel;
-#endif
-               ao_sample_pres_sum += ao_sample_pres;
-               ++nsamples;
-       } else {
-               ao_config_get();
-#if HAS_ACCEL
-               ao_ground_accel = ao_sample_accel_sum >> 9;
-               ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g;
-               ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g;
-#endif
-               ao_ground_pres = ao_sample_pres_sum >> 9;
-               ao_ground_height = ao_pres_to_altitude(ao_ground_pres);
-               ao_preflight = FALSE;
-       }
-}
-
-uint8_t
-ao_sample(void)
-{
-       ao_wakeup(DATA_TO_XDATA(&ao_sample_adc));
-       ao_sleep(DATA_TO_XDATA(&ao_adc_head));
-       while (ao_sample_adc != ao_adc_head) {
-               __xdata struct ao_adc *ao_adc;
-
-               /* Capture a sample */
-               ao_adc = &ao_adc_ring[ao_sample_adc];
-               ao_sample_tick = ao_adc->tick;
-               ao_sample_pres = ao_adc->pres;
-               ao_sample_alt = ao_pres_to_altitude(ao_sample_pres);
-               ao_sample_height = ao_sample_alt - ao_ground_height;
-#if HAS_ACCEL
-               ao_sample_accel = ao_adc->accel;
-#if HAS_ACCEL_REF
-               /*
-                * Ok, the math here is a bit tricky.
-                *
-                * ao_sample_accel:  ADC output for acceleration
-                * ao_accel_ref:  ADC output for the 5V reference.
-                * ao_cook_accel: Corrected acceleration value
-                * Vcc:           3.3V supply to the CC1111
-                * Vac:           5V supply to the accelerometer
-                * accel:         input voltage to accelerometer ADC pin
-                * ref:           input voltage to 5V reference ADC pin
-                *
-                *
-                * Measured acceleration is ratiometric to Vcc:
-                *
-                *     ao_sample_accel   accel
-                *     ------------ = -----
-                *        32767        Vcc
-                *
-                * Measured 5v reference is also ratiometric to Vcc:
-                *
-                *     ao_accel_ref    ref
-                *     ------------ = -----
-                *        32767        Vcc
-                *
-                *
-                *      ao_accel_ref = 32767 * (ref / Vcc)
-                *
-                * Acceleration is measured ratiometric to the 5V supply,
-                * so what we want is:
-                *
-                *      ao_cook_accel    accel
-                *      ------------- =  -----
-                *          32767         ref
-                *
-                *
-                *                      accel    Vcc
-                *                    = ----- *  ---
-                *                       Vcc     ref
-                *
-                *                      ao_sample_accel       32767
-                *                    = ------------ *  ------------
-                *                         32767        ao_accel_ref
-                *
-                * Multiply through by 32767:
-                *
-                *                      ao_sample_accel * 32767
-                *      ao_cook_accel = --------------------
-                *                          ao_accel_ref
-                *
-                * Now, the tricky part. Getting this to compile efficiently
-                * and keeping all of the values in-range.
-                *
-                * First off, we need to use a shift of 16 instead of * 32767 as SDCC
-                * does the obvious optimizations for byte-granularity shifts:
-                *
-                *      ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref
-                *
-                * Next, lets check our input ranges:
-                *
-                *      0 <= ao_sample_accel <= 0x7fff          (singled ended ADC conversion)
-                *      0x7000 <= ao_accel_ref <= 0x7fff        (the 5V ref value is close to 0x7fff)
-                *
-                * Plugging in our input ranges, we get an output range of 0 - 0x12490,
-                * which is 17 bits. That won't work. If we take the accel ref and shift
-                * by a bit, we'll change its range:
-                *
-                *      0xe000 <= ao_accel_ref<<1 <= 0xfffe
-                *
-                *      ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1)
-                *
-                * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It
-                * is, however, one bit too large for our signed computations. So, we
-                * take the result and shift that by a bit:
-                *
-                *      ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1
-                *
-                * This finally creates an output range of 0 - 0x4924. As the ADC only
-                * provides 11 bits of data, we haven't actually lost any precision,
-                * just dropped a bit of noise off the low end.
-                */
-               ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1;
-               if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
-                       ao_sample_accel = 0x7fff - ao_sample_accel;
-               ao_adc->accel = ao_sample_accel;
-#endif
-#endif
-
-               if (ao_preflight)
-                       ao_sample_preflight();
-               else
-                       ao_kalman();
-               ao_sample_adc = ao_adc_ring_next(ao_sample_adc);
-       }
-       return !ao_preflight;
-}
-
-void
-ao_sample_init(void)
-{
-       nsamples = 0;
-       ao_sample_pres_sum = 0;
-       ao_sample_pres = 0;
-#if HAS_ACCEL
-       ao_sample_accel_sum = 0;
-       ao_sample_accel = 0;
-#endif
-       ao_sample_adc = ao_adc_head;
-       ao_preflight = TRUE;
-}
diff --git a/src/ao_serial.c b/src/ao_serial.c
deleted file mode 100644 (file)
index 82370c6..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-volatile __xdata struct ao_fifo        ao_usart1_rx_fifo;
-volatile __xdata struct ao_fifo        ao_usart1_tx_fifo;
-
-void
-ao_serial_rx1_isr(void) __interrupt 3
-{
-       if (!ao_fifo_full(ao_usart1_rx_fifo))
-               ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF);
-       ao_wakeup(&ao_usart1_rx_fifo);
-#if USE_SERIAL_STDIN
-       ao_wakeup(&ao_stdin_ready);
-#endif
-}
-
-static __xdata uint8_t ao_serial_tx1_started;
-
-static void
-ao_serial_tx1_start(void)
-{
-       if (!ao_fifo_empty(ao_usart1_tx_fifo) &&
-           !ao_serial_tx1_started)
-       {
-               ao_serial_tx1_started = 1;
-               ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF);
-       }
-}
-
-void
-ao_serial_tx1_isr(void) __interrupt 14
-{
-       UTX1IF = 0;
-       ao_serial_tx1_started = 0;
-       ao_serial_tx1_start();
-       ao_wakeup(&ao_usart1_tx_fifo);
-}
-
-char
-ao_serial_getchar(void) __critical
-{
-       char    c;
-       while (ao_fifo_empty(ao_usart1_rx_fifo))
-               ao_sleep(&ao_usart1_rx_fifo);
-       ao_fifo_remove(ao_usart1_rx_fifo, c);
-       return c;
-}
-
-#if USE_SERIAL_STDIN
-char
-ao_serial_pollchar(void) __critical
-{
-       char    c;
-       if (ao_fifo_empty(ao_usart1_rx_fifo))
-               return AO_READ_AGAIN;
-       ao_fifo_remove(ao_usart1_rx_fifo,c);
-       return c;
-}
-#endif
-
-void
-ao_serial_putchar(char c) __critical
-{
-       while (ao_fifo_full(ao_usart1_tx_fifo))
-               ao_sleep(&ao_usart1_tx_fifo);
-       ao_fifo_insert(ao_usart1_tx_fifo, c);
-       ao_serial_tx1_start();
-}
-
-void
-ao_serial_drain(void) __critical
-{
-       while (!ao_fifo_empty(ao_usart1_tx_fifo))
-               ao_sleep(&ao_usart1_tx_fifo);
-}
-
-static __code struct {
-       uint8_t baud;
-       uint8_t gcr;
-} ao_serial_speeds[] = {
-       /* [AO_SERIAL_SPEED_4800] = */ {
-               /* .baud = */ 163,
-               /* .gcr  = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-       /* [AO_SERIAL_SPEED_9600] = */ {
-               /* .baud = */ 163,
-               /* .gcr  = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-       /* [AO_SERIAL_SPEED_19200] = */ {
-               /* .baud = */ 163,
-               /* .gcr  = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-       /* [AO_SERIAL_SPEED_57600] = */ {
-               /* .baud = */ 59,
-               /* .gcr =  */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-};
-
-void
-ao_serial_set_speed(uint8_t speed)
-{
-       ao_serial_drain();
-       if (speed > AO_SERIAL_SPEED_57600)
-               return;
-       U1UCR |= UxUCR_FLUSH;
-       U1BAUD = ao_serial_speeds[speed].baud;
-       U1GCR = ao_serial_speeds[speed].gcr;
-}
-
-void
-ao_serial_init(void)
-{
-#if HAS_SERIAL_1_ALT_1
-       /* Set up the USART pin assignment */
-       PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1;
-
-       P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0;
-
-       /* Make the USART pins be controlled by the USART */
-       P0SEL |= (1 << 5) | (1 << 4);
-#if HAS_SERIAL_1_HW_FLOW
-       P0SEL |= (1 << 3) | (1 << 2);
-#endif
-#else
-       /* Set up the USART pin assignment */
-       PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
-
-       P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) |
-               (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1);
-
-       /* Make the USART pins be controlled by the USART */
-       P1SEL |= (1 << 6) | (1 << 7);
-       P1SEL |= (1 << 5) | (1 << 4);
-#endif
-
-       /* UART mode with receiver enabled */
-       U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
-
-       /* Pick a 4800 baud rate */
-       ao_serial_set_speed(AO_SERIAL_SPEED_4800);
-
-       /* Reasonable serial parameters */
-       U1UCR = (UxUCR_FLUSH |
-#if HAS_SERIAL_1_HW_FLOW
-                UxUCR_FLOW_ENABLE |
-#else
-                UxUCR_FLOW_DISABLE |
-#endif
-                UxUCR_D9_EVEN_PARITY |
-                UxUCR_BIT9_8_BITS |
-                UxUCR_PARITY_DISABLE |
-                UxUCR_SPB_1_STOP_BIT |
-                UxUCR_STOP_HIGH |
-                UxUCR_START_LOW);
-
-       IEN0 |= IEN0_URX1IE;
-       IEN2 |= IEN2_UTX1IE;
-}
diff --git a/src/ao_spi.c b/src/ao_spi.c
deleted file mode 100644 (file)
index fbe613c..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/* Shared mutex to protect SPI bus, must cover the entire
- * operation, from CS low to CS high. This means that any SPI
- * user must protect the SPI bus with this mutex
- */
-__xdata uint8_t        ao_spi_mutex;
-__xdata uint8_t ao_spi_dma_in_done;
-__xdata uint8_t ao_spi_dma_out_done;
-
-uint8_t        ao_spi_dma_out_id;
-uint8_t ao_spi_dma_in_id;
-
-static __xdata uint8_t ao_spi_const = 0xff;
-
-/* Send bytes over SPI.
- *
- * This sets up two DMA engines, one writing the data and another reading
- * bytes coming back.  We use the bytes coming back to tell when the transfer
- * is complete, as the transmit register is double buffered and hence signals
- * completion one byte before the transfer is actually complete
- */
-void
-ao_spi_send(void __xdata *block, uint16_t len) __reentrant
-{
-       ao_dma_set_transfer(ao_spi_dma_in_id,
-                           &U0DBUFXADDR,
-                           &ao_spi_const,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_set_transfer(ao_spi_dma_out_id,
-                           block,
-                           &U0DBUFXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
-                           DMA_CFG1_SRCINC_1 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_start(ao_spi_dma_in_id);
-       ao_dma_start(ao_spi_dma_out_id);
-       ao_dma_trigger(ao_spi_dma_out_id);
-       __critical while (!ao_spi_dma_in_done)
-               ao_sleep(&ao_spi_dma_in_done);
-}
-
-/* Receive bytes over SPI.
- *
- * This sets up tow DMA engines, one reading the data and another
- * writing constant values to the SPI transmitter as that is what
- * clocks the data coming in.
- */
-void
-ao_spi_recv(void __xdata *block, uint16_t len) __reentrant
-{
-       ao_dma_set_transfer(ao_spi_dma_in_id,
-                           &U0DBUFXADDR,
-                           block,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_1 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_set_transfer(ao_spi_dma_out_id,
-                           &ao_spi_const,
-                           &U0DBUFXADDR,
-                           len,
-                           DMA_CFG0_WORDSIZE_8 |
-                           DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
-                           DMA_CFG1_SRCINC_0 |
-                           DMA_CFG1_DESTINC_0 |
-                           DMA_CFG1_PRIORITY_NORMAL);
-
-       ao_dma_start(ao_spi_dma_in_id);
-       ao_dma_start(ao_spi_dma_out_id);
-       ao_dma_trigger(ao_spi_dma_out_id);
-       __critical while (!ao_spi_dma_in_done)
-               ao_sleep(&ao_spi_dma_in_done);
-}
-
-/*
- * Initialize USART0 for SPI using config alt 2
- *
- *     MO      P1_5
- *     MI      P1_4
- *     CLK     P1_3
- *
- * Chip select is the responsibility of the caller
- */
-
-void
-ao_spi_init(void)
-{
-       /* Set up the USART pin assignment */
-       PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
-
-       /* Ensure that USART0 takes precidence over USART1 for pins that
-        * they share
-        */
-       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0;
-
-       /* Make the SPI pins be controlled by the USART peripheral */
-       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
-
-       /* Set up OUT DMA */
-       ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done);
-
-       /* Set up IN DMA */
-       ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done);
-
-       /* Set up the USART.
-        *
-        * SPI master mode
-        */
-       U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER);
-
-       /* Set the baud rate and signal parameters
-        *
-        * The cc1111 is limited to a 24/8 MHz SPI clock.
-        * Every peripheral I've ever seen goes faster than that,
-        * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0)
-        */
-       U0BAUD = 0;
-       U0GCR = (UxGCR_CPOL_NEGATIVE |
-                UxGCR_CPHA_FIRST_EDGE |
-                UxGCR_ORDER_MSB |
-                (17 << UxGCR_BAUD_E_SHIFT));
-}
diff --git a/src/ao_state.c b/src/ao_state.c
deleted file mode 100644 (file)
index ed197aa..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-const char const * const ao_state_names[] = {
-       "startup", "idle", "pad", "boost", "fast",
-       "coast", "drogue", "main", "landed", "invalid"
-};
diff --git a/src/ao_stdio.c b/src/ao_stdio.c
deleted file mode 100644 (file)
index c0138a3..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-/*
- * Basic I/O functions to support SDCC stdio package
- */
-
-#define AO_NUM_STDIOS  (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN)
-
-__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS];
-__pdata int8_t ao_cur_stdio;
-__pdata int8_t ao_num_stdios;
-
-void
-putchar(char c)
-{
-       if (c == '\n')
-               (*ao_stdios[ao_cur_stdio].putchar)('\r');
-       (*ao_stdios[ao_cur_stdio].putchar)(c);
-}
-
-void
-flush(void)
-{
-       if (ao_stdios[ao_cur_stdio].flush)
-               ao_stdios[ao_cur_stdio].flush();
-}
-
-__xdata uint8_t ao_stdin_ready;
-
-char
-getchar(void) __reentrant __critical
-{
-       char c;
-       int8_t stdio = ao_cur_stdio;
-
-       for (;;) {
-               c = ao_stdios[stdio].pollchar();
-               if (c != AO_READ_AGAIN)
-                       break;
-               if (++stdio == ao_num_stdios)
-                       stdio = 0;
-               if (stdio == ao_cur_stdio)
-                       ao_sleep(&ao_stdin_ready);
-       }
-       ao_cur_stdio = stdio;
-       return c;
-}
-
-uint8_t
-ao_echo(void)
-{
-       return ao_stdios[ao_cur_stdio].echo;
-}
-
-int8_t
-ao_add_stdio(char (*pollchar)(void),
-            void (*putchar)(char),
-            void (*flush)(void)) __reentrant
-{
-       if (ao_num_stdios == AO_NUM_STDIOS)
-               ao_panic(AO_PANIC_STDIO);
-       ao_stdios[ao_num_stdios].pollchar = pollchar;
-       ao_stdios[ao_num_stdios].putchar = putchar;
-       ao_stdios[ao_num_stdios].flush = flush;
-       ao_stdios[ao_num_stdios].echo = 1;
-       return ao_num_stdios++;
-}
diff --git a/src/ao_storage.c b/src/ao_storage.c
deleted file mode 100644 (file)
index 6ffca0e..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-uint8_t
-ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
-       uint16_t this_len;
-       uint16_t this_off;
-
-       ao_storage_setup();
-       if (pos >= ao_storage_total || pos + len > ao_storage_total)
-               return 0;
-       while (len) {
-
-               /* Compute portion of transfer within
-                * a single block
-                */
-               this_off = (uint16_t) pos & (ao_storage_unit - 1);
-               this_len = ao_storage_unit - this_off;
-               if (this_len > len)
-                       this_len = len;
-
-               if (!ao_storage_device_read(pos, buf, this_len))
-                       return 0;
-
-               /* See how much is left */
-               buf += this_len;
-               len -= this_len;
-               pos += this_len;
-       }
-       return 1;
-}
-
-uint8_t
-ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
-{
-       uint16_t this_len;
-       uint16_t this_off;
-
-       ao_storage_setup();
-       if (pos >= ao_storage_total || pos + len > ao_storage_total)
-               return 0;
-       while (len) {
-
-               /* Compute portion of transfer within
-                * a single block
-                */
-               this_off = (uint16_t) pos & (ao_storage_unit - 1);
-               this_len = ao_storage_unit - this_off;
-               if (this_len > len)
-                       this_len = len;
-
-               if (!ao_storage_device_write(pos, buf, this_len))
-                       return 0;
-
-               /* See how much is left */
-               buf += this_len;
-               len -= this_len;
-               pos += this_len;
-       }
-       return 1;
-}
-
-static __xdata uint8_t storage_data[8];
-
-static void
-ao_storage_dump(void) __reentrant
-{
-       uint8_t i, j;
-
-       ao_cmd_hex();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       for (i = 0; ; i += 8) {
-               if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i,
-                                 storage_data,
-                                 8)) {
-                       ao_cmd_put16((uint16_t) i);
-                       for (j = 0; j < 8; j++) {
-                               putchar(' ');
-                               ao_cmd_put8(storage_data[j]);
-                       }
-                       putchar ('\n');
-               }
-               if (i == 248)
-                       break;
-       }
-}
-
-#if 0
-
-/* not enough space for this today
- */
-static void
-ao_storage_store(void) __reentrant
-{
-       uint16_t block;
-       uint8_t i;
-       uint16_t len;
-       static __xdata uint8_t b;
-       uint32_t addr;
-
-       ao_cmd_hex();
-       block = ao_cmd_lex_i;
-       ao_cmd_hex();
-       i = ao_cmd_lex_i;
-       addr = ((uint32_t) block << 8) | i;
-       ao_cmd_hex();
-       len = ao_cmd_lex_i;
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       while (len--) {
-               ao_cmd_hex();
-               if (ao_cmd_status != ao_cmd_success)
-                       return;
-               b = ao_cmd_lex_i;
-               ao_storage_write(addr, &b, 1);
-               addr++;
-       }
-}
-#endif
-
-void
-ao_storage_zap(void) __reentrant
-{
-       ao_cmd_hex();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       ao_storage_erase((uint32_t) ao_cmd_lex_i << 8);
-}
-
-void
-ao_storage_zapall(void) __reentrant
-{
-       uint32_t        pos;
-
-       ao_cmd_white();
-       if (!ao_match_word("DoIt"))
-               return;
-       for (pos = 0; pos < ao_storage_config; pos += ao_storage_block)
-               ao_storage_erase(pos);
-}
-
-void
-ao_storage_info(void) __reentrant
-{
-       printf("Storage size: %ld\n", ao_storage_total);
-       printf("Storage erase unit: %ld\n", ao_storage_block);
-       ao_storage_device_info();
-}
-
-__code struct ao_cmds ao_storage_cmds[] = {
-       { ao_storage_info, "f\0Show storage" },
-       { ao_storage_dump, "e <block>\0Dump flash" },
-#ifdef HAS_STORAGE_DBG
-       { ao_storage_store, "w <block> <start> <len> <data> ...\0Write data to flash" },
-#endif
-       { ao_storage_zap, "z <block>\0Erase <block>" },
-       { ao_storage_zapall,"Z <key>\0Erase all. <key> is doit with D&I" },
-       { 0, NULL },
-};
-
-void
-ao_storage_init(void)
-{
-       ao_storage_device_init();
-       ao_cmd_register(&ao_storage_cmds[0]);
-}
diff --git a/src/ao_task.c b/src/ao_task.c
deleted file mode 100644 (file)
index f5850fa..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-#define AO_NO_TASK_INDEX       0xff
-
-__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS];
-__data uint8_t ao_num_tasks;
-__data uint8_t ao_cur_task_index;
-__xdata struct ao_task *__data ao_cur_task;
-
-void
-ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant
-{
-       uint8_t __xdata *stack;
-       uint8_t task_id;
-       uint8_t t;
-       if (ao_num_tasks == AO_NUM_TASKS)
-               ao_panic(AO_PANIC_NO_TASK);
-       for (task_id = 1; task_id != 0; task_id++) {
-               for (t = 0; t < ao_num_tasks; t++)
-                       if (ao_tasks[t]->task_id == task_id)
-                               break;
-               if (t == ao_num_tasks)
-                       break;
-       }
-       ao_tasks[ao_num_tasks++] = task;
-       task->task_id = task_id;
-       task->name = name;
-       /*
-        * Construct a stack frame so that it will 'return'
-        * to the start of the task
-        */
-       stack = task->stack;
-
-       *stack++ = ((uint16_t) start);          /* 0 */
-       *stack++ = ((uint16_t) start) >> 8;     /* 1 */
-
-       /* and the stuff saved by ao_switch */
-       *stack++ = 0;                           /* 2 acc */  
-       *stack++ = 0x80;                        /* 3 IE */
-
-       /*  4 DPL
-        *  5 DPH
-        *  6 B
-        *  7 R2
-        *  8 R3
-        *  9 R4
-        * 10 R5
-        * 11 R6
-        * 12 R7
-        * 13 R0
-        * 14 R1
-        * 15 PSW
-        * 16 BP
-        */
-       for (t = 0; t < 13; t++)
-               *stack++ = 0;
-
-       task->stack_count = 17;
-       task->wchan = NULL;
-}
-
-/* Task switching function. This must not use any stack variables */
-void
-ao_yield(void) __naked
-{
-
-       /* Save current context */
-       _asm
-               /* Push ACC first, as when restoring the context it must be restored
-                * last (it is used to set the IE register). */
-               push    ACC
-               /* Store the IE register then enable interrupts. */
-               push    _IEN0
-               setb    _EA
-               push    DPL
-               push    DPH
-               push    b
-               push    ar2
-               push    ar3
-               push    ar4
-               push    ar5
-               push    ar6
-               push    ar7
-               push    ar0
-               push    ar1
-               push    PSW
-       _endasm;
-       PSW = 0;
-       _asm
-               push    _bp
-       _endasm;
-
-       if (ao_cur_task_index == AO_NO_TASK_INDEX)
-               ao_cur_task_index = ao_num_tasks-1;
-       else
-       {
-               uint8_t stack_len;
-               __data uint8_t *stack_ptr;
-               __xdata uint8_t *save_ptr;
-               /* Save the current stack */
-               stack_len = SP - (AO_STACK_START - 1);
-               ao_cur_task->stack_count = stack_len;
-               stack_ptr = (uint8_t __data *) AO_STACK_START;
-               save_ptr = (uint8_t __xdata *) ao_cur_task->stack;
-               do
-                       *save_ptr++ = *stack_ptr++;
-               while (--stack_len);
-       }
-
-       /* Empty the stack; might as well let interrupts have the whole thing */
-       SP = AO_STACK_START - 1;
-
-       /* Find a task to run. If there isn't any runnable task,
-        * this loop will run forever, which is just fine
-        */
-       {
-               __pdata uint8_t ao_next_task_index = ao_cur_task_index;
-               for (;;) {
-                       ++ao_next_task_index;
-                       if (ao_next_task_index == ao_num_tasks)
-                               ao_next_task_index = 0;
-
-                       ao_cur_task = ao_tasks[ao_next_task_index];
-                       if (ao_cur_task->wchan == NULL) {
-                               ao_cur_task_index = ao_next_task_index;
-                               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) {
-                               ao_cur_task_index = ao_next_task_index;
-                               break;
-                       }
-
-                       /* Enter lower power mode when there isn't anything to do */
-                       if (ao_next_task_index == ao_cur_task_index)
-                               PCON = PCON_IDLE;
-               }
-       }
-
-       {
-               uint8_t stack_len;
-               __data uint8_t *stack_ptr;
-               __xdata uint8_t *save_ptr;
-
-               /* Restore the old stack */
-               stack_len = ao_cur_task->stack_count;
-               SP = AO_STACK_START - 1 + stack_len;
-
-               stack_ptr = (uint8_t __data *) AO_STACK_START;
-               save_ptr = (uint8_t __xdata *) ao_cur_task->stack;
-               do
-                       *stack_ptr++ = *save_ptr++;
-               while (--stack_len);
-       }
-
-       _asm
-               pop             _bp
-               pop             PSW
-               pop             ar1
-               pop             ar0
-               pop             ar7
-               pop             ar6
-               pop             ar5
-               pop             ar4
-               pop             ar3
-               pop             ar2
-               pop             b
-               pop             DPH
-               pop             DPL
-               /* The next byte of the stack is the IE register.  Only the global
-               enable bit forms part of the task context.  Pop off the IE then set
-               the global enable bit to match that of the stored IE register. */
-               pop             ACC
-               JB              ACC.7,0098$
-               CLR             _EA
-               LJMP    0099$
-       0098$:
-               SETB            _EA
-       0099$:
-               /* Finally pop off the ACC, which was the first register saved. */
-               pop             ACC
-               ret
-       _endasm;
-}
-
-uint8_t
-ao_sleep(__xdata void *wchan)
-{
-       __critical {
-               ao_cur_task->wchan = wchan;
-       }
-       ao_yield();
-       ao_cur_task->alarm = 0;
-       if (ao_cur_task->wchan) {
-               ao_cur_task->wchan = NULL;
-               return 1;
-       }
-       return 0;
-}
-
-void
-ao_wakeup(__xdata void *wchan)
-{
-       uint8_t i;
-
-       for (i = 0; i < ao_num_tasks; i++)
-               if (ao_tasks[i]->wchan == wchan)
-                       ao_tasks[i]->wchan = NULL;
-}
-
-void
-ao_alarm(uint16_t delay)
-{
-       /* 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() + delay + 1))
-               ao_cur_task->alarm = 1;
-}
-
-void
-ao_exit(void) __critical
-{
-       uint8_t i;
-       ao_num_tasks--;
-       for (i = ao_cur_task_index; i < ao_num_tasks; i++)
-               ao_tasks[i] = ao_tasks[i+1];
-       ao_cur_task_index = AO_NO_TASK_INDEX;
-       ao_yield();
-       /* we'll never get back here */
-}
-
-void
-ao_task_info(void)
-{
-       uint8_t i;
-       uint8_t pc_loc;
-       __xdata struct ao_task *task;
-
-       for (i = 0; i < ao_num_tasks; i++) {
-               task = ao_tasks[i];
-               pc_loc = task->stack_count - 17;
-               printf("%12s: wchan %04x pc %04x\n",
-                      task->name,
-                      (int16_t) task->wchan,
-                      (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8));
-       }
-}
-
-void
-ao_start_scheduler(void)
-{
-       ao_cur_task_index = AO_NO_TASK_INDEX;
-       ao_cur_task = NULL;
-       ao_yield();
-}
diff --git a/src/ao_telebt.c b/src/ao_telebt.c
deleted file mode 100644 (file)
index 8556517..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE;     /* until we actually log stuff */
-
-void
-main(void)
-{
-       ao_clock_init();
-
-       /* Turn on the LED until the system is stable */
-       ao_led_init(LEDS_AVAILABLE);
-       ao_led_on(AO_LED_RED);
-       ao_timer_init();
-#if HAS_BEEP
-       ao_beep_init();
-#endif
-       ao_cmd_init();
-#if HAS_EEPROM
-       ao_spi_init();
-       ao_storage_init();
-#endif
-       ao_usb_init();
-       ao_monitor_init(AO_LED_GREEN, TRUE);
-       ao_rssi_init(AO_LED_RED);
-       ao_radio_init();
-       ao_packet_master_init();
-       ao_btm_init();
-#if HAS_DBG
-       ao_dbg_init();
-#endif
-       ao_config_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c
deleted file mode 100644 (file)
index 008b200..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-void
-main(void)
-{
-       ao_clock_init();
-
-       /* Turn on the LED until the system is stable */
-       ao_led_init(LEDS_AVAILABLE);
-       ao_led_on(AO_LED_RED);
-       ao_timer_init();
-       ao_cmd_init();
-       ao_usb_init();
-       ao_monitor_init(AO_LED_GREEN, TRUE);
-       ao_rssi_init(AO_LED_RED);
-       ao_radio_init();
-       ao_packet_master_init();
-#if HAS_DBG
-       ao_dbg_init();
-#endif
-       ao_config_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_telem.h b/src/ao_telem.h
deleted file mode 100644 (file)
index 1a8da29..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_TELEM_H_
-#define _AO_TELEM_H_
-
-#define AO_TELEMETRY_VERSION           4
-
-/*
- * Telemetry version 4 and higher format:
- *
- * General header fields
- *
- *     Name            Value
- *
- *     VERSION         Telemetry version number (4 or more). Must be first.
- *     c               Callsign (string, no spaces allowed)
- *     n               Flight unit serial number (integer)
- *     f               Flight number (integer)
- *     r               Packet RSSI value (integer)
- *     s               Flight computer state (string, no spaces allowed)
- *     t               Flight computer clock (integer in centiseconds)
- */
-
-#define AO_TELEM_VERSION       "VERSION"
-#define AO_TELEM_CALL          "c"
-#define AO_TELEM_SERIAL                "n"
-#define AO_TELEM_FLIGHT                "f"
-#define AO_TELEM_RSSI          "r"
-#define AO_TELEM_STATE         "s"
-#define AO_TELEM_TICK          "t"
-
-/*
- * Raw sensor values
- *
- *     Name            Value
- *     r_a             Accelerometer reading (integer)
- *     r_b             Barometer reading (integer)
- *     r_t             Thermometer reading (integer)
- *     r_v             Battery reading (integer)
- *     r_d             Drogue continuity (integer)
- *     r_m             Main continuity (integer)
- */
-
-#define AO_TELEM_RAW_ACCEL     "r_a"
-#define AO_TELEM_RAW_BARO      "r_b"
-#define AO_TELEM_RAW_THERMO    "r_t"
-#define AO_TELEM_RAW_BATT      "r_v"
-#define AO_TELEM_RAW_DROGUE    "r_d"
-#define AO_TELEM_RAW_MAIN      "r_m"
-
-/*
- * Sensor calibration values
- *
- *     Name            Value
- *     c_a             Ground accelerometer reading (integer)
- *     c_b             Ground barometer reading (integer)
- *     c_p             Accelerometer reading for +1g
- *     c_m             Accelerometer reading for -1g
- */
-
-#define AO_TELEM_CAL_ACCEL_GROUND      "c_a"
-#define AO_TELEM_CAL_BARO_GROUND       "c_b"
-#define AO_TELEM_CAL_ACCEL_PLUS                "c_p"
-#define AO_TELEM_CAL_ACCEL_MINUS       "c_m"
-
-/*
- * Kalman state values
- *
- *     Name            Value
- *     k_h             Height above pad (integer, meters)
- *     k_s             Vertical speeed (integer, m/s * 16)
- *     k_a             Vertical acceleration (integer, m/s² * 16)
- */
-
-#define AO_TELEM_KALMAN_HEIGHT         "k_h"
-#define AO_TELEM_KALMAN_SPEED          "k_s"
-#define AO_TELEM_KALMAN_ACCEL          "k_a"
-
-/*
- * Ad-hoc flight values
- *
- *     Name            Value
- *     a_a             Acceleration (integer, sensor units)
- *     a_s             Speed (integer, integrated acceleration value)
- *     a_b             Barometer reading (integer, sensor units)
- */
-
-#define AO_TELEM_ADHOC_ACCEL           "a_a"
-#define AO_TELEM_ADHOC_SPEED           "a_s"
-#define AO_TELEM_ADHOC_BARO            "a_b"
-
-/*
- * GPS values
- *
- *     Name            Value
- *     g               GPS state (string):
- *                             l       locked
- *                             u       unlocked
- *                             e       error (missing or broken)
- *     g_n             Number of sats used in solution
- *     g_ns            Latitude (degrees * 10e7)
- *     g_ew            Longitude (degrees * 10e7)
- *     g_a             Altitude (integer meters)
- *     g_Y             GPS year (integer)
- *     g_M             GPS month (integer - 1-12)
- *     g_D             GPS day (integer - 1-31)
- *     g_h             GPS hour (integer - 0-23)
- *     g_m             GPS minute (integer - 0-59)
- *     g_s             GPS second (integer - 0-59)
- *     g_v             GPS vertical speed (integer, cm/sec)
- *     g_g             GPS horizontal speed (integer, cm/sec)
- *     g_c             GPS course (integer, 0-359)
- *     g_hd            GPS hdop (integer * 10)
- *     g_vd            GPS vdop (integer * 10)
- *     g_he            GPS h error (integer)
- *     g_ve            GPS v error (integer)
- */
-
-#define AO_TELEM_GPS_STATE             "g"
-#define AO_TELEM_GPS_STATE_LOCKED      'l'
-#define AO_TELEM_GPS_STATE_UNLOCKED    'u'
-#define AO_TELEM_GPS_STATE_ERROR       'e'
-#define AO_TELEM_GPS_NUM_SAT           "g_n"
-#define AO_TELEM_GPS_LATITUDE          "g_ns"
-#define AO_TELEM_GPS_LONGITUDE         "g_ew"
-#define AO_TELEM_GPS_ALTITUDE          "g_a"
-#define AO_TELEM_GPS_YEAR              "g_Y"
-#define AO_TELEM_GPS_MONTH             "g_M"
-#define AO_TELEM_GPS_DAY               "g_D"
-#define AO_TELEM_GPS_HOUR              "g_h"
-#define AO_TELEM_GPS_MINUTE            "g_m"
-#define AO_TELEM_GPS_SECOND            "g_s"
-#define AO_TELEM_GPS_VERTICAL_SPEED    "g_v"
-#define AO_TELEM_GPS_HORIZONTAL_SPEED  "g_g"
-#define AO_TELEM_GPS_COURSE            "g_c"
-#define AO_TELEM_GPS_HDOP              "g_hd"
-#define AO_TELEM_GPS_VDOP              "g_vd"
-#define AO_TELEM_GPS_HERROR            "g_he"
-#define AO_TELEM_GPS_VERROR            "g_ve"
-
-/*
- * GPS satellite values
- *
- *     Name            Value
- *     s_n             Number of satellites reported (integer)
- *     s_v0            Space vehicle ID (integer) for report 0
- *     s_c0            C/N0 number (integer) for report 0
- *     s_v1            Space vehicle ID (integer) for report 1
- *     s_c1            C/N0 number (integer) for report 1
- *     ...
- */
-
-#define AO_TELEM_SAT_NUM               "s_n"
-#define AO_TELEM_SAT_SVID              "s_v"
-#define AO_TELEM_SAT_C_N_0             "s_c"
-
-#endif /* _AO_TELEM_H_ */
diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c
deleted file mode 100644 (file)
index f560740..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_pins.h"
-
-void
-main(void)
-{
-       /*
-        * Reduce the transient on the ignite pins at startup by
-        * pulling the pins low as soon as possible at power up
-        */
-       ao_ignite_set_pins();
-
-       ao_clock_init();
-
-       /* Turn on the red LED until the system is stable */
-       ao_led_init(LEDS_AVAILABLE);
-       ao_led_on(AO_LED_RED);
-
-       /* A hack -- look at the SPI clock pin, if it's sitting at
-        *  ground, then we force the computer to idle mode instead of
-        *  flight mode
-        */
-       if (P1_3 == 0) {
-               ao_flight_force_idle = 1;
-               while (P1_3 == 0)
-                       ;
-       }
-       ao_timer_init();
-       ao_adc_init();
-       ao_beep_init();
-       ao_cmd_init();
-       ao_spi_init();
-       ao_storage_init();
-       ao_flight_init();
-       ao_log_init();
-       ao_report_init();
-       ao_usb_init();
-       ao_serial_init();
-       ao_gps_init();
-       ao_gps_report_init();
-       ao_telemetry_init();
-       ao_radio_init();
-       ao_packet_slave_init(TRUE);
-       ao_igniter_init();
-#if HAS_DBG
-       ao_dbg_init();
-#endif
-#if HAS_COMPANION
-       ao_companion_init();
-#endif
-       ao_config_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c
deleted file mode 100644 (file)
index c7338a5..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_product.h"
-
-static __pdata uint16_t ao_telemetry_interval;
-static __pdata int8_t ao_telemetry_config_max;
-static __pdata int8_t ao_telemetry_config_cur;
-#if HAS_GPS
-static __pdata int8_t ao_telemetry_loc_cur;
-static __pdata int8_t ao_telemetry_sat_cur;
-#endif
-#if HAS_COMPANION
-static __pdata int8_t ao_telemetry_companion_max;
-static __pdata int8_t ao_telemetry_companion_cur;
-#endif
-static __pdata uint8_t ao_rdf = 0;
-static __pdata uint16_t ao_rdf_time;
-
-#define AO_RDF_INTERVAL_TICKS  AO_SEC_TO_TICKS(5)
-#define AO_RDF_LENGTH_MS       500
-
-#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1)
-#define AO_TELEMETRY_SENSOR    AO_TELEMETRY_SENSOR_TELEMETRUM
-#endif
-
-#if defined(TELEMINI_V_1_0)
-#define AO_TELEMETRY_SENSOR    AO_TELEMETRY_SENSOR_TELEMINI
-#endif
-
-#if defined(TELENANO_V_0_1)
-#define AO_TELEMETRY_SENSOR    AO_TELEMETRY_SENSOR_TELENANO
-#endif
-
-static __xdata union ao_telemetry_all  telemetry;
-
-/* Send sensor packet */
-static void
-ao_send_sensor(void)
-{
-       uint8_t         sample;
-       sample = ao_sample_adc;
-                       
-       telemetry.generic.tick = ao_adc_ring[sample].tick;
-       telemetry.generic.type = AO_TELEMETRY_SENSOR;
-
-       telemetry.sensor.state = ao_flight_state;
-#if HAS_ACCEL
-       telemetry.sensor.accel = ao_adc_ring[sample].accel;
-#else
-       telemetry.sensor.accel = 0;
-#endif
-       telemetry.sensor.pres = ao_adc_ring[sample].pres;
-       telemetry.sensor.temp = ao_adc_ring[sample].temp;
-       telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt;
-#if HAS_IGNITE
-       telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d;
-       telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m;
-#else
-       telemetry.sensor.sense_d = 0;
-       telemetry.sensor.sense_m = 0;
-#endif
-
-       telemetry.sensor.acceleration = ao_accel;
-       telemetry.sensor.speed = ao_speed;
-       telemetry.sensor.height = ao_height;
-
-       telemetry.sensor.ground_pres = ao_ground_pres;
-#if HAS_ACCEL
-       telemetry.sensor.ground_accel = ao_ground_accel;
-       telemetry.sensor.accel_plus_g = ao_config.accel_plus_g;
-       telemetry.sensor.accel_minus_g = ao_config.accel_minus_g;
-#else
-       telemetry.sensor.ground_accel = 0;
-       telemetry.sensor.accel_plus_g = 0;
-       telemetry.sensor.accel_minus_g = 0;
-#endif
-
-       ao_radio_send(&telemetry, sizeof (telemetry));
-}
-
-static void
-ao_send_configuration(void)
-{
-       if (--ao_telemetry_config_cur <= 0)
-       {
-               telemetry.generic.type = AO_TELEMETRY_CONFIGURATION;
-               telemetry.configuration.device = AO_idProduct_NUMBER;
-               telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number;
-               telemetry.configuration.config_major = AO_CONFIG_MAJOR;
-               telemetry.configuration.config_minor = AO_CONFIG_MINOR;
-               telemetry.configuration.apogee_delay = ao_config.apogee_delay;
-               telemetry.configuration.main_deploy = ao_config.main_deploy;
-               telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10;
-               memcpy (telemetry.configuration.callsign,
-                       ao_config.callsign,
-                       AO_MAX_CALLSIGN);
-               memcpy (telemetry.configuration.version,
-                       ao_version,
-                       AO_MAX_VERSION);
-               ao_radio_send(&telemetry, sizeof (telemetry));
-               ao_telemetry_config_cur = ao_telemetry_config_max;
-       }
-}
-
-#if HAS_GPS
-static void
-ao_send_location(void)
-{
-       if (--ao_telemetry_loc_cur <= 0)
-       {
-               telemetry.generic.type = AO_TELEMETRY_LOCATION;
-               ao_mutex_get(&ao_gps_mutex);
-               memcpy(&telemetry.location.flags,
-                      &ao_gps_data.flags,
-                      26);
-               ao_mutex_put(&ao_gps_mutex);
-               ao_radio_send(&telemetry, sizeof (telemetry));
-               ao_telemetry_loc_cur = ao_telemetry_config_max;
-       }
-}
-
-static void
-ao_send_satellite(void)
-{
-       if (--ao_telemetry_sat_cur <= 0)
-       {
-               telemetry.generic.type = AO_TELEMETRY_SATELLITE;
-               ao_mutex_get(&ao_gps_mutex);
-               telemetry.satellite.channels = ao_gps_tracking_data.channels;
-               memcpy(&telemetry.satellite.sats,
-                      &ao_gps_tracking_data.sats,
-                      AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info));
-               ao_mutex_put(&ao_gps_mutex);
-               ao_radio_send(&telemetry, sizeof (telemetry));
-               ao_telemetry_sat_cur = ao_telemetry_config_max;
-       }
-}
-#endif
-
-#if HAS_COMPANION
-static void
-ao_send_companion(void)
-{
-       if (--ao_telemetry_companion_cur <= 0) {
-               telemetry.generic.type = AO_TELEMETRY_COMPANION;
-               telemetry.companion.board_id = ao_companion_setup.board_id;
-               telemetry.companion.update_period = ao_companion_setup.update_period;
-               telemetry.companion.channels = ao_companion_setup.channels;
-               ao_mutex_get(&ao_companion_mutex);
-               memcpy(&telemetry.companion.companion_data,
-                      ao_companion_data,
-                      ao_companion_setup.channels * 2);
-               ao_mutex_put(&ao_companion_mutex);
-               ao_radio_send(&telemetry, sizeof (telemetry));
-               ao_telemetry_companion_cur = ao_telemetry_companion_max;
-       }
-}
-#endif
-
-void
-ao_telemetry(void)
-{
-       uint16_t        time;
-       int16_t         delay;
-
-       ao_config_get();
-       if (!ao_config.radio_enable)
-               ao_exit();
-       while (!ao_flight_number)
-               ao_sleep(&ao_flight_number);
-
-       telemetry.generic.serial = ao_serial_number;
-       for (;;) {
-               while (ao_telemetry_interval == 0)
-                       ao_sleep(&telemetry);
-               time = ao_rdf_time = ao_time();
-               while (ao_telemetry_interval) {
-
-
-                       ao_send_sensor();
-#if HAS_COMPANION
-                       if (ao_companion_running)
-                               ao_send_companion();
-#endif
-                       ao_send_configuration();
-#if HAS_GPS
-                       ao_send_location();
-                       ao_send_satellite();
-#endif
-                       if (ao_rdf &&
-                           (int16_t) (ao_time() - ao_rdf_time) >= 0)
-                       {
-                               ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;
-                               ao_radio_rdf(AO_RDF_LENGTH_MS);
-                       }
-                       time += ao_telemetry_interval;
-                       delay = time - ao_time();
-                       if (delay > 0)
-                               ao_delay(delay);
-                       else
-                               time = ao_time();
-               }
-       }
-}
-
-void
-ao_telemetry_set_interval(uint16_t interval)
-{
-       ao_telemetry_interval = interval;
-
-#if HAS_COMPANION
-       if (!ao_companion_setup.update_period)
-               ao_companion_setup.update_period = AO_SEC_TO_TICKS(1);
-       ao_telemetry_companion_max = ao_companion_setup.update_period / interval;
-       ao_telemetry_companion_cur = 1;
-#endif
-
-       ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval;
-#if HAS_COMPANION
-       ao_telemetry_config_cur = ao_telemetry_companion_cur;
-       if (ao_telemetry_config_max > ao_telemetry_config_cur)
-               ao_telemetry_config_cur++;
-#else
-       ao_telemetry_config_cur = 1;
-#endif
-
-#if HAS_GPS
-       ao_telemetry_loc_cur = ao_telemetry_config_cur;
-       if (ao_telemetry_config_max > ao_telemetry_loc_cur)
-               ao_telemetry_loc_cur++;
-       ao_telemetry_sat_cur = ao_telemetry_loc_cur;
-       if (ao_telemetry_config_max > ao_telemetry_sat_cur)
-               ao_telemetry_sat_cur++;
-#endif
-       ao_wakeup(&telemetry);
-}
-
-void
-ao_rdf_set(uint8_t rdf)
-{
-       ao_rdf = rdf;
-       if (rdf == 0)
-               ao_radio_rdf_abort();
-       else
-               ao_rdf_time = ao_time();
-}
-
-__xdata struct ao_task ao_telemetry_task;
-
-void
-ao_telemetry_init()
-{
-       ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry");
-}
diff --git a/src/ao_telemini.c b/src/ao_telemini.c
deleted file mode 100644 (file)
index fa23de0..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_pins.h"
-
-void
-main(void)
-{
-       /*
-        * Reduce the transient on the ignite pins at startup by
-        * pulling the pins low as soon as possible at power up
-        */
-       ao_ignite_set_pins();
-
-       ao_clock_init();
-
-       /* Turn on the red LED until the system is stable */
-       ao_led_init(LEDS_AVAILABLE);
-       ao_led_on(AO_LED_RED);
-
-       ao_timer_init();
-       ao_adc_init();
-       ao_cmd_init();
-       ao_storage_init();
-       ao_flight_init();
-       ao_log_init();
-       ao_report_init();
-       ao_telemetry_init();
-       ao_radio_init();
-       ao_packet_slave_init(TRUE);
-       ao_igniter_init();
-       ao_config_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_telenano.c b/src/ao_telenano.c
deleted file mode 100644 (file)
index d91983d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_pins.h"
-
-void
-main(void)
-{
-       ao_clock_init();
-
-
-       /* Turn on the red LED until the system is stable */
-       ao_led_init(LEDS_AVAILABLE);
-       ao_led_on(AO_LED_RED);
-
-       ao_timer_init();
-       ao_adc_init();
-       ao_cmd_init();
-       ao_storage_init();
-       ao_flight_nano_init();
-       ao_log_init();
-       ao_report_init();
-       ao_telemetry_init();
-       ao_radio_init();
-       ao_packet_slave_init(TRUE);
-       ao_config_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c
deleted file mode 100644 (file)
index d696b91..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define AO_NO_ADC_ISR 1
-#include "ao.h"
-
-void
-main(void)
-{
-       ao_clock_init();
-
-       /* Turn on the red LED until the system is stable */
-       ao_led_init(AO_LED_RED|AO_LED_GREEN);
-       ao_led_on(AO_LED_RED);
-       ao_timer_init();
-       ao_beep_init();
-       ao_cmd_init();
-       ao_usb_init();
-       ao_serial_init();
-       ao_monitor_init(AO_LED_GREEN, TRUE);
-       ao_radio_init();
-       ao_config_init();
-       ao_start_scheduler();
-}
diff --git a/src/ao_test.c b/src/ao_test.c
deleted file mode 100644 (file)
index 14c2eb7..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-struct ao_task __xdata blink_0_task;
-struct ao_task __xdata blink_1_task;
-struct ao_task __xdata wakeup_task;
-struct ao_task __xdata beep_task;
-struct ao_task __xdata echo_task;
-
-void delay(int n) __reentrant
-{
-       uint8_t j = 0;
-       while (--n)
-               while (--j)
-                       ao_yield();
-}
-
-static __xdata uint8_t blink_chan;
-
-void
-blink_0(void)
-{
-       uint8_t b = 0;
-       for (;;) {
-               b = 1 - b;
-               if (b)
-                       ao_led_on(AO_LED_GREEN);
-               else
-                       ao_led_off(AO_LED_GREEN);
-               ao_sleep(&blink_chan);
-       }
-}
-
-void
-blink_1(void)
-{
-       static __xdata struct ao_adc adc;
-
-       for (;;) {
-               ao_sleep(&ao_adc_head);
-               ao_adc_get(&adc);
-               if (adc.accel < 15900)
-                       ao_led_on(AO_LED_RED);
-               else
-                       ao_led_off(AO_LED_RED);
-       }
-}
-
-void
-wakeup(void)
-{
-       for (;;) {
-               ao_delay(AO_MS_TO_TICKS(100));
-               ao_wakeup(&blink_chan);
-       }
-}
-
-void
-beep(void)
-{
-       static __xdata struct ao_adc adc;
-
-       for (;;) {
-               ao_delay(AO_SEC_TO_TICKS(1));
-               ao_adc_get(&adc);
-               if (adc.temp > 7400)
-                       ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(50));
-       }
-}
-
-void
-echo(void)
-{
-       char    c;
-       for (;;) {
-               ao_usb_flush();
-               c = ao_usb_getchar();
-               ao_usb_putchar(c);
-               if (c == '\r')
-                       ao_usb_putchar('\n');
-       }
-}
-
-void
-main(void)
-{
-       ao_clock_init();
-
-//     ao_add_task(&blink_0_task, blink_0);
-//     ao_add_task(&blink_1_task, blink_1);
-//     ao_add_task(&wakeup_task, wakeup);
-//     ao_add_task(&beep_task, beep);
-       ao_add_task(&echo_task, echo);
-       ao_timer_init();
-       ao_adc_init();
-       ao_beep_init();
-       ao_led_init();
-       ao_usb_init();
-
-       ao_start_scheduler();
-}
diff --git a/src/ao_tidongle.c b/src/ao_tidongle.c
deleted file mode 100644 (file)
index 3b7c273..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#define AO_NO_SERIAL_ISR 1
-#define AO_NO_ADC_ISR 1
-#include "ao.h"
-
-void
-main(void)
-{
-       ao_clock_init();
-
-       /* Turn on the LED until the system is stable */
-       ao_led_init(AO_LED_RED);
-       ao_led_on(AO_LED_RED);
-       ao_timer_init();
-       ao_cmd_init();
-       ao_usb_init();
-       ao_monitor_init(AO_LED_RED, TRUE);
-       ao_rssi_init(AO_LED_RED);
-       ao_radio_init();
-       ao_dbg_init();
-       ao_config_init();
-       /* Bring up the USB link */
-       P1DIR |= 1;
-       P1 |= 1;
-       ao_start_scheduler();
-}
diff --git a/src/ao_timer.c b/src/ao_timer.c
deleted file mode 100644 (file)
index c977fbc..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-
-static volatile __data uint16_t ao_tick_count;
-
-uint16_t ao_time(void) __critical
-{
-       return ao_tick_count;
-}
-
-static __xdata uint8_t ao_forever;
-
-void
-ao_delay(uint16_t ticks)
-{
-       ao_alarm(ticks);
-       ao_sleep(&ao_forever);
-}
-
-#define T1_CLOCK_DIVISOR       8       /* 24e6/8 = 3e6 */
-#define T1_SAMPLE_TIME         30000   /* 3e6/30000 = 100 */
-
-#if HAS_ADC
-volatile __data uint8_t        ao_adc_interval = 1;
-volatile __data uint8_t        ao_adc_count;
-#endif
-
-void ao_timer_isr(void) __interrupt 9
-{
-       ++ao_tick_count;
-#if HAS_ADC
-       if (++ao_adc_count == ao_adc_interval) {
-               ao_adc_count = 0;
-               ao_adc_poll();
-       }
-#endif
-}
-
-#if HAS_ADC
-void
-ao_timer_set_adc_interval(uint8_t interval) __critical
-{
-       ao_adc_interval = interval;
-       ao_adc_count = 0;
-}
-#endif
-
-void
-ao_timer_init(void)
-{
-       /* NOTE:  This uses a timer only present on cc1111 architecture. */
-
-       /* disable timer 1 */
-       T1CTL = 0;
-
-       /* set the sample rate */
-       T1CC0H = T1_SAMPLE_TIME >> 8;
-       T1CC0L = (uint8_t) T1_SAMPLE_TIME;
-
-       T1CCTL0 = T1CCTL_MODE_COMPARE;
-       T1CCTL1 = 0;
-       T1CCTL2 = 0;
-
-       /* clear timer value */
-       T1CNTL = 0;
-
-       /* enable overflow interrupt */
-       OVFIM = 1;
-       /* enable timer 1 interrupt */
-       T1IE = 1;
-
-       /* enable timer 1 in module mode, dividing by 8 */
-       T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8;
-}
-
-/*
- * AltOS always cranks the clock to the max frequency
- */
-void
-ao_clock_init(void)
-{
-       /* Switch system clock to crystal oscilator */
-       CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL);
-
-       while (!(SLEEP & SLEEP_XOSC_STB))
-               ;
-
-       /* Crank up the timer tick and system clock speed */
-       CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) |
-                 (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1));
-
-       while ((CLKCON & (CLKCON_TICKSPD_MASK|CLKCON_CLKSPD_MASK)) !=
-              (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1))
-               ;
-}
diff --git a/src/ao_usb.c b/src/ao_usb.c
deleted file mode 100644 (file)
index 08cb739..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao.h"
-#include "ao_usb.h"
-
-struct ao_task __xdata ao_usb_task;
-
-static __xdata uint16_t        ao_usb_in_bytes;
-static __pdata uint16_t ao_usb_in_bytes_last;
-static __xdata uint16_t        ao_usb_out_bytes;
-static __pdata uint8_t ao_usb_iif;
-static __pdata uint8_t ao_usb_running;
-
-static void
-ao_usb_set_interrupts(void)
-{
-       /* IN interrupts on the control an IN endpoints */
-       USBIIE = (1 << AO_USB_CONTROL_EP) | (1 << AO_USB_IN_EP);
-
-       /* OUT interrupts on the OUT endpoint */
-       USBOIE = (1 << AO_USB_OUT_EP);
-
-       /* Only care about reset */
-       USBCIE = USBCIE_RSTIE;
-}
-
-/* This interrupt is shared with port 2,
- * so when we hook that up, fix this
- */
-void
-ao_usb_isr(void) __interrupt 6
-{
-       USBIF = 0;
-       ao_usb_iif |= USBIIF;
-       if (ao_usb_iif & 1)
-               ao_wakeup(&ao_usb_task);
-       if (ao_usb_iif & (1 << AO_USB_IN_EP))
-               ao_wakeup(&ao_usb_in_bytes);
-
-       if (USBOIF & (1 << AO_USB_OUT_EP))
-               ao_wakeup(&ao_stdin_ready);
-
-       if (USBCIF & USBCIF_RSTIF)
-               ao_usb_set_interrupts();
-#if HAS_BTM
-#if BT_LINK_ON_P2
-       ao_btm_isr();
-#endif
-#endif
-}
-
-struct ao_usb_setup {
-       uint8_t         dir_type_recip;
-       uint8_t         request;
-       uint16_t        value;
-       uint16_t        index;
-       uint16_t        length;
-} __xdata ao_usb_setup;
-
-__pdata uint8_t ao_usb_ep0_state;
-uint8_t * __pdata ao_usb_ep0_in_data;
-__pdata uint8_t ao_usb_ep0_in_len;
-__pdata uint8_t        ao_usb_ep0_in_buf[2];
-__pdata uint8_t ao_usb_ep0_out_len;
-__xdata uint8_t *__pdata ao_usb_ep0_out_data;
-__pdata uint8_t ao_usb_configuration;
-
-/* Send an IN data packet */
-static void
-ao_usb_ep0_flush(void)
-{
-       __pdata uint8_t this_len;
-       __pdata uint8_t cs0;
-
-       /* If the IN packet hasn't been picked up, just return */
-       USBINDEX = 0;
-       cs0 = USBCS0;
-       if (cs0 & USBCS0_INPKT_RDY)
-               return;
-
-       this_len = ao_usb_ep0_in_len;
-       if (this_len > AO_USB_CONTROL_SIZE)
-               this_len = AO_USB_CONTROL_SIZE;
-       cs0 = USBCS0_INPKT_RDY;
-       if (this_len != AO_USB_CONTROL_SIZE) {
-               cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END;
-               ao_usb_ep0_state = AO_USB_EP0_IDLE;
-       }
-       ao_usb_ep0_in_len -= this_len;
-       while (this_len--)
-               USBFIFO[0] = *ao_usb_ep0_in_data++;
-       USBINDEX = 0;
-       USBCS0 = cs0;
-}
-
-__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
-
-/* Walk through the list of descriptors and find a match
- */
-static void
-ao_usb_get_descriptor(uint16_t value)
-{
-       __code uint8_t          *__pdata descriptor;
-       __pdata uint8_t         type = value >> 8;
-       __pdata uint8_t         index = value;
-
-       descriptor = ao_usb_descriptors;
-       while (descriptor[0] != 0) {
-               if (descriptor[1] == type && index-- == 0) {
-                       if (type == AO_USB_DESC_CONFIGURATION)
-                               ao_usb_ep0_in_len = descriptor[2];
-                       else
-                               ao_usb_ep0_in_len = descriptor[0];
-                       ao_usb_ep0_in_data = descriptor;
-                       break;
-               }
-               descriptor += descriptor[0];
-       }
-}
-
-/* Read data from the ep0 OUT fifo
- */
-static void
-ao_usb_ep0_fill(void)
-{
-       __pdata uint8_t len;
-
-       USBINDEX = 0;
-       len = USBCNT0;
-       if (len > ao_usb_ep0_out_len)
-               len = ao_usb_ep0_out_len;
-       ao_usb_ep0_out_len -= len;
-       while (len--)
-               *ao_usb_ep0_out_data++ = USBFIFO[0];
-}
-
-void
-ao_usb_ep0_queue_byte(uint8_t a)
-{
-       ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a;
-}
-
-void
-ao_usb_set_address(uint8_t address)
-{
-       ao_usb_running = 1;
-       USBADDR = address | 0x80;
-       while (USBADDR & 0x80)
-               ;
-}
-
-static void
-ao_usb_set_configuration(void)
-{
-       /* Set the IN max packet size, double buffered */
-       USBINDEX = AO_USB_IN_EP;
-       USBMAXI = AO_USB_IN_SIZE >> 3;
-       USBCSIH |= USBCSIH_IN_DBL_BUF;
-
-       /* Set the OUT max packet size, double buffered */
-       USBINDEX = AO_USB_OUT_EP;
-       USBMAXO = AO_USB_OUT_SIZE >> 3;
-       USBCSOH = USBCSOH_OUT_DBL_BUF;
-}
-
-static void
-ao_usb_ep0_setup(void)
-{
-       /* Pull the setup packet out of the fifo */
-       ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup;
-       ao_usb_ep0_out_len = 8;
-       ao_usb_ep0_fill();
-       if (ao_usb_ep0_out_len != 0)
-               return;
-
-       /* Figure out how to ACK the setup packet */
-       if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) {
-               if (ao_usb_setup.length)
-                       ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
-               else
-                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
-       } else {
-               if (ao_usb_setup.length)
-                       ao_usb_ep0_state = AO_USB_EP0_DATA_OUT;
-               else
-                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
-       }
-       USBINDEX = 0;
-       if (ao_usb_ep0_state == AO_USB_EP0_IDLE)
-               USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END;
-       else
-               USBCS0 = USBCS0_CLR_OUTPKT_RDY;
-
-       ao_usb_ep0_in_data = ao_usb_ep0_in_buf;
-       ao_usb_ep0_in_len = 0;
-       switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) {
-       case AO_USB_TYPE_STANDARD:
-               switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) {
-               case AO_USB_RECIP_DEVICE:
-                       switch(ao_usb_setup.request) {
-                       case AO_USB_REQ_GET_STATUS:
-                               ao_usb_ep0_queue_byte(0);
-                               ao_usb_ep0_queue_byte(0);
-                               break;
-                       case AO_USB_REQ_SET_ADDRESS:
-                               ao_usb_set_address(ao_usb_setup.value);
-                               break;
-                       case AO_USB_REQ_GET_DESCRIPTOR:
-                               ao_usb_get_descriptor(ao_usb_setup.value);
-                               break;
-                       case AO_USB_REQ_GET_CONFIGURATION:
-                               ao_usb_ep0_queue_byte(ao_usb_configuration);
-                               break;
-                       case AO_USB_REQ_SET_CONFIGURATION:
-                               ao_usb_configuration = ao_usb_setup.value;
-                               ao_usb_set_configuration();
-                               break;
-                       }
-                       break;
-               case AO_USB_RECIP_INTERFACE:
-                       #pragma disable_warning 110
-                       switch(ao_usb_setup.request) {
-                       case AO_USB_REQ_GET_STATUS:
-                               ao_usb_ep0_queue_byte(0);
-                               ao_usb_ep0_queue_byte(0);
-                               break;
-                       case AO_USB_REQ_GET_INTERFACE:
-                               ao_usb_ep0_queue_byte(0);
-                               break;
-                       case AO_USB_REQ_SET_INTERFACE:
-                               break;
-                       }
-                       break;
-               case AO_USB_RECIP_ENDPOINT:
-                       switch(ao_usb_setup.request) {
-                       case AO_USB_REQ_GET_STATUS:
-                               ao_usb_ep0_queue_byte(0);
-                               ao_usb_ep0_queue_byte(0);
-                               break;
-                       }
-                       break;
-               }
-               break;
-       case AO_USB_TYPE_CLASS:
-               switch (ao_usb_setup.request) {
-               case SET_LINE_CODING:
-                       ao_usb_ep0_out_len = 7;
-                       ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding;
-                       break;
-               case GET_LINE_CODING:
-                       ao_usb_ep0_in_len = 7;
-                       ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding;
-                       break;
-               case SET_CONTROL_LINE_STATE:
-                       break;
-               }
-               break;
-       }
-       if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) {
-               if (ao_usb_setup.length < ao_usb_ep0_in_len)
-                       ao_usb_ep0_in_len = ao_usb_setup.length;
-               ao_usb_ep0_flush();
-       }
-}
-
-/* End point 0 receives all of the control messages. */
-static void
-ao_usb_ep0(void)
-{
-       __pdata uint8_t cs0;
-
-       ao_usb_ep0_state = AO_USB_EP0_IDLE;
-       for (;;) {
-               __critical for (;;) {
-                       if (ao_usb_iif & 1) {
-                               ao_usb_iif &= ~1;
-                               break;
-                       }
-                       ao_sleep(&ao_usb_task);
-               }
-               USBINDEX = 0;
-               cs0 = USBCS0;
-               if (cs0 & USBCS0_SETUP_END) {
-                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
-                       USBCS0 = USBCS0_CLR_SETUP_END;
-               }
-               if (cs0 & USBCS0_SENT_STALL) {
-                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
-                       USBCS0 &= ~USBCS0_SENT_STALL;
-               }
-               if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN &&
-                   (cs0 & USBCS0_INPKT_RDY) == 0)
-               {
-                       ao_usb_ep0_flush();
-               }
-               if (cs0 & USBCS0_OUTPKT_RDY) {
-                       switch (ao_usb_ep0_state) {
-                       case AO_USB_EP0_IDLE:
-                               ao_usb_ep0_setup();
-                               break;
-                       case AO_USB_EP0_DATA_OUT:
-                               ao_usb_ep0_fill();
-                               if (ao_usb_ep0_out_len == 0)
-                                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
-                               USBINDEX = 0;
-                               if (ao_usb_ep0_state == AO_USB_EP0_IDLE)
-                                       USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END;
-                               else
-                                       USBCS0 = USBCS0_CLR_OUTPKT_RDY;
-                               break;
-                       }
-               }
-       }
-}
-
-/* Wait for a free IN buffer */
-static void
-ao_usb_in_wait(void)
-{
-       for (;;) {
-               USBINDEX = AO_USB_IN_EP;
-               if ((USBCSIL & USBCSIL_INPKT_RDY) == 0)
-                       break;
-               ao_sleep(&ao_usb_in_bytes);
-       }
-}
-
-/* Send the current IN packet */
-static void
-ao_usb_in_send(void)
-{
-       USBINDEX = AO_USB_IN_EP;
-       USBCSIL |= USBCSIL_INPKT_RDY;
-       ao_usb_in_bytes_last = ao_usb_in_bytes;
-       ao_usb_in_bytes = 0;
-}
-
-void
-ao_usb_flush(void) __critical
-{
-       if (!ao_usb_running)
-               return;
-
-       /* If there are pending bytes, or if the last packet was full,
-        * send another IN packet
-        */
-       if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) {
-               ao_usb_in_wait();
-               ao_usb_in_send();
-       }
-}
-
-void
-ao_usb_putchar(char c) __critical __reentrant
-{
-       if (!ao_usb_running)
-               return;
-
-       ao_usb_in_wait();
-
-       /* Queue a byte, sending the packet when full */
-       USBFIFO[AO_USB_IN_EP << 1] = c;
-       if (++ao_usb_in_bytes == AO_USB_IN_SIZE)
-               ao_usb_in_send();
-}
-
-char
-ao_usb_pollchar(void) __critical
-{
-       char c;
-       if (ao_usb_out_bytes == 0) {
-               USBINDEX = AO_USB_OUT_EP;
-               if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0)
-                       return AO_READ_AGAIN;
-               ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL;
-               if (ao_usb_out_bytes == 0) {
-                       USBINDEX = AO_USB_OUT_EP;
-                       USBCSOL &= ~USBCSOL_OUTPKT_RDY;
-                       return AO_READ_AGAIN;
-               }
-       }
-       --ao_usb_out_bytes;
-       c = USBFIFO[AO_USB_OUT_EP << 1];
-       if (ao_usb_out_bytes == 0) {
-               USBINDEX = AO_USB_OUT_EP;
-               USBCSOL &= ~USBCSOL_OUTPKT_RDY;
-       }
-       return c;
-}
-
-char
-ao_usb_getchar(void) __critical
-{
-       char    c;
-
-       while ((c = ao_usb_pollchar()) == AO_READ_AGAIN)
-               ao_sleep(&ao_stdin_ready);
-       return c;
-}
-
-void
-ao_usb_enable(void)
-{
-       /* Turn on the USB controller */
-       SLEEP |= SLEEP_USB_EN;
-
-       ao_usb_set_configuration();
-
-       ao_usb_set_interrupts();
-
-       /* enable USB interrupts */
-       IEN2 |= IEN2_USBIE;
-
-       /* Clear any pending interrupts */
-       USBCIF = 0;
-       USBOIF = 0;
-       USBIIF = 0;
-}
-
-void
-ao_usb_disable(void)
-{
-       /* Disable USB interrupts */
-       USBIIE = 0;
-       USBOIE = 0;
-       USBCIE = 0;
-       IEN2 &= ~IEN2_USBIE;
-
-       /* Clear any pending interrupts */
-       USBCIF = 0;
-       USBOIF = 0;
-       USBIIF = 0;
-
-       /* Turn off the USB controller */
-       SLEEP &= ~SLEEP_USB_EN;
-}
-
-void
-ao_usb_init(void)
-{
-       ao_usb_enable();
-
-       ao_add_task(&ao_usb_task, ao_usb_ep0, "usb");
-       ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
-}
diff --git a/src/ao_usb.h b/src/ao_usb.h
deleted file mode 100644 (file)
index 6633daf..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_USB_H_
-#define _AO_USB_H_
-
-#define AO_USB_SETUP_DIR_MASK  (0x01 << 7)
-#define AO_USB_SETUP_TYPE_MASK (0x03 << 5)
-#define AO_USB_SETUP_RECIP_MASK        (0x1f)
-
-#define AO_USB_DIR_OUT                 0
-#define AO_USB_DIR_IN                  (1 << 7)
-
-#define AO_USB_TYPE_STANDARD           0
-#define AO_USB_TYPE_CLASS              (1 << 5)
-#define AO_USB_TYPE_VENDOR             (2 << 5)
-#define AO_USB_TYPE_RESERVED           (3 << 5)
-
-#define AO_USB_RECIP_DEVICE            0
-#define AO_USB_RECIP_INTERFACE         1
-#define AO_USB_RECIP_ENDPOINT          2
-#define AO_USB_RECIP_OTHER             3
-
-/* standard requests */
-#define        AO_USB_REQ_GET_STATUS           0x00
-#define AO_USB_REQ_CLEAR_FEATURE       0x01
-#define AO_USB_REQ_SET_FEATURE         0x03
-#define AO_USB_REQ_SET_ADDRESS         0x05
-#define AO_USB_REQ_GET_DESCRIPTOR      0x06
-#define AO_USB_REQ_SET_DESCRIPTOR      0x07
-#define AO_USB_REQ_GET_CONFIGURATION   0x08
-#define AO_USB_REQ_SET_CONFIGURATION   0x09
-#define AO_USB_REQ_GET_INTERFACE       0x0A
-#define AO_USB_REQ_SET_INTERFACE       0x0B
-#define AO_USB_REQ_SYNCH_FRAME         0x0C
-
-#define AO_USB_DESC_DEVICE             1
-#define AO_USB_DESC_CONFIGURATION      2
-#define AO_USB_DESC_STRING             3
-#define AO_USB_DESC_INTERFACE          4
-#define AO_USB_DESC_ENDPOINT           5
-#define AO_USB_DESC_DEVICE_QUALIFIER   6
-#define AO_USB_DESC_OTHER_SPEED                7
-#define AO_USB_DESC_INTERFACE_POWER    8
-
-#define AO_USB_GET_DESC_TYPE(x)                (((x)>>8)&0xFF)
-#define AO_USB_GET_DESC_INDEX(x)       ((x)&0xFF)
-
-#define AO_USB_CONTROL_EP      0
-#define AO_USB_INT_EP          1
-#define AO_USB_OUT_EP          4
-#define AO_USB_IN_EP           5
-#define AO_USB_CONTROL_SIZE    32
-/*
- * Double buffer IN and OUT EPs, so each
- * gets half of the available space
- *
- * Ah, but USB bulk packets can only come in 8, 16, 32 and 64
- * byte sizes, so we'll use 64 for everything
- */
-#define AO_USB_IN_SIZE         64
-#define AO_USB_OUT_SIZE                64
-
-#define AO_USB_EP0_IDLE                0
-#define AO_USB_EP0_DATA_IN     1
-#define AO_USB_EP0_DATA_OUT    2
-
-#define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
-
-/* CDC definitions */
-#define CS_INTERFACE      0x24
-#define CS_ENDPOINT       0x25
-
-#define SET_LINE_CODING         0x20
-#define GET_LINE_CODING         0x21
-#define SET_CONTROL_LINE_STATE  0x22
-
-/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */
-struct ao_usb_line_coding {
-       uint32_t        rate;
-       uint8_t         char_format;
-       uint8_t         parity;
-       uint8_t         data_bits;
-} ;
-
-#endif /* _AO_USB_H_ */
diff --git a/src/at45db161d.h b/src/at45db161d.h
deleted file mode 100644 (file)
index 9ee6f1b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */
-
-#ifndef _AT45DB161D_H_
-#define _AT45DB161D_H_
-
-/*
- * We reserve the last block on the device for
- * configuration space. Writes and reads in this
- * area return errors.
- */
-
-
-#define FLASH_READ             0x03
-#define FLASH_WRITE            0x82
-#define FLASH_PAGE_ERASE       0x81
-#define FLASH_READ_STATUS      0xd7
-#define FLASH_SET_CONFIG       0x3d
-
-#define FLASH_SET_512_BYTE_0   0x2a
-#define FLASH_SET_512_BYTE_1   0x80
-#define FLASH_SET_512_BYTE_2   0xa6
-
-#define FLASH_STATUS_RDY               (1 << 7)
-#define FLASH_STATUS_COMP              (1 << 6)
-#define FLASH_STATUS_PROTECT           (1 << 1)
-#define FLASH_STATUS_PAGESIZE_512      (1 << 0)
-
-#endif /* _AT45DB161D_H_ */
diff --git a/src/cc1111.h b/src/cc1111.h
deleted file mode 100644 (file)
index e52aa79..0000000
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*-------------------------------------------------------------------------
-   Register Declarations for the ChipCon CC1111 Processor Range
-
-   Copyright © 2008 Keith Packard <keithp@keithp.com>
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; version 2 of the License.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-
-   Adapted from the Cygnal C8051F12x config file which is:
-
-   Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
--------------------------------------------------------------------------*/
-
-#ifndef _CC1111_H_
-#define _CC1111_H_
-#include <cc1110.h>
-#include <stdint.h>
-
-__sfr __at 0xA8 IEN0;          /* Interrupt Enable 0 Register */
-
-sbit __at 0xA8 RFTXRXIE;       /* RF TX/RX done interrupt enable */
-sbit __at 0xA9 ADCIE;          /* ADC interrupt enable */
-sbit __at 0xAA URX0IE;         /* USART0 RX interrupt enable */
-sbit __at 0xAB URX1IE;         /* USART1 RX interrupt enable (shared with I2S RX) */
-sbit __at 0xAB I2SRXIE;                /* I2S RX interrupt enable (shared with USART1 RX) */
-sbit __at 0xAC ENCIE;          /* AES encryption/decryption interrupt enable */
-sbit __at 0xAD STIE;           /* Sleep Timer interrupt enable */
-sbit __at 0xAF EA;             /* Enable All */
-
-#define IEN0_EA                        (1 << 7)
-#define IEN0_STIE              (1 << 5)
-#define IEN0_ENCIE             (1 << 4)
-#define IEN0_URX1IE            (1 << 3)
-#define IEN0_I2SRXIE           (1 << 3)
-#define IEN0_URX0IE            (1 << 2)
-#define IEN0_ADCIE             (1 << 1)
-#define IEN0_RFTXRXIE          (1 << 0)
-
-__sfr __at 0xB8 IEN1;          /* Interrupt Enable 1 Register */
-
-#define IEN1_P0IE              (1 << 5)        /* Port 0 interrupt enable */
-#define IEN1_T4IE              (1 << 4)        /* Timer 4 interrupt enable */
-#define IEN1_T3IE              (1 << 3)        /* Timer 3 interrupt enable */
-#define IEN1_T2IE              (1 << 2)        /* Timer 2 interrupt enable */
-#define IEN1_T1IE              (1 << 1)        /* Timer 1 interrupt enable */
-#define IEN1_DMAIE             (1 << 0)        /* DMA transfer interrupt enable */
-
-/* IEN2 */
-__sfr __at 0x9A IEN2;          /* Interrupt Enable 2 Register */
-
-#define IEN2_WDTIE             (1 << 5)        /* Watchdog timer interrupt enable */
-#define IEN2_P1IE              (1 << 4)        /* Port 1 interrupt enable */
-#define IEN2_UTX1IE            (1 << 3)        /* USART1 TX interrupt enable */
-#define IEN2_I2STXIE           (1 << 3)        /* I2S TX interrupt enable */
-#define IEN2_UTX0IE            (1 << 2)        /* USART0 TX interrupt enable */
-#define IEN2_P2IE              (1 << 1)        /* Port 2 interrupt enable */
-#define IEN2_USBIE             (1 << 1)        /* USB interrupt enable */
-#define IEN2_RFIE              (1 << 0)        /* RF general interrupt enable */
-
-/* CLKCON 0xC6 */
-__sfr __at 0xC6 CLKCON;                /* Clock Control */
-
-#define CLKCON_OSC32K_RC       (1 << 7)
-#define CLKCON_OSC32K_XTAL     (0 << 7)
-#define CLKCON_OSC32K_MASK     (1 << 7)
-#define CLKCON_OSC_RC          (1 << 6)
-#define CLKCON_OSC_XTAL                (0 << 6)
-#define CLKCON_OSC_MASK                (1 << 6)
-#define CLKCON_TICKSPD_MASK    (7 << 3)
-# define CLKCON_TICKSPD_1      (0 << 3)
-# define CLKCON_TICKSPD_1_2    (1 << 3)
-# define CLKCON_TICKSPD_1_4    (2 << 3)
-# define CLKCON_TICKSPD_1_8    (3 << 3)
-# define CLKCON_TICKSPD_1_16   (4 << 3)
-# define CLKCON_TICKSPD_1_32   (5 << 3)
-# define CLKCON_TICKSPD_1_64   (6 << 3)
-# define CLKCON_TICKSPD_1_128  (7 << 3)
-
-#define CLKCON_CLKSPD_MASK     (7 << 0)
-# define CLKCON_CLKSPD_1       (0 << 0)
-# define CLKCON_CLKSPD_1_2     (1 << 0)
-# define CLKCON_CLKSPD_1_4     (2 << 0)
-# define CLKCON_CLKSPD_1_8     (3 << 0)
-# define CLKCON_CLKSPD_1_16    (4 << 0)
-# define CLKCON_CLKSPD_1_32    (5 << 0)
-# define CLKCON_CLKSPD_1_64    (6 << 0)
-# define CLKCON_CLKSPD_1_128   (7 << 0)
-
-/* SLEEP 0xBE */
-#define SLEEP_USB_EN           (1 << 7)
-#define SLEEP_XOSC_STB         (1 << 6)
-#define SLEEP_HFRC_STB         (1 << 5)
-#define SLEEP_RST_POWER                (0 << 3)
-#define SLEEP_RST_EXTERNAL     (1 << 3)
-#define SLEEP_RST_WATCHDOG     (2 << 3)
-#define SLEEP_RST_MASK         (3 << 3)
-#define SLEEP_OSC_PD           (1 << 2)
-#define SLEEP_MODE_PM0         (0 << 0)
-#define SLEEP_MODE_PM1         (1 << 0)
-#define SLEEP_MODE_PM2         (2 << 0)
-#define SLEEP_MODE_PM3         (3 << 0)
-#define SLEEP_MODE_MASK                (3 << 0)
-
-/* PCON 0x87 */
-__sfr __at 0x87 PCON;          /* Power Mode Control Register */
-
-#define PCON_IDLE              (1 << 0)
-
-/*
- * TCON
- */
-__sfr __at 0x88 TCON;          /* CPU Interrupt Flag 1 */
-
-sbit __at 0x8F URX1IF;         /* USART1 RX interrupt flag. Automatically cleared */
-sbit __at 0x8F I2SRXIF;                /* I2S RX interrupt flag. Automatically cleared */
-sbit __at 0x8D ADCIF;          /* ADC interrupt flag. Automatically cleared */
-sbit __at 0x8B URX0IF;         /* USART0 RX interrupt flag. Automatically cleared */
-sbit __at 0x89 RFTXRXIF;       /* RF TX/RX complete interrupt flag. Automatically cleared */
-
-#define TCON_URX1IF    (1 << 7)
-#define TCON_I2SRXIF   (1 << 7)
-#define TCON_ADCIF     (1 << 5)
-#define TCON_URX0IF    (1 << 3)
-#define TCON_RFTXRXIF  (1 << 1)
-
-/*
- * S0CON
- */
-__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */
-
-sbit __at 0x98 ENCIF_0;        /* AES interrupt 0. */
-sbit __at 0x99 ENCIF_1;        /* AES interrupt 1. */
-
-#define S0CON_ENCIF_1  (1 << 1)
-#define S0CON_ENCIF_0  (1 << 0)
-
-/*
- * S1CON
- */
-__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */
-
-#define S1CON_RFIF_1   (1 << 1)
-#define S1CON_RFIF_0   (1 << 0)
-
-/*
- * IRCON
- */
-__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */
-
-sbit __at 0xC0 DMAIF;  /* DMA complete interrupt flag */
-sbit __at 0xC1 T1IF;   /* Timer 1 interrupt flag. Automatically cleared */
-sbit __at 0xC2 T2IF;   /* Timer 2 interrupt flag. Automatically cleared */
-sbit __at 0xC3 T3IF;   /* Timer 3 interrupt flag. Automatically cleared */
-sbit __at 0xC4 T4IF;   /* Timer 4 interrupt flag. Automatically cleared */
-sbit __at 0xC5 P0IF;   /* Port0 interrupt flag */
-sbit __at 0xC7 STIF;   /* Sleep Timer interrupt flag */
-
-#define IRCON_DMAIF    (1 << 0)        /* DMA complete interrupt flag */
-#define IRCON_T1IF     (1 << 1)        /* Timer 1 interrupt flag. Automatically cleared */
-#define IRCON_T2IF     (1 << 2)        /* Timer 2 interrupt flag. Automatically cleared */
-#define IRCON_T3IF     (1 << 3)        /* Timer 3 interrupt flag. Automatically cleared */
-#define IRCON_T4IF     (1 << 4)        /* Timer 4 interrupt flag. Automatically cleared */
-#define IRCON_P0IF     (1 << 5)        /* Port0 interrupt flag */
-#define IRCON_STIF     (1 << 7)        /* Sleep Timer interrupt flag */
-
-/*
- * IRCON2
- */
-__sfr __at 0xE8 IRCON2;        /* CPU Interrupt Flag 5 */
-
-sbit __at 0xE8 USBIF;  /* USB interrupt flag (shared with Port2) */
-sbit __at 0xE8 P2IF;   /* Port2 interrupt flag (shared with USB) */
-sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */
-sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */
-sbit __at 0xEA I2STXIF;        /* I2S TX interrupt flag (shared with USART1 TX) */
-sbit __at 0xEB P1IF;   /* Port1 interrupt flag */
-sbit __at 0xEC WDTIF;  /* Watchdog timer interrupt flag */
-
-#define IRCON2_USBIF   (1 << 0)        /* USB interrupt flag (shared with Port2) */
-#define IRCON2_P2IF    (1 << 0)        /* Port2 interrupt flag (shared with USB) */
-#define IRCON2_UTX0IF  (1 << 1)        /* USART0 TX interrupt flag */
-#define IRCON2_UTX1IF  (1 << 2)        /* USART1 TX interrupt flag (shared with I2S TX) */
-#define IRCON2_I2STXIF (1 << 2)        /* I2S TX interrupt flag (shared with USART1 TX) */
-#define IRCON2_P1IF    (1 << 3)        /* Port1 interrupt flag */
-#define IRCON2_WDTIF   (1 << 4)        /* Watchdog timer interrupt flag */
-
-/*
- * IP1 - Interrupt Priority 1
- */
-
-/*
- * Interrupt priority groups:
- *
- * IPG0                RFTXRX          RF              DMA
- * IPG1                ADC             T1              P2INT/USB
- * IPG2                URX0            T2              UTX0
- * IPG3                URX1/I2SRX      T3              UTX1 / I2STX
- * IPG4                ENC             T4              P1INT
- * IPG5                ST              P0INT           WDT
- *
- * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first
- */
-
-__sfr __at 0xB9 IP1;   /* Interrupt Priority 1 */
-__sfr __at 0xA9 IP0;   /* Interrupt Priority 0 */
-
-#define IP1_IPG5       (1 << 5)
-#define IP1_IPG4       (1 << 4)
-#define IP1_IPG3       (1 << 3)
-#define IP1_IPG2       (1 << 2)
-#define IP1_IPG1       (1 << 1)
-#define IP1_IPG0       (1 << 0)
-
-#define IP0_IPG5       (1 << 5)
-#define IP0_IPG4       (1 << 4)
-#define IP0_IPG3       (1 << 3)
-#define IP0_IPG2       (1 << 2)
-#define IP0_IPG1       (1 << 1)
-#define IP0_IPG0       (1 << 0)
-
-/*
- * Timer 1
- */
-#define T1CTL_MODE_SUSPENDED   (0 << 0)
-#define T1CTL_MODE_FREE                (1 << 0)
-#define T1CTL_MODE_MODULO      (2 << 0)
-#define T1CTL_MODE_UP_DOWN     (3 << 0)
-#define T1CTL_MODE_MASK                (3 << 0)
-#define T1CTL_DIV_1            (0 << 2)
-#define T1CTL_DIV_8            (1 << 2)
-#define T1CTL_DIV_32           (2 << 2)
-#define T1CTL_DIV_128          (3 << 2)
-#define T1CTL_DIV_MASK         (3 << 2)
-#define T1CTL_OVFIF            (1 << 4)
-#define T1CTL_CH0IF            (1 << 5)
-#define T1CTL_CH1IF            (1 << 6)
-#define T1CTL_CH2IF            (1 << 7)
-
-#define T1CCTL_NO_CAPTURE      (0 << 0)
-#define T1CCTL_CAPTURE_RISING  (1 << 0)
-#define T1CCTL_CAPTURE_FALLING (2 << 0)
-#define T1CCTL_CAPTURE_BOTH    (3 << 0)
-#define T1CCTL_CAPTURE_MASK    (3 << 0)
-
-#define T1CCTL_MODE_CAPTURE    (0 << 2)
-#define T1CCTL_MODE_COMPARE    (1 << 2)
-
-#define T1CTL_CMP_SET          (0 << 3)
-#define T1CTL_CMP_CLEAR                (1 << 3)
-#define T1CTL_CMP_TOGGLE       (2 << 3)
-#define T1CTL_CMP_SET_CLEAR    (3 << 3)
-#define T1CTL_CMP_CLEAR_SET    (4 << 3)
-
-#define T1CTL_IM_DISABLED      (0 << 6)
-#define T1CTL_IM_ENABLED       (1 << 6)
-
-#define T1CTL_CPSEL_NORMAL     (0 << 7)
-#define T1CTL_CPSEL_RF         (1 << 7)
-
-/*
- * Timer 3 and Timer 4
- */
-
-/* Timer count */
-__sfr __at 0xCA T3CNT;
-__sfr __at 0xEA T4CNT;
-
-/* Timer control */
-
-__sfr __at 0xCB T3CTL;
-__sfr __at 0xEB T4CTL;
-
-#define TxCTL_DIV_1            (0 << 5)
-#define TxCTL_DIV_2            (1 << 5)
-#define TxCTL_DIV_4            (2 << 5)
-#define TxCTL_DIV_8            (3 << 5)
-#define TxCTL_DIV_16           (4 << 5)
-#define TxCTL_DIV_32           (5 << 5)
-#define TxCTL_DIV_64           (6 << 5)
-#define TxCTL_DIV_128          (7 << 5)
-#define TxCTL_START            (1 << 4)
-#define TxCTL_OVFIM            (1 << 3)
-#define TxCTL_CLR              (1 << 2)
-#define TxCTL_MODE_FREE                (0 << 0)
-#define TxCTL_MODE_DOWN                (1 << 0)
-#define TxCTL_MODE_MODULO      (2 << 0)
-#define TxCTL_MODE_UP_DOWN     (3 << 0)
-
-/* Timer 4 channel 0 compare control */
-
-__sfr __at 0xCC T3CCTL0;
-__sfr __at 0xCE T3CCTL1;
-__sfr __at 0xEC T4CCTL0;
-__sfr __at 0xEE T4CCTL1;
-
-#define TxCCTLy_IM                     (1 << 6)
-#define TxCCTLy_CMP_SET                        (0 << 3)
-#define TxCCTLy_CMP_CLEAR              (1 << 3)
-#define TxCCTLy_CMP_TOGGLE             (2 << 3)
-#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN  (3 << 3)
-#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN  (4 << 3)
-#define TxCCTLy_CMP_SET_CLEAR_FF       (5 << 3)
-#define TxCCTLy_CMP_CLEAR_SET_00       (6 << 3)
-#define TxCCTLy_CMP_MODE_ENABLE                (1 << 2)
-
-/* Timer compare value */
-__sfr __at 0xCD T3CC0;
-__sfr __at 0xCF T3CC1;
-__sfr __at 0xED T4CC0;
-__sfr __at 0xEF T4CC1;
-
-/*
- * Peripheral control
- */
-
-__sfr __at 0xf1 PERCFG;
-#define PERCFG_T1CFG_ALT_1      (0 << 6)
-#define PERCFG_T1CFG_ALT_2      (1 << 6)
-#define PERCFG_T1CFG_ALT_MASK   (1 << 6)
-
-#define PERCFG_T3CFG_ALT_1      (0 << 5)
-#define PERCFG_T3CFG_ALT_2      (1 << 5)
-#define PERCFG_T3CFG_ALT_MASK   (1 << 5)
-
-#define PERCFG_T4CFG_ALT_1      (0 << 4)
-#define PERCFG_T4CFG_ALT_2      (1 << 4)
-#define PERCFG_T4CFG_ALT_MASK   (1 << 4)
-
-#define PERCFG_U1CFG_ALT_1      (0 << 1)
-#define PERCFG_U1CFG_ALT_2      (1 << 1)
-#define PERCFG_U1CFG_ALT_MASK   (1 << 1)
-
-#define PERCFG_U0CFG_ALT_1      (0 << 0)
-#define PERCFG_U0CFG_ALT_2      (1 << 0)
-#define PERCFG_U0CFG_ALT_MASK   (1 << 0)
-
-/* directly addressed USB registers */
-__xdata __at (0xde00) volatile uint8_t USBADDR;
-__xdata __at (0xde01) volatile uint8_t USBPOW;
-__xdata __at (0xde02) volatile uint8_t USBIIF;
-
-__xdata __at (0xde04) volatile uint8_t USBOIF;
-
-__xdata __at (0xde06) volatile uint8_t USBCIF;
-
-# define USBCIF_SOFIF          (1 << 3)
-# define USBCIF_RSTIF          (1 << 2)
-# define USBCIF_RESUMEIF       (1 << 1)
-# define USBCIF_SUSPENDIF      (1 << 0)
-
-__xdata __at (0xde07) volatile uint8_t USBIIE;
-
-__xdata __at (0xde09) volatile uint8_t USBOIE;
-
-__xdata __at (0xde0b) volatile uint8_t USBCIE;
-
-# define USBCIE_SOFIE          (1 << 3)
-# define USBCIE_RSTIE          (1 << 2)
-# define USBCIE_RESUMEIE       (1 << 1)
-# define USBCIE_SUSPENDIE      (1 << 0)
-
-__xdata __at (0xde0c) volatile uint8_t USBFRML;
-__xdata __at (0xde0d) volatile uint8_t USBFRMH;
-__xdata __at (0xde0e) volatile uint8_t USBINDEX;
-
-/* indexed USB registers, must set USBINDEX to 0-5 */
-__xdata __at (0xde10) volatile uint8_t USBMAXI;
-__xdata __at (0xde11) volatile uint8_t USBCS0;
-
-# define USBCS0_CLR_SETUP_END          (1 << 7)
-# define USBCS0_CLR_OUTPKT_RDY         (1 << 6)
-# define USBCS0_SEND_STALL             (1 << 5)
-# define USBCS0_SETUP_END              (1 << 4)
-# define USBCS0_DATA_END               (1 << 3)
-# define USBCS0_SENT_STALL             (1 << 2)
-# define USBCS0_INPKT_RDY              (1 << 1)
-# define USBCS0_OUTPKT_RDY             (1 << 0)
-
-__xdata __at (0xde11) volatile uint8_t USBCSIL;
-
-# define USBCSIL_CLR_DATA_TOG          (1 << 6)
-# define USBCSIL_SENT_STALL            (1 << 5)
-# define USBCSIL_SEND_STALL            (1 << 4)
-# define USBCSIL_FLUSH_PACKET          (1 << 3)
-# define USBCSIL_UNDERRUN              (1 << 2)
-# define USBCSIL_PKT_PRESENT           (1 << 1)
-# define USBCSIL_INPKT_RDY             (1 << 0)
-
-__xdata __at (0xde12) volatile uint8_t USBCSIH;
-
-# define USBCSIH_AUTOSET               (1 << 7)
-# define USBCSIH_ISO                   (1 << 6)
-# define USBCSIH_FORCE_DATA_TOG                (1 << 3)
-# define USBCSIH_IN_DBL_BUF            (1 << 0)
-
-__xdata __at (0xde13) volatile uint8_t USBMAXO;
-__xdata __at (0xde14) volatile uint8_t USBCSOL;
-
-# define USBCSOL_CLR_DATA_TOG          (1 << 7)
-# define USBCSOL_SENT_STALL            (1 << 6)
-# define USBCSOL_SEND_STALL            (1 << 5)
-# define USBCSOL_FLUSH_PACKET          (1 << 4)
-# define USBCSOL_DATA_ERROR            (1 << 3)
-# define USBCSOL_OVERRUN               (1 << 2)
-# define USBCSOL_FIFO_FULL             (1 << 1)
-# define USBCSOL_OUTPKT_RDY            (1 << 0)
-
-__xdata __at (0xde15) volatile uint8_t USBCSOH;
-
-# define USBCSOH_AUTOCLEAR             (1 << 7)
-# define USBCSOH_ISO                   (1 << 6)
-# define USBCSOH_OUT_DBL_BUF           (1 << 0)
-
-__xdata __at (0xde16) volatile uint8_t USBCNT0;
-__xdata __at (0xde16) volatile uint8_t USBCNTL;
-__xdata __at (0xde17) volatile uint8_t USBCNTH;
-
-__xdata __at (0xde20) volatile uint8_t USBFIFO[12];
-
-/* ADC Data register, low and high */
-__sfr at 0xBA ADCL;
-__sfr at 0xBB ADCH;
-__xdata __at (0xDFBA) volatile uint16_t ADCXDATA;
-
-/* ADC Control Register 1 */
-__sfr at 0xB4 ADCCON1;
-
-# define ADCCON1_EOC           (1 << 7)        /* conversion complete */
-# define ADCCON1_ST            (1 << 6)        /* start conversion */
-
-# define ADCCON1_STSEL_MASK    (3 << 4)        /* start select */
-# define ADCCON1_STSEL_EXTERNAL        (0 << 4)        /* P2_0 pin triggers */
-# define ADCCON1_STSEL_FULLSPEED (1 << 4)      /* full speed, no waiting */
-# define ADCCON1_STSEL_TIMER1  (2 << 4)        /* timer 1 channel 0 */
-# define ADCCON1_STSEL_START   (3 << 4)        /* set start bit */
-
-# define ADCCON1_RCTRL_MASK    (3 << 2)        /* random number control */
-# define ADCCON1_RCTRL_COMPLETE        (0 << 2)        /* operation completed */
-# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2)     /* Clock the LFSR once */
-
-/* ADC Control Register 2 */
-__sfr at 0xB5 ADCCON2;
-
-# define ADCCON2_SREF_MASK     (3 << 6)        /* reference voltage */
-# define ADCCON2_SREF_1_25V    (0 << 6)        /* internal 1.25V */
-# define ADCCON2_SREF_EXTERNAL (1 << 6)        /* external on AIN7 cc1110 */
-# define ADCCON2_SREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
-# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6)   /* external on AIN6-7 cc1110 */
-
-# define ADCCON2_SDIV_MASK     (3 << 4)        /* decimation rate */
-# define ADCCON2_SDIV_64       (0 << 4)        /* 7 bits */
-# define ADCCON2_SDIV_128      (1 << 4)        /* 9 bits */
-# define ADCCON2_SDIV_256      (2 << 4)        /* 10 bits */
-# define ADCCON2_SDIV_512      (3 << 4)        /* 12 bits */
-
-# define ADCCON2_SCH_MASK      (0xf << 0)      /* Sequence channel select */
-# define ADCCON2_SCH_SHIFT     0
-# define ADCCON2_SCH_AIN0      (0 << 0)
-# define ADCCON2_SCH_AIN1      (1 << 0)
-# define ADCCON2_SCH_AIN2      (2 << 0)
-# define ADCCON2_SCH_AIN3      (3 << 0)
-# define ADCCON2_SCH_AIN4      (4 << 0)
-# define ADCCON2_SCH_AIN5      (5 << 0)
-# define ADCCON2_SCH_AIN6      (6 << 0)
-# define ADCCON2_SCH_AIN7      (7 << 0)
-# define ADCCON2_SCH_AIN0_AIN1 (8 << 0)
-# define ADCCON2_SCH_AIN2_AIN3 (9 << 0)
-# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0)
-# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0)
-# define ADCCON2_SCH_GND       (0xc << 0)
-# define ADCCON2_SCH_VREF      (0xd << 0)
-# define ADCCON2_SCH_TEMP      (0xe << 0)
-# define ADCCON2_SCH_VDD_3     (0xf << 0)
-
-
-/* ADC Control Register 3 */
-__sfr at 0xB6 ADCCON3;
-
-# define ADCCON3_EREF_MASK     (3 << 6)        /* extra conversion reference */
-# define ADCCON3_EREF_1_25     (0 << 6)        /* internal 1.25V */
-# define ADCCON3_EREF_EXTERNAL (1 << 6)        /* external AIN7 cc1110 */
-# define ADCCON3_EREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
-# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6)   /* external AIN6-7 cc1110 */
-# define ADCCON3_EDIV_MASK     (3 << 4)        /* extral decimation */
-# define ADCCON3_EDIV_64       (0 << 4)        /* 7 bits */
-# define ADCCON3_EDIV_128      (1 << 4)        /* 9 bits */
-# define ADCCON3_EDIV_256      (2 << 4)        /* 10 bits */
-# define ADCCON3_EDIV_512      (3 << 4)        /* 12 bits */
-# define ADCCON3_ECH_MASK      (0xf << 0)      /* Sequence channel select */
-# define ADCCON3_ECH_SHIFT     0
-# define ADCCON3_ECH_AIN0      (0 << 0)
-# define ADCCON3_ECH_AIN1      (1 << 0)
-# define ADCCON3_ECH_AIN2      (2 << 0)
-# define ADCCON3_ECH_AIN3      (3 << 0)
-# define ADCCON3_ECH_AIN4      (4 << 0)
-# define ADCCON3_ECH_AIN5      (5 << 0)
-# define ADCCON3_ECH_AIN6      (6 << 0)
-# define ADCCON3_ECH_AIN7      (7 << 0)
-# define ADCCON3_ECH_AIN0_AIN1 (8 << 0)
-# define ADCCON3_ECH_AIN2_AIN3 (9 << 0)
-# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0)
-# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0)
-# define ADCCON3_ECH_GND       (0xc << 0)
-# define ADCCON3_ECH_VREF      (0xd << 0)
-# define ADCCON3_ECH_TEMP      (0xe << 0)
-# define ADCCON3_ECH_VDD_3     (0xf << 0)
-
-/*
- * ADC configuration register, this selects which
- * GPIO pins are to be used as ADC inputs
- */
-__sfr at 0xF2 ADCCFG;
-
-/*
- * Watchdog timer
- */
-
-__sfr at 0xc9 WDCTL;
-
-#define WDCTL_CLEAR_FIRST      (0xa << 4)
-#define WDCTL_CLEAR_SECOND     (0x5 << 4)
-#define WDCTL_EN               (1 << 3)
-#define WDCTL_MODE_WATCHDOG    (0 << 2)
-#define WDCTL_MODE_TIMER       (1 << 2)
-#define WDCTL_MODE_MASK                (1 << 2)
-#define WDCTL_INT_32768                (0 << 0)
-#define WDCTL_INT_8192         (1 << 0)
-#define WDCTL_INT_512          (2 << 0)
-#define WDCTL_INT_64           (3 << 0)
-
-/*
- * Pin selectors, these set which pins are
- * using their peripheral function
- */
-__sfr at 0xF3 P0SEL;
-__sfr at 0xF4 P1SEL;
-__sfr at 0xF5 P2SEL;
-
-#define P2SEL_PRI3P1_USART0            (0 << 6)
-#define P2SEL_PRI3P1_USART1            (1 << 6)
-#define P2SEL_PRI3P1_MASK              (1 << 6)
-#define P2SEL_PRI2P1_USART1            (0 << 5)
-#define P2SEL_PRI2P1_TIMER3            (1 << 5)
-#define P2SEL_PRI2P1_MASK              (1 << 5)
-#define P2SEL_PRI1P1_TIMER1            (0 << 4)
-#define P2SEL_PRI1P1_TIMER4            (1 << 4)
-#define P2SEL_PRI1P1_MASK              (1 << 4)
-#define P2SEL_PRI0P1_USART0            (0 << 3)
-#define P2SEL_PRI0P1_TIMER1            (1 << 3)
-#define P2SEL_PRI0P1_MASK              (1 << 3)
-#define P2SEL_SELP2_4_GPIO             (0 << 2)
-#define P2SEL_SELP2_4_PERIPHERAL       (1 << 2)
-#define P2SEL_SELP2_4_MASK             (1 << 2)
-#define P2SEL_SELP2_3_GPIO             (0 << 1)
-#define P2SEL_SELP2_3_PERIPHERAL       (1 << 1)
-#define P2SEL_SELP2_3_MASK             (1 << 1)
-#define P2SEL_SELP2_0_GPIO             (0 << 0)
-#define P2SEL_SELP2_0_PERIPHERAL       (1 << 0)
-#define P2SEL_SELP2_0_MASK             (1 << 0)
-
-/*
- * For pins used as GPIOs, these set which are used as outputs
- */
-__sfr at 0xFD P0DIR;
-__sfr at 0xFE P1DIR;
-__sfr at 0xFF P2DIR;
-
-#define P2DIR_PRIP0_USART0_USART1      (0 << 6)
-#define P2DIR_PRIP0_USART1_USART0      (1 << 6)
-#define P2DIR_PRIP0_TIMER1_01_USART1   (2 << 6)
-#define P2DIR_PRIP0_TIMER1_2_USART0    (3 << 6)
-#define P2DIR_PRIP0_MASK               (3 << 6)
-
-__sfr at 0x8F P0INP;
-
-/* Select between tri-state and pull up/down
- * for pins P0_0 - P0_7.
- */
-#define P0INP_MDP0_7_PULL      (0 << 7)
-#define P0INP_MDP0_7_TRISTATE  (1 << 7)
-#define P0INP_MDP0_6_PULL      (0 << 6)
-#define P0INP_MDP0_6_TRISTATE  (1 << 6)
-#define P0INP_MDP0_5_PULL      (0 << 5)
-#define P0INP_MDP0_5_TRISTATE  (1 << 5)
-#define P0INP_MDP0_4_PULL      (0 << 4)
-#define P0INP_MDP0_4_TRISTATE  (1 << 4)
-#define P0INP_MDP0_3_PULL      (0 << 3)
-#define P0INP_MDP0_3_TRISTATE  (1 << 3)
-#define P0INP_MDP0_2_PULL      (0 << 2)
-#define P0INP_MDP0_2_TRISTATE  (1 << 2)
-#define P0INP_MDP0_1_PULL      (0 << 1)
-#define P0INP_MDP0_1_TRISTATE  (1 << 1)
-#define P0INP_MDP0_0_PULL      (0 << 0)
-#define P0INP_MDP0_0_TRISTATE  (1 << 0)
-
-__sfr at 0xF6 P1INP;
-
-/* Select between tri-state and pull up/down
- * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are
- * always tri-stated
- */
-#define P1INP_MDP1_7_PULL      (0 << 7)
-#define P1INP_MDP1_7_TRISTATE  (1 << 7)
-#define P1INP_MDP1_6_PULL      (0 << 6)
-#define P1INP_MDP1_6_TRISTATE  (1 << 6)
-#define P1INP_MDP1_5_PULL      (0 << 5)
-#define P1INP_MDP1_5_TRISTATE  (1 << 5)
-#define P1INP_MDP1_4_PULL      (0 << 4)
-#define P1INP_MDP1_4_TRISTATE  (1 << 4)
-#define P1INP_MDP1_3_PULL      (0 << 3)
-#define P1INP_MDP1_3_TRISTATE  (1 << 3)
-#define P1INP_MDP1_2_PULL      (0 << 2)
-#define P1INP_MDP1_2_TRISTATE  (1 << 2)
-
-__sfr at 0xF7 P2INP;
-/* P2INP has three extra bits which are used to choose
- * between pull-up and pull-down when they are not tri-stated
- */
-#define P2INP_PDUP2_PULL_UP    (0 << 7)
-#define P2INP_PDUP2_PULL_DOWN  (1 << 7)
-#define P2INP_PDUP1_PULL_UP    (0 << 6)
-#define P2INP_PDUP1_PULL_DOWN  (1 << 6)
-#define P2INP_PDUP0_PULL_UP    (0 << 5)
-#define P2INP_PDUP0_PULL_DOWN  (1 << 5)
-
-/* For the P2 pins, choose between tri-state and pull up/down
- * mode
- */
-#define P2INP_MDP2_4_PULL      (0 << 4)
-#define P2INP_MDP2_4_TRISTATE  (1 << 4)
-#define P2INP_MDP2_3_PULL      (0 << 3)
-#define P2INP_MDP2_3_TRISTATE  (1 << 3)
-#define P2INP_MDP2_2_PULL      (0 << 2)
-#define P2INP_MDP2_2_TRISTATE  (1 << 2)
-#define P2INP_MDP2_1_PULL      (0 << 1)
-#define P2INP_MDP2_1_TRISTATE  (1 << 1)
-#define P2INP_MDP2_0_PULL      (0 << 0)
-#define P2INP_MDP2_0_TRISTATE  (1 << 0)
-
-/* GPIO interrupt status flags */
-__sfr at 0x89 P0IFG;
-__sfr at 0x8A P1IFG;
-__sfr at 0x8B P2IFG;
-
-#define P0IFG_USB_RESUME       (1 << 7)
-
-__sfr at 0x8C PICTL;
-#define PICTL_P2IEN    (1 << 5)
-#define PICTL_P0IENH   (1 << 4)
-#define PICTL_P0IENL   (1 << 3)
-#define PICTL_P2ICON   (1 << 2)
-#define PICTL_P1ICON   (1 << 1)
-#define PICTL_P0ICON   (1 << 0)
-
-/* GPIO pins */
-__sfr at 0x80 P0;
-
-sbit at 0x80 P0_0;
-sbit at 0x81 P0_1;
-sbit at 0x82 P0_2;
-sbit at 0x83 P0_3;
-sbit at 0x84 P0_4;
-sbit at 0x85 P0_5;
-sbit at 0x86 P0_6;
-sbit at 0x87 P0_7;
-
-__sfr at 0x90 P1;
-
-sbit at 0x90 P1_0;
-sbit at 0x91 P1_1;
-sbit at 0x92 P1_2;
-sbit at 0x93 P1_3;
-sbit at 0x94 P1_4;
-sbit at 0x95 P1_5;
-sbit at 0x96 P1_6;
-sbit at 0x97 P1_7;
-
-__sfr at 0xa0 P2;
-
-sbit at 0xa0 P2_0;
-sbit at 0xa1 P2_1;
-sbit at 0xa2 P2_2;
-sbit at 0xa3 P2_3;
-sbit at 0xa4 P2_4;
-
-/* DMA controller */
-struct cc_dma_channel {
-       uint8_t src_high;
-       uint8_t src_low;
-       uint8_t dst_high;
-       uint8_t dst_low;
-       uint8_t len_high;
-       uint8_t len_low;
-       uint8_t cfg0;
-       uint8_t cfg1;
-};
-
-# define DMA_LEN_HIGH_VLEN_MASK                (7 << 5)
-# define DMA_LEN_HIGH_VLEN_LEN         (0 << 5)
-# define DMA_LEN_HIGH_VLEN_PLUS_1      (1 << 5)
-# define DMA_LEN_HIGH_VLEN             (2 << 5)
-# define DMA_LEN_HIGH_VLEN_PLUS_2      (3 << 5)
-# define DMA_LEN_HIGH_VLEN_PLUS_3      (4 << 5)
-# define DMA_LEN_HIGH_MASK             (0x1f)
-
-# define DMA_CFG0_WORDSIZE_8           (0 << 7)
-# define DMA_CFG0_WORDSIZE_16          (1 << 7)
-# define DMA_CFG0_TMODE_MASK           (3 << 5)
-# define DMA_CFG0_TMODE_SINGLE         (0 << 5)
-# define DMA_CFG0_TMODE_BLOCK          (1 << 5)
-# define DMA_CFG0_TMODE_REPEATED_SINGLE        (2 << 5)
-# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5)
-
-/*
- * DMA triggers
- */
-# define DMA_CFG0_TRIGGER_NONE         0
-# define DMA_CFG0_TRIGGER_PREV         1
-# define DMA_CFG0_TRIGGER_T1_CH0       2
-# define DMA_CFG0_TRIGGER_T1_CH1       3
-# define DMA_CFG0_TRIGGER_T1_CH2       4
-# define DMA_CFG0_TRIGGER_T2_OVFL      6
-# define DMA_CFG0_TRIGGER_T3_CH0       7
-# define DMA_CFG0_TRIGGER_T3_CH1       8
-# define DMA_CFG0_TRIGGER_T4_CH0       9
-# define DMA_CFG0_TRIGGER_T4_CH1       10
-# define DMA_CFG0_TRIGGER_IOC_0                12
-# define DMA_CFG0_TRIGGER_IOC_1                13
-# define DMA_CFG0_TRIGGER_URX0         14
-# define DMA_CFG0_TRIGGER_UTX0         15
-# define DMA_CFG0_TRIGGER_URX1         16
-# define DMA_CFG0_TRIGGER_UTX1         17
-# define DMA_CFG0_TRIGGER_FLASH                18
-# define DMA_CFG0_TRIGGER_RADIO                19
-# define DMA_CFG0_TRIGGER_ADC_CHALL    20
-# define DMA_CFG0_TRIGGER_ADC_CH0      21
-# define DMA_CFG0_TRIGGER_ADC_CH1      22
-# define DMA_CFG0_TRIGGER_ADC_CH2      23
-# define DMA_CFG0_TRIGGER_ADC_CH3      24
-# define DMA_CFG0_TRIGGER_ADC_CH4      25
-# define DMA_CFG0_TRIGGER_ADC_CH5      26
-# define DMA_CFG0_TRIGGER_ADC_CH6      27
-# define DMA_CFG0_TRIGGER_I2SRX                27
-# define DMA_CFG0_TRIGGER_ADC_CH7      28
-# define DMA_CFG0_TRIGGER_I2STX                28
-# define DMA_CFG0_TRIGGER_ENC_DW       29
-# define DMA_CFG0_TRIGGER_DNC_UP       30
-
-# define DMA_CFG1_SRCINC_MASK          (3 << 6)
-# define DMA_CFG1_SRCINC_0             (0 << 6)
-# define DMA_CFG1_SRCINC_1             (1 << 6)
-# define DMA_CFG1_SRCINC_2             (2 << 6)
-# define DMA_CFG1_SRCINC_MINUS_1       (3 << 6)
-
-# define DMA_CFG1_DESTINC_MASK         (3 << 4)
-# define DMA_CFG1_DESTINC_0            (0 << 4)
-# define DMA_CFG1_DESTINC_1            (1 << 4)
-# define DMA_CFG1_DESTINC_2            (2 << 4)
-# define DMA_CFG1_DESTINC_MINUS_1      (3 << 4)
-
-# define DMA_CFG1_IRQMASK              (1 << 3)
-# define DMA_CFG1_M8                   (1 << 2)
-
-# define DMA_CFG1_PRIORITY_MASK                (3 << 0)
-# define DMA_CFG1_PRIORITY_LOW         (0 << 0)
-# define DMA_CFG1_PRIORITY_NORMAL      (1 << 0)
-# define DMA_CFG1_PRIORITY_HIGH                (2 << 0)
-
-/*
- * DMAARM - DMA Channel Arm
- */
-
-__sfr at 0xD6 DMAARM;
-
-# define DMAARM_ABORT                  (1 << 7)
-# define DMAARM_DMAARM4                        (1 << 4)
-# define DMAARM_DMAARM3                        (1 << 3)
-# define DMAARM_DMAARM2                        (1 << 2)
-# define DMAARM_DMAARM1                        (1 << 1)
-# define DMAARM_DMAARM0                        (1 << 0)
-
-/*
- * DMAREQ - DMA Channel Start Request and Status
- */
-
-__sfr at 0xD7 DMAREQ;
-
-# define DMAREQ_DMAREQ4                        (1 << 4)
-# define DMAREQ_DMAREQ3                        (1 << 3)
-# define DMAREQ_DMAREQ2                        (1 << 2)
-# define DMAREQ_DMAREQ1                        (1 << 1)
-# define DMAREQ_DMAREQ0                        (1 << 0)
-
-/*
- * DMA configuration 0 address
- */
-
-__sfr at 0xD5 DMA0CFGH;
-__sfr at 0xD4 DMA0CFGL;
-
-/*
- * DMA configuration 1-4 address
- */
-
-__sfr at 0xD3 DMA1CFGH;
-__sfr at 0xD2 DMA1CFGL;
-
-/*
- * DMAIRQ - DMA Interrupt Flag
- */
-
-__sfr at 0xD1 DMAIRQ;
-
-# define DMAIRQ_DMAIF4                 (1 << 4)
-# define DMAIRQ_DMAIF3                 (1 << 3)
-# define DMAIRQ_DMAIF2                 (1 << 2)
-# define DMAIRQ_DMAIF1                 (1 << 1)
-# define DMAIRQ_DMAIF0                 (1 << 0)
-
-/*
- * UART registers
- */
-
-/* USART config/status registers */
-__sfr at 0x86 U0CSR;
-__sfr at 0xF8 U1CSR;
-
-# define UxCSR_MODE_UART               (1 << 7)
-# define UxCSR_MODE_SPI                        (0 << 7)
-# define UxCSR_RE                      (1 << 6)
-# define UxCSR_SLAVE                   (1 << 5)
-# define UxCSR_MASTER                  (0 << 5)
-# define UxCSR_FE                      (1 << 4)
-# define UxCSR_ERR                     (1 << 3)
-# define UxCSR_RX_BYTE                 (1 << 2)
-# define UxCSR_TX_BYTE                 (1 << 1)
-# define UxCSR_ACTIVE                  (1 << 0)
-
-/* UART configuration registers */
-__sfr at 0xc4 U0UCR;
-__sfr at 0xfb U1UCR;
-
-# define UxUCR_FLUSH                    (1 << 7)
-# define UxUCR_FLOW_DISABLE             (0 << 6)
-# define UxUCR_FLOW_ENABLE              (1 << 6)
-# define UxUCR_D9_EVEN_PARITY           (0 << 5)
-# define UxUCR_D9_ODD_PARITY            (1 << 5)
-# define UxUCR_BIT9_8_BITS              (0 << 4)
-# define UxUCR_BIT9_9_BITS              (1 << 4)
-# define UxUCR_PARITY_DISABLE           (0 << 3)
-# define UxUCR_PARITY_ENABLE            (1 << 3)
-# define UxUCR_SPB_1_STOP_BIT           (0 << 2)
-# define UxUCR_SPB_2_STOP_BITS          (1 << 2)
-# define UxUCR_STOP_LOW                 (0 << 1)
-# define UxUCR_STOP_HIGH                (1 << 1)
-# define UxUCR_START_LOW                (0 << 0)
-# define UxUCR_START_HIGH               (1 << 0)
-
-/* USART General configuration registers (mostly SPI) */
-__sfr at 0xc5 U0GCR;
-__sfr at 0xfc U1GCR;
-
-# define UxGCR_CPOL_NEGATIVE           (0 << 7)
-# define UxGCR_CPOL_POSITIVE           (1 << 7)
-# define UxGCR_CPHA_FIRST_EDGE         (0 << 6)
-# define UxGCR_CPHA_SECOND_EDGE                (1 << 6)
-# define UxGCR_ORDER_LSB               (0 << 5)
-# define UxGCR_ORDER_MSB               (1 << 5)
-# define UxGCR_BAUD_E_MASK             (0x1f)
-# define UxGCR_BAUD_E_SHIFT            0
-
-/* USART data registers */
-__sfr at 0xc1 U0DBUF;
-__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR;
-__sfr at 0xf9 U1DBUF;
-__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR;
-
-/* USART baud rate registers, M value */
-__sfr at 0xc2 U0BAUD;
-__sfr at 0xfa U1BAUD;
-
-/* Flash controller */
-
-__sfr at 0xAE FCTL;
-#define FCTL_BUSY              (1 << 7)
-#define FCTL_SWBSY             (1 << 6)
-#define FCTL_CONTRD_ENABLE     (1 << 4)
-#define FCTL_WRITE             (1 << 1)
-#define FCTL_ERASE             (1 << 0)
-
-/* Flash write data. Write two bytes here */
-__sfr at 0xAF FWDATA;
-__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR;
-
-/* Flash write/erase address */
-__sfr at 0xAD FADDRH;
-__sfr at 0xAC FADDRL;
-
-/* Flash timing */
-__sfr at 0xAB FWT;
-
-/* Radio */
-
-__sfr at 0xD9 RFD;
-__xdata at (0xDFD9) volatile uint8_t RFDXADDR;
-
-__sfr at 0xE9 RFIF;
-#define RFIF_IM_TXUNF  (1 << 7)
-#define RFIF_IM_RXOVF  (1 << 6)
-#define RFIF_IM_TIMEOUT        (1 << 5)
-#define RFIF_IM_DONE   (1 << 4)
-#define RFIF_IM_CS     (1 << 3)
-#define RFIF_IM_PQT    (1 << 2)
-#define RFIF_IM_CCA    (1 << 1)
-#define RFIF_IM_SFD    (1 << 0)
-
-__sfr at 0x91 RFIM;
-#define RFIM_IM_TXUNF  (1 << 7)
-#define RFIM_IM_RXOVF  (1 << 6)
-#define RFIM_IM_TIMEOUT        (1 << 5)
-#define RFIM_IM_DONE   (1 << 4)
-#define RFIM_IM_CS     (1 << 3)
-#define RFIM_IM_PQT    (1 << 2)
-#define RFIM_IM_CCA    (1 << 1)
-#define RFIM_IM_SFD    (1 << 0)
-
-__sfr at 0xE1 RFST;
-
-#define RFST_SFSTXON   0x00
-#define RFST_SCAL      0x01
-#define RFST_SRX       0x02
-#define RFST_STX       0x03
-#define RFST_SIDLE     0x04
-
-__xdata __at (0xdf00) uint8_t RF[0x3c];
-
-__xdata __at (0xdf2f) uint8_t RF_IOCFG2;
-#define RF_IOCFG2_OFF  0x2f
-
-__xdata __at (0xdf30) uint8_t RF_IOCFG1;
-#define RF_IOCFG1_OFF  0x30
-
-__xdata __at (0xdf31) uint8_t RF_IOCFG0;
-#define RF_IOCFG0_OFF  0x31
-
-__xdata __at (0xdf00) uint8_t RF_SYNC1;
-#define RF_SYNC1_OFF   0x00
-
-__xdata __at (0xdf01) uint8_t RF_SYNC0;
-#define RF_SYNC0_OFF   0x01
-
-__xdata __at (0xdf02) uint8_t RF_PKTLEN;
-#define RF_PKTLEN_OFF  0x02
-
-__xdata __at (0xdf03) uint8_t RF_PKTCTRL1;
-#define RF_PKTCTRL1_OFF        0x03
-#define PKTCTRL1_PQT_MASK                      (0x7 << 5)
-#define PKTCTRL1_PQT_SHIFT                     5
-#define PKTCTRL1_APPEND_STATUS                 (1 << 2)
-#define PKTCTRL1_ADR_CHK_NONE                  (0 << 0)
-#define PKTCTRL1_ADR_CHK_NO_BROADCAST          (1 << 0)
-#define PKTCTRL1_ADR_CHK_00_BROADCAST          (2 << 0)
-#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST       (3 << 0)
-
-/* If APPEND_STATUS is used, two bytes will be added to the packet data */
-#define PKT_APPEND_STATUS_0_RSSI_MASK          (0xff)
-#define PKT_APPEND_STATUS_0_RSSI_SHIFT         0
-#define PKT_APPEND_STATUS_1_CRC_OK             (1 << 7)
-#define PKT_APPEND_STATUS_1_LQI_MASK           (0x7f)
-#define PKT_APPEND_STATUS_1_LQI_SHIFT          0
-
-__xdata __at (0xdf04) uint8_t RF_PKTCTRL0;
-#define RF_PKTCTRL0_OFF        0x04
-#define RF_PKTCTRL0_WHITE_DATA                 (1 << 6)
-#define RF_PKTCTRL0_PKT_FORMAT_NORMAL          (0 << 4)
-#define RF_PKTCTRL0_PKT_FORMAT_RANDOM          (2 << 4)
-#define RF_PKTCTRL0_CRC_EN                     (1 << 2)
-#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED                (0 << 0)
-#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE     (1 << 0)
-
-__xdata __at (0xdf05) uint8_t RF_ADDR;
-#define RF_ADDR_OFF    0x05
-
-__xdata __at (0xdf06) uint8_t RF_CHANNR;
-#define RF_CHANNR_OFF  0x06
-
-__xdata __at (0xdf07) uint8_t RF_FSCTRL1;
-#define RF_FSCTRL1_OFF 0x07
-
-#define RF_FSCTRL1_FREQ_IF_SHIFT       (0)
-
-__xdata __at (0xdf08) uint8_t RF_FSCTRL0;
-#define RF_FSCTRL0_OFF 0x08
-
-#define RF_FSCTRL0_FREQOFF_SHIFT       (0)
-
-__xdata __at (0xdf09) uint8_t RF_FREQ2;
-#define RF_FREQ2_OFF   0x09
-
-__xdata __at (0xdf0a) uint8_t RF_FREQ1;
-#define RF_FREQ1_OFF   0x0a
-
-__xdata __at (0xdf0b) uint8_t RF_FREQ0;
-#define RF_FREQ0_OFF   0x0b
-
-__xdata __at (0xdf0c) uint8_t RF_MDMCFG4;
-#define RF_MDMCFG4_OFF 0x0c
-
-#define RF_MDMCFG4_CHANBW_E_SHIFT      6
-#define RF_MDMCFG4_CHANBW_M_SHIFT      4
-#define RF_MDMCFG4_DRATE_E_SHIFT       0
-
-__xdata __at (0xdf0d) uint8_t RF_MDMCFG3;
-#define RF_MDMCFG3_OFF 0x0d
-
-#define RF_MDMCFG3_DRATE_M_SHIFT       0
-
-__xdata __at (0xdf0e) uint8_t RF_MDMCFG2;
-#define RF_MDMCFG2_OFF 0x0e
-
-#define RF_MDMCFG2_DEM_DCFILT_OFF      (1 << 7)
-#define RF_MDMCFG2_DEM_DCFILT_ON       (0 << 7)
-
-#define RF_MDMCFG2_MOD_FORMAT_MASK     (7 << 4)
-#define RF_MDMCFG2_MOD_FORMAT_2_FSK    (0 << 4)
-#define RF_MDMCFG2_MOD_FORMAT_GFSK     (1 << 4)
-#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK  (3 << 4)
-#define RF_MDMCFG2_MOD_FORMAT_MSK      (7 << 4)
-
-#define RF_MDMCFG2_MANCHESTER_EN       (1 << 3)
-
-#define RF_MDMCFG2_SYNC_MODE_MASK              (0x7 << 0)
-#define RF_MDMCFG2_SYNC_MODE_NONE              (0x0 << 0)
-#define RF_MDMCFG2_SYNC_MODE_15_16             (0x1 << 0)
-#define RF_MDMCFG2_SYNC_MODE_16_16             (0x2 << 0)
-#define RF_MDMCFG2_SYNC_MODE_30_32             (0x3 << 0)
-#define RF_MDMCFG2_SYNC_MODE_NONE_THRES                (0x4 << 0)
-#define RF_MDMCFG2_SYNC_MODE_15_16_THRES       (0x5 << 0)
-#define RF_MDMCFG2_SYNC_MODE_16_16_THRES       (0x6 << 0)
-#define RF_MDMCFG2_SYNC_MODE_30_32_THRES       (0x7 << 0)
-
-__xdata __at (0xdf0f) uint8_t RF_MDMCFG1;
-#define RF_MDMCFG1_OFF 0x0f
-
-#define RF_MDMCFG1_FEC_EN                      (1 << 7)
-#define RF_MDMCFG1_FEC_DIS                     (0 << 7)
-
-#define RF_MDMCFG1_NUM_PREAMBLE_MASK           (7 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_2              (0 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_3              (1 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_4              (2 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_6              (3 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_8              (4 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_12             (5 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_16             (6 << 4)
-#define RF_MDMCFG1_NUM_PREAMBLE_24             (7 << 4)
-
-#define RF_MDMCFG1_CHANSPC_E_MASK              (3 << 0)
-#define RF_MDMCFG1_CHANSPC_E_SHIFT             (0)
-
-__xdata __at (0xdf10) uint8_t RF_MDMCFG0;
-#define RF_MDMCFG0_OFF 0x10
-
-#define RF_MDMCFG0_CHANSPC_M_SHIFT             (0)
-
-__xdata __at (0xdf11) uint8_t RF_DEVIATN;
-#define RF_DEVIATN_OFF 0x11
-
-#define RF_DEVIATN_DEVIATION_E_SHIFT           4
-#define RF_DEVIATN_DEVIATION_M_SHIFT           0
-
-__xdata __at (0xdf12) uint8_t RF_MCSM2;
-#define RF_MCSM2_OFF   0x12
-#define RF_MCSM2_RX_TIME_RSSI                  (1 << 4)
-#define RF_MCSM2_RX_TIME_QUAL                  (1 << 3)
-#define RF_MCSM2_RX_TIME_MASK                  (0x7)
-#define RF_MCSM2_RX_TIME_SHIFT                 0
-#define RF_MCSM2_RX_TIME_END_OF_PACKET         (7)
-
-__xdata __at (0xdf13) uint8_t RF_MCSM1;
-#define RF_MCSM1_OFF   0x13
-#define RF_MCSM1_CCA_MODE_ALWAYS                       (0 << 4)
-#define RF_MCSM1_CCA_MODE_RSSI_BELOW                   (1 << 4)
-#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING             (2 << 4)
-#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING  (3 << 4)
-#define RF_MCSM1_RXOFF_MODE_IDLE                       (0 << 2)
-#define RF_MCSM1_RXOFF_MODE_FSTXON                     (1 << 2)
-#define RF_MCSM1_RXOFF_MODE_TX                         (2 << 2)
-#define RF_MCSM1_RXOFF_MODE_RX                         (3 << 2)
-#define RF_MCSM1_TXOFF_MODE_IDLE                       (0 << 0)
-#define RF_MCSM1_TXOFF_MODE_FSTXON                     (1 << 0)
-#define RF_MCSM1_TXOFF_MODE_TX                         (2 << 0)
-#define RF_MCSM1_TXOFF_MODE_RX                         (3 << 0)
-
-__xdata __at (0xdf14) uint8_t RF_MCSM0;
-#define RF_MCSM0_OFF   0x14
-#define RF_MCSM0_FS_AUTOCAL_NEVER              (0 << 4)
-#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE          (1 << 4)
-#define RF_MCSM0_FS_AUTOCAL_TO_IDLE            (2 << 4)
-#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4    (3 << 4)
-#define RF_MCSM0_MAGIC_3                       (1 << 3)
-#define RF_MCSM0_MAGIC_2                       (1 << 2)
-#define RF_MCSM0_CLOSE_IN_RX_0DB               (0 << 0)
-#define RF_MCSM0_CLOSE_IN_RX_6DB               (1 << 0)
-#define RF_MCSM0_CLOSE_IN_RX_12DB              (2 << 0)
-#define RF_MCSM0_CLOSE_IN_RX_18DB              (3 << 0)
-
-__xdata __at (0xdf15) uint8_t RF_FOCCFG;
-#define RF_FOCCFG_OFF  0x15
-#define RF_FOCCFG_FOC_BS_CS_GATE               (1 << 5)
-#define RF_FOCCFG_FOC_PRE_K_1K                 (0 << 3)
-#define RF_FOCCFG_FOC_PRE_K_2K                 (1 << 3)
-#define RF_FOCCFG_FOC_PRE_K_3K                 (2 << 3)
-#define RF_FOCCFG_FOC_PRE_K_4K                 (3 << 3)
-#define RF_FOCCFG_FOC_POST_K_PRE_K             (0 << 2)
-#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2      (1 << 2)
-#define RF_FOCCFG_FOC_LIMIT_0                  (0 << 0)
-#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8          (1 << 0)
-#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4          (2 << 0)
-#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2          (3 << 0)
-
-__xdata __at (0xdf16) uint8_t RF_BSCFG;
-#define RF_BSCFG_OFF   0x16
-#define RF_BSCFG_BS_PRE_K_1K                   (0 << 6)
-#define RF_BSCFG_BS_PRE_K_2K                   (1 << 6)
-#define RF_BSCFG_BS_PRE_K_3K                   (2 << 6)
-#define RF_BSCFG_BS_PRE_K_4K                   (3 << 6)
-#define RF_BSCFG_BS_PRE_KP_1KP                 (0 << 4)
-#define RF_BSCFG_BS_PRE_KP_2KP                 (1 << 4)
-#define RF_BSCFG_BS_PRE_KP_3KP                 (2 << 4)
-#define RF_BSCFG_BS_PRE_KP_4KP                 (3 << 4)
-#define RF_BSCFG_BS_POST_KI_PRE_KI             (0 << 3)
-#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2      (1 << 3)
-#define RF_BSCFG_BS_POST_KP_PRE_KP             (0 << 2)
-#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2      (1 << 2)
-#define RF_BSCFG_BS_LIMIT_0                    (0 << 0)
-#define RF_BSCFG_BS_LIMIT_3_125                        (1 << 0)
-#define RF_BSCFG_BS_LIMIT_6_25                 (2 << 0)
-#define RF_BSCFG_BS_LIMIT_12_5                 (3 << 0)
-
-__xdata __at (0xdf17) uint8_t RF_AGCCTRL2;
-#define RF_AGCCTRL2_OFF        0x17
-
-__xdata __at (0xdf18) uint8_t RF_AGCCTRL1;
-#define RF_AGCCTRL1_OFF        0x18
-
-__xdata __at (0xdf19) uint8_t RF_AGCCTRL0;
-#define RF_AGCCTRL0_OFF        0x19
-
-__xdata __at (0xdf1a) uint8_t RF_FREND1;
-#define RF_FREND1_OFF  0x1a
-
-#define RF_FREND1_LNA_CURRENT_SHIFT            6
-#define RF_FREND1_LNA2MIX_CURRENT_SHIFT                4
-#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT   2
-#define RF_FREND1_MIX_CURRENT_SHIFT            0
-
-__xdata __at (0xdf1b) uint8_t RF_FREND0;
-#define RF_FREND0_OFF  0x1b
-
-#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK    (0x3 << 4)
-#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT   4
-#define RF_FREND0_PA_POWER_MASK                        (0x7)
-#define RF_FREND0_PA_POWER_SHIFT               0
-
-__xdata __at (0xdf1c) uint8_t RF_FSCAL3;
-#define RF_FSCAL3_OFF  0x1c
-
-__xdata __at (0xdf1d) uint8_t RF_FSCAL2;
-#define RF_FSCAL2_OFF  0x1d
-
-__xdata __at (0xdf1e) uint8_t RF_FSCAL1;
-#define RF_FSCAL1_OFF  0x1e
-
-__xdata __at (0xdf1f) uint8_t RF_FSCAL0;
-#define RF_FSCAL0_OFF  0x1f
-
-__xdata __at (0xdf23) uint8_t RF_TEST2;
-#define RF_TEST2_OFF   0x23
-
-#define RF_TEST2_NORMAL_MAGIC          0x88
-#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC        0x81
-
-__xdata __at (0xdf24) uint8_t RF_TEST1;
-#define RF_TEST1_OFF   0x24
-
-#define RF_TEST1_TX_MAGIC              0x31
-#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC        0x35
-
-__xdata __at (0xdf25) uint8_t RF_TEST0;
-#define RF_TEST0_OFF   0x25
-
-#define RF_TEST0_7_2_MASK              (0xfc)
-#define RF_TEST0_VCO_SEL_CAL_EN                (1 << 1)
-#define RF_TEST0_0_MASK                        (1)
-
-/* These are undocumented, and must be computed
- * using the provided tool.
- */
-__xdata __at (0xdf27) uint8_t RF_PA_TABLE7;
-#define RF_PA_TABLE7_OFF       0x27
-
-__xdata __at (0xdf28) uint8_t RF_PA_TABLE6;
-#define RF_PA_TABLE6_OFF       0x28
-
-__xdata __at (0xdf29) uint8_t RF_PA_TABLE5;
-#define RF_PA_TABLE5_OFF       0x29
-
-__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4;
-#define RF_PA_TABLE4_OFF       0x2a
-
-__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3;
-#define RF_PA_TABLE3_OFF       0x2b
-
-__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2;
-#define RF_PA_TABLE2_OFF       0x2c
-
-__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1;
-#define RF_PA_TABLE1_OFF       0x2d
-
-__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0;
-#define RF_PA_TABLE0_OFF       0x2e
-
-__xdata __at (0xdf36) uint8_t RF_PARTNUM;
-#define RF_PARTNUM_OFF 0x36
-
-__xdata __at (0xdf37) uint8_t RF_VERSION;
-#define RF_VERSION_OFF 0x37
-
-__xdata __at (0xdf38) uint8_t RF_FREQEST;
-#define RF_FREQEST_OFF 0x38
-
-__xdata __at (0xdf39) uint8_t RF_LQI;
-#define RF_LQI_OFF     0x39
-
-#define RF_LQI_CRC_OK                  (1 << 7)
-#define RF_LQI_LQI_EST_MASK            (0x7f)
-
-__xdata __at (0xdf3a) uint8_t RF_RSSI;
-#define RF_RSSI_OFF    0x3a
-
-__xdata __at (0xdf3b) uint8_t RF_MARCSTATE;
-#define RF_MARCSTATE_OFF       0x3b
-
-#define RF_MARCSTATE_MASK              0x1f
-#define RF_MARCSTATE_SLEEP             0x00
-#define RF_MARCSTATE_IDLE              0x01
-#define RF_MARCSTATE_VCOON_MC          0x03
-#define RF_MARCSTATE_REGON_MC          0x04
-#define RF_MARCSTATE_MANCAL            0x05
-#define RF_MARCSTATE_VCOON             0x06
-#define RF_MARCSTATE_REGON             0x07
-#define RF_MARCSTATE_STARTCAL          0x08
-#define RF_MARCSTATE_BWBOOST           0x09
-#define RF_MARCSTATE_FS_LOCK           0x0a
-#define RF_MARCSTATE_IFADCON           0x0b
-#define RF_MARCSTATE_ENDCAL            0x0c
-#define RF_MARCSTATE_RX                        0x0d
-#define RF_MARCSTATE_RX_END            0x0e
-#define RF_MARCSTATE_RX_RST            0x0f
-#define RF_MARCSTATE_TXRX_SWITCH       0x10
-#define RF_MARCSTATE_RX_OVERFLOW       0x11
-#define RF_MARCSTATE_FSTXON            0x12
-#define RF_MARCSTATE_TX                        0x13
-#define RF_MARCSTATE_TX_END            0x14
-#define RF_MARCSTATE_RXTX_SWITCH       0x15
-#define RF_MARCSTATE_TX_UNDERFLOW      0x16
-
-
-__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS;
-#define RF_PKTSTATUS_OFF       0x3c
-
-#define RF_PKTSTATUS_CRC_OK            (1 << 7)
-#define RF_PKTSTATUS_CS                        (1 << 6)
-#define RF_PKTSTATUS_PQT_REACHED       (1 << 5)
-#define RF_PKTSTATUS_CCA               (1 << 4)
-#define RF_PKTSTATUS_SFD               (1 << 3)
-
-__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC;
-#define RF_VCO_VC_DAC_OFF      0x3d
-
-#endif
diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111
new file mode 100644 (file)
index 0000000..8de4a9b
--- /dev/null
@@ -0,0 +1,27 @@
+CC=sdcc
+
+CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE)
+
+CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product
+
+CODESIZE ?= 0x8000
+
+LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \
+       --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff
+
+REL=$(SRC:.c=.rel) ao_product.rel
+ADB=$(REL:.rel=.adb)
+ASM=$(REL:.rel=.asm)
+LNK=$(REL:.rel=.lnk)
+LST=$(REL:.rel=.lst)
+RST=$(REL:.rel=.rst)
+SYM=$(REL:.rel=.sym)
+
+PCDB=$(PROG:.ihx=.cdb)
+PLNK=$(PROG:.ihx=.lnk)
+PMAP=$(PROG:.ihx=.map)
+PMEM=$(PROG:.ihx=.mem)
+PAOM=$(PROG:.ihx=)
+
+%.rel : %.c $(INC)
+       $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $<
diff --git a/src/cc1111/_bp.c b/src/cc1111/_bp.c
new file mode 100644 (file)
index 0000000..6bf135b
--- /dev/null
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+
+  _bp.c :- just declares bp as a variable
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
+
+   This library is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This library 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+__data unsigned char bp ;
diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c
new file mode 100644 (file)
index 0000000..786dfd1
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pins.h"
+
+volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING];
+#if HAS_ACCEL_REF
+volatile __xdata uint16_t      ao_accel_ref[AO_ADC_RING];
+#endif
+volatile __data uint8_t                ao_adc_head;
+
+void
+ao_adc_poll(void)
+{
+#if HAS_ACCEL_REF
+       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2;
+#else
+# ifdef TELENANO_V_0_1
+       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1;
+# else
+       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0;
+# endif
+#endif
+}
+
+void
+ao_adc_get(__xdata struct ao_adc *packet)
+{
+       uint8_t i = ao_adc_ring_prev(ao_sample_adc);
+       memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc));
+}
+
+void
+ao_adc_isr(void) __interrupt 1
+{
+       uint8_t sequence;
+       uint8_t __xdata *a;
+
+       sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT;
+#if IGNITE_ON_P2
+       /* TeleMetrum readings */
+#if HAS_ACCEL_REF
+       if (sequence == 2) {
+               a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]);
+               sequence = 0;
+       } else
+#endif
+       {
+               if (sequence == ADCCON3_ECH_TEMP)
+                       sequence = 2;
+               a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence);
+               sequence++;
+       }
+#define GOT_ADC
+       a[0] = ADCL;
+       a[1] = ADCH;
+       if (sequence < 6) {
+#if HAS_EXTERNAL_TEMP == 0
+               /* start next channel conversion */
+               /* v0.2 replaces external temp sensor with internal one */
+               if (sequence == 2)
+                       ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
+               else
+#endif
+                       ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence;
+       }
+#endif
+
+#if IGNITE_ON_P0
+       /* TeleMini readings */
+       a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres);
+#ifdef TELEMINI_V_1_0
+       switch (sequence) {
+       case 0:
+               /* pressure */
+               a += 0;
+               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1;
+               break;
+       case 1:
+               /* drogue sense */
+               a += 6;
+               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2;
+               break;
+       case 2:
+               /* main sense */
+               a += 8;
+               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3;
+               break;
+       case 3:
+               /* battery */
+               a += 4;
+               sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
+               break;
+       case ADCCON3_ECH_TEMP:
+               a += 2;
+               sequence = 0;
+               break;
+       }
+#define GOT_ADC
+#endif
+#ifdef TELENANO_V_0_1
+       switch (sequence) {
+       case 1:
+               /* pressure */
+               a += 0;
+               sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3;
+               break;
+       case 3:
+               /* battery */
+               a += 4;
+               sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP;
+               break;
+       case ADCCON3_ECH_TEMP:
+               a += 2;
+               sequence = 0;
+               break;
+       }
+#define GOT_ADC
+#endif
+       a[0] = ADCL;
+       a[1] = ADCH;
+       if (sequence) {
+               /* Start next conversion */
+               ADCCON3 = sequence;
+       }
+#endif
+#ifndef GOT_ADC
+#error No known ADC configuration set
+#endif
+
+       else {
+               /* record this conversion series */
+               ao_adc_ring[ao_adc_head].tick = ao_time();
+               ao_adc_head = ao_adc_ring_next(ao_adc_head);
+               ao_wakeup(DATA_TO_XDATA(&ao_adc_head));
+       }
+}
+
+static void
+ao_adc_dump(void) __reentrant
+{
+       static __xdata struct ao_adc    packet;
+       ao_adc_get(&packet);
+       printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n",
+              packet.tick, packet.accel, packet.pres, packet.temp,
+              packet.v_batt, packet.sense_d, packet.sense_m);
+}
+
+__code struct ao_cmds ao_adc_cmds[] = {
+       { ao_adc_dump,  "a\0Current ADC" },
+       { 0, NULL },
+};
+
+void
+ao_adc_init(void)
+{
+#if IGNITE_ON_P2
+       /* TeleMetrum configuration */
+       ADCCFG = ((1 << 0) |    /* acceleration */
+                 (1 << 1) |    /* pressure */
+#if HAS_EXTERNAL_TEMP
+                 (1 << 2) |    /* v0.1 temperature */
+#endif
+                 (1 << 3) |    /* battery voltage */
+                 (1 << 4) |    /* drogue sense */
+                 (1 << 5));    /* main sense */
+#endif
+
+#if IGNITE_ON_P0
+       /* TeleMini configuration */
+       ADCCFG = ((1 << 0) |    /* pressure */
+                 (1 << 1) |    /* drogue sense */
+                 (1 << 2) |    /* main sense */
+                 (1 << 3));    /* battery voltage */
+#endif
+
+       /* enable interrupts */
+       ADCIF = 0;
+       IEN0 |= IEN0_ADCIE;
+       ao_cmd_register(&ao_adc_cmds[0]);
+}
diff --git a/src/cc1111/ao_beep.c b/src/cc1111/ao_beep.c
new file mode 100644 (file)
index 0000000..3642f4c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+ao_beep(uint8_t beep)
+{
+       if (beep == 0) {
+               P2_0 = 0;
+               P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO;
+               T4CTL = 0;
+       } else {
+               P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL;
+               T4CC0 = beep;
+               T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START;
+       }
+}
+
+void
+ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant
+{
+       ao_beep(beep);
+       ao_delay(ticks);
+       ao_beep(0);
+}
+
+void
+ao_beep_init(void)
+{
+       /* Our beeper is on P2_0, which is hooked to timer 4 using
+        * configuration alternative 2
+        */
+       P2_0 = 0;
+       P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO;
+       PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2;
+       T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE;
+}
diff --git a/src/cc1111/ao_dbg.c b/src/cc1111/ao_dbg.c
new file mode 100644 (file)
index 0000000..d4c9567
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pins.h"
+
+static void
+ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant
+{
+       DBG_PORT = (DBG_PORT & ~msk) | (val & msk);
+       _asm
+               nop
+               nop
+       _endasm;
+}
+
+void
+ao_dbg_send_byte(uint8_t byte)
+{
+       __pdata uint8_t b, d;
+
+       DBG_PORT |= DBG_DATA;
+       DBG_PORT_DIR |= DBG_DATA;
+       for (b = 0; b < 8; b++) {
+               d = 0;
+               if (byte & 0x80)
+                       d = DBG_DATA;
+               byte <<= 1;
+               ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d);
+               ao_dbg_send_bits(DBG_CLOCK|DBG_DATA,     0    |d);
+       }
+       DBG_PORT_DIR &= ~DBG_DATA;
+}
+
+uint8_t
+ao_dbg_recv_byte(void)
+{
+       __pdata uint8_t byte, b;
+
+       byte = 0;
+       for (b = 0; b < 8; b++) {
+               byte = byte << 1;
+               ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK);
+               if (DBG_DATA_PIN)
+                       byte |= 1;
+               ao_dbg_send_bits(DBG_CLOCK, 0);
+       }
+       return byte;
+}
+
+/* 8051 instructions
+ */
+#define NOP                    0x00
+#define MOV_direct_data                0x75
+#define LJMP                   0x02
+#define MOV_Rn_data(n)         (0x78 | (n))
+#define DJNZ_Rn_rel(n)         (0xd8 | (n))
+#define MOV_A_direct           0xe5
+#define MOV_direct1_direct2    0x85
+#define MOV_direct_A           0xf5
+#define MOV_DPTR_data16                0x90
+#define MOV_A_data             0x74
+#define MOVX_atDPTR_A          0xf0
+#define MOVX_A_atDPTR          0xe0
+#define INC_DPTR               0xa3
+#define TRAP                   0xa5
+#define SJMP                   0x80
+#define JB                     0x20
+
+#define DEBUG_INSTR(l)         (0x54 | (l))
+
+#define SFR_PSW                        0xD0
+#define SFR_DPL0               0x82
+#define SFR_DPH0               0x83
+#define SFR_DPL1               0x84
+#define SFR_DPH1               0x85
+
+__pdata uint8_t        save_acc;
+__pdata uint8_t save_psw;
+__pdata uint8_t save_dpl0;
+__pdata uint8_t save_dph0;
+__pdata uint8_t save_dpl1;
+__pdata uint8_t save_dph1;
+
+static uint8_t
+ao_dbg_inst1(uint8_t a) __reentrant
+{
+       ao_dbg_send_byte(DEBUG_INSTR(1));
+       ao_dbg_send_byte(a);
+       return ao_dbg_recv_byte();
+}
+
+static uint8_t
+ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant
+{
+       ao_dbg_send_byte(DEBUG_INSTR(2));
+       ao_dbg_send_byte(a);
+       ao_dbg_send_byte(b);
+       return ao_dbg_recv_byte();
+}
+
+static uint8_t
+ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant
+{
+       ao_dbg_send_byte(DEBUG_INSTR(3));
+       ao_dbg_send_byte(a);
+       ao_dbg_send_byte(b);
+       ao_dbg_send_byte(c);
+       return ao_dbg_recv_byte();
+}
+
+void
+ao_dbg_start_transfer(uint16_t addr)
+{
+       save_acc  = ao_dbg_inst1(NOP);
+       save_psw  = ao_dbg_inst2(MOV_A_direct, SFR_PSW);
+       save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0);
+       save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0);
+       save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1);
+       save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1);
+       ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr);
+}
+
+void
+ao_dbg_end_transfer(void)
+{
+       ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0);
+       ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0);
+       ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1);
+       ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1);
+       ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw);
+       ao_dbg_inst2(MOV_A_data, save_acc);
+}
+
+void
+ao_dbg_write_byte(uint8_t byte)
+{
+       ao_dbg_inst2(MOV_A_data, byte);
+       ao_dbg_inst1(MOVX_atDPTR_A);
+       ao_dbg_inst1(INC_DPTR);
+}
+
+uint8_t
+ao_dbg_read_byte(void)
+{
+       ao_dbg_inst1(MOVX_A_atDPTR);
+       return ao_dbg_inst1(INC_DPTR);
+}
+
+static void
+ao_dbg_set_pins(void)
+{
+       /* Make the DBG pins GPIOs. On TeleMetrum, this will
+        * disable the SPI link, so don't expect SPI to work after
+        * using the debugger.
+        */
+       DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N);
+
+       /* make DBG_DATA tri-state */
+       DBG_PORT_INP |= DBG_DATA;
+
+       /* Raise RESET_N and CLOCK */
+       DBG_PORT |= DBG_RESET_N | DBG_CLOCK;
+
+       /* RESET_N and CLOCK are outputs now */
+       DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK;
+       DBG_PORT_DIR &= ~DBG_DATA;
+}
+
+static void
+ao_dbg_long_delay(void)
+{
+       uint8_t n;
+
+       for (n = 0; n < 20; n++)
+               _asm nop _endasm;
+}
+
+#define AO_RESET_LOW_DELAY     AO_MS_TO_TICKS(100)
+#define AO_RESET_HIGH_DELAY    AO_MS_TO_TICKS(100)
+
+void
+ao_dbg_debug_mode(void)
+{
+       ao_dbg_set_pins();
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N,     0    |DBG_DATA|    0    );
+       ao_delay(AO_RESET_LOW_DELAY);
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N,     0    |DBG_DATA|    0    );
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N,     0    |DBG_DATA|DBG_RESET_N);
+       ao_delay(AO_RESET_HIGH_DELAY);
+}
+
+void
+ao_dbg_reset(void)
+{
+       ao_dbg_set_pins();
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
+       ao_delay(AO_RESET_LOW_DELAY);
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|    0    );
+       ao_dbg_long_delay();
+       ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
+       ao_delay(AO_RESET_HIGH_DELAY);
+}
+
+static void
+debug_enable(void)
+{
+       ao_dbg_debug_mode();
+}
+
+static void
+debug_reset(void)
+{
+       ao_dbg_reset();
+}
+
+static void
+debug_put(void)
+{
+       for (;;) {
+               ao_cmd_white ();
+               if (ao_cmd_lex_c == '\n')
+                       break;
+               ao_cmd_hex();
+               if (ao_cmd_status != ao_cmd_success)
+                       break;
+               ao_dbg_send_byte(ao_cmd_lex_i);
+       }
+}
+
+static void
+debug_get(void)
+{
+       __pdata uint16_t count;
+       __pdata uint16_t i;
+       __pdata uint8_t byte;
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       count = ao_cmd_lex_i;
+       if (count > 256) {
+               ao_cmd_status = ao_cmd_syntax_error;
+               return;
+       }
+       for (i = 0; i < count; i++) {
+               if (i && (i & 7) == 0)
+                       putchar('\n');
+               byte = ao_dbg_recv_byte();
+               ao_cmd_put8(byte);
+               putchar(' ');
+       }
+       putchar('\n');
+}
+
+static uint8_t
+getnibble(void)
+{
+       __pdata char    c;
+
+       c = getchar();
+       if ('0' <= c && c <= '9')
+               return c - '0';
+       if ('a' <= c && c <= 'f')
+               return c - ('a' - 10);
+       if ('A' <= c && c <= 'F')
+               return c - ('A' - 10);
+       ao_cmd_status = ao_cmd_lex_error;
+       return 0;
+}
+
+static void
+debug_input(void)
+{
+       __pdata uint16_t count;
+       __pdata uint16_t addr;
+       __pdata uint8_t b;
+       __pdata uint8_t i;
+
+       ao_cmd_hex();
+       count = ao_cmd_lex_i;
+       ao_cmd_hex();
+       addr = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_dbg_start_transfer(addr);
+       i = 0;
+       while (count--) {
+               if (!(i++ & 7))
+                       putchar('\n');
+               b = ao_dbg_read_byte();
+               ao_cmd_put8(b);
+       }
+       ao_dbg_end_transfer();
+       putchar('\n');
+}
+
+static void
+debug_output(void)
+{
+       __pdata uint16_t count;
+       __pdata uint16_t addr;
+       __pdata uint8_t b;
+
+       ao_cmd_hex();
+       count = ao_cmd_lex_i;
+       ao_cmd_hex();
+       addr = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_dbg_start_transfer(addr);
+       while (count--) {
+               b = getnibble() << 4;
+               b |= getnibble();
+               if (ao_cmd_status != ao_cmd_success)
+                       return;
+               ao_dbg_write_byte(b);
+       }
+       ao_dbg_end_transfer();
+}
+
+__code struct ao_cmds ao_dbg_cmds[7] = {
+       { debug_enable, "D\0Enable debug" },
+       { debug_get,    "G <count>\0Get data" },
+       { debug_input,  "I <count> <addr>\0Input <count> at <addr>" },
+       { debug_output, "O <count> <addr>\0Output <count> at <addr>" },
+       { debug_put,    "P <byte> ...\0Put data" },
+       { debug_reset,  "R\0Reset" },
+       { 0, NULL },
+};
+
+void
+ao_dbg_init(void)
+{
+       ao_cmd_register(&ao_dbg_cmds[0]);
+}
diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c
new file mode 100644 (file)
index 0000000..6052964
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#define NUM_DMA        5
+
+/*
+ * The config address for DMA0 is programmed
+ * separately from that of DMA1-4, but for simplicity,
+ * we make them all contiguous.
+ */
+
+static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA];
+static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA];
+static __data uint8_t ao_next_dma;
+
+uint8_t
+ao_dma_alloc(__xdata uint8_t *done)
+{
+       uint8_t id;
+
+       if (ao_next_dma == NUM_DMA)
+               ao_panic(AO_PANIC_DMA);
+       id = ao_next_dma++;
+       ao_dma_done[id] = done;
+
+       /* When the first dma object is allocated, set up the DMA
+        * controller
+        */
+       if (id == 0) {
+               DMAIRQ = 0;
+               DMAIF = 0;
+               IEN1 |= IEN1_DMAIE;
+       }
+
+       return id;
+}
+
+void
+ao_dma_set_transfer(uint8_t id,
+                   void __xdata *srcaddr,
+                   void __xdata *dstaddr,
+                   uint16_t count,
+                   uint8_t cfg0,
+                   uint8_t cfg1)
+{
+       if (DMAARM & (1 << id))
+               ao_panic(AO_PANIC_DMA);
+       ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8;
+       ao_dma_config[id].src_low = ((uint16_t) srcaddr);
+       ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8;
+       ao_dma_config[id].dst_low = ((uint16_t) dstaddr);
+       ao_dma_config[id].len_high = count >> 8;
+       ao_dma_config[id].len_low = count;
+       ao_dma_config[id].cfg0 = cfg0;
+       ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK;
+       if (id == 0) {
+               DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8;
+               DMA0CFGL = ((uint16_t) (&ao_dma_config[0]));
+       } else {
+               DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8;
+               DMA1CFGL = ((uint16_t) (&ao_dma_config[1]));
+       }
+}
+
+#define nop()  _asm nop _endasm;
+
+void
+ao_dma_start(uint8_t id)
+{
+       uint8_t mask = (1 << id);
+       DMAIRQ &= ~mask;
+       DMAARM = 0x80 | mask;
+       nop(); nop(); nop(); nop();
+       nop(); nop(); nop(); nop();
+       *(ao_dma_done[id]) = 0;
+       DMAARM = mask;
+       nop(); nop(); nop(); nop();
+       nop(); nop(); nop(); nop();
+       nop();
+}
+
+void
+ao_dma_trigger(uint8_t id)
+{
+       DMAREQ |= (1 << id);
+}
+
+void
+ao_dma_abort(uint8_t id)
+{
+       uint8_t mask = (1 << id);
+       DMAARM = 0x80 | mask;
+       DMAIRQ &= ~mask;
+}
+
+void
+ao_dma_isr(void) __interrupt 8
+{
+       uint8_t id, mask;
+
+       /* Find the first DMA channel which is done */
+       mask = 1;
+       for (id = 0; id < ao_next_dma; id++) {
+               if (DMAIRQ & mask) {
+                       /* Clear CPU interrupt flag */
+                       DMAIF = 0;
+                       /* Clear the completed ID */
+                       DMAIRQ = ~mask;
+                       *(ao_dma_done[id]) = 1;
+                       ao_wakeup(ao_dma_done[id]);
+                       break;
+               }
+               mask <<= 1;
+       }
+}
diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c
new file mode 100644 (file)
index 0000000..5238beb
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#if IGNITE_ON_P2
+#define AO_IGNITER_DROGUE      P2_3
+#define AO_IGNITER_MAIN                P2_4
+#define AO_IGNITER_DIR         P2DIR
+#define AO_IGNITER_DROGUE_BIT  (1 << 3)
+#define AO_IGNITER_MAIN_BIT    (1 << 4)
+#endif
+
+#if IGNITE_ON_P0
+#define AO_IGNITER_DROGUE      P0_5
+#define AO_IGNITER_MAIN                P0_4
+#define AO_IGNITER_DIR         P0DIR
+#define AO_IGNITER_DROGUE_BIT  (1 << 5)
+#define AO_IGNITER_MAIN_BIT    (1 << 4)
+#endif
+
+/* test these values with real igniters */
+#define AO_IGNITER_OPEN                1000
+#define AO_IGNITER_CLOSED      7000
+#define AO_IGNITER_FIRE_TIME   AO_MS_TO_TICKS(50)
+#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000)
+
+struct ao_ignition {
+       uint8_t request;
+       uint8_t fired;
+       uint8_t firing;
+};
+
+__xdata struct ao_ignition ao_ignition[2];
+
+void
+ao_ignite(enum ao_igniter igniter) __critical
+{
+       ao_ignition[igniter].request = 1;
+       ao_wakeup(&ao_ignition);
+}
+
+enum ao_igniter_status
+ao_igniter_status(enum ao_igniter igniter)
+{
+       __xdata struct ao_adc adc;
+       __pdata int16_t value;
+       __pdata uint8_t request, firing, fired;
+
+       __critical {
+               ao_adc_get(&adc);
+               request = ao_ignition[igniter].request;
+               fired = ao_ignition[igniter].fired;
+               firing = ao_ignition[igniter].firing;
+       }
+       if (firing || (request && !fired))
+               return ao_igniter_active;
+
+       value = (AO_IGNITER_CLOSED>>1);
+       switch (igniter) {
+       case ao_igniter_drogue:
+               value = adc.sense_d;
+               break;
+       case ao_igniter_main:
+               value = adc.sense_m;
+               break;
+       }
+       if (value < AO_IGNITER_OPEN)
+               return ao_igniter_open;
+       else if (value > AO_IGNITER_CLOSED)
+               return ao_igniter_ready;
+       else
+               return ao_igniter_unknown;
+}
+
+void
+ao_igniter_fire(enum ao_igniter igniter) __critical
+{
+       ao_ignition[igniter].firing = 1;
+       switch(ao_config.ignite_mode) {
+       case AO_IGNITE_MODE_DUAL:
+               switch (igniter) {
+               case ao_igniter_drogue:
+                       AO_IGNITER_DROGUE = 1;
+                       ao_delay(AO_IGNITER_FIRE_TIME);
+                       AO_IGNITER_DROGUE = 0;
+                       break;
+               case ao_igniter_main:
+                       AO_IGNITER_MAIN = 1;
+                       ao_delay(AO_IGNITER_FIRE_TIME);
+                       AO_IGNITER_MAIN = 0;
+                       break;
+               }
+               break;
+       case AO_IGNITE_MODE_APOGEE:
+               switch (igniter) {
+               case ao_igniter_drogue:
+                       AO_IGNITER_DROGUE = 1;
+                       ao_delay(AO_IGNITER_FIRE_TIME);
+                       AO_IGNITER_DROGUE = 0;
+                       ao_delay(AO_IGNITER_CHARGE_TIME);
+                       AO_IGNITER_MAIN = 1;
+                       ao_delay(AO_IGNITER_FIRE_TIME);
+                       AO_IGNITER_MAIN = 0;
+                       break;
+               }
+               break;
+       case AO_IGNITE_MODE_MAIN:
+               switch (igniter) {
+               case ao_igniter_main:
+                       AO_IGNITER_DROGUE = 1;
+                       ao_delay(AO_IGNITER_FIRE_TIME);
+                       AO_IGNITER_DROGUE = 0;
+                       ao_delay(AO_IGNITER_CHARGE_TIME);
+                       AO_IGNITER_MAIN = 1;
+                       ao_delay(AO_IGNITER_FIRE_TIME);
+                       AO_IGNITER_MAIN = 0;
+                       break;
+               }
+               break;
+       }
+       ao_ignition[igniter].firing = 0;
+}
+
+void
+ao_igniter(void)
+{
+       __xdata enum ao_ignter 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;
+                       }
+               }
+       }
+}
+
+void
+ao_ignite_manual(void)
+{
+       ao_cmd_white();
+       if (!ao_match_word("DoIt"))
+               return;
+       ao_cmd_white();
+       if (ao_cmd_lex_c == 'm') {
+               if(ao_match_word("main"))
+                       ao_igniter_fire(ao_igniter_main);
+       } else {
+               if(ao_match_word("drogue"))
+                       ao_igniter_fire(ao_igniter_drogue);
+       }
+}
+
+static __code char * __code igniter_status_names[] = {
+       "unknown", "ready", "active", "open"
+};
+
+void
+ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant
+{
+       enum ao_igniter_status status = ao_igniter_status(igniter);
+       printf("Igniter: %6s Status: %s\n",
+              name,
+              igniter_status_names[status]);
+}
+
+void
+ao_ignite_test(void)
+{
+       ao_ignite_print_status(ao_igniter_drogue, "drogue");
+       ao_ignite_print_status(ao_igniter_main, "main");
+}
+
+__code struct ao_cmds ao_ignite_cmds[] = {
+       { ao_ignite_manual,     "i <key> {main|drogue}\0Fire igniter. <key> is doit with D&I" },
+       { ao_ignite_test,       "t\0Test igniter" },
+       { 0,    NULL },
+};
+
+__xdata struct ao_task ao_igniter_task;
+
+void
+ao_ignite_set_pins(void)
+{
+       AO_IGNITER_DROGUE = 0;
+       AO_IGNITER_MAIN = 0;
+       AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT;
+}
+
+void
+ao_igniter_init(void)
+{
+       ao_ignite_set_pins();
+       ao_cmd_register(&ao_ignite_cmds[0]);
+       ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
+}
diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c
new file mode 100644 (file)
index 0000000..d76d954
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2011  Anthony Towns <aj@erisian.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "cc1111.h"
+
+#define ENDOFCODE  (CODESIZE)
+#define AO_INTFLASH_BLOCK      1024
+#define AO_INTFLASH_BLOCKS     ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK)
+#define AO_INTFLASH_SIZE       (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS)
+#define AO_INTFLASH_LOCATION   (0x8000 - AO_INTFLASH_SIZE)
+
+/*
+ *       21000 * 24e6
+ * FWT = ------------
+ *           16e9
+ *
+ *     = 31.5
+ *
+ * Round up and use 32
+ */
+
+#define FLASH_TIMING   0x20
+
+#if AO_INTFLASH_BLOCKS < 2
+#error "Too few pages"
+#endif
+
+#if AO_INFTLASH_LOCATION % 1024 != 0
+#error "Pages aren't aligned properly"
+#endif
+
+__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE];
+
+/* Total bytes of available storage */
+__pdata uint32_t       ao_storage_total = sizeof(ao_intflash);
+
+/* Block size - device is erased in these units. */
+__pdata uint32_t       ao_storage_block = AO_INTFLASH_BLOCK;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+__pdata uint32_t       ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. */
+__pdata uint16_t       ao_storage_unit = AO_INTFLASH_BLOCK;
+
+__xdata static uint8_t  ao_intflash_dma_done;
+static uint8_t ao_intflash_dma;
+
+/*
+ * The internal flash chip is arranged in 1kB sectors; the
+ * chip cannot erase in units smaller than that.
+ *
+ * Writing happens in units of 2 bytes and
+ * can only change bits from 1 to 0. So, you can rewrite
+ * the same contents, or append to an existing page easily enough
+ */
+
+/*
+ * Erase the specified sector
+ */
+uint8_t
+ao_storage_erase(uint32_t pos) __reentrant
+{
+       uint16_t addr;
+
+       if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total)
+               return 0;
+
+       addr = ((uint16_t)(ao_intflash + pos) >> 1);
+
+       FADDRH = addr >> 8;
+       FADDRL = addr;
+
+       __critical {
+               _asm
+               .even
+               orl _FCTL, #FCTL_ERASE;         ; FCTL |=  FCTL_ERASE
+               nop                             ; Required, see datasheet.
+               _endasm;
+       }
+
+       return 1;
+}
+
+/*
+ * Write to flash
+ */
+
+static void
+ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant
+{
+       pos = ((uint16_t) ao_intflash + pos) >> 1;
+
+       ao_dma_set_transfer(ao_intflash_dma,
+                           d,
+                           &FWDATAXADDR,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_FLASH,
+                           DMA_CFG1_SRCINC_1 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_HIGH);
+
+       FADDRH = pos >> 8;
+       FADDRL = pos;
+
+       ao_dma_start(ao_intflash_dma);
+
+       __critical {
+               _asm
+               .even
+               orl _FCTL, #FCTL_WRITE;         ; FCTL |=  FCTL_WRITE
+               nop
+               _endasm;
+       }
+}
+
+static void
+ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant
+{
+       static __xdata uint8_t b[2];
+
+       if (pos & 1) {
+               b[0] = 0xff;
+               b[1] = byte;
+       } else {
+               b[0] = byte;
+               b[1] = 0xff;
+       }
+       ao_intflash_write_aligned(pos, b, 2);
+}
+
+uint8_t
+ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant
+{
+       uint16_t pos = pos32;
+       __xdata uint8_t *d = v;
+       uint8_t oddlen;
+
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+       if (len == 0)
+               return 1;
+
+       if (pos & 1) {
+               ao_intflash_write_byte(pos++, *d++);
+               len--;
+       }
+       oddlen = len & 1;
+       len -= oddlen;
+       if (len)
+               ao_intflash_write_aligned(pos, d, len);
+       if (oddlen)
+               ao_intflash_write_byte(pos + len, d[len]);
+
+       return 1;
+}
+
+/*
+ * Read from flash
+ */
+uint8_t
+ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
+{
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+       memcpy(d, ao_intflash+pos, len);
+       return 1;
+}
+
+void
+ao_storage_flush(void) __reentrant
+{
+}
+
+void
+ao_storage_setup(void)
+{
+}
+
+void
+ao_storage_device_info(void) __reentrant
+{
+       printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION);
+}
+
+void
+ao_storage_device_init(void)
+{
+       ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done);
+
+       FWT = FLASH_TIMING;
+}
diff --git a/src/cc1111/ao_led.c b/src/cc1111/ao_led.c
new file mode 100644 (file)
index 0000000..5beed58
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__pdata uint8_t ao_led_enable;
+
+void
+ao_led_on(uint8_t colors)
+{
+       P1 |= (colors & ao_led_enable);
+}
+
+void
+ao_led_off(uint8_t colors)
+{
+       P1 &= ~(colors & ao_led_enable);
+}
+
+void
+ao_led_set(uint8_t colors)
+{
+       P1 = (P1 & ~(ao_led_enable)) | (colors & ao_led_enable);
+}
+
+void
+ao_led_toggle(uint8_t colors)
+{
+       P1 ^= (colors & ao_led_enable);
+}
+
+void
+ao_led_for(uint8_t colors, uint16_t ticks) __reentrant
+{
+       ao_led_on(colors);
+       ao_delay(ticks);
+       ao_led_off(colors);
+}
+
+void
+ao_led_init(uint8_t enable)
+{
+       ao_led_enable = enable;
+       P1SEL &= ~enable;
+       P1 &= ~enable;
+       P1DIR |= enable;
+}
diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c
new file mode 100644 (file)
index 0000000..f627e02
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__xdata struct ao_packet_recv ao_rx_packet;
+__xdata struct ao_packet ao_tx_packet;
+__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
+
+static __xdata char tx_data[AO_PACKET_MAX];
+static __xdata char rx_data[AO_PACKET_MAX];
+static __pdata uint8_t rx_seq;
+
+__xdata struct ao_task ao_packet_task;
+__xdata uint8_t ao_packet_enable;
+__xdata uint8_t ao_packet_master_sleeping;
+
+void
+ao_packet_send(void)
+{
+       ao_led_on(AO_LED_RED);
+       /* If any tx data is pending then copy it into the tx packet */
+       if (ao_packet_tx_used && ao_tx_packet.len == 0) {
+               memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used);
+               ao_tx_packet.len = ao_packet_tx_used;
+               ao_tx_packet.seq++;
+               ao_packet_tx_used = 0;
+               ao_wakeup(&tx_data);
+       }
+       ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet));
+       ao_led_off(AO_LED_RED);
+}
+
+uint8_t
+ao_packet_recv(void)
+{
+       uint8_t dma_done;
+
+#ifdef AO_LED_GREEN
+       ao_led_on(AO_LED_GREEN);
+#endif
+       dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv));
+#ifdef AO_LED_GREEN
+       ao_led_off(AO_LED_GREEN);
+#endif
+
+       /* Check to see if we got a valid packet */
+       if (!dma_done)
+               return 0;
+       if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK))
+               return 0;
+
+       /* SYN packets carry no data */
+       if (ao_rx_packet.packet.len == AO_PACKET_SYN) {
+               rx_seq = ao_rx_packet.packet.seq;
+               ao_tx_packet.seq = ao_rx_packet.packet.ack;
+               ao_tx_packet.ack = rx_seq;
+       } else if (ao_rx_packet.packet.len) {
+
+               /* Check for incoming data at the next sequence and
+                * for an empty data buffer
+                */
+               if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) &&
+                   ao_packet_rx_used == ao_packet_rx_len) {
+
+                       /* Copy data to the receive data buffer and set up the
+                        * offsets
+                        */
+                       memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len);
+                       ao_packet_rx_used = 0;
+                       ao_packet_rx_len = ao_rx_packet.packet.len;
+
+                       /* Mark the sequence that we've received to
+                        * let the sender know when we return a packet
+                        */
+                       rx_seq = ao_rx_packet.packet.seq;
+                       ao_tx_packet.ack = rx_seq;
+
+                       /* Poke anyone looking for received data */
+                       ao_wakeup(&ao_stdin_ready);
+               }
+       }
+
+       /* If the other side has seen the latest data we queued,
+        * wake up any task waiting to send data and let them go again
+        */
+       if (ao_rx_packet.packet.ack == ao_tx_packet.seq) {
+               ao_tx_packet.len = 0;
+               ao_wakeup(&ao_tx_packet);
+       }
+       return 1;
+}
+
+#ifndef PACKET_HAS_MASTER
+#define PACKET_HAS_MASTER 1
+#endif
+
+#if PACKET_HAS_MASTER
+void
+ao_packet_flush(void)
+{
+       /* If there is data to send, and this is the master,
+        * then poke the master to send all queued data
+        */
+       if (ao_packet_tx_used && ao_packet_master_sleeping)
+               ao_wakeup(&ao_packet_master_sleeping);
+}
+#endif /* PACKET_HAS_MASTER */
+
+void
+ao_packet_putchar(char c) __reentrant
+{
+       while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) {
+#if PACKET_HAS_MASTER
+               ao_packet_flush();
+#endif
+               ao_sleep(&tx_data);
+       }
+
+       if (ao_packet_enable)
+               tx_data[ao_packet_tx_used++] = c;
+}
+
+char
+ao_packet_pollchar(void) __critical
+{
+       if (!ao_packet_enable)
+               return AO_READ_AGAIN;
+
+       if (ao_packet_rx_used == ao_packet_rx_len)
+               return AO_READ_AGAIN;
+
+       return rx_data[ao_packet_rx_used++];
+}
diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c
new file mode 100644 (file)
index 0000000..b0fdf5a
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+static char
+ao_packet_getchar(void) __critical
+{
+       char c;
+       while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) {
+               if (!ao_packet_enable)
+                       break;
+               if (ao_packet_master_sleeping)
+                       ao_wakeup(&ao_packet_master_sleeping);
+               flush();
+               ao_sleep(&ao_stdin_ready);
+       }
+       return c;
+}
+
+static void
+ao_packet_echo(void) __reentrant
+{
+       char    c;
+       while (ao_packet_enable) {
+               c = ao_packet_getchar();
+               if (c != AO_READ_AGAIN)
+                       putchar(c);
+       }
+       ao_exit();
+}
+
+static __xdata struct ao_task  ao_packet_echo_task;
+static __xdata uint16_t                ao_packet_master_delay;
+static __xdata uint16_t                ao_packet_master_time;
+
+#define AO_PACKET_MASTER_DELAY_SHORT   AO_MS_TO_TICKS(100)
+#define AO_PACKET_MASTER_DELAY_LONG    AO_MS_TO_TICKS(1000)
+#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000)
+
+static void
+ao_packet_master_busy(void)
+{
+       ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
+       ao_packet_master_time = ao_time();
+}
+
+static void
+ao_packet_master_check_busy(void)
+{
+       int16_t idle;
+       if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT)
+               return;
+       idle = (int16_t) (ao_time() - ao_packet_master_time);
+
+       if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT)
+               ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG;
+}
+
+void
+ao_packet_master(void)
+{
+       ao_config_get();
+       ao_tx_packet.addr = ao_serial_number;
+       ao_tx_packet.len = AO_PACKET_SYN;
+       ao_packet_master_time = ao_time();
+       ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;
+       while (ao_packet_enable) {
+               memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
+               ao_packet_send();
+               if (ao_tx_packet.len)
+                       ao_packet_master_busy();
+               ao_packet_master_check_busy();
+               ao_alarm(ao_packet_master_delay);
+               if (ao_packet_recv()) {
+                       /* if we can transmit data, do so */
+                       if (ao_packet_tx_used && ao_tx_packet.len == 0)
+                               continue;
+                       if (ao_rx_packet.packet.len)
+                               ao_packet_master_busy();
+                       ao_packet_master_sleeping = 1;
+                       ao_alarm(ao_packet_master_delay);
+                       ao_sleep(&ao_packet_master_sleeping);
+                       ao_packet_master_sleeping = 0;
+               }
+       }
+       ao_exit();
+}
+
+static void
+ao_packet_forward(void) __reentrant
+{
+       char c;
+       ao_packet_enable = 1;
+       ao_cmd_white();
+
+       flush();
+#if HAS_MONITOR
+       ao_set_monitor(0);
+#endif
+       ao_add_task(&ao_packet_task, ao_packet_master, "master");
+       ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo");
+       while ((c = getchar()) != '~') {
+               if (c == '\r') c = '\n';
+               ao_packet_putchar(c);
+       }
+
+       /* Wait for a second if there is any pending data */
+       for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++)
+               ao_delay(AO_MS_TO_TICKS(100));
+       ao_packet_enable = 0;
+       while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
+               ao_radio_recv_abort();
+               ao_wakeup(&ao_stdin_ready);
+               ao_delay(AO_MS_TO_TICKS(10));
+       }
+}
+
+
+
+__code struct ao_cmds ao_packet_master_cmds[] = {
+       { ao_packet_forward,    "p\0Remote packet link." },
+       { 0,    NULL },
+};
+
+void
+ao_packet_master_init(void)
+{
+       ao_cmd_register(&ao_packet_master_cmds[0]);
+}
diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c
new file mode 100644 (file)
index 0000000..9f14052
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+ao_packet_slave(void)
+{
+       ao_tx_packet.addr = ao_serial_number;
+       ao_tx_packet.len = AO_PACKET_SYN;
+       while (ao_packet_enable) {
+               if (ao_packet_recv()) {
+                       memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
+#if HAS_FLIGHT
+                       ao_flight_force_idle = TRUE;
+#endif
+                       ao_packet_send();
+               }
+       }
+       ao_exit();
+}
+
+void
+ao_packet_slave_start(void)
+{
+       ao_packet_enable = 1;
+       ao_add_task(&ao_packet_task, ao_packet_slave, "slave");
+}
+
+void
+ao_packet_slave_stop(void)
+{
+       if (ao_packet_enable) {
+               ao_packet_enable = 0;
+               while (ao_packet_task.wchan) {
+                       ao_radio_recv_abort();
+                       ao_delay(AO_MS_TO_TICKS(10));
+               }
+       }
+}
+
+void
+ao_packet_slave_init(uint8_t enable)
+{
+       ao_add_stdio(ao_packet_pollchar,
+                    ao_packet_putchar,
+                    NULL);
+       if (enable)
+               ao_packet_slave_start();
+}
diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c
new file mode 100644 (file)
index 0000000..00816b3
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/* Values from SmartRF® Studio for:
+ *
+ * Deviation:  20.507812 kHz
+ * Datarate:   38.360596 kBaud
+ * Modulation: GFSK
+ * RF Freq:    434.549927 MHz
+ * Channel:    99.975586 kHz
+ * Channel:    0
+ * RX filter:  93.75 kHz
+ */
+
+/*
+ * For IF freq of 140.62kHz, the IF value is:
+ *
+ * 140.62e3 / (24e6 / 2**10) = 6
+ */
+
+#define IF_FREQ_CONTROL        6
+
+/*
+ * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are
+ *
+ * BW = 24e6 / (8 * (4 + M) * 2 ** E)
+ *
+ * So, M = 0 and E = 3
+ */
+
+#define CHANBW_M       0
+#define CHANBW_E       3
+
+/*
+ * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are:
+ *
+ * R = (256 + M) * 2** E * 24e6 / 2**28
+ *
+ * So M is 163 and E is 10
+ */
+
+#define DRATE_E                10
+#define DRATE_M                163
+
+/*
+ * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:
+ *
+ * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E
+ *
+ * So M is 6 and E is 3
+ */
+
+#define DEVIATION_M    6
+#define DEVIATION_E    3
+
+/*
+ * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone),
+ * so the DRATE_E and DRATE_M values are:
+ *
+ * M is 94 and E is 6
+ *
+ * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
+ */
+
+#define RDF_DRATE_E    6
+#define RDF_DRATE_M    94
+#define RDF_PACKET_LEN 50
+
+/*
+ * RDF deviation should match the normal NFM value of 5kHz
+ *
+ * M is 6 and E is 1
+ *
+ */
+
+#define RDF_DEVIATION_M        6
+#define RDF_DEVIATION_E        1
+
+/* This are from the table for 433MHz */
+
+#define RF_POWER_M30_DBM       0x12
+#define RF_POWER_M20_DBM       0x0e
+#define RF_POWER_M15_DBM       0x1d
+#define RF_POWER_M10_DBM       0x34
+#define RF_POWER_M5_DBM                0x2c
+#define RF_POWER_0_DBM         0x60
+#define RF_POWER_5_DBM         0x84
+#define RF_POWER_7_DBM         0xc8
+#define RF_POWER_10_DBM                0xc0
+
+#define RF_POWER               RF_POWER_10_DBM
+
+static __code uint8_t radio_setup[] = {
+       RF_PA_TABLE7_OFF,       RF_POWER,
+       RF_PA_TABLE6_OFF,       RF_POWER,
+       RF_PA_TABLE5_OFF,       RF_POWER,
+       RF_PA_TABLE4_OFF,       RF_POWER,
+       RF_PA_TABLE3_OFF,       RF_POWER,
+       RF_PA_TABLE2_OFF,       RF_POWER,
+       RF_PA_TABLE1_OFF,       RF_POWER,
+       RF_PA_TABLE0_OFF,       RF_POWER,
+
+       RF_FSCTRL1_OFF,         (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),
+       RF_FSCTRL0_OFF,         (0 << RF_FSCTRL0_FREQOFF_SHIFT),
+
+       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+       RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+                                RF_MDMCFG2_MOD_FORMAT_GFSK |
+                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
+                                RF_MDMCFG1_NUM_PREAMBLE_4 |
+                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
+       RF_MDMCFG0_OFF,         (17 << RF_MDMCFG0_CHANSPC_M_SHIFT),
+
+       RF_CHANNR_OFF,          0,
+
+       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+
+       /* SmartRF says set LODIV_BUF_CURRENT_TX to 0
+        * And, we're not using power ramping, so use PA_POWER 0
+        */
+       RF_FREND0_OFF,          ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) |
+                                (0 << RF_FREND0_PA_POWER_SHIFT)),
+
+       RF_FREND1_OFF,          ((1 << RF_FREND1_LNA_CURRENT_SHIFT) |
+                                (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) |
+                                (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) |
+                                (2 << RF_FREND1_MIX_CURRENT_SHIFT)),
+
+       RF_FSCAL3_OFF,          0xE9,
+       RF_FSCAL2_OFF,          0x0A,
+       RF_FSCAL1_OFF,          0x00,
+       RF_FSCAL0_OFF,          0x1F,
+
+       RF_TEST2_OFF,           0x88,
+       RF_TEST1_OFF,           0x31,
+       RF_TEST0_OFF,           0x09,
+
+       /* default sync values */
+       RF_SYNC1_OFF,           0xD3,
+       RF_SYNC0_OFF,           0x91,
+
+       /* max packet length */
+       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
+                                PKTCTRL1_APPEND_STATUS|
+                                PKTCTRL1_ADR_CHK_NONE),
+       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_WHITE_DATA|
+                                RF_PKTCTRL0_PKT_FORMAT_NORMAL|
+                                RF_PKTCTRL0_CRC_EN|
+                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
+       RF_ADDR_OFF,            0x00,
+       RF_MCSM2_OFF,           (RF_MCSM2_RX_TIME_END_OF_PACKET),
+       RF_MCSM1_OFF,           (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING|
+                                RF_MCSM1_RXOFF_MODE_IDLE|
+                                RF_MCSM1_TXOFF_MODE_IDLE),
+       RF_MCSM0_OFF,           (RF_MCSM0_FS_AUTOCAL_FROM_IDLE|
+                                RF_MCSM0_MAGIC_3|
+                                RF_MCSM0_CLOSE_IN_RX_0DB),
+       RF_FOCCFG_OFF,          (RF_FOCCFG_FOC_PRE_K_3K,
+                                RF_FOCCFG_FOC_POST_K_PRE_K,
+                                RF_FOCCFG_FOC_LIMIT_BW_OVER_4),
+       RF_BSCFG_OFF,           (RF_BSCFG_BS_PRE_K_2K|
+                                RF_BSCFG_BS_PRE_KP_3KP|
+                                RF_BSCFG_BS_POST_KI_PRE_KI|
+                                RF_BSCFG_BS_POST_KP_PRE_KP|
+                                RF_BSCFG_BS_LIMIT_0),
+       RF_AGCCTRL2_OFF,        0x43,
+       RF_AGCCTRL1_OFF,        0x40,
+       RF_AGCCTRL0_OFF,        0x91,
+
+       RF_IOCFG2_OFF,          0x00,
+       RF_IOCFG1_OFF,          0x00,
+       RF_IOCFG0_OFF,          0x00,
+};
+
+static __code uint8_t rdf_setup[] = {
+       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+       RF_MDMCFG3_OFF,         (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+                                RF_MDMCFG2_MOD_FORMAT_GFSK |
+                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_DIS |
+                                RF_MDMCFG1_NUM_PREAMBLE_2 |
+                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
+
+       RF_DEVIATN_OFF,         ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                                (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+
+       /* packet length is set in-line */
+       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
+                                PKTCTRL1_ADR_CHK_NONE),
+       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_PKT_FORMAT_NORMAL|
+                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
+};
+
+static __code uint8_t fixed_pkt_setup[] = {
+       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+       RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+                                RF_MDMCFG2_MOD_FORMAT_GFSK |
+                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
+                                RF_MDMCFG1_NUM_PREAMBLE_4 |
+                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
+
+       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+
+       /* max packet length -- now set inline */
+       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
+                                PKTCTRL1_APPEND_STATUS|
+                                PKTCTRL1_ADR_CHK_NONE),
+       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_WHITE_DATA|
+                                RF_PKTCTRL0_PKT_FORMAT_NORMAL|
+                                RF_PKTCTRL0_CRC_EN|
+                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
+};
+
+__xdata uint8_t        ao_radio_dma;
+__xdata uint8_t ao_radio_dma_done;
+__xdata uint8_t ao_radio_done;
+__xdata uint8_t ao_radio_abort;
+__xdata uint8_t ao_radio_mutex;
+
+void
+ao_radio_general_isr(void) __interrupt 16
+{
+       S1CON &= ~0x03;
+       if (RFIF & RFIF_IM_TIMEOUT) {
+               ao_radio_recv_abort();
+               RFIF &= ~ RFIF_IM_TIMEOUT;
+       } else if (RFIF & RFIF_IM_DONE) {
+               ao_radio_done = 1;
+               ao_wakeup(&ao_radio_done);
+               RFIF &= ~RFIF_IM_DONE;
+       }
+}
+
+void
+ao_radio_set_packet(void)
+{
+       uint8_t i;
+       for (i = 0; i < sizeof (fixed_pkt_setup); i += 2)
+               RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1];
+}
+
+void
+ao_radio_idle(void)
+{
+       if (RF_MARCSTATE != RF_MARCSTATE_IDLE)
+       {
+               do {
+                       RFST = RFST_SIDLE;
+                       ao_yield();
+               } while (RF_MARCSTATE != RF_MARCSTATE_IDLE);
+       }
+}
+
+void
+ao_radio_get(uint8_t len)
+{
+       ao_config_get();
+       ao_mutex_get(&ao_radio_mutex);
+       ao_radio_idle();
+       RF_CHANNR = ao_config.radio_channel;
+       RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16);
+       RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8);
+       RF_FREQ0 = (uint8_t) (ao_config.radio_setting);
+       RF_PKTLEN = len;
+}
+
+
+void
+ao_radio_send(__xdata void *packet, uint8_t size) __reentrant
+{
+       ao_radio_get(size);
+       ao_radio_done = 0;
+       ao_dma_set_transfer(ao_radio_dma,
+                           packet,
+                           &RFDXADDR,
+                           size,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_RADIO,
+                           DMA_CFG1_SRCINC_1 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_HIGH);
+       ao_dma_start(ao_radio_dma);
+       RFST = RFST_STX;
+       __critical while (!ao_radio_done)
+               ao_sleep(&ao_radio_done);
+       ao_radio_put();
+}
+
+uint8_t
+ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant
+{
+       ao_radio_abort = 0;
+       ao_radio_get(size - 2);
+       ao_dma_set_transfer(ao_radio_dma,
+                           &RFDXADDR,
+                           packet,
+                           size,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_RADIO,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_1 |
+                           DMA_CFG1_PRIORITY_HIGH);
+       ao_dma_start(ao_radio_dma);
+       RFST = RFST_SRX;
+
+       /* Wait for DMA to be done, for the radio receive process to
+        * get aborted or for a receive timeout to fire
+        */
+       __critical while (!ao_radio_dma_done && !ao_radio_abort)
+                          if (ao_sleep(&ao_radio_dma_done))
+                                  break;
+
+       /* If recv was aborted, clean up by stopping the DMA engine
+        * and idling the radio
+        */
+       if (!ao_radio_dma_done) {
+               ao_dma_abort(ao_radio_dma);
+               ao_radio_idle();
+       }
+       ao_radio_put();
+       return ao_radio_dma_done;
+}
+
+/*
+ * Wake up a task waiting to receive a radio packet
+ * and tell them to abort the transfer
+ */
+
+void
+ao_radio_recv_abort(void)
+{
+       ao_radio_abort = 1;
+       ao_wakeup(&ao_radio_dma_done);
+}
+
+__xdata ao_radio_rdf_value = 0x55;
+
+void
+ao_radio_rdf(int ms)
+{
+       uint8_t i;
+       uint8_t pkt_len;
+
+       /*
+        * Compute the packet length as follows:
+        *
+        * 2000 bps (for a 1kHz tone)
+        * so, for 'ms' milliseconds, we need
+        * 2 * ms bits, or ms / 4 bytes
+        */
+       if (ms > (255 * 4))
+               ms = 255 * 4;
+       pkt_len = ms >> 2;
+
+       ao_radio_abort = 0;
+       ao_radio_get(pkt_len);
+       ao_radio_done = 0;
+       for (i = 0; i < sizeof (rdf_setup); i += 2)
+               RF[rdf_setup[i]] = rdf_setup[i+1];
+
+       ao_dma_set_transfer(ao_radio_dma,
+                           &ao_radio_rdf_value,
+                           &RFDXADDR,
+                           pkt_len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_RADIO,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_HIGH);
+       ao_dma_start(ao_radio_dma);
+       RFST = RFST_STX;
+       __critical while (!ao_radio_done && !ao_radio_abort)
+                          ao_sleep(&ao_radio_done);
+       if (!ao_radio_done) {
+               ao_dma_abort(ao_radio_dma);
+               ao_radio_idle();
+       }
+       ao_radio_set_packet();
+       ao_radio_put();
+}
+
+void
+ao_radio_rdf_abort(void)
+{
+       ao_radio_abort = 1;
+       ao_wakeup(&ao_radio_done);
+}
+
+
+/* Output carrier */
+void
+ao_radio_test(void)
+{
+       uint8_t mode = 2;
+       static __xdata radio_on;
+       ao_cmd_white();
+       if (ao_cmd_lex_c != '\n') {
+               ao_cmd_decimal();
+               mode = (uint8_t) ao_cmd_lex_u32;
+       }
+       mode++;
+       if ((mode & 2) && !radio_on) {
+#if HAS_MONITOR
+               ao_set_monitor(0);
+#endif
+#if PACKET_HAS_SLAVE
+               ao_packet_slave_stop();
+#endif
+               ao_radio_get(0xff);
+               RFST = RFST_STX;
+               radio_on = 1;
+       }
+       if (mode == 3) {
+               printf ("Hit a character to stop..."); flush();
+               getchar();
+               putchar('\n');
+       }
+       if ((mode & 1) && radio_on) {
+               ao_radio_idle();
+               ao_radio_put();
+               radio_on = 0;
+       }
+}
+
+__code struct ao_cmds ao_radio_cmds[] = {
+       { ao_radio_test,        "C <1 start, 0 stop, none both>\0Radio carrier test" },
+       { 0,    NULL },
+};
+
+void
+ao_radio_init(void)
+{
+       uint8_t i;
+       for (i = 0; i < sizeof (radio_setup); i += 2)
+               RF[radio_setup[i]] = radio_setup[i+1];
+       ao_radio_set_packet();
+       ao_radio_dma_done = 1;
+       ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done);
+       RFIF = 0;
+       RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE;
+       IEN2 |= IEN2_RFIE;
+       ao_cmd_register(&ao_radio_cmds[0]);
+}
diff --git a/src/cc1111/ao_reboot.c b/src/cc1111/ao_reboot.c
new file mode 100644 (file)
index 0000000..8c47b89
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/* Use the watchdog timer to force a complete reboot
+ */
+void
+ao_reboot(void)
+{
+       WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768;
+       ao_delay(AO_SEC_TO_TICKS(2));
+       ao_panic(AO_PANIC_REBOOT);
+}
diff --git a/src/cc1111/ao_romconfig.c b/src/cc1111/ao_romconfig.c
new file mode 100644 (file)
index 0000000..f3fe61b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__code __at (0x00a0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION;
+__code __at (0x00a2) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION;
+__code __at (0x00a4) uint16_t ao_serial_number = 0;
+/*
+ * For 434.550MHz, the frequency value is:
+ *
+ * 434.550e6 / (24e6 / 2**16) = 1186611.2
+ *
+ * This value is stored in a const variable so that
+ * ao-load can change it during programming for
+ * devices that have no eeprom for config data.
+ */
+__code __at (0x00a6) uint32_t ao_radio_cal = 1186611;
diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c
new file mode 100644 (file)
index 0000000..82370c6
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+volatile __xdata struct ao_fifo        ao_usart1_rx_fifo;
+volatile __xdata struct ao_fifo        ao_usart1_tx_fifo;
+
+void
+ao_serial_rx1_isr(void) __interrupt 3
+{
+       if (!ao_fifo_full(ao_usart1_rx_fifo))
+               ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF);
+       ao_wakeup(&ao_usart1_rx_fifo);
+#if USE_SERIAL_STDIN
+       ao_wakeup(&ao_stdin_ready);
+#endif
+}
+
+static __xdata uint8_t ao_serial_tx1_started;
+
+static void
+ao_serial_tx1_start(void)
+{
+       if (!ao_fifo_empty(ao_usart1_tx_fifo) &&
+           !ao_serial_tx1_started)
+       {
+               ao_serial_tx1_started = 1;
+               ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF);
+       }
+}
+
+void
+ao_serial_tx1_isr(void) __interrupt 14
+{
+       UTX1IF = 0;
+       ao_serial_tx1_started = 0;
+       ao_serial_tx1_start();
+       ao_wakeup(&ao_usart1_tx_fifo);
+}
+
+char
+ao_serial_getchar(void) __critical
+{
+       char    c;
+       while (ao_fifo_empty(ao_usart1_rx_fifo))
+               ao_sleep(&ao_usart1_rx_fifo);
+       ao_fifo_remove(ao_usart1_rx_fifo, c);
+       return c;
+}
+
+#if USE_SERIAL_STDIN
+char
+ao_serial_pollchar(void) __critical
+{
+       char    c;
+       if (ao_fifo_empty(ao_usart1_rx_fifo))
+               return AO_READ_AGAIN;
+       ao_fifo_remove(ao_usart1_rx_fifo,c);
+       return c;
+}
+#endif
+
+void
+ao_serial_putchar(char c) __critical
+{
+       while (ao_fifo_full(ao_usart1_tx_fifo))
+               ao_sleep(&ao_usart1_tx_fifo);
+       ao_fifo_insert(ao_usart1_tx_fifo, c);
+       ao_serial_tx1_start();
+}
+
+void
+ao_serial_drain(void) __critical
+{
+       while (!ao_fifo_empty(ao_usart1_tx_fifo))
+               ao_sleep(&ao_usart1_tx_fifo);
+}
+
+static __code struct {
+       uint8_t baud;
+       uint8_t gcr;
+} ao_serial_speeds[] = {
+       /* [AO_SERIAL_SPEED_4800] = */ {
+               /* .baud = */ 163,
+               /* .gcr  = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+       /* [AO_SERIAL_SPEED_9600] = */ {
+               /* .baud = */ 163,
+               /* .gcr  = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+       /* [AO_SERIAL_SPEED_19200] = */ {
+               /* .baud = */ 163,
+               /* .gcr  = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+       /* [AO_SERIAL_SPEED_57600] = */ {
+               /* .baud = */ 59,
+               /* .gcr =  */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+};
+
+void
+ao_serial_set_speed(uint8_t speed)
+{
+       ao_serial_drain();
+       if (speed > AO_SERIAL_SPEED_57600)
+               return;
+       U1UCR |= UxUCR_FLUSH;
+       U1BAUD = ao_serial_speeds[speed].baud;
+       U1GCR = ao_serial_speeds[speed].gcr;
+}
+
+void
+ao_serial_init(void)
+{
+#if HAS_SERIAL_1_ALT_1
+       /* Set up the USART pin assignment */
+       PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1;
+
+       P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0;
+
+       /* Make the USART pins be controlled by the USART */
+       P0SEL |= (1 << 5) | (1 << 4);
+#if HAS_SERIAL_1_HW_FLOW
+       P0SEL |= (1 << 3) | (1 << 2);
+#endif
+#else
+       /* Set up the USART pin assignment */
+       PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
+
+       P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) |
+               (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1);
+
+       /* Make the USART pins be controlled by the USART */
+       P1SEL |= (1 << 6) | (1 << 7);
+       P1SEL |= (1 << 5) | (1 << 4);
+#endif
+
+       /* UART mode with receiver enabled */
+       U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
+
+       /* Pick a 4800 baud rate */
+       ao_serial_set_speed(AO_SERIAL_SPEED_4800);
+
+       /* Reasonable serial parameters */
+       U1UCR = (UxUCR_FLUSH |
+#if HAS_SERIAL_1_HW_FLOW
+                UxUCR_FLOW_ENABLE |
+#else
+                UxUCR_FLOW_DISABLE |
+#endif
+                UxUCR_D9_EVEN_PARITY |
+                UxUCR_BIT9_8_BITS |
+                UxUCR_PARITY_DISABLE |
+                UxUCR_SPB_1_STOP_BIT |
+                UxUCR_STOP_HIGH |
+                UxUCR_START_LOW);
+
+       IEN0 |= IEN0_URX1IE;
+       IEN2 |= IEN2_UTX1IE;
+}
diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c
new file mode 100644 (file)
index 0000000..fbe613c
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/* Shared mutex to protect SPI bus, must cover the entire
+ * operation, from CS low to CS high. This means that any SPI
+ * user must protect the SPI bus with this mutex
+ */
+__xdata uint8_t        ao_spi_mutex;
+__xdata uint8_t ao_spi_dma_in_done;
+__xdata uint8_t ao_spi_dma_out_done;
+
+uint8_t        ao_spi_dma_out_id;
+uint8_t ao_spi_dma_in_id;
+
+static __xdata uint8_t ao_spi_const = 0xff;
+
+/* Send bytes over SPI.
+ *
+ * This sets up two DMA engines, one writing the data and another reading
+ * bytes coming back.  We use the bytes coming back to tell when the transfer
+ * is complete, as the transmit register is double buffered and hence signals
+ * completion one byte before the transfer is actually complete
+ */
+void
+ao_spi_send(void __xdata *block, uint16_t len) __reentrant
+{
+       ao_dma_set_transfer(ao_spi_dma_in_id,
+                           &U0DBUFXADDR,
+                           &ao_spi_const,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_URX0,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_set_transfer(ao_spi_dma_out_id,
+                           block,
+                           &U0DBUFXADDR,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_UTX0,
+                           DMA_CFG1_SRCINC_1 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_start(ao_spi_dma_in_id);
+       ao_dma_start(ao_spi_dma_out_id);
+       ao_dma_trigger(ao_spi_dma_out_id);
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+}
+
+/* Receive bytes over SPI.
+ *
+ * This sets up tow DMA engines, one reading the data and another
+ * writing constant values to the SPI transmitter as that is what
+ * clocks the data coming in.
+ */
+void
+ao_spi_recv(void __xdata *block, uint16_t len) __reentrant
+{
+       ao_dma_set_transfer(ao_spi_dma_in_id,
+                           &U0DBUFXADDR,
+                           block,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_URX0,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_1 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_set_transfer(ao_spi_dma_out_id,
+                           &ao_spi_const,
+                           &U0DBUFXADDR,
+                           len,
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_UTX0,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_NORMAL);
+
+       ao_dma_start(ao_spi_dma_in_id);
+       ao_dma_start(ao_spi_dma_out_id);
+       ao_dma_trigger(ao_spi_dma_out_id);
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+}
+
+/*
+ * Initialize USART0 for SPI using config alt 2
+ *
+ *     MO      P1_5
+ *     MI      P1_4
+ *     CLK     P1_3
+ *
+ * Chip select is the responsibility of the caller
+ */
+
+void
+ao_spi_init(void)
+{
+       /* Set up the USART pin assignment */
+       PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
+
+       /* Ensure that USART0 takes precidence over USART1 for pins that
+        * they share
+        */
+       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0;
+
+       /* Make the SPI pins be controlled by the USART peripheral */
+       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
+
+       /* Set up OUT DMA */
+       ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done);
+
+       /* Set up IN DMA */
+       ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done);
+
+       /* Set up the USART.
+        *
+        * SPI master mode
+        */
+       U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER);
+
+       /* Set the baud rate and signal parameters
+        *
+        * The cc1111 is limited to a 24/8 MHz SPI clock.
+        * Every peripheral I've ever seen goes faster than that,
+        * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0)
+        */
+       U0BAUD = 0;
+       U0GCR = (UxGCR_CPOL_NEGATIVE |
+                UxGCR_CPHA_FIRST_EDGE |
+                UxGCR_ORDER_MSB |
+                (17 << UxGCR_BAUD_E_SHIFT));
+}
diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c
new file mode 100644 (file)
index 0000000..c977fbc
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+static volatile __data uint16_t ao_tick_count;
+
+uint16_t ao_time(void) __critical
+{
+       return ao_tick_count;
+}
+
+static __xdata uint8_t ao_forever;
+
+void
+ao_delay(uint16_t ticks)
+{
+       ao_alarm(ticks);
+       ao_sleep(&ao_forever);
+}
+
+#define T1_CLOCK_DIVISOR       8       /* 24e6/8 = 3e6 */
+#define T1_SAMPLE_TIME         30000   /* 3e6/30000 = 100 */
+
+#if HAS_ADC
+volatile __data uint8_t        ao_adc_interval = 1;
+volatile __data uint8_t        ao_adc_count;
+#endif
+
+void ao_timer_isr(void) __interrupt 9
+{
+       ++ao_tick_count;
+#if HAS_ADC
+       if (++ao_adc_count == ao_adc_interval) {
+               ao_adc_count = 0;
+               ao_adc_poll();
+       }
+#endif
+}
+
+#if HAS_ADC
+void
+ao_timer_set_adc_interval(uint8_t interval) __critical
+{
+       ao_adc_interval = interval;
+       ao_adc_count = 0;
+}
+#endif
+
+void
+ao_timer_init(void)
+{
+       /* NOTE:  This uses a timer only present on cc1111 architecture. */
+
+       /* disable timer 1 */
+       T1CTL = 0;
+
+       /* set the sample rate */
+       T1CC0H = T1_SAMPLE_TIME >> 8;
+       T1CC0L = (uint8_t) T1_SAMPLE_TIME;
+
+       T1CCTL0 = T1CCTL_MODE_COMPARE;
+       T1CCTL1 = 0;
+       T1CCTL2 = 0;
+
+       /* clear timer value */
+       T1CNTL = 0;
+
+       /* enable overflow interrupt */
+       OVFIM = 1;
+       /* enable timer 1 interrupt */
+       T1IE = 1;
+
+       /* enable timer 1 in module mode, dividing by 8 */
+       T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8;
+}
+
+/*
+ * AltOS always cranks the clock to the max frequency
+ */
+void
+ao_clock_init(void)
+{
+       /* Switch system clock to crystal oscilator */
+       CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL);
+
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+
+       /* Crank up the timer tick and system clock speed */
+       CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) |
+                 (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1));
+
+       while ((CLKCON & (CLKCON_TICKSPD_MASK|CLKCON_CLKSPD_MASK)) !=
+              (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1))
+               ;
+}
diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c
new file mode 100644 (file)
index 0000000..08cb739
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_usb.h"
+
+struct ao_task __xdata ao_usb_task;
+
+static __xdata uint16_t        ao_usb_in_bytes;
+static __pdata uint16_t ao_usb_in_bytes_last;
+static __xdata uint16_t        ao_usb_out_bytes;
+static __pdata uint8_t ao_usb_iif;
+static __pdata uint8_t ao_usb_running;
+
+static void
+ao_usb_set_interrupts(void)
+{
+       /* IN interrupts on the control an IN endpoints */
+       USBIIE = (1 << AO_USB_CONTROL_EP) | (1 << AO_USB_IN_EP);
+
+       /* OUT interrupts on the OUT endpoint */
+       USBOIE = (1 << AO_USB_OUT_EP);
+
+       /* Only care about reset */
+       USBCIE = USBCIE_RSTIE;
+}
+
+/* This interrupt is shared with port 2,
+ * so when we hook that up, fix this
+ */
+void
+ao_usb_isr(void) __interrupt 6
+{
+       USBIF = 0;
+       ao_usb_iif |= USBIIF;
+       if (ao_usb_iif & 1)
+               ao_wakeup(&ao_usb_task);
+       if (ao_usb_iif & (1 << AO_USB_IN_EP))
+               ao_wakeup(&ao_usb_in_bytes);
+
+       if (USBOIF & (1 << AO_USB_OUT_EP))
+               ao_wakeup(&ao_stdin_ready);
+
+       if (USBCIF & USBCIF_RSTIF)
+               ao_usb_set_interrupts();
+#if HAS_BTM
+#if BT_LINK_ON_P2
+       ao_btm_isr();
+#endif
+#endif
+}
+
+struct ao_usb_setup {
+       uint8_t         dir_type_recip;
+       uint8_t         request;
+       uint16_t        value;
+       uint16_t        index;
+       uint16_t        length;
+} __xdata ao_usb_setup;
+
+__pdata uint8_t ao_usb_ep0_state;
+uint8_t * __pdata ao_usb_ep0_in_data;
+__pdata uint8_t ao_usb_ep0_in_len;
+__pdata uint8_t        ao_usb_ep0_in_buf[2];
+__pdata uint8_t ao_usb_ep0_out_len;
+__xdata uint8_t *__pdata ao_usb_ep0_out_data;
+__pdata uint8_t ao_usb_configuration;
+
+/* Send an IN data packet */
+static void
+ao_usb_ep0_flush(void)
+{
+       __pdata uint8_t this_len;
+       __pdata uint8_t cs0;
+
+       /* If the IN packet hasn't been picked up, just return */
+       USBINDEX = 0;
+       cs0 = USBCS0;
+       if (cs0 & USBCS0_INPKT_RDY)
+               return;
+
+       this_len = ao_usb_ep0_in_len;
+       if (this_len > AO_USB_CONTROL_SIZE)
+               this_len = AO_USB_CONTROL_SIZE;
+       cs0 = USBCS0_INPKT_RDY;
+       if (this_len != AO_USB_CONTROL_SIZE) {
+               cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END;
+               ao_usb_ep0_state = AO_USB_EP0_IDLE;
+       }
+       ao_usb_ep0_in_len -= this_len;
+       while (this_len--)
+               USBFIFO[0] = *ao_usb_ep0_in_data++;
+       USBINDEX = 0;
+       USBCS0 = cs0;
+}
+
+__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+
+/* Walk through the list of descriptors and find a match
+ */
+static void
+ao_usb_get_descriptor(uint16_t value)
+{
+       __code uint8_t          *__pdata descriptor;
+       __pdata uint8_t         type = value >> 8;
+       __pdata uint8_t         index = value;
+
+       descriptor = ao_usb_descriptors;
+       while (descriptor[0] != 0) {
+               if (descriptor[1] == type && index-- == 0) {
+                       if (type == AO_USB_DESC_CONFIGURATION)
+                               ao_usb_ep0_in_len = descriptor[2];
+                       else
+                               ao_usb_ep0_in_len = descriptor[0];
+                       ao_usb_ep0_in_data = descriptor;
+                       break;
+               }
+               descriptor += descriptor[0];
+       }
+}
+
+/* Read data from the ep0 OUT fifo
+ */
+static void
+ao_usb_ep0_fill(void)
+{
+       __pdata uint8_t len;
+
+       USBINDEX = 0;
+       len = USBCNT0;
+       if (len > ao_usb_ep0_out_len)
+               len = ao_usb_ep0_out_len;
+       ao_usb_ep0_out_len -= len;
+       while (len--)
+               *ao_usb_ep0_out_data++ = USBFIFO[0];
+}
+
+void
+ao_usb_ep0_queue_byte(uint8_t a)
+{
+       ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a;
+}
+
+void
+ao_usb_set_address(uint8_t address)
+{
+       ao_usb_running = 1;
+       USBADDR = address | 0x80;
+       while (USBADDR & 0x80)
+               ;
+}
+
+static void
+ao_usb_set_configuration(void)
+{
+       /* Set the IN max packet size, double buffered */
+       USBINDEX = AO_USB_IN_EP;
+       USBMAXI = AO_USB_IN_SIZE >> 3;
+       USBCSIH |= USBCSIH_IN_DBL_BUF;
+
+       /* Set the OUT max packet size, double buffered */
+       USBINDEX = AO_USB_OUT_EP;
+       USBMAXO = AO_USB_OUT_SIZE >> 3;
+       USBCSOH = USBCSOH_OUT_DBL_BUF;
+}
+
+static void
+ao_usb_ep0_setup(void)
+{
+       /* Pull the setup packet out of the fifo */
+       ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup;
+       ao_usb_ep0_out_len = 8;
+       ao_usb_ep0_fill();
+       if (ao_usb_ep0_out_len != 0)
+               return;
+
+       /* Figure out how to ACK the setup packet */
+       if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) {
+               if (ao_usb_setup.length)
+                       ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
+               else
+                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+       } else {
+               if (ao_usb_setup.length)
+                       ao_usb_ep0_state = AO_USB_EP0_DATA_OUT;
+               else
+                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+       }
+       USBINDEX = 0;
+       if (ao_usb_ep0_state == AO_USB_EP0_IDLE)
+               USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END;
+       else
+               USBCS0 = USBCS0_CLR_OUTPKT_RDY;
+
+       ao_usb_ep0_in_data = ao_usb_ep0_in_buf;
+       ao_usb_ep0_in_len = 0;
+       switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) {
+       case AO_USB_TYPE_STANDARD:
+               switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) {
+               case AO_USB_RECIP_DEVICE:
+                       switch(ao_usb_setup.request) {
+                       case AO_USB_REQ_GET_STATUS:
+                               ao_usb_ep0_queue_byte(0);
+                               ao_usb_ep0_queue_byte(0);
+                               break;
+                       case AO_USB_REQ_SET_ADDRESS:
+                               ao_usb_set_address(ao_usb_setup.value);
+                               break;
+                       case AO_USB_REQ_GET_DESCRIPTOR:
+                               ao_usb_get_descriptor(ao_usb_setup.value);
+                               break;
+                       case AO_USB_REQ_GET_CONFIGURATION:
+                               ao_usb_ep0_queue_byte(ao_usb_configuration);
+                               break;
+                       case AO_USB_REQ_SET_CONFIGURATION:
+                               ao_usb_configuration = ao_usb_setup.value;
+                               ao_usb_set_configuration();
+                               break;
+                       }
+                       break;
+               case AO_USB_RECIP_INTERFACE:
+                       #pragma disable_warning 110
+                       switch(ao_usb_setup.request) {
+                       case AO_USB_REQ_GET_STATUS:
+                               ao_usb_ep0_queue_byte(0);
+                               ao_usb_ep0_queue_byte(0);
+                               break;
+                       case AO_USB_REQ_GET_INTERFACE:
+                               ao_usb_ep0_queue_byte(0);
+                               break;
+                       case AO_USB_REQ_SET_INTERFACE:
+                               break;
+                       }
+                       break;
+               case AO_USB_RECIP_ENDPOINT:
+                       switch(ao_usb_setup.request) {
+                       case AO_USB_REQ_GET_STATUS:
+                               ao_usb_ep0_queue_byte(0);
+                               ao_usb_ep0_queue_byte(0);
+                               break;
+                       }
+                       break;
+               }
+               break;
+       case AO_USB_TYPE_CLASS:
+               switch (ao_usb_setup.request) {
+               case SET_LINE_CODING:
+                       ao_usb_ep0_out_len = 7;
+                       ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding;
+                       break;
+               case GET_LINE_CODING:
+                       ao_usb_ep0_in_len = 7;
+                       ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding;
+                       break;
+               case SET_CONTROL_LINE_STATE:
+                       break;
+               }
+               break;
+       }
+       if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) {
+               if (ao_usb_setup.length < ao_usb_ep0_in_len)
+                       ao_usb_ep0_in_len = ao_usb_setup.length;
+               ao_usb_ep0_flush();
+       }
+}
+
+/* End point 0 receives all of the control messages. */
+static void
+ao_usb_ep0(void)
+{
+       __pdata uint8_t cs0;
+
+       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+       for (;;) {
+               __critical for (;;) {
+                       if (ao_usb_iif & 1) {
+                               ao_usb_iif &= ~1;
+                               break;
+                       }
+                       ao_sleep(&ao_usb_task);
+               }
+               USBINDEX = 0;
+               cs0 = USBCS0;
+               if (cs0 & USBCS0_SETUP_END) {
+                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+                       USBCS0 = USBCS0_CLR_SETUP_END;
+               }
+               if (cs0 & USBCS0_SENT_STALL) {
+                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+                       USBCS0 &= ~USBCS0_SENT_STALL;
+               }
+               if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN &&
+                   (cs0 & USBCS0_INPKT_RDY) == 0)
+               {
+                       ao_usb_ep0_flush();
+               }
+               if (cs0 & USBCS0_OUTPKT_RDY) {
+                       switch (ao_usb_ep0_state) {
+                       case AO_USB_EP0_IDLE:
+                               ao_usb_ep0_setup();
+                               break;
+                       case AO_USB_EP0_DATA_OUT:
+                               ao_usb_ep0_fill();
+                               if (ao_usb_ep0_out_len == 0)
+                                       ao_usb_ep0_state = AO_USB_EP0_IDLE;
+                               USBINDEX = 0;
+                               if (ao_usb_ep0_state == AO_USB_EP0_IDLE)
+                                       USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END;
+                               else
+                                       USBCS0 = USBCS0_CLR_OUTPKT_RDY;
+                               break;
+                       }
+               }
+       }
+}
+
+/* Wait for a free IN buffer */
+static void
+ao_usb_in_wait(void)
+{
+       for (;;) {
+               USBINDEX = AO_USB_IN_EP;
+               if ((USBCSIL & USBCSIL_INPKT_RDY) == 0)
+                       break;
+               ao_sleep(&ao_usb_in_bytes);
+       }
+}
+
+/* Send the current IN packet */
+static void
+ao_usb_in_send(void)
+{
+       USBINDEX = AO_USB_IN_EP;
+       USBCSIL |= USBCSIL_INPKT_RDY;
+       ao_usb_in_bytes_last = ao_usb_in_bytes;
+       ao_usb_in_bytes = 0;
+}
+
+void
+ao_usb_flush(void) __critical
+{
+       if (!ao_usb_running)
+               return;
+
+       /* If there are pending bytes, or if the last packet was full,
+        * send another IN packet
+        */
+       if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) {
+               ao_usb_in_wait();
+               ao_usb_in_send();
+       }
+}
+
+void
+ao_usb_putchar(char c) __critical __reentrant
+{
+       if (!ao_usb_running)
+               return;
+
+       ao_usb_in_wait();
+
+       /* Queue a byte, sending the packet when full */
+       USBFIFO[AO_USB_IN_EP << 1] = c;
+       if (++ao_usb_in_bytes == AO_USB_IN_SIZE)
+               ao_usb_in_send();
+}
+
+char
+ao_usb_pollchar(void) __critical
+{
+       char c;
+       if (ao_usb_out_bytes == 0) {
+               USBINDEX = AO_USB_OUT_EP;
+               if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0)
+                       return AO_READ_AGAIN;
+               ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL;
+               if (ao_usb_out_bytes == 0) {
+                       USBINDEX = AO_USB_OUT_EP;
+                       USBCSOL &= ~USBCSOL_OUTPKT_RDY;
+                       return AO_READ_AGAIN;
+               }
+       }
+       --ao_usb_out_bytes;
+       c = USBFIFO[AO_USB_OUT_EP << 1];
+       if (ao_usb_out_bytes == 0) {
+               USBINDEX = AO_USB_OUT_EP;
+               USBCSOL &= ~USBCSOL_OUTPKT_RDY;
+       }
+       return c;
+}
+
+char
+ao_usb_getchar(void) __critical
+{
+       char    c;
+
+       while ((c = ao_usb_pollchar()) == AO_READ_AGAIN)
+               ao_sleep(&ao_stdin_ready);
+       return c;
+}
+
+void
+ao_usb_enable(void)
+{
+       /* Turn on the USB controller */
+       SLEEP |= SLEEP_USB_EN;
+
+       ao_usb_set_configuration();
+
+       ao_usb_set_interrupts();
+
+       /* enable USB interrupts */
+       IEN2 |= IEN2_USBIE;
+
+       /* Clear any pending interrupts */
+       USBCIF = 0;
+       USBOIF = 0;
+       USBIIF = 0;
+}
+
+void
+ao_usb_disable(void)
+{
+       /* Disable USB interrupts */
+       USBIIE = 0;
+       USBOIE = 0;
+       USBCIE = 0;
+       IEN2 &= ~IEN2_USBIE;
+
+       /* Clear any pending interrupts */
+       USBCIF = 0;
+       USBOIF = 0;
+       USBIIF = 0;
+
+       /* Turn off the USB controller */
+       SLEEP &= ~SLEEP_USB_EN;
+}
+
+void
+ao_usb_init(void)
+{
+       ao_usb_enable();
+
+       ao_add_task(&ao_usb_task, ao_usb_ep0, "usb");
+       ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
+}
diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h
new file mode 100644 (file)
index 0000000..6633daf
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_USB_H_
+#define _AO_USB_H_
+
+#define AO_USB_SETUP_DIR_MASK  (0x01 << 7)
+#define AO_USB_SETUP_TYPE_MASK (0x03 << 5)
+#define AO_USB_SETUP_RECIP_MASK        (0x1f)
+
+#define AO_USB_DIR_OUT                 0
+#define AO_USB_DIR_IN                  (1 << 7)
+
+#define AO_USB_TYPE_STANDARD           0
+#define AO_USB_TYPE_CLASS              (1 << 5)
+#define AO_USB_TYPE_VENDOR             (2 << 5)
+#define AO_USB_TYPE_RESERVED           (3 << 5)
+
+#define AO_USB_RECIP_DEVICE            0
+#define AO_USB_RECIP_INTERFACE         1
+#define AO_USB_RECIP_ENDPOINT          2
+#define AO_USB_RECIP_OTHER             3
+
+/* standard requests */
+#define        AO_USB_REQ_GET_STATUS           0x00
+#define AO_USB_REQ_CLEAR_FEATURE       0x01
+#define AO_USB_REQ_SET_FEATURE         0x03
+#define AO_USB_REQ_SET_ADDRESS         0x05
+#define AO_USB_REQ_GET_DESCRIPTOR      0x06
+#define AO_USB_REQ_SET_DESCRIPTOR      0x07
+#define AO_USB_REQ_GET_CONFIGURATION   0x08
+#define AO_USB_REQ_SET_CONFIGURATION   0x09
+#define AO_USB_REQ_GET_INTERFACE       0x0A
+#define AO_USB_REQ_SET_INTERFACE       0x0B
+#define AO_USB_REQ_SYNCH_FRAME         0x0C
+
+#define AO_USB_DESC_DEVICE             1
+#define AO_USB_DESC_CONFIGURATION      2
+#define AO_USB_DESC_STRING             3
+#define AO_USB_DESC_INTERFACE          4
+#define AO_USB_DESC_ENDPOINT           5
+#define AO_USB_DESC_DEVICE_QUALIFIER   6
+#define AO_USB_DESC_OTHER_SPEED                7
+#define AO_USB_DESC_INTERFACE_POWER    8
+
+#define AO_USB_GET_DESC_TYPE(x)                (((x)>>8)&0xFF)
+#define AO_USB_GET_DESC_INDEX(x)       ((x)&0xFF)
+
+#define AO_USB_CONTROL_EP      0
+#define AO_USB_INT_EP          1
+#define AO_USB_OUT_EP          4
+#define AO_USB_IN_EP           5
+#define AO_USB_CONTROL_SIZE    32
+/*
+ * Double buffer IN and OUT EPs, so each
+ * gets half of the available space
+ *
+ * Ah, but USB bulk packets can only come in 8, 16, 32 and 64
+ * byte sizes, so we'll use 64 for everything
+ */
+#define AO_USB_IN_SIZE         64
+#define AO_USB_OUT_SIZE                64
+
+#define AO_USB_EP0_IDLE                0
+#define AO_USB_EP0_DATA_IN     1
+#define AO_USB_EP0_DATA_OUT    2
+
+#define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
+
+/* CDC definitions */
+#define CS_INTERFACE      0x24
+#define CS_ENDPOINT       0x25
+
+#define SET_LINE_CODING         0x20
+#define GET_LINE_CODING         0x21
+#define SET_CONTROL_LINE_STATE  0x22
+
+/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */
+struct ao_usb_line_coding {
+       uint32_t        rate;
+       uint8_t         char_format;
+       uint8_t         parity;
+       uint8_t         data_bits;
+} ;
+
+#endif /* _AO_USB_H_ */
diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h
new file mode 100644 (file)
index 0000000..e52aa79
--- /dev/null
@@ -0,0 +1,1306 @@
+/*-------------------------------------------------------------------------
+   Register Declarations for the ChipCon CC1111 Processor Range
+
+   Copyright © 2008 Keith Packard <keithp@keithp.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+   Adapted from the Cygnal C8051F12x config file which is:
+
+   Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+-------------------------------------------------------------------------*/
+
+#ifndef _CC1111_H_
+#define _CC1111_H_
+#include <cc1110.h>
+#include <stdint.h>
+
+__sfr __at 0xA8 IEN0;          /* Interrupt Enable 0 Register */
+
+sbit __at 0xA8 RFTXRXIE;       /* RF TX/RX done interrupt enable */
+sbit __at 0xA9 ADCIE;          /* ADC interrupt enable */
+sbit __at 0xAA URX0IE;         /* USART0 RX interrupt enable */
+sbit __at 0xAB URX1IE;         /* USART1 RX interrupt enable (shared with I2S RX) */
+sbit __at 0xAB I2SRXIE;                /* I2S RX interrupt enable (shared with USART1 RX) */
+sbit __at 0xAC ENCIE;          /* AES encryption/decryption interrupt enable */
+sbit __at 0xAD STIE;           /* Sleep Timer interrupt enable */
+sbit __at 0xAF EA;             /* Enable All */
+
+#define IEN0_EA                        (1 << 7)
+#define IEN0_STIE              (1 << 5)
+#define IEN0_ENCIE             (1 << 4)
+#define IEN0_URX1IE            (1 << 3)
+#define IEN0_I2SRXIE           (1 << 3)
+#define IEN0_URX0IE            (1 << 2)
+#define IEN0_ADCIE             (1 << 1)
+#define IEN0_RFTXRXIE          (1 << 0)
+
+__sfr __at 0xB8 IEN1;          /* Interrupt Enable 1 Register */
+
+#define IEN1_P0IE              (1 << 5)        /* Port 0 interrupt enable */
+#define IEN1_T4IE              (1 << 4)        /* Timer 4 interrupt enable */
+#define IEN1_T3IE              (1 << 3)        /* Timer 3 interrupt enable */
+#define IEN1_T2IE              (1 << 2)        /* Timer 2 interrupt enable */
+#define IEN1_T1IE              (1 << 1)        /* Timer 1 interrupt enable */
+#define IEN1_DMAIE             (1 << 0)        /* DMA transfer interrupt enable */
+
+/* IEN2 */
+__sfr __at 0x9A IEN2;          /* Interrupt Enable 2 Register */
+
+#define IEN2_WDTIE             (1 << 5)        /* Watchdog timer interrupt enable */
+#define IEN2_P1IE              (1 << 4)        /* Port 1 interrupt enable */
+#define IEN2_UTX1IE            (1 << 3)        /* USART1 TX interrupt enable */
+#define IEN2_I2STXIE           (1 << 3)        /* I2S TX interrupt enable */
+#define IEN2_UTX0IE            (1 << 2)        /* USART0 TX interrupt enable */
+#define IEN2_P2IE              (1 << 1)        /* Port 2 interrupt enable */
+#define IEN2_USBIE             (1 << 1)        /* USB interrupt enable */
+#define IEN2_RFIE              (1 << 0)        /* RF general interrupt enable */
+
+/* CLKCON 0xC6 */
+__sfr __at 0xC6 CLKCON;                /* Clock Control */
+
+#define CLKCON_OSC32K_RC       (1 << 7)
+#define CLKCON_OSC32K_XTAL     (0 << 7)
+#define CLKCON_OSC32K_MASK     (1 << 7)
+#define CLKCON_OSC_RC          (1 << 6)
+#define CLKCON_OSC_XTAL                (0 << 6)
+#define CLKCON_OSC_MASK                (1 << 6)
+#define CLKCON_TICKSPD_MASK    (7 << 3)
+# define CLKCON_TICKSPD_1      (0 << 3)
+# define CLKCON_TICKSPD_1_2    (1 << 3)
+# define CLKCON_TICKSPD_1_4    (2 << 3)
+# define CLKCON_TICKSPD_1_8    (3 << 3)
+# define CLKCON_TICKSPD_1_16   (4 << 3)
+# define CLKCON_TICKSPD_1_32   (5 << 3)
+# define CLKCON_TICKSPD_1_64   (6 << 3)
+# define CLKCON_TICKSPD_1_128  (7 << 3)
+
+#define CLKCON_CLKSPD_MASK     (7 << 0)
+# define CLKCON_CLKSPD_1       (0 << 0)
+# define CLKCON_CLKSPD_1_2     (1 << 0)
+# define CLKCON_CLKSPD_1_4     (2 << 0)
+# define CLKCON_CLKSPD_1_8     (3 << 0)
+# define CLKCON_CLKSPD_1_16    (4 << 0)
+# define CLKCON_CLKSPD_1_32    (5 << 0)
+# define CLKCON_CLKSPD_1_64    (6 << 0)
+# define CLKCON_CLKSPD_1_128   (7 << 0)
+
+/* SLEEP 0xBE */
+#define SLEEP_USB_EN           (1 << 7)
+#define SLEEP_XOSC_STB         (1 << 6)
+#define SLEEP_HFRC_STB         (1 << 5)
+#define SLEEP_RST_POWER                (0 << 3)
+#define SLEEP_RST_EXTERNAL     (1 << 3)
+#define SLEEP_RST_WATCHDOG     (2 << 3)
+#define SLEEP_RST_MASK         (3 << 3)
+#define SLEEP_OSC_PD           (1 << 2)
+#define SLEEP_MODE_PM0         (0 << 0)
+#define SLEEP_MODE_PM1         (1 << 0)
+#define SLEEP_MODE_PM2         (2 << 0)
+#define SLEEP_MODE_PM3         (3 << 0)
+#define SLEEP_MODE_MASK                (3 << 0)
+
+/* PCON 0x87 */
+__sfr __at 0x87 PCON;          /* Power Mode Control Register */
+
+#define PCON_IDLE              (1 << 0)
+
+/*
+ * TCON
+ */
+__sfr __at 0x88 TCON;          /* CPU Interrupt Flag 1 */
+
+sbit __at 0x8F URX1IF;         /* USART1 RX interrupt flag. Automatically cleared */
+sbit __at 0x8F I2SRXIF;                /* I2S RX interrupt flag. Automatically cleared */
+sbit __at 0x8D ADCIF;          /* ADC interrupt flag. Automatically cleared */
+sbit __at 0x8B URX0IF;         /* USART0 RX interrupt flag. Automatically cleared */
+sbit __at 0x89 RFTXRXIF;       /* RF TX/RX complete interrupt flag. Automatically cleared */
+
+#define TCON_URX1IF    (1 << 7)
+#define TCON_I2SRXIF   (1 << 7)
+#define TCON_ADCIF     (1 << 5)
+#define TCON_URX0IF    (1 << 3)
+#define TCON_RFTXRXIF  (1 << 1)
+
+/*
+ * S0CON
+ */
+__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */
+
+sbit __at 0x98 ENCIF_0;        /* AES interrupt 0. */
+sbit __at 0x99 ENCIF_1;        /* AES interrupt 1. */
+
+#define S0CON_ENCIF_1  (1 << 1)
+#define S0CON_ENCIF_0  (1 << 0)
+
+/*
+ * S1CON
+ */
+__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */
+
+#define S1CON_RFIF_1   (1 << 1)
+#define S1CON_RFIF_0   (1 << 0)
+
+/*
+ * IRCON
+ */
+__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */
+
+sbit __at 0xC0 DMAIF;  /* DMA complete interrupt flag */
+sbit __at 0xC1 T1IF;   /* Timer 1 interrupt flag. Automatically cleared */
+sbit __at 0xC2 T2IF;   /* Timer 2 interrupt flag. Automatically cleared */
+sbit __at 0xC3 T3IF;   /* Timer 3 interrupt flag. Automatically cleared */
+sbit __at 0xC4 T4IF;   /* Timer 4 interrupt flag. Automatically cleared */
+sbit __at 0xC5 P0IF;   /* Port0 interrupt flag */
+sbit __at 0xC7 STIF;   /* Sleep Timer interrupt flag */
+
+#define IRCON_DMAIF    (1 << 0)        /* DMA complete interrupt flag */
+#define IRCON_T1IF     (1 << 1)        /* Timer 1 interrupt flag. Automatically cleared */
+#define IRCON_T2IF     (1 << 2)        /* Timer 2 interrupt flag. Automatically cleared */
+#define IRCON_T3IF     (1 << 3)        /* Timer 3 interrupt flag. Automatically cleared */
+#define IRCON_T4IF     (1 << 4)        /* Timer 4 interrupt flag. Automatically cleared */
+#define IRCON_P0IF     (1 << 5)        /* Port0 interrupt flag */
+#define IRCON_STIF     (1 << 7)        /* Sleep Timer interrupt flag */
+
+/*
+ * IRCON2
+ */
+__sfr __at 0xE8 IRCON2;        /* CPU Interrupt Flag 5 */
+
+sbit __at 0xE8 USBIF;  /* USB interrupt flag (shared with Port2) */
+sbit __at 0xE8 P2IF;   /* Port2 interrupt flag (shared with USB) */
+sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */
+sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */
+sbit __at 0xEA I2STXIF;        /* I2S TX interrupt flag (shared with USART1 TX) */
+sbit __at 0xEB P1IF;   /* Port1 interrupt flag */
+sbit __at 0xEC WDTIF;  /* Watchdog timer interrupt flag */
+
+#define IRCON2_USBIF   (1 << 0)        /* USB interrupt flag (shared with Port2) */
+#define IRCON2_P2IF    (1 << 0)        /* Port2 interrupt flag (shared with USB) */
+#define IRCON2_UTX0IF  (1 << 1)        /* USART0 TX interrupt flag */
+#define IRCON2_UTX1IF  (1 << 2)        /* USART1 TX interrupt flag (shared with I2S TX) */
+#define IRCON2_I2STXIF (1 << 2)        /* I2S TX interrupt flag (shared with USART1 TX) */
+#define IRCON2_P1IF    (1 << 3)        /* Port1 interrupt flag */
+#define IRCON2_WDTIF   (1 << 4)        /* Watchdog timer interrupt flag */
+
+/*
+ * IP1 - Interrupt Priority 1
+ */
+
+/*
+ * Interrupt priority groups:
+ *
+ * IPG0                RFTXRX          RF              DMA
+ * IPG1                ADC             T1              P2INT/USB
+ * IPG2                URX0            T2              UTX0
+ * IPG3                URX1/I2SRX      T3              UTX1 / I2STX
+ * IPG4                ENC             T4              P1INT
+ * IPG5                ST              P0INT           WDT
+ *
+ * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first
+ */
+
+__sfr __at 0xB9 IP1;   /* Interrupt Priority 1 */
+__sfr __at 0xA9 IP0;   /* Interrupt Priority 0 */
+
+#define IP1_IPG5       (1 << 5)
+#define IP1_IPG4       (1 << 4)
+#define IP1_IPG3       (1 << 3)
+#define IP1_IPG2       (1 << 2)
+#define IP1_IPG1       (1 << 1)
+#define IP1_IPG0       (1 << 0)
+
+#define IP0_IPG5       (1 << 5)
+#define IP0_IPG4       (1 << 4)
+#define IP0_IPG3       (1 << 3)
+#define IP0_IPG2       (1 << 2)
+#define IP0_IPG1       (1 << 1)
+#define IP0_IPG0       (1 << 0)
+
+/*
+ * Timer 1
+ */
+#define T1CTL_MODE_SUSPENDED   (0 << 0)
+#define T1CTL_MODE_FREE                (1 << 0)
+#define T1CTL_MODE_MODULO      (2 << 0)
+#define T1CTL_MODE_UP_DOWN     (3 << 0)
+#define T1CTL_MODE_MASK                (3 << 0)
+#define T1CTL_DIV_1            (0 << 2)
+#define T1CTL_DIV_8            (1 << 2)
+#define T1CTL_DIV_32           (2 << 2)
+#define T1CTL_DIV_128          (3 << 2)
+#define T1CTL_DIV_MASK         (3 << 2)
+#define T1CTL_OVFIF            (1 << 4)
+#define T1CTL_CH0IF            (1 << 5)
+#define T1CTL_CH1IF            (1 << 6)
+#define T1CTL_CH2IF            (1 << 7)
+
+#define T1CCTL_NO_CAPTURE      (0 << 0)
+#define T1CCTL_CAPTURE_RISING  (1 << 0)
+#define T1CCTL_CAPTURE_FALLING (2 << 0)
+#define T1CCTL_CAPTURE_BOTH    (3 << 0)
+#define T1CCTL_CAPTURE_MASK    (3 << 0)
+
+#define T1CCTL_MODE_CAPTURE    (0 << 2)
+#define T1CCTL_MODE_COMPARE    (1 << 2)
+
+#define T1CTL_CMP_SET          (0 << 3)
+#define T1CTL_CMP_CLEAR                (1 << 3)
+#define T1CTL_CMP_TOGGLE       (2 << 3)
+#define T1CTL_CMP_SET_CLEAR    (3 << 3)
+#define T1CTL_CMP_CLEAR_SET    (4 << 3)
+
+#define T1CTL_IM_DISABLED      (0 << 6)
+#define T1CTL_IM_ENABLED       (1 << 6)
+
+#define T1CTL_CPSEL_NORMAL     (0 << 7)
+#define T1CTL_CPSEL_RF         (1 << 7)
+
+/*
+ * Timer 3 and Timer 4
+ */
+
+/* Timer count */
+__sfr __at 0xCA T3CNT;
+__sfr __at 0xEA T4CNT;
+
+/* Timer control */
+
+__sfr __at 0xCB T3CTL;
+__sfr __at 0xEB T4CTL;
+
+#define TxCTL_DIV_1            (0 << 5)
+#define TxCTL_DIV_2            (1 << 5)
+#define TxCTL_DIV_4            (2 << 5)
+#define TxCTL_DIV_8            (3 << 5)
+#define TxCTL_DIV_16           (4 << 5)
+#define TxCTL_DIV_32           (5 << 5)
+#define TxCTL_DIV_64           (6 << 5)
+#define TxCTL_DIV_128          (7 << 5)
+#define TxCTL_START            (1 << 4)
+#define TxCTL_OVFIM            (1 << 3)
+#define TxCTL_CLR              (1 << 2)
+#define TxCTL_MODE_FREE                (0 << 0)
+#define TxCTL_MODE_DOWN                (1 << 0)
+#define TxCTL_MODE_MODULO      (2 << 0)
+#define TxCTL_MODE_UP_DOWN     (3 << 0)
+
+/* Timer 4 channel 0 compare control */
+
+__sfr __at 0xCC T3CCTL0;
+__sfr __at 0xCE T3CCTL1;
+__sfr __at 0xEC T4CCTL0;
+__sfr __at 0xEE T4CCTL1;
+
+#define TxCCTLy_IM                     (1 << 6)
+#define TxCCTLy_CMP_SET                        (0 << 3)
+#define TxCCTLy_CMP_CLEAR              (1 << 3)
+#define TxCCTLy_CMP_TOGGLE             (2 << 3)
+#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN  (3 << 3)
+#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN  (4 << 3)
+#define TxCCTLy_CMP_SET_CLEAR_FF       (5 << 3)
+#define TxCCTLy_CMP_CLEAR_SET_00       (6 << 3)
+#define TxCCTLy_CMP_MODE_ENABLE                (1 << 2)
+
+/* Timer compare value */
+__sfr __at 0xCD T3CC0;
+__sfr __at 0xCF T3CC1;
+__sfr __at 0xED T4CC0;
+__sfr __at 0xEF T4CC1;
+
+/*
+ * Peripheral control
+ */
+
+__sfr __at 0xf1 PERCFG;
+#define PERCFG_T1CFG_ALT_1      (0 << 6)
+#define PERCFG_T1CFG_ALT_2      (1 << 6)
+#define PERCFG_T1CFG_ALT_MASK   (1 << 6)
+
+#define PERCFG_T3CFG_ALT_1      (0 << 5)
+#define PERCFG_T3CFG_ALT_2      (1 << 5)
+#define PERCFG_T3CFG_ALT_MASK   (1 << 5)
+
+#define PERCFG_T4CFG_ALT_1      (0 << 4)
+#define PERCFG_T4CFG_ALT_2      (1 << 4)
+#define PERCFG_T4CFG_ALT_MASK   (1 << 4)
+
+#define PERCFG_U1CFG_ALT_1      (0 << 1)
+#define PERCFG_U1CFG_ALT_2      (1 << 1)
+#define PERCFG_U1CFG_ALT_MASK   (1 << 1)
+
+#define PERCFG_U0CFG_ALT_1      (0 << 0)
+#define PERCFG_U0CFG_ALT_2      (1 << 0)
+#define PERCFG_U0CFG_ALT_MASK   (1 << 0)
+
+/* directly addressed USB registers */
+__xdata __at (0xde00) volatile uint8_t USBADDR;
+__xdata __at (0xde01) volatile uint8_t USBPOW;
+__xdata __at (0xde02) volatile uint8_t USBIIF;
+
+__xdata __at (0xde04) volatile uint8_t USBOIF;
+
+__xdata __at (0xde06) volatile uint8_t USBCIF;
+
+# define USBCIF_SOFIF          (1 << 3)
+# define USBCIF_RSTIF          (1 << 2)
+# define USBCIF_RESUMEIF       (1 << 1)
+# define USBCIF_SUSPENDIF      (1 << 0)
+
+__xdata __at (0xde07) volatile uint8_t USBIIE;
+
+__xdata __at (0xde09) volatile uint8_t USBOIE;
+
+__xdata __at (0xde0b) volatile uint8_t USBCIE;
+
+# define USBCIE_SOFIE          (1 << 3)
+# define USBCIE_RSTIE          (1 << 2)
+# define USBCIE_RESUMEIE       (1 << 1)
+# define USBCIE_SUSPENDIE      (1 << 0)
+
+__xdata __at (0xde0c) volatile uint8_t USBFRML;
+__xdata __at (0xde0d) volatile uint8_t USBFRMH;
+__xdata __at (0xde0e) volatile uint8_t USBINDEX;
+
+/* indexed USB registers, must set USBINDEX to 0-5 */
+__xdata __at (0xde10) volatile uint8_t USBMAXI;
+__xdata __at (0xde11) volatile uint8_t USBCS0;
+
+# define USBCS0_CLR_SETUP_END          (1 << 7)
+# define USBCS0_CLR_OUTPKT_RDY         (1 << 6)
+# define USBCS0_SEND_STALL             (1 << 5)
+# define USBCS0_SETUP_END              (1 << 4)
+# define USBCS0_DATA_END               (1 << 3)
+# define USBCS0_SENT_STALL             (1 << 2)
+# define USBCS0_INPKT_RDY              (1 << 1)
+# define USBCS0_OUTPKT_RDY             (1 << 0)
+
+__xdata __at (0xde11) volatile uint8_t USBCSIL;
+
+# define USBCSIL_CLR_DATA_TOG          (1 << 6)
+# define USBCSIL_SENT_STALL            (1 << 5)
+# define USBCSIL_SEND_STALL            (1 << 4)
+# define USBCSIL_FLUSH_PACKET          (1 << 3)
+# define USBCSIL_UNDERRUN              (1 << 2)
+# define USBCSIL_PKT_PRESENT           (1 << 1)
+# define USBCSIL_INPKT_RDY             (1 << 0)
+
+__xdata __at (0xde12) volatile uint8_t USBCSIH;
+
+# define USBCSIH_AUTOSET               (1 << 7)
+# define USBCSIH_ISO                   (1 << 6)
+# define USBCSIH_FORCE_DATA_TOG                (1 << 3)
+# define USBCSIH_IN_DBL_BUF            (1 << 0)
+
+__xdata __at (0xde13) volatile uint8_t USBMAXO;
+__xdata __at (0xde14) volatile uint8_t USBCSOL;
+
+# define USBCSOL_CLR_DATA_TOG          (1 << 7)
+# define USBCSOL_SENT_STALL            (1 << 6)
+# define USBCSOL_SEND_STALL            (1 << 5)
+# define USBCSOL_FLUSH_PACKET          (1 << 4)
+# define USBCSOL_DATA_ERROR            (1 << 3)
+# define USBCSOL_OVERRUN               (1 << 2)
+# define USBCSOL_FIFO_FULL             (1 << 1)
+# define USBCSOL_OUTPKT_RDY            (1 << 0)
+
+__xdata __at (0xde15) volatile uint8_t USBCSOH;
+
+# define USBCSOH_AUTOCLEAR             (1 << 7)
+# define USBCSOH_ISO                   (1 << 6)
+# define USBCSOH_OUT_DBL_BUF           (1 << 0)
+
+__xdata __at (0xde16) volatile uint8_t USBCNT0;
+__xdata __at (0xde16) volatile uint8_t USBCNTL;
+__xdata __at (0xde17) volatile uint8_t USBCNTH;
+
+__xdata __at (0xde20) volatile uint8_t USBFIFO[12];
+
+/* ADC Data register, low and high */
+__sfr at 0xBA ADCL;
+__sfr at 0xBB ADCH;
+__xdata __at (0xDFBA) volatile uint16_t ADCXDATA;
+
+/* ADC Control Register 1 */
+__sfr at 0xB4 ADCCON1;
+
+# define ADCCON1_EOC           (1 << 7)        /* conversion complete */
+# define ADCCON1_ST            (1 << 6)        /* start conversion */
+
+# define ADCCON1_STSEL_MASK    (3 << 4)        /* start select */
+# define ADCCON1_STSEL_EXTERNAL        (0 << 4)        /* P2_0 pin triggers */
+# define ADCCON1_STSEL_FULLSPEED (1 << 4)      /* full speed, no waiting */
+# define ADCCON1_STSEL_TIMER1  (2 << 4)        /* timer 1 channel 0 */
+# define ADCCON1_STSEL_START   (3 << 4)        /* set start bit */
+
+# define ADCCON1_RCTRL_MASK    (3 << 2)        /* random number control */
+# define ADCCON1_RCTRL_COMPLETE        (0 << 2)        /* operation completed */
+# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2)     /* Clock the LFSR once */
+
+/* ADC Control Register 2 */
+__sfr at 0xB5 ADCCON2;
+
+# define ADCCON2_SREF_MASK     (3 << 6)        /* reference voltage */
+# define ADCCON2_SREF_1_25V    (0 << 6)        /* internal 1.25V */
+# define ADCCON2_SREF_EXTERNAL (1 << 6)        /* external on AIN7 cc1110 */
+# define ADCCON2_SREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
+# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6)   /* external on AIN6-7 cc1110 */
+
+# define ADCCON2_SDIV_MASK     (3 << 4)        /* decimation rate */
+# define ADCCON2_SDIV_64       (0 << 4)        /* 7 bits */
+# define ADCCON2_SDIV_128      (1 << 4)        /* 9 bits */
+# define ADCCON2_SDIV_256      (2 << 4)        /* 10 bits */
+# define ADCCON2_SDIV_512      (3 << 4)        /* 12 bits */
+
+# define ADCCON2_SCH_MASK      (0xf << 0)      /* Sequence channel select */
+# define ADCCON2_SCH_SHIFT     0
+# define ADCCON2_SCH_AIN0      (0 << 0)
+# define ADCCON2_SCH_AIN1      (1 << 0)
+# define ADCCON2_SCH_AIN2      (2 << 0)
+# define ADCCON2_SCH_AIN3      (3 << 0)
+# define ADCCON2_SCH_AIN4      (4 << 0)
+# define ADCCON2_SCH_AIN5      (5 << 0)
+# define ADCCON2_SCH_AIN6      (6 << 0)
+# define ADCCON2_SCH_AIN7      (7 << 0)
+# define ADCCON2_SCH_AIN0_AIN1 (8 << 0)
+# define ADCCON2_SCH_AIN2_AIN3 (9 << 0)
+# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0)
+# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0)
+# define ADCCON2_SCH_GND       (0xc << 0)
+# define ADCCON2_SCH_VREF      (0xd << 0)
+# define ADCCON2_SCH_TEMP      (0xe << 0)
+# define ADCCON2_SCH_VDD_3     (0xf << 0)
+
+
+/* ADC Control Register 3 */
+__sfr at 0xB6 ADCCON3;
+
+# define ADCCON3_EREF_MASK     (3 << 6)        /* extra conversion reference */
+# define ADCCON3_EREF_1_25     (0 << 6)        /* internal 1.25V */
+# define ADCCON3_EREF_EXTERNAL (1 << 6)        /* external AIN7 cc1110 */
+# define ADCCON3_EREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
+# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6)   /* external AIN6-7 cc1110 */
+# define ADCCON3_EDIV_MASK     (3 << 4)        /* extral decimation */
+# define ADCCON3_EDIV_64       (0 << 4)        /* 7 bits */
+# define ADCCON3_EDIV_128      (1 << 4)        /* 9 bits */
+# define ADCCON3_EDIV_256      (2 << 4)        /* 10 bits */
+# define ADCCON3_EDIV_512      (3 << 4)        /* 12 bits */
+# define ADCCON3_ECH_MASK      (0xf << 0)      /* Sequence channel select */
+# define ADCCON3_ECH_SHIFT     0
+# define ADCCON3_ECH_AIN0      (0 << 0)
+# define ADCCON3_ECH_AIN1      (1 << 0)
+# define ADCCON3_ECH_AIN2      (2 << 0)
+# define ADCCON3_ECH_AIN3      (3 << 0)
+# define ADCCON3_ECH_AIN4      (4 << 0)
+# define ADCCON3_ECH_AIN5      (5 << 0)
+# define ADCCON3_ECH_AIN6      (6 << 0)
+# define ADCCON3_ECH_AIN7      (7 << 0)
+# define ADCCON3_ECH_AIN0_AIN1 (8 << 0)
+# define ADCCON3_ECH_AIN2_AIN3 (9 << 0)
+# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0)
+# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0)
+# define ADCCON3_ECH_GND       (0xc << 0)
+# define ADCCON3_ECH_VREF      (0xd << 0)
+# define ADCCON3_ECH_TEMP      (0xe << 0)
+# define ADCCON3_ECH_VDD_3     (0xf << 0)
+
+/*
+ * ADC configuration register, this selects which
+ * GPIO pins are to be used as ADC inputs
+ */
+__sfr at 0xF2 ADCCFG;
+
+/*
+ * Watchdog timer
+ */
+
+__sfr at 0xc9 WDCTL;
+
+#define WDCTL_CLEAR_FIRST      (0xa << 4)
+#define WDCTL_CLEAR_SECOND     (0x5 << 4)
+#define WDCTL_EN               (1 << 3)
+#define WDCTL_MODE_WATCHDOG    (0 << 2)
+#define WDCTL_MODE_TIMER       (1 << 2)
+#define WDCTL_MODE_MASK                (1 << 2)
+#define WDCTL_INT_32768                (0 << 0)
+#define WDCTL_INT_8192         (1 << 0)
+#define WDCTL_INT_512          (2 << 0)
+#define WDCTL_INT_64           (3 << 0)
+
+/*
+ * Pin selectors, these set which pins are
+ * using their peripheral function
+ */
+__sfr at 0xF3 P0SEL;
+__sfr at 0xF4 P1SEL;
+__sfr at 0xF5 P2SEL;
+
+#define P2SEL_PRI3P1_USART0            (0 << 6)
+#define P2SEL_PRI3P1_USART1            (1 << 6)
+#define P2SEL_PRI3P1_MASK              (1 << 6)
+#define P2SEL_PRI2P1_USART1            (0 << 5)
+#define P2SEL_PRI2P1_TIMER3            (1 << 5)
+#define P2SEL_PRI2P1_MASK              (1 << 5)
+#define P2SEL_PRI1P1_TIMER1            (0 << 4)
+#define P2SEL_PRI1P1_TIMER4            (1 << 4)
+#define P2SEL_PRI1P1_MASK              (1 << 4)
+#define P2SEL_PRI0P1_USART0            (0 << 3)
+#define P2SEL_PRI0P1_TIMER1            (1 << 3)
+#define P2SEL_PRI0P1_MASK              (1 << 3)
+#define P2SEL_SELP2_4_GPIO             (0 << 2)
+#define P2SEL_SELP2_4_PERIPHERAL       (1 << 2)
+#define P2SEL_SELP2_4_MASK             (1 << 2)
+#define P2SEL_SELP2_3_GPIO             (0 << 1)
+#define P2SEL_SELP2_3_PERIPHERAL       (1 << 1)
+#define P2SEL_SELP2_3_MASK             (1 << 1)
+#define P2SEL_SELP2_0_GPIO             (0 << 0)
+#define P2SEL_SELP2_0_PERIPHERAL       (1 << 0)
+#define P2SEL_SELP2_0_MASK             (1 << 0)
+
+/*
+ * For pins used as GPIOs, these set which are used as outputs
+ */
+__sfr at 0xFD P0DIR;
+__sfr at 0xFE P1DIR;
+__sfr at 0xFF P2DIR;
+
+#define P2DIR_PRIP0_USART0_USART1      (0 << 6)
+#define P2DIR_PRIP0_USART1_USART0      (1 << 6)
+#define P2DIR_PRIP0_TIMER1_01_USART1   (2 << 6)
+#define P2DIR_PRIP0_TIMER1_2_USART0    (3 << 6)
+#define P2DIR_PRIP0_MASK               (3 << 6)
+
+__sfr at 0x8F P0INP;
+
+/* Select between tri-state and pull up/down
+ * for pins P0_0 - P0_7.
+ */
+#define P0INP_MDP0_7_PULL      (0 << 7)
+#define P0INP_MDP0_7_TRISTATE  (1 << 7)
+#define P0INP_MDP0_6_PULL      (0 << 6)
+#define P0INP_MDP0_6_TRISTATE  (1 << 6)
+#define P0INP_MDP0_5_PULL      (0 << 5)
+#define P0INP_MDP0_5_TRISTATE  (1 << 5)
+#define P0INP_MDP0_4_PULL      (0 << 4)
+#define P0INP_MDP0_4_TRISTATE  (1 << 4)
+#define P0INP_MDP0_3_PULL      (0 << 3)
+#define P0INP_MDP0_3_TRISTATE  (1 << 3)
+#define P0INP_MDP0_2_PULL      (0 << 2)
+#define P0INP_MDP0_2_TRISTATE  (1 << 2)
+#define P0INP_MDP0_1_PULL      (0 << 1)
+#define P0INP_MDP0_1_TRISTATE  (1 << 1)
+#define P0INP_MDP0_0_PULL      (0 << 0)
+#define P0INP_MDP0_0_TRISTATE  (1 << 0)
+
+__sfr at 0xF6 P1INP;
+
+/* Select between tri-state and pull up/down
+ * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are
+ * always tri-stated
+ */
+#define P1INP_MDP1_7_PULL      (0 << 7)
+#define P1INP_MDP1_7_TRISTATE  (1 << 7)
+#define P1INP_MDP1_6_PULL      (0 << 6)
+#define P1INP_MDP1_6_TRISTATE  (1 << 6)
+#define P1INP_MDP1_5_PULL      (0 << 5)
+#define P1INP_MDP1_5_TRISTATE  (1 << 5)
+#define P1INP_MDP1_4_PULL      (0 << 4)
+#define P1INP_MDP1_4_TRISTATE  (1 << 4)
+#define P1INP_MDP1_3_PULL      (0 << 3)
+#define P1INP_MDP1_3_TRISTATE  (1 << 3)
+#define P1INP_MDP1_2_PULL      (0 << 2)
+#define P1INP_MDP1_2_TRISTATE  (1 << 2)
+
+__sfr at 0xF7 P2INP;
+/* P2INP has three extra bits which are used to choose
+ * between pull-up and pull-down when they are not tri-stated
+ */
+#define P2INP_PDUP2_PULL_UP    (0 << 7)
+#define P2INP_PDUP2_PULL_DOWN  (1 << 7)
+#define P2INP_PDUP1_PULL_UP    (0 << 6)
+#define P2INP_PDUP1_PULL_DOWN  (1 << 6)
+#define P2INP_PDUP0_PULL_UP    (0 << 5)
+#define P2INP_PDUP0_PULL_DOWN  (1 << 5)
+
+/* For the P2 pins, choose between tri-state and pull up/down
+ * mode
+ */
+#define P2INP_MDP2_4_PULL      (0 << 4)
+#define P2INP_MDP2_4_TRISTATE  (1 << 4)
+#define P2INP_MDP2_3_PULL      (0 << 3)
+#define P2INP_MDP2_3_TRISTATE  (1 << 3)
+#define P2INP_MDP2_2_PULL      (0 << 2)
+#define P2INP_MDP2_2_TRISTATE  (1 << 2)
+#define P2INP_MDP2_1_PULL      (0 << 1)
+#define P2INP_MDP2_1_TRISTATE  (1 << 1)
+#define P2INP_MDP2_0_PULL      (0 << 0)
+#define P2INP_MDP2_0_TRISTATE  (1 << 0)
+
+/* GPIO interrupt status flags */
+__sfr at 0x89 P0IFG;
+__sfr at 0x8A P1IFG;
+__sfr at 0x8B P2IFG;
+
+#define P0IFG_USB_RESUME       (1 << 7)
+
+__sfr at 0x8C PICTL;
+#define PICTL_P2IEN    (1 << 5)
+#define PICTL_P0IENH   (1 << 4)
+#define PICTL_P0IENL   (1 << 3)
+#define PICTL_P2ICON   (1 << 2)
+#define PICTL_P1ICON   (1 << 1)
+#define PICTL_P0ICON   (1 << 0)
+
+/* GPIO pins */
+__sfr at 0x80 P0;
+
+sbit at 0x80 P0_0;
+sbit at 0x81 P0_1;
+sbit at 0x82 P0_2;
+sbit at 0x83 P0_3;
+sbit at 0x84 P0_4;
+sbit at 0x85 P0_5;
+sbit at 0x86 P0_6;
+sbit at 0x87 P0_7;
+
+__sfr at 0x90 P1;
+
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+__sfr at 0xa0 P2;
+
+sbit at 0xa0 P2_0;
+sbit at 0xa1 P2_1;
+sbit at 0xa2 P2_2;
+sbit at 0xa3 P2_3;
+sbit at 0xa4 P2_4;
+
+/* DMA controller */
+struct cc_dma_channel {
+       uint8_t src_high;
+       uint8_t src_low;
+       uint8_t dst_high;
+       uint8_t dst_low;
+       uint8_t len_high;
+       uint8_t len_low;
+       uint8_t cfg0;
+       uint8_t cfg1;
+};
+
+# define DMA_LEN_HIGH_VLEN_MASK                (7 << 5)
+# define DMA_LEN_HIGH_VLEN_LEN         (0 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_1      (1 << 5)
+# define DMA_LEN_HIGH_VLEN             (2 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_2      (3 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_3      (4 << 5)
+# define DMA_LEN_HIGH_MASK             (0x1f)
+
+# define DMA_CFG0_WORDSIZE_8           (0 << 7)
+# define DMA_CFG0_WORDSIZE_16          (1 << 7)
+# define DMA_CFG0_TMODE_MASK           (3 << 5)
+# define DMA_CFG0_TMODE_SINGLE         (0 << 5)
+# define DMA_CFG0_TMODE_BLOCK          (1 << 5)
+# define DMA_CFG0_TMODE_REPEATED_SINGLE        (2 << 5)
+# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5)
+
+/*
+ * DMA triggers
+ */
+# define DMA_CFG0_TRIGGER_NONE         0
+# define DMA_CFG0_TRIGGER_PREV         1
+# define DMA_CFG0_TRIGGER_T1_CH0       2
+# define DMA_CFG0_TRIGGER_T1_CH1       3
+# define DMA_CFG0_TRIGGER_T1_CH2       4
+# define DMA_CFG0_TRIGGER_T2_OVFL      6
+# define DMA_CFG0_TRIGGER_T3_CH0       7
+# define DMA_CFG0_TRIGGER_T3_CH1       8
+# define DMA_CFG0_TRIGGER_T4_CH0       9
+# define DMA_CFG0_TRIGGER_T4_CH1       10
+# define DMA_CFG0_TRIGGER_IOC_0                12
+# define DMA_CFG0_TRIGGER_IOC_1                13
+# define DMA_CFG0_TRIGGER_URX0         14
+# define DMA_CFG0_TRIGGER_UTX0         15
+# define DMA_CFG0_TRIGGER_URX1         16
+# define DMA_CFG0_TRIGGER_UTX1         17
+# define DMA_CFG0_TRIGGER_FLASH                18
+# define DMA_CFG0_TRIGGER_RADIO                19
+# define DMA_CFG0_TRIGGER_ADC_CHALL    20
+# define DMA_CFG0_TRIGGER_ADC_CH0      21
+# define DMA_CFG0_TRIGGER_ADC_CH1      22
+# define DMA_CFG0_TRIGGER_ADC_CH2      23
+# define DMA_CFG0_TRIGGER_ADC_CH3      24
+# define DMA_CFG0_TRIGGER_ADC_CH4      25
+# define DMA_CFG0_TRIGGER_ADC_CH5      26
+# define DMA_CFG0_TRIGGER_ADC_CH6      27
+# define DMA_CFG0_TRIGGER_I2SRX                27
+# define DMA_CFG0_TRIGGER_ADC_CH7      28
+# define DMA_CFG0_TRIGGER_I2STX                28
+# define DMA_CFG0_TRIGGER_ENC_DW       29
+# define DMA_CFG0_TRIGGER_DNC_UP       30
+
+# define DMA_CFG1_SRCINC_MASK          (3 << 6)
+# define DMA_CFG1_SRCINC_0             (0 << 6)
+# define DMA_CFG1_SRCINC_1             (1 << 6)
+# define DMA_CFG1_SRCINC_2             (2 << 6)
+# define DMA_CFG1_SRCINC_MINUS_1       (3 << 6)
+
+# define DMA_CFG1_DESTINC_MASK         (3 << 4)
+# define DMA_CFG1_DESTINC_0            (0 << 4)
+# define DMA_CFG1_DESTINC_1            (1 << 4)
+# define DMA_CFG1_DESTINC_2            (2 << 4)
+# define DMA_CFG1_DESTINC_MINUS_1      (3 << 4)
+
+# define DMA_CFG1_IRQMASK              (1 << 3)
+# define DMA_CFG1_M8                   (1 << 2)
+
+# define DMA_CFG1_PRIORITY_MASK                (3 << 0)
+# define DMA_CFG1_PRIORITY_LOW         (0 << 0)
+# define DMA_CFG1_PRIORITY_NORMAL      (1 << 0)
+# define DMA_CFG1_PRIORITY_HIGH                (2 << 0)
+
+/*
+ * DMAARM - DMA Channel Arm
+ */
+
+__sfr at 0xD6 DMAARM;
+
+# define DMAARM_ABORT                  (1 << 7)
+# define DMAARM_DMAARM4                        (1 << 4)
+# define DMAARM_DMAARM3                        (1 << 3)
+# define DMAARM_DMAARM2                        (1 << 2)
+# define DMAARM_DMAARM1                        (1 << 1)
+# define DMAARM_DMAARM0                        (1 << 0)
+
+/*
+ * DMAREQ - DMA Channel Start Request and Status
+ */
+
+__sfr at 0xD7 DMAREQ;
+
+# define DMAREQ_DMAREQ4                        (1 << 4)
+# define DMAREQ_DMAREQ3                        (1 << 3)
+# define DMAREQ_DMAREQ2                        (1 << 2)
+# define DMAREQ_DMAREQ1                        (1 << 1)
+# define DMAREQ_DMAREQ0                        (1 << 0)
+
+/*
+ * DMA configuration 0 address
+ */
+
+__sfr at 0xD5 DMA0CFGH;
+__sfr at 0xD4 DMA0CFGL;
+
+/*
+ * DMA configuration 1-4 address
+ */
+
+__sfr at 0xD3 DMA1CFGH;
+__sfr at 0xD2 DMA1CFGL;
+
+/*
+ * DMAIRQ - DMA Interrupt Flag
+ */
+
+__sfr at 0xD1 DMAIRQ;
+
+# define DMAIRQ_DMAIF4                 (1 << 4)
+# define DMAIRQ_DMAIF3                 (1 << 3)
+# define DMAIRQ_DMAIF2                 (1 << 2)
+# define DMAIRQ_DMAIF1                 (1 << 1)
+# define DMAIRQ_DMAIF0                 (1 << 0)
+
+/*
+ * UART registers
+ */
+
+/* USART config/status registers */
+__sfr at 0x86 U0CSR;
+__sfr at 0xF8 U1CSR;
+
+# define UxCSR_MODE_UART               (1 << 7)
+# define UxCSR_MODE_SPI                        (0 << 7)
+# define UxCSR_RE                      (1 << 6)
+# define UxCSR_SLAVE                   (1 << 5)
+# define UxCSR_MASTER                  (0 << 5)
+# define UxCSR_FE                      (1 << 4)
+# define UxCSR_ERR                     (1 << 3)
+# define UxCSR_RX_BYTE                 (1 << 2)
+# define UxCSR_TX_BYTE                 (1 << 1)
+# define UxCSR_ACTIVE                  (1 << 0)
+
+/* UART configuration registers */
+__sfr at 0xc4 U0UCR;
+__sfr at 0xfb U1UCR;
+
+# define UxUCR_FLUSH                    (1 << 7)
+# define UxUCR_FLOW_DISABLE             (0 << 6)
+# define UxUCR_FLOW_ENABLE              (1 << 6)
+# define UxUCR_D9_EVEN_PARITY           (0 << 5)
+# define UxUCR_D9_ODD_PARITY            (1 << 5)
+# define UxUCR_BIT9_8_BITS              (0 << 4)
+# define UxUCR_BIT9_9_BITS              (1 << 4)
+# define UxUCR_PARITY_DISABLE           (0 << 3)
+# define UxUCR_PARITY_ENABLE            (1 << 3)
+# define UxUCR_SPB_1_STOP_BIT           (0 << 2)
+# define UxUCR_SPB_2_STOP_BITS          (1 << 2)
+# define UxUCR_STOP_LOW                 (0 << 1)
+# define UxUCR_STOP_HIGH                (1 << 1)
+# define UxUCR_START_LOW                (0 << 0)
+# define UxUCR_START_HIGH               (1 << 0)
+
+/* USART General configuration registers (mostly SPI) */
+__sfr at 0xc5 U0GCR;
+__sfr at 0xfc U1GCR;
+
+# define UxGCR_CPOL_NEGATIVE           (0 << 7)
+# define UxGCR_CPOL_POSITIVE           (1 << 7)
+# define UxGCR_CPHA_FIRST_EDGE         (0 << 6)
+# define UxGCR_CPHA_SECOND_EDGE                (1 << 6)
+# define UxGCR_ORDER_LSB               (0 << 5)
+# define UxGCR_ORDER_MSB               (1 << 5)
+# define UxGCR_BAUD_E_MASK             (0x1f)
+# define UxGCR_BAUD_E_SHIFT            0
+
+/* USART data registers */
+__sfr at 0xc1 U0DBUF;
+__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR;
+__sfr at 0xf9 U1DBUF;
+__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR;
+
+/* USART baud rate registers, M value */
+__sfr at 0xc2 U0BAUD;
+__sfr at 0xfa U1BAUD;
+
+/* Flash controller */
+
+__sfr at 0xAE FCTL;
+#define FCTL_BUSY              (1 << 7)
+#define FCTL_SWBSY             (1 << 6)
+#define FCTL_CONTRD_ENABLE     (1 << 4)
+#define FCTL_WRITE             (1 << 1)
+#define FCTL_ERASE             (1 << 0)
+
+/* Flash write data. Write two bytes here */
+__sfr at 0xAF FWDATA;
+__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR;
+
+/* Flash write/erase address */
+__sfr at 0xAD FADDRH;
+__sfr at 0xAC FADDRL;
+
+/* Flash timing */
+__sfr at 0xAB FWT;
+
+/* Radio */
+
+__sfr at 0xD9 RFD;
+__xdata at (0xDFD9) volatile uint8_t RFDXADDR;
+
+__sfr at 0xE9 RFIF;
+#define RFIF_IM_TXUNF  (1 << 7)
+#define RFIF_IM_RXOVF  (1 << 6)
+#define RFIF_IM_TIMEOUT        (1 << 5)
+#define RFIF_IM_DONE   (1 << 4)
+#define RFIF_IM_CS     (1 << 3)
+#define RFIF_IM_PQT    (1 << 2)
+#define RFIF_IM_CCA    (1 << 1)
+#define RFIF_IM_SFD    (1 << 0)
+
+__sfr at 0x91 RFIM;
+#define RFIM_IM_TXUNF  (1 << 7)
+#define RFIM_IM_RXOVF  (1 << 6)
+#define RFIM_IM_TIMEOUT        (1 << 5)
+#define RFIM_IM_DONE   (1 << 4)
+#define RFIM_IM_CS     (1 << 3)
+#define RFIM_IM_PQT    (1 << 2)
+#define RFIM_IM_CCA    (1 << 1)
+#define RFIM_IM_SFD    (1 << 0)
+
+__sfr at 0xE1 RFST;
+
+#define RFST_SFSTXON   0x00
+#define RFST_SCAL      0x01
+#define RFST_SRX       0x02
+#define RFST_STX       0x03
+#define RFST_SIDLE     0x04
+
+__xdata __at (0xdf00) uint8_t RF[0x3c];
+
+__xdata __at (0xdf2f) uint8_t RF_IOCFG2;
+#define RF_IOCFG2_OFF  0x2f
+
+__xdata __at (0xdf30) uint8_t RF_IOCFG1;
+#define RF_IOCFG1_OFF  0x30
+
+__xdata __at (0xdf31) uint8_t RF_IOCFG0;
+#define RF_IOCFG0_OFF  0x31
+
+__xdata __at (0xdf00) uint8_t RF_SYNC1;
+#define RF_SYNC1_OFF   0x00
+
+__xdata __at (0xdf01) uint8_t RF_SYNC0;
+#define RF_SYNC0_OFF   0x01
+
+__xdata __at (0xdf02) uint8_t RF_PKTLEN;
+#define RF_PKTLEN_OFF  0x02
+
+__xdata __at (0xdf03) uint8_t RF_PKTCTRL1;
+#define RF_PKTCTRL1_OFF        0x03
+#define PKTCTRL1_PQT_MASK                      (0x7 << 5)
+#define PKTCTRL1_PQT_SHIFT                     5
+#define PKTCTRL1_APPEND_STATUS                 (1 << 2)
+#define PKTCTRL1_ADR_CHK_NONE                  (0 << 0)
+#define PKTCTRL1_ADR_CHK_NO_BROADCAST          (1 << 0)
+#define PKTCTRL1_ADR_CHK_00_BROADCAST          (2 << 0)
+#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST       (3 << 0)
+
+/* If APPEND_STATUS is used, two bytes will be added to the packet data */
+#define PKT_APPEND_STATUS_0_RSSI_MASK          (0xff)
+#define PKT_APPEND_STATUS_0_RSSI_SHIFT         0
+#define PKT_APPEND_STATUS_1_CRC_OK             (1 << 7)
+#define PKT_APPEND_STATUS_1_LQI_MASK           (0x7f)
+#define PKT_APPEND_STATUS_1_LQI_SHIFT          0
+
+__xdata __at (0xdf04) uint8_t RF_PKTCTRL0;
+#define RF_PKTCTRL0_OFF        0x04
+#define RF_PKTCTRL0_WHITE_DATA                 (1 << 6)
+#define RF_PKTCTRL0_PKT_FORMAT_NORMAL          (0 << 4)
+#define RF_PKTCTRL0_PKT_FORMAT_RANDOM          (2 << 4)
+#define RF_PKTCTRL0_CRC_EN                     (1 << 2)
+#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED                (0 << 0)
+#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE     (1 << 0)
+
+__xdata __at (0xdf05) uint8_t RF_ADDR;
+#define RF_ADDR_OFF    0x05
+
+__xdata __at (0xdf06) uint8_t RF_CHANNR;
+#define RF_CHANNR_OFF  0x06
+
+__xdata __at (0xdf07) uint8_t RF_FSCTRL1;
+#define RF_FSCTRL1_OFF 0x07
+
+#define RF_FSCTRL1_FREQ_IF_SHIFT       (0)
+
+__xdata __at (0xdf08) uint8_t RF_FSCTRL0;
+#define RF_FSCTRL0_OFF 0x08
+
+#define RF_FSCTRL0_FREQOFF_SHIFT       (0)
+
+__xdata __at (0xdf09) uint8_t RF_FREQ2;
+#define RF_FREQ2_OFF   0x09
+
+__xdata __at (0xdf0a) uint8_t RF_FREQ1;
+#define RF_FREQ1_OFF   0x0a
+
+__xdata __at (0xdf0b) uint8_t RF_FREQ0;
+#define RF_FREQ0_OFF   0x0b
+
+__xdata __at (0xdf0c) uint8_t RF_MDMCFG4;
+#define RF_MDMCFG4_OFF 0x0c
+
+#define RF_MDMCFG4_CHANBW_E_SHIFT      6
+#define RF_MDMCFG4_CHANBW_M_SHIFT      4
+#define RF_MDMCFG4_DRATE_E_SHIFT       0
+
+__xdata __at (0xdf0d) uint8_t RF_MDMCFG3;
+#define RF_MDMCFG3_OFF 0x0d
+
+#define RF_MDMCFG3_DRATE_M_SHIFT       0
+
+__xdata __at (0xdf0e) uint8_t RF_MDMCFG2;
+#define RF_MDMCFG2_OFF 0x0e
+
+#define RF_MDMCFG2_DEM_DCFILT_OFF      (1 << 7)
+#define RF_MDMCFG2_DEM_DCFILT_ON       (0 << 7)
+
+#define RF_MDMCFG2_MOD_FORMAT_MASK     (7 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_2_FSK    (0 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_GFSK     (1 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK  (3 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_MSK      (7 << 4)
+
+#define RF_MDMCFG2_MANCHESTER_EN       (1 << 3)
+
+#define RF_MDMCFG2_SYNC_MODE_MASK              (0x7 << 0)
+#define RF_MDMCFG2_SYNC_MODE_NONE              (0x0 << 0)
+#define RF_MDMCFG2_SYNC_MODE_15_16             (0x1 << 0)
+#define RF_MDMCFG2_SYNC_MODE_16_16             (0x2 << 0)
+#define RF_MDMCFG2_SYNC_MODE_30_32             (0x3 << 0)
+#define RF_MDMCFG2_SYNC_MODE_NONE_THRES                (0x4 << 0)
+#define RF_MDMCFG2_SYNC_MODE_15_16_THRES       (0x5 << 0)
+#define RF_MDMCFG2_SYNC_MODE_16_16_THRES       (0x6 << 0)
+#define RF_MDMCFG2_SYNC_MODE_30_32_THRES       (0x7 << 0)
+
+__xdata __at (0xdf0f) uint8_t RF_MDMCFG1;
+#define RF_MDMCFG1_OFF 0x0f
+
+#define RF_MDMCFG1_FEC_EN                      (1 << 7)
+#define RF_MDMCFG1_FEC_DIS                     (0 << 7)
+
+#define RF_MDMCFG1_NUM_PREAMBLE_MASK           (7 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_2              (0 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_3              (1 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_4              (2 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_6              (3 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_8              (4 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_12             (5 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_16             (6 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_24             (7 << 4)
+
+#define RF_MDMCFG1_CHANSPC_E_MASK              (3 << 0)
+#define RF_MDMCFG1_CHANSPC_E_SHIFT             (0)
+
+__xdata __at (0xdf10) uint8_t RF_MDMCFG0;
+#define RF_MDMCFG0_OFF 0x10
+
+#define RF_MDMCFG0_CHANSPC_M_SHIFT             (0)
+
+__xdata __at (0xdf11) uint8_t RF_DEVIATN;
+#define RF_DEVIATN_OFF 0x11
+
+#define RF_DEVIATN_DEVIATION_E_SHIFT           4
+#define RF_DEVIATN_DEVIATION_M_SHIFT           0
+
+__xdata __at (0xdf12) uint8_t RF_MCSM2;
+#define RF_MCSM2_OFF   0x12
+#define RF_MCSM2_RX_TIME_RSSI                  (1 << 4)
+#define RF_MCSM2_RX_TIME_QUAL                  (1 << 3)
+#define RF_MCSM2_RX_TIME_MASK                  (0x7)
+#define RF_MCSM2_RX_TIME_SHIFT                 0
+#define RF_MCSM2_RX_TIME_END_OF_PACKET         (7)
+
+__xdata __at (0xdf13) uint8_t RF_MCSM1;
+#define RF_MCSM1_OFF   0x13
+#define RF_MCSM1_CCA_MODE_ALWAYS                       (0 << 4)
+#define RF_MCSM1_CCA_MODE_RSSI_BELOW                   (1 << 4)
+#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING             (2 << 4)
+#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING  (3 << 4)
+#define RF_MCSM1_RXOFF_MODE_IDLE                       (0 << 2)
+#define RF_MCSM1_RXOFF_MODE_FSTXON                     (1 << 2)
+#define RF_MCSM1_RXOFF_MODE_TX                         (2 << 2)
+#define RF_MCSM1_RXOFF_MODE_RX                         (3 << 2)
+#define RF_MCSM1_TXOFF_MODE_IDLE                       (0 << 0)
+#define RF_MCSM1_TXOFF_MODE_FSTXON                     (1 << 0)
+#define RF_MCSM1_TXOFF_MODE_TX                         (2 << 0)
+#define RF_MCSM1_TXOFF_MODE_RX                         (3 << 0)
+
+__xdata __at (0xdf14) uint8_t RF_MCSM0;
+#define RF_MCSM0_OFF   0x14
+#define RF_MCSM0_FS_AUTOCAL_NEVER              (0 << 4)
+#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE          (1 << 4)
+#define RF_MCSM0_FS_AUTOCAL_TO_IDLE            (2 << 4)
+#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4    (3 << 4)
+#define RF_MCSM0_MAGIC_3                       (1 << 3)
+#define RF_MCSM0_MAGIC_2                       (1 << 2)
+#define RF_MCSM0_CLOSE_IN_RX_0DB               (0 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_6DB               (1 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_12DB              (2 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_18DB              (3 << 0)
+
+__xdata __at (0xdf15) uint8_t RF_FOCCFG;
+#define RF_FOCCFG_OFF  0x15
+#define RF_FOCCFG_FOC_BS_CS_GATE               (1 << 5)
+#define RF_FOCCFG_FOC_PRE_K_1K                 (0 << 3)
+#define RF_FOCCFG_FOC_PRE_K_2K                 (1 << 3)
+#define RF_FOCCFG_FOC_PRE_K_3K                 (2 << 3)
+#define RF_FOCCFG_FOC_PRE_K_4K                 (3 << 3)
+#define RF_FOCCFG_FOC_POST_K_PRE_K             (0 << 2)
+#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2      (1 << 2)
+#define RF_FOCCFG_FOC_LIMIT_0                  (0 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8          (1 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4          (2 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2          (3 << 0)
+
+__xdata __at (0xdf16) uint8_t RF_BSCFG;
+#define RF_BSCFG_OFF   0x16
+#define RF_BSCFG_BS_PRE_K_1K                   (0 << 6)
+#define RF_BSCFG_BS_PRE_K_2K                   (1 << 6)
+#define RF_BSCFG_BS_PRE_K_3K                   (2 << 6)
+#define RF_BSCFG_BS_PRE_K_4K                   (3 << 6)
+#define RF_BSCFG_BS_PRE_KP_1KP                 (0 << 4)
+#define RF_BSCFG_BS_PRE_KP_2KP                 (1 << 4)
+#define RF_BSCFG_BS_PRE_KP_3KP                 (2 << 4)
+#define RF_BSCFG_BS_PRE_KP_4KP                 (3 << 4)
+#define RF_BSCFG_BS_POST_KI_PRE_KI             (0 << 3)
+#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2      (1 << 3)
+#define RF_BSCFG_BS_POST_KP_PRE_KP             (0 << 2)
+#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2      (1 << 2)
+#define RF_BSCFG_BS_LIMIT_0                    (0 << 0)
+#define RF_BSCFG_BS_LIMIT_3_125                        (1 << 0)
+#define RF_BSCFG_BS_LIMIT_6_25                 (2 << 0)
+#define RF_BSCFG_BS_LIMIT_12_5                 (3 << 0)
+
+__xdata __at (0xdf17) uint8_t RF_AGCCTRL2;
+#define RF_AGCCTRL2_OFF        0x17
+
+__xdata __at (0xdf18) uint8_t RF_AGCCTRL1;
+#define RF_AGCCTRL1_OFF        0x18
+
+__xdata __at (0xdf19) uint8_t RF_AGCCTRL0;
+#define RF_AGCCTRL0_OFF        0x19
+
+__xdata __at (0xdf1a) uint8_t RF_FREND1;
+#define RF_FREND1_OFF  0x1a
+
+#define RF_FREND1_LNA_CURRENT_SHIFT            6
+#define RF_FREND1_LNA2MIX_CURRENT_SHIFT                4
+#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT   2
+#define RF_FREND1_MIX_CURRENT_SHIFT            0
+
+__xdata __at (0xdf1b) uint8_t RF_FREND0;
+#define RF_FREND0_OFF  0x1b
+
+#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK    (0x3 << 4)
+#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT   4
+#define RF_FREND0_PA_POWER_MASK                        (0x7)
+#define RF_FREND0_PA_POWER_SHIFT               0
+
+__xdata __at (0xdf1c) uint8_t RF_FSCAL3;
+#define RF_FSCAL3_OFF  0x1c
+
+__xdata __at (0xdf1d) uint8_t RF_FSCAL2;
+#define RF_FSCAL2_OFF  0x1d
+
+__xdata __at (0xdf1e) uint8_t RF_FSCAL1;
+#define RF_FSCAL1_OFF  0x1e
+
+__xdata __at (0xdf1f) uint8_t RF_FSCAL0;
+#define RF_FSCAL0_OFF  0x1f
+
+__xdata __at (0xdf23) uint8_t RF_TEST2;
+#define RF_TEST2_OFF   0x23
+
+#define RF_TEST2_NORMAL_MAGIC          0x88
+#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC        0x81
+
+__xdata __at (0xdf24) uint8_t RF_TEST1;
+#define RF_TEST1_OFF   0x24
+
+#define RF_TEST1_TX_MAGIC              0x31
+#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC        0x35
+
+__xdata __at (0xdf25) uint8_t RF_TEST0;
+#define RF_TEST0_OFF   0x25
+
+#define RF_TEST0_7_2_MASK              (0xfc)
+#define RF_TEST0_VCO_SEL_CAL_EN                (1 << 1)
+#define RF_TEST0_0_MASK                        (1)
+
+/* These are undocumented, and must be computed
+ * using the provided tool.
+ */
+__xdata __at (0xdf27) uint8_t RF_PA_TABLE7;
+#define RF_PA_TABLE7_OFF       0x27
+
+__xdata __at (0xdf28) uint8_t RF_PA_TABLE6;
+#define RF_PA_TABLE6_OFF       0x28
+
+__xdata __at (0xdf29) uint8_t RF_PA_TABLE5;
+#define RF_PA_TABLE5_OFF       0x29
+
+__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4;
+#define RF_PA_TABLE4_OFF       0x2a
+
+__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3;
+#define RF_PA_TABLE3_OFF       0x2b
+
+__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2;
+#define RF_PA_TABLE2_OFF       0x2c
+
+__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1;
+#define RF_PA_TABLE1_OFF       0x2d
+
+__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0;
+#define RF_PA_TABLE0_OFF       0x2e
+
+__xdata __at (0xdf36) uint8_t RF_PARTNUM;
+#define RF_PARTNUM_OFF 0x36
+
+__xdata __at (0xdf37) uint8_t RF_VERSION;
+#define RF_VERSION_OFF 0x37
+
+__xdata __at (0xdf38) uint8_t RF_FREQEST;
+#define RF_FREQEST_OFF 0x38
+
+__xdata __at (0xdf39) uint8_t RF_LQI;
+#define RF_LQI_OFF     0x39
+
+#define RF_LQI_CRC_OK                  (1 << 7)
+#define RF_LQI_LQI_EST_MASK            (0x7f)
+
+__xdata __at (0xdf3a) uint8_t RF_RSSI;
+#define RF_RSSI_OFF    0x3a
+
+__xdata __at (0xdf3b) uint8_t RF_MARCSTATE;
+#define RF_MARCSTATE_OFF       0x3b
+
+#define RF_MARCSTATE_MASK              0x1f
+#define RF_MARCSTATE_SLEEP             0x00
+#define RF_MARCSTATE_IDLE              0x01
+#define RF_MARCSTATE_VCOON_MC          0x03
+#define RF_MARCSTATE_REGON_MC          0x04
+#define RF_MARCSTATE_MANCAL            0x05
+#define RF_MARCSTATE_VCOON             0x06
+#define RF_MARCSTATE_REGON             0x07
+#define RF_MARCSTATE_STARTCAL          0x08
+#define RF_MARCSTATE_BWBOOST           0x09
+#define RF_MARCSTATE_FS_LOCK           0x0a
+#define RF_MARCSTATE_IFADCON           0x0b
+#define RF_MARCSTATE_ENDCAL            0x0c
+#define RF_MARCSTATE_RX                        0x0d
+#define RF_MARCSTATE_RX_END            0x0e
+#define RF_MARCSTATE_RX_RST            0x0f
+#define RF_MARCSTATE_TXRX_SWITCH       0x10
+#define RF_MARCSTATE_RX_OVERFLOW       0x11
+#define RF_MARCSTATE_FSTXON            0x12
+#define RF_MARCSTATE_TX                        0x13
+#define RF_MARCSTATE_TX_END            0x14
+#define RF_MARCSTATE_RXTX_SWITCH       0x15
+#define RF_MARCSTATE_TX_UNDERFLOW      0x16
+
+
+__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS;
+#define RF_PKTSTATUS_OFF       0x3c
+
+#define RF_PKTSTATUS_CRC_OK            (1 << 7)
+#define RF_PKTSTATUS_CS                        (1 << 6)
+#define RF_PKTSTATUS_PQT_REACHED       (1 << 5)
+#define RF_PKTSTATUS_CCA               (1 << 4)
+#define RF_PKTSTATUS_SFD               (1 << 3)
+
+__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC;
+#define RF_VCO_VC_DAC_OFF      0x3d
+
+#endif
diff --git a/src/check-stack b/src/check-stack
deleted file mode 100755 (executable)
index 1e8044e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-HEADER=$1
-MEM=$2
-
-HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER`
-MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM`
-
-if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then
-        echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }'
-       exit 1
-else
-       exit 0
-fi
diff --git a/src/core/altitude.h b/src/core/altitude.h
new file mode 100644 (file)
index 0000000..a278bbc
--- /dev/null
@@ -0,0 +1,132 @@
+/*max error 3.197865153490684 at   0.782%. Average error 0.260150920474668*/
+#define NALT 129
+#define ALT_FRAC_BITS 8
+    15835, /*  10.56 kPa   0.000% */
+    15332, /*  11.42 kPa   0.781% */
+    14868, /*  12.29 kPa   1.563% */
+    14435, /*  13.16 kPa   2.344% */
+    14030, /*  14.02 kPa   3.125% */
+    13649, /*  14.90 kPa   3.906% */
+    13290, /*  15.76 kPa   4.688% */
+    12950, /*  16.63 kPa   5.469% */
+    12627, /*  17.50 kPa   6.250% */
+    12320, /*  18.37 kPa   7.031% */
+    12027, /*  19.24 kPa   7.813% */
+    11747, /*  20.10 kPa   8.594% */
+    11479, /*  20.97 kPa   9.375% */
+    11222, /*  21.84 kPa  10.156% */
+    10975, /*  22.71 kPa  10.938% */
+    10736, /*  23.58 kPa  11.719% */
+    10504, /*  24.44 kPa  12.500% */
+    10278, /*  25.31 kPa  13.281% */
+    10059, /*  26.18 kPa  14.063% */
+     9846, /*  27.05 kPa  14.844% */
+     9638, /*  27.91 kPa  15.625% */
+     9435, /*  28.78 kPa  16.406% */
+     9237, /*  29.65 kPa  17.188% */
+     9044, /*  30.52 kPa  17.969% */
+     8855, /*  31.39 kPa  18.750% */
+     8670, /*  32.26 kPa  19.531% */
+     8490, /*  33.13 kPa  20.313% */
+     8313, /*  33.99 kPa  21.094% */
+     8140, /*  34.86 kPa  21.875% */
+     7970, /*  35.73 kPa  22.656% */
+     7803, /*  36.60 kPa  23.438% */
+     7640, /*  37.47 kPa  24.219% */
+     7480, /*  38.33 kPa  25.000% */
+     7322, /*  39.20 kPa  25.781% */
+     7168, /*  40.07 kPa  26.563% */
+     7016, /*  40.94 kPa  27.344% */
+     6867, /*  41.80 kPa  28.125% */
+     6720, /*  42.67 kPa  28.906% */
+     6575, /*  43.54 kPa  29.688% */
+     6433, /*  44.41 kPa  30.469% */
+     6294, /*  45.28 kPa  31.250% */
+     6156, /*  46.15 kPa  32.031% */
+     6020, /*  47.01 kPa  32.813% */
+     5887, /*  47.88 kPa  33.594% */
+     5755, /*  48.75 kPa  34.375% */
+     5625, /*  49.62 kPa  35.156% */
+     5497, /*  50.49 kPa  35.938% */
+     5371, /*  51.35 kPa  36.719% */
+     5247, /*  52.22 kPa  37.500% */
+     5124, /*  53.09 kPa  38.281% */
+     5003, /*  53.96 kPa  39.063% */
+     4883, /*  54.83 kPa  39.844% */
+     4765, /*  55.69 kPa  40.625% */
+     4648, /*  56.56 kPa  41.406% */
+     4533, /*  57.43 kPa  42.188% */
+     4419, /*  58.30 kPa  42.969% */
+     4307, /*  59.17 kPa  43.750% */
+     4196, /*  60.03 kPa  44.531% */
+     4086, /*  60.90 kPa  45.313% */
+     3977, /*  61.77 kPa  46.094% */
+     3870, /*  62.63 kPa  46.875% */
+     3764, /*  63.51 kPa  47.656% */
+     3659, /*  64.38 kPa  48.438% */
+     3555, /*  65.24 kPa  49.219% */
+     3453, /*  66.11 kPa  50.000% */
+     3351, /*  66.98 kPa  50.781% */
+     3250, /*  67.85 kPa  51.563% */
+     3151, /*  68.72 kPa  52.344% */
+     3052, /*  69.58 kPa  53.125% */
+     2955, /*  70.45 kPa  53.906% */
+     2858, /*  71.32 kPa  54.688% */
+     2763, /*  72.19 kPa  55.469% */
+     2668, /*  73.06 kPa  56.250% */
+     2574, /*  73.92 kPa  57.031% */
+     2482, /*  74.79 kPa  57.813% */
+     2390, /*  75.66 kPa  58.594% */
+     2298, /*  76.52 kPa  59.375% */
+     2208, /*  77.40 kPa  60.156% */
+     2119, /*  78.26 kPa  60.938% */
+     2030, /*  79.13 kPa  61.719% */
+     1942, /*  80.00 kPa  62.500% */
+     1855, /*  80.87 kPa  63.281% */
+     1769, /*  81.74 kPa  64.063% */
+     1683, /*  82.60 kPa  64.844% */
+     1598, /*  83.47 kPa  65.625% */
+     1514, /*  84.34 kPa  66.406% */
+     1430, /*  85.21 kPa  67.188% */
+     1347, /*  86.08 kPa  67.969% */
+     1265, /*  86.94 kPa  68.750% */
+     1184, /*  87.81 kPa  69.531% */
+     1103, /*  88.68 kPa  70.313% */
+     1023, /*  89.55 kPa  71.094% */
+      943, /*  90.41 kPa  71.875% */
+      864, /*  91.28 kPa  72.656% */
+      786, /*  92.15 kPa  73.438% */
+      708, /*  93.02 kPa  74.219% */
+      631, /*  93.89 kPa  75.000% */
+      554, /*  94.76 kPa  75.781% */
+      478, /*  95.63 kPa  76.563% */
+      403, /*  96.49 kPa  77.344% */
+      328, /*  97.36 kPa  78.125% */
+      254, /*  98.23 kPa  78.906% */
+      180, /*  99.10 kPa  79.688% */
+      106, /*  99.97 kPa  80.469% */
+       34, /* 100.83 kPa  81.250% */
+      -39, /* 101.70 kPa  82.031% */
+     -111, /* 102.57 kPa  82.813% */
+     -182, /* 103.44 kPa  83.594% */
+     -253, /* 104.30 kPa  84.375% */
+     -323, /* 105.17 kPa  85.156% */
+     -393, /* 106.04 kPa  85.938% */
+     -462, /* 106.91 kPa  86.719% */
+     -531, /* 107.78 kPa  87.500% */
+     -600, /* 108.65 kPa  88.281% */
+     -668, /* 109.51 kPa  89.063% */
+     -736, /* 110.38 kPa  89.844% */
+     -803, /* 111.25 kPa  90.625% */
+     -870, /* 112.12 kPa  91.406% */
+     -936, /* 112.99 kPa  92.188% */
+    -1002, /* 113.85 kPa  92.969% */
+    -1068, /* 114.72 kPa  93.750% */
+    -1133, /* 115.59 kPa  94.531% */
+    -1198, /* 116.46 kPa  95.313% */
+    -1262, /* 117.33 kPa  96.094% */
+    -1326, /* 118.19 kPa  96.875% */
+    -1389, /* 119.06 kPa  97.656% */
+    -1453, /* 119.93 kPa  98.438% */
+    -1516, /* 120.80 kPa  99.219% */
+    -1578, /* 121.67 kPa 100.000% */
diff --git a/src/core/ao.h b/src/core/ao.h
new file mode 100644 (file)
index 0000000..8ac9ac3
--- /dev/null
@@ -0,0 +1,1610 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_H_
+#define _AO_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include "cc1111.h"
+#include "ao_pins.h"
+
+#define TRUE 1
+#define FALSE 0
+
+/* Convert a __data pointer into an __xdata pointer */
+#define DATA_TO_XDATA(a)       ((void __xdata *) ((uint8_t) (a) | 0xff00))
+
+/* Stack runs from above the allocated __data space to 0xfe, which avoids
+ * writing to 0xff as that triggers the stack overflow indicator
+ */
+#define AO_STACK_START 0x90
+#define AO_STACK_END   0xfe
+#define AO_STACK_SIZE  (AO_STACK_END - AO_STACK_START + 1)
+
+/* An AltOS task */
+struct ao_task {
+       __xdata void *wchan;            /* current wait channel (NULL if running) */
+       uint16_t alarm;                 /* abort ao_sleep time */
+       uint8_t stack_count;            /* amount of saved stack */
+       uint8_t task_id;                /* unique id */
+       __code char *name;              /* task name */
+       uint8_t stack[AO_STACK_SIZE];   /* saved stack */
+};
+
+extern __xdata struct ao_task *__data ao_cur_task;
+
+#define AO_NUM_TASKS           16      /* maximum number of tasks */
+#define AO_NO_TASK             0       /* no task id */
+
+/*
+ ao_task.c
+ */
+
+/* Suspend the current task until wchan is awoken.
+ * returns:
+ *  0 on normal wake
+ *  1 on alarm
+ */
+uint8_t
+ao_sleep(__xdata void *wchan);
+
+/* Wake all tasks sleeping on wchan */
+void
+ao_wakeup(__xdata void *wchan);
+
+/* set an alarm to go off in 'delay' ticks */
+void
+ao_alarm(uint16_t delay);
+
+/* Yield the processor to another task */
+void
+ao_yield(void) __naked;
+
+/* Add a task to the run queue */
+void
+ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant;
+
+/* Terminate the current task */
+void
+ao_exit(void);
+
+/* Dump task info to console */
+void
+ao_task_info(void);
+
+/* Start the scheduler. This will not return */
+void
+ao_start_scheduler(void);
+
+/*
+ * ao_panic.c
+ */
+
+#define AO_PANIC_NO_TASK       1       /* AO_NUM_TASKS is not large enough */
+#define AO_PANIC_DMA           2       /* Attempt to start DMA while active */
+#define AO_PANIC_MUTEX         3       /* Mis-using mutex API */
+#define AO_PANIC_EE            4       /* Mis-using eeprom API */
+#define AO_PANIC_LOG           5       /* Failing to read/write log data */
+#define AO_PANIC_CMD           6       /* Too many command sets registered */
+#define AO_PANIC_STDIO         7       /* Too many stdio handlers registered */
+#define AO_PANIC_REBOOT                8       /* Reboot failed */
+#define AO_PANIC_FLASH         9       /* Invalid flash part (or wrong blocksize) */
+#define AO_PANIC_USB           10      /* Trying to send USB packet while busy */
+#define AO_PANIC_BT            11      /* Communications with bluetooth device failed */
+
+/* Stop the operating system, beeping and blinking the reason */
+void
+ao_panic(uint8_t reason);
+
+/*
+ * ao_timer.c
+ */
+
+/* Our timer runs at 100Hz */
+#define AO_HERTZ               100
+#define AO_MS_TO_TICKS(ms)     ((ms) / (1000 / AO_HERTZ))
+#define AO_SEC_TO_TICKS(s)     ((s) * AO_HERTZ)
+
+/* Returns the current time in ticks */
+uint16_t
+ao_time(void);
+
+/* Suspend the current task until ticks time has passed */
+void
+ao_delay(uint16_t ticks);
+
+/* Set the ADC interval */
+void
+ao_timer_set_adc_interval(uint8_t interval) __critical;
+
+/* Timer interrupt */
+void
+ao_timer_isr(void) __interrupt 9;
+
+/* Initialize the timer */
+void
+ao_timer_init(void);
+
+/* Initialize the hardware clock. Must be called first */
+void
+ao_clock_init(void);
+
+/*
+ * One set of samples read from the A/D converter or telemetry
+ */
+struct ao_adc {
+       uint16_t        tick;           /* tick when the sample was read */
+       int16_t         accel;          /* accelerometer */
+       int16_t         pres;           /* pressure sensor */
+       int16_t         temp;           /* temperature sensor */
+       int16_t         v_batt;         /* battery voltage */
+       int16_t         sense_d;        /* drogue continuity sense */
+       int16_t         sense_m;        /* main continuity sense */
+};
+
+#ifndef HAS_ADC
+#error Please define HAS_ADC
+#endif
+
+#if HAS_ADC
+
+#if HAS_ACCEL
+#ifndef HAS_ACCEL_REF
+#error Please define HAS_ACCEL_REF
+#endif
+#else
+#define HAS_ACCEL_REF 0
+#endif
+
+/*
+ * ao_adc.c
+ */
+
+#define AO_ADC_RING    32
+#define ao_adc_ring_next(n)    (((n) + 1) & (AO_ADC_RING - 1))
+#define ao_adc_ring_prev(n)    (((n) - 1) & (AO_ADC_RING - 1))
+
+
+/*
+ * A/D data is stored in a ring, with the next sample to be written
+ * at ao_adc_head
+ */
+extern volatile __xdata struct ao_adc  ao_adc_ring[AO_ADC_RING];
+extern volatile __data uint8_t         ao_adc_head;
+#if HAS_ACCEL_REF
+extern volatile __xdata uint16_t       ao_accel_ref[AO_ADC_RING];
+#endif
+
+/* Trigger a conversion sequence (called from the timer interrupt) */
+void
+ao_adc_poll(void);
+
+/* Suspend the current task until another A/D sample is converted */
+void
+ao_adc_sleep(void);
+
+/* Get a copy of the last complete A/D sample set */
+void
+ao_adc_get(__xdata struct ao_adc *packet);
+
+/* The A/D interrupt handler */
+
+void
+ao_adc_isr(void) __interrupt 1;
+
+/* Initialize the A/D converter */
+void
+ao_adc_init(void);
+
+#endif /* HAS_ADC */
+
+/*
+ * ao_beep.c
+ */
+
+/*
+ * Various pre-defined beep frequencies
+ *
+ * frequency = 1/2 (24e6/32) / beep
+ */
+
+#define AO_BEEP_LOW    150     /* 2500Hz */
+#define AO_BEEP_MID    94      /* 3989Hz */
+#define AO_BEEP_HIGH   75      /* 5000Hz */
+#define AO_BEEP_OFF    0       /* off */
+
+#define AO_BEEP_g      240     /* 1562.5Hz */
+#define AO_BEEP_gs     227     /* 1652Hz (1655Hz) */
+#define AO_BEEP_aa     214     /* 1752Hz (1754Hz) */
+#define AO_BEEP_bbf    202     /* 1856Hz (1858Hz) */
+#define AO_BEEP_bb     190     /* 1974Hz (1969Hz) */
+#define AO_BEEP_cc     180     /* 2083Hz (2086Hz) */
+#define AO_BEEP_ccs    170     /* 2205Hz (2210Hz) */
+#define AO_BEEP_dd     160     /* 2344Hz (2341Hz) */
+#define AO_BEEP_eef    151     /* 2483Hz (2480Hz) */
+#define AO_BEEP_ee     143     /* 2622Hz (2628Hz) */
+#define AO_BEEP_ff     135     /* 2778Hz (2784Hz) */
+#define AO_BEEP_ffs    127     /* 2953Hz (2950Hz) */
+#define AO_BEEP_gg     120     /* 3125Hz */
+#define AO_BEEP_ggs    113     /* 3319Hz (3311Hz) */
+#define AO_BEEP_aaa    107     /* 3504Hz (3508Hz) */
+#define AO_BEEP_bbbf   101     /* 3713Hz (3716Hz) */
+#define AO_BEEP_bbb    95      /* 3947Hz (3937Hz) */
+#define AO_BEEP_ccc    90      /* 4167Hz (4171Hz) */
+#define AO_BEEP_cccs   85      /* 4412Hz (4419Hz) */
+#define AO_BEEP_ddd    80      /* 4688Hz (4682Hz) */
+#define AO_BEEP_eeef   76      /* 4934Hz (4961Hz) */
+#define AO_BEEP_eee    71      /* 5282Hz (5256Hz) */
+#define AO_BEEP_fff    67      /* 5597Hz (5568Hz) */
+#define AO_BEEP_fffs   64      /* 5859Hz (5899Hz) */
+#define AO_BEEP_ggg    60      /* 6250Hz */
+
+/* Set the beeper to the specified tone */
+void
+ao_beep(uint8_t beep);
+
+/* Turn on the beeper for the specified time */
+void
+ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant;
+
+/* Initialize the beeper */
+void
+ao_beep_init(void);
+
+/*
+ * ao_led.c
+ */
+
+#define AO_LED_NONE    0
+
+/* Turn on the specified LEDs */
+void
+ao_led_on(uint8_t colors);
+
+/* Turn off the specified LEDs */
+void
+ao_led_off(uint8_t colors);
+
+/* Set all of the LEDs to the specified state */
+void
+ao_led_set(uint8_t colors);
+
+/* Toggle the specified LEDs */
+void
+ao_led_toggle(uint8_t colors);
+
+/* Turn on the specified LEDs for the indicated interval */
+void
+ao_led_for(uint8_t colors, uint16_t ticks) __reentrant;
+
+/* Initialize the LEDs */
+void
+ao_led_init(uint8_t enable);
+
+/*
+ * ao_romconfig.c
+ */
+
+#define AO_ROMCONFIG_VERSION   2
+
+extern __code __at (0x00a0) uint16_t ao_romconfig_version;
+extern __code __at (0x00a2) uint16_t ao_romconfig_check;
+extern __code __at (0x00a4) uint16_t ao_serial_number;
+extern __code __at (0x00a6) uint32_t ao_radio_cal;
+
+#ifndef HAS_USB
+#error Please define HAS_USB
+#endif
+
+#if HAS_USB
+extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
+#endif
+
+/*
+ * ao_usb.c
+ */
+
+/* Put one character to the USB output queue */
+void
+ao_usb_putchar(char c);
+
+/* Get one character from the USB input queue */
+char
+ao_usb_getchar(void);
+
+/* Poll for a charcter on the USB input queue.
+ * returns AO_READ_AGAIN if none are available
+ */
+char
+ao_usb_pollchar(void);
+
+/* Flush the USB output queue */
+void
+ao_usb_flush(void);
+
+#if HAS_USB
+/* USB interrupt handler */
+void
+ao_usb_isr(void) __interrupt 6;
+#endif
+
+/* Enable the USB controller */
+void
+ao_usb_enable(void);
+
+/* Disable the USB controller */
+void
+ao_usb_disable(void);
+
+/* Initialize the USB system */
+void
+ao_usb_init(void);
+
+/*
+ * ao_cmd.c
+ */
+
+enum ao_cmd_status {
+       ao_cmd_success = 0,
+       ao_cmd_lex_error = 1,
+       ao_cmd_syntax_error = 2,
+};
+
+extern __pdata uint16_t ao_cmd_lex_i;
+extern __pdata uint32_t ao_cmd_lex_u32;
+extern __pdata char    ao_cmd_lex_c;
+extern __pdata enum ao_cmd_status ao_cmd_status;
+
+void
+ao_cmd_lex(void);
+
+void
+ao_cmd_put8(uint8_t v);
+
+void
+ao_cmd_put16(uint16_t v);
+
+void
+ao_cmd_white(void);
+
+void
+ao_cmd_hex(void);
+
+void
+ao_cmd_decimal(void);
+
+uint8_t
+ao_match_word(__code char *word);
+
+struct ao_cmds {
+       void            (*func)(void);
+       __code char     *help;
+};
+
+void
+ao_cmd_register(__code struct ao_cmds *cmds);
+
+void
+ao_cmd_init(void);
+
+#if HAS_CMD_FILTER
+/*
+ * Provided by an external module to filter raw command lines
+ */
+uint8_t
+ao_cmd_filter(void);
+#endif
+
+/*
+ * ao_dma.c
+ */
+
+/* Allocate a DMA channel. the 'done' parameter will be set when the
+ * dma is finished and will be used to wakeup any waiters
+ */
+
+uint8_t
+ao_dma_alloc(__xdata uint8_t * done);
+
+/* Setup a DMA channel */
+void
+ao_dma_set_transfer(uint8_t id,
+                   void __xdata *srcaddr,
+                   void __xdata *dstaddr,
+                   uint16_t count,
+                   uint8_t cfg0,
+                   uint8_t cfg1);
+
+/* Start a DMA channel */
+void
+ao_dma_start(uint8_t id);
+
+/* Manually trigger a DMA channel */
+void
+ao_dma_trigger(uint8_t id);
+
+/* Abort a running DMA transfer */
+void
+ao_dma_abort(uint8_t id);
+
+/* DMA interrupt routine */
+void
+ao_dma_isr(void) __interrupt 8;
+
+/*
+ * ao_mutex.c
+ */
+
+void
+ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant;
+
+void
+ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant;
+
+/*
+ * Storage interface, provided by one of the eeprom or flash
+ * drivers
+ */
+
+/* Total bytes of available storage */
+extern __pdata uint32_t        ao_storage_total;
+
+/* Block size - device is erased in these units. At least 256 bytes */
+extern __pdata uint32_t        ao_storage_block;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+extern __pdata uint32_t        ao_storage_config;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
+extern __pdata uint16_t ao_storage_unit;
+
+#define AO_STORAGE_ERASE_LOG   (ao_storage_config + AO_CONFIG_MAX_SIZE)
+
+/* Initialize above values. Can only be called once the OS is running */
+void
+ao_storage_setup(void) __reentrant;
+
+/* Write data. Returns 0 on failure, 1 on success */
+uint8_t
+ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
+
+/* Read data. Returns 0 on failure, 1 on success */
+uint8_t
+ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
+
+/* Erase a block of storage. This always clears ao_storage_block bytes */
+uint8_t
+ao_storage_erase(uint32_t pos) __reentrant;
+
+/* Flush any pending writes to stable storage */
+void
+ao_storage_flush(void) __reentrant;
+
+/* Initialize the storage code */
+void
+ao_storage_init(void);
+
+/*
+ * Low-level functions wrapped by ao_storage.c
+ */
+
+/* Read data within a storage unit */
+uint8_t
+ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
+
+/* Write data within a storage unit */
+uint8_t
+ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant;
+
+/* Initialize low-level device bits */
+void
+ao_storage_device_init(void);
+
+/* Print out information about flash chips */
+void
+ao_storage_device_info(void) __reentrant;
+
+/*
+ * ao_log.c
+ */
+
+/* We record flight numbers in the first record of
+ * the log. Tasks may wait for this to be initialized
+ * by sleeping on this variable.
+ */
+extern __xdata uint16_t ao_flight_number;
+
+extern __pdata uint32_t ao_log_current_pos;
+extern __pdata uint32_t ao_log_end_pos;
+extern __pdata uint32_t ao_log_start_pos;
+extern __xdata uint8_t ao_log_running;
+extern __pdata enum flight_state ao_log_state;
+
+/* required functions from the underlying log system */
+
+#define AO_LOG_FORMAT_UNKNOWN          0       /* unknown; altosui will have to guess */
+#define AO_LOG_FORMAT_FULL             1       /* 8 byte typed log records */
+#define AO_LOG_FORMAT_TINY             2       /* two byte state/baro records */
+#define AO_LOG_FORMAT_TELEMETRY                3       /* 32 byte ao_telemetry records */
+#define AO_LOG_FORMAT_TELESCIENCE      4       /* 32 byte typed telescience records */
+#define AO_LOG_FORMAT_NONE             127     /* No log at all */
+
+extern __code uint8_t ao_log_format;
+
+/* Return the flight number from the given log slot, 0 if none */
+uint16_t
+ao_log_flight(uint8_t slot);
+
+/* Flush the log */
+void
+ao_log_flush(void);
+
+/* Logging thread main routine */
+void
+ao_log(void);
+
+/* functions provided in ao_log.c */
+
+/* Figure out the current flight number */
+void
+ao_log_scan(void) __reentrant;
+
+/* Return the position of the start of the given log slot */
+uint32_t
+ao_log_pos(uint8_t slot);
+
+/* Start logging to eeprom */
+void
+ao_log_start(void);
+
+/* Stop logging */
+void
+ao_log_stop(void);
+
+/* Initialize the logging system */
+void
+ao_log_init(void);
+
+/* Write out the current flight number to the erase log */
+void
+ao_log_write_erase(uint8_t pos);
+
+/* Returns true if there are any logs stored in eeprom */
+uint8_t
+ao_log_present(void);
+
+/* Returns true if there is no more storage space available */
+uint8_t
+ao_log_full(void);
+
+/*
+ * ao_log_big.c
+ */
+
+/*
+ * The data log is recorded in the eeprom as a sequence
+ * of data packets.
+ *
+ * Each packet starts with a 4-byte header that has the
+ * packet type, the packet checksum and the tick count. Then
+ * they all contain 2 16 bit values which hold packet-specific
+ * data.
+ *
+ * For each flight, the first packet
+ * is FLIGHT packet, indicating the serial number of the
+ * device and a unique number marking the number of flights
+ * recorded by this device.
+ *
+ * During flight, data from the accelerometer and barometer
+ * are recorded in SENSOR packets, using the raw 16-bit values
+ * read from the A/D converter.
+ *
+ * Also during flight, but at a lower rate, the deployment
+ * sensors are recorded in DEPLOY packets. The goal here is to
+ * detect failure in the deployment circuits.
+ *
+ * STATE packets hold state transitions as the flight computer
+ * transitions through different stages of the flight.
+ */
+#define AO_LOG_FLIGHT          'F'
+#define AO_LOG_SENSOR          'A'
+#define AO_LOG_TEMP_VOLT       'T'
+#define AO_LOG_DEPLOY          'D'
+#define AO_LOG_STATE           'S'
+#define AO_LOG_GPS_TIME                'G'
+#define AO_LOG_GPS_LAT         'N'
+#define AO_LOG_GPS_LON         'W'
+#define AO_LOG_GPS_ALT         'H'
+#define AO_LOG_GPS_SAT         'V'
+#define AO_LOG_GPS_DATE                'Y'
+
+#define AO_LOG_POS_NONE                (~0UL)
+
+struct ao_log_record {
+       char                    type;
+       uint8_t                 csum;
+       uint16_t                tick;
+       union {
+               struct {
+                       int16_t         ground_accel;
+                       uint16_t        flight;
+               } flight;
+               struct {
+                       int16_t         accel;
+                       int16_t         pres;
+               } sensor;
+               struct {
+                       int16_t         temp;
+                       int16_t         v_batt;
+               } temp_volt;
+               struct {
+                       int16_t         drogue;
+                       int16_t         main;
+               } deploy;
+               struct {
+                       uint16_t        state;
+                       uint16_t        reason;
+               } state;
+               struct {
+                       uint8_t         hour;
+                       uint8_t         minute;
+                       uint8_t         second;
+                       uint8_t         flags;
+               } gps_time;
+               int32_t         gps_latitude;
+               int32_t         gps_longitude;
+               struct {
+                       int16_t         altitude;
+                       uint16_t        unused;
+               } gps_altitude;
+               struct {
+                       uint16_t        svid;
+                       uint8_t         unused;
+                       uint8_t         c_n;
+               } gps_sat;
+               struct {
+                       uint8_t         year;
+                       uint8_t         month;
+                       uint8_t         day;
+                       uint8_t         extra;
+               } gps_date;
+               struct {
+                       uint16_t        d0;
+                       uint16_t        d1;
+               } anon;
+       } u;
+};
+
+/* Write a record to the eeprom log */
+uint8_t
+ao_log_data(__xdata struct ao_log_record *log) __reentrant;
+
+/*
+ * ao_flight.c
+ */
+
+enum ao_flight_state {
+       ao_flight_startup = 0,
+       ao_flight_idle = 1,
+       ao_flight_pad = 2,
+       ao_flight_boost = 3,
+       ao_flight_fast = 4,
+       ao_flight_coast = 5,
+       ao_flight_drogue = 6,
+       ao_flight_main = 7,
+       ao_flight_landed = 8,
+       ao_flight_invalid = 9
+};
+
+extern __pdata enum ao_flight_state    ao_flight_state;
+
+extern __pdata uint16_t                        ao_launch_time;
+extern __pdata uint8_t                 ao_flight_force_idle;
+
+/* Flight thread */
+void
+ao_flight(void);
+
+/* Initialize flight thread */
+void
+ao_flight_init(void);
+
+/*
+ * ao_flight_nano.c
+ */
+
+void
+ao_flight_nano_init(void);
+
+/*
+ * ao_sample.c
+ */
+
+/*
+ * Barometer calibration
+ *
+ * We directly sample the barometer. The specs say:
+ *
+ * Pressure range: 15-115 kPa
+ * Voltage at 115kPa: 2.82
+ * Output scale: 27mV/kPa
+ *
+ * If we want to detect launch with the barometer, we need
+ * a large enough bump to not be fooled by noise. At typical
+ * launch elevations (0-2000m), a 200Pa pressure change cooresponds
+ * to about a 20m elevation change. This is 5.4mV, or about 3LSB.
+ * As all of our calculations are done in 16 bits, we'll actually see a change
+ * of 16 times this though
+ *
+ * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa
+ */
+
+/* Accelerometer calibration
+ *
+ * We're sampling the accelerometer through a resistor divider which
+ * consists of 5k and 10k resistors. This multiplies the values by 2/3.
+ * That goes into the cc1111 A/D converter, which is running at 11 bits
+ * of precision with the bits in the MSB of the 16 bit value. Only positive
+ * values are used, so values should range from 0-32752 for 0-3.3V. The
+ * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what
+ * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV,
+ * for a final computation of:
+ *
+ * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g
+ *
+ * Zero g was measured at 16000 (we would expect 16384).
+ * Note that this value is only require to tell if the
+ * rocket is standing upright. Once that is determined,
+ * the value of the accelerometer is averaged for 100 samples
+ * to find the resting accelerometer value, which is used
+ * for all further flight computations
+ */
+
+#define GRAVITY 9.80665
+
+/*
+ * Above this height, the baro sensor doesn't work
+ */
+#define AO_MAX_BARO_HEIGHT     12000
+
+/*
+ * Above this speed, baro measurements are unreliable
+ */
+#define AO_MAX_BARO_SPEED      200
+
+#define ACCEL_NOSE_UP  (ao_accel_2g >> 2)
+
+/*
+ * Speed and acceleration are scaled by 16 to provide a bit more
+ * resolution while still having reasonable range. Note that this
+ * limits speed to 2047m/s (around mach 6) and acceleration to
+ * 2047m/s² (over 200g)
+ */
+
+#define AO_M_TO_HEIGHT(m)      ((int16_t) (m))
+#define AO_MS_TO_SPEED(ms)     ((int16_t) ((ms) * 16))
+#define AO_MSS_TO_ACCEL(mss)   ((int16_t) ((mss) * 16))
+
+extern __pdata uint16_t        ao_sample_tick;         /* time of last data */
+extern __pdata int16_t ao_sample_pres;         /* most recent pressure sensor reading */
+extern __pdata int16_t ao_sample_alt;          /* MSL of ao_sample_pres */
+extern __pdata int16_t ao_sample_height;       /* AGL of ao_sample_pres */
+extern __data uint8_t  ao_sample_adc;          /* Ring position of last processed sample */
+
+#if HAS_ACCEL
+extern __pdata int16_t ao_sample_accel;        /* most recent accel sensor reading */
+#endif
+
+extern __pdata int16_t ao_ground_pres;         /* startup pressure */
+extern __pdata int16_t ao_ground_height;       /* MSL of ao_ground_pres */
+
+#if HAS_ACCEL
+extern __pdata int16_t ao_ground_accel;        /* startup acceleration */
+extern __pdata int16_t         ao_accel_2g;            /* factory accel calibration */
+extern __pdata int32_t ao_accel_scale;         /* sensor to m/s² conversion */
+#endif
+
+void ao_sample_init(void);
+
+/* returns FALSE in preflight mode, TRUE in flight mode */
+uint8_t ao_sample(void);
+
+/*
+ * ao_kalman.c
+ */
+
+#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
+#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define from_fix(x)    ((x) >> 16)
+
+extern __pdata int16_t                 ao_height;      /* meters */
+extern __pdata int16_t                 ao_speed;       /* m/s * 16 */
+extern __pdata int16_t                 ao_accel;       /* m/s² * 16 */
+extern __pdata int16_t                 ao_max_height;  /* max of ao_height */
+extern __pdata int16_t                 ao_avg_height;  /* running average of height */
+
+extern __pdata int16_t                 ao_error_h;
+extern __pdata int16_t                 ao_error_h_sq_avg;
+
+#if HAS_ACCEL
+extern __pdata int16_t                 ao_error_a;
+#endif
+
+void ao_kalman(void);
+
+/*
+ * ao_report.c
+ */
+
+void
+ao_report_init(void);
+
+/*
+ * ao_convert.c
+ *
+ * Given raw data, convert to SI units
+ */
+
+/* pressure from the sensor to altitude in meters */
+int16_t
+ao_pres_to_altitude(int16_t pres) __reentrant;
+
+int16_t
+ao_altitude_to_pres(int16_t alt) __reentrant;
+
+int16_t
+ao_temp_to_dC(int16_t temp) __reentrant;
+
+/*
+ * ao_dbg.c
+ *
+ * debug another telemetrum board
+ */
+
+/* Send a byte to the dbg target */
+void
+ao_dbg_send_byte(uint8_t byte);
+
+/* Receive a byte from the dbg target */
+uint8_t
+ao_dbg_recv_byte(void);
+
+/* Start a bulk transfer to/from dbg target memory */
+void
+ao_dbg_start_transfer(uint16_t addr);
+
+/* End a bulk transfer to/from dbg target memory */
+void
+ao_dbg_end_transfer(void);
+
+/* Write a byte to dbg target memory */
+void
+ao_dbg_write_byte(uint8_t byte);
+
+/* Read a byte from dbg target memory */
+uint8_t
+ao_dbg_read_byte(void);
+
+/* Enable dbg mode, switching use of the pins */
+void
+ao_dbg_debug_mode(void);
+
+/* Reset the dbg target */
+void
+ao_dbg_reset(void);
+
+void
+ao_dbg_init(void);
+
+/*
+ * ao_serial.c
+ */
+
+#ifndef HAS_SERIAL_1
+#error Please define HAS_SERIAL_1
+#endif
+
+#if HAS_SERIAL_1
+#ifndef USE_SERIAL_STDIN
+#error Please define USE_SERIAL_STDIN
+#endif
+
+void
+ao_serial_rx1_isr(void) __interrupt 3;
+
+void
+ao_serial_tx1_isr(void) __interrupt 14;
+
+char
+ao_serial_getchar(void) __critical;
+
+#if USE_SERIAL_STDIN
+char
+ao_serial_pollchar(void) __critical;
+
+void
+ao_serial_set_stdin(uint8_t stdin);
+#endif
+
+void
+ao_serial_putchar(char c) __critical;
+
+void
+ao_serial_drain(void) __critical;
+
+#define AO_SERIAL_SPEED_4800   0
+#define AO_SERIAL_SPEED_9600   1
+#define AO_SERIAL_SPEED_19200  2
+#define AO_SERIAL_SPEED_57600  3
+
+void
+ao_serial_set_speed(uint8_t speed);
+
+void
+ao_serial_init(void);
+#endif
+
+/*
+ * ao_spi.c
+ */
+
+extern __xdata uint8_t ao_spi_mutex;
+
+#define ao_spi_get_mask(reg,mask) do {\
+       ao_mutex_get(&ao_spi_mutex); \
+       (reg) &= ~(mask); \
+       } while (0)
+
+#define ao_spi_put_mask(reg,mask) do { \
+       (reg) |= (mask); \
+       ao_mutex_put(&ao_spi_mutex); \
+       } while (0)
+
+#define ao_spi_get_bit(bit) do {\
+       ao_mutex_get(&ao_spi_mutex); \
+       (bit) = 0; \
+       } while (0)
+
+#define ao_spi_put_bit(bit) do { \
+       (bit) = 1; \
+       ao_mutex_put(&ao_spi_mutex); \
+       } while (0)
+
+/*
+ * The SPI mutex must be held to call either of these
+ * functions -- this mutex covers the entire SPI operation,
+ * from chip select low to chip select high
+ */
+
+void
+ao_spi_send(void __xdata *block, uint16_t len) __reentrant;
+
+void
+ao_spi_recv(void __xdata *block, uint16_t len) __reentrant;
+
+void
+ao_spi_init(void);
+
+/*
+ * ao_telemetry.c
+ */
+#define AO_MAX_CALLSIGN                        8
+#define AO_MAX_VERSION                 8
+#define AO_MAX_TELEMETRY               128
+
+struct ao_telemetry_generic {
+       uint16_t        serial;         /* 0 */
+       uint16_t        tick;           /* 2 */
+       uint8_t         type;           /* 4 */
+       uint8_t         payload[27];    /* 5 */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01
+#define AO_TELEMETRY_SENSOR_TELEMINI   0x02
+#define AO_TELEMETRY_SENSOR_TELENANO   0x03
+
+struct ao_telemetry_sensor {
+       uint16_t        serial;         /*  0 */
+       uint16_t        tick;           /*  2 */
+       uint8_t         type;           /*  4 */
+
+       uint8_t         state;          /*  5 flight state */
+       int16_t         accel;          /*  6 accelerometer (TM only) */
+       int16_t         pres;           /*  8 pressure sensor */
+       int16_t         temp;           /* 10 temperature sensor */
+       int16_t         v_batt;         /* 12 battery voltage */
+       int16_t         sense_d;        /* 14 drogue continuity sense (TM/Tm) */
+       int16_t         sense_m;        /* 16 main continuity sense (TM/Tm) */
+
+       int16_t         acceleration;   /* 18 m/s² * 16 */
+       int16_t         speed;          /* 20 m/s * 16 */
+       int16_t         height;         /* 22 m */
+
+       int16_t         ground_pres;    /* 24 average pres on pad */
+       int16_t         ground_accel;   /* 26 average accel on pad */
+       int16_t         accel_plus_g;   /* 28 accel calibration at +1g */
+       int16_t         accel_minus_g;  /* 30 accel calibration at -1g */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_CONFIGURATION     0x04
+
+struct ao_telemetry_configuration {
+       uint16_t        serial;                         /*  0 */
+       uint16_t        tick;                           /*  2 */
+       uint8_t         type;                           /*  4 */
+
+       uint8_t         device;                         /*  5 device type */
+       uint16_t        flight;                         /*  6 flight number */
+       uint8_t         config_major;                   /*  8 Config major version */
+       uint8_t         config_minor;                   /*  9 Config minor version */
+       uint16_t        apogee_delay;                   /* 10 Apogee deploy delay in seconds */
+       uint16_t        main_deploy;                    /* 12 Main deploy alt in meters */
+       uint16_t        flight_log_max;                 /* 14 Maximum flight log size in kB */
+       char            callsign[AO_MAX_CALLSIGN];      /* 16 Radio operator identity */
+       char            version[AO_MAX_VERSION];        /* 24 Software version */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_LOCATION          0x05
+
+#define AO_GPS_MODE_NOT_VALID          'N'
+#define AO_GPS_MODE_AUTONOMOUS         'A'
+#define AO_GPS_MODE_DIFFERENTIAL       'D'
+#define AO_GPS_MODE_ESTIMATED          'E'
+#define AO_GPS_MODE_MANUAL             'M'
+#define AO_GPS_MODE_SIMULATED          'S'
+
+struct ao_telemetry_location {
+       uint16_t        serial;         /*  0 */
+       uint16_t        tick;           /*  2 */
+       uint8_t         type;           /*  4 */
+
+       uint8_t         flags;          /*  5 Number of sats and other flags */
+       int16_t         altitude;       /*  6 GPS reported altitude (m) */
+       int32_t         latitude;       /*  8 latitude (degrees * 10⁷) */
+       int32_t         longitude;      /* 12 longitude (degrees * 10⁷) */
+       uint8_t         year;           /* 16 (- 2000) */
+       uint8_t         month;          /* 17 (1-12) */
+       uint8_t         day;            /* 18 (1-31) */
+       uint8_t         hour;           /* 19 (0-23) */
+       uint8_t         minute;         /* 20 (0-59) */
+       uint8_t         second;         /* 21 (0-59) */
+       uint8_t         pdop;           /* 22 (m * 5) */
+       uint8_t         hdop;           /* 23 (m * 5) */
+       uint8_t         vdop;           /* 24 (m * 5) */
+       uint8_t         mode;           /* 25 */
+       uint16_t        ground_speed;   /* 26 cm/s */
+       int16_t         climb_rate;     /* 28 cm/s */
+       uint8_t         course;         /* 30 degrees / 2 */
+       uint8_t         unused[1];      /* 31 */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_SATELLITE         0x06
+
+struct ao_telemetry_satellite_info {
+       uint8_t         svid;
+       uint8_t         c_n_1;
+};
+
+struct ao_telemetry_satellite {
+       uint16_t                                serial;         /*  0 */
+       uint16_t                                tick;           /*  2 */
+       uint8_t                                 type;           /*  4 */
+       uint8_t                                 channels;       /*  5 number of reported sats */
+
+       struct ao_telemetry_satellite_info      sats[12];       /* 6 */
+       uint8_t                                 unused[2];      /* 30 */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_COMPANION         0x07
+
+#define AO_COMPANION_MAX_CHANNELS      12
+
+struct ao_telemetry_companion {
+       uint16_t                                serial;         /*  0 */
+       uint16_t                                tick;           /*  2 */
+       uint8_t                                 type;           /*  4 */
+       uint8_t                                 board_id;       /*  5 */
+
+       uint8_t                                 update_period;  /*  6 */
+       uint8_t                                 channels;       /*  7 */
+       uint16_t                                companion_data[AO_COMPANION_MAX_CHANNELS];      /*  8 */
+       /* 32 */
+};
+       
+union ao_telemetry_all {
+       struct ao_telemetry_generic             generic;
+       struct ao_telemetry_sensor              sensor;
+       struct ao_telemetry_configuration       configuration;
+       struct ao_telemetry_location            location;
+       struct ao_telemetry_satellite           satellite;
+       struct ao_telemetry_companion           companion;
+};
+
+/*
+ * ao_gps.c
+ */
+
+#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
+#define AO_GPS_NUM_SAT_SHIFT   (0)
+
+#define AO_GPS_VALID           (1 << 4)
+#define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
+#define AO_GPS_COURSE_VALID    (1 << 7)
+
+extern __pdata uint16_t ao_gps_tick;
+extern __xdata uint8_t ao_gps_mutex;
+extern __xdata struct ao_telemetry_location ao_gps_data;
+extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data;
+
+struct ao_gps_orig {
+       uint8_t                 year;
+       uint8_t                 month;
+       uint8_t                 day;
+       uint8_t                 hour;
+       uint8_t                 minute;
+       uint8_t                 second;
+       uint8_t                 flags;
+       int32_t                 latitude;       /* degrees * 10⁷ */
+       int32_t                 longitude;      /* degrees * 10⁷ */
+       int16_t                 altitude;       /* m */
+       uint16_t                ground_speed;   /* cm/s */
+       uint8_t                 course;         /* degrees / 2 */
+       uint8_t                 hdop;           /* * 5 */
+       int16_t                 climb_rate;     /* cm/s */
+       uint16_t                h_error;        /* m */
+       uint16_t                v_error;        /* m */
+};
+
+struct ao_gps_sat_orig {
+       uint8_t         svid;
+       uint8_t         c_n_1;
+};
+
+#define AO_MAX_GPS_TRACKING    12
+
+struct ao_gps_tracking_orig {
+       uint8_t                 channels;
+       struct ao_gps_sat_orig  sats[AO_MAX_GPS_TRACKING];
+};
+
+void
+ao_gps(void);
+
+void
+ao_gps_print(__xdata struct ao_gps_orig *gps_data);
+
+void
+ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data);
+
+void
+ao_gps_init(void);
+
+/*
+ * ao_gps_report.c
+ */
+
+void
+ao_gps_report(void);
+
+void
+ao_gps_report_init(void);
+
+/*
+ * ao_telemetry_orig.c
+ */
+
+struct ao_telemetry_orig {
+       uint16_t                serial;
+       uint16_t                flight;
+       uint8_t                 flight_state;
+       int16_t                 accel;
+       int16_t                 ground_accel;
+       union {
+               struct {
+                       int16_t                 speed;
+                       int16_t                 unused;
+               } k;
+               int32_t         flight_vel;
+       } u;
+       int16_t                 height;
+       int16_t                 ground_pres;
+       int16_t                 accel_plus_g;
+       int16_t                 accel_minus_g;
+       struct ao_adc           adc;
+       struct ao_gps_orig      gps;
+       char                    callsign[AO_MAX_CALLSIGN];
+       struct ao_gps_tracking_orig     gps_tracking;
+};
+
+struct ao_telemetry_tiny {
+       uint16_t                serial;
+       uint16_t                flight;
+       uint8_t                 flight_state;
+       int16_t                 height;         /* AGL in meters */
+       int16_t                 speed;          /* in m/s * 16 */
+       int16_t                 accel;          /* in m/s² * 16 */
+       int16_t                 ground_pres;    /* sensor units */
+       struct ao_adc           adc;            /* raw ADC readings */
+       char                    callsign[AO_MAX_CALLSIGN];
+};
+
+/*
+ * ao_radio_recv tacks on rssi and status bytes
+ */
+
+struct ao_telemetry_raw_recv {
+       uint8_t                 packet[AO_MAX_TELEMETRY + 2];
+};
+
+struct ao_telemetry_orig_recv {
+       struct ao_telemetry_orig        telemetry_orig;
+       int8_t                          rssi;
+       uint8_t                         status;
+};
+
+struct ao_telemetry_tiny_recv {
+       struct ao_telemetry_tiny        telemetry_tiny;
+       int8_t                          rssi;
+       uint8_t                         status;
+};
+
+/* Set delay between telemetry reports (0 to disable) */
+
+#define AO_TELEMETRY_INTERVAL_PAD      AO_MS_TO_TICKS(1000)
+#define AO_TELEMETRY_INTERVAL_FLIGHT   AO_MS_TO_TICKS(100)
+#define AO_TELEMETRY_INTERVAL_RECOVER  AO_MS_TO_TICKS(1000)
+
+void
+ao_telemetry_set_interval(uint16_t interval);
+
+void
+ao_rdf_set(uint8_t rdf);
+
+void
+ao_telemetry_init(void);
+
+void
+ao_telemetry_orig_init(void);
+
+void
+ao_telemetry_tiny_init(void);
+
+/*
+ * ao_radio.c
+ */
+
+extern __xdata uint8_t ao_radio_dma;
+extern __xdata uint8_t ao_radio_dma_done;
+extern __xdata uint8_t ao_radio_done;
+extern __xdata uint8_t ao_radio_mutex;
+
+void
+ao_radio_general_isr(void) __interrupt 16;
+
+void
+ao_radio_get(uint8_t len);
+
+#define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
+
+void
+ao_radio_set_packet(void);
+
+void
+ao_radio_send(__xdata void *data, uint8_t size) __reentrant;
+
+uint8_t
+ao_radio_recv(__xdata void *data, uint8_t size) __reentrant;
+
+void
+ao_radio_recv_abort(void);
+
+void
+ao_radio_rdf(int ms);
+
+void
+ao_radio_rdf_abort(void);
+
+void
+ao_radio_idle(void);
+
+void
+ao_radio_init(void);
+
+/*
+ * ao_monitor.c
+ */
+
+extern const char const * const ao_state_names[];
+
+void
+ao_monitor(void);
+
+#define AO_MONITORING_OFF      0
+#define AO_MONITORING_ORIG     1
+#define AO_MONITORING_TINY     2
+
+void
+ao_set_monitor(uint8_t monitoring);
+
+void
+ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant;
+
+/*
+ * ao_stdio.c
+ */
+
+#define AO_READ_AGAIN  ((char) -1)
+
+struct ao_stdio {
+       char    (*pollchar)(void);
+       void    (*putchar)(char c) __reentrant;
+       void    (*flush)(void);
+       uint8_t echo;
+};
+
+extern __xdata struct ao_stdio ao_stdios[];
+extern __pdata int8_t ao_cur_stdio;
+extern __pdata int8_t ao_num_stdios;
+
+void
+flush(void);
+
+extern __xdata uint8_t ao_stdin_ready;
+
+uint8_t
+ao_echo(void);
+
+int8_t
+ao_add_stdio(char (*pollchar)(void),
+            void (*putchar)(char) __reentrant,
+            void (*flush)(void)) __reentrant;
+
+/*
+ * ao_ignite.c
+ */
+
+enum ao_igniter {
+       ao_igniter_drogue = 0,
+       ao_igniter_main = 1
+};
+
+void
+ao_ignite(enum ao_igniter igniter);
+
+enum ao_igniter_status {
+       ao_igniter_unknown,     /* unknown status (ambiguous voltage) */
+       ao_igniter_ready,       /* continuity detected */
+       ao_igniter_active,      /* igniter firing */
+       ao_igniter_open,        /* open circuit detected */
+};
+
+enum ao_igniter_status
+ao_igniter_status(enum ao_igniter igniter);
+
+void
+ao_ignite_set_pins(void);
+
+void
+ao_igniter_init(void);
+
+/*
+ * ao_config.c
+ */
+
+#define AO_CONFIG_MAJOR        1
+#define AO_CONFIG_MINOR        8
+
+struct ao_config {
+       uint8_t         major;
+       uint8_t         minor;
+       uint16_t        main_deploy;
+       int16_t         accel_plus_g;           /* changed for minor version 2 */
+       uint8_t         radio_channel;
+       char            callsign[AO_MAX_CALLSIGN + 1];
+       uint8_t         apogee_delay;           /* minor version 1 */
+       int16_t         accel_minus_g;          /* minor version 2 */
+       uint32_t        radio_cal;              /* minor version 3 */
+       uint32_t        flight_log_max;         /* minor version 4 */
+       uint8_t         ignite_mode;            /* minor version 5 */
+       uint8_t         pad_orientation;        /* minor version 6 */
+       uint32_t        radio_setting;          /* minor version 7 */
+       uint8_t         radio_enable;           /* minor version 8 */
+};
+
+#define AO_IGNITE_MODE_DUAL            0
+#define AO_IGNITE_MODE_APOGEE          1
+#define AO_IGNITE_MODE_MAIN            2
+
+#define AO_PAD_ORIENTATION_ANTENNA_UP  0
+#define AO_PAD_ORIENTATION_ANTENNA_DOWN        1
+
+extern __xdata struct ao_config ao_config;
+
+#define AO_CONFIG_MAX_SIZE     128
+
+void
+ao_config_get(void);
+
+void
+ao_config_put(void);
+
+void
+ao_config_init(void);
+
+/*
+ * ao_rssi.c
+ */
+
+void
+ao_rssi_set(int rssi_value);
+
+void
+ao_rssi_init(uint8_t rssi_led);
+
+/*
+ * ao_product.c
+ *
+ * values which need to be defined for
+ * each instance of a product
+ */
+
+extern const char ao_version[];
+extern const char ao_manufacturer[];
+extern const char ao_product[];
+
+/*
+ * Fifos
+ */
+
+#define AO_FIFO_SIZE   32
+
+struct ao_fifo {
+       uint8_t insert;
+       uint8_t remove;
+       char    fifo[AO_FIFO_SIZE];
+};
+
+#define ao_fifo_insert(f,c) do { \
+       (f).fifo[(f).insert] = (c); \
+       (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \
+} while(0)
+
+#define ao_fifo_remove(f,c) do {\
+       c = (f).fifo[(f).remove]; \
+       (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \
+} while(0)
+
+#define ao_fifo_full(f)                ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
+#define ao_fifo_empty(f)       ((f).insert == (f).remove)
+
+/*
+ * ao_packet.c
+ *
+ * Packet-based command interface
+ */
+
+#define AO_PACKET_MAX          64
+#define AO_PACKET_SYN          (uint8_t) 0xff
+
+struct ao_packet {
+       uint8_t         addr;
+       uint8_t         len;
+       uint8_t         seq;
+       uint8_t         ack;
+       uint8_t         d[AO_PACKET_MAX];
+       uint8_t         callsign[AO_MAX_CALLSIGN];
+};
+
+struct ao_packet_recv {
+       struct ao_packet        packet;
+       int8_t                  rssi;
+       uint8_t                 status;
+};
+
+extern __xdata struct ao_packet_recv ao_rx_packet;
+extern __xdata struct ao_packet ao_tx_packet;
+extern __xdata struct ao_task  ao_packet_task;
+extern __xdata uint8_t ao_packet_enable;
+extern __xdata uint8_t ao_packet_master_sleeping;
+extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used;
+
+void
+ao_packet_send(void);
+
+uint8_t
+ao_packet_recv(void);
+
+void
+ao_packet_flush(void);
+
+void
+ao_packet_putchar(char c) __reentrant;
+
+char
+ao_packet_pollchar(void) __critical;
+
+/* ao_packet_master.c */
+
+void
+ao_packet_master_init(void);
+
+/* ao_packet_slave.c */
+
+void
+ao_packet_slave_start(void);
+
+void
+ao_packet_slave_stop(void);
+
+void
+ao_packet_slave_init(uint8_t enable);
+
+/* ao_btm.c */
+
+/* If bt_link is on P2, this interrupt is shared by USB, so the USB
+ * code calls this function. Otherwise, it's a regular ISR.
+ */
+
+void
+ao_btm_isr(void)
+#if BT_LINK_ON_P1
+       __interrupt 15
+#endif
+       ;
+
+void
+ao_btm_init(void);
+
+/* ao_companion.c */
+
+#define AO_COMPANION_SETUP             1
+#define AO_COMPANION_FETCH             2
+#define AO_COMPANION_NOTIFY            3
+
+struct ao_companion_command {
+       uint8_t         command;
+       uint8_t         flight_state;
+       uint16_t        tick;
+       uint16_t        serial;
+       uint16_t        flight;
+};
+
+struct ao_companion_setup {
+       uint16_t        board_id;
+       uint16_t        board_id_inverse;
+       uint8_t         update_period;
+       uint8_t         channels;
+};
+
+extern __pdata uint8_t                         ao_companion_running;
+extern __xdata struct ao_companion_setup       ao_companion_setup;
+extern __xdata uint8_t                         ao_companion_mutex;
+extern __xdata uint16_t                                ao_companion_data[AO_COMPANION_MAX_CHANNELS];
+
+void
+ao_companion_init(void);
+
+#endif /* _AO_H_ */
diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c
new file mode 100644 (file)
index 0000000..1442ebe
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__pdata uint16_t ao_cmd_lex_i;
+__pdata uint32_t ao_cmd_lex_u32;
+__pdata char   ao_cmd_lex_c;
+__pdata enum ao_cmd_status ao_cmd_status;
+
+#define CMD_LEN        32
+
+static __xdata char    cmd_line[CMD_LEN];
+static __pdata uint8_t cmd_len;
+static __pdata uint8_t cmd_i;
+
+static void
+put_string(__code char *s)
+{
+       char    c;
+       while (c = *s++)
+               putchar(c);
+}
+
+static void
+readline(void)
+{
+       __pdata char c;
+       if (ao_echo())
+               put_string("> ");
+       cmd_len = 0;
+       for (;;) {
+               flush();
+               c = getchar();
+               /* backspace/delete */
+               if (c == '\010' || c == '\177') {
+                       if (cmd_len != 0) {
+                               if (ao_echo())
+                                       put_string("\010 \010");
+                               --cmd_len;
+                       }
+                       continue;
+               }
+
+               /* ^U */
+               if (c == '\025') {
+                       while (cmd_len != 0) {
+                               if (ao_echo())
+                                       put_string("\010 \010");
+                               --cmd_len;
+                       }
+                       continue;
+               }
+
+               /* map CR to NL */
+               if (c == '\r')
+                       c = '\n';
+
+               if (c == '\n') {
+                       if (ao_echo())
+                               putchar('\n');
+                       break;
+               }
+
+               if (cmd_len >= CMD_LEN - 2) {
+                       if (ao_echo())
+                               putchar('\007');
+                       continue;
+               }
+               cmd_line[cmd_len++] = c;
+               if (ao_echo())
+                       putchar(c);
+       }
+       cmd_line[cmd_len++] = '\n';
+       cmd_line[cmd_len++] = '\0';
+       cmd_i = 0;
+}
+
+void
+ao_cmd_lex(void)
+{
+       ao_cmd_lex_c = '\n';
+       if (cmd_i < cmd_len)
+               ao_cmd_lex_c = cmd_line[cmd_i++];
+}
+
+static void
+putnibble(uint8_t v)
+{
+       if (v < 10)
+               putchar(v + '0');
+       else
+               putchar(v + ('a' - 10));
+}
+
+void
+ao_cmd_put16(uint16_t v)
+{
+       ao_cmd_put8(v >> 8);
+       ao_cmd_put8(v);
+}
+
+void
+ao_cmd_put8(uint8_t v)
+{
+       putnibble((v >> 4) & 0xf);
+       putnibble(v & 0xf);
+}
+
+void
+ao_cmd_white(void)
+{
+       while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t')
+               ao_cmd_lex();
+}
+
+void
+ao_cmd_hex(void)
+{
+       __pdata uint8_t r = ao_cmd_lex_error;
+       uint8_t n;
+
+       ao_cmd_lex_i = 0;
+       ao_cmd_white();
+       for(;;) {
+               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+                       n = (ao_cmd_lex_c - '0');
+               else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
+                       n = (ao_cmd_lex_c - 'a' + 10);
+               else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
+                       n = (ao_cmd_lex_c - 'A' + 10);
+               else
+                       break;
+               ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n;
+               r = ao_cmd_success;
+               ao_cmd_lex();
+       }
+       if (r != ao_cmd_success)
+               ao_cmd_status = r;
+}
+
+void
+ao_cmd_decimal(void)
+{
+       __pdata uint8_t r = ao_cmd_lex_error;
+
+       ao_cmd_lex_u32 = 0;
+       ao_cmd_white();
+       for(;;) {
+               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+                       ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0');
+               else
+                       break;
+               r = ao_cmd_success;
+               ao_cmd_lex();
+       }
+       if (r != ao_cmd_success)
+               ao_cmd_status = r;
+       ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32;
+}
+
+uint8_t
+ao_match_word(__code char *word)
+{
+       while (*word) {
+               if (ao_cmd_lex_c != *word) {
+                       ao_cmd_status = ao_cmd_syntax_error;
+                       return 0;
+               }
+               word++;
+               ao_cmd_lex();
+       }
+       return 1;
+}
+
+static void
+eol(void)
+{
+       while (ao_cmd_lex_c != '\n')
+               ao_cmd_lex();
+}
+
+static void
+echo(void)
+{
+       ao_cmd_hex();
+       if (ao_cmd_status == ao_cmd_success)
+               ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0;
+}
+
+static void
+ao_reboot(void)
+{
+       ao_cmd_white();
+       if (!ao_match_word("eboot"))
+               return;
+       WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64;
+       ao_delay(AO_SEC_TO_TICKS(2));
+       ao_panic(AO_PANIC_REBOOT);
+}
+
+static void
+version(void)
+{
+       printf("manufacturer     %s\n", ao_manufacturer);
+       printf("product          %s\n", ao_product);
+       printf("serial-number    %u\n", ao_serial_number);
+#if HAS_EEPROM
+       printf("log-format       %u\n", ao_log_format);
+#endif
+       printf("software-version %s\n", ao_version);
+}
+
+#define NUM_CMDS       11
+
+static __code struct ao_cmds   *__xdata (ao_cmds[NUM_CMDS]);
+static __pdata uint8_t         ao_ncmds;
+
+static void
+help(void)
+{
+       register uint8_t cmds;
+       register uint8_t cmd;
+       register __code struct ao_cmds * cs;
+
+       for (cmds = 0; cmds < ao_ncmds; cmds++) {
+               cs = ao_cmds[cmds];
+               for (cmd = 0; cs[cmd].func; cmd++)
+                       printf("%-45s %s\n",
+                               cs[cmd].help,
+                               cs[cmd].help+1+strlen(cs[cmd].help));
+       }
+}
+
+static void
+report(void)
+{
+       switch(ao_cmd_status) {
+       case ao_cmd_lex_error:
+       case ao_cmd_syntax_error:
+               puts("Syntax error");
+               ao_cmd_status = 0;
+               break;
+       }
+}
+
+void
+ao_cmd_register(__code struct ao_cmds *cmds)
+{
+       if (ao_ncmds >= NUM_CMDS)
+               ao_panic(AO_PANIC_CMD);
+       ao_cmds[ao_ncmds++] = cmds;
+}
+
+void
+ao_cmd(void)
+{
+       char    c;
+       uint8_t cmd, cmds;
+       __code struct ao_cmds * __xdata cs;
+       void (*__xdata func)(void);
+
+       for (;;) {
+               readline();
+               ao_cmd_lex();
+               ao_cmd_white();
+               c = ao_cmd_lex_c;
+               ao_cmd_lex();
+               if (c == '\r' || c == '\n')
+                       continue;
+               func = (void (*)(void)) NULL;
+               for (cmds = 0; cmds < ao_ncmds; cmds++) {
+                       cs = ao_cmds[cmds];
+                       for (cmd = 0; cs[cmd].func; cmd++)
+                               if (cs[cmd].help[0] == c) {
+                                       func = cs[cmd].func;
+                                       break;
+                               }
+                       if (func)
+                               break;
+               }
+               if (func)
+                       (*func)();
+               else
+                       ao_cmd_status = ao_cmd_syntax_error;
+               report();
+       }
+}
+
+__xdata struct ao_task ao_cmd_task;
+
+__code struct ao_cmds  ao_base_cmds[] = {
+       { help,         "?\0Help" },
+       { ao_task_info, "T\0Show tasks" },
+       { echo,         "E <0 off, 1 on>\0Set echo mode" },
+       { ao_reboot,    "r eboot\0Reboot" },
+       { version,      "v\0Version" },
+       { 0,    NULL },
+};
+
+void
+ao_cmd_init(void)
+{
+       ao_cmd_register(&ao_base_cmds[0]);
+       ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
+}
diff --git a/src/core/ao_config.c b/src/core/ao_config.c
new file mode 100644 (file)
index 0000000..0c10e60
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__xdata struct ao_config ao_config;
+__pdata uint8_t ao_config_loaded;
+__pdata uint8_t ao_config_dirty;
+__xdata uint8_t ao_config_mutex;
+
+#define AO_CONFIG_DEFAULT_MAIN_DEPLOY  250
+#define AO_CONFIG_DEFAULT_RADIO_CHANNEL        0
+#define AO_CONFIG_DEFAULT_CALLSIGN     "N0CALL"
+#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
+#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0
+#define AO_CONFIG_DEFAULT_IGNITE_MODE  AO_IGNITE_MODE_DUAL
+#define AO_CONFIG_DEFAULT_PAD_ORIENTATION      AO_PAD_ORIENTATION_ANTENNA_UP
+#if HAS_EEPROM
+#ifndef USE_INTERNAL_FLASH
+#error Please define USE_INTERNAL_FLASH
+#endif
+#endif
+#if USE_INTERNAL_FLASH
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       ao_storage_config
+#else
+#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX       ((uint32_t) 192 * (uint32_t) 1024)
+#endif
+
+#if HAS_EEPROM
+static void
+_ao_config_put(void)
+{
+       ao_storage_setup();
+       ao_storage_erase(ao_storage_config);
+       ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config));
+       ao_log_write_erase(0);
+       ao_storage_flush();
+}
+
+void
+ao_config_put(void)
+{
+       ao_mutex_get(&ao_config_mutex);
+       _ao_config_put();
+       ao_mutex_put(&ao_config_mutex);
+}
+#endif
+
+static void
+_ao_config_get(void)
+{
+       if (ao_config_loaded)
+               return;
+#if HAS_EEPROM
+       ao_storage_setup();
+       ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config));
+#endif
+       if (ao_config.major != AO_CONFIG_MAJOR) {
+               ao_config.major = AO_CONFIG_MAJOR;
+               ao_config.minor = 0;
+               ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
+               ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL;
+               memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
+               memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
+                      sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
+       }
+       if (ao_config.minor < AO_CONFIG_MINOR) {
+               /* Fixups for minor version 1 */
+               if (ao_config.minor < 1)
+                       ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY;
+               /* Fixups for minor version 2 */
+               if (ao_config.minor < 2) {
+                       ao_config.accel_plus_g = 0;
+                       ao_config.accel_minus_g = 0;
+               }
+               /* Fixups for minor version 3 */
+               if (ao_config.minor < 3)
+                       ao_config.radio_cal = ao_radio_cal;
+               /* Fixups for minor version 4 */
+               if (ao_config.minor < 4)
+                       ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX;
+               /* Fixupes for minor version 5 */
+               if (ao_config.minor < 5)
+                       ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE;
+               if (ao_config.minor < 6)
+                       ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION;
+               if (ao_config.minor < 7)
+                       ao_config.radio_setting = ao_config.radio_cal;
+               if (ao_config.minor < 8)
+                       ao_config.radio_enable = TRUE;
+               ao_config.minor = AO_CONFIG_MINOR;
+               ao_config_dirty = 1;
+       }
+       ao_config_loaded = 1;
+}
+
+static void
+_ao_config_edit_start(void)
+{
+       ao_mutex_get(&ao_config_mutex);
+       _ao_config_get();
+}
+
+static void
+_ao_config_edit_finish(void)
+{
+       ao_config_dirty = 1;
+       ao_mutex_put(&ao_config_mutex);
+}
+
+void
+ao_config_get(void)
+{
+       _ao_config_edit_start();
+       ao_mutex_put(&ao_config_mutex);
+}
+
+void
+ao_config_callsign_show(void)
+{
+       printf ("Callsign: \"%s\"\n", ao_config.callsign);
+}
+
+void
+ao_config_callsign_set(void) __reentrant
+{
+       uint8_t c;
+       static __xdata char callsign[AO_MAX_CALLSIGN + 1];
+
+       memset(callsign, '\0', sizeof callsign);
+       ao_cmd_white();
+       c = 0;
+       while (ao_cmd_lex_c != '\n') {
+               if (c < AO_MAX_CALLSIGN)
+                       callsign[c++] = ao_cmd_lex_c;
+               else
+                       ao_cmd_status = ao_cmd_lex_error;
+               ao_cmd_lex();
+       }
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       memcpy(&ao_config.callsign, &callsign,
+              AO_MAX_CALLSIGN + 1);
+       _ao_config_edit_finish();
+}
+
+void
+ao_config_radio_channel_show(void) __reentrant
+{
+       printf("Radio channel: %d\n",
+              ao_config.radio_channel);
+}
+
+void
+ao_config_radio_channel_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.radio_channel = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+       ao_radio_recv_abort();
+}
+
+#if HAS_ADC
+
+void
+ao_config_main_deploy_show(void) __reentrant
+{
+       printf("Main deploy: %d meters\n",
+              ao_config.main_deploy);
+}
+
+void
+ao_config_main_deploy_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.main_deploy = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+
+#if HAS_ACCEL
+void
+ao_config_accel_calibrate_show(void) __reentrant
+{
+       printf("Accel cal +1g: %d -1g: %d\n",
+              ao_config.accel_plus_g, ao_config.accel_minus_g);
+}
+
+#define ACCEL_CALIBRATE_SAMPLES        1024
+#define ACCEL_CALIBRATE_SHIFT  10
+
+static int16_t
+ao_config_accel_calibrate_auto(char *orientation) __reentrant
+{
+       uint16_t        i;
+       int32_t         accel_total;
+       uint8_t         cal_adc_ring;
+
+       printf("Orient antenna %s and press a key...", orientation);
+       flush();
+       (void) getchar();
+       puts("\r\n"); flush();
+       puts("Calibrating..."); flush();
+       i = ACCEL_CALIBRATE_SAMPLES;
+       accel_total = 0;
+       cal_adc_ring = ao_sample_adc;
+       while (i) {
+               ao_sleep(DATA_TO_XDATA(&ao_sample_adc));
+               while (i && cal_adc_ring != ao_sample_adc) {
+                       accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel;
+                       cal_adc_ring = ao_adc_ring_next(cal_adc_ring);
+                       i--;
+               }
+       }
+       return accel_total >> ACCEL_CALIBRATE_SHIFT;
+}
+
+void
+ao_config_accel_calibrate_set(void) __reentrant
+{
+       int16_t up, down;
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       if (ao_cmd_lex_i == 0) {
+               up = ao_config_accel_calibrate_auto("up");
+               down = ao_config_accel_calibrate_auto("down");
+       } else {
+               up = ao_cmd_lex_i;
+               ao_cmd_decimal();
+               if (ao_cmd_status != ao_cmd_success)
+                       return;
+               down = ao_cmd_lex_i;
+       }
+       if (up >= down) {
+               printf("Invalid accel: up (%d) down (%d)\n",
+                      up, down);
+               return;
+       }
+       _ao_config_edit_start();
+       ao_config.accel_plus_g = up;
+       ao_config.accel_minus_g = down;
+       _ao_config_edit_finish();
+}
+#endif /* HAS_ACCEL */
+
+void
+ao_config_apogee_delay_show(void) __reentrant
+{
+       printf("Apogee delay: %d seconds\n",
+              ao_config.apogee_delay);
+}
+
+void
+ao_config_apogee_delay_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.apogee_delay = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+
+#endif /* HAS_ADC */
+
+void
+ao_config_radio_cal_show(void) __reentrant
+{
+       printf("Radio cal: %ld\n", ao_config.radio_cal);
+}
+
+void
+ao_config_radio_cal_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32;
+       _ao_config_edit_finish();
+}
+
+#if HAS_EEPROM
+void
+ao_config_log_show(void) __reentrant
+{
+       printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10));
+}
+
+void
+ao_config_log_set(void) __reentrant
+{
+       uint16_t        block = (uint16_t) (ao_storage_block >> 10);
+       uint16_t        config = (uint16_t) (ao_storage_config >> 10);
+
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       if (ao_log_present())
+               printf("Storage must be empty before changing log size\n");
+       else if (block > 1024 && (ao_cmd_lex_i & (block - 1)))
+               printf("Flight log size must be multiple of %d kB\n", block);
+       else if (ao_cmd_lex_i > config)
+               printf("Flight log max %d kB\n", config);
+       else {
+               _ao_config_edit_start();
+               ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;
+               _ao_config_edit_finish();
+       }
+}
+#endif /* HAS_EEPROM */
+
+#if HAS_IGNITE
+void
+ao_config_ignite_mode_show(void) __reentrant
+{
+       printf("Ignite mode: %d\n", ao_config.ignite_mode);
+}
+
+void
+ao_config_ignite_mode_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.ignite_mode = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+#endif
+
+#if HAS_ACCEL
+void
+ao_config_pad_orientation_show(void) __reentrant
+{
+       printf("Pad orientation: %d\n", ao_config.pad_orientation);
+}
+
+void
+ao_config_pad_orientation_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_cmd_lex_i &= 1;
+       if (ao_config.pad_orientation != ao_cmd_lex_i) {
+               uint16_t t;
+               t = ao_config.accel_plus_g;
+               ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g;
+               ao_config.accel_minus_g = 0x7fff - t;
+       }
+       ao_config.pad_orientation = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+#endif
+
+void
+ao_config_radio_setting_show(void) __reentrant
+{
+       printf("Radio setting: %ld\n", ao_config.radio_setting);
+}
+
+void
+ao_config_radio_setting_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.radio_setting = ao_cmd_lex_u32;
+       ao_config.radio_channel = 0;
+       _ao_config_edit_finish();
+       ao_radio_recv_abort();
+}
+
+void
+ao_config_radio_enable_show(void) __reentrant
+{
+       printf("Radio enable: %d\n", ao_config.radio_enable);
+}
+
+void
+ao_config_radio_enable_set(void) __reentrant
+{
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       _ao_config_edit_start();
+       ao_config.radio_enable = ao_cmd_lex_i;
+       _ao_config_edit_finish();
+}
+       
+struct ao_config_var {
+       __code char     *str;
+       void            (*set)(void) __reentrant;
+       void            (*show)(void) __reentrant;
+};
+
+static void
+ao_config_help(void) __reentrant;
+
+static void
+ao_config_show(void) __reentrant;
+
+static void
+ao_config_write(void) __reentrant;
+
+__code struct ao_config_var ao_config_vars[] = {
+#if HAS_ADC
+       { "m <meters>\0Main deploy (in meters)",
+         ao_config_main_deploy_set,    ao_config_main_deploy_show, },
+       { "d <delay>\0Apogee delay (in seconds)",
+         ao_config_apogee_delay_set,   ao_config_apogee_delay_show },
+#endif /* HAS_ADC */
+       { "r <channel>\0Radio channel (freq = 434.550 + chan * .1)",
+         ao_config_radio_channel_set,  ao_config_radio_channel_show },
+       { "c <call>\0Callsign (8 char max)",
+         ao_config_callsign_set,       ao_config_callsign_show },
+       { "R <setting>\0Radio freq control (freq = 434.550 * setting/cal)",
+         ao_config_radio_setting_set,  ao_config_radio_setting_show },
+       { "e <0 disable, 1 enable>\0Enable telemetry and RDF",
+         ao_config_radio_enable_set, ao_config_radio_enable_show },
+#if HAS_ACCEL
+       { "a <+g> <-g>\0Accel calib (0 for auto)",
+         ao_config_accel_calibrate_set,ao_config_accel_calibrate_show },
+#endif /* HAS_ACCEL */
+       { "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",
+         ao_config_radio_cal_set,      ao_config_radio_cal_show },
+#if HAS_EEPROM
+       { "l <size>\0Flight log size in kB",
+         ao_config_log_set,            ao_config_log_show },
+#endif
+#if HAS_IGNITE
+       { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode",
+         ao_config_ignite_mode_set,    ao_config_ignite_mode_show },
+#endif
+#if HAS_ACCEL
+       { "o <0 antenna up, 1 antenna down>\0Set pad orientation",
+         ao_config_pad_orientation_set,ao_config_pad_orientation_show },
+#endif
+       { "s\0Show",
+         ao_config_show,               0 },
+#if HAS_EEPROM
+       { "w\0Write to eeprom",
+         ao_config_write,              0 },
+#endif
+       { "?\0Help",
+         ao_config_help,               0 },
+       { 0, 0, 0 }
+};
+
+void
+ao_config_set(void)
+{
+       char    c;
+       uint8_t cmd;
+       void (*__xdata func)(void) __reentrant;
+
+       ao_cmd_white();
+       c = ao_cmd_lex_c;
+       ao_cmd_lex();
+       func = 0;
+       for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
+               if (ao_config_vars[cmd].str[0] == c) {
+                       (*ao_config_vars[cmd].set)();
+                       return;
+               }
+       ao_cmd_status = ao_cmd_syntax_error;
+}
+
+static void
+ao_config_help(void) __reentrant
+{
+       uint8_t cmd;
+       for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
+               printf("%-20s %s\n",
+                      ao_config_vars[cmd].str,
+                      ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str));
+}
+
+static void
+ao_config_show(void) __reentrant
+{
+       uint8_t cmd;
+       printf("Config version: %d.%d\n",
+              ao_config.major, ao_config.minor);
+       for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++)
+               if (ao_config_vars[cmd].show)
+                       (*ao_config_vars[cmd].show)();
+}
+
+#if HAS_EEPROM
+static void
+ao_config_write(void) __reentrant
+{
+       uint8_t saved = 0;
+       ao_mutex_get(&ao_config_mutex);
+       if (ao_config_dirty) {
+               _ao_config_put();
+               ao_config_dirty = 0;
+               saved = 1;
+       }
+       ao_mutex_put(&ao_config_mutex);
+       if (saved)
+               puts("Saved");
+       else
+               puts("Nothing to save");
+}
+#endif
+
+__code struct ao_cmds ao_config_cmds[] = {
+       { ao_config_set,        "c <var> <value>\0Set config variable (? for help, s to show)" },
+       { 0, NULL },
+};
+
+void
+ao_config_init(void)
+{
+       ao_cmd_register(&ao_config_cmds[0]);
+}
diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c
new file mode 100644 (file)
index 0000000..0969f10
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST)
+#include "ao.h"
+#endif
+
+static const int16_t altitude_table[] = {
+#include "altitude.h"
+};
+
+#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
+#define ALT_FRAC_MASK  (ALT_FRAC_SCALE - 1)
+
+int16_t
+ao_pres_to_altitude(int16_t pres) __reentrant
+{
+       uint8_t o;
+       int16_t part;
+
+       if (pres < 0)
+               pres = 0;
+       o = pres >> ALT_FRAC_BITS;
+       part = pres & ALT_FRAC_MASK;
+
+       return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) +
+               (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS;
+}
+
+int16_t
+ao_altitude_to_pres(int16_t alt) __reentrant
+{
+       int16_t span, sub_span;
+       uint8_t l, h, m;
+       int32_t pres;
+
+       l = 0;
+       h = NALT - 1;
+       while ((h - l) != 1) {
+               m = (l + h) >> 1;
+               if (altitude_table[m] < alt)
+                       h = m;
+               else
+                       l = m;
+       }
+       span = altitude_table[l] - altitude_table[h];
+       sub_span = altitude_table[l] - alt;
+       pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span;
+       if (pres > 32767)
+               pres = 32767;
+       if (pres < 0)
+               pres = 0;
+       return (int16_t) pres;
+}
+
+int16_t
+ao_temp_to_dC(int16_t temp) __reentrant
+{
+       int16_t ret;
+
+       /* Output voltage at 0°C = 0.755V
+        * Coefficient = 0.00247V/°C
+        * Reference voltage = 1.25V
+        *
+        * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
+        *      = (value - 19791.268) / 32768 * 1.25 / 0.00247
+        *      ≃ (value - 19791) * 1012 / 65536
+        */
+       ret = ((temp - 19791) * 1012L) >> 16;
+       return ret;
+}
diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c
new file mode 100644 (file)
index 0000000..e2c28b7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdint.h>
+#define AO_CONVERT_TEST
+#include "ao_host.h"
+#include "ao_convert.c"
+
+#define STEP   1
+
+static inline i_abs(int i) { return i < 0 ? -i : i; }
+
+main ()
+{
+       int     i;
+       int16_t p_to_a, p_to_a_to_p;
+       int16_t a_to_p, a_to_p_to_a;
+       int max_p_error = 0, max_p_error_p = -1;
+       int max_a_error = 0, max_a_error_a = -1;
+       int p_error;
+       int a_error;
+       int ret = 0;
+
+       for (i = 0; i < 32767 + STEP; i += STEP) {
+               if (i > 32767)
+                       i = 32767;
+               p_to_a = ao_pres_to_altitude(i);
+               p_to_a_to_p = ao_altitude_to_pres(p_to_a);
+               p_error = i_abs(p_to_a_to_p - i);
+               if (p_error > max_p_error) {
+                       max_p_error = p_error;
+                       max_p_error_p = i;
+               }
+//             printf ("pres %d alt %d pres %d\n",
+//                     i, p_to_a, p_to_a_to_p);
+       }
+       for (i = -1578; i < 15835 + STEP; i += STEP) {
+               if (i > 15835)
+                       i = 15835;
+               a_to_p = ao_altitude_to_pres(i);
+               a_to_p_to_a = ao_pres_to_altitude(a_to_p);
+               a_error = i_abs(a_to_p_to_a - i);
+               if (a_error > max_a_error) {
+                       max_a_error = a_error;
+                       max_a_error_a = i;
+               }
+//             printf ("alt %d pres %d alt %d\n",
+//                     i, a_to_p, a_to_p_to_a);
+       }
+       if (max_p_error > 2) {
+               printf ("max p error %d at %d\n", max_p_error,
+                       max_p_error_p);
+               ret++;
+       }
+       if (max_a_error > 1) {
+               printf ("max a error %d at %d\n", max_a_error,
+                       max_a_error_a);
+               ret++;
+       }
+       return ret;
+}
diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c
new file mode 100644 (file)
index 0000000..b0c1d61
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/*
+ * For hardware without eeprom, the config code still
+ * wants to call these functions
+ */
+uint8_t
+ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
+{
+       (void) buf;
+       (void) len;
+       return 1;
+}
+
+uint8_t
+ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
+{
+       memset(buf, '\0', len);
+       return 1;
+}
diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c
new file mode 100644 (file)
index 0000000..85c1825
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef AO_FLIGHT_TEST
+#include "ao.h"
+#endif
+
+#ifndef HAS_ACCEL
+#error Please define HAS_ACCEL
+#endif
+
+#ifndef HAS_GPS
+#error Please define HAS_GPS
+#endif
+
+#ifndef HAS_USB
+#error Please define HAS_USB
+#endif
+
+/* Main flight thread. */
+
+__pdata enum ao_flight_state   ao_flight_state;        /* current flight state */
+__pdata uint16_t               ao_launch_tick;         /* time of launch detect */
+
+/*
+ * track min/max data over a long interval to detect
+ * resting
+ */
+__pdata uint16_t               ao_interval_end;
+__pdata int16_t                        ao_interval_min_height;
+__pdata int16_t                        ao_interval_max_height;
+__pdata uint8_t                        ao_flight_force_idle;
+
+/* We also have a clock, which can be used to sanity check things in
+ * case of other failures
+ */
+
+#define BOOST_TICKS_MAX        AO_SEC_TO_TICKS(15)
+
+/* Landing is detected by getting constant readings from both pressure and accelerometer
+ * for a fairly long time (AO_INTERVAL_TICKS)
+ */
+#define AO_INTERVAL_TICKS      AO_SEC_TO_TICKS(10)
+
+#define abs(a) ((a) < 0 ? -(a) : (a))
+
+void
+ao_flight(void)
+{
+       ao_sample_init();
+       ao_flight_state = ao_flight_startup;
+       for (;;) {
+
+               /*
+                * Process ADC samples, just looping
+                * until the sensors are calibrated.
+                */
+               if (!ao_sample())
+                       continue;
+
+               switch (ao_flight_state) {
+               case ao_flight_startup:
+
+                       /* Check to see what mode we should go to.
+                        *  - Invalid mode if accel cal appears to be out
+                        *  - pad mode if we're upright,
+                        *  - idle mode otherwise
+                        */
+#if HAS_ACCEL
+                       if (ao_config.accel_plus_g == 0 ||
+                           ao_config.accel_minus_g == 0 ||
+                           ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
+                           ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP)
+                       {
+                               /* Detected an accel value outside -1.5g to 1.5g
+                                * (or uncalibrated values), so we go into invalid mode
+                                */
+                               ao_flight_state = ao_flight_invalid;
+
+                       } else
+#endif
+                               if (!ao_flight_force_idle
+#if HAS_ACCEL
+                                   && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP
+#endif
+                                       )
+                       {
+                               /* Set pad mode - we can fly! */
+                               ao_flight_state = ao_flight_pad;
+#if HAS_USB
+                               /* Disable the USB controller in flight mode
+                                * to save power
+                                */
+                               ao_usb_disable();
+#endif
+
+                               /* Disable packet mode in pad state */
+                               ao_packet_slave_stop();
+
+                               /* Turn on telemetry system */
+                               ao_rdf_set(1);
+                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
+
+                               /* signal successful initialization by turning off the LED */
+                               ao_led_off(AO_LED_RED);
+                       } else {
+                               /* Set idle mode */
+                               ao_flight_state = ao_flight_idle;
+                               /* signal successful initialization by turning off the LED */
+                               ao_led_off(AO_LED_RED);
+                       }
+                       /* wakeup threads due to state change */
+                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+
+                       break;
+               case ao_flight_pad:
+
+                       /* pad to boost:
+                        *
+                        * barometer: > 20m vertical motion
+                        *             OR
+                        * accelerometer: > 2g AND velocity > 5m/s
+                        *
+                        * The accelerometer should always detect motion before
+                        * the barometer, but we use both to make sure this
+                        * transition is detected. If the device
+                        * doesn't have an accelerometer, then ignore the
+                        * speed and acceleration as they are quite noisy
+                        * on the pad.
+                        */
+                       if (ao_height > AO_M_TO_HEIGHT(20)
+#if HAS_ACCEL
+                           || (ao_accel > AO_MSS_TO_ACCEL(20) &&
+                               ao_speed > AO_MS_TO_SPEED(5))
+#endif
+                               )
+                       {
+                               ao_flight_state = ao_flight_boost;
+                               ao_launch_tick = ao_sample_tick;
+
+                               /* start logging data */
+                               ao_log_start();
+
+                               /* Increase telemetry rate */
+                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);
+
+                               /* disable RDF beacon */
+                               ao_rdf_set(0);
+
+#if HAS_GPS
+                               /* Record current GPS position by waking up GPS log tasks */
+                               ao_wakeup(&ao_gps_data);
+                               ao_wakeup(&ao_gps_tracking_data);
+#endif
+
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       }
+                       break;
+               case ao_flight_boost:
+
+                       /* boost to fast:
+                        *
+                        * accelerometer: start to fall at > 1/4 G
+                        *              OR
+                        * time: boost for more than 15 seconds
+                        *
+                        * Detects motor burn out by the switch from acceleration to
+                        * deceleration, or by waiting until the maximum burn duration
+                        * (15 seconds) has past.
+                        */
+                       if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) ||
+                           (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX)
+                       {
+#if HAS_ACCEL
+                               ao_flight_state = ao_flight_fast;
+#else
+                               ao_flight_state = ao_flight_coast;
+#endif
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       }
+                       break;
+#if HAS_ACCEL
+               case ao_flight_fast:
+                       /*
+                        * This is essentially the same as coast,
+                        * but the barometer is being ignored as
+                        * it may be unreliable.
+                        */
+                       if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED))
+                       {
+                               ao_flight_state = ao_flight_coast;
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       }
+                       break;
+#endif
+               case ao_flight_coast:
+
+                       /* apogee detect: coast to drogue deploy:
+                        *
+                        * speed: < 0
+                        *
+                        * Also make sure the model altitude is tracking
+                        * the measured altitude reasonably closely; otherwise
+                        * we're probably transsonic.
+                        */
+                       if (ao_speed < 0
+#if !HAS_ACCEL
+                           && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)
+#endif
+                               )
+                       {
+                               /* ignite the drogue charge */
+                               ao_ignite(ao_igniter_drogue);
+
+                               /* slow down the telemetry system */
+                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
+
+                               /* Turn the RDF beacon back on */
+                               ao_rdf_set(1);
+
+                               /* and enter drogue state */
+                               ao_flight_state = ao_flight_drogue;
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       }
+
+                       break;
+               case ao_flight_drogue:
+
+                       /* drogue to main deploy:
+                        *
+                        * barometer: reach main deploy altitude
+                        *
+                        * Would like to use the accelerometer for this test, but
+                        * the orientation of the flight computer is unknown after
+                        * drogue deploy, so we ignore it. Could also detect
+                        * high descent rate using the pressure sensor to
+                        * recognize drogue deploy failure and eject the main
+                        * at that point. Perhaps also use the drogue sense lines
+                        * to notice continutity?
+                        */
+                       if (ao_height <= ao_config.main_deploy)
+                       {
+                               ao_ignite(ao_igniter_main);
+
+                               /*
+                                * Start recording min/max height
+                                * to figure out when the rocket has landed
+                                */
+
+                               /* initialize interval values */
+                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
+
+                               ao_interval_min_height = ao_interval_max_height = ao_avg_height;
+
+                               ao_flight_state = ao_flight_main;
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       }
+                       break;
+
+                       /* fall through... */
+               case ao_flight_main:
+
+                       /* main to land:
+                        *
+                        * barometer: altitude stable
+                        */
+
+                       if (ao_avg_height < ao_interval_min_height)
+                               ao_interval_min_height = ao_avg_height;
+                       if (ao_avg_height > ao_interval_max_height)
+                               ao_interval_max_height = ao_avg_height;
+
+                       if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
+                               if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4))
+                               {
+                                       ao_flight_state = ao_flight_landed;
+
+                                       /* turn off the ADC capture */
+                                       ao_timer_set_adc_interval(0);
+
+                                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                               }
+                               ao_interval_min_height = ao_interval_max_height = ao_avg_height;
+                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
+                       }
+                       break;
+               case ao_flight_landed:
+                       break;
+               }
+       }
+}
+
+static __xdata struct ao_task  flight_task;
+
+void
+ao_flight_init(void)
+{
+       ao_flight_state = ao_flight_startup;
+       ao_add_task(&flight_task, ao_flight, "flight");
+}
diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c
new file mode 100644 (file)
index 0000000..2e332b1
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/* Main flight thread. */
+
+__pdata enum ao_flight_state   ao_flight_state;        /* current flight state */
+__pdata uint16_t               ao_launch_tick;         /* time of launch detect */
+
+/*
+ * track min/max data over a long interval to detect
+ * resting
+ */
+__pdata uint16_t               ao_interval_end;
+__pdata int16_t                        ao_interval_min_height;
+__pdata int16_t                        ao_interval_max_height;
+
+__pdata uint8_t                        ao_flight_force_idle;
+
+/* Landing is detected by getting constant readings from both pressure and accelerometer
+ * for a fairly long time (AO_INTERVAL_TICKS)
+ */
+#define AO_INTERVAL_TICKS      AO_SEC_TO_TICKS(5)
+
+static void
+ao_flight_nano(void)
+{
+       ao_sample_init();
+       ao_flight_state = ao_flight_startup;
+
+       for (;;) {
+               /*
+                * Process ADC samples, just looping
+                * until the sensors are calibrated.
+                */
+               if (!ao_sample())
+                       continue;
+
+               switch (ao_flight_state) {
+               case ao_flight_startup:
+                       if (ao_flight_force_idle) {
+                               /* Set idle mode */
+                               ao_flight_state = ao_flight_idle;
+                       } else {
+                               ao_flight_state = ao_flight_pad;
+                               /* Disable packet mode in pad state */
+                               ao_packet_slave_stop();
+
+                               /* Turn on telemetry system */
+                               ao_rdf_set(1);
+                               ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
+                       }
+                       /* signal successful initialization by turning off the LED */
+                       ao_led_off(AO_LED_RED);
+
+                       /* wakeup threads due to state change */
+                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       break;
+               case ao_flight_pad:
+                       if (ao_height> AO_M_TO_HEIGHT(20)) {
+                               ao_flight_state = ao_flight_drogue;
+                               ao_launch_tick = ao_sample_tick;
+
+                               /* start logging data */
+                               ao_log_start();
+
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                       }
+                       break;
+               case ao_flight_drogue:
+                       /* drogue/main to land:
+                        *
+                        * barometer: altitude stable
+                        */
+
+                       if (ao_height < ao_interval_min_height)
+                               ao_interval_min_height = ao_height;
+                       if (ao_height > ao_interval_max_height)
+                               ao_interval_max_height = ao_height;
+
+                       if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) {
+                               if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5))
+                               {
+                                       ao_flight_state = ao_flight_landed;
+
+                                       /* turn off the ADC capture */
+                                       ao_timer_set_adc_interval(0);
+                                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+                               }
+                               ao_interval_min_height = ao_interval_max_height = ao_height;
+                               ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS;
+                       }
+                       break;
+               }
+       }
+}
+
+static __xdata struct ao_task  flight_task;
+
+void
+ao_flight_nano_init(void)
+{
+       ao_flight_state = ao_flight_startup;
+       ao_add_task(&flight_task, ao_flight_nano, "flight");
+}
diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c
new file mode 100644 (file)
index 0000000..fcdedd3
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef AO_GPS_TEST
+#include "ao.h"
+#endif
+#include "ao_telem.h"
+
+void
+ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant
+{
+       char    state;
+
+       if (gps_data->flags & AO_GPS_VALID)
+               state = AO_TELEM_GPS_STATE_LOCKED;
+       else if (gps_data->flags & AO_GPS_RUNNING)
+               state = AO_TELEM_GPS_STATE_UNLOCKED;
+       else
+               state = AO_TELEM_GPS_STATE_ERROR;
+       printf(AO_TELEM_GPS_STATE " %c "
+              AO_TELEM_GPS_NUM_SAT " %d ",
+              state,
+              (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
+       if (!(gps_data->flags & AO_GPS_VALID))
+               return;
+       printf(AO_TELEM_GPS_LATITUDE " %ld "
+              AO_TELEM_GPS_LONGITUDE " %ld "
+              AO_TELEM_GPS_ALTITUDE " %d ",
+              gps_data->latitude,
+              gps_data->longitude,
+              gps_data->altitude);
+
+       if (gps_data->flags & AO_GPS_DATE_VALID)
+               printf(AO_TELEM_GPS_YEAR " %d "
+                      AO_TELEM_GPS_MONTH " %d "
+                      AO_TELEM_GPS_DAY " %d ",
+                      gps_data->year,
+                      gps_data->month,
+                      gps_data->day);
+
+       printf(AO_TELEM_GPS_HOUR " %d "
+              AO_TELEM_GPS_MINUTE " %d "
+              AO_TELEM_GPS_SECOND " %d ",
+              gps_data->hour,
+              gps_data->minute,
+              gps_data->second);
+
+       printf(AO_TELEM_GPS_HDOP " %d ",
+              gps_data->hdop * 2);
+
+       if (gps_data->flags & AO_GPS_COURSE_VALID) {
+               printf(AO_TELEM_GPS_HERROR " %d "
+                      AO_TELEM_GPS_VERROR " %d "
+                      AO_TELEM_GPS_VERTICAL_SPEED " %d "
+                      AO_TELEM_GPS_HORIZONTAL_SPEED " %d "
+                      AO_TELEM_GPS_COURSE " %d ",
+                      gps_data->h_error,
+                      gps_data->v_error,
+                      gps_data->climb_rate,
+                      gps_data->ground_speed,
+                      (int) gps_data->course * 2);
+       }
+}
+
+void
+ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant
+{
+       uint8_t c, n, v;
+       __xdata struct ao_gps_sat_orig  *sat;
+
+       n = gps_tracking_data->channels;
+       if (n == 0)
+               return;
+
+       sat = gps_tracking_data->sats;
+       v = 0;
+       for (c = 0; c < n; c++) {
+               if (sat->svid)
+                       v++;
+               sat++;
+       }
+
+       printf (AO_TELEM_SAT_NUM " %d ",
+               v);
+
+       sat = gps_tracking_data->sats;
+       v = 0;
+       for (c = 0; c < n; c++) {
+               if (sat->svid) {
+                       printf (AO_TELEM_SAT_SVID "%d %d "
+                               AO_TELEM_SAT_C_N_0 "%d %d ",
+                               v, sat->svid,
+                               v, sat->c_n_1);
+                       v++;
+               }
+               sat++;
+       }
+}
diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c
new file mode 100644 (file)
index 0000000..e57f874
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+ao_gps_report(void)
+{
+       static __xdata struct ao_log_record             gps_log;
+       static __xdata struct ao_telemetry_location     gps_data;
+       uint8_t date_reported = 0;
+
+       for (;;) {
+               ao_sleep(&ao_gps_data);
+               ao_mutex_get(&ao_gps_mutex);
+               memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data));
+               ao_mutex_put(&ao_gps_mutex);
+
+               if (!(gps_data.flags & AO_GPS_VALID))
+                       continue;
+
+               gps_log.tick = ao_gps_tick;
+               gps_log.type = AO_LOG_GPS_TIME;
+               gps_log.u.gps_time.hour = gps_data.hour;
+               gps_log.u.gps_time.minute = gps_data.minute;
+               gps_log.u.gps_time.second = gps_data.second;
+               gps_log.u.gps_time.flags = gps_data.flags;
+               ao_log_data(&gps_log);
+               gps_log.type = AO_LOG_GPS_LAT;
+               gps_log.u.gps_latitude = gps_data.latitude;
+               ao_log_data(&gps_log);
+               gps_log.type = AO_LOG_GPS_LON;
+               gps_log.u.gps_longitude = gps_data.longitude;
+               ao_log_data(&gps_log);
+               gps_log.type = AO_LOG_GPS_ALT;
+               gps_log.u.gps_altitude.altitude = gps_data.altitude;
+               gps_log.u.gps_altitude.unused = 0xffff;
+               ao_log_data(&gps_log);
+               if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {
+                       gps_log.type = AO_LOG_GPS_DATE;
+                       gps_log.u.gps_date.year = gps_data.year;
+                       gps_log.u.gps_date.month = gps_data.month;
+                       gps_log.u.gps_date.day = gps_data.day;
+                       gps_log.u.gps_date.extra = 0;
+                       date_reported = ao_log_data(&gps_log);
+               }
+       }
+}
+
+void
+ao_gps_tracking_report(void)
+{
+       static __xdata struct ao_log_record             gps_log;
+       static __xdata struct ao_telemetry_satellite    gps_tracking_data;
+       uint8_t c, n;
+
+       for (;;) {
+               ao_sleep(&ao_gps_tracking_data);
+               ao_mutex_get(&ao_gps_mutex);
+               gps_log.tick = ao_gps_tick;
+               memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data));
+               ao_mutex_put(&ao_gps_mutex);
+
+               if (!(n = gps_tracking_data.channels))
+                       continue;
+
+               gps_log.type = AO_LOG_GPS_SAT;
+               for (c = 0; c < n; c++)
+                       if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid))
+                       {
+                               gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1;
+                               ao_log_data(&gps_log);
+                       }
+       }
+}
+
+__xdata struct ao_task ao_gps_report_task;
+__xdata struct ao_task ao_gps_tracking_report_task;
+
+void
+ao_gps_report_init(void)
+{
+       ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report");
+       ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report");
+}
diff --git a/src/core/ao_host.h b/src/core/ao_host.h
new file mode 100644 (file)
index 0000000..65c25fe
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define _GNU_SOURCE
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define AO_ADC_RING    64
+#define ao_adc_ring_next(n)    (((n) + 1) & (AO_ADC_RING - 1))
+#define ao_adc_ring_prev(n)    (((n) - 1) & (AO_ADC_RING - 1))
+
+/*
+ * One set of samples read from the A/D converter
+ */
+struct ao_adc {
+       uint16_t        tick;           /* tick when the sample was read */
+       int16_t         accel;          /* accelerometer */
+       int16_t         pres;           /* pressure sensor */
+       int16_t         temp;           /* temperature sensor */
+       int16_t         v_batt;         /* battery voltage */
+       int16_t         sense_d;        /* drogue continuity sense */
+       int16_t         sense_m;        /* main continuity sense */
+};
+
+#define __pdata
+#define __data
+#define __xdata
+#define __code
+#define __reentrant
+
+enum ao_flight_state {
+       ao_flight_startup = 0,
+       ao_flight_idle = 1,
+       ao_flight_pad = 2,
+       ao_flight_boost = 3,
+       ao_flight_fast = 4,
+       ao_flight_coast = 5,
+       ao_flight_drogue = 6,
+       ao_flight_main = 7,
+       ao_flight_landed = 8,
+       ao_flight_invalid = 9
+};
+
+struct ao_adc ao_adc_ring[AO_ADC_RING];
+uint8_t ao_adc_head;
+
+#define ao_led_on(l)
+#define ao_led_off(l)
+#define ao_timer_set_adc_interval(i)
+#define ao_wakeup(wchan) ao_dump_state(wchan)
+#define ao_cmd_register(c)
+#define ao_usb_disable()
+#define ao_telemetry_set_interval(x)
+#define ao_delay(x)
+
+enum ao_igniter {
+       ao_igniter_drogue = 0,
+       ao_igniter_main = 1
+};
+
+void
+ao_ignite(enum ao_igniter igniter)
+{
+       printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main");
+}
+
+struct ao_task {
+       int dummy;
+};
+
+#define ao_add_task(t,f,n)
+
+#define ao_log_start()
+#define ao_log_stop()
+
+#define AO_MS_TO_TICKS(ms)     ((ms) / 10)
+#define AO_SEC_TO_TICKS(s)     ((s) * 100)
+
+#define AO_FLIGHT_TEST
+
+struct ao_adc ao_adc_static;
+
+FILE *emulator_in;
+
+void
+ao_dump_state(void *wchan);
+
+void
+ao_sleep(void *wchan);
+
+const char const * const ao_state_names[] = {
+       "startup", "idle", "pad", "boost", "fast",
+       "coast", "drogue", "main", "landed", "invalid"
+};
+
+struct ao_cmds {
+       void            (*func)(void);
+       const char      *help;
+};
+
+
+struct ao_config {
+       uint16_t        main_deploy;
+       int16_t         accel_zero_g;
+};
+
+#define ao_config_get()
+
+struct ao_config ao_config = { 250, 16000 };
diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c
new file mode 100644 (file)
index 0000000..ee01949
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef AO_FLIGHT_TEST
+#include "ao.h"
+#endif
+
+#include "ao_kalman.h"
+
+static __pdata int32_t         ao_k_height;
+static __pdata int32_t         ao_k_speed;
+static __pdata int32_t         ao_k_accel;
+
+#define AO_K_STEP_100          to_fix16(0.01)
+#define AO_K_STEP_2_2_100      to_fix16(0.00005)
+
+#define AO_K_STEP_10           to_fix16(0.1)
+#define AO_K_STEP_2_2_10       to_fix16(0.005)
+
+#define AO_K_STEP_1            to_fix16(1)
+#define AO_K_STEP_2_2_1                to_fix16(0.5)
+
+__pdata int16_t                        ao_height;
+__pdata int16_t                        ao_speed;
+__pdata int16_t                        ao_accel;
+__pdata int16_t                        ao_max_height;
+static __pdata int32_t         ao_avg_height_scaled;
+__pdata int16_t                        ao_avg_height;
+
+__pdata int16_t                        ao_error_h;
+__pdata int16_t                        ao_error_h_sq_avg;
+
+#if HAS_ACCEL
+__pdata int16_t                        ao_error_a;
+#endif
+
+static void
+ao_kalman_predict(void)
+{
+#ifdef AO_FLIGHT_TEST
+       if (ao_sample_tick - ao_sample_prev_tick > 50) {
+               ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 +
+                               (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4;
+               ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1;
+
+               return;
+       }
+       if (ao_sample_tick - ao_sample_prev_tick > 5) {
+               ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 +
+                               (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4;
+               ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10;
+
+               return;
+       }
+       if (ao_flight_debug) {
+               printf ("predict speed %g + (%g * %g) = %g\n",
+                       ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0,
+                       (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));
+       }
+#endif
+       ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 +
+                       (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4;
+       ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100;
+}
+
+static void
+ao_kalman_err_height(void)
+{
+       int16_t e;
+       int16_t height_distrust;
+#if HAS_ACCEL
+       int16_t speed_distrust;
+#endif
+
+       ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16);
+
+       e = ao_error_h;
+       if (e < 0)
+               e = -e;
+       if (e > 127)
+               e = 127;
+#if HAS_ACCEL
+       ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2;
+       ao_error_h_sq_avg += (e * e) >> 2;
+#else
+       ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4;
+       ao_error_h_sq_avg += (e * e) >> 4;
+#endif
+
+       if (ao_flight_state >= ao_flight_drogue)
+               return;
+       height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT;
+#if HAS_ACCEL
+       /* speed is stored * 16, but we need to ramp between 200 and 328, so
+        * we want to multiply by 2. The result is a shift by 3.
+        */
+       speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1);
+       if (speed_distrust <= 0)
+               speed_distrust = 0;
+       else if (speed_distrust > height_distrust)
+               height_distrust = speed_distrust;
+#endif
+       if (height_distrust > 0) {
+#ifdef AO_FLIGHT_TEST
+               int     old_ao_error_h = ao_error_h;
+#endif
+               if (height_distrust > 0x100)
+                       height_distrust = 0x100;
+               ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8);
+#ifdef AO_FLIGHT_TEST
+               if (ao_flight_debug) {
+                       printf("over height %g over speed %g distrust: %g height: error %d -> %d\n",
+                              (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT),
+                              (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0,
+                              height_distrust / 256.0,
+                              old_ao_error_h, ao_error_h);
+               }
+#endif
+       }
+}
+
+static void
+ao_kalman_correct_baro(void)
+{
+       ao_kalman_err_height();
+#ifdef AO_FLIGHT_TEST
+       if (ao_sample_tick - ao_sample_prev_tick > 50) {
+               ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h;
+               ao_k_speed  += (int32_t) AO_BARO_K1_1 * ao_error_h;
+               ao_k_accel  += (int32_t) AO_BARO_K2_1 * ao_error_h;
+               return;
+       }
+       if (ao_sample_tick - ao_sample_prev_tick > 5) {
+               ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h;
+               ao_k_speed  += (int32_t) AO_BARO_K1_10 * ao_error_h;
+               ao_k_accel  += (int32_t) AO_BARO_K2_10 * ao_error_h;
+               return;
+       }
+#endif
+       ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h;
+       ao_k_speed  += (int32_t) AO_BARO_K1_100 * ao_error_h;
+       ao_k_accel  += (int32_t) AO_BARO_K2_100 * ao_error_h;
+}
+
+#if HAS_ACCEL
+
+static void
+ao_kalman_err_accel(void)
+{
+       int32_t accel;
+
+       accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale;
+
+       /* Can't use ao_accel here as it is the pre-prediction value still */
+       ao_error_a = (accel - ao_k_accel) >> 16;
+}
+
+static void
+ao_kalman_correct_both(void)
+{
+       ao_kalman_err_height();
+       ao_kalman_err_accel();
+
+#ifdef AO_FLIGHT_TEST
+       if (ao_sample_tick - ao_sample_prev_tick > 50) {
+               if (ao_flight_debug) {
+                       printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
+                               ao_k_speed / (65536.0 * 16.0),
+                               (double) ao_error_h, AO_BOTH_K10_1 / 65536.0,
+                               (double) ao_error_a, AO_BOTH_K11_1 / 65536.0,
+                               (ao_k_speed +
+                                (int32_t) AO_BOTH_K10_1 * ao_error_h +
+                                (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));
+               }
+               ao_k_height +=
+                       (int32_t) AO_BOTH_K00_1 * ao_error_h +
+                       (int32_t) AO_BOTH_K01_1 * ao_error_a;
+               ao_k_speed +=
+                       (int32_t) AO_BOTH_K10_1 * ao_error_h +
+                       (int32_t) AO_BOTH_K11_1 * ao_error_a;
+               ao_k_accel +=
+                       (int32_t) AO_BOTH_K20_1 * ao_error_h +
+                       (int32_t) AO_BOTH_K21_1 * ao_error_a;
+               return;
+       }
+       if (ao_sample_tick - ao_sample_prev_tick > 5) {
+               if (ao_flight_debug) {
+                       printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
+                               ao_k_speed / (65536.0 * 16.0),
+                               (double) ao_error_h, AO_BOTH_K10_10 / 65536.0,
+                               (double) ao_error_a, AO_BOTH_K11_10 / 65536.0,
+                               (ao_k_speed +
+                                (int32_t) AO_BOTH_K10_10 * ao_error_h +
+                                (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));
+               }
+               ao_k_height +=
+                       (int32_t) AO_BOTH_K00_10 * ao_error_h +
+                       (int32_t) AO_BOTH_K01_10 * ao_error_a;
+               ao_k_speed +=
+                       (int32_t) AO_BOTH_K10_10 * ao_error_h +
+                       (int32_t) AO_BOTH_K11_10 * ao_error_a;
+               ao_k_accel +=
+                       (int32_t) AO_BOTH_K20_10 * ao_error_h +
+                       (int32_t) AO_BOTH_K21_10 * ao_error_a;
+               return;
+       }
+       if (ao_flight_debug) {
+               printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n",
+                       ao_k_speed / (65536.0 * 16.0),
+                       (double) ao_error_h, AO_BOTH_K10_100 / 65536.0,
+                       (double) ao_error_a, AO_BOTH_K11_100 / 65536.0,
+                       (ao_k_speed +
+                        (int32_t) AO_BOTH_K10_100 * ao_error_h +
+                        (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));
+       }
+#endif
+       ao_k_height +=
+               (int32_t) AO_BOTH_K00_100 * ao_error_h +
+               (int32_t) AO_BOTH_K01_100 * ao_error_a;
+       ao_k_speed +=
+               (int32_t) AO_BOTH_K10_100 * ao_error_h +
+               (int32_t) AO_BOTH_K11_100 * ao_error_a;
+       ao_k_accel +=
+               (int32_t) AO_BOTH_K20_100 * ao_error_h +
+               (int32_t) AO_BOTH_K21_100 * ao_error_a;
+}
+
+#ifdef FORCE_ACCEL
+static void
+ao_kalman_correct_accel(void)
+{
+       ao_kalman_err_accel();
+
+       if (ao_sample_tick - ao_sample_prev_tick > 5) {
+               ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a;
+               ao_k_speed  += (int32_t) AO_ACCEL_K1_10 * ao_error_a;
+               ao_k_accel  += (int32_t) AO_ACCEL_K2_10 * ao_error_a;
+               return;
+       }
+       ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a;
+       ao_k_speed  += (int32_t) AO_ACCEL_K1_100 * ao_error_a;
+       ao_k_accel  += (int32_t) AO_ACCEL_K2_100 * ao_error_a;
+}
+#endif
+#endif /* HAS_ACCEL */
+
+void
+ao_kalman(void)
+{
+       ao_kalman_predict();
+#if HAS_ACCEL
+       if (ao_flight_state <= ao_flight_coast) {
+#ifdef FORCE_ACCEL
+               ao_kalman_correct_accel();
+#else
+               ao_kalman_correct_both();
+#endif
+       } else
+#endif
+               ao_kalman_correct_baro();
+       ao_height = from_fix(ao_k_height);
+       ao_speed = from_fix(ao_k_speed);
+       ao_accel = from_fix(ao_k_accel);
+       if (ao_height > ao_max_height)
+               ao_max_height = ao_height;
+       ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height;
+#ifdef AO_FLIGHT_TEST
+       if (ao_sample_tick - ao_sample_prev_tick > 50)
+               ao_avg_height = (ao_avg_height_scaled + 1) >> 1;
+       else if (ao_sample_tick - ao_sample_prev_tick > 5)
+               ao_avg_height = (ao_avg_height_scaled + 7) >> 4;
+       else 
+#endif
+               ao_avg_height = (ao_avg_height_scaled + 63) >> 7;
+#ifdef AO_FLIGHT_TEST
+       ao_sample_prev_tick = ao_sample_tick;
+#endif
+}
diff --git a/src/core/ao_log.c b/src/core/ao_log.c
new file mode 100644 (file)
index 0000000..6d3ad53
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__pdata uint32_t ao_log_current_pos;
+__pdata uint32_t ao_log_end_pos;
+__pdata uint32_t ao_log_start_pos;
+__xdata uint8_t        ao_log_running;
+__pdata enum flight_state ao_log_state;
+__xdata uint16_t ao_flight_number;
+
+__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL;
+
+void
+ao_log_flush(void)
+{
+       ao_storage_flush();
+}
+
+/*
+ * When erasing a flight log, make sure the config block
+ * has an up-to-date version of the current flight number
+ */
+
+struct ao_log_erase {
+       uint8_t unused;
+       uint16_t flight;
+};
+
+static __xdata struct ao_log_erase erase;
+
+#define LOG_MAX_ERASE  16
+
+static uint32_t
+ao_log_erase_pos(uint8_t i)
+{
+       return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG;
+}
+
+void
+ao_log_write_erase(uint8_t pos)
+{
+       erase.unused = 0x00;
+       erase.flight = ao_flight_number;
+       ao_storage_write(ao_log_erase_pos(pos),  &erase, sizeof (erase));
+       ao_storage_flush();
+}
+
+static void
+ao_log_read_erase(uint8_t pos)
+{
+       ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase));
+}
+
+
+static void
+ao_log_erase_mark(void)
+{
+       uint8_t                         i;
+
+       for (i = 0; i < LOG_MAX_ERASE; i++) {
+               ao_log_read_erase(i);
+               if (erase.unused == 0 && erase.flight == ao_flight_number)
+                       return;
+               if (erase.unused == 0xff) {
+                       ao_log_write_erase(i);
+                       return;
+               }
+       }
+       ao_config_put();
+}
+
+static uint8_t
+ao_log_slots()
+{
+       return (uint8_t) (ao_storage_config / ao_config.flight_log_max);
+}
+
+uint32_t
+ao_log_pos(uint8_t slot)
+{
+       return ((slot) * ao_config.flight_log_max);
+}
+
+static uint16_t
+ao_log_max_flight(void)
+{
+       uint8_t         log_slot;
+       uint8_t         log_slots;
+       uint16_t        log_flight;
+       uint16_t        max_flight = 0;
+
+       /* Scan the log space looking for the biggest flight number */
+       log_slots = ao_log_slots();
+       for (log_slot = 0; log_slot < log_slots; log_slot++) {
+               log_flight = ao_log_flight(log_slot);
+               if (!log_flight)
+                       continue;
+               if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0)
+                       max_flight = log_flight;
+       }
+       return max_flight;
+}
+
+void
+ao_log_scan(void) __reentrant
+{
+       uint8_t         log_slot;
+       uint8_t         log_slots;
+       uint8_t         log_want;
+
+       ao_config_get();
+
+       ao_flight_number = ao_log_max_flight();
+       if (ao_flight_number)
+               if (++ao_flight_number == 0)
+                       ao_flight_number = 1;
+
+       /* Now look through the log of flight numbers from erase operations and
+        * see if the last one is bigger than what we found above
+        */
+       for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) {
+               ao_log_read_erase(log_slot);
+               if (erase.unused == 0) {
+                       if (ao_flight_number == 0 ||
+                           (int16_t) (erase.flight - ao_flight_number) > 0)
+                               ao_flight_number = erase.flight;
+                       break;
+               }
+       }
+       if (ao_flight_number == 0)
+               ao_flight_number = 1;
+
+       /* With a flight number in hand, find a place to write a new log,
+        * use the target flight number to index the available log slots so
+        * that we write logs to each spot about the same number of times.
+        */
+
+       /* Find a log slot for the next flight, if available */
+       ao_log_current_pos = ao_log_end_pos = 0;
+       log_slots = ao_log_slots();
+       log_want = (ao_flight_number - 1) % log_slots;
+       log_slot = log_want;
+       do {
+               if (ao_log_flight(log_slot) == 0) {
+                       ao_log_current_pos = ao_log_pos(log_slot);
+                       ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
+                       break;
+               }
+               if (++log_slot >= log_slots)
+                       log_slot = 0;
+       } while (log_slot != log_want);
+
+       ao_wakeup(&ao_flight_number);
+}
+
+void
+ao_log_start(void)
+{
+       /* start logging */
+       ao_log_running = 1;
+       ao_wakeup(&ao_log_running);
+}
+
+void
+ao_log_stop(void)
+{
+       ao_log_running = 0;
+       ao_log_flush();
+}
+
+uint8_t
+ao_log_present(void)
+{
+       return ao_log_max_flight() != 0;
+}
+
+uint8_t
+ao_log_full(void)
+{
+       return ao_log_current_pos == ao_log_end_pos;
+}
+
+static __xdata struct ao_task ao_log_task;
+
+void
+ao_log_list(void) __reentrant
+{
+       uint8_t slot;
+       uint8_t slots;
+       uint16_t flight;
+
+       slots = ao_log_slots();
+       for (slot = 0; slot < slots; slot++)
+       {
+               flight = ao_log_flight(slot);
+               if (flight)
+                       printf ("flight %d start %x end %x\n",
+                               flight,
+                               (uint16_t) (ao_log_pos(slot) >> 8),
+                               (uint16_t) (ao_log_pos(slot+1) >> 8));
+       }
+       printf ("done\n");
+}
+
+void
+ao_log_delete(void) __reentrant
+{
+       uint8_t slot;
+       uint8_t slots;
+
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+
+       slots = ao_log_slots();
+       /* Look for the flight log matching the requested flight */
+       if (ao_cmd_lex_i) {
+               for (slot = 0; slot < slots; slot++) {
+                       if (ao_log_flight(slot) == ao_cmd_lex_i) {
+                               ao_log_erase_mark();
+                               ao_log_current_pos = ao_log_pos(slot);
+                               ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max;
+                               while (ao_log_current_pos < ao_log_end_pos) {
+                                       uint8_t i;
+                                       static __xdata uint8_t b;
+
+                                       /*
+                                        * Check to see if we've reached the end of
+                                        * the used memory to avoid re-erasing the same
+                                        * memory over and over again
+                                        */
+                                       for (i = 0; i < 16; i++) {
+                                               if (ao_storage_read(ao_log_current_pos + i, &b, 1))
+                                                       if (b != 0xff)
+                                                               break;
+                                       }
+                                       if (i == 16)
+                                               break;
+                                       ao_storage_erase(ao_log_current_pos);
+                                       ao_log_current_pos += ao_storage_block;
+                               }
+                               puts("Erased");
+                               return;
+                       }
+               }
+       }
+       printf("No such flight: %d\n", ao_cmd_lex_i);
+}
+
+__code struct ao_cmds ao_log_cmds[] = {
+       { ao_log_list,  "l\0List flight logs" },
+       { ao_log_delete,        "d <flight-number>\0Delete flight" },
+       { 0,    NULL },
+};
+
+void
+ao_log_init(void)
+{
+       ao_log_running = 0;
+
+       /* For now, just log the flight starting at the begining of eeprom */
+       ao_log_state = ao_flight_invalid;
+
+       ao_cmd_register(&ao_log_cmds[0]);
+
+       /* Create a task to log events to eeprom */
+       ao_add_task(&ao_log_task, ao_log, "log");
+}
diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c
new file mode 100644 (file)
index 0000000..74d94c4
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+static __xdata uint8_t ao_log_mutex;
+static __xdata struct ao_log_record log;
+
+static uint8_t
+ao_log_csum(__xdata uint8_t *b) __reentrant
+{
+       uint8_t sum = 0x5a;
+       uint8_t i;
+
+       for (i = 0; i < sizeof (struct ao_log_record); i++)
+               sum += *b++;
+       return -sum;
+}
+
+uint8_t
+ao_log_data(__xdata struct ao_log_record *log) __reentrant
+{
+       uint8_t wrote = 0;
+       /* set checksum */
+       log->csum = 0;
+       log->csum = ao_log_csum((__xdata uint8_t *) log);
+       ao_mutex_get(&ao_log_mutex); {
+               if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
+                       ao_log_stop();
+               if (ao_log_running) {
+                       wrote = 1;
+                       ao_storage_write(ao_log_current_pos,
+                                        log,
+                                        sizeof (struct ao_log_record));
+                       ao_log_current_pos += sizeof (struct ao_log_record);
+               }
+       } ao_mutex_put(&ao_log_mutex);
+       return wrote;
+}
+
+static uint8_t
+ao_log_dump_check_data(void)
+{
+       if (ao_log_csum((uint8_t *) &log) != 0)
+               return 0;
+       return 1;
+}
+
+static __data uint8_t  ao_log_adc_pos;
+
+/* a hack to make sure that ao_log_records fill the eeprom block in even units */
+typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ;
+
+#define AO_SENSOR_INTERVAL_ASCENT      1
+#define AO_SENSOR_INTERVAL_DESCENT     10
+#define AO_OTHER_INTERVAL              32
+
+void
+ao_log(void)
+{
+       __pdata uint16_t        next_sensor, next_other;
+
+       ao_storage_setup();
+
+       ao_log_scan();
+
+       while (!ao_log_running)
+               ao_sleep(&ao_log_running);
+
+       log.type = AO_LOG_FLIGHT;
+       log.tick = ao_sample_tick;
+#if HAS_ACCEL
+       log.u.flight.ground_accel = ao_ground_accel;
+#endif
+       log.u.flight.flight = ao_flight_number;
+       ao_log_data(&log);
+
+       /* Write the whole contents of the ring to the log
+        * when starting up.
+        */
+       ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc);
+       next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick;
+       ao_log_state = ao_flight_startup;
+       for (;;) {
+               /* Write samples to EEPROM */
+               while (ao_log_adc_pos != ao_sample_adc) {
+                       log.tick = ao_adc_ring[ao_log_adc_pos].tick;
+                       if ((int16_t) (log.tick - next_sensor) >= 0) {
+                               log.type = AO_LOG_SENSOR;
+                               log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel;
+                               log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres;
+                               ao_log_data(&log);
+                               if (ao_log_state <= ao_flight_coast)
+                                       next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
+                               else
+                                       next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT;
+                       }
+                       if ((int16_t) (log.tick - next_other) >= 0) {
+                               log.type = AO_LOG_TEMP_VOLT;
+                               log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp;
+                               log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt;
+                               ao_log_data(&log);
+                               log.type = AO_LOG_DEPLOY;
+                               log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d;
+                               log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m;
+                               ao_log_data(&log);
+                               next_other = log.tick + AO_OTHER_INTERVAL;
+                       }
+                       ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos);
+               }
+               /* Write state change to EEPROM */
+               if (ao_flight_state != ao_log_state) {
+                       ao_log_state = ao_flight_state;
+                       log.type = AO_LOG_STATE;
+                       log.tick = ao_sample_tick;
+                       log.u.state.state = ao_log_state;
+                       log.u.state.reason = 0;
+                       ao_log_data(&log);
+
+                       if (ao_log_state == ao_flight_landed)
+                               ao_log_stop();
+               }
+
+               /* Wait for a while */
+               ao_delay(AO_MS_TO_TICKS(100));
+
+               /* Stop logging when told to */
+               while (!ao_log_running)
+                       ao_sleep(&ao_log_running);
+       }
+}
+
+uint16_t
+ao_log_flight(uint8_t slot)
+{
+       if (!ao_storage_read(ao_log_pos(slot),
+                            &log,
+                            sizeof (struct ao_log_record)))
+               return 0;
+
+       if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT)
+               return log.u.flight.flight;
+       return 0;
+}
diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c
new file mode 100644 (file)
index 0000000..1b472ef
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+ao_log_write_erase(uint8_t pos)
+{
+       (void) pos;
+}
+
+uint8_t
+ao_log_present(void)
+{
+       return 0;
+}
diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c
new file mode 100644 (file)
index 0000000..d5a3b99
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+static __data uint16_t ao_log_tiny_interval;
+
+#define AO_LOG_TINY_INTERVAL_DEFAULT   AO_MS_TO_TICKS(1000)
+#if USE_FAST_ASCENT_LOG
+#define AO_LOG_TINY_INTERVAL_ASCENT    AO_MS_TO_TICKS(100)
+#define AO_PAD_RING    8
+#else
+#define AO_LOG_TINY_INTERVAL_ASCENT    AO_LOG_TINY_INTERVAL_DEFAULT
+#define AO_PAD_RING    2
+#endif
+
+__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY;
+
+void
+ao_log_tiny_set_interval(uint16_t ticks)
+{
+       ao_log_tiny_interval = ticks;
+}
+
+
+static void ao_log_tiny_data(uint16_t d)
+{
+       if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
+               ao_log_stop();
+       if (ao_log_running) {
+               ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2);
+               ao_log_current_pos += 2;
+       }
+}
+
+static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING];
+static __pdata uint8_t ao_log_pad_ring_pos;
+
+#define ao_pad_ring_next(n)    (((n) + 1) & (AO_PAD_RING - 1))
+
+static void ao_log_tiny_queue(uint16_t d)
+{
+       ao_log_pad_ring[ao_log_pad_ring_pos] = d;
+       ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos);
+}
+
+static void ao_log_tiny_start(void)
+{
+       uint8_t         p;
+       uint16_t        d;
+
+       ao_log_tiny_data(ao_flight_number);
+       ao_log_tiny_data(ao_ground_pres);
+       p = ao_log_pad_ring_pos;
+       do {
+               d = ao_log_pad_ring[p];
+               /*
+                * ignore unwritten slots
+                */
+               if (d)
+                       ao_log_tiny_data(d);
+               p = ao_pad_ring_next(p);
+       } while (p != ao_log_pad_ring_pos);
+}
+
+void
+ao_log(void)
+{
+       uint16_t                last_time;
+       uint16_t                now;
+       enum ao_flight_state    ao_log_tiny_state;
+       int32_t                 sum;
+       int16_t                 count;
+       uint8_t                 ao_log_adc;
+       uint8_t                 ao_log_started = 0;
+
+       ao_storage_setup();
+
+       ao_log_scan();
+
+       ao_log_tiny_state = ao_flight_invalid;
+       ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
+       sum = 0;
+       count = 0;
+       ao_log_adc = ao_sample_adc;
+       last_time = ao_time();
+       for (;;) {
+
+               /*
+                * Add in pending sample data
+                */
+               ao_sleep(DATA_TO_XDATA(&ao_sample_adc));
+               while (ao_log_adc != ao_sample_adc) {
+                       sum += ao_adc_ring[ao_log_adc].pres;
+                       count++;
+                       ao_log_adc = ao_adc_ring_next(ao_log_adc);
+               }
+               if (ao_log_running) {
+                       if (!ao_log_started) {
+                               ao_log_tiny_start();
+                               ao_log_started = 1;
+                       }
+                       if (ao_flight_state != ao_log_tiny_state) {
+                               ao_log_tiny_data(ao_flight_state | 0x8000);
+                               ao_log_tiny_state = ao_flight_state;
+                               ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT;
+#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT
+                               if (ao_log_tiny_state <= ao_flight_coast)
+                                       ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
+#endif
+                               if (ao_log_tiny_state == ao_flight_landed)
+                                       ao_log_stop();
+                       }
+               }
+
+               /* Stop logging when told to */
+               if (!ao_log_running && ao_log_started)
+                       ao_exit();
+
+               /*
+                * Write out the sample when finished
+                */
+               now = ao_time();
+               if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) {
+                       count = sum / count;
+                       if (ao_log_started)
+                               ao_log_tiny_data(count);
+                       else
+                               ao_log_tiny_queue(count);
+                       sum = 0;
+                       count = 0;
+                       last_time = now;
+               }
+       }
+}
+
+uint16_t
+ao_log_flight(uint8_t slot)
+{
+       static __xdata uint16_t flight;
+
+       (void) slot;
+       ao_storage_read(0, &flight, 2);
+       if (flight == 0xffff)
+               flight = 0;
+       return flight;
+}
diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c
new file mode 100644 (file)
index 0000000..69eb58e
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_telem.h"
+
+#if !HAS_MONITOR
+#error Must define HAS_MONITOR to 1
+#endif
+
+__xdata uint8_t ao_monitoring;
+__pdata uint8_t ao_monitor_led;
+
+#define AO_MONITOR_RING        8
+
+__xdata union ao_monitor {
+               struct ao_telemetry_raw_recv    raw;
+               struct ao_telemetry_orig_recv   orig;
+               struct ao_telemetry_tiny_recv   tiny;
+} ao_monitor_ring[AO_MONITOR_RING];
+
+#define ao_monitor_ring_next(n)        (((n) + 1) & (AO_MONITOR_RING - 1))
+
+__data uint8_t ao_monitor_head;
+
+void
+ao_monitor_get(void)
+{
+       uint8_t size;
+
+       for (;;) {
+               switch (ao_monitoring) {
+               case 0:
+                       ao_sleep(&ao_monitoring);
+                       continue;
+               case AO_MONITORING_ORIG:
+                       size = sizeof (struct ao_telemetry_orig_recv);
+                       break;
+               case AO_MONITORING_TINY:
+                       size = sizeof (struct ao_telemetry_tiny_recv);
+                       break;
+               default:
+                       if (ao_monitoring > AO_MAX_TELEMETRY)
+                               ao_monitoring = AO_MAX_TELEMETRY;
+                       size = ao_monitoring;
+                       break;
+               }
+               if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2))
+                       continue;
+               ao_monitor_head = ao_monitor_ring_next(ao_monitor_head);
+               ao_wakeup(DATA_TO_XDATA(&ao_monitor_head));
+               ao_led_toggle(ao_monitor_led);
+       }
+}
+
+void
+ao_monitor_put(void)
+{
+       __xdata char callsign[AO_MAX_CALLSIGN+1];
+
+       uint8_t ao_monitor_tail;
+       uint8_t state;
+       uint8_t sum, byte;
+       int16_t rssi;
+       __xdata union ao_monitor        *m;
+
+#define recv_raw       ((m->raw))
+#define recv_orig      ((m->orig))
+#define recv_tiny      ((m->tiny))
+
+       ao_monitor_tail = ao_monitor_head;
+       for (;;) {
+               while (ao_monitor_tail == ao_monitor_head)
+                       ao_sleep(DATA_TO_XDATA(&ao_monitor_head));
+               m = &ao_monitor_ring[ao_monitor_tail];
+               ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail);
+               switch (ao_monitoring) {
+               case AO_MONITORING_ORIG:
+                       state = recv_orig.telemetry_orig.flight_state;
+
+                       /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */
+                       rssi = (int16_t) (recv_orig.rssi >> 1) - 74;
+                       memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN);
+                       if (state > ao_flight_invalid)
+                               state = ao_flight_invalid;
+                       if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) {
+
+                               /* General header fields */
+                               printf(AO_TELEM_VERSION " %d "
+                                      AO_TELEM_CALL " %s "
+                                      AO_TELEM_SERIAL " %d "
+                                      AO_TELEM_FLIGHT " %d "
+                                      AO_TELEM_RSSI " %d "
+                                      AO_TELEM_STATE " %s "
+                                      AO_TELEM_TICK " %d ",
+                                      AO_TELEMETRY_VERSION,
+                                      callsign,
+                                      recv_orig.telemetry_orig.serial,
+                                      recv_orig.telemetry_orig.flight,
+                                      rssi,
+                                      ao_state_names[state],
+                                      recv_orig.telemetry_orig.adc.tick);
+
+                               /* Raw sensor values */
+                               printf(AO_TELEM_RAW_ACCEL " %d "
+                                      AO_TELEM_RAW_BARO " %d "
+                                      AO_TELEM_RAW_THERMO " %d "
+                                      AO_TELEM_RAW_BATT " %d "
+                                      AO_TELEM_RAW_DROGUE " %d "
+                                      AO_TELEM_RAW_MAIN " %d ",
+                                      recv_orig.telemetry_orig.adc.accel,
+                                      recv_orig.telemetry_orig.adc.pres,
+                                      recv_orig.telemetry_orig.adc.temp,
+                                      recv_orig.telemetry_orig.adc.v_batt,
+                                      recv_orig.telemetry_orig.adc.sense_d,
+                                      recv_orig.telemetry_orig.adc.sense_m);
+
+                               /* Sensor calibration values */
+                               printf(AO_TELEM_CAL_ACCEL_GROUND " %d "
+                                      AO_TELEM_CAL_BARO_GROUND " %d "
+                                      AO_TELEM_CAL_ACCEL_PLUS " %d "
+                                      AO_TELEM_CAL_ACCEL_MINUS " %d ",
+                                      recv_orig.telemetry_orig.ground_accel,
+                                      recv_orig.telemetry_orig.ground_pres,
+                                      recv_orig.telemetry_orig.accel_plus_g,
+                                      recv_orig.telemetry_orig.accel_minus_g);
+
+                               if (recv_orig.telemetry_orig.u.k.unused == 0x8000) {
+                                       /* Kalman state values */
+                                       printf(AO_TELEM_KALMAN_HEIGHT " %d "
+                                              AO_TELEM_KALMAN_SPEED " %d "
+                                              AO_TELEM_KALMAN_ACCEL " %d ",
+                                              recv_orig.telemetry_orig.height,
+                                              recv_orig.telemetry_orig.u.k.speed,
+                                              recv_orig.telemetry_orig.accel);
+                               } else {
+                                       /* Ad-hoc flight values */
+                                       printf(AO_TELEM_ADHOC_ACCEL " %d "
+                                              AO_TELEM_ADHOC_SPEED " %ld "
+                                              AO_TELEM_ADHOC_BARO " %d ",
+                                              recv_orig.telemetry_orig.accel,
+                                              recv_orig.telemetry_orig.u.flight_vel,
+                                              recv_orig.telemetry_orig.height);
+                               }
+                               ao_gps_print(&recv_orig.telemetry_orig.gps);
+                               ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking);
+                               putchar('\n');
+                               ao_rssi_set(rssi);
+                       } else {
+                               printf("CRC INVALID RSSI %3d\n", rssi);
+                       }
+                       break;
+               case AO_MONITORING_TINY:
+                       state = recv_tiny.telemetry_tiny.flight_state;
+
+                       /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */
+                       rssi = (int16_t) (recv_tiny.rssi >> 1) - 74;
+                       memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN);
+                       if (state > ao_flight_invalid)
+                               state = ao_flight_invalid;
+                       if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) {
+                               /* General header fields */
+                               printf(AO_TELEM_VERSION " %d "
+                                      AO_TELEM_CALL " %s "
+                                      AO_TELEM_SERIAL " %d "
+                                      AO_TELEM_FLIGHT " %d "
+                                      AO_TELEM_RSSI " %d "
+                                      AO_TELEM_STATE " %s "
+                                      AO_TELEM_TICK " %d ",
+                                      AO_TELEMETRY_VERSION,
+                                      callsign,
+                                      recv_tiny.telemetry_tiny.serial,
+                                      recv_tiny.telemetry_tiny.flight,
+                                      rssi,
+                                      ao_state_names[state],
+                                      recv_tiny.telemetry_tiny.adc.tick);
+
+                               /* Raw sensor values */
+                               printf(AO_TELEM_RAW_BARO " %d "
+                                      AO_TELEM_RAW_THERMO " %d "
+                                      AO_TELEM_RAW_BATT " %d "
+                                      AO_TELEM_RAW_DROGUE " %d "
+                                      AO_TELEM_RAW_MAIN " %d ",
+                                      recv_tiny.telemetry_tiny.adc.pres,
+                                      recv_tiny.telemetry_tiny.adc.temp,
+                                      recv_tiny.telemetry_tiny.adc.v_batt,
+                                      recv_tiny.telemetry_tiny.adc.sense_d,
+                                      recv_tiny.telemetry_tiny.adc.sense_m);
+
+                               /* Sensor calibration values */
+                               printf(AO_TELEM_CAL_BARO_GROUND " %d ",
+                                      recv_tiny.telemetry_tiny.ground_pres);
+
+#if 1
+                               /* Kalman state values */
+                               printf(AO_TELEM_KALMAN_HEIGHT " %d "
+                                      AO_TELEM_KALMAN_SPEED " %d "
+                                      AO_TELEM_KALMAN_ACCEL " %d\n",
+                                      recv_tiny.telemetry_tiny.height,
+                                      recv_tiny.telemetry_tiny.speed,
+                                      recv_tiny.telemetry_tiny.accel);
+#else
+                               /* Ad-hoc flight values */
+                               printf(AO_TELEM_ADHOC_ACCEL " %d "
+                                      AO_TELEM_ADHOC_SPEED " %ld "
+                                      AO_TELEM_ADHOC_BARO " %d\n",
+                                      recv_tiny.telemetry_tiny.flight_accel,
+                                      recv_tiny.telemetry_tiny.flight_vel,
+                                      recv_tiny.telemetry_tiny.flight_pres);
+#endif
+                               ao_rssi_set(rssi);
+                       } else {
+                               printf("CRC INVALID RSSI %3d\n", rssi);
+                       }
+                       break;
+               default:
+                       printf ("TELEM %02x", ao_monitoring + 2);
+                       sum = 0x5a;
+                       for (state = 0; state < ao_monitoring + 2; state++) {
+                               byte = recv_raw.packet[state];
+                               sum += byte;
+                               printf("%02x", byte);
+                       }
+                       printf("%02x\n", sum);
+                       break;
+               }
+               ao_usb_flush();
+       }
+}
+
+__xdata struct ao_task ao_monitor_get_task;
+__xdata struct ao_task ao_monitor_put_task;
+
+void
+ao_set_monitor(uint8_t monitoring)
+{
+       if (ao_monitoring)
+               ao_radio_recv_abort();
+       ao_monitoring = monitoring;
+       ao_wakeup(&ao_monitoring);
+}
+
+static void
+set_monitor(void)
+{
+       ao_cmd_hex();
+       ao_set_monitor(ao_cmd_lex_i);
+}
+
+__code struct ao_cmds ao_monitor_cmds[] = {
+       { set_monitor,  "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" },
+       { 0,    NULL },
+};
+
+void
+ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant
+{
+       ao_monitor_led = monitor_led;
+       ao_monitoring = monitoring;
+       ao_cmd_register(&ao_monitor_cmds[0]);
+       ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get");
+       ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put");
+}
diff --git a/src/core/ao_mutex.c b/src/core/ao_mutex.c
new file mode 100644 (file)
index 0000000..c82a7d5
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+ao_mutex_get(__xdata uint8_t *mutex) __reentrant
+{
+       if (*mutex == ao_cur_task->task_id)
+               ao_panic(AO_PANIC_MUTEX);
+       __critical {
+               while (*mutex)
+                       ao_sleep(mutex);
+               *mutex = ao_cur_task->task_id;
+       }
+}
+
+void
+ao_mutex_put(__xdata uint8_t *mutex) __reentrant
+{
+       if (*mutex != ao_cur_task->task_id)
+               ao_panic(AO_PANIC_MUTEX);
+       __critical {
+               *mutex = 0;
+               ao_wakeup(mutex);
+       }
+}
diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c
new file mode 100644 (file)
index 0000000..fdada20
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#ifndef HAS_BEEP
+#error Please define HAS_BEEP
+#endif
+
+#if !HAS_BEEP
+#define ao_beep(x)
+#endif
+
+static void
+ao_panic_delay(uint8_t n)
+{
+       uint8_t i = 0, j = 0;
+
+       while (n--)
+               while (--j)
+                       while (--i)
+                               _asm nop _endasm;
+}
+
+void
+ao_panic(uint8_t reason)
+{
+       uint8_t n;
+
+       __critical for (;;) {
+               ao_panic_delay(20);
+               for (n = 0; n < 5; n++) {
+                       ao_led_on(AO_LED_RED);
+                       ao_beep(AO_BEEP_HIGH);
+                       ao_panic_delay(1);
+                       ao_led_off(AO_LED_RED);
+                       ao_beep(AO_BEEP_LOW);
+                       ao_panic_delay(1);
+               }
+               ao_beep(AO_BEEP_OFF);
+               ao_panic_delay(2);
+#pragma disable_warning 126
+               for (n = 0; n < reason; n++) {
+                       ao_led_on(AO_LED_RED);
+                       ao_beep(AO_BEEP_MID);
+                       ao_panic_delay(10);
+                       ao_led_off(AO_LED_RED);
+                       ao_beep(AO_BEEP_OFF);
+                       ao_panic_delay(10);
+               }
+       }
+}
diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h
new file mode 100644 (file)
index 0000000..e1f5459
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#if defined(TELEMETRUM_V_1_0)
+       #define HAS_FLIGHT              1
+       #define HAS_USB                 1
+       #define HAS_BEEP                1
+       #define HAS_GPS                 1
+       #define HAS_SERIAL_1            1
+       #define HAS_ADC                 1
+       #define USE_SERIAL_STDIN        0
+       #define HAS_EEPROM              1
+       #define USE_INTERNAL_FLASH      0
+       #define HAS_DBG                 1
+       #define DBG_ON_P1               1
+       #define DBG_ON_P0               0
+       #define IGNITE_ON_P2            1
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       0
+       #define PACKET_HAS_SLAVE        1
+
+       #define HAS_COMPANION           1
+       #define COMPANION_CS_ON_P1      1
+       #define COMPANION_CS_MASK       0x4     /* CS1 is P1_2 */
+       #define COMPANION_CS            P1_2
+
+       #define AO_LED_RED              1
+       #define LEDS_AVAILABLE          (AO_LED_RED)
+       #define HAS_EXTERNAL_TEMP       0
+       #define HAS_ACCEL_REF           0
+       #define HAS_ACCEL               1
+       #define HAS_IGNITE              1
+       #define HAS_MONITOR             0
+#endif
+
+#if defined(TELEMETRUM_V_1_1)
+       #define HAS_FLIGHT              1
+       #define HAS_USB                 1
+       #define HAS_BEEP                1
+       #define HAS_GPS                 1
+       #define HAS_SERIAL_1            1
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 1
+       #define HAS_EEPROM              1
+       #define USE_INTERNAL_FLASH      0
+       #define HAS_DBG                 1
+       #define DBG_ON_P1               1
+       #define DBG_ON_P0               0
+       #define IGNITE_ON_P2            1
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       0
+       #define PACKET_HAS_SLAVE        1
+
+       #define HAS_COMPANION           1
+       #define COMPANION_CS_ON_P1      1
+       #define COMPANION_CS_MASK       0x4     /* CS1 is P1_2 */
+       #define COMPANION_CS            P1_2
+
+       #define AO_LED_RED              1
+       #define LEDS_AVAILABLE          (AO_LED_RED)
+       #define HAS_EXTERNAL_TEMP       0
+       #define HAS_ACCEL_REF           1
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
+       #define M25_CS_MASK             0x02    /* CS0 is P1_1 */
+       #define M25_MAX_CHIPS           1
+       #define HAS_ACCEL               1
+       #define HAS_IGNITE              1
+       #define HAS_MONITOR             0
+#endif
+
+#if defined(TELEDONGLE_V_0_2)
+       #define HAS_FLIGHT              0
+       #define HAS_USB                 1
+       #define HAS_BEEP                0
+       #define HAS_SERIAL_1            0
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 0
+       #define HAS_DBG                 1
+       #define HAS_EEPROM              0
+       #define DBG_ON_P1               1
+       #define DBG_ON_P0               0
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       1
+       #define PACKET_HAS_SLAVE        0
+       #define AO_LED_RED              1
+       #define AO_LED_GREEN            2
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
+       #define HAS_IGNITE              0
+       #define HAS_MONITOR             1
+#endif
+
+#if defined(TELEMINI_V_1_0)
+       #define HAS_FLIGHT              1
+       #define HAS_USB                 0
+       #define HAS_BEEP                0
+       #define HAS_GPS                 0
+       #define HAS_SERIAL_1            0
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 1
+       #define HAS_EEPROM              1
+       #define USE_INTERNAL_FLASH      1
+       #define HAS_DBG                 0
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            1
+       #define PACKET_HAS_MASTER       0
+       #define PACKET_HAS_SLAVE        1
+       #define USE_FAST_ASCENT_LOG     1
+
+       #define AO_LED_GREEN            1
+       #define AO_LED_RED              2
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define HAS_EXTERNAL_TEMP       0
+       #define HAS_ACCEL               0
+       #define HAS_IGNITE              1
+       #define HAS_MONITOR             0
+#endif
+
+#if defined(TELENANO_V_0_1)
+       #define HAS_FLIGHT              1
+       #define HAS_USB                 0
+       #define HAS_BEEP                0
+       #define HAS_GPS                 0
+       #define HAS_SERIAL_1            0
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 1
+       #define HAS_EEPROM              1
+       #define USE_INTERNAL_FLASH      1
+       #define HAS_DBG                 0
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            1
+       #define PACKET_HAS_MASTER       0
+       #define PACKET_HAS_SLAVE        1
+
+       #define AO_LED_GREEN            1
+       #define AO_LED_RED              2
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define HAS_EXTERNAL_TEMP       0
+       #define HAS_ACCEL               0
+       #define HAS_IGNITE              0
+       #define HAS_MONITOR             0
+#endif
+
+#if defined(TELEMETRUM_V_0_1)
+       #define HAS_FLIGHT              1
+       #define HAS_USB                 1
+       #define HAS_BEEP                1
+       #define HAS_GPS                 1
+       #define HAS_SERIAL_1            1
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 1
+       #define HAS_DBG                 0
+       #define HAS_EEPROM              1
+       #define USE_INTERNAL_FLASH      0
+       #define DBG_ON_P1               0
+       #define DBG_ON_P0               1
+       #define IGNITE_ON_P2            1
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       0
+       #define PACKET_HAS_SLAVE        1
+       #define AO_LED_RED              2
+       #define AO_LED_GREEN            1
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define HAS_EXTERNAL_TEMP       1
+       #define HAS_ACCEL_REF           0
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
+       #define HAS_ACCEL               1
+       #define HAS_IGNITE              1
+       #define HAS_MONITOR             0
+#endif
+
+#if defined(TELEDONGLE_V_0_1)
+       #define HAS_FLIGHT              0
+       #define HAS_USB                 1
+       #define HAS_BEEP                0
+       #define HAS_SERIAL_1            0
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 0
+       #define HAS_DBG                 0
+       #define HAS_EEPROM              0
+       #define DBG_ON_P1               0
+       #define DBG_ON_P0               1
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       1
+       #define PACKET_HAS_SLAVE        0
+       #define AO_LED_RED              2
+       #define AO_LED_GREEN            1
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define SPI_CS_ON_P1            0
+       #define SPI_CS_ON_P0            1
+       #define HAS_IGNITE              0
+       #define HAS_MONITOR             1
+#endif
+
+#if defined(TIDONGLE)
+       #define HAS_FLIGHT              0
+       #define HAS_USB                 1
+       #define HAS_BEEP                0
+       #define HAS_SERIAL_1            0
+       #define USE_SERIAL_STDIN        0
+       #define HAS_ADC                 0
+       #define HAS_DBG                 1
+       #define HAS_EEPROM              0
+       #define DBG_ON_P1               0
+       #define DBG_ON_P0               1
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       1
+       #define PACKET_HAS_SLAVE        0
+       #define AO_LED_RED              2
+       #define LEDS_AVAILABLE          (AO_LED_RED)
+       #define SPI_CS_ON_P1            0
+       #define SPI_CS_ON_P0            1
+       #define HAS_IGNITE              0
+       #define HAS_MONITOR             1
+#endif
+
+#if defined(TELEBT_V_0_0)
+       #define HAS_FLIGHT              0
+       #define HAS_USB                 1
+       #define HAS_BEEP                0
+       #define HAS_SERIAL_1            1
+       #define USE_SERIAL_STDIN        1
+       #define HAS_ADC                 0
+       #define HAS_DBG                 1
+       #define HAS_EEPROM              0
+       #define HAS_BTM                 1
+       #define DBG_ON_P1               0
+       #define DBG_ON_P0               1
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       1
+       #define PACKET_HAS_SLAVE        0
+       #define AO_LED_RED              2
+       #define AO_LED_GREEN            1
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
+       #define HAS_IGNITE              0
+       #define BT_LINK_ON_P2           1
+       #define BT_LINK_ON_P1           0
+       #define BT_LINK_PIN_INDEX       7
+       #define BT_LINK_PIN             P2_1
+       #define HAS_MONITOR             1
+#endif
+
+#if defined(TELEBT_V_0_1)
+       #define HAS_FLIGHT              0
+       #define HAS_USB                 1
+       #define HAS_BEEP                1
+       #define HAS_SERIAL_1            1
+       #define HAS_SERIAL_1_ALT_1      1
+       #define HAS_SERIAL_1_ALT_2      0
+       #define HAS_SERIAL_1_HW_FLOW    1
+       #define USE_SERIAL_STDIN        1
+       #define HAS_ADC                 0
+       #define HAS_DBG                 1
+       #define HAS_EEPROM              1
+       #define USE_INTERNAL_FLASH      0
+       #define HAS_BTM                 1
+       #define DBG_ON_P1               1
+       #define DBG_ON_P0               0
+       #define IGNITE_ON_P2            0
+       #define IGNITE_ON_P0            0
+       #define PACKET_HAS_MASTER       1
+       #define PACKET_HAS_SLAVE        0
+       #define AO_LED_RED              1
+       #define AO_LED_GREEN            2
+       #define LEDS_AVAILABLE          (AO_LED_RED|AO_LED_GREEN)
+       #define SPI_CS_ON_P1            1
+       #define SPI_CS_ON_P0            0
+       #define M25_CS_MASK             0x04    /* CS0 is P1_2 */
+       #define M25_MAX_CHIPS           1
+       #define HAS_ACCEL               0
+       #define HAS_IGNITE              0
+       #define BT_LINK_ON_P2           0
+       #define BT_LINK_ON_P1           1
+       #define BT_LINK_PIN_INDEX       7
+       #define BT_LINK_PIN             P1_7
+       #define HAS_MONITOR             1
+#endif
+
+#if DBG_ON_P1
+
+       #define DBG_CLOCK       (1 << 4)        /* mi0 */
+       #define DBG_DATA        (1 << 5)        /* mo0 */
+       #define DBG_RESET_N     (1 << 3)        /* c0 */
+
+       #define DBG_CLOCK_PIN   (P1_4)
+       #define DBG_DATA_PIN    (P1_5)
+       #define DBG_RESET_N_PIN (P1_3)
+
+       #define DBG_PORT_NUM    1
+       #define DBG_PORT        P1
+       #define DBG_PORT_SEL    P1SEL
+       #define DBG_PORT_INP    P1INP
+       #define DBG_PORT_DIR    P1DIR
+
+#endif /* DBG_ON_P1 */
+
+#if DBG_ON_P0
+
+       #define DBG_CLOCK       (1 << 3)
+       #define DBG_DATA        (1 << 4)
+       #define DBG_RESET_N     (1 << 5)
+
+       #define DBG_CLOCK_PIN   (P0_3)
+       #define DBG_DATA_PIN    (P0_4)
+       #define DBG_RESET_N_PIN (P0_5)
+
+       #define DBG_PORT_NUM    0
+       #define DBG_PORT        P0
+       #define DBG_PORT_SEL    P0SEL
+       #define DBG_PORT_INP    P0INP
+       #define DBG_PORT_DIR    P0DIR
+
+#endif /* DBG_ON_P0 */
+
+#if COMPANION_CS_ON_P1
+       #define COMPANION_CS_PORT       P1
+       #define COMPANION_CS_SEL        P1SEL
+       #define COMPANION_CS_DIR        P1DIR
+#endif
+
+#if SPI_CS_ON_P1
+       #define SPI_CS_PORT     P1
+       #define SPI_CS_SEL      P1SEL
+       #define SPI_CS_DIR      P1DIR
+#endif
+
+#if SPI_CS_ON_P0
+       #define SPI_CS_PORT     P0
+       #define SPI_CS_SEL      P0SEL
+       #define SPI_CS_DIR      P0DIR
+#endif
+
+#ifndef IGNITE_ON_P2
+#error Please define IGNITE_ON_P2
+#endif
+
+#ifndef IGNITE_ON_P0
+#error Please define IGNITE_ON_P0
+#endif
+
+#ifndef HAS_SERIAL_1
+#error Please define HAS_SERIAL_1
+#endif
+
+#ifndef USE_SERIAL_STDIN
+#error Please define USE_SERIAL_STDIN
+#endif
+
+#ifndef HAS_ADC
+#error Please define HAS_ADC
+#endif
+
+#ifndef HAS_EEPROM
+#error Please define HAS_EEPROM
+#endif
+
+#if HAS_EEPROM
+#ifndef USE_INTERNAL_FLASH
+#error Please define USE_INTERNAL_FLASH
+#endif
+#endif
+
+#ifndef HAS_DBG
+#error Please define HAS_DBG
+#endif
+
+#ifndef HAS_IGNITE
+#error Please define HAS_IGNITE
+#endif
+
+#ifndef PACKET_HAS_MASTER
+#error Please define PACKET_HAS_MASTER
+#endif
+
+#ifndef PACKET_HAS_SLAVE
+#error Please define PACKET_HAS_SLAVE
+#endif
+
+#ifndef HAS_MONITOR
+#error Please define HAS_MONITOR
+#endif
+#endif /* _AO_PINS_H_ */
diff --git a/src/core/ao_product.c b/src/core/ao_product.c
new file mode 100644 (file)
index 0000000..fb59580
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_product.h"
+
+/* Defines which mark this particular AltOS product */
+
+const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING;
+const char ao_manufacturer[] = AO_iManufacturer_STRING;
+const char ao_product[] = AO_iProduct_STRING;
+
+#define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
+
+#if HAS_USB
+#include "ao_usb.h"
+/* USB descriptors in one giant block of bytes */
+__code __at(0x00aa) uint8_t ao_usb_descriptors [] =
+{
+       /* Device descriptor */
+       0x12,
+       AO_USB_DESC_DEVICE,
+       LE_WORD(0x0110),        /*  bcdUSB */
+       0x02,                   /*  bDeviceClass */
+       0x00,                   /*  bDeviceSubClass */
+       0x00,                   /*  bDeviceProtocol */
+       AO_USB_CONTROL_SIZE,    /*  bMaxPacketSize */
+       LE_WORD(0xFFFE),        /*  idVendor */
+       LE_WORD(AO_idProduct_NUMBER),   /*  idProduct */
+       LE_WORD(0x0100),        /*  bcdDevice */
+       0x01,                   /*  iManufacturer */
+       0x02,                   /*  iProduct */
+       0x03,                   /*  iSerialNumber */
+       0x01,                   /*  bNumConfigurations */
+
+       /* Configuration descriptor */
+       0x09,
+       AO_USB_DESC_CONFIGURATION,
+       LE_WORD(67),            /*  wTotalLength */
+       0x02,                   /*  bNumInterfaces */
+       0x01,                   /*  bConfigurationValue */
+       0x00,                   /*  iConfiguration */
+       0xC0,                   /*  bmAttributes */
+       0x32,                   /*  bMaxPower */
+
+       /* Control class interface */
+       0x09,
+       AO_USB_DESC_INTERFACE,
+       0x00,                   /*  bInterfaceNumber */
+       0x00,                   /*  bAlternateSetting */
+       0x01,                   /*  bNumEndPoints */
+       0x02,                   /*  bInterfaceClass */
+       0x02,                   /*  bInterfaceSubClass */
+       0x01,                   /*  bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
+       0x00,                   /*  iInterface */
+
+       /* Header functional descriptor */
+       0x05,
+       CS_INTERFACE,
+       0x00,                   /*  bDescriptor SubType Header */
+       LE_WORD(0x0110),        /*  CDC version 1.1 */
+
+       /* Call management functional descriptor */
+       0x05,
+       CS_INTERFACE,
+       0x01,                   /* bDescriptor SubType Call Management */
+       0x01,                   /* bmCapabilities = device handles call management */
+       0x01,                   /* bDataInterface call management interface number */
+
+       /* ACM functional descriptor */
+       0x04,
+       CS_INTERFACE,
+       0x02,                   /* bDescriptor SubType Abstract Control Management */
+       0x02,                   /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */
+
+       /* Union functional descriptor */
+       0x05,
+       CS_INTERFACE,
+       0x06,                   /* bDescriptor SubType Union Functional descriptor */
+       0x00,                   /* bMasterInterface */
+       0x01,                   /* bSlaveInterface0 */
+
+       /* Notification EP */
+       0x07,
+       AO_USB_DESC_ENDPOINT,
+       AO_USB_INT_EP|0x80,     /* bEndpointAddress */
+       0x03,                   /* bmAttributes = intr */
+       LE_WORD(8),             /* wMaxPacketSize */
+       0x0A,                   /* bInterval */
+
+       /* Data class interface descriptor */
+       0x09,
+       AO_USB_DESC_INTERFACE,
+       0x01,                   /* bInterfaceNumber */
+       0x00,                   /* bAlternateSetting */
+       0x02,                   /* bNumEndPoints */
+       0x0A,                   /* bInterfaceClass = data */
+       0x00,                   /* bInterfaceSubClass */
+       0x00,                   /* bInterfaceProtocol */
+       0x00,                   /* iInterface */
+
+       /* Data EP OUT */
+       0x07,
+       AO_USB_DESC_ENDPOINT,
+       AO_USB_OUT_EP,          /* bEndpointAddress */
+       0x02,                   /* bmAttributes = bulk */
+       LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
+       0x00,                   /* bInterval */
+
+       /* Data EP in */
+       0x07,
+       AO_USB_DESC_ENDPOINT,
+       AO_USB_IN_EP|0x80,      /* bEndpointAddress */
+       0x02,                   /* bmAttributes = bulk */
+       LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
+       0x00,                   /* bInterval */
+
+       /* String descriptors */
+       0x04,
+       AO_USB_DESC_STRING,
+       LE_WORD(0x0409),
+
+       /* iManufacturer */
+       AO_iManufacturer_LEN,
+       AO_USB_DESC_STRING,
+       AO_iManufacturer_UCS2,
+
+       /* iProduct */
+       AO_iProduct_LEN,
+       AO_USB_DESC_STRING,
+       AO_iProduct_UCS2,
+
+       /* iSerial */
+       AO_iSerial_LEN,
+       AO_USB_DESC_STRING,
+       AO_iSerial_UCS2,
+
+       /* Terminating zero */
+       0
+};
+#endif
diff --git a/src/core/ao_report.c b/src/core/ao_report.c
new file mode 100644 (file)
index 0000000..3cf558e
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#define BIT(i,x)          ((x) ? (1 << (i)) : 0)
+#define MORSE1(a)          (1 | BIT(3,a))
+#define MORSE2(a,b)        (2 | BIT(3,a) | BIT(4,b))
+#define MORSE3(a,b,c)      (3 | BIT(3,a) | BIT(4,b) | BIT(5,c))
+#define MORSE4(a,b,c,d)    (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d))
+#define MORSE5(a,b,c,d,e)  (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e))
+
+static const uint8_t flight_reports[] = {
+       MORSE3(0,0,0),          /* startup, 'S' */
+       MORSE2(0,0),            /* idle 'I' */
+       MORSE4(0,1,1,0),        /* pad 'P' */
+       MORSE4(1,0,0,0),        /* boost 'B' */
+       MORSE4(0,0,1,0),        /* fast 'F' */
+       MORSE4(1,0,1,0),        /* coast 'C' */
+       MORSE3(1,0,0),          /* drogue 'D' */
+       MORSE2(1,1),            /* main 'M' */
+       MORSE4(0,1,0,0),        /* landed 'L' */
+       MORSE4(1,0,0,1),        /* invalid 'X' */
+};
+
+#if HAS_BEEP
+#define low(time)      ao_beep_for(AO_BEEP_LOW, time)
+#define mid(time)      ao_beep_for(AO_BEEP_MID, time)
+#define high(time)     ao_beep_for(AO_BEEP_HIGH, time)
+#else
+#define low(time)      ao_led_for(AO_LED_GREEN, time)
+#define mid(time)      ao_led_for(AO_LED_RED, time)
+#define high(time)     ao_led_for(AO_LED_GREEN|AO_LED_RED, time)
+#endif
+#define pause(time)    ao_delay(time)
+
+static __pdata enum ao_flight_state ao_report_state;
+
+static void
+ao_report_beep(void) __reentrant
+{
+       uint8_t r = flight_reports[ao_flight_state];
+       uint8_t l = r & 7;
+
+       if (!r)
+               return;
+       while (l--) {
+               if (r & 8)
+                       mid(AO_MS_TO_TICKS(600));
+               else
+                       mid(AO_MS_TO_TICKS(200));
+               pause(AO_MS_TO_TICKS(200));
+               r >>= 1;
+       }
+       pause(AO_MS_TO_TICKS(400));
+}
+
+static void
+ao_report_digit(uint8_t digit) __reentrant
+{
+       if (!digit) {
+               mid(AO_MS_TO_TICKS(500));
+               pause(AO_MS_TO_TICKS(200));
+       } else {
+               while (digit--) {
+                       mid(AO_MS_TO_TICKS(200));
+                       pause(AO_MS_TO_TICKS(200));
+               }
+       }
+       pause(AO_MS_TO_TICKS(300));
+}
+
+static void
+ao_report_altitude(void)
+{
+       __pdata int16_t agl = ao_max_height;
+       __xdata uint8_t digits[10];
+       __pdata uint8_t ndigits, i;
+
+       if (agl < 0)
+               agl = 0;
+       ndigits = 0;
+       do {
+               digits[ndigits++] = agl % 10;
+               agl /= 10;
+       } while (agl);
+
+       for (;;) {
+               ao_report_beep();
+               i = ndigits;
+               do
+                       ao_report_digit(digits[--i]);
+               while (i != 0);
+               pause(AO_SEC_TO_TICKS(5));
+       }
+}
+
+#if HAS_IGNITE
+static uint8_t
+ao_report_igniter_ready(enum ao_igniter igniter)
+{
+       return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0;
+}
+
+static void
+ao_report_continuity(void) __reentrant
+{
+       uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) |
+                    (ao_report_igniter_ready(ao_igniter_main) << 1));
+       if (c) {
+               while (c--) {
+                       high(AO_MS_TO_TICKS(25));
+                       pause(AO_MS_TO_TICKS(100));
+               }
+       } else {
+               c = 10;
+               while (c--) {
+                       high(AO_MS_TO_TICKS(20));
+                       low(AO_MS_TO_TICKS(20));
+               }
+       }
+       if (ao_log_full()) {
+               pause(AO_MS_TO_TICKS(100));
+               c = 2;
+               while (c--) {
+                       low(AO_MS_TO_TICKS(100));
+                       mid(AO_MS_TO_TICKS(100));
+                       high(AO_MS_TO_TICKS(100));
+                       mid(AO_MS_TO_TICKS(100));
+               }
+       }
+       c = 50;
+       while (c-- && ao_flight_state == ao_flight_pad)
+               pause(AO_MS_TO_TICKS(100));
+}
+#endif
+
+void
+ao_report(void)
+{
+       ao_report_state = ao_flight_state;
+       for(;;) {
+               if (ao_flight_state == ao_flight_landed)
+                       ao_report_altitude();
+               ao_report_beep();
+#if HAS_IGNITE
+               if (ao_flight_state == ao_flight_idle)
+                       ao_report_continuity();
+               while (ao_flight_state == ao_flight_pad)
+                       ao_report_continuity();
+#endif
+               __critical {
+                       while (ao_report_state == ao_flight_state)
+                               ao_sleep(DATA_TO_XDATA(&ao_flight_state));
+                       ao_report_state = ao_flight_state;
+               }
+       }
+}
+
+static __xdata struct ao_task ao_report_task;
+
+void
+ao_report_init(void)
+{
+       ao_add_task(&ao_report_task, ao_report, "report");
+}
diff --git a/src/core/ao_rssi.c b/src/core/ao_rssi.c
new file mode 100644 (file)
index 0000000..e3964d2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+static __xdata volatile uint16_t       ao_rssi_time;
+static __pdata volatile uint16_t       ao_rssi_delay;
+static __pdata uint8_t                 ao_rssi_led;
+
+void
+ao_rssi(void)
+{
+       for (;;) {
+               while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3))
+                       ao_sleep(&ao_rssi_time);
+               ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100));
+               ao_delay(ao_rssi_delay);
+       }
+}
+
+void
+ao_rssi_set(int rssi_value)
+{
+       if (rssi_value > 0)
+               rssi_value = 0;
+       ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5);
+       ao_rssi_time = ao_time();
+       ao_wakeup(&ao_rssi_time);
+}
+
+__xdata struct ao_task ao_rssi_task;
+
+void
+ao_rssi_init(uint8_t rssi_led)
+{
+       ao_rssi_led = rssi_led;
+       ao_rssi_delay = 0;
+       ao_add_task(&ao_rssi_task, ao_rssi, "rssi");
+}
diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c
new file mode 100644 (file)
index 0000000..b2b8e9f
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef AO_FLIGHT_TEST
+#include "ao.h"
+#endif
+
+/*
+ * Current sensor values
+ */
+
+__pdata uint16_t       ao_sample_tick;         /* time of last data */
+__pdata int16_t                ao_sample_pres;
+__pdata int16_t                ao_sample_alt;
+__pdata int16_t                ao_sample_height;
+#if HAS_ACCEL
+__pdata int16_t                ao_sample_accel;
+#endif
+
+__data uint8_t         ao_sample_adc;
+
+/*
+ * Sensor calibration values
+ */
+
+__pdata int16_t                ao_ground_pres;         /* startup pressure */
+__pdata int16_t                ao_ground_height;       /* MSL of ao_ground_pres */
+
+#if HAS_ACCEL
+__pdata int16_t                ao_ground_accel;        /* startup acceleration */
+__pdata int16_t                ao_accel_2g;            /* factory accel calibration */
+__pdata int32_t                ao_accel_scale;         /* sensor to m/s² conversion */
+#endif
+
+static __pdata uint8_t ao_preflight;           /* in preflight mode */
+
+static __pdata uint16_t        nsamples;
+__pdata int32_t ao_sample_pres_sum;
+#if HAS_ACCEL
+__pdata int32_t ao_sample_accel_sum;
+#endif
+
+static void
+ao_sample_preflight(void)
+{
+       /* startup state:
+        *
+        * Collect 512 samples of acceleration and pressure
+        * data and average them to find the resting values
+        */
+       if (nsamples < 512) {
+#if HAS_ACCEL
+               ao_sample_accel_sum += ao_sample_accel;
+#endif
+               ao_sample_pres_sum += ao_sample_pres;
+               ++nsamples;
+       } else {
+               ao_config_get();
+#if HAS_ACCEL
+               ao_ground_accel = ao_sample_accel_sum >> 9;
+               ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g;
+               ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g;
+#endif
+               ao_ground_pres = ao_sample_pres_sum >> 9;
+               ao_ground_height = ao_pres_to_altitude(ao_ground_pres);
+               ao_preflight = FALSE;
+       }
+}
+
+uint8_t
+ao_sample(void)
+{
+       ao_wakeup(DATA_TO_XDATA(&ao_sample_adc));
+       ao_sleep(DATA_TO_XDATA(&ao_adc_head));
+       while (ao_sample_adc != ao_adc_head) {
+               __xdata struct ao_adc *ao_adc;
+
+               /* Capture a sample */
+               ao_adc = &ao_adc_ring[ao_sample_adc];
+               ao_sample_tick = ao_adc->tick;
+               ao_sample_pres = ao_adc->pres;
+               ao_sample_alt = ao_pres_to_altitude(ao_sample_pres);
+               ao_sample_height = ao_sample_alt - ao_ground_height;
+#if HAS_ACCEL
+               ao_sample_accel = ao_adc->accel;
+#if HAS_ACCEL_REF
+               /*
+                * Ok, the math here is a bit tricky.
+                *
+                * ao_sample_accel:  ADC output for acceleration
+                * ao_accel_ref:  ADC output for the 5V reference.
+                * ao_cook_accel: Corrected acceleration value
+                * Vcc:           3.3V supply to the CC1111
+                * Vac:           5V supply to the accelerometer
+                * accel:         input voltage to accelerometer ADC pin
+                * ref:           input voltage to 5V reference ADC pin
+                *
+                *
+                * Measured acceleration is ratiometric to Vcc:
+                *
+                *     ao_sample_accel   accel
+                *     ------------ = -----
+                *        32767        Vcc
+                *
+                * Measured 5v reference is also ratiometric to Vcc:
+                *
+                *     ao_accel_ref    ref
+                *     ------------ = -----
+                *        32767        Vcc
+                *
+                *
+                *      ao_accel_ref = 32767 * (ref / Vcc)
+                *
+                * Acceleration is measured ratiometric to the 5V supply,
+                * so what we want is:
+                *
+                *      ao_cook_accel    accel
+                *      ------------- =  -----
+                *          32767         ref
+                *
+                *
+                *                      accel    Vcc
+                *                    = ----- *  ---
+                *                       Vcc     ref
+                *
+                *                      ao_sample_accel       32767
+                *                    = ------------ *  ------------
+                *                         32767        ao_accel_ref
+                *
+                * Multiply through by 32767:
+                *
+                *                      ao_sample_accel * 32767
+                *      ao_cook_accel = --------------------
+                *                          ao_accel_ref
+                *
+                * Now, the tricky part. Getting this to compile efficiently
+                * and keeping all of the values in-range.
+                *
+                * First off, we need to use a shift of 16 instead of * 32767 as SDCC
+                * does the obvious optimizations for byte-granularity shifts:
+                *
+                *      ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref
+                *
+                * Next, lets check our input ranges:
+                *
+                *      0 <= ao_sample_accel <= 0x7fff          (singled ended ADC conversion)
+                *      0x7000 <= ao_accel_ref <= 0x7fff        (the 5V ref value is close to 0x7fff)
+                *
+                * Plugging in our input ranges, we get an output range of 0 - 0x12490,
+                * which is 17 bits. That won't work. If we take the accel ref and shift
+                * by a bit, we'll change its range:
+                *
+                *      0xe000 <= ao_accel_ref<<1 <= 0xfffe
+                *
+                *      ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1)
+                *
+                * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It
+                * is, however, one bit too large for our signed computations. So, we
+                * take the result and shift that by a bit:
+                *
+                *      ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1
+                *
+                * This finally creates an output range of 0 - 0x4924. As the ADC only
+                * provides 11 bits of data, we haven't actually lost any precision,
+                * just dropped a bit of noise off the low end.
+                */
+               ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1;
+               if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+                       ao_sample_accel = 0x7fff - ao_sample_accel;
+               ao_adc->accel = ao_sample_accel;
+#endif
+#endif
+
+               if (ao_preflight)
+                       ao_sample_preflight();
+               else
+                       ao_kalman();
+               ao_sample_adc = ao_adc_ring_next(ao_sample_adc);
+       }
+       return !ao_preflight;
+}
+
+void
+ao_sample_init(void)
+{
+       nsamples = 0;
+       ao_sample_pres_sum = 0;
+       ao_sample_pres = 0;
+#if HAS_ACCEL
+       ao_sample_accel_sum = 0;
+       ao_sample_accel = 0;
+#endif
+       ao_sample_adc = ao_adc_head;
+       ao_preflight = TRUE;
+}
diff --git a/src/core/ao_state.c b/src/core/ao_state.c
new file mode 100644 (file)
index 0000000..ed197aa
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+const char const * const ao_state_names[] = {
+       "startup", "idle", "pad", "boost", "fast",
+       "coast", "drogue", "main", "landed", "invalid"
+};
diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c
new file mode 100644 (file)
index 0000000..c0138a3
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/*
+ * Basic I/O functions to support SDCC stdio package
+ */
+
+#define AO_NUM_STDIOS  (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN)
+
+__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS];
+__pdata int8_t ao_cur_stdio;
+__pdata int8_t ao_num_stdios;
+
+void
+putchar(char c)
+{
+       if (c == '\n')
+               (*ao_stdios[ao_cur_stdio].putchar)('\r');
+       (*ao_stdios[ao_cur_stdio].putchar)(c);
+}
+
+void
+flush(void)
+{
+       if (ao_stdios[ao_cur_stdio].flush)
+               ao_stdios[ao_cur_stdio].flush();
+}
+
+__xdata uint8_t ao_stdin_ready;
+
+char
+getchar(void) __reentrant __critical
+{
+       char c;
+       int8_t stdio = ao_cur_stdio;
+
+       for (;;) {
+               c = ao_stdios[stdio].pollchar();
+               if (c != AO_READ_AGAIN)
+                       break;
+               if (++stdio == ao_num_stdios)
+                       stdio = 0;
+               if (stdio == ao_cur_stdio)
+                       ao_sleep(&ao_stdin_ready);
+       }
+       ao_cur_stdio = stdio;
+       return c;
+}
+
+uint8_t
+ao_echo(void)
+{
+       return ao_stdios[ao_cur_stdio].echo;
+}
+
+int8_t
+ao_add_stdio(char (*pollchar)(void),
+            void (*putchar)(char),
+            void (*flush)(void)) __reentrant
+{
+       if (ao_num_stdios == AO_NUM_STDIOS)
+               ao_panic(AO_PANIC_STDIO);
+       ao_stdios[ao_num_stdios].pollchar = pollchar;
+       ao_stdios[ao_num_stdios].putchar = putchar;
+       ao_stdios[ao_num_stdios].flush = flush;
+       ao_stdios[ao_num_stdios].echo = 1;
+       return ao_num_stdios++;
+}
diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c
new file mode 100644 (file)
index 0000000..6ffca0e
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+uint8_t
+ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
+{
+       uint16_t this_len;
+       uint16_t this_off;
+
+       ao_storage_setup();
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+       while (len) {
+
+               /* Compute portion of transfer within
+                * a single block
+                */
+               this_off = (uint16_t) pos & (ao_storage_unit - 1);
+               this_len = ao_storage_unit - this_off;
+               if (this_len > len)
+                       this_len = len;
+
+               if (!ao_storage_device_read(pos, buf, this_len))
+                       return 0;
+
+               /* See how much is left */
+               buf += this_len;
+               len -= this_len;
+               pos += this_len;
+       }
+       return 1;
+}
+
+uint8_t
+ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
+{
+       uint16_t this_len;
+       uint16_t this_off;
+
+       ao_storage_setup();
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+       while (len) {
+
+               /* Compute portion of transfer within
+                * a single block
+                */
+               this_off = (uint16_t) pos & (ao_storage_unit - 1);
+               this_len = ao_storage_unit - this_off;
+               if (this_len > len)
+                       this_len = len;
+
+               if (!ao_storage_device_write(pos, buf, this_len))
+                       return 0;
+
+               /* See how much is left */
+               buf += this_len;
+               len -= this_len;
+               pos += this_len;
+       }
+       return 1;
+}
+
+static __xdata uint8_t storage_data[8];
+
+static void
+ao_storage_dump(void) __reentrant
+{
+       uint8_t i, j;
+
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       for (i = 0; ; i += 8) {
+               if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i,
+                                 storage_data,
+                                 8)) {
+                       ao_cmd_put16((uint16_t) i);
+                       for (j = 0; j < 8; j++) {
+                               putchar(' ');
+                               ao_cmd_put8(storage_data[j]);
+                       }
+                       putchar ('\n');
+               }
+               if (i == 248)
+                       break;
+       }
+}
+
+#if 0
+
+/* not enough space for this today
+ */
+static void
+ao_storage_store(void) __reentrant
+{
+       uint16_t block;
+       uint8_t i;
+       uint16_t len;
+       static __xdata uint8_t b;
+       uint32_t addr;
+
+       ao_cmd_hex();
+       block = ao_cmd_lex_i;
+       ao_cmd_hex();
+       i = ao_cmd_lex_i;
+       addr = ((uint32_t) block << 8) | i;
+       ao_cmd_hex();
+       len = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       while (len--) {
+               ao_cmd_hex();
+               if (ao_cmd_status != ao_cmd_success)
+                       return;
+               b = ao_cmd_lex_i;
+               ao_storage_write(addr, &b, 1);
+               addr++;
+       }
+}
+#endif
+
+void
+ao_storage_zap(void) __reentrant
+{
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_storage_erase((uint32_t) ao_cmd_lex_i << 8);
+}
+
+void
+ao_storage_zapall(void) __reentrant
+{
+       uint32_t        pos;
+
+       ao_cmd_white();
+       if (!ao_match_word("DoIt"))
+               return;
+       for (pos = 0; pos < ao_storage_config; pos += ao_storage_block)
+               ao_storage_erase(pos);
+}
+
+void
+ao_storage_info(void) __reentrant
+{
+       printf("Storage size: %ld\n", ao_storage_total);
+       printf("Storage erase unit: %ld\n", ao_storage_block);
+       ao_storage_device_info();
+}
+
+__code struct ao_cmds ao_storage_cmds[] = {
+       { ao_storage_info, "f\0Show storage" },
+       { ao_storage_dump, "e <block>\0Dump flash" },
+#ifdef HAS_STORAGE_DBG
+       { ao_storage_store, "w <block> <start> <len> <data> ...\0Write data to flash" },
+#endif
+       { ao_storage_zap, "z <block>\0Erase <block>" },
+       { ao_storage_zapall,"Z <key>\0Erase all. <key> is doit with D&I" },
+       { 0, NULL },
+};
+
+void
+ao_storage_init(void)
+{
+       ao_storage_device_init();
+       ao_cmd_register(&ao_storage_cmds[0]);
+}
diff --git a/src/core/ao_task.c b/src/core/ao_task.c
new file mode 100644 (file)
index 0000000..f5850fa
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#define AO_NO_TASK_INDEX       0xff
+
+__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS];
+__data uint8_t ao_num_tasks;
+__data uint8_t ao_cur_task_index;
+__xdata struct ao_task *__data ao_cur_task;
+
+void
+ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant
+{
+       uint8_t __xdata *stack;
+       uint8_t task_id;
+       uint8_t t;
+       if (ao_num_tasks == AO_NUM_TASKS)
+               ao_panic(AO_PANIC_NO_TASK);
+       for (task_id = 1; task_id != 0; task_id++) {
+               for (t = 0; t < ao_num_tasks; t++)
+                       if (ao_tasks[t]->task_id == task_id)
+                               break;
+               if (t == ao_num_tasks)
+                       break;
+       }
+       ao_tasks[ao_num_tasks++] = task;
+       task->task_id = task_id;
+       task->name = name;
+       /*
+        * Construct a stack frame so that it will 'return'
+        * to the start of the task
+        */
+       stack = task->stack;
+
+       *stack++ = ((uint16_t) start);          /* 0 */
+       *stack++ = ((uint16_t) start) >> 8;     /* 1 */
+
+       /* and the stuff saved by ao_switch */
+       *stack++ = 0;                           /* 2 acc */  
+       *stack++ = 0x80;                        /* 3 IE */
+
+       /*  4 DPL
+        *  5 DPH
+        *  6 B
+        *  7 R2
+        *  8 R3
+        *  9 R4
+        * 10 R5
+        * 11 R6
+        * 12 R7
+        * 13 R0
+        * 14 R1
+        * 15 PSW
+        * 16 BP
+        */
+       for (t = 0; t < 13; t++)
+               *stack++ = 0;
+
+       task->stack_count = 17;
+       task->wchan = NULL;
+}
+
+/* Task switching function. This must not use any stack variables */
+void
+ao_yield(void) __naked
+{
+
+       /* Save current context */
+       _asm
+               /* Push ACC first, as when restoring the context it must be restored
+                * last (it is used to set the IE register). */
+               push    ACC
+               /* Store the IE register then enable interrupts. */
+               push    _IEN0
+               setb    _EA
+               push    DPL
+               push    DPH
+               push    b
+               push    ar2
+               push    ar3
+               push    ar4
+               push    ar5
+               push    ar6
+               push    ar7
+               push    ar0
+               push    ar1
+               push    PSW
+       _endasm;
+       PSW = 0;
+       _asm
+               push    _bp
+       _endasm;
+
+       if (ao_cur_task_index == AO_NO_TASK_INDEX)
+               ao_cur_task_index = ao_num_tasks-1;
+       else
+       {
+               uint8_t stack_len;
+               __data uint8_t *stack_ptr;
+               __xdata uint8_t *save_ptr;
+               /* Save the current stack */
+               stack_len = SP - (AO_STACK_START - 1);
+               ao_cur_task->stack_count = stack_len;
+               stack_ptr = (uint8_t __data *) AO_STACK_START;
+               save_ptr = (uint8_t __xdata *) ao_cur_task->stack;
+               do
+                       *save_ptr++ = *stack_ptr++;
+               while (--stack_len);
+       }
+
+       /* Empty the stack; might as well let interrupts have the whole thing */
+       SP = AO_STACK_START - 1;
+
+       /* Find a task to run. If there isn't any runnable task,
+        * this loop will run forever, which is just fine
+        */
+       {
+               __pdata uint8_t ao_next_task_index = ao_cur_task_index;
+               for (;;) {
+                       ++ao_next_task_index;
+                       if (ao_next_task_index == ao_num_tasks)
+                               ao_next_task_index = 0;
+
+                       ao_cur_task = ao_tasks[ao_next_task_index];
+                       if (ao_cur_task->wchan == NULL) {
+                               ao_cur_task_index = ao_next_task_index;
+                               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) {
+                               ao_cur_task_index = ao_next_task_index;
+                               break;
+                       }
+
+                       /* Enter lower power mode when there isn't anything to do */
+                       if (ao_next_task_index == ao_cur_task_index)
+                               PCON = PCON_IDLE;
+               }
+       }
+
+       {
+               uint8_t stack_len;
+               __data uint8_t *stack_ptr;
+               __xdata uint8_t *save_ptr;
+
+               /* Restore the old stack */
+               stack_len = ao_cur_task->stack_count;
+               SP = AO_STACK_START - 1 + stack_len;
+
+               stack_ptr = (uint8_t __data *) AO_STACK_START;
+               save_ptr = (uint8_t __xdata *) ao_cur_task->stack;
+               do
+                       *stack_ptr++ = *save_ptr++;
+               while (--stack_len);
+       }
+
+       _asm
+               pop             _bp
+               pop             PSW
+               pop             ar1
+               pop             ar0
+               pop             ar7
+               pop             ar6
+               pop             ar5
+               pop             ar4
+               pop             ar3
+               pop             ar2
+               pop             b
+               pop             DPH
+               pop             DPL
+               /* The next byte of the stack is the IE register.  Only the global
+               enable bit forms part of the task context.  Pop off the IE then set
+               the global enable bit to match that of the stored IE register. */
+               pop             ACC
+               JB              ACC.7,0098$
+               CLR             _EA
+               LJMP    0099$
+       0098$:
+               SETB            _EA
+       0099$:
+               /* Finally pop off the ACC, which was the first register saved. */
+               pop             ACC
+               ret
+       _endasm;
+}
+
+uint8_t
+ao_sleep(__xdata void *wchan)
+{
+       __critical {
+               ao_cur_task->wchan = wchan;
+       }
+       ao_yield();
+       ao_cur_task->alarm = 0;
+       if (ao_cur_task->wchan) {
+               ao_cur_task->wchan = NULL;
+               return 1;
+       }
+       return 0;
+}
+
+void
+ao_wakeup(__xdata void *wchan)
+{
+       uint8_t i;
+
+       for (i = 0; i < ao_num_tasks; i++)
+               if (ao_tasks[i]->wchan == wchan)
+                       ao_tasks[i]->wchan = NULL;
+}
+
+void
+ao_alarm(uint16_t delay)
+{
+       /* 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() + delay + 1))
+               ao_cur_task->alarm = 1;
+}
+
+void
+ao_exit(void) __critical
+{
+       uint8_t i;
+       ao_num_tasks--;
+       for (i = ao_cur_task_index; i < ao_num_tasks; i++)
+               ao_tasks[i] = ao_tasks[i+1];
+       ao_cur_task_index = AO_NO_TASK_INDEX;
+       ao_yield();
+       /* we'll never get back here */
+}
+
+void
+ao_task_info(void)
+{
+       uint8_t i;
+       uint8_t pc_loc;
+       __xdata struct ao_task *task;
+
+       for (i = 0; i < ao_num_tasks; i++) {
+               task = ao_tasks[i];
+               pc_loc = task->stack_count - 17;
+               printf("%12s: wchan %04x pc %04x\n",
+                      task->name,
+                      (int16_t) task->wchan,
+                      (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8));
+       }
+}
+
+void
+ao_start_scheduler(void)
+{
+       ao_cur_task_index = AO_NO_TASK_INDEX;
+       ao_cur_task = NULL;
+       ao_yield();
+}
diff --git a/src/core/ao_telem.h b/src/core/ao_telem.h
new file mode 100644 (file)
index 0000000..1a8da29
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_TELEM_H_
+#define _AO_TELEM_H_
+
+#define AO_TELEMETRY_VERSION           4
+
+/*
+ * Telemetry version 4 and higher format:
+ *
+ * General header fields
+ *
+ *     Name            Value
+ *
+ *     VERSION         Telemetry version number (4 or more). Must be first.
+ *     c               Callsign (string, no spaces allowed)
+ *     n               Flight unit serial number (integer)
+ *     f               Flight number (integer)
+ *     r               Packet RSSI value (integer)
+ *     s               Flight computer state (string, no spaces allowed)
+ *     t               Flight computer clock (integer in centiseconds)
+ */
+
+#define AO_TELEM_VERSION       "VERSION"
+#define AO_TELEM_CALL          "c"
+#define AO_TELEM_SERIAL                "n"
+#define AO_TELEM_FLIGHT                "f"
+#define AO_TELEM_RSSI          "r"
+#define AO_TELEM_STATE         "s"
+#define AO_TELEM_TICK          "t"
+
+/*
+ * Raw sensor values
+ *
+ *     Name            Value
+ *     r_a             Accelerometer reading (integer)
+ *     r_b             Barometer reading (integer)
+ *     r_t             Thermometer reading (integer)
+ *     r_v             Battery reading (integer)
+ *     r_d             Drogue continuity (integer)
+ *     r_m             Main continuity (integer)
+ */
+
+#define AO_TELEM_RAW_ACCEL     "r_a"
+#define AO_TELEM_RAW_BARO      "r_b"
+#define AO_TELEM_RAW_THERMO    "r_t"
+#define AO_TELEM_RAW_BATT      "r_v"
+#define AO_TELEM_RAW_DROGUE    "r_d"
+#define AO_TELEM_RAW_MAIN      "r_m"
+
+/*
+ * Sensor calibration values
+ *
+ *     Name            Value
+ *     c_a             Ground accelerometer reading (integer)
+ *     c_b             Ground barometer reading (integer)
+ *     c_p             Accelerometer reading for +1g
+ *     c_m             Accelerometer reading for -1g
+ */
+
+#define AO_TELEM_CAL_ACCEL_GROUND      "c_a"
+#define AO_TELEM_CAL_BARO_GROUND       "c_b"
+#define AO_TELEM_CAL_ACCEL_PLUS                "c_p"
+#define AO_TELEM_CAL_ACCEL_MINUS       "c_m"
+
+/*
+ * Kalman state values
+ *
+ *     Name            Value
+ *     k_h             Height above pad (integer, meters)
+ *     k_s             Vertical speeed (integer, m/s * 16)
+ *     k_a             Vertical acceleration (integer, m/s² * 16)
+ */
+
+#define AO_TELEM_KALMAN_HEIGHT         "k_h"
+#define AO_TELEM_KALMAN_SPEED          "k_s"
+#define AO_TELEM_KALMAN_ACCEL          "k_a"
+
+/*
+ * Ad-hoc flight values
+ *
+ *     Name            Value
+ *     a_a             Acceleration (integer, sensor units)
+ *     a_s             Speed (integer, integrated acceleration value)
+ *     a_b             Barometer reading (integer, sensor units)
+ */
+
+#define AO_TELEM_ADHOC_ACCEL           "a_a"
+#define AO_TELEM_ADHOC_SPEED           "a_s"
+#define AO_TELEM_ADHOC_BARO            "a_b"
+
+/*
+ * GPS values
+ *
+ *     Name            Value
+ *     g               GPS state (string):
+ *                             l       locked
+ *                             u       unlocked
+ *                             e       error (missing or broken)
+ *     g_n             Number of sats used in solution
+ *     g_ns            Latitude (degrees * 10e7)
+ *     g_ew            Longitude (degrees * 10e7)
+ *     g_a             Altitude (integer meters)
+ *     g_Y             GPS year (integer)
+ *     g_M             GPS month (integer - 1-12)
+ *     g_D             GPS day (integer - 1-31)
+ *     g_h             GPS hour (integer - 0-23)
+ *     g_m             GPS minute (integer - 0-59)
+ *     g_s             GPS second (integer - 0-59)
+ *     g_v             GPS vertical speed (integer, cm/sec)
+ *     g_g             GPS horizontal speed (integer, cm/sec)
+ *     g_c             GPS course (integer, 0-359)
+ *     g_hd            GPS hdop (integer * 10)
+ *     g_vd            GPS vdop (integer * 10)
+ *     g_he            GPS h error (integer)
+ *     g_ve            GPS v error (integer)
+ */
+
+#define AO_TELEM_GPS_STATE             "g"
+#define AO_TELEM_GPS_STATE_LOCKED      'l'
+#define AO_TELEM_GPS_STATE_UNLOCKED    'u'
+#define AO_TELEM_GPS_STATE_ERROR       'e'
+#define AO_TELEM_GPS_NUM_SAT           "g_n"
+#define AO_TELEM_GPS_LATITUDE          "g_ns"
+#define AO_TELEM_GPS_LONGITUDE         "g_ew"
+#define AO_TELEM_GPS_ALTITUDE          "g_a"
+#define AO_TELEM_GPS_YEAR              "g_Y"
+#define AO_TELEM_GPS_MONTH             "g_M"
+#define AO_TELEM_GPS_DAY               "g_D"
+#define AO_TELEM_GPS_HOUR              "g_h"
+#define AO_TELEM_GPS_MINUTE            "g_m"
+#define AO_TELEM_GPS_SECOND            "g_s"
+#define AO_TELEM_GPS_VERTICAL_SPEED    "g_v"
+#define AO_TELEM_GPS_HORIZONTAL_SPEED  "g_g"
+#define AO_TELEM_GPS_COURSE            "g_c"
+#define AO_TELEM_GPS_HDOP              "g_hd"
+#define AO_TELEM_GPS_VDOP              "g_vd"
+#define AO_TELEM_GPS_HERROR            "g_he"
+#define AO_TELEM_GPS_VERROR            "g_ve"
+
+/*
+ * GPS satellite values
+ *
+ *     Name            Value
+ *     s_n             Number of satellites reported (integer)
+ *     s_v0            Space vehicle ID (integer) for report 0
+ *     s_c0            C/N0 number (integer) for report 0
+ *     s_v1            Space vehicle ID (integer) for report 1
+ *     s_c1            C/N0 number (integer) for report 1
+ *     ...
+ */
+
+#define AO_TELEM_SAT_NUM               "s_n"
+#define AO_TELEM_SAT_SVID              "s_v"
+#define AO_TELEM_SAT_C_N_0             "s_c"
+
+#endif /* _AO_TELEM_H_ */
diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c
new file mode 100644 (file)
index 0000000..c7338a5
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_product.h"
+
+static __pdata uint16_t ao_telemetry_interval;
+static __pdata int8_t ao_telemetry_config_max;
+static __pdata int8_t ao_telemetry_config_cur;
+#if HAS_GPS
+static __pdata int8_t ao_telemetry_loc_cur;
+static __pdata int8_t ao_telemetry_sat_cur;
+#endif
+#if HAS_COMPANION
+static __pdata int8_t ao_telemetry_companion_max;
+static __pdata int8_t ao_telemetry_companion_cur;
+#endif
+static __pdata uint8_t ao_rdf = 0;
+static __pdata uint16_t ao_rdf_time;
+
+#define AO_RDF_INTERVAL_TICKS  AO_SEC_TO_TICKS(5)
+#define AO_RDF_LENGTH_MS       500
+
+#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1)
+#define AO_TELEMETRY_SENSOR    AO_TELEMETRY_SENSOR_TELEMETRUM
+#endif
+
+#if defined(TELEMINI_V_1_0)
+#define AO_TELEMETRY_SENSOR    AO_TELEMETRY_SENSOR_TELEMINI
+#endif
+
+#if defined(TELENANO_V_0_1)
+#define AO_TELEMETRY_SENSOR    AO_TELEMETRY_SENSOR_TELENANO
+#endif
+
+static __xdata union ao_telemetry_all  telemetry;
+
+/* Send sensor packet */
+static void
+ao_send_sensor(void)
+{
+       uint8_t         sample;
+       sample = ao_sample_adc;
+                       
+       telemetry.generic.tick = ao_adc_ring[sample].tick;
+       telemetry.generic.type = AO_TELEMETRY_SENSOR;
+
+       telemetry.sensor.state = ao_flight_state;
+#if HAS_ACCEL
+       telemetry.sensor.accel = ao_adc_ring[sample].accel;
+#else
+       telemetry.sensor.accel = 0;
+#endif
+       telemetry.sensor.pres = ao_adc_ring[sample].pres;
+       telemetry.sensor.temp = ao_adc_ring[sample].temp;
+       telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt;
+#if HAS_IGNITE
+       telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d;
+       telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m;
+#else
+       telemetry.sensor.sense_d = 0;
+       telemetry.sensor.sense_m = 0;
+#endif
+
+       telemetry.sensor.acceleration = ao_accel;
+       telemetry.sensor.speed = ao_speed;
+       telemetry.sensor.height = ao_height;
+
+       telemetry.sensor.ground_pres = ao_ground_pres;
+#if HAS_ACCEL
+       telemetry.sensor.ground_accel = ao_ground_accel;
+       telemetry.sensor.accel_plus_g = ao_config.accel_plus_g;
+       telemetry.sensor.accel_minus_g = ao_config.accel_minus_g;
+#else
+       telemetry.sensor.ground_accel = 0;
+       telemetry.sensor.accel_plus_g = 0;
+       telemetry.sensor.accel_minus_g = 0;
+#endif
+
+       ao_radio_send(&telemetry, sizeof (telemetry));
+}
+
+static void
+ao_send_configuration(void)
+{
+       if (--ao_telemetry_config_cur <= 0)
+       {
+               telemetry.generic.type = AO_TELEMETRY_CONFIGURATION;
+               telemetry.configuration.device = AO_idProduct_NUMBER;
+               telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number;
+               telemetry.configuration.config_major = AO_CONFIG_MAJOR;
+               telemetry.configuration.config_minor = AO_CONFIG_MINOR;
+               telemetry.configuration.apogee_delay = ao_config.apogee_delay;
+               telemetry.configuration.main_deploy = ao_config.main_deploy;
+               telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10;
+               memcpy (telemetry.configuration.callsign,
+                       ao_config.callsign,
+                       AO_MAX_CALLSIGN);
+               memcpy (telemetry.configuration.version,
+                       ao_version,
+                       AO_MAX_VERSION);
+               ao_radio_send(&telemetry, sizeof (telemetry));
+               ao_telemetry_config_cur = ao_telemetry_config_max;
+       }
+}
+
+#if HAS_GPS
+static void
+ao_send_location(void)
+{
+       if (--ao_telemetry_loc_cur <= 0)
+       {
+               telemetry.generic.type = AO_TELEMETRY_LOCATION;
+               ao_mutex_get(&ao_gps_mutex);
+               memcpy(&telemetry.location.flags,
+                      &ao_gps_data.flags,
+                      26);
+               ao_mutex_put(&ao_gps_mutex);
+               ao_radio_send(&telemetry, sizeof (telemetry));
+               ao_telemetry_loc_cur = ao_telemetry_config_max;
+       }
+}
+
+static void
+ao_send_satellite(void)
+{
+       if (--ao_telemetry_sat_cur <= 0)
+       {
+               telemetry.generic.type = AO_TELEMETRY_SATELLITE;
+               ao_mutex_get(&ao_gps_mutex);
+               telemetry.satellite.channels = ao_gps_tracking_data.channels;
+               memcpy(&telemetry.satellite.sats,
+                      &ao_gps_tracking_data.sats,
+                      AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info));
+               ao_mutex_put(&ao_gps_mutex);
+               ao_radio_send(&telemetry, sizeof (telemetry));
+               ao_telemetry_sat_cur = ao_telemetry_config_max;
+       }
+}
+#endif
+
+#if HAS_COMPANION
+static void
+ao_send_companion(void)
+{
+       if (--ao_telemetry_companion_cur <= 0) {
+               telemetry.generic.type = AO_TELEMETRY_COMPANION;
+               telemetry.companion.board_id = ao_companion_setup.board_id;
+               telemetry.companion.update_period = ao_companion_setup.update_period;
+               telemetry.companion.channels = ao_companion_setup.channels;
+               ao_mutex_get(&ao_companion_mutex);
+               memcpy(&telemetry.companion.companion_data,
+                      ao_companion_data,
+                      ao_companion_setup.channels * 2);
+               ao_mutex_put(&ao_companion_mutex);
+               ao_radio_send(&telemetry, sizeof (telemetry));
+               ao_telemetry_companion_cur = ao_telemetry_companion_max;
+       }
+}
+#endif
+
+void
+ao_telemetry(void)
+{
+       uint16_t        time;
+       int16_t         delay;
+
+       ao_config_get();
+       if (!ao_config.radio_enable)
+               ao_exit();
+       while (!ao_flight_number)
+               ao_sleep(&ao_flight_number);
+
+       telemetry.generic.serial = ao_serial_number;
+       for (;;) {
+               while (ao_telemetry_interval == 0)
+                       ao_sleep(&telemetry);
+               time = ao_rdf_time = ao_time();
+               while (ao_telemetry_interval) {
+
+
+                       ao_send_sensor();
+#if HAS_COMPANION
+                       if (ao_companion_running)
+                               ao_send_companion();
+#endif
+                       ao_send_configuration();
+#if HAS_GPS
+                       ao_send_location();
+                       ao_send_satellite();
+#endif
+                       if (ao_rdf &&
+                           (int16_t) (ao_time() - ao_rdf_time) >= 0)
+                       {
+                               ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;
+                               ao_radio_rdf(AO_RDF_LENGTH_MS);
+                       }
+                       time += ao_telemetry_interval;
+                       delay = time - ao_time();
+                       if (delay > 0)
+                               ao_delay(delay);
+                       else
+                               time = ao_time();
+               }
+       }
+}
+
+void
+ao_telemetry_set_interval(uint16_t interval)
+{
+       ao_telemetry_interval = interval;
+
+#if HAS_COMPANION
+       if (!ao_companion_setup.update_period)
+               ao_companion_setup.update_period = AO_SEC_TO_TICKS(1);
+       ao_telemetry_companion_max = ao_companion_setup.update_period / interval;
+       ao_telemetry_companion_cur = 1;
+#endif
+
+       ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval;
+#if HAS_COMPANION
+       ao_telemetry_config_cur = ao_telemetry_companion_cur;
+       if (ao_telemetry_config_max > ao_telemetry_config_cur)
+               ao_telemetry_config_cur++;
+#else
+       ao_telemetry_config_cur = 1;
+#endif
+
+#if HAS_GPS
+       ao_telemetry_loc_cur = ao_telemetry_config_cur;
+       if (ao_telemetry_config_max > ao_telemetry_loc_cur)
+               ao_telemetry_loc_cur++;
+       ao_telemetry_sat_cur = ao_telemetry_loc_cur;
+       if (ao_telemetry_config_max > ao_telemetry_sat_cur)
+               ao_telemetry_sat_cur++;
+#endif
+       ao_wakeup(&telemetry);
+}
+
+void
+ao_rdf_set(uint8_t rdf)
+{
+       ao_rdf = rdf;
+       if (rdf == 0)
+               ao_radio_rdf_abort();
+       else
+               ao_rdf_time = ao_time();
+}
+
+__xdata struct ao_task ao_telemetry_task;
+
+void
+ao_telemetry_init()
+{
+       ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry");
+}
diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c
new file mode 100644 (file)
index 0000000..738f8ce
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_25lc1024.h"
+
+#define EE_BLOCK_SIZE  ((uint16_t) (256))
+#define EE_BLOCK_SHIFT 8
+#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024)
+
+/* Total bytes of available storage */
+__pdata uint32_t       ao_storage_total;
+
+/* Block size - device is erased in these units. At least 256 bytes */
+__pdata uint32_t       ao_storage_block;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+__pdata uint32_t       ao_storage_config;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
+__pdata uint16_t       ao_storage_unit;
+
+/*
+ * Using SPI on USART 0, with P1_2 as the chip select
+ */
+
+#define EE_CS          P1_2
+#define EE_CS_INDEX    2
+
+static __xdata uint8_t ao_ee_mutex;
+
+#define ao_ee_delay() do { \
+       _asm nop _endasm; \
+       _asm nop _endasm; \
+       _asm nop _endasm; \
+} while(0)
+
+#define ao_ee_cs_low() ao_spi_get_bit(EE_CS)
+
+#define ao_ee_cs_high()        ao_spi_put_bit(EE_CS)
+
+struct ao_ee_instruction {
+       uint8_t instruction;
+       uint8_t address[3];
+} __xdata ao_ee_instruction;
+
+static void
+ao_ee_write_enable(void)
+{
+       ao_ee_cs_low();
+       ao_ee_instruction.instruction = EE_WREN;
+       ao_spi_send(&ao_ee_instruction, 1);
+       ao_ee_cs_high();
+}
+
+static uint8_t
+ao_ee_rdsr(void)
+{
+       ao_ee_cs_low();
+       ao_ee_instruction.instruction = EE_RDSR;
+       ao_spi_send(&ao_ee_instruction, 1);
+       ao_spi_recv(&ao_ee_instruction, 1);
+       ao_ee_cs_high();
+       return ao_ee_instruction.instruction;
+}
+
+static void
+ao_ee_wrsr(uint8_t status)
+{
+       ao_ee_cs_low();
+       ao_ee_instruction.instruction = EE_WRSR;
+       ao_ee_instruction.address[0] = status;
+       ao_spi_send(&ao_ee_instruction, 2);
+       ao_ee_cs_high();
+}
+
+#define EE_BLOCK_NONE  0xffff
+
+static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE];
+static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE;
+static __pdata uint8_t ao_ee_block_dirty;
+
+/* Write the current block to the EEPROM */
+static void
+ao_ee_write_block(void)
+{
+       uint8_t status;
+
+       status = ao_ee_rdsr();
+       if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) {
+               status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN);
+               ao_ee_wrsr(status);
+       }
+       ao_ee_write_enable();
+       ao_ee_cs_low();
+       ao_ee_instruction.instruction = EE_WRITE;
+       ao_ee_instruction.address[0] = ao_ee_block >> 8;
+       ao_ee_instruction.address[1] = ao_ee_block;
+       ao_ee_instruction.address[2] = 0;
+       ao_spi_send(&ao_ee_instruction, 4);
+       ao_spi_send(ao_ee_data, EE_BLOCK_SIZE);
+       ao_ee_cs_high();
+       for (;;) {
+               uint8_t status = ao_ee_rdsr();
+               if ((status & EE_STATUS_WIP) == 0)
+                       break;
+       }
+}
+
+/* Read the current block from the EEPROM */
+static void
+ao_ee_read_block(void)
+{
+       ao_ee_cs_low();
+       ao_ee_instruction.instruction = EE_READ;
+       ao_ee_instruction.address[0] = ao_ee_block >> 8;
+       ao_ee_instruction.address[1] = ao_ee_block;
+       ao_ee_instruction.address[2] = 0;
+       ao_spi_send(&ao_ee_instruction, 4);
+       ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE);
+       ao_ee_cs_high();
+}
+
+static void
+ao_ee_flush_internal(void)
+{
+       if (ao_ee_block_dirty) {
+               ao_ee_write_block();
+               ao_ee_block_dirty = 0;
+       }
+}
+
+static void
+ao_ee_fill(uint16_t block)
+{
+       if (block != ao_ee_block) {
+               ao_ee_flush_internal();
+               ao_ee_block = block;
+               ao_ee_read_block();
+       }
+}
+
+uint8_t
+ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
+{
+       uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
+
+       /* Transfer the data */
+       ao_mutex_get(&ao_ee_mutex); {
+               if (len != EE_BLOCK_SIZE)
+                       ao_ee_fill(block);
+               else {
+                       ao_ee_flush_internal();
+                       ao_ee_block = block;
+               }
+               memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len);
+               ao_ee_block_dirty = 1;
+       } ao_mutex_put(&ao_ee_mutex);
+       return 1;
+}
+
+uint8_t
+ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
+{
+       uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
+
+       /* Transfer the data */
+       ao_mutex_get(&ao_ee_mutex); {
+               ao_ee_fill(block);
+               memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len);
+       } ao_mutex_put(&ao_ee_mutex);
+       return 1;
+}
+
+void
+ao_storage_flush(void) __reentrant
+{
+       ao_mutex_get(&ao_ee_mutex); {
+               ao_ee_flush_internal();
+       } ao_mutex_put(&ao_ee_mutex);
+}
+
+uint8_t
+ao_storage_erase(uint32_t pos) __reentrant
+{
+       ao_mutex_get(&ao_ee_mutex); {
+               ao_ee_flush_internal();
+               ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT);
+               memset(ao_ee_data, 0xff, EE_BLOCK_SIZE);
+               ao_ee_block_dirty = 1;
+       } ao_mutex_put(&ao_ee_mutex);
+       return 1;
+}
+
+static void
+ee_store(void) __reentrant
+{
+}
+
+void
+ao_storage_setup(void)
+{
+       if (ao_storage_total == 0) {
+               ao_storage_total = EE_DEVICE_SIZE;
+               ao_storage_block = EE_BLOCK_SIZE;
+               ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE;
+               ao_storage_unit = EE_BLOCK_SIZE;
+       }
+}
+
+void
+ao_storage_device_info(void) __reentrant
+{
+}
+
+/*
+ * To initialize the chip, set up the CS line and
+ * the SPI interface
+ */
+void
+ao_storage_device_init(void)
+{
+       /* set up CS */
+       EE_CS = 1;
+       P1DIR |= (1 << EE_CS_INDEX);
+       P1SEL &= ~(1 << EE_CS_INDEX);
+}
diff --git a/src/drivers/ao_25lc1024.h b/src/drivers/ao_25lc1024.h
new file mode 100644 (file)
index 0000000..44e5238
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */
+
+#ifndef _25LC1024_H_
+#define _25LC1024_H_
+
+#define EE_READ                0x03
+#define EE_WRITE       0x02
+#define EE_WREN                0x06
+#define EE_WRDI                0x04
+#define EE_RDSR                0x05
+#define EE_WRSR                0x01
+#define EE_PE          0x42
+#define EE_SE          0xd8
+#define EE_CE          0xc7
+#define EE_RDID                0xab
+#define EE_DPD         0xb9
+
+#define EE_STATUS_WIP  (1 << 0)
+#define EE_STATUS_WEL  (1 << 1)
+#define EE_STATUS_BP0  (1 << 2)
+#define EE_STATUS_BP1  (1 << 3)
+#define EE_STATUS_WPEN (1 << 7)
+
+#endif /* _25LC1024_H_ */
diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c
new file mode 100644 (file)
index 0000000..aee9877
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_at45db161d.h"
+
+/* Total bytes of available storage */
+__pdata uint32_t       ao_storage_total;
+
+/* Block size - device is erased in these units. At least 256 bytes */
+__pdata uint32_t       ao_storage_block;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+__pdata uint32_t       ao_storage_config;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
+__pdata uint16_t       ao_storage_unit;
+
+#define FLASH_CS               P1_1
+#define FLASH_CS_INDEX         1
+
+#define FLASH_BLOCK_SIZE_MAX   512
+
+__xdata uint8_t ao_flash_mutex;
+
+#define ao_flash_delay() do { \
+       _asm nop _endasm; \
+       _asm nop _endasm; \
+       _asm nop _endasm; \
+} while(0)
+
+#define ao_flash_cs_low()      ao_spi_get_bit(FLASH_CS)
+
+#define ao_flash_cs_high()     ao_spi_put_bit(FLASH_CS)
+
+struct ao_flash_instruction {
+       uint8_t instruction;
+       uint8_t address[3];
+} __xdata ao_flash_instruction;
+
+static void
+ao_flash_set_pagesize_512(void)
+{
+       ao_flash_cs_low();
+       ao_flash_instruction.instruction = FLASH_SET_CONFIG;
+       ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0;
+       ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1;
+       ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2;
+       ao_spi_send(&ao_flash_instruction, 4);
+       ao_flash_cs_high();
+}
+
+
+static uint8_t
+ao_flash_read_status(void)
+{
+       ao_flash_cs_low();
+       ao_flash_instruction.instruction = FLASH_READ_STATUS;
+       ao_spi_send(&ao_flash_instruction, 1);
+       ao_spi_recv(&ao_flash_instruction, 1);
+       ao_flash_cs_high();
+       return ao_flash_instruction.instruction;
+}
+
+#define FLASH_BLOCK_NONE       0xffff
+
+static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX];
+static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE;
+static __pdata uint8_t ao_flash_block_dirty;
+static __pdata uint8_t  ao_flash_write_pending;
+static __pdata uint8_t ao_flash_setup_done;
+static __pdata uint8_t ao_flash_block_shift;
+static __pdata uint16_t        ao_flash_block_size;
+static __pdata uint16_t        ao_flash_block_mask;
+
+void
+ao_storage_setup(void) __reentrant
+{
+       uint8_t status;
+
+       if (ao_flash_setup_done)
+               return;
+
+       ao_mutex_get(&ao_flash_mutex);
+       if (ao_flash_setup_done) {
+               ao_mutex_put(&ao_flash_mutex);
+               return;
+       }
+
+       /* On first use, check to see if the flash chip has
+        * been programmed to use 512 byte pages. If not, do so.
+        * And then, because the flash part must be power cycled
+        * for that change to take effect, panic.
+        */
+       status = ao_flash_read_status();
+
+       if (!(status & FLASH_STATUS_PAGESIZE_512)) {
+               ao_flash_set_pagesize_512();
+               ao_panic(AO_PANIC_FLASH);
+       }
+
+       switch (status & 0x3c) {
+
+       /* AT45DB321D */
+       case 0x34:
+               ao_flash_block_shift = 9;
+               ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024);
+               break;
+
+       /* AT45DB161D */
+       case 0x2c:
+               ao_flash_block_shift = 9;
+               ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024);
+               break;
+
+       /* AT45DB081D */
+       case 0x24:
+               ao_flash_block_shift = 8;
+               ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024);
+               break;
+
+       /* AT45DB041D */
+       case 0x1c:
+               ao_flash_block_shift = 8;
+               ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024);
+               break;
+
+       /* AT45DB021D */
+       case 0x14:
+               ao_flash_block_shift = 8;
+               ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024);
+               break;
+
+       /* AT45DB011D */
+       case 0x0c:
+               ao_flash_block_shift = 8;
+               ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024);
+               break;
+
+       default:
+               ao_panic(AO_PANIC_FLASH);
+       }
+       ao_flash_block_size = 1 << ao_flash_block_shift;
+       ao_flash_block_mask = ao_flash_block_size - 1;
+
+       ao_storage_block = ao_flash_block_size;
+       ao_storage_config = ao_storage_total - ao_storage_block;
+       ao_storage_unit = ao_flash_block_size;
+
+       ao_flash_setup_done = 1;
+       ao_mutex_put(&ao_flash_mutex);
+}
+
+static void
+ao_flash_wait_write(void)
+{
+       if (ao_flash_write_pending) {
+               for (;;) {
+                       uint8_t status = ao_flash_read_status();
+                       if ((status & FLASH_STATUS_RDY))
+                               break;
+               }
+               ao_flash_write_pending = 0;
+       }
+}
+
+/* Write the current block to the FLASHPROM */
+static void
+ao_flash_write_block(void)
+{
+       ao_flash_wait_write();
+       ao_flash_cs_low();
+       ao_flash_instruction.instruction = FLASH_WRITE;
+
+       /* 13/14 block bits + 9/8 byte bits (always 0) */
+       ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
+       ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
+       ao_flash_instruction.address[2] = 0;
+       ao_spi_send(&ao_flash_instruction, 4);
+       ao_spi_send(ao_flash_data, ao_storage_block);
+       ao_flash_cs_high();
+       ao_flash_write_pending = 1;
+}
+
+/* Read the current block from the FLASHPROM */
+static void
+ao_flash_read_block(void)
+{
+       ao_flash_wait_write();
+       ao_flash_cs_low();
+       ao_flash_instruction.instruction = FLASH_READ;
+
+       /* 13/14 block bits + 9/8 byte bits (always 0) */
+       ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
+       ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
+       ao_flash_instruction.address[2] = 0;
+       ao_spi_send(&ao_flash_instruction, 4);
+       ao_spi_recv(ao_flash_data, ao_flash_block_size);
+       ao_flash_cs_high();
+}
+
+static void
+ao_flash_flush_internal(void)
+{
+       if (ao_flash_block_dirty) {
+               ao_flash_write_block();
+               ao_flash_block_dirty = 0;
+       }
+}
+
+static void
+ao_flash_fill(uint16_t block)
+{
+       if (block != ao_flash_block) {
+               ao_flash_flush_internal();
+               ao_flash_block = block;
+               ao_flash_read_block();
+       }
+}
+
+uint8_t
+ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
+{
+       uint16_t block = (uint16_t) (pos >> ao_flash_block_shift);
+
+       /* Transfer the data */
+       ao_mutex_get(&ao_flash_mutex); {
+               if (len != ao_flash_block_size)
+                       ao_flash_fill(block);
+               else {
+                       ao_flash_flush_internal();
+                       ao_flash_block = block;
+               }
+               memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
+                      buf,
+                      len);
+               ao_flash_block_dirty = 1;
+       } ao_mutex_put(&ao_flash_mutex);
+       return 1;
+}
+
+uint8_t
+ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
+{
+       uint16_t block = (uint16_t) (pos >> ao_flash_block_shift);
+
+       /* Transfer the data */
+       ao_mutex_get(&ao_flash_mutex); {
+               ao_flash_fill(block);
+               memcpy(buf,
+                      ao_flash_data + (uint16_t) (pos & ao_flash_block_mask),
+                      len);
+       } ao_mutex_put(&ao_flash_mutex);
+       return 1;
+}
+
+void
+ao_storage_flush(void) __reentrant
+{
+       ao_mutex_get(&ao_flash_mutex); {
+               ao_flash_flush_internal();
+       } ao_mutex_put(&ao_flash_mutex);
+}
+
+uint8_t
+ao_storage_erase(uint32_t pos) __reentrant
+{
+       ao_mutex_get(&ao_flash_mutex); {
+               ao_flash_flush_internal();
+               ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift);
+               memset(ao_flash_data, 0xff, ao_flash_block_size);
+               ao_flash_block_dirty = 1;
+       } ao_mutex_put(&ao_flash_mutex);
+       return 1;
+}
+
+void
+ao_storage_device_info(void) __reentrant
+{
+       uint8_t status;
+
+       ao_storage_setup();
+       ao_mutex_get(&ao_flash_mutex); {
+               status = ao_flash_read_status();
+               printf ("Flash status: 0x%02x\n", status);
+               printf ("Flash block shift: %d\n", ao_flash_block_shift);
+               printf ("Flash block size: %d\n", ao_flash_block_size);
+               printf ("Flash block mask: %d\n", ao_flash_block_mask);
+               printf ("Flash device size: %ld\n", ao_storage_total);
+       } ao_mutex_put(&ao_flash_mutex);
+}
+
+/*
+ * To initialize the chip, set up the CS line and
+ * the SPI interface
+ */
+void
+ao_storage_device_init(void)
+{
+       /* set up CS */
+       FLASH_CS = 1;
+       P1DIR |= (1 << FLASH_CS_INDEX);
+       P1SEL &= ~(1 << FLASH_CS_INDEX);
+}
diff --git a/src/drivers/ao_at45db161d.h b/src/drivers/ao_at45db161d.h
new file mode 100644 (file)
index 0000000..9ee6f1b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */
+
+#ifndef _AT45DB161D_H_
+#define _AT45DB161D_H_
+
+/*
+ * We reserve the last block on the device for
+ * configuration space. Writes and reads in this
+ * area return errors.
+ */
+
+
+#define FLASH_READ             0x03
+#define FLASH_WRITE            0x82
+#define FLASH_PAGE_ERASE       0x81
+#define FLASH_READ_STATUS      0xd7
+#define FLASH_SET_CONFIG       0x3d
+
+#define FLASH_SET_512_BYTE_0   0x2a
+#define FLASH_SET_512_BYTE_1   0x80
+#define FLASH_SET_512_BYTE_2   0xa6
+
+#define FLASH_STATUS_RDY               (1 << 7)
+#define FLASH_STATUS_COMP              (1 << 6)
+#define FLASH_STATUS_PROTECT           (1 << 1)
+#define FLASH_STATUS_PAGESIZE_512      (1 << 0)
+
+#endif /* _AT45DB161D_H_ */
diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c
new file mode 100644 (file)
index 0000000..44155ec
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+int8_t                 ao_btm_stdio;
+__xdata uint8_t                ao_btm_connected;
+
+#define AO_BTM_MAX_REPLY       16
+__xdata char           ao_btm_reply[AO_BTM_MAX_REPLY];
+
+extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo;
+
+/*
+ * Read a line of data from the serial port, truncating
+ * it after a few characters.
+ */
+
+uint8_t
+ao_btm_get_line(void)
+{
+       uint8_t ao_btm_reply_len = 0;
+       char c;
+
+       for (;;) {
+
+               while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) {
+                       if (ao_btm_reply_len < sizeof (ao_btm_reply))
+                               ao_btm_reply[ao_btm_reply_len++] = c;
+                       if (c == '\r' || c == '\n')
+                               goto done;
+               }
+               for (c = 0; c < 10; c++) {
+                       ao_delay(AO_MS_TO_TICKS(10));
+                       if (!ao_fifo_empty(ao_usart1_rx_fifo))
+                               break;
+               }
+               if (c == 10)
+                       goto done;
+       }
+done:
+       for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
+               ao_btm_reply[c++] = '\0';
+       return ao_btm_reply_len;
+}
+
+/*
+ * Drain the serial port completely
+ */
+void
+ao_btm_drain()
+{
+       while (ao_btm_get_line())
+               ;
+}
+
+/*
+ * Set the stdio echo for the bluetooth link
+ */
+void
+ao_btm_echo(uint8_t echo)
+{
+       ao_stdios[ao_btm_stdio].echo = echo;
+}
+
+/*
+ * Delay between command charaters; the BT module
+ * can't keep up with 57600 baud
+ */
+
+void
+ao_btm_putchar(char c)
+{
+       ao_serial_putchar(c);
+       ao_delay(1);
+}
+
+/*
+ * Wait for the bluetooth device to return
+ * status from the previously executed command
+ */
+uint8_t
+ao_btm_wait_reply(void)
+{
+       for (;;) {
+               ao_btm_get_line();
+               if (!strncmp(ao_btm_reply, "OK", 2))
+                       return 1;
+               if (!strncmp(ao_btm_reply, "ERROR", 5))
+                       return -1;
+               if (ao_btm_reply[0] == '\0')
+                       return 0;
+       }
+}
+
+void
+ao_btm_string(__code char *cmd)
+{
+       char    c;
+
+       while (c = *cmd++)
+               ao_btm_putchar(c);
+}
+
+uint8_t
+ao_btm_cmd(__code char *cmd)
+{
+       ao_btm_drain();
+       ao_btm_string(cmd);
+       return ao_btm_wait_reply();
+}
+
+uint8_t
+ao_btm_set_name(void)
+{
+       char    sn[8];
+       char    *s = sn + 8;
+       char    c;
+       int     n;
+       ao_btm_string("ATN=TeleBT-");
+       *--s = '\0';
+       *--s = '\r';
+       n = ao_serial_number;
+       do {
+               *--s = '0' + n % 10;
+       } while (n /= 10);
+       while ((c = *s++))
+               ao_btm_putchar(c);
+       return ao_btm_wait_reply();
+}
+
+uint8_t
+ao_btm_try_speed(uint8_t speed)
+{
+       ao_serial_set_speed(speed);
+       ao_btm_drain();
+       (void) ao_btm_cmd("\rATE0\rATQ0\r");
+       if (ao_btm_cmd("AT\r") == 1)
+               return 1;
+       return 0;
+}
+
+/*
+ * A thread to initialize the bluetooth device and
+ * hang around to blink the LED when connected
+ */
+void
+ao_btm(void)
+{
+       /*
+        * Wait for the bluetooth device to boot
+        */
+       ao_delay(AO_SEC_TO_TICKS(3));
+
+#if HAS_BEEP
+       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+#endif
+
+       /*
+        * The first time we connect, the BTM-180 comes up at 19200 baud.
+        * After that, it will remember and come up at 57600 baud. So, see
+        * if it is already running at 57600 baud, and if that doesn't work
+        * then tell it to switch to 57600 from 19200 baud.
+        */
+       while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) {
+               ao_delay(AO_SEC_TO_TICKS(1));
+               if (ao_btm_try_speed(AO_SERIAL_SPEED_19200))
+                       ao_btm_cmd("ATL4\r");
+               ao_delay(AO_SEC_TO_TICKS(1));
+       }
+
+       /* Disable echo */
+       ao_btm_cmd("ATE0\r");
+
+       /* Enable flow control */
+       ao_btm_cmd("ATC1\r");
+
+       /* Set the reported name to something we can find on the host */
+       ao_btm_set_name();
+
+       /* Turn off status reporting */
+       ao_btm_cmd("ATQ1\r");
+
+       ao_btm_stdio = ao_add_stdio(ao_serial_pollchar,
+                                   ao_serial_putchar,
+                                   NULL);
+       ao_btm_echo(0);
+
+       for (;;) {
+               while (!ao_btm_connected)
+                       ao_sleep(&ao_btm_connected);
+               while (ao_btm_connected) {
+                       ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20));
+                       ao_delay(AO_SEC_TO_TICKS(3));
+               }
+       }
+}
+
+__xdata struct ao_task ao_btm_task;
+
+#if BT_LINK_ON_P2
+#define BT_PICTL_ICON  PICTL_P2ICON
+#define BT_PIFG                P2IFG
+#define BT_PDIR                P2DIR
+#define BT_PINP                P2INP
+#define BT_IEN2_PIE    IEN2_P2IE
+#endif
+#if BT_LINK_ON_P1
+#define BT_PICTL_ICON  PICTL_P1ICON
+#define BT_PIFG                P1IFG
+#define BT_PDIR                P1DIR
+#define BT_PINP                P1INP
+#define BT_IEN2_PIE    IEN2_P1IE
+#endif
+
+void
+ao_btm_check_link() __critical
+{
+       /* Check the pin and configure the interrupt detector to wait for the
+        * pin to flip the other way
+        */
+       if (BT_LINK_PIN) {
+               ao_btm_connected = 0;
+               PICTL |= BT_PICTL_ICON;
+       } else {
+               ao_btm_connected = 1;
+               PICTL &= ~BT_PICTL_ICON;
+       }
+}
+
+void
+ao_btm_isr(void)
+#if BT_LINK_ON_P1
+       __interrupt 15
+#endif
+{
+#if BT_LINK_ON_P1
+       P1IF = 0;
+#endif
+       if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) {
+               ao_btm_check_link();
+               ao_wakeup(&ao_btm_connected);
+       }
+       BT_PIFG = 0;
+}
+
+void
+ao_btm_init (void)
+{
+       ao_serial_init();
+       ao_serial_set_speed(AO_SERIAL_SPEED_19200);
+
+#if BT_LINK_ON_P1
+       /*
+        * Configure ser reset line
+        */
+
+       P1_6 = 0;
+       P1DIR |= (1 << 6);
+#endif
+
+       /*
+        * Configure link status line
+        */
+
+       /* Set pin to input */
+       BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX);
+
+       /* Set pin to tri-state */
+       BT_PINP |= (1 << BT_LINK_PIN_INDEX);
+
+       /* Enable interrupts */
+       IEN2 |= BT_IEN2_PIE;
+
+       /* Check current pin state */
+       ao_btm_check_link();
+
+#if BT_LINK_ON_P2
+       /* Eable the pin interrupt */
+       PICTL |= PICTL_P2IEN;
+#endif
+#if BT_LINK_ON_P1
+       /* Enable pin interrupt */
+       P1IEN |= (1 << BT_LINK_PIN_INDEX);
+#endif
+
+       ao_add_task(&ao_btm_task, ao_btm, "bt");
+}
diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c
new file mode 100644 (file)
index 0000000..4c8f426
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE |          \
+                               UxGCR_CPHA_FIRST_EDGE |         \
+                               UxGCR_ORDER_MSB |               \
+                               (13 << UxGCR_BAUD_E_SHIFT)))
+
+#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE |          \
+                               UxGCR_CPHA_FIRST_EDGE |         \
+                               UxGCR_ORDER_MSB |               \
+                               (17 << UxGCR_BAUD_E_SHIFT)))
+
+#define COMPANION_SELECT()     do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0)
+#define COMPANION_DESELECT()   do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0)
+
+static __xdata struct ao_companion_command     ao_companion_command;
+__xdata struct ao_companion_setup              ao_companion_setup;
+
+__xdata uint16_t       ao_companion_data[AO_COMPANION_MAX_CHANNELS];
+__pdata uint8_t                ao_companion_running;
+__xdata uint8_t                ao_companion_mutex;
+
+static void
+ao_companion_send_command(uint8_t command)
+{
+       ao_companion_command.command = command;
+       ao_companion_command.flight_state = ao_flight_state;
+       ao_companion_command.tick = ao_time();
+       ao_companion_command.serial = ao_serial_number;
+       ao_companion_command.flight = ao_flight_number;
+       ao_spi_send(&ao_companion_command, sizeof (ao_companion_command));
+}
+
+static uint8_t
+ao_companion_get_setup(void)
+{
+       COMPANION_SELECT();
+       ao_companion_send_command(AO_COMPANION_SETUP);
+       ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup));
+       COMPANION_DESELECT();
+       return (ao_companion_setup.board_id ==
+               ~ao_companion_setup.board_id_inverse);
+}
+
+static void
+ao_companion_get_data(void)
+{
+       COMPANION_SELECT();
+       ao_companion_send_command(AO_COMPANION_FETCH);
+       ao_mutex_get(&ao_companion_mutex);
+       ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2);
+       ao_mutex_put(&ao_companion_mutex);
+       COMPANION_DESELECT();
+}
+
+static void
+ao_companion_notify(void)
+{
+       COMPANION_SELECT();
+       ao_companion_send_command(AO_COMPANION_NOTIFY);
+       COMPANION_DESELECT();
+}
+
+void
+ao_companion(void)
+{
+       uint8_t i;
+       while (!ao_flight_number)
+               ao_sleep(&ao_flight_number);
+       for (i = 0; i < 10; i++) {
+               ao_delay(AO_SEC_TO_TICKS(1));
+               if ((ao_companion_running = ao_companion_get_setup()))
+                   break;
+       }
+       while (ao_companion_running) {
+               ao_alarm(ao_companion_setup.update_period);
+               if (ao_sleep(DATA_TO_XDATA(&ao_flight_state)))
+                       ao_companion_get_data();
+               else
+                       ao_companion_notify();
+       }
+       ao_exit();
+}
+
+void
+ao_companion_status(void) __reentrant
+{
+       uint8_t i;
+       printf("Companion running: %d\n", ao_companion_running);
+       printf("device: %d\n", ao_companion_setup.board_id);
+       printf("update period: %d\n", ao_companion_setup.update_period);
+       printf("channels: %d\n", ao_companion_setup.channels);
+       printf("data:");
+       for(i = 0; i < ao_companion_setup.channels; i++)
+               printf(" %5u", ao_companion_data[i]);
+       printf("\n");
+}
+
+__code struct ao_cmds ao_companion_cmds[] = {
+       { ao_companion_status,  "L\0Companion link status" },
+       { 0, NULL },
+};
+
+static __xdata struct ao_task ao_companion_task;
+
+void
+ao_companion_init(void)
+{
+       COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */
+       COMPANION_CS_DIR |= COMPANION_CS_MASK;  /* set CS pins as outputs */
+       COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */
+
+       ao_cmd_register(&ao_companion_cmds[0]);
+       ao_add_task(&ao_companion_task, ao_companion, "companion");
+}
diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c
new file mode 100644 (file)
index 0000000..f2abbf8
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef AO_GPS_TEST
+#include "ao.h"
+#endif
+
+__xdata uint8_t ao_gps_mutex;
+__pdata uint16_t ao_gps_tick;
+__xdata struct ao_telemetry_location   ao_gps_data;
+__xdata struct ao_telemetry_satellite  ao_gps_tracking_data;
+
+static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n";
+
+const char ao_gps_config[] = {
+
+       0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */
+       136,                    /* mode control */
+       0, 0,                   /* reserved */
+       0,                      /* degraded mode (allow 1-SV navigation) */
+       0, 0,                   /* reserved */
+       0, 0,                   /* user specified altitude */
+       2,                      /* alt hold mode (disabled, require 3d fixes) */
+       0,                      /* alt hold source (use last computed altitude) */
+       0,                      /* reserved */
+       10,                     /* Degraded time out (10 sec) */
+       10,                     /* Dead Reckoning time out (10 sec) */
+       0,                      /* Track smoothing (disabled) */
+       0x00, 0x8e, 0xb0, 0xb3,
+
+       0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */
+       166,                    /* Set message rate */
+       2,                      /* enable/disable all messages */
+       0,                      /* message id (ignored) */
+       0,                      /* update rate (0 = disable) */
+       0, 0, 0, 0,             /* reserved */
+       0x00, 0xa8, 0xb0, 0xb3,
+
+       0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */
+       143,                    /* static navigation */
+       0,                      /* disable */
+       0x00, 0x8f, 0xb0, 0xb3,
+};
+
+#define NAV_TYPE_GPS_FIX_TYPE_MASK                     (7 << 0)
+#define NAV_TYPE_NO_FIX                                        (0 << 0)
+#define NAV_TYPE_SV_KF                                 (1 << 0)
+#define NAV_TYPE_2_SV_KF                               (2 << 0)
+#define NAV_TYPE_3_SV_KF                               (3 << 0)
+#define NAV_TYPE_4_SV_KF                               (4 << 0)
+#define NAV_TYPE_2D_LEAST_SQUARES                      (5 << 0)
+#define NAV_TYPE_3D_LEAST_SQUARES                      (6 << 0)
+#define NAV_TYPE_DR                                    (7 << 0)
+#define NAV_TYPE_TRICKLE_POWER                         (1 << 3)
+#define NAV_TYPE_ALTITUDE_HOLD_MASK                    (3 << 4)
+#define NAV_TYPE_ALTITUDE_HOLD_NONE                    (0 << 4)
+#define NAV_TYPE_ALTITUDE_HOLD_KF                      (1 << 4)
+#define NAV_TYPE_ALTITUDE_HOLD_USER                    (2 << 4)
+#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS                  (3 << 4)
+#define NAV_TYPE_DOP_LIMIT_EXCEEDED                    (1 << 6)
+#define NAV_TYPE_DGPS_APPLIED                          (1 << 7)
+#define NAV_TYPE_SENSOR_DR                             (1 << 8)
+#define NAV_TYPE_OVERDETERMINED                                (1 << 9)
+#define NAV_TYPE_DR_TIMEOUT_EXCEEDED                   (1 << 10)
+#define NAV_TYPE_FIX_MI_EDIT                           (1 << 11)
+#define NAV_TYPE_INVALID_VELOCITY                      (1 << 12)
+#define NAV_TYPE_ALTITUDE_HOLD_DISABLED                        (1 << 13)
+#define NAV_TYPE_DR_ERROR_STATUS_MASK                  (3 << 14)
+#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY              (0 << 14)
+#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS           (1 << 14)
+#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR       (2 << 14)
+#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST            (3 << 14)
+
+struct sirf_geodetic_nav_data {
+       uint16_t        nav_type;
+       uint16_t        utc_year;
+       uint8_t         utc_month;
+       uint8_t         utc_day;
+       uint8_t         utc_hour;
+       uint8_t         utc_minute;
+       uint16_t        utc_second;
+       int32_t         lat;
+       int32_t         lon;
+       int32_t         alt_msl;
+       uint16_t        ground_speed;
+       uint16_t        course;
+       int16_t         climb_rate;
+       uint32_t        h_error;
+       uint32_t        v_error;
+       uint8_t         num_sv;
+       uint8_t         hdop;
+};
+
+static __xdata struct sirf_geodetic_nav_data   ao_sirf_data;
+
+struct sirf_measured_sat_data {
+       uint8_t         svid;
+       uint8_t         c_n_1;
+};
+
+struct sirf_measured_tracker_data {
+       int16_t                         gps_week;
+       uint32_t                        gps_tow;
+       uint8_t                         channels;
+       struct sirf_measured_sat_data   sats[12];
+};
+
+static __xdata struct sirf_measured_tracker_data       ao_sirf_tracker_data;
+
+static __pdata uint16_t ao_sirf_cksum;
+static __pdata uint16_t ao_sirf_len;
+
+#define ao_sirf_byte() ((uint8_t) ao_serial_getchar())
+
+static uint8_t data_byte(void)
+{
+       uint8_t c = ao_sirf_byte();
+       --ao_sirf_len;
+       ao_sirf_cksum += c;
+       return c;
+}
+
+static char __xdata *sirf_target;
+
+static void sirf_u16(uint8_t offset)
+{
+       uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset);
+       uint16_t val;
+
+       val = data_byte() << 8;
+       val |= data_byte ();
+       *ptr = val;
+}
+
+static void sirf_u8(uint8_t offset)
+{
+       uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset);
+       uint8_t val;
+
+       val = data_byte ();
+       *ptr = val;
+}
+
+static void sirf_u32(uint8_t offset) __reentrant
+{
+       uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset);
+       uint32_t val;
+
+       val = ((uint32_t) data_byte ()) << 24;
+       val |= ((uint32_t) data_byte ()) << 16;
+       val |= ((uint32_t) data_byte ()) << 8;
+       val |= ((uint32_t) data_byte ());
+       *ptr = val;
+}
+
+static void sirf_discard(uint8_t len)
+{
+       while (len--)
+               data_byte();
+}
+
+#define SIRF_END       0
+#define SIRF_DISCARD   1
+#define SIRF_U8                2
+#define SIRF_U16       3
+#define SIRF_U32       4
+#define SIRF_U8X10     5
+
+struct sirf_packet_parse {
+       uint8_t type;
+       uint8_t offset;
+};
+
+static void
+ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant
+{
+       uint8_t i, offset, j;
+
+       sirf_target = target;
+       for (i = 0; ; i++) {
+               offset = parse[i].offset;
+               switch (parse[i].type) {
+               case SIRF_END:
+                       return;
+               case SIRF_DISCARD:
+                       sirf_discard(offset);
+                       break;
+               case SIRF_U8:
+                       sirf_u8(offset);
+                       break;
+               case SIRF_U16:
+                       sirf_u16(offset);
+                       break;
+               case SIRF_U32:
+                       sirf_u32(offset);
+                       break;
+               case SIRF_U8X10:
+                       for (j = 10; j--;)
+                               sirf_u8(offset++);
+                       break;
+               }
+       }
+}
+
+static const struct sirf_packet_parse geodetic_nav_data_packet[] = {
+       { SIRF_DISCARD, 2 },                                                    /* 1 nav valid */
+       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) },        /* 3 */
+       { SIRF_DISCARD, 6 },                                                    /* 5 week number, time of week */
+       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) },        /* 11 */
+       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) },        /* 13 */
+       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) },          /* 14 */
+       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) },         /* 15 */
+       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) },       /* 16 */
+       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) },      /* 17 */
+       { SIRF_DISCARD, 4 },    /* satellite id list */                         /* 19 */
+       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) },             /* 23 */
+       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) },             /* 27 */
+       { SIRF_DISCARD, 4 },    /* altitude from ellipsoid */                   /* 31 */
+       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) },         /* 35 */
+       { SIRF_DISCARD, 1 },    /* map datum */                                 /* 39 */
+       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) },    /* 40 */
+       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) },          /* 42 */
+       { SIRF_DISCARD, 2 },    /* magnetic variation */                        /* 44 */
+       { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) },      /* 46 */
+       { SIRF_DISCARD, 2 },    /* turn rate */                                 /* 48 */
+       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) },         /* 50 */
+       { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) },         /* 54 */
+       { SIRF_DISCARD, 30 },   /* time error, h_vel error, clock_bias,
+                                  clock bias error, clock drift,
+                                  clock drift error, distance,
+                                  distance error, heading error */             /* 58 */
+       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) },           /* 88 */
+       { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) },             /* 89 */
+       { SIRF_DISCARD, 1 },    /* additional mode info */                      /* 90 */
+       { SIRF_END, 0 },                                                        /* 91 */
+};
+
+static void
+ao_sirf_parse_41(void) __reentrant
+{
+       ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet);
+}
+
+static const struct sirf_packet_parse measured_tracker_data_packet[] = {
+       { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) },   /* 1 week */
+       { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) },    /* 3 time of week */
+       { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) },    /* 7 channels */
+       { SIRF_END, 0 },
+};
+
+static const struct sirf_packet_parse measured_sat_data_packet[] = {
+       { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) },            /* 0 SV id */
+       { SIRF_DISCARD, 4 },                                                    /* 1 azimuth, 2 elevation, 3 state */
+       { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) },           /* C/N0 1 */
+       { SIRF_DISCARD, 9 },                                                    /* C/N0 2-10 */
+       { SIRF_END, 0 },
+};
+
+static void
+ao_sirf_parse_4(void) __reentrant
+{
+       uint8_t i;
+       ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet);
+       for (i = 0; i < 12; i++)
+               ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet);
+}
+
+static void
+ao_gps_setup(void) __reentrant
+{
+       uint8_t i, k;
+       ao_serial_set_speed(AO_SERIAL_SPEED_4800);
+       for (i = 0; i < 64; i++)
+               ao_serial_putchar(0x00);
+       for (k = 0; k < 3; k++)
+               for (i = 0; i < sizeof (ao_gps_set_nmea); i++)
+                       ao_serial_putchar(ao_gps_set_nmea[i]);
+       ao_serial_set_speed(AO_SERIAL_SPEED_57600);
+       for (i = 0; i < 64; i++)
+               ao_serial_putchar(0x00);
+}
+
+static const char ao_gps_set_message_rate[] = {
+       0xa0, 0xa2, 0x00, 0x08,
+       166,
+       0,
+};
+
+void
+ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant
+{
+       uint16_t        cksum = 0x00a6;
+       uint8_t         i;
+
+       for (i = 0; i < sizeof (ao_gps_set_message_rate); i++)
+               ao_serial_putchar(ao_gps_set_message_rate[i]);
+       ao_serial_putchar(msg);
+       ao_serial_putchar(rate);
+       cksum = 0xa6 + msg + rate;
+       for (i = 0; i < 4; i++)
+               ao_serial_putchar(0);
+       ao_serial_putchar((cksum >> 8) & 0x7f);
+       ao_serial_putchar(cksum & 0xff);
+       ao_serial_putchar(0xb0);
+       ao_serial_putchar(0xb3);
+}
+
+static const uint8_t sirf_disable[] = {
+       2,
+       9,
+       10,
+       27,
+       50,
+       52,
+};
+
+void
+ao_gps(void) __reentrant
+{
+       uint8_t i, k;
+       uint16_t cksum;
+
+       ao_gps_setup();
+       for (k = 0; k < 5; k++)
+       {
+               for (i = 0; i < sizeof (ao_gps_config); i++)
+                       ao_serial_putchar(ao_gps_config[i]);
+               for (i = 0; i < sizeof (sirf_disable); i++)
+                       ao_sirf_set_message_rate(sirf_disable[i], 0);
+               ao_sirf_set_message_rate(41, 1);
+               ao_sirf_set_message_rate(4, 1);
+       }
+       for (;;) {
+               /* Locate the begining of the next record */
+               while (ao_sirf_byte() != (uint8_t) 0xa0)
+                       ;
+               if (ao_sirf_byte() != (uint8_t) 0xa2)
+                       continue;
+
+               /* Length */
+               ao_sirf_len = ao_sirf_byte() << 8;
+               ao_sirf_len |= ao_sirf_byte();
+               if (ao_sirf_len > 1023)
+                       continue;
+
+               ao_sirf_cksum = 0;
+
+               /* message ID */
+               i = data_byte ();                                                       /* 0 */
+
+               switch (i) {
+               case 41:
+                       if (ao_sirf_len < 90)
+                               break;
+                       ao_sirf_parse_41();
+                       break;
+               case 4:
+                       if (ao_sirf_len < 187)
+                               break;
+                       ao_sirf_parse_4();
+                       break;
+               }
+               if (ao_sirf_len != 0)
+                       continue;
+
+               /* verify checksum and end sequence */
+               ao_sirf_cksum &= 0x7fff;
+               cksum = ao_sirf_byte() << 8;
+               cksum |= ao_sirf_byte();
+               if (ao_sirf_cksum != cksum)
+                       continue;
+               if (ao_sirf_byte() != (uint8_t) 0xb0)
+                       continue;
+               if (ao_sirf_byte() != (uint8_t) 0xb3)
+                       continue;
+
+               switch (i) {
+               case 41:
+                       ao_mutex_get(&ao_gps_mutex);
+                       ao_gps_tick = ao_time();
+                       ao_gps_data.hour = ao_sirf_data.utc_hour;
+                       ao_gps_data.minute = ao_sirf_data.utc_minute;
+                       ao_gps_data.second = ao_sirf_data.utc_second / 1000;
+                       ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING;
+                       if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF)
+                               ao_gps_data.flags |= AO_GPS_VALID;
+                       ao_gps_data.latitude = ao_sirf_data.lat;
+                       ao_gps_data.longitude = ao_sirf_data.lon;
+                       ao_gps_data.altitude = ao_sirf_data.alt_msl / 100;
+                       ao_gps_data.ground_speed = ao_sirf_data.ground_speed;
+                       ao_gps_data.course = ao_sirf_data.course / 200;
+                       ao_gps_data.hdop = ao_sirf_data.hdop;
+                       ao_gps_data.climb_rate = ao_sirf_data.climb_rate;
+                       ao_gps_data.flags |= AO_GPS_COURSE_VALID;
+#if 0
+                       if (ao_sirf_data.h_error > 6553500)
+                               ao_gps_data.h_error = 65535;
+                       else
+                               ao_gps_data.h_error = ao_sirf_data.h_error / 100;
+                       if (ao_sirf_data.v_error > 6553500)
+                               ao_gps_data.v_error = 65535;
+                       else
+                               ao_gps_data.v_error = ao_sirf_data.v_error / 100;
+#endif
+                       ao_mutex_put(&ao_gps_mutex);
+                       ao_wakeup(&ao_gps_data);
+                       break;
+               case 4:
+                       ao_mutex_get(&ao_gps_mutex);
+                       ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels;
+                       for (i = 0; i < 12; i++) {
+                               ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid;
+                               ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1;
+                       }
+                       ao_mutex_put(&ao_gps_mutex);
+                       ao_wakeup(&ao_gps_tracking_data);
+                       break;
+               }
+       }
+}
+
+__xdata struct ao_task ao_gps_task;
+
+void
+ao_gps_init(void)
+{
+       ao_add_task(&ao_gps_task, ao_gps, "gps");
+}
diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c
new file mode 100644 (file)
index 0000000..7ac2694
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef AO_GPS_TEST
+#include "ao.h"
+#endif
+
+#define AO_GPS_LEADER          2
+
+static __code char ao_gps_header[] = "GP";
+
+__xdata uint8_t ao_gps_mutex;
+static __data char ao_gps_char;
+static __pdata uint8_t ao_gps_cksum;
+static __pdata uint8_t ao_gps_error;
+
+__pdata uint16_t ao_gps_tick;
+__xdata struct ao_telemetry_location   ao_gps_data;
+__xdata struct ao_telemetry_satellite  ao_gps_tracking_data;
+
+static __pdata uint16_t                                ao_gps_next_tick;
+static __xdata struct ao_telemetry_location    ao_gps_next;
+static __pdata uint8_t                         ao_gps_date_flags;
+static __xdata struct ao_telemetry_satellite   ao_gps_tracking_next;
+
+#define STQ_S 0xa0, 0xa1
+#define STQ_E 0x0d, 0x0a
+#define SKYTRAQ_MSG_2(id,a,b) \
+    STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E
+#define SKYTRAQ_MSG_3(id,a,b,c) \
+    STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E
+#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \
+    STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E
+#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
+    STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \
+    (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E
+
+static __code uint8_t ao_gps_config[] = {
+       SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */
+       /* gga interval */
+       /* gsa interval */
+       /* gsv interval */
+       /* gll interval */
+       /* rmc interval */
+       /* vtg interval */
+       /* zda interval */
+       /* attributes (0 = update to sram, 1 = update flash too) */
+
+       SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */
+       /* 0 = car, 1 = pedestrian */
+       /* 0 = update to sram, 1 = update sram + flash */
+};
+
+static void
+ao_gps_lexchar(void)
+{
+       if (ao_gps_error)
+               ao_gps_char = '\n';
+       else
+               ao_gps_char = ao_serial_getchar();
+       ao_gps_cksum ^= ao_gps_char;
+}
+
+void
+ao_gps_skip_field(void)
+{
+       while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n')
+               ao_gps_lexchar();
+}
+
+void
+ao_gps_skip_sep(void)
+{
+       if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*')
+               ao_gps_lexchar();
+}
+
+__pdata static uint8_t ao_gps_num_width;
+
+static int16_t
+ao_gps_decimal(uint8_t max_width)
+{
+       int16_t v;
+       __pdata uint8_t neg = 0;
+
+       ao_gps_skip_sep();
+       if (ao_gps_char == '-') {
+               neg = 1;
+               ao_gps_lexchar();
+       }
+       v = 0;
+       ao_gps_num_width = 0;
+       while (ao_gps_num_width < max_width) {
+               if (ao_gps_char < '0' || '9' < ao_gps_char)
+                       break;
+               v = v * (int16_t) 10 + ao_gps_char - '0';
+               ao_gps_num_width++;
+               ao_gps_lexchar();
+       }
+       if (neg)
+               v = -v;
+       return v;
+}
+
+static uint8_t
+ao_gps_hex(uint8_t max_width)
+{
+       uint8_t v, d;
+
+       ao_gps_skip_sep();
+       v = 0;
+       ao_gps_num_width = 0;
+       while (ao_gps_num_width < max_width) {
+               if ('0' <= ao_gps_char && ao_gps_char <= '9')
+                       d = ao_gps_char - '0';
+               else if ('A' <= ao_gps_char && ao_gps_char <= 'F')
+                       d = ao_gps_char - 'A' + 10;
+               else if ('a' <= ao_gps_char && ao_gps_char <= 'f')
+                       d = ao_gps_char - 'a' + 10;
+               else
+                       break;
+               v = (v << 4) | d;
+               ao_gps_num_width++;
+               ao_gps_lexchar();
+       }
+       return v;
+}
+
+static int32_t
+ao_gps_parse_pos(uint8_t deg_width) __reentrant
+{
+       int32_t d;
+       int32_t m;
+       int32_t f;
+
+       d = ao_gps_decimal(deg_width);
+       m = ao_gps_decimal(2);
+       if (ao_gps_char == '.') {
+               f = ao_gps_decimal(4);
+               while (ao_gps_num_width < 4) {
+                       f *= 10;
+                       ao_gps_num_width++;
+               }
+       } else {
+               f = 0;
+               if (ao_gps_char != ',')
+                       ao_gps_error = 1;
+       }
+       d = d * 10000000l;
+       m = m * 10000l + f;
+       d = d + m * 50 / 3;
+       return d;
+}
+
+static uint8_t
+ao_gps_parse_flag(char no_c, char yes_c) __reentrant
+{
+       uint8_t ret = 0;
+       ao_gps_skip_sep();
+       if (ao_gps_char == yes_c)
+               ret = 1;
+       else if (ao_gps_char == no_c)
+               ret = 0;
+       else
+               ao_gps_error = 1;
+       ao_gps_lexchar();
+       return ret;
+}
+
+static void
+ao_nmea_gga()
+{
+       uint8_t i;
+
+       /* Now read the data into the gps data record
+        *
+        * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66
+        *
+        * Essential fix data
+        *
+        *         025149.000   time (02:51:49.000 GMT)
+        *         4528.1723,N  Latitude 45°28.1723' N
+        *         12244.2480,W Longitude 122°44.2480' W
+        *         1            Fix quality:
+        *                                 0 = invalid
+        *                                 1 = GPS fix (SPS)
+        *                                 2 = DGPS fix
+        *                                 3 = PPS fix
+        *                                 4 = Real Time Kinematic
+        *                                 5 = Float RTK
+        *                                 6 = estimated (dead reckoning)
+        *                                 7 = Manual input mode
+        *                                 8 = Simulation mode
+        *         05           Number of satellites (5)
+        *         2.0          Horizontal dilution
+        *         103.5,M              Altitude, 103.5M above msl
+        *         -19.5,M              Height of geoid above WGS84 ellipsoid
+        *         ?            time in seconds since last DGPS update
+        *         0000         DGPS station ID
+        *         *66          checksum
+        */
+
+       ao_gps_next_tick = ao_time();
+       ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags;
+       ao_gps_next.hour = ao_gps_decimal(2);
+       ao_gps_next.minute = ao_gps_decimal(2);
+       ao_gps_next.second = ao_gps_decimal(2);
+       ao_gps_skip_field();    /* skip seconds fraction */
+
+       ao_gps_next.latitude = ao_gps_parse_pos(2);
+       if (ao_gps_parse_flag('N', 'S'))
+               ao_gps_next.latitude = -ao_gps_next.latitude;
+       ao_gps_next.longitude = ao_gps_parse_pos(3);
+       if (ao_gps_parse_flag('E', 'W'))
+               ao_gps_next.longitude = -ao_gps_next.longitude;
+
+       i = ao_gps_decimal(0xff);
+       if (i == 1)
+               ao_gps_next.flags |= AO_GPS_VALID;
+
+       i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT;
+       if (i > AO_GPS_NUM_SAT_MASK)
+               i = AO_GPS_NUM_SAT_MASK;
+       ao_gps_next.flags |= i;
+
+       ao_gps_lexchar();
+       i = ao_gps_decimal(0xff);
+       if (i <= 50) {
+               i = (uint8_t) 5 * i;
+               if (ao_gps_char == '.')
+                       i = (i + ((uint8_t) ao_gps_decimal(1) >> 1));
+       } else
+               i = 255;
+       ao_gps_next.hdop = i;
+       ao_gps_skip_field();
+
+       ao_gps_next.altitude = ao_gps_decimal(0xff);
+       ao_gps_skip_field();    /* skip any fractional portion */
+
+       /* Skip remaining fields */
+       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
+               ao_gps_lexchar();
+               ao_gps_skip_field();
+       }
+       if (ao_gps_char == '*') {
+               uint8_t cksum = ao_gps_cksum ^ '*';
+               if (cksum != ao_gps_hex(2))
+                       ao_gps_error = 1;
+       } else
+               ao_gps_error = 1;
+       if (!ao_gps_error) {
+               ao_mutex_get(&ao_gps_mutex);
+               ao_gps_tick = ao_gps_next_tick;
+               memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data));
+               ao_mutex_put(&ao_gps_mutex);
+               ao_wakeup(&ao_gps_data);
+       }
+}
+
+static void
+ao_nmea_gsv(void)
+{
+       char    c;
+       uint8_t i;
+       uint8_t done;
+       /* Now read the data into the GPS tracking data record
+        *
+        * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72<CR><LF>
+        *
+        * Satellites in view data
+        *
+        *      3               Total number of GSV messages
+        *      1               Sequence number of current GSV message
+        *      12              Total sats in view (0-12)
+        *      05              SVID
+        *      54              Elevation
+        *      069             Azimuth
+        *      45              C/N0 in dB
+        *      ...             other SVIDs
+        *      72              checksum
+        */
+       c = ao_gps_decimal(1);  /* total messages */
+       i = ao_gps_decimal(1);  /* message sequence */
+       if (i == 1) {
+               ao_gps_tracking_next.channels = 0;
+       }
+       done = (uint8_t) c == i;
+       ao_gps_lexchar();
+       ao_gps_skip_field();    /* sats in view */
+       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
+               i = ao_gps_tracking_next.channels;
+               c = ao_gps_decimal(2);  /* SVID */
+               if (i < AO_MAX_GPS_TRACKING)
+                       ao_gps_tracking_next.sats[i].svid = c;
+               ao_gps_lexchar();
+               ao_gps_skip_field();    /* elevation */
+               ao_gps_lexchar();
+               ao_gps_skip_field();    /* azimuth */
+               c = ao_gps_decimal(2);  /* C/N0 */
+               if (i < AO_MAX_GPS_TRACKING) {
+                       if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0)
+                               ao_gps_tracking_next.channels = i + 1;
+               }
+       }
+       if (ao_gps_char == '*') {
+               uint8_t cksum = ao_gps_cksum ^ '*';
+               if (cksum != ao_gps_hex(2))
+                       ao_gps_error = 1;
+       }
+       else
+               ao_gps_error = 1;
+       if (ao_gps_error)
+               ao_gps_tracking_next.channels = 0;
+       else if (done) {
+               ao_mutex_get(&ao_gps_mutex);
+               memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next,
+                      sizeof(ao_gps_tracking_data));
+               ao_mutex_put(&ao_gps_mutex);
+               ao_wakeup(&ao_gps_tracking_data);
+       }
+}
+
+static void
+ao_nmea_rmc(void)
+{
+       char    a, c;
+       uint8_t i;
+       /* Parse the RMC record to read out the current date */
+
+       /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61
+        *
+        * Recommended Minimum Specific GNSS Data
+        *
+        *      111636.932      UTC time 11:16:36.932
+        *      A               Data Valid (V = receiver warning)
+        *      2447.0949       Latitude
+        *      N               North/south indicator
+        *      12100.5223      Longitude
+        *      E               East/west indicator
+        *      000.0           Speed over ground
+        *      000.0           Course over ground
+        *      030407          UTC date (ddmmyy format)
+        *      A               Mode indicator:
+        *                      N = data not valid
+        *                      A = autonomous mode
+        *                      D = differential mode
+        *                      E = estimated (dead reckoning) mode
+        *                      M = manual input mode
+        *                      S = simulator mode
+        *      61              checksum
+        */
+       ao_gps_skip_field();
+       for (i = 0; i < 8; i++) {
+               ao_gps_lexchar();
+               ao_gps_skip_field();
+       }
+       a = ao_gps_decimal(2);
+       c = ao_gps_decimal(2);
+       i = ao_gps_decimal(2);
+       /* Skip remaining fields */
+       while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') {
+               ao_gps_lexchar();
+               ao_gps_skip_field();
+       }
+       if (ao_gps_char == '*') {
+               uint8_t cksum = ao_gps_cksum ^ '*';
+               if (cksum != ao_gps_hex(2))
+                       ao_gps_error = 1;
+       } else
+               ao_gps_error = 1;
+       if (!ao_gps_error) {
+               ao_gps_next.year = i;
+               ao_gps_next.month = c;
+               ao_gps_next.day = a;
+               ao_gps_date_flags = AO_GPS_DATE_VALID;
+       }
+}
+
+#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s))
+
+static void
+ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l)
+{
+       while (l--) {
+               uint8_t c = *b++;
+               if (c == 0xa0)
+                       ao_delay(AO_MS_TO_TICKS(500));
+               ao_serial_putchar(c);
+       }
+}
+
+static void
+ao_gps_nmea_parse(void)
+{
+       uint8_t a, b, c;
+
+       ao_gps_cksum = 0;
+       ao_gps_error = 0;
+
+       for (a = 0; a < AO_GPS_LEADER; a++) {
+               ao_gps_lexchar();
+               if (ao_gps_char != ao_gps_header[a])
+                       return;
+       }
+
+       ao_gps_lexchar();
+       a = ao_gps_char;
+       ao_gps_lexchar();
+       b = ao_gps_char;
+       ao_gps_lexchar();
+       c = ao_gps_char;
+       ao_gps_lexchar();
+
+       if (ao_gps_char != ',')
+               return;
+
+       if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') {
+               ao_nmea_gga();
+       } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') {
+               ao_nmea_gsv();
+       } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') {
+               ao_nmea_rmc();
+       }
+}
+
+void
+ao_gps(void) __reentrant
+{
+       ao_serial_set_speed(AO_SERIAL_SPEED_9600);
+
+       /* give skytraq time to boot in case of cold start */
+       ao_delay(AO_MS_TO_TICKS(2000));
+
+       ao_skytraq_sendstruct(ao_gps_config);
+
+       for (;;) {
+               /* Locate the begining of the next record */
+               if (ao_serial_getchar() == '$') {
+                       ao_gps_nmea_parse();
+               }
+
+       }
+}
+
+__xdata struct ao_task ao_gps_task;
+
+static void
+gps_dump(void) __reentrant
+{
+       uint8_t i;
+       ao_mutex_get(&ao_gps_mutex);
+       printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day);
+       printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);
+       printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude);
+       printf ("Alt: %d\n", ao_gps_data.altitude);
+       printf ("Flags: 0x%x\n", ao_gps_data.flags);
+       printf ("Sats: %d", ao_gps_tracking_data.channels);
+       for (i = 0; i < ao_gps_tracking_data.channels; i++)
+               printf (" %d %d",
+                       ao_gps_tracking_data.sats[i].svid,
+                       ao_gps_tracking_data.sats[i].c_n_1);
+       printf ("\ndone\n");
+       ao_mutex_put(&ao_gps_mutex);
+}
+
+__code struct ao_cmds ao_gps_cmds[] = {
+       { gps_dump,     "g\0Display GPS" },
+       { 0, NULL },
+};
+
+void
+ao_gps_init(void)
+{
+       ao_add_task(&ao_gps_task, ao_gps, "gps");
+       ao_cmd_register(&ao_gps_cmds[0]);
+}
diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c
new file mode 100644 (file)
index 0000000..d720827
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+/* Total bytes of available storage */
+__pdata uint32_t       ao_storage_total;
+
+/* Block size - device is erased in these units. At least 256 bytes */
+__pdata uint32_t       ao_storage_block;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+__pdata uint32_t       ao_storage_config;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */
+__pdata uint16_t       ao_storage_unit;
+
+/*
+ * Each flash chip is arranged in 64kB sectors; the
+ * chip cannot erase in units smaller than that.
+ *
+ * Writing happens in units of 256 byte pages and
+ * can only change bits from 1 to 0. So, you can rewrite
+ * the same contents, or append to an existing page easily enough
+ */
+
+#define M25_WREN       0x06    /* Write Enable */
+#define M25_WRDI       0x04    /* Write Disable */
+#define M25_RDID       0x9f    /* Read Identification */
+#define M25_RDSR       0x05    /* Read Status Register */
+#define M25_WRSR       0x01    /* Write Status Register */
+#define M25_READ       0x03    /* Read Data Bytes */
+#define M25_FAST_READ  0x0b    /* Read Data Bytes at Higher Speed */
+#define M25_PP         0x02    /* Page Program */
+#define M25_SE         0xd8    /* Sector Erase */
+#define M25_BE         0xc7    /* Bulk Erase */
+#define M25_DP         0xb9    /* Deep Power-down */
+
+/* RDID response */
+#define M25_MANUF_OFFSET       0
+#define M25_MEMORY_TYPE_OFFSET 1
+#define M25_CAPACITY_OFFSET    2
+#define M25_UID_OFFSET         3
+#define M25_CFI_OFFSET         4
+#define M25_RDID_LEN           4       /* that's all we need */
+
+#define M25_CAPACITY_128KB     0x11
+#define M25_CAPACITY_256KB     0x12
+#define M25_CAPACITY_512KB     0x13
+#define M25_CAPACITY_1MB       0x14
+#define M25_CAPACITY_2MB       0x15
+
+/*
+ * Status register bits
+ */
+
+#define M25_STATUS_SRWD                (1 << 7)        /* Status register write disable */
+#define M25_STATUS_BP_MASK     (7 << 2)        /* Block protect bits */
+#define M25_STATUS_BP_SHIFT    (2)
+#define M25_STATUS_WEL         (1 << 1)        /* Write enable latch */
+#define M25_STATUS_WIP         (1 << 0)        /* Write in progress */
+
+/*
+ * On teleterra, the m25 chip select pins are
+ * wired on P0_0 through P0_3.
+ */
+
+#if M25_MAX_CHIPS > 1
+static uint8_t ao_m25_size[M25_MAX_CHIPS];     /* number of sectors in each chip */
+static uint8_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 uint8_t ao_m25_wip;                     /* write in progress */
+
+static __xdata uint8_t ao_m25_mutex;
+
+/*
+ * This little array is abused to send and receive data. A particular
+ * caution -- the read and write addresses are written into the last
+ * three bytes of the array by ao_m25_set_page_address and then the
+ * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither
+ * of which touch those last three bytes.
+ */
+
+static __xdata uint8_t ao_m25_instruction[4];
+
+#define M25_SELECT(cs)         ao_spi_get_mask(SPI_CS_PORT,cs)
+#define M25_DESELECT(cs)       ao_spi_put_mask(SPI_CS_PORT,cs)
+
+#define M25_BLOCK_SHIFT                        16
+#define M25_BLOCK                      65536L
+#define M25_POS_TO_SECTOR(pos)         ((uint8_t) ((pos) >> M25_BLOCK_SHIFT))
+#define M25_SECTOR_TO_POS(sector)      (((uint32_t) (sector)) << M25_BLOCK_SHIFT)
+
+/*
+ * Block until the specified chip is done writing
+ */
+static void
+ao_m25_wait_wip(uint8_t cs)
+{
+       if (ao_m25_wip & cs) {
+               M25_SELECT(cs);
+               ao_m25_instruction[0] = M25_RDSR;
+               ao_spi_send(ao_m25_instruction, 1);
+               do {
+                       ao_spi_recv(ao_m25_instruction, 1);
+               } while (ao_m25_instruction[0] & M25_STATUS_WIP);
+               M25_DESELECT(cs);
+               ao_m25_wip &= ~cs;
+       }
+}
+
+/*
+ * Set the write enable latch so that page program and sector
+ * erase commands will work. Also mark the chip as busy writing
+ * so that future operations will block until the WIP bit goes off
+ */
+static void
+ao_m25_write_enable(uint8_t cs)
+{
+       M25_SELECT(cs);
+       ao_m25_instruction[0] = M25_WREN;
+       ao_spi_send(&ao_m25_instruction, 1);
+       M25_DESELECT(cs);
+       ao_m25_wip |= cs;
+}
+
+
+/*
+ * Returns the number of 64kB sectors
+ */
+static uint8_t
+ao_m25_read_capacity(uint8_t cs)
+{
+       uint8_t capacity;
+       M25_SELECT(cs);
+       ao_m25_instruction[0] = M25_RDID;
+       ao_spi_send(ao_m25_instruction, 1);
+       ao_spi_recv(ao_m25_instruction, M25_RDID_LEN);
+       M25_DESELECT(cs);
+
+       /* Check to see if the chip is present */
+       if (ao_m25_instruction[0] == 0xff)
+               return 0;
+       capacity = ao_m25_instruction[M25_CAPACITY_OFFSET];
+
+       /* Sanity check capacity number */
+       if (capacity < 0x11 || 0x1f < capacity)
+               return 0;
+       return 1 << (capacity - 0x10);
+}
+
+static uint8_t
+ao_m25_set_address(uint32_t pos)
+{
+       uint8_t chip;
+#if M25_MAX_CHIPS > 1
+       uint8_t size;
+
+       for (chip = 0; chip < ao_m25_numchips; chip++) {
+               size = ao_m25_size[chip];
+               if (M25_POS_TO_SECTOR(pos) < size)
+                       break;
+               pos -= M25_SECTOR_TO_POS(size);
+       }
+       if (chip == ao_m25_numchips)
+               return 0xff;
+
+       chip = ao_m25_pin[chip];
+#else
+       chip = M25_CS_MASK;
+#endif
+       ao_m25_wait_wip(chip);
+
+       ao_m25_instruction[1] = pos >> 16;
+       ao_m25_instruction[2] = pos >> 8;
+       ao_m25_instruction[3] = pos;
+       return chip;
+}
+
+/*
+ * Scan the possible chip select lines
+ * to see which flash chips are connected
+ */
+static uint8_t
+ao_m25_scan(void)
+{
+#if M25_MAX_CHIPS > 1
+       uint8_t pin, size;
+#endif
+
+       if (ao_m25_total)
+               return 1;
+
+#if M25_MAX_CHIPS > 1
+       ao_m25_numchips = 0;
+       for (pin = 1; pin != 0; pin <<= 1) {
+               if (M25_CS_MASK & pin) {
+                       size = ao_m25_read_capacity(pin);
+                       if (size != 0) {
+                               ao_m25_size[ao_m25_numchips] = size;
+                               ao_m25_pin[ao_m25_numchips] = pin;
+                               ao_m25_total += size;
+                               ao_m25_numchips++;
+                       }
+               }
+       }
+#else
+       ao_m25_total = ao_m25_read_capacity(M25_CS_MASK);
+#endif
+       if (!ao_m25_total)
+               return 0;
+       ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total);
+       ao_storage_block = M25_BLOCK;
+       ao_storage_config = ao_storage_total - M25_BLOCK;
+       ao_storage_unit = 256;
+       return 1;
+}
+
+/*
+ * Erase the specified sector
+ */
+uint8_t
+ao_storage_erase(uint32_t pos) __reentrant
+{
+       uint8_t cs;
+
+       if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total)
+               return 0;
+
+       ao_mutex_get(&ao_m25_mutex);
+       ao_m25_scan();
+
+       cs = ao_m25_set_address(pos);
+
+       ao_m25_wait_wip(cs);
+       ao_m25_write_enable(cs);
+
+       ao_m25_instruction[0] = M25_SE;
+       M25_SELECT(cs);
+       ao_spi_send(ao_m25_instruction, 4);
+       M25_DESELECT(cs);
+       ao_m25_wip |= cs;
+
+       ao_mutex_put(&ao_m25_mutex);
+       return 1;
+}
+
+/*
+ * Write to flash
+ */
+uint8_t
+ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
+{
+       uint8_t cs;
+
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+
+       ao_mutex_get(&ao_m25_mutex);
+       ao_m25_scan();
+
+       cs = ao_m25_set_address(pos);
+       ao_m25_write_enable(cs);
+
+       ao_m25_instruction[0] = M25_PP;
+       M25_SELECT(cs);
+       ao_spi_send(ao_m25_instruction, 4);
+       ao_spi_send(d, len);
+       M25_DESELECT(cs);
+
+       ao_mutex_put(&ao_m25_mutex);
+       return 1;
+}
+
+/*
+ * Read from flash
+ */
+uint8_t
+ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
+{
+       uint8_t cs;
+
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+       ao_mutex_get(&ao_m25_mutex);
+       ao_m25_scan();
+
+       cs = ao_m25_set_address(pos);
+
+       /* No need to use the FAST_READ as we're running at only 8MHz */
+       ao_m25_instruction[0] = M25_READ;
+       M25_SELECT(cs);
+       ao_spi_send(ao_m25_instruction, 4);
+       ao_spi_recv(d, len);
+       M25_DESELECT(cs);
+
+       ao_mutex_put(&ao_m25_mutex);
+       return 1;
+}
+
+void
+ao_storage_flush(void) __reentrant
+{
+}
+
+void
+ao_storage_setup(void)
+{
+       ao_mutex_get(&ao_m25_mutex);
+       ao_m25_scan();
+       ao_mutex_put(&ao_m25_mutex);
+}
+
+void
+ao_storage_device_info(void) __reentrant
+{
+       uint8_t cs;
+#if M25_MAX_CHIPS > 1
+       uint8_t chip;
+#endif
+
+       ao_mutex_get(&ao_m25_mutex);
+       ao_m25_scan();
+       ao_mutex_put(&ao_m25_mutex);
+
+#if M25_MAX_CHIPS > 1
+       printf ("Detected chips %d size %d\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);
+#endif
+
+       printf ("Available chips:\n");
+       for (cs = 1; cs != 0; cs <<= 1) {
+               if ((M25_CS_MASK & cs) == 0)
+                       continue;
+
+               ao_mutex_get(&ao_m25_mutex);
+               M25_SELECT(cs);
+               ao_m25_instruction[0] = M25_RDID;
+               ao_spi_send(ao_m25_instruction, 1);
+               ao_spi_recv(ao_m25_instruction, M25_RDID_LEN);
+               M25_DESELECT(cs);
+
+               printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n",
+                       cs,
+                       ao_m25_instruction[M25_MANUF_OFFSET],
+                       ao_m25_instruction[M25_MEMORY_TYPE_OFFSET],
+                       ao_m25_instruction[M25_CAPACITY_OFFSET],
+                       ao_m25_instruction[M25_UID_OFFSET]);
+               ao_mutex_put(&ao_m25_mutex);
+       }
+}
+
+void
+ao_storage_device_init(void)
+{
+       /* Set up chip select wires */
+       SPI_CS_PORT |= M25_CS_MASK;     /* raise all CS pins */
+       SPI_CS_DIR |= M25_CS_MASK;      /* set CS pins as outputs */
+       SPI_CS_SEL &= ~M25_CS_MASK;     /* set CS pins as GPIO */
+}
diff --git a/src/gps-cksum b/src/gps-cksum
deleted file mode 100755 (executable)
index a08153b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env nickle
-
-int checksum(string a)
-{
-       int     c = 0;
-       for (int i = 0; i < String::length(a); i++)
-               c ^= a[i];
-       return c;
-}
-
-void main()
-{
-       for (int i = 1; i < dim(argv); i++)
-               printf ("$%s*%02x\n", argv[i], checksum(argv[i]));
-}
-
-main();
diff --git a/src/make-altitude b/src/make-altitude
deleted file mode 100644 (file)
index 716aa8a..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-#!/usr/bin/nickle -f
-/*
- * Pressure Sensor Model, version 1.1
- *
- * written by Holly Grimes
- *
- * Uses the International Standard Atmosphere as described in
- *   "A Quick Derivation relating altitude to air pressure" (version 1.03)
- *    from the Portland State Aerospace Society, except that the atmosphere
- *    is divided into layers with each layer having a different lapse rate.
- *
- * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007
- *    at site <http://en.wikipedia.org/wiki/International_Standard_Atmosphere
- *
- * Height measurements use the local tangent plane.  The postive z-direction is up.
- *
- * All measurements are given in SI units (Kelvin, Pascal, meter, meters/second^2).
- *   The lapse rate is given in Kelvin/meter, the gas constant for air is given
- *   in Joules/(kilogram-Kelvin).
- */
-
-const real GRAVITATIONAL_ACCELERATION = -9.80665;
-const real AIR_GAS_CONSTANT = 287.053;
-const int NUMBER_OF_LAYERS = 7;
-const real MAXIMUM_ALTITUDE = 84852;
-const real MINIMUM_PRESSURE = 0.3734;
-const real LAYER0_BASE_TEMPERATURE = 288.15;
-const real LAYER0_BASE_PRESSURE = 101325;
-
-/* lapse rate and base altitude for each layer in the atmosphere */
-const real[NUMBER_OF_LAYERS] lapse_rate = {
-       -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
-};
-const int[NUMBER_OF_LAYERS] base_altitude = {
-       0, 11000, 20000, 32000, 47000, 51000, 71000
-};
-
-
-/* outputs atmospheric pressure associated with the given altitude. altitudes
-   are measured with respect to the mean sea level */
-real altitude_to_pressure(real altitude) {
-
-   real base_temperature = LAYER0_BASE_TEMPERATURE;
-   real base_pressure = LAYER0_BASE_PRESSURE;
-
-   real pressure;
-   real base; /* base for function to determine pressure */
-   real exponent; /* exponent for function to determine pressure */
-   int layer_number; /* identifies layer in the atmosphere */
-   int delta_z; /* difference between two altitudes */
-
-   if (altitude > MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */
-      return 0;
-
-   /* calculate the base temperature and pressure for the atmospheric layer
-      associated with the inputted altitude */
-   for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
-      delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
-      if (lapse_rate[layer_number] == 0.0) {
-         exponent = GRAVITATIONAL_ACCELERATION * delta_z
-              / AIR_GAS_CONSTANT / base_temperature;
-         base_pressure *= exp(exponent);
-      }
-      else {
-         base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
-         exponent = GRAVITATIONAL_ACCELERATION /
-              (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
-         base_pressure *= pow(base, exponent);
-      }
-      base_temperature += delta_z * lapse_rate[layer_number];
-   }
-
-   /* calculate the pressure at the inputted altitude */
-   delta_z = altitude - base_altitude[layer_number];
-   if (lapse_rate[layer_number] == 0.0) {
-      exponent = GRAVITATIONAL_ACCELERATION * delta_z
-           / AIR_GAS_CONSTANT / base_temperature;
-      pressure = base_pressure * exp(exponent);
-   }
-   else {
-      base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
-      exponent = GRAVITATIONAL_ACCELERATION /
-           (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
-      pressure = base_pressure * pow(base, exponent);
-   }
-
-   return pressure;
-}
-
-
-/* outputs the altitude associated with the given pressure. the altitude
-   returned is measured with respect to the mean sea level */
-real pressure_to_altitude(real pressure) {
-
-   real next_base_temperature = LAYER0_BASE_TEMPERATURE;
-   real next_base_pressure = LAYER0_BASE_PRESSURE;
-
-   real altitude;
-   real base_pressure;
-   real base_temperature;
-   real base; /* base for function to determine base pressure of next layer */
-   real exponent; /* exponent for function to determine base pressure
-                             of next layer */
-   real coefficient;
-   int layer_number; /* identifies layer in the atmosphere */
-   int delta_z; /* difference between two altitudes */
-
-   if (pressure < 0)  /* illegal pressure */
-      return -1;
-   if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
-      return MAXIMUM_ALTITUDE;
-
-   /* calculate the base temperature and pressure for the atmospheric layer
-      associated with the inputted pressure. */
-   layer_number = -1;
-   do {
-      layer_number++;
-      base_pressure = next_base_pressure;
-      base_temperature = next_base_temperature;
-      delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
-      if (lapse_rate[layer_number] == 0.0) {
-         exponent = GRAVITATIONAL_ACCELERATION * delta_z
-              / AIR_GAS_CONSTANT / base_temperature;
-         next_base_pressure *= exp(exponent);
-      }
-      else {
-         base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
-         exponent = GRAVITATIONAL_ACCELERATION /
-              (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
-         next_base_pressure *= pow(base, exponent);
-      }
-      next_base_temperature += delta_z * lapse_rate[layer_number];
-   }
-   while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
-
-   /* calculate the altitude associated with the inputted pressure */
-   if (lapse_rate[layer_number] == 0.0) {
-      coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION)
-                                                    * base_temperature;
-      altitude = base_altitude[layer_number]
-                    + coefficient * log(pressure / base_pressure);
-   }
-   else {
-      base = pressure / base_pressure;
-      exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number]
-                                       / GRAVITATIONAL_ACCELERATION;
-      coefficient = base_temperature / lapse_rate[layer_number];
-      altitude = base_altitude[layer_number]
-                      + coefficient * (pow(base, exponent) - 1);
-   }
-
-   return altitude;
-}
-
-real feet_to_meters(real feet)
-{
-    return feet * (12 * 2.54 / 100);
-}
-
-real meters_to_feet(real meters)
-{
-    return meters / (12 * 2.54 / 100);
-}
-
-/*
- * Values for our MP3H6115A pressure sensor
- *
- * From the data sheet:
- *
- * Pressure range: 15-115 kPa
- * Voltage at 115kPa: 2.82
- * Output scale: 27mV/kPa
- *
- *
- * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa
- * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa
- */
-
-real counts_per_kPa = 27 * 2047 / 3300;
-real counts_at_101_3kPa = 1674;
-
-real fraction_to_kPa(real fraction)
-{
-       return (fraction + 0.095) / 0.009;
-}
-
-
-real count_to_kPa(real count) = fraction_to_kPa(count / 2047);
-
-typedef struct {
-       real m, b;
-       int m_i, b_i;
-} line_t;
-
-line_t best_fit(real[] values, int first, int last) {
-       real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0;
-       int n = last - first + 1;
-       real m, b;
-       int m_i, b_i;
-
-       for (int i = first; i <= last; i++) {
-              sum_x += i;
-              sum_x2 += i**2;
-              sum_y += values[i];
-              sum_xy += values[i] * i;
-       }
-       m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2);
-       b = sum_y/n - m*(sum_x/n);
-       return (line_t) { m = m, b = b };
-}
-
-real count_to_altitude(real count) {
-     return pressure_to_altitude(count_to_kPa(count) * 1000);
-}
-
-real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000);
-
-int num_samples = 1024;
-
-real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) };
-
-int num_part = 128;
-int seg_len = num_samples / num_part;
-
-line_t [dim(alt) / seg_len] fit = {
-       [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1)
-};
-
-int[num_samples/seg_len + 1]   alt_part;
-
-alt_part[0] = floor (fit[0].b + 0.5);
-alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5);
-
-for (int i = 0; i < dim(fit) - 1; i++) {
-       real    here, there;
-       here = fit[i].m * (i+1) * seg_len + fit[i].b;
-       there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b;
-       alt_part[i+1] = floor ((here + there) / 2 + 0.5);
-}
-
-real count_to_fit_altitude(int count) {
-       int     sub = count // seg_len;
-       int     off = count % seg_len;
-       line_t  l = fit[sub];
-       real r_v;
-       real i_v;
-
-       r_v = count * l.m + l.b;
-       i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len;
-       return i_v;
-}
-
-real max_error = 0;
-int max_error_count = 0;
-real total_error = 0;
-
-for (int count = 0; count < num_samples; count++) {
-       real    kPa = fraction_to_kPa(count / (num_samples - 1));
-       real    meters = pressure_to_altitude(kPa * 1000);
-
-       real    meters_approx = count_to_fit_altitude(count);
-       real    error = abs(meters - meters_approx);
-
-       total_error += error;
-       if (error > max_error) {
-               max_error = error;
-               max_error_count = count;
-       }
-#      printf ("       %7d,    /* %6.2g kPa %5d count approx %d */\n",
-#              floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5));
-}
-
-printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples);
-
-printf ("#define NALT %d\n", dim(alt_part));
-printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1));
-
-for (int i = 0; i < dim(alt_part); i++) {
-       real fraction = i / (dim(alt_part) - 1);
-       real kPa = fraction_to_kPa(fraction);
-       printf ("%9d, /* %6.2f kPa %7.3f%% */\n",
-               alt_part[i], kPa, fraction * 100);
-}
diff --git a/src/make-kalman b/src/make-kalman
deleted file mode 100644 (file)
index 9ac3513..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-cd ../kalman
-
-SIGMA_BOTH="-M 2 -H 6 -A 2"
-SIGMA_BARO="-M 2 -H 6 -A 2"
-SIGMA_ACCEL="-M 2 -H 4 -A 4"
-
-nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH
-nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH
-nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH
-
-nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL
-nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL
-nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL
-
-nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO
-nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO
-nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO
diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt
new file mode 100644 (file)
index 0000000..99730b9
--- /dev/null
@@ -0,0 +1,97 @@
+#
+# TeleBT build file
+#
+# Define TELEBT_VER, TELEBT_DEF, TELEBT_INC and TELEBT_SRC
+# and include this file
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       cc1111.h \
+       ao_product.h \
+       $(TELEBT_INC)
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_gps_print.c \
+       ao_monitor.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_rssi.c \
+       ao_state.c \
+       ao_stdio.c \
+       ao_task.c
+
+CC1111_SRC = \
+       ao_dbg.c \
+       ao_dma.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_packet_master.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_serial.c \
+       ao_timer.c \
+       ao_usb.c \
+       _bp.c
+
+DRIVER_SRC = \
+       ao_btm.c
+
+PRODUCT_SRC = \
+       ao_telebt.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC) \
+       $(TELEBT_SRC)
+
+PROG = telebt-v$(TELEBT_VER)-$(VERSION).ihx
+PRODUCT=TeleBT-v$(TELEBT_VER)
+PRODUCT_DEF=-DTELEBT_V_$(TELEBT_DEF)
+IDPRODUCT=0x000e
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+       rm -f ao_product.h
+       rm -f ../$(PROG) ../$(PMAP)
+
+install:
+
+uninstall:
diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle
new file mode 100644 (file)
index 0000000..f32c037
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# TeleDongle build file
+#
+# The various teledongle versions differ only
+# in minor pin variations
+# so the per-board makefiles simply define
+# TD_VER, TD_DEF and include
+# this file
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_gps_print.c \
+       ao_monitor.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_rssi.c \
+       ao_state.c \
+       ao_stdio.c \
+       ao_task.c
+
+CC1111_SRC = \
+       ao_dbg.c \
+       ao_dma.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_packet_master.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_timer.c \
+       ao_usb.c \
+       _bp.c
+
+DRIVER_SRC =
+
+PRODUCT_SRC = \
+       ao_teledongle.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROG = teledongle-v$(TD_VER)-$(VERSION).ihx
+PRODUCT=TeleDongle-v$(TD_VER)
+PRODUCT_DEF=-DTELEDONGLE_V_$(TD_DEF)
+IDPRODUCT=0x000c
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+       rm -f ao_product.h
+       rm -f ../$(PROG) ../$(PMAP)
+
+install:
+
+uninstall:
diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum
new file mode 100644 (file)
index 0000000..fd958ae
--- /dev/null
@@ -0,0 +1,111 @@
+#
+# TeleMetrum build file
+#
+# The various telemetrum versions differ only
+# in which flash and GPS drivers are included,
+# so the per-board makefiles simply define
+# TM_VER, TM_DEF, TM_INC and TM_SRC and include
+# this file
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       cc1111.h \
+       altitude.h \
+       ao_kalman.h \
+       ao_product.h \
+       $(TM_INC)
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_convert.c \
+       ao_gps_report.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_stdio.c \
+       ao_storage.c \
+       ao_task.c \
+       ao_flight.c \
+       ao_sample.c \
+       ao_kalman.c \
+       ao_log.c \
+       ao_log_big.c \
+       ao_report.c \
+       ao_telemetry.c
+
+CC1111_SRC = \
+       ao_adc.c \
+       ao_beep.c \
+       ao_dbg.c \
+       ao_dma.c \
+       ao_ignite.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_packet_slave.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_serial.c \
+       ao_spi.c \
+       ao_timer.c \
+       ao_usb.c \
+       _bp.c
+
+DRIVER_SRC = \
+       $(TM_SRC)
+
+PRODUCT_SRC = \
+       ao_telemetrum.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx
+PRODUCT=TeleMetrum-v$(TM_VER)
+PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF)
+IDPRODUCT=0x000b
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+       rm -f ao_product.h
+       rm -f ../$(PROG) ../$(PMAP)
+
+install:
+
+uninstall:
diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini
new file mode 100644 (file)
index 0000000..3bd1422
--- /dev/null
@@ -0,0 +1,100 @@
+#
+# TeleMini build file
+#
+# Define TELEMINI_VER and TELEMINI_DEF and then
+# include this file
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_convert.c \
+       ao_flight.c \
+       ao_kalman.c \
+       ao_log.c \
+       ao_log_tiny.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_report.c \
+       ao_sample.c \
+       ao_stdio.c \
+       ao_storage.c \
+       ao_task.c \
+       ao_telemetry.c
+
+CC1111_SRC = \
+       ao_adc.c \
+       ao_dma.c \
+       ao_ignite.c \
+       ao_intflash.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_packet_slave.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_timer.c \
+       _bp.c
+
+DRIVER_SRC =
+
+PRODUCT_SRC = \
+       ao_telemini.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROG = telemini-v$(TELEMINI_VER)-$(VERSION).ihx
+PRODUCT=TeleMini-v$(TELEMINI_VER)
+PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF)
+IDPRODUCT=0x000a
+CODESIZE=0x6700
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+       rm -f ao_product.h
+       rm -f ../$(PROG) ../$(PMAP)
+
+install:
+
+uninstall:
diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano
new file mode 100644 (file)
index 0000000..7204304
--- /dev/null
@@ -0,0 +1,99 @@
+#
+# TeleNano build file
+#
+# Define TELENANO_VER and TELENANO_DEF and then
+# include this file
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_convert.c \
+       ao_flight_nano.c \
+       ao_kalman.c \
+       ao_log.c \
+       ao_log_tiny.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_report.c \
+       ao_sample.c \
+       ao_stdio.c \
+       ao_storage.c \
+       ao_task.c \
+       ao_telemetry.c
+
+CC1111_SRC = \
+       ao_adc.c \
+       ao_dma.c \
+       ao_intflash.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_packet_slave.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_timer.c \
+       _bp.c
+
+DRIVER_SRC =
+
+PRODUCT_SRC = \
+       ao_telenano.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROG = telenano-v$(TELENANO_VER)-$(VERSION).ihx
+PRODUCT=TeleNano-v$(TELENANO_VER)
+PRODUCT_DEF=-DTELENANO_V_$(TELENANO_DEF)
+IDPRODUCT=0x000a
+CODESIZE=0x6700
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+       rm -f ao_product.h
+       rm -f ../$(PROG) ../$(PMAP)
+
+install:
+
+uninstall:
diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c
new file mode 100644 (file)
index 0000000..8556517
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE;     /* until we actually log stuff */
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       /* Turn on the LED until the system is stable */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+#if HAS_BEEP
+       ao_beep_init();
+#endif
+       ao_cmd_init();
+#if HAS_EEPROM
+       ao_spi_init();
+       ao_storage_init();
+#endif
+       ao_usb_init();
+       ao_monitor_init(AO_LED_GREEN, TRUE);
+       ao_rssi_init(AO_LED_RED);
+       ao_radio_init();
+       ao_packet_master_init();
+       ao_btm_init();
+#if HAS_DBG
+       ao_dbg_init();
+#endif
+       ao_config_init();
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c
new file mode 100644 (file)
index 0000000..008b200
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       /* Turn on the LED until the system is stable */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+       ao_cmd_init();
+       ao_usb_init();
+       ao_monitor_init(AO_LED_GREEN, TRUE);
+       ao_rssi_init(AO_LED_RED);
+       ao_radio_init();
+       ao_packet_master_init();
+#if HAS_DBG
+       ao_dbg_init();
+#endif
+       ao_config_init();
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_telemetrum.c b/src/product/ao_telemetrum.c
new file mode 100644 (file)
index 0000000..f560740
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pins.h"
+
+void
+main(void)
+{
+       /*
+        * Reduce the transient on the ignite pins at startup by
+        * pulling the pins low as soon as possible at power up
+        */
+       ao_ignite_set_pins();
+
+       ao_clock_init();
+
+       /* Turn on the red LED until the system is stable */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+
+       /* A hack -- look at the SPI clock pin, if it's sitting at
+        *  ground, then we force the computer to idle mode instead of
+        *  flight mode
+        */
+       if (P1_3 == 0) {
+               ao_flight_force_idle = 1;
+               while (P1_3 == 0)
+                       ;
+       }
+       ao_timer_init();
+       ao_adc_init();
+       ao_beep_init();
+       ao_cmd_init();
+       ao_spi_init();
+       ao_storage_init();
+       ao_flight_init();
+       ao_log_init();
+       ao_report_init();
+       ao_usb_init();
+       ao_serial_init();
+       ao_gps_init();
+       ao_gps_report_init();
+       ao_telemetry_init();
+       ao_radio_init();
+       ao_packet_slave_init(TRUE);
+       ao_igniter_init();
+#if HAS_DBG
+       ao_dbg_init();
+#endif
+#if HAS_COMPANION
+       ao_companion_init();
+#endif
+       ao_config_init();
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c
new file mode 100644 (file)
index 0000000..fa23de0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pins.h"
+
+void
+main(void)
+{
+       /*
+        * Reduce the transient on the ignite pins at startup by
+        * pulling the pins low as soon as possible at power up
+        */
+       ao_ignite_set_pins();
+
+       ao_clock_init();
+
+       /* Turn on the red LED until the system is stable */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+
+       ao_timer_init();
+       ao_adc_init();
+       ao_cmd_init();
+       ao_storage_init();
+       ao_flight_init();
+       ao_log_init();
+       ao_report_init();
+       ao_telemetry_init();
+       ao_radio_init();
+       ao_packet_slave_init(TRUE);
+       ao_igniter_init();
+       ao_config_init();
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_telenano.c b/src/product/ao_telenano.c
new file mode 100644 (file)
index 0000000..d91983d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pins.h"
+
+void
+main(void)
+{
+       ao_clock_init();
+
+
+       /* Turn on the red LED until the system is stable */
+       ao_led_init(LEDS_AVAILABLE);
+       ao_led_on(AO_LED_RED);
+
+       ao_timer_init();
+       ao_adc_init();
+       ao_cmd_init();
+       ao_storage_init();
+       ao_flight_nano_init();
+       ao_log_init();
+       ao_report_init();
+       ao_telemetry_init();
+       ao_radio_init();
+       ao_packet_slave_init(TRUE);
+       ao_config_init();
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_teleterra.c b/src/product/ao_teleterra.c
new file mode 100644 (file)
index 0000000..d696b91
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define AO_NO_ADC_ISR 1
+#include "ao.h"
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       /* Turn on the red LED until the system is stable */
+       ao_led_init(AO_LED_RED|AO_LED_GREEN);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+       ao_beep_init();
+       ao_cmd_init();
+       ao_usb_init();
+       ao_serial_init();
+       ao_monitor_init(AO_LED_GREEN, TRUE);
+       ao_radio_init();
+       ao_config_init();
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_test.c b/src/product/ao_test.c
new file mode 100644 (file)
index 0000000..14c2eb7
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+struct ao_task __xdata blink_0_task;
+struct ao_task __xdata blink_1_task;
+struct ao_task __xdata wakeup_task;
+struct ao_task __xdata beep_task;
+struct ao_task __xdata echo_task;
+
+void delay(int n) __reentrant
+{
+       uint8_t j = 0;
+       while (--n)
+               while (--j)
+                       ao_yield();
+}
+
+static __xdata uint8_t blink_chan;
+
+void
+blink_0(void)
+{
+       uint8_t b = 0;
+       for (;;) {
+               b = 1 - b;
+               if (b)
+                       ao_led_on(AO_LED_GREEN);
+               else
+                       ao_led_off(AO_LED_GREEN);
+               ao_sleep(&blink_chan);
+       }
+}
+
+void
+blink_1(void)
+{
+       static __xdata struct ao_adc adc;
+
+       for (;;) {
+               ao_sleep(&ao_adc_head);
+               ao_adc_get(&adc);
+               if (adc.accel < 15900)
+                       ao_led_on(AO_LED_RED);
+               else
+                       ao_led_off(AO_LED_RED);
+       }
+}
+
+void
+wakeup(void)
+{
+       for (;;) {
+               ao_delay(AO_MS_TO_TICKS(100));
+               ao_wakeup(&blink_chan);
+       }
+}
+
+void
+beep(void)
+{
+       static __xdata struct ao_adc adc;
+
+       for (;;) {
+               ao_delay(AO_SEC_TO_TICKS(1));
+               ao_adc_get(&adc);
+               if (adc.temp > 7400)
+                       ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(50));
+       }
+}
+
+void
+echo(void)
+{
+       char    c;
+       for (;;) {
+               ao_usb_flush();
+               c = ao_usb_getchar();
+               ao_usb_putchar(c);
+               if (c == '\r')
+                       ao_usb_putchar('\n');
+       }
+}
+
+void
+main(void)
+{
+       ao_clock_init();
+
+//     ao_add_task(&blink_0_task, blink_0);
+//     ao_add_task(&blink_1_task, blink_1);
+//     ao_add_task(&wakeup_task, wakeup);
+//     ao_add_task(&beep_task, beep);
+       ao_add_task(&echo_task, echo);
+       ao_timer_init();
+       ao_adc_init();
+       ao_beep_init();
+       ao_led_init();
+       ao_usb_init();
+
+       ao_start_scheduler();
+}
diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c
new file mode 100644 (file)
index 0000000..3b7c273
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define AO_NO_SERIAL_ISR 1
+#define AO_NO_ADC_ISR 1
+#include "ao.h"
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       /* Turn on the LED until the system is stable */
+       ao_led_init(AO_LED_RED);
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+       ao_cmd_init();
+       ao_usb_init();
+       ao_monitor_init(AO_LED_RED, TRUE);
+       ao_rssi_init(AO_LED_RED);
+       ao_radio_init();
+       ao_dbg_init();
+       ao_config_init();
+       /* Bring up the USB link */
+       P1DIR |= 1;
+       P1 |= 1;
+       ao_start_scheduler();
+}
diff --git a/src/sirf-cksum b/src/sirf-cksum
deleted file mode 100755 (executable)
index b905f31..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env nickle
-
-int checksum(int[] msg)
-{
-       int sum = 0;
-       for (int i = 0; i < dim(msg); i++) {
-               sum += msg[i];
-               sum &= 0x7fff;
-       }
-       return sum;
-}
-
-void main()
-{
-       string[...]     input;
-       int[...]        msg;
-
-       setdim(input, 0);
-       while (!File::end(stdin)) {
-               input[dim(input)] = gets();
-       }
-
-       setdim(msg, 0);
-       for (int i = 0; i < dim(input); i++) {
-               string[*] words = String::wordsplit(input[i], " ,\t");
-               for (int j = 0; j < dim(words); j++) {
-                       if (words[j] == "/" + "*")
-                               break;
-                       if (String::length(words[j]) > 0 &&
-                           Ctype::isdigit(words[j][0])) {
-                               msg[dim(msg)] = string_to_integer(words[j]);
-                       }
-                }
-       }
-       printf("\t0xa0, 0xa2, 0x%02x, 0x%02x,\t/* length: %d bytes */\n",
-              dim(msg) >> 8, dim(msg) & 0xff, dim(msg));
-       for (int i = 0; i < dim(input); i++)
-               printf("%s\n", input[i]);
-       int csum = checksum(msg);
-       printf ("\t0x%02x, 0x%02x, 0xb0, 0xb3,\n",
-               csum >> 8, csum & 0xff);
-}
-
-main();
diff --git a/src/skytraq-cksum b/src/skytraq-cksum
deleted file mode 100644 (file)
index ab0464a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env nickle
-
-int checksum(int[] msg)
-{
-       int sum = 0;
-       for (int i = 0; i < dim(msg); i++) {
-               sum ^= msg[i];
-               sum &= 0xff;
-       }
-       return sum;
-}
-
-void main()
-{
-       string[...]     input;
-       int[...]        msg;
-
-       setdim(input, 0);
-       while (!File::end(stdin)) {
-               input[dim(input)] = gets();
-       }
-
-       setdim(msg, 0);
-       for (int i = 0; i < dim(input); i++) {
-               string[*] words = String::wordsplit(input[i], " ,\t");
-               for (int j = 0; j < dim(words); j++) {
-                       if (words[j] == "/" + "*")
-                               break;
-                       if (String::length(words[j]) > 0 &&
-                           Ctype::isdigit(words[j][0])) {
-                               msg[dim(msg)] = string_to_integer(words[j]);
-                       }
-                }
-       }
-       printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n",
-              dim(msg) >> 8, dim(msg) & 0xff, dim(msg));
-       for (int i = 0; i < dim(input); i++)
-               printf("%s\n", input[i]);
-       int csum = checksum(msg);
-       printf ("\t0x%02x, 0x0d, 0x0a,\n",
-               csum);
-}
-
-main();
index d8867b1968618baf423b097a78d0f914402e847a..e89639ab8daa5c6ac51a08c656d13f8383163517 100644 (file)
@@ -1 +1,9 @@
-include ../Makefile.proto
+#
+# TeleBT v0.0 build
+#
+
+TELEBT_VER=0.0
+TELEBT_DEF=0_0
+
+include ../product/Makefile.telebt
+
diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs
deleted file mode 100644 (file)
index f0bb5e0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-PROG = telebt-v0.0-$(VERSION).ihx
-
-SRC = \
-       $(TBT_BASE_SRC)
-
-PRODUCT=TeleBT-v0.0
-PRODUCT_DEF=-DTELEBT_V_0_0
-IDPRODUCT=0x000e
index d8867b1968618baf423b097a78d0f914402e847a..a34e89126e2f754dde0afd805476bec99e90e204 100644 (file)
@@ -1 +1,19 @@
-include ../Makefile.proto
+#
+# TeleBT v0.1 build
+#
+
+TELEBT_VER=0.1
+TELEBT_DEF=0_1
+
+TELEBT_INC = \
+       ao_25lc1024.h
+
+TELEBT_SRC = \
+       ao_beep.c \
+       ao_log_telem.c \
+       ao_spi.c \
+       ao_storage.c \
+       ao_m25.c
+
+include ../product/Makefile.telebt
+
diff --git a/src/telebt-v0.1/Makefile.defs b/src/telebt-v0.1/Makefile.defs
deleted file mode 100644 (file)
index 50657c8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-PROG = telebt-v0.1-$(VERSION).ihx
-
-SRC = \
-       $(TBT_V_0_1_SRC)
-
-PRODUCT=TeleBT-v0.1
-PRODUCT_DEF=-DTELEBT_V_0_1
-IDPRODUCT=0x000e
index d8867b1968618baf423b097a78d0f914402e847a..4842510786053a41f4f26f8dbf73e3b387d6d5c7 100644 (file)
@@ -1 +1,8 @@
-include ../Makefile.proto
+#
+# TeleDongle v0.2 build
+#
+
+TD_VER=0.1
+TD_DEF=0_1
+
+include ../product/Makefile.teledongle
diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs
deleted file mode 100644 (file)
index ceb80b7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-PROG = teledongle-v0.1-$(VERSION).ihx
-
-SRC = \
-       $(TD_SRC) \
-       $(DBG_SRC)
-
-PRODUCT=TeleDongle-v0.1
-PRODUCT_DEF=-DTELEDONGLE_V_0_1
-IDPRODUCT=0x000c
index d8867b1968618baf423b097a78d0f914402e847a..ce4ab437785c1fc83a8852a31ada325884eed4a0 100644 (file)
@@ -1 +1,8 @@
-include ../Makefile.proto
+#
+# TeleDongle v0.2 build
+#
+
+TD_VER=0.2
+TD_DEF=0_2
+
+include ../product/Makefile.teledongle
\ No newline at end of file
diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs
deleted file mode 100644 (file)
index ea9713b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-PROG = teledongle-v0.2-$(VERSION).ihx
-
-SRC = \
-       $(TD_SRC) \
-       $(DBG_SRC)
-
-PRODUCT=TeleDongle-v0.2
-PRODUCT_DEF=-DTELEDONGLE_V_0_2
-IDPRODUCT=0x000c
index d8867b1968618baf423b097a78d0f914402e847a..00cdc9c5a22f21c62ea665a1eb409a95096121a1 100644 (file)
@@ -1 +1,16 @@
-include ../Makefile.proto
+#
+# TeleMetrum v0.1 with SkyTraq GPS build
+#
+
+TM_VER=0.1
+TM_DEF=0_1
+
+TM_INC = \
+       ao_25lc1024.h
+
+TM_SRC = \
+       ao_gps_sirf.c \
+       ao_25lc1024.c
+
+include ../product/Makefile.telemetrum
+
diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs
deleted file mode 100644 (file)
index ac8dcdb..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-PROG = telemetrum-v0.1-sirf-$(VERSION).ihx
-
-SRC = \
-       $(TM_BASE_SRC) \
-       $(SPI_DRIVER_SRC) \
-       $(EE_DRIVER_SRC) \
-       $(SIRF_DRIVER_SRC) \
-       $(DBG_SRC)
-
-PRODUCT=TeleMetrum-v0.1-SiRF
-PRODUCT_DEF=-DTELEMETRUM_V_0_1
-IDPRODUCT=0x000b
index d8867b1968618baf423b097a78d0f914402e847a..e3c61db66c0fcb7550a73bddfa5d17dffd76f34c 100644 (file)
@@ -1 +1,16 @@
-include ../Makefile.proto
+#
+# TeleMetrum v0.1 with SkyTraq GPS build
+#
+
+TM_VER=0.1
+TM_DEF=0_1
+
+TM_INC = \
+       ao_25lc1024.h
+
+TM_SRC = \
+       ao_gps_skytraq.c \
+       ao_25lc1024.c
+
+include ../product/Makefile.telemetrum
+
diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs
deleted file mode 100644 (file)
index e032d1e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-PROG = telemetrum-v0.1-sky-$(VERSION).ihx
-
-SRC = \
-       $(TM_BASE_SRC) \
-       $(SPI_DRIVER_SRC) \
-       $(EE_DRIVER_SRC) \
-       $(SKY_DRIVER_SRC) \
-       $(DBG_SRC)
-
-PRODUCT=TeleMetrum-v0.1
-PRODUCT_DEF=-DTELEMETRUM_V_0_1
-IDPRODUCT=0x000b
index d8867b1968618baf423b097a78d0f914402e847a..4aae84c8e0749ce901197d4f17894072c63957fd 100644 (file)
@@ -1 +1,16 @@
-include ../Makefile.proto
+#
+# TeleMetrum v1.0 build
+#
+
+TM_VER=1.0
+TM_DEF=1_0
+
+TM_INC = \
+       ao_at45db161d.h
+
+TM_SRC = \
+       ao_companion.c \
+       ao_gps_skytraq.c \
+       ao_at45db161d.c
+
+include ../product/Makefile.telemetrum
diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs
deleted file mode 100644 (file)
index 5eefc39..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-PROG = telemetrum-v1.0-$(VERSION).ihx
-
-SRC = \
-       $(TM_BASE_SRC) \
-       $(SPI_DRIVER_SRC) \
-       $(FLASH_DRIVER_SRC) \
-       $(SKY_DRIVER_SRC) \
-       $(COMPANION_SRC) \
-       $(DBG_SRC)
-
-PRODUCT=TeleMetrum-v1.0
-PRODUCT_DEF=-DTELEMETRUM_V_1_0
-IDPRODUCT=0x000b
index d8867b1968618baf423b097a78d0f914402e847a..4bea03db3243ce92396623081ba65f74f1798b2c 100644 (file)
@@ -1 +1,16 @@
-include ../Makefile.proto
+#
+# AltOS build
+#
+#
+
+TM_VER=1.1
+TM_DEF=1_1
+
+TM_INC =
+
+TM_SRC = \
+       ao_companion.c \
+       ao_gps_skytraq.c \
+       ao_m25.c
+
+include ../product/Makefile.telemetrum
diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs
deleted file mode 100644 (file)
index 3c8b879..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-PROG = telemetrum-v1.1-$(VERSION).ihx
-
-SRC = \
-       $(TM_BASE_SRC) \
-       $(SPI_DRIVER_SRC) \
-       $(M25_DRIVER_SRC) \
-       $(SKY_DRIVER_SRC) \
-       $(COMPANION_SRC) \
-       $(DBG_SRC)
-
-PRODUCT=TeleMetrum-v1.1
-PRODUCT_DEF=-DTELEMETRUM_V_1_1
-IDPRODUCT=0x000b
index d8867b1968618baf423b097a78d0f914402e847a..4f1c8b51da91a4f46f1ae14c62269f8578d88d7b 100644 (file)
@@ -1 +1,8 @@
-include ../Makefile.proto
+#
+# TeleMini build file
+#
+
+TELEMINI_VER=1.0
+TELEMINI_DEF=1_0
+
+include ../product/Makefile.telemini
diff --git a/src/telemini-v1.0/Makefile.defs b/src/telemini-v1.0/Makefile.defs
deleted file mode 100644 (file)
index 0e91f2f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-PROG = telemini-v1.0-$(VERSION).ihx
-
-SRC = \
-       $(TMINI_BASE_SRC)
-
-PRODUCT=TeleMini-v1.0
-PRODUCT_DEF=-DTELEMINI_V_1_0
-IDPRODUCT=0x000a
-CODESIZE=0x6700
index d8867b1968618baf423b097a78d0f914402e847a..2714c1e98daee4b48e4ebe6a94fe22107a8a3ea0 100644 (file)
@@ -1 +1,9 @@
-include ../Makefile.proto
+#
+# TeleNano build file
+#
+
+TELENANO_VER=0.1
+TELENANO_DEF=0_1
+
+include ../product/Makefile.telenano
+
diff --git a/src/telenano-v0.1/Makefile.defs b/src/telenano-v0.1/Makefile.defs
deleted file mode 100644 (file)
index 34cf69d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-PROG = telenano-v0.1-$(VERSION).ihx
-
-SRC = \
-       $(TNANO_BASE_SRC)
-
-PRODUCT=TeleNano-v0.1
-PRODUCT_DEF=-DTELENANO_V_0_1
-IDPRODUCT=0x000a
-CODESIZE=0x6700
index 33203ffd25c2d3980c6fccf5232db272ca73ad80..333850e4e9c15963678fe9c572d98e97ee1aa2ce 100644 (file)
@@ -1,9 +1,8 @@
-vpath % ..
-vpath % ../kalman
+vpath % ..:../core:../drivers
 
 PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test
 
-CFLAGS=-I.. -I.
+CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g
 
 all: $(PROGS)
 
@@ -13,22 +12,19 @@ clean:
 install:
 
 ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h
-       cc -g -o $@ $<
+       cc $(CFLAGS) -o $@ $<
 
 ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kalman.c altitude.h ao_kalman.h
-       cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c
+       cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c
 
 ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kalman.c altitude.h ao_kalman.h
-       cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c
+       cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c
 
 ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h
-       cc -g -o $@ $<
+       cc $(CFLAGS) -o $@ $<
 
 ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h
-       cc -g -o $@ $<
+       cc $(CFLAGS) -o $@ $<
 
 ao_convert_test: ao_convert_test.c ao_convert.c altitude.h
-       cc -g -o $@ $<
-
-../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c
-       sh $< > $@
+       cc $(CFLAGS) -o $@ $<
diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c
new file mode 100644 (file)
index 0000000..56733c8
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <math.h>
+
+#define AO_HERTZ       100
+
+#define AO_ADC_RING    64
+#define ao_adc_ring_next(n)    (((n) + 1) & (AO_ADC_RING - 1))
+#define ao_adc_ring_prev(n)    (((n) - 1) & (AO_ADC_RING - 1))
+
+#define AO_M_TO_HEIGHT(m)      ((int16_t) (m))
+#define AO_MS_TO_SPEED(ms)     ((int16_t) ((ms) * 16))
+#define AO_MSS_TO_ACCEL(mss)   ((int16_t) ((mss) * 16))
+
+/*
+ * One set of samples read from the A/D converter
+ */
+struct ao_adc {
+       uint16_t        tick;           /* tick when the sample was read */
+       int16_t         accel;          /* accelerometer */
+       int16_t         pres;           /* pressure sensor */
+       int16_t         pres_real;      /* unclipped */
+       int16_t         temp;           /* temperature sensor */
+       int16_t         v_batt;         /* battery voltage */
+       int16_t         sense_d;        /* drogue continuity sense */
+       int16_t         sense_m;        /* main continuity sense */
+};
+
+#define __pdata
+#define __data
+#define __xdata
+#define __code
+#define __reentrant
+
+#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5))
+#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))
+#define from_fix(x)    ((x) >> 16)
+
+/*
+ * Above this height, the baro sensor doesn't work
+ */
+#define AO_MAX_BARO_HEIGHT     12000
+#define AO_BARO_SATURATE       13000
+#define AO_MIN_BARO_VALUE      ao_altitude_to_pres(AO_BARO_SATURATE)
+
+/*
+ * Above this speed, baro measurements are unreliable
+ */
+#define AO_MAX_BARO_SPEED      200
+
+#define ACCEL_NOSE_UP  (ao_accel_2g >> 2)
+
+enum ao_flight_state {
+       ao_flight_startup = 0,
+       ao_flight_idle = 1,
+       ao_flight_pad = 2,
+       ao_flight_boost = 3,
+       ao_flight_fast = 4,
+       ao_flight_coast = 5,
+       ao_flight_drogue = 6,
+       ao_flight_main = 7,
+       ao_flight_landed = 8,
+       ao_flight_invalid = 9
+};
+
+extern enum ao_flight_state ao_flight_state;
+
+#define FALSE 0
+#define TRUE 1
+
+struct ao_adc ao_adc_ring[AO_ADC_RING];
+uint8_t ao_adc_head;
+int    ao_summary = 0;
+
+#define ao_led_on(l)
+#define ao_led_off(l)
+#define ao_timer_set_adc_interval(i)
+#define ao_wakeup(wchan) ao_dump_state()
+#define ao_cmd_register(c)
+#define ao_usb_disable()
+#define ao_telemetry_set_interval(x)
+#define ao_rdf_set(rdf)
+#define ao_packet_slave_start()
+#define ao_packet_slave_stop()
+
+enum ao_igniter {
+       ao_igniter_drogue = 0,
+       ao_igniter_main = 1
+};
+
+struct ao_adc ao_adc_static;
+
+int    drogue_height;
+double drogue_time;
+int    main_height;
+double main_time;
+
+int    tick_offset;
+
+static int32_t ao_k_height;
+
+void
+ao_ignite(enum ao_igniter igniter)
+{
+       double time = (double) (ao_adc_static.tick + tick_offset) / 100;
+
+       if (igniter == ao_igniter_drogue) {
+               drogue_time = time;
+               drogue_height = ao_k_height >> 16;
+       } else {
+               main_time = time;
+               main_height = ao_k_height >> 16;
+       }
+}
+
+struct ao_task {
+       int dummy;
+};
+
+#define ao_add_task(t,f,n)
+
+#define ao_log_start()
+#define ao_log_stop()
+
+#define AO_MS_TO_TICKS(ms)     ((ms) / 10)
+#define AO_SEC_TO_TICKS(s)     ((s) * 100)
+
+#define AO_FLIGHT_TEST
+
+int    ao_flight_debug;
+
+FILE *emulator_in;
+char *emulator_app;
+char *emulator_name;
+double emulator_error_max = 4;
+double emulator_height_error_max = 20; /* noise in the baro sensor */
+
+void
+ao_dump_state(void);
+
+void
+ao_sleep(void *wchan);
+
+const char const * const ao_state_names[] = {
+       "startup", "idle", "pad", "boost", "fast",
+       "coast", "drogue", "main", "landed", "invalid"
+};
+
+struct ao_cmds {
+       void            (*func)(void);
+       const char      *help;
+};
+
+#include "ao_convert.c"
+
+struct ao_config {
+       uint16_t        main_deploy;
+       int16_t         accel_plus_g;
+       int16_t         accel_minus_g;
+       uint8_t         pad_orientation;
+};
+
+#define AO_PAD_ORIENTATION_ANTENNA_UP  0
+#define AO_PAD_ORIENTATION_ANTENNA_DOWN        1
+
+#define ao_config_get()
+
+struct ao_config ao_config;
+
+#define DATA_TO_XDATA(x) (x)
+
+#define HAS_FLIGHT 1
+#define HAS_ADC 1
+#define HAS_USB 1
+#define HAS_GPS 1
+#ifndef HAS_ACCEL
+#define HAS_ACCEL 1
+#define HAS_ACCEL_REF 0
+#endif
+
+#define GRAVITY 9.80665
+extern int16_t ao_ground_accel, ao_flight_accel;
+extern int16_t ao_accel_2g;
+
+extern uint16_t        ao_sample_tick;
+
+extern int16_t ao_sample_height;
+extern int16_t ao_sample_accel;
+extern int32_t ao_accel_scale;
+extern int16_t ao_ground_height;
+extern int16_t ao_sample_alt;
+
+int ao_sample_prev_tick;
+uint16_t       prev_tick;
+
+#include "ao_kalman.c"
+#include "ao_sample.c"
+#include "ao_flight.c"
+
+#define to_double(f)   ((f) / 65536.0)
+
+static int     ao_records_read = 0;
+static int     ao_eof_read = 0;
+static int     ao_flight_ground_accel;
+static int     ao_flight_started = 0;
+static int     ao_test_max_height;
+static double  ao_test_max_height_time;
+static int     ao_test_main_height;
+static double  ao_test_main_height_time;
+static double  ao_test_landed_time;
+static double  ao_test_landed_height;
+static double  ao_test_landed_time;
+static int     landed_set;
+static double  landed_time;
+static double  landed_height;
+
+void
+ao_test_exit(void)
+{
+       double  drogue_error;
+       double  main_error;
+       double  landed_error;
+       double  landed_time_error;
+
+       if (!ao_test_main_height_time) {
+               ao_test_main_height_time = ao_test_max_height_time;
+               ao_test_main_height = ao_test_max_height;
+       }
+       drogue_error = fabs(ao_test_max_height_time - drogue_time);
+       main_error = fabs(ao_test_main_height_time - main_time);
+       landed_error = fabs(ao_test_landed_height - landed_height);
+       landed_time_error = ao_test_landed_time - landed_time;
+       if (drogue_error > emulator_error_max || main_error > emulator_error_max ||
+           landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) {
+               printf ("%s %s\n",
+                       emulator_app, emulator_name);
+               printf ("\tApogee error %g\n", drogue_error);
+               printf ("\tMain error %g\n", main_error);
+               printf ("\tLanded height error %g\n", landed_error);
+               printf ("\tLanded time error %g\n", landed_time_error);
+               printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n",
+                       ao_test_max_height, ao_test_max_height_time,
+                       ao_test_main_height, ao_test_main_height_time,
+                       ao_test_landed_height, ao_test_landed_time);
+               printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n",
+                       drogue_height, drogue_time, main_height, main_time,
+                       landed_height, landed_time);
+               exit (1);
+       }
+       exit(0);
+}
+
+void
+ao_insert(void)
+{
+       double  time;
+
+       ao_adc_ring[ao_adc_head] = ao_adc_static;
+       ao_adc_head = ao_adc_ring_next(ao_adc_head);
+       if (ao_flight_state != ao_flight_startup) {
+               double  height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height;
+               double  accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) /
+                       (ao_config.accel_minus_g - ao_config.accel_plus_g);
+
+               if (!tick_offset)
+                       tick_offset = -ao_adc_static.tick;
+               if ((prev_tick - ao_adc_static.tick) > 0x400)
+                       tick_offset += 65536;
+               prev_tick = ao_adc_static.tick;
+               time = (double) (ao_adc_static.tick + tick_offset) / 100;
+
+               if (ao_test_max_height < height) {
+                       ao_test_max_height = height;
+                       ao_test_max_height_time = time;
+                       ao_test_landed_height = height;
+                       ao_test_landed_time = time;
+               }
+               if (height > ao_config.main_deploy) {
+                       ao_test_main_height_time = time;
+                       ao_test_main_height = height;
+               }
+
+               if (ao_test_landed_height > height) {
+                       ao_test_landed_height = height;
+                       ao_test_landed_time = time;
+               }
+
+               if (ao_flight_state == ao_flight_landed && !landed_set) {
+                       landed_set = 1;
+                       landed_time = time;
+                       landed_height = height;
+               }
+
+               if (!ao_summary) {
+                       printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n",
+                              time,
+                              height,
+                              accel,
+                              ao_state_names[ao_flight_state],
+                              ao_k_height / 65536.0,
+                              ao_k_speed / 65536.0 / 16.0,
+                              ao_k_accel / 65536.0 / 16.0,
+                              ao_avg_height,
+                              drogue_height,
+                              main_height,
+                              ao_error_h_sq_avg);
+                       
+//                     if (ao_flight_state == ao_flight_landed)
+//                             ao_test_exit();
+               }
+       }
+}
+
+#define AO_MAX_CALLSIGN                        8
+#define AO_MAX_VERSION                 8
+#define AO_MAX_TELEMETRY               128
+
+struct ao_telemetry_generic {
+       uint16_t        serial;         /* 0 */
+       uint16_t        tick;           /* 2 */
+       uint8_t         type;           /* 4 */
+       uint8_t         payload[27];    /* 5 */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01
+#define AO_TELEMETRY_SENSOR_TELEMINI   0x02
+#define AO_TELEMETRY_SENSOR_TELENANO   0x03
+
+struct ao_telemetry_sensor {
+       uint16_t        serial;         /*  0 */
+       uint16_t        tick;           /*  2 */
+       uint8_t         type;           /*  4 */
+
+       uint8_t         state;          /*  5 flight state */
+       int16_t         accel;          /*  6 accelerometer (TM only) */
+       int16_t         pres;           /*  8 pressure sensor */
+       int16_t         temp;           /* 10 temperature sensor */
+       int16_t         v_batt;         /* 12 battery voltage */
+       int16_t         sense_d;        /* 14 drogue continuity sense (TM/Tm) */
+       int16_t         sense_m;        /* 16 main continuity sense (TM/Tm) */
+
+       int16_t         acceleration;   /* 18 m/s² * 16 */
+       int16_t         speed;          /* 20 m/s * 16 */
+       int16_t         height;         /* 22 m */
+
+       int16_t         ground_pres;    /* 24 average pres on pad */
+       int16_t         ground_accel;   /* 26 average accel on pad */
+       int16_t         accel_plus_g;   /* 28 accel calibration at +1g */
+       int16_t         accel_minus_g;  /* 30 accel calibration at -1g */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_CONFIGURATION     0x04
+
+struct ao_telemetry_configuration {
+       uint16_t        serial;                         /*  0 */
+       uint16_t        tick;                           /*  2 */
+       uint8_t         type;                           /*  4 */
+
+       uint8_t         device;                         /*  5 device type */
+       uint16_t        flight;                         /*  6 flight number */
+       uint8_t         config_major;                   /*  8 Config major version */
+       uint8_t         config_minor;                   /*  9 Config minor version */
+       uint16_t        apogee_delay;                   /* 10 Apogee deploy delay in seconds */
+       uint16_t        main_deploy;                    /* 12 Main deploy alt in meters */
+       uint16_t        flight_log_max;                 /* 14 Maximum flight log size in kB */
+       char            callsign[AO_MAX_CALLSIGN];      /* 16 Radio operator identity */
+       char            version[AO_MAX_VERSION];        /* 24 Software version */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_LOCATION          0x05
+
+#define AO_GPS_MODE_NOT_VALID          'N'
+#define AO_GPS_MODE_AUTONOMOUS         'A'
+#define AO_GPS_MODE_DIFFERENTIAL       'D'
+#define AO_GPS_MODE_ESTIMATED          'E'
+#define AO_GPS_MODE_MANUAL             'M'
+#define AO_GPS_MODE_SIMULATED          'S'
+
+struct ao_telemetry_location {
+       uint16_t        serial;         /*  0 */
+       uint16_t        tick;           /*  2 */
+       uint8_t         type;           /*  4 */
+
+       uint8_t         flags;          /*  5 Number of sats and other flags */
+       int16_t         altitude;       /*  6 GPS reported altitude (m) */
+       int32_t         latitude;       /*  8 latitude (degrees * 10⁷) */
+       int32_t         longitude;      /* 12 longitude (degrees * 10⁷) */
+       uint8_t         year;           /* 16 (- 2000) */
+       uint8_t         month;          /* 17 (1-12) */
+       uint8_t         day;            /* 18 (1-31) */
+       uint8_t         hour;           /* 19 (0-23) */
+       uint8_t         minute;         /* 20 (0-59) */
+       uint8_t         second;         /* 21 (0-59) */
+       uint8_t         pdop;           /* 22 (m * 5) */
+       uint8_t         hdop;           /* 23 (m * 5) */
+       uint8_t         vdop;           /* 24 (m * 5) */
+       uint8_t         mode;           /* 25 */
+       uint16_t        ground_speed;   /* 26 cm/s */
+       int16_t         climb_rate;     /* 28 cm/s */
+       uint8_t         course;         /* 30 degrees / 2 */
+       uint8_t         unused[1];      /* 31 */
+       /* 32 */
+};
+
+#define AO_TELEMETRY_SATELLITE         0x06
+
+struct ao_telemetry_satellite_info {
+       uint8_t         svid;
+       uint8_t         c_n_1;
+};
+
+struct ao_telemetry_satellite {
+       uint16_t                                serial;         /*  0 */
+       uint16_t                                tick;           /*  2 */
+       uint8_t                                 type;           /*  4 */
+       uint8_t                                 channels;       /*  5 number of reported sats */
+
+       struct ao_telemetry_satellite_info      sats[12];       /* 6 */
+       uint8_t                                 unused[2];      /* 30 */
+       /* 32 */
+};
+
+union ao_telemetry_all {
+       struct ao_telemetry_generic             generic;
+       struct ao_telemetry_sensor              sensor;
+       struct ao_telemetry_configuration       configuration;
+       struct ao_telemetry_location            location;
+       struct ao_telemetry_satellite           satellite;
+};
+
+uint16_t
+uint16(uint8_t *bytes, int off)
+{
+       off++;
+       return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8);
+}
+
+int16_t
+int16(uint8_t *bytes, int off)
+{
+       return (int16_t) uint16(bytes, off);
+}
+
+void
+ao_sleep(void *wchan)
+{
+       if (wchan == &ao_adc_head) {
+               char            type;
+               uint16_t        tick;
+               uint16_t        a, b;
+               int             ret;
+               uint8_t         bytes[1024];
+               union ao_telemetry_all  telem;
+               char            line[1024];
+               char            *saveptr;
+               char            *l;
+               char            *words[64];
+               int             nword;
+
+               for (;;) {
+                       if (ao_records_read > 2 && ao_flight_state == ao_flight_startup)
+                       {
+                               ao_adc_static.accel = ao_flight_ground_accel;
+                               ao_insert();
+                               return;
+                       }
+
+                       if (!fgets(line, sizeof (line), emulator_in)) {
+                               if (++ao_eof_read >= 1000) {
+                                       if (!ao_summary)
+                                               printf ("no more data, exiting simulation\n");
+                                       ao_test_exit();
+                               }
+                               ao_adc_static.tick += 10;
+                               ao_insert();
+                               return;
+                       }
+                       l = line;
+                       for (nword = 0; nword < 64; nword++) {
+                               words[nword] = strtok_r(l, " \t\n", &saveptr);
+                               l = NULL;
+                               if (words[nword] == NULL)
+                                       break;
+                       }
+                       if (nword == 4) {
+                               type = words[0][0];
+                               tick = strtoul(words[1], NULL, 16);
+                               a = strtoul(words[2], NULL, 16);
+                               b = strtoul(words[3], NULL, 16);
+                               if (type == 'P')
+                                       type = 'A';
+                       } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) {
+                               ao_config.accel_plus_g = atoi(words[3]);
+                               ao_config.accel_minus_g = atoi(words[5]);
+                       } else if (nword >= 4 && strcmp(words[0], "Main") == 0) {
+                               ao_config.main_deploy = atoi(words[2]);
+                       } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) {
+                               tick = atoi(words[10]);
+                               if (!ao_flight_started) {
+                                       type = 'F';
+                                       a = atoi(words[26]);
+                                       ao_flight_started = 1;
+                               } else {
+                                       type = 'A';
+                                       a = atoi(words[12]);
+                                       b = atoi(words[14]);
+                               }
+                       } else if (nword == 3 && strcmp(words[0], "BARO") == 0) {
+                               tick = strtol(words[1], NULL, 16);
+                               a = 16384 - 328;
+                               b = strtol(words[2], NULL, 10);
+                               type = 'A';
+                               if (!ao_flight_started) {
+                                       ao_flight_ground_accel = 16384 - 328;
+                                       ao_config.accel_plus_g = 16384 - 328;
+                                       ao_config.accel_minus_g = 16384 + 328;
+                                       ao_flight_started = 1;
+                               }
+                       } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) {
+                               char    *hex = words[1];
+                               char    elt[3];
+                               int     i, len;
+                               uint8_t sum;
+
+                               len = strlen(hex);
+                               if (len > sizeof (bytes) * 2) {
+                                       len = sizeof (bytes)*2;
+                                       hex[len] = '\0';
+                               }
+                               for (i = 0; i < len; i += 2) {
+                                       elt[0] = hex[i];
+                                       elt[1] = hex[i+1];
+                                       elt[2] = '\0';
+                                       bytes[i/2] = (uint8_t) strtol(elt, NULL, 16);
+                               }
+                               len = i/2;
+                               if (bytes[0] != len - 2) {
+                                       printf ("bad length %d != %d\n", bytes[0], len - 2);
+                                       continue;
+                               }
+                               sum = 0x5a;
+                               for (i = 1; i < len-1; i++)
+                                       sum += bytes[i];
+                               if (sum != bytes[len-1]) {
+                                       printf ("bad checksum\n");
+                                       continue;
+                               }
+                               if ((bytes[len-2] & 0x80) == 0) {
+                                       continue;
+                               }
+                               if (len == 36) {
+                                       memcpy(&telem, bytes + 1, 32);
+                                       tick = telem.generic.tick;
+                                       switch (telem.generic.type) {
+                                       case AO_TELEMETRY_SENSOR_TELEMETRUM:
+                                       case AO_TELEMETRY_SENSOR_TELEMINI:
+                                       case AO_TELEMETRY_SENSOR_TELENANO:
+                                               if (!ao_flight_started) {
+                                                       ao_flight_ground_accel = telem.sensor.ground_accel;
+                                                       ao_config.accel_plus_g = telem.sensor.accel_plus_g;
+                                                       ao_config.accel_minus_g = telem.sensor.accel_minus_g;
+                                                       ao_flight_started = 1;
+                                               }
+                                               type = 'A';
+                                               a = telem.sensor.accel;
+                                               b = telem.sensor.pres;
+                                               break;
+                                       }
+                               } else if (len == 99) {
+                                       ao_flight_started = 1;
+                                       tick = uint16(bytes, 21);
+                                       ao_flight_ground_accel = int16(bytes, 7);
+                                       ao_config.accel_plus_g = int16(bytes, 17);
+                                       ao_config.accel_minus_g = int16(bytes, 19);
+                                       type = 'A';
+                                       a = int16(bytes, 23);
+                                       b = int16(bytes, 25);
+                               } else if (len == 98) {
+                                       ao_flight_started = 1;
+                                       tick = uint16(bytes, 20);
+                                       ao_flight_ground_accel = int16(bytes, 6);
+                                       ao_config.accel_plus_g = int16(bytes, 16);
+                                       ao_config.accel_minus_g = int16(bytes, 18);
+                                       type = 'A';
+                                       a = int16(bytes, 22);
+                                       b = int16(bytes, 24);
+                               } else {
+                                       printf("unknown len %d\n", len);
+                                       continue;
+                               }
+                       }
+                       if (type != 'F' && !ao_flight_started)
+                               continue;
+
+                       switch (type) {
+                       case 'F':
+                               ao_flight_ground_accel = a;
+                               if (ao_config.accel_plus_g == 0) {
+                                       ao_config.accel_plus_g = a;
+                                       ao_config.accel_minus_g = a + 530;
+                               }
+                               if (ao_config.main_deploy == 0)
+                                       ao_config.main_deploy = 250;
+                               ao_flight_started = 1;
+                               break;
+                       case 'S':
+                               break;
+                       case 'A':
+                               ao_adc_static.tick = tick;
+                               ao_adc_static.accel = a;
+                               ao_adc_static.pres_real = b;
+                               if (b < AO_MIN_BARO_VALUE)
+                                       b = AO_MIN_BARO_VALUE;
+                               ao_adc_static.pres = b;
+                               ao_records_read++;
+                               ao_insert();
+                               return;
+                       case 'T':
+                               ao_adc_static.tick = tick;
+                               ao_adc_static.temp = a;
+                               ao_adc_static.v_batt = b;
+                               break;
+                       case 'D':
+                       case 'G':
+                       case 'N':
+                       case 'W':
+                       case 'H':
+                               break;
+                       }
+               }
+
+       }
+}
+#define COUNTS_PER_G 264.8
+
+void
+ao_dump_state(void)
+{
+}
+
+static const struct option options[] = {
+       { .name = "summary", .has_arg = 0, .val = 's' },
+       { .name = "debug", .has_arg = 0, .val = 'd' },
+       { 0, 0, 0, 0},
+};
+
+void run_flight_fixed(char *name, FILE *f, int summary)
+{
+       emulator_name = name;
+       emulator_in = f;
+       ao_summary = summary;
+       ao_flight_init();
+       ao_flight();
+}
+
+int
+main (int argc, char **argv)
+{
+       int     summary = 0;
+       int     c;
+       int     i;
+
+#if HAS_ACCEL
+       emulator_app="full";
+#else
+       emulator_app="baro";
+#endif
+       while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) {
+               switch (c) {
+               case 's':
+                       summary = 1;
+                       break;
+               case 'd':
+                       ao_flight_debug = 1;
+                       break;
+               }
+       }
+
+       if (optind == argc)
+               run_flight_fixed("<stdin>", stdin, summary);
+       else
+               for (i = optind; i < argc; i++) {
+                       FILE    *f = fopen(argv[i], "r");
+                       if (!f) {
+                               perror(argv[i]);
+                               continue;
+                       }
+                       run_flight_fixed(argv[i], f, summary);
+                       fclose(f);
+               }
+}
diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c
new file mode 100644 (file)
index 0000000..93d7a9a
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define AO_GPS_TEST
+#include "ao_host.h"
+#include <termios.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
+#define AO_GPS_NUM_SAT_SHIFT   (0)
+
+#define AO_GPS_VALID           (1 << 4)
+#define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
+#define AO_GPS_COURSE_VALID    (1 << 7)
+
+struct ao_gps_orig {
+       uint8_t                 year;
+       uint8_t                 month;
+       uint8_t                 day;
+       uint8_t                 hour;
+       uint8_t                 minute;
+       uint8_t                 second;
+       uint8_t                 flags;
+       int32_t                 latitude;       /* degrees * 10⁷ */
+       int32_t                 longitude;      /* degrees * 10⁷ */
+       int16_t                 altitude;       /* m */
+       uint16_t                ground_speed;   /* cm/s */
+       uint8_t                 course;         /* degrees / 2 */
+       uint8_t                 hdop;           /* * 5 */
+       int16_t                 climb_rate;     /* cm/s */
+       uint16_t                h_error;        /* m */
+       uint16_t                v_error;        /* m */
+};
+
+#define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
+#define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
+#define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
+#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE                (1 << 3)
+#define SIRF_SAT_CARRIER_PULLIN_COMPLETE       (1 << 4)
+#define SIRF_SAT_CODE_LOCKED                   (1 << 5)
+#define SIRF_SAT_ACQUISITION_FAILED            (1 << 6)
+#define SIRF_SAT_EPHEMERIS_AVAILABLE           (1 << 7)
+
+struct ao_gps_sat_orig {
+       uint8_t         svid;
+       uint8_t         c_n_1;
+};
+
+#define AO_MAX_GPS_TRACKING    12
+
+struct ao_gps_tracking_orig {
+       uint8_t                 channels;
+       struct ao_gps_sat_orig  sats[AO_MAX_GPS_TRACKING];
+};
+
+#define ao_telemetry_location ao_gps_orig
+#define ao_telemetry_satellite ao_gps_tracking_orig
+#define ao_telemetry_satellite_info ao_gps_sat_orig
+
+void
+ao_mutex_get(uint8_t *mutex)
+{
+}
+
+void
+ao_mutex_put(uint8_t *mutex)
+{
+}
+
+static int
+ao_gps_fd;
+
+static void
+ao_dbg_char(char c)
+{
+       char    line[128];
+       line[0] = '\0';
+       if (c < ' ') {
+               if (c == '\n')
+                       sprintf (line, "\n");
+               else
+                       sprintf (line, "\\%02x", ((int) c) & 0xff);
+       } else {
+               sprintf (line, "%c", c);
+       }
+       write(1, line, strlen(line));
+}
+
+#define QUEUE_LEN      4096
+
+static char    input_queue[QUEUE_LEN];
+int            input_head, input_tail;
+
+#include <sys/time.h>
+
+int
+get_millis(void)
+{
+       struct timeval  tv;
+       gettimeofday(&tv, NULL);
+       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+static void
+check_sirf_message(char *from, uint8_t *msg, int len)
+{
+       uint16_t        encoded_len, encoded_cksum;
+       uint16_t        cksum;
+       uint8_t         id;
+       int             i;
+
+       if (msg[0] != 0xa0 || msg[1] != 0xa2) {
+               printf ("bad header\n");
+               return;
+       }
+       if (len < 7) {
+               printf("short\n");
+               return;
+       }
+       if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) {
+               printf ("bad trailer\n");
+               return;
+       }
+       encoded_len = (msg[2] << 8) | msg[3];
+       id = msg[4];
+/*     printf ("%9d: %3d\n", get_millis(), id); */
+       if (encoded_len != len - 8) {
+               if (id != 52)
+                       printf ("length mismatch (got %d, wanted %d)\n",
+                               len - 8, encoded_len);
+               return;
+       }
+       encoded_cksum = (msg[len - 4] << 8) | msg[len-3];
+       cksum = 0;
+       for (i = 4; i < len - 4; i++)
+               cksum = (cksum + msg[i]) & 0x7fff;
+       if (encoded_cksum != cksum) {
+               printf ("cksum mismatch (got %04x wanted %04x)\n",
+                       cksum, encoded_cksum);
+               return;
+       }
+       id = msg[4];
+       switch (id) {
+       case 41:{
+               int     off = 4;
+
+               uint8_t         id;
+               uint16_t        nav_valid;
+               uint16_t        nav_type;
+               uint16_t        week;
+               uint32_t        tow;
+               uint16_t        year;
+               uint8_t         month;
+               uint8_t         day;
+               uint8_t         hour;
+               uint8_t         minute;
+               uint16_t        second;
+               uint32_t        sat_list;
+               int32_t         lat;
+               int32_t         lon;
+               int32_t         alt_ell;
+               int32_t         alt_msl;
+               int8_t          datum;
+               uint16_t        sog;
+               uint16_t        cog;
+               int16_t         mag_var;
+               int16_t         climb_rate;
+               int16_t         heading_rate;
+               uint32_t        h_error;
+               uint32_t        v_error;
+               uint32_t        t_error;
+               uint16_t        h_v_error;
+
+#define get_u8(u)      u = (msg[off]); off+= 1
+#define get_u16(u)     u = (msg[off] << 8) | (msg[off + 1]); off+= 2
+#define get_u32(u)     u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4
+
+               get_u8(id);
+               get_u16(nav_valid);
+               get_u16(nav_type);
+               get_u16(week);
+               get_u32(tow);
+               get_u16(year);
+               get_u8(month);
+               get_u8(day);
+               get_u8(hour);
+               get_u8(minute);
+               get_u16(second);
+               get_u32(sat_list);
+               get_u32(lat);
+               get_u32(lon);
+               get_u32(alt_ell);
+               get_u32(alt_msl);
+               get_u8(datum);
+               get_u16(sog);
+               get_u16(cog);
+               get_u16(mag_var);
+               get_u16(climb_rate);
+               get_u16(heading_rate);
+               get_u32(h_error);
+               get_u32(v_error);
+               get_u32(t_error);
+               get_u16(h_v_error);
+
+
+               printf ("Geodetic Navigation Data (41):\n");
+               printf ("\tNav valid %04x\n", nav_valid);
+               printf ("\tNav type %04x\n", nav_type);
+               printf ("\tWeek %5d", week);
+               printf (" TOW %9d", tow);
+               printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n",
+                       year, month, day,
+                       hour, minute, second / 1000.0);
+               printf ("\tsats: %08x\n", sat_list);
+               printf ("\tlat: %g", lat / 1.0e7);
+               printf (" lon: %g", lon / 1.0e7);
+               printf (" alt_ell: %g", alt_ell / 100.0);
+               printf (" alt_msll: %g", alt_msl / 100.0);
+               printf (" datum: %d\n", datum);
+               printf ("\tground speed: %g", sog / 100.0);
+               printf (" course: %g", cog / 100.0);
+               printf (" climb: %g", climb_rate / 100.0);
+               printf (" heading rate: %g\n", heading_rate / 100.0);
+               printf ("\th error: %g", h_error / 100.0);
+               printf (" v error: %g", v_error / 100.0);
+               printf (" t error: %g", t_error / 100.0);
+               printf (" h vel error: %g\n", h_v_error / 100.0);
+               break;
+       }
+       case 4: {
+               int off = 4;
+               uint8_t         id;
+               int16_t         gps_week;
+               uint32_t        gps_tow;
+               uint8_t         channels;
+               int             j, k;
+
+               get_u8(id);
+               get_u16(gps_week);
+               get_u32(gps_tow);
+               get_u8(channels);
+
+               printf ("Measured Tracker Data (4):\n");
+               printf ("GPS week: %d\n", gps_week);
+               printf ("GPS time of week: %d\n", gps_tow);
+               printf ("channels: %d\n", channels);
+               for (j = 0; j < 12; j++) {
+                       uint8_t svid, azimuth, elevation;
+                       uint16_t state;
+                       uint8_t c_n[10];
+                       get_u8(svid);
+                       get_u8(azimuth);
+                       get_u8(elevation);
+                       get_u16(state);
+                       for (k = 0; k < 10; k++) {
+                               get_u8(c_n[k]);
+                       }
+                       printf ("Sat %3d:", svid);
+                       printf (" aziumuth: %6.1f", azimuth * 1.5);
+                       printf (" elevation: %6.1f", elevation * 0.5);
+                       printf (" state: 0x%02x", state);
+                       printf (" c_n:");
+                       for (k = 0; k < 10; k++)
+                               printf(" %3d", c_n[k]);
+                       if (state & SIRF_SAT_STATE_ACQUIRED)
+                               printf(" acq,");
+                       if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID)
+                               printf(" car,");
+                       if (state & SIRF_SAT_BIT_SYNC_COMPLETE)
+                               printf(" bit,");
+                       if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE)
+                               printf(" sub,");
+                       if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE)
+                               printf(" pullin,");
+                       if (state & SIRF_SAT_CODE_LOCKED)
+                               printf(" code,");
+                       if (state & SIRF_SAT_ACQUISITION_FAILED)
+                               printf(" fail,");
+                       if (state & SIRF_SAT_EPHEMERIS_AVAILABLE)
+                               printf(" ephem,");
+                       printf ("\n");
+               }
+               break;
+       }
+       default:
+               return;
+               printf ("%s %4d:", from, encoded_len);
+               for (i = 4; i < len - 4; i++) {
+                       if (((i - 4) & 0xf) == 0)
+                               printf("\n   ");
+                       printf (" %3d", msg[i]);
+               }
+               printf ("\n");
+       }
+}
+
+static uint8_t sirf_message[4096];
+static int     sirf_message_len;
+static uint8_t sirf_in_message[4096];
+static int     sirf_in_len;
+
+char
+ao_serial_getchar(void)
+{
+       char    c;
+       uint8_t uc;
+
+       while (input_head == input_tail) {
+               for (;;) {
+                       input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN);
+                       if (input_tail < 0) {
+                               if (errno == EINTR || errno == EAGAIN)
+                                       continue;
+                               perror ("getchar");
+                               exit (1);
+                       }
+                       input_head = 0;
+                       break;
+               }
+       }
+       c = input_queue[input_head];
+       input_head = (input_head + 1) % QUEUE_LEN;
+       uc = c;
+       if (sirf_in_len || uc == 0xa0) {
+               if (sirf_in_len < 4096)
+                       sirf_in_message[sirf_in_len++] = uc;
+               if (uc == 0xb3) {
+                       check_sirf_message("recv", sirf_in_message, sirf_in_len);
+                       sirf_in_len = 0;
+               }
+       }
+       return c;
+}
+
+
+void
+ao_serial_putchar(char c)
+{
+       int     i;
+       uint8_t uc = (uint8_t) c;
+
+       if (sirf_message_len || uc == 0xa0) {
+               if (sirf_message_len < 4096)
+                       sirf_message[sirf_message_len++] = uc;
+               if (uc == 0xb3) {
+                       check_sirf_message("send", sirf_message, sirf_message_len);
+                       sirf_message_len = 0;
+               }
+       }
+       for (;;) {
+               i = write(ao_gps_fd, &c, 1);
+               if (i == 1) {
+                       if ((uint8_t) c == 0xb3 || c == '\r') {
+                               static const struct timespec delay = {
+                                       .tv_sec = 0,
+                                       .tv_nsec = 100 * 1000 * 1000
+                               };
+                               tcdrain(ao_gps_fd);
+//                             nanosleep(&delay, NULL);
+                       }
+                       break;
+               }
+               if (i < 0 && (errno == EINTR || errno == EAGAIN))
+                       continue;
+               perror("putchar");
+               exit(1);
+       }
+}
+
+#define AO_SERIAL_SPEED_4800   0
+#define AO_SERIAL_SPEED_57600  1
+
+static void
+ao_serial_set_speed(uint8_t speed)
+{
+       int     fd = ao_gps_fd;
+       struct termios  termios;
+
+       tcdrain(fd);
+       tcgetattr(fd, &termios);
+       switch (speed) {
+       case AO_SERIAL_SPEED_4800:
+               cfsetspeed(&termios, B4800);
+               break;
+       case AO_SERIAL_SPEED_57600:
+               cfsetspeed(&termios, B57600);
+               break;
+       }
+       tcsetattr(fd, TCSAFLUSH, &termios);
+       tcflush(fd, TCIFLUSH);
+}
+
+#define ao_time() 0
+
+#include "ao_gps_print.c"
+#include "ao_gps_sirf.c"
+
+void
+ao_dump_state(void *wchan)
+{
+       double  lat, lon;
+       int     i;
+       if (wchan == &ao_gps_data)
+               ao_gps_print(&ao_gps_data);
+       else
+               ao_gps_tracking_print(&ao_gps_tracking_data);
+       putchar('\n');
+       return;
+       printf ("%02d:%02d:%02d",
+               ao_gps_data.hour, ao_gps_data.minute,
+               ao_gps_data.second);
+       printf (" nsat %d %svalid",
+               ao_gps_data.flags & AO_GPS_NUM_SAT_MASK,
+               ao_gps_data.flags & AO_GPS_VALID ? "" : "not ");
+       printf (" lat %g lon %g alt %d",
+               ao_gps_data.latitude / 1.0e7,
+               ao_gps_data.longitude / 1.0e7,
+               ao_gps_data.altitude);
+       printf (" speed %g climb %g course %d",
+               ao_gps_data.ground_speed / 100.0,
+               ao_gps_data.climb_rate / 100.0,
+               ao_gps_data.course * 2);
+       printf (" hdop %g h_error %d v_error %d",
+               ao_gps_data.hdop / 5.0,
+               ao_gps_data.h_error, ao_gps_data.v_error);
+       printf("\n");
+       printf ("\t");
+       for (i = 0; i < 12; i++)
+               printf (" %2d(%02d)",
+                       ao_gps_tracking_data.sats[i].svid,
+                       ao_gps_tracking_data.sats[i].c_n_1);
+       printf ("\n");
+}
+
+int
+ao_gps_open(const char *tty)
+{
+       struct termios  termios;
+       int fd;
+
+       fd = open (tty, O_RDWR);
+       if (fd < 0)
+               return -1;
+
+       tcgetattr(fd, &termios);
+       cfmakeraw(&termios);
+       cfsetspeed(&termios, B4800);
+       tcsetattr(fd, TCSAFLUSH, &termios);
+
+       tcdrain(fd);
+       tcflush(fd, TCIFLUSH);
+       return fd;
+}
+
+#include <getopt.h>
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--tty <tty-name>]\n", program);
+       exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+       char    *tty = "/dev/ttyUSB0";
+       int     c;
+
+       while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+       ao_gps_fd = ao_gps_open(tty);
+       if (ao_gps_fd < 0) {
+               perror (tty);
+               exit (1);
+       }
+       ao_gps_setup();
+       ao_gps();
+}
diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c
new file mode 100644 (file)
index 0000000..a78fae0
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define AO_GPS_TEST
+#include "ao_host.h"
+#include <termios.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define AO_GPS_NUM_SAT_MASK    (0xf << 0)
+#define AO_GPS_NUM_SAT_SHIFT   (0)
+
+#define AO_GPS_VALID           (1 << 4)
+#define AO_GPS_RUNNING         (1 << 5)
+#define AO_GPS_DATE_VALID      (1 << 6)
+#define AO_GPS_COURSE_VALID    (1 << 7)
+
+struct ao_gps_orig {
+       uint8_t                 year;
+       uint8_t                 month;
+       uint8_t                 day;
+       uint8_t                 hour;
+       uint8_t                 minute;
+       uint8_t                 second;
+       uint8_t                 flags;
+       int32_t                 latitude;       /* degrees * 10⁷ */
+       int32_t                 longitude;      /* degrees * 10⁷ */
+       int16_t                 altitude;       /* m */
+       uint16_t                ground_speed;   /* cm/s */
+       uint8_t                 course;         /* degrees / 2 */
+       uint8_t                 hdop;           /* * 5 */
+       int16_t                 climb_rate;     /* cm/s */
+       uint16_t                h_error;        /* m */
+       uint16_t                v_error;        /* m */
+};
+
+#define SIRF_SAT_STATE_ACQUIRED                        (1 << 0)
+#define SIRF_SAT_STATE_CARRIER_PHASE_VALID     (1 << 1)
+#define SIRF_SAT_BIT_SYNC_COMPLETE             (1 << 2)
+#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE                (1 << 3)
+#define SIRF_SAT_CARRIER_PULLIN_COMPLETE       (1 << 4)
+#define SIRF_SAT_CODE_LOCKED                   (1 << 5)
+#define SIRF_SAT_ACQUISITION_FAILED            (1 << 6)
+#define SIRF_SAT_EPHEMERIS_AVAILABLE           (1 << 7)
+
+struct ao_gps_sat_orig {
+       uint8_t         svid;
+       uint8_t         c_n_1;
+};
+
+#define AO_MAX_GPS_TRACKING    12
+
+struct ao_gps_tracking_orig {
+       uint8_t                 channels;
+       struct ao_gps_sat_orig  sats[AO_MAX_GPS_TRACKING];
+};
+
+#define ao_telemetry_location ao_gps_orig
+#define ao_telemetry_satellite ao_gps_tracking_orig
+#define ao_telemetry_satellite_info ao_gps_sat_orig
+
+void
+ao_mutex_get(uint8_t *mutex)
+{
+}
+
+void
+ao_mutex_put(uint8_t *mutex)
+{
+}
+
+static int
+ao_gps_fd;
+
+static void
+ao_dbg_char(char c)
+{
+       char    line[128];
+       line[0] = '\0';
+       if (c < ' ') {
+               if (c == '\n')
+                       sprintf (line, "\n");
+               else
+                       sprintf (line, "\\%02x", ((int) c) & 0xff);
+       } else {
+               sprintf (line, "%c", c);
+       }
+       write(1, line, strlen(line));
+}
+
+#define QUEUE_LEN      4096
+
+static char    input_queue[QUEUE_LEN];
+int            input_head, input_tail;
+
+#include <sys/time.h>
+
+int
+get_millis(void)
+{
+       struct timeval  tv;
+       gettimeofday(&tv, NULL);
+       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+static void
+check_skytraq_message(char *from, uint8_t *msg, int len)
+{
+       uint16_t        encoded_len, encoded_cksum;
+       uint16_t        cksum;
+       uint8_t         id;
+       int             i;
+
+//     fwrite(msg, 1, len, stdout);
+       return;
+       if (msg[0] != 0xa0 || msg[1] != 0xa2) {
+               printf ("bad header\n");
+               return;
+       }
+       if (len < 7) {
+               printf("short\n");
+               return;
+       }
+       if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) {
+               printf ("bad trailer\n");
+               return;
+       }
+       encoded_len = (msg[2] << 8) | msg[3];
+       id = msg[4];
+/*     printf ("%9d: %3d\n", get_millis(), id); */
+       if (encoded_len != len - 8) {
+               if (id != 52)
+                       printf ("length mismatch (got %d, wanted %d)\n",
+                               len - 8, encoded_len);
+               return;
+       }
+       encoded_cksum = (msg[len - 4] << 8) | msg[len-3];
+       cksum = 0;
+       for (i = 4; i < len - 4; i++)
+               cksum = (cksum + msg[i]) & 0x7fff;
+       if (encoded_cksum != cksum) {
+               printf ("cksum mismatch (got %04x wanted %04x)\n",
+                       cksum, encoded_cksum);
+               return;
+       }
+       id = msg[4];
+       switch (id) {
+       case 41:{
+               int     off = 4;
+
+               uint8_t         id;
+               uint16_t        nav_valid;
+               uint16_t        nav_type;
+               uint16_t        week;
+               uint32_t        tow;
+               uint16_t        year;
+               uint8_t         month;
+               uint8_t         day;
+               uint8_t         hour;
+               uint8_t         minute;
+               uint16_t        second;
+               uint32_t        sat_list;
+               int32_t         lat;
+               int32_t         lon;
+               int32_t         alt_ell;
+               int32_t         alt_msl;
+               int8_t          datum;
+               uint16_t        sog;
+               uint16_t        cog;
+               int16_t         mag_var;
+               int16_t         climb_rate;
+               int16_t         heading_rate;
+               uint32_t        h_error;
+               uint32_t        v_error;
+               uint32_t        t_error;
+               uint16_t        h_v_error;
+
+#define get_u8(u)      u = (msg[off]); off+= 1
+#define get_u16(u)     u = (msg[off] << 8) | (msg[off + 1]); off+= 2
+#define get_u32(u)     u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4
+
+               get_u8(id);
+               get_u16(nav_valid);
+               get_u16(nav_type);
+               get_u16(week);
+               get_u32(tow);
+               get_u16(year);
+               get_u8(month);
+               get_u8(day);
+               get_u8(hour);
+               get_u8(minute);
+               get_u16(second);
+               get_u32(sat_list);
+               get_u32(lat);
+               get_u32(lon);
+               get_u32(alt_ell);
+               get_u32(alt_msl);
+               get_u8(datum);
+               get_u16(sog);
+               get_u16(cog);
+               get_u16(mag_var);
+               get_u16(climb_rate);
+               get_u16(heading_rate);
+               get_u32(h_error);
+               get_u32(v_error);
+               get_u32(t_error);
+               get_u16(h_v_error);
+
+
+               printf ("Geodetic Navigation Data (41):\n");
+               printf ("\tNav valid %04x\n", nav_valid);
+               printf ("\tNav type %04x\n", nav_type);
+               printf ("\tWeek %5d", week);
+               printf (" TOW %9d", tow);
+               printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n",
+                       year, month, day,
+                       hour, minute, second / 1000.0);
+               printf ("\tsats: %08x\n", sat_list);
+               printf ("\tlat: %g", lat / 1.0e7);
+               printf (" lon: %g", lon / 1.0e7);
+               printf (" alt_ell: %g", alt_ell / 100.0);
+               printf (" alt_msll: %g", alt_msl / 100.0);
+               printf (" datum: %d\n", datum);
+               printf ("\tground speed: %g", sog / 100.0);
+               printf (" course: %g", cog / 100.0);
+               printf (" climb: %g", climb_rate / 100.0);
+               printf (" heading rate: %g\n", heading_rate / 100.0);
+               printf ("\th error: %g", h_error / 100.0);
+               printf (" v error: %g", v_error / 100.0);
+               printf (" t error: %g", t_error / 100.0);
+               printf (" h vel error: %g\n", h_v_error / 100.0);
+               break;
+       }
+       case 4: {
+               int off = 4;
+               uint8_t         id;
+               int16_t         gps_week;
+               uint32_t        gps_tow;
+               uint8_t         channels;
+               int             j, k;
+
+               get_u8(id);
+               get_u16(gps_week);
+               get_u32(gps_tow);
+               get_u8(channels);
+
+               printf ("Measured Tracker Data (4):\n");
+               printf ("GPS week: %d\n", gps_week);
+               printf ("GPS time of week: %d\n", gps_tow);
+               printf ("channels: %d\n", channels);
+               for (j = 0; j < 12; j++) {
+                       uint8_t svid, azimuth, elevation;
+                       uint16_t state;
+                       uint8_t c_n[10];
+                       get_u8(svid);
+                       get_u8(azimuth);
+                       get_u8(elevation);
+                       get_u16(state);
+                       for (k = 0; k < 10; k++) {
+                               get_u8(c_n[k]);
+                       }
+                       printf ("Sat %3d:", svid);
+                       printf (" aziumuth: %6.1f", azimuth * 1.5);
+                       printf (" elevation: %6.1f", elevation * 0.5);
+                       printf (" state: 0x%02x", state);
+                       printf (" c_n:");
+                       for (k = 0; k < 10; k++)
+                               printf(" %3d", c_n[k]);
+                       if (state & SIRF_SAT_STATE_ACQUIRED)
+                               printf(" acq,");
+                       if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID)
+                               printf(" car,");
+                       if (state & SIRF_SAT_BIT_SYNC_COMPLETE)
+                               printf(" bit,");
+                       if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE)
+                               printf(" sub,");
+                       if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE)
+                               printf(" pullin,");
+                       if (state & SIRF_SAT_CODE_LOCKED)
+                               printf(" code,");
+                       if (state & SIRF_SAT_ACQUISITION_FAILED)
+                               printf(" fail,");
+                       if (state & SIRF_SAT_EPHEMERIS_AVAILABLE)
+                               printf(" ephem,");
+                       printf ("\n");
+               }
+               break;
+       }
+       default:
+               return;
+               printf ("%s %4d:", from, encoded_len);
+               for (i = 4; i < len - 4; i++) {
+                       if (((i - 4) & 0xf) == 0)
+                               printf("\n   ");
+                       printf (" %3d", msg[i]);
+               }
+               printf ("\n");
+       }
+}
+
+static uint8_t skytraq_message[4096];
+static int     skytraq_message_len;
+static uint8_t skytraq_in_message[4096];
+static int     skytraq_in_len;
+
+char
+ao_serial_getchar(void)
+{
+       char    c;
+       uint8_t uc;
+
+       while (input_head == input_tail) {
+               for (;;) {
+                       input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN);
+                       if (input_tail < 0) {
+                               if (errno == EINTR || errno == EAGAIN)
+                                       continue;
+                               perror ("getchar");
+                               exit (1);
+                       }
+                       input_head = 0;
+                       break;
+               }
+       }
+       c = input_queue[input_head];
+       input_head = (input_head + 1) % QUEUE_LEN;
+       uc = c;
+//     printf ("c: %02x %c\n", uc, uc);
+       if (skytraq_in_len || uc == '$') {
+               if (skytraq_in_len < 4096)
+                       skytraq_in_message[skytraq_in_len++] = uc;
+               if (uc == 0x0a) {
+                       check_skytraq_message("recv", skytraq_in_message, skytraq_in_len);
+                       skytraq_in_len = 0;
+               }
+       }
+       return c;
+}
+
+
+void
+ao_serial_putchar(char c)
+{
+       int     i;
+       uint8_t uc = (uint8_t) c;
+
+       if (skytraq_message_len || uc == 0xa0) {
+               if (skytraq_message_len < 4096)
+                       skytraq_message[skytraq_message_len++] = uc;
+               if (uc == 0x0a) {
+                       check_skytraq_message("send", skytraq_message, skytraq_message_len);
+                       skytraq_message_len = 0;
+               }
+       }
+       for (;;) {
+               i = write(ao_gps_fd, &c, 1);
+               if (i == 1) {
+                       if ((uint8_t) c == 0xb3 || c == '\r') {
+                               static const struct timespec delay = {
+                                       .tv_sec = 0,
+                                       .tv_nsec = 100 * 1000 * 1000
+                               };
+                               tcdrain(ao_gps_fd);
+//                             nanosleep(&delay, NULL);
+                       }
+                       break;
+               }
+               if (i < 0 && (errno == EINTR || errno == EAGAIN))
+                       continue;
+               perror("putchar");
+               exit(1);
+       }
+}
+
+#define AO_SERIAL_SPEED_4800   0
+#define AO_SERIAL_SPEED_9600   1
+#define AO_SERIAL_SPEED_57600  2
+
+static void
+ao_serial_set_speed(uint8_t speed)
+{
+       int     fd = ao_gps_fd;
+       struct termios  termios;
+
+       tcdrain(fd);
+       tcgetattr(fd, &termios);
+       switch (speed) {
+       case AO_SERIAL_SPEED_4800:
+               cfsetspeed(&termios, B4800);
+               break;
+       case AO_SERIAL_SPEED_9600:
+               cfsetspeed(&termios, B38400);
+               break;
+       case AO_SERIAL_SPEED_57600:
+               cfsetspeed(&termios, B57600);
+               break;
+       }
+       tcsetattr(fd, TCSAFLUSH, &termios);
+       tcflush(fd, TCIFLUSH);
+}
+
+#define ao_time() 0
+
+#include "ao_gps_print.c"
+#include "ao_gps_skytraq.c"
+
+void
+ao_dump_state(void *wchan)
+{
+       double  lat, lon;
+       int     i;
+       if (wchan == &ao_gps_data)
+               ao_gps_print(&ao_gps_data);
+       else
+               ao_gps_tracking_print(&ao_gps_tracking_data);
+       putchar('\n');
+       return;
+}
+
+int
+ao_gps_open(const char *tty)
+{
+       struct termios  termios;
+       int fd;
+
+       fd = open (tty, O_RDWR);
+       if (fd < 0)
+               return -1;
+
+       tcgetattr(fd, &termios);
+       cfmakeraw(&termios);
+       cfsetspeed(&termios, B4800);
+       tcsetattr(fd, TCSAFLUSH, &termios);
+
+       tcdrain(fd);
+       tcflush(fd, TCIFLUSH);
+       return fd;
+}
+
+#include <getopt.h>
+
+static const struct option options[] = {
+       { .name = "tty", .has_arg = 1, .val = 'T' },
+       { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+       fprintf(stderr, "usage: %s [--tty <tty-name>]\n", program);
+       exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+       char    *tty = "/dev/ttyUSB0";
+       int     c;
+
+       while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) {
+               switch (c) {
+               case 'T':
+                       tty = optarg;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+       ao_gps_fd = ao_gps_open(tty);
+       if (ao_gps_fd < 0) {
+               perror (tty);
+               exit (1);
+       }
+       ao_gps();
+}
index d8867b1968618baf423b097a78d0f914402e847a..fc8df1f4cebd88e771cb99d0d726a85145635139 100644 (file)
@@ -1 +1,92 @@
-include ../Makefile.proto
+#
+# TIDongle build file
+#
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_gps_print.c \
+       ao_monitor.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_rssi.c \
+       ao_state.c \
+       ao_stdio.c \
+       ao_task.c
+
+CC1111_SRC = \
+       ao_dbg.c \
+       ao_dma.c \
+       ao_led.c \
+       ao_packet.c \
+       ao_packet_master.c \
+       ao_radio.c \
+       ao_romconfig.c \
+       ao_timer.c \
+       ao_usb.c \
+       _bp.c
+
+DRIVER_SRC =
+
+PRODUCT_SRC = \
+       ao_tidongle.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(DRIVER_SRC) \
+       $(PRODUCT_SRC)
+
+PROG = tidongle-$(VERSION).ihx
+PRODUCT=TIDongle
+PRODUCT_DEF=-DTIDONGLE
+IDPRODUCT=0x000a
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM)
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+       rm -f ao_product.h
+       rm -f ../$(PROG) ../$(PMAP)
+
+install:
+
+uninstall:
+
diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs
deleted file mode 100644 (file)
index 0e13cb2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-PROG = tidongle-$(VERSION).ihx
-
-SRC = \
-       $(TI_SRC)
-
-PRODUCT=TIDongle
-
-PRODUCT_DEF=-DTIDONGLE
-IDPRODUCT=0x000a
diff --git a/src/util/ao-make-product.5c b/src/util/ao-make-product.5c
new file mode 100644 (file)
index 0000000..5f2eb8e
--- /dev/null
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+autoimport ParseArgs;
+
+void
+write_ucs2(string a, string description)
+{
+       int len = String::length(a);
+
+       printf("/* %s */\n", description);
+       printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2);
+       printf("#define AO_%s_STRING \"%s\"\n", description, a);
+       printf("#define AO_%s_UCS2", description);
+       for (int i = 0; i < len; i++) {
+               int     c = a[i];
+               if (i > 0)
+                       printf(",");
+               if (0x20 <= c && c < 128)
+                       printf(" '%c', 0", c);
+               else
+                       printf(" LE_WORD(0x%04x),", c);
+       }
+       printf("\n\n");
+}
+
+void
+write_string(string a, string description)
+{
+       printf ("/* %s */\n", description);
+       printf ("#define AO_%s_STRING \"%s\"\n", description, a);
+}
+
+void
+write_int(int a, string description)
+{
+       printf ("/* %s */\n", description);
+       printf ("#define AO_%s_NUMBER %d\n\n", description, a);
+}
+
+void
+write_hex(int a, string description)
+{
+       printf ("/* %s */\n", description);
+       printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a);
+}
+
+string manufacturer = "altusmetrum.org";
+string product = "TeleMetrum";
+string version = "0.0";
+int serial = 1;
+int user_argind = 0;
+int id_product = 0x000a;
+
+argdesc argd = {
+       .args = {
+               {
+                       .var = { .arg_string = &manufacturer },
+                       .abbr = 'm',
+                       .name = "manufacturer",
+                       .expr_name = "manf",
+                       .desc = "Manufacturer name." },
+               {
+                       .var = { .arg_string = &product },
+                       .abbr = 'p',
+                       .name = "product",
+                       .expr_name = "prod",
+                       .desc = "Product name." },
+               {
+                       .var = { .arg_int = &id_product },
+                       .abbr = 'i',
+                       .name = "id_product",
+                       .expr_name = "id_p",
+                       .desc = "Product ID." },
+               {
+                       .var = { .arg_int = &serial },
+                       .abbr = 's',
+                       .name = "serial",
+                       .expr_name = "number",
+                       .desc = "Serial number." },
+               {
+                       .var = { .arg_string = &version },
+                       .abbr = 'v',
+                       .name = "version",
+                       .expr_name = "string",
+                       .desc = "Program version." },
+       },
+       .prog_name = "usb descriptors",
+};
+
+void
+main()
+{
+       string[dim(argv)-1] nargv = {[n] = argv[n+1]};
+       parseargs(&argd, &nargv);
+       write_ucs2(manufacturer, "iManufacturer");
+       write_ucs2(product, "iProduct");
+       write_ucs2(sprintf("%06d", serial), "iSerial");
+       write_int(serial, "iSerial");
+       write_hex(id_product, "idProduct");
+       write_string(version, "iVersion");
+}
+
+main();
diff --git a/src/util/check-stack b/src/util/check-stack
new file mode 100755 (executable)
index 0000000..1e8044e
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+HEADER=$1
+MEM=$2
+
+HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER`
+MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM`
+
+if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then
+        echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }'
+       exit 1
+else
+       exit 0
+fi
diff --git a/src/util/gps-cksum b/src/util/gps-cksum
new file mode 100755 (executable)
index 0000000..a08153b
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/env nickle
+
+int checksum(string a)
+{
+       int     c = 0;
+       for (int i = 0; i < String::length(a); i++)
+               c ^= a[i];
+       return c;
+}
+
+void main()
+{
+       for (int i = 1; i < dim(argv); i++)
+               printf ("$%s*%02x\n", argv[i], checksum(argv[i]));
+}
+
+main();
diff --git a/src/util/make-altitude b/src/util/make-altitude
new file mode 100644 (file)
index 0000000..716aa8a
--- /dev/null
@@ -0,0 +1,283 @@
+#!/usr/bin/nickle -f
+/*
+ * Pressure Sensor Model, version 1.1
+ *
+ * written by Holly Grimes
+ *
+ * Uses the International Standard Atmosphere as described in
+ *   "A Quick Derivation relating altitude to air pressure" (version 1.03)
+ *    from the Portland State Aerospace Society, except that the atmosphere
+ *    is divided into layers with each layer having a different lapse rate.
+ *
+ * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007
+ *    at site <http://en.wikipedia.org/wiki/International_Standard_Atmosphere
+ *
+ * Height measurements use the local tangent plane.  The postive z-direction is up.
+ *
+ * All measurements are given in SI units (Kelvin, Pascal, meter, meters/second^2).
+ *   The lapse rate is given in Kelvin/meter, the gas constant for air is given
+ *   in Joules/(kilogram-Kelvin).
+ */
+
+const real GRAVITATIONAL_ACCELERATION = -9.80665;
+const real AIR_GAS_CONSTANT = 287.053;
+const int NUMBER_OF_LAYERS = 7;
+const real MAXIMUM_ALTITUDE = 84852;
+const real MINIMUM_PRESSURE = 0.3734;
+const real LAYER0_BASE_TEMPERATURE = 288.15;
+const real LAYER0_BASE_PRESSURE = 101325;
+
+/* lapse rate and base altitude for each layer in the atmosphere */
+const real[NUMBER_OF_LAYERS] lapse_rate = {
+       -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
+};
+const int[NUMBER_OF_LAYERS] base_altitude = {
+       0, 11000, 20000, 32000, 47000, 51000, 71000
+};
+
+
+/* outputs atmospheric pressure associated with the given altitude. altitudes
+   are measured with respect to the mean sea level */
+real altitude_to_pressure(real altitude) {
+
+   real base_temperature = LAYER0_BASE_TEMPERATURE;
+   real base_pressure = LAYER0_BASE_PRESSURE;
+
+   real pressure;
+   real base; /* base for function to determine pressure */
+   real exponent; /* exponent for function to determine pressure */
+   int layer_number; /* identifies layer in the atmosphere */
+   int delta_z; /* difference between two altitudes */
+
+   if (altitude > MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */
+      return 0;
+
+   /* calculate the base temperature and pressure for the atmospheric layer
+      associated with the inputted altitude */
+   for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
+      delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+      if (lapse_rate[layer_number] == 0.0) {
+         exponent = GRAVITATIONAL_ACCELERATION * delta_z
+              / AIR_GAS_CONSTANT / base_temperature;
+         base_pressure *= exp(exponent);
+      }
+      else {
+         base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+         exponent = GRAVITATIONAL_ACCELERATION /
+              (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+         base_pressure *= pow(base, exponent);
+      }
+      base_temperature += delta_z * lapse_rate[layer_number];
+   }
+
+   /* calculate the pressure at the inputted altitude */
+   delta_z = altitude - base_altitude[layer_number];
+   if (lapse_rate[layer_number] == 0.0) {
+      exponent = GRAVITATIONAL_ACCELERATION * delta_z
+           / AIR_GAS_CONSTANT / base_temperature;
+      pressure = base_pressure * exp(exponent);
+   }
+   else {
+      base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+      exponent = GRAVITATIONAL_ACCELERATION /
+           (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+      pressure = base_pressure * pow(base, exponent);
+   }
+
+   return pressure;
+}
+
+
+/* outputs the altitude associated with the given pressure. the altitude
+   returned is measured with respect to the mean sea level */
+real pressure_to_altitude(real pressure) {
+
+   real next_base_temperature = LAYER0_BASE_TEMPERATURE;
+   real next_base_pressure = LAYER0_BASE_PRESSURE;
+
+   real altitude;
+   real base_pressure;
+   real base_temperature;
+   real base; /* base for function to determine base pressure of next layer */
+   real exponent; /* exponent for function to determine base pressure
+                             of next layer */
+   real coefficient;
+   int layer_number; /* identifies layer in the atmosphere */
+   int delta_z; /* difference between two altitudes */
+
+   if (pressure < 0)  /* illegal pressure */
+      return -1;
+   if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
+      return MAXIMUM_ALTITUDE;
+
+   /* calculate the base temperature and pressure for the atmospheric layer
+      associated with the inputted pressure. */
+   layer_number = -1;
+   do {
+      layer_number++;
+      base_pressure = next_base_pressure;
+      base_temperature = next_base_temperature;
+      delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+      if (lapse_rate[layer_number] == 0.0) {
+         exponent = GRAVITATIONAL_ACCELERATION * delta_z
+              / AIR_GAS_CONSTANT / base_temperature;
+         next_base_pressure *= exp(exponent);
+      }
+      else {
+         base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+         exponent = GRAVITATIONAL_ACCELERATION /
+              (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+         next_base_pressure *= pow(base, exponent);
+      }
+      next_base_temperature += delta_z * lapse_rate[layer_number];
+   }
+   while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
+
+   /* calculate the altitude associated with the inputted pressure */
+   if (lapse_rate[layer_number] == 0.0) {
+      coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION)
+                                                    * base_temperature;
+      altitude = base_altitude[layer_number]
+                    + coefficient * log(pressure / base_pressure);
+   }
+   else {
+      base = pressure / base_pressure;
+      exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number]
+                                       / GRAVITATIONAL_ACCELERATION;
+      coefficient = base_temperature / lapse_rate[layer_number];
+      altitude = base_altitude[layer_number]
+                      + coefficient * (pow(base, exponent) - 1);
+   }
+
+   return altitude;
+}
+
+real feet_to_meters(real feet)
+{
+    return feet * (12 * 2.54 / 100);
+}
+
+real meters_to_feet(real meters)
+{
+    return meters / (12 * 2.54 / 100);
+}
+
+/*
+ * Values for our MP3H6115A pressure sensor
+ *
+ * From the data sheet:
+ *
+ * Pressure range: 15-115 kPa
+ * Voltage at 115kPa: 2.82
+ * Output scale: 27mV/kPa
+ *
+ *
+ * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa
+ * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa
+ */
+
+real counts_per_kPa = 27 * 2047 / 3300;
+real counts_at_101_3kPa = 1674;
+
+real fraction_to_kPa(real fraction)
+{
+       return (fraction + 0.095) / 0.009;
+}
+
+
+real count_to_kPa(real count) = fraction_to_kPa(count / 2047);
+
+typedef struct {
+       real m, b;
+       int m_i, b_i;
+} line_t;
+
+line_t best_fit(real[] values, int first, int last) {
+       real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0;
+       int n = last - first + 1;
+       real m, b;
+       int m_i, b_i;
+
+       for (int i = first; i <= last; i++) {
+              sum_x += i;
+              sum_x2 += i**2;
+              sum_y += values[i];
+              sum_xy += values[i] * i;
+       }
+       m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2);
+       b = sum_y/n - m*(sum_x/n);
+       return (line_t) { m = m, b = b };
+}
+
+real count_to_altitude(real count) {
+     return pressure_to_altitude(count_to_kPa(count) * 1000);
+}
+
+real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000);
+
+int num_samples = 1024;
+
+real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) };
+
+int num_part = 128;
+int seg_len = num_samples / num_part;
+
+line_t [dim(alt) / seg_len] fit = {
+       [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1)
+};
+
+int[num_samples/seg_len + 1]   alt_part;
+
+alt_part[0] = floor (fit[0].b + 0.5);
+alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5);
+
+for (int i = 0; i < dim(fit) - 1; i++) {
+       real    here, there;
+       here = fit[i].m * (i+1) * seg_len + fit[i].b;
+       there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b;
+       alt_part[i+1] = floor ((here + there) / 2 + 0.5);
+}
+
+real count_to_fit_altitude(int count) {
+       int     sub = count // seg_len;
+       int     off = count % seg_len;
+       line_t  l = fit[sub];
+       real r_v;
+       real i_v;
+
+       r_v = count * l.m + l.b;
+       i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len;
+       return i_v;
+}
+
+real max_error = 0;
+int max_error_count = 0;
+real total_error = 0;
+
+for (int count = 0; count < num_samples; count++) {
+       real    kPa = fraction_to_kPa(count / (num_samples - 1));
+       real    meters = pressure_to_altitude(kPa * 1000);
+
+       real    meters_approx = count_to_fit_altitude(count);
+       real    error = abs(meters - meters_approx);
+
+       total_error += error;
+       if (error > max_error) {
+               max_error = error;
+               max_error_count = count;
+       }
+#      printf ("       %7d,    /* %6.2g kPa %5d count approx %d */\n",
+#              floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5));
+}
+
+printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples);
+
+printf ("#define NALT %d\n", dim(alt_part));
+printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1));
+
+for (int i = 0; i < dim(alt_part); i++) {
+       real fraction = i / (dim(alt_part) - 1);
+       real kPa = fraction_to_kPa(fraction);
+       printf ("%9d, /* %6.2f kPa %7.3f%% */\n",
+               alt_part[i], kPa, fraction * 100);
+}
diff --git a/src/util/make-kalman b/src/util/make-kalman
new file mode 100644 (file)
index 0000000..f78f30a
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+cd $1 >&/dev/null
+
+SIGMA_BOTH="-M 2 -H 6 -A 2"
+SIGMA_BARO="-M 2 -H 6 -A 2"
+SIGMA_ACCEL="-M 2 -H 4 -A 4"
+
+nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH
+nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH
+nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH
+
+nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL
+nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL
+nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL
+
+nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO
+nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO
+nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO
diff --git a/src/util/sirf-cksum b/src/util/sirf-cksum
new file mode 100755 (executable)
index 0000000..b905f31
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/env nickle
+
+int checksum(int[] msg)
+{
+       int sum = 0;
+       for (int i = 0; i < dim(msg); i++) {
+               sum += msg[i];
+               sum &= 0x7fff;
+       }
+       return sum;
+}
+
+void main()
+{
+       string[...]     input;
+       int[...]        msg;
+
+       setdim(input, 0);
+       while (!File::end(stdin)) {
+               input[dim(input)] = gets();
+       }
+
+       setdim(msg, 0);
+       for (int i = 0; i < dim(input); i++) {
+               string[*] words = String::wordsplit(input[i], " ,\t");
+               for (int j = 0; j < dim(words); j++) {
+                       if (words[j] == "/" + "*")
+                               break;
+                       if (String::length(words[j]) > 0 &&
+                           Ctype::isdigit(words[j][0])) {
+                               msg[dim(msg)] = string_to_integer(words[j]);
+                       }
+                }
+       }
+       printf("\t0xa0, 0xa2, 0x%02x, 0x%02x,\t/* length: %d bytes */\n",
+              dim(msg) >> 8, dim(msg) & 0xff, dim(msg));
+       for (int i = 0; i < dim(input); i++)
+               printf("%s\n", input[i]);
+       int csum = checksum(msg);
+       printf ("\t0x%02x, 0x%02x, 0xb0, 0xb3,\n",
+               csum >> 8, csum & 0xff);
+}
+
+main();
diff --git a/src/util/skytraq-cksum b/src/util/skytraq-cksum
new file mode 100644 (file)
index 0000000..ab0464a
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/env nickle
+
+int checksum(int[] msg)
+{
+       int sum = 0;
+       for (int i = 0; i < dim(msg); i++) {
+               sum ^= msg[i];
+               sum &= 0xff;
+       }
+       return sum;
+}
+
+void main()
+{
+       string[...]     input;
+       int[...]        msg;
+
+       setdim(input, 0);
+       while (!File::end(stdin)) {
+               input[dim(input)] = gets();
+       }
+
+       setdim(msg, 0);
+       for (int i = 0; i < dim(input); i++) {
+               string[*] words = String::wordsplit(input[i], " ,\t");
+               for (int j = 0; j < dim(words); j++) {
+                       if (words[j] == "/" + "*")
+                               break;
+                       if (String::length(words[j]) > 0 &&
+                           Ctype::isdigit(words[j][0])) {
+                               msg[dim(msg)] = string_to_integer(words[j]);
+                       }
+                }
+       }
+       printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n",
+              dim(msg) >> 8, dim(msg) & 0xff, dim(msg));
+       for (int i = 0; i < dim(input); i++)
+               printf("%s\n", input[i]);
+       int csum = checksum(msg);
+       printf ("\t0x%02x, 0x0d, 0x0a,\n",
+               csum);
+}
+
+main();