Merge remote-tracking branch 'mjb/master'
authorKeith Packard <keithp@keithp.com>
Wed, 29 Aug 2012 18:29:24 +0000 (11:29 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 29 Aug 2012 18:29:24 +0000 (11:29 -0700)
Pull in Mike's fancy new AltosDroid bits

98 files changed:
.gitignore
altoslib/AltosIdleMonitor.java
altoslib/AltosLink.java
altoslib/AltosRecord.java
altoslib/AltosRecordTM.java
altoslib/AltosState.java
altosui/AltosInfoTable.java
altosui/AltosSerial.java
altosui/altos-windows.nsi
altosui/libaltos/libaltos.c
ao-tools/ao-send-telem/ao-send-telem.c
ao-tools/ao-stmload/ao-stmload.c
debian/control
src/Makefile
src/aes/ao_aes.c [new file with mode: 0644]
src/aes/ao_aes_int.h [new file with mode: 0644]
src/aes/ao_aes_tables.c [new file with mode: 0644]
src/aes/ao_aes_tables.h [new file with mode: 0644]
src/avr/ao_timer.c
src/cc1111/Makefile.cc1111
src/cc1111/ao_adc.c
src/cc1111/ao_aes.c
src/cc1111/ao_arch.h
src/cc1111/ao_arch_funcs.h
src/cc1111/ao_launch.c
src/cc1111/ao_pins.h
src/cc1111/ao_radio.c
src/cc1111/ao_serial.c
src/cc1111/ao_spi.c
src/cc1111/ao_timer.c
src/core/ao.h
src/core/ao_aes.h
src/core/ao_config.c
src/core/ao_data.h
src/core/ao_led.h
src/core/ao_radio_cmac.c
src/core/ao_radio_cmac.h [new file with mode: 0644]
src/core/ao_radio_cmac_cmd.c [new file with mode: 0644]
src/core/ao_radio_cmac_cmd.h [new file with mode: 0644]
src/core/ao_storage.c
src/core/ao_task.c
src/drivers/ao_74hc497.c [new file with mode: 0644]
src/drivers/ao_74hc497.h [new file with mode: 0644]
src/drivers/ao_button.c [new file with mode: 0644]
src/drivers/ao_button.h [new file with mode: 0644]
src/drivers/ao_cc1120.c
src/drivers/ao_event.c [new file with mode: 0644]
src/drivers/ao_event.h [new file with mode: 0644]
src/drivers/ao_hmc5883.c
src/drivers/ao_hmc5883.h
src/drivers/ao_lco_cmd.c [new file with mode: 0644]
src/drivers/ao_lco_cmd.h [new file with mode: 0644]
src/drivers/ao_mma655x.c [new file with mode: 0644]
src/drivers/ao_mma655x.h [new file with mode: 0644]
src/drivers/ao_mpu6000.c
src/drivers/ao_mpu6000.h
src/drivers/ao_ms5607.c
src/drivers/ao_ms5607.h
src/drivers/ao_pad.c [new file with mode: 0644]
src/drivers/ao_pad.h [new file with mode: 0644]
src/drivers/ao_pca9922.c [new file with mode: 0644]
src/drivers/ao_quadrature.c [new file with mode: 0644]
src/drivers/ao_quadrature.h [new file with mode: 0644]
src/drivers/ao_radio_master.c [new file with mode: 0644]
src/drivers/ao_radio_slave.c [new file with mode: 0644]
src/drivers/ao_radio_spi.h [new file with mode: 0644]
src/drivers/ao_seven_segment.c [new file with mode: 0644]
src/drivers/ao_seven_segment.h [new file with mode: 0644]
src/megametrum-v0.1/Makefile
src/megametrum-v0.1/ao_megametrum.c
src/megametrum-v0.1/ao_pins.h
src/megametrum-v0.1/stlink-pins
src/product/ao_telelaunch.c
src/spiradio-v0.1/.sdcdbrc [new file with mode: 0644]
src/spiradio-v0.1/Makefile [new file with mode: 0644]
src/spiradio-v0.1/ao_pins.h [new file with mode: 0644]
src/spiradio-v0.1/ao_spiradio.c [new file with mode: 0644]
src/stm-demo/Makefile
src/stm-demo/ao_demo.c
src/stm-demo/ao_pins.h
src/stm/Makefile.defs
src/stm/ao_adc_stm.c
src/stm/ao_arch.h
src/stm/ao_arch_funcs.h
src/stm/ao_data.c [new file with mode: 0644]
src/stm/ao_eeprom_stm.c [new file with mode: 0644]
src/stm/ao_exti.h
src/stm/ao_exti_stm.c
src/stm/ao_lcd_stm.c
src/stm/ao_lcd_stm.h [new file with mode: 0644]
src/stm/ao_spi_stm.c
src/stm/ao_timer.c
src/stm/stm32l.h
src/telebt-v0.1/.sdcdbrc
src/telefire-v0.1/.sdcdbrc [new file with mode: 0644]
src/telefire-v0.1/Makefile [new file with mode: 0644]
src/telefire-v0.1/ao_pins.h [new file with mode: 0644]
src/telefire-v0.1/ao_telefire.c [new file with mode: 0644]

index 1773096d3a940df68d749ea26e26017e193cef27..782be7f62cbcd373897a7b07878851cf6d07162d 100644 (file)
@@ -33,6 +33,7 @@ ao-tools/ao-list/ao-list
 ao-tools/ao-load/ao-load
 ao-tools/ao-postflight/ao-postflight
 ao-tools/ao-rawload/ao-rawload
+ao-tools/ao-send-telem/ao-send-telem
 ao-tools/ao-view/ao-view
 ao-view/Makefile
 ao-view/ao-view
index 57c4da71f3ffb78465c78cd467e87e4faafbe033..27ea3a2bcfa21ad94b6913f1246004a2aeaabd3c 100644 (file)
@@ -23,16 +23,10 @@ import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.*;
 
-class AltosSensorTM {
-       int     tick;
-       int     accel;
-       int     pres;
-       int     temp;
-       int     batt;
-       int     drogue;
-       int     main;
+class AltosSensorTM extends AltosRecordTM {
 
-       public AltosSensorTM(AltosLink link) throws InterruptedException, TimeoutException {
+       public AltosSensorTM(AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+               super();
                link.printf("a\n");
                for (;;) {
                        String line = link.get_reply_no_dialog(5000);
@@ -82,6 +76,10 @@ class AltosSensorTM {
                        }
                        break;
                }
+               ground_accel = config_data.accel_cal_plus;
+               ground_pres = pres;
+               accel_plus_g = config_data.accel_cal_plus;
+               accel_minus_g = config_data.accel_cal_minus;
        }
 }
 
@@ -253,7 +251,7 @@ class AltosGPSQuery extends AltosGPS {
                        if (line.startsWith("Date:")) {
                                if (bits.length < 2)
                                        continue;
-                               String[] d = bits[1].split(":");
+                               String[] d = bits[1].split("/");
                                if (d.length < 3)
                                        continue;
                                year = Integer.parseInt(d[0]) + 2000;
@@ -264,7 +262,7 @@ class AltosGPSQuery extends AltosGPS {
                        if (line.startsWith("Time:")) {
                                if (bits.length < 2)
                                        continue;
-                               String[] d = bits[1].split("/");
+                               String[] d = bits[1].split(":");
                                if (d.length < 3)
                                        continue;
                                hour = Integer.parseInt(d[0]);
@@ -339,8 +337,7 @@ public class AltosIdleMonitor extends Thread {
        }
 
        void update_state() throws InterruptedException, TimeoutException {
-               AltosRecord     record;
-               int             rssi;
+               AltosRecord     record = null;
 
                try {
                        if (remote) {
@@ -350,20 +347,7 @@ public class AltosIdleMonitor extends Thread {
                                link.flush_input();
                        config_data = new AltosConfigData(link);
                        if (config_data.product.startsWith("TeleMetrum")) {
-                               AltosRecordTM record_tm = new AltosRecordTM();
-                               AltosSensorTM sensor = new AltosSensorTM(link);
-                               record_tm.accel = sensor.accel;
-                               record_tm.pres = sensor.pres;
-                               record_tm.batt = sensor.batt;
-                               record_tm.temp = sensor.temp;
-                               record_tm.drogue = sensor.drogue;
-                               record_tm.main = sensor.main;
-                               record_tm.ground_accel = record_tm.accel;
-                               record_tm.ground_pres = record_tm.pres;
-                               record_tm.accel_plus_g = config_data.accel_cal_plus;
-                               record_tm.accel_minus_g = config_data.accel_cal_minus;
-                               record_tm.tick = sensor.tick;
-                               record = record_tm;
+                               record = new AltosSensorTM(link, config_data);
                        } else if (config_data.product.startsWith("MegaMetrum")) {
                                AltosRecordMM record_mm = new AltosRecordMM();
                                AltosSensorMM sensor = new AltosSensorMM(link);
@@ -390,24 +374,27 @@ public class AltosIdleMonitor extends Thread {
                                record = new AltosRecord();
 
                        gps = new AltosGPSQuery(link, config_data);
+
+                       record.version = 0;
+                       record.callsign = config_data.callsign;
+                       record.serial = config_data.serial;
+                       record.flight = config_data.log_available() > 0 ? 255 : 0;
+                       record.status = 0;
+                       record.state = AltosLib.ao_flight_idle;
+                       record.gps = gps;
+                       record.new_gps = true;
+                       state = new AltosState (record, state);
                } finally {
                        if (remote) {
                                link.stop_remote();
-                               rssi = AltosRSSI();
-                       } else
-                               rssi = 0;
+                               if (record != null)
+                                       record.rssi = AltosRSSI();
+                       } else {
+                               if (record != null)
+                                       record.rssi = 0;
+                       }
                }
 
-               record.version = 0;
-               record.callsign = config_data.callsign;
-               record.serial = config_data.serial;
-               record.flight = config_data.log_available() > 0 ? 255 : 0;
-               record.rssi = rssi;
-               record.status = 0;
-               record.state = AltosLib.ao_flight_idle;
-
-               record.gps = gps;
-               state = new AltosState (record, state);
        }
 
        public void set_frequency(double in_frequency) {
index d59e73ba6eca2a690da98f0d46e9db7e6c870919..415c3c64c466daa80bbe5bd6f233a3aa2e821d8e 100644 (file)
@@ -23,7 +23,7 @@ import java.util.concurrent.*;
 import java.util.*;
 import java.text.*;
 
-public abstract class AltosLink {
+public abstract class AltosLink implements Runnable {
 
        public final static int ERROR = -1;
        public final static int TIMEOUT = -2;
@@ -101,15 +101,23 @@ public abstract class AltosLink {
                try {
                        for (;;) {
                                c = getchar();
-                               if (Thread.interrupted())
+                               if (Thread.interrupted()) {
+                                       if (debug)
+                                               System.out.printf("INTERRUPTED\n");
                                        break;
+                               }
                                if (c == ERROR) {
+                                       if (debug)
+                                               System.out.printf("ERROR\n");
                                        add_telem (new AltosLine());
                                        add_reply (new AltosLine());
                                        break;
                                }
-                               if (c == TIMEOUT)
+                               if (c == TIMEOUT) {
+                                       if (debug)
+                                               System.out.printf("TIMEOUT\n");
                                        continue;
+                               }
                                if (c == '\r')
                                        continue;
                                synchronized(this) {
@@ -180,6 +188,14 @@ public abstract class AltosLink {
                reply_queue.put (line);
        }
 
+       public void abort_reply() {
+               try {
+                       add_telem (new AltosLine());
+                       add_reply (new AltosLine());
+               } catch (InterruptedException e) {
+               }
+       }
+
        public void add_string(String line) throws InterruptedException {
                if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) {
                        add_telem(new AltosLine(line));
index e468f84b425b705a1b6a498d309679c11449b18d..8722bc050bac011f183248301012d27b1d46e5c0 100644 (file)
@@ -127,7 +127,7 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
 
                double  p = filtered_pressure();
                if (p == MISSING)
-                       return MISSING;
+                       return raw_altitude();
                return AltosConvert.pressure_to_altitude(p);
        }
 
index afb7079097fd05359fe8d998f4ca8fdf46515ee4..37accef60289cd8d2518d4217c5d9b22403cae26 100644 (file)
@@ -177,14 +177,14 @@ public class AltosRecordTM extends AltosRecord {
                drogue = MISSING;
                main = MISSING;
 
-               flight_accel = 0;
-               flight_vel = 0;
-               flight_pres = 0;
-
-               ground_accel = 0;
-               ground_pres = 0;
-               accel_plus_g = 0;
-               accel_minus_g = 0;
+               flight_accel = MISSING;
+               flight_vel = MISSING;
+               flight_pres = MISSING;
+
+               ground_accel = MISSING;
+               ground_pres = MISSING;
+               accel_plus_g = MISSING;
+               accel_minus_g = MISSING;
        }
 
        public AltosRecordTM(AltosRecord old) {
index e20ec9a7109dbcd493deac0b544f692f2e78cd38..3b37a3d4b498fc90a8ba4e47cd1d6a03fd5681d8 100644 (file)
@@ -38,6 +38,7 @@ public class AltosState {
        public boolean boost;   /* under power */
 
        public double   ground_altitude;
+       public double   altitude;
        public double   height;
        public double   speed;
        public double   acceleration;
@@ -82,6 +83,7 @@ public class AltosState {
                data = cur;
 
                ground_altitude = data.ground_altitude();
+               altitude = data.raw_altitude();
                height = data.filtered_height();
 
                report_time = System.currentTimeMillis();
index aa6a6d4e5d1ff7b55693ed240cf4dff6c922101b..c14009767447debd51491dfe1f6a1d449b4253ef 100644 (file)
@@ -40,18 +40,38 @@ public class AltosInfoTable extends JTable {
                return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
        }
 
+       int text_width(String t) {
+               FontMetrics     infoValueMetrics = getFontMetrics(Altos.table_value_font);
+
+               return infoValueMetrics.stringWidth(t);
+       }
+
+       void set_layout() {
+               setRowHeight(desired_row_height());
+               for (int i = 0; i < info_columns * 2; i++)
+               {
+                       TableColumn column = getColumnModel().getColumn(i);
+
+                       if ((i & 1) == 0)
+                               column.setPreferredWidth(text_width(" Satellites Visible "));
+                       else
+                               column.setPreferredWidth(text_width(" 179°59.99999' "));
+               }
+       }
+
        public AltosInfoTable() {
                super(new AltosFlightInfoTableModel(info_rows, info_columns));
                model = (AltosFlightInfoTableModel) getModel();
                setFont(Altos.table_value_font);
                setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
                setShowGrid(true);
-               setRowHeight(desired_row_height());
+               set_layout();
                doLayout();
        }
 
        public void set_font() {
                setFont(Altos.table_value_font);
+               set_layout();
                doLayout();
        }
 
@@ -95,13 +115,8 @@ public class AltosInfoTable extends JTable {
                if (state == null)
                        return;
                info_reset();
-               info_add_row(0, "Rocket state", "%s", state.data.state());
-               info_add_row(0, "Callsign", "%s", state.data.callsign);
-               info_add_row(0, "Rocket serial", "%6d", state.data.serial);
-               info_add_row(0, "Rocket flight", "%6d", state.data.flight);
-
-               info_add_row(0, "RSSI", "%6d    dBm", state.data.rssi);
-               info_add_row(0, "CRC Errors", "%6d", crc_errors);
+               info_add_row(0, "Altitude", "%6.0f    m", state.altitude);
+               info_add_row(0, "Pad altitude", "%6.0f    m", state.ground_altitude);
                info_add_row(0, "Height", "%6.0f    m", state.height);
                info_add_row(0, "Max height", "%6.0f    m", state.max_height);
                info_add_row(0, "Acceleration", "%8.1f  m/s²", state.acceleration);
@@ -114,7 +129,8 @@ public class AltosInfoTable extends JTable {
                        info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense);
                if (state.main_sense != AltosRecord.MISSING)
                        info_add_row(0, "Main", "%9.2f V", state.main_sense);
-               info_add_row(0, "Pad altitude", "%6.0f    m", state.ground_altitude);
+               info_add_row(0, "CRC Errors", "%6d", crc_errors);
+
                if (state.gps == null || !state.gps.connected) {
                        info_add_row(1, "GPS", "not available");
                } else {
index c4e9c69720339e0d0a4b474f87319986fc4dd33b..6cee1609e1db5ba6815bc0a6fd7e7195e16861f1 100644 (file)
@@ -41,7 +41,7 @@ import libaltosJNI.*;
  * threads.
  */
 
-public class AltosSerial extends AltosLink implements Runnable {
+public class AltosSerial extends AltosLink  {
 
        static java.util.List<String> devices_opened = Collections.synchronizedList(new LinkedList<String>());
 
@@ -54,13 +54,19 @@ public class AltosSerial extends AltosLink implements Runnable {
        Frame frame;
 
        public int getchar() {
+               if (altos == null)
+                       return ERROR;
                return libaltos.altos_getchar(altos, 0);
        }
 
        public void flush_output() {
                super.flush_output();
                if (altos != null) {
-                       libaltos.altos_flush(altos);
+                       if (libaltos.altos_flush(altos) != 0) {
+                               libaltos.altos_close(altos);
+                               altos = null;
+                               abort_reply();
+                       }
                }
        }
 
@@ -155,7 +161,11 @@ public class AltosSerial extends AltosLink implements Runnable {
 
        private void putc(char c) {
                if (altos != null)
-                       libaltos.altos_putchar(altos, c);
+                       if (libaltos.altos_putchar(altos, c) != 0) {
+                               libaltos.altos_close(altos);
+                               altos = null;
+                               abort_reply();
+                       }
        }
 
        public void print(String data) {
index 92c985a9550db170274d78300a40dc4931b9c6e6..986919d4a4297c0291ddca7e1ae0e89e8938a399 100644 (file)
@@ -1,6 +1,7 @@
 !addplugindir Instdrv/NSIS/Plugins
 ; Definitions for Java 1.6 Detection
 !define JRE_VERSION "1.6"
+!define JRE_ALTERNATE "1.7"
 !define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586-p.exe"
 !define PRODUCT_NAME "Altus Metrum Windows Software"
 
@@ -42,6 +43,8 @@ Function DetectJRE
              "CurrentVersion"
   StrCmp $2 ${JRE_VERSION} done
 
+  StrCmp $2 ${JRE_ALTERNATE} done
+
   Call GetJRE
 
   done:
index 1cc27cbee6e42040a287f85851cc179559edc6ae..515432f9ac21f8ed4e351ae89a881ae59cc398fe 100644 (file)
@@ -221,7 +221,7 @@ altos_flush(struct altos_file *file)
 #endif
                if (ret < 0) {
                        altos_set_last_posix_error();
-                       return -errno;
+                       return -last_error.code;
                }
                if (ret) {
                        memmove(file->out_data, file->out_data + ret,
@@ -247,7 +247,7 @@ altos_putchar(struct altos_file *file, char c)
        ret = 0;
        if (file->out_used == USB_BUF_SIZE)
                ret = altos_flush(file);
-       return 0;
+       return ret;
 }
 
 #ifdef USE_POLL
index c4c354e00f0469477f42e5789956dabfebd4e346..c6cc51a160227f7e3c9d7620f432fb388043a6db 100644 (file)
@@ -182,6 +182,7 @@ main (int argc, char **argv)
                        break;
                case 'R':
                        realtime = 1;
+                       break;
                default:
                        usage(argv[0]);
                        break;
index e689539bb41c5b3e372c3698d2ae601444fdf30c..a471dcc47358b6d54a1dcefaae6769d73b750946 100644 (file)
@@ -112,10 +112,17 @@ struct load {
        uint8_t         buf[0];
 };
 
+uint32_t round4(uint32_t a) {
+       return (a + 3) & ~3;
+}
+
 struct load *
 new_load (uint32_t addr, uint32_t len)
 {
-       struct load *new = calloc (1, sizeof (struct load) + len);
+       struct load *new;
+
+       len = round4(len);
+       new = calloc (1, sizeof (struct load) + len);
        if (!new)
                abort();
 
index 0b35bbe36bc0eda4487f565fc430c9aa5ddfa109..589e8d8f79c9ffb58a75d74dad7fc541a14e7652 100644 (file)
@@ -3,7 +3,7 @@ Section: electronics
 Priority: optional
 Maintainer: Bdale Garbee <bdale@gag.com>
 Uploaders: Keith Packard <keithp@keithp.com>
-Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, default-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config
+Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, default-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config, libelf-dev
 Standards-Version: 3.9.3
 Homepage: http://altusmetrum.org/AltOS
 Vcs-Git: git://git.gag.com/fw/altos
index 491618f69823001125858201fa0a751923d21b35..b8828d461d65e27e9c393b6163e035c48fbd39b7 100644 (file)
@@ -21,7 +21,9 @@ ifneq ($(shell which sdcc),)
        telebt-v0.0 telebt-v0.1 \
        telemetrum-v0.1-sky telemetrum-v0.1-sirf \
        telelaunch-v0.1 tidongle test \
-       teleterra-v0.2 teleshield-v0.1
+       teleterra-v0.2 teleshield-v0.1 \
+       telefire-v0.1 \
+       spiradio-v0.1
 endif
 
 ifneq ($(shell which avr-gcc),)
@@ -29,7 +31,7 @@ ifneq ($(shell which avr-gcc),)
 endif
 
 ifneq ($(shell which arm-none-eabi-gcc),)
-       SUBDIRS += megametrum-v0.1 stm-bringup stm-demo 
+       SUBDIRS += megametrum-v0.1 stm-bringup stm-demo telelco-v0.1
 endif
 
 all: all-local all-recursive
diff --git a/src/aes/ao_aes.c b/src/aes/ao_aes.c
new file mode 100644 (file)
index 0000000..4977aaf
--- /dev/null
@@ -0,0 +1,390 @@
+/* Copyright (C) 2000-2009 Peter Selinger.
+   This file is part of ccrypt. It is free software and it is covered
+   by the GNU general public license. See the file COPYING for details. */
+
+/* rijndael.c - optimized version of the Rijndeal cipher */
+/* $Id: rijndael.c 258 2009-08-26 17:46:10Z selinger $ */
+
+/* derived from original source: rijndael-alg-ref.c   v2.0   August '99
+ * Reference ANSI C code for NIST competition
+ * authors: Paulo Barreto
+ *          Vincent Rijmen
+ */
+
+#include <ao.h>
+#include <ao_aes.h>
+#include "ao_aes_int.h"
+
+static const int xshifts[3][2][4] = {
+  {{0, 1, 2, 3},
+   {0, 3, 2, 1}},
+
+  {{0, 1, 2, 3},
+   {0, 5, 4, 3}},
+
+  {{0, 1, 3, 4},
+   {0, 7, 5, 4}},
+};
+
+/* Exor corresponding text input and round key input bytes */
+/* the result is written to res, which can be the same as a */
+static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC],
+                        word32 rk[MAXBC], int BC)
+{
+  int j;
+
+  for (j = 0; j < BC; j++) {
+    res[j] = a[j] ^ rk[j];
+  }
+}
+
+#if 0                          /* code included for reference */
+
+/* shift rows a, return result in res. This avoids having to copy a
+   tmp array back to a. res must not be a. */
+static inline void xShiftRow(word32 res[MAXBC], word32 a[MAXBC], int shift[4],
+                     int BC)
+{
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+  word8 (*res8)[4] = (word8 (*)[4]) res;
+
+  /* Row 0 remains unchanged
+   * The other three rows are shifted a variable amount
+   */
+  int i, j;
+  int s;
+
+  for (j = 0; j < BC; j++) {
+    res8[j][0] = a8[j][0];
+  }
+  for (i = 1; i < 4; i++) {
+    s = shift[i];
+    for (j = 0; j < BC; j++) {
+      res8[j][i] = a8[(j + s) % BC][i];
+    }
+  }
+}
+
+static inline void xSubstitution(word32 a[MAXBC], word8 box[256], int BC)
+{
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+
+  /* Replace every byte of the input by the byte at that place
+   * in the nonlinear S-box
+   */
+  int i, j;
+
+  for (i = 0; i < 4; i++) {
+    for (j = 0; j < BC; j++) {
+      a8[j][i] = box[a[j][i]];
+    }
+  }
+}
+
+#endif                         /* code included for reference */
+
+/* profiling shows that the ccrypt program spends about 50% of its
+   time in the function xShiftSubst. Splitting the inner "for"
+   statement into two parts - versus using the expensive "%" modulo
+   operation, makes this function about 44% faster, thereby making the
+   entire program about 28% faster. With -O3 optimization, the time
+   savings are even more dramatic - ccrypt runs between 55% and 65%
+   faster on most platforms. */
+
+/* do ShiftRow and Substitution together. res must not be a. */
+static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC],
+                       int shift[4], int BC, const word8 box[256])
+{
+  int i, j;
+  int s;
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+  word8 (*res8)[4] = (word8 (*)[4]) res;
+
+  for (j = 0; j < BC; j++) {
+    res8[j][0] = box[a8[j][0]];
+  }
+  for (i = 1; i < 4; i++) {
+    s = shift[i];
+    for (j = 0; j < BC - s; j++) {
+      res8[j][i] = box[a8[(j + s)][i]];
+    }
+    for (j = BC - s; j < BC; j++) {
+      res8[j][i] = box[a8[(j + s) - BC][i]];
+    }
+  }
+}
+
+#if 0                          /* code included for reference */
+
+/* Mix the four bytes of every column in a linear way */
+/* the result is written to res, which may equal a */
+static inline void xMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC)
+{
+  int j;
+  word32 b;
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+
+  for (j = 0; j < BC; j++) {
+    b = M0[0][a8[j][0]].w32;
+    b ^= M0[1][a8[j][1]].w32;
+    b ^= M0[2][a8[j][2]].w32;
+    b ^= M0[3][a8[j][3]].w32;
+    res[j] = b;
+  }
+}
+
+#endif                         /* code included for reference */
+
+/* do MixColumn and KeyAddition together */
+static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC],
+                   word32 rk[MAXBC], int BC)
+{
+  int j;
+  word32 b;
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+
+  for (j = 0; j < BC; j++) {
+    b = M0[0][a8[j][0]].w32;
+    b ^= M0[1][a8[j][1]].w32;
+    b ^= M0[2][a8[j][2]].w32;
+    b ^= M0[3][a8[j][3]].w32;
+    b ^= rk[j];
+    res[j] = b;
+  }
+}
+
+/* Mix the four bytes of every column in a linear way
+ * This is the opposite operation of xMixColumn */
+/* the result is written to res, which may equal a */
+static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC)
+{
+  int j;
+  word32 b;
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+
+  for (j = 0; j < BC; j++) {
+    b = M1[0][a8[j][0]].w32;
+    b ^= M1[1][a8[j][1]].w32;
+    b ^= M1[2][a8[j][2]].w32;
+    b ^= M1[3][a8[j][3]].w32;
+    res[j] = b;
+  }
+}
+
+#if 0                          /* code included for reference */
+
+/* do KeyAddition and InvMixColumn together */
+static inline void xAddInvMix(word32 res[MAXBC], word32 a[MAXBC],
+                      word32 rk[MAXBC], int BC)
+{
+  int j;
+  word32 b;
+  word8 (*a8)[4] = (word8 (*)[4]) a;
+
+  for (j = 0; j < BC; j++) {
+    a[j] = a[j] ^ rk[j];
+    b = M1[0][a8[j][0]].w32;
+    b ^= M1[1][a8[j][1]].w32;
+    b ^= M1[2][a8[j][2]].w32;
+    b ^= M1[3][a8[j][3]].w32;
+    res[j] = b;
+  }
+}
+
+#endif                         /* code included for reference */
+
+int xrijndaelKeySched(word32 key[], int keyBits, int blockBits,
+                     roundkey *rkk)
+{
+  /* Calculate the necessary round keys
+   * The number of calculations depends on keyBits and blockBits */
+  int KC, BC, ROUNDS;
+  int i, j, t, rconpointer = 0;
+  word8 (*k8)[4] = (word8 (*)[4]) key;
+
+  switch (keyBits) {
+  case 128:
+    KC = 4;
+    break;
+  case 192:
+    KC = 6;
+    break;
+  case 256:
+    KC = 8;
+    break;
+  default:
+    return -1;
+  }
+
+  switch (blockBits) {
+  case 128:
+    BC = 4;
+    break;
+  case 192:
+    BC = 6;
+    break;
+  case 256:
+    BC = 8;
+    break;
+  default:
+    return -2;
+  }
+
+  ROUNDS = KC > BC ? KC + 6 : BC + 6;
+
+  t = 0;
+  /* copy values into round key array */
+  for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++)
+    rkk->rk[t] = key[j];
+
+  while (t < (ROUNDS + 1) * BC) {  /* while not enough round key material */
+    /* calculate new values */
+    for (i = 0; i < 4; i++) {
+      k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]];
+    }
+    k8[0][0] ^= xrcon[rconpointer++];
+
+    if (KC != 8) {
+      for (j = 1; j < KC; j++) {
+       key[j] ^= key[j - 1];
+      }
+    } else {
+      for (j = 1; j < 4; j++) {
+       key[j] ^= key[j - 1];
+      }
+      for (i = 0; i < 4; i++) {
+       k8[4][i] ^= xS[k8[3][i]];
+      }
+      for (j = 5; j < 8; j++) {
+       key[j] ^= key[j - 1];
+      }
+    }
+    /* copy values into round key array */
+    for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) {
+      rkk->rk[t] = key[j];
+    }
+  }
+
+  /* make roundkey structure */
+  rkk->BC = BC;
+  rkk->KC = KC;
+  rkk->ROUNDS = ROUNDS;
+  for (i = 0; i < 2; i++) {
+    for (j = 0; j < 4; j++) {
+      rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j];
+    }
+  }
+
+  return 0;
+}
+
+/* Encryption of one block. */
+
+void xrijndaelEncrypt(word32 block[], roundkey *rkk)
+{
+  word32 block2[MAXBC];                /* hold intermediate result */
+  int r;
+
+  int *shift = rkk->shift[0];
+  int BC = rkk->BC;
+  int ROUNDS = rkk->ROUNDS;
+  word32 *rp = rkk->rk;
+
+  /* begin with a key addition */
+  xKeyAddition(block, block, rp, BC);
+  rp += BC;
+
+  /* ROUNDS-1 ordinary rounds */
+  for (r = 1; r < ROUNDS; r++) {
+    xShiftSubst(block2, block, shift, BC, xS);
+    xMixAdd(block, block2, rp, BC);
+    rp += BC;
+  }
+
+  /* Last round is special: there is no xMixColumn */
+  xShiftSubst(block2, block, shift, BC, xS);
+  xKeyAddition(block, block2, rp, BC);
+}
+
+void xrijndaelDecrypt(word32 block[], roundkey *rkk)
+{
+  word32 block2[MAXBC];                /* hold intermediate result */
+  int r;
+
+  int *shift = rkk->shift[1];
+  int BC = rkk->BC;
+  int ROUNDS = rkk->ROUNDS;
+  word32 *rp = rkk->rk + ROUNDS * BC;
+
+  /* To decrypt: apply the inverse operations of the encrypt routine,
+   *             in opposite order
+   * 
+   * (xKeyAddition is an involution: it's equal to its inverse)
+   * (the inverse of xSubstitution with table S is xSubstitution with the 
+   * inverse table of S)
+   * (the inverse of xShiftRow is xShiftRow over a suitable distance)
+   */
+
+  /* First the special round:
+   *   without xInvMixColumn
+   *   with extra xKeyAddition
+   */
+  xKeyAddition(block2, block, rp, BC);
+  xShiftSubst(block, block2, shift, BC, xSi);
+  rp -= BC;
+
+  /* ROUNDS-1 ordinary rounds
+   */
+  for (r = ROUNDS - 1; r > 0; r--) {
+    xKeyAddition(block, block, rp, BC);
+    xInvMixColumn(block2, block, BC);
+    xShiftSubst(block, block2, shift, BC, xSi);
+    rp -= BC;
+  }
+
+  /* End with the extra key addition
+   */
+
+  xKeyAddition(block, block, rp, BC);
+}
+
+uint8_t ao_aes_mutex;
+static roundkey        rkk;
+
+static uint8_t iv[16];
+
+void
+ao_aes_set_mode(enum ao_aes_mode mode)
+{
+       /* we only do CBC_MAC anyways... */
+}
+
+void
+ao_aes_set_key(__xdata uint8_t *in)
+{
+       xrijndaelKeySched((word32 *) in, 128, 128, &rkk);
+}
+
+void
+ao_aes_zero_iv(void)
+{
+       memset(iv, '\0', sizeof (iv));
+}
+
+void
+ao_aes_run(__xdata uint8_t *in,
+          __xdata uint8_t *out)
+{
+       uint8_t i;
+
+       for (i = 0; i < 16; i++)
+               iv[i] ^= in[i];
+       xrijndaelEncrypt((word32 *) iv, &rkk);
+       if (out)
+               memcpy(out, iv, 16);
+}
+
+void
+ao_aes_init(void)
+{
+}
diff --git a/src/aes/ao_aes_int.h b/src/aes/ao_aes_int.h
new file mode 100644 (file)
index 0000000..7990a2e
--- /dev/null
@@ -0,0 +1,64 @@
+/* Copyright (C) 2000-2009 Peter Selinger.
+   This file is part of ccrypt. It is free software and it is covered
+   by the GNU general public license. See the file COPYING for details. */
+
+/* rijndael.h */
+/* $Id: rijndael.h 258 2009-08-26 17:46:10Z selinger $ */
+
+/* derived from original source: rijndael-alg-ref.h   v2.0   August '99
+ * Reference ANSI C code for NIST competition
+ * authors: Paulo Barreto
+ *          Vincent Rijmen
+ */
+
+#ifndef __RIJNDAEL_H
+#define __RIJNDAEL_H
+
+#include <stdint.h>
+
+typedef uint8_t word8;
+typedef uint32_t word32;
+
+/* a type to hold 32 bits accessible as 1 integer or 4 bytes */
+union word8x4_u {
+  word8 w8[4];
+  word32 w32;
+};
+typedef union word8x4_u word8x4;
+
+#include "ao_aes_tables.h"
+
+#define MAXBC          (256/32)
+#define MAXKC          (256/32)
+#define MAXROUNDS      14
+#define MAXRK           ((MAXROUNDS+1)*MAXBC)
+
+typedef struct {
+  int BC;
+  int KC;
+  int ROUNDS;
+  int shift[2][4];
+  word32 rk[MAXRK];
+} roundkey;
+
+/* keys and blocks are externally treated as word32 arrays, to
+   make sure they are aligned on 4-byte boundaries on architectures
+   that require it. */
+
+/* make a roundkey rkk from key. key must have appropriate size given
+   by keyBits. keyBits and blockBits may only be 128, 196, or
+   256. Returns non-zero if arguments are invalid. */
+
+int xrijndaelKeySched(word32 key[], int keyBits, int blockBits,
+                     roundkey *rkk);
+
+/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must
+   have been created with xrijndaelKeySched. Size of block, in bits,
+   must be equal to blockBits parameter that was used to make rkk. In
+   all other cases, behavior is undefined - for reasons of speed, no
+   check for error conditions is done. */
+
+void xrijndaelEncrypt(word32 block[], roundkey *rkk);
+void xrijndaelDecrypt(word32 block[], roundkey *rkk);
+
+#endif                         /* __RIJNDAEL_H */
diff --git a/src/aes/ao_aes_tables.c b/src/aes/ao_aes_tables.c
new file mode 100644 (file)
index 0000000..1bca227
--- /dev/null
@@ -0,0 +1,768 @@
+/* Copyright (C) 2000-2009 Peter Selinger.
+   This file is part of ccrypt. It is free software and it is covered
+   by the GNU general public license. See the file COPYING for details. */
+
+/* generated by maketables.c */
+
+#include "ao_aes_int.h"
+
+const word8x4 M0[4][256] = {
+ {
+  {{  0,   0,   0,   0}}, {{  2,   1,   1,   3}}, {{  4,   2,   2,   6}}, 
+  {{  6,   3,   3,   5}}, {{  8,   4,   4,  12}}, {{ 10,   5,   5,  15}}, 
+  {{ 12,   6,   6,  10}}, {{ 14,   7,   7,   9}}, {{ 16,   8,   8,  24}}, 
+  {{ 18,   9,   9,  27}}, {{ 20,  10,  10,  30}}, {{ 22,  11,  11,  29}}, 
+  {{ 24,  12,  12,  20}}, {{ 26,  13,  13,  23}}, {{ 28,  14,  14,  18}}, 
+  {{ 30,  15,  15,  17}}, {{ 32,  16,  16,  48}}, {{ 34,  17,  17,  51}}, 
+  {{ 36,  18,  18,  54}}, {{ 38,  19,  19,  53}}, {{ 40,  20,  20,  60}}, 
+  {{ 42,  21,  21,  63}}, {{ 44,  22,  22,  58}}, {{ 46,  23,  23,  57}}, 
+  {{ 48,  24,  24,  40}}, {{ 50,  25,  25,  43}}, {{ 52,  26,  26,  46}}, 
+  {{ 54,  27,  27,  45}}, {{ 56,  28,  28,  36}}, {{ 58,  29,  29,  39}}, 
+  {{ 60,  30,  30,  34}}, {{ 62,  31,  31,  33}}, {{ 64,  32,  32,  96}}, 
+  {{ 66,  33,  33,  99}}, {{ 68,  34,  34, 102}}, {{ 70,  35,  35, 101}}, 
+  {{ 72,  36,  36, 108}}, {{ 74,  37,  37, 111}}, {{ 76,  38,  38, 106}}, 
+  {{ 78,  39,  39, 105}}, {{ 80,  40,  40, 120}}, {{ 82,  41,  41, 123}}, 
+  {{ 84,  42,  42, 126}}, {{ 86,  43,  43, 125}}, {{ 88,  44,  44, 116}}, 
+  {{ 90,  45,  45, 119}}, {{ 92,  46,  46, 114}}, {{ 94,  47,  47, 113}}, 
+  {{ 96,  48,  48,  80}}, {{ 98,  49,  49,  83}}, {{100,  50,  50,  86}}, 
+  {{102,  51,  51,  85}}, {{104,  52,  52,  92}}, {{106,  53,  53,  95}}, 
+  {{108,  54,  54,  90}}, {{110,  55,  55,  89}}, {{112,  56,  56,  72}}, 
+  {{114,  57,  57,  75}}, {{116,  58,  58,  78}}, {{118,  59,  59,  77}}, 
+  {{120,  60,  60,  68}}, {{122,  61,  61,  71}}, {{124,  62,  62,  66}}, 
+  {{126,  63,  63,  65}}, {{128,  64,  64, 192}}, {{130,  65,  65, 195}}, 
+  {{132,  66,  66, 198}}, {{134,  67,  67, 197}}, {{136,  68,  68, 204}}, 
+  {{138,  69,  69, 207}}, {{140,  70,  70, 202}}, {{142,  71,  71, 201}}, 
+  {{144,  72,  72, 216}}, {{146,  73,  73, 219}}, {{148,  74,  74, 222}}, 
+  {{150,  75,  75, 221}}, {{152,  76,  76, 212}}, {{154,  77,  77, 215}}, 
+  {{156,  78,  78, 210}}, {{158,  79,  79, 209}}, {{160,  80,  80, 240}}, 
+  {{162,  81,  81, 243}}, {{164,  82,  82, 246}}, {{166,  83,  83, 245}}, 
+  {{168,  84,  84, 252}}, {{170,  85,  85, 255}}, {{172,  86,  86, 250}}, 
+  {{174,  87,  87, 249}}, {{176,  88,  88, 232}}, {{178,  89,  89, 235}}, 
+  {{180,  90,  90, 238}}, {{182,  91,  91, 237}}, {{184,  92,  92, 228}}, 
+  {{186,  93,  93, 231}}, {{188,  94,  94, 226}}, {{190,  95,  95, 225}}, 
+  {{192,  96,  96, 160}}, {{194,  97,  97, 163}}, {{196,  98,  98, 166}}, 
+  {{198,  99,  99, 165}}, {{200, 100, 100, 172}}, {{202, 101, 101, 175}}, 
+  {{204, 102, 102, 170}}, {{206, 103, 103, 169}}, {{208, 104, 104, 184}}, 
+  {{210, 105, 105, 187}}, {{212, 106, 106, 190}}, {{214, 107, 107, 189}}, 
+  {{216, 108, 108, 180}}, {{218, 109, 109, 183}}, {{220, 110, 110, 178}}, 
+  {{222, 111, 111, 177}}, {{224, 112, 112, 144}}, {{226, 113, 113, 147}}, 
+  {{228, 114, 114, 150}}, {{230, 115, 115, 149}}, {{232, 116, 116, 156}}, 
+  {{234, 117, 117, 159}}, {{236, 118, 118, 154}}, {{238, 119, 119, 153}}, 
+  {{240, 120, 120, 136}}, {{242, 121, 121, 139}}, {{244, 122, 122, 142}}, 
+  {{246, 123, 123, 141}}, {{248, 124, 124, 132}}, {{250, 125, 125, 135}}, 
+  {{252, 126, 126, 130}}, {{254, 127, 127, 129}}, {{ 27, 128, 128, 155}}, 
+  {{ 25, 129, 129, 152}}, {{ 31, 130, 130, 157}}, {{ 29, 131, 131, 158}}, 
+  {{ 19, 132, 132, 151}}, {{ 17, 133, 133, 148}}, {{ 23, 134, 134, 145}}, 
+  {{ 21, 135, 135, 146}}, {{ 11, 136, 136, 131}}, {{  9, 137, 137, 128}}, 
+  {{ 15, 138, 138, 133}}, {{ 13, 139, 139, 134}}, {{  3, 140, 140, 143}}, 
+  {{  1, 141, 141, 140}}, {{  7, 142, 142, 137}}, {{  5, 143, 143, 138}}, 
+  {{ 59, 144, 144, 171}}, {{ 57, 145, 145, 168}}, {{ 63, 146, 146, 173}}, 
+  {{ 61, 147, 147, 174}}, {{ 51, 148, 148, 167}}, {{ 49, 149, 149, 164}}, 
+  {{ 55, 150, 150, 161}}, {{ 53, 151, 151, 162}}, {{ 43, 152, 152, 179}}, 
+  {{ 41, 153, 153, 176}}, {{ 47, 154, 154, 181}}, {{ 45, 155, 155, 182}}, 
+  {{ 35, 156, 156, 191}}, {{ 33, 157, 157, 188}}, {{ 39, 158, 158, 185}}, 
+  {{ 37, 159, 159, 186}}, {{ 91, 160, 160, 251}}, {{ 89, 161, 161, 248}}, 
+  {{ 95, 162, 162, 253}}, {{ 93, 163, 163, 254}}, {{ 83, 164, 164, 247}}, 
+  {{ 81, 165, 165, 244}}, {{ 87, 166, 166, 241}}, {{ 85, 167, 167, 242}}, 
+  {{ 75, 168, 168, 227}}, {{ 73, 169, 169, 224}}, {{ 79, 170, 170, 229}}, 
+  {{ 77, 171, 171, 230}}, {{ 67, 172, 172, 239}}, {{ 65, 173, 173, 236}}, 
+  {{ 71, 174, 174, 233}}, {{ 69, 175, 175, 234}}, {{123, 176, 176, 203}}, 
+  {{121, 177, 177, 200}}, {{127, 178, 178, 205}}, {{125, 179, 179, 206}}, 
+  {{115, 180, 180, 199}}, {{113, 181, 181, 196}}, {{119, 182, 182, 193}}, 
+  {{117, 183, 183, 194}}, {{107, 184, 184, 211}}, {{105, 185, 185, 208}}, 
+  {{111, 186, 186, 213}}, {{109, 187, 187, 214}}, {{ 99, 188, 188, 223}}, 
+  {{ 97, 189, 189, 220}}, {{103, 190, 190, 217}}, {{101, 191, 191, 218}}, 
+  {{155, 192, 192,  91}}, {{153, 193, 193,  88}}, {{159, 194, 194,  93}}, 
+  {{157, 195, 195,  94}}, {{147, 196, 196,  87}}, {{145, 197, 197,  84}}, 
+  {{151, 198, 198,  81}}, {{149, 199, 199,  82}}, {{139, 200, 200,  67}}, 
+  {{137, 201, 201,  64}}, {{143, 202, 202,  69}}, {{141, 203, 203,  70}}, 
+  {{131, 204, 204,  79}}, {{129, 205, 205,  76}}, {{135, 206, 206,  73}}, 
+  {{133, 207, 207,  74}}, {{187, 208, 208, 107}}, {{185, 209, 209, 104}}, 
+  {{191, 210, 210, 109}}, {{189, 211, 211, 110}}, {{179, 212, 212, 103}}, 
+  {{177, 213, 213, 100}}, {{183, 214, 214,  97}}, {{181, 215, 215,  98}}, 
+  {{171, 216, 216, 115}}, {{169, 217, 217, 112}}, {{175, 218, 218, 117}}, 
+  {{173, 219, 219, 118}}, {{163, 220, 220, 127}}, {{161, 221, 221, 124}}, 
+  {{167, 222, 222, 121}}, {{165, 223, 223, 122}}, {{219, 224, 224,  59}}, 
+  {{217, 225, 225,  56}}, {{223, 226, 226,  61}}, {{221, 227, 227,  62}}, 
+  {{211, 228, 228,  55}}, {{209, 229, 229,  52}}, {{215, 230, 230,  49}}, 
+  {{213, 231, 231,  50}}, {{203, 232, 232,  35}}, {{201, 233, 233,  32}}, 
+  {{207, 234, 234,  37}}, {{205, 235, 235,  38}}, {{195, 236, 236,  47}}, 
+  {{193, 237, 237,  44}}, {{199, 238, 238,  41}}, {{197, 239, 239,  42}}, 
+  {{251, 240, 240,  11}}, {{249, 241, 241,   8}}, {{255, 242, 242,  13}}, 
+  {{253, 243, 243,  14}}, {{243, 244, 244,   7}}, {{241, 245, 245,   4}}, 
+  {{247, 246, 246,   1}}, {{245, 247, 247,   2}}, {{235, 248, 248,  19}}, 
+  {{233, 249, 249,  16}}, {{239, 250, 250,  21}}, {{237, 251, 251,  22}}, 
+  {{227, 252, 252,  31}}, {{225, 253, 253,  28}}, {{231, 254, 254,  25}}, 
+  {{229, 255, 255,  26}}, 
+ },
+ {
+  {{  0,   0,   0,   0}}, {{  3,   2,   1,   1}}, {{  6,   4,   2,   2}}, 
+  {{  5,   6,   3,   3}}, {{ 12,   8,   4,   4}}, {{ 15,  10,   5,   5}}, 
+  {{ 10,  12,   6,   6}}, {{  9,  14,   7,   7}}, {{ 24,  16,   8,   8}}, 
+  {{ 27,  18,   9,   9}}, {{ 30,  20,  10,  10}}, {{ 29,  22,  11,  11}}, 
+  {{ 20,  24,  12,  12}}, {{ 23,  26,  13,  13}}, {{ 18,  28,  14,  14}}, 
+  {{ 17,  30,  15,  15}}, {{ 48,  32,  16,  16}}, {{ 51,  34,  17,  17}}, 
+  {{ 54,  36,  18,  18}}, {{ 53,  38,  19,  19}}, {{ 60,  40,  20,  20}}, 
+  {{ 63,  42,  21,  21}}, {{ 58,  44,  22,  22}}, {{ 57,  46,  23,  23}}, 
+  {{ 40,  48,  24,  24}}, {{ 43,  50,  25,  25}}, {{ 46,  52,  26,  26}}, 
+  {{ 45,  54,  27,  27}}, {{ 36,  56,  28,  28}}, {{ 39,  58,  29,  29}}, 
+  {{ 34,  60,  30,  30}}, {{ 33,  62,  31,  31}}, {{ 96,  64,  32,  32}}, 
+  {{ 99,  66,  33,  33}}, {{102,  68,  34,  34}}, {{101,  70,  35,  35}}, 
+  {{108,  72,  36,  36}}, {{111,  74,  37,  37}}, {{106,  76,  38,  38}}, 
+  {{105,  78,  39,  39}}, {{120,  80,  40,  40}}, {{123,  82,  41,  41}}, 
+  {{126,  84,  42,  42}}, {{125,  86,  43,  43}}, {{116,  88,  44,  44}}, 
+  {{119,  90,  45,  45}}, {{114,  92,  46,  46}}, {{113,  94,  47,  47}}, 
+  {{ 80,  96,  48,  48}}, {{ 83,  98,  49,  49}}, {{ 86, 100,  50,  50}}, 
+  {{ 85, 102,  51,  51}}, {{ 92, 104,  52,  52}}, {{ 95, 106,  53,  53}}, 
+  {{ 90, 108,  54,  54}}, {{ 89, 110,  55,  55}}, {{ 72, 112,  56,  56}}, 
+  {{ 75, 114,  57,  57}}, {{ 78, 116,  58,  58}}, {{ 77, 118,  59,  59}}, 
+  {{ 68, 120,  60,  60}}, {{ 71, 122,  61,  61}}, {{ 66, 124,  62,  62}}, 
+  {{ 65, 126,  63,  63}}, {{192, 128,  64,  64}}, {{195, 130,  65,  65}}, 
+  {{198, 132,  66,  66}}, {{197, 134,  67,  67}}, {{204, 136,  68,  68}}, 
+  {{207, 138,  69,  69}}, {{202, 140,  70,  70}}, {{201, 142,  71,  71}}, 
+  {{216, 144,  72,  72}}, {{219, 146,  73,  73}}, {{222, 148,  74,  74}}, 
+  {{221, 150,  75,  75}}, {{212, 152,  76,  76}}, {{215, 154,  77,  77}}, 
+  {{210, 156,  78,  78}}, {{209, 158,  79,  79}}, {{240, 160,  80,  80}}, 
+  {{243, 162,  81,  81}}, {{246, 164,  82,  82}}, {{245, 166,  83,  83}}, 
+  {{252, 168,  84,  84}}, {{255, 170,  85,  85}}, {{250, 172,  86,  86}}, 
+  {{249, 174,  87,  87}}, {{232, 176,  88,  88}}, {{235, 178,  89,  89}}, 
+  {{238, 180,  90,  90}}, {{237, 182,  91,  91}}, {{228, 184,  92,  92}}, 
+  {{231, 186,  93,  93}}, {{226, 188,  94,  94}}, {{225, 190,  95,  95}}, 
+  {{160, 192,  96,  96}}, {{163, 194,  97,  97}}, {{166, 196,  98,  98}}, 
+  {{165, 198,  99,  99}}, {{172, 200, 100, 100}}, {{175, 202, 101, 101}}, 
+  {{170, 204, 102, 102}}, {{169, 206, 103, 103}}, {{184, 208, 104, 104}}, 
+  {{187, 210, 105, 105}}, {{190, 212, 106, 106}}, {{189, 214, 107, 107}}, 
+  {{180, 216, 108, 108}}, {{183, 218, 109, 109}}, {{178, 220, 110, 110}}, 
+  {{177, 222, 111, 111}}, {{144, 224, 112, 112}}, {{147, 226, 113, 113}}, 
+  {{150, 228, 114, 114}}, {{149, 230, 115, 115}}, {{156, 232, 116, 116}}, 
+  {{159, 234, 117, 117}}, {{154, 236, 118, 118}}, {{153, 238, 119, 119}}, 
+  {{136, 240, 120, 120}}, {{139, 242, 121, 121}}, {{142, 244, 122, 122}}, 
+  {{141, 246, 123, 123}}, {{132, 248, 124, 124}}, {{135, 250, 125, 125}}, 
+  {{130, 252, 126, 126}}, {{129, 254, 127, 127}}, {{155,  27, 128, 128}}, 
+  {{152,  25, 129, 129}}, {{157,  31, 130, 130}}, {{158,  29, 131, 131}}, 
+  {{151,  19, 132, 132}}, {{148,  17, 133, 133}}, {{145,  23, 134, 134}}, 
+  {{146,  21, 135, 135}}, {{131,  11, 136, 136}}, {{128,   9, 137, 137}}, 
+  {{133,  15, 138, 138}}, {{134,  13, 139, 139}}, {{143,   3, 140, 140}}, 
+  {{140,   1, 141, 141}}, {{137,   7, 142, 142}}, {{138,   5, 143, 143}}, 
+  {{171,  59, 144, 144}}, {{168,  57, 145, 145}}, {{173,  63, 146, 146}}, 
+  {{174,  61, 147, 147}}, {{167,  51, 148, 148}}, {{164,  49, 149, 149}}, 
+  {{161,  55, 150, 150}}, {{162,  53, 151, 151}}, {{179,  43, 152, 152}}, 
+  {{176,  41, 153, 153}}, {{181,  47, 154, 154}}, {{182,  45, 155, 155}}, 
+  {{191,  35, 156, 156}}, {{188,  33, 157, 157}}, {{185,  39, 158, 158}}, 
+  {{186,  37, 159, 159}}, {{251,  91, 160, 160}}, {{248,  89, 161, 161}}, 
+  {{253,  95, 162, 162}}, {{254,  93, 163, 163}}, {{247,  83, 164, 164}}, 
+  {{244,  81, 165, 165}}, {{241,  87, 166, 166}}, {{242,  85, 167, 167}}, 
+  {{227,  75, 168, 168}}, {{224,  73, 169, 169}}, {{229,  79, 170, 170}}, 
+  {{230,  77, 171, 171}}, {{239,  67, 172, 172}}, {{236,  65, 173, 173}}, 
+  {{233,  71, 174, 174}}, {{234,  69, 175, 175}}, {{203, 123, 176, 176}}, 
+  {{200, 121, 177, 177}}, {{205, 127, 178, 178}}, {{206, 125, 179, 179}}, 
+  {{199, 115, 180, 180}}, {{196, 113, 181, 181}}, {{193, 119, 182, 182}}, 
+  {{194, 117, 183, 183}}, {{211, 107, 184, 184}}, {{208, 105, 185, 185}}, 
+  {{213, 111, 186, 186}}, {{214, 109, 187, 187}}, {{223,  99, 188, 188}}, 
+  {{220,  97, 189, 189}}, {{217, 103, 190, 190}}, {{218, 101, 191, 191}}, 
+  {{ 91, 155, 192, 192}}, {{ 88, 153, 193, 193}}, {{ 93, 159, 194, 194}}, 
+  {{ 94, 157, 195, 195}}, {{ 87, 147, 196, 196}}, {{ 84, 145, 197, 197}}, 
+  {{ 81, 151, 198, 198}}, {{ 82, 149, 199, 199}}, {{ 67, 139, 200, 200}}, 
+  {{ 64, 137, 201, 201}}, {{ 69, 143, 202, 202}}, {{ 70, 141, 203, 203}}, 
+  {{ 79, 131, 204, 204}}, {{ 76, 129, 205, 205}}, {{ 73, 135, 206, 206}}, 
+  {{ 74, 133, 207, 207}}, {{107, 187, 208, 208}}, {{104, 185, 209, 209}}, 
+  {{109, 191, 210, 210}}, {{110, 189, 211, 211}}, {{103, 179, 212, 212}}, 
+  {{100, 177, 213, 213}}, {{ 97, 183, 214, 214}}, {{ 98, 181, 215, 215}}, 
+  {{115, 171, 216, 216}}, {{112, 169, 217, 217}}, {{117, 175, 218, 218}}, 
+  {{118, 173, 219, 219}}, {{127, 163, 220, 220}}, {{124, 161, 221, 221}}, 
+  {{121, 167, 222, 222}}, {{122, 165, 223, 223}}, {{ 59, 219, 224, 224}}, 
+  {{ 56, 217, 225, 225}}, {{ 61, 223, 226, 226}}, {{ 62, 221, 227, 227}}, 
+  {{ 55, 211, 228, 228}}, {{ 52, 209, 229, 229}}, {{ 49, 215, 230, 230}}, 
+  {{ 50, 213, 231, 231}}, {{ 35, 203, 232, 232}}, {{ 32, 201, 233, 233}}, 
+  {{ 37, 207, 234, 234}}, {{ 38, 205, 235, 235}}, {{ 47, 195, 236, 236}}, 
+  {{ 44, 193, 237, 237}}, {{ 41, 199, 238, 238}}, {{ 42, 197, 239, 239}}, 
+  {{ 11, 251, 240, 240}}, {{  8, 249, 241, 241}}, {{ 13, 255, 242, 242}}, 
+  {{ 14, 253, 243, 243}}, {{  7, 243, 244, 244}}, {{  4, 241, 245, 245}}, 
+  {{  1, 247, 246, 246}}, {{  2, 245, 247, 247}}, {{ 19, 235, 248, 248}}, 
+  {{ 16, 233, 249, 249}}, {{ 21, 239, 250, 250}}, {{ 22, 237, 251, 251}}, 
+  {{ 31, 227, 252, 252}}, {{ 28, 225, 253, 253}}, {{ 25, 231, 254, 254}}, 
+  {{ 26, 229, 255, 255}}, 
+ },
+ {
+  {{  0,   0,   0,   0}}, {{  1,   3,   2,   1}}, {{  2,   6,   4,   2}}, 
+  {{  3,   5,   6,   3}}, {{  4,  12,   8,   4}}, {{  5,  15,  10,   5}}, 
+  {{  6,  10,  12,   6}}, {{  7,   9,  14,   7}}, {{  8,  24,  16,   8}}, 
+  {{  9,  27,  18,   9}}, {{ 10,  30,  20,  10}}, {{ 11,  29,  22,  11}}, 
+  {{ 12,  20,  24,  12}}, {{ 13,  23,  26,  13}}, {{ 14,  18,  28,  14}}, 
+  {{ 15,  17,  30,  15}}, {{ 16,  48,  32,  16}}, {{ 17,  51,  34,  17}}, 
+  {{ 18,  54,  36,  18}}, {{ 19,  53,  38,  19}}, {{ 20,  60,  40,  20}}, 
+  {{ 21,  63,  42,  21}}, {{ 22,  58,  44,  22}}, {{ 23,  57,  46,  23}}, 
+  {{ 24,  40,  48,  24}}, {{ 25,  43,  50,  25}}, {{ 26,  46,  52,  26}}, 
+  {{ 27,  45,  54,  27}}, {{ 28,  36,  56,  28}}, {{ 29,  39,  58,  29}}, 
+  {{ 30,  34,  60,  30}}, {{ 31,  33,  62,  31}}, {{ 32,  96,  64,  32}}, 
+  {{ 33,  99,  66,  33}}, {{ 34, 102,  68,  34}}, {{ 35, 101,  70,  35}}, 
+  {{ 36, 108,  72,  36}}, {{ 37, 111,  74,  37}}, {{ 38, 106,  76,  38}}, 
+  {{ 39, 105,  78,  39}}, {{ 40, 120,  80,  40}}, {{ 41, 123,  82,  41}}, 
+  {{ 42, 126,  84,  42}}, {{ 43, 125,  86,  43}}, {{ 44, 116,  88,  44}}, 
+  {{ 45, 119,  90,  45}}, {{ 46, 114,  92,  46}}, {{ 47, 113,  94,  47}}, 
+  {{ 48,  80,  96,  48}}, {{ 49,  83,  98,  49}}, {{ 50,  86, 100,  50}}, 
+  {{ 51,  85, 102,  51}}, {{ 52,  92, 104,  52}}, {{ 53,  95, 106,  53}}, 
+  {{ 54,  90, 108,  54}}, {{ 55,  89, 110,  55}}, {{ 56,  72, 112,  56}}, 
+  {{ 57,  75, 114,  57}}, {{ 58,  78, 116,  58}}, {{ 59,  77, 118,  59}}, 
+  {{ 60,  68, 120,  60}}, {{ 61,  71, 122,  61}}, {{ 62,  66, 124,  62}}, 
+  {{ 63,  65, 126,  63}}, {{ 64, 192, 128,  64}}, {{ 65, 195, 130,  65}}, 
+  {{ 66, 198, 132,  66}}, {{ 67, 197, 134,  67}}, {{ 68, 204, 136,  68}}, 
+  {{ 69, 207, 138,  69}}, {{ 70, 202, 140,  70}}, {{ 71, 201, 142,  71}}, 
+  {{ 72, 216, 144,  72}}, {{ 73, 219, 146,  73}}, {{ 74, 222, 148,  74}}, 
+  {{ 75, 221, 150,  75}}, {{ 76, 212, 152,  76}}, {{ 77, 215, 154,  77}}, 
+  {{ 78, 210, 156,  78}}, {{ 79, 209, 158,  79}}, {{ 80, 240, 160,  80}}, 
+  {{ 81, 243, 162,  81}}, {{ 82, 246, 164,  82}}, {{ 83, 245, 166,  83}}, 
+  {{ 84, 252, 168,  84}}, {{ 85, 255, 170,  85}}, {{ 86, 250, 172,  86}}, 
+  {{ 87, 249, 174,  87}}, {{ 88, 232, 176,  88}}, {{ 89, 235, 178,  89}}, 
+  {{ 90, 238, 180,  90}}, {{ 91, 237, 182,  91}}, {{ 92, 228, 184,  92}}, 
+  {{ 93, 231, 186,  93}}, {{ 94, 226, 188,  94}}, {{ 95, 225, 190,  95}}, 
+  {{ 96, 160, 192,  96}}, {{ 97, 163, 194,  97}}, {{ 98, 166, 196,  98}}, 
+  {{ 99, 165, 198,  99}}, {{100, 172, 200, 100}}, {{101, 175, 202, 101}}, 
+  {{102, 170, 204, 102}}, {{103, 169, 206, 103}}, {{104, 184, 208, 104}}, 
+  {{105, 187, 210, 105}}, {{106, 190, 212, 106}}, {{107, 189, 214, 107}}, 
+  {{108, 180, 216, 108}}, {{109, 183, 218, 109}}, {{110, 178, 220, 110}}, 
+  {{111, 177, 222, 111}}, {{112, 144, 224, 112}}, {{113, 147, 226, 113}}, 
+  {{114, 150, 228, 114}}, {{115, 149, 230, 115}}, {{116, 156, 232, 116}}, 
+  {{117, 159, 234, 117}}, {{118, 154, 236, 118}}, {{119, 153, 238, 119}}, 
+  {{120, 136, 240, 120}}, {{121, 139, 242, 121}}, {{122, 142, 244, 122}}, 
+  {{123, 141, 246, 123}}, {{124, 132, 248, 124}}, {{125, 135, 250, 125}}, 
+  {{126, 130, 252, 126}}, {{127, 129, 254, 127}}, {{128, 155,  27, 128}}, 
+  {{129, 152,  25, 129}}, {{130, 157,  31, 130}}, {{131, 158,  29, 131}}, 
+  {{132, 151,  19, 132}}, {{133, 148,  17, 133}}, {{134, 145,  23, 134}}, 
+  {{135, 146,  21, 135}}, {{136, 131,  11, 136}}, {{137, 128,   9, 137}}, 
+  {{138, 133,  15, 138}}, {{139, 134,  13, 139}}, {{140, 143,   3, 140}}, 
+  {{141, 140,   1, 141}}, {{142, 137,   7, 142}}, {{143, 138,   5, 143}}, 
+  {{144, 171,  59, 144}}, {{145, 168,  57, 145}}, {{146, 173,  63, 146}}, 
+  {{147, 174,  61, 147}}, {{148, 167,  51, 148}}, {{149, 164,  49, 149}}, 
+  {{150, 161,  55, 150}}, {{151, 162,  53, 151}}, {{152, 179,  43, 152}}, 
+  {{153, 176,  41, 153}}, {{154, 181,  47, 154}}, {{155, 182,  45, 155}}, 
+  {{156, 191,  35, 156}}, {{157, 188,  33, 157}}, {{158, 185,  39, 158}}, 
+  {{159, 186,  37, 159}}, {{160, 251,  91, 160}}, {{161, 248,  89, 161}}, 
+  {{162, 253,  95, 162}}, {{163, 254,  93, 163}}, {{164, 247,  83, 164}}, 
+  {{165, 244,  81, 165}}, {{166, 241,  87, 166}}, {{167, 242,  85, 167}}, 
+  {{168, 227,  75, 168}}, {{169, 224,  73, 169}}, {{170, 229,  79, 170}}, 
+  {{171, 230,  77, 171}}, {{172, 239,  67, 172}}, {{173, 236,  65, 173}}, 
+  {{174, 233,  71, 174}}, {{175, 234,  69, 175}}, {{176, 203, 123, 176}}, 
+  {{177, 200, 121, 177}}, {{178, 205, 127, 178}}, {{179, 206, 125, 179}}, 
+  {{180, 199, 115, 180}}, {{181, 196, 113, 181}}, {{182, 193, 119, 182}}, 
+  {{183, 194, 117, 183}}, {{184, 211, 107, 184}}, {{185, 208, 105, 185}}, 
+  {{186, 213, 111, 186}}, {{187, 214, 109, 187}}, {{188, 223,  99, 188}}, 
+  {{189, 220,  97, 189}}, {{190, 217, 103, 190}}, {{191, 218, 101, 191}}, 
+  {{192,  91, 155, 192}}, {{193,  88, 153, 193}}, {{194,  93, 159, 194}}, 
+  {{195,  94, 157, 195}}, {{196,  87, 147, 196}}, {{197,  84, 145, 197}}, 
+  {{198,  81, 151, 198}}, {{199,  82, 149, 199}}, {{200,  67, 139, 200}}, 
+  {{201,  64, 137, 201}}, {{202,  69, 143, 202}}, {{203,  70, 141, 203}}, 
+  {{204,  79, 131, 204}}, {{205,  76, 129, 205}}, {{206,  73, 135, 206}}, 
+  {{207,  74, 133, 207}}, {{208, 107, 187, 208}}, {{209, 104, 185, 209}}, 
+  {{210, 109, 191, 210}}, {{211, 110, 189, 211}}, {{212, 103, 179, 212}}, 
+  {{213, 100, 177, 213}}, {{214,  97, 183, 214}}, {{215,  98, 181, 215}}, 
+  {{216, 115, 171, 216}}, {{217, 112, 169, 217}}, {{218, 117, 175, 218}}, 
+  {{219, 118, 173, 219}}, {{220, 127, 163, 220}}, {{221, 124, 161, 221}}, 
+  {{222, 121, 167, 222}}, {{223, 122, 165, 223}}, {{224,  59, 219, 224}}, 
+  {{225,  56, 217, 225}}, {{226,  61, 223, 226}}, {{227,  62, 221, 227}}, 
+  {{228,  55, 211, 228}}, {{229,  52, 209, 229}}, {{230,  49, 215, 230}}, 
+  {{231,  50, 213, 231}}, {{232,  35, 203, 232}}, {{233,  32, 201, 233}}, 
+  {{234,  37, 207, 234}}, {{235,  38, 205, 235}}, {{236,  47, 195, 236}}, 
+  {{237,  44, 193, 237}}, {{238,  41, 199, 238}}, {{239,  42, 197, 239}}, 
+  {{240,  11, 251, 240}}, {{241,   8, 249, 241}}, {{242,  13, 255, 242}}, 
+  {{243,  14, 253, 243}}, {{244,   7, 243, 244}}, {{245,   4, 241, 245}}, 
+  {{246,   1, 247, 246}}, {{247,   2, 245, 247}}, {{248,  19, 235, 248}}, 
+  {{249,  16, 233, 249}}, {{250,  21, 239, 250}}, {{251,  22, 237, 251}}, 
+  {{252,  31, 227, 252}}, {{253,  28, 225, 253}}, {{254,  25, 231, 254}}, 
+  {{255,  26, 229, 255}}, 
+ },
+ {
+  {{  0,   0,   0,   0}}, {{  1,   1,   3,   2}}, {{  2,   2,   6,   4}}, 
+  {{  3,   3,   5,   6}}, {{  4,   4,  12,   8}}, {{  5,   5,  15,  10}}, 
+  {{  6,   6,  10,  12}}, {{  7,   7,   9,  14}}, {{  8,   8,  24,  16}}, 
+  {{  9,   9,  27,  18}}, {{ 10,  10,  30,  20}}, {{ 11,  11,  29,  22}}, 
+  {{ 12,  12,  20,  24}}, {{ 13,  13,  23,  26}}, {{ 14,  14,  18,  28}}, 
+  {{ 15,  15,  17,  30}}, {{ 16,  16,  48,  32}}, {{ 17,  17,  51,  34}}, 
+  {{ 18,  18,  54,  36}}, {{ 19,  19,  53,  38}}, {{ 20,  20,  60,  40}}, 
+  {{ 21,  21,  63,  42}}, {{ 22,  22,  58,  44}}, {{ 23,  23,  57,  46}}, 
+  {{ 24,  24,  40,  48}}, {{ 25,  25,  43,  50}}, {{ 26,  26,  46,  52}}, 
+  {{ 27,  27,  45,  54}}, {{ 28,  28,  36,  56}}, {{ 29,  29,  39,  58}}, 
+  {{ 30,  30,  34,  60}}, {{ 31,  31,  33,  62}}, {{ 32,  32,  96,  64}}, 
+  {{ 33,  33,  99,  66}}, {{ 34,  34, 102,  68}}, {{ 35,  35, 101,  70}}, 
+  {{ 36,  36, 108,  72}}, {{ 37,  37, 111,  74}}, {{ 38,  38, 106,  76}}, 
+  {{ 39,  39, 105,  78}}, {{ 40,  40, 120,  80}}, {{ 41,  41, 123,  82}}, 
+  {{ 42,  42, 126,  84}}, {{ 43,  43, 125,  86}}, {{ 44,  44, 116,  88}}, 
+  {{ 45,  45, 119,  90}}, {{ 46,  46, 114,  92}}, {{ 47,  47, 113,  94}}, 
+  {{ 48,  48,  80,  96}}, {{ 49,  49,  83,  98}}, {{ 50,  50,  86, 100}}, 
+  {{ 51,  51,  85, 102}}, {{ 52,  52,  92, 104}}, {{ 53,  53,  95, 106}}, 
+  {{ 54,  54,  90, 108}}, {{ 55,  55,  89, 110}}, {{ 56,  56,  72, 112}}, 
+  {{ 57,  57,  75, 114}}, {{ 58,  58,  78, 116}}, {{ 59,  59,  77, 118}}, 
+  {{ 60,  60,  68, 120}}, {{ 61,  61,  71, 122}}, {{ 62,  62,  66, 124}}, 
+  {{ 63,  63,  65, 126}}, {{ 64,  64, 192, 128}}, {{ 65,  65, 195, 130}}, 
+  {{ 66,  66, 198, 132}}, {{ 67,  67, 197, 134}}, {{ 68,  68, 204, 136}}, 
+  {{ 69,  69, 207, 138}}, {{ 70,  70, 202, 140}}, {{ 71,  71, 201, 142}}, 
+  {{ 72,  72, 216, 144}}, {{ 73,  73, 219, 146}}, {{ 74,  74, 222, 148}}, 
+  {{ 75,  75, 221, 150}}, {{ 76,  76, 212, 152}}, {{ 77,  77, 215, 154}}, 
+  {{ 78,  78, 210, 156}}, {{ 79,  79, 209, 158}}, {{ 80,  80, 240, 160}}, 
+  {{ 81,  81, 243, 162}}, {{ 82,  82, 246, 164}}, {{ 83,  83, 245, 166}}, 
+  {{ 84,  84, 252, 168}}, {{ 85,  85, 255, 170}}, {{ 86,  86, 250, 172}}, 
+  {{ 87,  87, 249, 174}}, {{ 88,  88, 232, 176}}, {{ 89,  89, 235, 178}}, 
+  {{ 90,  90, 238, 180}}, {{ 91,  91, 237, 182}}, {{ 92,  92, 228, 184}}, 
+  {{ 93,  93, 231, 186}}, {{ 94,  94, 226, 188}}, {{ 95,  95, 225, 190}}, 
+  {{ 96,  96, 160, 192}}, {{ 97,  97, 163, 194}}, {{ 98,  98, 166, 196}}, 
+  {{ 99,  99, 165, 198}}, {{100, 100, 172, 200}}, {{101, 101, 175, 202}}, 
+  {{102, 102, 170, 204}}, {{103, 103, 169, 206}}, {{104, 104, 184, 208}}, 
+  {{105, 105, 187, 210}}, {{106, 106, 190, 212}}, {{107, 107, 189, 214}}, 
+  {{108, 108, 180, 216}}, {{109, 109, 183, 218}}, {{110, 110, 178, 220}}, 
+  {{111, 111, 177, 222}}, {{112, 112, 144, 224}}, {{113, 113, 147, 226}}, 
+  {{114, 114, 150, 228}}, {{115, 115, 149, 230}}, {{116, 116, 156, 232}}, 
+  {{117, 117, 159, 234}}, {{118, 118, 154, 236}}, {{119, 119, 153, 238}}, 
+  {{120, 120, 136, 240}}, {{121, 121, 139, 242}}, {{122, 122, 142, 244}}, 
+  {{123, 123, 141, 246}}, {{124, 124, 132, 248}}, {{125, 125, 135, 250}}, 
+  {{126, 126, 130, 252}}, {{127, 127, 129, 254}}, {{128, 128, 155,  27}}, 
+  {{129, 129, 152,  25}}, {{130, 130, 157,  31}}, {{131, 131, 158,  29}}, 
+  {{132, 132, 151,  19}}, {{133, 133, 148,  17}}, {{134, 134, 145,  23}}, 
+  {{135, 135, 146,  21}}, {{136, 136, 131,  11}}, {{137, 137, 128,   9}}, 
+  {{138, 138, 133,  15}}, {{139, 139, 134,  13}}, {{140, 140, 143,   3}}, 
+  {{141, 141, 140,   1}}, {{142, 142, 137,   7}}, {{143, 143, 138,   5}}, 
+  {{144, 144, 171,  59}}, {{145, 145, 168,  57}}, {{146, 146, 173,  63}}, 
+  {{147, 147, 174,  61}}, {{148, 148, 167,  51}}, {{149, 149, 164,  49}}, 
+  {{150, 150, 161,  55}}, {{151, 151, 162,  53}}, {{152, 152, 179,  43}}, 
+  {{153, 153, 176,  41}}, {{154, 154, 181,  47}}, {{155, 155, 182,  45}}, 
+  {{156, 156, 191,  35}}, {{157, 157, 188,  33}}, {{158, 158, 185,  39}}, 
+  {{159, 159, 186,  37}}, {{160, 160, 251,  91}}, {{161, 161, 248,  89}}, 
+  {{162, 162, 253,  95}}, {{163, 163, 254,  93}}, {{164, 164, 247,  83}}, 
+  {{165, 165, 244,  81}}, {{166, 166, 241,  87}}, {{167, 167, 242,  85}}, 
+  {{168, 168, 227,  75}}, {{169, 169, 224,  73}}, {{170, 170, 229,  79}}, 
+  {{171, 171, 230,  77}}, {{172, 172, 239,  67}}, {{173, 173, 236,  65}}, 
+  {{174, 174, 233,  71}}, {{175, 175, 234,  69}}, {{176, 176, 203, 123}}, 
+  {{177, 177, 200, 121}}, {{178, 178, 205, 127}}, {{179, 179, 206, 125}}, 
+  {{180, 180, 199, 115}}, {{181, 181, 196, 113}}, {{182, 182, 193, 119}}, 
+  {{183, 183, 194, 117}}, {{184, 184, 211, 107}}, {{185, 185, 208, 105}}, 
+  {{186, 186, 213, 111}}, {{187, 187, 214, 109}}, {{188, 188, 223,  99}}, 
+  {{189, 189, 220,  97}}, {{190, 190, 217, 103}}, {{191, 191, 218, 101}}, 
+  {{192, 192,  91, 155}}, {{193, 193,  88, 153}}, {{194, 194,  93, 159}}, 
+  {{195, 195,  94, 157}}, {{196, 196,  87, 147}}, {{197, 197,  84, 145}}, 
+  {{198, 198,  81, 151}}, {{199, 199,  82, 149}}, {{200, 200,  67, 139}}, 
+  {{201, 201,  64, 137}}, {{202, 202,  69, 143}}, {{203, 203,  70, 141}}, 
+  {{204, 204,  79, 131}}, {{205, 205,  76, 129}}, {{206, 206,  73, 135}}, 
+  {{207, 207,  74, 133}}, {{208, 208, 107, 187}}, {{209, 209, 104, 185}}, 
+  {{210, 210, 109, 191}}, {{211, 211, 110, 189}}, {{212, 212, 103, 179}}, 
+  {{213, 213, 100, 177}}, {{214, 214,  97, 183}}, {{215, 215,  98, 181}}, 
+  {{216, 216, 115, 171}}, {{217, 217, 112, 169}}, {{218, 218, 117, 175}}, 
+  {{219, 219, 118, 173}}, {{220, 220, 127, 163}}, {{221, 221, 124, 161}}, 
+  {{222, 222, 121, 167}}, {{223, 223, 122, 165}}, {{224, 224,  59, 219}}, 
+  {{225, 225,  56, 217}}, {{226, 226,  61, 223}}, {{227, 227,  62, 221}}, 
+  {{228, 228,  55, 211}}, {{229, 229,  52, 209}}, {{230, 230,  49, 215}}, 
+  {{231, 231,  50, 213}}, {{232, 232,  35, 203}}, {{233, 233,  32, 201}}, 
+  {{234, 234,  37, 207}}, {{235, 235,  38, 205}}, {{236, 236,  47, 195}}, 
+  {{237, 237,  44, 193}}, {{238, 238,  41, 199}}, {{239, 239,  42, 197}}, 
+  {{240, 240,  11, 251}}, {{241, 241,   8, 249}}, {{242, 242,  13, 255}}, 
+  {{243, 243,  14, 253}}, {{244, 244,   7, 243}}, {{245, 245,   4, 241}}, 
+  {{246, 246,   1, 247}}, {{247, 247,   2, 245}}, {{248, 248,  19, 235}}, 
+  {{249, 249,  16, 233}}, {{250, 250,  21, 239}}, {{251, 251,  22, 237}}, 
+  {{252, 252,  31, 227}}, {{253, 253,  28, 225}}, {{254, 254,  25, 231}}, 
+  {{255, 255,  26, 229}}, 
+ },
+};
+
+const word8x4 M1[4][256] = {
+ {
+  {{  0,   0,   0,   0}}, {{ 14,   9,  13,  11}}, {{ 28,  18,  26,  22}}, 
+  {{ 18,  27,  23,  29}}, {{ 56,  36,  52,  44}}, {{ 54,  45,  57,  39}}, 
+  {{ 36,  54,  46,  58}}, {{ 42,  63,  35,  49}}, {{112,  72, 104,  88}}, 
+  {{126,  65, 101,  83}}, {{108,  90, 114,  78}}, {{ 98,  83, 127,  69}}, 
+  {{ 72, 108,  92, 116}}, {{ 70, 101,  81, 127}}, {{ 84, 126,  70,  98}}, 
+  {{ 90, 119,  75, 105}}, {{224, 144, 208, 176}}, {{238, 153, 221, 187}}, 
+  {{252, 130, 202, 166}}, {{242, 139, 199, 173}}, {{216, 180, 228, 156}}, 
+  {{214, 189, 233, 151}}, {{196, 166, 254, 138}}, {{202, 175, 243, 129}}, 
+  {{144, 216, 184, 232}}, {{158, 209, 181, 227}}, {{140, 202, 162, 254}}, 
+  {{130, 195, 175, 245}}, {{168, 252, 140, 196}}, {{166, 245, 129, 207}}, 
+  {{180, 238, 150, 210}}, {{186, 231, 155, 217}}, {{219,  59, 187, 123}}, 
+  {{213,  50, 182, 112}}, {{199,  41, 161, 109}}, {{201,  32, 172, 102}}, 
+  {{227,  31, 143,  87}}, {{237,  22, 130,  92}}, {{255,  13, 149,  65}}, 
+  {{241,   4, 152,  74}}, {{171, 115, 211,  35}}, {{165, 122, 222,  40}}, 
+  {{183,  97, 201,  53}}, {{185, 104, 196,  62}}, {{147,  87, 231,  15}}, 
+  {{157,  94, 234,   4}}, {{143,  69, 253,  25}}, {{129,  76, 240,  18}}, 
+  {{ 59, 171, 107, 203}}, {{ 53, 162, 102, 192}}, {{ 39, 185, 113, 221}}, 
+  {{ 41, 176, 124, 214}}, {{  3, 143,  95, 231}}, {{ 13, 134,  82, 236}}, 
+  {{ 31, 157,  69, 241}}, {{ 17, 148,  72, 250}}, {{ 75, 227,   3, 147}}, 
+  {{ 69, 234,  14, 152}}, {{ 87, 241,  25, 133}}, {{ 89, 248,  20, 142}}, 
+  {{115, 199,  55, 191}}, {{125, 206,  58, 180}}, {{111, 213,  45, 169}}, 
+  {{ 97, 220,  32, 162}}, {{173, 118, 109, 246}}, {{163, 127,  96, 253}}, 
+  {{177, 100, 119, 224}}, {{191, 109, 122, 235}}, {{149,  82,  89, 218}}, 
+  {{155,  91,  84, 209}}, {{137,  64,  67, 204}}, {{135,  73,  78, 199}}, 
+  {{221,  62,   5, 174}}, {{211,  55,   8, 165}}, {{193,  44,  31, 184}}, 
+  {{207,  37,  18, 179}}, {{229,  26,  49, 130}}, {{235,  19,  60, 137}}, 
+  {{249,   8,  43, 148}}, {{247,   1,  38, 159}}, {{ 77, 230, 189,  70}}, 
+  {{ 67, 239, 176,  77}}, {{ 81, 244, 167,  80}}, {{ 95, 253, 170,  91}}, 
+  {{117, 194, 137, 106}}, {{123, 203, 132,  97}}, {{105, 208, 147, 124}}, 
+  {{103, 217, 158, 119}}, {{ 61, 174, 213,  30}}, {{ 51, 167, 216,  21}}, 
+  {{ 33, 188, 207,   8}}, {{ 47, 181, 194,   3}}, {{  5, 138, 225,  50}}, 
+  {{ 11, 131, 236,  57}}, {{ 25, 152, 251,  36}}, {{ 23, 145, 246,  47}}, 
+  {{118,  77, 214, 141}}, {{120,  68, 219, 134}}, {{106,  95, 204, 155}}, 
+  {{100,  86, 193, 144}}, {{ 78, 105, 226, 161}}, {{ 64,  96, 239, 170}}, 
+  {{ 82, 123, 248, 183}}, {{ 92, 114, 245, 188}}, {{  6,   5, 190, 213}}, 
+  {{  8,  12, 179, 222}}, {{ 26,  23, 164, 195}}, {{ 20,  30, 169, 200}}, 
+  {{ 62,  33, 138, 249}}, {{ 48,  40, 135, 242}}, {{ 34,  51, 144, 239}}, 
+  {{ 44,  58, 157, 228}}, {{150, 221,   6,  61}}, {{152, 212,  11,  54}}, 
+  {{138, 207,  28,  43}}, {{132, 198,  17,  32}}, {{174, 249,  50,  17}}, 
+  {{160, 240,  63,  26}}, {{178, 235,  40,   7}}, {{188, 226,  37,  12}}, 
+  {{230, 149, 110, 101}}, {{232, 156,  99, 110}}, {{250, 135, 116, 115}}, 
+  {{244, 142, 121, 120}}, {{222, 177,  90,  73}}, {{208, 184,  87,  66}}, 
+  {{194, 163,  64,  95}}, {{204, 170,  77,  84}}, {{ 65, 236, 218, 247}}, 
+  {{ 79, 229, 215, 252}}, {{ 93, 254, 192, 225}}, {{ 83, 247, 205, 234}}, 
+  {{121, 200, 238, 219}}, {{119, 193, 227, 208}}, {{101, 218, 244, 205}}, 
+  {{107, 211, 249, 198}}, {{ 49, 164, 178, 175}}, {{ 63, 173, 191, 164}}, 
+  {{ 45, 182, 168, 185}}, {{ 35, 191, 165, 178}}, {{  9, 128, 134, 131}}, 
+  {{  7, 137, 139, 136}}, {{ 21, 146, 156, 149}}, {{ 27, 155, 145, 158}}, 
+  {{161, 124,  10,  71}}, {{175, 117,   7,  76}}, {{189, 110,  16,  81}}, 
+  {{179, 103,  29,  90}}, {{153,  88,  62, 107}}, {{151,  81,  51,  96}}, 
+  {{133,  74,  36, 125}}, {{139,  67,  41, 118}}, {{209,  52,  98,  31}}, 
+  {{223,  61, 111,  20}}, {{205,  38, 120,   9}}, {{195,  47, 117,   2}}, 
+  {{233,  16,  86,  51}}, {{231,  25,  91,  56}}, {{245,   2,  76,  37}}, 
+  {{251,  11,  65,  46}}, {{154, 215,  97, 140}}, {{148, 222, 108, 135}}, 
+  {{134, 197, 123, 154}}, {{136, 204, 118, 145}}, {{162, 243,  85, 160}}, 
+  {{172, 250,  88, 171}}, {{190, 225,  79, 182}}, {{176, 232,  66, 189}}, 
+  {{234, 159,   9, 212}}, {{228, 150,   4, 223}}, {{246, 141,  19, 194}}, 
+  {{248, 132,  30, 201}}, {{210, 187,  61, 248}}, {{220, 178,  48, 243}}, 
+  {{206, 169,  39, 238}}, {{192, 160,  42, 229}}, {{122,  71, 177,  60}}, 
+  {{116,  78, 188,  55}}, {{102,  85, 171,  42}}, {{104,  92, 166,  33}}, 
+  {{ 66,  99, 133,  16}}, {{ 76, 106, 136,  27}}, {{ 94, 113, 159,   6}}, 
+  {{ 80, 120, 146,  13}}, {{ 10,  15, 217, 100}}, {{  4,   6, 212, 111}}, 
+  {{ 22,  29, 195, 114}}, {{ 24,  20, 206, 121}}, {{ 50,  43, 237,  72}}, 
+  {{ 60,  34, 224,  67}}, {{ 46,  57, 247,  94}}, {{ 32,  48, 250,  85}}, 
+  {{236, 154, 183,   1}}, {{226, 147, 186,  10}}, {{240, 136, 173,  23}}, 
+  {{254, 129, 160,  28}}, {{212, 190, 131,  45}}, {{218, 183, 142,  38}}, 
+  {{200, 172, 153,  59}}, {{198, 165, 148,  48}}, {{156, 210, 223,  89}}, 
+  {{146, 219, 210,  82}}, {{128, 192, 197,  79}}, {{142, 201, 200,  68}}, 
+  {{164, 246, 235, 117}}, {{170, 255, 230, 126}}, {{184, 228, 241,  99}}, 
+  {{182, 237, 252, 104}}, {{ 12,  10, 103, 177}}, {{  2,   3, 106, 186}}, 
+  {{ 16,  24, 125, 167}}, {{ 30,  17, 112, 172}}, {{ 52,  46,  83, 157}}, 
+  {{ 58,  39,  94, 150}}, {{ 40,  60,  73, 139}}, {{ 38,  53,  68, 128}}, 
+  {{124,  66,  15, 233}}, {{114,  75,   2, 226}}, {{ 96,  80,  21, 255}}, 
+  {{110,  89,  24, 244}}, {{ 68, 102,  59, 197}}, {{ 74, 111,  54, 206}}, 
+  {{ 88, 116,  33, 211}}, {{ 86, 125,  44, 216}}, {{ 55, 161,  12, 122}}, 
+  {{ 57, 168,   1, 113}}, {{ 43, 179,  22, 108}}, {{ 37, 186,  27, 103}}, 
+  {{ 15, 133,  56,  86}}, {{  1, 140,  53,  93}}, {{ 19, 151,  34,  64}}, 
+  {{ 29, 158,  47,  75}}, {{ 71, 233, 100,  34}}, {{ 73, 224, 105,  41}}, 
+  {{ 91, 251, 126,  52}}, {{ 85, 242, 115,  63}}, {{127, 205,  80,  14}}, 
+  {{113, 196,  93,   5}}, {{ 99, 223,  74,  24}}, {{109, 214,  71,  19}}, 
+  {{215,  49, 220, 202}}, {{217,  56, 209, 193}}, {{203,  35, 198, 220}}, 
+  {{197,  42, 203, 215}}, {{239,  21, 232, 230}}, {{225,  28, 229, 237}}, 
+  {{243,   7, 242, 240}}, {{253,  14, 255, 251}}, {{167, 121, 180, 146}}, 
+  {{169, 112, 185, 153}}, {{187, 107, 174, 132}}, {{181,  98, 163, 143}}, 
+  {{159,  93, 128, 190}}, {{145,  84, 141, 181}}, {{131,  79, 154, 168}}, 
+  {{141,  70, 151, 163}}, 
+ },
+ {
+  {{  0,   0,   0,   0}}, {{ 11,  14,   9,  13}}, {{ 22,  28,  18,  26}}, 
+  {{ 29,  18,  27,  23}}, {{ 44,  56,  36,  52}}, {{ 39,  54,  45,  57}}, 
+  {{ 58,  36,  54,  46}}, {{ 49,  42,  63,  35}}, {{ 88, 112,  72, 104}}, 
+  {{ 83, 126,  65, 101}}, {{ 78, 108,  90, 114}}, {{ 69,  98,  83, 127}}, 
+  {{116,  72, 108,  92}}, {{127,  70, 101,  81}}, {{ 98,  84, 126,  70}}, 
+  {{105,  90, 119,  75}}, {{176, 224, 144, 208}}, {{187, 238, 153, 221}}, 
+  {{166, 252, 130, 202}}, {{173, 242, 139, 199}}, {{156, 216, 180, 228}}, 
+  {{151, 214, 189, 233}}, {{138, 196, 166, 254}}, {{129, 202, 175, 243}}, 
+  {{232, 144, 216, 184}}, {{227, 158, 209, 181}}, {{254, 140, 202, 162}}, 
+  {{245, 130, 195, 175}}, {{196, 168, 252, 140}}, {{207, 166, 245, 129}}, 
+  {{210, 180, 238, 150}}, {{217, 186, 231, 155}}, {{123, 219,  59, 187}}, 
+  {{112, 213,  50, 182}}, {{109, 199,  41, 161}}, {{102, 201,  32, 172}}, 
+  {{ 87, 227,  31, 143}}, {{ 92, 237,  22, 130}}, {{ 65, 255,  13, 149}}, 
+  {{ 74, 241,   4, 152}}, {{ 35, 171, 115, 211}}, {{ 40, 165, 122, 222}}, 
+  {{ 53, 183,  97, 201}}, {{ 62, 185, 104, 196}}, {{ 15, 147,  87, 231}}, 
+  {{  4, 157,  94, 234}}, {{ 25, 143,  69, 253}}, {{ 18, 129,  76, 240}}, 
+  {{203,  59, 171, 107}}, {{192,  53, 162, 102}}, {{221,  39, 185, 113}}, 
+  {{214,  41, 176, 124}}, {{231,   3, 143,  95}}, {{236,  13, 134,  82}}, 
+  {{241,  31, 157,  69}}, {{250,  17, 148,  72}}, {{147,  75, 227,   3}}, 
+  {{152,  69, 234,  14}}, {{133,  87, 241,  25}}, {{142,  89, 248,  20}}, 
+  {{191, 115, 199,  55}}, {{180, 125, 206,  58}}, {{169, 111, 213,  45}}, 
+  {{162,  97, 220,  32}}, {{246, 173, 118, 109}}, {{253, 163, 127,  96}}, 
+  {{224, 177, 100, 119}}, {{235, 191, 109, 122}}, {{218, 149,  82,  89}}, 
+  {{209, 155,  91,  84}}, {{204, 137,  64,  67}}, {{199, 135,  73,  78}}, 
+  {{174, 221,  62,   5}}, {{165, 211,  55,   8}}, {{184, 193,  44,  31}}, 
+  {{179, 207,  37,  18}}, {{130, 229,  26,  49}}, {{137, 235,  19,  60}}, 
+  {{148, 249,   8,  43}}, {{159, 247,   1,  38}}, {{ 70,  77, 230, 189}}, 
+  {{ 77,  67, 239, 176}}, {{ 80,  81, 244, 167}}, {{ 91,  95, 253, 170}}, 
+  {{106, 117, 194, 137}}, {{ 97, 123, 203, 132}}, {{124, 105, 208, 147}}, 
+  {{119, 103, 217, 158}}, {{ 30,  61, 174, 213}}, {{ 21,  51, 167, 216}}, 
+  {{  8,  33, 188, 207}}, {{  3,  47, 181, 194}}, {{ 50,   5, 138, 225}}, 
+  {{ 57,  11, 131, 236}}, {{ 36,  25, 152, 251}}, {{ 47,  23, 145, 246}}, 
+  {{141, 118,  77, 214}}, {{134, 120,  68, 219}}, {{155, 106,  95, 204}}, 
+  {{144, 100,  86, 193}}, {{161,  78, 105, 226}}, {{170,  64,  96, 239}}, 
+  {{183,  82, 123, 248}}, {{188,  92, 114, 245}}, {{213,   6,   5, 190}}, 
+  {{222,   8,  12, 179}}, {{195,  26,  23, 164}}, {{200,  20,  30, 169}}, 
+  {{249,  62,  33, 138}}, {{242,  48,  40, 135}}, {{239,  34,  51, 144}}, 
+  {{228,  44,  58, 157}}, {{ 61, 150, 221,   6}}, {{ 54, 152, 212,  11}}, 
+  {{ 43, 138, 207,  28}}, {{ 32, 132, 198,  17}}, {{ 17, 174, 249,  50}}, 
+  {{ 26, 160, 240,  63}}, {{  7, 178, 235,  40}}, {{ 12, 188, 226,  37}}, 
+  {{101, 230, 149, 110}}, {{110, 232, 156,  99}}, {{115, 250, 135, 116}}, 
+  {{120, 244, 142, 121}}, {{ 73, 222, 177,  90}}, {{ 66, 208, 184,  87}}, 
+  {{ 95, 194, 163,  64}}, {{ 84, 204, 170,  77}}, {{247,  65, 236, 218}}, 
+  {{252,  79, 229, 215}}, {{225,  93, 254, 192}}, {{234,  83, 247, 205}}, 
+  {{219, 121, 200, 238}}, {{208, 119, 193, 227}}, {{205, 101, 218, 244}}, 
+  {{198, 107, 211, 249}}, {{175,  49, 164, 178}}, {{164,  63, 173, 191}}, 
+  {{185,  45, 182, 168}}, {{178,  35, 191, 165}}, {{131,   9, 128, 134}}, 
+  {{136,   7, 137, 139}}, {{149,  21, 146, 156}}, {{158,  27, 155, 145}}, 
+  {{ 71, 161, 124,  10}}, {{ 76, 175, 117,   7}}, {{ 81, 189, 110,  16}}, 
+  {{ 90, 179, 103,  29}}, {{107, 153,  88,  62}}, {{ 96, 151,  81,  51}}, 
+  {{125, 133,  74,  36}}, {{118, 139,  67,  41}}, {{ 31, 209,  52,  98}}, 
+  {{ 20, 223,  61, 111}}, {{  9, 205,  38, 120}}, {{  2, 195,  47, 117}}, 
+  {{ 51, 233,  16,  86}}, {{ 56, 231,  25,  91}}, {{ 37, 245,   2,  76}}, 
+  {{ 46, 251,  11,  65}}, {{140, 154, 215,  97}}, {{135, 148, 222, 108}}, 
+  {{154, 134, 197, 123}}, {{145, 136, 204, 118}}, {{160, 162, 243,  85}}, 
+  {{171, 172, 250,  88}}, {{182, 190, 225,  79}}, {{189, 176, 232,  66}}, 
+  {{212, 234, 159,   9}}, {{223, 228, 150,   4}}, {{194, 246, 141,  19}}, 
+  {{201, 248, 132,  30}}, {{248, 210, 187,  61}}, {{243, 220, 178,  48}}, 
+  {{238, 206, 169,  39}}, {{229, 192, 160,  42}}, {{ 60, 122,  71, 177}}, 
+  {{ 55, 116,  78, 188}}, {{ 42, 102,  85, 171}}, {{ 33, 104,  92, 166}}, 
+  {{ 16,  66,  99, 133}}, {{ 27,  76, 106, 136}}, {{  6,  94, 113, 159}}, 
+  {{ 13,  80, 120, 146}}, {{100,  10,  15, 217}}, {{111,   4,   6, 212}}, 
+  {{114,  22,  29, 195}}, {{121,  24,  20, 206}}, {{ 72,  50,  43, 237}}, 
+  {{ 67,  60,  34, 224}}, {{ 94,  46,  57, 247}}, {{ 85,  32,  48, 250}}, 
+  {{  1, 236, 154, 183}}, {{ 10, 226, 147, 186}}, {{ 23, 240, 136, 173}}, 
+  {{ 28, 254, 129, 160}}, {{ 45, 212, 190, 131}}, {{ 38, 218, 183, 142}}, 
+  {{ 59, 200, 172, 153}}, {{ 48, 198, 165, 148}}, {{ 89, 156, 210, 223}}, 
+  {{ 82, 146, 219, 210}}, {{ 79, 128, 192, 197}}, {{ 68, 142, 201, 200}}, 
+  {{117, 164, 246, 235}}, {{126, 170, 255, 230}}, {{ 99, 184, 228, 241}}, 
+  {{104, 182, 237, 252}}, {{177,  12,  10, 103}}, {{186,   2,   3, 106}}, 
+  {{167,  16,  24, 125}}, {{172,  30,  17, 112}}, {{157,  52,  46,  83}}, 
+  {{150,  58,  39,  94}}, {{139,  40,  60,  73}}, {{128,  38,  53,  68}}, 
+  {{233, 124,  66,  15}}, {{226, 114,  75,   2}}, {{255,  96,  80,  21}}, 
+  {{244, 110,  89,  24}}, {{197,  68, 102,  59}}, {{206,  74, 111,  54}}, 
+  {{211,  88, 116,  33}}, {{216,  86, 125,  44}}, {{122,  55, 161,  12}}, 
+  {{113,  57, 168,   1}}, {{108,  43, 179,  22}}, {{103,  37, 186,  27}}, 
+  {{ 86,  15, 133,  56}}, {{ 93,   1, 140,  53}}, {{ 64,  19, 151,  34}}, 
+  {{ 75,  29, 158,  47}}, {{ 34,  71, 233, 100}}, {{ 41,  73, 224, 105}}, 
+  {{ 52,  91, 251, 126}}, {{ 63,  85, 242, 115}}, {{ 14, 127, 205,  80}}, 
+  {{  5, 113, 196,  93}}, {{ 24,  99, 223,  74}}, {{ 19, 109, 214,  71}}, 
+  {{202, 215,  49, 220}}, {{193, 217,  56, 209}}, {{220, 203,  35, 198}}, 
+  {{215, 197,  42, 203}}, {{230, 239,  21, 232}}, {{237, 225,  28, 229}}, 
+  {{240, 243,   7, 242}}, {{251, 253,  14, 255}}, {{146, 167, 121, 180}}, 
+  {{153, 169, 112, 185}}, {{132, 187, 107, 174}}, {{143, 181,  98, 163}}, 
+  {{190, 159,  93, 128}}, {{181, 145,  84, 141}}, {{168, 131,  79, 154}}, 
+  {{163, 141,  70, 151}}, 
+ },
+ {
+  {{  0,   0,   0,   0}}, {{ 13,  11,  14,   9}}, {{ 26,  22,  28,  18}}, 
+  {{ 23,  29,  18,  27}}, {{ 52,  44,  56,  36}}, {{ 57,  39,  54,  45}}, 
+  {{ 46,  58,  36,  54}}, {{ 35,  49,  42,  63}}, {{104,  88, 112,  72}}, 
+  {{101,  83, 126,  65}}, {{114,  78, 108,  90}}, {{127,  69,  98,  83}}, 
+  {{ 92, 116,  72, 108}}, {{ 81, 127,  70, 101}}, {{ 70,  98,  84, 126}}, 
+  {{ 75, 105,  90, 119}}, {{208, 176, 224, 144}}, {{221, 187, 238, 153}}, 
+  {{202, 166, 252, 130}}, {{199, 173, 242, 139}}, {{228, 156, 216, 180}}, 
+  {{233, 151, 214, 189}}, {{254, 138, 196, 166}}, {{243, 129, 202, 175}}, 
+  {{184, 232, 144, 216}}, {{181, 227, 158, 209}}, {{162, 254, 140, 202}}, 
+  {{175, 245, 130, 195}}, {{140, 196, 168, 252}}, {{129, 207, 166, 245}}, 
+  {{150, 210, 180, 238}}, {{155, 217, 186, 231}}, {{187, 123, 219,  59}}, 
+  {{182, 112, 213,  50}}, {{161, 109, 199,  41}}, {{172, 102, 201,  32}}, 
+  {{143,  87, 227,  31}}, {{130,  92, 237,  22}}, {{149,  65, 255,  13}}, 
+  {{152,  74, 241,   4}}, {{211,  35, 171, 115}}, {{222,  40, 165, 122}}, 
+  {{201,  53, 183,  97}}, {{196,  62, 185, 104}}, {{231,  15, 147,  87}}, 
+  {{234,   4, 157,  94}}, {{253,  25, 143,  69}}, {{240,  18, 129,  76}}, 
+  {{107, 203,  59, 171}}, {{102, 192,  53, 162}}, {{113, 221,  39, 185}}, 
+  {{124, 214,  41, 176}}, {{ 95, 231,   3, 143}}, {{ 82, 236,  13, 134}}, 
+  {{ 69, 241,  31, 157}}, {{ 72, 250,  17, 148}}, {{  3, 147,  75, 227}}, 
+  {{ 14, 152,  69, 234}}, {{ 25, 133,  87, 241}}, {{ 20, 142,  89, 248}}, 
+  {{ 55, 191, 115, 199}}, {{ 58, 180, 125, 206}}, {{ 45, 169, 111, 213}}, 
+  {{ 32, 162,  97, 220}}, {{109, 246, 173, 118}}, {{ 96, 253, 163, 127}}, 
+  {{119, 224, 177, 100}}, {{122, 235, 191, 109}}, {{ 89, 218, 149,  82}}, 
+  {{ 84, 209, 155,  91}}, {{ 67, 204, 137,  64}}, {{ 78, 199, 135,  73}}, 
+  {{  5, 174, 221,  62}}, {{  8, 165, 211,  55}}, {{ 31, 184, 193,  44}}, 
+  {{ 18, 179, 207,  37}}, {{ 49, 130, 229,  26}}, {{ 60, 137, 235,  19}}, 
+  {{ 43, 148, 249,   8}}, {{ 38, 159, 247,   1}}, {{189,  70,  77, 230}}, 
+  {{176,  77,  67, 239}}, {{167,  80,  81, 244}}, {{170,  91,  95, 253}}, 
+  {{137, 106, 117, 194}}, {{132,  97, 123, 203}}, {{147, 124, 105, 208}}, 
+  {{158, 119, 103, 217}}, {{213,  30,  61, 174}}, {{216,  21,  51, 167}}, 
+  {{207,   8,  33, 188}}, {{194,   3,  47, 181}}, {{225,  50,   5, 138}}, 
+  {{236,  57,  11, 131}}, {{251,  36,  25, 152}}, {{246,  47,  23, 145}}, 
+  {{214, 141, 118,  77}}, {{219, 134, 120,  68}}, {{204, 155, 106,  95}}, 
+  {{193, 144, 100,  86}}, {{226, 161,  78, 105}}, {{239, 170,  64,  96}}, 
+  {{248, 183,  82, 123}}, {{245, 188,  92, 114}}, {{190, 213,   6,   5}}, 
+  {{179, 222,   8,  12}}, {{164, 195,  26,  23}}, {{169, 200,  20,  30}}, 
+  {{138, 249,  62,  33}}, {{135, 242,  48,  40}}, {{144, 239,  34,  51}}, 
+  {{157, 228,  44,  58}}, {{  6,  61, 150, 221}}, {{ 11,  54, 152, 212}}, 
+  {{ 28,  43, 138, 207}}, {{ 17,  32, 132, 198}}, {{ 50,  17, 174, 249}}, 
+  {{ 63,  26, 160, 240}}, {{ 40,   7, 178, 235}}, {{ 37,  12, 188, 226}}, 
+  {{110, 101, 230, 149}}, {{ 99, 110, 232, 156}}, {{116, 115, 250, 135}}, 
+  {{121, 120, 244, 142}}, {{ 90,  73, 222, 177}}, {{ 87,  66, 208, 184}}, 
+  {{ 64,  95, 194, 163}}, {{ 77,  84, 204, 170}}, {{218, 247,  65, 236}}, 
+  {{215, 252,  79, 229}}, {{192, 225,  93, 254}}, {{205, 234,  83, 247}}, 
+  {{238, 219, 121, 200}}, {{227, 208, 119, 193}}, {{244, 205, 101, 218}}, 
+  {{249, 198, 107, 211}}, {{178, 175,  49, 164}}, {{191, 164,  63, 173}}, 
+  {{168, 185,  45, 182}}, {{165, 178,  35, 191}}, {{134, 131,   9, 128}}, 
+  {{139, 136,   7, 137}}, {{156, 149,  21, 146}}, {{145, 158,  27, 155}}, 
+  {{ 10,  71, 161, 124}}, {{  7,  76, 175, 117}}, {{ 16,  81, 189, 110}}, 
+  {{ 29,  90, 179, 103}}, {{ 62, 107, 153,  88}}, {{ 51,  96, 151,  81}}, 
+  {{ 36, 125, 133,  74}}, {{ 41, 118, 139,  67}}, {{ 98,  31, 209,  52}}, 
+  {{111,  20, 223,  61}}, {{120,   9, 205,  38}}, {{117,   2, 195,  47}}, 
+  {{ 86,  51, 233,  16}}, {{ 91,  56, 231,  25}}, {{ 76,  37, 245,   2}}, 
+  {{ 65,  46, 251,  11}}, {{ 97, 140, 154, 215}}, {{108, 135, 148, 222}}, 
+  {{123, 154, 134, 197}}, {{118, 145, 136, 204}}, {{ 85, 160, 162, 243}}, 
+  {{ 88, 171, 172, 250}}, {{ 79, 182, 190, 225}}, {{ 66, 189, 176, 232}}, 
+  {{  9, 212, 234, 159}}, {{  4, 223, 228, 150}}, {{ 19, 194, 246, 141}}, 
+  {{ 30, 201, 248, 132}}, {{ 61, 248, 210, 187}}, {{ 48, 243, 220, 178}}, 
+  {{ 39, 238, 206, 169}}, {{ 42, 229, 192, 160}}, {{177,  60, 122,  71}}, 
+  {{188,  55, 116,  78}}, {{171,  42, 102,  85}}, {{166,  33, 104,  92}}, 
+  {{133,  16,  66,  99}}, {{136,  27,  76, 106}}, {{159,   6,  94, 113}}, 
+  {{146,  13,  80, 120}}, {{217, 100,  10,  15}}, {{212, 111,   4,   6}}, 
+  {{195, 114,  22,  29}}, {{206, 121,  24,  20}}, {{237,  72,  50,  43}}, 
+  {{224,  67,  60,  34}}, {{247,  94,  46,  57}}, {{250,  85,  32,  48}}, 
+  {{183,   1, 236, 154}}, {{186,  10, 226, 147}}, {{173,  23, 240, 136}}, 
+  {{160,  28, 254, 129}}, {{131,  45, 212, 190}}, {{142,  38, 218, 183}}, 
+  {{153,  59, 200, 172}}, {{148,  48, 198, 165}}, {{223,  89, 156, 210}}, 
+  {{210,  82, 146, 219}}, {{197,  79, 128, 192}}, {{200,  68, 142, 201}}, 
+  {{235, 117, 164, 246}}, {{230, 126, 170, 255}}, {{241,  99, 184, 228}}, 
+  {{252, 104, 182, 237}}, {{103, 177,  12,  10}}, {{106, 186,   2,   3}}, 
+  {{125, 167,  16,  24}}, {{112, 172,  30,  17}}, {{ 83, 157,  52,  46}}, 
+  {{ 94, 150,  58,  39}}, {{ 73, 139,  40,  60}}, {{ 68, 128,  38,  53}}, 
+  {{ 15, 233, 124,  66}}, {{  2, 226, 114,  75}}, {{ 21, 255,  96,  80}}, 
+  {{ 24, 244, 110,  89}}, {{ 59, 197,  68, 102}}, {{ 54, 206,  74, 111}}, 
+  {{ 33, 211,  88, 116}}, {{ 44, 216,  86, 125}}, {{ 12, 122,  55, 161}}, 
+  {{  1, 113,  57, 168}}, {{ 22, 108,  43, 179}}, {{ 27, 103,  37, 186}}, 
+  {{ 56,  86,  15, 133}}, {{ 53,  93,   1, 140}}, {{ 34,  64,  19, 151}}, 
+  {{ 47,  75,  29, 158}}, {{100,  34,  71, 233}}, {{105,  41,  73, 224}}, 
+  {{126,  52,  91, 251}}, {{115,  63,  85, 242}}, {{ 80,  14, 127, 205}}, 
+  {{ 93,   5, 113, 196}}, {{ 74,  24,  99, 223}}, {{ 71,  19, 109, 214}}, 
+  {{220, 202, 215,  49}}, {{209, 193, 217,  56}}, {{198, 220, 203,  35}}, 
+  {{203, 215, 197,  42}}, {{232, 230, 239,  21}}, {{229, 237, 225,  28}}, 
+  {{242, 240, 243,   7}}, {{255, 251, 253,  14}}, {{180, 146, 167, 121}}, 
+  {{185, 153, 169, 112}}, {{174, 132, 187, 107}}, {{163, 143, 181,  98}}, 
+  {{128, 190, 159,  93}}, {{141, 181, 145,  84}}, {{154, 168, 131,  79}}, 
+  {{151, 163, 141,  70}}, 
+ },
+ {
+  {{  0,   0,   0,   0}}, {{  9,  13,  11,  14}}, {{ 18,  26,  22,  28}}, 
+  {{ 27,  23,  29,  18}}, {{ 36,  52,  44,  56}}, {{ 45,  57,  39,  54}}, 
+  {{ 54,  46,  58,  36}}, {{ 63,  35,  49,  42}}, {{ 72, 104,  88, 112}}, 
+  {{ 65, 101,  83, 126}}, {{ 90, 114,  78, 108}}, {{ 83, 127,  69,  98}}, 
+  {{108,  92, 116,  72}}, {{101,  81, 127,  70}}, {{126,  70,  98,  84}}, 
+  {{119,  75, 105,  90}}, {{144, 208, 176, 224}}, {{153, 221, 187, 238}}, 
+  {{130, 202, 166, 252}}, {{139, 199, 173, 242}}, {{180, 228, 156, 216}}, 
+  {{189, 233, 151, 214}}, {{166, 254, 138, 196}}, {{175, 243, 129, 202}}, 
+  {{216, 184, 232, 144}}, {{209, 181, 227, 158}}, {{202, 162, 254, 140}}, 
+  {{195, 175, 245, 130}}, {{252, 140, 196, 168}}, {{245, 129, 207, 166}}, 
+  {{238, 150, 210, 180}}, {{231, 155, 217, 186}}, {{ 59, 187, 123, 219}}, 
+  {{ 50, 182, 112, 213}}, {{ 41, 161, 109, 199}}, {{ 32, 172, 102, 201}}, 
+  {{ 31, 143,  87, 227}}, {{ 22, 130,  92, 237}}, {{ 13, 149,  65, 255}}, 
+  {{  4, 152,  74, 241}}, {{115, 211,  35, 171}}, {{122, 222,  40, 165}}, 
+  {{ 97, 201,  53, 183}}, {{104, 196,  62, 185}}, {{ 87, 231,  15, 147}}, 
+  {{ 94, 234,   4, 157}}, {{ 69, 253,  25, 143}}, {{ 76, 240,  18, 129}}, 
+  {{171, 107, 203,  59}}, {{162, 102, 192,  53}}, {{185, 113, 221,  39}}, 
+  {{176, 124, 214,  41}}, {{143,  95, 231,   3}}, {{134,  82, 236,  13}}, 
+  {{157,  69, 241,  31}}, {{148,  72, 250,  17}}, {{227,   3, 147,  75}}, 
+  {{234,  14, 152,  69}}, {{241,  25, 133,  87}}, {{248,  20, 142,  89}}, 
+  {{199,  55, 191, 115}}, {{206,  58, 180, 125}}, {{213,  45, 169, 111}}, 
+  {{220,  32, 162,  97}}, {{118, 109, 246, 173}}, {{127,  96, 253, 163}}, 
+  {{100, 119, 224, 177}}, {{109, 122, 235, 191}}, {{ 82,  89, 218, 149}}, 
+  {{ 91,  84, 209, 155}}, {{ 64,  67, 204, 137}}, {{ 73,  78, 199, 135}}, 
+  {{ 62,   5, 174, 221}}, {{ 55,   8, 165, 211}}, {{ 44,  31, 184, 193}}, 
+  {{ 37,  18, 179, 207}}, {{ 26,  49, 130, 229}}, {{ 19,  60, 137, 235}}, 
+  {{  8,  43, 148, 249}}, {{  1,  38, 159, 247}}, {{230, 189,  70,  77}}, 
+  {{239, 176,  77,  67}}, {{244, 167,  80,  81}}, {{253, 170,  91,  95}}, 
+  {{194, 137, 106, 117}}, {{203, 132,  97, 123}}, {{208, 147, 124, 105}}, 
+  {{217, 158, 119, 103}}, {{174, 213,  30,  61}}, {{167, 216,  21,  51}}, 
+  {{188, 207,   8,  33}}, {{181, 194,   3,  47}}, {{138, 225,  50,   5}}, 
+  {{131, 236,  57,  11}}, {{152, 251,  36,  25}}, {{145, 246,  47,  23}}, 
+  {{ 77, 214, 141, 118}}, {{ 68, 219, 134, 120}}, {{ 95, 204, 155, 106}}, 
+  {{ 86, 193, 144, 100}}, {{105, 226, 161,  78}}, {{ 96, 239, 170,  64}}, 
+  {{123, 248, 183,  82}}, {{114, 245, 188,  92}}, {{  5, 190, 213,   6}}, 
+  {{ 12, 179, 222,   8}}, {{ 23, 164, 195,  26}}, {{ 30, 169, 200,  20}}, 
+  {{ 33, 138, 249,  62}}, {{ 40, 135, 242,  48}}, {{ 51, 144, 239,  34}}, 
+  {{ 58, 157, 228,  44}}, {{221,   6,  61, 150}}, {{212,  11,  54, 152}}, 
+  {{207,  28,  43, 138}}, {{198,  17,  32, 132}}, {{249,  50,  17, 174}}, 
+  {{240,  63,  26, 160}}, {{235,  40,   7, 178}}, {{226,  37,  12, 188}}, 
+  {{149, 110, 101, 230}}, {{156,  99, 110, 232}}, {{135, 116, 115, 250}}, 
+  {{142, 121, 120, 244}}, {{177,  90,  73, 222}}, {{184,  87,  66, 208}}, 
+  {{163,  64,  95, 194}}, {{170,  77,  84, 204}}, {{236, 218, 247,  65}}, 
+  {{229, 215, 252,  79}}, {{254, 192, 225,  93}}, {{247, 205, 234,  83}}, 
+  {{200, 238, 219, 121}}, {{193, 227, 208, 119}}, {{218, 244, 205, 101}}, 
+  {{211, 249, 198, 107}}, {{164, 178, 175,  49}}, {{173, 191, 164,  63}}, 
+  {{182, 168, 185,  45}}, {{191, 165, 178,  35}}, {{128, 134, 131,   9}}, 
+  {{137, 139, 136,   7}}, {{146, 156, 149,  21}}, {{155, 145, 158,  27}}, 
+  {{124,  10,  71, 161}}, {{117,   7,  76, 175}}, {{110,  16,  81, 189}}, 
+  {{103,  29,  90, 179}}, {{ 88,  62, 107, 153}}, {{ 81,  51,  96, 151}}, 
+  {{ 74,  36, 125, 133}}, {{ 67,  41, 118, 139}}, {{ 52,  98,  31, 209}}, 
+  {{ 61, 111,  20, 223}}, {{ 38, 120,   9, 205}}, {{ 47, 117,   2, 195}}, 
+  {{ 16,  86,  51, 233}}, {{ 25,  91,  56, 231}}, {{  2,  76,  37, 245}}, 
+  {{ 11,  65,  46, 251}}, {{215,  97, 140, 154}}, {{222, 108, 135, 148}}, 
+  {{197, 123, 154, 134}}, {{204, 118, 145, 136}}, {{243,  85, 160, 162}}, 
+  {{250,  88, 171, 172}}, {{225,  79, 182, 190}}, {{232,  66, 189, 176}}, 
+  {{159,   9, 212, 234}}, {{150,   4, 223, 228}}, {{141,  19, 194, 246}}, 
+  {{132,  30, 201, 248}}, {{187,  61, 248, 210}}, {{178,  48, 243, 220}}, 
+  {{169,  39, 238, 206}}, {{160,  42, 229, 192}}, {{ 71, 177,  60, 122}}, 
+  {{ 78, 188,  55, 116}}, {{ 85, 171,  42, 102}}, {{ 92, 166,  33, 104}}, 
+  {{ 99, 133,  16,  66}}, {{106, 136,  27,  76}}, {{113, 159,   6,  94}}, 
+  {{120, 146,  13,  80}}, {{ 15, 217, 100,  10}}, {{  6, 212, 111,   4}}, 
+  {{ 29, 195, 114,  22}}, {{ 20, 206, 121,  24}}, {{ 43, 237,  72,  50}}, 
+  {{ 34, 224,  67,  60}}, {{ 57, 247,  94,  46}}, {{ 48, 250,  85,  32}}, 
+  {{154, 183,   1, 236}}, {{147, 186,  10, 226}}, {{136, 173,  23, 240}}, 
+  {{129, 160,  28, 254}}, {{190, 131,  45, 212}}, {{183, 142,  38, 218}}, 
+  {{172, 153,  59, 200}}, {{165, 148,  48, 198}}, {{210, 223,  89, 156}}, 
+  {{219, 210,  82, 146}}, {{192, 197,  79, 128}}, {{201, 200,  68, 142}}, 
+  {{246, 235, 117, 164}}, {{255, 230, 126, 170}}, {{228, 241,  99, 184}}, 
+  {{237, 252, 104, 182}}, {{ 10, 103, 177,  12}}, {{  3, 106, 186,   2}}, 
+  {{ 24, 125, 167,  16}}, {{ 17, 112, 172,  30}}, {{ 46,  83, 157,  52}}, 
+  {{ 39,  94, 150,  58}}, {{ 60,  73, 139,  40}}, {{ 53,  68, 128,  38}}, 
+  {{ 66,  15, 233, 124}}, {{ 75,   2, 226, 114}}, {{ 80,  21, 255,  96}}, 
+  {{ 89,  24, 244, 110}}, {{102,  59, 197,  68}}, {{111,  54, 206,  74}}, 
+  {{116,  33, 211,  88}}, {{125,  44, 216,  86}}, {{161,  12, 122,  55}}, 
+  {{168,   1, 113,  57}}, {{179,  22, 108,  43}}, {{186,  27, 103,  37}}, 
+  {{133,  56,  86,  15}}, {{140,  53,  93,   1}}, {{151,  34,  64,  19}}, 
+  {{158,  47,  75,  29}}, {{233, 100,  34,  71}}, {{224, 105,  41,  73}}, 
+  {{251, 126,  52,  91}}, {{242, 115,  63,  85}}, {{205,  80,  14, 127}}, 
+  {{196,  93,   5, 113}}, {{223,  74,  24,  99}}, {{214,  71,  19, 109}}, 
+  {{ 49, 220, 202, 215}}, {{ 56, 209, 193, 217}}, {{ 35, 198, 220, 203}}, 
+  {{ 42, 203, 215, 197}}, {{ 21, 232, 230, 239}}, {{ 28, 229, 237, 225}}, 
+  {{  7, 242, 240, 243}}, {{ 14, 255, 251, 253}}, {{121, 180, 146, 167}}, 
+  {{112, 185, 153, 169}}, {{107, 174, 132, 187}}, {{ 98, 163, 143, 181}}, 
+  {{ 93, 128, 190, 159}}, {{ 84, 141, 181, 145}}, {{ 79, 154, 168, 131}}, 
+  {{ 70, 151, 163, 141}}, 
+ },
+};
+
+const int xrcon[30] = {
+  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 
+  0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 
+  0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 
+};
+
+const word8 xS[256] = {
+   99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 
+  171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 
+  156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 
+  229, 241, 113, 216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154, 
+    7,  18, 128, 226, 235,  39, 178, 117,   9, 131,  44,  26,  27, 110, 
+   90, 160,  82,  59, 214, 179,  41, 227,  47, 132,  83, 209,   0, 237, 
+   32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 208, 239, 
+  170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168, 
+   81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 
+  243, 210, 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 
+  100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 
+  184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 
+  194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213, 
+   78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  46, 
+   28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
+  181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 
+  225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85, 
+   40, 223, 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 
+  176,  84, 187,  22, 
+};
+
+const word8 xSi[256] = {
+   82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 
+  215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 
+  196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 
+  149,  11,  66, 250, 195,  78,   8,  46, 161, 102,  40, 217,  36, 178, 
+  118,  91, 162,  73, 109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 
+  152,  22, 212, 164,  92, 204,  93, 101, 182, 146, 108, 112,  72,  80, 
+  253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132, 144, 216, 
+  171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6, 
+  208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 
+  138, 107,  58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 
+  240, 180, 230, 115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249, 
+   55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 
+  111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210, 
+  121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,  51, 
+  136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81, 
+  127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 
+  160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 
+  153,  97,  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99, 
+   85,  33,  12, 125, 
+};
+
diff --git a/src/aes/ao_aes_tables.h b/src/aes/ao_aes_tables.h
new file mode 100644 (file)
index 0000000..73bcf3f
--- /dev/null
@@ -0,0 +1,10 @@
+/* Copyright (C) 2000-2009 Peter Selinger.
+   This file is part of ccrypt. It is free software and it is covered
+   by the GNU general public license. See the file COPYING for details. */
+
+extern const word8x4 M0[4][256];
+extern const word8x4 M1[4][256];
+extern const int xrcon[30];
+extern const word8 xS[256];
+extern const word8 xSi[256];
+
index cd81b163bc37bf657971095de81f8f83a774d053..d2ea2be7da5ce142ceb46ad0d3ebaa40c1689add 100644 (file)
@@ -28,15 +28,6 @@ uint16_t ao_time(void)
        return v;
 }
 
-static __xdata uint8_t ao_forever;
-
-void
-ao_delay(uint16_t ticks)
-{
-       ao_alarm(ticks);
-       ao_sleep(&ao_forever);
-}
-
 #define T1_CLOCK_DIVISOR       8       /* 24e6/8 = 3e6 */
 #define T1_SAMPLE_TIME         30000   /* 3e6/30000 = 100 */
 
index f7ecce33d019597ad9d25a95bbacdc268db78b75..0e19603b29429d4e8177f163ac05d7134dd9b421 100644 (file)
@@ -2,7 +2,7 @@ CC=sdcc
 
 CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE)
 
-CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product
+CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../drivers -I../product
 
 CODESIZE ?= 0x8000
 
@@ -33,3 +33,6 @@ clean-cc1111:
        rm -f $(PROGNAME)-*
        rm -f ao_product.h
        rm -f ../$(PROGNAME)-*
+
+../ao_kalman.h:
+       +(cd .. && make ao_kalman.h)
index ce827e2596ac7b576fc84056507e0e68cecf1dd1..f7b52281ae799855008bdcb1d296779e23e5024e 100644 (file)
@@ -140,6 +140,15 @@ ao_adc_isr(void) __interrupt 1
        }
 #endif /* telemini || telenano */
 
+#ifdef TELEFIRE_V_0_1
+       a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence);
+       a[0] = ADCL;
+       a[1] = ADCH;
+       if (sequence < 5)
+               ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1);
+#define GOT_ADC
+#endif /* TELEFIRE_V_0_1 */
+
 #ifndef GOT_ADC
 #error No known ADC configuration set
 #endif
@@ -157,9 +166,13 @@ ao_adc_dump(void) __reentrant
 {
        static __xdata struct ao_data   packet;
        ao_data_get(&packet);
+#ifndef AO_ADC_DUMP
        printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n",
               packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp,
               packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m);
+#else
+       AO_ADC_DUMP(&packet);
+#endif
 }
 
 __code struct ao_cmds ao_adc_cmds[] = {
@@ -170,6 +183,11 @@ __code struct ao_cmds ao_adc_cmds[] = {
 void
 ao_adc_init(void)
 {
+#ifdef AO_ADC_PINS
+       ADCCFG = AO_ADC_PINS;
+
+#else
+
 #if IGNITE_ON_P2
        /* TeleMetrum configuration */
        ADCCFG = ((1 << 0) |    /* acceleration */
@@ -190,6 +208,8 @@ ao_adc_init(void)
                  (1 << 3));    /* battery voltage */
 #endif
 
+#endif /* else AO_ADC_PINS */
+
        /* enable interrupts */
        ADCIF = 0;
        IEN0 |= IEN0_ADCIE;
index d50fecfb997afacdbedc814a86a7ad3d70009fae..b1f305eca2ddee9279dff315c3ea1f4b2ee3d256 100644 (file)
@@ -135,7 +135,11 @@ ao_aes_run(__xdata uint8_t *in,
 void
 ao_aes_init(void)
 {
+#if DMA_SHARE_AES_RADIO
+       ao_aes_dma_in = ao_radio_dma;
+#else
        ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done);
+#endif
        ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done);
        S0CON = 0;
        ENCIE = 1;
index 06b04b93651d75fcad23fd40433ad3a0d9fd5622..a97515a7547509d31b1a4328d2f272fa7bd0e28e 100644 (file)
@@ -200,18 +200,6 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal;
 
 #define ao_arch_critical(b) __critical { b }
 
-struct ao_adc {
-       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 */
-#if HAS_ACCEL_REF
-       uint16_t        accel_ref;      /* acceleration reference */
-#endif
-};
-
 #define AO_DATA_RING   32
 
 /* ao_button.c */
index 0737e7abeb2c113449e9ee839d4a68328d5dc265..8f1cc09476e099766247de88705fe3bbd22bb54d 100644 (file)
@@ -29,6 +29,15 @@ extern __xdata uint8_t       ao_spi_mutex;
                                          UxGCR_ORDER_MSB |             \
                                          ((speed) << UxGCR_BAUD_E_SHIFT)))
 
+#define ao_spi_get_slave(bus) do {                     \
+               ao_mutex_get(&ao_spi_mutex);            \
+               ao_spi_set_speed(AO_SPI_SPEED_FAST);    \
+       } while (0)
+
+#define ao_spi_put_slave(bus) do {             \
+               ao_mutex_put(&ao_spi_mutex);    \
+       } while (0)
+
 #define ao_spi_get_mask(reg,mask,bus,speed) do {       \
                ao_mutex_get(&ao_spi_mutex);            \
                ao_spi_set_speed(speed);                \
@@ -68,6 +77,14 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant;
 #define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len)
 #define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len)
 
+#if AO_SPI_SLAVE
+void
+ao_spi_send_wait(void);
+
+void
+ao_spi_recv_wait(void);
+#endif
+
 void
 ao_spi_init(void);
 
@@ -88,3 +105,4 @@ ao_spi_init(void);
 #define token_paster(x,y)      x ## y
 #define token_evaluator(x,y)   token_paster(x,y)
 #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)
+#define ao_gpio_set(port, bit, pin, v) ((pin) = (v))
index a593d0b2b624f94a16a98cab68a0a52e0f76d308..420f75683666c41125a19e259f11d491c6f7d284 100644 (file)
@@ -15,7 +15,8 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao.h"
+#include <ao.h>
+#include <ao_radio_cmac.h>
 
 __xdata uint16_t ao_launch_ignite;
 
index fc6ed3ec280a0287fe1fe6b3b800cce4cc0364f6..2f0e2884826107ba51ab49166ad3789827ca7e7c 100644 (file)
 #define AO_IGNITER_FIRE_TIME   AO_MS_TO_TICKS(50)
 #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000)
 
+struct ao_adc {
+       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 */
+#if HAS_ACCEL_REF
+       uint16_t        accel_ref;      /* acceleration reference */
+#endif
+};
+
 #endif /* _AO_PINS_H_ */
index 2071c47a432cae2c4f8d3c628fea19e8578a9c34..cb2c2fddba411fee29ea427bd11f44b402d96fd7 100644 (file)
@@ -16,6 +16,9 @@
  */
 
 #include "ao.h"
+#if HAS_PAD
+#include <ao_pad.h>
+#endif
 
 /* Values from SmartRF® Studio for:
  *
@@ -467,8 +470,44 @@ ao_radio_rdf_abort(void)
 
 
 /* Output carrier */
+
+static __xdata ao_radio_test_on;
+
 void
-ao_radio_test(void)
+ao_radio_test(uint8_t on)
+{
+       if (on) {
+               if (!ao_radio_test_on) {
+#if HAS_MONITOR
+                       ao_monitor_disable();
+#endif
+#if PACKET_HAS_SLAVE
+                       ao_packet_slave_stop();
+#endif
+#if HAS_PAD
+                       ao_pad_disable();
+#endif
+                       ao_radio_get(0xff);
+                       RFST = RFST_STX;
+                       ao_radio_test_on = 1;
+               }
+       } else  {
+               if (ao_radio_test_on) {
+                       ao_radio_idle();
+                       ao_radio_put();
+                       ao_radio_test_on = 0;
+#if HAS_MONITOR
+                       ao_monitor_enable();
+#endif
+#if HAS_PAD
+                       ao_pad_enable();
+#endif
+               }
+       }
+}
+
+static void
+ao_radio_test_cmd(void)
 {
        uint8_t mode = 2;
        static __xdata radio_on;
@@ -478,34 +517,19 @@ ao_radio_test(void)
                mode = (uint8_t) ao_cmd_lex_u32;
        }
        mode++;
-       if ((mode & 2) && !radio_on) {
-#if HAS_MONITOR
-               ao_monitor_disable();
-#endif
-#if PACKET_HAS_SLAVE
-               ao_packet_slave_stop();
-#endif
-               ao_radio_get(0xff);
-               RFST = RFST_STX;
-               radio_on = 1;
-       }
+       if ((mode & 2))
+               ao_radio_test(1);
        if (mode == 3) {
                printf ("Hit a character to stop..."); flush();
                getchar();
                putchar('\n');
        }
-       if ((mode & 1) && radio_on) {
-               ao_radio_idle();
-               ao_radio_put();
-               radio_on = 0;
-#if HAS_MONITOR
-               ao_monitor_enable();
-#endif
-       }
+       if ((mode & 1))
+               ao_radio_test(0);
 }
 
 __code struct ao_cmds ao_radio_cmds[] = {
-       { ao_radio_test,        "C <1 start, 0 stop, none both>\0Radio carrier test" },
+       { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
        { 0,    NULL },
 };
 
index 00c85ff3fa268e7b31caab8fa999a4f665c02cd5..4838380228214dcf7fe0e475bf493a89237bcc21 100644 (file)
 
 #include "ao.h"
 
+const __code struct ao_serial_speed ao_serial_speeds[] = {
+       /* [AO_SERIAL_SPEED_4800] = */ {
+               /* .baud = */ 163,
+               /* .gcr  = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+       /* [AO_SERIAL_SPEED_9600] = */ {
+               /* .baud = */ 163,
+               /* .gcr  = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+       /* [AO_SERIAL_SPEED_19200] = */ {
+               /* .baud = */ 163,
+               /* .gcr  = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+       /* [AO_SERIAL_SPEED_57600] = */ {
+               /* .baud = */ 59,
+               /* .gcr =  */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
+       },
+};
+
 #if HAS_SERIAL_0
 
 volatile __xdata struct ao_fifo        ao_serial0_rx_fifo;
@@ -116,7 +135,7 @@ ao_serial1_rx_isr(void) __interrupt 3
        if (!ao_fifo_full(ao_serial1_rx_fifo))
                ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF);
        ao_wakeup(&ao_serial1_rx_fifo);
-#if USE_SERIAL1_STDIN
+#if USE_SERIAL_1_STDIN
        ao_wakeup(&ao_stdin_ready);
 #endif
 }
@@ -181,25 +200,6 @@ ao_serial1_drain(void) __critical
                ao_sleep(&ao_serial1_tx_fifo);
 }
 
-const __code struct ao_serial_speed ao_serial_speeds[] = {
-       /* [AO_SERIAL_SPEED_4800] = */ {
-               /* .baud = */ 163,
-               /* .gcr  = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-       /* [AO_SERIAL_SPEED_9600] = */ {
-               /* .baud = */ 163,
-               /* .gcr  = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-       /* [AO_SERIAL_SPEED_19200] = */ {
-               /* .baud = */ 163,
-               /* .gcr  = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-       /* [AO_SERIAL_SPEED_57600] = */ {
-               /* .baud = */ 59,
-               /* .gcr =  */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB
-       },
-};
-
 void
 ao_serial1_set_speed(uint8_t speed)
 {
@@ -236,9 +236,9 @@ ao_serial_init(void)
                (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0);
 
        /* Make the USART pins be controlled by the USART */
-       P1SEL |= (1 << 2) | (1 << 3);
-#if HAS_SERIAL_0_HW_FLOW
        P1SEL |= (1 << 5) | (1 << 4);
+#if HAS_SERIAL_0_HW_FLOW
+       P1SEL |= (1 << 3) | (1 << 2);
 #endif
 #endif
 
@@ -292,7 +292,9 @@ ao_serial_init(void)
 
        /* Make the USART pins be controlled by the USART */
        P1SEL |= (1 << 6) | (1 << 7);
+#if HAS_SERIAL_1_HW_FLOW
        P1SEL |= (1 << 5) | (1 << 4);
+#endif
 #endif
 
        /* UART mode with receiver enabled */
index 1bf5e1551b0c7a9013c009880f3326e875e3dfe4..cdef6bda9d85948bc45ec0fd3f427068c62b4560 100644 (file)
 
 #include "ao.h"
 
+/* Default pin usage for existing Altus Metrum devices */
+#if !HAS_SPI_0 && !HAS_SPI_1
+#define HAS_SPI_0      1
+#define SPI_0_ALT_2    1
+#endif
+
+#ifndef SPI_CONST
+#define SPI_CONST      0xff
+#endif
+
+/*
+ * USART0 SPI config alt 1
+ * 
+ *     MO      P0_3
+ *     MI      P0_2
+ *     CLK     P0_5
+ *     SS      P0_4
+ *
+ * USART0 SPI config alt 2
+ *
+ *     MO      P1_5
+ *     MI      P1_4
+ *     CLK     P1_3
+ *     CSS     P1_2
+ *
+ * USART1 SPI config alt 1
+ *
+ *     MO      P0_4
+ *     MI      P0_5
+ *     CLK     P0_3
+ *     SS      P0_2
+ *
+ * USART1 SPI config alt 2
+ *
+ *     MO      P1_6
+ *     MI      P1_7
+ *     CLK     P1_5
+ *     SS      P1_4
+ *
+ *
+ * Chip select is the responsibility of the caller in master mode
+ */
+
+#if HAS_SPI_0
+#define SPI_CSR                U0CSR
+#define SPI_BUF                U0DBUFXADDR
+#define SPI_BAUD       U0BAUD
+#define SPI_GCR                U0GCR
+#define SPI_CFG_MASK   PERCFG_U0CFG_ALT_MASK
+#define SPI_DMA_TX     DMA_CFG0_TRIGGER_UTX0
+#define SPI_DMA_RX     DMA_CFG0_TRIGGER_URX0
+
+#if SPI_0_ALT_1
+#define SPI_CFG                PERCFG_U0CFG_ALT_1
+#define SPI_SEL                P0SEL
+#define SPI_BITS       (1 << 3) | (1 << 2) | (1 << 5)
+#define SPI_CSS_BIT    (1 << 4)
+#endif
+
+#if SPI_0_ALT_2
+#define SPI_CFG                PERCFG_U0CFG_ALT_2
+#define SPI_SEL                P1SEL
+#define SPI_PRI                P2SEL_PRI3P1_USART0
+#define SPI_BITS       (1 << 5) | (1 << 4) | (1 << 3)
+#define SPI_CSS_BIT    (1 << 2)
+#endif
+
+#endif
+
+#if HAS_SPI_1
+#define SPI_CSR                U1CSR
+#define SPI_BUF                U1DBUFXADDR
+#define SPI_BAUD       U1BAUD
+#define SPI_GCR                U1GCR
+#define SPI_CFG_MASK   PERCFG_U1CFG_ALT_MASK
+#define SPI_DMA_TX     DMA_CFG0_TRIGGER_UTX1
+#define SPI_DMA_RX     DMA_CFG0_TRIGGER_URX1
+
+#if SPI_1_ALT_1
+#define SPI_CFG                PERCFG_U1CFG_ALT_1
+#define SPI_SEL                P0SEL
+#define SPI_BITS       (1 << 4) | (1 << 5) | (1 << 3)
+#define SPI_CSS_BIT    (1 << 2)
+#endif
+
+#if SPI_1_ALT_2
+#define SPI_CFG                PERCFG_U1CFG_ALT_2
+#define SPI_SEL                P1SEL
+#define SPI_PRI                P2SEL_PRI3P1_USART1
+#define SPI_BITS       (1 << 6) | (1 << 7) | (1 << 5)
+#define SPI_CSS_BIT    (1 << 4)
+#endif
+
+#endif
+
+#if AO_SPI_SLAVE
+#define CSS            SPI_CSS_BIT
+#define UxCSR_DIRECTION        UxCSR_SLAVE
+#else
+#define CSS            0
+#define UxCSR_DIRECTION        UxCSR_MASTER
+#endif
+
 /* Shared mutex to protect SPI bus, must cover the entire
  * operation, from CS low to CS high. This means that any SPI
  * user must protect the SPI bus with this mutex
@@ -41,23 +144,22 @@ void
 ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant
 {
        ao_dma_set_transfer(ao_spi_dma_in_id,
-                           &U0DBUFXADDR,
+                           &SPI_BUF,
                            &ao_spi_const,
                            len,
                            DMA_CFG0_WORDSIZE_8 |
                            DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
+                           SPI_DMA_RX,
                            DMA_CFG1_SRCINC_0 |
                            DMA_CFG1_DESTINC_0 |
                            DMA_CFG1_PRIORITY_NORMAL);
-
        ao_dma_set_transfer(ao_spi_dma_out_id,
                            block,
-                           &U0DBUFXADDR,
+                           &SPI_BUF,
                            len,
                            DMA_CFG0_WORDSIZE_8 |
                            DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
+                           SPI_DMA_TX,
                            DMA_CFG1_SRCINC_1 |
                            DMA_CFG1_DESTINC_0 |
                            DMA_CFG1_PRIORITY_NORMAL);
@@ -65,10 +167,21 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant
        ao_dma_start(ao_spi_dma_in_id);
        ao_dma_start(ao_spi_dma_out_id);
        ao_dma_trigger(ao_spi_dma_out_id);
+#if !AO_SPI_SLAVE
        __critical while (!ao_spi_dma_in_done)
                ao_sleep(&ao_spi_dma_in_done);
+#endif
 }
 
+#if AO_SPI_SLAVE
+void
+ao_spi_send_wait(void)
+{
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+}
+#endif
+
 /* Receive bytes over SPI.
  *
  * This sets up tow DMA engines, one reading the data and another
@@ -79,59 +192,64 @@ void
 ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant
 {
        ao_dma_set_transfer(ao_spi_dma_in_id,
-                           &U0DBUFXADDR,
+                           &SPI_BUF,
                            block,
                            len,
                            DMA_CFG0_WORDSIZE_8 |
                            DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_URX0,
+                           SPI_DMA_RX,
                            DMA_CFG1_SRCINC_0 |
                            DMA_CFG1_DESTINC_1 |
                            DMA_CFG1_PRIORITY_NORMAL);
 
-       ao_spi_const = 0xff;
+       ao_spi_const = SPI_CONST;
 
+#if !AO_SPI_SLAVE
        ao_dma_set_transfer(ao_spi_dma_out_id,
                            &ao_spi_const,
-                           &U0DBUFXADDR,
+                           &SPI_BUF,
                            len,
                            DMA_CFG0_WORDSIZE_8 |
                            DMA_CFG0_TMODE_SINGLE |
-                           DMA_CFG0_TRIGGER_UTX0,
+                           SPI_DMA_TX,
                            DMA_CFG1_SRCINC_0 |
                            DMA_CFG1_DESTINC_0 |
                            DMA_CFG1_PRIORITY_NORMAL);
+#endif
 
        ao_dma_start(ao_spi_dma_in_id);
+#if !AO_SPI_SLAVE
        ao_dma_start(ao_spi_dma_out_id);
        ao_dma_trigger(ao_spi_dma_out_id);
        __critical while (!ao_spi_dma_in_done)
                ao_sleep(&ao_spi_dma_in_done);
+#endif
 }
 
-/*
- * Initialize USART0 for SPI using config alt 2
- *
- *     MO      P1_5
- *     MI      P1_4
- *     CLK     P1_3
- *
- * Chip select is the responsibility of the caller
- */
+#if AO_SPI_SLAVE
+void
+ao_spi_recv_wait(void)
+{
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+}
+#endif
 
 void
 ao_spi_init(void)
 {
        /* Set up the USART pin assignment */
-       PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
+       PERCFG = (PERCFG & ~SPI_CFG_MASK) | SPI_CFG;
 
-       /* Ensure that USART0 takes precidence over USART1 for pins that
-        * they share
+       /* Ensure that SPI USART takes precidence over the other USART
+        * for pins that they share
         */
-       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0;
+#ifdef SPI_PRI
+       P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | SPI_PRI;
+#endif
 
        /* Make the SPI pins be controlled by the USART peripheral */
-       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
+       SPI_SEL |= SPI_BITS | CSS;
 
        /* Set up OUT DMA */
        ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done);
@@ -141,9 +259,9 @@ ao_spi_init(void)
 
        /* Set up the USART.
         *
-        * SPI master mode
+        * SPI master/slave mode
         */
-       U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER);
+       SPI_CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION);
 
        /* Set the baud rate and signal parameters
         *
@@ -151,9 +269,9 @@ ao_spi_init(void)
         * Every peripheral I've ever seen goes faster than that,
         * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0)
         */
-       U0BAUD = 0;
-       U0GCR = (UxGCR_CPOL_NEGATIVE |
-                UxGCR_CPHA_FIRST_EDGE |
-                UxGCR_ORDER_MSB |
-                (17 << UxGCR_BAUD_E_SHIFT));
+       SPI_BAUD = 0;
+       SPI_GCR = (UxGCR_CPOL_NEGATIVE |
+                  UxGCR_CPHA_FIRST_EDGE |
+                  UxGCR_ORDER_MSB |
+                  (17 << UxGCR_BAUD_E_SHIFT));
 }
index 602f98c8276720c047751d95baff9c4fd14fbecc..a64b5aba90a0fb5e104a3005dbf2cdda464056ad 100644 (file)
@@ -24,16 +24,6 @@ uint16_t ao_time(void) __critical
        return ao_tick_count;
 }
 
-static __xdata uint8_t ao_forever;
-
-void
-ao_delay(uint16_t ticks)
-{
-       ao_alarm(ticks);
-       ao_sleep(&ao_forever);
-       ao_clear_alarm();
-}
-
 #define T1_CLOCK_DIVISOR       8       /* 24e6/8 = 3e6 */
 #define T1_SAMPLE_TIME         30000   /* 3e6/30000 = 100 */
 
index 65b9eb18f409a33a6b32a7e67d68879bc6b558be..66c0881f7862cb01a949c4e8d1cca9be5d0da804 100644 (file)
@@ -125,7 +125,12 @@ ao_panic(uint8_t reason);
  * ao_timer.c
  */
 
-extern volatile __data uint16_t ao_tick_count;
+#ifndef AO_TICK_TYPE
+#define AO_TICK_TYPE   uint16_t
+#define AO_TICK_SIGNED int16_t
+#endif
+
+extern volatile __data AO_TICK_TYPE ao_tick_count;
 
 /* Our timer runs at 100Hz */
 #define AO_HERTZ               100
@@ -432,6 +437,7 @@ ao_gps_report_mega_init(void);
  * ao_telemetry_orig.c
  */
 
+#if LEGACY_MONITOR
 struct ao_adc_orig {
        uint16_t        tick;           /* tick when the sample was read */
        int16_t         accel;          /* accelerometer */
@@ -489,6 +495,8 @@ struct ao_telemetry_tiny_recv {
        uint8_t                         status;
 };
 
+#endif /* LEGACY_MONITOR */
+
 /* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method
  * for reporting RSSI. So, now we use these values everywhere
  */
@@ -535,9 +543,6 @@ ao_telemetry_tiny_init(void);
  */
 
 extern __xdata uint8_t ao_radio_dma;
-extern __xdata uint8_t ao_radio_dma_done;
-extern __xdata uint8_t ao_radio_done;
-extern __xdata uint8_t ao_radio_mutex;
 
 #ifdef PKT_APPEND_STATUS_1_CRC_OK
 #define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK
@@ -558,6 +563,9 @@ ao_radio_recv(__xdata void *d, uint8_t size) __reentrant;
 void
 ao_radio_recv_abort(void);
 
+void
+ao_radio_test(uint8_t on);
+
 /*
  * Compute the packet length as follows:
  *
@@ -582,6 +590,8 @@ ao_radio_init(void);
  * ao_monitor.c
  */
 
+#if HAS_MONITOR
+
 extern const char const * const ao_state_names[];
 
 #define AO_MONITOR_RING        8
@@ -618,6 +628,8 @@ ao_monitor_enable(void);
 void
 ao_monitor_init(void) __reentrant;
 
+#endif
+
 /*
  * ao_stdio.c
  */
@@ -706,6 +718,8 @@ extern __xdata uint8_t ao_force_freq;
 
 #define AO_AES_LEN 16
 
+extern __xdata uint8_t ao_config_aes_seq;
+
 struct ao_config {
        uint8_t         major;
        uint8_t         minor;
index 7f67374d6ed6140567bb29dedb0198b7e2c34d45..c47bc2db22f6921eeee524d46240e04951d89ac9 100644 (file)
@@ -29,9 +29,11 @@ enum ao_aes_mode {
 };
 
 #if HAS_AES
+#ifdef SDCC
 void
 ao_aes_isr(void) __interrupt 4;
 #endif
+#endif
 
 void
 ao_aes_set_mode(enum ao_aes_mode mode);
@@ -49,21 +51,4 @@ ao_aes_run(__xdata uint8_t *in,
 void
 ao_aes_init(void);
 
-/* ao_radio_cmac.c */
-
-int8_t
-ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant;
-
-#define AO_RADIO_CMAC_OK       0
-#define AO_RADIO_CMAC_LEN_ERROR        -1
-#define AO_RADIO_CMAC_CRC_ERROR        -2
-#define AO_RADIO_CMAC_MAC_ERROR        -3
-#define AO_RADIO_CMAC_TIMEOUT  -4
-
-int8_t
-ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant;
-
-void
-ao_radio_cmac_init(void);
-
 #endif /* _AO_AES_H_ */
index e2095e65977e7608e7e21809742083973530f6cb..ce855ad1b51e1dcfdd6afb8d2d455fe45528e2d9 100644 (file)
 
 #include "ao.h"
 #include "ao_log.h"
+#include <ao_storage.h>
+#if HAS_FLIGHT
 #include <ao_sample.h>
 #include <ao_data.h>
+#endif
 
 __xdata struct ao_config ao_config;
 __pdata uint8_t ao_config_loaded;
@@ -460,6 +463,9 @@ ao_config_radio_enable_set(void) __reentrant
 #endif /* HAS_RADIO */
        
 #if HAS_AES
+
+__xdata uint8_t        ao_config_aes_seq = 1;
+
 void
 ao_config_key_show(void) __reentrant
 {
@@ -482,6 +488,7 @@ ao_config_key_set(void) __reentrant
                        break;
                ao_config.aes_key[i] = ao_cmd_lex_i;
        }
+       ++ao_config_aes_seq;
        _ao_config_edit_finish();
 }
 #endif
index fdc49ca202df0425eb56e75162f8adc86b13e037..3b66ef5d1a598e65e9369d6d7adcb33f10a08eee 100644 (file)
 #ifndef _AO_DATA_H_
 #define _AO_DATA_H_
 
+#if HAS_ADC
+#define AO_DATA_ADC    (1 << 0)
+#else
+#define AO_DATA_ADC    0
+#endif
+
 #if HAS_MS5607
 #include <ao_ms5607.h>
+#define AO_DATA_MS5607 (1 << 1)
+#else
+#define AO_DATA_MS5607 (1 << 1)
 #endif
 
 #if HAS_MPU6000
 #include <ao_mpu6000.h>
+#define AO_DATA_MPU6000        (1 << 2)
+#else
+#define AO_DATA_MPU6000        0
 #endif
 
 #if HAS_HMC5883
 #include <ao_hmc5883.h>
+#define AO_DATA_HMC5883        (1 << 3)
+#else
+#define AO_DATA_HMC5883        0
+#endif
+
+#if HAS_MMA655X
+#include <ao_mma655x.h>
+#define AO_DATA_MMA655X (1 << 4)
+#else
+#define AO_DATA_MMA655X 0
 #endif
 
+#define AO_DATA_ALL    (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X)
+
 struct ao_data {
        uint16_t                        tick;
 #if HAS_ADC
@@ -45,6 +69,9 @@ struct ao_data {
 #if HAS_HMC5883
        struct ao_hmc5883_sample        hmc5883;
 #endif
+#if HAS_MMA655X
+       uint16_t                        mma655x;
+#endif
 };
 
 #define ao_data_ring_next(n)   (((n) + 1) & (AO_DATA_RING - 1))
@@ -52,6 +79,29 @@ struct ao_data {
 
 extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING];
 extern volatile __data uint8_t         ao_data_head;
+extern volatile __data uint8_t         ao_data_present;
+extern volatile __data uint8_t         ao_data_count;
+
+/*
+ * Mark a section of data as ready, check for data complete
+ */
+#define AO_DATA_PRESENT(bit)   do {                                    \
+               if ((ao_data_present |= (bit)) == AO_DATA_ALL) {        \
+                       ao_data_ring[ao_data_head].tick = ao_tick_count; \
+                       ao_data_head = ao_data_ring_next(ao_data_head); \
+                       ao_data_present = 0;                            \
+                       ao_wakeup((void *) &ao_data_head);              \
+               }                                                       \
+       } while (0);
+
+/*
+ * Wait for data to be completed by looking at the
+ * indicated bit
+ */
+#define AO_DATA_WAIT() do {                            \
+               ao_sleep((void *) &ao_data_count);      \
+       } while (0)
+
 
 #if HAS_MS5607
 
index edc5fd1f9fb41d97bae679067f8fe5fec1759c08..d9a0914a761cb931bdc4d92bf7388ad8cb4839f8 100644 (file)
@@ -40,6 +40,10 @@ ao_led_off(AO_LED_TYPE colors);
 void
 ao_led_set(AO_LED_TYPE colors);
 
+/* Set all LEDs in 'mask' to the specified state */
+void
+ao_led_set_mask(uint8_t colors, uint8_t mask);
+
 /* Toggle the specified LEDs */
 void
 ao_led_toggle(AO_LED_TYPE colors);
index e263f0db8289bbe69697016dca4786494fb71bff..fc0ca8b1310382912895f25d7f6e023525f1c0e2 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao.h"
-
-#define AO_CMAC_KEY_LEN                AO_AES_LEN
-#define AO_CMAC_MAX_LEN                (128 - AO_CMAC_KEY_LEN)
+#include <ao.h>
+#include <ao_radio_cmac.h>
 
 static __xdata uint8_t ao_radio_cmac_mutex;
-__pdata int16_t ao_radio_cmac_rssi;
+__pdata int8_t ao_radio_cmac_rssi;
 static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN];
 static __pdata uint8_t ao_radio_cmac_len;
 
-static uint8_t
-getnibble(void)
-{
-       int8_t  b;
-
-       b = ao_cmd_hexchar(getchar());
-       if (b < 0) {
-               ao_cmd_status = ao_cmd_lex_error;
-               return 0;
-       }
-       return (uint8_t) b;
-}
-
-static uint8_t
-getbyte(void)
-{
-       uint8_t b;
-       b = getnibble() << 4;
-       b |= getnibble();
-       return b;
-}
-       
 static uint8_t
 round_len(uint8_t len)
 {
@@ -120,8 +96,8 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant
                return AO_RADIO_CMAC_TIMEOUT;
        }
 
-       ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74;
-       if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK))
+       ao_radio_cmac_rssi = (int8_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74;
+       if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK))
                return AO_RADIO_CMAC_CRC_ERROR;
 
        ao_config_get();
@@ -159,8 +135,14 @@ ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant
        if (len > AO_CMAC_MAX_LEN)
                return AO_RADIO_CMAC_LEN_ERROR;
        ao_mutex_get(&ao_radio_cmac_mutex);
-       memcpy(cmac_data, packet, len);
+       ao_xmemcpy(cmac_data, packet, len);
+#if AO_LED_TX
+       ao_led_on(AO_LED_TX);
+#endif
        radio_cmac_send(len);
+#if AO_LED_TX
+       ao_led_off(AO_LED_TX);
+#endif
        ao_mutex_put(&ao_radio_cmac_mutex);
        return AO_RADIO_CMAC_OK;
 }
@@ -172,235 +154,16 @@ ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentr
        if (len > AO_CMAC_MAX_LEN)
                return AO_RADIO_CMAC_LEN_ERROR;
        ao_mutex_get(&ao_radio_cmac_mutex);
+#if AO_LED_RX
+       ao_led_on(AO_LED_RX);
+#endif
        i = radio_cmac_recv(len, timeout);
+#if AO_LED_RX
+       ao_led_off(AO_LED_RX);
+#endif
        if (i == AO_RADIO_CMAC_OK)
-               memcpy(packet, cmac_data, len);
+               ao_xmemcpy(packet, cmac_data, len);
        ao_mutex_put(&ao_radio_cmac_mutex);
        return i;
 }
 
-static void
-radio_cmac_send_cmd(void) __reentrant
-{
-       uint8_t i;
-       uint8_t len;
-
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       len = ao_cmd_lex_i;
-       if (len > AO_CMAC_MAX_LEN) {
-               ao_cmd_status = ao_cmd_syntax_error;
-               return;
-       }
-       flush();
-       ao_mutex_get(&ao_radio_cmac_mutex);
-       len = ao_cmd_lex_i;
-       for (i = 0; i < len; i++) {
-               cmac_data[i] = getbyte();
-               if (ao_cmd_status != ao_cmd_success)
-                       return;
-       }
-       radio_cmac_send(len);
-       ao_mutex_put(&ao_radio_cmac_mutex);
-}
-
-static void
-radio_cmac_recv_cmd(void) __reentrant
-{
-       uint8_t         len, i;
-       uint16_t        timeout;
-
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       len = ao_cmd_lex_i;
-       ao_cmd_decimal();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       timeout = AO_MS_TO_TICKS(ao_cmd_lex_i);
-       ao_mutex_get(&ao_radio_cmac_mutex);
-       i = radio_cmac_recv(len, timeout);
-       if (i == AO_RADIO_CMAC_OK) {
-               printf ("PACKET ");
-               for (i = 0; i < len; i++)
-                       printf("%02x", cmac_data[i]);
-               printf (" %d\n", ao_radio_cmac_rssi);
-       } else
-               printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi);
-       ao_mutex_put(&ao_radio_cmac_mutex);
-}
-
-static __xdata struct ao_launch_command        command;
-static __xdata struct ao_launch_query  query;
-static pdata uint16_t  launch_serial;
-static pdata uint8_t   launch_channel;
-static pdata uint16_t  tick_offset;
-
-static void
-launch_args(void) __reentrant
-{
-       ao_cmd_decimal();
-       launch_serial = ao_cmd_lex_i;
-       ao_cmd_decimal();
-       launch_channel = ao_cmd_lex_i;
-}
-
-static int8_t
-launch_query(void)
-{
-       uint8_t i;
-       int8_t  r = AO_RADIO_CMAC_OK;
-
-       tick_offset = ao_time();
-       for (i = 0; i < 10; i++) {
-               printf ("."); flush();
-               command.tick = ao_time();
-               command.serial = launch_serial;
-               command.cmd = AO_LAUNCH_QUERY;
-               command.channel = launch_channel;
-               ao_radio_cmac_send(&command, sizeof (command));
-               r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500));
-               if (r == AO_RADIO_CMAC_OK)
-                       break;
-       }
-       tick_offset -= query.tick;
-       printf("\n"); flush();
-       return r;
-}
-
-static void
-launch_report_cmd(void) __reentrant
-{
-       int8_t          r;
-
-       launch_args();
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       r = launch_query();
-       switch (r) {
-       case AO_RADIO_CMAC_OK:
-               if (query.valid) {
-                       switch (query.arm_status) {
-                       case ao_igniter_ready:
-                       case ao_igniter_active:
-                               printf ("Armed: ");
-                               break;
-                       default:
-                               printf("Disarmed: ");
-                       }
-                       switch (query.igniter_status) {
-                       default:
-                               printf("unknown\n");
-                               break;
-                       case ao_igniter_ready:
-                               printf("igniter good\n");
-                               break;
-                       case ao_igniter_open:
-                               printf("igniter bad\n");
-                               break;
-                       }
-               } else {
-                       printf("Invalid channel %d\n", launch_channel);
-               }
-               printf("Rssi: %d\n", ao_radio_cmac_rssi);
-               break;
-       default:
-               printf("Error %d\n", r);
-               break;
-       }
-}
-
-static void
-launch_arm(void) __reentrant
-{
-       command.tick = ao_time() - tick_offset;
-       command.serial = launch_serial;
-       command.cmd = AO_LAUNCH_ARM;
-       command.channel = launch_channel;
-       ao_radio_cmac_send(&command, sizeof (command));
-}
-
-static void
-launch_ignite(void) __reentrant
-{
-       command.tick = ao_time() - tick_offset;
-       command.serial = launch_serial;
-       command.cmd = AO_LAUNCH_FIRE;
-       command.channel = 0;
-       ao_radio_cmac_send(&command, sizeof (command));
-}
-
-static void
-launch_fire_cmd(void) __reentrant
-{
-       static __xdata struct ao_launch_command command;
-       uint8_t         secs;
-       uint8_t         i;
-       int8_t          r;
-
-       launch_args();
-       ao_cmd_decimal();
-       secs = ao_cmd_lex_i;
-       if (ao_cmd_status != ao_cmd_success)
-               return;
-       r = launch_query();
-       if (r != AO_RADIO_CMAC_OK) {
-               printf("query failed %d\n", r);
-               return;
-       }
-
-       for (i = 0; i < 4; i++) {
-               printf("arm %d\n", i); flush();
-               launch_arm();
-       }
-
-       secs = secs * 10 - 5;
-       if (secs > 100)
-               secs = 100;
-       for (i = 0; i < secs; i++) {
-               printf("fire %d\n", i); flush();
-               launch_ignite();
-               ao_delay(AO_MS_TO_TICKS(100));
-       }
-}
-
-static void
-launch_arm_cmd(void) __reentrant
-{
-       uint8_t i;
-       int8_t  r;
-       launch_args();
-       r = launch_query();
-       if (r != AO_RADIO_CMAC_OK) {
-               printf("query failed %d\n", r);
-               return;
-       }
-       for (i = 0; i < 4; i++)
-               launch_arm();
-}
-
-static void
-launch_ignite_cmd(void) __reentrant
-{
-       uint8_t i;
-       launch_args();
-       for (i = 0; i < 4; i++)
-               launch_ignite();
-}
-
-static __code struct ao_cmds ao_radio_cmac_cmds[] = {
-       { radio_cmac_send_cmd,  "s <length>\0Send AES-CMAC packet. Bytes to send follow on next line" },
-       { radio_cmac_recv_cmd,  "S <length> <timeout>\0Receive AES-CMAC packet. Timeout in ms" },
-       { launch_report_cmd,    "l <serial> <channel>\0Get remote launch status" },
-       { launch_fire_cmd,      "f <serial> <channel> <secs>\0Fire remote igniter" },
-       { launch_arm_cmd,       "a <serial> <channel>\0Arm remote igniter" },
-       { launch_ignite_cmd,    "i <serial> <channel>\0Pulse remote igniter" },
-       { 0, NULL },
-};
-
-void
-ao_radio_cmac_init(void)
-{
-       ao_cmd_register(&ao_radio_cmac_cmds[0]);
-}
diff --git a/src/core/ao_radio_cmac.h b/src/core/ao_radio_cmac.h
new file mode 100644 (file)
index 0000000..e86f31e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_RADIO_CMAC_H_
+#define _AO_RADIO_CMAC_H_
+
+#include <ao_aes.h>
+
+#define AO_CMAC_KEY_LEN                AO_AES_LEN
+#define AO_CMAC_MAX_LEN                (128 - AO_CMAC_KEY_LEN)
+
+extern __pdata int8_t ao_radio_cmac_rssi;
+
+int8_t
+ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant;
+
+#define AO_RADIO_CMAC_OK       0
+#define AO_RADIO_CMAC_LEN_ERROR        -1
+#define AO_RADIO_CMAC_CRC_ERROR        -2
+#define AO_RADIO_CMAC_MAC_ERROR        -3
+#define AO_RADIO_CMAC_TIMEOUT  -4
+
+int8_t
+ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant;
+
+void
+ao_radio_cmac_init(void);
+
+#endif /* _AO_RADIO_CMAC_H_ */
diff --git a/src/core/ao_radio_cmac_cmd.c b/src/core/ao_radio_cmac_cmd.c
new file mode 100644 (file)
index 0000000..6441092
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_radio_cmac.h>
+
+static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN];
+
+static uint8_t
+getnibble(void)
+{
+       int8_t  b;
+
+       b = ao_cmd_hexchar(getchar());
+       if (b < 0) {
+               ao_cmd_status = ao_cmd_lex_error;
+               return 0;
+       }
+       return (uint8_t) b;
+}
+
+static uint8_t
+getbyte(void)
+{
+       uint8_t b;
+       b = getnibble() << 4;
+       b |= getnibble();
+       return b;
+}
+       
+static void
+radio_cmac_send_cmd(void) __reentrant
+{
+       uint8_t i;
+       uint8_t len;
+
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       len = ao_cmd_lex_i;
+       if (len > AO_CMAC_MAX_LEN) {
+               ao_cmd_status = ao_cmd_syntax_error;
+               return;
+       }
+       flush();
+       len = ao_cmd_lex_i;
+       for (i = 0; i < len; i++) {
+               cmac_data[i] = getbyte();
+               if (ao_cmd_status != ao_cmd_success)
+                       return;
+       }
+       ao_radio_cmac_send(cmac_data, len);
+}
+
+static void
+radio_cmac_recv_cmd(void) __reentrant
+{
+       uint8_t         len, i;
+       uint16_t        timeout;
+
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       len = ao_cmd_lex_i;
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       timeout = AO_MS_TO_TICKS(ao_cmd_lex_i);
+       i = ao_radio_cmac_recv(cmac_data, len, timeout);
+       if (i == AO_RADIO_CMAC_OK) {
+               printf ("PACKET ");
+               for (i = 0; i < len; i++)
+                       printf("%02x", cmac_data[i]);
+               printf (" %d\n", ao_radio_cmac_rssi);
+       } else
+               printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi);
+}
+
+static __code struct ao_cmds ao_radio_cmac_cmds[] = {
+       { radio_cmac_send_cmd,  "s <length>\0Send AES-CMAC packet. Bytes to send follow on next line" },
+       { radio_cmac_recv_cmd,  "S <length> <timeout>\0Receive AES-CMAC packet. Timeout in ms" },
+       { 0, NULL },
+};
+
+void
+ao_radio_cmac_cmd_init(void)
+{
+       ao_cmd_register(&ao_radio_cmac_cmds[0]);
+}
diff --git a/src/core/ao_radio_cmac_cmd.h b/src/core/ao_radio_cmac_cmd.h
new file mode 100644 (file)
index 0000000..6b8782d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_RADIO_CMAC_CMD_H_
+#define _AO_RADIO_CMAC_CMD_H_
+
+void
+ao_radio_cmac_cmd_init(void);
+
+#endif /* _AO_RADIO_CMAC_CMD_H_ */
index b2dd435bba84a541e0fd3d895f110ba517c6bfb3..adf7e4d4949491f99a5609b2f22dc4fd650466b4 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <ao.h>
+#include <ao_storage.h>
 
 uint8_t
 ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant
