From: Keith Packard Date: Wed, 29 Aug 2012 18:29:24 +0000 (-0700) Subject: Merge remote-tracking branch 'mjb/master' X-Git-Tag: 1.1~47 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=583458772746317b98fced907ec780edff465888;hp=17b6ffb6c090112367eac944494f0fa58da453c7 Merge remote-tracking branch 'mjb/master' Pull in Mike's fancy new AltosDroid bits --- diff --git a/.gitignore b/.gitignore index 1773096d..782be7f6 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index 57c4da71..27ea3a2b 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -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) { diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index d59e73ba..415c3c64 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -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)); diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index e468f84b..8722bc05 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -127,7 +127,7 @@ public class AltosRecord implements Comparable , Cloneable { double p = filtered_pressure(); if (p == MISSING) - return MISSING; + return raw_altitude(); return AltosConvert.pressure_to_altitude(p); } diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java index afb70790..37accef6 100644 --- a/altoslib/AltosRecordTM.java +++ b/altoslib/AltosRecordTM.java @@ -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) { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index e20ec9a7..3b37a3d4 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -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(); diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index aa6a6d4e..c1400976 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -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 { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index c4e9c697..6cee1609 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -41,7 +41,7 @@ import libaltosJNI.*; * threads. */ -public class AltosSerial extends AltosLink implements Runnable { +public class AltosSerial extends AltosLink { static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); @@ -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) { diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 92c985a9..986919d4 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -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: diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 1cc27cbe..515432f9 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -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 diff --git a/ao-tools/ao-send-telem/ao-send-telem.c b/ao-tools/ao-send-telem/ao-send-telem.c index c4c354e0..c6cc51a1 100644 --- a/ao-tools/ao-send-telem/ao-send-telem.c +++ b/ao-tools/ao-send-telem/ao-send-telem.c @@ -182,6 +182,7 @@ main (int argc, char **argv) break; case 'R': realtime = 1; + break; default: usage(argv[0]); break; diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index e689539b..a471dcc4 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -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(); diff --git a/debian/control b/debian/control index 0b35bbe3..589e8d8f 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: electronics Priority: optional Maintainer: Bdale Garbee Uploaders: Keith Packard -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 diff --git a/src/Makefile b/src/Makefile index 491618f6..b8828d46 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 index 00000000..4977aaf8 --- /dev/null +++ b/src/aes/ao_aes.c @@ -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 +#include +#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 index 00000000..7990a2e1 --- /dev/null +++ b/src/aes/ao_aes_int.h @@ -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 + +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 index 00000000..1bca227c --- /dev/null +++ b/src/aes/ao_aes_tables.c @@ -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 index 00000000..73bcf3fb --- /dev/null +++ b/src/aes/ao_aes_tables.h @@ -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]; + diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index cd81b163..d2ea2be7 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -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 */ diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index f7ecce33..0e19603b 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -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) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index ce827e25..f7b52281 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -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; diff --git a/src/cc1111/ao_aes.c b/src/cc1111/ao_aes.c index d50fecfb..b1f305ec 100644 --- a/src/cc1111/ao_aes.c +++ b/src/cc1111/ao_aes.c @@ -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; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 06b04b93..a97515a7 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -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 */ diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 0737e7ab..8f1cc094 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -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)) diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c index a593d0b2..420f7568 100644 --- a/src/cc1111/ao_launch.c +++ b/src/cc1111/ao_launch.c @@ -15,7 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include __xdata uint16_t ao_launch_ignite; diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index fc6ed3ec..2f0e2884 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -560,4 +560,16 @@ #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_ */ diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 2071c47a..cb2c2fdd 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#if HAS_PAD +#include +#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 }, }; diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 00c85ff3..48383802 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -17,6 +17,25 @@ #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 */ diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 1bf5e155..cdef6bda 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -17,6 +17,109 @@ #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)); } diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index 602f98c8..a64b5aba 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -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 */ diff --git a/src/core/ao.h b/src/core/ao.h index 65b9eb18..66c0881f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -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; diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index 7f67374d..c47bc2db 100644 --- a/src/core/ao_aes.h +++ b/src/core/ao_aes.h @@ -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_ */ diff --git a/src/core/ao_config.c b/src/core/ao_config.c index e2095e65..ce855ad1 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -17,8 +17,11 @@ #include "ao.h" #include "ao_log.h" +#include +#if HAS_FLIGHT #include #include +#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 diff --git a/src/core/ao_data.h b/src/core/ao_data.h index fdc49ca2..3b66ef5d 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -18,18 +18,42 @@ #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 +#define AO_DATA_MS5607 (1 << 1) +#else +#define AO_DATA_MS5607 (1 << 1) #endif #if HAS_MPU6000 #include +#define AO_DATA_MPU6000 (1 << 2) +#else +#define AO_DATA_MPU6000 0 #endif #if HAS_HMC5883 #include +#define AO_DATA_HMC5883 (1 << 3) +#else +#define AO_DATA_HMC5883 0 +#endif + +#if HAS_MMA655X +#include +#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 diff --git a/src/core/ao_led.h b/src/core/ao_led.h index edc5fd1f..d9a0914a 100644 --- a/src/core/ao_led.h +++ b/src/core/ao_led.h @@ -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); diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index e263f0db..fc0ca8b1 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -15,38 +15,14 @@ * 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 +#include 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 \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \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 index 00000000..e86f31e9 --- /dev/null +++ b/src/core/ao_radio_cmac.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_RADIO_CMAC_H_ +#define _AO_RADIO_CMAC_H_ + +#include + +#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 index 00000000..64410921 --- /dev/null +++ b/src/core/ao_radio_cmac_cmd.c @@ -0,0 +1,104 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +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 \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \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 index 00000000..6b8782de --- /dev/null +++ b/src/core/ao_radio_cmac_cmd.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_RADIO_CMAC_CMD_H_ +#define _AO_RADIO_CMAC_CMD_H_ + +void +ao_radio_cmac_cmd_init(void); + +#endif /* _AO_RADIO_CMAC_CMD_H_ */ diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index b2dd435b..adf7e4d4 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -16,6 +16,7 @@ */ #include +#include uint8_t ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 4011a36e..65654731 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -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 index 00000000..4c13ee71 --- /dev/null +++ b/src/drivers/ao_74hc497.c @@ -0,0 +1,55 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * 74HC597 driver. + * Reads a single byte from the shift register + */ + +#include +#include + +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 index 00000000..6df7bcae --- /dev/null +++ b/src/drivers/ao_74hc497.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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 index 00000000..a507c909 --- /dev/null +++ b/src/drivers/ao_button.c @@ -0,0 +1,94 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#if AO_EVENT +#include +#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 index 00000000..ce349d65 --- /dev/null +++ b/src/drivers/ao_button.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BUTTON_H_ +#define _AO_BUTTON_H_ + +void +ao_button_init(void); + +#endif /* _AO_BUTTON_H_ */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 97a434d8..4df931b5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -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 index 00000000..440ef2de --- /dev/null +++ b/src/drivers/ao_event.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#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 index 00000000..25c49c35 --- /dev/null +++ b/src/drivers/ao_event.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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_ */ diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index dbeb66b8..ade6c263 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,7 +19,7 @@ #include #include -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 diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 8d726510..55690978 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -75,14 +75,10 @@ #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 index 00000000..b49c9dba --- /dev/null +++ b/src/drivers/ao_lco_cmd.c @@ -0,0 +1,198 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +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 \0Get remote launch status" }, + { launch_fire_cmd, "F \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \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 index 00000000..c55448cd --- /dev/null +++ b/src/drivers/ao_lco_cmd.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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 index 00000000..cd304d80 --- /dev/null +++ b/src/drivers/ao_mma655x.c @@ -0,0 +1,227 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#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 index 00000000..9c0c59dc --- /dev/null +++ b/src/drivers/ao_mma655x.h @@ -0,0 +1,85 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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_ */ diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index a1c32d4d..e8c80f12 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -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]); diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index fc7af1e0..ca76b081 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -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); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 17fe853b..ec0d2202 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -19,6 +19,8 @@ #include #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 diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index fa3b1c5b..e9c364d9 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -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 index 00000000..cd901aa3 --- /dev/null +++ b/src/drivers/ao_pad.c @@ -0,0 +1,315 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +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 \0Fire igniter. 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 index 00000000..3b0cf1fe --- /dev/null +++ b/src/drivers/ao_pad.h @@ -0,0 +1,73 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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 index 00000000..6d8d18d8 --- /dev/null +++ b/src/drivers/ao_pca9922.c @@ -0,0 +1,86 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * 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 + +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 index 00000000..6cc2467a --- /dev/null +++ b/src/drivers/ao_quadrature.c @@ -0,0 +1,134 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#if AO_EVENT +#include +#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 \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 index 00000000..d7dda682 --- /dev/null +++ b/src/drivers/ao_quadrature.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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 index 00000000..73ac3c03 --- /dev/null +++ b/src/drivers/ao_radio_master.c @@ -0,0 +1,314 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +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 index 00000000..9a01bbfa --- /dev/null +++ b/src/drivers/ao_radio_slave.c @@ -0,0 +1,125 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +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 index 00000000..2957f70d --- /dev/null +++ b/src/drivers/ao_radio_spi.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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 index 00000000..b3b5f878 --- /dev/null +++ b/src/drivers/ao_seven_segment.c @@ -0,0 +1,220 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +/* + * 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 \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 index 00000000..5b29deaf --- /dev/null +++ b/src/drivers/ao_seven_segment.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 4a4c983a..a93f6f17 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -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 \ diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 55324514..d3ae4690 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,9 @@ main(void) #if HAS_MPU6000 ao_mpu6000_init(); #endif +#if HAS_MMA655X + ao_mma655x_init(); +#endif ao_storage_init(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 6b0f9832..8b631ae9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -69,13 +69,14 @@ #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 diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins index 71042acc..e6094372 100644 --- a/src/megametrum-v0.1/stlink-pins +++ b/src/megametrum-v0.1/stlink-pins @@ -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 diff --git a/src/product/ao_telelaunch.c b/src/product/ao_telelaunch.c index 506431de..b6e4bfc1 100644 --- a/src/product/ao_telelaunch.c +++ b/src/product/ao_telelaunch.c @@ -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 index 00000000..b9f6129c --- /dev/null +++ b/src/spiradio-v0.1/.sdcdbrc @@ -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 index 00000000..a207d34f --- /dev/null +++ b/src/spiradio-v0.1/Makefile @@ -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 index 00000000..f38aade6 --- /dev/null +++ b/src/spiradio-v0.1/ao_pins.h @@ -0,0 +1,64 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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 index 00000000..d3647cc7 --- /dev/null +++ b/src/spiradio-v0.1/ao_spiradio.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +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(); +} diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 055a73af..09c9c3ca 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -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 diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 9a581ff9..fe7c69f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -16,6 +16,10 @@ */ #include "ao.h" +#include +#include +#include +#include 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); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 7e222122..c9c7446e 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -135,6 +135,8 @@ #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_ */ diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 3edfa41d..04404cdc 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -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 diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 7564c7fa..18ca6ea0 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -17,15 +17,6 @@ #include #include -#if HAS_MPU6000 -#include -#endif -#if HAS_MS5607 -#include -#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 { diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 484ce89e..87eda18b 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,10 +25,15 @@ * 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)) diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d2c973f5..d4fbea37 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -20,12 +20,37 @@ /* 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 index 00000000..38d2f7ff --- /dev/null +++ b/src/stm/ao_data.c @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +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 index 00000000..5a75a97d --- /dev/null +++ b/src/stm/ao_eeprom_stm.c @@ -0,0 +1,203 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +/* 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) +{ +} diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index b579ad9f..35b56b57 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -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)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index d54e6ee6..1361d0d4 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -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); } diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index b1909444..0f9a8eb5 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -16,6 +16,7 @@ */ #include +#include 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 \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 index 00000000..14667546 --- /dev/null +++ b/src/stm/ao_lcd_stm.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_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_ */ diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 547de9e5..ade86a27 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -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 diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index ebe75366..f561e6b5 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -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 diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index ff8dddff..25f5af07 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -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) diff --git a/src/telebt-v0.1/.sdcdbrc b/src/telebt-v0.1/.sdcdbrc index 710b4a2f..b9f6129c 100644 --- a/src/telebt-v0.1/.sdcdbrc +++ b/src/telebt-v0.1/.sdcdbrc @@ -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 index 00000000..b9f6129c --- /dev/null +++ b/src/telefire-v0.1/.sdcdbrc @@ -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 index 00000000..712b2e8b --- /dev/null +++ b/src/telefire-v0.1/Makefile @@ -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 = \ + ao_adc.c \ + ao_aes.c \ + ao_beep.c \ + ao_dma.c \ + ao_intflash.c \ + ao_radio.c \ + ao_radio_cmac.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_pca9922.c \ + ao_74hc497.c \ + ao_pad.c \ + ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ + ao_telefire.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = telefire-v$(TELEFIRE_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleFire-v$(TELEFIRE_VER) +PRODUCT_DEF=-DTELEFIRE_V_$(TELEFIRE_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/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h new file mode 100644 index 00000000..eecf783e --- /dev/null +++ b/src/telefire-v0.1/ao_pins.h @@ -0,0 +1,113 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define HAS_PAD 1 +#define USE_INTERNAL_FLASH 1 +#define DBG_ON_P1 0 +#define IGNITE_ON_P2 0 +#define IGNITE_ON_P1 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 + +#define AO_LED_CONTINUITY(c) (1 << (c)) +#define AO_LED_CONTINUITY_MASK (0xf) +#define AO_LED_RX 0x10 +#define AO_LED_TX 0x20 +#define AO_LED_ARMED 0x40 +#define AO_LED_POWER 0x80 + +#define AO_LED_RED AO_LED_TX +#define AO_LED_GREEN AO_LED_RX + +#define LEDS_AVAILABLE (0xff) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL_REF 0 +#define SPI_CS_ON_P1 1 +#define HAS_AES 1 +#define DMA_SHARE_AES_RADIO 1 + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +#define SPI_CONST 0x00 + +#define HAS_SPI_0 0 +#define HAS_SPI_1 1 +#define SPI_1_ALT_1 0 +#define SPI_1_ALT_2 1 + +#define AO_74HC497_CS_PORT P1 +#define AO_74HC497_CS_PIN 4 +#define AO_74HC497_CS P1_4 + +#define AO_PCA9922_CS_PORT P1 +#define AO_PCA9922_CS_PIN 4 +#define AO_PCA9922_CS P1_4 + +#define AO_PAD_NUM 4 +#define AO_PAD_PORT P1 +#define AO_PAD_DIR P1DIR +#define AO_PAD_PIN_0 0 +#define AO_PAD_0 P1_0 +#define AO_PAD_PIN_1 1 +#define AO_PAD_1 P1_1 +#define AO_PAD_PIN_2 2 +#define AO_PAD_2 P1_2 +#define AO_PAD_PIN_3 3 +#define AO_PAD_3 P1_3 +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +struct ao_adc { + int16_t sense[4]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], \ + (p)->adc.sense[1], \ + (p)->adc.sense[2], \ + (p)->adc.sense[3], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c new file mode 100644 index 00000000..cc0f668f --- /dev/null +++ b/src/telefire-v0.1/ao_telefire.c @@ -0,0 +1,44 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_74hc497_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_aes_init(); + ao_pad_init(); +// ao_radio_cmac_cmd_init(); + ao_config_init(); + ao_start_scheduler(); +}