From: Keith Packard Date: Thu, 4 Jun 2009 17:41:34 +0000 (-0700) Subject: Use autotools, move altos to src subdir X-Git-Tag: 0.5~59 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=210dbaa23cdacf3a6f2d6e23493e96ee2ac9bca7 Use autotools, move altos to src subdir Signed-off-by: Keith Packard --- diff --git a/.gitignore b/.gitignore index 24dee3b0..190ba2fd 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,15 @@ ao-telemetrum.h 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 diff --git a/25lc1024.h b/25lc1024.h deleted file mode 100644 index 44e52387..00000000 --- a/25lc1024.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */ - -#ifndef _25LC1024_H_ -#define _25LC1024_H_ - -#define EE_READ 0x03 -#define EE_WRITE 0x02 -#define EE_WREN 0x06 -#define EE_WRDI 0x04 -#define EE_RDSR 0x05 -#define EE_WRSR 0x01 -#define EE_PE 0x42 -#define EE_SE 0xd8 -#define EE_CE 0xc7 -#define EE_RDID 0xab -#define EE_DPD 0xb9 - -#define EE_STATUS_WIP (1 << 0) -#define EE_STATUS_WEL (1 << 1) -#define EE_STATUS_BP0 (1 << 2) -#define EE_STATUS_BP1 (1 << 3) -#define EE_STATUS_WPEN (1 << 7) - -#endif /* _25LC1024_H_ */ diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..9cee0373 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Keith Packard diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..c9fd2c0c --- /dev/null +++ b/INSTALL @@ -0,0 +1,290 @@ +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 `' 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. diff --git a/Makefile b/Makefile deleted file mode 100644 index ca296c6f..00000000 --- a/Makefile +++ /dev/null @@ -1,262 +0,0 @@ -# -# 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 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..e5c0c1e8 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=src aoview diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/_bp.c b/_bp.c deleted file mode 100644 index a57b99bc..00000000 --- a/_bp.c +++ /dev/null @@ -1,26 +0,0 @@ -/*------------------------------------------------------------------------- - - _bp.c :- just declares bp as a variable - - Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! --------------------------------------------------------------------------*/ - -__data unsigned char bp ; diff --git a/altitude.h b/altitude.h deleted file mode 100644 index 5225df4d..00000000 --- a/altitude.h +++ /dev/null @@ -1,2048 +0,0 @@ - 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 */ diff --git a/ao-make-product.5c b/ao-make-product.5c deleted file mode 100644 index 933032dd..00000000 --- a/ao-make-product.5c +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh - -autoimport ParseArgs; - -void -write_ucs2(string a, string description) -{ - int len = String::length(a); - - printf("/* %s */\n", description); - printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2); - printf("#define AO_%s_STRING \"%s\"\n", description, a); - printf("#define AO_%s_UCS2", description); - for (int i = 0; i < len; i++) { - int c = a[i]; - if (i > 0) - printf(","); - if (0x20 <= c && c < 128) - printf(" '%c', 0", c); - else - printf(" LE_WORD(0x%04x),", c); - } - printf("\n\n"); -} - -void -write_string(string a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_STRING \"%s\"\n", description, a); -} - -void -write_int(int a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_NUMBER %d\n\n", description, a); -} - -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(); diff --git a/ao.h b/ao.h deleted file mode 100644 index c4cb5bf7..00000000 --- a/ao.h +++ /dev/null @@ -1,926 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 -#include -#include -#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_ */ diff --git a/ao_adc.c b/ao_adc.c deleted file mode 100644 index bef6bb7f..00000000 --- a/ao_adc.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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]); -} - diff --git a/ao_adc_fake.c b/ao_adc_fake.c deleted file mode 100644 index 6ca88d4e..00000000 --- a/ao_adc_fake.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; - -/* Stub for systems which have no ADC */ -void -ao_adc_poll(void) -{ -} diff --git a/ao_beep.c b/ao_beep.c deleted file mode 100644 index 3642f4c6..00000000 --- a/ao_beep.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -void -ao_beep(uint8_t beep) -{ - if (beep == 0) { - P2_0 = 0; - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; - T4CTL = 0; - } else { - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL; - T4CC0 = beep; - T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START; - } -} - -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant -{ - ao_beep(beep); - ao_delay(ticks); - ao_beep(0); -} - -void -ao_beep_init(void) -{ - /* Our beeper is on P2_0, which is hooked to timer 4 using - * configuration alternative 2 - */ - P2_0 = 0; - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; - PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2; - T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; -} diff --git a/ao_cmd.c b/ao_cmd.c deleted file mode 100644 index 827545d0..00000000 --- a/ao_cmd.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 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"); -} diff --git a/ao_config.c b/ao_config.c deleted file mode 100644 index 657c7a8a..00000000 --- a/ao_config.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 Set height above launch for main deploy (in meters)" }, - { 'a', ao_config_accel_zero_g_set, ao_config_accel_zero_g_show, - "a Set accelerometer zero g point (0 for auto)" }, - { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, - "r Set radio channel (freq = 434.550 + channel * .1)" }, - { 'c', ao_config_callsign_set, ao_config_callsign_show, - "c 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 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]); -} diff --git a/ao_convert.c b/ao_convert.c deleted file mode 100644 index 57ed7370..00000000 --- a/ao_convert.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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; -} diff --git a/ao_dbg.c b/ao_dbg.c deleted file mode 100644 index 8a11a444..00000000 --- a/ao_dbg.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 Get data from debug port" }, - { 'I', debug_input, "I Input bytes to target at " }, - { 'O', debug_output, "O Output bytes to target at " }, - { 'P', debug_put, "P ... 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]); -} diff --git a/ao_dma.c b/ao_dma.c deleted file mode 100644 index 8d96cc4b..00000000 --- a/ao_dma.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -#define NUM_DMA 5 - -/* - * The config address for DMA0 is programmed - * separately from that of DMA1-4, but for simplicity, - * we make them all contiguous. - */ - -static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA]; -static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA]; -static __data uint8_t ao_next_dma; - -uint8_t -ao_dma_alloc(__xdata uint8_t *done) -{ - uint8_t id; - - if (ao_next_dma == NUM_DMA) - ao_panic(AO_PANIC_DMA); - id = ao_next_dma++; - ao_dma_done[id] = done; - - /* When the first dma object is allocated, set up the DMA - * controller - */ - if (id == 0) { - DMAIRQ = 0; - DMAIF = 0; - IEN1 |= IEN1_DMAIE; - } - - return id; -} - -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1) -{ - if (DMAARM & (1 << id)) - ao_panic(AO_PANIC_DMA); - ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8; - ao_dma_config[id].src_low = ((uint16_t) srcaddr); - ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8; - ao_dma_config[id].dst_low = ((uint16_t) dstaddr); - ao_dma_config[id].len_high = count >> 8; - ao_dma_config[id].len_low = count; - ao_dma_config[id].cfg0 = cfg0; - ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; - if (id == 0) { - DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; - DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); - } else { - DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; - DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); - } -} - -#define nop() _asm nop _endasm; - -void -ao_dma_start(uint8_t id) -{ - uint8_t mask = (1 << id); - DMAIRQ &= ~mask; - DMAARM = 0x80 | mask; - nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); - *(ao_dma_done[id]) = 0; - DMAARM = mask; - nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); - nop(); -} - -void -ao_dma_trigger(uint8_t id) -{ - DMAREQ |= (1 << id); -} - -void -ao_dma_abort(uint8_t id) -{ - uint8_t mask = (1 << id); - DMAARM = 0x80 | mask; - DMAIRQ &= ~mask; -} - -void -ao_dma_isr(void) interrupt 8 -{ - uint8_t id, mask; - - /* Find the first DMA channel which is done */ - mask = 1; - for (id = 0; id < ao_next_dma; id++) { - if (DMAIRQ & mask) { - /* Clear CPU interrupt flag */ - DMAIF = 0; - /* Clear the completed ID */ - DMAIRQ = ~mask; - *(ao_dma_done[id]) = 1; - ao_wakeup(ao_dma_done[id]); - break; - } - mask <<= 1; - } -} diff --git a/ao_ee.c b/ao_ee.c deleted file mode 100644 index a0f2e23a..00000000 --- a/ao_ee.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 Dump a block of EEPROM data" }, - { 'w', ee_store, "w ... 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]); -} diff --git a/ao_ee_fake.c b/ao_ee_fake.c deleted file mode 100644 index b0c1d61e..00000000 --- a/ao_ee_fake.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -/* - * For hardware without eeprom, the config code still - * wants to call these functions - */ -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant -{ - (void) buf; - (void) len; - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - memset(buf, '\0', len); - return 1; -} diff --git a/ao_flight.c b/ao_flight.c deleted file mode 100644 index c0f56830..00000000 --- a/ao_flight.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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]); -} diff --git a/ao_flight_test.c b/ao_flight_test.c deleted file mode 100644 index f4731aa8..00000000 --- a/ao_flight_test.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 -#include -#include -#include - -#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(); -} diff --git a/ao_gps.c b/ao_gps.c deleted file mode 100644 index e5a5a884..00000000 --- a/ao_gps.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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]); -} diff --git a/ao_gps_print.c b/ao_gps_print.c deleted file mode 100644 index 8cadd31f..00000000 --- a/ao_gps_print.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); - } -} - diff --git a/ao_gps_report.c b/ao_gps_report.c deleted file mode 100644 index 1b5402a8..00000000 --- a/ao_gps_report.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); -} diff --git a/ao_ignite.c b/ao_ignite.c deleted file mode 100644 index be291523..00000000 --- a/ao_ignite.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 {main|drogue} Fire igniter. 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"); -} diff --git a/ao_led.c b/ao_led.c deleted file mode 100644 index 6c698b4b..00000000 --- a/ao_led.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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; -} diff --git a/ao_log.c b/ao_log.c deleted file mode 100644 index 7284121d..00000000 --- a/ao_log.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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]); -} diff --git a/ao_main.c b/ao_main.c deleted file mode 100644 index 1f7a829f..00000000 --- a/ao_main.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_monitor.c b/ao_monitor.c deleted file mode 100644 index 5997d427..00000000 --- a/ao_monitor.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); -} diff --git a/ao_mutex.c b/ao_mutex.c deleted file mode 100644 index 8212a515..00000000 --- a/ao_mutex.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -void -ao_mutex_get(__xdata uint8_t *mutex) __reentrant -{ - if (*mutex == ao_cur_task->task_id) - ao_panic(AO_PANIC_MUTEX); - __critical { - while (*mutex) - ao_sleep(mutex); - *mutex = ao_cur_task->task_id; - } -} - -void -ao_mutex_put(__xdata uint8_t *mutex) __reentrant -{ - if (*mutex != ao_cur_task->task_id) - ao_panic(AO_PANIC_MUTEX); - __critical { - *mutex = 0; - ao_wakeup(mutex); - } -} diff --git a/ao_panic.c b/ao_panic.c deleted file mode 100644 index f6ecc380..00000000 --- a/ao_panic.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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); - } - } -} diff --git a/ao_product.c b/ao_product.c deleted file mode 100644 index b42e62c0..00000000 --- a/ao_product.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 -}; diff --git a/ao_radio.c b/ao_radio.c deleted file mode 100644 index e090fe74..00000000 --- a/ao_radio.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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); -} - diff --git a/ao_report.c b/ao_report.c deleted file mode 100644 index e52b2928..00000000 --- a/ao_report.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); -} diff --git a/ao_rssi.c b/ao_rssi.c deleted file mode 100644 index 6912b9a2..00000000 --- a/ao_rssi.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); -} diff --git a/ao_serial.c b/ao_serial.c deleted file mode 100644 index ce116940..00000000 --- a/ao_serial.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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 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]); -} diff --git a/ao_state.c b/ao_state.c deleted file mode 100644 index 96b4c1a4..00000000 --- a/ao_state.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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" -}; diff --git a/ao_stdio.c b/ao_stdio.c deleted file mode 100644 index fb8ce093..00000000 --- a/ao_stdio.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_task.c b/ao_task.c deleted file mode 100644 index 06c279e9..00000000 --- a/ao_task.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_teledongle.c b/ao_teledongle.c deleted file mode 100644 index 67fe7614..00000000 --- a/ao_teledongle.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_telemetrum.c b/ao_telemetrum.c deleted file mode 100644 index a680ce19..00000000 --- a/ao_telemetrum.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_telemetry.c b/ao_telemetry.c deleted file mode 100644 index 463bcd91..00000000 --- a/ao_telemetry.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); -} diff --git a/ao_teleterra.c b/ao_teleterra.c deleted file mode 100644 index ad3e2d9b..00000000 --- a/ao_teleterra.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_test.c b/ao_test.c deleted file mode 100644 index 6d005ff6..00000000 --- a/ao_test.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_tidongle.c b/ao_tidongle.c deleted file mode 100644 index b068d045..00000000 --- a/ao_tidongle.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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(); -} diff --git a/ao_timer.c b/ao_timer.c deleted file mode 100644 index a6a7646f..00000000 --- a/ao_timer.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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; -} - diff --git a/ao_usb.c b/ao_usb.c deleted file mode 100644 index 315eea08..00000000 --- a/ao_usb.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; 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"); -} diff --git a/ao_usb.h b/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/aoview/Makefile b/aoview/Makefile deleted file mode 100644 index 6bf789bb..00000000 --- a/aoview/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -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/$$/"/' $< > $@ diff --git a/aoview/Makefile.am b/aoview/Makefile.am new file mode 100644 index 00000000..9f67ac40 --- /dev/null +++ b/aoview/Makefile.am @@ -0,0 +1,28 @@ +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/$$/"/' $< > $@ diff --git a/aoview/aoview_convert.c b/aoview/aoview_convert.c index a4bf813d..02416647 100644 --- a/aoview/aoview_convert.c +++ b/aoview/aoview_convert.c @@ -18,7 +18,7 @@ #include "aoview.h" static int16_t altitude_table[2048] = { -#include "../altitude.h" +#include "altitude.h" }; int16_t diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..4e8b11ba --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#! /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 "$@" diff --git a/cc1111.h b/cc1111.h deleted file mode 100644 index 4e451465..00000000 --- a/cc1111.h +++ /dev/null @@ -1,1214 +0,0 @@ -/*------------------------------------------------------------------------- - Register Declarations for the ChipCon CC1111 Processor Range - - Copyright © 2008 Keith Packard - - This program is free software; 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 -#include - -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 diff --git a/check-stack b/check-stack deleted file mode 100755 index 82680b88..00000000 --- a/check-stack +++ /dev/null @@ -1,14 +0,0 @@ -#!/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 diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..0419489a --- /dev/null +++ b/configure.ac @@ -0,0 +1,58 @@ +dnl +dnl Copyright © 2008 Keith Packard +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 +]) diff --git a/gps-cksum b/gps-cksum deleted file mode 100755 index a08153bf..00000000 --- a/gps-cksum +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(string a) -{ - int c = 0; - for (int i = 0; i < String::length(a); i++) - c ^= a[i]; - return c; -} - -void main() -{ - for (int i = 1; i < dim(argv); i++) - printf ("$%s*%02x\n", argv[i], checksum(argv[i])); -} - -main(); diff --git a/make-altitude b/make-altitude deleted file mode 100644 index ddfab5fc..00000000 --- a/make-altitude +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/nickle -f -/* - * Pressure Sensor Model, version 1.1 - * - * written by Holly Grimes - * - * Uses the International Standard Atmosphere as described in - * "A Quick Derivation relating altitude to air pressure" (version 1.03) - * from the Portland State Aerospace Society, except that the atmosphere - * is divided into layers with each layer having a different lapse rate. - * - * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 - * at site 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); -} diff --git a/src/25lc1024.h b/src/25lc1024.h new file mode 100644 index 00000000..44e52387 --- /dev/null +++ b/src/25lc1024.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */ + +#ifndef _25LC1024_H_ +#define _25LC1024_H_ + +#define EE_READ 0x03 +#define EE_WRITE 0x02 +#define EE_WREN 0x06 +#define EE_WRDI 0x04 +#define EE_RDSR 0x05 +#define EE_WRSR 0x01 +#define EE_PE 0x42 +#define EE_SE 0xd8 +#define EE_CE 0xc7 +#define EE_RDID 0xab +#define EE_DPD 0xb9 + +#define EE_STATUS_WIP (1 << 0) +#define EE_STATUS_WEL (1 << 1) +#define EE_STATUS_BP0 (1 << 2) +#define EE_STATUS_BP1 (1 << 3) +#define EE_STATUS_WPEN (1 << 7) + +#endif /* _25LC1024_H_ */ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 00000000..39281369 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,262 @@ +# +# 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 diff --git a/src/_bp.c b/src/_bp.c new file mode 100644 index 00000000..6bf135bc --- /dev/null +++ b/src/_bp.c @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + + _bp.c :- just declares bp as a variable + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +__data unsigned char bp ; diff --git a/src/altitude.h b/src/altitude.h new file mode 100644 index 00000000..5225df4d --- /dev/null +++ b/src/altitude.h @@ -0,0 +1,2048 @@ + 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 */ diff --git a/src/ao-make-product.5c b/src/ao-make-product.5c new file mode 100644 index 00000000..933032dd --- /dev/null +++ b/src/ao-make-product.5c @@ -0,0 +1,88 @@ +#!/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(); diff --git a/src/ao.h b/src/ao.h new file mode 100644 index 00000000..c4cb5bf7 --- /dev/null +++ b/src/ao.h @@ -0,0 +1,926 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 +#include +#include +#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_ */ diff --git a/src/ao_adc.c b/src/ao_adc.c new file mode 100644 index 00000000..26209dcf --- /dev/null +++ b/src/ao_adc.c @@ -0,0 +1,92 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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]); +} diff --git a/src/ao_adc_fake.c b/src/ao_adc_fake.c new file mode 100644 index 00000000..6ca88d4e --- /dev/null +++ b/src/ao_adc_fake.c @@ -0,0 +1,27 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t ao_adc_head; + +/* Stub for systems which have no ADC */ +void +ao_adc_poll(void) +{ +} diff --git a/src/ao_beep.c b/src/ao_beep.c new file mode 100644 index 00000000..3642f4c6 --- /dev/null +++ b/src/ao_beep.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + P2_0 = 0; + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; + T4CTL = 0; + } else { + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL; + T4CC0 = beep; + T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START; + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on P2_0, which is hooked to timer 4 using + * configuration alternative 2 + */ + P2_0 = 0; + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; + PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2; + T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; +} diff --git a/src/ao_cmd.c b/src/ao_cmd.c new file mode 100644 index 00000000..33619b24 --- /dev/null +++ b/src/ao_cmd.c @@ -0,0 +1,318 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 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"); +} diff --git a/src/ao_config.c b/src/ao_config.c new file mode 100644 index 00000000..657c7a8a --- /dev/null +++ b/src/ao_config.c @@ -0,0 +1,287 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 Set height above launch for main deploy (in meters)" }, + { 'a', ao_config_accel_zero_g_set, ao_config_accel_zero_g_show, + "a Set accelerometer zero g point (0 for auto)" }, + { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, + "r Set radio channel (freq = 434.550 + channel * .1)" }, + { 'c', ao_config_callsign_set, ao_config_callsign_show, + "c 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 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]); +} diff --git a/src/ao_convert.c b/src/ao_convert.c new file mode 100644 index 00000000..57ed7370 --- /dev/null +++ b/src/ao_convert.c @@ -0,0 +1,55 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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; +} diff --git a/src/ao_dbg.c b/src/ao_dbg.c new file mode 100644 index 00000000..c8dc6ddc --- /dev/null +++ b/src/ao_dbg.c @@ -0,0 +1,367 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 Get data from debug port" }, + { 'I', debug_input, "I Input bytes to target at " }, + { 'O', debug_output, "O Output bytes to target at " }, + { 'P', debug_put, "P ... 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]); +} diff --git a/src/ao_dma.c b/src/ao_dma.c new file mode 100644 index 00000000..a4d45f14 --- /dev/null +++ b/src/ao_dma.c @@ -0,0 +1,131 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define NUM_DMA 5 + +/* + * The config address for DMA0 is programmed + * separately from that of DMA1-4, but for simplicity, + * we make them all contiguous. + */ + +static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA]; +static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA]; +static __data uint8_t ao_next_dma; + +uint8_t +ao_dma_alloc(__xdata uint8_t *done) +{ + uint8_t id; + + if (ao_next_dma == NUM_DMA) + ao_panic(AO_PANIC_DMA); + id = ao_next_dma++; + ao_dma_done[id] = done; + + /* When the first dma object is allocated, set up the DMA + * controller + */ + if (id == 0) { + DMAIRQ = 0; + DMAIF = 0; + IEN1 |= IEN1_DMAIE; + } + + return id; +} + +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1) +{ + if (DMAARM & (1 << id)) + ao_panic(AO_PANIC_DMA); + ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8; + ao_dma_config[id].src_low = ((uint16_t) srcaddr); + ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8; + ao_dma_config[id].dst_low = ((uint16_t) dstaddr); + ao_dma_config[id].len_high = count >> 8; + ao_dma_config[id].len_low = count; + ao_dma_config[id].cfg0 = cfg0; + ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; + if (id == 0) { + DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; + DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); + } else { + DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; + DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); + } +} + +#define nop() _asm nop _endasm; + +void +ao_dma_start(uint8_t id) +{ + uint8_t mask = (1 << id); + DMAIRQ &= ~mask; + DMAARM = 0x80 | mask; + nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); + *(ao_dma_done[id]) = 0; + DMAARM = mask; + nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); + nop(); +} + +void +ao_dma_trigger(uint8_t id) +{ + DMAREQ |= (1 << id); +} + +void +ao_dma_abort(uint8_t id) +{ + uint8_t mask = (1 << id); + DMAARM = 0x80 | mask; + DMAIRQ &= ~mask; +} + +void +ao_dma_isr(void) interrupt 8 +{ + uint8_t id, mask; + + /* Find the first DMA channel which is done */ + mask = 1; + for (id = 0; id < ao_next_dma; id++) { + if (DMAIRQ & mask) { + /* Clear CPU interrupt flag */ + DMAIF = 0; + /* Clear the completed ID */ + DMAIRQ = ~mask; + *(ao_dma_done[id]) = 1; + ao_wakeup(ao_dma_done[id]); + break; + } + mask <<= 1; + } +} diff --git a/src/ao_ee.c b/src/ao_ee.c new file mode 100644 index 00000000..f299b925 --- /dev/null +++ b/src/ao_ee.c @@ -0,0 +1,459 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 Dump a block of EEPROM data" }, + { 'w', ee_store, "w ... 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]); +} diff --git a/src/ao_ee_fake.c b/src/ao_ee_fake.c new file mode 100644 index 00000000..b0c1d61e --- /dev/null +++ b/src/ao_ee_fake.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* + * For hardware without eeprom, the config code still + * wants to call these functions + */ +uint8_t +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +{ + (void) buf; + (void) len; + return 1; +} + +uint8_t +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant +{ + memset(buf, '\0', len); + return 1; +} diff --git a/src/ao_flight.c b/src/ao_flight.c new file mode 100644 index 00000000..c0f56830 --- /dev/null +++ b/src/ao_flight.c @@ -0,0 +1,484 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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]); +} diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c new file mode 100644 index 00000000..f4731aa8 --- /dev/null +++ b/src/ao_flight_test.c @@ -0,0 +1,288 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 +#include +#include +#include + +#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(); +} diff --git a/src/ao_gps.c b/src/ao_gps.c new file mode 100644 index 00000000..cbde8b48 --- /dev/null +++ b/src/ao_gps.c @@ -0,0 +1,275 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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]); +} diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c new file mode 100644 index 00000000..7e157db5 --- /dev/null +++ b/src/ao_gps_print.c @@ -0,0 +1,45 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); + } +} diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c new file mode 100644 index 00000000..1b5402a8 --- /dev/null +++ b/src/ao_gps_report.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); +} diff --git a/src/ao_ignite.c b/src/ao_ignite.c new file mode 100644 index 00000000..be291523 --- /dev/null +++ b/src/ao_ignite.c @@ -0,0 +1,186 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 {main|drogue} Fire igniter. 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"); +} diff --git a/src/ao_led.c b/src/ao_led.c new file mode 100644 index 00000000..6c698b4b --- /dev/null +++ b/src/ao_led.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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; +} diff --git a/src/ao_log.c b/src/ao_log.c new file mode 100644 index 00000000..19bfdfb8 --- /dev/null +++ b/src/ao_log.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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]); +} diff --git a/src/ao_main.c b/src/ao_main.c new file mode 100644 index 00000000..1f7a829f --- /dev/null +++ b/src/ao_main.c @@ -0,0 +1,45 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_monitor.c b/src/ao_monitor.c new file mode 100644 index 00000000..5997d427 --- /dev/null +++ b/src/ao_monitor.c @@ -0,0 +1,95 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); +} diff --git a/src/ao_mutex.c b/src/ao_mutex.c new file mode 100644 index 00000000..c82a7d57 --- /dev/null +++ b/src/ao_mutex.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_mutex_get(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex == ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + while (*mutex) + ao_sleep(mutex); + *mutex = ao_cur_task->task_id; + } +} + +void +ao_mutex_put(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex != ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + *mutex = 0; + ao_wakeup(mutex); + } +} diff --git a/src/ao_panic.c b/src/ao_panic.c new file mode 100644 index 00000000..e996371e --- /dev/null +++ b/src/ao_panic.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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); + } + } +} diff --git a/src/ao_product.c b/src/ao_product.c new file mode 100644 index 00000000..b42e62c0 --- /dev/null +++ b/src/ao_product.c @@ -0,0 +1,154 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 +}; diff --git a/src/ao_radio.c b/src/ao_radio.c new file mode 100644 index 00000000..ca1ec7e8 --- /dev/null +++ b/src/ao_radio.c @@ -0,0 +1,286 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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); +} diff --git a/src/ao_report.c b/src/ao_report.c new file mode 100644 index 00000000..e52b2928 --- /dev/null +++ b/src/ao_report.c @@ -0,0 +1,122 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); +} diff --git a/src/ao_rssi.c b/src/ao_rssi.c new file mode 100644 index 00000000..6912b9a2 --- /dev/null +++ b/src/ao_rssi.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); +} diff --git a/src/ao_serial.c b/src/ao_serial.c new file mode 100644 index 00000000..ce116940 --- /dev/null +++ b/src/ao_serial.c @@ -0,0 +1,119 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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 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]); +} diff --git a/src/ao_state.c b/src/ao_state.c new file mode 100644 index 00000000..96b4c1a4 --- /dev/null +++ b/src/ao_state.c @@ -0,0 +1,23 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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" +}; diff --git a/src/ao_stdio.c b/src/ao_stdio.c new file mode 100644 index 00000000..fb8ce093 --- /dev/null +++ b/src/ao_stdio.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_task.c b/src/ao_task.c new file mode 100644 index 00000000..12b73943 --- /dev/null +++ b/src/ao_task.c @@ -0,0 +1,224 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c new file mode 100644 index 00000000..567751c6 --- /dev/null +++ b/src/ao_teledongle.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c new file mode 100644 index 00000000..a680ce19 --- /dev/null +++ b/src/ao_telemetrum.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c new file mode 100644 index 00000000..463bcd91 --- /dev/null +++ b/src/ao_telemetry.c @@ -0,0 +1,61 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); +} diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c new file mode 100644 index 00000000..ad3e2d9b --- /dev/null +++ b/src/ao_teleterra.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_test.c b/src/ao_test.c new file mode 100644 index 00000000..c9bb02ae --- /dev/null +++ b/src/ao_test.c @@ -0,0 +1,119 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_tidongle.c b/src/ao_tidongle.c new file mode 100644 index 00000000..6dfa9ae9 --- /dev/null +++ b/src/ao_tidongle.c @@ -0,0 +1,44 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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(); +} diff --git a/src/ao_timer.c b/src/ao_timer.c new file mode 100644 index 00000000..81c3b376 --- /dev/null +++ b/src/ao_timer.c @@ -0,0 +1,85 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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; +} diff --git a/src/ao_usb.c b/src/ao_usb.c new file mode 100644 index 00000000..99f0715b --- /dev/null +++ b/src/ao_usb.c @@ -0,0 +1,418 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; 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"); +} diff --git a/src/ao_usb.h b/src/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/ao_usb.h @@ -0,0 +1,100 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/cc1111.h b/src/cc1111.h new file mode 100644 index 00000000..f55e802f --- /dev/null +++ b/src/cc1111.h @@ -0,0 +1,1214 @@ +/*------------------------------------------------------------------------- + Register Declarations for the ChipCon CC1111 Processor Range + + Copyright © 2008 Keith Packard + + This program is free software; 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 +#include + +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 diff --git a/src/check-stack b/src/check-stack new file mode 100755 index 00000000..82680b88 --- /dev/null +++ b/src/check-stack @@ -0,0 +1,14 @@ +#!/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 diff --git a/src/gps-cksum b/src/gps-cksum new file mode 100755 index 00000000..a08153bf --- /dev/null +++ b/src/gps-cksum @@ -0,0 +1,17 @@ +#!/usr/bin/env nickle + +int checksum(string a) +{ + int c = 0; + for (int i = 0; i < String::length(a); i++) + c ^= a[i]; + return c; +} + +void main() +{ + for (int i = 1; i < dim(argv); i++) + printf ("$%s*%02x\n", argv[i], checksum(argv[i])); +} + +main(); diff --git a/src/make-altitude b/src/make-altitude new file mode 100644 index 00000000..ac04e84f --- /dev/null +++ b/src/make-altitude @@ -0,0 +1,192 @@ +#!/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 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); +}