index 4011a36e06297f7423c85aabed8d6f2f2a0561d9..65654731aeaeaccc9f45477e156ffa1419d13c0b 100644 (file)
@@ -82,39 +82,36 @@ ao_yield(void) ao_arch_naked_define
 
        ao_arch_isr_stack();
 
-#if CHECK_STACK
+#if AO_CHECK_STACK
        in_yield = 1;
 #endif
        /* 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;
+               __pdata uint8_t ao_last_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_index;
+                       if (ao_cur_task_index == ao_num_tasks)
+                               ao_cur_task_index = 0;
+
+                       ao_cur_task = ao_tasks[ao_cur_task_index];
 
-                       ao_cur_task = ao_tasks[ao_next_task_index];
-                       if (ao_cur_task->wchan == NULL) {
-                               ao_cur_task_index = ao_next_task_index;
+                       /* Check for ready task */
+                       if (ao_cur_task->wchan == NULL)
                                break;
-                       }
 
                        /* Check if the alarm is set for a time which has passed */
                        if (ao_cur_task->alarm &&
-                           (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) {
-                               ao_cur_task_index = ao_next_task_index;
+                           (int16_t) (ao_time() - ao_cur_task->alarm) >= 0)
                                break;
-                       }
 
                        /* Enter lower power mode when there isn't anything to do */
