diff options
121 files changed, 5615 insertions, 863 deletions
| @@ -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.pngBinary files differ new file mode 100644 index 00000000..d4393217 --- /dev/null +++ b/altosdroid/res/drawable-hdpi/am_status_c.png diff --git a/altosdroid/res/drawable-hdpi/am_status.png b/altosdroid/res/drawable-hdpi/am_status_g.pngBinary files differ index 03f9dd7d..03f9dd7d 100644 --- a/altosdroid/res/drawable-hdpi/am_status.png +++ b/altosdroid/res/drawable-hdpi/am_status_g.png diff --git a/altosdroid/res/drawable-mdpi/am_status_c.png b/altosdroid/res/drawable-mdpi/am_status_c.pngBinary files differ new file mode 100644 index 00000000..30a8d29a --- /dev/null +++ b/altosdroid/res/drawable-mdpi/am_status_c.png diff --git a/altosdroid/res/drawable-mdpi/am_status.png b/altosdroid/res/drawable-mdpi/am_status_g.pngBinary files differ index 07f7f073..07f7f073 100644 --- a/altosdroid/res/drawable-mdpi/am_status.png +++ b/altosdroid/res/drawable-mdpi/am_status_g.png 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(); +} | 
