summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBdale Garbee <bdale@gag.com>2012-08-28 23:39:53 -0600
committerBdale Garbee <bdale@gag.com>2012-08-28 23:39:53 -0600
commit5ed88fb72c3e3ecf3333c700d838667db71cfbdc (patch)
tree3b371f563c0f7607f2fe53242673adb352b48514
parentadbe64c5a9402b7c5075a444a12629131b663877 (diff)
parent621d0930244f25165d2ac5da596dcc87e253b965 (diff)
Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
Conflicts: debian/control
-rw-r--r--.gitignore1
-rw-r--r--altosdroid/.classpath4
-rw-r--r--altosdroid/.gitignore1
-rw-r--r--altosdroid/AndroidManifest.xml2
-rw-r--r--altosdroid/Makefile.am13
-rw-r--r--altosdroid/build.properties1
-rw-r--r--altosdroid/libs/.gitignore1
-rw-r--r--altosdroid/local.properties.in1
-rw-r--r--altosdroid/res/drawable-hdpi/am_status_c.pngbin0 -> 994 bytes
-rw-r--r--altosdroid/res/drawable-hdpi/am_status_g.png (renamed from altosdroid/res/drawable-hdpi/am_status.png)bin804 -> 804 bytes
-rw-r--r--altosdroid/res/drawable-mdpi/am_status_c.pngbin0 -> 703 bytes
-rw-r--r--altosdroid/res/drawable-mdpi/am_status_g.png (renamed from altosdroid/res/drawable-mdpi/am_status.png)bin595 -> 595 bytes
-rw-r--r--altosdroid/res/layout/main.xml25
-rw-r--r--altosdroid/res/menu/option_menu.xml12
-rw-r--r--altosdroid/res/values/strings.xml29
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java111
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java54
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java51
-rw-r--r--altoslib/AltosIdleMonitor.java67
-rw-r--r--altoslib/AltosIgnite.java (renamed from altosui/AltosIgnite.java)91
-rw-r--r--altoslib/AltosLink.java22
-rw-r--r--altoslib/AltosRecord.java2
-rw-r--r--altoslib/AltosRecordTM.java16
-rw-r--r--altoslib/AltosState.java2
-rw-r--r--altoslib/Makefile.am1
-rw-r--r--altosui/.gitignore1
-rw-r--r--altosui/AltosIgniteUI.java7
-rw-r--r--altosui/AltosInfoTable.java34
-rw-r--r--altosui/AltosSerial.java16
-rw-r--r--altosui/Makefile.am1
-rw-r--r--altosui/altos-windows.nsi3
-rw-r--r--altosui/libaltos/libaltos.c4
-rw-r--r--ao-tools/Makefile.am2
-rw-r--r--ao-tools/ao-send-telem/Makefile.am12
-rw-r--r--ao-tools/ao-send-telem/ao-send-telem.164
-rw-r--r--ao-tools/ao-send-telem/ao-send-telem.c239
-rw-r--r--ao-tools/ao-stmload/Makefile.am11
-rw-r--r--configure.ac8
-rw-r--r--src/Makefile6
-rw-r--r--src/aes/ao_aes.c390
-rw-r--r--src/aes/ao_aes_int.h64
-rw-r--r--src/aes/ao_aes_tables.c768
-rw-r--r--src/aes/ao_aes_tables.h10
-rw-r--r--src/cc1111/Makefile.cc11115
-rw-r--r--src/cc1111/ao_adc.c20
-rw-r--r--src/cc1111/ao_aes.c4
-rw-r--r--src/cc1111/ao_arch.h12
-rw-r--r--src/cc1111/ao_arch_funcs.h10
-rw-r--r--src/cc1111/ao_launch.c3
-rw-r--r--src/cc1111/ao_pins.h12
-rw-r--r--src/cc1111/ao_radio.c66
-rw-r--r--src/cc1111/ao_serial.c46
-rw-r--r--src/cc1111/ao_spi.c172
-rw-r--r--src/core/ao.h20
-rw-r--r--src/core/ao_aes.h19
-rw-r--r--src/core/ao_config.c3
-rw-r--r--src/core/ao_data.h50
-rw-r--r--src/core/ao_led.h4
-rw-r--r--src/core/ao_radio_cmac.c169
-rw-r--r--src/core/ao_radio_cmac.h43
-rw-r--r--src/core/ao_send_packet.c74
-rw-r--r--src/core/ao_send_packet.h24
-rw-r--r--src/core/ao_storage.c1
-rw-r--r--src/core/ao_task.c29
-rw-r--r--src/drivers/ao_74hc497.c55
-rw-r--r--src/drivers/ao_74hc497.h27
-rw-r--r--src/drivers/ao_button.c94
-rw-r--r--src/drivers/ao_button.h24
-rw-r--r--src/drivers/ao_cc1120.c4
-rw-r--r--src/drivers/ao_event.c77
-rw-r--r--src/drivers/ao_event.h41
-rw-r--r--src/drivers/ao_hmc5883.c23
-rw-r--r--src/drivers/ao_hmc5883.h4
-rw-r--r--src/drivers/ao_lco_cmd.c (renamed from src/ao_radio_cmac.c)304
-rw-r--r--src/drivers/ao_lco_cmd.h24
-rw-r--r--src/drivers/ao_mma655x.c227
-rw-r--r--src/drivers/ao_mma655x.h85
-rw-r--r--src/drivers/ao_mpu6000.c30
-rw-r--r--src/drivers/ao_mpu6000.h3
-rw-r--r--src/drivers/ao_ms5607.c33
-rw-r--r--src/drivers/ao_ms5607.h3
-rw-r--r--src/drivers/ao_pad.c308
-rw-r--r--src/drivers/ao_pad.h73
-rw-r--r--src/drivers/ao_pca9922.c86
-rw-r--r--src/drivers/ao_quadrature.c134
-rw-r--r--src/drivers/ao_quadrature.h32
-rw-r--r--src/drivers/ao_radio_master.c266
-rw-r--r--src/drivers/ao_radio_slave.c127
-rw-r--r--src/drivers/ao_radio_spi.h58
-rw-r--r--src/drivers/ao_seven_segment.c216
-rw-r--r--src/drivers/ao_seven_segment.h34
-rw-r--r--src/megametrum-v0.1/Makefile4
-rw-r--r--src/megametrum-v0.1/ao_megametrum.c4
-rw-r--r--src/megametrum-v0.1/ao_pins.h25
-rw-r--r--src/megametrum-v0.1/stlink-pins49
-rw-r--r--src/product/Makefile.teledongle1
-rw-r--r--src/product/ao_teledongle.c2
-rw-r--r--src/product/ao_telelaunch.c1
-rw-r--r--src/spiradio-v0.1/.sdcdbrc2
-rw-r--r--src/spiradio-v0.1/ao_pins.h61
-rw-r--r--src/spiradio-v0.1/ao_spiradio.c37
-rw-r--r--src/stm-demo/Makefile7
-rw-r--r--src/stm-demo/ao_demo.c24
-rw-r--r--src/stm-demo/ao_pins.h27
-rw-r--r--src/stm/Makefile.defs2
-rw-r--r--src/stm/ao_adc_stm.c42
-rw-r--r--src/stm/ao_arch.h7
-rw-r--r--src/stm/ao_arch_funcs.h40
-rw-r--r--src/stm/ao_eeprom_stm.c191
-rw-r--r--src/stm/ao_exti.h3
-rw-r--r--src/stm/ao_exti_stm.c14
-rw-r--r--src/stm/ao_lcd_stm.c109
-rw-r--r--src/stm/ao_lcd_stm.h30
-rw-r--r--src/stm/ao_spi_stm.c162
-rw-r--r--src/stm/ao_timer.c21
-rw-r--r--src/stm/stm32l.h26
-rw-r--r--src/telebt-v0.1/.sdcdbrc3
-rw-r--r--src/telefire-v0.1/.sdcdbrc2
-rw-r--r--src/telefire-v0.1/Makefile102
-rw-r--r--src/telefire-v0.1/ao_pins.h113
-rw-r--r--src/telefire-v0.1/ao_telefire.c42
121 files changed, 5615 insertions, 863 deletions
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/altosdroid/.classpath b/altosdroid/.classpath
index d260cafa..0ca188f9 100644
--- a/altosdroid/.classpath
+++ b/altosdroid/.classpath
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
- <classpathentry kind="lib" path="lib/AltosLib.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
- <classpathentry kind="output" path="bin"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
</classpath>
diff --git a/altosdroid/.gitignore b/altosdroid/.gitignore
index 44f249ee..c0bb8dd4 100644
--- a/altosdroid/.gitignore
+++ b/altosdroid/.gitignore
@@ -1,4 +1,3 @@
local.properties
bin
gen
-local.properties
diff --git a/altosdroid/AndroidManifest.xml b/altosdroid/AndroidManifest.xml
index 1d55737d..96fe5ac7 100644
--- a/altosdroid/AndroidManifest.xml
+++ b/altosdroid/AndroidManifest.xml
@@ -17,7 +17,7 @@
package="org.altusmetrum.AltosDroid"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk minSdkVersion="6" />
+ <uses-sdk android:targetSdkVersion="10" android:minSdkVersion="10"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am
index 0732087b..6ee984c2 100644
--- a/altosdroid/Makefile.am
+++ b/altosdroid/Makefile.am
@@ -15,6 +15,11 @@ APKBUILDER=$(SDK)/tools/apkbuilder
ZIPALIGN=$(SDK)/tools/zipalign
SRC_DIR=src/org/altusmetrum/AltosDroid
+EXT_LIBDIR=libs
+ALTOSLIB_SRCDIR=../altoslib
+ALTOSLIB_JAR=AltosLib.jar
+
+ALTOSLIB=$(EXT_LIBDIR)/$(ALTOSLIB_JAR)
SRC=\
$(SRC_DIR)/AltosDroid.java \
@@ -25,11 +30,9 @@ SRC=\
all: $(all_target)
-ALTOSLIB=bin/classes/AltosLib.jar
-
-$(ALTOSLIB):
- mkdir -p bin/classes
- cd bin/classes && ln -s ../../../altoslib/AltosLib.jar .
+$(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR)
+ mkdir -p $(EXT_LIBDIR)
+ cd $(EXT_LIBDIR) && ln -s $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) .
if ANDROID
install-release: bin/AltosDroid-release.apk
diff --git a/altosdroid/build.properties b/altosdroid/build.properties
deleted file mode 100644
index 63d080cc..00000000
--- a/altosdroid/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-jar.libs.dir=../altoslib \ No newline at end of file
diff --git a/altosdroid/libs/.gitignore b/altosdroid/libs/.gitignore
new file mode 100644
index 00000000..b4e68f63
--- /dev/null
+++ b/altosdroid/libs/.gitignore
@@ -0,0 +1 @@
+AltosLib.jar
diff --git a/altosdroid/local.properties.in b/altosdroid/local.properties.in
index 543ce208..14df0494 100644
--- a/altosdroid/local.properties.in
+++ b/altosdroid/local.properties.in
@@ -8,4 +8,3 @@
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=@ANDROID_SDK@
-extensible.libs.classpath=../altoslib
diff --git a/altosdroid/res/drawable-hdpi/am_status_c.png b/altosdroid/res/drawable-hdpi/am_status_c.png
new file mode 100644
index 00000000..d4393217
--- /dev/null
+++ b/altosdroid/res/drawable-hdpi/am_status_c.png
Binary files differ
diff --git a/altosdroid/res/drawable-hdpi/am_status.png b/altosdroid/res/drawable-hdpi/am_status_g.png
index 03f9dd7d..03f9dd7d 100644
--- a/altosdroid/res/drawable-hdpi/am_status.png
+++ b/altosdroid/res/drawable-hdpi/am_status_g.png
Binary files differ
diff --git a/altosdroid/res/drawable-mdpi/am_status_c.png b/altosdroid/res/drawable-mdpi/am_status_c.png
new file mode 100644
index 00000000..30a8d29a
--- /dev/null
+++ b/altosdroid/res/drawable-mdpi/am_status_c.png
Binary files differ
diff --git a/altosdroid/res/drawable-mdpi/am_status.png b/altosdroid/res/drawable-mdpi/am_status_g.png
index 07f7f073..07f7f073 100644
--- a/altosdroid/res/drawable-mdpi/am_status.png
+++ b/altosdroid/res/drawable-mdpi/am_status_g.png
Binary files differ
diff --git a/altosdroid/res/layout/main.xml b/altosdroid/res/layout/main.xml
index 17025f6b..070928a5 100644
--- a/altosdroid/res/layout/main.xml
+++ b/altosdroid/res/layout/main.xml
@@ -19,24 +19,31 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <ListView android:id="@+id/in"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:stackFromBottom="true"
- android:transcriptMode="alwaysScroll"
+
+ <TextView
+ android:id="@+id/in"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
android:layout_weight="1"
- />
+ android:gravity="bottom"
+ android:scrollbars="vertical"
+ android:textSize="7dp"
+ android:typeface="monospace" />
+
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
- <EditText android:id="@+id/edit_text_out"
+
+ <EditText
+ android:id="@+id/edit_text_out"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
android:layout_gravity="bottom"
- />
+ android:layout_weight="1"
+ android:inputType="text|textNoSuggestions" />
+
<Button android:id="@+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml
index 27625e9c..feb5668e 100644
--- a/altosdroid/res/menu/option_menu.xml
+++ b/altosdroid/res/menu/option_menu.xml
@@ -14,19 +14,13 @@
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/connect_scan"
+ android:icon="@android:drawable/ic_menu_search"
+ android:title="@string/connect_device" />
<item android:id="@+id/telemetry_service_control"
android:icon="@android:drawable/ic_menu_manage"
android:title="@string/telemetry_service_control" />
<item android:id="@+id/telemetry_service_bind"
android:icon="@android:drawable/ic_menu_rotate"
android:title="@string/telemetry_service_bind" />
- <item android:id="@+id/secure_connect_scan"
- android:icon="@android:drawable/ic_menu_search"
- android:title="@string/secure_connect" />
- <item android:id="@+id/insecure_connect_scan"
- android:icon="@android:drawable/ic_menu_search"
- android:title="@string/insecure_connect" />
- <item android:id="@+id/discoverable"
- android:icon="@android:drawable/ic_menu_mylocation"
- android:title="@string/discoverable" />
</menu>
diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml
index 0b2f9227..72a4ddec 100644
--- a/altosdroid/res/values/strings.xml
+++ b/altosdroid/res/values/strings.xml
@@ -21,12 +21,12 @@
<string name="send">Send</string>
<string name="not_connected">You are not connected to a device</string>
<string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string>
- <string name="title_connecting">connecting...</string>
+ <string name="title_connecting">connecting…</string>
<string name="title_connected_to">connected: </string>
<string name="title_not_connected">not connected</string>
<!-- DeviceListActivity -->
- <string name="scanning">scanning for devices...</string>
+ <string name="scanning">scanning for devices…</string>
<string name="select_device">select a device to connect</string>
<string name="none_paired">No devices have been paired</string>
<string name="none_found">No devices found</string>
@@ -35,32 +35,31 @@
<string name="button_scan">Scan for devices</string>
<!-- Options Menu -->
- <string name="secure_connect">Connect a device - Secure</string>
- <string name="insecure_connect">Connect a device - Insecure</string>
- <string name="discoverable">Make discoverable</string>
+ <string name="connect_device">Connect a device</string>
+ <string name="telemetry_service_control">Control Service</string>
+ <string name="telemetry_service_bind">(Un)Bind Service</string>
+
+
<!-- Service -->
- <string name="telemetry_service_label">AltOS Telemetry Service</string>
+ <string name="telemetry_service_label">AltosDroid Telemetry Service</string>
<string name="telemetry_service_started">Telemetry Service Started</string>
<string name="telemetry_service_stopped">Telemetry Service Stopped</string>
-
-
- <string name="telemetry_service_control">Start/Stop Service</string>
- <string name="telemetry_service_bind">Bind/Unbind Service</string>
-
- <string name="activity_telemetry_service_controller">App/Service/Local Service Controller</string>
- <string name="telemetry_service_controller">This demonstrates how you can implement persistent services that
- may be started and stopped as desired.</string>
+ <!-- Service control activity - temporary! -->
+ <string name="activity_telemetry_service_controller">Telemetry Service Controller</string>
+ <string name="telemetry_service_controller">Use the following buttons to start and stop the Telemetry
+ service.</string>
<string name="start_service">Start Service</string>
<string name="stop_service">Stop Service</string>
- <string name="activity_telemetry_service_binding">App/Service/Local Service Binding</string>
+ <string name="activity_telemetry_service_binding">Telemetry Service Binding</string>
<string name="telemetry_service_binding">This demonstrates how you can connect with a persistent
service. Notice how it automatically starts for you, and play around with the
interaction between this and Local Service Controller.</string>
<string name="bind_service">Bind Service</string>
<string name="unbind_service">Unbind Service</string>
+
<string name="telemetry_service_connected">Connected to local service</string>
<string name="telemetry_service_disconnected">Disconnected from local service</string>
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
index b4a3227c..b4725e22 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -32,10 +33,8 @@ import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
-import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
-import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.altusmetrum.AltosDroid.R;
@@ -46,11 +45,9 @@ import org.altusmetrum.AltosLib.*;
*/
public class AltosDroid extends Activity {
// Debugging
- private static final String TAG = "BluetoothChat";
+ private static final String TAG = "AltosDroid";
private static final boolean D = true;
- private static final AltosLine q = new AltosLine();
-
// Message types sent from the BluetoothChatService Handler
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
@@ -63,20 +60,17 @@ public class AltosDroid extends Activity {
public static final String TOAST = "toast";
// Intent request codes
- private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
- private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
- private static final int REQUEST_ENABLE_BT = 3;
+ private static final int REQUEST_CONNECT_DEVICE = 1;
+ private static final int REQUEST_ENABLE_BT = 2;
// Layout Views
private TextView mTitle;
- private ListView mConversationView;
+ private TextView mSerialView;
private EditText mOutEditText;
private Button mSendButton;
// Name of the connected device
private String mConnectedDeviceName = null;
- // Array adapter for the conversation thread
- private ArrayAdapter<String> mConversationArrayAdapter;
// String buffer for outgoing messages
private StringBuffer mOutStringBuffer;
// Local Bluetooth adapter
@@ -144,13 +138,35 @@ public class AltosDroid extends Activity {
}
}
+ @Override
+ public synchronized void onPause() {
+ super.onPause();
+ if(D) Log.e(TAG, "- ON PAUSE -");
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if(D) Log.e(TAG, "-- ON STOP --");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ // Stop the Bluetooth chat services
+ if (mChatService != null) mChatService.stop();
+ if(D) Log.e(TAG, "--- ON DESTROY ---");
+ }
+
+
+
private void setupChat() {
Log.d(TAG, "setupChat()");
- // Initialize the array adapter for the conversation thread
- mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
- mConversationView = (ListView) findViewById(R.id.in);
- mConversationView.setAdapter(mConversationArrayAdapter);
+ mSerialView = (TextView) findViewById(R.id.in);
+ mSerialView.setMovementMethod(new ScrollingMovementMethod());
+ mSerialView.setClickable(false);
+ mSerialView.setLongClickable(false);
// Initialize the compose field with a listener for the return key
mOutEditText = (EditText) findViewById(R.id.edit_text_out);
@@ -174,36 +190,6 @@ public class AltosDroid extends Activity {
mOutStringBuffer = new StringBuffer("");
}
- @Override
- public synchronized void onPause() {
- super.onPause();
- if(D) Log.e(TAG, "- ON PAUSE -");
- }
-
- @Override
- public void onStop() {
- super.onStop();
- if(D) Log.e(TAG, "-- ON STOP --");
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- // Stop the Bluetooth chat services
- if (mChatService != null) mChatService.stop();
- if(D) Log.e(TAG, "--- ON DESTROY ---");
- }
-
- private void ensureDiscoverable() {
- if(D) Log.d(TAG, "ensure discoverable");
- if (mBluetoothAdapter.getScanMode() !=
- BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
- Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
- discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
- startActivity(discoverableIntent);
- }
- }
-
/**
* Sends a message.
* @param message A string of text to send.
@@ -252,7 +238,7 @@ public class AltosDroid extends Activity {
case BluetoothChatService.STATE_CONNECTED:
mTitle.setText(R.string.title_connected_to);
mTitle.append(mConnectedDeviceName);
- mConversationArrayAdapter.clear();
+ mSerialView.setText("");
break;
case BluetoothChatService.STATE_CONNECTING:
mTitle.setText(R.string.title_connecting);
@@ -267,13 +253,13 @@ public class AltosDroid extends Activity {
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
- mConversationArrayAdapter.add("Me: " + writeMessage);
+ mSerialView.append(writeMessage + '\n');
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
- mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
+ mSerialView.append(readMessage);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
@@ -292,16 +278,10 @@ public class AltosDroid extends Activity {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(D) Log.d(TAG, "onActivityResult " + resultCode);
switch (requestCode) {
- case REQUEST_CONNECT_DEVICE_SECURE:
- // When DeviceListActivity returns with a device to connect
+ case REQUEST_CONNECT_DEVICE:
+ // When DeviceListActivity returns with a device to connect to
if (resultCode == Activity.RESULT_OK) {
- connectDevice(data, true);
- }
- break;
- case REQUEST_CONNECT_DEVICE_INSECURE:
- // When DeviceListActivity returns with a device to connect
- if (resultCode == Activity.RESULT_OK) {
- connectDevice(data, false);
+ connectDevice(data);
}
break;
case REQUEST_ENABLE_BT:
@@ -318,14 +298,14 @@ public class AltosDroid extends Activity {
}
}
- private void connectDevice(Intent data, boolean secure) {
+ private void connectDevice(Intent data) {
// Get the device MAC address
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BLuetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
- mChatService.connect(device, secure);
+ mChatService.connect(device);
}
@Override
@@ -347,19 +327,10 @@ public class AltosDroid extends Activity {
serverIntent = new Intent(this, TelemetryServiceActivities.Binding.class);
startActivity(serverIntent);
return true;
- case R.id.secure_connect_scan:
- // Launch the DeviceListActivity to see devices and do scan
- serverIntent = new Intent(this, DeviceListActivity.class);
- startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
- return true;
- case R.id.insecure_connect_scan:
+ case R.id.connect_scan:
// Launch the DeviceListActivity to see devices and do scan
serverIntent = new Intent(this, DeviceListActivity.class);
- startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
- return true;
- case R.id.discoverable:
- // Ensure this device is discoverable by others
- ensureDiscoverable();
+ startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
}
return false;
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java b/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java
index 93cb75de..a93c08d6 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java
@@ -19,9 +19,7 @@ package org.altusmetrum.AltosDroid;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-//import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
+import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
@@ -103,9 +101,8 @@ public class BluetoothChatService {
/**
* Start the ConnectThread to initiate a connection to a remote device.
* @param device The BluetoothDevice to connect
- * @param secure Socket Security type - Secure (true) , Insecure (false)
*/
- public synchronized void connect(BluetoothDevice device, boolean secure) {
+ public synchronized void connect(BluetoothDevice device) {
if (D) Log.d(TAG, "connect to: " + device);
// Cancel any thread attempting to make a connection
@@ -117,7 +114,7 @@ public class BluetoothChatService {
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
// Start the thread to connect with the given device
- mConnectThread = new ConnectThread(device, secure);
+ mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
@@ -127,9 +124,8 @@ public class BluetoothChatService {
* @param socket The BluetoothSocket on which the connection was made
* @param device The BluetoothDevice that has been connected
*/
- public synchronized void connected(BluetoothSocket socket, BluetoothDevice
- device, final String socketType) {
- if (D) Log.d(TAG, "connected, Socket Type:" + socketType);
+ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
+ if (D) Log.d(TAG, "connected");
// Cancel the thread that completed the connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
@@ -138,7 +134,7 @@ public class BluetoothChatService {
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
// Start the thread to manage the connection and perform transmissions
- mConnectedThread = new ConnectedThread(socket, socketType);
+ mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
@@ -224,37 +220,25 @@ public class BluetoothChatService {
* succeeds or fails.
*/
private class ConnectThread extends Thread {
+ private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
- private String mSocketType;
- public ConnectThread(BluetoothDevice device, boolean secure) {
+ public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
- mSocketType = secure ? "Secure" : "Insecure";
- // Get a BluetoothSocket for a connection with the
- // given BluetoothDevice
try {
- if (secure) {
- Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
- tmp = (BluetoothSocket) m.invoke(device, 2);
-// tmp = device.createRfcommSocket(1);
- } else {
- Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class});
- tmp = (BluetoothSocket) m.invoke(device, 2);
-// tmp = device.createInsecureRfcommSocket(1);
- }
- } catch (Exception e) {
- Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
+ tmp = mmDevice.createInsecureRfcommSocketToServiceRecord(SPP_UUID);
+ } catch (IOException e) {
e.printStackTrace();
}
mmSocket = tmp;
}
public void run() {
- Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
- setName("ConnectThread" + mSocketType);
+ Log.i(TAG, "BEGIN mConnectThread");
+ setName("ConnectThread");
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
@@ -269,8 +253,7 @@ public class BluetoothChatService {
try {
mmSocket.close();
} catch (IOException e2) {
- Log.e(TAG, "unable to close() " + mSocketType +
- " socket during connection failure", e2);
+ Log.e(TAG, "unable to close() socket during connection failure", e2);
}
connectionFailed();
return;
@@ -282,14 +265,14 @@ public class BluetoothChatService {
}
// Start the connected thread
- connected(mmSocket, mmDevice, mSocketType);
+ connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
- Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
+ Log.e(TAG, "close() of connect socket failed", e);
}
}
}
@@ -303,8 +286,8 @@ public class BluetoothChatService {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
- public ConnectedThread(BluetoothSocket socket, String socketType) {
- Log.d(TAG, "create ConnectedThread: " + socketType);
+ public ConnectedThread(BluetoothSocket socket) {
+ Log.d(TAG, "create ConnectedThread");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
@@ -333,7 +316,7 @@ public class BluetoothChatService {
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
- mHandler.obtainMessage(AltosDroid.MESSAGE_READ, bytes, -1, buffer)
+ mHandler.obtainMessage(AltosDroid.MESSAGE_READ, bytes, -1, buffer.clone())
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
@@ -350,6 +333,7 @@ public class BluetoothChatService {
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
+ mmOutStream.write('\n');
// Share the sent message back to the UI Activity
mHandler.obtainMessage(AltosDroid.MESSAGE_WRITE, -1, -1, buffer)
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
index 40dff354..c0a32c92 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
@@ -37,7 +37,7 @@ public class TelemetryService extends Service {
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
- private int NOTIFICATION = R.string.telemetry_service_started;
+ private int NOTIFICATION = R.string.telemetry_service_label;
/**
* Class for clients to access. Because we know this service always
@@ -52,15 +52,32 @@ public class TelemetryService extends Service {
@Override
public void onCreate() {
+ // Create a reference to the NotificationManager so that we can update our notifcation text later
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
-
- // Display a notification about us starting. We put an icon in the status bar.
- showNotification();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("TelemetryService", "Received start id " + startId + ": " + intent);
+
+ CharSequence text = getText(R.string.telemetry_service_started);
+
+ // Create notification to be displayed while the service runs
+ Notification notification = new Notification(R.drawable.am_status_c, text, 0);
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, TelemetryServiceActivities.Controller.class), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.telemetry_service_label), text, contentIntent);
+
+ // Set the notification to be in the "Ongoing" section.
+ notification.flags |= Notification.FLAG_ONGOING_EVENT;
+
+ // Move us into the foreground.
+ startForeground(NOTIFICATION, notification);
+
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
@@ -68,8 +85,8 @@ public class TelemetryService extends Service {
@Override
public void onDestroy() {
- // Cancel the persistent notification.
- mNM.cancel(NOTIFICATION);
+ // Demote us from the foreground, and cancel the persistent notification.
+ stopForeground(true);
// Tell the user we stopped.
Toast.makeText(this, R.string.telemetry_service_stopped, Toast.LENGTH_SHORT).show();
@@ -84,26 +101,4 @@ public class TelemetryService extends Service {
// RemoteService for a more complete example.
private final IBinder mBinder = new TelemetryBinder();
- /**
- * Show a notification while this service is running.
- */
- private void showNotification() {
- // In this sample, we'll use the same text for the ticker and the expanded notification
- CharSequence text = getText(R.string.telemetry_service_started);
-
- // Set the icon, scrolling text and timestamp
- Notification notification = new Notification(R.drawable.am_status, text,
- System.currentTimeMillis());
-
- // The PendingIntent to launch our activity if the user selects this notification
- PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
- new Intent(this, TelemetryServiceActivities.Controller.class), 0);
-
- // Set the info for the views that show in the notification panel.
- notification.setLatestEventInfo(this, getText(R.string.telemetry_service_label),
- text, contentIntent);
-
- // Send the notification.
- mNM.notify(NOTIFICATION, notification);
- }
}
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/altosui/AltosIgnite.java b/altoslib/AltosIgnite.java
index f84db0b9..cc814337 100644
--- a/altosui/AltosIgnite.java
+++ b/altoslib/AltosIgnite.java
@@ -15,46 +15,39 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package altosui;
+package org.altusmetrum.AltosLib;
import java.io.*;
import java.util.concurrent.*;
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.table.*;
-import javax.swing.event.*;
-import org.altusmetrum.AltosLib.*;
public class AltosIgnite {
- AltosDevice device;
- AltosSerial serial;
+ AltosLink link;
boolean remote;
- boolean serial_started;
- final static int None = 0;
- final static int Apogee = 1;
- final static int Main = 2;
-
- final static int Unknown = 0;
- final static int Ready = 1;
- final static int Active = 2;
- final static int Open = 3;
-
- private void start_serial() throws InterruptedException, TimeoutException {
- serial_started = true;
+ boolean link_started;
+
+ public final static int None = 0;
+ public final static int Apogee = 1;
+ public final static int Main = 2;
+
+ public final static int Unknown = 0;
+ public final static int Ready = 1;
+ public final static int Active = 2;
+ public final static int Open = 3;
+
+ private void start_link() throws InterruptedException, TimeoutException {
+ link_started = true;
if (remote)
- serial.start_remote();
+ link.start_remote();
}
- private void stop_serial() throws InterruptedException {
- if (!serial_started)
+ private void stop_link() throws InterruptedException {
+ if (!link_started)
return;
- serial_started = false;
- if (serial == null)
+ link_started = false;
+ if (link == null)
return;
if (remote)
- serial.stop_remote();
+ link.stop_remote();
}
class string_ref {
@@ -100,14 +93,14 @@ public class AltosIgnite {
public int status(int igniter) throws InterruptedException, TimeoutException {
int status = Unknown;
- if (serial == null)
+ if (link == null)
return status;
string_ref status_name = new string_ref();
try {
- start_serial();
- serial.printf("t\n");
+ start_link();
+ link.printf("t\n");
for (;;) {
- String line = serial.get_reply(5000);
+ String line = link.get_reply(5000);
if (line == null)
throw new TimeoutException();
String[] items = line.split("\\s+");
@@ -131,7 +124,7 @@ public class AltosIgnite {
}
}
} finally {
- stop_serial();
+ stop_link();
}
return status;
}
@@ -147,23 +140,23 @@ public class AltosIgnite {
}
public void fire(int igniter) {
- if (serial == null)
+ if (link == null)
return;
try {
- start_serial();
+ start_link();
switch (igniter) {
case Main:
- serial.printf("i DoIt main\n");
+ link.printf("i DoIt main\n");
break;
case Apogee:
- serial.printf("i DoIt drogue\n");
+ link.printf("i DoIt drogue\n");
break;
}
} catch (InterruptedException ie) {
} catch (TimeoutException te) {
} finally {
try {
- stop_serial();
+ stop_link();
} catch (InterruptedException ie) {
}
}
@@ -171,25 +164,17 @@ public class AltosIgnite {
public void close() {
try {
- stop_serial();
+ stop_link();
} catch (InterruptedException ie) {
}
- serial.close();
- serial = null;
+ link.close();
+ link = null;
}
- public void set_frame(Frame frame) {
- serial.set_frame(frame);
- }
-
- public AltosIgnite(AltosDevice in_device)
- throws FileNotFoundException, AltosSerialInUseException, TimeoutException, InterruptedException {
-
- device = in_device;
- serial = new AltosSerial(device);
- remote = false;
+ public AltosIgnite(AltosLink in_link, boolean in_remote)
+ throws FileNotFoundException, TimeoutException, InterruptedException {
- if (!device.matchProduct(Altos.product_altimeter))
- remote = true;
+ link = in_link;
+ remote = in_remote;
}
} \ No newline at end of file
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 <AltosRecord>, 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/altoslib/Makefile.am b/altoslib/Makefile.am
index a39623ee..1f42140b 100644
--- a/altoslib/Makefile.am
+++ b/altoslib/Makefile.am
@@ -29,6 +29,7 @@ AltosLib_JAVA = \
$(SRC)/AltosGreatCircle.java \
$(SRC)/AltosIdleMonitor.java \
$(SRC)/AltosIdleMonitorListener.java \
+ $(SRC)/AltosIgnite.java \
$(SRC)/AltosLine.java \
$(SRC)/AltosLink.java \
$(SRC)/AltosLog.java \
diff --git a/altosui/.gitignore b/altosui/.gitignore
index 6d65611f..6d2d8c23 100644
--- a/altosui/.gitignore
+++ b/altosui/.gitignore
@@ -5,6 +5,7 @@ fat/
Manifest.txt
Manifest-fat.txt
AltosVersion.java
+Info.plist
libaltosJNI
classes
altosui
diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java
index 076d99b2..78eba8e6 100644
--- a/altosui/AltosIgniteUI.java
+++ b/altosui/AltosIgniteUI.java
@@ -72,12 +72,15 @@ public class AltosIgniteUI
public void run () {
try {
- ignite = new AltosIgnite(device);
+ AltosSerial serial = new AltosSerial(device);
+ serial.set_frame(owner);
+ ignite = new AltosIgnite(serial,
+ !device.matchProduct(Altos.product_altimeter));
+
} catch (Exception e) {
send_exception(e);
return;
}
- ignite.set_frame(owner);
for (;;) {
Runnable r;
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<String> devices_opened = Collections.synchronizedList(new LinkedList<String>());
@@ -54,13 +54,19 @@ public class AltosSerial extends AltosLink implements Runnable {
Frame frame;
public int getchar() {
+ if (altos == null)
+ return ERROR;
return libaltos.altos_getchar(altos, 0);
}
public void flush_output() {
super.flush_output();
if (altos != null) {
- libaltos.altos_flush(altos);
+ if (libaltos.altos_flush(altos) != 0) {
+ libaltos.altos_close(altos);
+ altos = null;
+ abort_reply();
+ }
}
}
@@ -155,7 +161,11 @@ public class AltosSerial extends AltosLink implements Runnable {
private void putc(char c) {
if (altos != null)
- libaltos.altos_putchar(altos, c);
+ if (libaltos.altos_putchar(altos, c) != 0) {
+ libaltos.altos_close(altos);
+ altos = null;
+ abort_reply();
+ }
}
public void print(String data) {
diff --git a/altosui/Makefile.am b/altosui/Makefile.am
index 1c8ea491..19db6698 100644
--- a/altosui/Makefile.am
+++ b/altosui/Makefile.am
@@ -55,7 +55,6 @@ altosui_JAVA = \
AltosHexfile.java \
Altos.java \
AltosIdleMonitorUI.java \
- AltosIgnite.java \
AltosIgniteUI.java \
AltosLaunch.java \
AltosLaunchUI.java \
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/Makefile.am b/ao-tools/Makefile.am
index 6c315dd1..257fdaec 100644
--- a/ao-tools/Makefile.am
+++ b/ao-tools/Makefile.am
@@ -1 +1 @@
-SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload
+SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload ao-send-telem
diff --git a/ao-tools/ao-send-telem/Makefile.am b/ao-tools/ao-send-telem/Makefile.am
new file mode 100644
index 00000000..bfddf131
--- /dev/null
+++ b/ao-tools/ao-send-telem/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS=ao-send-telem
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_send_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
+
+ao_send_telem_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS)
+
+ao_send_telem_SOURCES = ao-send-telem.c
+
+man_MANS = ao-send-telem.1
diff --git a/ao-tools/ao-send-telem/ao-send-telem.1 b/ao-tools/ao-send-telem/ao-send-telem.1
new file mode 100644
index 00000000..fbdb2fe9
--- /dev/null
+++ b/ao-tools/ao-send-telem/ao-send-telem.1
@@ -0,0 +1,64 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-SEND-TELEM 1 "ao-send-telem" ""
+.SH NAME
+ao-send-telem \- Re-transmit stored telemetry file
+.SH SYNOPSIS
+.B "ao-send-telem"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+[\-F \fIfrequency (kHz)\fP]
+[\--frequency \fIfrequency (kHz)\fP]
+[\-R]
+[\--realtime]
+<flight.telem>
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device ao-dumplog uses to communicate with
+the target device.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleDongle:2
+.br
+TeleDongle
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.TP
+\-F kHz | --frequency kHz
+This selects which frequency to send the specified packets on.
+.TP
+\-R | --realtime
+This makes the program delay between packets in pad mode. Normally,
+pad mode packets are sent as quickly as possible.
+.SH DESCRIPTION
+.I ao-send-telem
+reads the specified flight telemetry log and re-transmits it via the
+specified ground station device
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-send-telem/ao-send-telem.c b/ao-tools/ao-send-telem/ao-send-telem.c
new file mode 100644
index 00000000..c6cc51a1
--- /dev/null
+++ b/ao-tools/ao-send-telem/ao-send-telem.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "cc.h"
+#include "cc-usb.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "frequency", .has_arg = 1, .val = 'F' },
+ { .name = "realtime", .has_arg = 0, .val = 'R' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--frequency <kHz>] [--realtime] file.telem ...\n", program);
+ exit(1);
+}
+
+#define bool(b) ((b) ? "true" : "false")
+
+struct ao_telem_list {
+ struct ao_telem_list *next;
+ union ao_telemetry_all telem;
+};
+
+static struct ao_telem_list *telem_list, **telem_last;
+
+static void
+trim_telem(uint16_t time)
+{
+ while (telem_list && (int16_t) (time - telem_list->telem.generic.tick) > 0) {
+ struct ao_telem_list *next = telem_list->next;
+ free(telem_list);
+ telem_list = next;
+ }
+ if (!telem_list)
+ telem_last = &telem_list;
+}
+
+static void
+add_telem(union ao_telemetry_all *telem)
+{
+ struct ao_telem_list *new = malloc (sizeof (struct ao_telem_list));
+ trim_telem((uint16_t) (telem->generic.tick - 20 * 100));
+ new->telem = *telem;
+ new->next = 0;
+ *telem_last = new;
+ telem_last = &new->next;
+}
+
+static enum ao_flight_state cur_state = ao_flight_invalid;
+static enum ao_flight_state last_state = ao_flight_invalid;
+
+static enum ao_flight_state
+packet_state(union ao_telemetry_all *telem)
+{
+ switch (telem->generic.type) {
+ case AO_TELEMETRY_SENSOR_TELEMETRUM:
+ case AO_TELEMETRY_SENSOR_TELEMINI:
+ case AO_TELEMETRY_SENSOR_TELENANO:
+ cur_state = telem->sensor.state;
+ break;
+ case AO_TELEMETRY_MEGA_DATA:
+ cur_state = telem->mega_data.state;
+ break;
+ }
+ return cur_state;
+}
+
+static const char *state_names[] = {
+ "startup",
+ "idle",
+ "pad",
+ "boost",
+ "fast",
+ "coast",
+ "drogue",
+ "main",
+ "landed",
+ "invalid"
+};
+
+static void
+send_telem(struct cc_usb *cc, union ao_telemetry_all *telem)
+{
+ int rssi = (int8_t) telem->generic.rssi / 2 - 74;
+ int i;
+ uint8_t *b;
+
+ packet_state(telem);
+ if (cur_state != last_state) {
+ if (0 <= cur_state && cur_state < sizeof(state_names) / sizeof (state_names[0]))
+ printf ("%s\n", state_names[cur_state]);
+ last_state = cur_state;
+ }
+ cc_usb_printf(cc, "S 20\n");
+ b = (uint8_t *) telem;
+ for (i = 0; i < 0x20; i++)
+ cc_usb_printf(cc, "%02x", b[i]);
+ cc_usb_sync(cc);
+}
+
+static void
+do_delay(uint16_t now, uint16_t then)
+{
+ int16_t delay = (int16_t) (now - then);
+
+ if (delay > 0 && delay < 1000)
+ usleep(delay * 10 * 1000);
+}
+
+static uint16_t
+send_queued(struct cc_usb *cc, int pause)
+{
+ struct ao_telem_list *next;
+ uint16_t tick = 0;
+ int started = 0;
+
+ while (telem_list) {
+ if (started && pause)
+ do_delay(telem_list->telem.generic.tick, tick);
+ tick = telem_list->telem.generic.tick;
+ started = 1;
+ send_telem(cc, &telem_list->telem);
+
+ next = telem_list->next;
+ free(telem_list);
+ telem_list = next;
+ }
+ return tick;
+}
+
+int
+main (int argc, char **argv)
+{
+ struct cc_usb *cc;
+ char *tty = NULL;
+ char *device = NULL;
+ char line[80];
+ int c, i, ret = 0;
+ int freq = 434550;
+ char *s;
+ FILE *file;
+ int serial;
+ uint16_t last_tick;
+ int started;
+ int realtime = 0;
+
+
+ while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'F':
+ freq = atoi(optarg);
+ break;
+ case 'R':
+ realtime = 1;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleDongle");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+ cc = cc_usb_open(tty);
+ if (!cc)
+ exit (1);
+
+ cc_usb_printf(cc, "m 0\n");
+ cc_usb_printf(cc, "F %d\n", freq);
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (!file) {
+ perror(argv[i]);
+ ret++;
+ continue;
+ }
+ started = 0;
+ last_tick = 0;
+ while (fgets(line, sizeof (line), file)) {
+ union ao_telemetry_all telem;
+
+ if (cc_telemetry_parse(line, &telem)) {
+ /*
+ * Skip packets with CRC errors.
+ */
+ if ((telem.generic.status & (1 << 7)) == 0)
+ continue;
+
+ if (started) {
+ do_delay(telem.generic.tick, last_tick);
+ last_tick = telem.generic.tick;
+ send_telem(cc, &telem);
+ } else {
+ add_telem(&telem);
+ if (packet_state(&telem) > ao_flight_pad) {
+ started = 1;
+ last_tick = send_queued(cc, realtime);
+ }
+ }
+ }
+ }
+ fclose (file);
+
+ }
+ return ret;
+}
diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am
index 77979daf..5aea7db4 100644
--- a/ao-tools/ao-stmload/Makefile.am
+++ b/ao-tools/ao-stmload/Makefile.am
@@ -1,14 +1,15 @@
+if LIBSTLINK
+
bin_PROGRAMS=ao-stmload
LIBSTLINKDIR=/local/src/stlink
-AM_CFLAGS=-I$(LIBSTLINKDIR)/src $(LIBUSB_CFLAGS) -I../lib
-
-AO_STMLOAD_LIBS=$(LIBSTLINKDIR)/libstlink.a
-ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS)
+AM_CFLAGS=$(LIBSTLINK_CFLAGS) $(LIBUSB_CFLAGS) -I../lib
-ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBUSB_LIBS) -lelf
+ao_stmload_LDADD=$(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf
ao_stmload_SOURCES=ao-stmload.c
man_MANS = ao-stmload.1
+
+endif
diff --git a/configure.ac b/configure.ac
index 10bf9abf..a54ef626 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,6 +136,13 @@ AC_CHECK_LIB(readline, readline)
PKG_CHECK_MODULES([LIBUSB], [libusb-1.0])
+AC_CHECK_HEADERS(libelf.h libelf/libelf.h, [break])
+AC_CHECK_HEADERS(gelf.h libelf/gelf.h, [break])
+
+PKG_CHECK_MODULES([LIBSTLINK], [stlink], [HAVE_STLINK=yes], [HAVE_STLINK=no])
+
+AM_CONDITIONAL([LIBSTLINK], [test x$HAVE_STLINK != xno])
+
AC_OUTPUT([
Makefile
altoslib/Makefile
@@ -155,6 +162,7 @@ ao-tools/ao-list/Makefile
ao-tools/ao-load/Makefile
ao-tools/ao-telem/Makefile
ao-tools/ao-stmload/Makefile
+ao-tools/ao-send-telem/Makefile
ao-utils/Makefile
src/Version
])
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 <ao.h>
+#include <ao_aes.h>
+#include "ao_aes_int.h"
+
+static const int xshifts[3][2][4] = {
+ {{0, 1, 2, 3},
+ {0, 3, 2, 1}},
+
+ {{0, 1, 2, 3},
+ {0, 5, 4, 3}},
+
+ {{0, 1, 3, 4},
+ {0, 7, 5, 4}},
+};
+
+/* Exor corresponding text input and round key input bytes */
+/* the result is written to res, which can be the same as a */
+static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC],
+ word32 rk[MAXBC], int BC)
+{
+ int j;
+
+ for (j = 0; j < BC; j++) {
+ res[j] = a[j] ^ rk[j];
+ }
+}
+
+#if 0 /* code included for reference */
+
+/* shift rows a, return result in res. This avoids having to copy a
+ tmp array back to a. res must not be a. */
+static inline void xShiftRow(word32 res[MAXBC], word32 a[MAXBC], int shift[4],
+ int BC)
+{
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+ word8 (*res8)[4] = (word8 (*)[4]) res;
+
+ /* Row 0 remains unchanged
+ * The other three rows are shifted a variable amount
+ */
+ int i, j;
+ int s;
+
+ for (j = 0; j < BC; j++) {
+ res8[j][0] = a8[j][0];
+ }
+ for (i = 1; i < 4; i++) {
+ s = shift[i];
+ for (j = 0; j < BC; j++) {
+ res8[j][i] = a8[(j + s) % BC][i];
+ }
+ }
+}
+
+static inline void xSubstitution(word32 a[MAXBC], word8 box[256], int BC)
+{
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+
+ /* Replace every byte of the input by the byte at that place
+ * in the nonlinear S-box
+ */
+ int i, j;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < BC; j++) {
+ a8[j][i] = box[a[j][i]];
+ }
+ }
+}
+
+#endif /* code included for reference */
+
+/* profiling shows that the ccrypt program spends about 50% of its
+ time in the function xShiftSubst. Splitting the inner "for"
+ statement into two parts - versus using the expensive "%" modulo
+ operation, makes this function about 44% faster, thereby making the
+ entire program about 28% faster. With -O3 optimization, the time
+ savings are even more dramatic - ccrypt runs between 55% and 65%
+ faster on most platforms. */
+
+/* do ShiftRow and Substitution together. res must not be a. */
+static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC],
+ int shift[4], int BC, const word8 box[256])
+{
+ int i, j;
+ int s;
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+ word8 (*res8)[4] = (word8 (*)[4]) res;
+
+ for (j = 0; j < BC; j++) {
+ res8[j][0] = box[a8[j][0]];
+ }
+ for (i = 1; i < 4; i++) {
+ s = shift[i];
+ for (j = 0; j < BC - s; j++) {
+ res8[j][i] = box[a8[(j + s)][i]];
+ }
+ for (j = BC - s; j < BC; j++) {
+ res8[j][i] = box[a8[(j + s) - BC][i]];
+ }
+ }
+}
+
+#if 0 /* code included for reference */
+
+/* Mix the four bytes of every column in a linear way */
+/* the result is written to res, which may equal a */
+static inline void xMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC)
+{
+ int j;
+ word32 b;
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+
+ for (j = 0; j < BC; j++) {
+ b = M0[0][a8[j][0]].w32;
+ b ^= M0[1][a8[j][1]].w32;
+ b ^= M0[2][a8[j][2]].w32;
+ b ^= M0[3][a8[j][3]].w32;
+ res[j] = b;
+ }
+}
+
+#endif /* code included for reference */
+
+/* do MixColumn and KeyAddition together */
+static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC],
+ word32 rk[MAXBC], int BC)
+{
+ int j;
+ word32 b;
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+
+ for (j = 0; j < BC; j++) {
+ b = M0[0][a8[j][0]].w32;
+ b ^= M0[1][a8[j][1]].w32;
+ b ^= M0[2][a8[j][2]].w32;
+ b ^= M0[3][a8[j][3]].w32;
+ b ^= rk[j];
+ res[j] = b;
+ }
+}
+
+/* Mix the four bytes of every column in a linear way
+ * This is the opposite operation of xMixColumn */
+/* the result is written to res, which may equal a */
+static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC)
+{
+ int j;
+ word32 b;
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+
+ for (j = 0; j < BC; j++) {
+ b = M1[0][a8[j][0]].w32;
+ b ^= M1[1][a8[j][1]].w32;
+ b ^= M1[2][a8[j][2]].w32;
+ b ^= M1[3][a8[j][3]].w32;
+ res[j] = b;
+ }
+}
+
+#if 0 /* code included for reference */
+
+/* do KeyAddition and InvMixColumn together */
+static inline void xAddInvMix(word32 res[MAXBC], word32 a[MAXBC],
+ word32 rk[MAXBC], int BC)
+{
+ int j;
+ word32 b;
+ word8 (*a8)[4] = (word8 (*)[4]) a;
+
+ for (j = 0; j < BC; j++) {
+ a[j] = a[j] ^ rk[j];
+ b = M1[0][a8[j][0]].w32;
+ b ^= M1[1][a8[j][1]].w32;
+ b ^= M1[2][a8[j][2]].w32;
+ b ^= M1[3][a8[j][3]].w32;
+ res[j] = b;
+ }
+}
+
+#endif /* code included for reference */
+
+int xrijndaelKeySched(word32 key[], int keyBits, int blockBits,
+ roundkey *rkk)
+{
+ /* Calculate the necessary round keys
+ * The number of calculations depends on keyBits and blockBits */
+ int KC, BC, ROUNDS;
+ int i, j, t, rconpointer = 0;
+ word8 (*k8)[4] = (word8 (*)[4]) key;
+
+ switch (keyBits) {
+ case 128:
+ KC = 4;
+ break;
+ case 192:
+ KC = 6;
+ break;
+ case 256:
+ KC = 8;
+ break;
+ default:
+ return -1;
+ }
+
+ switch (blockBits) {
+ case 128:
+ BC = 4;
+ break;
+ case 192:
+ BC = 6;
+ break;
+ case 256:
+ BC = 8;
+ break;
+ default:
+ return -2;
+ }
+
+ ROUNDS = KC > BC ? KC + 6 : BC + 6;
+
+ t = 0;
+ /* copy values into round key array */
+ for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++)
+ rkk->rk[t] = key[j];
+
+ while (t < (ROUNDS + 1) * BC) { /* while not enough round key material */
+ /* calculate new values */
+ for (i = 0; i < 4; i++) {
+ k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]];
+ }
+ k8[0][0] ^= xrcon[rconpointer++];
+
+ if (KC != 8) {
+ for (j = 1; j < KC; j++) {
+ key[j] ^= key[j - 1];
+ }
+ } else {
+ for (j = 1; j < 4; j++) {
+ key[j] ^= key[j - 1];
+ }
+ for (i = 0; i < 4; i++) {
+ k8[4][i] ^= xS[k8[3][i]];
+ }
+ for (j = 5; j < 8; j++) {
+ key[j] ^= key[j - 1];
+ }
+ }
+ /* copy values into round key array */
+ for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) {
+ rkk->rk[t] = key[j];
+ }
+ }
+
+ /* make roundkey structure */
+ rkk->BC = BC;
+ rkk->KC = KC;
+ rkk->ROUNDS = ROUNDS;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j];
+ }
+ }
+
+ return 0;
+}
+
+/* Encryption of one block. */
+
+void xrijndaelEncrypt(word32 block[], roundkey *rkk)
+{
+ word32 block2[MAXBC]; /* hold intermediate result */
+ int r;
+
+ int *shift = rkk->shift[0];
+ int BC = rkk->BC;
+ int ROUNDS = rkk->ROUNDS;
+ word32 *rp = rkk->rk;
+
+ /* begin with a key addition */
+ xKeyAddition(block, block, rp, BC);
+ rp += BC;
+
+ /* ROUNDS-1 ordinary rounds */
+ for (r = 1; r < ROUNDS; r++) {
+ xShiftSubst(block2, block, shift, BC, xS);
+ xMixAdd(block, block2, rp, BC);
+ rp += BC;
+ }
+
+ /* Last round is special: there is no xMixColumn */
+ xShiftSubst(block2, block, shift, BC, xS);
+ xKeyAddition(block, block2, rp, BC);
+}
+
+void xrijndaelDecrypt(word32 block[], roundkey *rkk)
+{
+ word32 block2[MAXBC]; /* hold intermediate result */
+ int r;
+
+ int *shift = rkk->shift[1];
+ int BC = rkk->BC;
+ int ROUNDS = rkk->ROUNDS;
+ word32 *rp = rkk->rk + ROUNDS * BC;
+
+ /* To decrypt: apply the inverse operations of the encrypt routine,
+ * in opposite order
+ *
+ * (xKeyAddition is an involution: it's equal to its inverse)
+ * (the inverse of xSubstitution with table S is xSubstitution with the
+ * inverse table of S)
+ * (the inverse of xShiftRow is xShiftRow over a suitable distance)
+ */
+
+ /* First the special round:
+ * without xInvMixColumn
+ * with extra xKeyAddition
+ */
+ xKeyAddition(block2, block, rp, BC);
+ xShiftSubst(block, block2, shift, BC, xSi);
+ rp -= BC;
+
+ /* ROUNDS-1 ordinary rounds
+ */
+ for (r = ROUNDS - 1; r > 0; r--) {
+ xKeyAddition(block, block, rp, BC);
+ xInvMixColumn(block2, block, BC);
+ xShiftSubst(block, block2, shift, BC, xSi);
+ rp -= BC;
+ }
+
+ /* End with the extra key addition
+ */
+
+ xKeyAddition(block, block, rp, BC);
+}
+
+uint8_t ao_aes_mutex;
+static roundkey rkk;
+
+static uint8_t iv[16];
+
+void
+ao_aes_set_mode(enum ao_aes_mode mode)
+{
+ /* we only do CBC_MAC anyways... */
+}
+
+void
+ao_aes_set_key(__xdata uint8_t *in)
+{
+ xrijndaelKeySched((word32 *) in, 128, 128, &rkk);
+}
+
+void
+ao_aes_zero_iv(void)
+{
+ memset(iv, '\0', sizeof (iv));
+}
+
+void
+ao_aes_run(__xdata uint8_t *in,
+ __xdata uint8_t *out)
+{
+ uint8_t i;
+
+ for (i = 0; i < 16; i++)
+ iv[i] ^= in[i];
+ xrijndaelEncrypt((word32 *) iv, &rkk);
+ if (out)
+ memcpy(out, iv, 16);
+}
+
+void
+ao_aes_init(void)
+{
+}
diff --git a/src/aes/ao_aes_int.h b/src/aes/ao_aes_int.h
new file mode 100644
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 <stdint.h>
+
+typedef uint8_t word8;
+typedef uint32_t word32;
+
+/* a type to hold 32 bits accessible as 1 integer or 4 bytes */
+union word8x4_u {
+ word8 w8[4];
+ word32 w32;
+};
+typedef union word8x4_u word8x4;
+
+#include "ao_aes_tables.h"
+
+#define MAXBC (256/32)
+#define MAXKC (256/32)
+#define MAXROUNDS 14
+#define MAXRK ((MAXROUNDS+1)*MAXBC)
+
+typedef struct {
+ int BC;
+ int KC;
+ int ROUNDS;
+ int shift[2][4];
+ word32 rk[MAXRK];
+} roundkey;
+
+/* keys and blocks are externally treated as word32 arrays, to
+ make sure they are aligned on 4-byte boundaries on architectures
+ that require it. */
+
+/* make a roundkey rkk from key. key must have appropriate size given
+ by keyBits. keyBits and blockBits may only be 128, 196, or
+ 256. Returns non-zero if arguments are invalid. */
+
+int xrijndaelKeySched(word32 key[], int keyBits, int blockBits,
+ roundkey *rkk);
+
+/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must
+ have been created with xrijndaelKeySched. Size of block, in bits,
+ must be equal to blockBits parameter that was used to make rkk. In
+ all other cases, behavior is undefined - for reasons of speed, no
+ check for error conditions is done. */
+
+void xrijndaelEncrypt(word32 block[], roundkey *rkk);
+void xrijndaelDecrypt(word32 block[], roundkey *rkk);
+
+#endif /* __RIJNDAEL_H */
diff --git a/src/aes/ao_aes_tables.c b/src/aes/ao_aes_tables.c
new file mode 100644
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/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..0e32abf6 100644
--- a/src/cc1111/ao_aes.c
+++ b/src/cc1111/ao_aes.c
@@ -136,7 +136,11 @@ void
ao_aes_init(void)
{
ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done);
+#if DMA_SHARE_AES_RADIO
+ ao_aes_dma_out = ao_radio_dma;
+#else
ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done);
+#endif
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..5e2fc13d 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); \
@@ -88,3 +97,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 <ao.h>
+#include <ao_radio_cmac.h>
__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 <ao_pad.h>
+#endif
/* Values from SmartRF® Studio for:
*
@@ -467,8 +470,44 @@ ao_radio_rdf_abort(void)
/* Output carrier */
+
+static __xdata ao_radio_test_on;
+
void
-ao_radio_test(void)
+ao_radio_test(uint8_t on)
+{
+ if (on) {
+ if (!ao_radio_test_on) {
+#if HAS_MONITOR
+ ao_monitor_disable();
+#endif
+#if PACKET_HAS_SLAVE
+ ao_packet_slave_stop();
+#endif
+#if HAS_PAD
+ ao_pad_disable();
+#endif
+ ao_radio_get(0xff);
+ RFST = RFST_STX;
+ ao_radio_test_on = 1;
+ }
+ } else {
+ if (ao_radio_test_on) {
+ ao_radio_idle();
+ ao_radio_put();
+ ao_radio_test_on = 0;
+#if HAS_MONITOR
+ ao_monitor_enable();
+#endif
+#if HAS_PAD
+ ao_pad_enable();
+#endif
+ }
+ }
+}
+
+static void
+ao_radio_test_cmd(void)
{
uint8_t mode = 2;
static __xdata radio_on;
@@ -478,34 +517,19 @@ ao_radio_test(void)
mode = (uint8_t) ao_cmd_lex_u32;
}
mode++;
- if ((mode & 2) && !radio_on) {
-#if HAS_MONITOR
- ao_monitor_disable();
-#endif
-#if PACKET_HAS_SLAVE
- ao_packet_slave_stop();
-#endif
- ao_radio_get(0xff);
- RFST = RFST_STX;
- radio_on = 1;
- }
+ if ((mode & 2))
+ ao_radio_test(1);
if (mode == 3) {
printf ("Hit a character to stop..."); flush();
getchar();
putchar('\n');
}
- if ((mode & 1) && radio_on) {
- ao_radio_idle();
- ao_radio_put();
- radio_on = 0;
-#if HAS_MONITOR
- ao_monitor_enable();
-#endif
- }
+ if ((mode & 1))
+ ao_radio_test(0);
}
__code struct ao_cmds ao_radio_cmds[] = {
- { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" },
+ { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
{ 0, NULL },
};
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,8 +292,10 @@ 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 */
U1CSR = (UxCSR_MODE_UART | UxCSR_RE);
diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c
index 1bf5e155..2b4fd186 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
@@ -40,35 +143,45 @@ static __xdata uint8_t ao_spi_const;
void
ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant
{
+#if !AO_SPI_SLAVE
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);
-
+#endif
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);
+#if !AO_SPI_SLAVE
ao_dma_start(ao_spi_dma_in_id);
+#endif
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_out_done)
+ ao_sleep(&ao_spi_dma_out_done);
+#else
__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,56 @@ 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);
+#endif
__critical while (!ao_spi_dma_in_done)
ao_sleep(&ao_spi_dma_in_done);
}
-/*
- * Initialize USART0 for SPI using config alt 2
- *
- * MO P1_5
- * MI P1_4
- * CLK P1_3
- *
- * Chip select is the responsibility of the caller
- */
void
ao_spi_init(void)
{
/* Set up the USART pin assignment */
- PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2;
+ 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 +251,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 +261,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/core/ao.h b/src/core/ao.h
index 65b9eb18..b8bedd85 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
*/
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..f19dd9cd 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 <ao_storage.h>
+#if HAS_FLIGHT
#include <ao_sample.h>
#include <ao_data.h>
+#endif
__xdata struct ao_config ao_config;
__pdata uint8_t ao_config_loaded;
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 <ao_ms5607.h>
+#define AO_DATA_MS5607 (1 << 1)
+#else
+#define AO_DATA_MS5607 (1 << 1)
#endif
#if HAS_MPU6000
#include <ao_mpu6000.h>
+#define AO_DATA_MPU6000 (1 << 2)
+#else
+#define AO_DATA_MPU6000 0
#endif
#if HAS_HMC5883
#include <ao_hmc5883.h>
+#define AO_DATA_HMC5883 (1 << 3)
+#else
+#define AO_DATA_HMC5883 0
+#endif
+
+#if HAS_MMA655X
+#include <ao_mma655x.h>
+#define AO_DATA_MMA655X (1 << 4)
+#else
+#define AO_DATA_MMA655X 0
#endif
+#define AO_DATA_ALL (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X)
+
struct ao_data {
uint16_t tick;
#if HAS_ADC
@@ -45,6 +69,9 @@ struct ao_data {
#if HAS_HMC5883
struct ao_hmc5883_sample hmc5883;
#endif
+#if HAS_MMA655X
+ uint16_t mma655x;
+#endif
};
#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1))
@@ -52,6 +79,29 @@ struct ao_data {
extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING];
extern volatile __data uint8_t ao_data_head;
+extern volatile __data uint8_t ao_data_present;
+extern volatile __data uint8_t ao_data_count;
+
+/*
+ * Mark a section of data as ready, check for data complete
+ */
+#define AO_DATA_PRESENT(bit) do { \
+ if ((ao_data_present |= (bit)) == AO_DATA_ALL) { \
+ ao_data_ring[ao_data_head].tick = ao_tick_count; \
+ ao_data_head = ao_data_ring_next(ao_data_head); \
+ ao_data_present = 0; \
+ ao_wakeup((void *) &ao_data_head); \
+ } \
+ } while (0);
+
+/*
+ * Wait for data to be completed by looking at the
+ * indicated bit
+ */
+#define AO_DATA_WAIT() do { \
+ ao_sleep((void *) &ao_data_count); \
+ } while (0)
+
#if HAS_MS5607
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
new file mode 100644
index 00000000..fc0ca8b1
--- /dev/null
+++ b/src/core/ao_radio_cmac.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_cmac.h>
+
+static __xdata uint8_t ao_radio_cmac_mutex;
+__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
+round_len(uint8_t len)
+{
+ uint8_t rem;
+
+ /* Make sure we transfer at least one packet, and
+ * then make sure every packet is full. Note that
+ * there is no length encoded, and that the receiver
+ * must deal with any extra bytes in the packet
+ */
+ if (len < AO_CMAC_KEY_LEN)
+ len = AO_CMAC_KEY_LEN;
+ rem = len % AO_CMAC_KEY_LEN;
+ if (rem != 0)
+ len += (AO_CMAC_KEY_LEN - rem);
+ return len;
+}
+
+/*
+ * Sign and deliver the data sitting in the cmac buffer
+ */
+static void
+radio_cmac_send(uint8_t len) __reentrant
+{
+ uint8_t i;
+
+ len = round_len(len);
+ /* Make sure the AES key is loaded */
+ ao_config_get();
+
+#if HAS_MONITOR
+ ao_monitor_set(0);
+#endif
+
+ ao_mutex_get(&ao_aes_mutex);
+ ao_aes_set_mode(ao_aes_mode_cbc_mac);
+ ao_aes_set_key(ao_config.aes_key);
+ ao_aes_zero_iv();
+ for (i = 0; i < len; i += AO_CMAC_KEY_LEN) {
+ if (i + AO_CMAC_KEY_LEN < len)
+ ao_aes_run(&cmac_data[i], NULL);
+ else
+ ao_aes_run(&cmac_data[i], &cmac_data[len]);
+ }
+ ao_mutex_put(&ao_aes_mutex);
+
+ ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN);
+}
+
+/*
+ * Receive and validate an incoming packet
+ */
+
+static int8_t
+radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant
+{
+ uint8_t i;
+
+ len = round_len(len);
+#if HAS_MONITOR
+ ao_monitor_set(0);
+#endif
+ if (timeout)
+ ao_alarm(timeout);
+
+ i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2);
+ ao_clear_alarm();
+
+ if (!i) {
+ ao_radio_cmac_rssi = 0;
+ return AO_RADIO_CMAC_TIMEOUT;
+ }
+
+ 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();
+
+ /* Compute the packet signature
+ */
+ ao_mutex_get(&ao_aes_mutex);
+ ao_aes_set_mode(ao_aes_mode_cbc_mac);
+ ao_aes_set_key(ao_config.aes_key);
+ ao_aes_zero_iv();
+ for (i = 0; i < len; i += AO_CMAC_KEY_LEN) {
+ if (i + AO_CMAC_KEY_LEN < len)
+ ao_aes_run(&cmac_data[i], NULL);
+ else
+ ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]);
+ }
+ ao_mutex_put(&ao_aes_mutex);
+
+ /* Check the packet signature against the signature provided
+ * over the link
+ */
+
+ if (memcmp(&cmac_data[len],
+ &cmac_data[len + AO_CMAC_KEY_LEN + 2],
+ AO_CMAC_KEY_LEN) != 0) {
+ return AO_RADIO_CMAC_MAC_ERROR;
+ }
+
+ return AO_RADIO_CMAC_OK;
+}
+
+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_mutex_get(&ao_radio_cmac_mutex);
+ 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;
+}
+
+int8_t
+ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
+{
+ uint8_t i;
+ 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)
+ ao_xmemcpy(packet, cmac_data, len);
+ ao_mutex_put(&ao_radio_cmac_mutex);
+ return i;
+}
+
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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_RADIO_CMAC_H_
+#define _AO_RADIO_CMAC_H_
+
+#include <ao_aes.h>
+
+#define AO_CMAC_KEY_LEN AO_AES_LEN
+#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN)
+
+extern __pdata int8_t ao_radio_cmac_rssi;
+
+int8_t
+ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant;
+
+#define AO_RADIO_CMAC_OK 0
+#define AO_RADIO_CMAC_LEN_ERROR -1
+#define AO_RADIO_CMAC_CRC_ERROR -2
+#define AO_RADIO_CMAC_MAC_ERROR -3
+#define AO_RADIO_CMAC_TIMEOUT -4
+
+int8_t
+ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant;
+
+void
+ao_radio_cmac_init(void);
+
+#endif /* _AO_RADIO_CMAC_H_ */
diff --git a/src/core/ao_send_packet.c b/src/core/ao_send_packet.c
new file mode 100644
index 00000000..1a8e74de
--- /dev/null
+++ b/src/core/ao_send_packet.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+#define AO_MAX_SEND 128
+
+static __xdata uint8_t ao_send[AO_MAX_SEND];
+
+static uint8_t
+getnibble(void)
+{
+ char c;
+
+ c = getchar();
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ if ('a' <= c && c <= 'f')
+ return c - ('a' - 10);
+ if ('A' <= c && c <= 'F')
+ return c - ('A' - 10);
+ ao_cmd_status = ao_cmd_lex_error;
+ return 0;
+}
+
+static void
+ao_send_packet(void)
+{
+ __pdata uint16_t count;
+ uint8_t b;
+ __pdata uint8_t i;
+
+ ao_cmd_hex();
+ count = ao_cmd_lex_i;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ if (count > AO_MAX_SEND - 2) {
+ ao_cmd_status = ao_cmd_syntax_error;
+ return;
+ }
+ for (i = 0; i < count; i++) {
+ b = getnibble() << 4;
+ b |= getnibble();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ ao_send[i] = b;
+ }
+ ao_radio_send(ao_send, count);
+}
+
+static __code struct ao_cmds ao_send_packet_cmds[] = {
+ { ao_send_packet, "S <len>\0Send packet. Data on next line" },
+ { 0, NULL }
+};
+
+void
+ao_send_packet_init(void)
+{
+ ao_cmd_register(&ao_send_packet_cmds[0]);
+}
diff --git a/src/core/ao_send_packet.h b/src/core/ao_send_packet.h
new file mode 100644
index 00000000..526f7b55
--- /dev/null
+++ b/src/core/ao_send_packet.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SEND_PACKET_H_
+#define _AO_SEND_PACKET_H_
+
+void
+ao_send_packet_init(void);
+
+#endif /* _AO_SEND_PACKET_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 <ao.h>
+#include <ao_storage.h>
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..4593bd79 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
@@ -177,7 +174,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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/*
+ * 74HC597 driver.
+ * Reads a single byte from the shift register
+ */
+
+#include <ao.h>
+#include <ao_74hc497.h>
+
+uint8_t
+ao_74hc497_read(void)
+{
+ static __xdata state;
+ ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST);
+ ao_spi_recv(&state, 1, AO_74HC497_SPI_BUS);
+ ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS);
+ return state;
+}
+
+static void
+ao_74hc497_cmd(void)
+{
+ uint8_t v;
+
+ v = ao_74hc497_read();
+ printf ("Switches: 0x%02x\n", v);
+}
+
+static const struct ao_cmds ao_74hc497_cmds[] = {
+ { ao_74hc497_cmd, "L\0Show 74hc497" },
+ { 0, NULL }
+};
+
+void
+ao_74hc497_init(void)
+{
+ ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1);
+ ao_cmd_register(&ao_74hc497_cmds[0]);
+}
diff --git a/src/drivers/ao_74hc497.h b/src/drivers/ao_74hc497.h
new file mode 100644
index 00000000..6df7bcae
--- /dev/null
+++ b/src/drivers/ao_74hc497.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_74HC497_H_
+#define _AO_74HC497_H_
+
+uint8_t
+ao_74hc497_read(void);
+
+void
+ao_74hc497_init(void);
+
+#endif /* _AO_74HC497_H_ */
diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c
new file mode 100644
index 00000000..a507c909
--- /dev/null
+++ b/src/drivers/ao_button.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_button.h>
+#include <ao_exti.h>
+#if AO_EVENT
+#include <ao_event.h>
+#define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v)
+#else
+#define ao_button_queue(b,v)
+#endif
+
+static uint8_t ao_button[AO_BUTTON_COUNT];
+static AO_TICK_TYPE ao_button_time[AO_BUTTON_COUNT];
+
+#define AO_DEBOUNCE AO_MS_TO_TICKS(20)
+
+#define port(q) AO_BUTTON_ ## q ## _PORT
+#define bit(q) AO_BUTTON_ ## q
+#define pin(q) AO_BUTTON_ ## q ## _PIN
+
+static void
+ao_button_do(uint8_t b, uint8_t v)
+{
+ /* Debounce */
+ if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE)
+ return;
+
+ /* pins are inverted */
+ v = !v;
+ if (ao_button[b] != v) {
+ ao_button[b] = v;
+ ao_button_time[b] = ao_tick_count;
+ ao_button_queue(b, v);
+ ao_wakeup(&ao_button[b]);
+ }
+}
+
+#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+
+static void
+ao_button_isr(void)
+{
+#if AO_BUTTON_COUNT > 0
+ ao_button_update(0);
+#endif
+#if AO_BUTTON_COUNT > 1
+ ao_button_update(1);
+#endif
+#if AO_BUTTON_COUNT > 2
+ ao_button_update(2);
+#endif
+#if AO_BUTTON_COUNT > 3
+ ao_button_update(3);
+#endif
+#if AO_BUTTON_COUNT > 4
+ ao_button_update(4);
+#endif
+}
+
+#define init(b) do { \
+ ao_enable_port(port(b)); \
+ \
+ ao_exti_setup(port(b), bit(b), \
+ AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
+ ao_button_isr); \
+ ao_exti_enable(port(b), bit(b)); \
+ } while (0)
+
+void
+ao_button_init(void)
+{
+#if AO_BUTTON_COUNT > 0
+ init(0);
+#endif
+#if AO_BUTTON_COUNT > 1
+ init(1);
+#endif
+}
diff --git a/src/drivers/ao_button.h b/src/drivers/ao_button.h
new file mode 100644
index 00000000..ce349d65
--- /dev/null
+++ b/src/drivers/ao_button.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_BUTTON_H_
+#define _AO_BUTTON_H_
+
+void
+ao_button_init(void);
+
+#endif /* _AO_BUTTON_H_ */
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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_event.h>
+
+#define AO_EVENT_QUEUE 64
+
+#define ao_event_queue_next(n) (((n) + 1) & (AO_EVENT_QUEUE - 1))
+#define ao_event_queue_prev(n) (((n) - 1) & (AO_EVENT_QUEUE - 1))
+#define ao_event_queue_empty() (ao_event_queue_insert == ao_event_queue_remove)
+#define ao_event_queue_full() (ao_event_queue_next(ao_event_queue_insert) == ao_event_queue_remove)
+
+/*
+ * Whether a sequence of events from the same device should be collapsed
+ */
+#define ao_event_can_collapse(type) ((type) == AO_EVENT_QUADRATURE)
+
+struct ao_event ao_event_queue[AO_EVENT_QUEUE];
+uint8_t ao_event_queue_insert;
+uint8_t ao_event_queue_remove;
+
+
+uint8_t
+ao_event_get(struct ao_event *ev)
+{
+ ao_arch_critical(
+ while (ao_event_queue_empty())
+ ao_sleep(&ao_event_queue);
+ *ev = ao_event_queue[ao_event_queue_remove];
+ ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+ );
+}
+
+/* called with interrupts disabled */
+void
+ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value)
+{
+ if (!ao_event_queue_full()) {
+
+ if (ao_event_can_collapse(type) && !ao_event_queue_empty()) {
+ uint8_t prev = ao_event_queue_prev(ao_event_queue_insert);
+
+ if (ao_event_queue[prev].type == type &&
+ ao_event_queue[prev].unit == unit)
+ ao_event_queue_insert = prev;
+ }
+ ao_event_queue[ao_event_queue_insert] = (struct ao_event) {
+ .type = type,
+ .unit = unit,
+ .tick = ao_tick_count,
+ .value = value
+ };
+ ao_event_queue_insert = ao_event_queue_next(ao_event_queue_insert);
+ ao_wakeup(&ao_event_queue);
+ }
+}
+
+void
+ao_event_put(uint8_t type, uint8_t unit, uint32_t value)
+{
+ ao_arch_critical(ao_event_put_isr(type, unit, value););
+}
diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h
new file mode 100644
index 00000000..25c49c35
--- /dev/null
+++ b/src/drivers/ao_event.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_EVENT_H_
+#define _AO_EVENT_H_
+
+#define AO_EVENT_NONE 0
+#define AO_EVENT_QUADRATURE 1
+#define AO_EVENT_BUTTON 2
+
+struct ao_event {
+ uint8_t type;
+ uint8_t unit;
+ uint16_t tick;
+ uint32_t value;
+};
+
+uint8_t
+ao_event_get(struct ao_event *ev);
+
+void
+ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value);
+
+void
+ao_event_put(uint8_t type, uint8_t unit, uint32_t value);
+
+#endif /* _AO_EVENT_H_ */
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 <ao_hmc5883.h>
#include <ao_exti.h>
-uint8_t ao_hmc5883_valid;
+#if HAS_HMC5883
static uint8_t ao_hmc5883_configured;
@@ -123,21 +123,16 @@ ao_hmc5883_setup(void)
return 1;
}
-struct ao_hmc5883_sample ao_hmc5883_current;
-
static void
ao_hmc5883(void)
{
ao_hmc5883_setup();
for (;;) {
- struct ao_hmc5883_sample ao_hmc5883_next;
-
- ao_hmc5883_sample(&ao_hmc5883_next);
+ ao_hmc5883_sample((struct ao_hmc5883_sample *) &ao_data_ring[ao_data_head].hmc5883);
ao_arch_critical(
- ao_hmc5883_current = ao_hmc5883_next;
- ao_hmc5883_valid = 1;
+ AO_DATA_PRESENT(AO_DATA_HMC5883);
+ AO_DATA_WAIT();
);
- ao_delay(0);
}
}
@@ -146,11 +141,10 @@ static struct ao_task ao_hmc5883_task;
static void
ao_hmc5883_show(void)
{
- struct ao_hmc5883_sample sample;
-
- sample = ao_hmc5883_current;
+ struct ao_data sample;
+ ao_data_get(&sample);
printf ("X: %d Y: %d Z: %d missed irq: %lu\n",
- sample.x, sample.y, sample.z, ao_hmc5883_missed_irq);
+ sample.hmc5883.x, sample.hmc5883.y, sample.hmc5883.z, ao_hmc5883_missed_irq);
}
static const struct ao_cmds ao_hmc5883_cmds[] = {
@@ -162,7 +156,6 @@ void
ao_hmc5883_init(void)
{
ao_hmc5883_configured = 0;
- ao_hmc5883_valid = 0;
ao_enable_port(AO_HMC5883_INT_PORT);
ao_exti_setup(AO_HMC5883_INT_PORT,
@@ -173,3 +166,5 @@ ao_hmc5883_init(void)
ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883");
ao_cmd_register(&ao_hmc5883_cmds[0]);
}
+
+#endif
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/ao_radio_cmac.c b/src/drivers/ao_lco_cmd.c
index e263f0db..3fe0d9cc 100644
--- a/src/ao_radio_cmac.c
+++ b/src/drivers/ao_lco_cmd.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,227 +15,15 @@
* 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)
-
-static __xdata uint8_t ao_radio_cmac_mutex;
-__pdata int16_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)
-{
- uint8_t rem;
-
- /* Make sure we transfer at least one packet, and
- * then make sure every packet is full. Note that
- * there is no length encoded, and that the receiver
- * must deal with any extra bytes in the packet
- */
- if (len < AO_CMAC_KEY_LEN)
- len = AO_CMAC_KEY_LEN;
- rem = len % AO_CMAC_KEY_LEN;
- if (rem != 0)
- len += (AO_CMAC_KEY_LEN - rem);
- return len;
-}
-
-/*
- * Sign and deliver the data sitting in the cmac buffer
- */
-static void
-radio_cmac_send(uint8_t len) __reentrant
-{
- uint8_t i;
-
- len = round_len(len);
- /* Make sure the AES key is loaded */
- ao_config_get();
-
-#if HAS_MONITOR
- ao_monitor_set(0);
-#endif
-
- ao_mutex_get(&ao_aes_mutex);
- ao_aes_set_mode(ao_aes_mode_cbc_mac);
- ao_aes_set_key(ao_config.aes_key);
- ao_aes_zero_iv();
- for (i = 0; i < len; i += AO_CMAC_KEY_LEN) {
- if (i + AO_CMAC_KEY_LEN < len)
- ao_aes_run(&cmac_data[i], NULL);
- else
- ao_aes_run(&cmac_data[i], &cmac_data[len]);
- }
- ao_mutex_put(&ao_aes_mutex);
-
- ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN);
-}
-
-/*
- * Receive and validate an incoming packet
- */
-
-static int8_t
-radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant
-{
- uint8_t i;
-
- len = round_len(len);
-#if HAS_MONITOR
- ao_monitor_set(0);
-#endif
- if (timeout)
- ao_alarm(timeout);
-
- i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2);
- ao_clear_alarm();
-
- if (!i) {
- ao_radio_cmac_rssi = 0;
- 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))
- return AO_RADIO_CMAC_CRC_ERROR;
-
- ao_config_get();
-
- /* Compute the packet signature
- */
- ao_mutex_get(&ao_aes_mutex);
- ao_aes_set_mode(ao_aes_mode_cbc_mac);
- ao_aes_set_key(ao_config.aes_key);
- ao_aes_zero_iv();
- for (i = 0; i < len; i += AO_CMAC_KEY_LEN) {
- if (i + AO_CMAC_KEY_LEN < len)
- ao_aes_run(&cmac_data[i], NULL);
- else
- ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]);
- }
- ao_mutex_put(&ao_aes_mutex);
-
- /* Check the packet signature against the signature provided
- * over the link
- */
-
- if (memcmp(&cmac_data[len],
- &cmac_data[len + AO_CMAC_KEY_LEN + 2],
- AO_CMAC_KEY_LEN) != 0) {
- return AO_RADIO_CMAC_MAC_ERROR;
- }
-
- return AO_RADIO_CMAC_OK;
-}
-
-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_mutex_get(&ao_radio_cmac_mutex);
- memcpy(cmac_data, packet, len);
- radio_cmac_send(len);
- ao_mutex_put(&ao_radio_cmac_mutex);
- return AO_RADIO_CMAC_OK;
-}
-
-int8_t
-ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
-{
- uint8_t i;
- if (len > AO_CMAC_MAX_LEN)
- return AO_RADIO_CMAC_LEN_ERROR;
- ao_mutex_get(&ao_radio_cmac_mutex);
- i = radio_cmac_recv(len, timeout);
- if (i == AO_RADIO_CMAC_OK)
- memcpy(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);
-}
+#include <ao.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac.h>
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 __pdata uint16_t launch_serial;
+static __pdata uint8_t launch_channel;
+static __pdata uint16_t tick_offset;
static void
launch_args(void) __reentrant
@@ -389,7 +177,79 @@ launch_ignite_cmd(void) __reentrant
launch_ignite();
}
-static __code struct ao_cmds ao_radio_cmac_cmds[] = {
+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 __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN];
+
+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_lco_cmds[] = {
{ radio_cmac_send_cmd, "s <length>\0Send AES-CMAC packet. Bytes to send follow on next line" },
{ radio_cmac_recv_cmd, "S <length> <timeout>\0Receive AES-CMAC packet. Timeout in ms" },
{ launch_report_cmd, "l <serial> <channel>\0Get remote launch status" },
@@ -400,7 +260,7 @@ static __code struct ao_cmds ao_radio_cmac_cmds[] = {
};
void
-ao_radio_cmac_init(void)
+ao_lco_cmd_init(void)
{
- ao_cmd_register(&ao_radio_cmac_cmds[0]);
+ 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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_LCO_CMD_H_
+#define _AO_LCO_CMD_H_
+
+void
+ao_lco_cmd_init(void);
+
+#endif /* _AO_LCO_CMD_H_ */
diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c
new file mode 100644
index 00000000..cd304d80
--- /dev/null
+++ b/src/drivers/ao_mma655x.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_mma655x.h>
+
+#if HAS_MMA655X
+
+static uint8_t mma655x_configured;
+
+static void
+ao_mma655x_start(void) {
+ ao_spi_get_bit(AO_MMA655X_CS_GPIO,
+ AO_MMA655X_CS,
+ AO_MMA655X_CS_PIN,
+ AO_MMA655X_SPI_INDEX,
+ AO_SPI_SPEED_FAST);
+}
+
+static void
+ao_mma655x_stop(void) {
+ ao_spi_put_bit(AO_MMA655X_CS_GPIO,
+ AO_MMA655X_CS,
+ AO_MMA655X_CS_PIN,
+ AO_MMA655X_SPI_INDEX);
+}
+
+static uint8_t
+ao_parity(uint8_t v)
+{
+ /* down to four bits */
+ v = (v ^ (v >> 4)) & 0xf;
+
+ /* Cute lookup hack -- 0x6996 encodes the sixteen
+ * even parity values in order.
+ */
+ return (~0x6996 >> v) & 1;
+}
+
+static void
+ao_mma655x_cmd(uint8_t d[2])
+{
+ ao_mma655x_start();
+ ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX);
+ ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX);
+ ao_mma655x_stop();
+}
+
+static uint8_t
+ao_mma655x_reg_write(uint8_t addr, uint8_t value)
+{
+ uint8_t d[2];
+
+ addr |= (1 << 6); /* write mode */
+ d[0] = addr | (ao_parity(addr^value) << 7);
+ d[1] = value;
+ ao_mma655x_cmd(d);
+ return d[1];
+}
+
+static uint8_t
+ao_mma655x_reg_read(uint8_t addr)
+{
+ uint8_t d[2];
+
+ d[0] = addr | (ao_parity(addr) << 7);
+ d[1] = 0;
+ ao_mma655x_cmd(d);
+ return d[1];
+}
+
+static uint16_t
+ao_mma655x_value(void)
+{
+ uint8_t d[2];
+ uint16_t v;
+
+ d[0] = ((0 << 7) | /* Axis selection (X) */
+ (1 << 6) | /* Acceleration operation */
+ (1 << 5)); /* Raw data */
+ d[1] = ((1 << 3) | /* must be one */
+ (1 << 2) | /* Unsigned data */
+ (0 << 1) | /* Arm disabled */
+ (1 << 0)); /* Odd parity */
+ ao_mma655x_cmd(d);
+ v = (uint16_t) d[1] << 2;
+ v |= d[0] >> 6;
+ v |= (uint16_t) (d[0] & 3) << 10;
+ return v;
+}
+
+static void
+ao_mma655x_reset(void) {
+ ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+ (0 << AO_MMA655X_DEVCTL_RES_1) |
+ (0 << AO_MMA655X_DEVCTL_RES_1));
+ ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+ (1 << AO_MMA655X_DEVCTL_RES_1) |
+ (1 << AO_MMA655X_DEVCTL_RES_1));
+ ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+ (0 << AO_MMA655X_DEVCTL_RES_1) |
+ (1 << AO_MMA655X_DEVCTL_RES_1));
+}
+
+#define DEVCFG_VALUE (\
+ (1 << AO_MMA655X_DEVCFG_OC) | /* Disable offset cancelation */ \
+ (1 << AO_MMA655X_DEVCFG_SD) | /* Receive unsigned data */ \
+ (0 << AO_MMA655X_DEVCFG_OFMON) | /* Disable offset monitor */ \
+ (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG))
+
+#define AXISCFG_VALUE (\
+ (0 << AO_MMA655X_AXISCFG_LPF)) /* 100Hz 4-pole filter */
+
+
+static void
+ao_mma655x_setup(void)
+{
+ uint8_t v;
+ uint16_t a, a_st;
+ uint8_t stdefl;
+
+ if (mma655x_configured)
+ return;
+ mma655x_configured = 1;
+ ao_delay(AO_MS_TO_TICKS(10)); /* Top */
+ ao_mma655x_reset();
+ ao_delay(AO_MS_TO_TICKS(10)); /* Top */
+ (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
+ v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
+
+ /* Configure R/W register values.
+ * Most of them relate to the arming feature, which
+ * we don't use, so the only registers we need to
+ * write are DEVCFG and AXISCFG
+ */
+
+ ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
+ DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT));
+
+ /* Test X axis
+ */
+
+ ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
+ AXISCFG_VALUE |
+ (1 << AO_MMA655X_AXISCFG_ST));
+ a_st = ao_mma655x_value();
+
+ stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL);
+
+ ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
+ AXISCFG_VALUE |
+ (0 << AO_MMA655X_AXISCFG_ST));
+ a = ao_mma655x_value();
+ printf ("normal: %u self_test: %u stdefl: %u\n",
+ a, a_st, stdefl);
+
+ ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
+ DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT));
+}
+
+static void
+ao_mma655x_dump(void)
+{
+ uint8_t s0, s1, s2, s3;
+ uint32_t lot;
+ uint16_t serial;
+
+ ao_mma655x_setup();
+
+ s0 = ao_mma655x_reg_read(AO_MMA655X_SN0);
+ s1 = ao_mma655x_reg_read(AO_MMA655X_SN1);
+ s2 = ao_mma655x_reg_read(AO_MMA655X_SN2);
+ s3 = ao_mma655x_reg_read(AO_MMA655X_SN3);
+ lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) |
+ ((uint32_t) s1 << 8) | ((uint32_t) s0);
+ serial = lot & 0x1fff;
+ lot >>= 12;
+ printf ("MMA655X lot %d serial %d\n", lot, serial);
+ mma655x_configured = 0;
+}
+
+__code struct ao_cmds ao_mma655x_cmds[] = {
+ { ao_mma655x_dump, "A\0Display MMA655X data" },
+ { 0, NULL },
+};
+
+static void
+ao_mma655x(void)
+{
+ ao_mma655x_setup();
+ for (;;) {
+ ao_data_ring[ao_data_head].mma655x = ao_mma655x_value();
+ ao_arch_critical(
+ AO_DATA_PRESENT(AO_DATA_MMA655X);
+ AO_DATA_WAIT();
+ );
+ }
+}
+
+static __xdata struct ao_task ao_mma655x_task;
+
+void
+ao_mma655x_init(void)
+{
+ mma655x_configured = 0;
+
+ ao_cmd_register(&ao_mma655x_cmds[0]);
+ ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS));
+
+ ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x");
+}
+
+#endif
diff --git a/src/drivers/ao_mma655x.h b/src/drivers/ao_mma655x.h
new file mode 100644
index 00000000..9c0c59dc
--- /dev/null
+++ b/src/drivers/ao_mma655x.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_MMA655X_H_
+#define _AO_MMA655X_H_
+
+
+#define AO_MMA655X_SN0 0x00
+#define AO_MMA655X_SN1 0x01
+#define AO_MMA655X_SN2 0x02
+#define AO_MMA655X_SN3 0x03
+#define AO_MMA655X_SN3 0x03
+#define AO_MMA655X_STDEFL 0x04
+#define AO_MMA655X_FCTCFG 0x06
+# define AO_MMA655X_FCTCFG_STMAG 7
+
+#define AO_MMA655X_PN 0x08
+#define AO_MMA655X_DEVCTL 0x0a
+#define AO_MMA655X_DEVCTL_RES_1 7
+#define AO_MMA655X_DEVCTL_RES_0 6
+#define AO_MMA655X_DEVCTL_OCPHASE 4
+#define AO_MMA655X_DEVCTL_OCPHASE_MASK 3
+#define AO_MMA655X_DEVCTL_OFFCFG_EN 3
+
+#define AO_MMA655X_DEVCFG 0x0b
+#define AO_MMA655X_DEVCFG_OC 7
+#define AO_MMA655X_DEVCFG_ENDINIT 5
+#define AO_MMA655X_DEVCFG_SD 4
+#define AO_MMA655X_DEVCFG_OFMON 3
+#define AO_MMA655X_DEVCFG_A_CFG 0
+#define AO_MMA655X_DEVCFG_A_CFG_DISABLE 0
+#define AO_MMA655X_DEVCFG_A_CFG_PCM 1
+#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_HIGH 2
+#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_LOW 3
+#define AO_MMA655X_DEVCFG_A_CFG_COUNT_HIGH 4
+#define AO_MMA655X_DEVCFG_A_CFG_COUNT_LOW 5
+#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_HIGH 6
+#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_LOW 7
+#define AO_MMA655X_DEVCFG_A_CFG_MASK 7
+
+#define AO_MMA655X_AXISCFG 0x0c
+#define AO_MMA655X_AXISCFG_ST 7
+#define AO_MMA655X_AXISCFG_LPF 0
+#define AO_MMA655X_AXISCFG_LPF_MASK 0xf
+
+#define AO_MMA655X_ARMCFG 0x0e
+#define AO_MMA655X_ARMCFG_APS 4
+#define AO_MMA655X_ARMCFG_APS_MASK 3
+#define AO_MMA655X_ARMCFG_AWS_N 2
+#define AO_MMA655X_ARMCFG_AWS_N_MASK 3
+#define AO_MMA655X_ARMCFG_AWS_P 0
+#define AO_MMA655X_ARMCFG_AWS_P_MASK 3
+
+#define AO_MMA655X_ARMT_P 0x10
+#define AO_MMA655X_ARMT_N 0x12
+
+#define AO_MMA655X_DEVSTAT 0x14
+#define AO_MMA655X_DEVSTAT_IDE 6
+#define AO_MMA655X_DEVSTAT_DEVINIT 4
+#define AO_MMA655X_DEVSTAT_MISOERR 3
+#define AO_MMA655X_DEVSTAT_OFFSET 1
+#define AO_MMA655X_DEVSTAT_DEVRES 0
+
+#define AO_MMA655X_COUNT 0x15
+#define AO_MMA655X_OFFCORR 0x16
+
+
+void
+ao_mma655x_init(void);
+
+#endif /* _AO_MMA655X_H_ */
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 <ao_exti.h>
#include "ao_ms5607.h"
+#if HAS_MS5607
+
static struct ao_ms5607_prom ms5607_prom;
static uint8_t ms5607_configured;
@@ -134,11 +136,18 @@ ao_ms5607_get_sample(uint8_t cmd) {
ao_ms5607_start();
ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX);
ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO);
+#if AO_MS5607_PRIVATE_PINS
+ ao_spi_put(AO_MS5607_SPI_INDEX);
+#endif
cli();
while (!ao_ms5607_done)
ao_sleep(&ao_ms5607_done);
sei();
+#if AO_MS5607_PRIVATE_PINS
+ stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1);
+#else
ao_ms5607_stop();
+#endif
ao_ms5607_start();
read = AO_MS5607_ADC_READ;
@@ -194,22 +203,17 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value
value->temp = TEMP;
}
-struct ao_ms5607_sample ao_ms5607_current;
-uint8_t ao_ms5607_valid;
-
static void
ao_ms5607(void)
{
ao_ms5607_setup();
for (;;)
{
- static struct ao_ms5607_sample ao_ms5607_next;
- ao_ms5607_sample(&ao_ms5607_next);
+ ao_ms5607_sample((struct ao_ms5607_sample *) &ao_data_ring[ao_data_head].ms5607_raw);
ao_arch_critical(
- ao_ms5607_current = ao_ms5607_next;
- ao_ms5607_valid = 1;
+ AO_DATA_PRESENT(AO_DATA_MS5607);
+ AO_DATA_WAIT();
);
- ao_delay(0);
}
}
@@ -231,13 +235,13 @@ ao_ms5607_info(void)
static void
ao_ms5607_dump(void)
{
- struct ao_ms5607_sample sample;
+ struct ao_data sample;
struct ao_ms5607_value value;
- sample = ao_ms5607_current;
- ao_ms5607_convert(&sample, &value);
- printf ("Pressure: %8u %8d\n", sample.pres, value.pres);
- printf ("Temperature: %8u %8d\n", sample.temp, value.temp);
+ ao_data_get(&sample);
+ ao_ms5607_convert(&sample.ms5607_raw, &value);
+ printf ("Pressure: %8u %8d\n", sample.ms5607_raw.pres, value.pres);
+ printf ("Temperature: %8u %8d\n", sample.ms5607_raw.temp, value.temp);
printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres));
}
@@ -250,7 +254,6 @@ void
ao_ms5607_init(void)
{
ms5607_configured = 0;
- ao_ms5607_valid = 0;
ao_cmd_register(&ao_ms5607_cmds[0]);
ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS));
@@ -272,3 +275,5 @@ ao_ms5607_init(void)
AO_MS5607_MISO,
STM_MODER_ALTERNATE);
}
+
+#endif
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..b33a5ffd
--- /dev/null
+++ b/src/drivers/ao_pad.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_74hc497.h>
+#include <ao_radio_cmac.h>
+
+static __xdata uint8_t ao_pad_ignite;
+static __xdata struct ao_pad_command command;
+static __xdata struct ao_pad_query query;
+
+#if 0
+#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;
+
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+ ao_pad_box = ao_74hc497_read();
+ ao_led_set(0);
+ ao_led_on(AO_LED_POWER);
+ for (;;) {
+ FLUSHD();
+ while (ao_pad_disabled)
+ ao_sleep(&ao_pad_disabled);
+ if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK)
+ continue;
+
+ PRINTD ("tick %d serial %d cmd %d channel %d\n",
+ command.tick, command.serial, command.cmd, command.channel);
+
+ 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 serial %d channel %d valid %d arm %d igniter %d\n",
+ query.tick, query.serial, query.channel, query.valid, query.arm_status,
+ query.igniter_status);
+ ao_radio_cmac_send(&query, sizeof (query));
+ break;
+ case AO_LAUNCH_FIRE:
+ if (!ao_pad_armed) {
+ PRINTD ("not armed\n");
+ break;
+ }
+ if ((uint16_t) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) {
+ PRINTD ("late pad arm_time %d time %d\n",
+ ao_pad_arm_time, ao_time());
+ break;
+ }
+ time_difference = command.tick - ao_time();
+ if (time_difference < 0)
+ time_difference = -time_difference;
+ if (time_difference > 10) {
+ PRINTD ("time different too large %d\n", time_difference);
+ break;
+ }
+ PRINTD ("ignite\n");
+ ao_pad_ignite = ao_pad_armed;
+ ao_wakeup(&ao_pad_ignite);
+ break;
+ }
+ }
+}
+
+void
+ao_pad_test(void)
+{
+ uint8_t c;
+
+ printf ("Arm switch: ");
+ switch (query.arm_status) {
+ case AO_PAD_ARM_STATUS_ARMED:
+ printf ("Armed\n");
+ break;
+ case AO_PAD_ARM_STATUS_DISARMED:
+ printf ("Disarmed\n");
+ break;
+ case AO_PAD_ARM_STATUS_UNKNOWN:
+ printf ("Unknown\n");
+ break;
+ }
+
+ for (c = 0; c < AO_PAD_NUM; c++) {
+ printf ("Pad %d: ");
+ switch (query.igniter_status[c]) {
+ case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED: printf ("No igniter. Relay closed\n"); break;
+ case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN: printf ("No igniter. Relay open\n"); break;
+ case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN: printf ("Good igniter. Relay open\n"); break;
+ case AO_PAD_IGNITER_STATUS_UNKNOWN: printf ("Unknown\n"); break;
+ }
+ }
+}
+
+void
+ao_pad_manual(void)
+{
+ ao_cmd_white();
+ if (!ao_match_word("DoIt"))
+ return;
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ ao_pad_ignite = 1 << ao_cmd_lex_i;
+ ao_wakeup(&ao_pad_ignite);
+}
+
+static __xdata struct ao_task ao_pad_task;
+static __xdata struct ao_task ao_pad_ignite_task;
+static __xdata struct ao_task ao_pad_monitor_task;
+
+__code struct ao_cmds ao_pad_cmds[] = {
+ { ao_pad_test, "t\0Test pad continuity" },
+ { ao_pad_manual, "i <key> <n>\0Fire igniter. <key> is doit with D&I" },
+ { 0, NULL }
+};
+
+void
+ao_pad_init(void)
+{
+#if AO_PAD_NUM > 0
+ ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0);
+#endif
+#if AO_PAD_NUM > 1
+ ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0);
+#endif
+#if AO_PAD_NUM > 2
+ ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0);
+#endif
+#if AO_PAD_NUM > 3
+ ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0);
+#endif
+ ao_cmd_register(&ao_pad_cmds[0]);
+ ao_add_task(&ao_pad_task, ao_pad, "pad listener");
+ ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter");
+ ao_add_task(&ao_pad_monitor_task, ao_pad_monitor, "pad monitor");
+}
diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h
new file mode 100644
index 00000000..3b0cf1fe
--- /dev/null
+++ b/src/drivers/ao_pad.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PAD_H_
+#define _AO_PAD_H_
+
+#define AO_PAD_MAX_CHANNELS 8
+
+struct ao_pad_command {
+ uint16_t tick;
+ uint16_t box;
+ uint8_t cmd;
+ uint8_t channels;
+};
+
+/* Report current telefire status.
+ */
+
+#define AO_PAD_QUERY 1
+
+struct ao_pad_query {
+ uint16_t tick; /* telefire tick */
+ uint16_t box; /* telefire box number */
+ uint8_t channels; /* which chanels are present */
+ uint8_t armed; /* which channels are armed */
+ uint8_t arm_status; /* status of arming switch */
+ uint8_t igniter_status[AO_PAD_MAX_CHANNELS]; /* status for each igniter */
+};
+
+/* Set current armed pads, report back status
+ */
+
+#define AO_PAD_ARM 2
+
+/* Fire current armed pads for 200ms, no report
+ */
+#define AO_PAD_FIRE 3
+
+#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(1000)
+
+#define AO_PAD_ARM_STATUS_DISARMED 0
+#define AO_PAD_ARM_STATUS_ARMED 1
+#define AO_PAD_ARM_STATUS_UNKNOWN 2
+
+#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN 0
+#define AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN 1
+#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED 2
+#define AO_PAD_IGNITER_STATUS_UNKNOWN 3
+
+void
+ao_pad_init(void);
+
+void
+ao_pad_disable(void);
+
+void
+ao_pad_enable(void);
+
+#endif /* _AO_PAD_H_ */
diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c
new file mode 100644
index 00000000..6d8d18d8
--- /dev/null
+++ b/src/drivers/ao_pca9922.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/*
+ * PCA9922 LED driver. This uses SPI to send a single byte to the device to
+ * set the current state of the LEDs using the existing LED interface
+ */
+
+#include <ao.h>
+
+static __xdata uint8_t ao_led_state;
+
+static void
+ao_led_apply(void)
+{
+ /* Don't try the SPI bus during initialization */
+ if (!ao_cur_task)
+ return;
+ ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST);
+ ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS);
+ ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS);
+}
+
+void
+ao_led_on(uint8_t colors)
+{
+ ao_led_state |= colors;
+ ao_led_apply();
+}
+
+void
+ao_led_off(uint8_t colors)
+{
+ ao_led_state &= ~colors;
+ ao_led_apply();
+}
+
+void
+ao_led_set(uint8_t colors)
+{
+ ao_led_state = colors;
+ ao_led_apply();
+}
+
+void
+ao_led_set_mask(uint8_t colors, uint8_t mask)
+{
+ ao_led_state = (ao_led_state & ~mask) | (colors & mask);
+ ao_led_apply();
+}
+
+void
+ao_led_toggle(uint8_t colors)
+{
+ ao_led_state ^= colors;
+ ao_led_apply();
+}
+
+void
+ao_led_for(uint8_t colors, uint16_t ticks) __reentrant
+{
+ ao_led_on(colors);
+ ao_delay(ticks);
+ ao_led_off(colors);
+}
+
+void
+ao_led_init(uint8_t enable)
+{
+ (void) enable;
+ ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1);
+}
diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c
new file mode 100644
index 00000000..6cc2467a
--- /dev/null
+++ b/src/drivers/ao_quadrature.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_quadrature.h>
+#include <ao_exti.h>
+#if AO_EVENT
+#include <ao_event.h>
+#define ao_quadrature_queue(q) ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q])
+#else
+#define ao_quadrature_queue(q)
+#endif
+
+__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
+
+static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
+
+#define BIT(a,b) ((a) | ((b) << 1))
+#define STATE(old_a, old_b, new_a, new_b) (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b)))
+
+#define port(q) AO_QUADRATURE_ ## q ## _PORT
+#define bita(q) AO_QUADRATURE_ ## q ## _A
+#define bitb(q) AO_QUADRATURE_ ## q ## _B
+
+#define ao_quadrature_update(q) do { \
+ ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \
+ ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \
+ ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \
+ } while (0)
+
+
+static void
+ao_quadrature_isr(void)
+{
+ uint8_t q;
+#if AO_QUADRATURE_COUNT > 0
+ ao_quadrature_update(0);
+#endif
+#if AO_QUADRATURE_COUNT > 1
+ ao_quadrature_update(1);
+#endif
+
+ for (q = 0; q < AO_QUADRATURE_COUNT; q++) {
+ switch (ao_quadrature_state[q]) {
+ case STATE(0, 1, 0, 0):
+ ao_quadrature_count[q]++;
+ break;
+ case STATE(1, 0, 0, 0):
+ ao_quadrature_count[q]--;
+ break;
+ default:
+ continue;
+ }
+ ao_quadrature_queue(q);
+ ao_wakeup(&ao_quadrature_count[q]);
+ }
+}
+
+int32_t
+ao_quadrature_poll(uint8_t q)
+{
+ int32_t ret;
+ ao_arch_critical(ret = ao_quadrature_count[q];);
+ return ret;
+}
+
+int32_t
+ao_quadrature_wait(uint8_t q)
+{
+ ao_sleep(&ao_quadrature_count[q]);
+ return ao_quadrature_poll(q);
+}
+
+static void
+ao_quadrature_test(void)
+{
+ uint8_t q;
+
+ ao_cmd_decimal();
+ q = ao_cmd_lex_i;
+ for (;;) {
+ int32_t c;
+ flush();
+ c = ao_quadrature_wait(q);
+ printf ("new count %6d\n", c);
+ if (c == 100)
+ break;
+ }
+}
+
+static const struct ao_cmds ao_quadrature_cmds[] = {
+ { ao_quadrature_test, "q <unit>\0Test quadrature" },
+ { 0, NULL }
+};
+
+#define init(q) do { \
+ ao_enable_port(port(q)); \
+ \
+ ao_exti_setup(port(q), bita(q), \
+ AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
+ ao_quadrature_isr); \
+ ao_exti_enable(port(q), bita(q)); \
+ \
+ ao_exti_setup(port(q), bitb(q), \
+ AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
+ ao_quadrature_isr); \
+ ao_exti_enable(port(q), bitb(q)); \
+ } while (0)
+
+void
+ao_quadrature_init(void)
+{
+#if AO_QUADRATURE_COUNT > 0
+ init(0);
+#endif
+#if AO_QUADRATURE_COUNT > 1
+ init(1);
+#endif
+ ao_cmd_register(&ao_quadrature_cmds[0]);
+}
diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h
new file mode 100644
index 00000000..d7dda682
--- /dev/null
+++ b/src/drivers/ao_quadrature.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_QUADRATURE_H_
+#define _AO_QUADRATURE_H_
+
+extern __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
+
+int32_t
+ao_quadrature_wait(uint8_t q);
+
+int32_t
+ao_quadrature_poll(uint8_t q);
+
+void
+ao_quadrature_init(void);
+
+#endif /* _AO_QUADRATURE_H_ */
diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c
new file mode 100644
index 00000000..6edea66d
--- /dev/null
+++ b/src/drivers/ao_radio_master.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_spi.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac.h>
+
+static __xdata struct ao_radio_spi_reply ao_radio_spi_reply;
+static __xdata struct ao_radio_spi_request ao_radio_spi_request;
+static __xdata uint8_t ao_radio_done;
+static __xdata uint8_t ao_radio_mutex;
+
+__xdata int8_t ao_radio_cmac_rssi;
+
+static void
+ao_radio_isr(void)
+{
+ ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
+ ao_radio_done = 1;
+ ao_wakeup(&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_1MHz);
+}
+
+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)
+{
+ ao_radio_done = 0;
+ ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
+ ao_radio_master_start();
+ ao_spi_send(&ao_radio_spi_request,
+ ao_radio_spi_request.len,
+ AO_RADIO_SPI_BUS);
+ ao_radio_master_stop();
+ cli();
+ while (!ao_radio_done)
+ if (ao_sleep(&ao_radio_done))
+ break;
+ sei();
+ return ao_radio_done;
+}
+
+static void
+ao_radio_master_recv(uint16_t len)
+{
+ ao_radio_master_start();
+ ao_spi_recv(&ao_radio_spi_reply,
+ len,
+ AO_RADIO_SPI_BUS);
+ ao_radio_master_stop();
+}
+
+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)
+{
+ 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);
+}
+
+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;
+}
+
+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;
+
+ /* Set the key.
+ */
+ 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();
+
+ /* Send the data
+ */
+
+ 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();
+ return AO_RADIO_CMAC_OK;
+}
+
+int8_t
+ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
+{
+ int8_t ret;
+ uint8_t recv;
+
+ if (len > AO_CMAC_MAX_LEN)
+ return AO_RADIO_CMAC_LEN_ERROR;
+
+ /* Set the key.
+ */
+ ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
+ ao_radio_spi_request.timeout = timeout;
+ ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
+ ao_radio_master_send();
+ ao_radio_put();
+
+ /* Recv the data
+ */
+
+ ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0);
+ ao_radio_spi_request.recv_len = len;
+ recv = ao_radio_master_send();
+ if (!recv) {
+ ao_radio_put();
+ ao_radio_recv_abort();
+ return AO_RADIO_CMAC_TIMEOUT;
+ }
+ ao_radio_get_data(packet, len);
+ recv = ao_radio_spi_reply.status;
+ ao_radio_put();
+ 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_FALLING,
+ ao_radio_isr);
+ 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..9dff511b
--- /dev/null
+++ b/src/drivers/ao_radio_slave.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_spi.h>
+#include <ao_radio_cmac.h>
+
+static __xdata struct ao_radio_spi_reply ao_radio_spi_reply;
+
+static __xdata struct ao_radio_spi_request ao_radio_spi_request;
+
+static __xdata uint8_t ao_radio_spi_recv_request;
+static __xdata uint8_t ao_radio_spi_recv_len;
+static __xdata uint16_t ao_radio_spi_recv_timeout;
+
+static void
+ao_radio_slave_signal(void)
+{
+ ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0);
+ ao_arch_nop();
+ ao_arch_nop();
+ ao_arch_nop();
+ ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0);
+}
+
+static void
+ao_radio_slave_spi(void)
+{
+ for (;;) {
+ ao_spi_get_slave(AO_RADIO_SLAVE_BUS);
+ ao_spi_recv(&ao_radio_spi_request, (2 << 13) | sizeof (ao_radio_spi_request), AO_RADIO_SLAVE_BUS);
+ ao_spi_put_slave(AO_RADIO_SLAVE_BUS);
+ ao_led_for(AO_LED_RED, AO_MS_TO_TICKS(1000));
+ switch (ao_radio_spi_request.request) {
+ case AO_RADIO_SPI_RECV:
+ case AO_RADIO_SPI_CMAC_RECV:
+ ao_config.radio_setting = ao_radio_spi_request.setting;
+ ao_radio_spi_recv_request = ao_radio_spi_request.request;
+ ao_radio_spi_recv_len = ao_radio_spi_request.recv_len;
+ ao_radio_spi_recv_timeout = ao_radio_spi_request.timeout;
+ ao_wakeup(&ao_radio_spi_recv_len);
+ break;
+ case AO_RADIO_SPI_RECV_FETCH:
+ ao_spi_get_slave(AO_RADIO_SLAVE_BUS);
+ ao_spi_send(&ao_radio_spi_reply,
+ ao_radio_spi_request.recv_len + AO_RADIO_SPI_REPLY_HEADER_LEN,
+ AO_RADIO_SLAVE_BUS);
+ ao_spi_put_slave(AO_RADIO_SLAVE_BUS);
+ break;
+ case AO_RADIO_SPI_RECV_ABORT:
+ ao_radio_recv_abort();
+ break;
+ 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);
+ ao_radio_slave_signal();
+ 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);
+ ao_radio_slave_signal();
+ break;
+
+ case AO_RADIO_SPI_CMAC_KEY:
+ ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN);
+ ao_radio_slave_signal();
+ break;
+
+ case AO_RADIO_SPI_TEST_ON:
+ ao_radio_test(1);
+ ao_radio_slave_signal();
+ break;
+
+ case AO_RADIO_SPI_TEST_OFF:
+ ao_radio_test(0);
+ ao_radio_slave_signal();
+ break;
+ }
+ }
+}
+
+static void
+ao_radio_slave_recv(void)
+{
+ uint8_t len;
+ for (;;) {
+ while (!ao_radio_spi_recv_len)
+ ao_sleep(&ao_radio_spi_recv_len);
+ len = ao_radio_spi_recv_len;
+ ao_radio_spi_recv_len = 0;
+ if (ao_radio_spi_recv_request == AO_RADIO_SPI_RECV) {
+ ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload, len);
+ ao_radio_spi_reply.rssi = 0;
+ } else {
+ ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload, len,
+ ao_radio_spi_recv_timeout);
+ ao_radio_spi_reply.rssi = ao_radio_cmac_rssi;
+ }
+ ao_radio_slave_signal();
+ }
+}
+
+static __xdata struct ao_task ao_radio_slave_spi_task;
+static __xdata struct ao_task ao_radio_slave_recv_task;
+
+void
+ao_radio_slave_init(void)
+{
+ ao_add_task(&ao_radio_slave_spi_task, ao_radio_slave_spi, "radio_spi");
+ ao_add_task(&ao_radio_slave_recv_task, ao_radio_slave_recv, "radio_recv");
+ ao_enable_output(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1);
+}
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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_RADIO_SPI_H_
+#define _AO_RADIO_SPI_H_
+
+#define AO_RADIO_SPI_RECV 0
+#define AO_RADIO_SPI_RECV_ABORT 1
+#define AO_RADIO_SPI_RECV_FETCH 2
+#define AO_RADIO_SPI_SEND 3
+
+#define AO_RADIO_SPI_CMAC_KEY 4
+#define AO_RADIO_SPI_CMAC_RECV 5
+#define AO_RADIO_SPI_CMAC_SEND 6
+
+#define AO_RADIO_SPI_TEST_ON 7
+#define AO_RADIO_SPI_TEST_OFF 8
+
+#define AO_RADIO_SPI_MAX_PAYLOAD 128
+
+struct ao_radio_spi_request {
+ uint8_t len; /* required to be first by cc1111 DMA engine */
+ uint8_t request;
+ uint8_t recv_len;
+ uint8_t pad;
+ uint32_t setting;
+ uint16_t timeout;
+ uint8_t payload[AO_RADIO_SPI_MAX_PAYLOAD];
+};
+
+#define AO_RADIO_SPI_REQUEST_HEADER_LEN (sizeof (struct ao_radio_spi_request) - AO_RADIO_SPI_MAX_PAYLOAD)
+
+struct ao_radio_spi_reply {
+ uint8_t status;
+ int8_t rssi;
+ uint8_t payload[AO_RADIO_SPI_MAX_PAYLOAD];
+};
+
+#define AO_RADIO_SPI_REPLY_HEADER_LEN (sizeof (struct ao_radio_spi_reply) - AO_RADIO_SPI_MAX_PAYLOAD)
+
+void
+ao_radio_slave_init(void);
+
+#endif /* _AO_RADIO_SPI_H_ */
diff --git a/src/drivers/ao_seven_segment.c b/src/drivers/ao_seven_segment.c
new file mode 100644
index 00000000..1a643eff
--- /dev/null
+++ b/src/drivers/ao_seven_segment.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_seven_segment.h>
+#include <ao_lcd_stm.h>
+
+/*
+ * 0
+ * -------
+ * | |
+ * 1 | | 2
+ * | 3 |
+ * -------
+ * | |
+ * 4 | | 5
+ * | 6 |
+ * -------
+ * [] 7
+ *
+ */
+
+static const uint8_t ao_segments[] = {
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (0 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 0 */
+
+ (0 << AO_SEGMENT_0) |
+ (0 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (0 << AO_SEGMENT_3) |
+ (0 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (0 << AO_SEGMENT_6), /* 1 */
+
+ (1 << AO_SEGMENT_0) |
+ (0 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (0 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 2 */
+
+ (1 << AO_SEGMENT_0) |
+ (0 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (0 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 3 */
+
+ (0 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (0 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (0 << AO_SEGMENT_6), /* 4 */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (0 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (0 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 5 */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (0 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 6 */
+
+ (1 << AO_SEGMENT_0) |
+ (0 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (0 << AO_SEGMENT_3) |
+ (0 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (0 << AO_SEGMENT_6), /* 7 */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 8 */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (0 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* 9 */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (0 << AO_SEGMENT_6), /* A */
+
+ (0 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (0 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* b */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (0 << AO_SEGMENT_2) |
+ (0 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (0 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* c */
+
+ (0 << AO_SEGMENT_0) |
+ (0 << AO_SEGMENT_1) |
+ (1 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (1 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* d */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (0 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (0 << AO_SEGMENT_5) |
+ (1 << AO_SEGMENT_6), /* E */
+
+ (1 << AO_SEGMENT_0) |
+ (1 << AO_SEGMENT_1) |
+ (0 << AO_SEGMENT_2) |
+ (1 << AO_SEGMENT_3) |
+ (1 << AO_SEGMENT_4) |
+ (0 << AO_SEGMENT_5) |
+ (0 << AO_SEGMENT_6), /* F */
+};
+
+void
+ao_seven_segment_set(uint8_t digit, uint8_t value)
+{
+ uint8_t s;
+ uint8_t segments;
+
+ if (value == AO_SEVEN_SEGMENT_CLEAR)
+ segments = 0;
+ else {
+ segments = ao_segments[value & 0xf];
+
+ /* Check for decimal point */
+ if (value & 0x10)
+ segments |= (1 << AO_SEGMENT_7);
+ }
+
+ for (s = 0; s <= 7; s++)
+ ao_lcd_set(digit, s, !!(segments & (1 << s)));
+ ao_lcd_flush();
+}
+
+void
+ao_seven_segment_clear(void)
+{
+ ao_lcd_clear();
+}
+
+
+static void
+ao_seven_segment_show(void)
+{
+ uint8_t digit, value;
+ ao_cmd_decimal();
+ digit = ao_cmd_lex_i;
+ ao_cmd_decimal();
+ value = ao_cmd_lex_i;
+ ao_seven_segment_set(digit, value);
+}
+
+
+static const struct ao_cmds ao_seven_segment_cmds[] = {
+ { ao_seven_segment_show, "S <digit> <value>\0Set LCD digit" },
+ { 0, NULL },
+};
+
+void
+ao_seven_segment_init(void)
+{
+ ao_cmd_register(ao_seven_segment_cmds);
+}
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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SEVEN_SEGMENT_H_
+#define _AO_SEVEN_SEGMENT_H_
+
+#define AO_SEVEN_SEGMENT_DECIMAL 0x10
+
+#define AO_SEVEN_SEGMENT_CLEAR 0xff
+
+void
+ao_seven_segment_set(uint8_t digit, uint8_t value);
+
+void
+ao_seven_segment_clear(void);
+
+void
+ao_seven_segment_init(void);
+
+#endif /* _AO_SEVEN_SEGMENT_H_ */
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 <ao.h>
#include <ao_hmc5883.h>
#include <ao_mpu6000.h>
+#include <ao_mma655x.h>
#include <ao_log.h>
#include <ao_exti.h>
#include <ao_packet.h>
@@ -53,6 +54,9 @@ main(void)
#if HAS_MPU6000
ao_mpu6000_init();
#endif
+#if HAS_MMA655X
+ ao_mma655x_init();
+#endif
ao_storage_init();
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
new file mode 100644
index 00000000..e6094372
--- /dev/null
+++ b/src/megametrum-v0.1/stlink-pins
@@ -0,0 +1,49 @@
+ ST discovery card pins
+
+1 AIN-1
+2 JTCK
+3 GND
+4 JTMS
+5 NRST
+6 SWO
+
+MM misc connector
+
+1 GND
+2 reset_n
+3 boot0
+4 tx1
+5 rx1
+6 +3.3V
+7 GND
+8 jtms
+9 jtck
+10 jtdi
+11 jtdo
+12 jntrst
+13 sda2
+14 scl2
+15 pe1
+16 pe0
+
+For debugging:
+
+ ST MM
+JTCK 2 9
+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
+PC0 (pin15) (blue) PE0 (pin97) accel_ref (debug 16)
+PC1 (pin16) (green) PE1 (pin98) accel (debug 15)
diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle
index 5105b567..3101b777 100644
--- a/src/product/Makefile.teledongle
+++ b/src/product/Makefile.teledongle
@@ -43,6 +43,7 @@ CC1111_SRC = \
ao_packet.c \
ao_packet_master.c \
ao_radio.c \
+ ao_send_packet.c \
ao_romconfig.c \
ao_string.c \
ao_timer.c \
diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c
index 0c829e97..25ebe73e 100644
--- a/src/product/ao_teledongle.c
+++ b/src/product/ao_teledongle.c
@@ -16,6 +16,7 @@
*/
#include "ao.h"
+#include <ao_send_packet.h>
void
main(void)
@@ -32,6 +33,7 @@ main(void)
ao_rssi_init(AO_LED_RED);
ao_radio_init();
ao_packet_master_init();
+ ao_send_packet_init();
#if HAS_DBG
ao_dbg_init();
#endif
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/ao_pins.h b/src/spiradio-v0.1/ao_pins.h
new file mode 100644
index 00000000..363eafa4
--- /dev/null
+++ b/src/spiradio-v0.1/ao_pins.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+
+#define HAS_FLIGHT 0
+#define HAS_USB 0
+#define HAS_BEEP 0
+#define HAS_GPS 0
+#define HAS_SERIAL_0 1
+#define HAS_SERIAL_0_ALT_1 1
+#define HAS_SERIAL_0_HW_FLOW 0
+#define USE_SERIAL_0_STDIN 1
+#define DELAY_SERIAL_0_STDIN 0
+#define HAS_SERIAL_1 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 2
+#define AO_LED_GREEN 1
+#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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_radio_spi.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_serial_init();
+ ao_timer_init();
+ ao_cmd_init();
+ ao_spi_init();
+ ao_radio_init();
+ ao_aes_init();
+ ao_config_init();
+ ao_radio_slave_init();
+ ao_start_scheduler();
+}
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 <ao_exti.h>
+#include <ao_event.h>
+#include <ao_quadrature.h>
+#include <ao_button.h>
struct ao_task demo_task;
@@ -148,12 +152,29 @@ ao_temp (void)
printf ("temp: %d\n", temp);
}
+static void
+ao_event(void)
+{
+ struct ao_event event;
+
+ for (;;) {
+ flush();
+ ao_event_get(&event);
+ printf ("type %1d unit %1d tick %5u value %ld\n",
+ event.type, event.unit, event.tick, event.value);
+ if (event.value == 100)
+ break;
+ }
+
+}
+
__code struct ao_cmds ao_demo_cmds[] = {
{ ao_dma_test, "D\0DMA test" },
{ ao_spi_write, "W\0SPI write" },
{ ao_spi_read, "R\0SPI read" },
{ ao_i2c_write, "i\0I2C write" },
{ ao_temp, "t\0Show temp" },
+ { ao_event, "e\0Monitor event queue" },
{ 0, NULL }
};
@@ -170,6 +191,9 @@ main(void)
// ao_lcd_font_init();
ao_spi_init();
ao_i2c_init();
+ ao_exti_init();
+ ao_quadrature_init();
+ ao_button_init();
ao_timer_set_adc_interval(100);
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 <ao.h>
#include <ao_data.h>
-#if HAS_MPU6000
-#include <ao_mpu6000.h>
-#endif
-#if HAS_MS5607
-#include <ao_ms5607.h>
-#endif
-
-volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING];
-volatile __data uint8_t ao_data_head;
static uint8_t ao_adc_ready;
@@ -50,27 +41,7 @@ static uint8_t ao_adc_ready;
*/
static void ao_adc_done(int index)
{
- uint8_t step = 1;
- ao_data_ring[ao_data_head].tick = ao_time();
-#if HAS_MPU6000
- if (!ao_mpu6000_valid)
- step = 0;
- ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current;
-#endif
-#if HAS_MS5607
- if (!ao_ms5607_valid)
- step = 0;
- ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current;
-#endif
-#if HAS_HMC5883
- if (!ao_hmc5883_valid)
- step = 0;
- ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current;
-#endif
- if (step) {
- ao_data_head = ao_data_ring_next(ao_data_head);
- ao_wakeup((void *) &ao_data_head);
- }
+ AO_DATA_PRESENT(AO_DATA_ADC);
ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
ao_adc_ready = 1;
}
@@ -117,17 +88,6 @@ ao_adc_get(__xdata struct ao_adc *packet)
memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc));
}
-void
-ao_data_get(__xdata struct ao_data *packet)
-{
-#if HAS_FLIGHT
- uint8_t i = ao_data_ring_prev(ao_sample_data);
-#else
- uint8_t i = ao_data_ring_prev(ao_data_head);
-#endif
- memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data));
-}
-
static void
ao_adc_dump(void) __reentrant
{
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_eeprom_stm.c b/src/stm/ao_eeprom_stm.c
new file mode 100644
index 00000000..1e51b417
--- /dev/null
+++ b/src/stm/ao_eeprom_stm.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_storage.h>
+
+/* Total bytes of available storage */
+ao_pos_t ao_storage_total = 4096;
+
+/* Block size - device is erased in these units. */
+ao_pos_t ao_storage_block = 1024;
+
+/* Byte offset of config block. Will be ao_storage_block bytes long */
+ao_pos_t ao_storage_config = 0;
+
+/* Storage unit size - device reads and writes must be within blocks of this size. */
+uint16_t ao_storage_unit = 1024;
+
+/* Location of eeprom in address space */
+#define stm_eeprom ((uint8_t *) 0x08080000)
+
+/*
+ * The internal flash chip is arranged in 8 byte sectors; the
+ * chip cannot erase in units smaller than that.
+ *
+ * Writing happens in units of 2 bytes and
+ * can only change bits from 1 to 0. So, you can rewrite
+ * the same contents, or append to an existing page easily enough
+ */
+
+/*
+ * Erase the specified sector
+ */
+uint8_t
+ao_storage_erase(ao_pos_t pos) __reentrant
+{
+ /* Not necessary */
+ return 1;
+}
+
+static void
+ao_intflash_unlock(void)
+{
+ /* Unlock Data EEPROM and FLASH_PECR register */
+ stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1;
+ stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2;
+
+ /* Configure the FTDW bit (FLASH_PECR[8]) to execute
+ * word write, whatever the previous value of the word
+ * being written to
+ */
+ stm_flash.pecr = ((0 << STM_FLASH_PECR_OBL_LAUNCH) |
+ (0 << STM_FLASH_PECR_ERRIE) |
+ (0 << STM_FLASH_PECR_EOPIE) |
+ (0 << STM_FLASH_PECR_FPRG) |
+ (0 << STM_FLASH_PECR_ERASE) |
+ (0 << STM_FLASH_PECR_FTDW) |
+ (1 << STM_FLASH_PECR_DATA) |
+ (0 << STM_FLASH_PECR_PROG) |
+ (0 << STM_FLASH_PECR_OPTLOCK) |
+ (0 << STM_FLASH_PECR_PRGLOCK) |
+ (0 << STM_FLASH_PECR_PELOCK));
+}
+
+static void
+ao_intflash_lock(void)
+{
+ stm_flash.pecr |= (1 << STM_FLASH_PECR_PELOCK);
+}
+
+static void
+ao_intflash_write32(uint16_t pos, uint32_t w)
+{
+ uint32_t *addr;
+
+ addr = (uint32_t *) (stm_eeprom + pos);
+
+ /* Write a word to a valid address in the data EEPROM */
+ *addr = w;
+
+ /* Wait for the flash unit to go idle */
+ while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+ ;
+}
+
+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
+{
+ 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
@@ -30,6 +30,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)());
void
diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c
index d54e6ee6..11099b02 100644
--- a/src/stm/ao_exti_stm.c
+++ b/src/stm/ao_exti_stm.c
@@ -116,6 +116,20 @@ 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) {
+ 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;
}
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 <ao.h>
+#include <ao_lcd_stm.h>
struct ao_lcd_segment {
uint8_t reg;
@@ -88,7 +89,7 @@ static inline int ao_lcd_stm_com_enabled(int com) {
(1 << 31))
#else
-#define AO_LCD_STM_GPIOC_28_C_SEGS 0
+#define AO_LCD_STM_GPIOC_28_SEGS 0
#define AO_LCD_STM_GPIOD_28_SEGS ( \
(1 << 28) | \
@@ -227,6 +228,21 @@ static const struct ao_lcd_segment coms[] = {
#define NSEG (sizeof segs/sizeof segs[0])
#define NCOM (sizeof coms/sizeof coms[0])
+static uint8_t ao_lcd_update_active;
+
+void
+stm_lcd_isr(void)
+{
+ if (stm_lcd.sr & (1 << STM_LCD_SR_UDD)) {
+ stm_lcd.clr = (1 << STM_LCD_CLR_UDDC);
+ if (ao_lcd_update_active) {
+ ao_lcd_update_active = 0;
+ ao_wakeup(&ao_lcd_update_active);
+ }
+ }
+}
+
+
static void
ao_lcd_stm_fcr_sync(void)
{
@@ -234,6 +250,45 @@ ao_lcd_stm_fcr_sync(void)
asm("nop");
}
+void
+ao_lcd_flush(void)
+{
+ cli();
+ ao_lcd_update_active = 1;
+ stm_lcd.sr = (1 << STM_LCD_SR_UDR);
+ while (ao_lcd_update_active)
+ ao_sleep(&ao_lcd_update_active);
+ sei();
+}
+
+void
+ao_lcd_clear(void)
+{
+ uint8_t i;
+
+ for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++)
+ stm_lcd.ram[i] = 0;
+ ao_lcd_flush();
+}
+
+void
+ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value)
+{
+ uint8_t n;
+
+ if (digit >= NCOM)
+ digit = NCOM-1;
+ if (segment >= NSEG)
+ segment = NSEG-1;
+
+ n = (segment >> 5) & 1;
+ if (value)
+ stm_lcd.ram[digit * 2 + n] |= (1 << (segment & 0x1f));
+ else
+ stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f));
+}
+
+#if 0
static void
ao_lcd_stm_seg_set(void)
{
@@ -246,34 +301,16 @@ ao_lcd_stm_seg_set(void)
ao_cmd_decimal();
val = ao_cmd_lex_i;
printf ("com: %d seg: %d val: %d\n", com, seg, val);
- n = (seg >> 5) & 1;
- if (com >= NCOM)
- com = NCOM-1;
- if (seg >= NSEG)
- seg = NSEG-1;
- if (val)
- stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f));
- else
- stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f));
- stm_lcd.sr = (1 << STM_LCD_SR_UDR);
+ ao_lcd_set(com, seg, val);
+ ao_lcd_flush();
}
-static void
-ao_lcd_stm_clear(void)
-{
- int i;
-
- for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++)
- stm_lcd.ram[i] = 0;
- stm_lcd.sr = (1 << STM_LCD_SR_UDR);
-}
-
-
-const struct ao_cmds ao_lcd_stm_cmds[] = {
+static const struct ao_cmds ao_lcd_stm_cmds[] = {
{ ao_lcd_stm_seg_set, "s <com> <seg> <value>\0Set LCD segment" },
- { ao_lcd_stm_clear, "C\0Clear LCD" },
+ { ao_lcd_clear, "C\0Clear LCD" },
{ 0, NULL },
};
+#endif
void
ao_lcd_stm_init(void)
@@ -332,14 +369,14 @@ ao_lcd_stm_init(void)
stm_lcd.cr = 0;
/* duty cycle 1/3, radio 352, frame rate about 33Hz */
- stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) |
+ stm_lcd.fcr = ((STM_LCD_FCR_PS_8 << STM_LCD_FCR_PS) |
(STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) |
- (4 << STM_LCD_FCR_CC) |
+ (7 << STM_LCD_FCR_CC) |
(0 << STM_LCD_FCR_DEAD) |
- (4 << STM_LCD_FCR_PON) |
- (0 << STM_LCD_FCR_UDDIE) |
+ (1 << STM_LCD_FCR_PON) |
+ (1 << STM_LCD_FCR_UDDIE) |
(0 << STM_LCD_FCR_SOFIE) |
- (0 << STM_LCD_FCR_HD));
+ (1 << STM_LCD_FCR_HD));
ao_lcd_stm_fcr_sync();
@@ -347,10 +384,10 @@ ao_lcd_stm_init(void)
/* Program desired BIAS in LCD_CR */
/* Enable mux seg */
/* Internal voltage source */
- stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) |
+ stm_lcd.cr = ((AO_LCD_DUTY << STM_LCD_CR_DUTY) |
(STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) |
(0 << STM_LCD_CR_VSEL) |
- (1 << STM_LCD_CR_MUX_SEG));
+ (0 << STM_LCD_CR_MUX_SEG));
ao_lcd_stm_fcr_sync();
@@ -362,12 +399,6 @@ ao_lcd_stm_init(void)
/* Load initial data into LCD_RAM and set the
* UDR bit in the LCD_SR register */
- for (r = 0; r < NCOM; r++) {
- stm_lcd.ram[r*2] = 0;
- stm_lcd.ram[r*2 + 1] = 0;
- }
-
- stm_lcd.sr = (1 << STM_LCD_SR_UDR);
/* Program desired frame rate (PS and DIV bits in LCD_FCR) */
@@ -376,7 +407,11 @@ ao_lcd_stm_init(void)
/* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */
/* Program the required interrupts */
+ stm_nvic_set_enable(STM_ISR_LCD_POS);
+ stm_nvic_set_priority(STM_ISR_LCD_POS, AO_STM_NVIC_LOW_PRIORITY);
/* All done */
+#if 0
ao_cmd_register(ao_lcd_stm_cmds);
+#endif
}
diff --git a/src/stm/ao_lcd_stm.h b/src/stm/ao_lcd_stm.h
new file mode 100644
index 00000000..14667546
--- /dev/null
+++ b/src/stm/ao_lcd_stm.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_LCD_STM_H_
+#define _AO_LCD_STM_H_
+
+void
+ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value);
+
+void
+ao_lcd_clear(void);
+
+void
+ao_lcd_flush(void);
+
+#endif /* _AO_LCD_STM_H_ */
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..78228e65 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)
{
@@ -37,9 +37,9 @@ ao_delay(uint16_t 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 +51,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 +67,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..3a498a0a 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;
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..cfa4b3ed
--- /dev/null
+++ b/src/telefire-v0.1/Makefile
@@ -0,0 +1,102 @@
+#
+# 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
+
+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 <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+
+#define HAS_FLIGHT 0
+#define HAS_USB 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..210be08b
--- /dev/null
+++ b/src/telefire-v0.1/ao_telefire.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_74hc497.h>
+
+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_config_init();
+ ao_start_scheduler();
+}