-                       if (ao_next_task_index == ao_cur_task_index) {
+                       if (ao_cur_task_index == ao_last_task_index)
                                ao_arch_cpu_idle();
-                       }
                }
        }
-#if CHECK_STACK
+#if AO_CHECK_STACK
        cli();
        in_yield = 0;
 #endif
@@ -128,6 +125,7 @@ ao_sleep(__xdata void *wchan)
        ao_yield();
        if (ao_cur_task->wchan) {
                ao_cur_task->wchan = NULL;
+               ao_cur_task->alarm = 0;
                return 1;
        }
        return 0;
@@ -160,6 +158,16 @@ ao_clear_alarm(void)
        ao_cur_task->alarm = 0;
 }
 
+static __xdata uint8_t ao_forever;
+
+void
+ao_delay(uint16_t ticks)
+{
+       ao_alarm(ticks);
+       ao_sleep(&ao_forever);
+       ao_clear_alarm();
+}
+
 void
 ao_exit(void)
 {
@@ -177,7 +185,7 @@ ao_exit(void)
 void
 ao_task_info(void)
 {
-       uint8_t i;
+       uint8_t         i;
        __xdata struct ao_task *task;
 
        for (i = 0; i < ao_num_tasks; i++) {
diff --git a/src/drivers/ao_74hc497.c b/src/drivers/ao_74hc497.c
new file mode 100644 (file)
index 0000000..4c13ee7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/*
+ * 74HC597 driver.
+ * Reads a single byte from the shift register
+ */
+
+#include <ao.h>
+#include <ao_74hc497.h>
+
+uint8_t
+ao_74hc497_read(void)
+{
+       static __xdata state;
+       ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST);
+       ao_spi_recv(&state, 1, AO_74HC497_SPI_BUS);
+       ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS);
+       return state;
+}
+
+static void
+ao_74hc497_cmd(void)
+{
+       uint8_t v;
+
+       v = ao_74hc497_read();
+       printf ("Switches: 0x%02x\n", v);
+}
+
+static const struct ao_cmds ao_74hc497_cmds[] = {
+       { ao_74hc497_cmd, "L\0Show 74hc497" },
+       { 0, NULL }
+};
+
+void
+ao_74hc497_init(void)
+{
+       ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1);
+       ao_cmd_register(&ao_74hc497_cmds[0]);
+}
diff --git a/src/drivers/ao_74hc497.h b/src/drivers/ao_74hc497.h
new file mode 100644 (file)
index 0000000..6df7bca
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_74HC497_H_
+#define _AO_74HC497_H_
+
+uint8_t
+ao_74hc497_read(void);
+
+void
+ao_74hc497_init(void);
+
+#endif /* _AO_74HC497_H_ */
diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c
new file mode 100644 (file)
index 0000000..a507c90
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_button.h>
+#include <ao_exti.h>
+#if AO_EVENT
+#include <ao_event.h>
+#define ao_button_queue(b,v)   ao_event_put_isr(AO_EVENT_BUTTON, b, v)
+#else
+#define ao_button_queue(b,v)
+#endif
+
+static uint8_t         ao_button[AO_BUTTON_COUNT];
+static AO_TICK_TYPE    ao_button_time[AO_BUTTON_COUNT];
+
+#define AO_DEBOUNCE    AO_MS_TO_TICKS(20)
+
+#define port(q)        AO_BUTTON_ ## q ## _PORT
+#define bit(q) AO_BUTTON_ ## q
+#define pin(q) AO_BUTTON_ ## q ## _PIN
+
+static void
+ao_button_do(uint8_t b, uint8_t v)
+{
+       /* Debounce */
+       if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE)
+               return;
+
+       /* pins are inverted */
+       v = !v;
+       if (ao_button[b] != v) {
+               ao_button[b] = v;
+               ao_button_time[b] = ao_tick_count;
+               ao_button_queue(b, v);
+               ao_wakeup(&ao_button[b]);
+       }
+}
+
+#define ao_button_update(b)    ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+
+static void
+ao_button_isr(void)
+{
+#if AO_BUTTON_COUNT > 0
+       ao_button_update(0);
+#endif
+#if AO_BUTTON_COUNT > 1
+       ao_button_update(1);
+#endif
+#if AO_BUTTON_COUNT > 2
+       ao_button_update(2);
+#endif
+#if AO_BUTTON_COUNT > 3
+       ao_button_update(3);
+#endif
+#if AO_BUTTON_COUNT > 4
+       ao_button_update(4);
+#endif
+}
+
+#define init(b) do {                                                   \
+               ao_enable_port(port(b));                                \
+                                                                       \
+               ao_exti_setup(port(b), bit(b),                          \
+                             AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
+                             ao_button_isr);                   \
+               ao_exti_enable(port(b), bit(b));                        \
+       } while (0)
+
+void
+ao_button_init(void)
+{
+#if AO_BUTTON_COUNT > 0
+       init(0);
+#endif
+#if AO_BUTTON_COUNT > 1
+       init(1);
+#endif
+}
diff --git a/src/drivers/ao_button.h b/src/drivers/ao_button.h
new file mode 100644 (file)
index 0000000..ce349d6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_BUTTON_H_
+#define _AO_BUTTON_H_
+
+void
+ao_button_init(void);
+
+#endif /* _AO_BUTTON_H_ */
index 97a434d8975131338034ad1783c1e0e61bae5c7a..4df931b5094b0349b9c903f768170dc21553f89f 100644 (file)
@@ -515,7 +515,7 @@ ao_radio_rdf_abort(void)
 }
 
 static void
