diff options
42 files changed, 696 insertions, 443 deletions
| diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml index 3bd5a54e..f005e881 100644 --- a/altosdroid/res/menu/option_menu.xml +++ b/altosdroid/res/menu/option_menu.xml @@ -17,6 +17,9 @@      <item android:id="@+id/connect_scan"            android:icon="@android:drawable/ic_menu_search"            android:title="@string/connect_device" /> +    <item android:id="@+id/disconnect" +	  android:icon="@android:drawable/ic_notification_clear_all" +	  android:title="@string/disconnect_device" />      <item android:id="@+id/quit"            android:icon="@android:drawable/ic_menu_close_clear_cancel"            android:title="@string/quit" /> diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 0cc99349..8a5b29b4 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -27,6 +27,7 @@  	<!-- Options Menu -->  	<string name="connect_device">Connect a device</string> +	<string name="disconnect_device">Disconnect device</string>  	<string name="quit">Quit</string>  	<string name="select_freq">Select radio frequency</string>  	<string name="select_rate">Select data rate</string> diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 3740f55d..973250a5 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -62,6 +62,65 @@ public class AltosBluetooth extends AltosLink {  	} +	private void connected() { +		try { +			synchronized(this) { +				if (socket != null) { +					input = socket.getInputStream(); +					output = socket.getOutputStream(); + +					input_thread = new Thread(this); +					input_thread.start(); + +					// Configure the newly connected device for telemetry +					print("~\nE 0\n"); +					set_monitor(false); +					if (D) Log.d(TAG, "ConnectThread: connected"); + +					/* Let TelemetryService know we're connected +					 */ +					handler.obtainMessage(TelemetryService.MSG_CONNECTED).sendToTarget(); + +					/* Notify other waiting threads that we're connected now +					 */ +					notifyAll(); +				} +			} +		} catch (IOException io) { +			connect_failed(); +		} +	} + +	private void connect_failed() { +		synchronized (this) { +			if (socket != null) { +				try { +					socket.close(); +				} catch (IOException e2) { +					if (D) Log.e(TAG, "ConnectThread: Failed to close() socket after failed connection"); +				} +				socket = null; +			} +			input = null; +			output = null; +			handler.obtainMessage(TelemetryService.MSG_CONNECT_FAILED).sendToTarget(); +			if (D) Log.e(TAG, "ConnectThread: Failed to establish connection"); +		} +	} + +	private Object closing_lock = new Object(); +	private boolean closing = false; + +	private void disconnected() { +		synchronized(closing_lock) { +			if (D) Log.e(TAG, String.format("Connection lost during I/O. Closing  %b", closing)); +			if (!closing) { +				if (D) Log.d(TAG, "Sending disconnected message"); +				handler.obtainMessage(TelemetryService.MSG_DISCONNECTED).sendToTarget(); +			} +		} +	} +  	private class ConnectThread extends Thread {  		private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); @@ -83,54 +142,44 @@ public class AltosBluetooth extends AltosLink {  			// Always cancel discovery because it will slow down a connection  			adapter.cancelDiscovery(); -			synchronized (AltosBluetooth.this) { -				// Make a connection to the BluetoothSocket -				try { -					// This is a blocking call and will only return on a -					// successful connection or an exception -					socket.connect(); +			BluetoothSocket	local_socket; -					input = socket.getInputStream(); -					output = socket.getOutputStream(); -				} catch (IOException e) { -					// Close the socket -					try { -						socket.close(); -					} catch (IOException e2) { -						if (D) Log.e(TAG, "ConnectThread: Failed to close() socket after failed connection"); -					} -					input = null; -					output = null; -					AltosBluetooth.this.notifyAll(); -					handler.obtainMessage(TelemetryService.MSG_CONNECT_FAILED).sendToTarget(); -					if (D) Log.e(TAG, "ConnectThread: Failed to establish connection"); -					return; +			try { +				synchronized (AltosBluetooth.this) { +					local_socket = socket;  				} -				input_thread = new Thread(AltosBluetooth.this); -				input_thread.start(); - -				// Configure the newly connected device for telemetry -				print("~\nE 0\n"); -				set_monitor(false); +				if (local_socket != null) { +					// Make a connection to the BluetoothSocket +					// This is a blocking call and will only return on a +					// successful connection or an exception +					local_socket.connect(); +				} -				// Let TelemetryService know we're connected -				handler.obtainMessage(TelemetryService.MSG_CONNECTED).sendToTarget(); +				connected(); -				// Notify other waiting threads, now that we're connected -				AltosBluetooth.this.notifyAll(); +			} catch (IOException e) { +				connect_failed(); +			} -				// Reset the ConnectThread because we're done +			synchronized (AltosBluetooth.this) { +				/* Reset the ConnectThread because we're done +				 */  				connect_thread = null; - -				if (D) Log.d(TAG, "ConnectThread: Connect completed");  			} +			if (D) Log.d(TAG, "ConnectThread: Connect completed");  		}  		public void cancel() {  			try { -				if (socket != null) -					socket.close(); +				BluetoothSocket	local_socket; +				synchronized(AltosBluetooth.this) { +					local_socket = socket; +					socket = null; +				} +				if (local_socket != null) +					local_socket.close(); +  			} catch (IOException e) {  				if (D) Log.e(TAG, "ConnectThread: close() of connect socket failed", e);  			} @@ -154,17 +203,13 @@ public class AltosBluetooth extends AltosLink {  	}  	private synchronized void wait_connected() throws InterruptedException, IOException { -		if (input == null) { +		if (input == null && socket != null) {  			if (D) Log.d(TAG, "wait_connected...");  			wait();  			if (D) Log.d(TAG, "wait_connected done"); -			if (input == null) throw new IOException();  		} -	} - -	private void connection_lost() { -		if (D) Log.e(TAG, "Connection lost during I/O"); -		handler.obtainMessage(TelemetryService.MSG_DISCONNECTED).sendToTarget(); +		if (socket == null) +			throw new IOException();  	}  	public void print(String data) { @@ -175,9 +220,9 @@ public class AltosBluetooth extends AltosLink {  			output.write(bytes);  			if (D) Log.d(TAG, "print(): Wrote bytes: '" + data.replace('\n', '\\') + "'");  		} catch (IOException e) { -			connection_lost(); +			disconnected();  		} catch (InterruptedException e) { -			connection_lost(); +			disconnected();  		}  	} @@ -189,9 +234,9 @@ public class AltosBluetooth extends AltosLink {  			output.write(bytes);  			if (D) Log.d(TAG, "print(): Wrote byte: '" + c + "'");  		} catch (IOException e) { -			connection_lost(); +			disconnected();  		} catch (InterruptedException e) { -			connection_lost(); +			disconnected();  		}  	} @@ -208,32 +253,44 @@ public class AltosBluetooth extends AltosLink {  				buffer_len = input.read(buffer);  				buffer_off = 0;  			} catch (IOException e) { -				connection_lost(); +				if (D) Log.d(TAG, "getchar IOException"); +				disconnected();  				return AltosLink.ERROR;  			} catch (java.lang.InterruptedException e) { -				connection_lost(); +				if (D) Log.d(TAG, "getchar Interrupted"); +				disconnected();  				return AltosLink.ERROR;  			}  		}  		return buffer[buffer_off++];  	} +	public void closing() { +		synchronized(closing_lock) { +			if (D) Log.d(TAG, "Marked closing true"); +			closing = true; +		} +	} + +  	public void close() {  		if (D) Log.d(TAG, "close(): begin"); + +		closing(); +  		synchronized(this) {  			if (D) Log.d(TAG, "close(): synched"); -			if (connect_thread != null) { -				if (D) Log.d(TAG, "close(): stopping connect_thread"); -				connect_thread.cancel(); -				connect_thread = null; -			} -			if (D) Log.d(TAG, "close(): Closing socket"); -			try { -				socket.close(); -			} catch (IOException e) { -				if (D) Log.e(TAG, "close(): unable to close() socket"); +			if (socket != null) { +				if (D) Log.d(TAG, "close(): Closing socket"); +				try { +					socket.close(); +				} catch (IOException e) { +					if (D) Log.e(TAG, "close(): unable to close() socket"); +				} +				socket = null;  			} +			connect_thread = null;  			if (input_thread != null) {  				if (D) Log.d(TAG, "close(): stopping input_thread");  				try { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 53963f25..41045f03 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -207,9 +207,12 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  			}  			break;  		case TelemetryState.CONNECT_CONNECTING: -			mTitle.setText(R.string.title_connecting); +			if (telemetry_state.address != null) +				mTitle.setText(String.format("Connecting to %s...", telemetry_state.address.name)); +			else +				mTitle.setText("Connecting to something...");  			break; -		case TelemetryState.CONNECT_READY: +		case TelemetryState.CONNECT_DISCONNECTED:  		case TelemetryState.CONNECT_NONE:  			mTitle.setText(R.string.title_not_connected);  			break; @@ -244,8 +247,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  		update_ui(telemetry_state.state, telemetry_state.location);  		if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED)  			start_timer(); -		else -			stop_timer();  	}  	boolean same_string(String a, String b) { @@ -267,8 +268,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  	void update_ui(AltosState state, Location location) { -		Log.d(TAG, "update_ui"); -  		int prev_state = AltosLib.ao_flight_invalid;  		AltosGreatCircle from_receiver = null; @@ -277,7 +276,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  			prev_state = saved_state.state;  		if (state != null) { -			Log.d(TAG, String.format("prev state %d new state  %d\n", prev_state, state.state));  			if (state.state == AltosLib.ao_flight_stateless) {  				boolean	prev_locked = false;  				boolean locked = false; @@ -297,7 +295,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  			} else {  				if (prev_state != state.state) {  					String currentTab = mTabHost.getCurrentTabTag(); -					Log.d(TAG, "switch state");  					switch (state.state) {  					case AltosLib.ao_flight_boost:  						if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent"); @@ -328,22 +325,18 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  			}  			if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) { -				Log.d(TAG, "update callsign");  				mCallsignView.setText(state.callsign);  			}  			if (saved_state == null || state.serial != saved_state.serial) { -				Log.d(TAG, "update serial");  				mSerialView.setText(String.format("%d", state.serial));  			}  			if (saved_state == null || state.flight != saved_state.flight) { -				Log.d(TAG, "update flight");  				if (state.flight == AltosLib.MISSING)  					mFlightView.setText("");  				else  					mFlightView.setText(String.format("%d", state.flight));  			}  			if (saved_state == null || state.state != saved_state.state) { -				Log.d(TAG, "update state");  				if (state.state == AltosLib.ao_flight_stateless) {  					mStateLayout.setVisibility(View.GONE);  				} else { @@ -352,7 +345,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  				}  			}  			if (saved_state == null || state.rssi != saved_state.rssi) { -				Log.d(TAG, "update rssi");  				mRSSIView.setText(String.format("%d", state.rssi));  			}  		} @@ -360,7 +352,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  		for (AltosDroidTab mTab : mTabs)  			mTab.update_ui(state, from_receiver, location, mTab == mTabsAdapter.currentItem()); -		if (state != null) +		if (state != null && mAltosVoice != null)  			mAltosVoice.tell(state, from_receiver);  		saved_state = state; @@ -473,8 +465,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  		mStateLayout   = (RelativeLayout) findViewById(R.id.state_container);  		mStateView     = (TextView) findViewById(R.id.state_value);  		mAgeView       = (TextView) findViewById(R.id.age_value); - -		mAltosVoice = new AltosVoice(this);  	}  	@Override @@ -492,16 +482,18 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  		doBindService(); +		if (mAltosVoice == null) +			mAltosVoice = new AltosVoice(this);  	}  	@Override -	public synchronized void onResume() { +	public void onResume() {  		super.onResume();  		if(D) Log.e(TAG, "+ ON RESUME +");  	}  	@Override -	public synchronized void onPause() { +	public void onPause() {  		super.onPause();  		if(D) Log.e(TAG, "- ON PAUSE -");  	} @@ -512,6 +504,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  		if(D) Log.e(TAG, "-- ON STOP --");  		doUnbindService(); +		if (mAltosVoice != null) { +			mAltosVoice.stop(); +			mAltosVoice = null; +		}  	}  	@Override @@ -548,19 +544,24 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  		}  	} -	private void connectDevice(String address) { +	private void connectDevice(Intent data) {  		// Attempt to connect to the device  		try { -			if (D) Log.d(TAG, "Connecting to " + address); -			mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, address)); +			String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); +			String name = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_NAME); + +			if (D) Log.d(TAG, "Connecting to " + address + name); +			DeviceAddress	a = new DeviceAddress(address, name); +			mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, a));  		} catch (RemoteException e) {  		}  	} -	private void connectDevice(Intent data) { -		// Get the device MAC address -		String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); -		connectDevice(address); +	private void disconnectDevice() { +		try { +			mService.send(Message.obtain(null, TelemetryService.MSG_DISCONNECT, null)); +		} catch (RemoteException e) { +		}  	}  	@Override @@ -620,9 +621,14 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener {  			serverIntent = new Intent(this, DeviceListActivity.class);  			startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);  			return true; +		case R.id.disconnect: +			/* Disconnect the bluetooth device +			 */ +			disconnectDevice(); +			return true;  		case R.id.quit:  			Log.d(TAG, "R.id.quit"); -			stopService(new Intent(AltosDroid.this, TelemetryService.class)); +			disconnectDevice();  			finish();  			return true;  		case R.id.select_freq: diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java index 7ab70147..372500c1 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java @@ -22,9 +22,10 @@ import org.altusmetrum.altoslib_6.*;  public class AltosDroidPreferences extends AltosPreferences {  	/* Active device preference name */ -	final static String activeDevicePreference = "ACTIVE-DEVICE"; +	final static String activeDeviceAddressPreference = "ACTIVE-DEVICE-ADDRESS"; +	final static String activeDeviceNamePreference = "ACTIVE-DEVICE-NAME"; -	static String active_device_address; +	static DeviceAddress	active_device_address;  	public static void init(Context context) {  		if (backend != null) @@ -32,18 +33,23 @@ public class AltosDroidPreferences extends AltosPreferences {  		AltosPreferences.init(new AltosDroidPreferencesBackend(context)); -		active_device_address = backend.getString(activeDevicePreference, null); +		String address = backend.getString(activeDeviceAddressPreference, null); +		String name = backend.getString(activeDeviceNamePreference, null); + +		if (address != null && name != null) +			active_device_address = new DeviceAddress (address, name);  	} -	public static void set_active_device(String address) { +	public static void set_active_device(DeviceAddress address) {  		synchronized(backend) {  			active_device_address = address; -			backend.putString(activeDevicePreference, active_device_address); +			backend.putString(activeDeviceAddressPreference, active_device_address.address); +			backend.putString(activeDeviceNamePreference, active_device_address.name);  			flush_preferences();  		}  	} -	public static String active_device() { +	public static DeviceAddress active_device() {  		synchronized(backend) {  			return active_device_address;  		} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index cbb20045..0896b3a3 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -64,20 +64,16 @@ public abstract class AltosDroidTab extends Fragment implements AltosUnitsListen  			ft.show(this);  		} else  			ft.hide(this); -		ft.commit(); +		ft.commitAllowingStateLoss();  	}  	public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver, boolean is_current) {  		last_state = state;  		last_from_receiver = from_receiver;  		last_receiver = receiver; -		if (is_current) { -			if (AltosDroid.D) Log.d(AltosDroid.TAG, String.format("%s: visible, performing update", tab_name())); - +		if (is_current)  			show(state, from_receiver, receiver); -		} else { -			if (AltosDroid.D) Log.d(AltosDroid.TAG, String.format("%s: not visible, skipping update", tab_name())); +		else  			return; -		}  	}  } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/DeviceAddress.java b/altosdroid/src/org/altusmetrum/AltosDroid/DeviceAddress.java new file mode 100644 index 00000000..673d72dd --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/DeviceAddress.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2015 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. + */ + +package org.altusmetrum.AltosDroid; + +public class DeviceAddress { +	public String	address; +	public String	name; + +	public DeviceAddress(String address, String name) { +		this.address = address; +		this.name = name; +	} +} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java index 71692122..fd6abe0f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java @@ -50,7 +50,8 @@ public class DeviceListActivity extends Activity {  	private static final boolean D = true;  	// Return Intent extra -	public static String EXTRA_DEVICE_ADDRESS = "device_address"; +	public static final String EXTRA_DEVICE_ADDRESS = "device_address"; +	public static final String EXTRA_DEVICE_NAME = "device_name";  	// Member fields  	private BluetoothAdapter mBtAdapter; @@ -164,9 +165,20 @@ public class DeviceListActivity extends Activity {  			String info = ((TextView) v).getText().toString();  			String address = info.substring(info.length() - 17); +			int newline = info.indexOf('\n'); + +			String name = null; +			if (newline > 0) +				name = info.substring(0, newline); +			else +				name = info; + +			if (D) Log.d(TAG, String.format("******* selected item '%s'", info)); +  			// Create the result Intent and include the MAC address  			Intent intent = new Intent();  			intent.putExtra(EXTRA_DEVICE_ADDRESS, address); +			intent.putExtra(EXTRA_DEVICE_NAME, name);  			// Set result and finish this Activity  			setResult(Activity.RESULT_OK, intent); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index d4ac66aa..5f138972 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -63,30 +63,28 @@ public class TelemetryService extends Service implements LocationListener {  	static final int MSG_SETFREQUENCY      = 8;  	static final int MSG_CRC_ERROR	       = 9;  	static final int MSG_SETBAUD	       = 10; +	static final int MSG_DISCONNECT	       = 11;  	// Unique Identification Number for the Notification.  	// We use it on Notification start, and to cancel it.  	private int NOTIFICATION = R.string.telemetry_service_label;  	//private NotificationManager mNM; -	// Timer - we wake up every now and then to decide if the service should stop -	private Timer timer = new Timer(); - -	ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients. -	final Handler   mHandler   = new IncomingHandler(this); -	final Messenger mMessenger = new Messenger(mHandler); // Target we publish for clients to send messages to IncomingHandler. +	ArrayList<Messenger> clients = new ArrayList<Messenger>(); // Keeps track of all current registered clients. +	final Handler   handler   = new IncomingHandler(this); +	final Messenger messenger = new Messenger(handler); // Target we publish for clients to send messages to IncomingHandler.  	// Name of the connected device -	String address; -	private AltosBluetooth  mAltosBluetooth  = null; -	private TelemetryReader mTelemetryReader = null; -	private TelemetryLogger mTelemetryLogger = null; -	// Local Bluetooth adapter -	private BluetoothAdapter mBluetoothAdapter = null; +	DeviceAddress address; +	private AltosBluetooth  altos_bluetooth  = null; +	private TelemetryReader telemetry_reader = null; +	private TelemetryLogger telemetry_logger = null; -	private TelemetryState	telemetry_state; +	// Local Bluetooth adapter +	private BluetoothAdapter bluetooth_adapter = null;  	// Last data seen; send to UI when it starts +	private TelemetryState	telemetry_state;  	// Handler of incoming messages from clients.  	static class IncomingHandler extends Handler { @@ -99,27 +97,51 @@ public class TelemetryService extends Service implements LocationListener {  			if (s == null)  				return;  			switch (msg.what) { + +				/* Messages from application */  			case MSG_REGISTER_CLIENT: -				s.mClients.add(msg.replyTo); -				try { -					// Now we try to send the freshly connected UI any relavant information about what -					// we're talking to -					msg.replyTo.send(s.message()); -				} catch (RemoteException e) { -					s.mClients.remove(msg.replyTo); -				} -				if (D) Log.d(TAG, "Client bound to service"); +				s.add_client(msg.replyTo);  				break;  			case MSG_UNREGISTER_CLIENT: -				s.mClients.remove(msg.replyTo); -				if (D) Log.d(TAG, "Client unbound from service"); +				s.remove_client(msg.replyTo);  				break;  			case MSG_CONNECT:  				if (D) Log.d(TAG, "Connect command received"); -				String address = (String) msg.obj; +				DeviceAddress address = (DeviceAddress) msg.obj;  				AltosDroidPreferences.set_active_device(address); -				s.startAltosBluetooth(address); +				s.start_altos_bluetooth(address); +				break; +			case MSG_DISCONNECT: +				if (D) Log.d(TAG, "Disconnect command received"); +				s.address = null; +				s.stop_altos_bluetooth(true); +				break; +			case MSG_SETFREQUENCY: +				if (D) Log.d(TAG, "MSG_SETFREQUENCY"); +				s.telemetry_state.frequency = (Double) msg.obj; +				if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) { +					try { +						s.altos_bluetooth.set_radio_frequency(s.telemetry_state.frequency); +						s.altos_bluetooth.save_frequency(); +					} catch (InterruptedException e) { +					} catch (TimeoutException e) { +					} +				} +				s.send_to_clients();  				break; +			case MSG_SETBAUD: +				if (D) Log.d(TAG, "MSG_SETBAUD"); +				s.telemetry_state.telemetry_rate = (Integer) msg.obj; +				if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) { +					s.altos_bluetooth.set_telemetry_rate(s.telemetry_state.telemetry_rate); +					s.altos_bluetooth.save_telemetry_rate(); +				} +				s.send_to_clients(); +				break; + +				/* +				 *Messages from AltosBluetooth +				 */  			case MSG_CONNECTED:  				if (D) Log.d(TAG, "Connected to device");  				try { @@ -128,51 +150,40 @@ public class TelemetryService extends Service implements LocationListener {  				}  				break;  			case MSG_CONNECT_FAILED: -				if (D) Log.d(TAG, "Connection failed... retrying"); -				if (s.address != null) -					s.startAltosBluetooth(s.address); +				if (s.address != null) { +					if (D) Log.d(TAG, "Connection failed... retrying"); +					s.start_altos_bluetooth(s.address); +				} else { +					s.stop_altos_bluetooth(true); +				}  				break;  			case MSG_DISCONNECTED:  				Log.d(TAG, "MSG_DISCONNECTED"); -				s.stopAltosBluetooth(); +				if (s.address != null) { +					if (D) Log.d(TAG, "Connection lost... retrying"); +					s.start_altos_bluetooth(s.address); +				} else { +					s.stop_altos_bluetooth(true); +				}  				break; + +				/* +				 * Messages from TelemetryReader +				 */  			case MSG_TELEMETRY: -				// forward telemetry messages  				s.telemetry_state.state = (AltosState) msg.obj;  				if (s.telemetry_state.state != null) {  					if (D) Log.d(TAG, "Save state");  					AltosPreferences.set_state(0, s.telemetry_state.state, null);  				}  				if (D) Log.d(TAG, "MSG_TELEMETRY"); -				s.sendMessageToClients(); +				s.send_to_clients();  				break;  			case MSG_CRC_ERROR:  				// forward crc error messages  				s.telemetry_state.crc_errors = (Integer) msg.obj;  				if (D) Log.d(TAG, "MSG_CRC_ERROR"); -				s.sendMessageToClients(); -				break; -			case MSG_SETFREQUENCY: -				if (D) Log.d(TAG, "MSG_SETFREQUENCY"); -				s.telemetry_state.frequency = (Double) msg.obj; -				if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) { -					try { -						s.mAltosBluetooth.set_radio_frequency(s.telemetry_state.frequency); -						s.mAltosBluetooth.save_frequency(); -					} catch (InterruptedException e) { -					} catch (TimeoutException e) { -					} -				} -				s.sendMessageToClients(); -				break; -			case MSG_SETBAUD: -				if (D) Log.d(TAG, "MSG_SETBAUD"); -				s.telemetry_state.telemetry_rate = (Integer) msg.obj; -				if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) { -					s.mAltosBluetooth.set_telemetry_rate(s.telemetry_state.telemetry_rate); -					s.mAltosBluetooth.save_telemetry_rate(); -				} -				s.sendMessageToClients(); +				s.send_to_clients();  				break;  			default:  				super.handleMessage(msg); @@ -180,6 +191,8 @@ public class TelemetryService extends Service implements LocationListener {  		}  	} +	/* Construct the message to deliver to clients +	 */  	private Message message() {  		if (telemetry_state == null)  			Log.d(TAG, "telemetry_state null!"); @@ -188,117 +201,149 @@ public class TelemetryService extends Service implements LocationListener {  		return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);  	} -	private void sendMessageToClients() { -		Message m = message(); -		if (D) Log.d(TAG, String.format("Send message to %d clients", mClients.size())); -		for (int i=mClients.size()-1; i>=0; i--) { -			try { -				if (D) Log.d(TAG, String.format("Send message to client %d", i)); -				mClients.get(i).send(m); -			} catch (RemoteException e) { -				mClients.remove(i); -			} +	/* A new friend has connected +	 */ +	private void add_client(Messenger client) { + +		clients.add(client); +		if (D) Log.d(TAG, "Client bound to service"); + +		/* On connect, send the current state to the new client +		 */ +		send_to_client(client, message()); + +		/* If we've got an address from a previous session, then +		 * go ahead and try to reconnect to the device +		 */ +		if (address != null && telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED) { +			if (D) Log.d(TAG, "Reconnecting now..."); +			start_altos_bluetooth(address); +		} +	} + +	/* A client has disconnected, clean up +	 */ +	private void remove_client(Messenger client) { +		clients.remove(client); +		if (D) Log.d(TAG, "Client unbound from service"); + +		/* When the list of clients is empty, stop the service if +		 * we have no current telemetry source +		 */ + +		 if (clients.isEmpty() && telemetry_state.connect == TelemetryState.CONNECT_DISCONNECTED) { +			 if (!D) Log.d(TAG, "No clients, no connection. Stopping\n"); +			 stopSelf(); +		 } +	} + +	private void send_to_client(Messenger client, Message m) { +		try { +			if (D) Log.d(TAG, String.format("Send message to client %s", client.toString())); +			client.send(m); +		} catch (RemoteException e) { +			if (D) Log.e(TAG, String.format("Client %s disappeared", client.toString())); +			remove_client(client);  		}  	} -	private void stopAltosBluetooth() { -		if (D) Log.d(TAG, "stopAltosBluetooth(): begin"); -		telemetry_state.connect = TelemetryState.CONNECT_READY; -		if (mTelemetryReader != null) { -			if (D) Log.d(TAG, "stopAltosBluetooth(): stopping TelemetryReader"); -			mTelemetryReader.interrupt(); +	private void send_to_clients() { +		Message m = message(); +		if (D) Log.d(TAG, String.format("Send message to %d clients", clients.size())); +		for (Messenger client : clients) +			send_to_client(client, m); +	} + +	private void stop_altos_bluetooth(boolean notify) { +		if (D) Log.d(TAG, "stop_altos_bluetooth(): begin"); +		telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED; +		telemetry_state.address = null; + +		if (altos_bluetooth != null) +			altos_bluetooth.closing(); + +		if (telemetry_reader != null) { +			if (D) Log.d(TAG, "stop_altos_bluetooth(): stopping TelemetryReader"); +			telemetry_reader.interrupt();  			try { -				mTelemetryReader.join(); +				telemetry_reader.join();  			} catch (InterruptedException e) {  			} -			mTelemetryReader = null; +			telemetry_reader = null;  		} -		if (mTelemetryLogger != null) { -			if (D) Log.d(TAG, "stopAltosBluetooth(): stopping TelemetryLogger"); -			mTelemetryLogger.stop(); -			mTelemetryLogger = null; +		if (telemetry_logger != null) { +			if (D) Log.d(TAG, "stop_altos_bluetooth(): stopping TelemetryLogger"); +			telemetry_logger.stop(); +			telemetry_logger = null;  		} -		if (mAltosBluetooth != null) { -			if (D) Log.d(TAG, "stopAltosBluetooth(): stopping AltosBluetooth"); -			mAltosBluetooth.close(); -			mAltosBluetooth = null; +		if (altos_bluetooth != null) { +			if (D) Log.d(TAG, "stop_altos_bluetooth(): stopping AltosBluetooth"); +			altos_bluetooth.close(); +			altos_bluetooth = null;  		}  		telemetry_state.config = null; -		if (D) Log.d(TAG, "stopAltosBluetooth(): send message to clients"); -		sendMessageToClients(); +		if (notify) { +			if (D) Log.d(TAG, "stop_altos_bluetooth(): send message to clients"); +			send_to_clients(); +			if (clients.isEmpty()) { +				if (D) Log.d(TAG, "stop_altos_bluetooth(): no clients, terminating"); +				stopSelf(); +			} +		}  	} -	private void startAltosBluetooth(String address) { +	private void start_altos_bluetooth(DeviceAddress address) {  		// Get the BLuetoothDevice object -		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); +		BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address); +		stop_altos_bluetooth(false);  		this.address = address; -		if (mAltosBluetooth == null) { -			if (D) Log.d(TAG, String.format("startAltosBluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress())); -			mAltosBluetooth = new AltosBluetooth(device, mHandler); -			telemetry_state.connect = TelemetryState.CONNECT_CONNECTING; -			sendMessageToClients(); -		} else { -			// This is a bit of a hack - if it appears we're still connected, we treat this as a restart. -			// So, to give a suitable delay to teardown/bringup, we just schedule a resend of a message -			// to ourselves in a few seconds time that will ultimately call this method again. -			// ... then we tear down the existing connection. -			// We do it this way around so that we don't lose a reference to the device when this method -			// is called on reception of MSG_CONNECT_FAILED in the handler above. -			mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, address), 3000); -			stopAltosBluetooth(); -		} +		if (D) Log.d(TAG, String.format("start_altos_bluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress())); +		altos_bluetooth = new AltosBluetooth(device, handler); +		telemetry_state.connect = TelemetryState.CONNECT_CONNECTING; +		telemetry_state.address = address; +		send_to_clients();  	}  	private void connected() throws InterruptedException {  		if (D) Log.d(TAG, "connected top");  		try { -			if (mAltosBluetooth == null) +			if (altos_bluetooth == null)  				throw new InterruptedException("no bluetooth"); -			telemetry_state.config = mAltosBluetooth.config_data(); -			mAltosBluetooth.set_radio_frequency(telemetry_state.frequency); -			mAltosBluetooth.set_telemetry_rate(telemetry_state.telemetry_rate); +			telemetry_state.config = altos_bluetooth.config_data(); +			altos_bluetooth.set_radio_frequency(telemetry_state.frequency); +			altos_bluetooth.set_telemetry_rate(telemetry_state.telemetry_rate);  		} catch (TimeoutException e) {  			// If this timed out, then we really want to retry it, but  			// probably safer to just retry the connection from scratch. -			mHandler.obtainMessage(MSG_CONNECT_FAILED).sendToTarget(); +			handler.obtainMessage(MSG_CONNECT_FAILED).sendToTarget();  			return;  		}  		if (D) Log.d(TAG, "connected bluetooth configured");  		telemetry_state.connect = TelemetryState.CONNECT_CONNECTED; +		telemetry_state.address = address; -		mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler, telemetry_state.state); -		mTelemetryReader.start(); +		telemetry_reader = new TelemetryReader(altos_bluetooth, handler, telemetry_state.state); +		telemetry_reader.start();  		if (D) Log.d(TAG, "connected TelemetryReader started"); -		mTelemetryLogger = new TelemetryLogger(this, mAltosBluetooth); +		telemetry_logger = new TelemetryLogger(this, altos_bluetooth);  		if (D) Log.d(TAG, "Notify UI of connection"); -		sendMessageToClients(); -	} - -	private void onTimerTick() { -		if (D) Log.d(TAG, "Timer wakeup"); -		try { -			if (mClients.size() <= 0 && telemetry_state.connect != TelemetryState.CONNECT_CONNECTED) { -				stopSelf(); -			} -		} catch (Throwable t) { -			Log.e(TAG, "Timer failed: ", t); -		} +		send_to_clients();  	}  	@Override  	public void onCreate() {  		// Get local Bluetooth adapter -		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); +		bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();  		// If the adapter is null, then Bluetooth is not supported -		if (mBluetoothAdapter == null) { +		if (bluetooth_adapter == null) {  			Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();  		} @@ -310,7 +355,8 @@ public class TelemetryService extends Service implements LocationListener {  		// Create a reference to the NotificationManager so that we can update our notifcation text later  		//mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); -		telemetry_state.connect = TelemetryState.CONNECT_READY; +		telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED; +		telemetry_state.address = null;  		AltosSavedState saved_state = AltosPreferences.state(0); @@ -319,17 +365,14 @@ public class TelemetryService extends Service implements LocationListener {  			telemetry_state.state = saved_state.state;  		} -		// Start our timer - first event in 10 seconds, then every 10 seconds after that. -		timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L); -  		// Listen for GPS and Network position updates  		LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);  		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this); -		String address = AltosDroidPreferences.active_device(); +		DeviceAddress address = AltosDroidPreferences.active_device();  		if (address != null) -			startAltosBluetooth(address); +			start_altos_bluetooth(address);  	}  	@Override @@ -366,28 +409,25 @@ public class TelemetryService extends Service implements LocationListener {  		((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);  		// Stop the bluetooth Comms threads -		stopAltosBluetooth(); +		stop_altos_bluetooth(true);  		// Demote us from the foreground, and cancel the persistent notification.  		stopForeground(true); -		// Stop our timer -		if (timer != null) {timer.cancel();} -  		// Tell the user we stopped.  		Toast.makeText(this, R.string.telemetry_service_stopped, Toast.LENGTH_SHORT).show();  	}  	@Override  	public IBinder onBind(Intent intent) { -		return mMessenger.getBinder(); +		return messenger.getBinder();  	}  	public void onLocationChanged(Location location) {  		telemetry_state.location = location;  		if (D) Log.d(TAG, "location changed"); -		sendMessageToClients(); +		send_to_clients();  	}  	public void onStatusChanged(String provider, int status, Bundle extras) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java index 862847d2..ca066fc2 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java @@ -21,12 +21,13 @@ import org.altusmetrum.altoslib_6.*;  import android.location.Location;  public class TelemetryState { -	public static final int CONNECT_NONE       = 0; -	public static final int CONNECT_READY      = 1; -	public static final int CONNECT_CONNECTING = 2; -	public static final int CONNECT_CONNECTED  = 3; +	public static final int CONNECT_NONE         = 0; +	public static final int CONNECT_DISCONNECTED = 1; +	public static final int CONNECT_CONNECTING   = 2; +	public static final int CONNECT_CONNECTED    = 3;  	int		connect; +	DeviceAddress	address;  	AltosConfigData	config;  	AltosState	state;  	Location	location; diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 944c659b..1a2dc4f1 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -50,8 +50,6 @@ public class AltosIgniteUI  	LinkedBlockingQueue<String>	command_queue; -	LinkedBlockingQueue<String>	reply_queue; -  	class Igniter {  		JRadioButton	button;  		JLabel		status_label; @@ -150,8 +148,7 @@ public class AltosIgniteUI  						}  						reply = "status";  					} else if (command.equals("get_npyro")) { -						put_reply(String.format("%d", ignite.npyro())); -						continue; +						reply = String.format("npyro %d", ignite.npyro());  					} else if (command.equals("quit")) {  						ignite.close();  						break; @@ -211,6 +208,9 @@ public class AltosIgniteUI  			set_ignite_status();  		} else if (reply.equals("fired")) {  			fired(); +		} else if (reply.startsWith("npyro")) { +			npyro = Integer.parseInt(reply.substring(6)); +			make_ui();  		}  	} @@ -250,24 +250,6 @@ public class AltosIgniteUI  		}  	} -	void put_reply(String reply) { -		try { -			reply_queue.put(reply); -		} catch (Exception ex) { -			ignite_exception(ex); -		} -	} - -	String get_reply() { -		String reply = ""; -		try { -			reply = reply_queue.take(); -		} catch (Exception ex) { -			ignite_exception(ex); -		} -		return reply; -	} -  	boolean	getting_status = false;  	boolean	visible = false; @@ -287,12 +269,6 @@ public class AltosIgniteUI  		}  	} -	int get_npyro() { -		send_command("get_npyro"); -		String reply = get_reply(); -		return Integer.parseInt(reply); -	} -  	boolean	firing = false;  	void start_fire(String which) { @@ -310,8 +286,9 @@ public class AltosIgniteUI  	void close() {  		if (opened) {  			send_command("quit"); -			timer.stop();  		} +		if (timer != null) +			timer.stop();  		setVisible(false);  		dispose();  	} @@ -383,7 +360,6 @@ public class AltosIgniteUI  	private boolean open() {  		command_queue = new LinkedBlockingQueue<String>(); -		reply_queue = new LinkedBlockingQueue<String>();  		opened = false;  		device = AltosDeviceUIDialog.show(owner, Altos.product_any); @@ -403,13 +379,7 @@ public class AltosIgniteUI  		return false;  	} -	public AltosIgniteUI(JFrame in_owner) { - -		owner = in_owner; - -		if (!open()) -			return; - +	private void make_ui() {  		group = new ButtonGroup();  		Container		pane = getContentPane(); @@ -422,8 +392,6 @@ public class AltosIgniteUI  		timer_running = false;  		timer.restart(); -		owner = in_owner; -  		pane.setLayout(new GridBagLayout());  		c.fill = GridBagConstraints.NONE; @@ -443,8 +411,6 @@ public class AltosIgniteUI  		y++; -		int npyro = get_npyro(); -  		igniters = new Igniter[2 + npyro];  		igniters[0] = new Igniter(this, "Apogee", AltosIgnite.Apogee, y++); @@ -492,4 +458,14 @@ public class AltosIgniteUI  		addWindowListener(new ConfigListener(this));  	} -}
\ No newline at end of file + +	public AltosIgniteUI(JFrame in_owner) { + +		owner = in_owner; + +		if (!open()) +			return; + +		send_command("get_npyro"); +	} +} diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index 6e497c42..ace8fbe5 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -54,7 +54,7 @@ public class AltosFlashUI  	// Flash controller  	AltosProgrammer	programmer; -	private static String[] pair_programmed = { +	private static final String[] pair_programmed_files = {  		"teleballoon",  		"telebt-v1",  		"teledongle-v0", @@ -67,20 +67,34 @@ public class AltosFlashUI  		"teleterra"  	}; +	private static final String[] pair_programmed_devices = { +		"TeleBalloon", +		"TeleBT-v1", +		"TeleDongle-v0", +		"TeleFire", +		"TeleMetrum-v0", +		"TeleMetrum-v1", +		"TeleMini", +		"TeleNano", +		"TeleShield", +		"TeleTerra" +	}; +  	private boolean is_pair_programmed() {  		if (file != null) {  			String	name = file.getName(); -			for (int i = 0; i < pair_programmed.length; i++) { -				if (name.startsWith(pair_programmed[i])) +			for (int i = 0; i < pair_programmed_files.length; i++) { +				if (name.startsWith(pair_programmed_files[i]))  					return true;  			}  		}  		if (device != null) { -			if (!device.matchProduct(AltosLib.product_altusmetrum) && -			    (device.matchProduct(AltosLib.product_teledongle) || -			     device.matchProduct(AltosLib.product_telebt))) -				return true; +			String	name = device.toString(); +			for (int i = 0; i < pair_programmed_devices.length; i++) { +				if (name.startsWith(pair_programmed_devices[i])) +					return true; +			}  		}  		return false;  	} diff --git a/ao-bringup/turnon_telebt b/ao-bringup/turnon_telebt index c4902f31..f4100ae2 100755 --- a/ao-bringup/turnon_telebt +++ b/ao-bringup/turnon_telebt @@ -1,8 +1,5 @@  #!/bin/sh -# serial number of the TeleDongle being used as the flash programmer -DONGLE=612 -  if [ -x ../ao-tools/ao-load/ao-load ]; then  	AOLOAD=../ao-tools/ao-load/ao-load  elif [ -x /usr/bin/ao-load ]; then @@ -34,6 +31,19 @@ read SERIAL  echo $RAWLOAD +case $USER in +    bdale) +	DONGLE=100 +	;; +    keithp) +	DONGLE=186 +	;; +    *) +	echo "Unknow user" +	exit 1 +	;; +esac +  $RAWLOAD -D $DONGLE -r ao_led_blink.ihx  echo "LEDs should be blinking"  sleep 5 @@ -45,7 +55,7 @@ read FREQ  CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"`  echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D $DONGLE --cal $CAL_VALUE /usr/share/altos/telebt-v1.0*.ihx $SERIAL +$AOLOAD -D $DONGLE --cal $CAL_VALUE ~/altusmetrumllc/Binaries/telebt-v1.0*.ihx $SERIAL  echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE  echo $SERIAL","$CAL_VALUE >> cal_values diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini index 4450d6f6..6aef7f51 100755 --- a/ao-bringup/turnon_telemini +++ b/ao-bringup/turnon_telemini @@ -18,11 +18,13 @@ else  	exit 1  fi -echo "TeleMini v1.0 Turn-On and Calibration Program" +VERSION=1.0 + +echo "TeleMini v$VERSION Turn-On and Calibration Program"  echo "Copyright 2011 by Bdale Garbee.  Released under GPL v2"  echo  echo "Expectations:" -echo "\tTeleMini v1.0 powered from LiPo" +echo "\tTeleMini v$VERSION powered from LiPo"  echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header"  echo "\t\twith frequency counter able to sample RF output"  echo @@ -31,18 +33,27 @@ read SERIAL  echo $RAWLOAD -$RAWLOAD -D 100 -r ao_led_blink.ihx +case $USER in +    bdale) +	programmer=100 +	;; +    keithp) +	programmer=186 +	;; +esac + +$RAWLOAD -D $programmer -r ao_led_blink.ihx  echo "LEDs should be blinking"  sleep 5 -$RAWLOAD -D 100 -r ao_radio_xmit.ihx +$RAWLOAD -D $programmer -r ao_radio_xmit.ihx  echo -n "Generating RF carrier.  Please enter measured frequency: "  read FREQ  CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"`  echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/telemini-v1.0*.ihx $SERIAL +$AOLOAD -D $programmer --cal $CAL_VALUE ~/altusmetrumllc/Binaries/telemini-v$VERSION-*.ihx $SERIAL  echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE  echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-tools/ao-usbtrng/ao-usbtrng.1 b/ao-tools/ao-usbtrng/ao-usbtrng.1 index 7a1311b9..eabdd8a1 100644 --- a/ao-tools/ao-usbtrng/ao-usbtrng.1 +++ b/ao-tools/ao-usbtrng/ao-usbtrng.1 @@ -16,28 +16,28 @@  .\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.  .\"  .\" -.TH AO-LOAD 1 "ao-usbtrng" "" +.TH AO-USBTRNG 1 "ao-usbtrng" ""  .SH NAME  ao-usbtrng \- dump random numbers from USBtrng  .SH SYNOPSIS -.B "ao-usbtrng" -[\-T \fItty-device\fP] -[\--tty \fItty-device\fP] -[\-D \fIaltos-device\fP] -[\--device \fIaltos-device\fP] -\fIkbytes\fP +.B "ao-usbtrng" [OPTION...] [KBYTES]  .SH DESCRIPTION  .I ao-usbtrng -dumps random numbers from a USBtrng device +dumps random numbers from a USBtrng device. If provided KBYTES specifies the number of 1024 byte blocks to produce on standard output. Without KBYTES +.I ao-usbtrng +produces random bytes continuously until killed.  .SH OPTIONS  .TP -\-T tty-device | --tty tty-device +\-v, --verbose +increase verbosity +.TP +\-T, -tty=TTYDEVICE  This selects which tty device the debugger uses to communicate with  the target device. The special name 'BITBANG' directs ao-dbg to use  the cp2103 connection, otherwise this should be a usb serial port  connected to a suitable cc1111 debug node.  .TP -\-D AltOS-device | --device AltOS-device +\-D, --device=ALTOSDEVICE  Search for a connected device. This requires an argument of one of the  following forms:  .IP @@ -52,7 +52,7 @@ product, leaving out the serial number will cause the tool to match  one of the available devices.  .SH USAGE  .I ao-usbtrng -opens the target device and reads the specified number of kbytes of +opens the target device and reads the specified number of KBYTES of  random data.  .SH AUTHOR  Keith Packard diff --git a/ao-tools/ao-usbtrng/ao-usbtrng.c b/ao-tools/ao-usbtrng/ao-usbtrng.c index 232f4e3e..456885d9 100644 --- a/ao-tools/ao-usbtrng/ao-usbtrng.c +++ b/ao-tools/ao-usbtrng/ao-usbtrng.c @@ -35,14 +35,13 @@  static const struct option options[] = {  	{ .name = "tty", .has_arg = 1, .val = 'T' },  	{ .name = "device", .has_arg = 1, .val = 'D' }, -	{ .name = "raw", .has_arg = 0, .val = 'r' }, -	{ .name = "verbose", .has_arg = 1, .val = 'v' }, +	{ .name = "verbose", .has_arg = 0, .val = 'v' },  	{ 0, 0, 0, 0},  };  static void usage(char *program)  { -	fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] <kbytes>\n", program); +	fprintf(stderr, "usage: %s [--verbose] [--device=<AltOS-device>] [-tty=<tty>] [<kbytes>]\n", program);  	exit(1);  } @@ -58,21 +57,17 @@ main (int argc, char **argv)  {  	char			*device = NULL;  	char			*filename; -	Elf			*e; -	unsigned int		s;  	int			i;  	int			c; -	int			tries;  	struct cc_usb		*cc = NULL;  	char			*tty = NULL; -	int			success;  	int			verbose = 0;  	int			ret = 0; -	int			expected_size; -	int			kbytes; +	int			kbytes = 0; /* 0 == continuous */ +	int			written;  	uint8_t			bits[1024]; -	while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) { +	while ((c = getopt_long(argc, argv, "vT:D:", options, NULL)) != -1) {  		switch (c) {  		case 'T':  			tty = optarg; @@ -89,12 +84,8 @@ main (int argc, char **argv)  		}  	} -	if (!argv[optind]) -		usage(argv[0]); - -	kbytes = atoi(argv[optind]); -	if (kbytes < 1) -		kbytes = 1; +	if (optind < argc) +		kbytes = atoi(argv[optind]);  	ao_verbose = verbose; @@ -113,13 +104,22 @@ main (int argc, char **argv)  	if (!cc)  		exit(1); -	cc_usb_printf(cc, "f %d\n", kbytes); +	if (kbytes) { +		cc_usb_printf(cc, "f %d\n", kbytes); -	while (kbytes--) { -		int	i; -		for (i = 0; i < 1024; i++) -			bits[i] = cc_usb_getchar(cc); -		write(1, bits, 1024); +		while (kbytes--) { +			for (i = 0; i < 1024; i++) +				bits[i] = cc_usb_getchar(cc); +			write(1, bits, 1024); +		} +	} else { /* 0 == continuous */ +		written = 0; +		while (written >= 0) { +			cc_usb_printf(cc, "f 1\n"); +			for (i = 0; i < 1024; i++) +				bits[i] = cc_usb_getchar(cc); +			written = write(1, bits, 1024); +		}  	}  	done(cc, ret); diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index b3c6b5dc..6eb1a111 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -228,7 +228,7 @@ void  ao_button_init(void);  char -ao_button_get(void) __critical; +ao_button_get(uint16_t timeout) __critical;  void  ao_button_clear(void) __critical; diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 69f3475f..a0f221c2 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -72,12 +72,12 @@ ao_button_mask(uint8_t reg)  }  char -ao_button_get(void) __critical +ao_button_get(uint16_t timeout) __critical  {  	char	b;  	while (ao_fifo_empty(ao_button_fifo)) -		if (ao_sleep(&ao_button_fifo)) +		if (ao_sleep_for(&ao_button_fifo, timeout))  			return 0;  	ao_fifo_remove(ao_button_fifo, b);  	return b; diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index b9821a42..cead0364 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -451,13 +451,9 @@ ao_radio_recv(__xdata void *packet, uint8_t size, uint8_t timeout) __reentrant  	/* Wait for DMA to be done, for the radio receive process to  	 * get aborted or for a receive timeout to fire  	 */ -	if (timeout) -		ao_alarm(timeout);  	__critical while (!ao_radio_dma_done && !ao_radio_abort) -			   if (ao_sleep(&ao_radio_dma_done)) +			   if (ao_sleep_for(&ao_radio_dma_done, timeout))  				   break; -	if (timeout) -		ao_clear_alarm();  	/* If recv was aborted, clean up by stopping the DMA engine  	 * and idling the radio diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index e6b28688..93d9dd9d 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -23,7 +23,7 @@  #ifndef ao_serial_btm_getchar  #define ao_serial_btm_putchar	ao_serial1_putchar  #define _ao_serial_btm_pollchar	_ao_serial1_pollchar -#define _ao_serial_btm_sleep()	ao_sleep((void *) &ao_serial1_rx_fifo) +#define _ao_serial_btm_sleep_for(timeout)	ao_sleep_for((void *) &ao_serial1_rx_fifo, timeout)  #define ao_serial_btm_set_speed ao_serial1_set_speed  #define ao_serial_btm_drain	ao_serial1_drain  #endif @@ -111,7 +111,7 @@ ao_btm_do_echo(void)  	while (ao_btm_enable) {  		ao_arch_block_interrupts();  		while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable) -			_ao_serial_btm_sleep(); +			_ao_serial_btm_sleep_for(0);  		ao_arch_release_interrupts();  		if (c != AO_READ_AGAIN) {  			putchar(c); @@ -166,9 +166,7 @@ ao_btm_getchar(void)  	ao_arch_block_interrupts();  	while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) { -		ao_alarm(AO_MS_TO_TICKS(10)); -		c = _ao_serial_btm_sleep(); -		ao_clear_alarm(); +		c = _ao_serial_btm_sleep_for(AO_MS_TO_TICKS(10));  		if (c) {  			c = AO_READ_AGAIN;  			break; diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 90d6cc75..5b814667 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -837,15 +837,11 @@ ao_radio_test_cmd(void)  static void  ao_radio_wait_isr(uint16_t timeout)  { -	if (timeout) -		ao_alarm(timeout);  	ao_arch_block_interrupts();  	while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) -		if (ao_sleep(&ao_radio_wake)) +		if (ao_sleep_for(&ao_radio_wake, timeout))  			ao_radio_abort = 1;  	ao_arch_release_interrupts(); -	if (timeout) -		ao_clear_alarm();  	if (ao_radio_mcu_wake)  		ao_radio_check_marc_status();  } @@ -1060,19 +1056,17 @@ ao_radio_rx_isr(void)  static uint16_t  ao_radio_rx_wait(void)  { -	ao_alarm(AO_MS_TO_TICKS(100));  	ao_arch_block_interrupts();  	rx_waiting = 1;  	while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&  	       !ao_radio_abort &&  	       !ao_radio_mcu_wake)  	{ -		if (ao_sleep(&ao_radio_wake)) +		if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100)))  			ao_radio_abort = 1;  	}  	rx_waiting = 0;  	ao_arch_release_interrupts(); -	ao_clear_alarm();  	if (ao_radio_abort || ao_radio_mcu_wake)  		return 0;  	rx_data_consumed += AO_FEC_DECODE_BLOCK; @@ -1133,19 +1127,15 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)  	ao_radio_strobe(CC1120_SRX); -	if (timeout) -		ao_alarm(timeout);  	ao_arch_block_interrupts();  	while (rx_starting && !ao_radio_abort) { -		if (ao_sleep(&ao_radio_wake)) +		if (ao_sleep_for(&ao_radio_wake, timeout))  			ao_radio_abort = 1;  	}  	uint8_t	rx_task_id_save = rx_task_id;  	rx_task_id = 0;  	rx_starting = 0;  	ao_arch_release_interrupts(); -	if (timeout) -		ao_clear_alarm();  	if (ao_radio_abort) {  		if (rx_task_id_save == 0) diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 8546900e..df4bd335 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -715,17 +715,11 @@ ao_radio_show_state(char *where)  static void  ao_radio_wait_isr(uint16_t timeout)  { -	if (timeout) -		ao_alarm(timeout); -  	ao_arch_block_interrupts();  	while (!ao_radio_wake && !ao_radio_abort) -		if (ao_sleep(&ao_radio_wake)) +		if (ao_sleep_for(&ao_radio_wake, timeout))  			ao_radio_abort = 1;  	ao_arch_release_interrupts(); - -	if (timeout) -		ao_clear_alarm();  }  static void diff --git a/src/drivers/ao_cc1200.h b/src/drivers/ao_cc1200.h index b04775fd..b2b63cde 100644 --- a/src/drivers/ao_cc1200.h +++ b/src/drivers/ao_cc1200.h @@ -438,6 +438,38 @@  #define CC1200_IF_MIX_CFG	(CC1200_EXTENDED_BIT | 0x00)  #define CC1200_FREQOFF_CFG	(CC1200_EXTENDED_BIT | 0x01)  #define CC1200_TOC_CFG		(CC1200_EXTENDED_BIT | 0x02) + +#define CC1200_TOC_CFG_TOC_LIMIT		6 +#define  CC1200_TOC_CFG_TOC_LIMIT_0_2			0 +#define  CC1200_TOC_CFG_TOC_LIMIT_2			1 +#define  CC1200_TOC_CFG_TOC_LIMIT_12			3 + +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN	3 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_8			0 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_16		1 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_32		2 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_64		3 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_128		4 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_256		5 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_8_16		0 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_6_16		1 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_2_16		2 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_1_16		3 +#define  CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_1_16_SYNC		4 + +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN	0 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_8		0 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_16		1 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_32		2 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_64		3 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_128		4 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_256		5 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_FREEZE		0 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_6_32		1 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_2_32		2 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_1_32		3 +#define  CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_1_32_SYNC	4 +  #define CC1200_MARC_SPARE	(CC1200_EXTENDED_BIT | 0x03)  #define CC1200_ECG_CFG		(CC1200_EXTENDED_BIT | 0x04)  #define CC1200_MDMCFG2		(CC1200_EXTENDED_BIT | 0x05) diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index 35673123..f0214c2a 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -101,6 +101,15 @@  		 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |  		 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |  		 (0 << CC1200_MDMCFG2_CFM_DATA_EN)), +	CC1200_MDMCFG0,					 /* General Modem Parameter Configuration Reg. 0 */  +		((0 << CC1200_MDMCFG0_TRANSPARENT_MODE_EN) | +		 (0 << CC1200_MDMCFG0_TRANSPARENT_INTFACT) | +		 (0 << CC1200_MDMCFG0_DATA_FILTER_EN) |	 +		 (1 << CC1200_MDMCFG0_VITERBI_EN)), +	CC1200_TOC_CFG,					/* Timing Offset Correction Configuration */ +		((CC1200_TOC_CFG_TOC_LIMIT_2 << CC1200_TOC_CFG_TOC_LIMIT) | +		 (CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_6_16 << CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN)| +		 (CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_2_32 << CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN)),          CC1200_FREQ2,                        0x6c,       /* Frequency Configuration [23:16] */          CC1200_FREQ1,                        0xa3,       /* Frequency Configuration [15:8] */          CC1200_FREQ0,                        0x33,       /* Frequency Configuration [7:0] */ diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 570b9e40..7e02939b 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -102,8 +102,7 @@ ao_companion(void)  		    break;  	}  	while (ao_companion_running) { -		ao_alarm(ao_companion_setup.update_period); -		if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) +		if (ao_sleep_for(DATA_TO_XDATA(&ao_flight_state), ao_companion_setup.update_period))  			ao_companion_get_data();  		else  			ao_companion_notify(); diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 2d217bcf..f761671a 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -75,13 +75,11 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample)  	ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN);  	ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); -	ao_alarm(AO_MS_TO_TICKS(10));  	ao_arch_block_interrupts();  	while (!ao_hmc5883_done) -		if (ao_sleep(&ao_hmc5883_done)) +		if (ao_sleep_for(&ao_hmc5883_done, AO_MS_TO_TICKS(10)))  			++ao_hmc5883_missed_irq;  	ao_arch_release_interrupts(); -	ao_clear_alarm();  	ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample));  #if __BYTE_ORDER == __LITTLE_ENDIAN diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 8cdf85a9..18330ead 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -54,14 +54,14 @@ ao_packet_send(void)  }  uint8_t -ao_packet_recv(void) +ao_packet_recv(uint16_t timeout)  {  	uint8_t	dma_done;  #ifdef AO_LED_GREEN  	ao_led_on(AO_LED_GREEN);  #endif -	dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv), 0); +	dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv), timeout);  #ifdef AO_LED_GREEN  	ao_led_off(AO_LED_GREEN);  #endif diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 42a4f5bf..5e440db0 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -97,9 +97,7 @@ ao_packet_master(void)  		if (ao_tx_packet.len)  			ao_packet_master_busy();  		ao_packet_master_check_busy(); -		ao_alarm(AO_PACKET_MASTER_RECV_DELAY); -		r = ao_packet_recv(); -		ao_clear_alarm(); +		r = ao_packet_recv(AO_PACKET_MASTER_RECV_DELAY);  		if (r) {  			/* if we can transmit data, do so */  			if (ao_packet_tx_used && ao_tx_packet.len == 0) @@ -107,9 +105,7 @@ ao_packet_master(void)  			if (ao_rx_packet.packet.len)  				ao_packet_master_busy();  			ao_packet_master_sleeping = 1; -			ao_alarm(ao_packet_master_delay); -			ao_sleep(&ao_packet_master_sleeping); -			ao_clear_alarm(); +			ao_sleep_for(&ao_packet_master_sleeping, ao_packet_master_delay);  			ao_packet_master_sleeping = 0;  		}  	} diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c index e75df0d6..0872682f 100644 --- a/src/drivers/ao_packet_slave.c +++ b/src/drivers/ao_packet_slave.c @@ -24,7 +24,7 @@ ao_packet_slave(void)  	ao_tx_packet.len = AO_PACKET_SYN;  	ao_packet_restart = 1;  	while (ao_packet_enable) { -		if (ao_packet_recv()) { +		if (ao_packet_recv(0)) {  			ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);  #if HAS_FLIGHT  			ao_flight_force_idle = TRUE; diff --git a/src/kernel/ao_packet.h b/src/kernel/ao_packet.h index b8426cf9..136609c3 100644 --- a/src/kernel/ao_packet.h +++ b/src/kernel/ao_packet.h @@ -54,7 +54,7 @@ void  ao_packet_send(void);  uint8_t -ao_packet_recv(void); +ao_packet_recv(uint16_t timeout);  void  ao_packet_flush(void); diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c index 3044d565..43e73de4 100644 --- a/src/kernel/ao_pyro.c +++ b/src/kernel/ao_pyro.c @@ -375,9 +375,7 @@ ao_pyro(void)  		ao_sleep(&ao_flight_state);  	for (;;) { -		ao_alarm(AO_MS_TO_TICKS(100)); -		ao_sleep(&ao_pyro_wakeup); -		ao_clear_alarm(); +		ao_sleep_for(&ao_pyro_wakeup, AO_MS_TO_TICKS(100));  		if (ao_flight_state >= ao_flight_landed)  			break;  		any_waiting = ao_pyro_check(); diff --git a/src/kernel/ao_serial.h b/src/kernel/ao_serial.h index dbc9f8e4..e21643ac 100644 --- a/src/kernel/ao_serial.h +++ b/src/kernel/ao_serial.h @@ -35,7 +35,7 @@ int  _ao_serial0_pollchar(void);  uint8_t -_ao_serial0_sleep(void); +_ao_serial0_sleep_for(uint16_t timeout);  void  ao_serial0_putchar(char c); @@ -58,7 +58,7 @@ int  _ao_serial1_pollchar(void);  uint8_t -_ao_serial1_sleep(void); +_ao_serial1_sleep_for(uint16_t timeout);  void  ao_serial1_putchar(char c); @@ -81,7 +81,7 @@ int  _ao_serial2_pollchar(void);  uint8_t -_ao_serial2_sleep(void); +_ao_serial2_sleep_for(uint16_t timeout);  void  ao_serial2_putchar(char c); @@ -104,7 +104,7 @@ int  _ao_serial3_pollchar(void);  uint8_t -_ao_serial3_sleep(void); +_ao_serial3_sleep_for(uint16_t timeout);  void  ao_serial3_putchar(char c); diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index bafb4943..55e423bb 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -450,37 +450,39 @@ ao_wakeup(__xdata void *wchan) __reentrant  	ao_check_stack();  } -void -ao_alarm(uint16_t delay) +uint8_t +ao_sleep_for(__xdata void *wchan, uint16_t timeout)  { +	uint8_t	ret; +	if (timeout) {  #if HAS_TASK_QUEUE -	uint32_t flags; -	/* Make sure we sleep *at least* delay ticks, which means adding -	 * one to account for the fact that we may be close to the next tick -	 */ -	flags = ao_arch_irqsave(); +		uint32_t flags; +		/* Make sure we sleep *at least* delay ticks, which means adding +		 * one to account for the fact that we may be close to the next tick +		 */ +		flags = ao_arch_irqsave();  #endif -	if (!(ao_cur_task->alarm = ao_time() + delay + 1)) -		ao_cur_task->alarm = 1; +		if (!(ao_cur_task->alarm = ao_time() + timeout + 1)) +			ao_cur_task->alarm = 1;  #if HAS_TASK_QUEUE -	ao_task_to_alarm_queue(ao_cur_task); -	ao_arch_irqrestore(flags); +		ao_task_to_alarm_queue(ao_cur_task); +		ao_arch_irqrestore(flags);  #endif -} - -void -ao_clear_alarm(void) -{ +	} +	ret = ao_sleep(wchan); +	if (timeout) {  #if HAS_TASK_QUEUE -	uint32_t flags; +		uint32_t flags; -	flags = ao_arch_irqsave(); +		flags = ao_arch_irqsave();  #endif -	ao_cur_task->alarm = 0; +		ao_cur_task->alarm = 0;  #if HAS_TASK_QUEUE -	ao_task_from_alarm_queue(ao_cur_task); -	ao_arch_irqrestore(flags); +		ao_task_from_alarm_queue(ao_cur_task); +		ao_arch_irqrestore(flags);  #endif +	} +	return ret;  }  static __xdata uint8_t ao_forever; @@ -488,9 +490,7 @@ static __xdata uint8_t ao_forever;  void  ao_delay(uint16_t ticks)  { -	ao_alarm(ticks); -	ao_sleep(&ao_forever); -	ao_clear_alarm(); +	ao_sleep_for(&ao_forever, ticks);  }  void diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h index 9c56b480..c6bec0e3 100644 --- a/src/kernel/ao_task.h +++ b/src/kernel/ao_task.h @@ -68,10 +68,19 @@ extern __data uint8_t ao_task_minimize_latency;	/* Reduce IRQ latency */  uint8_t  ao_sleep(__xdata void *wchan); +/* Suspend the current task until wchan is awoken or the timeout + * expires. returns: + *  0 on normal wake + *  1 on alarm + */ +uint8_t +ao_sleep_for(__xdata void *wchan, uint16_t timeout); +  /* Wake all tasks sleeping on wchan */  void  ao_wakeup(__xdata void *wchan) __reentrant; +#if 0  /* set an alarm to go off in 'delay' ticks */  void  ao_alarm(uint16_t delay); @@ -79,6 +88,7 @@ ao_alarm(uint16_t delay);  /* Clear any pending alarm */  void  ao_clear_alarm(void); +#endif  /* Yield the processor to another task */  void diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index e2197f7a..854ac898 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -486,9 +486,7 @@ ao_telemetry(void)  #endif /* HAS_APRS */  			delay = time - ao_time();  			if (delay > 0) { -				ao_alarm(delay); -				ao_sleep(&telemetry); -				ao_clear_alarm(); +				ao_sleep_for(&telemetry, delay);  			}  		}  	} diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 8fd97033..1e7b5dcd 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -539,9 +539,7 @@ ao_terraui(void)  		else  			ao_terraui_page[ao_current_page](); -		ao_alarm(AO_SEC_TO_TICKS(1)); -		b = ao_button_get(); -		ao_clear_alarm(); +		b = ao_button_get(AO_SEC_TO_TICKS(1));  		if (b > 0) {  			ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(10)); diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 1c90cdb8..158f5b21 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -195,15 +195,13 @@ ao_i2c_start(uint8_t index, uint16_t addr)  		if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START)))  			break;  	} -	ao_alarm(AO_MS_TO_TICKS(250));  	ao_arch_block_interrupts();  	stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);  	ao_i2c_ev_isr(index);  	while (ao_i2c_state[index] == I2C_IDLE) -		if (ao_sleep(&ao_i2c_state[index])) +		if (ao_sleep_for(&ao_i2c_state[index], AO_MS_TO_TICKS(250)))  			break;  	ao_arch_release_interrupts(); -	ao_clear_alarm();  	return ao_i2c_state[index] == I2C_RUNNING;  } @@ -258,16 +256,14 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop)  			    (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));  	ao_dma_start(tx_dma_index); -	ao_alarm(1 + len);  	ao_arch_block_interrupts();  	while (!ao_dma_done[tx_dma_index]) -		if (ao_sleep(&ao_dma_done[tx_dma_index])) +		if (ao_sleep_for(&ao_dma_done[tx_dma_index], 1 + len))  			break; -	ao_clear_alarm();  	ao_dma_done_transfer(tx_dma_index);  	stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);  	while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0) -		if (ao_sleep(&ao_i2c_state[index])) +		if (ao_sleep_for(&ao_i2c_state[index], 1 + len))  			break;  	stm_i2c->cr2 = AO_STM_I2C_CR2;  	ao_arch_release_interrupts(); @@ -321,14 +317,12 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)  		if (stop)  			stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); -		ao_alarm(1);  		ao_arch_block_interrupts();  		while (ao_i2c_recv_len[index]) -			if (ao_sleep(&ao_i2c_recv_len[index])) +			if (ao_sleep_for(&ao_i2c_recv_len[index], 1))  				break;  		ao_arch_release_interrupts();  		ret = ao_i2c_recv_len[index] == 0; -		ao_clear_alarm();  	} else {  		uint8_t		rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;  		ao_dma_set_transfer(rx_dma_index, @@ -351,13 +345,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop)  		ao_i2c_wait_addr(index);  		ao_dma_start(rx_dma_index); -		ao_alarm(len);  		ao_arch_block_interrupts();  		while (!ao_dma_done[rx_dma_index]) -			if (ao_sleep(&ao_dma_done[rx_dma_index])) +			if (ao_sleep_for(&ao_dma_done[rx_dma_index], len))  				break;  		ao_arch_release_interrupts(); -		ao_clear_alarm();  		ret = ao_dma_done[rx_dma_index];  		ao_dma_done_transfer(rx_dma_index);  		stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 2568cf43..88f2d029 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -86,9 +86,9 @@ ao_usart_getchar(struct ao_stm_usart *usart)  }  static inline uint8_t -_ao_usart_sleep(struct ao_stm_usart *usart) +_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)  { -	return ao_sleep(&usart->rx_fifo); +	return ao_sleep_for(&usart->rx_fifo, timeout);  }  void @@ -217,9 +217,9 @@ _ao_serial1_pollchar(void)  }  uint8_t -_ao_serial1_sleep(void) +_ao_serial1_sleep_for(uint16_t timeout)  { -	return _ao_usart_sleep(&ao_stm_usart1); +	return _ao_usart_sleep_for(&ao_stm_usart1, timeout);  }  void @@ -260,9 +260,9 @@ _ao_serial2_pollchar(void)  }  uint8_t -_ao_serial2_sleep(void) +_ao_serial2_sleep_for(uint16_t timeout)  { -	return _ao_usart_sleep(&ao_stm_usart2); +	return _ao_usart_sleep_for(&ao_stm_usart2, timeout);  }  void @@ -303,9 +303,9 @@ _ao_serial3_pollchar(void)  }  uint8_t -_ao_serial3_sleep(void) +_ao_serial3_sleep_for(uint16_t timeout)  { -	return _ao_usart_sleep(&ao_stm_usart3); +	return _ao_usart_sleep_for(&ao_stm_usart3, timeout);  }  void diff --git a/src/stmf0/ao_crc_stm.c b/src/stmf0/ao_crc_stm.c new file mode 100644 index 00000000..78efa93a --- /dev/null +++ b/src/stmf0/ao_crc_stm.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2015 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_crc.h> + +#ifndef AO_CRC_WIDTH +#error "Must define AO_CRC_WIDTH" +#endif + +/* Only the STM32F07x and ST32F09x series have + * programmable CRC units. Others can only do the ANSI CRC-32 computation + */ + +#if !AO_HAVE_PROGRAMMABLE_CRC_UNIT && AO_CRC_WIDTH != 32 +#error "Target hardware does not have programmable CRC unit" +#endif + +#ifndef AO_CRC_POLY +#if AO_CRC_WIDTH == 16 +#define AO_CRC_POLY	AO_CRC_16_DEFAULT +#endif +#if AO_CRC_WIDTH == 32 +#define AO_CRC_POLY	AO_CRC_32_DEFAULT +#endif +#endif + +#if !AO_HAVE_PROGRAMMABLE_CRC_UNIT && (AO_CRC_WIDTH != 32 || AO_CRC_POLY != AO_CRC_32_ANSI) +#error "Target hardware does not have programmable CRC unit" +#endif + +#if AO_CRC_WIDTH == 32 +#define AO_CRC_CR_POLYSIZE	STM_CRC_CR_POLYSIZE_32 +#endif + +#if AO_CRC_WIDTH == 16 +#define AO_CRC_CR_POLYSIZE	STM_CRC_CR_POLYSIZE_16 +#endif + +#if AO_CRC_WIDTH == 8 +#define AO_CRC_CR_POLYSIZE	STM_CRC_CR_POLYSIZE_8 +#endif + +#if AO_CRC_WIDTH == 7 +#define AO_CRC_CR_POLYSIZE	STM_CRC_CR_POLYSIZE_7 +#endif + +#ifndef AO_CRC_INIT +#define AO_CRC_INIT	0xffffffff; +#endif + +void +ao_crc_reset(void) +{ +	stm_crc.cr |= (1 << STM_CRC_CR_RESET); +	while ((stm_crc.cr & (1 << STM_CRC_CR_RESET)) != 0) +		; +} + +void +ao_crc_init(void) +{ +	/* Turn on the CRC clock */ +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_CRCEN); + +	/* Need to initialize CR even on non-programmable hardware, +	 * the write to the POLYSIZE bits will be ignored in that +	 * case +	 */ +	stm_crc.cr = (AO_CRC_CR_POLYSIZE << STM_CRC_CR_POLYSIZE); +	stm_crc.init = AO_CRC_INIT; +#if AO_HAVE_PROGRAMMABLE_CRC_UNIT +	stm_crc.pol = AO_CRC_POLY; +#endif +	ao_crc_reset(); +} diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index 838f0dfc..6e90afcc 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -168,7 +168,7 @@ struct ao_adc {  #define ao_serial_btm_getchar	ao_serial2_getchar  #define ao_serial_btm_putchar	ao_serial2_putchar  #define _ao_serial_btm_pollchar	_ao_serial2_pollchar -#define _ao_serial_btm_sleep	_ao_serial2_sleep +#define _ao_serial_btm_sleep_for	_ao_serial2_sleep_for  #define ao_serial_btm_set_speed ao_serial2_set_speed  #define ao_serial_btm_drain	ao_serial2_drain  #define ao_serial_btm_rx_fifo	(ao_stm_usart2.rx_fifo) diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index 79f3896b..cb2195ef 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -280,9 +280,7 @@ ao_lco_igniter_status(void)  	uint16_t	delay;  	for (;;) { -//		ao_alarm(delay);  		ao_sleep(&ao_pad_query); -//		ao_clear_alarm();  		if (!ao_lco_valid) {  			ao_led_on(AO_LED_RED);  			ao_led_off(AO_LED_GREEN); @@ -364,9 +362,7 @@ ao_lco_monitor(void)  			delay = AO_MS_TO_TICKS(100);  		else  			delay = AO_SEC_TO_TICKS(1); -		ao_alarm(delay); -		ao_sleep(&ao_lco_armed); -		ao_clear_alarm(); +		ao_sleep_for(&ao_lco_armed, delay);  	}  } diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c index 4b5f7a9b..12a247bf 100644 --- a/src/telelco-v0.2/ao_lco.c +++ b/src/telelco-v0.2/ao_lco.c @@ -369,9 +369,7 @@ ao_lco_monitor(void)  			delay = AO_MS_TO_TICKS(100);  		else  			delay = AO_SEC_TO_TICKS(1); -		ao_alarm(delay); -		ao_sleep(&ao_lco_armed); -		ao_clear_alarm(); +		ao_sleep_for(&ao_lco_armed, delay);  	}  } | 
