ao-teleterra.h
ao-teledongle.h
ao-tidongle.h
+Makefile.in
+aclocal.m4
+.deps
+autom4te.cache
+config.*
+depcomp
+install-sh
+missing
+stamp-h1
+configure
+Makefile
+aoview/Makefile
+++ /dev/null
-/*
- * 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_ */
--- /dev/null
+Keith Packard <keithp@keithp.com>
--- /dev/null
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008 Free Software Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 6. Often, you can also type `make uninstall' to remove the installed
+ files again.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *Note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+++ /dev/null
-#
-# AltOS build
-#
-#
-CC=sdcc
-
-VERSION=$(shell git describe)
-
-CFLAGS=--model-small --debug --opt-code-speed
-
-LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \
- --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff
-
-INC = \
- ao.h \
- cc1111.h \
- altitude.h \
- 25lc1024.h
-
-#
-# Common AltOS sources
-#
-ALTOS_SRC = \
- ao_cmd.c \
- ao_dbg.c \
- ao_dma.c \
- ao_mutex.c \
- ao_panic.c \
- ao_task.c \
- ao_timer.c \
- _bp.c
-
-#
-# Shared AltOS drivers
-#
-ALTOS_DRIVER_SRC = \
- ao_beep.c \
- ao_config.c \
- ao_led.c \
- ao_radio.c \
- ao_stdio.c \
- ao_usb.c
-
-TELE_COMMON_SRC = \
- ao_gps_print.c \
- ao_state.c
-
-#
-# Receiver code
-#
-TELE_RECEIVER_SRC =\
- ao_monitor.c \
- ao_rssi.c
-
-#
-# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle)
-#
-
-TELE_DRIVER_SRC = \
- ao_convert.c \
- ao_gps.c \
- ao_serial.c
-
-#
-# Drivers for partially-flled boards (TT, TD and TI)
-#
-TELE_FAKE_SRC = \
- ao_adc_fake.c \
- ao_ee_fake.c
-
-#
-# Drivers only on TeleMetrum
-#
-TM_DRIVER_SRC = \
- ao_adc.c \
- ao_ee.c \
- ao_gps_report.c \
- ao_ignite.c
-
-#
-# Tasks run on TeleMetrum
-#
-TM_TASK_SRC = \
- ao_flight.c \
- ao_log.c \
- ao_report.c \
- ao_telemetry.c
-
-TM_MAIN_SRC = \
- ao_telemetrum.c
-
-#
-# All sources for TeleMetrum
-#
-TM_SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_DRIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(TM_DRIVER_SRC) \
- $(TM_TASK_SRC) \
- $(TM_MAIN_SRC)
-
-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) \
- $(TELE_FAKE_SRC) \
- $(TI_MAIN_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) \
- $(TELE_FAKE_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) \
- $(TELE_FAKE_SRC) \
- $(TD_MAIN_SRC)
-
-SRC = \
- $(ALTOS_SRC) \
- $(ALTOS_DRIVER_SRC) \
- $(TELE_DRIVER_SRC) \
- $(TELE_RECEIVER_SRC) \
- $(TELE_COMMON_SRC) \
- $(TELE_FAKE_SRC) \
- $(TM_DRIVER_SRC) \
- $(TM_TASK_SRC) \
- $(TM_MAIN_SRC) \
- $(TI_MAIN_SRC) \
- $(TD_MAIN_SRC) \
- $(TT_MAIN_SRC)
-
-TM_REL=$(TM_SRC:.c=.rel) ao_product-telemetrum.rel
-TI_REL=$(TI_SRC:.c=.rel) ao_product-tidongle.rel
-TT_REL=$(TT_SRC:.c=.rel) ao_product-teleterra.rel
-TD_REL=$(TD_SRC:.c=.rel) ao_product-teledongle.rel
-
-PROD_REL=\
- ao_product-telemetrum.rel \
- ao_product-tidongle.rel \
- ao_product-teleterra.rel \
- ao_product-teledongle.rel
-
-REL=$(SRC:.c=.rel) $(PROD_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)
-
-PROGS= telemetrum.ihx tidongle.ihx \
- teleterra.ihx teledongle.ihx
-
-HOST_PROGS=ao_flight_test
-
-PCDB=$(PROGS:.ihx=.cdb)
-PLNK=$(PROGS:.ihx=.lnk)
-PMAP=$(PROGS:.ihx=.map)
-PMEM=$(PROGS:.ihx=.mem)
-PAOM=$(PROGS:.ihx=)
-
-%.rel : %.c $(INC)
- $(CC) -c $(CFLAGS) -o$*.rel $*.c
-
-all: $(PROGS) $(HOST_PROGS)
-
-telemetrum.ihx: $(TM_REL) Makefile
- $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_REL)
- sh check-stack ao.h telemetrum.mem
-
-tidongle.ihx: $(TI_REL) Makefile
- $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL)
- sh check-stack ao.h tidongle.mem
-
-tidongle.ihx: telemetrum.ihx
-
-teleterra.ihx: $(TT_REL) Makefile
- $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TT_REL)
- sh check-stack ao.h teleterra.mem
-
-teleterra.ihx: tidongle.ihx
-
-teledongle.ihx: $(TD_REL) Makefile
- $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TD_REL)
- sh check-stack ao.h teledongle.mem
-
-teledongle.ihx: teleterra.ihx
-
-altitude.h: make-altitude
- nickle make-altitude > altitude.h
-
-TELEMETRUM_DEFS=ao-telemetrum.h
-TELETERRA_DEFS=ao-teleterra.h
-TELEDONGLE_DEFS=ao-teledongle.h
-TIDONGLE_DEFS=ao-tidongle.h
-
-ALL_DEFS=$(TELEMETRUM_DEFS) $(TELETERRA_DEFS) \
- $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS)
-ao_product-telemetrum.rel: ao_product.c $(TELEMETRUM_DEFS)
- $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEMETRUM_DEFS)\"' -o$@ ao_product.c
-
-ao_product-teleterra.rel: ao_product.c $(TELETERRA_DEFS)
- $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELETERRA_DEFS)\"' -o$@ ao_product.c
-
-ao_product-teledongle.rel: ao_product.c $(TELEDONGLE_DEFS)
- $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEDONGLE_DEFS)\"' -o$@ ao_product.c
-
-ao_product-tidongle.rel: ao_product.c $(TIDONGLE_DEFS)
- $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TIDONGLE_DEFS)\"' -o$@ ao_product.c
-
-$(TELEMETRUM_DEFS): ao-make-product.5c
- nickle ao-make-product.5c -m altusmetrum.org -p TeleMetrum -v $(VERSION) > $@
-
-$(TELETERRA_DEFS): ao-make-product.5c
- nickle ao-make-product.5c -m altusmetrum.org -p TeleTerra -v $(VERSION) > $@
-
-$(TELEDONGLE_DEFS): ao-make-product.5c
- nickle ao-make-product.5c -m altusmetrum.org -p TeleDongle -v $(VERSION) > $@
-
-$(TIDONGLE_DEFS): ao-make-product.5c
- nickle ao-make-product.5c -m altusmetrum.org -p TIDongle -v $(VERSION) > $@
-
-clean:
- rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
- rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
- rm -f $(ALL_DEFS) $(HOST_PROGS)
- rm -f $(TELEMETRUM_DEFS) $(TELETERRA_DEFS) $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS)
-
-install:
-
-ao_flight_test: ao_flight.c ao_flight_test.c
- cc -g -o $@ ao_flight_test.c
--- /dev/null
+SUBDIRS=src aoview
+++ /dev/null
-/*-------------------------------------------------------------------------
-
- _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 ;
+++ /dev/null
- 15837, /* 10.56 kPa 0 count */
- 15804, /* 10.61 kPa 1 count */
- 15772, /* 10.66 kPa 2 count */
- 15740, /* 10.72 kPa 3 count */
- 15708, /* 10.77 kPa 4 count */
- 15676, /* 10.83 kPa 5 count */
- 15644, /* 10.88 kPa 6 count */
- 15613, /* 10.94 kPa 7 count */
- 15581, /* 10.99 kPa 8 count */
- 15550, /* 11.04 kPa 9 count */
- 15519, /* 11.10 kPa 10 count */
- 15488, /* 11.15 kPa 11 count */
- 15457, /* 11.21 kPa 12 count */
- 15426, /* 11.26 kPa 13 count */
- 15396, /* 11.32 kPa 14 count */
- 15366, /* 11.37 kPa 15 count */
- 15335, /* 11.42 kPa 16 count */
- 15305, /* 11.48 kPa 17 count */
- 15275, /* 11.53 kPa 18 count */
- 15246, /* 11.59 kPa 19 count */
- 15216, /* 11.64 kPa 20 count */
- 15187, /* 11.70 kPa 21 count */
- 15157, /* 11.75 kPa 22 count */
- 15128, /* 11.80 kPa 23 count */
- 15099, /* 11.86 kPa 24 count */
- 15070, /* 11.91 kPa 25 count */
- 15041, /* 11.97 kPa 26 count */
- 15012, /* 12.02 kPa 27 count */
- 14984, /* 12.08 kPa 28 count */
- 14955, /* 12.13 kPa 29 count */
- 14927, /* 12.18 kPa 30 count */
- 14899, /* 12.24 kPa 31 count */
- 14871, /* 12.29 kPa 32 count */
- 14843, /* 12.35 kPa 33 count */
- 14815, /* 12.40 kPa 34 count */
- 14787, /* 12.46 kPa 35 count */
- 14760, /* 12.51 kPa 36 count */
- 14732, /* 12.56 kPa 37 count */
- 14705, /* 12.62 kPa 38 count */
- 14678, /* 12.67 kPa 39 count */
- 14651, /* 12.73 kPa 40 count */
- 14624, /* 12.78 kPa 41 count */
- 14597, /* 12.84 kPa 42 count */
- 14570, /* 12.89 kPa 43 count */
- 14543, /* 12.94 kPa 44 count */
- 14517, /* 13.00 kPa 45 count */
- 14490, /* 13.05 kPa 46 count */
- 14464, /* 13.11 kPa 47 count */
- 14438, /* 13.16 kPa 48 count */
- 14412, /* 13.22 kPa 49 count */
- 14386, /* 13.27 kPa 50 count */
- 14360, /* 13.32 kPa 51 count */
- 14334, /* 13.38 kPa 52 count */
- 14308, /* 13.43 kPa 53 count */
- 14283, /* 13.49 kPa 54 count */
- 14257, /* 13.54 kPa 55 count */
- 14232, /* 13.60 kPa 56 count */
- 14207, /* 13.65 kPa 57 count */
- 14182, /* 13.70 kPa 58 count */
- 14156, /* 13.76 kPa 59 count */
- 14132, /* 13.81 kPa 60 count */
- 14107, /* 13.87 kPa 61 count */
- 14082, /* 13.92 kPa 62 count */
- 14057, /* 13.98 kPa 63 count */
- 14033, /* 14.03 kPa 64 count */
- 14008, /* 14.08 kPa 65 count */
- 13984, /* 14.14 kPa 66 count */
- 13959, /* 14.19 kPa 67 count */
- 13935, /* 14.25 kPa 68 count */
- 13911, /* 14.30 kPa 69 count */
- 13887, /* 14.36 kPa 70 count */
- 13863, /* 14.41 kPa 71 count */
- 13839, /* 14.46 kPa 72 count */
- 13816, /* 14.52 kPa 73 count */
- 13792, /* 14.57 kPa 74 count */
- 13768, /* 14.63 kPa 75 count */
- 13745, /* 14.68 kPa 76 count */
- 13721, /* 14.74 kPa 77 count */
- 13698, /* 14.79 kPa 78 count */
- 13675, /* 14.84 kPa 79 count */
- 13652, /* 14.90 kPa 80 count */
- 13629, /* 14.95 kPa 81 count */
- 13606, /* 15.01 kPa 82 count */
- 13583, /* 15.06 kPa 83 count */
- 13560, /* 15.12 kPa 84 count */
- 13537, /* 15.17 kPa 85 count */
- 13515, /* 15.22 kPa 86 count */
- 13492, /* 15.28 kPa 87 count */
- 13470, /* 15.33 kPa 88 count */
- 13447, /* 15.39 kPa 89 count */
- 13425, /* 15.44 kPa 90 count */
- 13403, /* 15.50 kPa 91 count */
- 13380, /* 15.55 kPa 92 count */
- 13358, /* 15.60 kPa 93 count */
- 13336, /* 15.66 kPa 94 count */
- 13314, /* 15.71 kPa 95 count */
- 13292, /* 15.77 kPa 96 count */
- 13271, /* 15.82 kPa 97 count */
- 13249, /* 15.87 kPa 98 count */
- 13227, /* 15.93 kPa 99 count */
- 13206, /* 15.98 kPa 100 count */
- 13184, /* 16.04 kPa 101 count */
- 13163, /* 16.09 kPa 102 count */
- 13141, /* 16.15 kPa 103 count */
- 13120, /* 16.20 kPa 104 count */
- 13099, /* 16.25 kPa 105 count */
- 13078, /* 16.31 kPa 106 count */
- 13057, /* 16.36 kPa 107 count */
- 13036, /* 16.42 kPa 108 count */
- 13015, /* 16.47 kPa 109 count */
- 12994, /* 16.53 kPa 110 count */
- 12973, /* 16.58 kPa 111 count */
- 12952, /* 16.63 kPa 112 count */
- 12932, /* 16.69 kPa 113 count */
- 12911, /* 16.74 kPa 114 count */
- 12891, /* 16.80 kPa 115 count */
- 12870, /* 16.85 kPa 116 count */
- 12850, /* 16.91 kPa 117 count */
- 12829, /* 16.96 kPa 118 count */
- 12809, /* 17.01 kPa 119 count */
- 12789, /* 17.07 kPa 120 count */
- 12769, /* 17.12 kPa 121 count */
- 12749, /* 17.18 kPa 122 count */
- 12729, /* 17.23 kPa 123 count */
- 12709, /* 17.29 kPa 124 count */
- 12689, /* 17.34 kPa 125 count */
- 12669, /* 17.39 kPa 126 count */
- 12649, /* 17.45 kPa 127 count */
- 12630, /* 17.50 kPa 128 count */
- 12610, /* 17.56 kPa 129 count */
- 12590, /* 17.61 kPa 130 count */
- 12571, /* 17.67 kPa 131 count */
- 12551, /* 17.72 kPa 132 count */
- 12532, /* 17.77 kPa 133 count */
- 12513, /* 17.83 kPa 134 count */
- 12493, /* 17.88 kPa 135 count */
- 12474, /* 17.94 kPa 136 count */
- 12455, /* 17.99 kPa 137 count */
- 12436, /* 18.05 kPa 138 count */
- 12417, /* 18.10 kPa 139 count */
- 12398, /* 18.15 kPa 140 count */
- 12379, /* 18.21 kPa 141 count */
- 12360, /* 18.26 kPa 142 count */
- 12341, /* 18.32 kPa 143 count */
- 12323, /* 18.37 kPa 144 count */
- 12304, /* 18.43 kPa 145 count */
- 12285, /* 18.48 kPa 146 count */
- 12267, /* 18.53 kPa 147 count */
- 12248, /* 18.59 kPa 148 count */
- 12230, /* 18.64 kPa 149 count */
- 12211, /* 18.70 kPa 150 count */
- 12193, /* 18.75 kPa 151 count */
- 12174, /* 18.81 kPa 152 count */
- 12156, /* 18.86 kPa 153 count */
- 12138, /* 18.91 kPa 154 count */
- 12120, /* 18.97 kPa 155 count */
- 12102, /* 19.02 kPa 156 count */
- 12084, /* 19.08 kPa 157 count */
- 12065, /* 19.13 kPa 158 count */
- 12048, /* 19.19 kPa 159 count */
- 12030, /* 19.24 kPa 160 count */
- 12012, /* 19.29 kPa 161 count */
- 11994, /* 19.35 kPa 162 count */
- 11976, /* 19.40 kPa 163 count */
- 11958, /* 19.46 kPa 164 count */
- 11941, /* 19.51 kPa 165 count */
- 11923, /* 19.57 kPa 166 count */
- 11906, /* 19.62 kPa 167 count */
- 11888, /* 19.67 kPa 168 count */
- 11871, /* 19.73 kPa 169 count */
- 11853, /* 19.78 kPa 170 count */
- 11836, /* 19.84 kPa 171 count */
- 11818, /* 19.89 kPa 172 count */
- 11801, /* 19.95 kPa 173 count */
- 11784, /* 20.00 kPa 174 count */
- 11767, /* 20.05 kPa 175 count */
- 11750, /* 20.11 kPa 176 count */
- 11733, /* 20.16 kPa 177 count */
- 11715, /* 20.22 kPa 178 count */
- 11698, /* 20.27 kPa 179 count */
- 11682, /* 20.33 kPa 180 count */
- 11665, /* 20.38 kPa 181 count */
- 11648, /* 20.43 kPa 182 count */
- 11631, /* 20.49 kPa 183 count */
- 11614, /* 20.54 kPa 184 count */
- 11597, /* 20.60 kPa 185 count */
- 11581, /* 20.65 kPa 186 count */
- 11564, /* 20.71 kPa 187 count */
- 11547, /* 20.76 kPa 188 count */
- 11531, /* 20.81 kPa 189 count */
- 11514, /* 20.87 kPa 190 count */
- 11498, /* 20.92 kPa 191 count */
- 11481, /* 20.98 kPa 192 count */
- 11465, /* 21.03 kPa 193 count */
- 11449, /* 21.09 kPa 194 count */
- 11432, /* 21.14 kPa 195 count */
- 11416, /* 21.19 kPa 196 count */
- 11400, /* 21.25 kPa 197 count */
- 11384, /* 21.30 kPa 198 count */
- 11368, /* 21.36 kPa 199 count */
- 11352, /* 21.41 kPa 200 count */
- 11336, /* 21.47 kPa 201 count */
- 11319, /* 21.52 kPa 202 count */
- 11304, /* 21.57 kPa 203 count */
- 11288, /* 21.63 kPa 204 count */
- 11272, /* 21.68 kPa 205 count */
- 11256, /* 21.74 kPa 206 count */
- 11240, /* 21.79 kPa 207 count */
- 11224, /* 21.85 kPa 208 count */
- 11208, /* 21.90 kPa 209 count */
- 11193, /* 21.95 kPa 210 count */
- 11177, /* 22.01 kPa 211 count */
- 11162, /* 22.06 kPa 212 count */
- 11146, /* 22.12 kPa 213 count */
- 11130, /* 22.17 kPa 214 count */
- 11115, /* 22.23 kPa 215 count */
- 11099, /* 22.28 kPa 216 count */
- 11084, /* 22.33 kPa 217 count */
- 11069, /* 22.39 kPa 218 count */
- 11053, /* 22.44 kPa 219 count */
- 11038, /* 22.50 kPa 220 count */
- 11023, /* 22.55 kPa 221 count */
- 11007, /* 22.61 kPa 222 count */
- 10992, /* 22.66 kPa 223 count */
- 10977, /* 22.71 kPa 224 count */
- 10962, /* 22.77 kPa 225 count */
- 10947, /* 22.82 kPa 226 count */
- 10932, /* 22.88 kPa 227 count */
- 10917, /* 22.93 kPa 228 count */
- 10902, /* 22.99 kPa 229 count */
- 10887, /* 23.04 kPa 230 count */
- 10872, /* 23.09 kPa 231 count */
- 10857, /* 23.15 kPa 232 count */
- 10842, /* 23.20 kPa 233 count */
- 10827, /* 23.26 kPa 234 count */
- 10812, /* 23.31 kPa 235 count */
- 10797, /* 23.37 kPa 236 count */
- 10782, /* 23.42 kPa 237 count */
- 10768, /* 23.47 kPa 238 count */
- 10753, /* 23.53 kPa 239 count */
- 10738, /* 23.58 kPa 240 count */
- 10723, /* 23.64 kPa 241 count */
- 10709, /* 23.69 kPa 242 count */
- 10694, /* 23.75 kPa 243 count */
- 10679, /* 23.80 kPa 244 count */
- 10665, /* 23.85 kPa 245 count */
- 10650, /* 23.91 kPa 246 count */
- 10636, /* 23.96 kPa 247 count */
- 10621, /* 24.02 kPa 248 count */
- 10607, /* 24.07 kPa 249 count */
- 10592, /* 24.13 kPa 250 count */
- 10578, /* 24.18 kPa 251 count */
- 10563, /* 24.23 kPa 252 count */
- 10549, /* 24.29 kPa 253 count */
- 10535, /* 24.34 kPa 254 count */
- 10520, /* 24.40 kPa 255 count */
- 10506, /* 24.45 kPa 256 count */
- 10492, /* 24.51 kPa 257 count */
- 10478, /* 24.56 kPa 258 count */
- 10463, /* 24.61 kPa 259 count */
- 10449, /* 24.67 kPa 260 count */
- 10435, /* 24.72 kPa 261 count */
- 10421, /* 24.78 kPa 262 count */
- 10407, /* 24.83 kPa 263 count */
- 10393, /* 24.89 kPa 264 count */
- 10379, /* 24.94 kPa 265 count */
- 10364, /* 24.99 kPa 266 count */
- 10350, /* 25.05 kPa 267 count */
- 10336, /* 25.10 kPa 268 count */
- 10322, /* 25.16 kPa 269 count */
- 10309, /* 25.21 kPa 270 count */
- 10295, /* 25.27 kPa 271 count */
- 10281, /* 25.32 kPa 272 count */
- 10267, /* 25.37 kPa 273 count */
- 10253, /* 25.43 kPa 274 count */
- 10239, /* 25.48 kPa 275 count */
- 10225, /* 25.54 kPa 276 count */
- 10212, /* 25.59 kPa 277 count */
- 10198, /* 25.65 kPa 278 count */
- 10184, /* 25.70 kPa 279 count */
- 10170, /* 25.75 kPa 280 count */
- 10157, /* 25.81 kPa 281 count */
- 10143, /* 25.86 kPa 282 count */
- 10129, /* 25.92 kPa 283 count */
- 10116, /* 25.97 kPa 284 count */
- 10102, /* 26.03 kPa 285 count */
- 10089, /* 26.08 kPa 286 count */
- 10075, /* 26.13 kPa 287 count */
- 10062, /* 26.19 kPa 288 count */
- 10048, /* 26.24 kPa 289 count */
- 10035, /* 26.30 kPa 290 count */
- 10021, /* 26.35 kPa 291 count */
- 10008, /* 26.41 kPa 292 count */
- 9994, /* 26.46 kPa 293 count */
- 9981, /* 26.51 kPa 294 count */
- 9967, /* 26.57 kPa 295 count */
- 9954, /* 26.62 kPa 296 count */
- 9941, /* 26.68 kPa 297 count */
- 9928, /* 26.73 kPa 298 count */
- 9914, /* 26.79 kPa 299 count */
- 9901, /* 26.84 kPa 300 count */
- 9888, /* 26.89 kPa 301 count */
- 9875, /* 26.95 kPa 302 count */
- 9861, /* 27.00 kPa 303 count */
- 9848, /* 27.06 kPa 304 count */
- 9835, /* 27.11 kPa 305 count */
- 9822, /* 27.17 kPa 306 count */
- 9809, /* 27.22 kPa 307 count */
- 9796, /* 27.27 kPa 308 count */
- 9783, /* 27.33 kPa 309 count */
- 9770, /* 27.38 kPa 310 count */
- 9757, /* 27.44 kPa 311 count */
- 9744, /* 27.49 kPa 312 count */
- 9731, /* 27.55 kPa 313 count */
- 9718, /* 27.60 kPa 314 count */
- 9705, /* 27.65 kPa 315 count */
- 9692, /* 27.71 kPa 316 count */
- 9679, /* 27.76 kPa 317 count */
- 9666, /* 27.82 kPa 318 count */
- 9653, /* 27.87 kPa 319 count */
- 9640, /* 27.93 kPa 320 count */
- 9627, /* 27.98 kPa 321 count */
- 9615, /* 28.03 kPa 322 count */
- 9602, /* 28.09 kPa 323 count */
- 9589, /* 28.14 kPa 324 count */
- 9576, /* 28.20 kPa 325 count */
- 9564, /* 28.25 kPa 326 count */
- 9551, /* 28.31 kPa 327 count */
- 9538, /* 28.36 kPa 328 count */
- 9526, /* 28.41 kPa 329 count */
- 9513, /* 28.47 kPa 330 count */
- 9500, /* 28.52 kPa 331 count */
- 9488, /* 28.58 kPa 332 count */
- 9475, /* 28.63 kPa 333 count */
- 9463, /* 28.69 kPa 334 count */
- 9450, /* 28.74 kPa 335 count */
- 9438, /* 28.79 kPa 336 count */
- 9425, /* 28.85 kPa 337 count */
- 9413, /* 28.90 kPa 338 count */
- 9400, /* 28.96 kPa 339 count */
- 9388, /* 29.01 kPa 340 count */
- 9375, /* 29.07 kPa 341 count */
- 9363, /* 29.12 kPa 342 count */
- 9350, /* 29.17 kPa 343 count */
- 9338, /* 29.23 kPa 344 count */
- 9326, /* 29.28 kPa 345 count */
- 9313, /* 29.34 kPa 346 count */
- 9301, /* 29.39 kPa 347 count */
- 9289, /* 29.44 kPa 348 count */
- 9276, /* 29.50 kPa 349 count */
- 9264, /* 29.55 kPa 350 count */
- 9252, /* 29.61 kPa 351 count */
- 9240, /* 29.66 kPa 352 count */
- 9227, /* 29.72 kPa 353 count */
- 9215, /* 29.77 kPa 354 count */
- 9203, /* 29.82 kPa 355 count */
- 9191, /* 29.88 kPa 356 count */
- 9179, /* 29.93 kPa 357 count */
- 9167, /* 29.99 kPa 358 count */
- 9155, /* 30.04 kPa 359 count */
- 9142, /* 30.10 kPa 360 count */
- 9130, /* 30.15 kPa 361 count */
- 9118, /* 30.20 kPa 362 count */
- 9106, /* 30.26 kPa 363 count */
- 9094, /* 30.31 kPa 364 count */
- 9082, /* 30.37 kPa 365 count */
- 9070, /* 30.42 kPa 366 count */
- 9058, /* 30.48 kPa 367 count */
- 9046, /* 30.53 kPa 368 count */
- 9035, /* 30.58 kPa 369 count */
- 9023, /* 30.64 kPa 370 count */
- 9011, /* 30.69 kPa 371 count */
- 8999, /* 30.75 kPa 372 count */
- 8987, /* 30.80 kPa 373 count */
- 8975, /* 30.86 kPa 374 count */
- 8963, /* 30.91 kPa 375 count */
- 8952, /* 30.96 kPa 376 count */
- 8940, /* 31.02 kPa 377 count */
- 8928, /* 31.07 kPa 378 count */
- 8916, /* 31.13 kPa 379 count */
- 8904, /* 31.18 kPa 380 count */
- 8893, /* 31.24 kPa 381 count */
- 8881, /* 31.29 kPa 382 count */
- 8869, /* 31.34 kPa 383 count */
- 8858, /* 31.40 kPa 384 count */
- 8846, /* 31.45 kPa 385 count */
- 8834, /* 31.51 kPa 386 count */
- 8823, /* 31.56 kPa 387 count */
- 8811, /* 31.62 kPa 388 count */
- 8800, /* 31.67 kPa 389 count */
- 8788, /* 31.72 kPa 390 count */
- 8776, /* 31.78 kPa 391 count */
- 8765, /* 31.83 kPa 392 count */
- 8753, /* 31.89 kPa 393 count */
- 8742, /* 31.94 kPa 394 count */
- 8730, /* 32.00 kPa 395 count */
- 8719, /* 32.05 kPa 396 count */
- 8707, /* 32.10 kPa 397 count */
- 8696, /* 32.16 kPa 398 count */
- 8684, /* 32.21 kPa 399 count */
- 8673, /* 32.27 kPa 400 count */
- 8662, /* 32.32 kPa 401 count */
- 8650, /* 32.38 kPa 402 count */
- 8639, /* 32.43 kPa 403 count */
- 8628, /* 32.48 kPa 404 count */
- 8616, /* 32.54 kPa 405 count */
- 8605, /* 32.59 kPa 406 count */
- 8594, /* 32.65 kPa 407 count */
- 8582, /* 32.70 kPa 408 count */
- 8571, /* 32.76 kPa 409 count */
- 8560, /* 32.81 kPa 410 count */
- 8548, /* 32.86 kPa 411 count */
- 8537, /* 32.92 kPa 412 count */
- 8526, /* 32.97 kPa 413 count */
- 8515, /* 33.03 kPa 414 count */
- 8504, /* 33.08 kPa 415 count */
- 8492, /* 33.14 kPa 416 count */
- 8481, /* 33.19 kPa 417 count */
- 8470, /* 33.24 kPa 418 count */
- 8459, /* 33.30 kPa 419 count */
- 8448, /* 33.35 kPa 420 count */
- 8437, /* 33.41 kPa 421 count */
- 8426, /* 33.46 kPa 422 count */
- 8415, /* 33.52 kPa 423 count */
- 8403, /* 33.57 kPa 424 count */
- 8392, /* 33.62 kPa 425 count */
- 8381, /* 33.68 kPa 426 count */
- 8370, /* 33.73 kPa 427 count */
- 8359, /* 33.79 kPa 428 count */
- 8348, /* 33.84 kPa 429 count */
- 8337, /* 33.90 kPa 430 count */
- 8326, /* 33.95 kPa 431 count */
- 8316, /* 34.00 kPa 432 count */
- 8305, /* 34.06 kPa 433 count */
- 8294, /* 34.11 kPa 434 count */
- 8283, /* 34.17 kPa 435 count */
- 8272, /* 34.22 kPa 436 count */
- 8261, /* 34.28 kPa 437 count */
- 8250, /* 34.33 kPa 438 count */
- 8239, /* 34.38 kPa 439 count */
- 8228, /* 34.44 kPa 440 count */
- 8218, /* 34.49 kPa 441 count */
- 8207, /* 34.55 kPa 442 count */
- 8196, /* 34.60 kPa 443 count */
- 8185, /* 34.66 kPa 444 count */
- 8175, /* 34.71 kPa 445 count */
- 8164, /* 34.76 kPa 446 count */
- 8153, /* 34.82 kPa 447 count */
- 8142, /* 34.87 kPa 448 count */
- 8132, /* 34.93 kPa 449 count */
- 8121, /* 34.98 kPa 450 count */
- 8110, /* 35.04 kPa 451 count */
- 8100, /* 35.09 kPa 452 count */
- 8089, /* 35.14 kPa 453 count */
- 8078, /* 35.20 kPa 454 count */
- 8068, /* 35.25 kPa 455 count */
- 8057, /* 35.31 kPa 456 count */
- 8046, /* 35.36 kPa 457 count */
- 8036, /* 35.42 kPa 458 count */
- 8025, /* 35.47 kPa 459 count */
- 8015, /* 35.52 kPa 460 count */
- 8004, /* 35.58 kPa 461 count */
- 7994, /* 35.63 kPa 462 count */
- 7983, /* 35.69 kPa 463 count */
- 7973, /* 35.74 kPa 464 count */
- 7962, /* 35.80 kPa 465 count */
- 7952, /* 35.85 kPa 466 count */
- 7941, /* 35.90 kPa 467 count */
- 7931, /* 35.96 kPa 468 count */
- 7920, /* 36.01 kPa 469 count */
- 7910, /* 36.07 kPa 470 count */
- 7899, /* 36.12 kPa 471 count */
- 7889, /* 36.18 kPa 472 count */
- 7879, /* 36.23 kPa 473 count */
- 7868, /* 36.28 kPa 474 count */
- 7858, /* 36.34 kPa 475 count */
- 7847, /* 36.39 kPa 476 count */
- 7837, /* 36.45 kPa 477 count */
- 7827, /* 36.50 kPa 478 count */
- 7816, /* 36.56 kPa 479 count */
- 7806, /* 36.61 kPa 480 count */
- 7796, /* 36.66 kPa 481 count */
- 7785, /* 36.72 kPa 482 count */
- 7775, /* 36.77 kPa 483 count */
- 7765, /* 36.83 kPa 484 count */
- 7755, /* 36.88 kPa 485 count */
- 7744, /* 36.94 kPa 486 count */
- 7734, /* 36.99 kPa 487 count */
- 7724, /* 37.04 kPa 488 count */
- 7714, /* 37.10 kPa 489 count */
- 7704, /* 37.15 kPa 490 count */
- 7693, /* 37.21 kPa 491 count */
- 7683, /* 37.26 kPa 492 count */
- 7673, /* 37.32 kPa 493 count */
- 7663, /* 37.37 kPa 494 count */
- 7653, /* 37.42 kPa 495 count */
- 7643, /* 37.48 kPa 496 count */
- 7633, /* 37.53 kPa 497 count */
- 7623, /* 37.59 kPa 498 count */
- 7613, /* 37.64 kPa 499 count */
- 7602, /* 37.70 kPa 500 count */
- 7592, /* 37.75 kPa 501 count */
- 7582, /* 37.80 kPa 502 count */
- 7572, /* 37.86 kPa 503 count */
- 7562, /* 37.91 kPa 504 count */
- 7552, /* 37.97 kPa 505 count */
- 7542, /* 38.02 kPa 506 count */
- 7532, /* 38.08 kPa 507 count */
- 7522, /* 38.13 kPa 508 count */
- 7512, /* 38.18 kPa 509 count */
- 7502, /* 38.24 kPa 510 count */
- 7492, /* 38.29 kPa 511 count */
- 7483, /* 38.35 kPa 512 count */
- 7473, /* 38.40 kPa 513 count */
- 7463, /* 38.46 kPa 514 count */
- 7453, /* 38.51 kPa 515 count */
- 7443, /* 38.56 kPa 516 count */
- 7433, /* 38.62 kPa 517 count */
- 7423, /* 38.67 kPa 518 count */
- 7413, /* 38.73 kPa 519 count */
- 7403, /* 38.78 kPa 520 count */
- 7394, /* 38.84 kPa 521 count */
- 7384, /* 38.89 kPa 522 count */
- 7374, /* 38.94 kPa 523 count */
- 7364, /* 39.00 kPa 524 count */
- 7354, /* 39.05 kPa 525 count */
- 7345, /* 39.11 kPa 526 count */
- 7335, /* 39.16 kPa 527 count */
- 7325, /* 39.22 kPa 528 count */
- 7315, /* 39.27 kPa 529 count */
- 7306, /* 39.32 kPa 530 count */
- 7296, /* 39.38 kPa 531 count */
- 7286, /* 39.43 kPa 532 count */
- 7277, /* 39.49 kPa 533 count */
- 7267, /* 39.54 kPa 534 count */
- 7257, /* 39.60 kPa 535 count */
- 7248, /* 39.65 kPa 536 count */
- 7238, /* 39.70 kPa 537 count */
- 7228, /* 39.76 kPa 538 count */
- 7219, /* 39.81 kPa 539 count */
- 7209, /* 39.87 kPa 540 count */
- 7199, /* 39.92 kPa 541 count */
- 7190, /* 39.98 kPa 542 count */
- 7180, /* 40.03 kPa 543 count */
- 7171, /* 40.08 kPa 544 count */
- 7161, /* 40.14 kPa 545 count */
- 7152, /* 40.19 kPa 546 count */
- 7142, /* 40.25 kPa 547 count */
- 7132, /* 40.30 kPa 548 count */
- 7123, /* 40.36 kPa 549 count */
- 7113, /* 40.41 kPa 550 count */
- 7104, /* 40.46 kPa 551 count */
- 7094, /* 40.52 kPa 552 count */
- 7085, /* 40.57 kPa 553 count */
- 7075, /* 40.63 kPa 554 count */
- 7066, /* 40.68 kPa 555 count */
- 7056, /* 40.74 kPa 556 count */
- 7047, /* 40.79 kPa 557 count */
- 7038, /* 40.84 kPa 558 count */
- 7028, /* 40.90 kPa 559 count */
- 7019, /* 40.95 kPa 560 count */
- 7009, /* 41.01 kPa 561 count */
- 7000, /* 41.06 kPa 562 count */
- 6991, /* 41.12 kPa 563 count */
- 6981, /* 41.17 kPa 564 count */
- 6972, /* 41.22 kPa 565 count */
- 6962, /* 41.28 kPa 566 count */
- 6953, /* 41.33 kPa 567 count */
- 6944, /* 41.39 kPa 568 count */
- 6934, /* 41.44 kPa 569 count */
- 6925, /* 41.50 kPa 570 count */
- 6916, /* 41.55 kPa 571 count */
- 6907, /* 41.60 kPa 572 count */
- 6897, /* 41.66 kPa 573 count */
- 6888, /* 41.71 kPa 574 count */
- 6879, /* 41.77 kPa 575 count */
- 6869, /* 41.82 kPa 576 count */
- 6860, /* 41.88 kPa 577 count */
- 6851, /* 41.93 kPa 578 count */
- 6842, /* 41.98 kPa 579 count */
- 6833, /* 42.04 kPa 580 count */
- 6823, /* 42.09 kPa 581 count */
- 6814, /* 42.15 kPa 582 count */
- 6805, /* 42.20 kPa 583 count */
- 6796, /* 42.26 kPa 584 count */
- 6787, /* 42.31 kPa 585 count */
- 6777, /* 42.36 kPa 586 count */
- 6768, /* 42.42 kPa 587 count */
- 6759, /* 42.47 kPa 588 count */
- 6750, /* 42.53 kPa 589 count */
- 6741, /* 42.58 kPa 590 count */
- 6732, /* 42.64 kPa 591 count */
- 6723, /* 42.69 kPa 592 count */
- 6714, /* 42.74 kPa 593 count */
- 6705, /* 42.80 kPa 594 count */
- 6695, /* 42.85 kPa 595 count */
- 6686, /* 42.91 kPa 596 count */
- 6677, /* 42.96 kPa 597 count */
- 6668, /* 43.01 kPa 598 count */
- 6659, /* 43.07 kPa 599 count */
- 6650, /* 43.12 kPa 600 count */
- 6641, /* 43.18 kPa 601 count */
- 6632, /* 43.23 kPa 602 count */
- 6623, /* 43.29 kPa 603 count */
- 6614, /* 43.34 kPa 604 count */
- 6605, /* 43.39 kPa 605 count */
- 6596, /* 43.45 kPa 606 count */
- 6587, /* 43.50 kPa 607 count */
- 6578, /* 43.56 kPa 608 count */
- 6569, /* 43.61 kPa 609 count */
- 6560, /* 43.67 kPa 610 count */
- 6552, /* 43.72 kPa 611 count */
- 6543, /* 43.77 kPa 612 count */
- 6534, /* 43.83 kPa 613 count */
- 6525, /* 43.88 kPa 614 count */
- 6516, /* 43.94 kPa 615 count */
- 6507, /* 43.99 kPa 616 count */
- 6498, /* 44.05 kPa 617 count */
- 6489, /* 44.10 kPa 618 count */
- 6480, /* 44.15 kPa 619 count */
- 6472, /* 44.21 kPa 620 count */
- 6463, /* 44.26 kPa 621 count */
- 6454, /* 44.32 kPa 622 count */
- 6445, /* 44.37 kPa 623 count */
- 6436, /* 44.43 kPa 624 count */
- 6427, /* 44.48 kPa 625 count */
- 6419, /* 44.53 kPa 626 count */
- 6410, /* 44.59 kPa 627 count */
- 6401, /* 44.64 kPa 628 count */
- 6392, /* 44.70 kPa 629 count */
- 6384, /* 44.75 kPa 630 count */
- 6375, /* 44.81 kPa 631 count */
- 6366, /* 44.86 kPa 632 count */
- 6357, /* 44.91 kPa 633 count */
- 6349, /* 44.97 kPa 634 count */
- 6340, /* 45.02 kPa 635 count */
- 6331, /* 45.08 kPa 636 count */
- 6322, /* 45.13 kPa 637 count */
- 6314, /* 45.19 kPa 638 count */
- 6305, /* 45.24 kPa 639 count */
- 6296, /* 45.29 kPa 640 count */
- 6288, /* 45.35 kPa 641 count */
- 6279, /* 45.40 kPa 642 count */
- 6270, /* 45.46 kPa 643 count */
- 6262, /* 45.51 kPa 644 count */
- 6253, /* 45.57 kPa 645 count */
- 6245, /* 45.62 kPa 646 count */
- 6236, /* 45.67 kPa 647 count */
- 6227, /* 45.73 kPa 648 count */
- 6219, /* 45.78 kPa 649 count */
- 6210, /* 45.84 kPa 650 count */
- 6202, /* 45.89 kPa 651 count */
- 6193, /* 45.95 kPa 652 count */
- 6184, /* 46.00 kPa 653 count */
- 6176, /* 46.05 kPa 654 count */
- 6167, /* 46.11 kPa 655 count */
- 6159, /* 46.16 kPa 656 count */
- 6150, /* 46.22 kPa 657 count */
- 6142, /* 46.27 kPa 658 count */
- 6133, /* 46.33 kPa 659 count */
- 6125, /* 46.38 kPa 660 count */
- 6116, /* 46.43 kPa 661 count */
- 6108, /* 46.49 kPa 662 count */
- 6099, /* 46.54 kPa 663 count */
- 6091, /* 46.60 kPa 664 count */
- 6082, /* 46.65 kPa 665 count */
- 6074, /* 46.71 kPa 666 count */
- 6065, /* 46.76 kPa 667 count */
- 6057, /* 46.81 kPa 668 count */
- 6048, /* 46.87 kPa 669 count */
- 6040, /* 46.92 kPa 670 count */
- 6032, /* 46.98 kPa 671 count */
- 6023, /* 47.03 kPa 672 count */
- 6015, /* 47.09 kPa 673 count */
- 6006, /* 47.14 kPa 674 count */
- 5998, /* 47.19 kPa 675 count */
- 5990, /* 47.25 kPa 676 count */
- 5981, /* 47.30 kPa 677 count */
- 5973, /* 47.36 kPa 678 count */
- 5964, /* 47.41 kPa 679 count */
- 5956, /* 47.47 kPa 680 count */
- 5948, /* 47.52 kPa 681 count */
- 5939, /* 47.57 kPa 682 count */
- 5931, /* 47.63 kPa 683 count */
- 5923, /* 47.68 kPa 684 count */
- 5914, /* 47.74 kPa 685 count */
- 5906, /* 47.79 kPa 686 count */
- 5898, /* 47.85 kPa 687 count */
- 5890, /* 47.90 kPa 688 count */
- 5881, /* 47.95 kPa 689 count */
- 5873, /* 48.01 kPa 690 count */
- 5865, /* 48.06 kPa 691 count */
- 5856, /* 48.12 kPa 692 count */
- 5848, /* 48.17 kPa 693 count */
- 5840, /* 48.23 kPa 694 count */
- 5832, /* 48.28 kPa 695 count */
- 5823, /* 48.33 kPa 696 count */
- 5815, /* 48.39 kPa 697 count */
- 5807, /* 48.44 kPa 698 count */
- 5799, /* 48.50 kPa 699 count */
- 5791, /* 48.55 kPa 700 count */
- 5782, /* 48.61 kPa 701 count */
- 5774, /* 48.66 kPa 702 count */
- 5766, /* 48.71 kPa 703 count */
- 5758, /* 48.77 kPa 704 count */
- 5750, /* 48.82 kPa 705 count */
- 5742, /* 48.88 kPa 706 count */
- 5733, /* 48.93 kPa 707 count */
- 5725, /* 48.99 kPa 708 count */
- 5717, /* 49.04 kPa 709 count */
- 5709, /* 49.09 kPa 710 count */
- 5701, /* 49.15 kPa 711 count */
- 5693, /* 49.20 kPa 712 count */
- 5685, /* 49.26 kPa 713 count */
- 5677, /* 49.31 kPa 714 count */
- 5668, /* 49.37 kPa 715 count */
- 5660, /* 49.42 kPa 716 count */
- 5652, /* 49.47 kPa 717 count */
- 5644, /* 49.53 kPa 718 count */
- 5636, /* 49.58 kPa 719 count */
- 5628, /* 49.64 kPa 720 count */
- 5620, /* 49.69 kPa 721 count */
- 5612, /* 49.75 kPa 722 count */
- 5604, /* 49.80 kPa 723 count */
- 5596, /* 49.85 kPa 724 count */
- 5588, /* 49.91 kPa 725 count */
- 5580, /* 49.96 kPa 726 count */
- 5572, /* 50.02 kPa 727 count */
- 5564, /* 50.07 kPa 728 count */
- 5556, /* 50.13 kPa 729 count */
- 5548, /* 50.18 kPa 730 count */
- 5540, /* 50.23 kPa 731 count */
- 5532, /* 50.29 kPa 732 count */
- 5524, /* 50.34 kPa 733 count */
- 5516, /* 50.40 kPa 734 count */
- 5508, /* 50.45 kPa 735 count */
- 5500, /* 50.51 kPa 736 count */
- 5492, /* 50.56 kPa 737 count */
- 5484, /* 50.61 kPa 738 count */
- 5476, /* 50.67 kPa 739 count */
- 5468, /* 50.72 kPa 740 count */
- 5461, /* 50.78 kPa 741 count */
- 5453, /* 50.83 kPa 742 count */
- 5445, /* 50.89 kPa 743 count */
- 5437, /* 50.94 kPa 744 count */
- 5429, /* 50.99 kPa 745 count */
- 5421, /* 51.05 kPa 746 count */
- 5413, /* 51.10 kPa 747 count */
- 5405, /* 51.16 kPa 748 count */
- 5398, /* 51.21 kPa 749 count */
- 5390, /* 51.27 kPa 750 count */
- 5382, /* 51.32 kPa 751 count */
- 5374, /* 51.37 kPa 752 count */
- 5366, /* 51.43 kPa 753 count */
- 5358, /* 51.48 kPa 754 count */
- 5351, /* 51.54 kPa 755 count */
- 5343, /* 51.59 kPa 756 count */
- 5335, /* 51.65 kPa 757 count */
- 5327, /* 51.70 kPa 758 count */
- 5319, /* 51.75 kPa 759 count */
- 5312, /* 51.81 kPa 760 count */
- 5304, /* 51.86 kPa 761 count */
- 5296, /* 51.92 kPa 762 count */
- 5288, /* 51.97 kPa 763 count */
- 5281, /* 52.03 kPa 764 count */
- 5273, /* 52.08 kPa 765 count */
- 5265, /* 52.13 kPa 766 count */
- 5257, /* 52.19 kPa 767 count */
- 5250, /* 52.24 kPa 768 count */
- 5242, /* 52.30 kPa 769 count */
- 5234, /* 52.35 kPa 770 count */
- 5226, /* 52.41 kPa 771 count */
- 5219, /* 52.46 kPa 772 count */
- 5211, /* 52.51 kPa 773 count */
- 5203, /* 52.57 kPa 774 count */
- 5196, /* 52.62 kPa 775 count */
- 5188, /* 52.68 kPa 776 count */
- 5180, /* 52.73 kPa 777 count */
- 5173, /* 52.79 kPa 778 count */
- 5165, /* 52.84 kPa 779 count */
- 5157, /* 52.89 kPa 780 count */
- 5150, /* 52.95 kPa 781 count */
- 5142, /* 53.00 kPa 782 count */
- 5134, /* 53.06 kPa 783 count */
- 5127, /* 53.11 kPa 784 count */
- 5119, /* 53.17 kPa 785 count */
- 5112, /* 53.22 kPa 786 count */
- 5104, /* 53.27 kPa 787 count */
- 5096, /* 53.33 kPa 788 count */
- 5089, /* 53.38 kPa 789 count */
- 5081, /* 53.44 kPa 790 count */
- 5074, /* 53.49 kPa 791 count */
- 5066, /* 53.55 kPa 792 count */
- 5058, /* 53.60 kPa 793 count */
- 5051, /* 53.65 kPa 794 count */
- 5043, /* 53.71 kPa 795 count */
- 5036, /* 53.76 kPa 796 count */
- 5028, /* 53.82 kPa 797 count */
- 5021, /* 53.87 kPa 798 count */
- 5013, /* 53.93 kPa 799 count */
- 5006, /* 53.98 kPa 800 count */
- 4998, /* 54.03 kPa 801 count */
- 4991, /* 54.09 kPa 802 count */
- 4983, /* 54.14 kPa 803 count */
- 4976, /* 54.20 kPa 804 count */
- 4968, /* 54.25 kPa 805 count */
- 4961, /* 54.31 kPa 806 count */
- 4953, /* 54.36 kPa 807 count */
- 4946, /* 54.41 kPa 808 count */
- 4938, /* 54.47 kPa 809 count */
- 4931, /* 54.52 kPa 810 count */
- 4923, /* 54.58 kPa 811 count */
- 4916, /* 54.63 kPa 812 count */
- 4908, /* 54.69 kPa 813 count */
- 4901, /* 54.74 kPa 814 count */
- 4893, /* 54.79 kPa 815 count */
- 4886, /* 54.85 kPa 816 count */
- 4879, /* 54.90 kPa 817 count */
- 4871, /* 54.96 kPa 818 count */
- 4864, /* 55.01 kPa 819 count */
- 4856, /* 55.07 kPa 820 count */
- 4849, /* 55.12 kPa 821 count */
- 4842, /* 55.17 kPa 822 count */
- 4834, /* 55.23 kPa 823 count */
- 4827, /* 55.28 kPa 824 count */
- 4819, /* 55.34 kPa 825 count */
- 4812, /* 55.39 kPa 826 count */
- 4805, /* 55.45 kPa 827 count */
- 4797, /* 55.50 kPa 828 count */
- 4790, /* 55.55 kPa 829 count */
- 4783, /* 55.61 kPa 830 count */
- 4775, /* 55.66 kPa 831 count */
- 4768, /* 55.72 kPa 832 count */
- 4761, /* 55.77 kPa 833 count */
- 4753, /* 55.83 kPa 834 count */
- 4746, /* 55.88 kPa 835 count */
- 4739, /* 55.93 kPa 836 count */
- 4731, /* 55.99 kPa 837 count */
- 4724, /* 56.04 kPa 838 count */
- 4717, /* 56.10 kPa 839 count */
- 4709, /* 56.15 kPa 840 count */
- 4702, /* 56.21 kPa 841 count */
- 4695, /* 56.26 kPa 842 count */
- 4688, /* 56.31 kPa 843 count */
- 4680, /* 56.37 kPa 844 count */
- 4673, /* 56.42 kPa 845 count */
- 4666, /* 56.48 kPa 846 count */
- 4659, /* 56.53 kPa 847 count */
- 4651, /* 56.58 kPa 848 count */
- 4644, /* 56.64 kPa 849 count */
- 4637, /* 56.69 kPa 850 count */
- 4630, /* 56.75 kPa 851 count */
- 4622, /* 56.80 kPa 852 count */
- 4615, /* 56.86 kPa 853 count */
- 4608, /* 56.91 kPa 854 count */
- 4601, /* 56.96 kPa 855 count */
- 4594, /* 57.02 kPa 856 count */
- 4586, /* 57.07 kPa 857 count */
- 4579, /* 57.13 kPa 858 count */
- 4572, /* 57.18 kPa 859 count */
- 4565, /* 57.24 kPa 860 count */
- 4558, /* 57.29 kPa 861 count */
- 4550, /* 57.34 kPa 862 count */
- 4543, /* 57.40 kPa 863 count */
- 4536, /* 57.45 kPa 864 count */
- 4529, /* 57.51 kPa 865 count */
- 4522, /* 57.56 kPa 866 count */
- 4515, /* 57.62 kPa 867 count */
- 4508, /* 57.67 kPa 868 count */
- 4500, /* 57.72 kPa 869 count */
- 4493, /* 57.78 kPa 870 count */
- 4486, /* 57.83 kPa 871 count */
- 4479, /* 57.89 kPa 872 count */
- 4472, /* 57.94 kPa 873 count */
- 4465, /* 58.00 kPa 874 count */
- 4458, /* 58.05 kPa 875 count */
- 4451, /* 58.10 kPa 876 count */
- 4444, /* 58.16 kPa 877 count */
- 4437, /* 58.21 kPa 878 count */
- 4429, /* 58.27 kPa 879 count */
- 4422, /* 58.32 kPa 880 count */
- 4415, /* 58.38 kPa 881 count */
- 4408, /* 58.43 kPa 882 count */
- 4401, /* 58.48 kPa 883 count */
- 4394, /* 58.54 kPa 884 count */
- 4387, /* 58.59 kPa 885 count */
- 4380, /* 58.65 kPa 886 count */
- 4373, /* 58.70 kPa 887 count */
- 4366, /* 58.76 kPa 888 count */
- 4359, /* 58.81 kPa 889 count */
- 4352, /* 58.86 kPa 890 count */
- 4345, /* 58.92 kPa 891 count */
- 4338, /* 58.97 kPa 892 count */
- 4331, /* 59.03 kPa 893 count */
- 4324, /* 59.08 kPa 894 count */
- 4317, /* 59.14 kPa 895 count */
- 4310, /* 59.19 kPa 896 count */
- 4303, /* 59.24 kPa 897 count */
- 4296, /* 59.30 kPa 898 count */
- 4289, /* 59.35 kPa 899 count */
- 4282, /* 59.41 kPa 900 count */
- 4275, /* 59.46 kPa 901 count */
- 4268, /* 59.52 kPa 902 count */
- 4261, /* 59.57 kPa 903 count */
- 4254, /* 59.62 kPa 904 count */
- 4247, /* 59.68 kPa 905 count */
- 4240, /* 59.73 kPa 906 count */
- 4234, /* 59.79 kPa 907 count */
- 4227, /* 59.84 kPa 908 count */
- 4220, /* 59.90 kPa 909 count */
- 4213, /* 59.95 kPa 910 count */
- 4206, /* 60.00 kPa 911 count */
- 4199, /* 60.06 kPa 912 count */
- 4192, /* 60.11 kPa 913 count */
- 4185, /* 60.17 kPa 914 count */
- 4178, /* 60.22 kPa 915 count */
- 4171, /* 60.28 kPa 916 count */
- 4164, /* 60.33 kPa 917 count */
- 4158, /* 60.38 kPa 918 count */
- 4151, /* 60.44 kPa 919 count */
- 4144, /* 60.49 kPa 920 count */
- 4137, /* 60.55 kPa 921 count */
- 4130, /* 60.60 kPa 922 count */
- 4123, /* 60.66 kPa 923 count */
- 4116, /* 60.71 kPa 924 count */
- 4110, /* 60.76 kPa 925 count */
- 4103, /* 60.82 kPa 926 count */
- 4096, /* 60.87 kPa 927 count */
- 4089, /* 60.93 kPa 928 count */
- 4082, /* 60.98 kPa 929 count */
- 4076, /* 61.04 kPa 930 count */
- 4069, /* 61.09 kPa 931 count */
- 4062, /* 61.14 kPa 932 count */
- 4055, /* 61.20 kPa 933 count */
- 4048, /* 61.25 kPa 934 count */
- 4042, /* 61.31 kPa 935 count */
- 4035, /* 61.36 kPa 936 count */
- 4028, /* 61.42 kPa 937 count */
- 4021, /* 61.47 kPa 938 count */
- 4014, /* 61.52 kPa 939 count */
- 4008, /* 61.58 kPa 940 count */
- 4001, /* 61.63 kPa 941 count */
- 3994, /* 61.69 kPa 942 count */
- 3987, /* 61.74 kPa 943 count */
- 3981, /* 61.80 kPa 944 count */
- 3974, /* 61.85 kPa 945 count */
- 3967, /* 61.90 kPa 946 count */
- 3960, /* 61.96 kPa 947 count */
- 3954, /* 62.01 kPa 948 count */
- 3947, /* 62.07 kPa 949 count */
- 3940, /* 62.12 kPa 950 count */
- 3934, /* 62.18 kPa 951 count */
- 3927, /* 62.23 kPa 952 count */
- 3920, /* 62.28 kPa 953 count */
- 3913, /* 62.34 kPa 954 count */
- 3907, /* 62.39 kPa 955 count */
- 3900, /* 62.45 kPa 956 count */
- 3893, /* 62.50 kPa 957 count */
- 3887, /* 62.56 kPa 958 count */
- 3880, /* 62.61 kPa 959 count */
- 3873, /* 62.66 kPa 960 count */
- 3867, /* 62.72 kPa 961 count */
- 3860, /* 62.77 kPa 962 count */
- 3853, /* 62.83 kPa 963 count */
- 3847, /* 62.88 kPa 964 count */
- 3840, /* 62.94 kPa 965 count */
- 3833, /* 62.99 kPa 966 count */
- 3827, /* 63.04 kPa 967 count */
- 3820, /* 63.10 kPa 968 count */
- 3814, /* 63.15 kPa 969 count */
- 3807, /* 63.21 kPa 970 count */
- 3800, /* 63.26 kPa 971 count */
- 3794, /* 63.32 kPa 972 count */
- 3787, /* 63.37 kPa 973 count */
- 3780, /* 63.42 kPa 974 count */
- 3774, /* 63.48 kPa 975 count */
- 3767, /* 63.53 kPa 976 count */
- 3761, /* 63.59 kPa 977 count */
- 3754, /* 63.64 kPa 978 count */
- 3748, /* 63.70 kPa 979 count */
- 3741, /* 63.75 kPa 980 count */
- 3734, /* 63.80 kPa 981 count */
- 3728, /* 63.86 kPa 982 count */
- 3721, /* 63.91 kPa 983 count */
- 3715, /* 63.97 kPa 984 count */
- 3708, /* 64.02 kPa 985 count */
- 3702, /* 64.08 kPa 986 count */
- 3695, /* 64.13 kPa 987 count */
- 3688, /* 64.18 kPa 988 count */
- 3682, /* 64.24 kPa 989 count */
- 3675, /* 64.29 kPa 990 count */
- 3669, /* 64.35 kPa 991 count */
- 3662, /* 64.40 kPa 992 count */
- 3656, /* 64.46 kPa 993 count */
- 3649, /* 64.51 kPa 994 count */
- 3643, /* 64.56 kPa 995 count */
- 3636, /* 64.62 kPa 996 count */
- 3630, /* 64.67 kPa 997 count */
- 3623, /* 64.73 kPa 998 count */
- 3617, /* 64.78 kPa 999 count */
- 3610, /* 64.84 kPa 1000 count */
- 3604, /* 64.89 kPa 1001 count */
- 3597, /* 64.94 kPa 1002 count */
- 3591, /* 65.00 kPa 1003 count */
- 3584, /* 65.05 kPa 1004 count */
- 3578, /* 65.11 kPa 1005 count */
- 3571, /* 65.16 kPa 1006 count */
- 3565, /* 65.22 kPa 1007 count */
- 3559, /* 65.27 kPa 1008 count */
- 3552, /* 65.32 kPa 1009 count */
- 3546, /* 65.38 kPa 1010 count */
- 3539, /* 65.43 kPa 1011 count */
- 3533, /* 65.49 kPa 1012 count */
- 3526, /* 65.54 kPa 1013 count */
- 3520, /* 65.60 kPa 1014 count */
- 3514, /* 65.65 kPa 1015 count */
- 3507, /* 65.70 kPa 1016 count */
- 3501, /* 65.76 kPa 1017 count */
- 3494, /* 65.81 kPa 1018 count */
- 3488, /* 65.87 kPa 1019 count */
- 3481, /* 65.92 kPa 1020 count */
- 3475, /* 65.98 kPa 1021 count */
- 3469, /* 66.03 kPa 1022 count */
- 3462, /* 66.08 kPa 1023 count */
- 3456, /* 66.14 kPa 1024 count */
- 3450, /* 66.19 kPa 1025 count */
- 3443, /* 66.25 kPa 1026 count */
- 3437, /* 66.30 kPa 1027 count */
- 3430, /* 66.36 kPa 1028 count */
- 3424, /* 66.41 kPa 1029 count */
- 3418, /* 66.46 kPa 1030 count */
- 3411, /* 66.52 kPa 1031 count */
- 3405, /* 66.57 kPa 1032 count */
- 3399, /* 66.63 kPa 1033 count */
- 3392, /* 66.68 kPa 1034 count */
- 3386, /* 66.74 kPa 1035 count */
- 3380, /* 66.79 kPa 1036 count */
- 3373, /* 66.84 kPa 1037 count */
- 3367, /* 66.90 kPa 1038 count */
- 3361, /* 66.95 kPa 1039 count */
- 3354, /* 67.01 kPa 1040 count */
- 3348, /* 67.06 kPa 1041 count */
- 3342, /* 67.12 kPa 1042 count */
- 3335, /* 67.17 kPa 1043 count */
- 3329, /* 67.22 kPa 1044 count */
- 3323, /* 67.28 kPa 1045 count */
- 3316, /* 67.33 kPa 1046 count */
- 3310, /* 67.39 kPa 1047 count */
- 3304, /* 67.44 kPa 1048 count */
- 3298, /* 67.50 kPa 1049 count */
- 3291, /* 67.55 kPa 1050 count */
- 3285, /* 67.60 kPa 1051 count */
- 3279, /* 67.66 kPa 1052 count */
- 3273, /* 67.71 kPa 1053 count */
- 3266, /* 67.77 kPa 1054 count */
- 3260, /* 67.82 kPa 1055 count */
- 3254, /* 67.88 kPa 1056 count */
- 3248, /* 67.93 kPa 1057 count */
- 3241, /* 67.98 kPa 1058 count */
- 3235, /* 68.04 kPa 1059 count */
- 3229, /* 68.09 kPa 1060 count */
- 3223, /* 68.15 kPa 1061 count */
- 3216, /* 68.20 kPa 1062 count */
- 3210, /* 68.26 kPa 1063 count */
- 3204, /* 68.31 kPa 1064 count */
- 3198, /* 68.36 kPa 1065 count */
- 3191, /* 68.42 kPa 1066 count */
- 3185, /* 68.47 kPa 1067 count */
- 3179, /* 68.53 kPa 1068 count */
- 3173, /* 68.58 kPa 1069 count */
- 3167, /* 68.64 kPa 1070 count */
- 3160, /* 68.69 kPa 1071 count */
- 3154, /* 68.74 kPa 1072 count */
- 3148, /* 68.80 kPa 1073 count */
- 3142, /* 68.85 kPa 1074 count */
- 3136, /* 68.91 kPa 1075 count */
- 3130, /* 68.96 kPa 1076 count */
- 3123, /* 69.02 kPa 1077 count */
- 3117, /* 69.07 kPa 1078 count */
- 3111, /* 69.12 kPa 1079 count */
- 3105, /* 69.18 kPa 1080 count */
- 3099, /* 69.23 kPa 1081 count */
- 3093, /* 69.29 kPa 1082 count */
- 3087, /* 69.34 kPa 1083 count */
- 3080, /* 69.40 kPa 1084 count */
- 3074, /* 69.45 kPa 1085 count */
- 3068, /* 69.50 kPa 1086 count */
- 3062, /* 69.56 kPa 1087 count */
- 3056, /* 69.61 kPa 1088 count */
- 3050, /* 69.67 kPa 1089 count */
- 3044, /* 69.72 kPa 1090 count */
- 3037, /* 69.78 kPa 1091 count */
- 3031, /* 69.83 kPa 1092 count */
- 3025, /* 69.88 kPa 1093 count */
- 3019, /* 69.94 kPa 1094 count */
- 3013, /* 69.99 kPa 1095 count */
- 3007, /* 70.05 kPa 1096 count */
- 3001, /* 70.10 kPa 1097 count */
- 2995, /* 70.15 kPa 1098 count */
- 2989, /* 70.21 kPa 1099 count */
- 2983, /* 70.26 kPa 1100 count */
- 2977, /* 70.32 kPa 1101 count */
- 2970, /* 70.37 kPa 1102 count */
- 2964, /* 70.43 kPa 1103 count */
- 2958, /* 70.48 kPa 1104 count */
- 2952, /* 70.53 kPa 1105 count */
- 2946, /* 70.59 kPa 1106 count */
- 2940, /* 70.64 kPa 1107 count */
- 2934, /* 70.70 kPa 1108 count */
- 2928, /* 70.75 kPa 1109 count */
- 2922, /* 70.81 kPa 1110 count */
- 2916, /* 70.86 kPa 1111 count */
- 2910, /* 70.91 kPa 1112 count */
- 2904, /* 70.97 kPa 1113 count */
- 2898, /* 71.02 kPa 1114 count */
- 2892, /* 71.08 kPa 1115 count */
- 2886, /* 71.13 kPa 1116 count */
- 2880, /* 71.19 kPa 1117 count */
- 2874, /* 71.24 kPa 1118 count */
- 2868, /* 71.29 kPa 1119 count */
- 2862, /* 71.35 kPa 1120 count */
- 2856, /* 71.40 kPa 1121 count */
- 2850, /* 71.46 kPa 1122 count */
- 2844, /* 71.51 kPa 1123 count */
- 2838, /* 71.57 kPa 1124 count */
- 2832, /* 71.62 kPa 1125 count */
- 2826, /* 71.67 kPa 1126 count */
- 2820, /* 71.73 kPa 1127 count */
- 2814, /* 71.78 kPa 1128 count */
- 2808, /* 71.84 kPa 1129 count */
- 2802, /* 71.89 kPa 1130 count */
- 2796, /* 71.95 kPa 1131 count */
- 2790, /* 72.00 kPa 1132 count */
- 2784, /* 72.05 kPa 1133 count */
- 2778, /* 72.11 kPa 1134 count */
- 2772, /* 72.16 kPa 1135 count */
- 2766, /* 72.22 kPa 1136 count */
- 2760, /* 72.27 kPa 1137 count */
- 2754, /* 72.33 kPa 1138 count */
- 2748, /* 72.38 kPa 1139 count */
- 2743, /* 72.43 kPa 1140 count */
- 2737, /* 72.49 kPa 1141 count */
- 2731, /* 72.54 kPa 1142 count */
- 2725, /* 72.60 kPa 1143 count */
- 2719, /* 72.65 kPa 1144 count */
- 2713, /* 72.71 kPa 1145 count */
- 2707, /* 72.76 kPa 1146 count */
- 2701, /* 72.81 kPa 1147 count */
- 2695, /* 72.87 kPa 1148 count */
- 2689, /* 72.92 kPa 1149 count */
- 2683, /* 72.98 kPa 1150 count */
- 2678, /* 73.03 kPa 1151 count */
- 2672, /* 73.09 kPa 1152 count */
- 2666, /* 73.14 kPa 1153 count */
- 2660, /* 73.19 kPa 1154 count */
- 2654, /* 73.25 kPa 1155 count */
- 2648, /* 73.30 kPa 1156 count */
- 2642, /* 73.36 kPa 1157 count */
- 2636, /* 73.41 kPa 1158 count */
- 2631, /* 73.47 kPa 1159 count */
- 2625, /* 73.52 kPa 1160 count */
- 2619, /* 73.57 kPa 1161 count */
- 2613, /* 73.63 kPa 1162 count */
- 2607, /* 73.68 kPa 1163 count */
- 2601, /* 73.74 kPa 1164 count */
- 2595, /* 73.79 kPa 1165 count */
- 2590, /* 73.85 kPa 1166 count */
- 2584, /* 73.90 kPa 1167 count */
- 2578, /* 73.95 kPa 1168 count */
- 2572, /* 74.01 kPa 1169 count */
- 2566, /* 74.06 kPa 1170 count */
- 2560, /* 74.12 kPa 1171 count */
- 2555, /* 74.17 kPa 1172 count */
- 2549, /* 74.23 kPa 1173 count */
- 2543, /* 74.28 kPa 1174 count */
- 2537, /* 74.33 kPa 1175 count */
- 2531, /* 74.39 kPa 1176 count */
- 2526, /* 74.44 kPa 1177 count */
- 2520, /* 74.50 kPa 1178 count */
- 2514, /* 74.55 kPa 1179 count */
- 2508, /* 74.61 kPa 1180 count */
- 2502, /* 74.66 kPa 1181 count */
- 2497, /* 74.71 kPa 1182 count */
- 2491, /* 74.77 kPa 1183 count */
- 2485, /* 74.82 kPa 1184 count */
- 2479, /* 74.88 kPa 1185 count */
- 2473, /* 74.93 kPa 1186 count */
- 2468, /* 74.99 kPa 1187 count */
- 2462, /* 75.04 kPa 1188 count */
- 2456, /* 75.09 kPa 1189 count */
- 2450, /* 75.15 kPa 1190 count */
- 2445, /* 75.20 kPa 1191 count */
- 2439, /* 75.26 kPa 1192 count */
- 2433, /* 75.31 kPa 1193 count */
- 2427, /* 75.37 kPa 1194 count */
- 2422, /* 75.42 kPa 1195 count */
- 2416, /* 75.47 kPa 1196 count */
- 2410, /* 75.53 kPa 1197 count */
- 2405, /* 75.58 kPa 1198 count */
- 2399, /* 75.64 kPa 1199 count */
- 2393, /* 75.69 kPa 1200 count */
- 2387, /* 75.75 kPa 1201 count */
- 2382, /* 75.80 kPa 1202 count */
- 2376, /* 75.85 kPa 1203 count */
- 2370, /* 75.91 kPa 1204 count */
- 2364, /* 75.96 kPa 1205 count */
- 2359, /* 76.02 kPa 1206 count */
- 2353, /* 76.07 kPa 1207 count */
- 2347, /* 76.13 kPa 1208 count */
- 2342, /* 76.18 kPa 1209 count */
- 2336, /* 76.23 kPa 1210 count */
- 2330, /* 76.29 kPa 1211 count */
- 2325, /* 76.34 kPa 1212 count */
- 2319, /* 76.40 kPa 1213 count */
- 2313, /* 76.45 kPa 1214 count */
- 2308, /* 76.51 kPa 1215 count */
- 2302, /* 76.56 kPa 1216 count */
- 2296, /* 76.61 kPa 1217 count */
- 2291, /* 76.67 kPa 1218 count */
- 2285, /* 76.72 kPa 1219 count */
- 2279, /* 76.78 kPa 1220 count */
- 2274, /* 76.83 kPa 1221 count */
- 2268, /* 76.89 kPa 1222 count */
- 2262, /* 76.94 kPa 1223 count */
- 2257, /* 76.99 kPa 1224 count */
- 2251, /* 77.05 kPa 1225 count */
- 2245, /* 77.10 kPa 1226 count */
- 2240, /* 77.16 kPa 1227 count */
- 2234, /* 77.21 kPa 1228 count */
- 2228, /* 77.27 kPa 1229 count */
- 2223, /* 77.32 kPa 1230 count */
- 2217, /* 77.37 kPa 1231 count */
- 2212, /* 77.43 kPa 1232 count */
- 2206, /* 77.48 kPa 1233 count */
- 2200, /* 77.54 kPa 1234 count */
- 2195, /* 77.59 kPa 1235 count */
- 2189, /* 77.65 kPa 1236 count */
- 2184, /* 77.70 kPa 1237 count */
- 2178, /* 77.75 kPa 1238 count */
- 2172, /* 77.81 kPa 1239 count */
- 2167, /* 77.86 kPa 1240 count */
- 2161, /* 77.92 kPa 1241 count */
- 2156, /* 77.97 kPa 1242 count */
- 2150, /* 78.03 kPa 1243 count */
- 2144, /* 78.08 kPa 1244 count */
- 2139, /* 78.13 kPa 1245 count */
- 2133, /* 78.19 kPa 1246 count */
- 2128, /* 78.24 kPa 1247 count */
- 2122, /* 78.30 kPa 1248 count */
- 2117, /* 78.35 kPa 1249 count */
- 2111, /* 78.41 kPa 1250 count */
- 2105, /* 78.46 kPa 1251 count */
- 2100, /* 78.51 kPa 1252 count */
- 2094, /* 78.57 kPa 1253 count */
- 2089, /* 78.62 kPa 1254 count */
- 2083, /* 78.68 kPa 1255 count */
- 2078, /* 78.73 kPa 1256 count */
- 2072, /* 78.79 kPa 1257 count */
- 2067, /* 78.84 kPa 1258 count */
- 2061, /* 78.89 kPa 1259 count */
- 2056, /* 78.95 kPa 1260 count */
- 2050, /* 79.00 kPa 1261 count */
- 2045, /* 79.06 kPa 1262 count */
- 2039, /* 79.11 kPa 1263 count */
- 2033, /* 79.17 kPa 1264 count */
- 2028, /* 79.22 kPa 1265 count */
- 2022, /* 79.27 kPa 1266 count */
- 2017, /* 79.33 kPa 1267 count */
- 2011, /* 79.38 kPa 1268 count */
- 2006, /* 79.44 kPa 1269 count */
- 2000, /* 79.49 kPa 1270 count */
- 1995, /* 79.55 kPa 1271 count */
- 1989, /* 79.60 kPa 1272 count */
- 1984, /* 79.65 kPa 1273 count */
- 1978, /* 79.71 kPa 1274 count */
- 1973, /* 79.76 kPa 1275 count */
- 1967, /* 79.82 kPa 1276 count */
- 1962, /* 79.87 kPa 1277 count */
- 1957, /* 79.93 kPa 1278 count */
- 1951, /* 79.98 kPa 1279 count */
- 1946, /* 80.03 kPa 1280 count */
- 1940, /* 80.09 kPa 1281 count */
- 1935, /* 80.14 kPa 1282 count */
- 1929, /* 80.20 kPa 1283 count */
- 1924, /* 80.25 kPa 1284 count */
- 1918, /* 80.31 kPa 1285 count */
- 1913, /* 80.36 kPa 1286 count */
- 1907, /* 80.41 kPa 1287 count */
- 1902, /* 80.47 kPa 1288 count */
- 1896, /* 80.52 kPa 1289 count */
- 1891, /* 80.58 kPa 1290 count */
- 1886, /* 80.63 kPa 1291 count */
- 1880, /* 80.69 kPa 1292 count */
- 1875, /* 80.74 kPa 1293 count */
- 1869, /* 80.79 kPa 1294 count */
- 1864, /* 80.85 kPa 1295 count */
- 1858, /* 80.90 kPa 1296 count */
- 1853, /* 80.96 kPa 1297 count */
- 1848, /* 81.01 kPa 1298 count */
- 1842, /* 81.07 kPa 1299 count */
- 1837, /* 81.12 kPa 1300 count */
- 1831, /* 81.17 kPa 1301 count */
- 1826, /* 81.23 kPa 1302 count */
- 1821, /* 81.28 kPa 1303 count */
- 1815, /* 81.34 kPa 1304 count */
- 1810, /* 81.39 kPa 1305 count */
- 1804, /* 81.45 kPa 1306 count */
- 1799, /* 81.50 kPa 1307 count */
- 1794, /* 81.55 kPa 1308 count */
- 1788, /* 81.61 kPa 1309 count */
- 1783, /* 81.66 kPa 1310 count */
- 1777, /* 81.72 kPa 1311 count */
- 1772, /* 81.77 kPa 1312 count */
- 1767, /* 81.83 kPa 1313 count */
- 1761, /* 81.88 kPa 1314 count */
- 1756, /* 81.93 kPa 1315 count */
- 1751, /* 81.99 kPa 1316 count */
- 1745, /* 82.04 kPa 1317 count */
- 1740, /* 82.10 kPa 1318 count */
- 1735, /* 82.15 kPa 1319 count */
- 1729, /* 82.21 kPa 1320 count */
- 1724, /* 82.26 kPa 1321 count */
- 1718, /* 82.31 kPa 1322 count */
- 1713, /* 82.37 kPa 1323 count */
- 1708, /* 82.42 kPa 1324 count */
- 1702, /* 82.48 kPa 1325 count */
- 1697, /* 82.53 kPa 1326 count */
- 1692, /* 82.59 kPa 1327 count */
- 1686, /* 82.64 kPa 1328 count */
- 1681, /* 82.69 kPa 1329 count */
- 1676, /* 82.75 kPa 1330 count */
- 1670, /* 82.80 kPa 1331 count */
- 1665, /* 82.86 kPa 1332 count */
- 1660, /* 82.91 kPa 1333 count */
- 1655, /* 82.97 kPa 1334 count */
- 1649, /* 83.02 kPa 1335 count */
- 1644, /* 83.07 kPa 1336 count */
- 1639, /* 83.13 kPa 1337 count */
- 1633, /* 83.18 kPa 1338 count */
- 1628, /* 83.24 kPa 1339 count */
- 1623, /* 83.29 kPa 1340 count */
- 1617, /* 83.35 kPa 1341 count */
- 1612, /* 83.40 kPa 1342 count */
- 1607, /* 83.45 kPa 1343 count */
- 1602, /* 83.51 kPa 1344 count */
- 1596, /* 83.56 kPa 1345 count */
- 1591, /* 83.62 kPa 1346 count */
- 1586, /* 83.67 kPa 1347 count */
- 1580, /* 83.72 kPa 1348 count */
- 1575, /* 83.78 kPa 1349 count */
- 1570, /* 83.83 kPa 1350 count */
- 1565, /* 83.89 kPa 1351 count */
- 1559, /* 83.94 kPa 1352 count */
- 1554, /* 84.00 kPa 1353 count */
- 1549, /* 84.05 kPa 1354 count */
- 1544, /* 84.10 kPa 1355 count */
- 1538, /* 84.16 kPa 1356 count */
- 1533, /* 84.21 kPa 1357 count */
- 1528, /* 84.27 kPa 1358 count */
- 1523, /* 84.32 kPa 1359 count */
- 1517, /* 84.38 kPa 1360 count */
- 1512, /* 84.43 kPa 1361 count */
- 1507, /* 84.48 kPa 1362 count */
- 1502, /* 84.54 kPa 1363 count */
- 1496, /* 84.59 kPa 1364 count */
- 1491, /* 84.65 kPa 1365 count */
- 1486, /* 84.70 kPa 1366 count */
- 1481, /* 84.76 kPa 1367 count */
- 1475, /* 84.81 kPa 1368 count */
- 1470, /* 84.86 kPa 1369 count */
- 1465, /* 84.92 kPa 1370 count */
- 1460, /* 84.97 kPa 1371 count */
- 1455, /* 85.03 kPa 1372 count */
- 1449, /* 85.08 kPa 1373 count */
- 1444, /* 85.14 kPa 1374 count */
- 1439, /* 85.19 kPa 1375 count */
- 1434, /* 85.24 kPa 1376 count */
- 1429, /* 85.30 kPa 1377 count */
- 1423, /* 85.35 kPa 1378 count */
- 1418, /* 85.41 kPa 1379 count */
- 1413, /* 85.46 kPa 1380 count */
- 1408, /* 85.52 kPa 1381 count */
- 1403, /* 85.57 kPa 1382 count */
- 1398, /* 85.62 kPa 1383 count */
- 1392, /* 85.68 kPa 1384 count */
- 1387, /* 85.73 kPa 1385 count */
- 1382, /* 85.79 kPa 1386 count */
- 1377, /* 85.84 kPa 1387 count */
- 1372, /* 85.90 kPa 1388 count */
- 1366, /* 85.95 kPa 1389 count */
- 1361, /* 86.00 kPa 1390 count */
- 1356, /* 86.06 kPa 1391 count */
- 1351, /* 86.11 kPa 1392 count */
- 1346, /* 86.17 kPa 1393 count */
- 1341, /* 86.22 kPa 1394 count */
- 1336, /* 86.28 kPa 1395 count */
- 1330, /* 86.33 kPa 1396 count */
- 1325, /* 86.38 kPa 1397 count */
- 1320, /* 86.44 kPa 1398 count */
- 1315, /* 86.49 kPa 1399 count */
- 1310, /* 86.55 kPa 1400 count */
- 1305, /* 86.60 kPa 1401 count */
- 1300, /* 86.66 kPa 1402 count */
- 1294, /* 86.71 kPa 1403 count */
- 1289, /* 86.76 kPa 1404 count */
- 1284, /* 86.82 kPa 1405 count */
- 1279, /* 86.87 kPa 1406 count */
- 1274, /* 86.93 kPa 1407 count */
- 1269, /* 86.98 kPa 1408 count */
- 1264, /* 87.04 kPa 1409 count */
- 1259, /* 87.09 kPa 1410 count */
- 1254, /* 87.14 kPa 1411 count */
- 1248, /* 87.20 kPa 1412 count */
- 1243, /* 87.25 kPa 1413 count */
- 1238, /* 87.31 kPa 1414 count */
- 1233, /* 87.36 kPa 1415 count */
- 1228, /* 87.42 kPa 1416 count */
- 1223, /* 87.47 kPa 1417 count */
- 1218, /* 87.52 kPa 1418 count */
- 1213, /* 87.58 kPa 1419 count */
- 1208, /* 87.63 kPa 1420 count */
- 1203, /* 87.69 kPa 1421 count */
- 1198, /* 87.74 kPa 1422 count */
- 1192, /* 87.80 kPa 1423 count */
- 1187, /* 87.85 kPa 1424 count */
- 1182, /* 87.90 kPa 1425 count */
- 1177, /* 87.96 kPa 1426 count */
- 1172, /* 88.01 kPa 1427 count */
- 1167, /* 88.07 kPa 1428 count */
- 1162, /* 88.12 kPa 1429 count */
- 1157, /* 88.18 kPa 1430 count */
- 1152, /* 88.23 kPa 1431 count */
- 1147, /* 88.28 kPa 1432 count */
- 1142, /* 88.34 kPa 1433 count */
- 1137, /* 88.39 kPa 1434 count */
- 1132, /* 88.45 kPa 1435 count */
- 1127, /* 88.50 kPa 1436 count */
- 1122, /* 88.56 kPa 1437 count */
- 1117, /* 88.61 kPa 1438 count */
- 1112, /* 88.66 kPa 1439 count */
- 1107, /* 88.72 kPa 1440 count */
- 1102, /* 88.77 kPa 1441 count */
- 1097, /* 88.83 kPa 1442 count */
- 1091, /* 88.88 kPa 1443 count */
- 1086, /* 88.94 kPa 1444 count */
- 1081, /* 88.99 kPa 1445 count */
- 1076, /* 89.04 kPa 1446 count */
- 1071, /* 89.10 kPa 1447 count */
- 1066, /* 89.15 kPa 1448 count */
- 1061, /* 89.21 kPa 1449 count */
- 1056, /* 89.26 kPa 1450 count */
- 1051, /* 89.32 kPa 1451 count */
- 1046, /* 89.37 kPa 1452 count */
- 1041, /* 89.42 kPa 1453 count */
- 1036, /* 89.48 kPa 1454 count */
- 1031, /* 89.53 kPa 1455 count */
- 1026, /* 89.59 kPa 1456 count */
- 1021, /* 89.64 kPa 1457 count */
- 1016, /* 89.70 kPa 1458 count */
- 1011, /* 89.75 kPa 1459 count */
- 1006, /* 89.80 kPa 1460 count */
- 1001, /* 89.86 kPa 1461 count */
- 996, /* 89.91 kPa 1462 count */
- 992, /* 89.97 kPa 1463 count */
- 987, /* 90.02 kPa 1464 count */
- 982, /* 90.08 kPa 1465 count */
- 977, /* 90.13 kPa 1466 count */
- 972, /* 90.18 kPa 1467 count */
- 967, /* 90.24 kPa 1468 count */
- 962, /* 90.29 kPa 1469 count */
- 957, /* 90.35 kPa 1470 count */
- 952, /* 90.40 kPa 1471 count */
- 947, /* 90.46 kPa 1472 count */
- 942, /* 90.51 kPa 1473 count */
- 937, /* 90.56 kPa 1474 count */
- 932, /* 90.62 kPa 1475 count */
- 927, /* 90.67 kPa 1476 count */
- 922, /* 90.73 kPa 1477 count */
- 917, /* 90.78 kPa 1478 count */
- 912, /* 90.84 kPa 1479 count */
- 907, /* 90.89 kPa 1480 count */
- 902, /* 90.94 kPa 1481 count */
- 897, /* 91.00 kPa 1482 count */
- 892, /* 91.05 kPa 1483 count */
- 888, /* 91.11 kPa 1484 count */
- 883, /* 91.16 kPa 1485 count */
- 878, /* 91.22 kPa 1486 count */
- 873, /* 91.27 kPa 1487 count */
- 868, /* 91.32 kPa 1488 count */
- 863, /* 91.38 kPa 1489 count */
- 858, /* 91.43 kPa 1490 count */
- 853, /* 91.49 kPa 1491 count */
- 848, /* 91.54 kPa 1492 count */
- 843, /* 91.60 kPa 1493 count */
- 838, /* 91.65 kPa 1494 count */
- 834, /* 91.70 kPa 1495 count */
- 829, /* 91.76 kPa 1496 count */
- 824, /* 91.81 kPa 1497 count */
- 819, /* 91.87 kPa 1498 count */
- 814, /* 91.92 kPa 1499 count */
- 809, /* 91.98 kPa 1500 count */
- 804, /* 92.03 kPa 1501 count */
- 799, /* 92.08 kPa 1502 count */
- 794, /* 92.14 kPa 1503 count */
- 790, /* 92.19 kPa 1504 count */
- 785, /* 92.25 kPa 1505 count */
- 780, /* 92.30 kPa 1506 count */
- 775, /* 92.36 kPa 1507 count */
- 770, /* 92.41 kPa 1508 count */
- 765, /* 92.46 kPa 1509 count */
- 760, /* 92.52 kPa 1510 count */
- 755, /* 92.57 kPa 1511 count */
- 751, /* 92.63 kPa 1512 count */
- 746, /* 92.68 kPa 1513 count */
- 741, /* 92.74 kPa 1514 count */
- 736, /* 92.79 kPa 1515 count */
- 731, /* 92.84 kPa 1516 count */
- 726, /* 92.90 kPa 1517 count */
- 721, /* 92.95 kPa 1518 count */
- 717, /* 93.01 kPa 1519 count */
- 712, /* 93.06 kPa 1520 count */
- 707, /* 93.12 kPa 1521 count */
- 702, /* 93.17 kPa 1522 count */
- 697, /* 93.22 kPa 1523 count */
- 692, /* 93.28 kPa 1524 count */
- 688, /* 93.33 kPa 1525 count */
- 683, /* 93.39 kPa 1526 count */
- 678, /* 93.44 kPa 1527 count */
- 673, /* 93.50 kPa 1528 count */
- 668, /* 93.55 kPa 1529 count */
- 664, /* 93.60 kPa 1530 count */
- 659, /* 93.66 kPa 1531 count */
- 654, /* 93.71 kPa 1532 count */
- 649, /* 93.77 kPa 1533 count */
- 644, /* 93.82 kPa 1534 count */
- 639, /* 93.88 kPa 1535 count */
- 635, /* 93.93 kPa 1536 count */
- 630, /* 93.98 kPa 1537 count */
- 625, /* 94.04 kPa 1538 count */
- 620, /* 94.09 kPa 1539 count */
- 615, /* 94.15 kPa 1540 count */
- 611, /* 94.20 kPa 1541 count */
- 606, /* 94.26 kPa 1542 count */
- 601, /* 94.31 kPa 1543 count */
- 596, /* 94.36 kPa 1544 count */
- 591, /* 94.42 kPa 1545 count */
- 587, /* 94.47 kPa 1546 count */
- 582, /* 94.53 kPa 1547 count */
- 577, /* 94.58 kPa 1548 count */
- 572, /* 94.64 kPa 1549 count */
- 568, /* 94.69 kPa 1550 count */
- 563, /* 94.74 kPa 1551 count */
- 558, /* 94.80 kPa 1552 count */
- 553, /* 94.85 kPa 1553 count */
- 549, /* 94.91 kPa 1554 count */
- 544, /* 94.96 kPa 1555 count */
- 539, /* 95.02 kPa 1556 count */
- 534, /* 95.07 kPa 1557 count */
- 529, /* 95.12 kPa 1558 count */
- 525, /* 95.18 kPa 1559 count */
- 520, /* 95.23 kPa 1560 count */
- 515, /* 95.29 kPa 1561 count */
- 510, /* 95.34 kPa 1562 count */
- 506, /* 95.40 kPa 1563 count */
- 501, /* 95.45 kPa 1564 count */
- 496, /* 95.50 kPa 1565 count */
- 492, /* 95.56 kPa 1566 count */
- 487, /* 95.61 kPa 1567 count */
- 482, /* 95.67 kPa 1568 count */
- 477, /* 95.72 kPa 1569 count */
- 473, /* 95.78 kPa 1570 count */
- 468, /* 95.83 kPa 1571 count */
- 463, /* 95.88 kPa 1572 count */
- 458, /* 95.94 kPa 1573 count */
- 454, /* 95.99 kPa 1574 count */
- 449, /* 96.05 kPa 1575 count */
- 444, /* 96.10 kPa 1576 count */
- 440, /* 96.16 kPa 1577 count */
- 435, /* 96.21 kPa 1578 count */
- 430, /* 96.26 kPa 1579 count */
- 425, /* 96.32 kPa 1580 count */
- 421, /* 96.37 kPa 1581 count */
- 416, /* 96.43 kPa 1582 count */
- 411, /* 96.48 kPa 1583 count */
- 407, /* 96.54 kPa 1584 count */
- 402, /* 96.59 kPa 1585 count */
- 397, /* 96.64 kPa 1586 count */
- 392, /* 96.70 kPa 1587 count */
- 388, /* 96.75 kPa 1588 count */
- 383, /* 96.81 kPa 1589 count */
- 378, /* 96.86 kPa 1590 count */
- 374, /* 96.91 kPa 1591 count */
- 369, /* 96.97 kPa 1592 count */
- 364, /* 97.02 kPa 1593 count */
- 360, /* 97.08 kPa 1594 count */
- 355, /* 97.13 kPa 1595 count */
- 350, /* 97.19 kPa 1596 count */
- 346, /* 97.24 kPa 1597 count */
- 341, /* 97.29 kPa 1598 count */
- 336, /* 97.35 kPa 1599 count */
- 332, /* 97.40 kPa 1600 count */
- 327, /* 97.46 kPa 1601 count */
- 322, /* 97.51 kPa 1602 count */
- 318, /* 97.57 kPa 1603 count */
- 313, /* 97.62 kPa 1604 count */
- 308, /* 97.67 kPa 1605 count */
- 304, /* 97.73 kPa 1606 count */
- 299, /* 97.78 kPa 1607 count */
- 294, /* 97.84 kPa 1608 count */
- 290, /* 97.89 kPa 1609 count */
- 285, /* 97.95 kPa 1610 count */
- 280, /* 98.00 kPa 1611 count */
- 276, /* 98.05 kPa 1612 count */
- 271, /* 98.11 kPa 1613 count */
- 267, /* 98.16 kPa 1614 count */
- 262, /* 98.22 kPa 1615 count */
- 257, /* 98.27 kPa 1616 count */
- 253, /* 98.33 kPa 1617 count */
- 248, /* 98.38 kPa 1618 count */
- 243, /* 98.43 kPa 1619 count */
- 239, /* 98.49 kPa 1620 count */
- 234, /* 98.54 kPa 1621 count */
- 230, /* 98.60 kPa 1622 count */
- 225, /* 98.65 kPa 1623 count */
- 220, /* 98.71 kPa 1624 count */
- 216, /* 98.76 kPa 1625 count */
- 211, /* 98.81 kPa 1626 count */
- 206, /* 98.87 kPa 1627 count */
- 202, /* 98.92 kPa 1628 count */
- 197, /* 98.98 kPa 1629 count */
- 193, /* 99.03 kPa 1630 count */
- 188, /* 99.09 kPa 1631 count */
- 183, /* 99.14 kPa 1632 count */
- 179, /* 99.19 kPa 1633 count */
- 174, /* 99.25 kPa 1634 count */
- 170, /* 99.30 kPa 1635 count */
- 165, /* 99.36 kPa 1636 count */
- 160, /* 99.41 kPa 1637 count */
- 156, /* 99.47 kPa 1638 count */
- 151, /* 99.52 kPa 1639 count */
- 147, /* 99.57 kPa 1640 count */
- 142, /* 99.63 kPa 1641 count */
- 138, /* 99.68 kPa 1642 count */
- 133, /* 99.74 kPa 1643 count */
- 128, /* 99.79 kPa 1644 count */
- 124, /* 99.85 kPa 1645 count */
- 119, /* 99.90 kPa 1646 count */
- 115, /* 99.95 kPa 1647 count */
- 110, /* 100.01 kPa 1648 count */
- 106, /* 100.06 kPa 1649 count */
- 101, /* 100.12 kPa 1650 count */
- 96, /* 100.17 kPa 1651 count */
- 92, /* 100.23 kPa 1652 count */
- 87, /* 100.28 kPa 1653 count */
- 83, /* 100.33 kPa 1654 count */
- 78, /* 100.39 kPa 1655 count */
- 74, /* 100.44 kPa 1656 count */
- 69, /* 100.50 kPa 1657 count */
- 65, /* 100.55 kPa 1658 count */
- 60, /* 100.61 kPa 1659 count */
- 55, /* 100.66 kPa 1660 count */
- 51, /* 100.71 kPa 1661 count */
- 46, /* 100.77 kPa 1662 count */
- 42, /* 100.82 kPa 1663 count */
- 37, /* 100.88 kPa 1664 count */
- 33, /* 100.93 kPa 1665 count */
- 28, /* 100.99 kPa 1666 count */
- 24, /* 101.04 kPa 1667 count */
- 19, /* 101.09 kPa 1668 count */
- 15, /* 101.15 kPa 1669 count */
- 10, /* 101.20 kPa 1670 count */
- 6, /* 101.26 kPa 1671 count */
- 1, /* 101.31 kPa 1672 count */
- -3, /* 101.37 kPa 1673 count */
- -8, /* 101.42 kPa 1674 count */
- -12, /* 101.47 kPa 1675 count */
- -17, /* 101.53 kPa 1676 count */
- -21, /* 101.58 kPa 1677 count */
- -26, /* 101.64 kPa 1678 count */
- -30, /* 101.69 kPa 1679 count */
- -35, /* 101.75 kPa 1680 count */
- -39, /* 101.80 kPa 1681 count */
- -44, /* 101.85 kPa 1682 count */
- -48, /* 101.91 kPa 1683 count */
- -53, /* 101.96 kPa 1684 count */
- -57, /* 102.02 kPa 1685 count */
- -62, /* 102.07 kPa 1686 count */
- -66, /* 102.13 kPa 1687 count */
- -71, /* 102.18 kPa 1688 count */
- -75, /* 102.23 kPa 1689 count */
- -80, /* 102.29 kPa 1690 count */
- -84, /* 102.34 kPa 1691 count */
- -89, /* 102.40 kPa 1692 count */
- -93, /* 102.45 kPa 1693 count */
- -98, /* 102.51 kPa 1694 count */
- -102, /* 102.56 kPa 1695 count */
- -107, /* 102.61 kPa 1696 count */
- -111, /* 102.67 kPa 1697 count */
- -116, /* 102.72 kPa 1698 count */
- -120, /* 102.78 kPa 1699 count */
- -125, /* 102.83 kPa 1700 count */
- -129, /* 102.89 kPa 1701 count */
- -134, /* 102.94 kPa 1702 count */
- -138, /* 102.99 kPa 1703 count */
- -143, /* 103.05 kPa 1704 count */
- -147, /* 103.10 kPa 1705 count */
- -151, /* 103.16 kPa 1706 count */
- -156, /* 103.21 kPa 1707 count */
- -160, /* 103.27 kPa 1708 count */
- -165, /* 103.32 kPa 1709 count */
- -169, /* 103.37 kPa 1710 count */
- -174, /* 103.43 kPa 1711 count */
- -178, /* 103.48 kPa 1712 count */
- -183, /* 103.54 kPa 1713 count */
- -187, /* 103.59 kPa 1714 count */
- -191, /* 103.65 kPa 1715 count */
- -196, /* 103.70 kPa 1716 count */
- -200, /* 103.75 kPa 1717 count */
- -205, /* 103.81 kPa 1718 count */
- -209, /* 103.86 kPa 1719 count */
- -214, /* 103.92 kPa 1720 count */
- -218, /* 103.97 kPa 1721 count */
- -222, /* 104.03 kPa 1722 count */
- -227, /* 104.08 kPa 1723 count */
- -231, /* 104.13 kPa 1724 count */
- -236, /* 104.19 kPa 1725 count */
- -240, /* 104.24 kPa 1726 count */
- -245, /* 104.30 kPa 1727 count */
- -249, /* 104.35 kPa 1728 count */
- -253, /* 104.41 kPa 1729 count */
- -258, /* 104.46 kPa 1730 count */
- -262, /* 104.51 kPa 1731 count */
- -267, /* 104.57 kPa 1732 count */
- -271, /* 104.62 kPa 1733 count */
- -275, /* 104.68 kPa 1734 count */
- -280, /* 104.73 kPa 1735 count */
- -284, /* 104.79 kPa 1736 count */
- -289, /* 104.84 kPa 1737 count */
- -293, /* 104.89 kPa 1738 count */
- -297, /* 104.95 kPa 1739 count */
- -302, /* 105.00 kPa 1740 count */
- -306, /* 105.06 kPa 1741 count */
- -311, /* 105.11 kPa 1742 count */
- -315, /* 105.17 kPa 1743 count */
- -319, /* 105.22 kPa 1744 count */
- -324, /* 105.27 kPa 1745 count */
- -328, /* 105.33 kPa 1746 count */
- -332, /* 105.38 kPa 1747 count */
- -337, /* 105.44 kPa 1748 count */
- -341, /* 105.49 kPa 1749 count */
- -346, /* 105.55 kPa 1750 count */
- -350, /* 105.60 kPa 1751 count */
- -354, /* 105.65 kPa 1752 count */
- -359, /* 105.71 kPa 1753 count */
- -363, /* 105.76 kPa 1754 count */
- -367, /* 105.82 kPa 1755 count */
- -372, /* 105.87 kPa 1756 count */
- -376, /* 105.93 kPa 1757 count */
- -380, /* 105.98 kPa 1758 count */
- -385, /* 106.03 kPa 1759 count */
- -389, /* 106.09 kPa 1760 count */
- -394, /* 106.14 kPa 1761 count */
- -398, /* 106.20 kPa 1762 count */
- -402, /* 106.25 kPa 1763 count */
- -407, /* 106.31 kPa 1764 count */
- -411, /* 106.36 kPa 1765 count */
- -415, /* 106.41 kPa 1766 count */
- -420, /* 106.47 kPa 1767 count */
- -424, /* 106.52 kPa 1768 count */
- -428, /* 106.58 kPa 1769 count */
- -433, /* 106.63 kPa 1770 count */
- -437, /* 106.69 kPa 1771 count */
- -441, /* 106.74 kPa 1772 count */
- -446, /* 106.79 kPa 1773 count */
- -450, /* 106.85 kPa 1774 count */
- -454, /* 106.90 kPa 1775 count */
- -459, /* 106.96 kPa 1776 count */
- -463, /* 107.01 kPa 1777 count */
- -467, /* 107.07 kPa 1778 count */
- -472, /* 107.12 kPa 1779 count */
- -476, /* 107.17 kPa 1780 count */
- -480, /* 107.23 kPa 1781 count */
- -485, /* 107.28 kPa 1782 count */
- -489, /* 107.34 kPa 1783 count */
- -493, /* 107.39 kPa 1784 count */
- -497, /* 107.45 kPa 1785 count */
- -502, /* 107.50 kPa 1786 count */
- -506, /* 107.55 kPa 1787 count */
- -510, /* 107.61 kPa 1788 count */
- -515, /* 107.66 kPa 1789 count */
- -519, /* 107.72 kPa 1790 count */
- -523, /* 107.77 kPa 1791 count */
- -528, /* 107.83 kPa 1792 count */
- -532, /* 107.88 kPa 1793 count */
- -536, /* 107.93 kPa 1794 count */
- -540, /* 107.99 kPa 1795 count */
- -545, /* 108.04 kPa 1796 count */
- -549, /* 108.10 kPa 1797 count */
- -553, /* 108.15 kPa 1798 count */
- -558, /* 108.21 kPa 1799 count */
- -562, /* 108.26 kPa 1800 count */
- -566, /* 108.31 kPa 1801 count */
- -570, /* 108.37 kPa 1802 count */
- -575, /* 108.42 kPa 1803 count */
- -579, /* 108.48 kPa 1804 count */
- -583, /* 108.53 kPa 1805 count */
- -588, /* 108.59 kPa 1806 count */
- -592, /* 108.64 kPa 1807 count */
- -596, /* 108.69 kPa 1808 count */
- -600, /* 108.75 kPa 1809 count */
- -605, /* 108.80 kPa 1810 count */
- -609, /* 108.86 kPa 1811 count */
- -613, /* 108.91 kPa 1812 count */
- -617, /* 108.97 kPa 1813 count */
- -622, /* 109.02 kPa 1814 count */
- -626, /* 109.07 kPa 1815 count */
- -630, /* 109.13 kPa 1816 count */
- -634, /* 109.18 kPa 1817 count */
- -639, /* 109.24 kPa 1818 count */
- -643, /* 109.29 kPa 1819 count */
- -647, /* 109.35 kPa 1820 count */
- -651, /* 109.40 kPa 1821 count */
- -656, /* 109.45 kPa 1822 count */
- -660, /* 109.51 kPa 1823 count */
- -664, /* 109.56 kPa 1824 count */
- -668, /* 109.62 kPa 1825 count */
- -673, /* 109.67 kPa 1826 count */
- -677, /* 109.73 kPa 1827 count */
- -681, /* 109.78 kPa 1828 count */
- -685, /* 109.83 kPa 1829 count */
- -690, /* 109.89 kPa 1830 count */
- -694, /* 109.94 kPa 1831 count */
- -698, /* 110.00 kPa 1832 count */
- -702, /* 110.05 kPa 1833 count */
- -706, /* 110.11 kPa 1834 count */
- -711, /* 110.16 kPa 1835 count */
- -715, /* 110.21 kPa 1836 count */
- -719, /* 110.27 kPa 1837 count */
- -723, /* 110.32 kPa 1838 count */
- -728, /* 110.38 kPa 1839 count */
- -732, /* 110.43 kPa 1840 count */
- -736, /* 110.48 kPa 1841 count */
- -740, /* 110.54 kPa 1842 count */
- -744, /* 110.59 kPa 1843 count */
- -749, /* 110.65 kPa 1844 count */
- -753, /* 110.70 kPa 1845 count */
- -757, /* 110.76 kPa 1846 count */
- -761, /* 110.81 kPa 1847 count */
- -765, /* 110.86 kPa 1848 count */
- -770, /* 110.92 kPa 1849 count */
- -774, /* 110.97 kPa 1850 count */
- -778, /* 111.03 kPa 1851 count */
- -782, /* 111.08 kPa 1852 count */
- -786, /* 111.14 kPa 1853 count */
- -791, /* 111.19 kPa 1854 count */
- -795, /* 111.24 kPa 1855 count */
- -799, /* 111.30 kPa 1856 count */
- -803, /* 111.35 kPa 1857 count */
- -807, /* 111.41 kPa 1858 count */
- -812, /* 111.46 kPa 1859 count */
- -816, /* 111.52 kPa 1860 count */
- -820, /* 111.57 kPa 1861 count */
- -824, /* 111.62 kPa 1862 count */
- -828, /* 111.68 kPa 1863 count */
- -832, /* 111.73 kPa 1864 count */
- -837, /* 111.79 kPa 1865 count */
- -841, /* 111.84 kPa 1866 count */
- -845, /* 111.90 kPa 1867 count */
- -849, /* 111.95 kPa 1868 count */
- -853, /* 112.00 kPa 1869 count */
- -857, /* 112.06 kPa 1870 count */
- -862, /* 112.11 kPa 1871 count */
- -866, /* 112.17 kPa 1872 count */
- -870, /* 112.22 kPa 1873 count */
- -874, /* 112.28 kPa 1874 count */
- -878, /* 112.33 kPa 1875 count */
- -882, /* 112.38 kPa 1876 count */
- -887, /* 112.44 kPa 1877 count */
- -891, /* 112.49 kPa 1878 count */
- -895, /* 112.55 kPa 1879 count */
- -899, /* 112.60 kPa 1880 count */
- -903, /* 112.66 kPa 1881 count */
- -907, /* 112.71 kPa 1882 count */
- -911, /* 112.76 kPa 1883 count */
- -916, /* 112.82 kPa 1884 count */
- -920, /* 112.87 kPa 1885 count */
- -924, /* 112.93 kPa 1886 count */
- -928, /* 112.98 kPa 1887 count */
- -932, /* 113.04 kPa 1888 count */
- -936, /* 113.09 kPa 1889 count */
- -940, /* 113.14 kPa 1890 count */
- -945, /* 113.20 kPa 1891 count */
- -949, /* 113.25 kPa 1892 count */
- -953, /* 113.31 kPa 1893 count */
- -957, /* 113.36 kPa 1894 count */
- -961, /* 113.42 kPa 1895 count */
- -965, /* 113.47 kPa 1896 count */
- -969, /* 113.52 kPa 1897 count */
- -973, /* 113.58 kPa 1898 count */
- -978, /* 113.63 kPa 1899 count */
- -982, /* 113.69 kPa 1900 count */
- -986, /* 113.74 kPa 1901 count */
- -990, /* 113.80 kPa 1902 count */
- -994, /* 113.85 kPa 1903 count */
- -998, /* 113.90 kPa 1904 count */
- -1002, /* 113.96 kPa 1905 count */
- -1006, /* 114.01 kPa 1906 count */
- -1010, /* 114.07 kPa 1907 count */
- -1015, /* 114.12 kPa 1908 count */
- -1019, /* 114.18 kPa 1909 count */
- -1023, /* 114.23 kPa 1910 count */
- -1027, /* 114.28 kPa 1911 count */
- -1031, /* 114.34 kPa 1912 count */
- -1035, /* 114.39 kPa 1913 count */
- -1039, /* 114.45 kPa 1914 count */
- -1043, /* 114.50 kPa 1915 count */
- -1047, /* 114.56 kPa 1916 count */
- -1051, /* 114.61 kPa 1917 count */
- -1056, /* 114.66 kPa 1918 count */
- -1060, /* 114.72 kPa 1919 count */
- -1064, /* 114.77 kPa 1920 count */
- -1068, /* 114.83 kPa 1921 count */
- -1072, /* 114.88 kPa 1922 count */
- -1076, /* 114.94 kPa 1923 count */
- -1080, /* 114.99 kPa 1924 count */
- -1084, /* 115.04 kPa 1925 count */
- -1088, /* 115.10 kPa 1926 count */
- -1092, /* 115.15 kPa 1927 count */
- -1096, /* 115.21 kPa 1928 count */
- -1100, /* 115.26 kPa 1929 count */
- -1104, /* 115.32 kPa 1930 count */
- -1109, /* 115.37 kPa 1931 count */
- -1113, /* 115.42 kPa 1932 count */
- -1117, /* 115.48 kPa 1933 count */
- -1121, /* 115.53 kPa 1934 count */
- -1125, /* 115.59 kPa 1935 count */
- -1129, /* 115.64 kPa 1936 count */
- -1133, /* 115.70 kPa 1937 count */
- -1137, /* 115.75 kPa 1938 count */
- -1141, /* 115.80 kPa 1939 count */
- -1145, /* 115.86 kPa 1940 count */
- -1149, /* 115.91 kPa 1941 count */
- -1153, /* 115.97 kPa 1942 count */
- -1157, /* 116.02 kPa 1943 count */
- -1161, /* 116.08 kPa 1944 count */
- -1165, /* 116.13 kPa 1945 count */
- -1169, /* 116.18 kPa 1946 count */
- -1173, /* 116.24 kPa 1947 count */
- -1177, /* 116.29 kPa 1948 count */
- -1182, /* 116.35 kPa 1949 count */
- -1186, /* 116.40 kPa 1950 count */
- -1190, /* 116.46 kPa 1951 count */
- -1194, /* 116.51 kPa 1952 count */
- -1198, /* 116.56 kPa 1953 count */
- -1202, /* 116.62 kPa 1954 count */
- -1206, /* 116.67 kPa 1955 count */
- -1210, /* 116.73 kPa 1956 count */
- -1214, /* 116.78 kPa 1957 count */
- -1218, /* 116.84 kPa 1958 count */
- -1222, /* 116.89 kPa 1959 count */
- -1226, /* 116.94 kPa 1960 count */
- -1230, /* 117.00 kPa 1961 count */
- -1234, /* 117.05 kPa 1962 count */
- -1238, /* 117.11 kPa 1963 count */
- -1242, /* 117.16 kPa 1964 count */
- -1246, /* 117.22 kPa 1965 count */
- -1250, /* 117.27 kPa 1966 count */
- -1254, /* 117.32 kPa 1967 count */
- -1258, /* 117.38 kPa 1968 count */
- -1262, /* 117.43 kPa 1969 count */
- -1266, /* 117.49 kPa 1970 count */
- -1270, /* 117.54 kPa 1971 count */
- -1274, /* 117.60 kPa 1972 count */
- -1278, /* 117.65 kPa 1973 count */
- -1282, /* 117.70 kPa 1974 count */
- -1286, /* 117.76 kPa 1975 count */
- -1290, /* 117.81 kPa 1976 count */
- -1294, /* 117.87 kPa 1977 count */
- -1298, /* 117.92 kPa 1978 count */
- -1302, /* 117.98 kPa 1979 count */
- -1306, /* 118.03 kPa 1980 count */
- -1310, /* 118.08 kPa 1981 count */
- -1314, /* 118.14 kPa 1982 count */
- -1318, /* 118.19 kPa 1983 count */
- -1322, /* 118.25 kPa 1984 count */
- -1326, /* 118.30 kPa 1985 count */
- -1330, /* 118.36 kPa 1986 count */
- -1334, /* 118.41 kPa 1987 count */
- -1338, /* 118.46 kPa 1988 count */
- -1342, /* 118.52 kPa 1989 count */
- -1346, /* 118.57 kPa 1990 count */
- -1350, /* 118.63 kPa 1991 count */
- -1354, /* 118.68 kPa 1992 count */
- -1358, /* 118.74 kPa 1993 count */
- -1362, /* 118.79 kPa 1994 count */
- -1366, /* 118.84 kPa 1995 count */
- -1370, /* 118.90 kPa 1996 count */
- -1374, /* 118.95 kPa 1997 count */
- -1378, /* 119.01 kPa 1998 count */
- -1382, /* 119.06 kPa 1999 count */
- -1386, /* 119.12 kPa 2000 count */
- -1390, /* 119.17 kPa 2001 count */
- -1394, /* 119.22 kPa 2002 count */
- -1397, /* 119.28 kPa 2003 count */
- -1401, /* 119.33 kPa 2004 count */
- -1405, /* 119.39 kPa 2005 count */
- -1409, /* 119.44 kPa 2006 count */
- -1413, /* 119.50 kPa 2007 count */
- -1417, /* 119.55 kPa 2008 count */
- -1421, /* 119.60 kPa 2009 count */
- -1425, /* 119.66 kPa 2010 count */
- -1429, /* 119.71 kPa 2011 count */
- -1433, /* 119.77 kPa 2012 count */
- -1437, /* 119.82 kPa 2013 count */
- -1441, /* 119.88 kPa 2014 count */
- -1445, /* 119.93 kPa 2015 count */
- -1449, /* 119.98 kPa 2016 count */
- -1453, /* 120.04 kPa 2017 count */
- -1457, /* 120.09 kPa 2018 count */
- -1461, /* 120.15 kPa 2019 count */
- -1465, /* 120.20 kPa 2020 count */
- -1469, /* 120.26 kPa 2021 count */
- -1472, /* 120.31 kPa 2022 count */
- -1476, /* 120.36 kPa 2023 count */
- -1480, /* 120.42 kPa 2024 count */
- -1484, /* 120.47 kPa 2025 count */
- -1488, /* 120.53 kPa 2026 count */
- -1492, /* 120.58 kPa 2027 count */
- -1496, /* 120.64 kPa 2028 count */
- -1500, /* 120.69 kPa 2029 count */
- -1504, /* 120.74 kPa 2030 count */
- -1508, /* 120.80 kPa 2031 count */
- -1512, /* 120.85 kPa 2032 count */
- -1516, /* 120.91 kPa 2033 count */
- -1520, /* 120.96 kPa 2034 count */
- -1523, /* 121.02 kPa 2035 count */
- -1527, /* 121.07 kPa 2036 count */
- -1531, /* 121.12 kPa 2037 count */
- -1535, /* 121.18 kPa 2038 count */
- -1539, /* 121.23 kPa 2039 count */
- -1543, /* 121.29 kPa 2040 count */
- -1547, /* 121.34 kPa 2041 count */
- -1551, /* 121.40 kPa 2042 count */
- -1555, /* 121.45 kPa 2043 count */
- -1559, /* 121.50 kPa 2044 count */
- -1562, /* 121.56 kPa 2045 count */
- -1566, /* 121.61 kPa 2046 count */
- -1570, /* 121.67 kPa 2047 count */
+++ /dev/null
-#!/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);
-}
-
-string manufacturer = "altusmetrum.org";
-string product = "TeleMetrum";
-string version = "0.0";
-int serial = 1;
-int user_argind = 0;
-
-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 = &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_string(version, "iVersion");
-}
-
-main();
+++ /dev/null
-/*
- * 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 "cc1111.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 0x80
-#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) */
- uint8_t stack_count; /* amount of saved stack */
- uint8_t task_id; /* index in the task array */
- __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 */
-void
-ao_sleep(__xdata void *wchan);
-
-/* Wake all tasks sleeping on wchan */
-void
-ao_wakeup(__xdata void *wchan);
-
-/* 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;
-
-/* 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 */
-
-/* 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_MS_TO_TICKS(ms) ((ms) / 10)
-#define AO_SEC_TO_TICKS(s) ((s) * 100)
-
-/* 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);
-
-/*
- * ao_adc.c
- */
-
-#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 */
-};
-
-/*
- * 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;
-
-/* 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 */
-#if !AO_NO_ADC_ISR
-void
-ao_adc_isr(void) interrupt 1;
-#endif
-
-/* Initialize the A/D converter */
-void
-ao_adc_init(void);
-
-/*
- * 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
-#define AO_LED_GREEN 1
-#define AO_LED_RED 2
-
-/* 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_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);
-
-/* Flush the USB output queue */
-void
-ao_usb_flush(void);
-
-/* USB interrupt handler */
-void
-ao_usb_isr(void) interrupt 6;
-
-/* 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 __xdata uint16_t ao_cmd_lex_i;
-extern __xdata char ao_cmd_lex_c;
-extern __xdata 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);
-
-struct ao_cmds {
- char cmd;
- void (*func)(void);
- const char *help;
-};
-
-void
-ao_cmd_register(__code struct ao_cmds *cmds);
-
-void
-ao_cmd_init(void);
-
-/*
- * ao_dma.c
- */
-
-/* Allocate a DMA channel. the 'done' parameter will be set to 1
- * 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;
-
-/*
- * ao_ee.c
- */
-
-/*
- * We reserve the last block on the device for
- * configuration space. Writes and reads in this
- * area return errors.
- */
-
-#define AO_EE_BLOCK_SIZE ((uint16_t) (256))
-#define AO_EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024)
-#define AO_EE_DATA_SIZE (AO_EE_DEVICE_SIZE - (uint32_t) AO_EE_BLOCK_SIZE)
-#define AO_EE_CONFIG_BLOCK ((uint16_t) (AO_EE_DATA_SIZE / AO_EE_BLOCK_SIZE))
-
-void
-ao_ee_flush(void) __reentrant;
-
-/* Write to the eeprom */
-uint8_t
-ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant;
-
-/* Read from the eeprom */
-uint8_t
-ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant;
-
-/* Write the config block (at the end of the eeprom) */
-uint8_t
-ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant;
-
-/* Read the config block (at the end of the eeprom) */
-uint8_t
-ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant;
-
-/* Initialize the EEPROM code */
-void
-ao_ee_init(void);
-
-/*
- * ao_log.c
- */
-
-/* Structure containing GPS position, either lat or lon */
-
-struct ao_gps_pos {
- uint8_t degrees;
- uint8_t minutes;
- uint16_t minutes_fraction; /* in units of 1/10000 minutes */
-};
-
-/*
- * 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_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;
- struct ao_gps_pos gps_latitude;
- struct ao_gps_pos gps_longitude;
- struct {
- int16_t altitude;
- uint16_t unused;
- } gps_altitude;
- struct {
- uint16_t d0;
- uint16_t d1;
- } anon;
- } u;
-};
-
-/* Write a record to the eeprom log */
-void
-ao_log_data(struct ao_log_record *log);
-
-/* Flush the log */
-void
-ao_log_flush(void);
-
-/* Log dumping API:
- * ao_log_dump_first() - get first log record
- * ao_log_dump_next() - get next log record
- */
-extern __xdata struct ao_log_record ao_log_dump;
-
-/* Retrieve first log record for the current flight */
-uint8_t
-ao_log_dump_first(void);
-
-/* return next log record for the current flight */
-uint8_t
-ao_log_dump_next(void);
-
-/* Logging thread main routine */
-void
-ao_log(void);
-
-/* 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);
-
-/*
- * ao_flight.c
- */
-
-enum ao_flight_state {
- ao_flight_startup = 0,
- ao_flight_idle = 1,
- ao_flight_launchpad = 2,
- ao_flight_boost = 3,
- ao_flight_coast = 4,
- ao_flight_apogee = 5,
- ao_flight_drogue = 6,
- ao_flight_main = 7,
- ao_flight_landed = 8,
- ao_flight_invalid = 9
-};
-
-extern __xdata struct ao_adc ao_flight_data;
-extern __pdata enum ao_flight_state ao_flight_state;
-extern __pdata uint16_t ao_flight_tick;
-extern __pdata int16_t ao_flight_accel;
-extern __pdata int16_t ao_flight_pres;
-extern __pdata int32_t ao_flight_vel;
-extern __pdata int16_t ao_ground_pres;
-extern __pdata int16_t ao_ground_accel;
-extern __pdata int16_t ao_min_pres;
-extern __pdata uint16_t ao_launch_time;
-
-/* Flight thread */
-void
-ao_flight(void);
-
-/* Initialize flight thread */
-void
-ao_flight_init(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
- */
-
-#if !AO_NO_SERIAL_ISR
-void
-ao_serial_rx1_isr(void) interrupt 3;
-
-void
-ao_serial_tx1_isr(void) interrupt 14;
-#endif
-
-char
-ao_serial_getchar(void) __critical;
-
-void
-ao_serial_putchar(char c) __critical;
-
-void
-ao_serial_init(void);
-
-/*
- * 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_LONGITUDE_MASK (1 << 5)
-#define AO_GPS_LONGITUDE_EAST (0 << 5)
-#define AO_GPS_LONGITUDE_WEST (1 << 5)
-
-#define AO_GPS_LATITUDE_MASK (1 << 6)
-#define AO_GPS_LATITUDE_NORTH (0 << 6)
-#define AO_GPS_LATITUDE_SOUTH (1 << 6)
-
-struct ao_gps_data {
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
- uint8_t flags;
- struct ao_gps_pos latitude;
- struct ao_gps_pos longitude;
- int16_t altitude;
-};
-
-extern __xdata uint8_t ao_gps_mutex;
-extern __xdata struct ao_gps_data ao_gps_data;
-
-void
-ao_gps(void);
-
-void
-ao_gps_print(__xdata struct ao_gps_data *gps_data);
-
-void
-ao_gps_init(void);
-
-/*
- * ao_gps_report.c
- */
-
-void
-ao_gps_report(void);
-
-void
-ao_gps_report_init(void);
-
-/*
- * ao_telemetry.c
- */
-
-#define AO_MAX_CALLSIGN 8
-
-struct ao_telemetry {
- uint8_t addr;
- uint8_t flight_state;
- int16_t flight_accel;
- int16_t ground_accel;
- int32_t flight_vel;
- int16_t flight_pres;
- int16_t ground_pres;
- struct ao_adc adc;
- struct ao_gps_data gps;
- char callsign[AO_MAX_CALLSIGN];
-};
-
-/* 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(50)
-#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000)
-
-void
-ao_telemetry_set_interval(uint16_t interval);
-
-void
-ao_telemetry_init(void);
-
-/*
- * ao_radio.c
- */
-
-void
-ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant;
-
-struct ao_radio_recv {
- struct ao_telemetry telemetry;
- int8_t rssi;
- uint8_t status;
-};
-
-void
-ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant;
-
-void
-ao_radio_init(void);
-
-/*
- * ao_monitor.c
- */
-
-extern const char const * const ao_state_names[];
-
-void
-ao_monitor(void);
-
-void
-ao_set_monitor(uint8_t monitoring);
-
-void
-ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant;
-
-/*
- * ao_stdio.c
- */
-
-void
-flush(void);
-
-/*
- * 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_igniter_init(void);
-
-/*
- * ao_config.c
- */
-
-#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 0
-
-struct ao_config {
- uint8_t major;
- uint8_t minor;
- uint16_t main_deploy;
- int16_t accel_zero_g;
- uint8_t radio_channel;
- char callsign[AO_MAX_CALLSIGN + 1];
-};
-
-extern __xdata struct ao_config ao_config;
-
-void
-ao_config_get(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 uint8_t ao_usb_descriptors [];
-extern const uint16_t ao_serial_number;
-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 32
-#define AO_PACKET_WIN 256
-
-#define AO_PACKET_FIN (1 << 0)
-#define AO_PACKET_SYN (1 << 1)
-#define AO_PACKET_RST (1 << 2)
-#define AO_PACKET_ACK (1 << 3)
-
-struct ao_packet {
- uint8_t addr;
- uint8_t flags;
- uint16_t seq;
- uint16_t ack;
- uint16_t window;
- uint8_t len;
- uint8_t d[AO_PACKET_MAX];
-};
-
-uint8_t
-ao_packet_connect(uint8_t dest);
-
-uint8_t
-ao_packet_accept(void);
-
-int
-ao_packet_send(uint8_t *data, int len);
-
-int
-ao_packet_recv(uint8_t *data, int len);
-
-void
-ao_packet_init(void);
-
-#endif /* _AO_H_ */
+++ /dev/null
-/*
- * 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;
-
-void
-ao_adc_poll(void)
-{
- ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0;
-}
-
-void
-ao_adc_sleep(void)
-{
- ao_sleep(&ao_adc_ring);
-}
-
-void
-ao_adc_get(__xdata struct ao_adc *packet)
-{
- uint8_t i = ao_adc_ring_prev(ao_adc_head);
- 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;
- a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence);
- a[0] = ADCL;
- a[1] = ADCH;
- if (sequence < 5) {
- /* start next channel conversion */
- ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1);
- } 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(ao_adc_ring);
- }
-}
-
-static void
-ao_adc_dump(void)
-{
- __xdata struct ao_adc packet;
- ao_adc_get(&packet);
- printf("tick: %5u accel: %4d pres: %4d temp: %4d batt: %4d drogue: %4d main: %4d\n",
- packet.tick, packet.accel >> 4, packet.pres >> 4, packet.temp >> 4,
- packet.v_batt >> 4, packet.sense_d >> 4, packet.sense_m >> 4);
-}
-
-__code struct ao_cmds ao_adc_cmds[] = {
- { 'a', ao_adc_dump, "a Display current ADC values" },
- { 0, ao_adc_dump, NULL },
-};
-
-void
-ao_adc_init(void)
-{
- ADCCFG = ((1 << 0) | /* acceleration */
- (1 << 1) | /* pressure */
- (1 << 2) | /* temperature */
- (1 << 3) | /* battery voltage */
- (1 << 4) | /* drogue sense */
- (1 << 5)); /* main sense */
-
- /* enable interrupts */
- ADCIF = 0;
- IEN0 |= IEN0_ADCIE;
- ao_cmd_register(&ao_adc_cmds[0]);
-}
-
+++ /dev/null
-/*
- * 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)
-{
-}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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 uint16_t ao_cmd_lex_i;
-__xdata char ao_cmd_lex_c;
-__xdata enum ao_cmd_status ao_cmd_status;
-static __xdata uint8_t lex_echo;
-
-#define CMD_LEN 32
-
-static __xdata char cmd_line[CMD_LEN];
-static __xdata uint8_t cmd_len;
-static __xdata uint8_t cmd_i;
-
-static void
-put_string(char *s)
-{
- __xdata char c;
- while (c = *s++)
- putchar(c);
-}
-
-static void
-readline(void)
-{
- __xdata char c;
- if (lex_echo)
- put_string("> ");
- cmd_len = 0;
- for (;;) {
- flush();
- c = getchar();
- /* backspace/delete */
- if (c == '\010' || c == '\177') {
- if (cmd_len != 0) {
- if (lex_echo)
- put_string("\010 \010");
- --cmd_len;
- }
- continue;
- }
-
- /* ^U */
- if (c == '\025') {
- while (cmd_len != 0) {
- if (lex_echo)
- put_string("\010 \010");
- --cmd_len;
- }
- continue;
- }
-
- /* map CR to NL */
- if (c == '\r')
- c = '\n';
-
- if (c == '\n') {
- if (lex_echo)
- putchar('\n');
- break;
- }
-
- if (cmd_len >= CMD_LEN - 2) {
- if (lex_echo)
- putchar('\007');
- continue;
- }
- cmd_line[cmd_len++] = c;
- if (lex_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)
-{
- int8_t i;
- for (i = 3; i >= 0; i--)
- putnibble((v >> (i << 2)) & 0xf);
-}
-
-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)
-{
- __xdata uint8_t r = ao_cmd_lex_error;
-
- ao_cmd_lex_i = 0;
- ao_cmd_white();
- for(;;) {
- if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
- ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - '0');
- else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
- ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'a' + 10);
- else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
- ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'A' + 10);
- else
- break;
- r = ao_cmd_success;
- ao_cmd_lex();
- }
- if (r != ao_cmd_success)
- ao_cmd_status = r;
-}
-
-void
-ao_cmd_decimal(void)
-{
- __xdata uint8_t r = ao_cmd_lex_error;
-
- ao_cmd_lex_i = 0;
- ao_cmd_white();
- for(;;) {
- if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
- ao_cmd_lex_i = (ao_cmd_lex_i * 10) + (ao_cmd_lex_c - '0');
- else
- break;
- r = ao_cmd_success;
- ao_cmd_lex();
- }
- if (r != ao_cmd_success)
- ao_cmd_status = r;
-}
-
-static void
-eol(void)
-{
- while (ao_cmd_lex_c != '\n')
- ao_cmd_lex();
-}
-
-static void
-dump(void)
-{
- __xdata uint16_t c;
- __xdata uint8_t * __xdata start, * __xdata end;
-
- ao_cmd_hex();
- start = (uint8_t __xdata *) ao_cmd_lex_i;
- ao_cmd_hex();
- end = (uint8_t __xdata *) ao_cmd_lex_i;
- if (ao_cmd_status != ao_cmd_success)
- return;
- c = 0;
- while (start <= end) {
- if ((c & 7) == 0) {
- if (c)
- putchar('\n');
- ao_cmd_put16((uint16_t) start);
- }
- putchar(' ');
- ao_cmd_put8(*start);
- ++c;
- start++;
- }
- putchar('\n');
-}
-
-static void
-echo(void)
-{
- ao_cmd_hex();
- lex_echo = ao_cmd_lex_i != 0;
-}
-
-static void
-version(void)
-{
- printf("manufacturer %s\n", ao_manufacturer);
- printf("product %s\n", ao_product);
- printf("serial-number %u\n", ao_serial_number);
- printf("software-version %s\n", ao_version);
-}
-
-static const char help_txt[] = "All numbers are in hex";
-
-#define NUM_CMDS 11
-
-static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]);
-static __xdata uint8_t ao_ncmds;
-
-static void
-help(void)
-{
- __xdata uint8_t cmds;
- __xdata uint8_t cmd;
- __code struct ao_cmds * __xdata cs;
- puts(help_txt);
- for (cmds = 0; cmds < ao_ncmds; cmds++) {
- cs = ao_cmds[cmds];
- for (cmd = 0; cs[cmd].cmd != '\0'; cmd++)
- puts(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 *parameters)
-{
- __xdata char c;
- __xdata uint8_t cmd, cmds;
- __code struct ao_cmds * __xdata cs;
- void (*__xdata func)(void);
- (void) parameters;
-
- lex_echo = 1;
- 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].cmd != '\0'; cmd++)
- if (cs[cmd].cmd == 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, "? Print this message" },
- { 'T', ao_task_info, "T Show task states" },
- { 'E', echo, "E <0 off, 1 on> Set command echo mode" },
- { 'd', dump, "d <start> <end> Dump memory" },
- { 'v', version, "v Show version" },
- { 0, help, NULL },
-};
-
-void
-ao_cmd_init(void)
-{
- ao_cmd_register(&ao_base_cmds[0]);
- ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
-}
+++ /dev/null
-/*
- * 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;
-__xdata uint8_t ao_config_loaded;
-__xdata 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 "KD7SQG"
-#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
-
-static void
-_ao_config_put(void)
-{
- ao_ee_write_config((uint8_t *) &ao_config, sizeof (ao_config));
-}
-
-static void
-_ao_config_get(void)
-{
- if (ao_config_loaded)
- return;
- ao_ee_read_config((uint8_t *) &ao_config, sizeof (ao_config));
- if (ao_config.major != AO_CONFIG_MAJOR) {
- ao_config.major = AO_CONFIG_MAJOR;
- ao_config.minor = AO_CONFIG_MINOR;
- ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
- ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL;
- ao_config.accel_zero_g = AO_CONFIG_DEFAULT_ACCEL_ZERO_G;
- memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
- memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
- sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
- ao_config_dirty = 1;
- }
- /* deal with minor version issues here, at 0 we haven't any */
- ao_config_loaded = 1;
-}
-
-void
-ao_config_get(void)
-{
- ao_mutex_get(&ao_config_mutex);
- _ao_config_get();
- 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;
- char callsign[AO_MAX_CALLSIGN + 1];
-
- 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_mutex_get(&ao_config_mutex);
- _ao_config_get();
- while (c < AO_MAX_CALLSIGN + 1)
- callsign[c++] = '\0';
- memcpy(&ao_config.callsign, &callsign,
- AO_MAX_CALLSIGN + 1);
- ao_config_dirty = 1;
- ao_mutex_put(&ao_config_mutex);
- ao_config_callsign_show();
-}
-
-void
-ao_config_radio_channel_show(void) __reentrant
-{
- uint32_t freq = 434550L + ao_config.radio_channel * 100L;
- uint16_t mhz = freq / 1000L;
- uint16_t khz = freq % 1000L;
-
- printf("Radio channel: %d (%d.%03dMHz)\n",
- ao_config.radio_channel, mhz, khz);
-}
-
-void
-ao_config_radio_channel_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- ao_mutex_get(&ao_config_mutex);
- _ao_config_get();
- ao_config.radio_channel = ao_cmd_lex_i;
- ao_config_dirty = 1;
- ao_mutex_put(&ao_config_mutex);
- ao_config_radio_channel_show();
-}
-
-void
-ao_config_main_deploy_show(void) __reentrant
-{
- printf("Main deploy set to %d meters (%d feet)\n",
- ao_config.main_deploy,
- (int16_t) ((int32_t) ao_config.main_deploy * 328 / 100));
-}
-
-void
-ao_config_main_deploy_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- ao_mutex_get(&ao_config_mutex);
- _ao_config_get();
- ao_config.main_deploy = ao_cmd_lex_i;
- ao_config_dirty = 1;
- ao_mutex_put(&ao_config_mutex);
- ao_config_main_deploy_show();
-}
-
-void
-ao_config_accel_zero_g_show(void) __reentrant
-{
- printf("Accel zero g point set to %d\n",
- ao_config.accel_zero_g);
-}
-
-#define ZERO_G_SAMPLES 1000
-
-static int16_t
-ao_config_accel_zero_g_auto(void) __reentrant
-{
- uint16_t i;
- int32_t accel_total;
- uint8_t cal_adc_ring;
-
- puts("Calibrating accelerometer..."); flush();
- i = ZERO_G_SAMPLES;
- accel_total = 0;
- cal_adc_ring = ao_adc_head;
- while (i) {
- ao_sleep(&ao_adc_ring);
- while (i && cal_adc_ring != ao_adc_head) {
- accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel;
- cal_adc_ring = ao_adc_ring_next(cal_adc_ring);
- i--;
- }
- }
- return (int16_t) (accel_total / ZERO_G_SAMPLES);
-}
-void
-ao_config_accel_zero_g_set(void) __reentrant
-{
- ao_cmd_decimal();
- if (ao_cmd_status != ao_cmd_success)
- return;
- if (ao_cmd_lex_i == 0)
- ao_cmd_lex_i = ao_config_accel_zero_g_auto();
- ao_mutex_get(&ao_config_mutex);
- _ao_config_get();
- ao_config.accel_zero_g = ao_cmd_lex_i;
- ao_config_dirty = 1;
- ao_mutex_put(&ao_config_mutex);
- ao_config_accel_zero_g_show();
-}
-
-struct ao_config_var {
- char cmd;
- void (*set)(void) __reentrant;
- void (*show)(void) __reentrant;
- const char *help;
-};
-
-void
-ao_config_help(void) __reentrant;
-
-void
-ao_config_show(void) __reentrant;
-
-void
-ao_config_write(void) __reentrant;
-
-__code struct ao_config_var ao_config_vars[] = {
- { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show,
- "m <meters> Set height above launch for main deploy (in meters)" },
- { 'a', ao_config_accel_zero_g_set, ao_config_accel_zero_g_show,
- "a <value> Set accelerometer zero g point (0 for auto)" },
- { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show,
- "r <channel> Set radio channel (freq = 434.550 + channel * .1)" },
- { 'c', ao_config_callsign_set, ao_config_callsign_show,
- "c <call> Set callsign broadcast in each packet (8 char max)" },
- { 's', ao_config_show, ao_config_show,
- "s Show current config values" },
- { 'w', ao_config_write, ao_config_write,
- "w Write current values to eeprom" },
- { '?', ao_config_help, ao_config_help,
- "? Show available config variables" },
- { 0, ao_config_main_deploy_set, ao_config_main_deploy_show,
- NULL },
-};
-
-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].cmd != '\0'; cmd++)
- if (ao_config_vars[cmd].cmd == c) {
- func = ao_config_vars[cmd].set;
- break;
- }
- if (func)
- (*func)();
- else
- ao_cmd_status = ao_cmd_syntax_error;
-}
-
-void
-ao_config_help(void) __reentrant
-{
- uint8_t cmd;
- for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++)
- puts (ao_config_vars[cmd].help);
-}
-
-void
-ao_config_show(void) __reentrant
-{
- uint8_t cmd;
- for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++)
- if (ao_config_vars[cmd].show != ao_config_vars[cmd].set)
- (*ao_config_vars[cmd].show)();
-}
-
-void
-ao_config_write(void) __reentrant
-{
- ao_mutex_get(&ao_config_mutex);
- if (ao_config_dirty) {
- _ao_config_put();
- ao_config_dirty = 0;
- printf("Saved\n");
- }
- ao_mutex_put(&ao_config_mutex);
-}
-
-__code struct ao_cmds ao_config_cmds[] = {
- { 'c', ao_config_set, "c <var> <value> Set config variable (? for help, s to show)" },
- { '\0', ao_config_set, NULL },
-};
-
-void
-ao_config_init(void)
-{
- ao_cmd_register(&ao_config_cmds[0]);
-}
+++ /dev/null
-/*
- * 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 const int16_t altitude_table[2048] = {
-#include "altitude.h"
-};
-
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant
-{
- pres = pres >> 4;
- if (pres < 0) pres = 0;
- if (pres > 2047) pres = 2047;
- return altitude_table[pres];
-}
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
-{
- int16_t pres;
-
- for (pres = 0; pres < 2047; pres++)
- if (altitude_table[pres] <= alt)
- break;
- return pres << 4;
-}
-
-static __xdata uint8_t ao_temp_mutex;
-
-int16_t
-ao_temp_to_dC(int16_t temp) __reentrant
-{
- int16_t ret;
-
- ao_mutex_get(&ao_temp_mutex);
- ret = (int16_t) ((temp >> 4) * 3300L / 2047L) - 500;
- ao_mutex_put(&ao_temp_mutex);
- return ret;
-}
+++ /dev/null
-/*
- * 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 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)
-
-static void
-ao_dbg_send_bits(uint8_t msk, uint8_t val)
-{
- P0 = (P0 & ~msk) | (val & msk);
- _asm
- nop
- nop
- _endasm;
-}
-
-void
-ao_dbg_send_byte(uint8_t byte)
-{
- __xdata uint8_t b, d;
-
- P0 |= DBG_DATA;
- P0DIR |= 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);
- }
- P0DIR &= ~DBG_DATA;
-}
-
-uint8_t
-ao_dbg_recv_byte(void)
-{
- __xdata 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
-
-__xdata uint8_t save_acc;
-__xdata uint8_t save_psw;
-__xdata uint8_t save_dpl0;
-__xdata uint8_t save_dph0;
-__xdata uint8_t save_dpl1;
-__xdata 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)
-{
- /* Disable peripheral use of P0 */
- ADCCFG = 0;
- P0SEL = 0;
-
-
- /* make P0_4 tri-state */
- P0INP = DBG_DATA;
- P2INP &= ~(P2INP_PDUP0_PULL_DOWN);
-
- /* Raise RESET_N and CLOCK */
- P0 = DBG_RESET_N | DBG_CLOCK;
-
- /* RESET_N and CLOCK are outputs now */
- P0DIR = DBG_RESET_N | DBG_CLOCK;
-}
-
-static void
-ao_dbg_long_delay(void)
-{
- uint8_t n;
-
- for (n = 0; n < 20; n++)
- _asm nop _endasm;
-}
-
-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_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| 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_dbg_long_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_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| 0 );
- 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();
-}
-
-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)
-{
- __xdata uint16_t count;
- __xdata uint16_t i;
- __xdata 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)
-{
- __xdata 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)
-{
- __xdata uint16_t count;
- __xdata uint16_t addr;
- __xdata uint8_t b;
- __xdata 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)
-{
- __xdata uint16_t count;
- __xdata uint16_t addr;
- __xdata 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] = {
- { 'D', debug_enable, "D Enable debug mode" },
- { 'G', debug_get, "G <count> Get data from debug port" },
- { 'I', debug_input, "I <count> <addr> Input <count> bytes to target at <addr>" },
- { 'O', debug_output, "O <count> <addr> Output <count> bytes to target at <addr>" },
- { 'P', debug_put, "P <byte> ... Put data to debug port" },
- { 'R', debug_reset, "R Reset target" },
- { 0, debug_reset, 0 },
-};
-
-void
-ao_dbg_init(void)
-{
- ao_cmd_register(&ao_dbg_cmds[0]);
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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"
-
-/*
- * Using SPI on USART 0, with P1_2 as the chip select
- */
-
-#define EE_CS P1_2
-#define EE_CS_INDEX 2
-
-__xdata uint8_t ao_ee_dma_in_done;
-__xdata uint8_t ao_ee_dma_out_done;
-__xdata uint8_t ao_ee_mutex;
-
-uint8_t ao_ee_dma_out_id;
-uint8_t ao_ee_dma_in_id;
-
-static __xdata uint8_t ao_ee_const = 0xff;
-
-#define ao_ee_delay() do { \
- _asm nop _endasm; \
- _asm nop _endasm; \
- _asm nop _endasm; \
-} while(0)
-
-void ao_ee_cs_low(void)
-{
- ao_ee_delay();
- EE_CS = 0;
- ao_ee_delay();
-}
-
-void ao_ee_cs_high(void)
-{
- ao_ee_delay();
- EE_CS = 1;
- ao_ee_delay();
-}
-
-/* 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
- */
-static void
-ao_ee_send(void __xdata *block, uint16_t len)
-{
- ao_dma_set_transfer(ao_ee_dma_in_id,
- &U0DBUFXADDR,
- &ao_ee_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_ee_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_ee_dma_in_id);
- ao_dma_start(ao_ee_dma_out_id);
- ao_dma_trigger(ao_ee_dma_out_id);
- __critical while (!ao_ee_dma_in_done)
- ao_sleep(&ao_ee_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.
- */
-static void
-ao_ee_recv(void __xdata *block, uint16_t len)
-{
- ao_dma_set_transfer(ao_ee_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_ee_dma_out_id,
- &ao_ee_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_ee_dma_in_id);
- ao_dma_start(ao_ee_dma_out_id);
- ao_dma_trigger(ao_ee_dma_out_id);
- __critical while (!ao_ee_dma_in_done)
- ao_sleep(&ao_ee_dma_in_done);
-}
-
-#define EE_BLOCK 256
-
-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_ee_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_ee_send(&ao_ee_instruction, 1);
- ao_ee_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_ee_send(&ao_ee_instruction, 2);
- ao_ee_cs_high();
-}
-
-#define EE_BLOCK_NONE 0xffff
-
-static __xdata uint8_t ao_ee_data[EE_BLOCK];
-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_ee_send(&ao_ee_instruction, 4);
- ao_ee_send(ao_ee_data, EE_BLOCK);
- 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_ee_send(&ao_ee_instruction, 4);
- ao_ee_recv(ao_ee_data, EE_BLOCK);
- 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_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant
-{
- uint16_t block;
- uint16_t this_len;
- uint8_t this_off;
-
- if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE)
- return 0;
- while (len) {
-
- /* Compute portion of transfer within
- * a single block
- */
- this_off = pos;
- this_len = 256 - (uint16_t) this_off;
- block = (uint16_t) (pos >> 8);
- if (this_len > len)
- this_len = len;
- if (this_len & 0xff00)
- ao_panic(AO_PANIC_EE);
-
- /* Transfer the data */
- ao_mutex_get(&ao_ee_mutex); {
- if (this_len != 256)
- ao_ee_fill(block);
- else {
- ao_ee_flush_internal();
- ao_ee_block = block;
- }
- memcpy(ao_ee_data + this_off, buf, this_len);
- ao_ee_block_dirty = 1;
- } ao_mutex_put(&ao_ee_mutex);
-
- /* See how much is left */
- buf += this_len;
- len -= this_len;
- }
- return 1;
-}
-
-uint8_t
-ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant
-{
- uint16_t block;
- uint16_t this_len;
- uint8_t this_off;
-
- if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE)
- return 0;
- while (len) {
-
- /* Compute portion of transfer within
- * a single block
- */
- this_off = pos;
- this_len = 256 - (uint16_t) this_off;
- block = (uint16_t) (pos >> 8);
- if (this_len > len)
- this_len = len;
- if (this_len & 0xff00)
- ao_panic(AO_PANIC_EE);
-
- /* Transfer the data */
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_fill(block);
- memcpy(buf, ao_ee_data + this_off, this_len);
- } ao_mutex_put(&ao_ee_mutex);
-
- /* See how much is left */
- buf += this_len;
- len -= this_len;
- }
- return 1;
-}
-
-void
-ao_ee_flush(void) __reentrant
-{
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_flush_internal();
- } ao_mutex_put(&ao_ee_mutex);
-}
-
-/*
- * Read/write the config block, which is in
- * the last block of the ao_eeprom
- */
-uint8_t
-ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
-{
- if (len > AO_EE_BLOCK_SIZE)
- return 0;
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_fill(AO_EE_CONFIG_BLOCK);
- memcpy(ao_ee_data, buf, len);
- ao_ee_block_dirty = 1;
- ao_ee_flush_internal();
- } ao_mutex_put(&ao_ee_mutex);
- return 1;
-}
-
-uint8_t
-ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
-{
- if (len > AO_EE_BLOCK_SIZE)
- return 0;
- ao_mutex_get(&ao_ee_mutex); {
- ao_ee_fill(AO_EE_CONFIG_BLOCK);
- memcpy(buf, ao_ee_data, len);
- } ao_mutex_put(&ao_ee_mutex);
- return 1;
-}
-
-static void
-ee_dump(void)
-{
- __xdata uint8_t b;
- __xdata uint16_t block;
- __xdata uint8_t i;
-
- ao_cmd_hex();
- block = ao_cmd_lex_i;
- if (ao_cmd_status != ao_cmd_success)
- return;
- i = 0;
- do {
- if ((i & 7) == 0) {
- if (i)
- putchar('\n');
- ao_cmd_put16((uint16_t) i);
- }
- putchar(' ');
- ao_ee_read(((uint32_t) block << 8) | i, &b, 1);
- ao_cmd_put8(b);
- ++i;
- } while (i != 0);
- putchar('\n');
-}
-
-static void
-ee_store(void)
-{
- __xdata uint16_t block;
- __xdata uint8_t i;
- __xdata uint16_t len;
- __xdata uint8_t b;
- __xdata 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_ee_write(addr, &b, 1);
- addr++;
- }
- ao_ee_flush();
-}
-
-__code struct ao_cmds ao_ee_cmds[] = {
- { 'e', ee_dump, "e <block> Dump a block of EEPROM data" },
- { 'w', ee_store, "w <block> <start> <len> <data> ... Write data to EEPROM" },
- { 0, ee_store, NULL },
-};
-
-/*
- * To initialize the chip, set up the CS line and
- * the SPI interface
- */
-void
-ao_ee_init(void)
-{
- /* set up CS */
- EE_CS = 1;
- P1DIR |= (1 << EE_CS_INDEX);
- P1SEL &= ~(1 << EE_CS_INDEX);
-
- /* 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_ee_dma_out_id = ao_dma_alloc(&ao_ee_dma_out_done);
-
- /* Set up IN DMA */
- ao_ee_dma_in_id = ao_dma_alloc(&ao_ee_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,
- * while the 25LC1024 is limited to 20MHz. So,
- * use the 3MHz clock (BAUD_E 17, BAUD_M 0)
- */
- U0BAUD = 0;
- U0GCR = (UxGCR_CPOL_NEGATIVE |
- UxGCR_CPHA_FIRST_EDGE |
- UxGCR_ORDER_MSB |
- (17 << UxGCR_BAUD_E_SHIFT));
- ao_cmd_register(&ao_ee_cmds[0]);
-}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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
-
-/* Main flight thread. */
-
-__pdata enum ao_flight_state ao_flight_state; /* current flight state */
-__pdata uint16_t ao_flight_tick; /* time of last data */
-__pdata uint16_t ao_flight_prev_tick; /* time of previous data */
-__pdata int16_t ao_flight_accel; /* filtered acceleration */
-__pdata int16_t ao_flight_pres; /* filtered pressure */
-__pdata int16_t ao_ground_pres; /* startup pressure */
-__pdata int16_t ao_ground_accel; /* startup acceleration */
-__pdata int16_t ao_min_pres; /* minimum recorded pressure */
-__pdata uint16_t ao_launch_tick; /* time of launch detect */
-__pdata int16_t ao_main_pres; /* pressure to eject main */
-
-/*
- * track min/max data over a long interval to detect
- * resting
- */
-__pdata uint16_t ao_interval_end;
-__pdata int16_t ao_interval_cur_min_accel;
-__pdata int16_t ao_interval_cur_max_accel;
-__pdata int16_t ao_interval_cur_min_pres;
-__pdata int16_t ao_interval_cur_max_pres;
-__pdata int16_t ao_interval_min_accel;
-__pdata int16_t ao_interval_max_accel;
-__pdata int16_t ao_interval_min_pres;
-__pdata int16_t ao_interval_max_pres;
-
-__data uint8_t ao_flight_adc;
-__pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres;
-
-/* 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
-/* convert m/s to velocity count */
-#define VEL_MPS_TO_COUNT(mps) ((int32_t) (((mps) / GRAVITY) * ACCEL_G * 100))
-
-#define ACCEL_G 265
-#define ACCEL_ZERO_G 16000
-#define ACCEL_NOSE_UP (ACCEL_G * 2 /3)
-#define ACCEL_BOOST ACCEL_G * 2
-#define ACCEL_INT_LAND (ACCEL_G / 10)
-#define ACCEL_VEL_LAND VEL_MPS_TO_COUNT(10)
-#define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200)
-#define ACCEL_VEL_APOGEE VEL_MPS_TO_COUNT(2)
-#define ACCEL_VEL_MAIN VEL_MPS_TO_COUNT(100)
-#define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5)
-
-/*
- * 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
- */
-
-#define BARO_kPa 268
-#define BARO_LAUNCH (BARO_kPa / 5) /* .2kPa, or about 20m */
-#define BARO_APOGEE (BARO_kPa / 10) /* .1kPa, or about 10m */
-#define BARO_COAST (BARO_kPa * 5) /* 5kpa, or about 500m */
-#define BARO_MAIN (BARO_kPa) /* 1kPa, or about 100m */
-#define BARO_INT_LAND (BARO_kPa / 20) /* .05kPa, or about 5m */
-#define BARO_LAND (BARO_kPa * 10) /* 10kPa or about 1000m */
-
-/* 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)
-
-/* This value is scaled in a weird way. It's a running total of accelerometer
- * readings minus the ground accelerometer reading. That means it measures
- * velocity, and quite accurately too. As it gets updated 100 times a second,
- * it's scaled by 100
- */
-__pdata int32_t ao_flight_vel;
-__pdata int32_t ao_min_vel;
-__pdata int32_t ao_old_vel;
-__pdata int16_t ao_old_vel_tick;
-__xdata int32_t ao_raw_accel_sum, ao_raw_pres_sum;
-
-/* 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(20)
-
-#define abs(a) ((a) < 0 ? -(a) : (a))
-
-void
-ao_flight(void)
-{
- __pdata static uint16_t nsamples = 0;
-
- ao_flight_adc = ao_adc_head;
- ao_raw_accel_prev = 0;
- ao_raw_accel = 0;
- ao_raw_pres = 0;
- ao_flight_tick = 0;
- for (;;) {
- ao_sleep(&ao_adc_ring);
- while (ao_flight_adc != ao_adc_head) {
- __pdata uint8_t ticks;
- __pdata int16_t ao_vel_change;
- ao_flight_prev_tick = ao_flight_tick;
-
- /* Capture a sample */
- ao_raw_accel = ao_adc_ring[ao_flight_adc].accel;
- ao_raw_pres = ao_adc_ring[ao_flight_adc].pres;
- ao_flight_tick = ao_adc_ring[ao_flight_adc].tick;
-
- ao_flight_accel -= ao_flight_accel >> 4;
- ao_flight_accel += ao_raw_accel >> 4;
- ao_flight_pres -= ao_flight_pres >> 4;
- ao_flight_pres += ao_raw_pres >> 4;
- /* Update velocity
- *
- * The accelerometer is mounted so that
- * acceleration yields negative values
- * while deceleration yields positive values,
- * so subtract instead of add.
- */
- ticks = ao_flight_tick - ao_flight_prev_tick;
- ao_vel_change = (((ao_raw_accel >> 1) + (ao_raw_accel_prev >> 1)) - ao_ground_accel);
- ao_raw_accel_prev = ao_raw_accel;
-
- /* one is a common interval */
- if (ticks == 1)
- ao_flight_vel -= (int32_t) ao_vel_change;
- else
- ao_flight_vel -= (int32_t) ao_vel_change * (int32_t) ticks;
-
- ao_flight_adc = ao_adc_ring_next(ao_flight_adc);
- }
-
- if (ao_flight_pres < ao_min_pres)
- ao_min_pres = ao_flight_pres;
- if (ao_flight_vel >= 0) {
- if (ao_flight_vel < ao_min_vel)
- ao_min_vel = ao_flight_vel;
- } else {
- if (-ao_flight_vel < ao_min_vel)
- ao_min_vel = -ao_flight_vel;
- }
-
- switch (ao_flight_state) {
- case ao_flight_startup:
-
- /* startup state:
- *
- * Collect 1000 samples of acceleration and pressure
- * data and average them to find the resting values
- */
- if (nsamples < 1000) {
- ao_raw_accel_sum += ao_raw_accel;
- ao_raw_pres_sum += ao_raw_pres;
- ++nsamples;
- continue;
- }
- ao_ground_accel = (ao_raw_accel_sum / nsamples);
- ao_ground_pres = (ao_raw_pres_sum / nsamples);
- ao_min_pres = ao_ground_pres;
- ao_config_get();
- ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy);
- ao_flight_vel = 0;
- ao_min_vel = 0;
- ao_old_vel = ao_flight_vel;
- ao_old_vel_tick = ao_flight_tick;
-
- /* Go to launchpad state if the nose is pointing up */
- ao_config_get();
- if (ao_flight_accel < ao_config.accel_zero_g - ACCEL_NOSE_UP) {
-
- /* Disable the USB controller in flight mode
- * to save power
- */
- ao_usb_disable();
-
- /* Turn on telemetry system
- */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
-
- ao_flight_state = ao_flight_launchpad;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- } else {
- ao_flight_state = ao_flight_idle;
-
- /* Turn on the Green LED in idle mode
- */
- ao_led_on(AO_LED_GREEN);
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- /* signal successful initialization by turning off the LED */
- ao_led_off(AO_LED_RED);
- break;
- case ao_flight_launchpad:
-
- /* Trim velocity
- *
- * Once a second, remove any velocity from
- * a second ago
- */
- if ((int16_t) (ao_flight_tick - ao_old_vel_tick) >= AO_SEC_TO_TICKS(1)) {
- ao_old_vel_tick = ao_flight_tick;
- ao_flight_vel -= ao_old_vel;
- ao_old_vel = ao_flight_vel;
- }
- /* pad to boost:
- *
- * accelerometer: > 2g AND velocity > 5m/s
- * OR
- * barometer: > 20m vertical motion
- *
- * The accelerometer should always detect motion before
- * the barometer, but we use both to make sure this
- * transition is detected
- */
- if ((ao_flight_accel < ao_ground_accel - ACCEL_BOOST &&
- ao_flight_vel > ACCEL_VEL_BOOST) ||
- ao_flight_pres < ao_ground_pres - BARO_LAUNCH)
- {
- ao_flight_state = ao_flight_boost;
- ao_launch_tick = ao_flight_tick;
-
- /* start logging data */
- ao_log_start();
-
- /* Increase telemetry rate */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);
-
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- break;
- }
- break;
- case ao_flight_boost:
-
- /* boost to coast:
- *
- * 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_flight_accel > ao_ground_accel + (ACCEL_G >> 2) ||
- (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX)
- {
- ao_flight_state = ao_flight_coast;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- break;
- }
- break;
- case ao_flight_coast:
-
- /* coast to apogee detect:
- *
- * accelerometer: integrated velocity < 200 m/s
- * OR
- * barometer: fall at least 500m from max altitude
- *
- * This extra state is required to avoid mis-detecting
- * apogee due to mach transitions.
- *
- * XXX this is essentially a single-detector test
- * as the 500m altitude change would likely result
- * in a loss of the rocket. More data on precisely
- * how big a pressure change the mach transition
- * generates would be useful here.
- */
- if (ao_flight_vel < ACCEL_VEL_MACH ||
- ao_flight_pres > ao_min_pres + BARO_COAST)
- {
- /* set min velocity to current velocity for
- * apogee detect
- */
- ao_min_vel = abs(ao_flight_vel);
- ao_flight_state = ao_flight_apogee;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
- break;
- case ao_flight_apogee:
-
- /* apogee detect to drogue deploy:
- *
- * accelerometer: abs(velocity) > min_velocity + 2m/s
- * OR
- * barometer: fall at least 10m
- *
- * If the barometer saturates because the flight
- * goes over its measuring range (about 53k'),
- * requiring a 10m fall will avoid prematurely
- * detecting apogee; the accelerometer will take
- * over in that case and the integrated velocity
- * measurement should suffice to find apogee
- */
- if (/* abs(ao_flight_vel) > ao_min_vel + ACCEL_VEL_APOGEE || */
- ao_flight_pres > ao_min_pres + BARO_APOGEE)
- {
- /* ignite the drogue charge */
- ao_ignite(ao_igniter_drogue);
-
- /* slow down the telemetry system */
- ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
-
- /* slow down the ADC sample rate */
- ao_timer_set_adc_interval(10);
-
- /*
- * Start recording min/max accel and pres for a while
- * to figure out when the rocket has landed
- */
- /* Set the 'last' limits to max range to prevent
- * early resting detection
- */
- ao_interval_min_accel = 0;
- ao_interval_max_accel = 0x7fff;
- ao_interval_min_pres = 0;
- ao_interval_max_pres = 0x7fff;
-
- /* initialize interval values */
- ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS;
-
- ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres;
- ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel;
-
- /* 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_flight_pres >= ao_main_pres)
- {
- ao_ignite(ao_igniter_main);
- ao_flight_state = ao_flight_main;
- ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
- }
-
- /* fall through... */
- case ao_flight_main:
-
- /* drogue/main to land:
- *
- * accelerometer: value stable
- * AND
- * barometer: altitude stable and within 1000m of the launch altitude
- */
-
- if (ao_flight_pres < ao_interval_cur_min_pres)
- ao_interval_cur_min_pres = ao_flight_pres;
- if (ao_flight_pres > ao_interval_cur_max_pres)
- ao_interval_cur_max_pres = ao_flight_pres;
- if (ao_flight_accel < ao_interval_cur_min_accel)
- ao_interval_cur_min_accel = ao_flight_accel;
- if (ao_flight_accel > ao_interval_cur_max_accel)
- ao_interval_cur_max_accel = ao_flight_accel;
-
- if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) {
- ao_interval_max_pres = ao_interval_cur_max_pres;
- ao_interval_min_pres = ao_interval_cur_min_pres;
- ao_interval_max_accel = ao_interval_cur_max_accel;
- ao_interval_min_accel = ao_interval_cur_min_accel;
- ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS;
- ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres;
- ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel;
- }
-
- if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND &&
- ao_flight_pres > ao_ground_pres - BARO_LAND &&
- (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND)
- {
- 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));
- }
- break;
- case ao_flight_landed:
- break;
- }
- }
-}
-
-#define AO_ACCEL_COUNT_TO_MSS(count) ((count) / 27)
-#define AO_VEL_COUNT_TO_MS(count) ((int16_t) ((count) / 2700))
-
-static void
-ao_flight_status(void)
-{
- printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n",
- ao_state_names[ao_flight_state],
- AO_ACCEL_COUNT_TO_MSS(ACCEL_ZERO_G - ao_flight_accel),
- AO_VEL_COUNT_TO_MS(ao_flight_vel),
- ao_pres_to_altitude(ao_flight_pres),
- ao_pres_to_altitude(ao_main_pres));
-}
-
-static __xdata struct ao_task flight_task;
-
-__code struct ao_cmds ao_flight_cmds[] = {
- { 'f', ao_flight_status, "f Display current flight state" },
- { 0, ao_flight_status, NULL }
-};
-
-void
-ao_flight_init(void)
-{
- ao_flight_state = ao_flight_startup;
- ao_interval_min_accel = 0;
- ao_interval_max_accel = 0x7fff;
- ao_interval_min_pres = 0;
- ao_interval_max_pres = 0x7fff;
- ao_interval_end = AO_INTERVAL_TICKS;
-
- ao_add_task(&flight_task, ao_flight, "flight");
- ao_cmd_register(&ao_flight_cmds[0]);
-}
+++ /dev/null
-/*
- * 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>
-
-#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_launchpad = 2,
- ao_flight_boost = 3,
- ao_flight_coast = 4,
- ao_flight_apogee = 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()
-#define ao_cmd_register(c)
-#define ao_usb_disable()
-#define ao_telemetry_set_interval(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);
-
-void
-ao_sleep(void *wchan);
-
-const char const * const ao_state_names[] = {
- "startup", "idle", "pad", "boost", "coast",
- "apogee", "drogue", "main", "landed", "invalid"
-};
-
-struct ao_cmds {
- char cmd;
- void (*func)(void);
- const char *help;
-};
-
-
-static int16_t altitude_table[2048] = {
-#include "altitude.h"
-};
-
-int16_t
-ao_pres_to_altitude(int16_t pres) __reentrant
-{
- pres = pres >> 4;
- if (pres < 0) pres = 0;
- if (pres > 2047) pres = 2047;
- return altitude_table[pres];
-}
-
-int16_t
-ao_altitude_to_pres(int16_t alt) __reentrant
-{
- int16_t pres;
-
- for (pres = 0; pres < 2047; pres++)
- if (altitude_table[pres] <= alt)
- break;
- return pres << 4;
-}
-
-struct ao_config {
- uint16_t main_deploy;
- int16_t accel_zero_g;
-};
-
-#define ao_config_get()
-
-struct ao_config ao_config = { 250, 16000 };
-
-#include "ao_flight.c"
-
-void
-ao_insert(void)
-{
- 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) {
- printf("time %g accel %d pres %d\n",
- (double) ao_adc_static.tick / 100,
- ao_adc_static.accel,
- ao_adc_static.pres);
- }
-}
-
-static int ao_records_read = 0;
-static int ao_eof_read = 0;
-static int ao_flight_ground_accel;
-static int ao_flight_started = 0;
-
-void
-ao_sleep(void *wchan)
-{
- ao_dump_state();
- if (wchan == &ao_adc_ring) {
- char type;
- uint16_t tick;
- uint16_t a, b;
- int ret;
- 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) {
- printf ("no more data, exiting simulation\n");
- exit(0);
- }
- 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[2], NULL, 16);
- } 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]);
- }
- }
- if (type != 'F' && !ao_flight_started)
- continue;
-
- switch (type) {
- case 'F':
- ao_flight_ground_accel = a;
- ao_flight_started = 1;
- break;
- case 'S':
- break;
- case 'A':
- ao_adc_static.tick = tick;
- ao_adc_static.accel = a;
- 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)
-{
- if (ao_flight_state == ao_flight_startup)
- return;
- printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n",
- ao_state_names[ao_flight_state],
- (ao_ground_accel - ao_flight_accel) / COUNTS_PER_G * GRAVITY,
- (double) ao_flight_vel / 100 / COUNTS_PER_G * GRAVITY,
- ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres),
- ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres));
- if (ao_flight_state == ao_flight_landed)
- exit(0);
-}
-
-int
-main (int argc, char **argv)
-{
- emulator_in = fopen (argv[1], "r");
- if (!emulator_in) {
- perror(argv[1]);
- exit(1);
- }
- ao_flight_init();
- ao_flight();
-}
+++ /dev/null
-/*
- * 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_GPS_LEADER 6
-
-static const char ao_gps_header[] = "GPGGA,";
-__xdata uint8_t ao_gps_mutex;
-static __xdata char ao_gps_char;
-static __xdata uint8_t ao_gps_cksum;
-static __xdata uint8_t ao_gps_error;
-
-__xdata struct ao_gps_data ao_gps_data;
-static __xdata struct ao_gps_data ao_gps_next;
-
-const char ao_gps_config[] =
- "$PSRF103,00,00,01,01*25\r\n" /* GGA 1 per sec */
- "$PSRF103,01,00,00,01*25\r\n" /* GLL disable */
- "$PSRF103,02,00,00,01*26\r\n" /* GSA disable */
- "$PSRF103,03,00,00,01*27\r\n" /* GSV disable */
- "$PSRF103,04,00,00,01*20\r\n" /* RMC disable */
- "$PSRF103,05,00,00,01*21\r\n"; /* VTG disable */
-
-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(void)
-{
- while (ao_gps_char >= '0')
- ao_gps_lexchar();
-}
-
-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)
-{
- while (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*')
- ao_gps_lexchar();
-}
-
-__xdata static uint8_t ao_gps_num_width;
-
-static int16_t
-ao_gps_decimal(uint8_t max_width)
-{
- int16_t v;
- __xdata 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 void
-ao_gps_parse_pos(__xdata struct ao_gps_pos * pos, uint8_t deg_width) __reentrant
-{
- pos->degrees = ao_gps_decimal(deg_width);
- pos->minutes = ao_gps_decimal(2);
- if (ao_gps_char == '.') {
- pos->minutes_fraction = ao_gps_decimal(4);
- while (ao_gps_num_width < 4) {
- pos->minutes_fraction *= 10;
- ao_gps_num_width++;
- }
- } else {
- pos->minutes_fraction = 0;
- if (ao_gps_char != ',')
- ao_gps_error = 1;
- }
-}
-
-static void
-ao_gps_parse_flag(char yes_c, uint8_t yes, char no_c, uint8_t no) __reentrant
-{
- ao_gps_skip_sep();
- if (ao_gps_char == yes_c)
- ao_gps_next.flags |= yes;
- else if (ao_gps_char == no_c)
- ao_gps_next.flags |= no;
- else
- ao_gps_error = 1;
- ao_gps_lexchar();
-}
-
-
-void
-ao_gps(void) __reentrant
-{
- char c;
- uint8_t i;
-
- for (i = 0; (c = ao_gps_config[i]); i++)
- ao_serial_putchar(c);
- for (;;) {
- /* Locate the begining of the next record */
- for (;;) {
- c = ao_serial_getchar();
- if (c == '$')
- break;
- }
-
- ao_gps_cksum = 0;
- ao_gps_error = 0;
-
- /* Skip anything other than GGA */
- for (i = 0; i < AO_GPS_LEADER; i++) {
- ao_gps_lexchar();
- if (ao_gps_char != ao_gps_header[i])
- break;
- }
- if (i != AO_GPS_LEADER)
- continue;
-
- /* 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.flags = 0;
- 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_parse_pos(&ao_gps_next.latitude, 2);
- ao_gps_parse_flag('N', AO_GPS_LATITUDE_NORTH, 'S', AO_GPS_LATITUDE_SOUTH);
- ao_gps_parse_pos(&ao_gps_next.longitude, 3);
- ao_gps_parse_flag('W', AO_GPS_LONGITUDE_WEST, 'E', AO_GPS_LONGITUDE_EAST);
-
- 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();
- ao_gps_skip_field(); /* Horizontal dilution */
-
- 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);
- memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data));
- ao_mutex_put(&ao_gps_mutex);
- ao_wakeup(&ao_gps_data);
- }
- }
-}
-
-__xdata struct ao_task ao_gps_task;
-
-static void
-gps_dump(void) __reentrant
-{
- ao_mutex_get(&ao_gps_mutex);
- ao_gps_print(&ao_gps_data);
- ao_mutex_put(&ao_gps_mutex);
-}
-
-__code struct ao_cmds ao_gps_cmds[] = {
- { 'g', gps_dump, "g Display current GPS values" },
- { 0, gps_dump, NULL },
-};
-
-void
-ao_gps_init(void)
-{
- ao_add_task(&ao_gps_task, ao_gps, "gps");
- ao_cmd_register(&ao_gps_cmds[0]);
-}
+++ /dev/null
-/*
- * 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_print(__xdata struct ao_gps_data *gps_data) __reentrant
-{
- printf("GPS %2d sat",
- (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);;
- if (gps_data->flags & AO_GPS_VALID) {
- printf(" %2d:%02d:%02d %2d°%2d.%04d'%c %2d°%2d.%04d'%c %5dm\n",
- gps_data->hour,
- gps_data->minute,
- gps_data->second,
- gps_data->latitude.degrees,
- gps_data->latitude.minutes,
- gps_data->latitude.minutes_fraction,
- (gps_data->flags & AO_GPS_LATITUDE_MASK) == AO_GPS_LATITUDE_NORTH ?
- 'N' : 'S',
- gps_data->longitude.degrees,
- gps_data->longitude.minutes,
- gps_data->longitude.minutes_fraction,
- (gps_data->flags & AO_GPS_LONGITUDE_MASK) == AO_GPS_LONGITUDE_WEST ?
- 'W' : 'E',
- gps_data->altitude,
- (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
- } else {
- printf(" unlocked\n");
- }
-}
-
+++ /dev/null
-/*
- * 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_gps_data gps_data;
-
- for (;;) {
- ao_sleep(&ao_gps_data);
- ao_mutex_get(&ao_gps_mutex);
- memcpy(&gps_data, &ao_gps_data, sizeof (struct ao_gps_data));
- ao_mutex_put(&ao_gps_mutex);
-
- if (!(gps_data.flags & AO_GPS_VALID))
- continue;
-
- gps_log.tick = ao_time();
- 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.degrees = gps_data.latitude.degrees;
- gps_log.u.gps_latitude.minutes = gps_data.latitude.minutes;
- gps_log.u.gps_latitude.minutes_fraction = gps_data.latitude.minutes_fraction;
- ao_log_data(&gps_log);
- gps_log.type = AO_LOG_GPS_LON;
- gps_log.u.gps_longitude.degrees = gps_data.longitude.degrees;
- gps_log.u.gps_longitude.minutes = gps_data.longitude.minutes;
- gps_log.u.gps_longitude.minutes_fraction = gps_data.longitude.minutes_fraction;
- 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);
- }
-}
-
-__xdata struct ao_task ao_gps_report_task;
-
-void
-ao_gps_report_init(void)
-{
- ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report");
-}
+++ /dev/null
-/*
- * 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_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)
-
-/* 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(500)
-#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[0]);
-}
-
-enum ao_igniter_status
-ao_igniter_status(enum ao_igniter igniter)
-{
- __xdata struct ao_adc adc;
- __xdata int16_t value;
- __xdata uint8_t request, firing, fired;
-
- __critical {
- ao_adc_sleep();
- 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 (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;
- }
- ao_ignition[igniter].firing = 0;
-}
-
-void
-ao_igniter(void)
-{
- __xdata enum ao_ignter igniter;
- __xdata enum ao_igniter_status status;
-
- for (;;) {
- ao_sleep(&ao_ignition);
- for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) {
- if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) {
- ao_igniter_fire(igniter);
- ao_delay(AO_IGNITER_CHARGE_TIME);
- status = ao_igniter_status(igniter);
- if (status == ao_igniter_open)
- ao_ignition[igniter].fired = 1;
- }
- }
- }
-}
-
-static 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;
-}
-
-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 *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[] = {
- { 'i', ao_ignite_manual, "i <key> {main|drogue} Fire igniter. <key> is doit with D&I" },
- { 't', ao_ignite_test, "t Test igniter continuity" },
- { 0, ao_ignite_manual, NULL },
-};
-
-__xdata struct ao_task ao_igniter_task;
-
-void
-ao_igniter_init(void)
-{
- AO_IGNITER_DROGUE = 0;
- AO_IGNITER_MAIN = 0;
- AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT;
- ao_cmd_register(&ao_ignite_cmds[0]);
- ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
-}
+++ /dev/null
-/*
- * 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_LED_ALL (AO_LED_GREEN|AO_LED_RED)
-
-__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;
-}
+++ /dev/null
-/*
- * 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 __pdata uint32_t ao_log_current_pos;
-static __pdata uint32_t ao_log_start_pos;
-static __xdata uint8_t ao_log_running;
-static __xdata uint8_t ao_log_mutex;
-
-static uint8_t
-ao_log_csum(uint8_t *b)
-{
- uint8_t sum = 0x5a;
- uint8_t i;
-
- for (i = 0; i < sizeof (struct ao_log_record); i++)
- sum += *b++;
- return -sum;
-}
-
-void
-ao_log_data(struct ao_log_record *log)
-{
- /* set checksum */
- log->csum = 0;
- log->csum = ao_log_csum((uint8_t *) log);
- ao_mutex_get(&ao_log_mutex); {
- if (ao_log_running) {
- ao_ee_write(ao_log_current_pos,
- (uint8_t *) log,
- sizeof (struct ao_log_record));
- ao_log_current_pos += sizeof (struct ao_log_record);
- if (ao_log_current_pos >= AO_EE_DATA_SIZE)
- ao_log_current_pos = 0;
- if (ao_log_current_pos == ao_log_start_pos)
- ao_log_running = 0;
- }
- } ao_mutex_put(&ao_log_mutex);
-}
-
-void
-ao_log_flush(void)
-{
- ao_ee_flush();
-}
-
-__xdata struct ao_log_record ao_log_dump;
-static __xdata uint16_t ao_log_dump_flight;
-static __xdata uint32_t ao_log_dump_pos;
-
-static uint8_t
-ao_log_dump_check_data(void)
-{
- if (ao_log_csum((uint8_t *) &ao_log_dump) != 0)
- return 0;
- return 1;
-}
-
-static uint8_t
-ao_log_dump_scan(void)
-{
- if (!ao_ee_read(0, (uint8_t *) &ao_log_dump, sizeof (struct ao_log_record)))
- ao_panic(AO_PANIC_LOG);
- if (ao_log_dump_check_data() && ao_log_dump.type == AO_LOG_FLIGHT) {
- ao_log_dump_flight = ao_log_dump.u.flight.flight;
- return 1;
- } else {
- ao_log_dump_flight = 0;
- return 0;
- }
-}
-
-uint8_t
-ao_log_dump_first(void)
-{
- ao_log_dump_pos = 0;
- if (!ao_log_dump_scan())
- return 0;
- return 1;
-}
-
-uint8_t
-ao_log_dump_next(void)
-{
- ao_log_dump_pos += sizeof (struct ao_log_record);
- if (ao_log_dump_pos >= AO_EE_DEVICE_SIZE)
- return 0;
- if (!ao_ee_read(ao_log_dump_pos, (uint8_t *) &ao_log_dump,
- sizeof (struct ao_log_record)))
- return 0;
- return ao_log_dump_check_data();
-}
-
-__xdata uint8_t ao_log_adc_pos;
-__xdata enum flight_state ao_log_state;
-
-void
-ao_log(void)
-{
- static __xdata struct ao_log_record log;
-
- ao_log_dump_scan();
-
- while (!ao_log_running)
- ao_sleep(&ao_log_running);
-
- log.type = AO_LOG_FLIGHT;
- log.tick = ao_flight_tick;
- log.u.flight.ground_accel = ao_ground_accel;
- log.u.flight.flight = ao_log_dump_flight + 1;
- 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_adc_head);
- for (;;) {
- /* Write samples to EEPROM */
- while (ao_log_adc_pos != ao_adc_head) {
- log.type = AO_LOG_SENSOR;
- log.tick = ao_adc_ring[ao_log_adc_pos].tick;
- 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_adc_pos & 0x1f) == 0) {
- log.type = AO_LOG_TEMP_VOLT;
- log.tick = ao_adc_ring[ao_log_adc_pos].tick;
- 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.tick = ao_adc_ring[ao_log_adc_pos].tick;
- 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);
- }
- 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_flight_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);
- }
-}
-
-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();
-}
-
-static void
-dump_log(void)
-{
- uint8_t more;
-
- for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) {
- printf("%c %4x %4x %4x\n",
- ao_log_dump.type,
- ao_log_dump.tick,
- ao_log_dump.u.anon.d0,
- ao_log_dump.u.anon.d1);
- if (ao_log_dump.type == AO_LOG_STATE &&
- ao_log_dump.u.state.state == ao_flight_landed)
- break;
- }
- printf("end\n");
-}
-
-__code struct ao_cmds ao_log_cmds[] = {
- { 'l', dump_log, "l Dump last flight log" },
- { 0, dump_log, NULL },
-};
-
-static __xdata struct ao_task ao_log_task;
-
-void
-ao_log_init(void)
-{
- ao_log_running = 0;
-
- /* For now, just log the flight starting at the begining of eeprom */
- ao_log_start_pos = 0;
- ao_log_current_pos = ao_log_start_pos;
- ao_log_state = ao_flight_invalid;
-
- /* Create a task to log events to eeprom */
- ao_add_task(&ao_log_task, ao_log, "log");
- ao_cmd_register(&ao_log_cmds[0]);
-}
+++ /dev/null
-/*
- * 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)
-{
- CLKCON = 0;
- while (!(SLEEP & SLEEP_XOSC_STB))
- ;
-
- /* 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();
-}
+++ /dev/null
-/*
- * 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 uint8_t ao_monitoring;
-__pdata uint8_t ao_monitor_led;
-
-void
-ao_monitor(void)
-{
- __xdata struct ao_radio_recv recv;
- __xdata char callsign[AO_MAX_CALLSIGN+1];
- uint8_t state;
-
- for (;;) {
- __critical while (!ao_monitoring)
- ao_sleep(&ao_monitoring);
- ao_radio_recv(&recv);
- state = recv.telemetry.flight_state;
- memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN);
- if (state > ao_flight_invalid)
- state = ao_flight_invalid;
- if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) {
- printf ("CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ",
- callsign,
- recv.telemetry.addr,
- (int) recv.rssi - 74, recv.status,
- ao_state_names[state]);
- printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d ",
- recv.telemetry.adc.tick,
- recv.telemetry.adc.accel,
- recv.telemetry.adc.pres,
- recv.telemetry.adc.temp,
- recv.telemetry.adc.v_batt,
- recv.telemetry.adc.sense_d,
- recv.telemetry.adc.sense_m,
- recv.telemetry.flight_accel,
- recv.telemetry.ground_accel,
- recv.telemetry.flight_vel,
- recv.telemetry.flight_pres,
- recv.telemetry.ground_pres);
- ao_gps_print(&recv.telemetry.gps);
- ao_rssi_set((int) recv.rssi - 74);
- } else {
- printf("CRC INVALID RSSI %3d\n", (int) recv.rssi - 74);
- }
- ao_usb_flush();
- ao_led_toggle(ao_monitor_led);
- }
-}
-
-__xdata struct ao_task ao_monitor_task;
-
-void
-ao_set_monitor(uint8_t monitoring)
-{
- ao_monitoring = monitoring;
- ao_wakeup(&ao_monitoring);
-}
-
-static void
-set_monitor(void)
-{
- ao_cmd_hex();
- ao_set_monitor(ao_cmd_lex_i != 0);
-}
-
-__code struct ao_cmds ao_monitor_cmds[] = {
- { 'm', set_monitor, "m <0 off, 1 on> Enable/disable radio monitoring" },
- { 0, set_monitor, 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_task, ao_monitor, "monitor");
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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 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);
- }
- }
-}
+++ /dev/null
-/*
- * 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"
-#include PRODUCT_DEFS
-
-/* Defines which mark this particular AltOS product */
-
-const uint16_t ao_serial_number = AO_iSerial_NUMBER;
-const char ao_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))
-
-/* USB descriptors in one giant block of bytes */
-const 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(0x000A), /* 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
-};
+++ /dev/null
-/*
- * 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 434.550MHz, the frequency value is:
- *
- * 434.550e6 / (24e6 / 2**16) = 1186611.2
- */
-
-#define FREQ_CONTROL 1186611
-
-/*
- * 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
-
-/* 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_FREQ2_OFF, (FREQ_CONTROL >> 16) & 0xff,
- RF_FREQ1_OFF, (FREQ_CONTROL >> 8) & 0xff,
- RF_FREQ0_OFF, (FREQ_CONTROL >> 0) & 0xff,
-
- 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_PKTLEN_OFF, sizeof (struct ao_telemetry),
-
- 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 telemetry_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 */
- RF_PKTLEN_OFF, sizeof (struct ao_telemetry),
- 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_mutex;
-
-static void
-ao_radio_idle(void)
-{
- if (RF_MARCSTATE != RF_MARCSTATE_IDLE)
- {
- RFST = RFST_SIDLE;
- do {
- ao_yield();
- } while (RF_MARCSTATE != RF_MARCSTATE_IDLE);
- }
-}
-
-void
-ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant
-{
- ao_config_get();
- ao_mutex_get(&ao_radio_mutex);
- ao_radio_idle();
- RF_CHANNR = ao_config.radio_channel;
- ao_dma_set_transfer(ao_radio_dma,
- telemetry,
- &RFDXADDR,
- sizeof (struct ao_telemetry),
- 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_dma_done)
- ao_sleep(&ao_radio_dma_done);
- ao_mutex_put(&ao_radio_mutex);
-}
-
-void
-ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant
-{
- ao_config_get();
- ao_mutex_get(&ao_radio_mutex);
- ao_radio_idle();
- RF_CHANNR = ao_config.radio_channel;
- ao_dma_set_transfer(ao_radio_dma,
- &RFDXADDR,
- radio,
- sizeof (struct ao_radio_recv),
- 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;
- __critical while (!ao_radio_dma_done)
- ao_sleep(&ao_radio_dma_done);
- ao_mutex_put(&ao_radio_mutex);
-}
-
-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_dma_done = 1;
- ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done);
-}
-
+++ /dev/null
-/*
- * 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 const char * __xdata flight_reports[] = {
- "...", /* startup, 'S' */
- "..", /* idle 'I' */
- ".--.", /* launchpad 'P' */
- "-...", /* boost 'B' */
- "-.-.", /* coast 'C' */
- ".-", /* apogee 'A' */
- "-..", /* drogue 'D' */
- "--", /* main 'M' */
- ".-..", /* landed 'L' */
- ".-.-.-", /* invalid */
-};
-
-#if 1
-#define signal(time) ao_beep_for(AO_BEEP_MID, time)
-#else
-#define signal(time) ao_led_for(AO_LED_RED, time)
-#endif
-#define pause(time) ao_delay(time)
-
-static __xdata enum ao_flight_state ao_report_state;
-
-static void
-ao_report_beep(void) __reentrant
-{
- char *r = flight_reports[ao_flight_state];
- char c;
-
- if (!r)
- return;
- while (c = *r++) {
- if (c == '.')
- signal(AO_MS_TO_TICKS(200));
- else
- signal(AO_MS_TO_TICKS(600));
- pause(AO_MS_TO_TICKS(200));
- }
- pause(AO_MS_TO_TICKS(400));
-}
-
-static void
-ao_report_digit(uint8_t digit) __reentrant
-{
- if (!digit) {
- signal(AO_MS_TO_TICKS(500));
- pause(AO_MS_TO_TICKS(200));
- } else {
- while (digit--) {
- signal(AO_MS_TO_TICKS(200));
- pause(AO_MS_TO_TICKS(200));
- }
- }
- pause(AO_MS_TO_TICKS(300));
-}
-
-static void
-ao_report_altitude(void)
-{
- __xdata int16_t agl = ao_pres_to_altitude(ao_min_pres) - ao_pres_to_altitude(ao_ground_pres);
- __xdata uint8_t digits[10];
- __xdata 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));
- }
-}
-
-void
-ao_report(void)
-{
- ao_report_state = ao_flight_state;
- for(;;) {
- if (ao_flight_state == ao_flight_landed)
- ao_report_altitude();
- ao_report_beep();
- __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");
-}
+++ /dev/null
-/*
- * 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 __xdata volatile uint16_t ao_rssi_delay;
-static __xdata 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");
-}
+++ /dev/null
-/*
- * 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);
-}
-
-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;
-}
-
-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();
-}
-
-static void
-send_serial(void)
-{
- ao_cmd_white();
- while (ao_cmd_lex_c != '\n') {
- ao_serial_putchar(ao_cmd_lex_c);
- ao_cmd_lex();
- }
-}
-
-__code struct ao_cmds ao_serial_cmds[] = {
- { 'S', send_serial, "S <data> Send data to serial line" },
- { 0, send_serial, NULL },
-};
-
-void
-ao_serial_init(void)
-{
- /* Set up the USART pin assignment */
- PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
-
- /* ee has already set the P2SEL bits */
-
- /* Make the USART pins be controlled by the USART */
- P1SEL |= (1 << 6) | (1 << 7);
-
- /* UART mode with receiver enabled */
- U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
-
- /* Pick a 4800 baud rate */
- U1BAUD = 163; /* 4800 */
- U1GCR = 7 << UxGCR_BAUD_E_SHIFT; /* 4800 */
-
- /* Reasonable serial parameters */
- U1UCR = (UxUCR_FLUSH |
- UxUCR_FLOW_DISABLE |
- UxUCR_D9_ODD_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;
-
- ao_cmd_register(&ao_serial_cmds[0]);
-}
+++ /dev/null
-/*
- * 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", "coast",
- "apogee", "drogue", "main", "landed", "invalid"
-};
+++ /dev/null
-/*
- * 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
- */
-
-void
-putchar(char c)
-{
- if (c == '\n')
- ao_usb_putchar('\r');
- ao_usb_putchar(c);
-}
-
-void
-flush(void)
-{
- ao_usb_flush();
-}
-
-char
-getchar(void)
-{
- return ao_usb_getchar();
-}
+++ /dev/null
-/*
- * 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;
- if (ao_num_tasks == AO_NUM_TASKS)
- ao_panic(AO_PANIC_NO_TASK);
- ao_tasks[ao_num_tasks++] = task;
- task->task_id = ao_num_tasks;
- 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);
- *stack++ = ((uint16_t) start) >> 8;
-
- /* and the stuff saved by ao_switch */
- *stack++ = 0; /* acc */
- *stack++ = 0x80; /* IE */
- *stack++ = 0; /* DPL */
- *stack++ = 0; /* DPH */
- *stack++ = 0; /* B */
- *stack++ = 0; /* R2 */
- *stack++ = 0; /* R3 */
- *stack++ = 0; /* R4 */
- *stack++ = 0; /* R5 */
- *stack++ = 0; /* R6 */
- *stack++ = 0; /* R7 */
- *stack++ = 0; /* R0 */
- *stack++ = 0; /* R1 */
- *stack++ = 0; /* PSW */
- *stack++ = 0; /* BP */
- task->stack_count = stack - task->stack;
- 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)
- {
- 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;
- }
-
- /* 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;
-}
-
-void
-ao_sleep(__xdata void *wchan)
-{
- __critical {
- ao_cur_task->wchan = wchan;
- }
- ao_yield();
-}
-
-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_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();
-}
+++ /dev/null
-/*
- * 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)
-{
- CLKCON = 0;
- while (!(SLEEP & SLEEP_XOSC_STB))
- ;
-
- /* Turn on the 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_cmd_init();
- ao_usb_init();
- ao_monitor_init(AO_LED_GREEN, TRUE);
- ao_rssi_init(AO_LED_RED);
- ao_radio_init();
- ao_dbg_init();
- ao_config_init();
- ao_start_scheduler();
-}
+++ /dev/null
-/*
- * 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)
-{
- CLKCON = 0;
- while (!(SLEEP & SLEEP_XOSC_STB))
- ;
-
- /* 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_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_gps_report_init();
- ao_telemetry_init();
- ao_radio_init();
- ao_igniter_init();
- ao_dbg_init();
- ao_config_init();
- ao_start_scheduler();
-}
+++ /dev/null
-/*
- * 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 uint16_t ao_telemetry_interval = 0;
-
-void
-ao_telemetry(void)
-{
- static __xdata struct ao_telemetry telemetry;
-
- ao_config_get();
- memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
- telemetry.addr = ao_serial_number;
- for (;;) {
- while (ao_telemetry_interval == 0)
- ao_sleep(&ao_telemetry_interval);
- telemetry.flight_state = ao_flight_state;
- telemetry.flight_accel = ao_flight_accel;
- telemetry.ground_accel = ao_ground_accel;
- telemetry.flight_vel = ao_flight_vel;
- telemetry.flight_pres = ao_flight_pres;
- telemetry.ground_pres = ao_ground_pres;
- ao_adc_get(&telemetry.adc);
- ao_mutex_get(&ao_gps_mutex);
- memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data));
- ao_mutex_put(&ao_gps_mutex);
- ao_radio_send(&telemetry);
- ao_delay(ao_telemetry_interval);
- }
-}
-
-void
-ao_telemetry_set_interval(uint16_t interval)
-{
- ao_telemetry_interval = interval;
- ao_wakeup(&ao_telemetry_interval);
-}
-
-__xdata struct ao_task ao_telemetry_task;
-
-void
-ao_telemetry_init()
-{
- ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry");
-}
+++ /dev/null
-/*
- * 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)
-{
- CLKCON = 0;
- while (!(SLEEP & SLEEP_XOSC_STB))
- ;
-
- /* 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_gps_init();
- ao_monitor_init(AO_LED_GREEN, TRUE);
- ao_radio_init();
- ao_dbg_init();
- ao_config_init();
- ao_start_scheduler();
-}
+++ /dev/null
-/*
- * 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_ring);
- 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)
-{
- CLKCON = 0;
- while (!(SLEEP & SLEEP_XOSC_STB))
- ;
-
-// 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();
-}
+++ /dev/null
-/*
- * 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)
-{
- CLKCON = 0;
- while (!(SLEEP & SLEEP_XOSC_STB))
- ;
-
- /* 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();
-}
+++ /dev/null
-/*
- * 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;
-}
-
-void
-ao_delay(uint16_t ticks)
-{
- uint16_t until = ao_time() + ticks;
-
- while ((int16_t) (until - ao_time()) > 0)
- ao_sleep(DATA_TO_XDATA(&ao_tick_count));
-}
-
-#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */
-#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */
-
-volatile __data uint8_t ao_adc_interval = 1;
-volatile __data uint8_t ao_adc_count;
-
-void ao_timer_isr(void) interrupt 9
-{
- ++ao_tick_count;
- if (++ao_adc_count == ao_adc_interval) {
- ao_adc_count = 0;
- ao_adc_poll();
- }
- ao_wakeup(DATA_TO_XDATA(&ao_tick_count));
-}
-
-void
-ao_timer_set_adc_interval(uint8_t interval) __critical
-{
- ao_adc_interval = interval;
- ao_adc_count = 0;
-}
-
-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;
-}
-
+++ /dev/null
-/*
- * 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 __xdata uint16_t ao_usb_out_bytes;
-static __xdata uint8_t ao_usb_iif;
-static __xdata 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_usb_out_bytes);
-
- if (USBCIF & USBCIF_RSTIF)
- ao_usb_set_interrupts();
-}
-
-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;
-
-__xdata uint8_t ao_usb_ep0_state;
-uint8_t * __xdata ao_usb_ep0_in_data;
-__xdata uint8_t ao_usb_ep0_in_len;
-__xdata uint8_t ao_usb_ep0_in_buf[2];
-__xdata uint8_t ao_usb_ep0_out_len;
-__xdata uint8_t *__data ao_usb_ep0_out_data;
-__xdata uint8_t ao_usb_configuration;
-
-/* Send an IN data packet */
-static void
-ao_usb_ep0_flush(void)
-{
- __xdata uint8_t this_len;
- __xdata uint8_t cs0;
-
- USBINDEX = 0;
- cs0 = USBCS0;
- if (cs0 & USBCS0_INPKT_RDY)
- ao_panic(0);
-
- 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)
-{
- const uint8_t *__xdata descriptor;
- __xdata uint8_t type = value >> 8;
- __xdata 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)
-{
- __xdata 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)
-{
- __xdata 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;
- }
- }
- }
-}
-
-void
-ao_usb_flush(void) __critical
-{
- if (ao_usb_in_bytes) {
- USBINDEX = AO_USB_IN_EP;
- USBCSIL |= USBCSIL_INPKT_RDY;
- ao_usb_in_bytes = 0;
- }
-}
-
-void
-ao_usb_putchar(char c) __critical
-{
- if (!ao_usb_running)
- return;
- for (;;) {
- USBINDEX = AO_USB_IN_EP;
- if ((USBCSIL & USBCSIL_INPKT_RDY) == 0)
- break;
- ao_sleep(&ao_usb_in_bytes);
- }
- USBFIFO[AO_USB_IN_EP << 1] = c;
- if (++ao_usb_in_bytes == AO_USB_IN_SIZE) {
- USBINDEX = AO_USB_IN_EP;
- USBCSIL |= USBCSIL_INPKT_RDY;
- ao_usb_in_bytes = 0;
- }
-}
-
-char
-ao_usb_getchar(void) __critical
-{
- __xdata char c;
- while (ao_usb_out_bytes == 0) {
- for (;;) {
- USBINDEX = AO_USB_OUT_EP;
- if ((USBCSOL & USBCSOL_OUTPKT_RDY) != 0)
- break;
- ao_sleep(&ao_usb_out_bytes);
- }
- ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL;
- }
- --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;
-}
-
-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");
-}
+++ /dev/null
-/*
- * 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_ */
+++ /dev/null
-VERSION=$(shell git describe)
-MODULES=gtk+-2.0 libglade-2.0 gconf-2.0
-INCLUDES=$(shell pkg-config --cflags $(MODULES)) -I..
-WARN= -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -fno-strict-aliasing
-CFLAGS=$(INCLUDES) -O0 -g $(WARN) -DAOVIEW_VERSION='"$(VERSION)"'
-LIBS=$(shell pkg-config --libs $(MODULES)) -lm
-
-BIN=/usr/local/bin
-
-SRC = \
- aoview_main.c \
- aoview_dev.c \
- aoview_dev_dialog.c \
- aoview_serial.c \
- aoview_monitor.c \
- aoview_state.c \
- aoview_convert.c \
- aoview_log.c \
- aoview_table.c \
- aoview_util.c \
- aoview_file.c \
- aoview_eeprom.c
-
-INC = \
- aoview.h
-
-OBJ = \
- $(SRC:.c=.o)
-
-PROG = aoview
-
-$(PROG): $(OBJ)
- $(CC) $(CFLAGS) -o $@ $(OBJ) $(LIBS)
-
-$(OBJ): $(INC)
-
-aoview_main.o: aoview_glade.h
-
-clean:
- rm -f $(OBJ) $(PROG)
-
-install: $(BIN)/aoview
-
-$(BIN)/aoview: aoview
- install aoview $(BIN)
-
-aoview_glade.h: aoview.glade
- sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@
--- /dev/null
+VERSION=$(shell git describe)
+AM_CFLAGS=$(AOVIEW_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\"
+
+bin_PROGRAMS=aoview
+
+aoview_LDADD=$(AOVIEW_LIBS)
+
+aoview_SOURCES = \
+ aoview_main.c \
+ aoview_dev.c \
+ aoview_dev_dialog.c \
+ aoview_serial.c \
+ aoview_monitor.c \
+ aoview_state.c \
+ aoview_convert.c \
+ aoview_log.c \
+ aoview_table.c \
+ aoview_util.c \
+ aoview_file.c \
+ aoview_eeprom.c \
+ aoview.h
+
+BUILT_SOURCES = aoview_glade.h
+
+CLEANFILES = aoview_glade.h
+
+aoview_glade.h: aoview.glade
+ sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@
#include "aoview.h"
static int16_t altitude_table[2048] = {
-#include "../altitude.h"
+#include "altitude.h"
};
int16_t
--- /dev/null
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf --force -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
+++ /dev/null
-/*-------------------------------------------------------------------------
- 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 */
-
-/* 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;
-
-/*
- * 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_PRI1P1_TIMER1 (0 << 4)
-#define P2SEL_PRI1P1_TIMER4 (1 << 4)
-#define P2SEL_PRI0P1_USART0 (0 << 3)
-#define P2SEL_PRI0P1_TIMER1 (1 << 3)
-#define P2SEL_SELP2_4_GPIO (0 << 2)
-#define P2SEL_SELP2_4_PERIPHERAL (1 << 2)
-#define P2SEL_SELP2_3_GPIO (0 << 1)
-#define P2SEL_SELP2_3_PERIPHERAL (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;
-
-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)
-
-/* 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;
-sbit at 0xa5 P2_5;
-sbit at 0xa6 P2_6;
-sbit at 0xa7 P2_7;
-
-/* 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;
-
-/* 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 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
+++ /dev/null
-#!/bin/sh
-HEADER=$1
-MEM=$2
-
-HEADER_STACK=`awk '/#define AO_STACK_START/ {print $3}' $HEADER | nickle`
-MEM_STACK=`awk '/Stack starts at/ {print $4}' $MEM | nickle`
-
-if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then
- MIN=0x`nickle -e "$MEM_STACK # 16"`
- echo "Set AO_STACK_START to at least $MIN"
- exit 1
-else
- exit 0
-fi
--- /dev/null
+dnl
+dnl Copyright © 2008 Keith Packard <keithp@keithp.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License along
+dnl with this program; if not, write to the Free Software Foundation, Inc.,
+dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+dnl
+dnl Process this file with autoconf to create configure.
+
+AC_INIT(aoview)
+
+AM_INIT_AUTOMAKE(aoview, 0.1)
+AM_MAINTAINER_MODE
+
+dnl ==========================================================================
+
+AM_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_RANLIB
+PKG_PROG_PKG_CONFIG
+
+CFLAGS="-g"
+WARN_CFLAGS=""
+if test "x$GCC" = "xyes"; then
+ WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes \
+ -Wmissing-prototypes -Wmissing-declarations \
+ -Wnested-externs -fno-strict-aliasing"
+ AC_DEFINE_UNQUOTED(HAVE_WARNING_CPP_DIRECTIVE,1,
+ [Can use #warning in C files])
+fi
+AC_SUBST(WARN_CFLAGS)
+
+dnl ==========================================================================
+
+AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes)
+
+dnl ==========================================================================
+
+
+PKG_CHECK_MODULES([AOVIEW], [gtk+-2.0 libglade-2.0 gconf-2.0])
+
+AC_OUTPUT([
+Makefile
+aoview/Makefile
+])
+++ /dev/null
-#!/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();
+++ /dev/null
-#!/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 count_to_kPa(real count)
-{
- return (count / 2047 + 0.095) / 0.009;
-}
-
-for (real count = 0; count <= 2047; count++) {
- real kPa = count_to_kPa(count);
- real meters = pressure_to_altitude(kPa * 1000);
- printf (" %d, /* %6.2g kPa %d count */\n",
- floor (meters + 0.5), kPa, count);
-}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+#
+# AltOS build
+#
+#
+CC=sdcc
+
+VERSION=$(shell git describe)
+
+CFLAGS=--model-small --debug --opt-code-speed
+
+LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \
+ --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff
+
+INC = \
+ ao.h \
+ cc1111.h \
+ altitude.h \
+ 25lc1024.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_cmd.c \
+ ao_dbg.c \
+ ao_dma.c \
+ ao_mutex.c \
+ ao_panic.c \
+ ao_task.c \
+ ao_timer.c \
+ _bp.c
+
+#
+# Shared AltOS drivers
+#
+ALTOS_DRIVER_SRC = \
+ ao_beep.c \
+ ao_config.c \
+ ao_led.c \
+ ao_radio.c \
+ ao_stdio.c \
+ ao_usb.c
+
+TELE_COMMON_SRC = \
+ ao_gps_print.c \
+ ao_state.c
+
+#
+# Receiver code
+#
+TELE_RECEIVER_SRC =\
+ ao_monitor.c \
+ ao_rssi.c
+
+#
+# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle)
+#
+
+TELE_DRIVER_SRC = \
+ ao_convert.c \
+ ao_gps.c \
+ ao_serial.c
+
+#
+# Drivers for partially-flled boards (TT, TD and TI)
+#
+TELE_FAKE_SRC = \
+ ao_adc_fake.c \
+ ao_ee_fake.c
+
+#
+# Drivers only on TeleMetrum
+#
+TM_DRIVER_SRC = \
+ ao_adc.c \
+ ao_ee.c \
+ ao_gps_report.c \
+ ao_ignite.c
+
+#
+# Tasks run on TeleMetrum
+#
+TM_TASK_SRC = \
+ ao_flight.c \
+ ao_log.c \
+ ao_report.c \
+ ao_telemetry.c
+
+TM_MAIN_SRC = \
+ ao_telemetrum.c
+
+#
+# All sources for TeleMetrum
+#
+TM_SRC = \
+ $(ALTOS_SRC) \
+ $(ALTOS_DRIVER_SRC) \
+ $(TELE_DRIVER_SRC) \
+ $(TELE_COMMON_SRC) \
+ $(TM_DRIVER_SRC) \
+ $(TM_TASK_SRC) \
+ $(TM_MAIN_SRC)
+
+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) \
+ $(TELE_FAKE_SRC) \
+ $(TI_MAIN_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) \
+ $(TELE_FAKE_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) \
+ $(TELE_FAKE_SRC) \
+ $(TD_MAIN_SRC)
+
+SRC = \
+ $(ALTOS_SRC) \
+ $(ALTOS_DRIVER_SRC) \
+ $(TELE_DRIVER_SRC) \
+ $(TELE_RECEIVER_SRC) \
+ $(TELE_COMMON_SRC) \
+ $(TELE_FAKE_SRC) \
+ $(TM_DRIVER_SRC) \
+ $(TM_TASK_SRC) \
+ $(TM_MAIN_SRC) \
+ $(TI_MAIN_SRC) \
+ $(TD_MAIN_SRC) \
+ $(TT_MAIN_SRC)
+
+TM_REL=$(TM_SRC:.c=.rel) ao_product-telemetrum.rel
+TI_REL=$(TI_SRC:.c=.rel) ao_product-tidongle.rel
+TT_REL=$(TT_SRC:.c=.rel) ao_product-teleterra.rel
+TD_REL=$(TD_SRC:.c=.rel) ao_product-teledongle.rel
+
+PROD_REL=\
+ ao_product-telemetrum.rel \
+ ao_product-tidongle.rel \
+ ao_product-teleterra.rel \
+ ao_product-teledongle.rel
+
+REL=$(SRC:.c=.rel) $(PROD_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)
+
+PROGS= telemetrum.ihx tidongle.ihx \
+ teleterra.ihx teledongle.ihx
+
+HOST_PROGS=ao_flight_test
+
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c $(INC)
+ $(CC) -c $(CFLAGS) -o$*.rel $*.c
+
+all: $(PROGS) $(HOST_PROGS)
+
+telemetrum.ihx: $(TM_REL) Makefile
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_REL)
+ sh check-stack ao.h telemetrum.mem
+
+tidongle.ihx: $(TI_REL) Makefile
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL)
+ sh check-stack ao.h tidongle.mem
+
+tidongle.ihx: telemetrum.ihx
+
+teleterra.ihx: $(TT_REL) Makefile
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TT_REL)
+ sh check-stack ao.h teleterra.mem
+
+teleterra.ihx: tidongle.ihx
+
+teledongle.ihx: $(TD_REL) Makefile
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TD_REL)
+ sh check-stack ao.h teledongle.mem
+
+teledongle.ihx: teleterra.ihx
+
+altitude.h: make-altitude
+ nickle make-altitude > altitude.h
+
+TELEMETRUM_DEFS=ao-telemetrum.h
+TELETERRA_DEFS=ao-teleterra.h
+TELEDONGLE_DEFS=ao-teledongle.h
+TIDONGLE_DEFS=ao-tidongle.h
+
+ALL_DEFS=$(TELEMETRUM_DEFS) $(TELETERRA_DEFS) \
+ $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS)
+ao_product-telemetrum.rel: ao_product.c $(TELEMETRUM_DEFS)
+ $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEMETRUM_DEFS)\"' -o$@ ao_product.c
+
+ao_product-teleterra.rel: ao_product.c $(TELETERRA_DEFS)
+ $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELETERRA_DEFS)\"' -o$@ ao_product.c
+
+ao_product-teledongle.rel: ao_product.c $(TELEDONGLE_DEFS)
+ $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEDONGLE_DEFS)\"' -o$@ ao_product.c
+
+ao_product-tidongle.rel: ao_product.c $(TIDONGLE_DEFS)
+ $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TIDONGLE_DEFS)\"' -o$@ ao_product.c
+
+$(TELEMETRUM_DEFS): ao-make-product.5c
+ nickle ao-make-product.5c -m altusmetrum.org -p TeleMetrum -v $(VERSION) > $@
+
+$(TELETERRA_DEFS): ao-make-product.5c
+ nickle ao-make-product.5c -m altusmetrum.org -p TeleTerra -v $(VERSION) > $@
+
+$(TELEDONGLE_DEFS): ao-make-product.5c
+ nickle ao-make-product.5c -m altusmetrum.org -p TeleDongle -v $(VERSION) > $@
+
+$(TIDONGLE_DEFS): ao-make-product.5c
+ nickle ao-make-product.5c -m altusmetrum.org -p TIDongle -v $(VERSION) > $@
+
+clean:
+ rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+ rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+ rm -f $(ALL_DEFS) $(HOST_PROGS)
+ rm -f $(TELEMETRUM_DEFS) $(TELETERRA_DEFS) $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS)
+
+install:
+
+ao_flight_test: ao_flight.c ao_flight_test.c
+ cc -g -o $@ ao_flight_test.c
--- /dev/null
+/*-------------------------------------------------------------------------
+
+ _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 ;
--- /dev/null
+ 15837, /* 10.56 kPa 0 count */
+ 15804, /* 10.61 kPa 1 count */
+ 15772, /* 10.66 kPa 2 count */
+ 15740, /* 10.72 kPa 3 count */
+ 15708, /* 10.77 kPa 4 count */
+ 15676, /* 10.83 kPa 5 count */
+ 15644, /* 10.88 kPa 6 count */
+ 15613, /* 10.94 kPa 7 count */
+ 15581, /* 10.99 kPa 8 count */
+ 15550, /* 11.04 kPa 9 count */
+ 15519, /* 11.10 kPa 10 count */
+ 15488, /* 11.15 kPa 11 count */
+ 15457, /* 11.21 kPa 12 count */
+ 15426, /* 11.26 kPa 13 count */
+ 15396, /* 11.32 kPa 14 count */
+ 15366, /* 11.37 kPa 15 count */
+ 15335, /* 11.42 kPa 16 count */
+ 15305, /* 11.48 kPa 17 count */
+ 15275, /* 11.53 kPa 18 count */
+ 15246, /* 11.59 kPa 19 count */
+ 15216, /* 11.64 kPa 20 count */
+ 15187, /* 11.70 kPa 21 count */
+ 15157, /* 11.75 kPa 22 count */
+ 15128, /* 11.80 kPa 23 count */
+ 15099, /* 11.86 kPa 24 count */
+ 15070, /* 11.91 kPa 25 count */
+ 15041, /* 11.97 kPa 26 count */
+ 15012, /* 12.02 kPa 27 count */
+ 14984, /* 12.08 kPa 28 count */
+ 14955, /* 12.13 kPa 29 count */
+ 14927, /* 12.18 kPa 30 count */
+ 14899, /* 12.24 kPa 31 count */
+ 14871, /* 12.29 kPa 32 count */
+ 14843, /* 12.35 kPa 33 count */
+ 14815, /* 12.40 kPa 34 count */
+ 14787, /* 12.46 kPa 35 count */
+ 14760, /* 12.51 kPa 36 count */
+ 14732, /* 12.56 kPa 37 count */
+ 14705, /* 12.62 kPa 38 count */
+ 14678, /* 12.67 kPa 39 count */
+ 14651, /* 12.73 kPa 40 count */
+ 14624, /* 12.78 kPa 41 count */
+ 14597, /* 12.84 kPa 42 count */
+ 14570, /* 12.89 kPa 43 count */
+ 14543, /* 12.94 kPa 44 count */
+ 14517, /* 13.00 kPa 45 count */
+ 14490, /* 13.05 kPa 46 count */
+ 14464, /* 13.11 kPa 47 count */
+ 14438, /* 13.16 kPa 48 count */
+ 14412, /* 13.22 kPa 49 count */
+ 14386, /* 13.27 kPa 50 count */
+ 14360, /* 13.32 kPa 51 count */
+ 14334, /* 13.38 kPa 52 count */
+ 14308, /* 13.43 kPa 53 count */
+ 14283, /* 13.49 kPa 54 count */
+ 14257, /* 13.54 kPa 55 count */
+ 14232, /* 13.60 kPa 56 count */
+ 14207, /* 13.65 kPa 57 count */
+ 14182, /* 13.70 kPa 58 count */
+ 14156, /* 13.76 kPa 59 count */
+ 14132, /* 13.81 kPa 60 count */
+ 14107, /* 13.87 kPa 61 count */
+ 14082, /* 13.92 kPa 62 count */
+ 14057, /* 13.98 kPa 63 count */
+ 14033, /* 14.03 kPa 64 count */
+ 14008, /* 14.08 kPa 65 count */
+ 13984, /* 14.14 kPa 66 count */
+ 13959, /* 14.19 kPa 67 count */
+ 13935, /* 14.25 kPa 68 count */
+ 13911, /* 14.30 kPa 69 count */
+ 13887, /* 14.36 kPa 70 count */
+ 13863, /* 14.41 kPa 71 count */
+ 13839, /* 14.46 kPa 72 count */
+ 13816, /* 14.52 kPa 73 count */
+ 13792, /* 14.57 kPa 74 count */
+ 13768, /* 14.63 kPa 75 count */
+ 13745, /* 14.68 kPa 76 count */
+ 13721, /* 14.74 kPa 77 count */
+ 13698, /* 14.79 kPa 78 count */
+ 13675, /* 14.84 kPa 79 count */
+ 13652, /* 14.90 kPa 80 count */
+ 13629, /* 14.95 kPa 81 count */
+ 13606, /* 15.01 kPa 82 count */
+ 13583, /* 15.06 kPa 83 count */
+ 13560, /* 15.12 kPa 84 count */
+ 13537, /* 15.17 kPa 85 count */
+ 13515, /* 15.22 kPa 86 count */
+ 13492, /* 15.28 kPa 87 count */
+ 13470, /* 15.33 kPa 88 count */
+ 13447, /* 15.39 kPa 89 count */
+ 13425, /* 15.44 kPa 90 count */
+ 13403, /* 15.50 kPa 91 count */
+ 13380, /* 15.55 kPa 92 count */
+ 13358, /* 15.60 kPa 93 count */
+ 13336, /* 15.66 kPa 94 count */
+ 13314, /* 15.71 kPa 95 count */
+ 13292, /* 15.77 kPa 96 count */
+ 13271, /* 15.82 kPa 97 count */
+ 13249, /* 15.87 kPa 98 count */
+ 13227, /* 15.93 kPa 99 count */
+ 13206, /* 15.98 kPa 100 count */
+ 13184, /* 16.04 kPa 101 count */
+ 13163, /* 16.09 kPa 102 count */
+ 13141, /* 16.15 kPa 103 count */
+ 13120, /* 16.20 kPa 104 count */
+ 13099, /* 16.25 kPa 105 count */
+ 13078, /* 16.31 kPa 106 count */
+ 13057, /* 16.36 kPa 107 count */
+ 13036, /* 16.42 kPa 108 count */
+ 13015, /* 16.47 kPa 109 count */
+ 12994, /* 16.53 kPa 110 count */
+ 12973, /* 16.58 kPa 111 count */
+ 12952, /* 16.63 kPa 112 count */
+ 12932, /* 16.69 kPa 113 count */
+ 12911, /* 16.74 kPa 114 count */
+ 12891, /* 16.80 kPa 115 count */
+ 12870, /* 16.85 kPa 116 count */
+ 12850, /* 16.91 kPa 117 count */
+ 12829, /* 16.96 kPa 118 count */
+ 12809, /* 17.01 kPa 119 count */
+ 12789, /* 17.07 kPa 120 count */
+ 12769, /* 17.12 kPa 121 count */
+ 12749, /* 17.18 kPa 122 count */
+ 12729, /* 17.23 kPa 123 count */
+ 12709, /* 17.29 kPa 124 count */
+ 12689, /* 17.34 kPa 125 count */
+ 12669, /* 17.39 kPa 126 count */
+ 12649, /* 17.45 kPa 127 count */
+ 12630, /* 17.50 kPa 128 count */
+ 12610, /* 17.56 kPa 129 count */
+ 12590, /* 17.61 kPa 130 count */
+ 12571, /* 17.67 kPa 131 count */
+ 12551, /* 17.72 kPa 132 count */
+ 12532, /* 17.77 kPa 133 count */
+ 12513, /* 17.83 kPa 134 count */
+ 12493, /* 17.88 kPa 135 count */
+ 12474, /* 17.94 kPa 136 count */
+ 12455, /* 17.99 kPa 137 count */
+ 12436, /* 18.05 kPa 138 count */
+ 12417, /* 18.10 kPa 139 count */
+ 12398, /* 18.15 kPa 140 count */
+ 12379, /* 18.21 kPa 141 count */
+ 12360, /* 18.26 kPa 142 count */
+ 12341, /* 18.32 kPa 143 count */
+ 12323, /* 18.37 kPa 144 count */
+ 12304, /* 18.43 kPa 145 count */
+ 12285, /* 18.48 kPa 146 count */
+ 12267, /* 18.53 kPa 147 count */
+ 12248, /* 18.59 kPa 148 count */
+ 12230, /* 18.64 kPa 149 count */
+ 12211, /* 18.70 kPa 150 count */
+ 12193, /* 18.75 kPa 151 count */
+ 12174, /* 18.81 kPa 152 count */
+ 12156, /* 18.86 kPa 153 count */
+ 12138, /* 18.91 kPa 154 count */
+ 12120, /* 18.97 kPa 155 count */
+ 12102, /* 19.02 kPa 156 count */
+ 12084, /* 19.08 kPa 157 count */
+ 12065, /* 19.13 kPa 158 count */
+ 12048, /* 19.19 kPa 159 count */
+ 12030, /* 19.24 kPa 160 count */
+ 12012, /* 19.29 kPa 161 count */
+ 11994, /* 19.35 kPa 162 count */
+ 11976, /* 19.40 kPa 163 count */
+ 11958, /* 19.46 kPa 164 count */
+ 11941, /* 19.51 kPa 165 count */
+ 11923, /* 19.57 kPa 166 count */
+ 11906, /* 19.62 kPa 167 count */
+ 11888, /* 19.67 kPa 168 count */
+ 11871, /* 19.73 kPa 169 count */
+ 11853, /* 19.78 kPa 170 count */
+ 11836, /* 19.84 kPa 171 count */
+ 11818, /* 19.89 kPa 172 count */
+ 11801, /* 19.95 kPa 173 count */
+ 11784, /* 20.00 kPa 174 count */
+ 11767, /* 20.05 kPa 175 count */
+ 11750, /* 20.11 kPa 176 count */
+ 11733, /* 20.16 kPa 177 count */
+ 11715, /* 20.22 kPa 178 count */
+ 11698, /* 20.27 kPa 179 count */
+ 11682, /* 20.33 kPa 180 count */
+ 11665, /* 20.38 kPa 181 count */
+ 11648, /* 20.43 kPa 182 count */
+ 11631, /* 20.49 kPa 183 count */
+ 11614, /* 20.54 kPa 184 count */
+ 11597, /* 20.60 kPa 185 count */
+ 11581, /* 20.65 kPa 186 count */
+ 11564, /* 20.71 kPa 187 count */
+ 11547, /* 20.76 kPa 188 count */
+ 11531, /* 20.81 kPa 189 count */
+ 11514, /* 20.87 kPa 190 count */
+ 11498, /* 20.92 kPa 191 count */
+ 11481, /* 20.98 kPa 192 count */
+ 11465, /* 21.03 kPa 193 count */
+ 11449, /* 21.09 kPa 194 count */
+ 11432, /* 21.14 kPa 195 count */
+ 11416, /* 21.19 kPa 196 count */
+ 11400, /* 21.25 kPa 197 count */
+ 11384, /* 21.30 kPa 198 count */
+ 11368, /* 21.36 kPa 199 count */
+ 11352, /* 21.41 kPa 200 count */
+ 11336, /* 21.47 kPa 201 count */
+ 11319, /* 21.52 kPa 202 count */
+ 11304, /* 21.57 kPa 203 count */
+ 11288, /* 21.63 kPa 204 count */
+ 11272, /* 21.68 kPa 205 count */
+ 11256, /* 21.74 kPa 206 count */
+ 11240, /* 21.79 kPa 207 count */
+ 11224, /* 21.85 kPa 208 count */
+ 11208, /* 21.90 kPa 209 count */
+ 11193, /* 21.95 kPa 210 count */
+ 11177, /* 22.01 kPa 211 count */
+ 11162, /* 22.06 kPa 212 count */
+ 11146, /* 22.12 kPa 213 count */
+ 11130, /* 22.17 kPa 214 count */
+ 11115, /* 22.23 kPa 215 count */
+ 11099, /* 22.28 kPa 216 count */
+ 11084, /* 22.33 kPa 217 count */
+ 11069, /* 22.39 kPa 218 count */
+ 11053, /* 22.44 kPa 219 count */
+ 11038, /* 22.50 kPa 220 count */
+ 11023, /* 22.55 kPa 221 count */
+ 11007, /* 22.61 kPa 222 count */
+ 10992, /* 22.66 kPa 223 count */
+ 10977, /* 22.71 kPa 224 count */
+ 10962, /* 22.77 kPa 225 count */
+ 10947, /* 22.82 kPa 226 count */
+ 10932, /* 22.88 kPa 227 count */
+ 10917, /* 22.93 kPa 228 count */
+ 10902, /* 22.99 kPa 229 count */
+ 10887, /* 23.04 kPa 230 count */
+ 10872, /* 23.09 kPa 231 count */
+ 10857, /* 23.15 kPa 232 count */
+ 10842, /* 23.20 kPa 233 count */
+ 10827, /* 23.26 kPa 234 count */
+ 10812, /* 23.31 kPa 235 count */
+ 10797, /* 23.37 kPa 236 count */
+ 10782, /* 23.42 kPa 237 count */
+ 10768, /* 23.47 kPa 238 count */
+ 10753, /* 23.53 kPa 239 count */
+ 10738, /* 23.58 kPa 240 count */
+ 10723, /* 23.64 kPa 241 count */
+ 10709, /* 23.69 kPa 242 count */
+ 10694, /* 23.75 kPa 243 count */
+ 10679, /* 23.80 kPa 244 count */
+ 10665, /* 23.85 kPa 245 count */
+ 10650, /* 23.91 kPa 246 count */
+ 10636, /* 23.96 kPa 247 count */
+ 10621, /* 24.02 kPa 248 count */
+ 10607, /* 24.07 kPa 249 count */
+ 10592, /* 24.13 kPa 250 count */
+ 10578, /* 24.18 kPa 251 count */
+ 10563, /* 24.23 kPa 252 count */
+ 10549, /* 24.29 kPa 253 count */
+ 10535, /* 24.34 kPa 254 count */
+ 10520, /* 24.40 kPa 255 count */
+ 10506, /* 24.45 kPa 256 count */
+ 10492, /* 24.51 kPa 257 count */
+ 10478, /* 24.56 kPa 258 count */
+ 10463, /* 24.61 kPa 259 count */
+ 10449, /* 24.67 kPa 260 count */
+ 10435, /* 24.72 kPa 261 count */
+ 10421, /* 24.78 kPa 262 count */
+ 10407, /* 24.83 kPa 263 count */
+ 10393, /* 24.89 kPa 264 count */
+ 10379, /* 24.94 kPa 265 count */
+ 10364, /* 24.99 kPa 266 count */
+ 10350, /* 25.05 kPa 267 count */
+ 10336, /* 25.10 kPa 268 count */
+ 10322, /* 25.16 kPa 269 count */
+ 10309, /* 25.21 kPa 270 count */
+ 10295, /* 25.27 kPa 271 count */
+ 10281, /* 25.32 kPa 272 count */
+ 10267, /* 25.37 kPa 273 count */
+ 10253, /* 25.43 kPa 274 count */
+ 10239, /* 25.48 kPa 275 count */
+ 10225, /* 25.54 kPa 276 count */
+ 10212, /* 25.59 kPa 277 count */
+ 10198, /* 25.65 kPa 278 count */
+ 10184, /* 25.70 kPa 279 count */
+ 10170, /* 25.75 kPa 280 count */
+ 10157, /* 25.81 kPa 281 count */
+ 10143, /* 25.86 kPa 282 count */
+ 10129, /* 25.92 kPa 283 count */
+ 10116, /* 25.97 kPa 284 count */
+ 10102, /* 26.03 kPa 285 count */
+ 10089, /* 26.08 kPa 286 count */
+ 10075, /* 26.13 kPa 287 count */
+ 10062, /* 26.19 kPa 288 count */
+ 10048, /* 26.24 kPa 289 count */
+ 10035, /* 26.30 kPa 290 count */
+ 10021, /* 26.35 kPa 291 count */
+ 10008, /* 26.41 kPa 292 count */
+ 9994, /* 26.46 kPa 293 count */
+ 9981, /* 26.51 kPa 294 count */
+ 9967, /* 26.57 kPa 295 count */
+ 9954, /* 26.62 kPa 296 count */
+ 9941, /* 26.68 kPa 297 count */
+ 9928, /* 26.73 kPa 298 count */
+ 9914, /* 26.79 kPa 299 count */
+ 9901, /* 26.84 kPa 300 count */
+ 9888, /* 26.89 kPa 301 count */
+ 9875, /* 26.95 kPa 302 count */
+ 9861, /* 27.00 kPa 303 count */
+ 9848, /* 27.06 kPa 304 count */
+ 9835, /* 27.11 kPa 305 count */
+ 9822, /* 27.17 kPa 306 count */
+ 9809, /* 27.22 kPa 307 count */
+ 9796, /* 27.27 kPa 308 count */
+ 9783, /* 27.33 kPa 309 count */
+ 9770, /* 27.38 kPa 310 count */
+ 9757, /* 27.44 kPa 311 count */
+ 9744, /* 27.49 kPa 312 count */
+ 9731, /* 27.55 kPa 313 count */
+ 9718, /* 27.60 kPa 314 count */
+ 9705, /* 27.65 kPa 315 count */
+ 9692, /* 27.71 kPa 316 count */
+ 9679, /* 27.76 kPa 317 count */
+ 9666, /* 27.82 kPa 318 count */
+ 9653, /* 27.87 kPa 319 count */
+ 9640, /* 27.93 kPa 320 count */
+ 9627, /* 27.98 kPa 321 count */
+ 9615, /* 28.03 kPa 322 count */
+ 9602, /* 28.09 kPa 323 count */
+ 9589, /* 28.14 kPa 324 count */
+ 9576, /* 28.20 kPa 325 count */
+ 9564, /* 28.25 kPa 326 count */
+ 9551, /* 28.31 kPa 327 count */
+ 9538, /* 28.36 kPa 328 count */
+ 9526, /* 28.41 kPa 329 count */
+ 9513, /* 28.47 kPa 330 count */
+ 9500, /* 28.52 kPa 331 count */
+ 9488, /* 28.58 kPa 332 count */
+ 9475, /* 28.63 kPa 333 count */
+ 9463, /* 28.69 kPa 334 count */
+ 9450, /* 28.74 kPa 335 count */
+ 9438, /* 28.79 kPa 336 count */
+ 9425, /* 28.85 kPa 337 count */
+ 9413, /* 28.90 kPa 338 count */
+ 9400, /* 28.96 kPa 339 count */
+ 9388, /* 29.01 kPa 340 count */
+ 9375, /* 29.07 kPa 341 count */
+ 9363, /* 29.12 kPa 342 count */
+ 9350, /* 29.17 kPa 343 count */
+ 9338, /* 29.23 kPa 344 count */
+ 9326, /* 29.28 kPa 345 count */
+ 9313, /* 29.34 kPa 346 count */
+ 9301, /* 29.39 kPa 347 count */
+ 9289, /* 29.44 kPa 348 count */
+ 9276, /* 29.50 kPa 349 count */
+ 9264, /* 29.55 kPa 350 count */
+ 9252, /* 29.61 kPa 351 count */
+ 9240, /* 29.66 kPa 352 count */
+ 9227, /* 29.72 kPa 353 count */
+ 9215, /* 29.77 kPa 354 count */
+ 9203, /* 29.82 kPa 355 count */
+ 9191, /* 29.88 kPa 356 count */
+ 9179, /* 29.93 kPa 357 count */
+ 9167, /* 29.99 kPa 358 count */
+ 9155, /* 30.04 kPa 359 count */
+ 9142, /* 30.10 kPa 360 count */
+ 9130, /* 30.15 kPa 361 count */
+ 9118, /* 30.20 kPa 362 count */
+ 9106, /* 30.26 kPa 363 count */
+ 9094, /* 30.31 kPa 364 count */
+ 9082, /* 30.37 kPa 365 count */
+ 9070, /* 30.42 kPa 366 count */
+ 9058, /* 30.48 kPa 367 count */
+ 9046, /* 30.53 kPa 368 count */
+ 9035, /* 30.58 kPa 369 count */
+ 9023, /* 30.64 kPa 370 count */
+ 9011, /* 30.69 kPa 371 count */
+ 8999, /* 30.75 kPa 372 count */
+ 8987, /* 30.80 kPa 373 count */
+ 8975, /* 30.86 kPa 374 count */
+ 8963, /* 30.91 kPa 375 count */
+ 8952, /* 30.96 kPa 376 count */
+ 8940, /* 31.02 kPa 377 count */
+ 8928, /* 31.07 kPa 378 count */
+ 8916, /* 31.13 kPa 379 count */
+ 8904, /* 31.18 kPa 380 count */
+ 8893, /* 31.24 kPa 381 count */
+ 8881, /* 31.29 kPa 382 count */
+ 8869, /* 31.34 kPa 383 count */
+ 8858, /* 31.40 kPa 384 count */
+ 8846, /* 31.45 kPa 385 count */
+ 8834, /* 31.51 kPa 386 count */
+ 8823, /* 31.56 kPa 387 count */
+ 8811, /* 31.62 kPa 388 count */
+ 8800, /* 31.67 kPa 389 count */
+ 8788, /* 31.72 kPa 390 count */
+ 8776, /* 31.78 kPa 391 count */
+ 8765, /* 31.83 kPa 392 count */
+ 8753, /* 31.89 kPa 393 count */
+ 8742, /* 31.94 kPa 394 count */
+ 8730, /* 32.00 kPa 395 count */
+ 8719, /* 32.05 kPa 396 count */
+ 8707, /* 32.10 kPa 397 count */
+ 8696, /* 32.16 kPa 398 count */
+ 8684, /* 32.21 kPa 399 count */
+ 8673, /* 32.27 kPa 400 count */
+ 8662, /* 32.32 kPa 401 count */
+ 8650, /* 32.38 kPa 402 count */
+ 8639, /* 32.43 kPa 403 count */
+ 8628, /* 32.48 kPa 404 count */
+ 8616, /* 32.54 kPa 405 count */
+ 8605, /* 32.59 kPa 406 count */
+ 8594, /* 32.65 kPa 407 count */
+ 8582, /* 32.70 kPa 408 count */
+ 8571, /* 32.76 kPa 409 count */
+ 8560, /* 32.81 kPa 410 count */
+ 8548, /* 32.86 kPa 411 count */
+ 8537, /* 32.92 kPa 412 count */
+ 8526, /* 32.97 kPa 413 count */
+ 8515, /* 33.03 kPa 414 count */
+ 8504, /* 33.08 kPa 415 count */
+ 8492, /* 33.14 kPa 416 count */
+ 8481, /* 33.19 kPa 417 count */
+ 8470, /* 33.24 kPa 418 count */
+ 8459, /* 33.30 kPa 419 count */
+ 8448, /* 33.35 kPa 420 count */
+ 8437, /* 33.41 kPa 421 count */
+ 8426, /* 33.46 kPa 422 count */
+ 8415, /* 33.52 kPa 423 count */
+ 8403, /* 33.57 kPa 424 count */
+ 8392, /* 33.62 kPa 425 count */
+ 8381, /* 33.68 kPa 426 count */
+ 8370, /* 33.73 kPa 427 count */
+ 8359, /* 33.79 kPa 428 count */
+ 8348, /* 33.84 kPa 429 count */
+ 8337, /* 33.90 kPa 430 count */
+ 8326, /* 33.95 kPa 431 count */
+ 8316, /* 34.00 kPa 432 count */
+ 8305, /* 34.06 kPa 433 count */
+ 8294, /* 34.11 kPa 434 count */
+ 8283, /* 34.17 kPa 435 count */
+ 8272, /* 34.22 kPa 436 count */
+ 8261, /* 34.28 kPa 437 count */
+ 8250, /* 34.33 kPa 438 count */
+ 8239, /* 34.38 kPa 439 count */
+ 8228, /* 34.44 kPa 440 count */
+ 8218, /* 34.49 kPa 441 count */
+ 8207, /* 34.55 kPa 442 count */
+ 8196, /* 34.60 kPa 443 count */
+ 8185, /* 34.66 kPa 444 count */
+ 8175, /* 34.71 kPa 445 count */
+ 8164, /* 34.76 kPa 446 count */
+ 8153, /* 34.82 kPa 447 count */
+ 8142, /* 34.87 kPa 448 count */
+ 8132, /* 34.93 kPa 449 count */
+ 8121, /* 34.98 kPa 450 count */
+ 8110, /* 35.04 kPa 451 count */
+ 8100, /* 35.09 kPa 452 count */
+ 8089, /* 35.14 kPa 453 count */
+ 8078, /* 35.20 kPa 454 count */
+ 8068, /* 35.25 kPa 455 count */
+ 8057, /* 35.31 kPa 456 count */
+ 8046, /* 35.36 kPa 457 count */
+ 8036, /* 35.42 kPa 458 count */
+ 8025, /* 35.47 kPa 459 count */
+ 8015, /* 35.52 kPa 460 count */
+ 8004, /* 35.58 kPa 461 count */
+ 7994, /* 35.63 kPa 462 count */
+ 7983, /* 35.69 kPa 463 count */
+ 7973, /* 35.74 kPa 464 count */
+ 7962, /* 35.80 kPa 465 count */
+ 7952, /* 35.85 kPa 466 count */
+ 7941, /* 35.90 kPa 467 count */
+ 7931, /* 35.96 kPa 468 count */
+ 7920, /* 36.01 kPa 469 count */
+ 7910, /* 36.07 kPa 470 count */
+ 7899, /* 36.12 kPa 471 count */
+ 7889, /* 36.18 kPa 472 count */
+ 7879, /* 36.23 kPa 473 count */
+ 7868, /* 36.28 kPa 474 count */
+ 7858, /* 36.34 kPa 475 count */
+ 7847, /* 36.39 kPa 476 count */
+ 7837, /* 36.45 kPa 477 count */
+ 7827, /* 36.50 kPa 478 count */
+ 7816, /* 36.56 kPa 479 count */
+ 7806, /* 36.61 kPa 480 count */
+ 7796, /* 36.66 kPa 481 count */
+ 7785, /* 36.72 kPa 482 count */
+ 7775, /* 36.77 kPa 483 count */
+ 7765, /* 36.83 kPa 484 count */
+ 7755, /* 36.88 kPa 485 count */
+ 7744, /* 36.94 kPa 486 count */
+ 7734, /* 36.99 kPa 487 count */
+ 7724, /* 37.04 kPa 488 count */
+ 7714, /* 37.10 kPa 489 count */
+ 7704, /* 37.15 kPa 490 count */
+ 7693, /* 37.21 kPa 491 count */
+ 7683, /* 37.26 kPa 492 count */
+ 7673, /* 37.32 kPa 493 count */
+ 7663, /* 37.37 kPa 494 count */
+ 7653, /* 37.42 kPa 495 count */
+ 7643, /* 37.48 kPa 496 count */
+ 7633, /* 37.53 kPa 497 count */
+ 7623, /* 37.59 kPa 498 count */
+ 7613, /* 37.64 kPa 499 count */
+ 7602, /* 37.70 kPa 500 count */
+ 7592, /* 37.75 kPa 501 count */
+ 7582, /* 37.80 kPa 502 count */
+ 7572, /* 37.86 kPa 503 count */
+ 7562, /* 37.91 kPa 504 count */
+ 7552, /* 37.97 kPa 505 count */
+ 7542, /* 38.02 kPa 506 count */
+ 7532, /* 38.08 kPa 507 count */
+ 7522, /* 38.13 kPa 508 count */
+ 7512, /* 38.18 kPa 509 count */
+ 7502, /* 38.24 kPa 510 count */
+ 7492, /* 38.29 kPa 511 count */
+ 7483, /* 38.35 kPa 512 count */
+ 7473, /* 38.40 kPa 513 count */
+ 7463, /* 38.46 kPa 514 count */
+ 7453, /* 38.51 kPa 515 count */
+ 7443, /* 38.56 kPa 516 count */
+ 7433, /* 38.62 kPa 517 count */
+ 7423, /* 38.67 kPa 518 count */
+ 7413, /* 38.73 kPa 519 count */
+ 7403, /* 38.78 kPa 520 count */
+ 7394, /* 38.84 kPa 521 count */
+ 7384, /* 38.89 kPa 522 count */
+ 7374, /* 38.94 kPa 523 count */
+ 7364, /* 39.00 kPa 524 count */
+ 7354, /* 39.05 kPa 525 count */
+ 7345, /* 39.11 kPa 526 count */
+ 7335, /* 39.16 kPa 527 count */
+ 7325, /* 39.22 kPa 528 count */
+ 7315, /* 39.27 kPa 529 count */
+ 7306, /* 39.32 kPa 530 count */
+ 7296, /* 39.38 kPa 531 count */
+ 7286, /* 39.43 kPa 532 count */
+ 7277, /* 39.49 kPa 533 count */
+ 7267, /* 39.54 kPa 534 count */
+ 7257, /* 39.60 kPa 535 count */
+ 7248, /* 39.65 kPa 536 count */
+ 7238, /* 39.70 kPa 537 count */
+ 7228, /* 39.76 kPa 538 count */
+ 7219, /* 39.81 kPa 539 count */
+ 7209, /* 39.87 kPa 540 count */
+ 7199, /* 39.92 kPa 541 count */
+ 7190, /* 39.98 kPa 542 count */
+ 7180, /* 40.03 kPa 543 count */
+ 7171, /* 40.08 kPa 544 count */
+ 7161, /* 40.14 kPa 545 count */
+ 7152, /* 40.19 kPa 546 count */
+ 7142, /* 40.25 kPa 547 count */
+ 7132, /* 40.30 kPa 548 count */
+ 7123, /* 40.36 kPa 549 count */
+ 7113, /* 40.41 kPa 550 count */
+ 7104, /* 40.46 kPa 551 count */
+ 7094, /* 40.52 kPa 552 count */
+ 7085, /* 40.57 kPa 553 count */
+ 7075, /* 40.63 kPa 554 count */
+ 7066, /* 40.68 kPa 555 count */
+ 7056, /* 40.74 kPa 556 count */
+ 7047, /* 40.79 kPa 557 count */
+ 7038, /* 40.84 kPa 558 count */
+ 7028, /* 40.90 kPa 559 count */
+ 7019, /* 40.95 kPa 560 count */
+ 7009, /* 41.01 kPa 561 count */
+ 7000, /* 41.06 kPa 562 count */
+ 6991, /* 41.12 kPa 563 count */
+ 6981, /* 41.17 kPa 564 count */
+ 6972, /* 41.22 kPa 565 count */
+ 6962, /* 41.28 kPa 566 count */
+ 6953, /* 41.33 kPa 567 count */
+ 6944, /* 41.39 kPa 568 count */
+ 6934, /* 41.44 kPa 569 count */
+ 6925, /* 41.50 kPa 570 count */
+ 6916, /* 41.55 kPa 571 count */
+ 6907, /* 41.60 kPa 572 count */
+ 6897, /* 41.66 kPa 573 count */
+ 6888, /* 41.71 kPa 574 count */
+ 6879, /* 41.77 kPa 575 count */
+ 6869, /* 41.82 kPa 576 count */
+ 6860, /* 41.88 kPa 577 count */
+ 6851, /* 41.93 kPa 578 count */
+ 6842, /* 41.98 kPa 579 count */
+ 6833, /* 42.04 kPa 580 count */
+ 6823, /* 42.09 kPa 581 count */
+ 6814, /* 42.15 kPa 582 count */
+ 6805, /* 42.20 kPa 583 count */
+ 6796, /* 42.26 kPa 584 count */
+ 6787, /* 42.31 kPa 585 count */
+ 6777, /* 42.36 kPa 586 count */
+ 6768, /* 42.42 kPa 587 count */
+ 6759, /* 42.47 kPa 588 count */
+ 6750, /* 42.53 kPa 589 count */
+ 6741, /* 42.58 kPa 590 count */
+ 6732, /* 42.64 kPa 591 count */
+ 6723, /* 42.69 kPa 592 count */
+ 6714, /* 42.74 kPa 593 count */
+ 6705, /* 42.80 kPa 594 count */
+ 6695, /* 42.85 kPa 595 count */
+ 6686, /* 42.91 kPa 596 count */
+ 6677, /* 42.96 kPa 597 count */
+ 6668, /* 43.01 kPa 598 count */
+ 6659, /* 43.07 kPa 599 count */
+ 6650, /* 43.12 kPa 600 count */
+ 6641, /* 43.18 kPa 601 count */
+ 6632, /* 43.23 kPa 602 count */
+ 6623, /* 43.29 kPa 603 count */
+ 6614, /* 43.34 kPa 604 count */
+ 6605, /* 43.39 kPa 605 count */
+ 6596, /* 43.45 kPa 606 count */
+ 6587, /* 43.50 kPa 607 count */
+ 6578, /* 43.56 kPa 608 count */
+ 6569, /* 43.61 kPa 609 count */
+ 6560, /* 43.67 kPa 610 count */
+ 6552, /* 43.72 kPa 611 count */
+ 6543, /* 43.77 kPa 612 count */
+ 6534, /* 43.83 kPa 613 count */
+ 6525, /* 43.88 kPa 614 count */
+ 6516, /* 43.94 kPa 615 count */
+ 6507, /* 43.99 kPa 616 count */
+ 6498, /* 44.05 kPa 617 count */
+ 6489, /* 44.10 kPa 618 count */
+ 6480, /* 44.15 kPa 619 count */
+ 6472, /* 44.21 kPa 620 count */
+ 6463, /* 44.26 kPa 621 count */
+ 6454, /* 44.32 kPa 622 count */
+ 6445, /* 44.37 kPa 623 count */
+ 6436, /* 44.43 kPa 624 count */
+ 6427, /* 44.48 kPa 625 count */
+ 6419, /* 44.53 kPa 626 count */
+ 6410, /* 44.59 kPa 627 count */
+ 6401, /* 44.64 kPa 628 count */
+ 6392, /* 44.70 kPa 629 count */
+ 6384, /* 44.75 kPa 630 count */
+ 6375, /* 44.81 kPa 631 count */
+ 6366, /* 44.86 kPa 632 count */
+ 6357, /* 44.91 kPa 633 count */
+ 6349, /* 44.97 kPa 634 count */
+ 6340, /* 45.02 kPa 635 count */
+ 6331, /* 45.08 kPa 636 count */
+ 6322, /* 45.13 kPa 637 count */
+ 6314, /* 45.19 kPa 638 count */
+ 6305, /* 45.24 kPa 639 count */
+ 6296, /* 45.29 kPa 640 count */
+ 6288, /* 45.35 kPa 641 count */
+ 6279, /* 45.40 kPa 642 count */
+ 6270, /* 45.46 kPa 643 count */
+ 6262, /* 45.51 kPa 644 count */
+ 6253, /* 45.57 kPa 645 count */
+ 6245, /* 45.62 kPa 646 count */
+ 6236, /* 45.67 kPa 647 count */
+ 6227, /* 45.73 kPa 648 count */
+ 6219, /* 45.78 kPa 649 count */
+ 6210, /* 45.84 kPa 650 count */
+ 6202, /* 45.89 kPa 651 count */
+ 6193, /* 45.95 kPa 652 count */
+ 6184, /* 46.00 kPa 653 count */
+ 6176, /* 46.05 kPa 654 count */
+ 6167, /* 46.11 kPa 655 count */
+ 6159, /* 46.16 kPa 656 count */
+ 6150, /* 46.22 kPa 657 count */
+ 6142, /* 46.27 kPa 658 count */
+ 6133, /* 46.33 kPa 659 count */
+ 6125, /* 46.38 kPa 660 count */
+ 6116, /* 46.43 kPa 661 count */
+ 6108, /* 46.49 kPa 662 count */
+ 6099, /* 46.54 kPa 663 count */
+ 6091, /* 46.60 kPa 664 count */
+ 6082, /* 46.65 kPa 665 count */
+ 6074, /* 46.71 kPa 666 count */
+ 6065, /* 46.76 kPa 667 count */
+ 6057, /* 46.81 kPa 668 count */
+ 6048, /* 46.87 kPa 669 count */
+ 6040, /* 46.92 kPa 670 count */
+ 6032, /* 46.98 kPa 671 count */
+ 6023, /* 47.03 kPa 672 count */
+ 6015, /* 47.09 kPa 673 count */
+ 6006, /* 47.14 kPa 674 count */
+ 5998, /* 47.19 kPa 675 count */
+ 5990, /* 47.25 kPa 676 count */
+ 5981, /* 47.30 kPa 677 count */
+ 5973, /* 47.36 kPa 678 count */
+ 5964, /* 47.41 kPa 679 count */
+ 5956, /* 47.47 kPa 680 count */
+ 5948, /* 47.52 kPa 681 count */
+ 5939, /* 47.57 kPa 682 count */
+ 5931, /* 47.63 kPa 683 count */
+ 5923, /* 47.68 kPa 684 count */
+ 5914, /* 47.74 kPa 685 count */
+ 5906, /* 47.79 kPa 686 count */
+ 5898, /* 47.85 kPa 687 count */
+ 5890, /* 47.90 kPa 688 count */
+ 5881, /* 47.95 kPa 689 count */
+ 5873, /* 48.01 kPa 690 count */
+ 5865, /* 48.06 kPa 691 count */
+ 5856, /* 48.12 kPa 692 count */
+ 5848, /* 48.17 kPa 693 count */
+ 5840, /* 48.23 kPa 694 count */
+ 5832, /* 48.28 kPa 695 count */
+ 5823, /* 48.33 kPa 696 count */
+ 5815, /* 48.39 kPa 697 count */
+ 5807, /* 48.44 kPa 698 count */
+ 5799, /* 48.50 kPa 699 count */
+ 5791, /* 48.55 kPa 700 count */
+ 5782, /* 48.61 kPa 701 count */
+ 5774, /* 48.66 kPa 702 count */
+ 5766, /* 48.71 kPa 703 count */
+ 5758, /* 48.77 kPa 704 count */
+ 5750, /* 48.82 kPa 705 count */
+ 5742, /* 48.88 kPa 706 count */
+ 5733, /* 48.93 kPa 707 count */
+ 5725, /* 48.99 kPa 708 count */
+ 5717, /* 49.04 kPa 709 count */
+ 5709, /* 49.09 kPa 710 count */
+ 5701, /* 49.15 kPa 711 count */
+ 5693, /* 49.20 kPa 712 count */
+ 5685, /* 49.26 kPa 713 count */
+ 5677, /* 49.31 kPa 714 count */
+ 5668, /* 49.37 kPa 715 count */
+ 5660, /* 49.42 kPa 716 count */
+ 5652, /* 49.47 kPa 717 count */
+ 5644, /* 49.53 kPa 718 count */
+ 5636, /* 49.58 kPa 719 count */
+ 5628, /* 49.64 kPa 720 count */
+ 5620, /* 49.69 kPa 721 count */
+ 5612, /* 49.75 kPa 722 count */
+ 5604, /* 49.80 kPa 723 count */
+ 5596, /* 49.85 kPa 724 count */
+ 5588, /* 49.91 kPa 725 count */
+ 5580, /* 49.96 kPa 726 count */
+ 5572, /* 50.02 kPa 727 count */
+ 5564, /* 50.07 kPa 728 count */
+ 5556, /* 50.13 kPa 729 count */
+ 5548, /* 50.18 kPa 730 count */
+ 5540, /* 50.23 kPa 731 count */
+ 5532, /* 50.29 kPa 732 count */
+ 5524, /* 50.34 kPa 733 count */
+ 5516, /* 50.40 kPa 734 count */
+ 5508, /* 50.45 kPa 735 count */
+ 5500, /* 50.51 kPa 736 count */
+ 5492, /* 50.56 kPa 737 count */
+ 5484, /* 50.61 kPa 738 count */
+ 5476, /* 50.67 kPa 739 count */
+ 5468, /* 50.72 kPa 740 count */
+ 5461, /* 50.78 kPa 741 count */
+ 5453, /* 50.83 kPa 742 count */
+ 5445, /* 50.89 kPa 743 count */
+ 5437, /* 50.94 kPa 744 count */
+ 5429, /* 50.99 kPa 745 count */
+ 5421, /* 51.05 kPa 746 count */
+ 5413, /* 51.10 kPa 747 count */
+ 5405, /* 51.16 kPa 748 count */
+ 5398, /* 51.21 kPa 749 count */
+ 5390, /* 51.27 kPa 750 count */
+ 5382, /* 51.32 kPa 751 count */
+ 5374, /* 51.37 kPa 752 count */
+ 5366, /* 51.43 kPa 753 count */
+ 5358, /* 51.48 kPa 754 count */
+ 5351, /* 51.54 kPa 755 count */
+ 5343, /* 51.59 kPa 756 count */
+ 5335, /* 51.65 kPa 757 count */
+ 5327, /* 51.70 kPa 758 count */
+ 5319, /* 51.75 kPa 759 count */
+ 5312, /* 51.81 kPa 760 count */
+ 5304, /* 51.86 kPa 761 count */
+ 5296, /* 51.92 kPa 762 count */
+ 5288, /* 51.97 kPa 763 count */
+ 5281, /* 52.03 kPa 764 count */
+ 5273, /* 52.08 kPa 765 count */
+ 5265, /* 52.13 kPa 766 count */
+ 5257, /* 52.19 kPa 767 count */
+ 5250, /* 52.24 kPa 768 count */
+ 5242, /* 52.30 kPa 769 count */
+ 5234, /* 52.35 kPa 770 count */
+ 5226, /* 52.41 kPa 771 count */
+ 5219, /* 52.46 kPa 772 count */
+ 5211, /* 52.51 kPa 773 count */
+ 5203, /* 52.57 kPa 774 count */
+ 5196, /* 52.62 kPa 775 count */
+ 5188, /* 52.68 kPa 776 count */
+ 5180, /* 52.73 kPa 777 count */
+ 5173, /* 52.79 kPa 778 count */
+ 5165, /* 52.84 kPa 779 count */
+ 5157, /* 52.89 kPa 780 count */
+ 5150, /* 52.95 kPa 781 count */
+ 5142, /* 53.00 kPa 782 count */
+ 5134, /* 53.06 kPa 783 count */
+ 5127, /* 53.11 kPa 784 count */
+ 5119, /* 53.17 kPa 785 count */
+ 5112, /* 53.22 kPa 786 count */
+ 5104, /* 53.27 kPa 787 count */
+ 5096, /* 53.33 kPa 788 count */
+ 5089, /* 53.38 kPa 789 count */
+ 5081, /* 53.44 kPa 790 count */
+ 5074, /* 53.49 kPa 791 count */
+ 5066, /* 53.55 kPa 792 count */
+ 5058, /* 53.60 kPa 793 count */
+ 5051, /* 53.65 kPa 794 count */
+ 5043, /* 53.71 kPa 795 count */
+ 5036, /* 53.76 kPa 796 count */
+ 5028, /* 53.82 kPa 797 count */
+ 5021, /* 53.87 kPa 798 count */
+ 5013, /* 53.93 kPa 799 count */
+ 5006, /* 53.98 kPa 800 count */
+ 4998, /* 54.03 kPa 801 count */
+ 4991, /* 54.09 kPa 802 count */
+ 4983, /* 54.14 kPa 803 count */
+ 4976, /* 54.20 kPa 804 count */
+ 4968, /* 54.25 kPa 805 count */
+ 4961, /* 54.31 kPa 806 count */
+ 4953, /* 54.36 kPa 807 count */
+ 4946, /* 54.41 kPa 808 count */
+ 4938, /* 54.47 kPa 809 count */
+ 4931, /* 54.52 kPa 810 count */
+ 4923, /* 54.58 kPa 811 count */
+ 4916, /* 54.63 kPa 812 count */
+ 4908, /* 54.69 kPa 813 count */
+ 4901, /* 54.74 kPa 814 count */
+ 4893, /* 54.79 kPa 815 count */
+ 4886, /* 54.85 kPa 816 count */
+ 4879, /* 54.90 kPa 817 count */
+ 4871, /* 54.96 kPa 818 count */
+ 4864, /* 55.01 kPa 819 count */
+ 4856, /* 55.07 kPa 820 count */
+ 4849, /* 55.12 kPa 821 count */
+ 4842, /* 55.17 kPa 822 count */
+ 4834, /* 55.23 kPa 823 count */
+ 4827, /* 55.28 kPa 824 count */
+ 4819, /* 55.34 kPa 825 count */
+ 4812, /* 55.39 kPa 826 count */
+ 4805, /* 55.45 kPa 827 count */
+ 4797, /* 55.50 kPa 828 count */
+ 4790, /* 55.55 kPa 829 count */
+ 4783, /* 55.61 kPa 830 count */
+ 4775, /* 55.66 kPa 831 count */
+ 4768, /* 55.72 kPa 832 count */
+ 4761, /* 55.77 kPa 833 count */
+ 4753, /* 55.83 kPa 834 count */
+ 4746, /* 55.88 kPa 835 count */
+ 4739, /* 55.93 kPa 836 count */
+ 4731, /* 55.99 kPa 837 count */
+ 4724, /* 56.04 kPa 838 count */
+ 4717, /* 56.10 kPa 839 count */
+ 4709, /* 56.15 kPa 840 count */
+ 4702, /* 56.21 kPa 841 count */
+ 4695, /* 56.26 kPa 842 count */
+ 4688, /* 56.31 kPa 843 count */
+ 4680, /* 56.37 kPa 844 count */
+ 4673, /* 56.42 kPa 845 count */
+ 4666, /* 56.48 kPa 846 count */
+ 4659, /* 56.53 kPa 847 count */
+ 4651, /* 56.58 kPa 848 count */
+ 4644, /* 56.64 kPa 849 count */
+ 4637, /* 56.69 kPa 850 count */
+ 4630, /* 56.75 kPa 851 count */
+ 4622, /* 56.80 kPa 852 count */
+ 4615, /* 56.86 kPa 853 count */
+ 4608, /* 56.91 kPa 854 count */
+ 4601, /* 56.96 kPa 855 count */
+ 4594, /* 57.02 kPa 856 count */
+ 4586, /* 57.07 kPa 857 count */
+ 4579, /* 57.13 kPa 858 count */
+ 4572, /* 57.18 kPa 859 count */
+ 4565, /* 57.24 kPa 860 count */
+ 4558, /* 57.29 kPa 861 count */
+ 4550, /* 57.34 kPa 862 count */
+ 4543, /* 57.40 kPa 863 count */
+ 4536, /* 57.45 kPa 864 count */
+ 4529, /* 57.51 kPa 865 count */
+ 4522, /* 57.56 kPa 866 count */
+ 4515, /* 57.62 kPa 867 count */
+ 4508, /* 57.67 kPa 868 count */
+ 4500, /* 57.72 kPa 869 count */
+ 4493, /* 57.78 kPa 870 count */
+ 4486, /* 57.83 kPa 871 count */
+ 4479, /* 57.89 kPa 872 count */
+ 4472, /* 57.94 kPa 873 count */
+ 4465, /* 58.00 kPa 874 count */
+ 4458, /* 58.05 kPa 875 count */
+ 4451, /* 58.10 kPa 876 count */
+ 4444, /* 58.16 kPa 877 count */
+ 4437, /* 58.21 kPa 878 count */
+ 4429, /* 58.27 kPa 879 count */
+ 4422, /* 58.32 kPa 880 count */
+ 4415, /* 58.38 kPa 881 count */
+ 4408, /* 58.43 kPa 882 count */
+ 4401, /* 58.48 kPa 883 count */
+ 4394, /* 58.54 kPa 884 count */
+ 4387, /* 58.59 kPa 885 count */
+ 4380, /* 58.65 kPa 886 count */
+ 4373, /* 58.70 kPa 887 count */
+ 4366, /* 58.76 kPa 888 count */
+ 4359, /* 58.81 kPa 889 count */
+ 4352, /* 58.86 kPa 890 count */
+ 4345, /* 58.92 kPa 891 count */
+ 4338, /* 58.97 kPa 892 count */
+ 4331, /* 59.03 kPa 893 count */
+ 4324, /* 59.08 kPa 894 count */
+ 4317, /* 59.14 kPa 895 count */
+ 4310, /* 59.19 kPa 896 count */
+ 4303, /* 59.24 kPa 897 count */
+ 4296, /* 59.30 kPa 898 count */
+ 4289, /* 59.35 kPa 899 count */
+ 4282, /* 59.41 kPa 900 count */
+ 4275, /* 59.46 kPa 901 count */
+ 4268, /* 59.52 kPa 902 count */
+ 4261, /* 59.57 kPa 903 count */
+ 4254, /* 59.62 kPa 904 count */
+ 4247, /* 59.68 kPa 905 count */
+ 4240, /* 59.73 kPa 906 count */
+ 4234, /* 59.79 kPa 907 count */
+ 4227, /* 59.84 kPa 908 count */
+ 4220, /* 59.90 kPa 909 count */
+ 4213, /* 59.95 kPa 910 count */
+ 4206, /* 60.00 kPa 911 count */
+ 4199, /* 60.06 kPa 912 count */
+ 4192, /* 60.11 kPa 913 count */
+ 4185, /* 60.17 kPa 914 count */
+ 4178, /* 60.22 kPa 915 count */
+ 4171, /* 60.28 kPa 916 count */
+ 4164, /* 60.33 kPa 917 count */
+ 4158, /* 60.38 kPa 918 count */
+ 4151, /* 60.44 kPa 919 count */
+ 4144, /* 60.49 kPa 920 count */
+ 4137, /* 60.55 kPa 921 count */
+ 4130, /* 60.60 kPa 922 count */
+ 4123, /* 60.66 kPa 923 count */
+ 4116, /* 60.71 kPa 924 count */
+ 4110, /* 60.76 kPa 925 count */
+ 4103, /* 60.82 kPa 926 count */
+ 4096, /* 60.87 kPa 927 count */
+ 4089, /* 60.93 kPa 928 count */
+ 4082, /* 60.98 kPa 929 count */
+ 4076, /* 61.04 kPa 930 count */
+ 4069, /* 61.09 kPa 931 count */
+ 4062, /* 61.14 kPa 932 count */
+ 4055, /* 61.20 kPa 933 count */
+ 4048, /* 61.25 kPa 934 count */
+ 4042, /* 61.31 kPa 935 count */
+ 4035, /* 61.36 kPa 936 count */
+ 4028, /* 61.42 kPa 937 count */
+ 4021, /* 61.47 kPa 938 count */
+ 4014, /* 61.52 kPa 939 count */
+ 4008, /* 61.58 kPa 940 count */
+ 4001, /* 61.63 kPa 941 count */
+ 3994, /* 61.69 kPa 942 count */
+ 3987, /* 61.74 kPa 943 count */
+ 3981, /* 61.80 kPa 944 count */
+ 3974, /* 61.85 kPa 945 count */
+ 3967, /* 61.90 kPa 946 count */
+ 3960, /* 61.96 kPa 947 count */
+ 3954, /* 62.01 kPa 948 count */
+ 3947, /* 62.07 kPa 949 count */
+ 3940, /* 62.12 kPa 950 count */
+ 3934, /* 62.18 kPa 951 count */
+ 3927, /* 62.23 kPa 952 count */
+ 3920, /* 62.28 kPa 953 count */
+ 3913, /* 62.34 kPa 954 count */
+ 3907, /* 62.39 kPa 955 count */
+ 3900, /* 62.45 kPa 956 count */
+ 3893, /* 62.50 kPa 957 count */
+ 3887, /* 62.56 kPa 958 count */
+ 3880, /* 62.61 kPa 959 count */
+ 3873, /* 62.66 kPa 960 count */
+ 3867, /* 62.72 kPa 961 count */
+ 3860, /* 62.77 kPa 962 count */
+ 3853, /* 62.83 kPa 963 count */
+ 3847, /* 62.88 kPa 964 count */
+ 3840, /* 62.94 kPa 965 count */
+ 3833, /* 62.99 kPa 966 count */
+ 3827, /* 63.04 kPa 967 count */
+ 3820, /* 63.10 kPa 968 count */
+ 3814, /* 63.15 kPa 969 count */
+ 3807, /* 63.21 kPa 970 count */
+ 3800, /* 63.26 kPa 971 count */
+ 3794, /* 63.32 kPa 972 count */
+ 3787, /* 63.37 kPa 973 count */
+ 3780, /* 63.42 kPa 974 count */
+ 3774, /* 63.48 kPa 975 count */
+ 3767, /* 63.53 kPa 976 count */
+ 3761, /* 63.59 kPa 977 count */
+ 3754, /* 63.64 kPa 978 count */
+ 3748, /* 63.70 kPa 979 count */
+ 3741, /* 63.75 kPa 980 count */
+ 3734, /* 63.80 kPa 981 count */
+ 3728, /* 63.86 kPa 982 count */
+ 3721, /* 63.91 kPa 983 count */
+ 3715, /* 63.97 kPa 984 count */
+ 3708, /* 64.02 kPa 985 count */
+ 3702, /* 64.08 kPa 986 count */
+ 3695, /* 64.13 kPa 987 count */
+ 3688, /* 64.18 kPa 988 count */
+ 3682, /* 64.24 kPa 989 count */
+ 3675, /* 64.29 kPa 990 count */
+ 3669, /* 64.35 kPa 991 count */
+ 3662, /* 64.40 kPa 992 count */
+ 3656, /* 64.46 kPa 993 count */
+ 3649, /* 64.51 kPa 994 count */
+ 3643, /* 64.56 kPa 995 count */
+ 3636, /* 64.62 kPa 996 count */
+ 3630, /* 64.67 kPa 997 count */
+ 3623, /* 64.73 kPa 998 count */
+ 3617, /* 64.78 kPa 999 count */
+ 3610, /* 64.84 kPa 1000 count */
+ 3604, /* 64.89 kPa 1001 count */
+ 3597, /* 64.94 kPa 1002 count */
+ 3591, /* 65.00 kPa 1003 count */
+ 3584, /* 65.05 kPa 1004 count */
+ 3578, /* 65.11 kPa 1005 count */
+ 3571, /* 65.16 kPa 1006 count */
+ 3565, /* 65.22 kPa 1007 count */
+ 3559, /* 65.27 kPa 1008 count */
+ 3552, /* 65.32 kPa 1009 count */
+ 3546, /* 65.38 kPa 1010 count */
+ 3539, /* 65.43 kPa 1011 count */
+ 3533, /* 65.49 kPa 1012 count */
+ 3526, /* 65.54 kPa 1013 count */
+ 3520, /* 65.60 kPa 1014 count */
+ 3514, /* 65.65 kPa 1015 count */
+ 3507, /* 65.70 kPa 1016 count */
+ 3501, /* 65.76 kPa 1017 count */
+ 3494, /* 65.81 kPa 1018 count */
+ 3488, /* 65.87 kPa 1019 count */
+ 3481, /* 65.92 kPa 1020 count */
+ 3475, /* 65.98 kPa 1021 count */
+ 3469, /* 66.03 kPa 1022 count */
+ 3462, /* 66.08 kPa 1023 count */
+ 3456, /* 66.14 kPa 1024 count */
+ 3450, /* 66.19 kPa 1025 count */
+ 3443, /* 66.25 kPa 1026 count */
+ 3437, /* 66.30 kPa 1027 count */
+ 3430, /* 66.36 kPa 1028 count */
+ 3424, /* 66.41 kPa 1029 count */
+ 3418, /* 66.46 kPa 1030 count */
+ 3411, /* 66.52 kPa 1031 count */
+ 3405, /* 66.57 kPa 1032 count */
+ 3399, /* 66.63 kPa 1033 count */
+ 3392, /* 66.68 kPa 1034 count */
+ 3386, /* 66.74 kPa 1035 count */
+ 3380, /* 66.79 kPa 1036 count */
+ 3373, /* 66.84 kPa 1037 count */
+ 3367, /* 66.90 kPa 1038 count */
+ 3361, /* 66.95 kPa 1039 count */
+ 3354, /* 67.01 kPa 1040 count */
+ 3348, /* 67.06 kPa 1041 count */
+ 3342, /* 67.12 kPa 1042 count */
+ 3335, /* 67.17 kPa 1043 count */
+ 3329, /* 67.22 kPa 1044 count */
+ 3323, /* 67.28 kPa 1045 count */
+ 3316, /* 67.33 kPa 1046 count */
+ 3310, /* 67.39 kPa 1047 count */
+ 3304, /* 67.44 kPa 1048 count */
+ 3298, /* 67.50 kPa 1049 count */
+ 3291, /* 67.55 kPa 1050 count */
+ 3285, /* 67.60 kPa 1051 count */
+ 3279, /* 67.66 kPa 1052 count */
+ 3273, /* 67.71 kPa 1053 count */
+ 3266, /* 67.77 kPa 1054 count */
+ 3260, /* 67.82 kPa 1055 count */
+ 3254, /* 67.88 kPa 1056 count */
+ 3248, /* 67.93 kPa 1057 count */
+ 3241, /* 67.98 kPa 1058 count */
+ 3235, /* 68.04 kPa 1059 count */
+ 3229, /* 68.09 kPa 1060 count */
+ 3223, /* 68.15 kPa 1061 count */
+ 3216, /* 68.20 kPa 1062 count */
+ 3210, /* 68.26 kPa 1063 count */
+ 3204, /* 68.31 kPa 1064 count */
+ 3198, /* 68.36 kPa 1065 count */
+ 3191, /* 68.42 kPa 1066 count */
+ 3185, /* 68.47 kPa 1067 count */
+ 3179, /* 68.53 kPa 1068 count */
+ 3173, /* 68.58 kPa 1069 count */
+ 3167, /* 68.64 kPa 1070 count */
+ 3160, /* 68.69 kPa 1071 count */
+ 3154, /* 68.74 kPa 1072 count */
+ 3148, /* 68.80 kPa 1073 count */
+ 3142, /* 68.85 kPa 1074 count */
+ 3136, /* 68.91 kPa 1075 count */
+ 3130, /* 68.96 kPa 1076 count */
+ 3123, /* 69.02 kPa 1077 count */
+ 3117, /* 69.07 kPa 1078 count */
+ 3111, /* 69.12 kPa 1079 count */
+ 3105, /* 69.18 kPa 1080 count */
+ 3099, /* 69.23 kPa 1081 count */
+ 3093, /* 69.29 kPa 1082 count */
+ 3087, /* 69.34 kPa 1083 count */
+ 3080, /* 69.40 kPa 1084 count */
+ 3074, /* 69.45 kPa 1085 count */
+ 3068, /* 69.50 kPa 1086 count */
+ 3062, /* 69.56 kPa 1087 count */
+ 3056, /* 69.61 kPa 1088 count */
+ 3050, /* 69.67 kPa 1089 count */
+ 3044, /* 69.72 kPa 1090 count */
+ 3037, /* 69.78 kPa 1091 count */
+ 3031, /* 69.83 kPa 1092 count */
+ 3025, /* 69.88 kPa 1093 count */
+ 3019, /* 69.94 kPa 1094 count */
+ 3013, /* 69.99 kPa 1095 count */
+ 3007, /* 70.05 kPa 1096 count */
+ 3001, /* 70.10 kPa 1097 count */
+ 2995, /* 70.15 kPa 1098 count */
+ 2989, /* 70.21 kPa 1099 count */
+ 2983, /* 70.26 kPa 1100 count */
+ 2977, /* 70.32 kPa 1101 count */
+ 2970, /* 70.37 kPa 1102 count */
+ 2964, /* 70.43 kPa 1103 count */
+ 2958, /* 70.48 kPa 1104 count */
+ 2952, /* 70.53 kPa 1105 count */
+ 2946, /* 70.59 kPa 1106 count */
+ 2940, /* 70.64 kPa 1107 count */
+ 2934, /* 70.70 kPa 1108 count */
+ 2928, /* 70.75 kPa 1109 count */
+ 2922, /* 70.81 kPa 1110 count */
+ 2916, /* 70.86 kPa 1111 count */
+ 2910, /* 70.91 kPa 1112 count */
+ 2904, /* 70.97 kPa 1113 count */
+ 2898, /* 71.02 kPa 1114 count */
+ 2892, /* 71.08 kPa 1115 count */
+ 2886, /* 71.13 kPa 1116 count */
+ 2880, /* 71.19 kPa 1117 count */
+ 2874, /* 71.24 kPa 1118 count */
+ 2868, /* 71.29 kPa 1119 count */
+ 2862, /* 71.35 kPa 1120 count */
+ 2856, /* 71.40 kPa 1121 count */
+ 2850, /* 71.46 kPa 1122 count */
+ 2844, /* 71.51 kPa 1123 count */
+ 2838, /* 71.57 kPa 1124 count */
+ 2832, /* 71.62 kPa 1125 count */
+ 2826, /* 71.67 kPa 1126 count */
+ 2820, /* 71.73 kPa 1127 count */
+ 2814, /* 71.78 kPa 1128 count */
+ 2808, /* 71.84 kPa 1129 count */
+ 2802, /* 71.89 kPa 1130 count */
+ 2796, /* 71.95 kPa 1131 count */
+ 2790, /* 72.00 kPa 1132 count */
+ 2784, /* 72.05 kPa 1133 count */
+ 2778, /* 72.11 kPa 1134 count */
+ 2772, /* 72.16 kPa 1135 count */
+ 2766, /* 72.22 kPa 1136 count */
+ 2760, /* 72.27 kPa 1137 count */
+ 2754, /* 72.33 kPa 1138 count */
+ 2748, /* 72.38 kPa 1139 count */
+ 2743, /* 72.43 kPa 1140 count */
+ 2737, /* 72.49 kPa 1141 count */
+ 2731, /* 72.54 kPa 1142 count */
+ 2725, /* 72.60 kPa 1143 count */
+ 2719, /* 72.65 kPa 1144 count */
+ 2713, /* 72.71 kPa 1145 count */
+ 2707, /* 72.76 kPa 1146 count */
+ 2701, /* 72.81 kPa 1147 count */
+ 2695, /* 72.87 kPa 1148 count */
+ 2689, /* 72.92 kPa 1149 count */
+ 2683, /* 72.98 kPa 1150 count */
+ 2678, /* 73.03 kPa 1151 count */
+ 2672, /* 73.09 kPa 1152 count */
+ 2666, /* 73.14 kPa 1153 count */
+ 2660, /* 73.19 kPa 1154 count */
+ 2654, /* 73.25 kPa 1155 count */
+ 2648, /* 73.30 kPa 1156 count */
+ 2642, /* 73.36 kPa 1157 count */
+ 2636, /* 73.41 kPa 1158 count */
+ 2631, /* 73.47 kPa 1159 count */
+ 2625, /* 73.52 kPa 1160 count */
+ 2619, /* 73.57 kPa 1161 count */
+ 2613, /* 73.63 kPa 1162 count */
+ 2607, /* 73.68 kPa 1163 count */
+ 2601, /* 73.74 kPa 1164 count */
+ 2595, /* 73.79 kPa 1165 count */
+ 2590, /* 73.85 kPa 1166 count */
+ 2584, /* 73.90 kPa 1167 count */
+ 2578, /* 73.95 kPa 1168 count */
+ 2572, /* 74.01 kPa 1169 count */
+ 2566, /* 74.06 kPa 1170 count */
+ 2560, /* 74.12 kPa 1171 count */
+ 2555, /* 74.17 kPa 1172 count */
+ 2549, /* 74.23 kPa 1173 count */
+ 2543, /* 74.28 kPa 1174 count */
+ 2537, /* 74.33 kPa 1175 count */
+ 2531, /* 74.39 kPa 1176 count */
+ 2526, /* 74.44 kPa 1177 count */
+ 2520, /* 74.50 kPa 1178 count */
+ 2514, /* 74.55 kPa 1179 count */
+ 2508, /* 74.61 kPa 1180 count */
+ 2502, /* 74.66 kPa 1181 count */
+ 2497, /* 74.71 kPa 1182 count */
+ 2491, /* 74.77 kPa 1183 count */
+ 2485, /* 74.82 kPa 1184 count */
+ 2479, /* 74.88 kPa 1185 count */
+ 2473, /* 74.93 kPa 1186 count */
+ 2468, /* 74.99 kPa 1187 count */
+ 2462, /* 75.04 kPa 1188 count */
+ 2456, /* 75.09 kPa 1189 count */
+ 2450, /* 75.15 kPa 1190 count */
+ 2445, /* 75.20 kPa 1191 count */
+ 2439, /* 75.26 kPa 1192 count */
+ 2433, /* 75.31 kPa 1193 count */
+ 2427, /* 75.37 kPa 1194 count */
+ 2422, /* 75.42 kPa 1195 count */
+ 2416, /* 75.47 kPa 1196 count */
+ 2410, /* 75.53 kPa 1197 count */
+ 2405, /* 75.58 kPa 1198 count */
+ 2399, /* 75.64 kPa 1199 count */
+ 2393, /* 75.69 kPa 1200 count */
+ 2387, /* 75.75 kPa 1201 count */
+ 2382, /* 75.80 kPa 1202 count */
+ 2376, /* 75.85 kPa 1203 count */
+ 2370, /* 75.91 kPa 1204 count */
+ 2364, /* 75.96 kPa 1205 count */
+ 2359, /* 76.02 kPa 1206 count */
+ 2353, /* 76.07 kPa 1207 count */
+ 2347, /* 76.13 kPa 1208 count */
+ 2342, /* 76.18 kPa 1209 count */
+ 2336, /* 76.23 kPa 1210 count */
+ 2330, /* 76.29 kPa 1211 count */
+ 2325, /* 76.34 kPa 1212 count */
+ 2319, /* 76.40 kPa 1213 count */
+ 2313, /* 76.45 kPa 1214 count */
+ 2308, /* 76.51 kPa 1215 count */
+ 2302, /* 76.56 kPa 1216 count */
+ 2296, /* 76.61 kPa 1217 count */
+ 2291, /* 76.67 kPa 1218 count */
+ 2285, /* 76.72 kPa 1219 count */
+ 2279, /* 76.78 kPa 1220 count */
+ 2274, /* 76.83 kPa 1221 count */
+ 2268, /* 76.89 kPa 1222 count */
+ 2262, /* 76.94 kPa 1223 count */
+ 2257, /* 76.99 kPa 1224 count */
+ 2251, /* 77.05 kPa 1225 count */
+ 2245, /* 77.10 kPa 1226 count */
+ 2240, /* 77.16 kPa 1227 count */
+ 2234, /* 77.21 kPa 1228 count */
+ 2228, /* 77.27 kPa 1229 count */
+ 2223, /* 77.32 kPa 1230 count */
+ 2217, /* 77.37 kPa 1231 count */
+ 2212, /* 77.43 kPa 1232 count */
+ 2206, /* 77.48 kPa 1233 count */
+ 2200, /* 77.54 kPa 1234 count */
+ 2195, /* 77.59 kPa 1235 count */
+ 2189, /* 77.65 kPa 1236 count */
+ 2184, /* 77.70 kPa 1237 count */
+ 2178, /* 77.75 kPa 1238 count */
+ 2172, /* 77.81 kPa 1239 count */
+ 2167, /* 77.86 kPa 1240 count */
+ 2161, /* 77.92 kPa 1241 count */
+ 2156, /* 77.97 kPa 1242 count */
+ 2150, /* 78.03 kPa 1243 count */
+ 2144, /* 78.08 kPa 1244 count */
+ 2139, /* 78.13 kPa 1245 count */
+ 2133, /* 78.19 kPa 1246 count */
+ 2128, /* 78.24 kPa 1247 count */
+ 2122, /* 78.30 kPa 1248 count */
+ 2117, /* 78.35 kPa 1249 count */
+ 2111, /* 78.41 kPa 1250 count */
+ 2105, /* 78.46 kPa 1251 count */
+ 2100, /* 78.51 kPa 1252 count */
+ 2094, /* 78.57 kPa 1253 count */
+ 2089, /* 78.62 kPa 1254 count */
+ 2083, /* 78.68 kPa 1255 count */
+ 2078, /* 78.73 kPa 1256 count */
+ 2072, /* 78.79 kPa 1257 count */
+ 2067, /* 78.84 kPa 1258 count */
+ 2061, /* 78.89 kPa 1259 count */
+ 2056, /* 78.95 kPa 1260 count */
+ 2050, /* 79.00 kPa 1261 count */
+ 2045, /* 79.06 kPa 1262 count */
+ 2039, /* 79.11 kPa 1263 count */
+ 2033, /* 79.17 kPa 1264 count */
+ 2028, /* 79.22 kPa 1265 count */
+ 2022, /* 79.27 kPa 1266 count */
+ 2017, /* 79.33 kPa 1267 count */
+ 2011, /* 79.38 kPa 1268 count */
+ 2006, /* 79.44 kPa 1269 count */
+ 2000, /* 79.49 kPa 1270 count */
+ 1995, /* 79.55 kPa 1271 count */
+ 1989, /* 79.60 kPa 1272 count */
+ 1984, /* 79.65 kPa 1273 count */
+ 1978, /* 79.71 kPa 1274 count */
+ 1973, /* 79.76 kPa 1275 count */
+ 1967, /* 79.82 kPa 1276 count */
+ 1962, /* 79.87 kPa 1277 count */
+ 1957, /* 79.93 kPa 1278 count */
+ 1951, /* 79.98 kPa 1279 count */
+ 1946, /* 80.03 kPa 1280 count */
+ 1940, /* 80.09 kPa 1281 count */
+ 1935, /* 80.14 kPa 1282 count */
+ 1929, /* 80.20 kPa 1283 count */
+ 1924, /* 80.25 kPa 1284 count */
+ 1918, /* 80.31 kPa 1285 count */
+ 1913, /* 80.36 kPa 1286 count */
+ 1907, /* 80.41 kPa 1287 count */
+ 1902, /* 80.47 kPa 1288 count */
+ 1896, /* 80.52 kPa 1289 count */
+ 1891, /* 80.58 kPa 1290 count */
+ 1886, /* 80.63 kPa 1291 count */
+ 1880, /* 80.69 kPa 1292 count */
+ 1875, /* 80.74 kPa 1293 count */
+ 1869, /* 80.79 kPa 1294 count */
+ 1864, /* 80.85 kPa 1295 count */
+ 1858, /* 80.90 kPa 1296 count */
+ 1853, /* 80.96 kPa 1297 count */
+ 1848, /* 81.01 kPa 1298 count */
+ 1842, /* 81.07 kPa 1299 count */
+ 1837, /* 81.12 kPa 1300 count */
+ 1831, /* 81.17 kPa 1301 count */
+ 1826, /* 81.23 kPa 1302 count */
+ 1821, /* 81.28 kPa 1303 count */
+ 1815, /* 81.34 kPa 1304 count */
+ 1810, /* 81.39 kPa 1305 count */
+ 1804, /* 81.45 kPa 1306 count */
+ 1799, /* 81.50 kPa 1307 count */
+ 1794, /* 81.55 kPa 1308 count */
+ 1788, /* 81.61 kPa 1309 count */
+ 1783, /* 81.66 kPa 1310 count */
+ 1777, /* 81.72 kPa 1311 count */
+ 1772, /* 81.77 kPa 1312 count */
+ 1767, /* 81.83 kPa 1313 count */
+ 1761, /* 81.88 kPa 1314 count */
+ 1756, /* 81.93 kPa 1315 count */
+ 1751, /* 81.99 kPa 1316 count */
+ 1745, /* 82.04 kPa 1317 count */
+ 1740, /* 82.10 kPa 1318 count */
+ 1735, /* 82.15 kPa 1319 count */
+ 1729, /* 82.21 kPa 1320 count */
+ 1724, /* 82.26 kPa 1321 count */
+ 1718, /* 82.31 kPa 1322 count */
+ 1713, /* 82.37 kPa 1323 count */
+ 1708, /* 82.42 kPa 1324 count */
+ 1702, /* 82.48 kPa 1325 count */
+ 1697, /* 82.53 kPa 1326 count */
+ 1692, /* 82.59 kPa 1327 count */
+ 1686, /* 82.64 kPa 1328 count */
+ 1681, /* 82.69 kPa 1329 count */
+ 1676, /* 82.75 kPa 1330 count */
+ 1670, /* 82.80 kPa 1331 count */
+ 1665, /* 82.86 kPa 1332 count */
+ 1660, /* 82.91 kPa 1333 count */
+ 1655, /* 82.97 kPa 1334 count */
+ 1649, /* 83.02 kPa 1335 count */
+ 1644, /* 83.07 kPa 1336 count */
+ 1639, /* 83.13 kPa 1337 count */
+ 1633, /* 83.18 kPa 1338 count */
+ 1628, /* 83.24 kPa 1339 count */
+ 1623, /* 83.29 kPa 1340 count */
+ 1617, /* 83.35 kPa 1341 count */
+ 1612, /* 83.40 kPa 1342 count */
+ 1607, /* 83.45 kPa 1343 count */
+ 1602, /* 83.51 kPa 1344 count */
+ 1596, /* 83.56 kPa 1345 count */
+ 1591, /* 83.62 kPa 1346 count */
+ 1586, /* 83.67 kPa 1347 count */
+ 1580, /* 83.72 kPa 1348 count */
+ 1575, /* 83.78 kPa 1349 count */
+ 1570, /* 83.83 kPa 1350 count */
+ 1565, /* 83.89 kPa 1351 count */
+ 1559, /* 83.94 kPa 1352 count */
+ 1554, /* 84.00 kPa 1353 count */
+ 1549, /* 84.05 kPa 1354 count */
+ 1544, /* 84.10 kPa 1355 count */
+ 1538, /* 84.16 kPa 1356 count */
+ 1533, /* 84.21 kPa 1357 count */
+ 1528, /* 84.27 kPa 1358 count */
+ 1523, /* 84.32 kPa 1359 count */
+ 1517, /* 84.38 kPa 1360 count */
+ 1512, /* 84.43 kPa 1361 count */
+ 1507, /* 84.48 kPa 1362 count */
+ 1502, /* 84.54 kPa 1363 count */
+ 1496, /* 84.59 kPa 1364 count */
+ 1491, /* 84.65 kPa 1365 count */
+ 1486, /* 84.70 kPa 1366 count */
+ 1481, /* 84.76 kPa 1367 count */
+ 1475, /* 84.81 kPa 1368 count */
+ 1470, /* 84.86 kPa 1369 count */
+ 1465, /* 84.92 kPa 1370 count */
+ 1460, /* 84.97 kPa 1371 count */
+ 1455, /* 85.03 kPa 1372 count */
+ 1449, /* 85.08 kPa 1373 count */
+ 1444, /* 85.14 kPa 1374 count */
+ 1439, /* 85.19 kPa 1375 count */
+ 1434, /* 85.24 kPa 1376 count */
+ 1429, /* 85.30 kPa 1377 count */
+ 1423, /* 85.35 kPa 1378 count */
+ 1418, /* 85.41 kPa 1379 count */
+ 1413, /* 85.46 kPa 1380 count */
+ 1408, /* 85.52 kPa 1381 count */
+ 1403, /* 85.57 kPa 1382 count */
+ 1398, /* 85.62 kPa 1383 count */
+ 1392, /* 85.68 kPa 1384 count */
+ 1387, /* 85.73 kPa 1385 count */
+ 1382, /* 85.79 kPa 1386 count */
+ 1377, /* 85.84 kPa 1387 count */
+ 1372, /* 85.90 kPa 1388 count */
+ 1366, /* 85.95 kPa 1389 count */
+ 1361, /* 86.00 kPa 1390 count */
+ 1356, /* 86.06 kPa 1391 count */
+ 1351, /* 86.11 kPa 1392 count */
+ 1346, /* 86.17 kPa 1393 count */
+ 1341, /* 86.22 kPa 1394 count */
+ 1336, /* 86.28 kPa 1395 count */
+ 1330, /* 86.33 kPa 1396 count */
+ 1325, /* 86.38 kPa 1397 count */
+ 1320, /* 86.44 kPa 1398 count */
+ 1315, /* 86.49 kPa 1399 count */
+ 1310, /* 86.55 kPa 1400 count */
+ 1305, /* 86.60 kPa 1401 count */
+ 1300, /* 86.66 kPa 1402 count */
+ 1294, /* 86.71 kPa 1403 count */
+ 1289, /* 86.76 kPa 1404 count */
+ 1284, /* 86.82 kPa 1405 count */
+ 1279, /* 86.87 kPa 1406 count */
+ 1274, /* 86.93 kPa 1407 count */
+ 1269, /* 86.98 kPa 1408 count */
+ 1264, /* 87.04 kPa 1409 count */
+ 1259, /* 87.09 kPa 1410 count */
+ 1254, /* 87.14 kPa 1411 count */
+ 1248, /* 87.20 kPa 1412 count */
+ 1243, /* 87.25 kPa 1413 count */
+ 1238, /* 87.31 kPa 1414 count */
+ 1233, /* 87.36 kPa 1415 count */
+ 1228, /* 87.42 kPa 1416 count */
+ 1223, /* 87.47 kPa 1417 count */
+ 1218, /* 87.52 kPa 1418 count */
+ 1213, /* 87.58 kPa 1419 count */
+ 1208, /* 87.63 kPa 1420 count */
+ 1203, /* 87.69 kPa 1421 count */
+ 1198, /* 87.74 kPa 1422 count */
+ 1192, /* 87.80 kPa 1423 count */
+ 1187, /* 87.85 kPa 1424 count */
+ 1182, /* 87.90 kPa 1425 count */
+ 1177, /* 87.96 kPa 1426 count */
+ 1172, /* 88.01 kPa 1427 count */
+ 1167, /* 88.07 kPa 1428 count */
+ 1162, /* 88.12 kPa 1429 count */
+ 1157, /* 88.18 kPa 1430 count */
+ 1152, /* 88.23 kPa 1431 count */
+ 1147, /* 88.28 kPa 1432 count */
+ 1142, /* 88.34 kPa 1433 count */
+ 1137, /* 88.39 kPa 1434 count */
+ 1132, /* 88.45 kPa 1435 count */
+ 1127, /* 88.50 kPa 1436 count */
+ 1122, /* 88.56 kPa 1437 count */
+ 1117, /* 88.61 kPa 1438 count */
+ 1112, /* 88.66 kPa 1439 count */
+ 1107, /* 88.72 kPa 1440 count */
+ 1102, /* 88.77 kPa 1441 count */
+ 1097, /* 88.83 kPa 1442 count */
+ 1091, /* 88.88 kPa 1443 count */
+ 1086, /* 88.94 kPa 1444 count */
+ 1081, /* 88.99 kPa 1445 count */
+ 1076, /* 89.04 kPa 1446 count */
+ 1071, /* 89.10 kPa 1447 count */
+ 1066, /* 89.15 kPa 1448 count */
+ 1061, /* 89.21 kPa 1449 count */
+ 1056, /* 89.26 kPa 1450 count */
+ 1051, /* 89.32 kPa 1451 count */
+ 1046, /* 89.37 kPa 1452 count */
+ 1041, /* 89.42 kPa 1453 count */
+ 1036, /* 89.48 kPa 1454 count */
+ 1031, /* 89.53 kPa 1455 count */
+ 1026, /* 89.59 kPa 1456 count */
+ 1021, /* 89.64 kPa 1457 count */
+ 1016, /* 89.70 kPa 1458 count */
+ 1011, /* 89.75 kPa 1459 count */
+ 1006, /* 89.80 kPa 1460 count */
+ 1001, /* 89.86 kPa 1461 count */
+ 996, /* 89.91 kPa 1462 count */
+ 992, /* 89.97 kPa 1463 count */
+ 987, /* 90.02 kPa 1464 count */
+ 982, /* 90.08 kPa 1465 count */
+ 977, /* 90.13 kPa 1466 count */
+ 972, /* 90.18 kPa 1467 count */
+ 967, /* 90.24 kPa 1468 count */
+ 962, /* 90.29 kPa 1469 count */
+ 957, /* 90.35 kPa 1470 count */
+ 952, /* 90.40 kPa 1471 count */
+ 947, /* 90.46 kPa 1472 count */
+ 942, /* 90.51 kPa 1473 count */
+ 937, /* 90.56 kPa 1474 count */
+ 932, /* 90.62 kPa 1475 count */
+ 927, /* 90.67 kPa 1476 count */
+ 922, /* 90.73 kPa 1477 count */
+ 917, /* 90.78 kPa 1478 count */
+ 912, /* 90.84 kPa 1479 count */
+ 907, /* 90.89 kPa 1480 count */
+ 902, /* 90.94 kPa 1481 count */
+ 897, /* 91.00 kPa 1482 count */
+ 892, /* 91.05 kPa 1483 count */
+ 888, /* 91.11 kPa 1484 count */
+ 883, /* 91.16 kPa 1485 count */
+ 878, /* 91.22 kPa 1486 count */
+ 873, /* 91.27 kPa 1487 count */
+ 868, /* 91.32 kPa 1488 count */
+ 863, /* 91.38 kPa 1489 count */
+ 858, /* 91.43 kPa 1490 count */
+ 853, /* 91.49 kPa 1491 count */
+ 848, /* 91.54 kPa 1492 count */
+ 843, /* 91.60 kPa 1493 count */
+ 838, /* 91.65 kPa 1494 count */
+ 834, /* 91.70 kPa 1495 count */
+ 829, /* 91.76 kPa 1496 count */
+ 824, /* 91.81 kPa 1497 count */
+ 819, /* 91.87 kPa 1498 count */
+ 814, /* 91.92 kPa 1499 count */
+ 809, /* 91.98 kPa 1500 count */
+ 804, /* 92.03 kPa 1501 count */
+ 799, /* 92.08 kPa 1502 count */
+ 794, /* 92.14 kPa 1503 count */
+ 790, /* 92.19 kPa 1504 count */
+ 785, /* 92.25 kPa 1505 count */
+ 780, /* 92.30 kPa 1506 count */
+ 775, /* 92.36 kPa 1507 count */
+ 770, /* 92.41 kPa 1508 count */
+ 765, /* 92.46 kPa 1509 count */
+ 760, /* 92.52 kPa 1510 count */
+ 755, /* 92.57 kPa 1511 count */
+ 751, /* 92.63 kPa 1512 count */
+ 746, /* 92.68 kPa 1513 count */
+ 741, /* 92.74 kPa 1514 count */
+ 736, /* 92.79 kPa 1515 count */
+ 731, /* 92.84 kPa 1516 count */
+ 726, /* 92.90 kPa 1517 count */
+ 721, /* 92.95 kPa 1518 count */
+ 717, /* 93.01 kPa 1519 count */
+ 712, /* 93.06 kPa 1520 count */
+ 707, /* 93.12 kPa 1521 count */
+ 702, /* 93.17 kPa 1522 count */
+ 697, /* 93.22 kPa 1523 count */
+ 692, /* 93.28 kPa 1524 count */
+ 688, /* 93.33 kPa 1525 count */
+ 683, /* 93.39 kPa 1526 count */
+ 678, /* 93.44 kPa 1527 count */
+ 673, /* 93.50 kPa 1528 count */
+ 668, /* 93.55 kPa 1529 count */
+ 664, /* 93.60 kPa 1530 count */
+ 659, /* 93.66 kPa 1531 count */
+ 654, /* 93.71 kPa 1532 count */
+ 649, /* 93.77 kPa 1533 count */
+ 644, /* 93.82 kPa 1534 count */
+ 639, /* 93.88 kPa 1535 count */
+ 635, /* 93.93 kPa 1536 count */
+ 630, /* 93.98 kPa 1537 count */
+ 625, /* 94.04 kPa 1538 count */
+ 620, /* 94.09 kPa 1539 count */
+ 615, /* 94.15 kPa 1540 count */
+ 611, /* 94.20 kPa 1541 count */
+ 606, /* 94.26 kPa 1542 count */
+ 601, /* 94.31 kPa 1543 count */
+ 596, /* 94.36 kPa 1544 count */
+ 591, /* 94.42 kPa 1545 count */
+ 587, /* 94.47 kPa 1546 count */
+ 582, /* 94.53 kPa 1547 count */
+ 577, /* 94.58 kPa 1548 count */
+ 572, /* 94.64 kPa 1549 count */
+ 568, /* 94.69 kPa 1550 count */
+ 563, /* 94.74 kPa 1551 count */
+ 558, /* 94.80 kPa 1552 count */
+ 553, /* 94.85 kPa 1553 count */
+ 549, /* 94.91 kPa 1554 count */
+ 544, /* 94.96 kPa 1555 count */
+ 539, /* 95.02 kPa 1556 count */
+ 534, /* 95.07 kPa 1557 count */
+ 529, /* 95.12 kPa 1558 count */
+ 525, /* 95.18 kPa 1559 count */
+ 520, /* 95.23 kPa 1560 count */
+ 515, /* 95.29 kPa 1561 count */
+ 510, /* 95.34 kPa 1562 count */
+ 506, /* 95.40 kPa 1563 count */
+ 501, /* 95.45 kPa 1564 count */
+ 496, /* 95.50 kPa 1565 count */
+ 492, /* 95.56 kPa 1566 count */
+ 487, /* 95.61 kPa 1567 count */
+ 482, /* 95.67 kPa 1568 count */
+ 477, /* 95.72 kPa 1569 count */
+ 473, /* 95.78 kPa 1570 count */
+ 468, /* 95.83 kPa 1571 count */
+ 463, /* 95.88 kPa 1572 count */
+ 458, /* 95.94 kPa 1573 count */
+ 454, /* 95.99 kPa 1574 count */
+ 449, /* 96.05 kPa 1575 count */
+ 444, /* 96.10 kPa 1576 count */
+ 440, /* 96.16 kPa 1577 count */
+ 435, /* 96.21 kPa 1578 count */
+ 430, /* 96.26 kPa 1579 count */
+ 425, /* 96.32 kPa 1580 count */
+ 421, /* 96.37 kPa 1581 count */
+ 416, /* 96.43 kPa 1582 count */
+ 411, /* 96.48 kPa 1583 count */
+ 407, /* 96.54 kPa 1584 count */
+ 402, /* 96.59 kPa 1585 count */
+ 397, /* 96.64 kPa 1586 count */
+ 392, /* 96.70 kPa 1587 count */
+ 388, /* 96.75 kPa 1588 count */
+ 383, /* 96.81 kPa 1589 count */
+ 378, /* 96.86 kPa 1590 count */
+ 374, /* 96.91 kPa 1591 count */
+ 369, /* 96.97 kPa 1592 count */
+ 364, /* 97.02 kPa 1593 count */
+ 360, /* 97.08 kPa 1594 count */
+ 355, /* 97.13 kPa 1595 count */
+ 350, /* 97.19 kPa 1596 count */
+ 346, /* 97.24 kPa 1597 count */
+ 341, /* 97.29 kPa 1598 count */
+ 336, /* 97.35 kPa 1599 count */
+ 332, /* 97.40 kPa 1600 count */
+ 327, /* 97.46 kPa 1601 count */
+ 322, /* 97.51 kPa 1602 count */
+ 318, /* 97.57 kPa 1603 count */
+ 313, /* 97.62 kPa 1604 count */
+ 308, /* 97.67 kPa 1605 count */
+ 304, /* 97.73 kPa 1606 count */
+ 299, /* 97.78 kPa 1607 count */
+ 294, /* 97.84 kPa 1608 count */
+ 290, /* 97.89 kPa 1609 count */
+ 285, /* 97.95 kPa 1610 count */
+ 280, /* 98.00 kPa 1611 count */
+ 276, /* 98.05 kPa 1612 count */
+ 271, /* 98.11 kPa 1613 count */
+ 267, /* 98.16 kPa 1614 count */
+ 262, /* 98.22 kPa 1615 count */
+ 257, /* 98.27 kPa 1616 count */
+ 253, /* 98.33 kPa 1617 count */
+ 248, /* 98.38 kPa 1618 count */
+ 243, /* 98.43 kPa 1619 count */
+ 239, /* 98.49 kPa 1620 count */
+ 234, /* 98.54 kPa 1621 count */
+ 230, /* 98.60 kPa 1622 count */
+ 225, /* 98.65 kPa 1623 count */
+ 220, /* 98.71 kPa 1624 count */
+ 216, /* 98.76 kPa 1625 count */
+ 211, /* 98.81 kPa 1626 count */
+ 206, /* 98.87 kPa 1627 count */
+ 202, /* 98.92 kPa 1628 count */
+ 197, /* 98.98 kPa 1629 count */
+ 193, /* 99.03 kPa 1630 count */
+ 188, /* 99.09 kPa 1631 count */
+ 183, /* 99.14 kPa 1632 count */
+ 179, /* 99.19 kPa 1633 count */
+ 174, /* 99.25 kPa 1634 count */
+ 170, /* 99.30 kPa 1635 count */
+ 165, /* 99.36 kPa 1636 count */
+ 160, /* 99.41 kPa 1637 count */
+ 156, /* 99.47 kPa 1638 count */
+ 151, /* 99.52 kPa 1639 count */
+ 147, /* 99.57 kPa 1640 count */
+ 142, /* 99.63 kPa 1641 count */
+ 138, /* 99.68 kPa 1642 count */
+ 133, /* 99.74 kPa 1643 count */
+ 128, /* 99.79 kPa 1644 count */
+ 124, /* 99.85 kPa 1645 count */
+ 119, /* 99.90 kPa 1646 count */
+ 115, /* 99.95 kPa 1647 count */
+ 110, /* 100.01 kPa 1648 count */
+ 106, /* 100.06 kPa 1649 count */
+ 101, /* 100.12 kPa 1650 count */
+ 96, /* 100.17 kPa 1651 count */
+ 92, /* 100.23 kPa 1652 count */
+ 87, /* 100.28 kPa 1653 count */
+ 83, /* 100.33 kPa 1654 count */
+ 78, /* 100.39 kPa 1655 count */
+ 74, /* 100.44 kPa 1656 count */
+ 69, /* 100.50 kPa 1657 count */
+ 65, /* 100.55 kPa 1658 count */
+ 60, /* 100.61 kPa 1659 count */
+ 55, /* 100.66 kPa 1660 count */
+ 51, /* 100.71 kPa 1661 count */
+ 46, /* 100.77 kPa 1662 count */
+ 42, /* 100.82 kPa 1663 count */
+ 37, /* 100.88 kPa 1664 count */
+ 33, /* 100.93 kPa 1665 count */
+ 28, /* 100.99 kPa 1666 count */
+ 24, /* 101.04 kPa 1667 count */
+ 19, /* 101.09 kPa 1668 count */
+ 15, /* 101.15 kPa 1669 count */
+ 10, /* 101.20 kPa 1670 count */
+ 6, /* 101.26 kPa 1671 count */
+ 1, /* 101.31 kPa 1672 count */
+ -3, /* 101.37 kPa 1673 count */
+ -8, /* 101.42 kPa 1674 count */
+ -12, /* 101.47 kPa 1675 count */
+ -17, /* 101.53 kPa 1676 count */
+ -21, /* 101.58 kPa 1677 count */
+ -26, /* 101.64 kPa 1678 count */
+ -30, /* 101.69 kPa 1679 count */
+ -35, /* 101.75 kPa 1680 count */
+ -39, /* 101.80 kPa 1681 count */
+ -44, /* 101.85 kPa 1682 count */
+ -48, /* 101.91 kPa 1683 count */
+ -53, /* 101.96 kPa 1684 count */
+ -57, /* 102.02 kPa 1685 count */
+ -62, /* 102.07 kPa 1686 count */
+ -66, /* 102.13 kPa 1687 count */
+ -71, /* 102.18 kPa 1688 count */
+ -75, /* 102.23 kPa 1689 count */
+ -80, /* 102.29 kPa 1690 count */
+ -84, /* 102.34 kPa 1691 count */
+ -89, /* 102.40 kPa 1692 count */
+ -93, /* 102.45 kPa 1693 count */
+ -98, /* 102.51 kPa 1694 count */
+ -102, /* 102.56 kPa 1695 count */
+ -107, /* 102.61 kPa 1696 count */
+ -111, /* 102.67 kPa 1697 count */
+ -116, /* 102.72 kPa 1698 count */
+ -120, /* 102.78 kPa 1699 count */
+ -125, /* 102.83 kPa 1700 count */
+ -129, /* 102.89 kPa 1701 count */
+ -134, /* 102.94 kPa 1702 count */
+ -138, /* 102.99 kPa 1703 count */
+ -143, /* 103.05 kPa 1704 count */
+ -147, /* 103.10 kPa 1705 count */
+ -151, /* 103.16 kPa 1706 count */
+ -156, /* 103.21 kPa 1707 count */
+ -160, /* 103.27 kPa 1708 count */
+ -165, /* 103.32 kPa 1709 count */
+ -169, /* 103.37 kPa 1710 count */
+ -174, /* 103.43 kPa 1711 count */
+ -178, /* 103.48 kPa 1712 count */
+ -183, /* 103.54 kPa 1713 count */
+ -187, /* 103.59 kPa 1714 count */
+ -191, /* 103.65 kPa 1715 count */
+ -196, /* 103.70 kPa 1716 count */
+ -200, /* 103.75 kPa 1717 count */
+ -205, /* 103.81 kPa 1718 count */
+ -209, /* 103.86 kPa 1719 count */
+ -214, /* 103.92 kPa 1720 count */
+ -218, /* 103.97 kPa 1721 count */
+ -222, /* 104.03 kPa 1722 count */
+ -227, /* 104.08 kPa 1723 count */
+ -231, /* 104.13 kPa 1724 count */
+ -236, /* 104.19 kPa 1725 count */
+ -240, /* 104.24 kPa 1726 count */
+ -245, /* 104.30 kPa 1727 count */
+ -249, /* 104.35 kPa 1728 count */
+ -253, /* 104.41 kPa 1729 count */
+ -258, /* 104.46 kPa 1730 count */
+ -262, /* 104.51 kPa 1731 count */
+ -267, /* 104.57 kPa 1732 count */
+ -271, /* 104.62 kPa 1733 count */
+ -275, /* 104.68 kPa 1734 count */
+ -280, /* 104.73 kPa 1735 count */
+ -284, /* 104.79 kPa 1736 count */
+ -289, /* 104.84 kPa 1737 count */
+ -293, /* 104.89 kPa 1738 count */
+ -297, /* 104.95 kPa 1739 count */
+ -302, /* 105.00 kPa 1740 count */
+ -306, /* 105.06 kPa 1741 count */
+ -311, /* 105.11 kPa 1742 count */
+ -315, /* 105.17 kPa 1743 count */
+ -319, /* 105.22 kPa 1744 count */
+ -324, /* 105.27 kPa 1745 count */
+ -328, /* 105.33 kPa 1746 count */
+ -332, /* 105.38 kPa 1747 count */
+ -337, /* 105.44 kPa 1748 count */
+ -341, /* 105.49 kPa 1749 count */
+ -346, /* 105.55 kPa 1750 count */
+ -350, /* 105.60 kPa 1751 count */
+ -354, /* 105.65 kPa 1752 count */
+ -359, /* 105.71 kPa 1753 count */
+ -363, /* 105.76 kPa 1754 count */
+ -367, /* 105.82 kPa 1755 count */
+ -372, /* 105.87 kPa 1756 count */
+ -376, /* 105.93 kPa 1757 count */
+ -380, /* 105.98 kPa 1758 count */
+ -385, /* 106.03 kPa 1759 count */
+ -389, /* 106.09 kPa 1760 count */
+ -394, /* 106.14 kPa 1761 count */
+ -398, /* 106.20 kPa 1762 count */
+ -402, /* 106.25 kPa 1763 count */
+ -407, /* 106.31 kPa 1764 count */
+ -411, /* 106.36 kPa 1765 count */
+ -415, /* 106.41 kPa 1766 count */
+ -420, /* 106.47 kPa 1767 count */
+ -424, /* 106.52 kPa 1768 count */
+ -428, /* 106.58 kPa 1769 count */
+ -433, /* 106.63 kPa 1770 count */
+ -437, /* 106.69 kPa 1771 count */
+ -441, /* 106.74 kPa 1772 count */
+ -446, /* 106.79 kPa 1773 count */
+ -450, /* 106.85 kPa 1774 count */
+ -454, /* 106.90 kPa 1775 count */
+ -459, /* 106.96 kPa 1776 count */
+ -463, /* 107.01 kPa 1777 count */
+ -467, /* 107.07 kPa 1778 count */
+ -472, /* 107.12 kPa 1779 count */
+ -476, /* 107.17 kPa 1780 count */
+ -480, /* 107.23 kPa 1781 count */
+ -485, /* 107.28 kPa 1782 count */
+ -489, /* 107.34 kPa 1783 count */
+ -493, /* 107.39 kPa 1784 count */
+ -497, /* 107.45 kPa 1785 count */
+ -502, /* 107.50 kPa 1786 count */
+ -506, /* 107.55 kPa 1787 count */
+ -510, /* 107.61 kPa 1788 count */
+ -515, /* 107.66 kPa 1789 count */
+ -519, /* 107.72 kPa 1790 count */
+ -523, /* 107.77 kPa 1791 count */
+ -528, /* 107.83 kPa 1792 count */
+ -532, /* 107.88 kPa 1793 count */
+ -536, /* 107.93 kPa 1794 count */
+ -540, /* 107.99 kPa 1795 count */
+ -545, /* 108.04 kPa 1796 count */
+ -549, /* 108.10 kPa 1797 count */
+ -553, /* 108.15 kPa 1798 count */
+ -558, /* 108.21 kPa 1799 count */
+ -562, /* 108.26 kPa 1800 count */
+ -566, /* 108.31 kPa 1801 count */
+ -570, /* 108.37 kPa 1802 count */
+ -575, /* 108.42 kPa 1803 count */
+ -579, /* 108.48 kPa 1804 count */
+ -583, /* 108.53 kPa 1805 count */
+ -588, /* 108.59 kPa 1806 count */
+ -592, /* 108.64 kPa 1807 count */
+ -596, /* 108.69 kPa 1808 count */
+ -600, /* 108.75 kPa 1809 count */
+ -605, /* 108.80 kPa 1810 count */
+ -609, /* 108.86 kPa 1811 count */
+ -613, /* 108.91 kPa 1812 count */
+ -617, /* 108.97 kPa 1813 count */
+ -622, /* 109.02 kPa 1814 count */
+ -626, /* 109.07 kPa 1815 count */
+ -630, /* 109.13 kPa 1816 count */
+ -634, /* 109.18 kPa 1817 count */
+ -639, /* 109.24 kPa 1818 count */
+ -643, /* 109.29 kPa 1819 count */
+ -647, /* 109.35 kPa 1820 count */
+ -651, /* 109.40 kPa 1821 count */
+ -656, /* 109.45 kPa 1822 count */
+ -660, /* 109.51 kPa 1823 count */
+ -664, /* 109.56 kPa 1824 count */
+ -668, /* 109.62 kPa 1825 count */
+ -673, /* 109.67 kPa 1826 count */
+ -677, /* 109.73 kPa 1827 count */
+ -681, /* 109.78 kPa 1828 count */
+ -685, /* 109.83 kPa 1829 count */
+ -690, /* 109.89 kPa 1830 count */
+ -694, /* 109.94 kPa 1831 count */
+ -698, /* 110.00 kPa 1832 count */
+ -702, /* 110.05 kPa 1833 count */
+ -706, /* 110.11 kPa 1834 count */
+ -711, /* 110.16 kPa 1835 count */
+ -715, /* 110.21 kPa 1836 count */
+ -719, /* 110.27 kPa 1837 count */
+ -723, /* 110.32 kPa 1838 count */
+ -728, /* 110.38 kPa 1839 count */
+ -732, /* 110.43 kPa 1840 count */
+ -736, /* 110.48 kPa 1841 count */
+ -740, /* 110.54 kPa 1842 count */
+ -744, /* 110.59 kPa 1843 count */
+ -749, /* 110.65 kPa 1844 count */
+ -753, /* 110.70 kPa 1845 count */
+ -757, /* 110.76 kPa 1846 count */
+ -761, /* 110.81 kPa 1847 count */
+ -765, /* 110.86 kPa 1848 count */
+ -770, /* 110.92 kPa 1849 count */
+ -774, /* 110.97 kPa 1850 count */
+ -778, /* 111.03 kPa 1851 count */
+ -782, /* 111.08 kPa 1852 count */
+ -786, /* 111.14 kPa 1853 count */
+ -791, /* 111.19 kPa 1854 count */
+ -795, /* 111.24 kPa 1855 count */
+ -799, /* 111.30 kPa 1856 count */
+ -803, /* 111.35 kPa 1857 count */
+ -807, /* 111.41 kPa 1858 count */
+ -812, /* 111.46 kPa 1859 count */
+ -816, /* 111.52 kPa 1860 count */
+ -820, /* 111.57 kPa 1861 count */
+ -824, /* 111.62 kPa 1862 count */
+ -828, /* 111.68 kPa 1863 count */
+ -832, /* 111.73 kPa 1864 count */
+ -837, /* 111.79 kPa 1865 count */
+ -841, /* 111.84 kPa 1866 count */
+ -845, /* 111.90 kPa 1867 count */
+ -849, /* 111.95 kPa 1868 count */
+ -853, /* 112.00 kPa 1869 count */
+ -857, /* 112.06 kPa 1870 count */
+ -862, /* 112.11 kPa 1871 count */
+ -866, /* 112.17 kPa 1872 count */
+ -870, /* 112.22 kPa 1873 count */
+ -874, /* 112.28 kPa 1874 count */
+ -878, /* 112.33 kPa 1875 count */
+ -882, /* 112.38 kPa 1876 count */
+ -887, /* 112.44 kPa 1877 count */
+ -891, /* 112.49 kPa 1878 count */
+ -895, /* 112.55 kPa 1879 count */
+ -899, /* 112.60 kPa 1880 count */
+ -903, /* 112.66 kPa 1881 count */
+ -907, /* 112.71 kPa 1882 count */
+ -911, /* 112.76 kPa 1883 count */
+ -916, /* 112.82 kPa 1884 count */
+ -920, /* 112.87 kPa 1885 count */
+ -924, /* 112.93 kPa 1886 count */
+ -928, /* 112.98 kPa 1887 count */
+ -932, /* 113.04 kPa 1888 count */
+ -936, /* 113.09 kPa 1889 count */
+ -940, /* 113.14 kPa 1890 count */
+ -945, /* 113.20 kPa 1891 count */
+ -949, /* 113.25 kPa 1892 count */
+ -953, /* 113.31 kPa 1893 count */
+ -957, /* 113.36 kPa 1894 count */
+ -961, /* 113.42 kPa 1895 count */
+ -965, /* 113.47 kPa 1896 count */
+ -969, /* 113.52 kPa 1897 count */
+ -973, /* 113.58 kPa 1898 count */
+ -978, /* 113.63 kPa 1899 count */
+ -982, /* 113.69 kPa 1900 count */
+ -986, /* 113.74 kPa 1901 count */
+ -990, /* 113.80 kPa 1902 count */
+ -994, /* 113.85 kPa 1903 count */
+ -998, /* 113.90 kPa 1904 count */
+ -1002, /* 113.96 kPa 1905 count */
+ -1006, /* 114.01 kPa 1906 count */
+ -1010, /* 114.07 kPa 1907 count */
+ -1015, /* 114.12 kPa 1908 count */
+ -1019, /* 114.18 kPa 1909 count */
+ -1023, /* 114.23 kPa 1910 count */
+ -1027, /* 114.28 kPa 1911 count */
+ -1031, /* 114.34 kPa 1912 count */
+ -1035, /* 114.39 kPa 1913 count */
+ -1039, /* 114.45 kPa 1914 count */
+ -1043, /* 114.50 kPa 1915 count */
+ -1047, /* 114.56 kPa 1916 count */
+ -1051, /* 114.61 kPa 1917 count */
+ -1056, /* 114.66 kPa 1918 count */
+ -1060, /* 114.72 kPa 1919 count */
+ -1064, /* 114.77 kPa 1920 count */
+ -1068, /* 114.83 kPa 1921 count */
+ -1072, /* 114.88 kPa 1922 count */
+ -1076, /* 114.94 kPa 1923 count */
+ -1080, /* 114.99 kPa 1924 count */
+ -1084, /* 115.04 kPa 1925 count */
+ -1088, /* 115.10 kPa 1926 count */
+ -1092, /* 115.15 kPa 1927 count */
+ -1096, /* 115.21 kPa 1928 count */
+ -1100, /* 115.26 kPa 1929 count */
+ -1104, /* 115.32 kPa 1930 count */
+ -1109, /* 115.37 kPa 1931 count */
+ -1113, /* 115.42 kPa 1932 count */
+ -1117, /* 115.48 kPa 1933 count */
+ -1121, /* 115.53 kPa 1934 count */
+ -1125, /* 115.59 kPa 1935 count */
+ -1129, /* 115.64 kPa 1936 count */
+ -1133, /* 115.70 kPa 1937 count */
+ -1137, /* 115.75 kPa 1938 count */
+ -1141, /* 115.80 kPa 1939 count */
+ -1145, /* 115.86 kPa 1940 count */
+ -1149, /* 115.91 kPa 1941 count */
+ -1153, /* 115.97 kPa 1942 count */
+ -1157, /* 116.02 kPa 1943 count */
+ -1161, /* 116.08 kPa 1944 count */
+ -1165, /* 116.13 kPa 1945 count */
+ -1169, /* 116.18 kPa 1946 count */
+ -1173, /* 116.24 kPa 1947 count */
+ -1177, /* 116.29 kPa 1948 count */
+ -1182, /* 116.35 kPa 1949 count */
+ -1186, /* 116.40 kPa 1950 count */
+ -1190, /* 116.46 kPa 1951 count */
+ -1194, /* 116.51 kPa 1952 count */
+ -1198, /* 116.56 kPa 1953 count */
+ -1202, /* 116.62 kPa 1954 count */
+ -1206, /* 116.67 kPa 1955 count */
+ -1210, /* 116.73 kPa 1956 count */
+ -1214, /* 116.78 kPa 1957 count */
+ -1218, /* 116.84 kPa 1958 count */
+ -1222, /* 116.89 kPa 1959 count */
+ -1226, /* 116.94 kPa 1960 count */
+ -1230, /* 117.00 kPa 1961 count */
+ -1234, /* 117.05 kPa 1962 count */
+ -1238, /* 117.11 kPa 1963 count */
+ -1242, /* 117.16 kPa 1964 count */
+ -1246, /* 117.22 kPa 1965 count */
+ -1250, /* 117.27 kPa 1966 count */
+ -1254, /* 117.32 kPa 1967 count */
+ -1258, /* 117.38 kPa 1968 count */
+ -1262, /* 117.43 kPa 1969 count */
+ -1266, /* 117.49 kPa 1970 count */
+ -1270, /* 117.54 kPa 1971 count */
+ -1274, /* 117.60 kPa 1972 count */
+ -1278, /* 117.65 kPa 1973 count */
+ -1282, /* 117.70 kPa 1974 count */
+ -1286, /* 117.76 kPa 1975 count */
+ -1290, /* 117.81 kPa 1976 count */
+ -1294, /* 117.87 kPa 1977 count */
+ -1298, /* 117.92 kPa 1978 count */
+ -1302, /* 117.98 kPa 1979 count */
+ -1306, /* 118.03 kPa 1980 count */
+ -1310, /* 118.08 kPa 1981 count */
+ -1314, /* 118.14 kPa 1982 count */
+ -1318, /* 118.19 kPa 1983 count */
+ -1322, /* 118.25 kPa 1984 count */
+ -1326, /* 118.30 kPa 1985 count */
+ -1330, /* 118.36 kPa 1986 count */
+ -1334, /* 118.41 kPa 1987 count */
+ -1338, /* 118.46 kPa 1988 count */
+ -1342, /* 118.52 kPa 1989 count */
+ -1346, /* 118.57 kPa 1990 count */
+ -1350, /* 118.63 kPa 1991 count */
+ -1354, /* 118.68 kPa 1992 count */
+ -1358, /* 118.74 kPa 1993 count */
+ -1362, /* 118.79 kPa 1994 count */
+ -1366, /* 118.84 kPa 1995 count */
+ -1370, /* 118.90 kPa 1996 count */
+ -1374, /* 118.95 kPa 1997 count */
+ -1378, /* 119.01 kPa 1998 count */
+ -1382, /* 119.06 kPa 1999 count */
+ -1386, /* 119.12 kPa 2000 count */
+ -1390, /* 119.17 kPa 2001 count */
+ -1394, /* 119.22 kPa 2002 count */
+ -1397, /* 119.28 kPa 2003 count */
+ -1401, /* 119.33 kPa 2004 count */
+ -1405, /* 119.39 kPa 2005 count */
+ -1409, /* 119.44 kPa 2006 count */
+ -1413, /* 119.50 kPa 2007 count */
+ -1417, /* 119.55 kPa 2008 count */
+ -1421, /* 119.60 kPa 2009 count */
+ -1425, /* 119.66 kPa 2010 count */
+ -1429, /* 119.71 kPa 2011 count */
+ -1433, /* 119.77 kPa 2012 count */
+ -1437, /* 119.82 kPa 2013 count */
+ -1441, /* 119.88 kPa 2014 count */
+ -1445, /* 119.93 kPa 2015 count */
+ -1449, /* 119.98 kPa 2016 count */
+ -1453, /* 120.04 kPa 2017 count */
+ -1457, /* 120.09 kPa 2018 count */
+ -1461, /* 120.15 kPa 2019 count */
+ -1465, /* 120.20 kPa 2020 count */
+ -1469, /* 120.26 kPa 2021 count */
+ -1472, /* 120.31 kPa 2022 count */
+ -1476, /* 120.36 kPa 2023 count */
+ -1480, /* 120.42 kPa 2024 count */
+ -1484, /* 120.47 kPa 2025 count */
+ -1488, /* 120.53 kPa 2026 count */
+ -1492, /* 120.58 kPa 2027 count */
+ -1496, /* 120.64 kPa 2028 count */
+ -1500, /* 120.69 kPa 2029 count */
+ -1504, /* 120.74 kPa 2030 count */
+ -1508, /* 120.80 kPa 2031 count */
+ -1512, /* 120.85 kPa 2032 count */
+ -1516, /* 120.91 kPa 2033 count */
+ -1520, /* 120.96 kPa 2034 count */
+ -1523, /* 121.02 kPa 2035 count */
+ -1527, /* 121.07 kPa 2036 count */
+ -1531, /* 121.12 kPa 2037 count */
+ -1535, /* 121.18 kPa 2038 count */
+ -1539, /* 121.23 kPa 2039 count */
+ -1543, /* 121.29 kPa 2040 count */
+ -1547, /* 121.34 kPa 2041 count */
+ -1551, /* 121.40 kPa 2042 count */
+ -1555, /* 121.45 kPa 2043 count */
+ -1559, /* 121.50 kPa 2044 count */
+ -1562, /* 121.56 kPa 2045 count */
+ -1566, /* 121.61 kPa 2046 count */
+ -1570, /* 121.67 kPa 2047 count */
--- /dev/null
+#!/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);
+}
+
+string manufacturer = "altusmetrum.org";
+string product = "TeleMetrum";
+string version = "0.0";
+int serial = 1;
+int user_argind = 0;
+
+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 = &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_string(version, "iVersion");
+}
+
+main();
--- /dev/null
+/*
+ * 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 "cc1111.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 0x80
+#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) */
+ uint8_t stack_count; /* amount of saved stack */
+ uint8_t task_id; /* index in the task array */
+ __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 */
+void
+ao_sleep(__xdata void *wchan);
+
+/* Wake all tasks sleeping on wchan */
+void
+ao_wakeup(__xdata void *wchan);
+
+/* 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;
+
+/* 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 */
+
+/* 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_MS_TO_TICKS(ms) ((ms) / 10)
+#define AO_SEC_TO_TICKS(s) ((s) * 100)
+
+/* 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);
+
+/*
+ * ao_adc.c
+ */
+
+#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 */
+};
+
+/*
+ * 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;
+
+/* 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 */
+#if !AO_NO_ADC_ISR
+void
+ao_adc_isr(void) interrupt 1;
+#endif
+
+/* Initialize the A/D converter */
+void
+ao_adc_init(void);
+
+/*
+ * 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
+#define AO_LED_GREEN 1
+#define AO_LED_RED 2
+
+/* 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_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);
+
+/* Flush the USB output queue */
+void
+ao_usb_flush(void);
+
+/* USB interrupt handler */
+void
+ao_usb_isr(void) interrupt 6;
+
+/* 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 __xdata uint16_t ao_cmd_lex_i;
+extern __xdata char ao_cmd_lex_c;
+extern __xdata 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);
+
+struct ao_cmds {
+ char cmd;
+ void (*func)(void);
+ const char *help;
+};
+
+void
+ao_cmd_register(__code struct ao_cmds *cmds);
+
+void
+ao_cmd_init(void);
+
+/*
+ * ao_dma.c
+ */
+
+/* Allocate a DMA channel. the 'done' parameter will be set to 1
+ * 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;
+
+/*
+ * ao_ee.c
+ */
+
+/*
+ * We reserve the last block on the device for
+ * configuration space. Writes and reads in this
+ * area return errors.
+ */
+
+#define AO_EE_BLOCK_SIZE ((uint16_t) (256))
+#define AO_EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024)
+#define AO_EE_DATA_SIZE (AO_EE_DEVICE_SIZE - (uint32_t) AO_EE_BLOCK_SIZE)
+#define AO_EE_CONFIG_BLOCK ((uint16_t) (AO_EE_DATA_SIZE / AO_EE_BLOCK_SIZE))
+
+void
+ao_ee_flush(void) __reentrant;
+
+/* Write to the eeprom */
+uint8_t
+ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant;
+
+/* Read from the eeprom */
+uint8_t
+ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant;
+
+/* Write the config block (at the end of the eeprom) */
+uint8_t
+ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant;
+
+/* Read the config block (at the end of the eeprom) */
+uint8_t
+ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant;
+
+/* Initialize the EEPROM code */
+void
+ao_ee_init(void);
+
+/*
+ * ao_log.c
+ */
+
+/* Structure containing GPS position, either lat or lon */
+
+struct ao_gps_pos {
+ uint8_t degrees;
+ uint8_t minutes;
+ uint16_t minutes_fraction; /* in units of 1/10000 minutes */
+};
+
+/*
+ * 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_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;
+ struct ao_gps_pos gps_latitude;
+ struct ao_gps_pos gps_longitude;
+ struct {
+ int16_t altitude;
+ uint16_t unused;
+ } gps_altitude;
+ struct {
+ uint16_t d0;
+ uint16_t d1;
+ } anon;
+ } u;
+};
+
+/* Write a record to the eeprom log */
+void
+ao_log_data(struct ao_log_record *log);
+
+/* Flush the log */
+void
+ao_log_flush(void);
+
+/* Log dumping API:
+ * ao_log_dump_first() - get first log record
+ * ao_log_dump_next() - get next log record
+ */
+extern __xdata struct ao_log_record ao_log_dump;
+
+/* Retrieve first log record for the current flight */
+uint8_t
+ao_log_dump_first(void);
+
+/* return next log record for the current flight */
+uint8_t
+ao_log_dump_next(void);
+
+/* Logging thread main routine */
+void
+ao_log(void);
+
+/* 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);
+
+/*
+ * ao_flight.c
+ */
+
+enum ao_flight_state {
+ ao_flight_startup = 0,
+ ao_flight_idle = 1,
+ ao_flight_launchpad = 2,
+ ao_flight_boost = 3,
+ ao_flight_coast = 4,
+ ao_flight_apogee = 5,
+ ao_flight_drogue = 6,
+ ao_flight_main = 7,
+ ao_flight_landed = 8,
+ ao_flight_invalid = 9
+};
+
+extern __xdata struct ao_adc ao_flight_data;
+extern __pdata enum ao_flight_state ao_flight_state;
+extern __pdata uint16_t ao_flight_tick;
+extern __pdata int16_t ao_flight_accel;
+extern __pdata int16_t ao_flight_pres;
+extern __pdata int32_t ao_flight_vel;
+extern __pdata int16_t ao_ground_pres;
+extern __pdata int16_t ao_ground_accel;
+extern __pdata int16_t ao_min_pres;
+extern __pdata uint16_t ao_launch_time;
+
+/* Flight thread */
+void
+ao_flight(void);
+
+/* Initialize flight thread */
+void
+ao_flight_init(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
+ */
+
+#if !AO_NO_SERIAL_ISR
+void
+ao_serial_rx1_isr(void) interrupt 3;
+
+void
+ao_serial_tx1_isr(void) interrupt 14;
+#endif
+
+char
+ao_serial_getchar(void) __critical;
+
+void
+ao_serial_putchar(char c) __critical;
+
+void
+ao_serial_init(void);
+
+/*
+ * 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_LONGITUDE_MASK (1 << 5)
+#define AO_GPS_LONGITUDE_EAST (0 << 5)
+#define AO_GPS_LONGITUDE_WEST (1 << 5)
+
+#define AO_GPS_LATITUDE_MASK (1 << 6)
+#define AO_GPS_LATITUDE_NORTH (0 << 6)
+#define AO_GPS_LATITUDE_SOUTH (1 << 6)
+
+struct ao_gps_data {
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ uint8_t flags;
+ struct ao_gps_pos latitude;
+ struct ao_gps_pos longitude;
+ int16_t altitude;
+};
+
+extern __xdata uint8_t ao_gps_mutex;
+extern __xdata struct ao_gps_data ao_gps_data;
+
+void
+ao_gps(void);
+
+void
+ao_gps_print(__xdata struct ao_gps_data *gps_data);
+
+void
+ao_gps_init(void);
+
+/*
+ * ao_gps_report.c
+ */
+
+void
+ao_gps_report(void);
+
+void
+ao_gps_report_init(void);
+
+/*
+ * ao_telemetry.c
+ */
+
+#define AO_MAX_CALLSIGN 8
+
+struct ao_telemetry {
+ uint8_t addr;
+ uint8_t flight_state;
+ int16_t flight_accel;
+ int16_t ground_accel;
+ int32_t flight_vel;
+ int16_t flight_pres;
+ int16_t ground_pres;
+ struct ao_adc adc;
+ struct ao_gps_data gps;
+ char callsign[AO_MAX_CALLSIGN];
+};
+
+/* 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(50)
+#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000)
+
+void
+ao_telemetry_set_interval(uint16_t interval);
+
+void
+ao_telemetry_init(void);
+
+/*
+ * ao_radio.c
+ */
+
+void
+ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant;
+
+struct ao_radio_recv {
+ struct ao_telemetry telemetry;
+ int8_t rssi;
+ uint8_t status;
+};
+
+void
+ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant;
+
+void
+ao_radio_init(void);
+
+/*
+ * ao_monitor.c
+ */
+
+extern const char const * const ao_state_names[];
+
+void
+ao_monitor(void);
+
+void
+ao_set_monitor(uint8_t monitoring);
+
+void
+ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant;
+
+/*
+ * ao_stdio.c
+ */
+
+void
+flush(void);
+
+/*
+ * 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_igniter_init(void);
+
+/*
+ * ao_config.c
+ */
+
+#define AO_CONFIG_MAJOR 1
+#define AO_CONFIG_MINOR 0
+
+struct ao_config {
+ uint8_t major;
+ uint8_t minor;
+ uint16_t main_deploy;
+ int16_t accel_zero_g;
+ uint8_t radio_channel;
+ char callsign[AO_MAX_CALLSIGN + 1];
+};
+
+extern __xdata struct ao_config ao_config;
+
+void
+ao_config_get(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 uint8_t ao_usb_descriptors [];
+extern const uint16_t ao_serial_number;
+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 32
+#define AO_PACKET_WIN 256
+
+#define AO_PACKET_FIN (1 << 0)
+#define AO_PACKET_SYN (1 << 1)
+#define AO_PACKET_RST (1 << 2)
+#define AO_PACKET_ACK (1 << 3)
+
+struct ao_packet {
+ uint8_t addr;
+ uint8_t flags;
+ uint16_t seq;
+ uint16_t ack;
+ uint16_t window;
+ uint8_t len;
+ uint8_t d[AO_PACKET_MAX];
+};
+
+uint8_t
+ao_packet_connect(uint8_t dest);
+
+uint8_t
+ao_packet_accept(void);
+
+int
+ao_packet_send(uint8_t *data, int len);
+
+int
+ao_packet_recv(uint8_t *data, int len);
+
+void
+ao_packet_init(void);
+
+#endif /* _AO_H_ */
--- /dev/null
+/*
+ * 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;
+
+void
+ao_adc_poll(void)
+{
+ ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0;
+}
+
+void
+ao_adc_sleep(void)
+{
+ ao_sleep(&ao_adc_ring);
+}
+
+void
+ao_adc_get(__xdata struct ao_adc *packet)
+{
+ uint8_t i = ao_adc_ring_prev(ao_adc_head);
+ 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;
+ a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence);
+ a[0] = ADCL;
+ a[1] = ADCH;
+ if (sequence < 5) {
+ /* start next channel conversion */
+ ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1);
+ } 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(ao_adc_ring);
+ }
+}
+
+static void
+ao_adc_dump(void)
+{
+ __xdata struct ao_adc packet;
+ ao_adc_get(&packet);
+ printf("tick: %5u accel: %4d pres: %4d temp: %4d batt: %4d drogue: %4d main: %4d\n",
+ packet.tick, packet.accel >> 4, packet.pres >> 4, packet.temp >> 4,
+ packet.v_batt >> 4, packet.sense_d >> 4, packet.sense_m >> 4);
+}
+
+__code struct ao_cmds ao_adc_cmds[] = {
+ { 'a', ao_adc_dump, "a Display current ADC values" },
+ { 0, ao_adc_dump, NULL },
+};
+
+void
+ao_adc_init(void)
+{
+ ADCCFG = ((1 << 0) | /* acceleration */
+ (1 << 1) | /* pressure */
+ (1 << 2) | /* temperature */
+ (1 << 3) | /* battery voltage */
+ (1 << 4) | /* drogue sense */
+ (1 << 5)); /* main sense */
+
+ /* enable interrupts */
+ ADCIF = 0;
+ IEN0 |= IEN0_ADCIE;
+ ao_cmd_register(&ao_adc_cmds[0]);
+}
--- /dev/null
+/*
+ * 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)
+{
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 uint16_t ao_cmd_lex_i;
+__xdata char ao_cmd_lex_c;
+__xdata enum ao_cmd_status ao_cmd_status;
+static __xdata uint8_t lex_echo;
+
+#define CMD_LEN 32
+
+static __xdata char cmd_line[CMD_LEN];
+static __xdata uint8_t cmd_len;
+static __xdata uint8_t cmd_i;
+
+static void
+put_string(char *s)
+{
+ __xdata char c;
+ while (c = *s++)
+ putchar(c);
+}
+
+static void
+readline(void)
+{
+ __xdata char c;
+ if (lex_echo)
+ put_string("> ");
+ cmd_len = 0;
+ for (;;) {
+ flush();
+ c = getchar();
+ /* backspace/delete */
+ if (c == '\010' || c == '\177') {
+ if (cmd_len != 0) {
+ if (lex_echo)
+ put_string("\010 \010");
+ --cmd_len;
+ }
+ continue;
+ }
+
+ /* ^U */
+ if (c == '\025') {
+ while (cmd_len != 0) {
+ if (lex_echo)
+ put_string("\010 \010");
+ --cmd_len;
+ }
+ continue;
+ }
+
+ /* map CR to NL */
+ if (c == '\r')
+ c = '\n';
+
+ if (c == '\n') {
+ if (lex_echo)
+ putchar('\n');
+ break;
+ }
+
+ if (cmd_len >= CMD_LEN - 2) {
+ if (lex_echo)
+ putchar('\007');
+ continue;
+ }
+ cmd_line[cmd_len++] = c;
+ if (lex_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)
+{
+ int8_t i;
+ for (i = 3; i >= 0; i--)
+ putnibble((v >> (i << 2)) & 0xf);
+}
+
+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)
+{
+ __xdata uint8_t r = ao_cmd_lex_error;
+
+ ao_cmd_lex_i = 0;
+ ao_cmd_white();
+ for(;;) {
+ if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+ ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - '0');
+ else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
+ ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'a' + 10);
+ else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
+ ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'A' + 10);
+ else
+ break;
+ r = ao_cmd_success;
+ ao_cmd_lex();
+ }
+ if (r != ao_cmd_success)
+ ao_cmd_status = r;
+}
+
+void
+ao_cmd_decimal(void)
+{
+ __xdata uint8_t r = ao_cmd_lex_error;
+
+ ao_cmd_lex_i = 0;
+ ao_cmd_white();
+ for(;;) {
+ if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+ ao_cmd_lex_i = (ao_cmd_lex_i * 10) + (ao_cmd_lex_c - '0');
+ else
+ break;
+ r = ao_cmd_success;
+ ao_cmd_lex();
+ }
+ if (r != ao_cmd_success)
+ ao_cmd_status = r;
+}
+
+static void
+eol(void)
+{
+ while (ao_cmd_lex_c != '\n')
+ ao_cmd_lex();
+}
+
+static void
+dump(void)
+{
+ __xdata uint16_t c;
+ __xdata uint8_t * __xdata start, * __xdata end;
+
+ ao_cmd_hex();
+ start = (uint8_t __xdata *) ao_cmd_lex_i;
+ ao_cmd_hex();
+ end = (uint8_t __xdata *) ao_cmd_lex_i;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ c = 0;
+ while (start <= end) {
+ if ((c & 7) == 0) {
+ if (c)
+ putchar('\n');
+ ao_cmd_put16((uint16_t) start);
+ }
+ putchar(' ');
+ ao_cmd_put8(*start);
+ ++c;
+ start++;
+ }
+ putchar('\n');
+}
+
+static void
+echo(void)
+{
+ ao_cmd_hex();
+ lex_echo = ao_cmd_lex_i != 0;
+}
+
+static void
+version(void)
+{
+ printf("manufacturer %s\n", ao_manufacturer);
+ printf("product %s\n", ao_product);
+ printf("serial-number %u\n", ao_serial_number);
+ printf("software-version %s\n", ao_version);
+}
+
+static const char help_txt[] = "All numbers are in hex";
+
+#define NUM_CMDS 11
+
+static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]);
+static __xdata uint8_t ao_ncmds;
+
+static void
+help(void)
+{
+ __xdata uint8_t cmds;
+ __xdata uint8_t cmd;
+ __code struct ao_cmds * __xdata cs;
+ puts(help_txt);
+ for (cmds = 0; cmds < ao_ncmds; cmds++) {
+ cs = ao_cmds[cmds];
+ for (cmd = 0; cs[cmd].cmd != '\0'; cmd++)
+ puts(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 *parameters)
+{
+ __xdata char c;
+ __xdata uint8_t cmd, cmds;
+ __code struct ao_cmds * __xdata cs;
+ void (*__xdata func)(void);
+ (void) parameters;
+
+ lex_echo = 1;
+ 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].cmd != '\0'; cmd++)
+ if (cs[cmd].cmd == 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, "? Print this message" },
+ { 'T', ao_task_info, "T Show task states" },
+ { 'E', echo, "E <0 off, 1 on> Set command echo mode" },
+ { 'd', dump, "d <start> <end> Dump memory" },
+ { 'v', version, "v Show version" },
+ { 0, help, NULL },
+};
+
+void
+ao_cmd_init(void)
+{
+ ao_cmd_register(&ao_base_cmds[0]);
+ ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
+}
--- /dev/null
+/*
+ * 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;
+__xdata uint8_t ao_config_loaded;
+__xdata 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 "KD7SQG"
+#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000
+
+static void
+_ao_config_put(void)
+{
+ ao_ee_write_config((uint8_t *) &ao_config, sizeof (ao_config));
+}
+
+static void
+_ao_config_get(void)
+{
+ if (ao_config_loaded)
+ return;
+ ao_ee_read_config((uint8_t *) &ao_config, sizeof (ao_config));
+ if (ao_config.major != AO_CONFIG_MAJOR) {
+ ao_config.major = AO_CONFIG_MAJOR;
+ ao_config.minor = AO_CONFIG_MINOR;
+ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;
+ ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL;
+ ao_config.accel_zero_g = AO_CONFIG_DEFAULT_ACCEL_ZERO_G;
+ memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));
+ memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,
+ sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1);
+ ao_config_dirty = 1;
+ }
+ /* deal with minor version issues here, at 0 we haven't any */
+ ao_config_loaded = 1;
+}
+
+void
+ao_config_get(void)
+{
+ ao_mutex_get(&ao_config_mutex);
+ _ao_config_get();
+ 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;
+ char callsign[AO_MAX_CALLSIGN + 1];
+
+ 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_mutex_get(&ao_config_mutex);
+ _ao_config_get();
+ while (c < AO_MAX_CALLSIGN + 1)
+ callsign[c++] = '\0';
+ memcpy(&ao_config.callsign, &callsign,
+ AO_MAX_CALLSIGN + 1);
+ ao_config_dirty = 1;
+ ao_mutex_put(&ao_config_mutex);
+ ao_config_callsign_show();
+}
+
+void
+ao_config_radio_channel_show(void) __reentrant
+{
+ uint32_t freq = 434550L + ao_config.radio_channel * 100L;
+ uint16_t mhz = freq / 1000L;
+ uint16_t khz = freq % 1000L;
+
+ printf("Radio channel: %d (%d.%03dMHz)\n",
+ ao_config.radio_channel, mhz, khz);
+}
+
+void
+ao_config_radio_channel_set(void) __reentrant
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ ao_mutex_get(&ao_config_mutex);
+ _ao_config_get();
+ ao_config.radio_channel = ao_cmd_lex_i;
+ ao_config_dirty = 1;
+ ao_mutex_put(&ao_config_mutex);
+ ao_config_radio_channel_show();
+}
+
+void
+ao_config_main_deploy_show(void) __reentrant
+{
+ printf("Main deploy set to %d meters (%d feet)\n",
+ ao_config.main_deploy,
+ (int16_t) ((int32_t) ao_config.main_deploy * 328 / 100));
+}
+
+void
+ao_config_main_deploy_set(void) __reentrant
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ ao_mutex_get(&ao_config_mutex);
+ _ao_config_get();
+ ao_config.main_deploy = ao_cmd_lex_i;
+ ao_config_dirty = 1;
+ ao_mutex_put(&ao_config_mutex);
+ ao_config_main_deploy_show();
+}
+
+void
+ao_config_accel_zero_g_show(void) __reentrant
+{
+ printf("Accel zero g point set to %d\n",
+ ao_config.accel_zero_g);
+}
+
+#define ZERO_G_SAMPLES 1000
+
+static int16_t
+ao_config_accel_zero_g_auto(void) __reentrant
+{
+ uint16_t i;
+ int32_t accel_total;
+ uint8_t cal_adc_ring;
+
+ puts("Calibrating accelerometer..."); flush();
+ i = ZERO_G_SAMPLES;
+ accel_total = 0;
+ cal_adc_ring = ao_adc_head;
+ while (i) {
+ ao_sleep(&ao_adc_ring);
+ while (i && cal_adc_ring != ao_adc_head) {
+ accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel;
+ cal_adc_ring = ao_adc_ring_next(cal_adc_ring);
+ i--;
+ }
+ }
+ return (int16_t) (accel_total / ZERO_G_SAMPLES);
+}
+void
+ao_config_accel_zero_g_set(void) __reentrant
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ if (ao_cmd_lex_i == 0)
+ ao_cmd_lex_i = ao_config_accel_zero_g_auto();
+ ao_mutex_get(&ao_config_mutex);
+ _ao_config_get();
+ ao_config.accel_zero_g = ao_cmd_lex_i;
+ ao_config_dirty = 1;
+ ao_mutex_put(&ao_config_mutex);
+ ao_config_accel_zero_g_show();
+}
+
+struct ao_config_var {
+ char cmd;
+ void (*set)(void) __reentrant;
+ void (*show)(void) __reentrant;
+ const char *help;
+};
+
+void
+ao_config_help(void) __reentrant;
+
+void
+ao_config_show(void) __reentrant;
+
+void
+ao_config_write(void) __reentrant;
+
+__code struct ao_config_var ao_config_vars[] = {
+ { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show,
+ "m <meters> Set height above launch for main deploy (in meters)" },
+ { 'a', ao_config_accel_zero_g_set, ao_config_accel_zero_g_show,
+ "a <value> Set accelerometer zero g point (0 for auto)" },
+ { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show,
+ "r <channel> Set radio channel (freq = 434.550 + channel * .1)" },
+ { 'c', ao_config_callsign_set, ao_config_callsign_show,
+ "c <call> Set callsign broadcast in each packet (8 char max)" },
+ { 's', ao_config_show, ao_config_show,
+ "s Show current config values" },
+ { 'w', ao_config_write, ao_config_write,
+ "w Write current values to eeprom" },
+ { '?', ao_config_help, ao_config_help,
+ "? Show available config variables" },
+ { 0, ao_config_main_deploy_set, ao_config_main_deploy_show,
+ NULL },
+};
+
+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].cmd != '\0'; cmd++)
+ if (ao_config_vars[cmd].cmd == c) {
+ func = ao_config_vars[cmd].set;
+ break;
+ }
+ if (func)
+ (*func)();
+ else
+ ao_cmd_status = ao_cmd_syntax_error;
+}
+
+void
+ao_config_help(void) __reentrant
+{
+ uint8_t cmd;
+ for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++)
+ puts (ao_config_vars[cmd].help);
+}
+
+void
+ao_config_show(void) __reentrant
+{
+ uint8_t cmd;
+ for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++)
+ if (ao_config_vars[cmd].show != ao_config_vars[cmd].set)
+ (*ao_config_vars[cmd].show)();
+}
+
+void
+ao_config_write(void) __reentrant
+{
+ ao_mutex_get(&ao_config_mutex);
+ if (ao_config_dirty) {
+ _ao_config_put();
+ ao_config_dirty = 0;
+ printf("Saved\n");
+ }
+ ao_mutex_put(&ao_config_mutex);
+}
+
+__code struct ao_cmds ao_config_cmds[] = {
+ { 'c', ao_config_set, "c <var> <value> Set config variable (? for help, s to show)" },
+ { '\0', ao_config_set, NULL },
+};
+
+void
+ao_config_init(void)
+{
+ ao_cmd_register(&ao_config_cmds[0]);
+}
--- /dev/null
+/*
+ * 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 const int16_t altitude_table[2048] = {
+#include "altitude.h"
+};
+
+int16_t
+ao_pres_to_altitude(int16_t pres) __reentrant
+{
+ pres = pres >> 4;
+ if (pres < 0) pres = 0;
+ if (pres > 2047) pres = 2047;
+ return altitude_table[pres];
+}
+
+int16_t
+ao_altitude_to_pres(int16_t alt) __reentrant
+{
+ int16_t pres;
+
+ for (pres = 0; pres < 2047; pres++)
+ if (altitude_table[pres] <= alt)
+ break;
+ return pres << 4;
+}
+
+static __xdata uint8_t ao_temp_mutex;
+
+int16_t
+ao_temp_to_dC(int16_t temp) __reentrant
+{
+ int16_t ret;
+
+ ao_mutex_get(&ao_temp_mutex);
+ ret = (int16_t) ((temp >> 4) * 3300L / 2047L) - 500;
+ ao_mutex_put(&ao_temp_mutex);
+ return ret;
+}
--- /dev/null
+/*
+ * 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 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)
+
+static void
+ao_dbg_send_bits(uint8_t msk, uint8_t val)
+{
+ P0 = (P0 & ~msk) | (val & msk);
+ _asm
+ nop
+ nop
+ _endasm;
+}
+
+void
+ao_dbg_send_byte(uint8_t byte)
+{
+ __xdata uint8_t b, d;
+
+ P0 |= DBG_DATA;
+ P0DIR |= 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);
+ }
+ P0DIR &= ~DBG_DATA;
+}
+
+uint8_t
+ao_dbg_recv_byte(void)
+{
+ __xdata 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
+
+__xdata uint8_t save_acc;
+__xdata uint8_t save_psw;
+__xdata uint8_t save_dpl0;
+__xdata uint8_t save_dph0;
+__xdata uint8_t save_dpl1;
+__xdata 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)
+{
+ /* Disable peripheral use of P0 */
+ ADCCFG = 0;
+ P0SEL = 0;
+
+
+ /* make P0_4 tri-state */
+ P0INP = DBG_DATA;
+ P2INP &= ~(P2INP_PDUP0_PULL_DOWN);
+
+ /* Raise RESET_N and CLOCK */
+ P0 = DBG_RESET_N | DBG_CLOCK;
+
+ /* RESET_N and CLOCK are outputs now */
+ P0DIR = DBG_RESET_N | DBG_CLOCK;
+}
+
+static void
+ao_dbg_long_delay(void)
+{
+ uint8_t n;
+
+ for (n = 0; n < 20; n++)
+ _asm nop _endasm;
+}
+
+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_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| 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_dbg_long_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_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| 0 );
+ 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();
+}
+
+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)
+{
+ __xdata uint16_t count;
+ __xdata uint16_t i;
+ __xdata 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)
+{
+ __xdata 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)
+{
+ __xdata uint16_t count;
+ __xdata uint16_t addr;
+ __xdata uint8_t b;
+ __xdata 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)
+{
+ __xdata uint16_t count;
+ __xdata uint16_t addr;
+ __xdata 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] = {
+ { 'D', debug_enable, "D Enable debug mode" },
+ { 'G', debug_get, "G <count> Get data from debug port" },
+ { 'I', debug_input, "I <count> <addr> Input <count> bytes to target at <addr>" },
+ { 'O', debug_output, "O <count> <addr> Output <count> bytes to target at <addr>" },
+ { 'P', debug_put, "P <byte> ... Put data to debug port" },
+ { 'R', debug_reset, "R Reset target" },
+ { 0, debug_reset, 0 },
+};
+
+void
+ao_dbg_init(void)
+{
+ ao_cmd_register(&ao_dbg_cmds[0]);
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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"
+
+/*
+ * Using SPI on USART 0, with P1_2 as the chip select
+ */
+
+#define EE_CS P1_2
+#define EE_CS_INDEX 2
+
+__xdata uint8_t ao_ee_dma_in_done;
+__xdata uint8_t ao_ee_dma_out_done;
+__xdata uint8_t ao_ee_mutex;
+
+uint8_t ao_ee_dma_out_id;
+uint8_t ao_ee_dma_in_id;
+
+static __xdata uint8_t ao_ee_const = 0xff;
+
+#define ao_ee_delay() do { \
+ _asm nop _endasm; \
+ _asm nop _endasm; \
+ _asm nop _endasm; \
+} while(0)
+
+void ao_ee_cs_low(void)
+{
+ ao_ee_delay();
+ EE_CS = 0;
+ ao_ee_delay();
+}
+
+void ao_ee_cs_high(void)
+{
+ ao_ee_delay();
+ EE_CS = 1;
+ ao_ee_delay();
+}
+
+/* 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
+ */
+static void
+ao_ee_send(void __xdata *block, uint16_t len)
+{
+ ao_dma_set_transfer(ao_ee_dma_in_id,
+ &U0DBUFXADDR,
+ &ao_ee_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_ee_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_ee_dma_in_id);
+ ao_dma_start(ao_ee_dma_out_id);
+ ao_dma_trigger(ao_ee_dma_out_id);
+ __critical while (!ao_ee_dma_in_done)
+ ao_sleep(&ao_ee_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.
+ */
+static void
+ao_ee_recv(void __xdata *block, uint16_t len)
+{
+ ao_dma_set_transfer(ao_ee_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_ee_dma_out_id,
+ &ao_ee_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_ee_dma_in_id);
+ ao_dma_start(ao_ee_dma_out_id);
+ ao_dma_trigger(ao_ee_dma_out_id);
+ __critical while (!ao_ee_dma_in_done)
+ ao_sleep(&ao_ee_dma_in_done);
+}
+
+#define EE_BLOCK 256
+
+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_ee_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_ee_send(&ao_ee_instruction, 1);
+ ao_ee_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_ee_send(&ao_ee_instruction, 2);
+ ao_ee_cs_high();
+}
+
+#define EE_BLOCK_NONE 0xffff
+
+static __xdata uint8_t ao_ee_data[EE_BLOCK];
+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_ee_send(&ao_ee_instruction, 4);
+ ao_ee_send(ao_ee_data, EE_BLOCK);
+ 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_ee_send(&ao_ee_instruction, 4);
+ ao_ee_recv(ao_ee_data, EE_BLOCK);
+ 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_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant
+{
+ uint16_t block;
+ uint16_t this_len;
+ uint8_t this_off;
+
+ if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE)
+ return 0;
+ while (len) {
+
+ /* Compute portion of transfer within
+ * a single block
+ */
+ this_off = pos;
+ this_len = 256 - (uint16_t) this_off;
+ block = (uint16_t) (pos >> 8);
+ if (this_len > len)
+ this_len = len;
+ if (this_len & 0xff00)
+ ao_panic(AO_PANIC_EE);
+
+ /* Transfer the data */
+ ao_mutex_get(&ao_ee_mutex); {
+ if (this_len != 256)
+ ao_ee_fill(block);
+ else {
+ ao_ee_flush_internal();
+ ao_ee_block = block;
+ }
+ memcpy(ao_ee_data + this_off, buf, this_len);
+ ao_ee_block_dirty = 1;
+ } ao_mutex_put(&ao_ee_mutex);
+
+ /* See how much is left */
+ buf += this_len;
+ len -= this_len;
+ }
+ return 1;
+}
+
+uint8_t
+ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant
+{
+ uint16_t block;
+ uint16_t this_len;
+ uint8_t this_off;
+
+ if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE)
+ return 0;
+ while (len) {
+
+ /* Compute portion of transfer within
+ * a single block
+ */
+ this_off = pos;
+ this_len = 256 - (uint16_t) this_off;
+ block = (uint16_t) (pos >> 8);
+ if (this_len > len)
+ this_len = len;
+ if (this_len & 0xff00)
+ ao_panic(AO_PANIC_EE);
+
+ /* Transfer the data */
+ ao_mutex_get(&ao_ee_mutex); {
+ ao_ee_fill(block);
+ memcpy(buf, ao_ee_data + this_off, this_len);
+ } ao_mutex_put(&ao_ee_mutex);
+
+ /* See how much is left */
+ buf += this_len;
+ len -= this_len;
+ }
+ return 1;
+}
+
+void
+ao_ee_flush(void) __reentrant
+{
+ ao_mutex_get(&ao_ee_mutex); {
+ ao_ee_flush_internal();
+ } ao_mutex_put(&ao_ee_mutex);
+}
+
+/*
+ * Read/write the config block, which is in
+ * the last block of the ao_eeprom
+ */
+uint8_t
+ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
+{
+ if (len > AO_EE_BLOCK_SIZE)
+ return 0;
+ ao_mutex_get(&ao_ee_mutex); {
+ ao_ee_fill(AO_EE_CONFIG_BLOCK);
+ memcpy(ao_ee_data, buf, len);
+ ao_ee_block_dirty = 1;
+ ao_ee_flush_internal();
+ } ao_mutex_put(&ao_ee_mutex);
+ return 1;
+}
+
+uint8_t
+ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
+{
+ if (len > AO_EE_BLOCK_SIZE)
+ return 0;
+ ao_mutex_get(&ao_ee_mutex); {
+ ao_ee_fill(AO_EE_CONFIG_BLOCK);
+ memcpy(buf, ao_ee_data, len);
+ } ao_mutex_put(&ao_ee_mutex);
+ return 1;
+}
+
+static void
+ee_dump(void)
+{
+ __xdata uint8_t b;
+ __xdata uint16_t block;
+ __xdata uint8_t i;
+
+ ao_cmd_hex();
+ block = ao_cmd_lex_i;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ i = 0;
+ do {
+ if ((i & 7) == 0) {
+ if (i)
+ putchar('\n');
+ ao_cmd_put16((uint16_t) i);
+ }
+ putchar(' ');
+ ao_ee_read(((uint32_t) block << 8) | i, &b, 1);
+ ao_cmd_put8(b);
+ ++i;
+ } while (i != 0);
+ putchar('\n');
+}
+
+static void
+ee_store(void)
+{
+ __xdata uint16_t block;
+ __xdata uint8_t i;
+ __xdata uint16_t len;
+ __xdata uint8_t b;
+ __xdata 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_ee_write(addr, &b, 1);
+ addr++;
+ }
+ ao_ee_flush();
+}
+
+__code struct ao_cmds ao_ee_cmds[] = {
+ { 'e', ee_dump, "e <block> Dump a block of EEPROM data" },
+ { 'w', ee_store, "w <block> <start> <len> <data> ... Write data to EEPROM" },
+ { 0, ee_store, NULL },
+};
+
+/*
+ * To initialize the chip, set up the CS line and
+ * the SPI interface
+ */
+void
+ao_ee_init(void)
+{
+ /* set up CS */
+ EE_CS = 1;
+ P1DIR |= (1 << EE_CS_INDEX);
+ P1SEL &= ~(1 << EE_CS_INDEX);
+
+ /* 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_ee_dma_out_id = ao_dma_alloc(&ao_ee_dma_out_done);
+
+ /* Set up IN DMA */
+ ao_ee_dma_in_id = ao_dma_alloc(&ao_ee_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,
+ * while the 25LC1024 is limited to 20MHz. So,
+ * use the 3MHz clock (BAUD_E 17, BAUD_M 0)
+ */
+ U0BAUD = 0;
+ U0GCR = (UxGCR_CPOL_NEGATIVE |
+ UxGCR_CPHA_FIRST_EDGE |
+ UxGCR_ORDER_MSB |
+ (17 << UxGCR_BAUD_E_SHIFT));
+ ao_cmd_register(&ao_ee_cmds[0]);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
+
+/* Main flight thread. */
+
+__pdata enum ao_flight_state ao_flight_state; /* current flight state */
+__pdata uint16_t ao_flight_tick; /* time of last data */
+__pdata uint16_t ao_flight_prev_tick; /* time of previous data */
+__pdata int16_t ao_flight_accel; /* filtered acceleration */
+__pdata int16_t ao_flight_pres; /* filtered pressure */
+__pdata int16_t ao_ground_pres; /* startup pressure */
+__pdata int16_t ao_ground_accel; /* startup acceleration */
+__pdata int16_t ao_min_pres; /* minimum recorded pressure */
+__pdata uint16_t ao_launch_tick; /* time of launch detect */
+__pdata int16_t ao_main_pres; /* pressure to eject main */
+
+/*
+ * track min/max data over a long interval to detect
+ * resting
+ */
+__pdata uint16_t ao_interval_end;
+__pdata int16_t ao_interval_cur_min_accel;
+__pdata int16_t ao_interval_cur_max_accel;
+__pdata int16_t ao_interval_cur_min_pres;
+__pdata int16_t ao_interval_cur_max_pres;
+__pdata int16_t ao_interval_min_accel;
+__pdata int16_t ao_interval_max_accel;
+__pdata int16_t ao_interval_min_pres;
+__pdata int16_t ao_interval_max_pres;
+
+__data uint8_t ao_flight_adc;
+__pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres;
+
+/* 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
+/* convert m/s to velocity count */
+#define VEL_MPS_TO_COUNT(mps) ((int32_t) (((mps) / GRAVITY) * ACCEL_G * 100))
+
+#define ACCEL_G 265
+#define ACCEL_ZERO_G 16000
+#define ACCEL_NOSE_UP (ACCEL_G * 2 /3)
+#define ACCEL_BOOST ACCEL_G * 2
+#define ACCEL_INT_LAND (ACCEL_G / 10)
+#define ACCEL_VEL_LAND VEL_MPS_TO_COUNT(10)
+#define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200)
+#define ACCEL_VEL_APOGEE VEL_MPS_TO_COUNT(2)
+#define ACCEL_VEL_MAIN VEL_MPS_TO_COUNT(100)
+#define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5)
+
+/*
+ * 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
+ */
+
+#define BARO_kPa 268
+#define BARO_LAUNCH (BARO_kPa / 5) /* .2kPa, or about 20m */
+#define BARO_APOGEE (BARO_kPa / 10) /* .1kPa, or about 10m */
+#define BARO_COAST (BARO_kPa * 5) /* 5kpa, or about 500m */
+#define BARO_MAIN (BARO_kPa) /* 1kPa, or about 100m */
+#define BARO_INT_LAND (BARO_kPa / 20) /* .05kPa, or about 5m */
+#define BARO_LAND (BARO_kPa * 10) /* 10kPa or about 1000m */
+
+/* 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)
+
+/* This value is scaled in a weird way. It's a running total of accelerometer
+ * readings minus the ground accelerometer reading. That means it measures
+ * velocity, and quite accurately too. As it gets updated 100 times a second,
+ * it's scaled by 100
+ */
+__pdata int32_t ao_flight_vel;
+__pdata int32_t ao_min_vel;
+__pdata int32_t ao_old_vel;
+__pdata int16_t ao_old_vel_tick;
+__xdata int32_t ao_raw_accel_sum, ao_raw_pres_sum;
+
+/* 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(20)
+
+#define abs(a) ((a) < 0 ? -(a) : (a))
+
+void
+ao_flight(void)
+{
+ __pdata static uint16_t nsamples = 0;
+
+ ao_flight_adc = ao_adc_head;
+ ao_raw_accel_prev = 0;
+ ao_raw_accel = 0;
+ ao_raw_pres = 0;
+ ao_flight_tick = 0;
+ for (;;) {
+ ao_sleep(&ao_adc_ring);
+ while (ao_flight_adc != ao_adc_head) {
+ __pdata uint8_t ticks;
+ __pdata int16_t ao_vel_change;
+ ao_flight_prev_tick = ao_flight_tick;
+
+ /* Capture a sample */
+ ao_raw_accel = ao_adc_ring[ao_flight_adc].accel;
+ ao_raw_pres = ao_adc_ring[ao_flight_adc].pres;
+ ao_flight_tick = ao_adc_ring[ao_flight_adc].tick;
+
+ ao_flight_accel -= ao_flight_accel >> 4;
+ ao_flight_accel += ao_raw_accel >> 4;
+ ao_flight_pres -= ao_flight_pres >> 4;
+ ao_flight_pres += ao_raw_pres >> 4;
+ /* Update velocity
+ *
+ * The accelerometer is mounted so that
+ * acceleration yields negative values
+ * while deceleration yields positive values,
+ * so subtract instead of add.
+ */
+ ticks = ao_flight_tick - ao_flight_prev_tick;
+ ao_vel_change = (((ao_raw_accel >> 1) + (ao_raw_accel_prev >> 1)) - ao_ground_accel);
+ ao_raw_accel_prev = ao_raw_accel;
+
+ /* one is a common interval */
+ if (ticks == 1)
+ ao_flight_vel -= (int32_t) ao_vel_change;
+ else
+ ao_flight_vel -= (int32_t) ao_vel_change * (int32_t) ticks;
+
+ ao_flight_adc = ao_adc_ring_next(ao_flight_adc);
+ }
+
+ if (ao_flight_pres < ao_min_pres)
+ ao_min_pres = ao_flight_pres;
+ if (ao_flight_vel >= 0) {
+ if (ao_flight_vel < ao_min_vel)
+ ao_min_vel = ao_flight_vel;
+ } else {
+ if (-ao_flight_vel < ao_min_vel)
+ ao_min_vel = -ao_flight_vel;
+ }
+
+ switch (ao_flight_state) {
+ case ao_flight_startup:
+
+ /* startup state:
+ *
+ * Collect 1000 samples of acceleration and pressure
+ * data and average them to find the resting values
+ */
+ if (nsamples < 1000) {
+ ao_raw_accel_sum += ao_raw_accel;
+ ao_raw_pres_sum += ao_raw_pres;
+ ++nsamples;
+ continue;
+ }
+ ao_ground_accel = (ao_raw_accel_sum / nsamples);
+ ao_ground_pres = (ao_raw_pres_sum / nsamples);
+ ao_min_pres = ao_ground_pres;
+ ao_config_get();
+ ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy);
+ ao_flight_vel = 0;
+ ao_min_vel = 0;
+ ao_old_vel = ao_flight_vel;
+ ao_old_vel_tick = ao_flight_tick;
+
+ /* Go to launchpad state if the nose is pointing up */
+ ao_config_get();
+ if (ao_flight_accel < ao_config.accel_zero_g - ACCEL_NOSE_UP) {
+
+ /* Disable the USB controller in flight mode
+ * to save power
+ */
+ ao_usb_disable();
+
+ /* Turn on telemetry system
+ */
+ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD);
+
+ ao_flight_state = ao_flight_launchpad;
+ ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+ } else {
+ ao_flight_state = ao_flight_idle;
+
+ /* Turn on the Green LED in idle mode
+ */
+ ao_led_on(AO_LED_GREEN);
+ ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+ }
+ /* signal successful initialization by turning off the LED */
+ ao_led_off(AO_LED_RED);
+ break;
+ case ao_flight_launchpad:
+
+ /* Trim velocity
+ *
+ * Once a second, remove any velocity from
+ * a second ago
+ */
+ if ((int16_t) (ao_flight_tick - ao_old_vel_tick) >= AO_SEC_TO_TICKS(1)) {
+ ao_old_vel_tick = ao_flight_tick;
+ ao_flight_vel -= ao_old_vel;
+ ao_old_vel = ao_flight_vel;
+ }
+ /* pad to boost:
+ *
+ * accelerometer: > 2g AND velocity > 5m/s
+ * OR
+ * barometer: > 20m vertical motion
+ *
+ * The accelerometer should always detect motion before
+ * the barometer, but we use both to make sure this
+ * transition is detected
+ */
+ if ((ao_flight_accel < ao_ground_accel - ACCEL_BOOST &&
+ ao_flight_vel > ACCEL_VEL_BOOST) ||
+ ao_flight_pres < ao_ground_pres - BARO_LAUNCH)
+ {
+ ao_flight_state = ao_flight_boost;
+ ao_launch_tick = ao_flight_tick;
+
+ /* start logging data */
+ ao_log_start();
+
+ /* Increase telemetry rate */
+ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT);
+
+ ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+ break;
+ }
+ break;
+ case ao_flight_boost:
+
+ /* boost to coast:
+ *
+ * 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_flight_accel > ao_ground_accel + (ACCEL_G >> 2) ||
+ (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX)
+ {
+ ao_flight_state = ao_flight_coast;
+ ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+ break;
+ }
+ break;
+ case ao_flight_coast:
+
+ /* coast to apogee detect:
+ *
+ * accelerometer: integrated velocity < 200 m/s
+ * OR
+ * barometer: fall at least 500m from max altitude
+ *
+ * This extra state is required to avoid mis-detecting
+ * apogee due to mach transitions.
+ *
+ * XXX this is essentially a single-detector test
+ * as the 500m altitude change would likely result
+ * in a loss of the rocket. More data on precisely
+ * how big a pressure change the mach transition
+ * generates would be useful here.
+ */
+ if (ao_flight_vel < ACCEL_VEL_MACH ||
+ ao_flight_pres > ao_min_pres + BARO_COAST)
+ {
+ /* set min velocity to current velocity for
+ * apogee detect
+ */
+ ao_min_vel = abs(ao_flight_vel);
+ ao_flight_state = ao_flight_apogee;
+ ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+ }
+ break;
+ case ao_flight_apogee:
+
+ /* apogee detect to drogue deploy:
+ *
+ * accelerometer: abs(velocity) > min_velocity + 2m/s
+ * OR
+ * barometer: fall at least 10m
+ *
+ * If the barometer saturates because the flight
+ * goes over its measuring range (about 53k'),
+ * requiring a 10m fall will avoid prematurely
+ * detecting apogee; the accelerometer will take
+ * over in that case and the integrated velocity
+ * measurement should suffice to find apogee
+ */
+ if (/* abs(ao_flight_vel) > ao_min_vel + ACCEL_VEL_APOGEE || */
+ ao_flight_pres > ao_min_pres + BARO_APOGEE)
+ {
+ /* ignite the drogue charge */
+ ao_ignite(ao_igniter_drogue);
+
+ /* slow down the telemetry system */
+ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER);
+
+ /* slow down the ADC sample rate */
+ ao_timer_set_adc_interval(10);
+
+ /*
+ * Start recording min/max accel and pres for a while
+ * to figure out when the rocket has landed
+ */
+ /* Set the 'last' limits to max range to prevent
+ * early resting detection
+ */
+ ao_interval_min_accel = 0;
+ ao_interval_max_accel = 0x7fff;
+ ao_interval_min_pres = 0;
+ ao_interval_max_pres = 0x7fff;
+
+ /* initialize interval values */
+ ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS;
+
+ ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres;
+ ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel;
+
+ /* 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_flight_pres >= ao_main_pres)
+ {
+ ao_ignite(ao_igniter_main);
+ ao_flight_state = ao_flight_main;
+ ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
+ }
+
+ /* fall through... */
+ case ao_flight_main:
+
+ /* drogue/main to land:
+ *
+ * accelerometer: value stable
+ * AND
+ * barometer: altitude stable and within 1000m of the launch altitude
+ */
+
+ if (ao_flight_pres < ao_interval_cur_min_pres)
+ ao_interval_cur_min_pres = ao_flight_pres;
+ if (ao_flight_pres > ao_interval_cur_max_pres)
+ ao_interval_cur_max_pres = ao_flight_pres;
+ if (ao_flight_accel < ao_interval_cur_min_accel)
+ ao_interval_cur_min_accel = ao_flight_accel;
+ if (ao_flight_accel > ao_interval_cur_max_accel)
+ ao_interval_cur_max_accel = ao_flight_accel;
+
+ if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) {
+ ao_interval_max_pres = ao_interval_cur_max_pres;
+ ao_interval_min_pres = ao_interval_cur_min_pres;
+ ao_interval_max_accel = ao_interval_cur_max_accel;
+ ao_interval_min_accel = ao_interval_cur_min_accel;
+ ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS;
+ ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres;
+ ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel;
+ }
+
+ if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND &&
+ ao_flight_pres > ao_ground_pres - BARO_LAND &&
+ (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND)
+ {
+ 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));
+ }
+ break;
+ case ao_flight_landed:
+ break;
+ }
+ }
+}
+
+#define AO_ACCEL_COUNT_TO_MSS(count) ((count) / 27)
+#define AO_VEL_COUNT_TO_MS(count) ((int16_t) ((count) / 2700))
+
+static void
+ao_flight_status(void)
+{
+ printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n",
+ ao_state_names[ao_flight_state],
+ AO_ACCEL_COUNT_TO_MSS(ACCEL_ZERO_G - ao_flight_accel),
+ AO_VEL_COUNT_TO_MS(ao_flight_vel),
+ ao_pres_to_altitude(ao_flight_pres),
+ ao_pres_to_altitude(ao_main_pres));
+}
+
+static __xdata struct ao_task flight_task;
+
+__code struct ao_cmds ao_flight_cmds[] = {
+ { 'f', ao_flight_status, "f Display current flight state" },
+ { 0, ao_flight_status, NULL }
+};
+
+void
+ao_flight_init(void)
+{
+ ao_flight_state = ao_flight_startup;
+ ao_interval_min_accel = 0;
+ ao_interval_max_accel = 0x7fff;
+ ao_interval_min_pres = 0;
+ ao_interval_max_pres = 0x7fff;
+ ao_interval_end = AO_INTERVAL_TICKS;
+
+ ao_add_task(&flight_task, ao_flight, "flight");
+ ao_cmd_register(&ao_flight_cmds[0]);
+}
--- /dev/null
+/*
+ * 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>
+
+#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_launchpad = 2,
+ ao_flight_boost = 3,
+ ao_flight_coast = 4,
+ ao_flight_apogee = 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()
+#define ao_cmd_register(c)
+#define ao_usb_disable()
+#define ao_telemetry_set_interval(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);
+
+void
+ao_sleep(void *wchan);
+
+const char const * const ao_state_names[] = {
+ "startup", "idle", "pad", "boost", "coast",
+ "apogee", "drogue", "main", "landed", "invalid"
+};
+
+struct ao_cmds {
+ char cmd;
+ void (*func)(void);
+ const char *help;
+};
+
+
+static int16_t altitude_table[2048] = {
+#include "altitude.h"
+};
+
+int16_t
+ao_pres_to_altitude(int16_t pres) __reentrant
+{
+ pres = pres >> 4;
+ if (pres < 0) pres = 0;
+ if (pres > 2047) pres = 2047;
+ return altitude_table[pres];
+}
+
+int16_t
+ao_altitude_to_pres(int16_t alt) __reentrant
+{
+ int16_t pres;
+
+ for (pres = 0; pres < 2047; pres++)
+ if (altitude_table[pres] <= alt)
+ break;
+ return pres << 4;
+}
+
+struct ao_config {
+ uint16_t main_deploy;
+ int16_t accel_zero_g;
+};
+
+#define ao_config_get()
+
+struct ao_config ao_config = { 250, 16000 };
+
+#include "ao_flight.c"
+
+void
+ao_insert(void)
+{
+ 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) {
+ printf("time %g accel %d pres %d\n",
+ (double) ao_adc_static.tick / 100,
+ ao_adc_static.accel,
+ ao_adc_static.pres);
+ }
+}
+
+static int ao_records_read = 0;
+static int ao_eof_read = 0;
+static int ao_flight_ground_accel;
+static int ao_flight_started = 0;
+
+void
+ao_sleep(void *wchan)
+{
+ ao_dump_state();
+ if (wchan == &ao_adc_ring) {
+ char type;
+ uint16_t tick;
+ uint16_t a, b;
+ int ret;
+ 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) {
+ printf ("no more data, exiting simulation\n");
+ exit(0);
+ }
+ 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[2], NULL, 16);
+ } 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]);
+ }
+ }
+ if (type != 'F' && !ao_flight_started)
+ continue;
+
+ switch (type) {
+ case 'F':
+ ao_flight_ground_accel = a;
+ ao_flight_started = 1;
+ break;
+ case 'S':
+ break;
+ case 'A':
+ ao_adc_static.tick = tick;
+ ao_adc_static.accel = a;
+ 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)
+{
+ if (ao_flight_state == ao_flight_startup)
+ return;
+ printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n",
+ ao_state_names[ao_flight_state],
+ (ao_ground_accel - ao_flight_accel) / COUNTS_PER_G * GRAVITY,
+ (double) ao_flight_vel / 100 / COUNTS_PER_G * GRAVITY,
+ ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres),
+ ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres));
+ if (ao_flight_state == ao_flight_landed)
+ exit(0);
+}
+
+int
+main (int argc, char **argv)
+{
+ emulator_in = fopen (argv[1], "r");
+ if (!emulator_in) {
+ perror(argv[1]);
+ exit(1);
+ }
+ ao_flight_init();
+ ao_flight();
+}
--- /dev/null
+/*
+ * 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_GPS_LEADER 6
+
+static const char ao_gps_header[] = "GPGGA,";
+__xdata uint8_t ao_gps_mutex;
+static __xdata char ao_gps_char;
+static __xdata uint8_t ao_gps_cksum;
+static __xdata uint8_t ao_gps_error;
+
+__xdata struct ao_gps_data ao_gps_data;
+static __xdata struct ao_gps_data ao_gps_next;
+
+const char ao_gps_config[] =
+ "$PSRF103,00,00,01,01*25\r\n" /* GGA 1 per sec */
+ "$PSRF103,01,00,00,01*25\r\n" /* GLL disable */
+ "$PSRF103,02,00,00,01*26\r\n" /* GSA disable */
+ "$PSRF103,03,00,00,01*27\r\n" /* GSV disable */
+ "$PSRF103,04,00,00,01*20\r\n" /* RMC disable */
+ "$PSRF103,05,00,00,01*21\r\n"; /* VTG disable */
+
+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(void)
+{
+ while (ao_gps_char >= '0')
+ ao_gps_lexchar();
+}
+
+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)
+{
+ while (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*')
+ ao_gps_lexchar();
+}
+
+__xdata static uint8_t ao_gps_num_width;
+
+static int16_t
+ao_gps_decimal(uint8_t max_width)
+{
+ int16_t v;
+ __xdata 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 void
+ao_gps_parse_pos(__xdata struct ao_gps_pos * pos, uint8_t deg_width) __reentrant
+{
+ pos->degrees = ao_gps_decimal(deg_width);
+ pos->minutes = ao_gps_decimal(2);
+ if (ao_gps_char == '.') {
+ pos->minutes_fraction = ao_gps_decimal(4);
+ while (ao_gps_num_width < 4) {
+ pos->minutes_fraction *= 10;
+ ao_gps_num_width++;
+ }
+ } else {
+ pos->minutes_fraction = 0;
+ if (ao_gps_char != ',')
+ ao_gps_error = 1;
+ }
+}
+
+static void
+ao_gps_parse_flag(char yes_c, uint8_t yes, char no_c, uint8_t no) __reentrant
+{
+ ao_gps_skip_sep();
+ if (ao_gps_char == yes_c)
+ ao_gps_next.flags |= yes;
+ else if (ao_gps_char == no_c)
+ ao_gps_next.flags |= no;
+ else
+ ao_gps_error = 1;
+ ao_gps_lexchar();
+}
+
+
+void
+ao_gps(void) __reentrant
+{
+ char c;
+ uint8_t i;
+
+ for (i = 0; (c = ao_gps_config[i]); i++)
+ ao_serial_putchar(c);
+ for (;;) {
+ /* Locate the begining of the next record */
+ for (;;) {
+ c = ao_serial_getchar();
+ if (c == '$')
+ break;
+ }
+
+ ao_gps_cksum = 0;
+ ao_gps_error = 0;
+
+ /* Skip anything other than GGA */
+ for (i = 0; i < AO_GPS_LEADER; i++) {
+ ao_gps_lexchar();
+ if (ao_gps_char != ao_gps_header[i])
+ break;
+ }
+ if (i != AO_GPS_LEADER)
+ continue;
+
+ /* 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.flags = 0;
+ 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_parse_pos(&ao_gps_next.latitude, 2);
+ ao_gps_parse_flag('N', AO_GPS_LATITUDE_NORTH, 'S', AO_GPS_LATITUDE_SOUTH);
+ ao_gps_parse_pos(&ao_gps_next.longitude, 3);
+ ao_gps_parse_flag('W', AO_GPS_LONGITUDE_WEST, 'E', AO_GPS_LONGITUDE_EAST);
+
+ 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();
+ ao_gps_skip_field(); /* Horizontal dilution */
+
+ 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);
+ memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data));
+ ao_mutex_put(&ao_gps_mutex);
+ ao_wakeup(&ao_gps_data);
+ }
+ }
+}
+
+__xdata struct ao_task ao_gps_task;
+
+static void
+gps_dump(void) __reentrant
+{
+ ao_mutex_get(&ao_gps_mutex);
+ ao_gps_print(&ao_gps_data);
+ ao_mutex_put(&ao_gps_mutex);
+}
+
+__code struct ao_cmds ao_gps_cmds[] = {
+ { 'g', gps_dump, "g Display current GPS values" },
+ { 0, gps_dump, NULL },
+};
+
+void
+ao_gps_init(void)
+{
+ ao_add_task(&ao_gps_task, ao_gps, "gps");
+ ao_cmd_register(&ao_gps_cmds[0]);
+}
--- /dev/null
+/*
+ * 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_print(__xdata struct ao_gps_data *gps_data) __reentrant
+{
+ printf("GPS %2d sat",
+ (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);;
+ if (gps_data->flags & AO_GPS_VALID) {
+ printf(" %2d:%02d:%02d %2d°%2d.%04d'%c %2d°%2d.%04d'%c %5dm\n",
+ gps_data->hour,
+ gps_data->minute,
+ gps_data->second,
+ gps_data->latitude.degrees,
+ gps_data->latitude.minutes,
+ gps_data->latitude.minutes_fraction,
+ (gps_data->flags & AO_GPS_LATITUDE_MASK) == AO_GPS_LATITUDE_NORTH ?
+ 'N' : 'S',
+ gps_data->longitude.degrees,
+ gps_data->longitude.minutes,
+ gps_data->longitude.minutes_fraction,
+ (gps_data->flags & AO_GPS_LONGITUDE_MASK) == AO_GPS_LONGITUDE_WEST ?
+ 'W' : 'E',
+ gps_data->altitude,
+ (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
+ } else {
+ printf(" unlocked\n");
+ }
+}
--- /dev/null
+/*
+ * 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_gps_data gps_data;
+
+ for (;;) {
+ ao_sleep(&ao_gps_data);
+ ao_mutex_get(&ao_gps_mutex);
+ memcpy(&gps_data, &ao_gps_data, sizeof (struct ao_gps_data));
+ ao_mutex_put(&ao_gps_mutex);
+
+ if (!(gps_data.flags & AO_GPS_VALID))
+ continue;
+
+ gps_log.tick = ao_time();
+ 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.degrees = gps_data.latitude.degrees;
+ gps_log.u.gps_latitude.minutes = gps_data.latitude.minutes;
+ gps_log.u.gps_latitude.minutes_fraction = gps_data.latitude.minutes_fraction;
+ ao_log_data(&gps_log);
+ gps_log.type = AO_LOG_GPS_LON;
+ gps_log.u.gps_longitude.degrees = gps_data.longitude.degrees;
+ gps_log.u.gps_longitude.minutes = gps_data.longitude.minutes;
+ gps_log.u.gps_longitude.minutes_fraction = gps_data.longitude.minutes_fraction;
+ 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);
+ }
+}
+
+__xdata struct ao_task ao_gps_report_task;
+
+void
+ao_gps_report_init(void)
+{
+ ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report");
+}
--- /dev/null
+/*
+ * 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_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)
+
+/* 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(500)
+#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[0]);
+}
+
+enum ao_igniter_status
+ao_igniter_status(enum ao_igniter igniter)
+{
+ __xdata struct ao_adc adc;
+ __xdata int16_t value;
+ __xdata uint8_t request, firing, fired;
+
+ __critical {
+ ao_adc_sleep();
+ 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 (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;
+ }
+ ao_ignition[igniter].firing = 0;
+}
+
+void
+ao_igniter(void)
+{
+ __xdata enum ao_ignter igniter;
+ __xdata enum ao_igniter_status status;
+
+ for (;;) {
+ ao_sleep(&ao_ignition);
+ for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) {
+ if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) {
+ ao_igniter_fire(igniter);
+ ao_delay(AO_IGNITER_CHARGE_TIME);
+ status = ao_igniter_status(igniter);
+ if (status == ao_igniter_open)
+ ao_ignition[igniter].fired = 1;
+ }
+ }
+ }
+}
+
+static 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;
+}
+
+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 *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[] = {
+ { 'i', ao_ignite_manual, "i <key> {main|drogue} Fire igniter. <key> is doit with D&I" },
+ { 't', ao_ignite_test, "t Test igniter continuity" },
+ { 0, ao_ignite_manual, NULL },
+};
+
+__xdata struct ao_task ao_igniter_task;
+
+void
+ao_igniter_init(void)
+{
+ AO_IGNITER_DROGUE = 0;
+ AO_IGNITER_MAIN = 0;
+ AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT;
+ ao_cmd_register(&ao_ignite_cmds[0]);
+ ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
+}
--- /dev/null
+/*
+ * 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_LED_ALL (AO_LED_GREEN|AO_LED_RED)
+
+__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;
+}
--- /dev/null
+/*
+ * 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 __pdata uint32_t ao_log_current_pos;
+static __pdata uint32_t ao_log_start_pos;
+static __xdata uint8_t ao_log_running;
+static __xdata uint8_t ao_log_mutex;
+
+static uint8_t
+ao_log_csum(uint8_t *b)
+{
+ uint8_t sum = 0x5a;
+ uint8_t i;
+
+ for (i = 0; i < sizeof (struct ao_log_record); i++)
+ sum += *b++;
+ return -sum;
+}
+
+void
+ao_log_data(struct ao_log_record *log)
+{
+ /* set checksum */
+ log->csum = 0;
+ log->csum = ao_log_csum((uint8_t *) log);
+ ao_mutex_get(&ao_log_mutex); {
+ if (ao_log_running) {
+ ao_ee_write(ao_log_current_pos,
+ (uint8_t *) log,
+ sizeof (struct ao_log_record));
+ ao_log_current_pos += sizeof (struct ao_log_record);
+ if (ao_log_current_pos >= AO_EE_DATA_SIZE)
+ ao_log_current_pos = 0;
+ if (ao_log_current_pos == ao_log_start_pos)
+ ao_log_running = 0;
+ }
+ } ao_mutex_put(&ao_log_mutex);
+}
+
+void
+ao_log_flush(void)
+{
+ ao_ee_flush();
+}
+
+__xdata struct ao_log_record ao_log_dump;
+static __xdata uint16_t ao_log_dump_flight;
+static __xdata uint32_t ao_log_dump_pos;
+
+static uint8_t
+ao_log_dump_check_data(void)
+{
+ if (ao_log_csum((uint8_t *) &ao_log_dump) != 0)
+ return 0;
+ return 1;
+}
+
+static uint8_t
+ao_log_dump_scan(void)
+{
+ if (!ao_ee_read(0, (uint8_t *) &ao_log_dump, sizeof (struct ao_log_record)))
+ ao_panic(AO_PANIC_LOG);
+ if (ao_log_dump_check_data() && ao_log_dump.type == AO_LOG_FLIGHT) {
+ ao_log_dump_flight = ao_log_dump.u.flight.flight;
+ return 1;
+ } else {
+ ao_log_dump_flight = 0;
+ return 0;
+ }
+}
+
+uint8_t
+ao_log_dump_first(void)
+{
+ ao_log_dump_pos = 0;
+ if (!ao_log_dump_scan())
+ return 0;
+ return 1;
+}
+
+uint8_t
+ao_log_dump_next(void)
+{
+ ao_log_dump_pos += sizeof (struct ao_log_record);
+ if (ao_log_dump_pos >= AO_EE_DEVICE_SIZE)
+ return 0;
+ if (!ao_ee_read(ao_log_dump_pos, (uint8_t *) &ao_log_dump,
+ sizeof (struct ao_log_record)))
+ return 0;
+ return ao_log_dump_check_data();
+}
+
+__xdata uint8_t ao_log_adc_pos;
+__xdata enum flight_state ao_log_state;
+
+void
+ao_log(void)
+{
+ static __xdata struct ao_log_record log;
+
+ ao_log_dump_scan();
+
+ while (!ao_log_running)
+ ao_sleep(&ao_log_running);
+
+ log.type = AO_LOG_FLIGHT;
+ log.tick = ao_flight_tick;
+ log.u.flight.ground_accel = ao_ground_accel;
+ log.u.flight.flight = ao_log_dump_flight + 1;
+ 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_adc_head);
+ for (;;) {
+ /* Write samples to EEPROM */
+ while (ao_log_adc_pos != ao_adc_head) {
+ log.type = AO_LOG_SENSOR;
+ log.tick = ao_adc_ring[ao_log_adc_pos].tick;
+ 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_adc_pos & 0x1f) == 0) {
+ log.type = AO_LOG_TEMP_VOLT;
+ log.tick = ao_adc_ring[ao_log_adc_pos].tick;
+ 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.tick = ao_adc_ring[ao_log_adc_pos].tick;
+ 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);
+ }
+ 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_flight_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);
+ }
+}
+
+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();
+}
+
+static void
+dump_log(void)
+{
+ uint8_t more;
+
+ for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) {
+ printf("%c %4x %4x %4x\n",
+ ao_log_dump.type,
+ ao_log_dump.tick,
+ ao_log_dump.u.anon.d0,
+ ao_log_dump.u.anon.d1);
+ if (ao_log_dump.type == AO_LOG_STATE &&
+ ao_log_dump.u.state.state == ao_flight_landed)
+ break;
+ }
+ printf("end\n");
+}
+
+__code struct ao_cmds ao_log_cmds[] = {
+ { 'l', dump_log, "l Dump last flight log" },
+ { 0, dump_log, NULL },
+};
+
+static __xdata struct ao_task ao_log_task;
+
+void
+ao_log_init(void)
+{
+ ao_log_running = 0;
+
+ /* For now, just log the flight starting at the begining of eeprom */
+ ao_log_start_pos = 0;
+ ao_log_current_pos = ao_log_start_pos;
+ ao_log_state = ao_flight_invalid;
+
+ /* Create a task to log events to eeprom */
+ ao_add_task(&ao_log_task, ao_log, "log");
+ ao_cmd_register(&ao_log_cmds[0]);
+}
--- /dev/null
+/*
+ * 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)
+{
+ CLKCON = 0;
+ while (!(SLEEP & SLEEP_XOSC_STB))
+ ;
+
+ /* 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();
+}
--- /dev/null
+/*
+ * 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 uint8_t ao_monitoring;
+__pdata uint8_t ao_monitor_led;
+
+void
+ao_monitor(void)
+{
+ __xdata struct ao_radio_recv recv;
+ __xdata char callsign[AO_MAX_CALLSIGN+1];
+ uint8_t state;
+
+ for (;;) {
+ __critical while (!ao_monitoring)
+ ao_sleep(&ao_monitoring);
+ ao_radio_recv(&recv);
+ state = recv.telemetry.flight_state;
+ memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN);
+ if (state > ao_flight_invalid)
+ state = ao_flight_invalid;
+ if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) {
+ printf ("CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ",
+ callsign,
+ recv.telemetry.addr,
+ (int) recv.rssi - 74, recv.status,
+ ao_state_names[state]);
+ printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d ",
+ recv.telemetry.adc.tick,
+ recv.telemetry.adc.accel,
+ recv.telemetry.adc.pres,
+ recv.telemetry.adc.temp,
+ recv.telemetry.adc.v_batt,
+ recv.telemetry.adc.sense_d,
+ recv.telemetry.adc.sense_m,
+ recv.telemetry.flight_accel,
+ recv.telemetry.ground_accel,
+ recv.telemetry.flight_vel,
+ recv.telemetry.flight_pres,
+ recv.telemetry.ground_pres);
+ ao_gps_print(&recv.telemetry.gps);
+ ao_rssi_set((int) recv.rssi - 74);
+ } else {
+ printf("CRC INVALID RSSI %3d\n", (int) recv.rssi - 74);
+ }
+ ao_usb_flush();
+ ao_led_toggle(ao_monitor_led);
+ }
+}
+
+__xdata struct ao_task ao_monitor_task;
+
+void
+ao_set_monitor(uint8_t monitoring)
+{
+ ao_monitoring = monitoring;
+ ao_wakeup(&ao_monitoring);
+}
+
+static void
+set_monitor(void)
+{
+ ao_cmd_hex();
+ ao_set_monitor(ao_cmd_lex_i != 0);
+}
+
+__code struct ao_cmds ao_monitor_cmds[] = {
+ { 'm', set_monitor, "m <0 off, 1 on> Enable/disable radio monitoring" },
+ { 0, set_monitor, 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_task, ao_monitor, "monitor");
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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"
+#include PRODUCT_DEFS
+
+/* Defines which mark this particular AltOS product */
+
+const uint16_t ao_serial_number = AO_iSerial_NUMBER;
+const char ao_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))
+
+/* USB descriptors in one giant block of bytes */
+const 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(0x000A), /* 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
+};
--- /dev/null
+/*
+ * 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 434.550MHz, the frequency value is:
+ *
+ * 434.550e6 / (24e6 / 2**16) = 1186611.2
+ */
+
+#define FREQ_CONTROL 1186611
+
+/*
+ * 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
+
+/* 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_FREQ2_OFF, (FREQ_CONTROL >> 16) & 0xff,
+ RF_FREQ1_OFF, (FREQ_CONTROL >> 8) & 0xff,
+ RF_FREQ0_OFF, (FREQ_CONTROL >> 0) & 0xff,
+
+ 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_PKTLEN_OFF, sizeof (struct ao_telemetry),
+
+ 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 telemetry_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 */
+ RF_PKTLEN_OFF, sizeof (struct ao_telemetry),
+ 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_mutex;
+
+static void
+ao_radio_idle(void)
+{
+ if (RF_MARCSTATE != RF_MARCSTATE_IDLE)
+ {
+ RFST = RFST_SIDLE;
+ do {
+ ao_yield();
+ } while (RF_MARCSTATE != RF_MARCSTATE_IDLE);
+ }
+}
+
+void
+ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant
+{
+ ao_config_get();
+ ao_mutex_get(&ao_radio_mutex);
+ ao_radio_idle();
+ RF_CHANNR = ao_config.radio_channel;
+ ao_dma_set_transfer(ao_radio_dma,
+ telemetry,
+ &RFDXADDR,
+ sizeof (struct ao_telemetry),
+ 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_dma_done)
+ ao_sleep(&ao_radio_dma_done);
+ ao_mutex_put(&ao_radio_mutex);
+}
+
+void
+ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant
+{
+ ao_config_get();
+ ao_mutex_get(&ao_radio_mutex);
+ ao_radio_idle();
+ RF_CHANNR = ao_config.radio_channel;
+ ao_dma_set_transfer(ao_radio_dma,
+ &RFDXADDR,
+ radio,
+ sizeof (struct ao_radio_recv),
+ 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;
+ __critical while (!ao_radio_dma_done)
+ ao_sleep(&ao_radio_dma_done);
+ ao_mutex_put(&ao_radio_mutex);
+}
+
+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_dma_done = 1;
+ ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done);
+}
--- /dev/null
+/*
+ * 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 const char * __xdata flight_reports[] = {
+ "...", /* startup, 'S' */
+ "..", /* idle 'I' */
+ ".--.", /* launchpad 'P' */
+ "-...", /* boost 'B' */
+ "-.-.", /* coast 'C' */
+ ".-", /* apogee 'A' */
+ "-..", /* drogue 'D' */
+ "--", /* main 'M' */
+ ".-..", /* landed 'L' */
+ ".-.-.-", /* invalid */
+};
+
+#if 1
+#define signal(time) ao_beep_for(AO_BEEP_MID, time)
+#else
+#define signal(time) ao_led_for(AO_LED_RED, time)
+#endif
+#define pause(time) ao_delay(time)
+
+static __xdata enum ao_flight_state ao_report_state;
+
+static void
+ao_report_beep(void) __reentrant
+{
+ char *r = flight_reports[ao_flight_state];
+ char c;
+
+ if (!r)
+ return;
+ while (c = *r++) {
+ if (c == '.')
+ signal(AO_MS_TO_TICKS(200));
+ else
+ signal(AO_MS_TO_TICKS(600));
+ pause(AO_MS_TO_TICKS(200));
+ }
+ pause(AO_MS_TO_TICKS(400));
+}
+
+static void
+ao_report_digit(uint8_t digit) __reentrant
+{
+ if (!digit) {
+ signal(AO_MS_TO_TICKS(500));
+ pause(AO_MS_TO_TICKS(200));
+ } else {
+ while (digit--) {
+ signal(AO_MS_TO_TICKS(200));
+ pause(AO_MS_TO_TICKS(200));
+ }
+ }
+ pause(AO_MS_TO_TICKS(300));
+}
+
+static void
+ao_report_altitude(void)
+{
+ __xdata int16_t agl = ao_pres_to_altitude(ao_min_pres) - ao_pres_to_altitude(ao_ground_pres);
+ __xdata uint8_t digits[10];
+ __xdata 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));
+ }
+}
+
+void
+ao_report(void)
+{
+ ao_report_state = ao_flight_state;
+ for(;;) {
+ if (ao_flight_state == ao_flight_landed)
+ ao_report_altitude();
+ ao_report_beep();
+ __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");
+}
--- /dev/null
+/*
+ * 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 __xdata volatile uint16_t ao_rssi_delay;
+static __xdata 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");
+}
--- /dev/null
+/*
+ * 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);
+}
+
+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;
+}
+
+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();
+}
+
+static void
+send_serial(void)
+{
+ ao_cmd_white();
+ while (ao_cmd_lex_c != '\n') {
+ ao_serial_putchar(ao_cmd_lex_c);
+ ao_cmd_lex();
+ }
+}
+
+__code struct ao_cmds ao_serial_cmds[] = {
+ { 'S', send_serial, "S <data> Send data to serial line" },
+ { 0, send_serial, NULL },
+};
+
+void
+ao_serial_init(void)
+{
+ /* Set up the USART pin assignment */
+ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2;
+
+ /* ee has already set the P2SEL bits */
+
+ /* Make the USART pins be controlled by the USART */
+ P1SEL |= (1 << 6) | (1 << 7);
+
+ /* UART mode with receiver enabled */
+ U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
+
+ /* Pick a 4800 baud rate */
+ U1BAUD = 163; /* 4800 */
+ U1GCR = 7 << UxGCR_BAUD_E_SHIFT; /* 4800 */
+
+ /* Reasonable serial parameters */
+ U1UCR = (UxUCR_FLUSH |
+ UxUCR_FLOW_DISABLE |
+ UxUCR_D9_ODD_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;
+
+ ao_cmd_register(&ao_serial_cmds[0]);
+}
--- /dev/null
+/*
+ * 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", "coast",
+ "apogee", "drogue", "main", "landed", "invalid"
+};
--- /dev/null
+/*
+ * 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
+ */
+
+void
+putchar(char c)
+{
+ if (c == '\n')
+ ao_usb_putchar('\r');
+ ao_usb_putchar(c);
+}
+
+void
+flush(void)
+{
+ ao_usb_flush();
+}
+
+char
+getchar(void)
+{
+ return ao_usb_getchar();
+}
--- /dev/null
+/*
+ * 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;
+ if (ao_num_tasks == AO_NUM_TASKS)
+ ao_panic(AO_PANIC_NO_TASK);
+ ao_tasks[ao_num_tasks++] = task;
+ task->task_id = ao_num_tasks;
+ 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);
+ *stack++ = ((uint16_t) start) >> 8;
+
+ /* and the stuff saved by ao_switch */
+ *stack++ = 0; /* acc */
+ *stack++ = 0x80; /* IE */
+ *stack++ = 0; /* DPL */
+ *stack++ = 0; /* DPH */
+ *stack++ = 0; /* B */
+ *stack++ = 0; /* R2 */
+ *stack++ = 0; /* R3 */
+ *stack++ = 0; /* R4 */
+ *stack++ = 0; /* R5 */
+ *stack++ = 0; /* R6 */
+ *stack++ = 0; /* R7 */
+ *stack++ = 0; /* R0 */
+ *stack++ = 0; /* R1 */
+ *stack++ = 0; /* PSW */
+ *stack++ = 0; /* BP */
+ task->stack_count = stack - task->stack;
+ 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)
+ {
+ 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;
+ }
+
+ /* 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;
+}
+
+void
+ao_sleep(__xdata void *wchan)
+{
+ __critical {
+ ao_cur_task->wchan = wchan;
+ }
+ ao_yield();
+}
+
+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_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();
+}
--- /dev/null
+/*
+ * 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)
+{
+ CLKCON = 0;
+ while (!(SLEEP & SLEEP_XOSC_STB))
+ ;
+
+ /* Turn on the 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_cmd_init();
+ ao_usb_init();
+ ao_monitor_init(AO_LED_GREEN, TRUE);
+ ao_rssi_init(AO_LED_RED);
+ ao_radio_init();
+ ao_dbg_init();
+ ao_config_init();
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * 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)
+{
+ CLKCON = 0;
+ while (!(SLEEP & SLEEP_XOSC_STB))
+ ;
+
+ /* 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_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_gps_report_init();
+ ao_telemetry_init();
+ ao_radio_init();
+ ao_igniter_init();
+ ao_dbg_init();
+ ao_config_init();
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * 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 uint16_t ao_telemetry_interval = 0;
+
+void
+ao_telemetry(void)
+{
+ static __xdata struct ao_telemetry telemetry;
+
+ ao_config_get();
+ memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN);
+ telemetry.addr = ao_serial_number;
+ for (;;) {
+ while (ao_telemetry_interval == 0)
+ ao_sleep(&ao_telemetry_interval);
+ telemetry.flight_state = ao_flight_state;
+ telemetry.flight_accel = ao_flight_accel;
+ telemetry.ground_accel = ao_ground_accel;
+ telemetry.flight_vel = ao_flight_vel;
+ telemetry.flight_pres = ao_flight_pres;
+ telemetry.ground_pres = ao_ground_pres;
+ ao_adc_get(&telemetry.adc);
+ ao_mutex_get(&ao_gps_mutex);
+ memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data));
+ ao_mutex_put(&ao_gps_mutex);
+ ao_radio_send(&telemetry);
+ ao_delay(ao_telemetry_interval);
+ }
+}
+
+void
+ao_telemetry_set_interval(uint16_t interval)
+{
+ ao_telemetry_interval = interval;
+ ao_wakeup(&ao_telemetry_interval);
+}
+
+__xdata struct ao_task ao_telemetry_task;
+
+void
+ao_telemetry_init()
+{
+ ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry");
+}
--- /dev/null
+/*
+ * 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)
+{
+ CLKCON = 0;
+ while (!(SLEEP & SLEEP_XOSC_STB))
+ ;
+
+ /* 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_gps_init();
+ ao_monitor_init(AO_LED_GREEN, TRUE);
+ ao_radio_init();
+ ao_dbg_init();
+ ao_config_init();
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * 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_ring);
+ 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)
+{
+ CLKCON = 0;
+ while (!(SLEEP & SLEEP_XOSC_STB))
+ ;
+
+// 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();
+}
--- /dev/null
+/*
+ * 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)
+{
+ CLKCON = 0;
+ while (!(SLEEP & SLEEP_XOSC_STB))
+ ;
+
+ /* 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();
+}
--- /dev/null
+/*
+ * 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;
+}
+
+void
+ao_delay(uint16_t ticks)
+{
+ uint16_t until = ao_time() + ticks;
+
+ while ((int16_t) (until - ao_time()) > 0)
+ ao_sleep(DATA_TO_XDATA(&ao_tick_count));
+}
+
+#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */
+#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */
+
+volatile __data uint8_t ao_adc_interval = 1;
+volatile __data uint8_t ao_adc_count;
+
+void ao_timer_isr(void) interrupt 9
+{
+ ++ao_tick_count;
+ if (++ao_adc_count == ao_adc_interval) {
+ ao_adc_count = 0;
+ ao_adc_poll();
+ }
+ ao_wakeup(DATA_TO_XDATA(&ao_tick_count));
+}
+
+void
+ao_timer_set_adc_interval(uint8_t interval) __critical
+{
+ ao_adc_interval = interval;
+ ao_adc_count = 0;
+}
+
+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;
+}
--- /dev/null
+/*
+ * 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 __xdata uint16_t ao_usb_out_bytes;
+static __xdata uint8_t ao_usb_iif;
+static __xdata 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_usb_out_bytes);
+
+ if (USBCIF & USBCIF_RSTIF)
+ ao_usb_set_interrupts();
+}
+
+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;
+
+__xdata uint8_t ao_usb_ep0_state;
+uint8_t * __xdata ao_usb_ep0_in_data;
+__xdata uint8_t ao_usb_ep0_in_len;
+__xdata uint8_t ao_usb_ep0_in_buf[2];
+__xdata uint8_t ao_usb_ep0_out_len;
+__xdata uint8_t *__data ao_usb_ep0_out_data;
+__xdata uint8_t ao_usb_configuration;
+
+/* Send an IN data packet */
+static void
+ao_usb_ep0_flush(void)
+{
+ __xdata uint8_t this_len;
+ __xdata uint8_t cs0;
+
+ USBINDEX = 0;
+ cs0 = USBCS0;
+ if (cs0 & USBCS0_INPKT_RDY)
+ ao_panic(0);
+
+ 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)
+{
+ const uint8_t *__xdata descriptor;
+ __xdata uint8_t type = value >> 8;
+ __xdata 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)
+{
+ __xdata 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)
+{
+ __xdata 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;
+ }
+ }
+ }
+}
+
+void
+ao_usb_flush(void) __critical
+{
+ if (ao_usb_in_bytes) {
+ USBINDEX = AO_USB_IN_EP;
+ USBCSIL |= USBCSIL_INPKT_RDY;
+ ao_usb_in_bytes = 0;
+ }
+}
+
+void
+ao_usb_putchar(char c) __critical
+{
+ if (!ao_usb_running)
+ return;
+ for (;;) {
+ USBINDEX = AO_USB_IN_EP;
+ if ((USBCSIL & USBCSIL_INPKT_RDY) == 0)
+ break;
+ ao_sleep(&ao_usb_in_bytes);
+ }
+ USBFIFO[AO_USB_IN_EP << 1] = c;
+ if (++ao_usb_in_bytes == AO_USB_IN_SIZE) {
+ USBINDEX = AO_USB_IN_EP;
+ USBCSIL |= USBCSIL_INPKT_RDY;
+ ao_usb_in_bytes = 0;
+ }
+}
+
+char
+ao_usb_getchar(void) __critical
+{
+ __xdata char c;
+ while (ao_usb_out_bytes == 0) {
+ for (;;) {
+ USBINDEX = AO_USB_OUT_EP;
+ if ((USBCSOL & USBCSOL_OUTPKT_RDY) != 0)
+ break;
+ ao_sleep(&ao_usb_out_bytes);
+ }
+ ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL;
+ }
+ --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;
+}
+
+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");
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*-------------------------------------------------------------------------
+ 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 */
+
+/* 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;
+
+/*
+ * 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_PRI1P1_TIMER1 (0 << 4)
+#define P2SEL_PRI1P1_TIMER4 (1 << 4)
+#define P2SEL_PRI0P1_USART0 (0 << 3)
+#define P2SEL_PRI0P1_TIMER1 (1 << 3)
+#define P2SEL_SELP2_4_GPIO (0 << 2)
+#define P2SEL_SELP2_4_PERIPHERAL (1 << 2)
+#define P2SEL_SELP2_3_GPIO (0 << 1)
+#define P2SEL_SELP2_3_PERIPHERAL (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;
+
+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)
+
+/* 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;
+sbit at 0xa5 P2_5;
+sbit at 0xa6 P2_6;
+sbit at 0xa7 P2_7;
+
+/* 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;
+
+/* 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 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
--- /dev/null
+#!/bin/sh
+HEADER=$1
+MEM=$2
+
+HEADER_STACK=`awk '/#define AO_STACK_START/ {print $3}' $HEADER | nickle`
+MEM_STACK=`awk '/Stack starts at/ {print $4}' $MEM | nickle`
+
+if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then
+ MIN=0x`nickle -e "$MEM_STACK # 16"`
+ echo "Set AO_STACK_START to at least $MIN"
+ exit 1
+else
+ exit 0
+fi
--- /dev/null
+#!/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();
--- /dev/null
+#!/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 count_to_kPa(real count)
+{
+ return (count / 2047 + 0.095) / 0.009;
+}
+
+for (real count = 0; count <= 2047; count++) {
+ real kPa = count_to_kPa(count);
+ real meters = pressure_to_altitude(kPa * 1000);
+ printf (" %d, /* %6.2g kPa %d count */\n",
+ floor (meters + 0.5), kPa, count);
+}