-ao_radio_test(void)
+ao_radio_test_cmd(void)
 {
        uint8_t mode = 2;
        uint8_t radio_on;
@@ -1008,7 +1008,7 @@ ao_radio_test_recv()
 #endif
 
 static const struct ao_cmds ao_radio_cmds[] = {
-       { ao_radio_test,        "C <1 start, 0 stop, none both>\0Radio carrier test" },
+       { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
 #if CC1120_DEBUG
        { ao_radio_show,        "R\0Show CC1120 status" },
        { ao_radio_beep,        "b\0Emit an RDF beacon" },
diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c
new file mode 100644 (file)
index 0000000..440ef2d
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_event.h>
+
+#define AO_EVENT_QUEUE 64
+
+#define ao_event_queue_next(n) (((n) + 1) & (AO_EVENT_QUEUE - 1))
+#define ao_event_queue_prev(n) (((n) - 1) & (AO_EVENT_QUEUE - 1))
+#define ao_event_queue_empty() (ao_event_queue_insert == ao_event_queue_remove)
+#define ao_event_queue_full()  (ao_event_queue_next(ao_event_queue_insert) == ao_event_queue_remove)
+
+/*
+ * Whether a sequence of events from the same device should be collapsed
+ */
+#define ao_event_can_collapse(type)    ((type) == AO_EVENT_QUADRATURE)
+
+struct ao_event ao_event_queue[AO_EVENT_QUEUE];
+uint8_t                ao_event_queue_insert;
+uint8_t                ao_event_queue_remove;
+
+
+uint8_t
+ao_event_get(struct ao_event *ev)
+{
+       ao_arch_critical(
+               while (ao_event_queue_empty())
+                       ao_sleep(&ao_event_queue);
+               *ev = ao_event_queue[ao_event_queue_remove];
+               ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+               );
+}
+
+/* called with interrupts disabled */
+void
+ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value)
+{
+       if (!ao_event_queue_full()) {
+
+               if (ao_event_can_collapse(type) && !ao_event_queue_empty()) {
+                       uint8_t prev = ao_event_queue_prev(ao_event_queue_insert);
+
+                       if (ao_event_queue[prev].type == type &&
+                           ao_event_queue[prev].unit == unit)
+                               ao_event_queue_insert = prev;
+               }
+               ao_event_queue[ao_event_queue_insert] = (struct ao_event) {
+                       .type = type,
+                       .unit = unit,
+                       .tick = ao_tick_count,
+                       .value = value
+               };
+               ao_event_queue_insert = ao_event_queue_next(ao_event_queue_insert);
+               ao_wakeup(&ao_event_queue);
+       }
+}
+
+void
+ao_event_put(uint8_t type, uint8_t unit, uint32_t value)
+{
+       ao_arch_critical(ao_event_put_isr(type, unit, value););
+}
diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h
new file mode 100644 (file)
index 0000000..25c49c3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_EVENT_H_
+#define _AO_EVENT_H_
+
+#define AO_EVENT_NONE          0
+#define AO_EVENT_QUADRATURE    1
+#define AO_EVENT_BUTTON                2
+
+struct ao_event {
+       uint8_t         type;
+       uint8_t         unit;
+       uint16_t        tick;
+       uint32_t        value;
+};
+
+uint8_t
+ao_event_get(struct ao_event *ev);
+
+void
+ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value);
+
+void
+ao_event_put(uint8_t type, uint8_t unit, uint32_t value);
+
+#endif /* _AO_EVENT_H_ */
index dbeb66b818905e4ac2c455744c4c71c8f3bd30bb..ade6c263d84236823d7d366cdb1c42b8b18348c8 100644 (file)
@@ -19,7 +19,7 @@
 #include <ao_hmc5883.h>
 #include <ao_exti.h>
 
-uint8_t        ao_hmc5883_valid;
+#if HAS_HMC5883
 
 static uint8_t ao_hmc5883_configured;
 
@@ -123,21 +123,16 @@ ao_hmc5883_setup(void)
        return 1;
 }
 
-struct ao_hmc5883_sample ao_hmc5883_current;
-
 static void
 ao_hmc5883(void)
 {
        ao_hmc5883_setup();
        for (;;) {
-               struct ao_hmc5883_sample ao_hmc5883_next;
-
-               ao_hmc5883_sample(&ao_hmc5883_next);
+               ao_hmc5883_sample((struct ao_hmc5883_sample *) &ao_data_ring[ao_data_head].hmc5883);
                ao_arch_critical(
-                       ao_hmc5883_current = ao_hmc5883_next;
-                       ao_hmc5883_valid = 1;
+                       AO_DATA_PRESENT(AO_DATA_HMC5883);
+                       AO_DATA_WAIT();
                        );
-               ao_delay(0);
        }
 }
 
@@ -146,11 +141,10 @@ static struct ao_task ao_hmc5883_task;
 static void
 ao_hmc5883_show(void)
 {
-       struct ao_hmc5883_sample        sample;
-
-       sample = ao_hmc5883_current;
+       struct ao_data  sample;
+       ao_data_get(&sample);
        printf ("X: %d Y: %d Z: %d missed irq: %lu\n",
-               sample.x, sample.y, sample.z, ao_hmc5883_missed_irq);
+               sample.hmc5883.x, sample.hmc5883.y, sample.hmc5883.z, ao_hmc5883_missed_irq);
 }
 
 static const struct ao_cmds ao_hmc5883_cmds[] = {
@@ -162,7 +156,6 @@ void
 ao_hmc5883_init(void)
 {
        ao_hmc5883_configured = 0;
-       ao_hmc5883_valid = 0;
 
        ao_enable_port(AO_HMC5883_INT_PORT);
        ao_exti_setup(AO_HMC5883_INT_PORT,
@@ -173,3 +166,5 @@ ao_hmc5883_init(void)
        ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883");
        ao_cmd_register(&ao_hmc5883_cmds[0]);
 }
+
+#endif
index 8d726510911558ae4e6ec3b8883941f286bf0bfc..556909784040f9be4fd5979d793d189f5b1ec7ec 100644 (file)
 #define HMC5883_ID_B           11
 #define HMC5883_ID_C           12
 
-extern uint8_t ao_hmc5883_valid;
-
 struct ao_hmc5883_sample {
        int16_t         x, y, z;
 };
 
-extern struct ao_hmc5883_sample ao_hmc5883_current;
-
 void
 ao_hmc5883_init(void);
 
diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c
new file mode 100644 (file)
index 0000000..b49c9db
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac.h>
+
+static __xdata struct ao_pad_command   command;
+static __xdata struct ao_pad_query     query;
+static __pdata uint16_t        launch_box;
+static __pdata uint8_t launch_channels;
+static __pdata uint16_t        tick_offset;
+
+static void
+launch_args(void) __reentrant
+{
+       ao_cmd_decimal();
+       launch_box = ao_cmd_lex_i;
+       ao_cmd_hex();
+       launch_channels = ao_cmd_lex_i;
+}
+
+static int8_t
+launch_query(void)
+{
+       uint8_t i;
+       int8_t  r = AO_RADIO_CMAC_OK;
+
+       tick_offset = ao_time();
+       for (i = 0; i < 10; i++) {
+               printf ("."); flush();
+               command.tick = ao_time();
+               command.box = launch_box;
+               command.cmd = AO_LAUNCH_QUERY;
+               command.channels = launch_channels;
+               ao_radio_cmac_send(&command, sizeof (command));
+               r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500));
+               if (r == AO_RADIO_CMAC_OK)
+                       break;
+       }
+       tick_offset -= query.tick;
+       printf("\n"); flush();
+       return r;
+}
+
+static void
+launch_report_cmd(void) __reentrant
+{
+       int8_t          r;
+       uint8_t         c;
+
+       launch_args();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       r = launch_query();
+       switch (r) {
+       case AO_RADIO_CMAC_OK:
+               switch (query.arm_status) {
+               case ao_igniter_ready:
+               case ao_igniter_active:
+                       printf ("Armed: ");
+                       break;
+               default:
+                       printf("Disarmed: ");
+               }
+               for (c = 0; c < AO_PAD_MAX_CHANNELS; c++) {
+                       if (query.channels & (1 << c)) {
+                               printf (" pad %d ", c);
+                               switch (query.igniter_status[c]) {
+                               default:
+                                       printf("unknown, ");
+                                       break;
+                               case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN:
+                                       printf("bad-open, ");
+                                       break;
+                               case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN:
+                                       printf("good-igniter, ");
+                                       break;
+                               case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED:
+                                       printf("bad-closed, ");
+                                       break;
+                               }
+                       }
+               }
+               printf("Rssi: %d\n", ao_radio_cmac_rssi);
+               break;
+       default:
+               printf("Error %d\n", r);
+               break;
+       }
+}
+
+static void
+launch_arm(void) __reentrant
+{
+       command.tick = ao_time() - tick_offset;
+       command.box = launch_box;
+       command.cmd = AO_LAUNCH_ARM;
+       command.channels = launch_channels;
+       ao_radio_cmac_send(&command, sizeof (command));
+}
+
+static void
+launch_ignite(void) __reentrant
+{
+       command.tick = ao_time() - tick_offset;
+       command.box = launch_box;
+       command.cmd = AO_LAUNCH_FIRE;
+       command.channels = 0;
+       ao_radio_cmac_send(&command, sizeof (command));
+}
+
+static void
+launch_fire_cmd(void) __reentrant
+{
+       static __xdata struct ao_pad_command    command;
+       uint8_t         secs;
+       uint8_t         i;
+       int8_t          r;
+
+       launch_args();
+       ao_cmd_decimal();
+       secs = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       r = launch_query();
+       if (r != AO_RADIO_CMAC_OK) {
+               printf("query failed %d\n", r);
+               return;
+       }
+
+       for (i = 0; i < 4; i++) {
+               printf("arm %d\n", i); flush();
+               launch_arm();
+       }
+
+       secs = secs * 10 - 5;
+       if (secs > 100)
+               secs = 100;
+       for (i = 0; i < secs; i++) {
+               printf("fire %d\n", i); flush();
+               launch_ignite();
+               ao_delay(AO_MS_TO_TICKS(100));
+       }
+}
+
+static void
+launch_arm_cmd(void) __reentrant
+{
+       uint8_t i;
+       int8_t  r;
+       launch_args();
+       r = launch_query();
+       if (r != AO_RADIO_CMAC_OK) {
+               printf("query failed %d\n", r);
+               return;
+       }
+       for (i = 0; i < 4; i++)
+               launch_arm();
+}
+
+static void
+launch_ignite_cmd(void) __reentrant
+{
+       uint8_t i;
+       launch_args();
+       for (i = 0; i < 4; i++)
+               launch_ignite();
+}
+
+static __code struct ao_cmds ao_lco_cmds[] = {
+       { launch_report_cmd,    "l <box> <channel>\0Get remote launch status" },
+       { launch_fire_cmd,      "F <box> <channel> <secs>\0Fire remote igniter" },
+       { launch_arm_cmd,       "a <box> <channel>\0Arm remote igniter" },
+       { launch_ignite_cmd,    "i <box> <channel>\0Pulse remote igniter" },
+       { 0, NULL },
+};
+
+void
+ao_lco_cmd_init(void)
+{
+       ao_cmd_register(&ao_lco_cmds[0]);
+}
diff --git a/src/drivers/ao_lco_cmd.h b/src/drivers/ao_lco_cmd.h
new file mode 100644 (file)
index 0000000..c55448c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_LCO_CMD_H_
+#define _AO_LCO_CMD_H_
+
+void
+ao_lco_cmd_init(void);
+
+#endif /* _AO_LCO_CMD_H_ */
diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c
new file mode 100644 (file)
index 0000000..cd304d8
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_mma655x.h>
+
+#if HAS_MMA655X
+
+static uint8_t mma655x_configured;
+
+static void
+ao_mma655x_start(void) {
+       ao_spi_get_bit(AO_MMA655X_CS_GPIO,
+                      AO_MMA655X_CS,
+                      AO_MMA655X_CS_PIN,
+                      AO_MMA655X_SPI_INDEX,
+                      AO_SPI_SPEED_FAST);
+}
+
+static void
+ao_mma655x_stop(void) {
+       ao_spi_put_bit(AO_MMA655X_CS_GPIO,
+                      AO_MMA655X_CS,
+                      AO_MMA655X_CS_PIN,
+                      AO_MMA655X_SPI_INDEX);
+}
+
+static uint8_t
+ao_parity(uint8_t v)
+{
+       /* down to four bits */
+       v = (v ^ (v >> 4)) & 0xf;
+
+       /* Cute lookup hack -- 0x6996 encodes the sixteen
+        * even parity values in order.
+        */
+       return (~0x6996 >> v) & 1;
+}
+
+static void
+ao_mma655x_cmd(uint8_t d[2])
+{
+       ao_mma655x_start();
+       ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX);
+       ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX);
+       ao_mma655x_stop();
+}
+
+static uint8_t
+ao_mma655x_reg_write(uint8_t addr, uint8_t value)
+{
+       uint8_t d[2];
+
+       addr |= (1 << 6);       /* write mode */
+       d[0] = addr | (ao_parity(addr^value) << 7);
+       d[1] = value;
+       ao_mma655x_cmd(d);
+       return d[1];
+}
+
+static uint8_t
+ao_mma655x_reg_read(uint8_t addr)
+{
+       uint8_t d[2];
+
+       d[0] = addr | (ao_parity(addr) << 7);
+       d[1] = 0;
+       ao_mma655x_cmd(d);
+       return d[1];
+}
+
+static uint16_t
+ao_mma655x_value(void)
+{
+       uint8_t         d[2];
+       uint16_t        v;
+
+       d[0] = ((0 << 7) |      /* Axis selection (X) */
+               (1 << 6) |      /* Acceleration operation */
+               (1 << 5));      /* Raw data */
+       d[1] = ((1 << 3) |      /* must be one */
+               (1 << 2) |      /* Unsigned data */
+               (0 << 1) |      /* Arm disabled */
+               (1 << 0));      /* Odd parity */
+       ao_mma655x_cmd(d);
+       v = (uint16_t) d[1] << 2;
+       v |= d[0] >> 6;
+       v |= (uint16_t) (d[0] & 3) << 10;
+       return v;
+}
+
+static void
+ao_mma655x_reset(void) {
+       ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+                            (0 << AO_MMA655X_DEVCTL_RES_1) |
+                            (0 << AO_MMA655X_DEVCTL_RES_1));
+       ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+                            (1 << AO_MMA655X_DEVCTL_RES_1) |
+                            (1 << AO_MMA655X_DEVCTL_RES_1));
+       ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+                            (0 << AO_MMA655X_DEVCTL_RES_1) |
+                            (1 << AO_MMA655X_DEVCTL_RES_1));
+}
+
+#define DEVCFG_VALUE   (\
+       (1 << AO_MMA655X_DEVCFG_OC) |           /* Disable offset cancelation */ \
+       (1 << AO_MMA655X_DEVCFG_SD) |           /* Receive unsigned data */ \
+       (0 << AO_MMA655X_DEVCFG_OFMON) |        /* Disable offset monitor */ \
+       (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG))
+
+#define AXISCFG_VALUE  (\
+               (0 << AO_MMA655X_AXISCFG_LPF))  /* 100Hz 4-pole filter */
+
+
+static void
+ao_mma655x_setup(void)
+{
+       uint8_t         v;
+       uint16_t        a, a_st;
+       uint8_t         stdefl;
+
+       if (mma655x_configured)
+               return;
+       mma655x_configured = 1;
+       ao_delay(AO_MS_TO_TICKS(10));   /* Top */
+       ao_mma655x_reset();
+       ao_delay(AO_MS_TO_TICKS(10));   /* Top */
+       (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
+       v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
+
+       /* Configure R/W register values.
+        * Most of them relate to the arming feature, which
+        * we don't use, so the only registers we need to
+        * write are DEVCFG and AXISCFG
+        */
+
+       ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
+                            DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT));
+
+       /* Test X axis
+        */
+       
+       ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
+                            AXISCFG_VALUE |
+                            (1 << AO_MMA655X_AXISCFG_ST));
+       a_st = ao_mma655x_value();
+
+       stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL);
+
+       ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
+                            AXISCFG_VALUE |
+                            (0 << AO_MMA655X_AXISCFG_ST));
+       a = ao_mma655x_value();
+       printf ("normal: %u self_test: %u stdefl: %u\n",
+               a, a_st, stdefl);
+
+       ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
+                            DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT));
+}
+
+static void
+ao_mma655x_dump(void)
+{
+       uint8_t s0, s1, s2, s3;
+       uint32_t        lot;
+       uint16_t        serial;
+
+       ao_mma655x_setup();
+
+       s0 = ao_mma655x_reg_read(AO_MMA655X_SN0);
+       s1 = ao_mma655x_reg_read(AO_MMA655X_SN1);
+       s2 = ao_mma655x_reg_read(AO_MMA655X_SN2);
+       s3 = ao_mma655x_reg_read(AO_MMA655X_SN3);
+       lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) |
+               ((uint32_t) s1 << 8) | ((uint32_t) s0);
+       serial = lot & 0x1fff;
+       lot >>= 12;
+       printf ("MMA655X lot %d serial %d\n", lot, serial);
+       mma655x_configured = 0;
+}
+
+__code struct ao_cmds ao_mma655x_cmds[] = {
+       { ao_mma655x_dump,      "A\0Display MMA655X data" },
+       { 0, NULL },
+};
+
+static void
+ao_mma655x(void)
+{
+       ao_mma655x_setup();
+       for (;;) {
+               ao_data_ring[ao_data_head].mma655x = ao_mma655x_value();
+               ao_arch_critical(
+                       AO_DATA_PRESENT(AO_DATA_MMA655X);
+                       AO_DATA_WAIT();
+                       );
+       }
+}
+
+static __xdata struct ao_task ao_mma655x_task;
+
+void
+ao_mma655x_init(void)
+{
+       mma655x_configured = 0;
+
+       ao_cmd_register(&ao_mma655x_cmds[0]);
+       ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS));
+
+       ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x");
+}
+
+#endif
diff --git a/src/drivers/ao_mma655x.h b/src/drivers/ao_mma655x.h
new file mode 100644 (file)
index 0000000..9c0c59d
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_MMA655X_H_
+#define _AO_MMA655X_H_
+
+
+#define AO_MMA655X_SN0         0x00
+#define AO_MMA655X_SN1         0x01
+#define AO_MMA655X_SN2         0x02
+#define AO_MMA655X_SN3         0x03
+#define AO_MMA655X_SN3         0x03
+#define AO_MMA655X_STDEFL      0x04
+#define AO_MMA655X_FCTCFG      0x06
+# define AO_MMA655X_FCTCFG_STMAG       7
+
+#define AO_MMA655X_PN          0x08
+#define AO_MMA655X_DEVCTL      0x0a
+#define AO_MMA655X_DEVCTL_RES_1                7
+#define AO_MMA655X_DEVCTL_RES_0                6
+#define AO_MMA655X_DEVCTL_OCPHASE      4
+#define AO_MMA655X_DEVCTL_OCPHASE_MASK 3
+#define AO_MMA655X_DEVCTL_OFFCFG_EN    3
+
+#define AO_MMA655X_DEVCFG      0x0b
+#define AO_MMA655X_DEVCFG_OC           7
+#define AO_MMA655X_DEVCFG_ENDINIT      5
+#define AO_MMA655X_DEVCFG_SD           4
+#define AO_MMA655X_DEVCFG_OFMON                3
+#define AO_MMA655X_DEVCFG_A_CFG                0
+#define AO_MMA655X_DEVCFG_A_CFG_DISABLE                0
+#define AO_MMA655X_DEVCFG_A_CFG_PCM            1
+#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_HIGH        2
+#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_LOW 3
+#define AO_MMA655X_DEVCFG_A_CFG_COUNT_HIGH     4
+#define AO_MMA655X_DEVCFG_A_CFG_COUNT_LOW      5
+#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_HIGH        6
+#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_LOW 7
+#define AO_MMA655X_DEVCFG_A_CFG_MASK           7
+
+#define AO_MMA655X_AXISCFG     0x0c
+#define AO_MMA655X_AXISCFG_ST          7
+#define AO_MMA655X_AXISCFG_LPF         0
+#define AO_MMA655X_AXISCFG_LPF_MASK    0xf
+
+#define AO_MMA655X_ARMCFG      0x0e
+#define AO_MMA655X_ARMCFG_APS          4
+#define AO_MMA655X_ARMCFG_APS_MASK     3
+#define AO_MMA655X_ARMCFG_AWS_N                2
+#define AO_MMA655X_ARMCFG_AWS_N_MASK   3
+#define AO_MMA655X_ARMCFG_AWS_P                0
+#define AO_MMA655X_ARMCFG_AWS_P_MASK   3
+
+#define AO_MMA655X_ARMT_P      0x10
+#define AO_MMA655X_ARMT_N      0x12
+
+#define AO_MMA655X_DEVSTAT     0x14
+#define AO_MMA655X_DEVSTAT_IDE         6
+#define AO_MMA655X_DEVSTAT_DEVINIT     4
+#define AO_MMA655X_DEVSTAT_MISOERR     3
+#define AO_MMA655X_DEVSTAT_OFFSET      1
+#define AO_MMA655X_DEVSTAT_DEVRES      0
+
+#define AO_MMA655X_COUNT       0x15
+#define AO_MMA655X_OFFCORR     0x16
+
+
+void
+ao_mma655x_init(void);
+
+#endif /* _AO_MMA655X_H_ */
index a1c32d4d836db80808389009a8b38d0e6d2565ee..e8c80f12428943bf365977a03dbc9695656003ac 100644 (file)
@@ -240,22 +240,17 @@ ao_mpu6000_setup(void)
        ao_mpu6000_configured = 1;
 }
 
-struct ao_mpu6000_sample ao_mpu6000_current;
-uint8_t ao_mpu6000_valid;
-
 static void
 ao_mpu6000(void)
 {
        ao_mpu6000_setup();
        for (;;)
        {
-               struct ao_mpu6000_sample ao_mpu6000_next;
-               ao_mpu6000_sample(&ao_mpu6000_next);
+               ao_mpu6000_sample((struct ao_mpu6000_sample *) &ao_data_ring[ao_data_head].mpu6000);
                ao_arch_critical(
-                       ao_mpu6000_current = ao_mpu6000_next;
-                       ao_mpu6000_valid = 1;
+                       AO_DATA_PRESENT(AO_DATA_MPU6000);
+                       AO_DATA_WAIT();
                        );
-               ao_delay(0);
        }
 }
 
@@ -264,18 +259,16 @@ static struct ao_task ao_mpu6000_task;
 static void
 ao_mpu6000_show(void)
 {
-       struct ao_mpu6000_sample        sample;
+       struct ao_data  sample;
 
-       ao_arch_critical(
-               sample = ao_mpu6000_current;
-               );
+       ao_data_get(&sample);
        printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n",
-               sample.accel_x,
-               sample.accel_y,
-               sample.accel_z,
-               sample.gyro_x,
-               sample.gyro_y,
-               sample.gyro_z);
+               sample.mpu6000.accel_x,
+               sample.mpu6000.accel_y,
+               sample.mpu6000.accel_z,
+               sample.mpu6000.gyro_x,
+               sample.mpu6000.gyro_y,
+               sample.mpu6000.gyro_z);
 }
 
 static const struct ao_cmds ao_mpu6000_cmds[] = {
@@ -287,7 +280,6 @@ void
 ao_mpu6000_init(void)
 {
        ao_mpu6000_configured = 0;
-       ao_mpu6000_valid = 0;
 
        ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000");
        ao_cmd_register(&ao_mpu6000_cmds[0]);
index fc7af1e0390c289c308a5c445175bdf04940e96b..ca76b08128ddc3888cb611f30a295b5f9cbdd6bc 100644 (file)
@@ -155,9 +155,6 @@ struct ao_mpu6000_sample {
        int16_t         gyro_z;
 };
 
-extern struct ao_mpu6000_sample ao_mpu6000_current;
-extern uint8_t ao_mpu6000_valid;
-
 void
 ao_mpu6000_init(void);
 
index 17fe853bc1d336a76cb4f838e7c5289c0cfa6c3e..ec0d2202216c3fcff64f06a950de37b47d5fd4d8 100644 (file)
@@ -19,6 +19,8 @@
 #include <ao_exti.h>
 #include "ao_ms5607.h"
 
+#if HAS_MS5607
+
 static struct ao_ms5607_prom   ms5607_prom;
 static uint8_t                 ms5607_configured;
 
@@ -134,11 +136,18 @@ ao_ms5607_get_sample(uint8_t cmd) {
        ao_ms5607_start();
        ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX);
        ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO);
+#if AO_MS5607_PRIVATE_PINS
+       ao_spi_put(AO_MS5607_SPI_INDEX);
+#endif
        cli();
        while (!ao_ms5607_done)
                ao_sleep(&ao_ms5607_done);
        sei();
+#if AO_MS5607_PRIVATE_PINS
+       stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1);
+#else
        ao_ms5607_stop();
+#endif
 
        ao_ms5607_start();
        read = AO_MS5607_ADC_READ;
@@ -194,22 +203,17 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value
        value->temp = TEMP;
 }
 
-struct ao_ms5607_sample        ao_ms5607_current;
-uint8_t ao_ms5607_valid;
-
 static void
 ao_ms5607(void)
 {
        ao_ms5607_setup();
        for (;;)
        {
-               static struct ao_ms5607_sample  ao_ms5607_next;
-               ao_ms5607_sample(&ao_ms5607_next);
+               ao_ms5607_sample((struct ao_ms5607_sample *) &ao_data_ring[ao_data_head].ms5607_raw);
                ao_arch_critical(
-                       ao_ms5607_current = ao_ms5607_next;
-                       ao_ms5607_valid = 1;
+                       AO_DATA_PRESENT(AO_DATA_MS5607);
+                       AO_DATA_WAIT();
                        );
-               ao_delay(0);
        }
 }
 
@@ -231,13 +235,13 @@ ao_ms5607_info(void)
 static void
 ao_ms5607_dump(void)
 {
-       struct ao_ms5607_sample sample;
+       struct ao_data  sample;
        struct ao_ms5607_value value;
 
-       sample = ao_ms5607_current;
-       ao_ms5607_convert(&sample, &value);
-       printf ("Pressure:    %8u %8d\n", sample.pres, value.pres);
-       printf ("Temperature: %8u %8d\n", sample.temp, value.temp);
+       ao_data_get(&sample);
+       ao_ms5607_convert(&sample.ms5607_raw, &value);
+       printf ("Pressure:    %8u %8d\n", sample.ms5607_raw.pres, value.pres);
+       printf ("Temperature: %8u %8d\n", sample.ms5607_raw.temp, value.temp);
        printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres));
 }
 
@@ -250,7 +254,6 @@ void
 ao_ms5607_init(void)
 {
        ms5607_configured = 0;
-       ao_ms5607_valid = 0;
        ao_cmd_register(&ao_ms5607_cmds[0]);
        ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS));
 
@@ -272,3 +275,5 @@ ao_ms5607_init(void)
                      AO_MS5607_MISO,
                      STM_MODER_ALTERNATE);
 }
+
+#endif
index fa3b1c5b83df662386411e1a36d7439b2e7c29b9..e9c364d900917f7149289e43182b3e930e035cfa 100644 (file)
@@ -51,9 +51,6 @@ struct ao_ms5607_sample {
        uint32_t        temp;   /* raw 24 bit sensor */
 };
 
-extern uint8_t ao_ms5607_valid;
-extern struct ao_ms5607_sample ao_ms5607_current;
-
 struct ao_ms5607_value {
        int32_t         pres;   /* in Pa * 10 */
        int32_t         temp;   /* in °C * 100 */
diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c
new file mode 100644 (file)
index 0000000..cd901aa
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_74hc497.h>
+#include <ao_radio_cmac.h>
+
+static __xdata uint8_t ao_pad_ignite;
+static __xdata struct ao_pad_command   command;
+static __xdata struct ao_pad_query     query;
+
+#if 1
+#define PRINTD(...) printf(__VA_ARGS__)
+#define FLUSHD()    flush()
+#else
+#define PRINTD(...) 
+#define FLUSHD()    
+#endif
+
+static void
+ao_pad_run(void)
+{
+       for (;;) {
+               while (!ao_pad_ignite)
+                       ao_sleep(&ao_pad_ignite);
+               /*
+                * Actually set the pad bits
+                */
+               AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | ao_pad_ignite;
+               while (ao_pad_ignite) {
+                       ao_pad_ignite = 0;
+                       ao_delay(AO_PAD_FIRE_TIME);
+               }
+               AO_PAD_PORT &= ~(AO_PAD_ALL_PINS);
+       }
+}
+
+static void
+ao_pad_monitor(void)
+{
+       uint8_t                 c;
+       uint8_t                 sample;
+       __pdata uint8_t         prev = 0, cur = 0;
+       __pdata uint8_t         beeping = 0;
+       __xdata struct ao_data  *packet;
+
+       sample = ao_data_head;
+       for (;;) {
+               __pdata int16_t                 pyro;
+               ao_arch_critical(
+                       while (sample == ao_data_head)
+                               ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
+                       );
+
+               packet = &ao_data_ring[sample];
+               sample = ao_data_ring_next(sample);
+
+               pyro = packet->adc.pyro;
+
+#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0))
+
+               cur = 0;
+               if (pyro > VOLTS_TO_PYRO(4))
+                       query.arm_status = AO_PAD_ARM_STATUS_ARMED;
+               else if (pyro < VOLTS_TO_PYRO(1))
+                       query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
+               else
+                       query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
+
+               for (c = 0; c < AO_PAD_NUM; c++) {
+                       int16_t         sense = packet->adc.sense[c];
+                       uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN;
+
+                       if (query.arm_status == AO_PAD_ARM_STATUS_ARMED) {
+                               /*
+                                *      pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20
+                                *      v_pyro = pyro * 127 / 27
+                                *
+                                *              v_pyro \
+                                *      100k            igniter
+                                *              output /        
+                                *      100k           \
+                                *              sense   relay
+                                *      27k            / 
+                                *              gnd ---   
+                                *
+                                *      If the relay is closed, then sense will be 0
+                                *      If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
+                                *      If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
+                                */
+
+                               if (sense <= pyro / 8)
+                                       status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
+                               else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
+                                       status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+                               else if (pyro / 8 * 7 <= sense) {
+                                       status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+                                       cur |= AO_LED_CONTINUITY(c);
+                               }
+                       }
+                       query.igniter_status[c] = status;
+               }
+               if (cur != prev) {
+                       ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK);
+                       prev = cur;
+               }
+
+               if (pyro > VOLTS_TO_PYRO(9) && sample == 0) {
+                       beeping = 1;
+                       ao_beep(AO_BEEP_HIGH);
+               } else if (beeping) {
+                       beeping = 0;
+                       ao_beep(0);
+               }
+       }
+}
+
+static __pdata uint8_t ao_pad_armed;
+static __pdata uint16_t        ao_pad_arm_time;
+static __pdata uint8_t ao_pad_box;
+static __xdata uint8_t ao_pad_disabled;
+
+void
+ao_pad_disable(void)
+{
+       if (!ao_pad_disabled) {
+               ao_pad_disabled = 1;
+               ao_radio_recv_abort();
+       }
+}
+
+void
+ao_pad_enable(void)
+{
+       ao_pad_disabled = 0;
+       ao_wakeup (&ao_pad_disabled);
+}
+
+static void
+ao_pad(void)
+{
+       int16_t time_difference;
+       int8_t  ret;
+
+       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+       ao_pad_box = 0;
+       ao_led_set(0);
+       ao_led_on(AO_LED_POWER);
+       for (;;) {
+               FLUSHD();
+               while (ao_pad_disabled)
+                       ao_sleep(&ao_pad_disabled);
+               ret = ao_radio_cmac_recv(&command, sizeof (command), 0);
+               PRINTD ("cmac_recv %d\n", ret);
+               if (ret != AO_RADIO_CMAC_OK)
+                       continue;
+               
+               PRINTD ("tick %d box %d cmd %d channels %02x\n",
+                       command.tick, command.box, command.cmd, command.channels);
+
+               switch (command.cmd) {
+               case AO_LAUNCH_ARM:
+                       if (command.box != ao_pad_box) {
+                               PRINTD ("box number mismatch\n");
+                               break;
+                       }
+
+                       if (command.channels & ~(AO_PAD_ALL_PINS))
+                               break;
+
+                       time_difference = command.tick - ao_time();
+                       PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time());
+                       if (time_difference < 0)
+                               time_difference = -time_difference;
+                       if (time_difference > 10) {
+                               PRINTD ("time difference too large %d\n", time_difference);
+                               break;
+                       }
+                       PRINTD ("armed\n");
+                       ao_pad_armed = command.channels;
+                       ao_pad_arm_time = ao_time();
+
+                       /* fall through ... */
+
+               case AO_LAUNCH_QUERY:
+                       if (command.box != ao_pad_box) {
+                               PRINTD ("box number mismatch\n");
+                               break;
+                       }
+
+                       query.tick = ao_time();
+                       query.box = ao_pad_box;
+                       query.channels = AO_PAD_ALL_PINS;
+                       query.armed = ao_pad_armed;
+                       PRINTD ("query tick %d box %d channels %02x arm %d arm_status %d igniter %d,%d,%d,%d\n",
+                               query.tick, query.box, query.channels, query.armed,
+                               query.arm_status,
+                               query.igniter_status[0],
+                               query.igniter_status[1],
+                               query.igniter_status[2],
+                               query.igniter_status[3]);
+                       ao_radio_cmac_send(&query, sizeof (query));
+                       break;
+               case AO_LAUNCH_FIRE:
+                       if (!ao_pad_armed) {
+                               PRINTD ("not armed\n");
+                               break;
+                       }
+                       if ((uint16_t) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) {
+                               PRINTD ("late pad arm_time %d time %d\n",
+                                       ao_pad_arm_time, ao_time());
+                               break;
+                       }
+                       time_difference = command.tick - ao_time();
+                       if (time_difference < 0)
+                               time_difference = -time_difference;
+                       if (time_difference > 10) {
+                               PRINTD ("time different too large %d\n", time_difference);
+                               break;
+                       }
+                       PRINTD ("ignite\n");
+                       ao_pad_ignite = ao_pad_armed;
+                       ao_wakeup(&ao_pad_ignite);
+                       break;
+               }
+       }
+}
+
+void
+ao_pad_test(void)
+{
+       uint8_t c;
+
+       printf ("Arm switch: ");
+       switch (query.arm_status) {
+       case AO_PAD_ARM_STATUS_ARMED:
+               printf ("Armed\n");
+               break;
+       case AO_PAD_ARM_STATUS_DISARMED:
+               printf ("Disarmed\n");
+               break;
+       case AO_PAD_ARM_STATUS_UNKNOWN:
+               printf ("Unknown\n");
+               break;
+       }
+
+       for (c = 0; c < AO_PAD_NUM; c++) {
+               printf ("Pad %d: ");
+               switch (query.igniter_status[c]) {
+               case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED:     printf ("No igniter. Relay closed\n"); break;
+               case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN:       printf ("No igniter. Relay open\n"); break;
+               case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN:     printf ("Good igniter. Relay open\n"); break;
+               case AO_PAD_IGNITER_STATUS_UNKNOWN:                     printf ("Unknown\n"); break;
+               }
+       }
+}
+
+void
+ao_pad_manual(void)
+{
+       ao_cmd_white();
+       if (!ao_match_word("DoIt"))
+               return;
+       ao_cmd_decimal();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_pad_ignite = 1 << ao_cmd_lex_i;
+       ao_wakeup(&ao_pad_ignite);
+}
+
+static __xdata struct ao_task ao_pad_task;
+static __xdata struct ao_task ao_pad_ignite_task;
+static __xdata struct ao_task ao_pad_monitor_task;
+
+__code struct ao_cmds ao_pad_cmds[] = {
+       { ao_pad_test,  "t\0Test pad continuity" },
+       { ao_pad_manual,        "i <key> <n>\0Fire igniter. <key> is doit with D&I" },
+       { 0, NULL }
+};
+
+void
+ao_pad_init(void)
+{
+#if AO_PAD_NUM > 0
+       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0);
+#endif
+#if AO_PAD_NUM > 1
+       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0);
+#endif
+#if AO_PAD_NUM > 2
+       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0);
+#endif
+#if AO_PAD_NUM > 3
+       ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0);
+#endif
+       ao_cmd_register(&ao_pad_cmds[0]);
+       ao_add_task(&ao_pad_task, ao_pad, "pad listener");
+       ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter");
+       ao_add_task(&ao_pad_monitor_task, ao_pad_monitor, "pad monitor");
+}
diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h
new file mode 100644 (file)
index 0000000..3b0cf1f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PAD_H_
+#define _AO_PAD_H_
+
+#define AO_PAD_MAX_CHANNELS    8
+
+struct ao_pad_command {
+       uint16_t        tick;
+       uint16_t        box;
+       uint8_t         cmd;
+       uint8_t         channels;
+};
+
+/* Report current telefire status.
+ */
+
+#define AO_PAD_QUERY           1
+
+struct ao_pad_query {
+       uint16_t        tick;           /* telefire tick */
+       uint16_t        box;            /* telefire box number */
+       uint8_t         channels;       /* which chanels are present */
+       uint8_t         armed;          /* which channels are armed */
+       uint8_t         arm_status;     /* status of arming switch */
+       uint8_t         igniter_status[AO_PAD_MAX_CHANNELS];    /* status for each igniter */
+};
+
+/* Set current armed pads, report back status
+ */
+  
+#define AO_PAD_ARM             2
+
+/* Fire current armed pads for 200ms, no report
+ */
+#define AO_PAD_FIRE            3
+
+#define AO_PAD_FIRE_TIME       AO_MS_TO_TICKS(1000)
+
+#define AO_PAD_ARM_STATUS_DISARMED     0
+#define AO_PAD_ARM_STATUS_ARMED                1
+#define AO_PAD_ARM_STATUS_UNKNOWN      2
+
+#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN    0
+#define AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN  1
+#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED  2
+#define AO_PAD_IGNITER_STATUS_UNKNOWN                  3
+
+void
+ao_pad_init(void);
+
+void
+ao_pad_disable(void);
+
+void
+ao_pad_enable(void);
+
+#endif /* _AO_PAD_H_ */
diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c
new file mode 100644 (file)
index 0000000..6d8d18d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/*
+ * PCA9922 LED driver. This uses SPI to send a single byte to the device to
+ * set the current state of the LEDs using the existing LED interface
+ */
+
+#include <ao.h>
+
+static __xdata uint8_t ao_led_state;
+
+static void
+ao_led_apply(void)
+{
+       /* Don't try the SPI bus during initialization */
+       if (!ao_cur_task)
+               return;
+       ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST);
+       ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS);
+       ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS);
+}
+
+void
+ao_led_on(uint8_t colors)
+{
+       ao_led_state |= colors;
+       ao_led_apply();
+}
+
+void
+ao_led_off(uint8_t colors)
+{
+       ao_led_state &= ~colors;
+       ao_led_apply();
+}
+
+void
+ao_led_set(uint8_t colors)
+{
+       ao_led_state = colors;
+       ao_led_apply();
+}
+
+void
+ao_led_set_mask(uint8_t colors, uint8_t mask)
+{
+       ao_led_state = (ao_led_state & ~mask) | (colors & mask);
+       ao_led_apply();
+}
+
+void
+ao_led_toggle(uint8_t colors)
+{
+       ao_led_state ^= colors;
+       ao_led_apply();
+}
+
+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)
+{
+       (void) enable;
+       ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1);
+}
diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c
new file mode 100644 (file)
index 0000000..6cc2467
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_quadrature.h>
+#include <ao_exti.h>
+#if AO_EVENT
+#include <ao_event.h>
+#define ao_quadrature_queue(q) ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q])
+#else
+#define ao_quadrature_queue(q)
+#endif
+
+__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
+
+static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
+
+#define BIT(a,b)       ((a) | ((b) << 1))
+#define STATE(old_a, old_b, new_a, new_b)      (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b)))
+
+#define port(q)        AO_QUADRATURE_ ## q ## _PORT
+#define bita(q) AO_QUADRATURE_ ## q ## _A
+#define bitb(q) AO_QUADRATURE_ ## q ## _B
+
+#define ao_quadrature_update(q) do {                                   \
+               ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \
+               ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \
+               ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \
+       } while (0)
+       
+
+static void
+ao_quadrature_isr(void)
+{
+       uint8_t q;
+#if AO_QUADRATURE_COUNT > 0
+       ao_quadrature_update(0);
+#endif
+#if AO_QUADRATURE_COUNT > 1
+       ao_quadrature_update(1);
+#endif
+
+       for (q = 0; q < AO_QUADRATURE_COUNT; q++) {
+               switch (ao_quadrature_state[q]) {
+               case STATE(0, 1, 0, 0):
+                       ao_quadrature_count[q]++;
+                       break;
+               case STATE(1, 0, 0, 0):
+                       ao_quadrature_count[q]--;
+                       break;
+               default:
+                       continue;
+               }
+               ao_quadrature_queue(q);
+               ao_wakeup(&ao_quadrature_count[q]);
+       }
+}
+
+int32_t
+ao_quadrature_poll(uint8_t q)
+{
+       int32_t ret;
+       ao_arch_critical(ret = ao_quadrature_count[q];);
+       return ret;
+}
+
+int32_t
+ao_quadrature_wait(uint8_t q)
+{
+       ao_sleep(&ao_quadrature_count[q]);
+       return ao_quadrature_poll(q);
+}
+
+static void
+ao_quadrature_test(void)
+{
+       uint8_t q;
+
+       ao_cmd_decimal();
+       q = ao_cmd_lex_i;
+       for (;;) {
+               int32_t c;
+               flush();
+               c = ao_quadrature_wait(q);
+               printf ("new count %6d\n", c);
+               if (c == 100)
+                       break;
+       }
+}
+
+static const struct ao_cmds ao_quadrature_cmds[] = {
+       { ao_quadrature_test,   "q <unit>\0Test quadrature" },
+       { 0, NULL }
+};
+
+#define init(q) do {                                                   \
+               ao_enable_port(port(q));                                \
+                                                                       \
+               ao_exti_setup(port(q), bita(q),                         \
+                             AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
+                             ao_quadrature_isr);                       \
+               ao_exti_enable(port(q), bita(q));                       \
+                                                                       \
+               ao_exti_setup(port(q), bitb(q),                         \
+                             AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
+                             ao_quadrature_isr);                       \
+               ao_exti_enable(port(q), bitb(q));                       \
+       } while (0)
+
+void
+ao_quadrature_init(void)
+{
+#if AO_QUADRATURE_COUNT > 0
+       init(0);
+#endif
+#if AO_QUADRATURE_COUNT > 1
+       init(1);
+#endif
+       ao_cmd_register(&ao_quadrature_cmds[0]);
+}
diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h
new file mode 100644 (file)
index 0000000..d7dda68
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_QUADRATURE_H_
+#define _AO_QUADRATURE_H_
+
+extern __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
+
+int32_t
+ao_quadrature_wait(uint8_t q);
+
+int32_t
+ao_quadrature_poll(uint8_t q);
+
+void
+ao_quadrature_init(void);
+
+#endif /* _AO_QUADRATURE_H_ */
diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c
new file mode 100644 (file)
index 0000000..73ac3c0
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_spi.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac.h>
+
+static __xdata struct ao_radio_spi_reply       ao_radio_spi_reply;
+static __xdata struct ao_radio_spi_request     ao_radio_spi_request;
+static volatile __xdata uint8_t                        ao_radio_wait_mode;
+static volatile __xdata uint8_t                        ao_radio_done = 0;
+static volatile __xdata uint8_t                        ao_radio_ready = 1;
+static __xdata uint8_t                         ao_radio_mutex;
+static __xdata uint8_t                         ao_radio_aes_seq;
+
+__xdata int8_t                                 ao_radio_cmac_rssi;
+
+#if 0
+#define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(...) 
+#endif
+
+static void
+ao_radio_isr(void)
+{
+       if (ao_gpio_get(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, AO_RADIO_INT)) {
+               ao_radio_ready = 1;
+               ao_wakeup((void *) &ao_radio_ready);
+       } else {
+               ao_radio_done = 1;
+               ao_wakeup((void *) &ao_radio_done);
+       }
+}
+
+static void
+ao_radio_master_start(void)
+{
+       ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
+                      AO_RADIO_SPI_BUS,
+                      AO_SPI_SPEED_200kHz);
+}
+
+static void
+ao_radio_master_stop(void)
+{
+       ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
+                      AO_RADIO_SPI_BUS);
+}
+
+static uint8_t
+ao_radio_master_send(void)
+{
+       uint8_t ret;
+
+       PRINTD("send %d\n", ao_radio_spi_request.len);
+       ao_radio_done = 0;
+
+       /* Wait for radio chip to be ready for a command
+        */
+
+       PRINTD("Waiting radio ready\n");
+       cli();
+       ao_radio_ready = ao_gpio_get(AO_RADIO_INT_PORT,
+                                    AO_RADIO_INT_PIN, AO_RADIO_INT);
+       ret = 0;
+       while (!ao_radio_ready) {
+               ret = ao_sleep((void *) &ao_radio_ready);
+               if (ret)
+                       break;
+       }
+       sei();
+       if (ret)
+               return 0;
+
+       PRINTD("radio_ready %d radio_done %d\n", ao_radio_ready, ao_radio_done);
+
+       /* Send the command
+        */
+       ao_radio_wait_mode = 0;
+       ao_radio_master_start();
+       ao_spi_send(&ao_radio_spi_request,
+                   ao_radio_spi_request.len,
+                   AO_RADIO_SPI_BUS);
+       ao_radio_master_stop();
+       PRINTD("waiting for send done %d\n", ao_radio_done);
+       cli();
+       while (!ao_radio_done)
+               if (ao_sleep((void *) &ao_radio_done))
+                       break;
+       sei();
+       PRINTD ("sent, radio done %d isr_0 %d isr_1 %d\n", ao_radio_done, isr_0_count, isr_1_count);
+       return ao_radio_done;
+}
+
+static void
+ao_radio_get(uint8_t req, uint8_t len)
+{
+       ao_config_get();
+       ao_mutex_get(&ao_radio_mutex);
+       ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN + len;
+       ao_radio_spi_request.request = req;
+       ao_radio_spi_request.setting = ao_config.radio_setting;
+}
+
+static void
+ao_radio_put(void)
+{
+       ao_mutex_put(&ao_radio_mutex);
+}
+
+static void
+ao_radio_get_data(__xdata void *d, uint8_t size)
+{
+       PRINTD ("fetch\n");
+       ao_radio_master_start();
+       ao_spi_recv(&ao_radio_spi_reply,
+                   AO_RADIO_SPI_REPLY_HEADER_LEN + size,
+                   AO_RADIO_SPI_BUS);
+       ao_radio_master_stop();
+       ao_xmemcpy(d, ao_radio_spi_reply.payload, size);
+       PRINTD ("fetched %d\n", size);
+}
+
+void
+ao_radio_recv_abort(void)
+{
+       ao_radio_get(AO_RADIO_SPI_RECV_ABORT, 0);
+       ao_radio_master_send();
+       ao_radio_put();
+}
+
+void
+ao_radio_send(const void *d, uint8_t size)
+{
+       ao_radio_get(AO_RADIO_SPI_SEND, size);
+       ao_xmemcpy(&ao_radio_spi_request.payload, d, size);
+       ao_radio_master_send();
+       ao_radio_put();
+}
+
+
+uint8_t
+ao_radio_recv(__xdata void *d, uint8_t size)
+{
+       int8_t  ret;
+       uint8_t recv;
+
+       /* Recv the data
+        */
+       
+       ao_radio_get(AO_RADIO_SPI_RECV, 0);
+       ao_radio_spi_request.recv_len = size;
+       recv = ao_radio_master_send();
+       if (!recv) {
+               ao_radio_put();
+               ao_radio_recv_abort();
+               return 0;
+       }
+       ao_radio_get_data(d, size);
+       recv = ao_radio_spi_reply.status;
+       ao_radio_put();
+
+       return recv;
+}
+
+static void
+ao_radio_cmac_set_key(void)
+{
+       if (ao_radio_aes_seq == ao_config_aes_seq)
+               return;
+       /* Set the key.
+        */
+       PRINTD ("set key\n");
+       ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
+       ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
+       ao_radio_master_send();
+       ao_radio_put();
+       PRINTD ("key set\n");
+       ao_radio_aes_seq = ao_config_aes_seq;
+}
+
+int8_t
+ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant
+{
+       if (len > AO_CMAC_MAX_LEN)
+               return AO_RADIO_CMAC_LEN_ERROR;
+
+       ao_radio_cmac_set_key();
+
+       PRINTD ("cmac_send: send %d\n", len);
+
+       /* Send the data
+        */
+       
+       PRINTD ("sending packet\n");
+       ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len);
+       ao_xmemcpy(&ao_radio_spi_request.payload, packet, len);
+       ao_radio_master_send();
+       ao_radio_put();
+       PRINTD ("packet sent\n");
+       return AO_RADIO_CMAC_OK;
+}
+
+int8_t
+ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
+{
+       int8_t  ret;
+       int8_t  recv;
+
+       if (len > AO_CMAC_MAX_LEN)
+               return AO_RADIO_CMAC_LEN_ERROR;
+
+       ao_radio_cmac_set_key();
+
+       /* Recv the data
+        */
+       PRINTD ("queuing recv\n");
+       ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0);
+       ao_radio_spi_request.recv_len = len;
+       ao_radio_spi_request.timeout = timeout;
+       recv = ao_radio_master_send();
+       PRINTD ("recv queued: %d\n", recv);
+       if (!recv) {
+               ao_radio_put();
+               ao_radio_recv_abort();
+               return AO_RADIO_CMAC_TIMEOUT;
+       }
+
+       PRINTD ("fetching data\n");
+       ao_radio_get_data(packet, len);
+       recv = ao_radio_spi_reply.status;
+       ao_radio_cmac_rssi = ao_radio_spi_reply.rssi;
+       ao_radio_put();
+       PRINTD ("data fetched: %d %d\n", recv, ao_radio_cmac_rssi);
+       return recv;
+}
+
+static uint8_t ao_radio_test_on;
+
+void
+ao_radio_test(uint8_t on)
+{
+       if (on) {
+               if (!ao_radio_test_on) {
+                       ao_radio_get(AO_RADIO_SPI_TEST_ON, 0);
+                       ao_radio_test_on = 1;
+                       ao_radio_master_send();
+               }
+       } else {
+               if (ao_radio_test_on) {
+                       ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN;
+                       ao_radio_spi_request.request = AO_RADIO_SPI_TEST_OFF;
+                       ao_radio_master_send();
+                       ao_radio_test_on = 0;
+                       ao_radio_put();
+               }
+       }
+}
+
+static void
+ao_radio_test_cmd(void)
+{
+       uint8_t mode = 2;
+       ao_cmd_white();
+       if (ao_cmd_lex_c != '\n') {
+               ao_cmd_decimal();
+               mode = (uint8_t) ao_cmd_lex_u32;
+       }
+       mode++;
+       if ((mode & 2))
+               ao_radio_test(1);
+       if (mode == 3) {
+               printf ("Hit a character to stop..."); flush();
+               getchar();
+               putchar('\n');
+       }
+       if ((mode & 1))
+               ao_radio_test(0);
+}
+
+__code struct ao_cmds ao_radio_cmds[] = {
+       { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
+       { 0,    NULL },
+};
+
+void
+ao_radio_init(void)
+{
+       ao_spi_init_cs(AO_RADIO_CS_PORT, (1 << AO_RADIO_CS_PIN));
+
+       ao_enable_port(AO_RADIO_INT_PORT);
+       ao_exti_setup(AO_RADIO_INT_PORT,
+                     AO_RADIO_INT_PIN,
+                     AO_EXTI_MODE_RISING|AO_EXTI_MODE_FALLING,
+                     ao_radio_isr);
+       ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
+       ao_cmd_register(&ao_radio_cmds[0]);
+}
diff --git a/src/drivers/ao_radio_slave.c b/src/drivers/ao_radio_slave.c
new file mode 100644 (file)
index 0000000..9a01bbf
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_spi.h>
+#include <ao_radio_cmac.h>
+
+static __xdata struct ao_radio_spi_reply ao_radio_spi_reply;
+
+static __xdata struct ao_radio_spi_request ao_radio_spi_request;
+
+static __xdata uint8_t slave_state;
+
+static void
+ao_radio_slave_low(void)
+{
+       uint16_t        i;
+
+       if (slave_state != 1)
+               ao_panic(1);
+       ao_led_toggle(AO_LED_GREEN);
+       ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0);
+       for (i = 0; i < 1000; i++)
+               ao_arch_nop();
+       slave_state = 0;
+}
+
+static void
+ao_radio_slave_high(void)
+{
+       if (slave_state != 0)
+               ao_panic(2);
+       ao_led_toggle(AO_LED_RED);
+       ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1);
+       slave_state = 1;
+}
+
+static void
+ao_radio_slave_spi(void)
+{
+       ao_spi_get_slave(AO_RADIO_SLAVE_BUS);
+       for (;;) {
+               ao_spi_recv(&ao_radio_spi_request,
+                           (2 << 13) | sizeof (ao_radio_spi_request),
+                           AO_RADIO_SLAVE_BUS);
+               ao_radio_slave_high();
+               ao_spi_recv_wait();
+               switch (ao_radio_spi_request.request) {
+               case AO_RADIO_SPI_RECV:
+
+                       /* XXX monitor CS to interrupt the receive */
+
+                       ao_config.radio_setting = ao_radio_spi_request.setting;
+                       ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload,
+                                                                 ao_radio_spi_request.recv_len);
+                       ao_radio_spi_reply.rssi = 0;
+                       ao_spi_send(&ao_radio_spi_reply,
+                                   AO_RADIO_SPI_REPLY_HEADER_LEN + ao_radio_spi_request.recv_len,
+                                   AO_RADIO_SLAVE_BUS);
+                       ao_radio_slave_low();
+                       ao_spi_send_wait();
+                       continue;
+               case AO_RADIO_SPI_CMAC_RECV:
+                       ao_config.radio_setting = ao_radio_spi_request.setting;
+                       ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload,
+                                                                      ao_radio_spi_request.recv_len,
+                                                                      ao_radio_spi_request.timeout);
+                       ao_radio_spi_reply.rssi = ao_radio_cmac_rssi;
+                       ao_spi_send(&ao_radio_spi_reply,
+                                   AO_RADIO_SPI_REPLY_HEADER_LEN + ao_radio_spi_request.recv_len,
+                                   AO_RADIO_SLAVE_BUS);
+                       ao_radio_slave_low();
+                       ao_spi_send_wait();
+                       continue;
+               case AO_RADIO_SPI_SEND:
+                       ao_config.radio_setting = ao_radio_spi_request.setting;
+                       ao_radio_send(&ao_radio_spi_request.payload,
+                                     ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN);
+                       break;
+
+               case AO_RADIO_SPI_CMAC_SEND:
+                       ao_config.radio_setting = ao_radio_spi_request.setting;
+                       ao_radio_cmac_send(&ao_radio_spi_request.payload,
+                                          ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN);
+                       break;
+                       
+               case AO_RADIO_SPI_CMAC_KEY:
+                       ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN);
+                       break;
+
+               case AO_RADIO_SPI_TEST_ON:
+                       ao_config.radio_setting = ao_radio_spi_request.setting;
+                       ao_radio_test(1);
+                       break;
+
+               case AO_RADIO_SPI_TEST_OFF:
+                       ao_radio_test(0);
+                       break;
+               }
+               ao_radio_slave_low();
+       }
+}
+
+static __xdata struct ao_task ao_radio_slave_spi_task;
+
+void
+ao_radio_slave_init(void)
+{
+       ao_add_task(&ao_radio_slave_spi_task, ao_radio_slave_spi, "radio_spi");
+       ao_enable_output(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0);
+}
diff --git a/src/drivers/ao_radio_spi.h b/src/drivers/ao_radio_spi.h
new file mode 100644 (file)
index 0000000..2957f70
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_RADIO_SPI_H_
+#define _AO_RADIO_SPI_H_
+
+#define AO_RADIO_SPI_RECV      0
+#define AO_RADIO_SPI_RECV_ABORT        1
+#define AO_RADIO_SPI_RECV_FETCH        2
+#define AO_RADIO_SPI_SEND      3
+
+#define AO_RADIO_SPI_CMAC_KEY  4
+#define AO_RADIO_SPI_CMAC_RECV 5
+#define AO_RADIO_SPI_CMAC_SEND 6
+
+#define AO_RADIO_SPI_TEST_ON   7
+#define AO_RADIO_SPI_TEST_OFF  8
+
+#define AO_RADIO_SPI_MAX_PAYLOAD       128
+
+struct ao_radio_spi_request {
+       uint8_t         len;            /* required to be first by cc1111 DMA engine */
+       uint8_t         request;
+       uint8_t         recv_len;
+       uint8_t         pad;
+       uint32_t        setting;
+       uint16_t        timeout;
+       uint8_t         payload[AO_RADIO_SPI_MAX_PAYLOAD];
+};
+
+#define AO_RADIO_SPI_REQUEST_HEADER_LEN        (sizeof (struct ao_radio_spi_request) - AO_RADIO_SPI_MAX_PAYLOAD)
+
+struct ao_radio_spi_reply {
+       uint8_t         status;
+       int8_t          rssi;
+       uint8_t         payload[AO_RADIO_SPI_MAX_PAYLOAD];
+};
+
+#define AO_RADIO_SPI_REPLY_HEADER_LEN  (sizeof (struct ao_radio_spi_reply) - AO_RADIO_SPI_MAX_PAYLOAD)
+
+void
+ao_radio_slave_init(void);
+
+#endif /* _AO_RADIO_SPI_H_ */
diff --git a/src/drivers/ao_seven_segment.c b/src/drivers/ao_seven_segment.c
new file mode 100644 (file)
index 0000000..b3b5f87
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_seven_segment.h>
+#include <ao_lcd_stm.h>
+
+/*
+ *         0
+ *     -------
+ *     |       |  
+ *   1 |       | 2
+ *     |   3   |
+ *      -------
+ *     |       |
+ *   4 |       | 5
+ *     |   6   |
+ *      -------
+ *              [] 7
+ *
+ */
+
+static const uint8_t ao_segments[] = {
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (0 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 0 */
+
+       (0 << AO_SEGMENT_0) |
+       (0 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (0 << AO_SEGMENT_3) |
+       (0 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (0 << AO_SEGMENT_6),            /* 1 */
+
+       (1 << AO_SEGMENT_0) |
+       (0 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (0 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 2 */
+
+       (1 << AO_SEGMENT_0) |
+       (0 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (0 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 3 */
+
+       (0 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (0 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (0 << AO_SEGMENT_6),            /* 4 */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (0 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (0 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 5 */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (0 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 6 */
+
+       (1 << AO_SEGMENT_0) |
+       (0 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (0 << AO_SEGMENT_3) |
+       (0 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (0 << AO_SEGMENT_6),            /* 7 */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 8 */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (0 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* 9 */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (0 << AO_SEGMENT_6),            /* A */
+
+       (0 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (0 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* b */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (0 << AO_SEGMENT_2) |
+       (0 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (0 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* c */
+
+       (0 << AO_SEGMENT_0) |
+       (0 << AO_SEGMENT_1) |
+       (1 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (1 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* d */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (0 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (0 << AO_SEGMENT_5) |
+       (1 << AO_SEGMENT_6),            /* E */
+
+       (1 << AO_SEGMENT_0) |
+       (1 << AO_SEGMENT_1) |
+       (0 << AO_SEGMENT_2) |
+       (1 << AO_SEGMENT_3) |
+       (1 << AO_SEGMENT_4) |
+       (0 << AO_SEGMENT_5) |
+       (0 << AO_SEGMENT_6),            /* F */
+};
+
+void
+ao_seven_segment_set(uint8_t digit, uint8_t value)
+{
+       uint8_t s;
+       uint8_t segments;
+
+       if (value == AO_SEVEN_SEGMENT_CLEAR)
+               segments = 0;
+       else {
+               segments = ao_segments[value & 0xf];
+
+               /* Check for decimal point */
+               if (value & 0x10)
+                       segments |= (1 << AO_SEGMENT_7);
+       }
+
+       for (s = 0; s <= 7; s++)
+               ao_lcd_set(digit, s, !!(segments & (1 << s)));
+       ao_lcd_flush();
+}
+
+void
+ao_seven_segment_clear(void)
+{
+       ao_lcd_clear();
+}
+
+
+#if 0
+static void
+ao_seven_segment_show(void)
+{
+       uint8_t digit, value;
+       ao_cmd_decimal();
+       digit = ao_cmd_lex_i;
+       ao_cmd_decimal();
+       value = ao_cmd_lex_i;
+       ao_seven_segment_set(digit, value);
+}
+
+
+static const struct ao_cmds ao_seven_segment_cmds[] = {
+       { ao_seven_segment_show,        "S <digit> <value>\0Set LCD digit" },
+       { 0, NULL },
+};
+#endif
+
+void
+ao_seven_segment_init(void)
+{
+#if 0
+       ao_cmd_register(ao_seven_segment_cmds);
+#endif
+}
diff --git a/src/drivers/ao_seven_segment.h b/src/drivers/ao_seven_segment.h
new file mode 100644 (file)
index 0000000..5b29dea
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SEVEN_SEGMENT_H_
+#define _AO_SEVEN_SEGMENT_H_
+
+#define AO_SEVEN_SEGMENT_DECIMAL       0x10
+
+#define AO_SEVEN_SEGMENT_CLEAR         0xff
+
+void
+ao_seven_segment_set(uint8_t digit, uint8_t value);
+
+void
+ao_seven_segment_clear(void);
+
+void
+ao_seven_segment_init(void);
+
+#endif /* _AO_SEVEN_SEGMENT_H_ */
index 4a4c983ac544d701f4299851e7f5d11c885fddb6..a93f6f1742d856ad19a36718a1590a4f04007ab1 100644 (file)
@@ -19,6 +19,7 @@ INC = \
        ao_ms5607.h \
        ao_hmc5883.h \
        ao_mpu6000.h \
+       ao_mma655x.h \
        ao_cc1120_CC1120.h \
        ao_profile.h \
        ao_whiten.h \
@@ -55,7 +56,10 @@ ALTOS_SRC = \
        ao_cc1120.c \
        ao_fec_tx.c \
        ao_fec_rx.c \
+       ao_data.c \
        ao_ms5607.c \
+       ao_mma655x.c \
+       ao_hmc5883.c \
        ao_adc_stm.c \
        ao_beep_stm.c \
        ao_storage.c \
index 55324514cb062d3b0eba7720279dda4ea7917e20..d3ae4690c41de2e85c9ea4b402fb35cc8e009d48 100644 (file)
@@ -18,6 +18,7 @@
 #include <ao.h>
 #include <ao_hmc5883.h>
 #include <ao_mpu6000.h>
+#include <ao_mma655x.h>
 #include <ao_log.h>
 #include <ao_exti.h>
 #include <ao_packet.h>
@@ -53,6 +54,9 @@ main(void)
 #if HAS_MPU6000
        ao_mpu6000_init();
 #endif
+#if HAS_MMA655X
+       ao_mma655x_init();
+#endif
 
        ao_storage_init();
        
index 6b0f9832f669696ce411c09a4a66a83f6cd56527..8b631ae970dff80f19787919843a9c7d30fc5adb 100644 (file)
 #define HAS_TELEMETRY          1
 
 #define HAS_SPI_1              1
-#define SPI_1_PA5_PA6_PA7      1
+#define SPI_1_PA5_PA6_PA7      1       /* Barometer */
 #define SPI_1_PB3_PB4_PB5      0
-#define SPI_1_PE13_PE14_PE15   0
+#define SPI_1_PE13_PE14_PE15   1       /* Accelerometer */
 
 #define HAS_SPI_2              1
-#define SPI_2_PB13_PB14_PB15   1
+#define SPI_2_PB13_PB14_PB15   1       /* Flash, Companion */
 #define SPI_2_PD1_PD3_PD4      0
+
 #define SPI_2_GPIO             (&stm_gpiob)
 #define SPI_2_SCK              13
 #define SPI_2_MISO             14
@@ -247,13 +248,14 @@ struct ao_adc {
  * Pressure sensor settings
  */
 #define HAS_MS5607             1
+#define AO_MS5607_PRIVATE_PINS 1
 #define AO_MS5607_CS_GPIO      (&stm_gpioc)
 #define AO_MS5607_CS           4
 #define AO_MS5607_CS_MASK      (1 << AO_MS5607_CS)
 #define AO_MS5607_MISO_GPIO    (&stm_gpioa)
 #define AO_MS5607_MISO         6
 #define AO_MS5607_MISO_MASK    (1 << AO_MS5607_MISO)
-#define AO_MS5607_SPI_INDEX    (STM_SPI_INDEX(1))
+#define AO_MS5607_SPI_INDEX    AO_SPI_1_PA5_PA6_PA7
 
 /*
  * SPI Flash memory
@@ -262,7 +264,7 @@ struct ao_adc {
 #define M25_MAX_CHIPS          1
 #define AO_M25_SPI_CS_PORT     (&stm_gpiod)
 #define AO_M25_SPI_CS_MASK     (1 << 3)
-#define AO_M25_SPI_BUS         STM_SPI_INDEX(2)
+#define AO_M25_SPI_BUS         AO_SPI_2_PB13_PB14_PB15
 
 /*
  * Radio (cc1120)
@@ -275,7 +277,7 @@ struct ao_adc {
 #define AO_FEC_DEBUG           0
 #define AO_CC1120_SPI_CS_PORT  (&stm_gpioc)
 #define AO_CC1120_SPI_CS_PIN   5
-#define AO_CC1120_SPI_BUS      STM_SPI_INDEX(2)
+#define AO_CC1120_SPI_BUS      AO_SPI_2_PB13_PB14_PB15
 
 #define AO_CC1120_INT_PORT     (&stm_gpioc)
 #define AO_CC1120_INT_PIN      14
@@ -303,6 +305,15 @@ struct ao_adc {
 
 #define HAS_HIGHG_ACCEL                0
 
+/*
+ * mma655x
+ */
+
+#define HAS_MMA655X            0
+#define AO_MMA655X_SPI_INDEX   AO_SPI_1_PA5_PA6_PA7
+#define AO_MMA655X_CS_GPIO     (&stm_gpiod)
+#define AO_MMA655X_CS          4
+
 #define NUM_CMDS               16
 
 /*
@@ -311,7 +322,7 @@ struct ao_adc {
 
 #define AO_COMPANION_CS_PORT   (&stm_gpiod)
 #define AO_COMPANION_CS_PIN    (0)
-#define AO_COMPANION_SPI_BUS   STM_SPI_INDEX(2)
+#define AO_COMPANION_SPI_BUS   AO_SPI_2_PB13_PB14_PB15
 
 /*
  * Monitor
index 71042acc841a3f28096d34dae12c11405de94af8..e6094372120676fd72573cb5eed91cde3031b86c 100644 (file)
@@ -34,6 +34,14 @@ GND  3       7
 JTMS   4       8
 NRST   5       2
 
+TL debug connector:
+
+       TL      ST
+GND    1       3
+NRST   2       5
+SWDIO  3       4
+SWCLK  4       2
+
 MegaAccel:
 
 Jumpers
index 506431ded9245778734002f99c4b99ebc71ad820..b6e4bfc130c2b7243deb39e295e227618d1aa536 100644 (file)
@@ -39,7 +39,6 @@ main(void)
        ao_dbg_init();
 #endif
        ao_aes_init();
-       ao_radio_cmac_init();
        ao_launch_init();
        ao_config_init();
        ao_start_scheduler();
diff --git a/src/spiradio-v0.1/.sdcdbrc b/src/spiradio-v0.1/.sdcdbrc
new file mode 100644 (file)
index 0000000..b9f6129
--- /dev/null
@@ -0,0 +1,2 @@
+--directory=../cc1111:../product:../core:../drivers:.
+
diff --git a/src/spiradio-v0.1/Makefile b/src/spiradio-v0.1/Makefile
new file mode 100644 (file)
index 0000000..a207d34
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# SpiRadio build file
+#
+
+SPIRADIO_VER=0.1
+SPIRADIO_DEF=0_1
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       cc1111.h \
+       ao_product.h \
+       ao_radio_spi.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_stdio.c \
+       ao_task.c \
+       ao_freq.c
+
+CC1111_SRC = \
+       ao_aes.c \
+       ao_dma.c \
+       ao_led.c \
+       ao_radio.c \
+       ao_radio_cmac.c \
+       ao_radio_slave.c \
+       ao_romconfig.c \
+       ao_serial.c \
+       ao_spi.c \
+       ao_string.c \
+       ao_timer.c \
+       _bp.c
+
+PRODUCT_SRC = \
+       ao_spiradio.c
+
+SRC = \
+       $(CORE_SRC) \
+       $(CC1111_SRC) \
+       $(PRODUCT_SRC)
+
+PROGNAME = spiradio-v$(SPIRADIO_VER)
+PROG = $(PROGNAME)-$(VERSION).ihx
+PRODUCT=SpiRadio-v$(SPIRADIO_VER)
+PRODUCT_DEF=-DSPIRADIO_V_$(SPIRADIO_DEF)
+IDPRODUCT=0x000f
+CODESIZE=0x6700
+
+include ../cc1111/Makefile.cc1111
+
+NICKLE=nickle
+CHECK_STACK=sh ../util/check-stack
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: ../$(PROG)
+
+../$(PROG): $(REL) Makefile
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) ..
+       $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM)  || rm $@
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean:     clean
+
+clean: clean-cc1111
+
+install:
+
+uninstall:
+
diff --git a/src/spiradio-v0.1/ao_pins.h b/src/spiradio-v0.1/ao_pins.h
new file mode 100644 (file)
index 0000000..f38aade
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO              1
+
+#define HAS_FLIGHT             0
+#define HAS_USB                        0
+#define HAS_BEEP               0
+#define HAS_GPS                        0
+#define HAS_SERIAL_0           0
+#define HAS_SERIAL_0_ALT_1     0
+#define HAS_SERIAL_0_HW_FLOW   0
+#define USE_SERIAL_0_STDIN     0
+#define HAS_SERIAL_1           1
+#define HAS_SERIAL_1_ALT_1     1
+#define HAS_SERIAL_1_HW_FLOW   0
+#define USE_SERIAL_1_STDIN     1
+#define DELAY_SERIAL_1_STDIN   0
+#define HAS_ADC                        0
+#define HAS_DBG                        0
+#define HAS_EEPROM             0
+#define HAS_LOG                        0
+#define USE_INTERNAL_FLASH     0
+#define DBG_ON_P1              0
+#define PACKET_HAS_MASTER      0
+#define PACKET_HAS_SLAVE       0
+#define AO_LED_RED             1
+#define AO_LED_GREEN           2
+#define LEDS_AVAILABLE         (AO_LED_RED|AO_LED_GREEN)
+#define HAS_EXTERNAL_TEMP      0
+#define HAS_ACCEL_REF          0
+#define SPI_CS_ON_P1           1
+#define HAS_AES                        1
+
+#define SPI_CS_PORT            P1
+#define SPI_CS_SEL             P1SEL
+#define SPI_CS_DIR             P1DIR
+#define AO_SPI_SLAVE           1
+#define HAS_SPI_0              1
+#define SPI_0_ALT_2            1
+#define HAS_SPI_1              0
+
+#define AO_RADIO_SLAVE_INT_PORT        P1
+#define AO_RADIO_SLAVE_INT_BIT 6
+#define AO_RADIO_SLAVE_INT_PIN P1_6
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/spiradio-v0.1/ao_spiradio.c b/src/spiradio-v0.1/ao_spiradio.c
new file mode 100644 (file)
index 0000000..d3647cc
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_spi.h>
+
+void
+main(void)
+{
+       ao_clock_init();
+
+       ao_led_init(LEDS_AVAILABLE);
+
+       ao_serial_init();
+       ao_timer_init();
+       ao_cmd_init();
+       ao_spi_init();
+       ao_radio_init();
+       ao_aes_init();
+       ao_config_init();
+       ao_radio_slave_init();
+       ao_start_scheduler();
+}
index 055a73af2ffd8779d80954685359ec3188f906e2..09c9c3cabfe83b7c37445ed0dd6b3e160a01f719 100644 (file)
@@ -32,8 +32,13 @@ ALTOS_SRC = \
        ao_dma_stm.c \
        ao_spi_stm.c \
        ao_adc_stm.c \
+       ao_data.c \
        ao_i2c_stm.c \
-       ao_usb_stm.c
+       ao_usb_stm.c \
+       ao_exti_stm.c \
+       ao_event.c \
+       ao_quadrature.c \
+       ao_button.c
 
 PRODUCT=StmDemo-v0.0
 PRODUCT_DEF=-DSTM_DEMO
index 9a581ff91a9ce4dc0ec19fa14f6ef1e01948899d..fe7c69f2a4e8fac88416ca5c75aa94c23e9dbe34 100644 (file)
  */
 
 #include "ao.h"
+#include <ao_exti.h>
+#include <ao_event.h>
+#include <ao_quadrature.h>
+#include <ao_button.h>
 
 struct ao_task demo_task;
 
@@ -148,12 +152,29 @@ ao_temp (void)
        printf ("temp: %d\n", temp);
 }
 
+static void
+ao_event(void)
+{
+       struct ao_event event;
+
+       for (;;) {
+               flush();
+               ao_event_get(&event);
+               printf ("type %1d unit %1d tick %5u value %ld\n",
+                       event.type, event.unit, event.tick, event.value);
+               if (event.value == 100)
+                       break;
+       }
+
+}
+
 __code struct ao_cmds ao_demo_cmds[] = {
        { ao_dma_test,  "D\0DMA test" },
        { ao_spi_write, "W\0SPI write" },
        { ao_spi_read, "R\0SPI read" },
        { ao_i2c_write, "i\0I2C write" },
        { ao_temp, "t\0Show temp" },
+       { ao_event, "e\0Monitor event queue" },
        { 0, NULL }
 };
 
@@ -170,6 +191,9 @@ main(void)
 //     ao_lcd_font_init();
        ao_spi_init();
        ao_i2c_init();
+       ao_exti_init();
+       ao_quadrature_init();
+       ao_button_init();
 
        ao_timer_set_adc_interval(100);
 
index 7e22212223033d1c50363a253cf4c245708f2186..c9c7446e4e21d489aa1ff80fe25a9c2e1fce3779 100644 (file)
 
 #define AO_LCD_28_ON_C 1
 
+#define AO_LCD_DUTY    STM_LCD_CR_DUTY_STATIC
+
 #define HAS_ADC                        1
 
 #define AO_ADC_RING            32
@@ -170,4 +172,29 @@ struct ao_adc {
 #define HAS_I2C_2              0
 #define I2C_2_PB10_PB11                0
 
+#define AO_EVENT               1
+
+#define AO_QUADRATURE_COUNT    2
+#define AO_QUADRATURE_MODE     AO_EXTI_MODE_PULL_UP
+
+#define AO_QUADRATURE_0_PORT   &stm_gpioc
+#define AO_QUADRATURE_0_A      1
+#define AO_QUADRATURE_0_B      0
+
+#define AO_QUADRATURE_1_PORT   &stm_gpioc
+#define AO_QUADRATURE_1_A      3
+#define AO_QUADRATURE_1_B      2
+
+#define AO_BUTTON_COUNT                2
+#define AO_BUTTON_MODE         AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT       &stm_gpioc
+#define AO_BUTTON_0            6
+
+#define AO_BUTTON_1_PORT       &stm_gpioc
+#define AO_BUTTON_1            7
+
+#define AO_TICK_TYPE           uint32_t
+#define AO_TICK_SIGNED         int32_t
+
 #endif /* _AO_PINS_H_ */
index 3edfa41d5a512deca15f0b17d9ea8bafea3f10da..04404cdcda11b3a86c400becabfcfdee7721cd57 100644 (file)
@@ -1,4 +1,4 @@
-vpath % ../stm:../product:../drivers:../core:../util:../kalman:..
+vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:..
 vpath make-altitude ../util
 vpath make-kalman ../util
 vpath kalman.5c ../kalman
index 7564c7fa9a0a810e466b0ce5418e0d27b800f53c..18ca6ea01885770a2cb18190f3ad20c2481becff 100644 (file)
 
 #include <ao.h>
 #include <ao_data.h>
-#if HAS_MPU6000
-#include <ao_mpu6000.h>
-#endif
-#if HAS_MS5607
-#include <ao_ms5607.h>
-#endif
-
-volatile __xdata struct ao_data        ao_data_ring[AO_DATA_RING];
-volatile __data uint8_t                ao_data_head;
 
 static uint8_t                 ao_adc_ready;
 
@@ -50,27 +41,7 @@ static uint8_t                       ao_adc_ready;
  */
 static void ao_adc_done(int index)
 {
-       uint8_t step = 1;
-       ao_data_ring[ao_data_head].tick = ao_time();
-#if HAS_MPU6000
-       if (!ao_mpu6000_valid)
-               step = 0;
-       ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current;
-#endif
-#if HAS_MS5607
-       if (!ao_ms5607_valid)
-               step = 0;
-       ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current;
-#endif 
-#if HAS_HMC5883
-       if (!ao_hmc5883_valid)
-               step = 0;
-       ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current;
-#endif
-       if (step) {
-               ao_data_head = ao_data_ring_next(ao_data_head);
-               ao_wakeup((void *) &ao_data_head);
-       }
+       AO_DATA_PRESENT(AO_DATA_ADC);
        ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
        ao_adc_ready = 1;
 }
@@ -117,17 +88,6 @@ ao_adc_get(__xdata struct ao_adc *packet)
        memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc));
 }
 
-void
-ao_data_get(__xdata struct ao_data *packet)
-{
-#if HAS_FLIGHT
-       uint8_t i = ao_data_ring_prev(ao_sample_data);
-#else
-       uint8_t i = ao_data_ring_prev(ao_data_head);
-#endif
-       memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));
-}
-
 static void
 ao_adc_dump(void) __reentrant
 {
index 484ce89eb5892232e4109ea232a66cffeba3614f..87eda18b2a89878a2576d79f90bed05ab0e51a39 100644 (file)
  * STM32L definitions and code fragments for AltOS
  */
 
-#define AO_STACK_SIZE  668
+#define AO_STACK_SIZE  512
 
 #define AO_LED_TYPE    uint16_t
 
+#ifndef AO_TICK_TYPE
+#define AO_TICK_TYPE   uint16_t
+#define AO_TICK_SIGNED int16_t
+#endif
+
 /* Various definitions to make GCC look more like SDCC */
 
 #define ao_arch_naked_declare  __attribute__((naked))
index d2c973f5d9cc149b87917186a4b3aff3ccd97417..d4fbea37ea8f0afe94fc8d0d44fad8b617d54d6d 100644 (file)
 
 /* ao_spi_stm.c
  */
-extern uint8_t ao_spi_mutex[STM_NUM_SPI];
 
 #define AO_SPI_SPEED_FAST      STM_SPI_CR1_BR_PCLK_4
 #define AO_SPI_SPEED_1MHz      STM_SPI_CR1_BR_PCLK_16
 #define AO_SPI_SPEED_200kHz    STM_SPI_CR1_BR_PCLK_256
 
+#define AO_SPI_CONFIG_1                0x00
+#define AO_SPI_1_CONFIG_PA5_PA6_PA7    AO_SPI_CONFIG_1
+#define AO_SPI_2_CONFIG_PB13_PB14_PB15 AO_SPI_CONFIG_1
+
+#define AO_SPI_CONFIG_2                0x04
+#define AO_SPI_1_CONFIG_PB3_PB4_PB5    AO_SPI_CONFIG_2
+#define AO_SPI_2_CONFIG_PD1_PD3_PD4    AO_SPI_CONFIG_2
+
+#define AO_SPI_CONFIG_3                0x08
+#define AO_SPI_1_CONFIG_PE13_PE14_PE15 AO_SPI_CONFIG_3
+
+#define AO_SPI_CONFIG_NONE     0x0c
+
+#define AO_SPI_INDEX_MASK      0x01
+#define AO_SPI_CONFIG_MASK     0x0c
+
+#define AO_SPI_1_PA5_PA6_PA7   (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7)
+#define AO_SPI_1_PB3_PB4_PB5   (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5)
+#define AO_SPI_1_PE13_PE14_PE15        (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PE13_PE14_PE15)
+
+#define AO_SPI_2_PB13_PB14_PB15        (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15)
+#define AO_SPI_2_PD1_PD3_PD4   (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4)
+
+#define AO_SPI_INDEX(id)       ((id) & AO_SPI_INDEX_MASK)
+#define AO_SPI_CONFIG(id)      ((id) & AO_SPI_CONFIG_MASK)
+
 void
 ao_spi_get(uint8_t spi_index, uint32_t speed);
 
@@ -78,12 +103,25 @@ ao_spi_init(void);
 
 #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
 
+#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
+
 #define ao_enable_output(port,bit,pin,v) do {                  \
                ao_enable_port(port);                           \
                ao_gpio_set(port, bit, pin, v);                 \
                stm_moder_set(port, bit, STM_MODER_OUTPUT);\
        } while (0)
 
+#define ao_enable_input(port,bit,mode) do {                            \
+               ao_enable_port(port);                                   \
+               stm_moder_set(port, bit, STM_MODER_INPUT);              \
+               if (mode == AO_EXTI_MODE_PULL_UP)                       \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP);    \
+               else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN);  \
+               else                                                    \
+                       stm_pupdr_set(port, bit, STM_PUPDR_NONE);       \
+       } while (0)
+
 #define ao_enable_cs(port,bit) do {                            \
                stm_gpio_set((port), bit, 1);                   \
                stm_moder_set((port), bit, STM_MODER_OUTPUT);   \
diff --git a/src/stm/ao_data.c b/src/stm/ao_data.c
new file mode 100644 (file)
index 0000000..38d2f7f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_data.h>
+
+volatile __xdata struct ao_data        ao_data_ring[AO_DATA_RING];
+volatile __data uint8_t                ao_data_head;
+volatile __data uint8_t                ao_data_present;
+
+void
+ao_data_get(__xdata struct ao_data *packet)
+{
+#if HAS_FLIGHT
+       uint8_t i = ao_data_ring_prev(ao_sample_data);
+#else
+       uint8_t i = ao_data_ring_prev(ao_data_head);
+#endif
+       memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));
+}
diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c
new file mode 100644 (file)
index 0000000..5a75a97
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_storage.h>
+
+/* Total bytes of available storage */
+ao_pos_t       ao_storage_total = 4096;
+
+/* Block size - device is erased in these units. */
+ao_pos_t       ao_storage_block = 1024;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+ao_pos_t       ao_storage_config = 0;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. */
+uint16_t       ao_storage_unit = 1024;
+
+/* Location of eeprom in address space */
+#define stm_eeprom     ((uint8_t *) 0x08080000)
+
+/*
+ * The internal flash chip is arranged in 8 byte sectors; the
+ * chip cannot erase in units smaller than that.
+ *
+ * Writing happens in units of 2 bytes and
+ * can only change bits from 1 to 0. So, you can rewrite
+ * the same contents, or append to an existing page easily enough
+ */
+
+/*
+ * Erase the specified sector
+ */
+uint8_t
+ao_storage_erase(ao_pos_t pos) __reentrant
+{
+       /* Not necessary */
+       return 1;
+}
+
+static void
+ao_intflash_unlock(void)
+{
+       /* Unlock Data EEPROM and FLASH_PECR register */
+       stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1;
+       stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2;
+
+       /* Configure the FTDW bit (FLASH_PECR[8]) to execute
+        * word write, whatever the previous value of the word
+        * being written to
+        */
+       stm_flash.pecr = ((0 << STM_FLASH_PECR_OBL_LAUNCH) |
+                         (0 << STM_FLASH_PECR_ERRIE) |
+                         (0 << STM_FLASH_PECR_EOPIE) |
+                         (0 << STM_FLASH_PECR_FPRG) |
+                         (0 << STM_FLASH_PECR_ERASE) |
+                         (0 << STM_FLASH_PECR_FTDW) |
+                         (1 << STM_FLASH_PECR_DATA) |
+                         (0 << STM_FLASH_PECR_PROG) |
+                         (0 << STM_FLASH_PECR_OPTLOCK) |
+                         (0 << STM_FLASH_PECR_PRGLOCK) |
+                         (0 << STM_FLASH_PECR_PELOCK));
+}
+
+static void
+ao_intflash_lock(void)
+{
+       stm_flash.pecr |= (1 << STM_FLASH_PECR_PELOCK);
+}
+
+static void
+ao_intflash_wait(void)
+{
+       /* Wait for the flash unit to go idle */
+       while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+               ;
+}
+
+static void
+ao_intflash_write32(uint16_t pos, uint32_t w)
+{
+       volatile uint32_t       *addr;
+
+       addr = (uint32_t *) (stm_eeprom + pos);
+
+       /* Erase previous word */
+       *addr = 0;
+       ao_intflash_wait();
+
+       if (w) {
+               /* Write a word to a valid address in the data EEPROM */
+               *addr = w;
+               ao_intflash_wait();
+       }
+}
+
+static void
+ao_intflash_write8(uint16_t pos, uint8_t d)
+{
+       uint32_t        w, *addr, mask;
+       uint8_t         shift;
+       
+       addr = (uint32_t *) (stm_eeprom + (pos & ~3));
+
+       /* Compute word to be written */
+       shift = (pos & 3) << 3;
+       mask = 0xff << shift;
+       w = (*addr & ~mask) | (d << shift);
+
+       ao_intflash_write32(pos & ~3, w);
+}
+
+static uint8_t
+ao_intflash_read(uint16_t pos)
+{
+       return stm_eeprom[pos];
+}
+
+/*
+ * Write to flash
+ */
+
+uint8_t
+ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentrant
+{
+       uint16_t pos = pos32;
+       __xdata uint8_t *d = v;
+
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+
+       ao_intflash_unlock();
+       while (len) {
+               if ((pos & 3) == 0 && len >= 4) {
+                       uint32_t        w;
+
+                       w = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
+                       ao_intflash_write32(pos, w);
+                       pos += 4;
+                       d += 4;
+                       len -= 4;
+               } else {
+                       ao_intflash_write8(pos, *d);
+                       pos += 1;
+                       d += 1;
+                       len -= 1;
+               }
+       }
+       ao_intflash_lock();
+
+       return 1;
+}
+
+/*
+ * Read from flash
+ */
+uint8_t
+ao_storage_device_read(ao_pos_t pos, __xdata void *v, uint16_t len) __reentrant
+{
+       uint8_t *d = v;
+       
+       if (pos >= ao_storage_total || pos + len > ao_storage_total)
+               return 0;
+       while (len--)
+               *d++ = ao_intflash_read(pos++);
+       return 1;
+}
+
+void
+ao_storage_flush(void) __reentrant
+{
+}
+
+void
+ao_storage_setup(void)
+{
+}
+
+void
+ao_storage_device_info(void) __reentrant
+{
+       uint8_t i;
+       printf ("Using internal flash\n");
+}
+
+void
+ao_storage_device_init(void)
+{
+}
index b579ad9fa5aeee46872450ffa3f73c0b61fafad2..35b56b571582fd392201bf0172767ff9f53119ad 100644 (file)
@@ -29,6 +29,9 @@
 void
 ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)());
 
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
+
 void
 ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)());
 
index d54e6ee637d8a797665392a13e2edb171c5d47f6..1361d0d4a8cb6caf0a41b3522c9ae49c53c71cf5 100644 (file)
@@ -115,6 +115,20 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback
        stm_nvic_set_enable(irq);
 }
 
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+       uint32_t        mask = 1 << pin;
+       
+       if (mode & AO_EXTI_MODE_RISING)
+               stm_exti.rtsr |= mask;
+       else
+               stm_exti.rtsr &= ~mask;
+       if (mode & AO_EXTI_MODE_FALLING)
+               stm_exti.ftsr |= mask;
+       else
+               stm_exti.ftsr &= ~mask;
+}
+
 void
 ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
        ao_exti_callback[pin] = callback;
@@ -137,10 +151,4 @@ ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
 void
 ao_exti_init(void)
 {
-       stm_nvic_set_priority(STM_ISR_EXTI1_POS, AO_STM_NVIC_MED_PRIORITY);
-       stm_nvic_set_priority(STM_ISR_EXTI2_POS, AO_STM_NVIC_MED_PRIORITY);
-       stm_nvic_set_priority(STM_ISR_EXTI3_POS, AO_STM_NVIC_MED_PRIORITY);
-       stm_nvic_set_priority(STM_ISR_EXTI4_POS, AO_STM_NVIC_MED_PRIORITY);
-       stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, AO_STM_NVIC_MED_PRIORITY);
-       stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, AO_STM_NVIC_MED_PRIORITY);
 }
index b19094440a9ff8f1027510f026f8266a150e0396..0f9a8eb53ee4325ab2c55f24be7df6b413a9604d 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <ao.h>
+#include <ao_lcd_stm.h>
 
 struct ao_lcd_segment {
        uint8_t reg;
@@ -88,7 +89,7 @@ static inline int ao_lcd_stm_com_enabled(int com) {
                (1 << 31))
 
 #else
-#define AO_LCD_STM_GPIOC_28_C_SEGS     0
+#define AO_LCD_STM_GPIOC_28_SEGS       0
 
 #define AO_LCD_STM_GPIOD_28_SEGS       (       \
                (1 << 28) |                     \
@@ -227,6 +228,21 @@ static const struct ao_lcd_segment coms[] = {
 #define NSEG   (sizeof segs/sizeof segs[0])
 #define NCOM   (sizeof coms/sizeof coms[0])
 
+static uint8_t ao_lcd_update_active;
+
+void
+stm_lcd_isr(void)
+{
+       if (stm_lcd.sr & (1 << STM_LCD_SR_UDD)) {
+               stm_lcd.clr = (1 << STM_LCD_CLR_UDDC);
+               if (ao_lcd_update_active) {
+                       ao_lcd_update_active = 0;
+                       ao_wakeup(&ao_lcd_update_active);
+               }
+       }
+}
+
+
 static void
 ao_lcd_stm_fcr_sync(void)
 {
@@ -234,6 +250,45 @@ ao_lcd_stm_fcr_sync(void)
                asm("nop");
 }
 
+void
+ao_lcd_flush(void)
+{
+       cli();
+       ao_lcd_update_active = 1;
+       stm_lcd.sr = (1 << STM_LCD_SR_UDR);
+       while (ao_lcd_update_active)
+               ao_sleep(&ao_lcd_update_active);
+       sei();
+}
+
+void
+ao_lcd_clear(void)
+{
+       uint8_t i;
+
+       for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++)
+               stm_lcd.ram[i] = 0;
+       ao_lcd_flush();
+}
+
+void
+ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value)
+{
+       uint8_t n;
+
+       if (digit >= NCOM)
+               digit = NCOM-1;
+       if (segment >= NSEG)
+               segment = NSEG-1;
+
+       n = (segment >> 5) & 1;
+       if (value)
+               stm_lcd.ram[digit * 2 + n] |= (1 << (segment & 0x1f));
+       else
+               stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f));
+}
+
+#if 0
 static void
 ao_lcd_stm_seg_set(void)
 {
@@ -246,34 +301,16 @@ ao_lcd_stm_seg_set(void)
        ao_cmd_decimal();
        val = ao_cmd_lex_i;
        printf ("com: %d seg: %d val: %d\n", com, seg, val);
-       n = (seg >> 5) & 1;
-       if (com >= NCOM)
-               com = NCOM-1;
-       if (seg >= NSEG)
-               seg = NSEG-1;
-       if (val)
-               stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f));
-       else
-               stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f));
-       stm_lcd.sr = (1 << STM_LCD_SR_UDR);
+       ao_lcd_set(com, seg, val);
+       ao_lcd_flush();
 }
 
-static void
-ao_lcd_stm_clear(void)
-{
-       int     i;
-
-       for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++)
-               stm_lcd.ram[i] = 0;
-       stm_lcd.sr = (1 << STM_LCD_SR_UDR);
-}
-
-
-const struct ao_cmds ao_lcd_stm_cmds[] = {
+static const struct ao_cmds ao_lcd_stm_cmds[] = {
        { ao_lcd_stm_seg_set,   "s <com> <seg> <value>\0Set LCD segment" },
-       { ao_lcd_stm_clear,     "C\0Clear LCD" },
+       { ao_lcd_clear,         "C\0Clear LCD" },
        { 0, NULL },
 };
+#endif
 
 void
 ao_lcd_stm_init(void)
@@ -332,14 +369,14 @@ ao_lcd_stm_init(void)
        stm_lcd.cr = 0;
 
        /* duty cycle 1/3, radio 352, frame rate about 33Hz */
-       stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) |
+       stm_lcd.fcr = ((STM_LCD_FCR_PS_8 << STM_LCD_FCR_PS) |
                       (STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) |
-                      (4 << STM_LCD_FCR_CC) |
+                      (7 << STM_LCD_FCR_CC) |
                       (0 << STM_LCD_FCR_DEAD) |
-                      (4 << STM_LCD_FCR_PON) |
-                      (0 << STM_LCD_FCR_UDDIE) |
+                      (1 << STM_LCD_FCR_PON) |
+                      (1 << STM_LCD_FCR_UDDIE) |
                       (0 << STM_LCD_FCR_SOFIE) |
-                      (0 << STM_LCD_FCR_HD));
+                      (1 << STM_LCD_FCR_HD));
 
        ao_lcd_stm_fcr_sync();
 
@@ -347,10 +384,10 @@ ao_lcd_stm_init(void)
        /* Program desired BIAS in LCD_CR */
        /* Enable mux seg */
        /* Internal voltage source */
-       stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) |
+       stm_lcd.cr = ((AO_LCD_DUTY << STM_LCD_CR_DUTY) |
                      (STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) |
                      (0 << STM_LCD_CR_VSEL) |
-                     (1 << STM_LCD_CR_MUX_SEG));
+                     (0 << STM_LCD_CR_MUX_SEG));
 
        ao_lcd_stm_fcr_sync();
 
@@ -362,12 +399,6 @@ ao_lcd_stm_init(void)
 
        /* Load initial data into LCD_RAM and set the
         * UDR bit in the LCD_SR register */
-       for (r = 0; r < NCOM; r++) {
-               stm_lcd.ram[r*2] = 0;
-               stm_lcd.ram[r*2 + 1] = 0;
-       }
-
-       stm_lcd.sr = (1 << STM_LCD_SR_UDR);
 
        /* Program desired frame rate (PS and DIV bits in LCD_FCR) */
 
@@ -376,7 +407,11 @@ ao_lcd_stm_init(void)
        /* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */
 
        /* Program the required interrupts */
+       stm_nvic_set_enable(STM_ISR_LCD_POS);
+       stm_nvic_set_priority(STM_ISR_LCD_POS, AO_STM_NVIC_LOW_PRIORITY);
 
        /* All done */
+#if 0
        ao_cmd_register(ao_lcd_stm_cmds);
+#endif
 }
diff --git a/src/stm/ao_lcd_stm.h b/src/stm/ao_lcd_stm.h
new file mode 100644 (file)
index 0000000..1466754
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_LCD_STM_H_
+#define _AO_LCD_STM_H_
+
+void
+ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value);
+
+void
+ao_lcd_clear(void);
+
+void
+ao_lcd_flush(void);
+
+#endif /* _AO_LCD_STM_H_ */
index 547de9e50ca0b887864ecaab28986d923b2ed572..ade86a2720c024f59029e8d37f511f9fef19baf8 100644 (file)
@@ -23,7 +23,8 @@ struct ao_spi_stm_info {
        struct stm_spi *stm_spi;
 };
 
-uint8_t                ao_spi_mutex[STM_NUM_SPI];
+static uint8_t         ao_spi_mutex[STM_NUM_SPI];
+static uint8_t         ao_spi_config[STM_NUM_SPI];
 
 static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
        {
@@ -43,9 +44,9 @@ static uint8_t        spi_dev_null;
 void
 ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
 
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
@@ -99,9 +100,9 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
 void
 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
 
        /* Set up the transmit DMA to deliver data */
        ao_dma_set_transfer(mosi_dma_index,
@@ -155,9 +156,9 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
 
        /* Set up transmit DMA to make the SPI hardware actually run */
        ao_dma_set_transfer(mosi_dma_index,
@@ -212,9 +213,9 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
 void
 ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
 {
-       struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
-       uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index;
-       uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index;
+       struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+       uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
 
        /* Set up transmit DMA to send data */
        ao_dma_set_transfer(mosi_dma_index,
@@ -269,9 +270,94 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
 void
 ao_spi_get(uint8_t spi_index, uint32_t speed)
 {
-       struct stm_spi  *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
-
-       ao_mutex_get(&ao_spi_mutex[spi_index]);
+       struct stm_spi  *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+       uint8_t         config = AO_SPI_CONFIG(spi_index);
+
+       ao_mutex_get(&ao_spi_mutex[AO_SPI_INDEX(spi_index)]);
+       if (config != ao_spi_config[AO_SPI_INDEX(spi_index)]) {
+               
+               /* Disable current config
+                */
+               switch (AO_SPI_INDEX(spi_index)) {
+               case STM_SPI_INDEX(1):
+                       switch (ao_spi_config[AO_SPI_INDEX(spi_index)]) {
+                       case AO_SPI_1_CONFIG_PA5_PA6_PA7:
+                               stm_gpio_set(&stm_gpioa, 5, 0);
+                               stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+                               stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+                               stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
+                               break;
+                       case AO_SPI_1_CONFIG_PB3_PB4_PB5:
+                               stm_gpio_set(&stm_gpiob, 3, 0);
+                               stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+                               stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+                               stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+                               break;
+                       case AO_SPI_1_CONFIG_PE13_PE14_PE15:
+                               stm_gpio_set(&stm_gpioe, 13, 0);
+                               stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT);
+                               stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT);
+                               stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT);
+                               break;
+                       }
+                       break;
+               case STM_SPI_INDEX(2):
+                       switch (ao_spi_config[AO_SPI_INDEX(spi_index)]) {
+                       case AO_SPI_2_CONFIG_PB13_PB14_PB15:
+                               stm_gpio_set(&stm_gpiob, 13, 0);
+                               stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+                               stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+                               stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+                               break;
+                       case AO_SPI_2_CONFIG_PD1_PD3_PD4:
+                               stm_gpio_set(&stm_gpiod, 1, 0);
+                               stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT);
+                               stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT);
+                               stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT);
+                               break;
+                       }
+                       break;
+               }
+
+               /* Enable new config
+                */
+               switch (AO_SPI_INDEX(spi_index)) {
+               case 0:
+                       switch (AO_SPI_CONFIG(spi_index)) {
+                       case AO_SPI_1_CONFIG_PA5_PA6_PA7:
+                               stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
+                               break;
+                       case AO_SPI_1_CONFIG_PB3_PB4_PB5:
+                               stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
+                               break;
+                       case AO_SPI_1_CONFIG_PE13_PE14_PE15:
+                               stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
+                               break;
+                       }
+                       break;
+               case 1:
+                       switch (AO_SPI_CONFIG(spi_index)) {
+                       case AO_SPI_2_CONFIG_PB13_PB14_PB15:
+                               stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
+                               break;
+                       case AO_SPI_2_CONFIG_PD1_PD3_PD4:
+                               stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
+                               stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
+                               break;
+                       }
+                       break;
+               }
+               ao_spi_config[AO_SPI_INDEX(spi_index)] = AO_SPI_CONFIG(spi_index);
+       }
        stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |                   /* Three wire mode */
                        (0 << STM_SPI_CR1_BIDIOE) |
                        (0 << STM_SPI_CR1_CRCEN) |                      /* CRC disabled */
@@ -291,16 +377,16 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)
 void
 ao_spi_put(uint8_t spi_index)
 {
-       struct stm_spi  *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
+       struct stm_spi  *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
 
        stm_spi->cr1 = 0;
-       ao_mutex_put(&ao_spi_mutex[spi_index]);
+       ao_mutex_put(&ao_spi_mutex[AO_SPI_INDEX(spi_index)]);
 }
 
 static void
 ao_spi_channel_init(uint8_t spi_index)
 {
-       struct stm_spi  *stm_spi = ao_spi_stm_info[spi_index].stm_spi;
+       struct stm_spi  *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
 
        stm_spi->cr1 = 0;
        (void) stm_spi->sr;
@@ -318,50 +404,28 @@ ao_spi_init(void)
 #if HAS_SPI_1
 # if SPI_1_PA5_PA6_PA7
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
-       stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
-       stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
-       stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
-# else
-#  if SPI_1_PB3_PB4_PB5
+# endif
+# if SPI_1_PB3_PB4_PB5
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
-       stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
-       stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
-       stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
-#  else
-#   if SPI_1_PE13_PE14_PE15
+# endif
+# if SPI_1_PE13_PE14_PE15
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN);
-       stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
-       stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
-       stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
-#   else
-#    error "No SPI_1 port configuration specified"
-#   endif
-#  endif
 # endif
-
        stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
-
+       ao_spi_config[0] = AO_SPI_CONFIG_NONE;
        ao_spi_channel_init(0);
 #endif
 
 #if HAS_SPI_2
 # if SPI_2_PB13_PB14_PB15
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
-       stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
-       stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
-       stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
-# else
-#  if SPI_2_PPD1_PD3_PD4
+# endif
+# if SPI_2_PD1_PD3_PD4
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
-       stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
-       stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
-       stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
-#  else
-#   error "No SPI_2 port configuration specified"
-#  endif
 # endif
 
        stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+       ao_spi_config[1] = AO_SPI_CONFIG_NONE;
 
        ao_spi_channel_init(1);
 #endif
index ebe753668e6036cb376bf1d82d5a55de7d53b479..f561e6b56851303d1af929c849acd0658e23dff8 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "ao.h"
 
-volatile __data uint16_t ao_tick_count;
+volatile __data AO_TICK_TYPE ao_tick_count;
 
 uint16_t ao_time(void)
 {
@@ -28,18 +28,9 @@ uint16_t ao_time(void)
        return v;
 }
 
-static __xdata uint8_t ao_forever;
-
-void
-ao_delay(uint16_t ticks)
-{
-       ao_alarm(ticks);
-       ao_sleep(&ao_forever);
-}
-
-#if HAS_ADC
-volatile __data uint8_t        ao_adc_interval = 1;
-volatile __data uint8_t        ao_adc_count;
+#if AO_DATA_ALL
+volatile __data uint8_t        ao_data_interval = 1;
+volatile __data uint8_t        ao_data_count;
 #endif
 
 void
@@ -51,10 +42,13 @@ void stm_tim6_isr(void)
        if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
                stm_tim6.sr = 0;
                ++ao_tick_count;
-#if HAS_ADC
-               if (++ao_adc_count == ao_adc_interval) {
-                       ao_adc_count = 0;
+#if AO_DATA_ALL
+               if (++ao_data_count == ao_data_interval) {
+                       ao_data_count = 0;
                        ao_adc_poll();
+#if (AO_DATA_ALL & ~(AO_DATA_ADC))
+                       ao_wakeup((void *) &ao_data_count);
+#endif
                }
 #endif
        }
@@ -64,8 +58,8 @@ void stm_tim6_isr(void)
 void
 ao_timer_set_adc_interval(uint8_t interval) __critical
 {
-       ao_adc_interval = interval;
-       ao_adc_count = 0;
+       ao_data_interval = interval;
+       ao_data_count = 0;
 }
 #endif
 
index ff8dddffc2bb1cbb95947f5fb995a917020f0288..25f5af073d76659b3ec7cba65252d6f19b8161fc 100644 (file)
@@ -167,7 +167,7 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {
 }
 
 static inline uint8_t
-stm_gpio_isset(struct stm_gpio *gpio, int pin) {
+stm_gpio_get(struct stm_gpio *gpio, int pin) {
        return (gpio->idr >> pin) & 1;
 }
 
@@ -281,6 +281,30 @@ extern struct stm_flash    stm_flash;
 #define STM_FLASH_ACR_PRFEN    (1)
 #define STM_FLASH_ACR_LATENCY  (0)
 
+#define STM_FLASH_PECR_OBL_LAUNCH      18
+#define STM_FLASH_PECR_ERRIE           17
+#define STM_FLASH_PECR_EOPIE           16
+#define STM_FLASH_PECR_FPRG            10
+#define STM_FLASH_PECR_ERASE           9
+#define STM_FLASH_PECR_FTDW            8
+#define STM_FLASH_PECR_DATA            4
+#define STM_FLASH_PECR_PROG            3
+#define STM_FLASH_PECR_OPTLOCK         2
+#define STM_FLASH_PECR_PRGLOCK         1
+#define STM_FLASH_PECR_PELOCK          0
+
+#define STM_FLASH_SR_OPTVERR           11
+#define STM_FLASH_SR_SIZERR            10
+#define STM_FLASH_SR_PGAERR            9
+#define STM_FLASH_SR_WRPERR            8
+#define STM_FLASH_SR_READY             3
+#define STM_FLASH_SR_ENDHV             2
+#define STM_FLASH_SR_EOP               1
+#define STM_FLASH_SR_BSY               0
+
+#define STM_FLASH_PEKEYR_PEKEY1        0x89ABCDEF
+#define STM_FLASH_PEKEYR_PEKEY2 0x02030405
+
 struct stm_rcc {
        vuint32_t       cr;
        vuint32_t       icscr;
@@ -881,6 +905,9 @@ stm_exticr_set(struct stm_gpio *gpio, int pin) {
        uint8_t shift = (pin & 3) << 2;
        uint8_t val = 0;
 
+       /* Enable SYSCFG */
+       stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN);
+
        if (gpio == &stm_gpioa)
                val = STM_SYSCFG_EXTICR_PA;
        else if (gpio == &stm_gpiob)
index 710b4a2f81a006199805bc2149605d33b66e0aee..b9f6129cc5e3163b05dea20a1d16d80f43be2363 100644 (file)
@@ -1 +1,2 @@
---directory=..
+--directory=../cc1111:../product:../core:../drivers:.
+
diff --git a/src/telefire-v0.1/.sdcdbrc b/src/telefire-v0.1/.sdcdbrc
new file mode 100644 (file)
index 0000000..b9f6129
--- /dev/null
@@ -0,0 +1,2 @@
+--directory=../cc1111:../product:../core:../drivers:.
+
diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile
new file mode 100644 (file)
index 0000000..712b2e8
--- /dev/null
@@ -0,0 +1,103 @@
+#
+# TeleFire build file
+#
+
+TELEFIRE_VER=0.1
+TELEFIRE_DEF=0_1
+
+vpath %.c ..:../core:../cc1111:../drivers:../product
+vpath %.h ..:../core:../cc1111:../drivers:../product
+vpath ao-make-product.5c ../util
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_pins.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pad.h \
+       cc1111.h \
+       ao_product.h
+
+CORE_SRC = \
+       ao_cmd.c \
+       ao_config.c \
+       ao_convert.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_stdio.c \
+       ao_storage.c \
+       ao_task.c \
+       ao_freq.c
+
+CC1111_SRC&nb