diff options
| -rw-r--r-- | altosui/Altos.java | 2 | ||||
| -rw-r--r-- | altosui/AltosBTDevice.java | 7 | ||||
| -rw-r--r-- | altosui/AltosCSVUI.java | 2 | ||||
| -rw-r--r-- | altosui/AltosConfig.java | 3 | ||||
| -rw-r--r-- | altosui/AltosConfigureUI.java | 33 | ||||
| -rw-r--r-- | altosui/AltosDataChooser.java | 2 | ||||
| -rw-r--r-- | altosui/AltosDevice.java | 1 | ||||
| -rw-r--r-- | altosui/AltosDeviceDialog.java | 36 | ||||
| -rw-r--r-- | altosui/AltosEepromDownload.java | 12 | ||||
| -rw-r--r-- | altosui/AltosEepromManage.java | 3 | ||||
| -rw-r--r-- | altosui/AltosFlashUI.java | 4 | ||||
| -rw-r--r-- | altosui/AltosIgniteUI.java | 3 | ||||
| -rw-r--r-- | altosui/AltosLanded.java | 4 | ||||
| -rw-r--r-- | altosui/AltosLaunch.java | 201 | ||||
| -rw-r--r-- | altosui/AltosLaunchUI.java | 517 | ||||
| -rw-r--r-- | altosui/AltosPreferences.java | 39 | ||||
| -rw-r--r-- | altosui/AltosScanUI.java | 6 | ||||
| -rw-r--r-- | altosui/AltosSerial.java | 4 | ||||
| -rw-r--r-- | altosui/AltosUI.java | 20 | ||||
| -rw-r--r-- | altosui/AltosUSBDevice.java | 7 | ||||
| -rw-r--r-- | altosui/Makefile.am | 5 | ||||
| -rw-r--r-- | altosui/libaltos/libaltos.c | 175 | ||||
| -rw-r--r-- | altosui/libaltos/libaltos.h | 13 | ||||
| -rw-r--r-- | configure.ac | 4 | ||||
| -rw-r--r-- | src/Makefile | 28 | ||||
| -rw-r--r-- | src/Makefile.proto | 380 | ||||
| -rw-r--r-- | src/ao_aes.c | 142 | ||||
| -rw-r--r-- | src/ao_radio_cmac.c | 406 | ||||
| -rw-r--r-- | src/ao_telelaunch.c (renamed from src/ao_main.c) | 21 | ||||
| -rw-r--r-- | src/avr-demo/Makefile | 105 | ||||
| -rw-r--r-- | src/avr-demo/ao_demo.c | 52 | ||||
| -rw-r--r-- | src/avr/ao_adc_avr.c | 168 | ||||
| -rw-r--r-- | src/avr/ao_arch.h | 158 | ||||
| -rw-r--r-- | src/avr/ao_avr_stdio.c | 52 | ||||
| -rw-r--r-- | src/avr/ao_clock.c | 77 | ||||
| -rw-r--r-- | src/avr/ao_debug_avr.c | 78 | ||||
| -rw-r--r-- | src/avr/ao_led.c | 67 | ||||
| -rw-r--r-- | src/avr/ao_pins.h | 88 | ||||
| -rw-r--r-- | src/avr/ao_romconfig.c (renamed from src/ao_log_telem.c) | 12 | ||||
| -rw-r--r-- | src/avr/ao_serial_avr.c | 166 | ||||
| -rw-r--r-- | src/avr/ao_spi_slave.c | 115 | ||||
| -rw-r--r-- | src/avr/ao_spi_usart.c | 112 | ||||
| -rw-r--r-- | src/avr/ao_timer.c | 89 | ||||
| -rw-r--r-- | src/avr/ao_usb.h (renamed from src/ao_usb.h) | 0 | ||||
| -rw-r--r-- | src/avr/ao_usb_avr.c | 688 | ||||
| -rw-r--r-- | src/cc1111/Makefile.cc1111 | 27 | ||||
| -rw-r--r-- | src/cc1111/_bp.c (renamed from src/_bp.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_adc.c (renamed from src/ao_adc.c) | 4 | ||||
| -rw-r--r-- | src/cc1111/ao_arch.h | 207 | ||||
| -rw-r--r-- | src/cc1111/ao_beep.c (renamed from src/ao_beep.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_dbg.c (renamed from src/ao_dbg.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_dma.c (renamed from src/ao_dma.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_ignite.c (renamed from src/ao_ignite.c) | 28 | ||||
| -rw-r--r-- | src/cc1111/ao_intflash.c (renamed from src/ao_intflash.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_launch.c | 209 | ||||
| -rw-r--r-- | src/cc1111/ao_led.c (renamed from src/ao_led.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_packet.c (renamed from src/ao_packet.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_packet_master.c (renamed from src/ao_packet_master.c) | 6 | ||||
| -rw-r--r-- | src/cc1111/ao_packet_slave.c (renamed from src/ao_packet_slave.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_pins.h (renamed from src/ao_pins.h) | 106 | ||||
| -rw-r--r-- | src/cc1111/ao_radio.c (renamed from src/ao_radio.c) | 14 | ||||
| -rw-r--r-- | src/cc1111/ao_reboot.c (renamed from src/ao_reboot.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_romconfig.c (renamed from src/ao_romconfig.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_serial.c (renamed from src/ao_serial.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_spi.c (renamed from src/ao_spi.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_timer.c (renamed from src/ao_timer.c) | 1 | ||||
| -rw-r--r-- | src/cc1111/ao_usb.c (renamed from src/ao_usb.c) | 0 | ||||
| -rw-r--r-- | src/cc1111/ao_usb.h | 100 | ||||
| -rw-r--r-- | src/cc1111/cc1111.h (renamed from src/cc1111.h) | 24 | ||||
| -rw-r--r-- | src/core/altitude.h (renamed from src/altitude.h) | 0 | ||||
| -rw-r--r-- | src/core/ao.h (renamed from src/ao.h) | 350 | ||||
| -rw-r--r-- | src/core/ao_cmd.c (renamed from src/ao_cmd.c) | 59 | ||||
| -rw-r--r-- | src/core/ao_config.c (renamed from src/ao_config.c) | 44 | ||||
| -rw-r--r-- | src/core/ao_convert.c (renamed from src/ao_convert.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_convert_test.c (renamed from src/ao_convert_test.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_ee_fake.c (renamed from src/ao_ee_fake.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_flight.c (renamed from src/ao_flight.c) | 19 | ||||
| -rw-r--r-- | src/core/ao_flight_nano.c (renamed from src/ao_flight_nano.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_gps_print.c (renamed from src/ao_gps_print.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_gps_report.c (renamed from src/ao_gps_report.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_host.h (renamed from src/ao_host.h) | 0 | ||||
| -rw-r--r-- | src/core/ao_kalman.c (renamed from src/ao_kalman.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_log.c (renamed from src/ao_log.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_log_big.c (renamed from src/ao_log_big.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_log_single.c | 198 | ||||
| -rw-r--r-- | src/core/ao_log_telem.c | 127 | ||||
| -rw-r--r-- | src/core/ao_log_telescience.c | 117 | ||||
| -rw-r--r-- | src/core/ao_log_tiny.c (renamed from src/ao_log_tiny.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_monitor.c (renamed from src/ao_monitor.c) | 39 | ||||
| -rw-r--r-- | src/core/ao_mutex.c (renamed from src/ao_mutex.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_panic.c (renamed from src/ao_panic.c) | 9 | ||||
| -rw-r--r-- | src/core/ao_product.c (renamed from src/ao_product.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_report.c (renamed from src/ao_report.c) | 24 | ||||
| -rw-r--r-- | src/core/ao_rssi.c (renamed from src/ao_rssi.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_sample.c (renamed from src/ao_sample.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_state.c (renamed from src/ao_state.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_stdio.c (renamed from src/ao_stdio.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_storage.c (renamed from src/ao_storage.c) | 0 | ||||
| -rw-r--r-- | src/core/ao_task.c (renamed from src/ao_task.c) | 164 | ||||
| -rw-r--r-- | src/core/ao_telem.h (renamed from src/ao_telem.h) | 0 | ||||
| -rw-r--r-- | src/core/ao_telemetry.c (renamed from src/ao_telemetry.c) | 31 | ||||
| -rw-r--r-- | src/drivers/ao_25lc1024.c (renamed from src/ao_ee.c) | 2 | ||||
| -rw-r--r-- | src/drivers/ao_25lc1024.h (renamed from src/25lc1024.h) | 0 | ||||
| -rw-r--r-- | src/drivers/ao_at45db161d.c (renamed from src/ao_flash.c) | 2 | ||||
| -rw-r--r-- | src/drivers/ao_at45db161d.h (renamed from src/at45db161d.h) | 0 | ||||
| -rw-r--r-- | src/drivers/ao_btm.c (renamed from src/ao_btm.c) | 88 | ||||
| -rw-r--r-- | src/drivers/ao_companion.c (renamed from src/ao_companion.c) | 2 | ||||
| -rw-r--r-- | src/drivers/ao_gps_sirf.c (renamed from src/ao_gps_sirf.c) | 0 | ||||
| -rw-r--r-- | src/drivers/ao_gps_skytraq.c (renamed from src/ao_gps_skytraq.c) | 0 | ||||
| -rw-r--r-- | src/drivers/ao_lcd.c | 281 | ||||
| -rw-r--r-- | src/drivers/ao_m25.c (renamed from src/ao_m25.c) | 2 | ||||
| -rw-r--r-- | src/drivers/ao_pyro_slave.c | 51 | ||||
| -rw-r--r-- | src/drivers/ao_science_slave.c | 62 | ||||
| -rw-r--r-- | src/product/Makefile.telebt | 98 | ||||
| -rw-r--r-- | src/product/Makefile.teledongle | 98 | ||||
| -rw-r--r-- | src/product/Makefile.telelaunch | 101 | ||||
| -rw-r--r-- | src/product/Makefile.telemetrum | 111 | ||||
| -rw-r--r-- | src/product/Makefile.telemini | 100 | ||||
| -rw-r--r-- | src/product/Makefile.telenano | 99 | ||||
| -rw-r--r-- | src/product/ao_telebt.c (renamed from src/ao_telebt.c) | 13 | ||||
| -rw-r--r-- | src/product/ao_teledongle.c (renamed from src/ao_teledongle.c) | 2 | ||||
| -rw-r--r-- | src/product/ao_telemetrum.c (renamed from src/ao_telemetrum.c) | 0 | ||||
| -rw-r--r-- | src/product/ao_telemini.c (renamed from src/ao_telemini.c) | 0 | ||||
| -rw-r--r-- | src/product/ao_telenano.c (renamed from src/ao_telenano.c) | 0 | ||||
| -rw-r--r-- | src/product/ao_telepyro.c (renamed from src/ao_adc_fake.c) | 23 | ||||
| -rw-r--r-- | src/product/ao_telescience.c | 39 | ||||
| -rw-r--r-- | src/product/ao_teleterra.c (renamed from src/ao_teleterra.c) | 0 | ||||
| -rw-r--r-- | src/product/ao_test.c (renamed from src/ao_test.c) | 0 | ||||
| -rw-r--r-- | src/product/ao_tidongle.c (renamed from src/ao_tidongle.c) | 2 | ||||
| -rw-r--r-- | src/telebt-v0.0/Makefile | 10 | ||||
| -rw-r--r-- | src/telebt-v0.0/Makefile.defs | 8 | ||||
| -rw-r--r-- | src/telebt-v0.1/Makefile | 22 | ||||
| -rw-r--r-- | src/telebt-v0.1/Makefile.defs | 8 | ||||
| -rw-r--r-- | src/teledongle-v0.1/.sdcdbrc | 1 | ||||
| -rw-r--r-- | src/teledongle-v0.1/Makefile | 9 | ||||
| -rw-r--r-- | src/teledongle-v0.1/Makefile.defs | 9 | ||||
| -rw-r--r-- | src/teledongle-v0.2/Makefile | 9 | ||||
| -rw-r--r-- | src/teledongle-v0.2/Makefile.defs | 9 | ||||
| -rw-r--r-- | src/telelaunch-v0.1/.gitignore | 2 | ||||
| -rw-r--r-- | src/telelaunch-v0.1/.sdcdbrc | 1 | ||||
| -rw-r--r-- | src/telelaunch-v0.1/Makefile | 4 | ||||
| -rw-r--r-- | src/telelaunch-v0.1/Makefile.defs | 14 | ||||
| -rw-r--r-- | src/telemetrum-v0.1-sirf/Makefile | 17 | ||||
| -rw-r--r-- | src/telemetrum-v0.1-sirf/Makefile.defs | 12 | ||||
| -rw-r--r-- | src/telemetrum-v0.1-sky/Makefile | 17 | ||||
| -rw-r--r-- | src/telemetrum-v0.1-sky/Makefile.defs | 12 | ||||
| -rw-r--r-- | src/telemetrum-v1.0/Makefile | 17 | ||||
| -rw-r--r-- | src/telemetrum-v1.0/Makefile.defs | 13 | ||||
| -rw-r--r-- | src/telemetrum-v1.1/Makefile | 17 | ||||
| -rw-r--r-- | src/telemetrum-v1.1/Makefile.defs | 13 | ||||
| -rw-r--r-- | src/telemini-v1.0/Makefile | 9 | ||||
| -rw-r--r-- | src/telemini-v1.0/Makefile.defs | 9 | ||||
| -rw-r--r-- | src/telenano-v0.1/Makefile | 10 | ||||
| -rw-r--r-- | src/telenano-v0.1/Makefile.defs | 9 | ||||
| -rw-r--r-- | src/telepyro-v0.1/Makefile | 101 | ||||
| -rw-r--r-- | src/telescience-v0.1/Makefile | 112 | ||||
| -rw-r--r-- | src/test/Makefile | 20 | ||||
| -rw-r--r-- | src/test/ao_flight_test.c (renamed from src/ao_flight_test.c) | 0 | ||||
| -rw-r--r-- | src/test/ao_gps_test.c (renamed from src/ao_gps_test.c) | 0 | ||||
| -rw-r--r-- | src/test/ao_gps_test_skytraq.c (renamed from src/ao_gps_test_skytraq.c) | 0 | ||||
| -rw-r--r-- | src/tidongle/Makefile | 95 | ||||
| -rw-r--r-- | src/tidongle/Makefile.defs | 9 | ||||
| -rw-r--r-- | src/util/ao-make-product.5c (renamed from src/ao-make-product.5c) | 0 | ||||
| -rw-r--r-- | src/util/check-avr-mem | 9 | ||||
| -rwxr-xr-x | src/util/check-stack (renamed from src/check-stack) | 0 | ||||
| -rwxr-xr-x | src/util/gps-cksum (renamed from src/gps-cksum) | 0 | ||||
| -rw-r--r-- | src/util/make-altitude (renamed from src/make-altitude) | 0 | ||||
| -rw-r--r-- | src/util/make-kalman (renamed from src/make-kalman) | 4 | ||||
| -rwxr-xr-x | src/util/sirf-cksum (renamed from src/sirf-cksum) | 0 | ||||
| -rw-r--r-- | src/util/skytraq-cksum (renamed from src/skytraq-cksum) | 0 | 
170 files changed, 6860 insertions, 941 deletions
diff --git a/altosui/Altos.java b/altosui/Altos.java index e4f974f9..aa2fd77a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -498,5 +498,5 @@ public class Altos {  	public final static String bt_product_telebt = bt_product_telebt(); -//	public static AltosBTKnown bt_known = new AltosBTKnown(); +	public static AltosBTKnown bt_known = new AltosBTKnown();  } diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 7a876c25..55b8f8fc 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -42,6 +42,13 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice {  		return getAddr();  	} +	public String getErrorString() { +		altos_error	error = new altos_error(); + +		libaltos.altos_get_last_error(error); +		return String.format("%s (%d)", error.getString(), error.getCode()); +	} +  	public int getSerial() {  		String name = getName();  		if (name == null) diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index e1b6002d..a212409e 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -99,7 +99,7 @@ public class AltosCSVUI  				writer.close();  			} catch (FileNotFoundException ee) {  				JOptionPane.showMessageDialog(frame, -							      file.getName(), +							      ee.getMessage(),  							      "Cannot open file",  							      JOptionPane.ERROR_MESSAGE);  			} diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 122ebecc..93def70d 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -480,8 +480,7 @@ public class AltosConfig implements ActionListener {  				}  			} catch (FileNotFoundException ee) {  				JOptionPane.showMessageDialog(owner, -							      String.format("Cannot open device \"%s\"", -									    device.toShortString()), +							      ee.getMessage(),  							      "Cannot open target device",  							      JOptionPane.ERROR_MESSAGE);  			} catch (AltosSerialInUseException si) { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index bcb9636b..980068c0 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -52,8 +52,7 @@ public class AltosConfigureUI  	JRadioButton	serial_debug; -// BLUETOOTH -//	JButton		manage_bluetooth; +	JButton		manage_bluetooth;  	JButton		manage_frequencies;  	final static String[] font_size_names = { "Small", "Medium", "Large" }; @@ -241,19 +240,18 @@ public class AltosConfigureUI  		c.anchor = GridBagConstraints.WEST;  		pane.add(serial_debug, c); -// BLUETOOTH -//		manage_bluetooth = new JButton("Manage Bluetooth"); -//		manage_bluetooth.addActionListener(new ActionListener() { -//				public void actionPerformed(ActionEvent e) { -//					AltosBTManage.show(owner, Altos.bt_known); -//				} -//			}); -//		c.gridx = 0; -//		c.gridy = row++; -//		c.gridwidth = 2; -//		c.fill = GridBagConstraints.NONE; -//		c.anchor = GridBagConstraints.WEST; -//		pane.add(manage_bluetooth, c); +		manage_bluetooth = new JButton("Manage Bluetooth"); +		manage_bluetooth.addActionListener(new ActionListener() { +				public void actionPerformed(ActionEvent e) { +					AltosBTManage.show(owner, Altos.bt_known); +				} +			}); +		c.gridx = 0; +		c.gridy = row; +		c.gridwidth = 2; +		c.fill = GridBagConstraints.NONE; +		c.anchor = GridBagConstraints.WEST; +		pane.add(manage_bluetooth, c);  		manage_frequencies = new JButton("Manage Frequencies");  		manage_frequencies.addActionListener(new ActionListener() { @@ -262,9 +260,8 @@ public class AltosConfigureUI  				}  			});  		manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); -// BLUETOOTH -//		c.gridx = 2; -		c.gridx = 1; +		c.gridx = 2; +		c.gridx = 2;  		c.gridy = row++;  		c.gridwidth = 2;  		c.fill = GridBagConstraints.NONE; diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 15de05c2..d81ca6d1 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -61,7 +61,7 @@ public class AltosDataChooser extends JFileChooser {  				}  			} catch (FileNotFoundException fe) {  				JOptionPane.showMessageDialog(frame, -							      filename, +							      fe.getMessage(),  							      "Cannot open file",  							      JOptionPane.ERROR_MESSAGE);  			} diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java index 3357c550..1b5c1a91 100644 --- a/altosui/AltosDevice.java +++ b/altosui/AltosDevice.java @@ -26,5 +26,6 @@ public interface AltosDevice {  	public abstract int getSerial();  	public abstract String getPath();  	public abstract boolean matchProduct(int product); +	public abstract String getErrorString();  	public SWIGTYPE_p_altos_file open();  } diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index fa9587bc..610bb73e 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -30,8 +30,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {  	private JList		list;  	private JButton		cancel_button;  	private JButton		select_button; -// BLUETOOTH -//	private JButton		manage_bluetooth_button; +	private JButton		manage_bluetooth_button;  	private Frame		frame;  	private int		product; @@ -42,17 +41,15 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {  	private AltosDevice[] devices() {  		java.util.List<AltosDevice>	usb_devices = AltosUSBDevice.list(product);  		int				num_devices = usb_devices.size(); -// BLUETOOTH -//		java.util.List<AltosDevice>	bt_devices = Altos.bt_known.list(product); -//		num_devices += bt_devices.size(); +		java.util.List<AltosDevice>	bt_devices = Altos.bt_known.list(product); +		num_devices += bt_devices.size();  		AltosDevice[]			devices = new AltosDevice[num_devices];  		for (int i = 0; i < usb_devices.size(); i++)  			devices[i] = usb_devices.get(i); -// BLUETOOTH -//		int off = usb_devices.size(); -//		for (int j = 0; j < bt_devices.size(); j++) -//			devices[off + j] = bt_devices.get(j); +		int off = usb_devices.size(); +		for (int j = 0; j < bt_devices.size(); j++) +			devices[off + j] = bt_devices.get(j);  		return devices;  	} @@ -75,10 +72,9 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {  		cancel_button.setActionCommand("cancel");  		cancel_button.addActionListener(this); -// BLUETOOTH -//		manage_bluetooth_button = new JButton("Manage Bluetooth"); -//		manage_bluetooth_button.setActionCommand("manage"); -//		manage_bluetooth_button.addActionListener(this); +		manage_bluetooth_button = new JButton("Manage Bluetooth"); +		manage_bluetooth_button.setActionCommand("manage"); +		manage_bluetooth_button.addActionListener(this);  		select_button = new JButton("Select");  		select_button.setActionCommand("select"); @@ -152,8 +148,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {  		buttonPane.add(Box.createHorizontalGlue());  		buttonPane.add(cancel_button);  		buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); -// BLUETOOTH -//		buttonPane.add(manage_bluetooth_button); +		buttonPane.add(manage_bluetooth_button);  		buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));  		buttonPane.add(select_button); @@ -173,12 +168,11 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {  	public void actionPerformed(ActionEvent e) {  		if ("select".equals(e.getActionCommand()))  			value = (AltosDevice)(list.getSelectedValue()); -// BLUETOOTH -//		if ("manage".equals(e.getActionCommand())) { -//			AltosBTManage.show(frame, Altos.bt_known); -//			update_devices(); -//			return; -//		} +		if ("manage".equals(e.getActionCommand())) { +			AltosBTManage.show(frame, Altos.bt_known); +			update_devices(); +			return; +		}  		setVisible(false);  	} diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 358ad337..e7e52466 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -248,6 +248,10 @@ public class AltosEepromDownload implements Runnable {  			done = true;  	} +	void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException { +		 +	} +  	void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException {  		int			block, state_block = 0;  		int			log_format = flights.config_data.log_format; @@ -300,10 +304,10 @@ public class AltosEepromDownload implements Runnable {  				extension = "eeprom";  				CaptureTiny(eechunk);  				break; -//			case Altos.AO_LOG_FORMAT_TELEMETRY: -//				extension = "telem"; -//				CaptureTelemetry(eechunk); -//				break; +			case Altos.AO_LOG_FORMAT_TELEMETRY: +				extension = "telem"; +				CaptureTelemetry(eechunk); +				break;  			case Altos.AO_LOG_FORMAT_TELESCIENCE:  				extension = "science";  				CaptureTeleScience(eechunk); diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 2e520628..083c7372 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -219,8 +219,7 @@ public class AltosEepromManage implements ActionListener {  				t.start();  			} catch (FileNotFoundException ee) {  				JOptionPane.showMessageDialog(frame, -							      String.format("Cannot open device \"%s\"", -									    device.toShortString()), +							      ee.getMessage(),  							      "Cannot open target device",  							      JOptionPane.ERROR_MESSAGE);  			} catch (AltosSerialInUseException si) { diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 3874b500..3956ff20 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -200,8 +200,8 @@ public class AltosFlashUI  	void exception (Exception e) {  		if (e instanceof FileNotFoundException) {  			JOptionPane.showMessageDialog(frame, -						      "Cannot open image", -						      file.toString(), +						      ((FileNotFoundException) e).getMessage(), +						      "Cannot open file",  						      JOptionPane.ERROR_MESSAGE);  		} else if (e instanceof AltosSerialInUseException) {  			JOptionPane.showMessageDialog(frame, diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index c11a8614..b215c228 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -122,8 +122,7 @@ public class AltosIgniteUI  	void ignite_exception(Exception e) {  		if (e instanceof FileNotFoundException) {  			JOptionPane.showMessageDialog(owner, -						      String.format("Cannot open device \"%s\"", -								    device.toShortString()), +						      ((FileNotFoundException) e).getMessage(),  						      "Cannot open target device",  						      JOptionPane.ERROR_MESSAGE);  		} else if (e instanceof AltosSerialInUseException) { diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 50e6b542..4dd9a2dd 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -250,7 +250,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio  						FileInputStream in = new FileInputStream(file);  						records = new AltosTelemetryIterable(in);  					} else { -						throw new FileNotFoundException(); +						throw new FileNotFoundException(filename);  					}  					try {  						new AltosGraphUI(records, filename); @@ -259,7 +259,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio  					}  				} catch (FileNotFoundException fe) {  					JOptionPane.showMessageDialog(null, -								      filename, +								      fe.getMessage(),  								      "Cannot open file",  								      JOptionPane.ERROR_MESSAGE);  				} diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java new file mode 100644 index 00000000..77f681b8 --- /dev/null +++ b/altosui/AltosLaunch.java @@ -0,0 +1,201 @@ +/* + * 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. + */ + +package altosui; + +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.*; + +public class AltosLaunch { +	AltosDevice	device; +	AltosSerial	serial; +	boolean		serial_started; +	int		launcher_serial; +	int		launcher_channel; +	int		rssi; + +	final static int	Unknown = -1; +	final static int	Good = 0; +	final static int	Bad = 1; + +	int		armed; +	int		igniter; + +	private void start_serial() throws InterruptedException { +		serial_started = true; +	} + +	private void stop_serial() throws InterruptedException { +		if (!serial_started) +			return; +		serial_started = false; +		if (serial == null) +			return; +	} + +	class string_ref { +		String	value; + +		public String get() { +			return value; +		} +		public void set(String i) { +			value = i; +		} +		public string_ref() { +			value = null; +		} +	} + +	private boolean get_string(String line, String label, string_ref s) { +		if (line.startsWith(label)) { +			String	quoted = line.substring(label.length()).trim(); + +			if (quoted.startsWith("\"")) +				quoted = quoted.substring(1); +			if (quoted.endsWith("\"")) +				quoted = quoted.substring(0,quoted.length()-1); +			s.set(quoted); +			return true; +		} else { +			return false; +		} +	} + +	public boolean status() throws InterruptedException, TimeoutException { +		boolean ok = false; +		if (serial == null) +			return false; +		string_ref status_name = new string_ref(); +		start_serial(); +		serial.printf("l %d %d\n", launcher_serial, launcher_channel); +		for (;;) { +			String line = serial.get_reply(20000); +			if (line == null) +				throw new TimeoutException(); +			if (get_string(line, "Rssi: ", status_name)) { +				try { +					rssi = Altos.fromdec(status_name.get()); +				} catch (NumberFormatException ne) { +				} +				break; +			} else if (get_string(line, "Armed: ", status_name)) { +				armed = Good; +				String status = status_name.get(); +				if (status.startsWith("igniter good")) +					igniter = Good; +				else if (status.startsWith("igniter bad")) +					igniter = Bad; +				else +					igniter = Unknown; +				ok = true; +			} else if (get_string(line, "Disarmed: ", status_name)) { +				armed = Bad; +				if (status_name.get().startsWith("igniter good")) +					igniter = Good; +				else if (status_name.get().startsWith("igniter bad")) +					igniter = Bad; +				else +					igniter = Unknown; +				ok = true; +			} else if (get_string(line, "Error ", status_name)) { +				armed = Unknown; +				igniter = Unknown; +				ok = false; +				break; +			} +		} +		stop_serial(); +		if (!ok) { +			armed = Unknown; +			igniter = Unknown; +		} +		return ok; +	} + +	public static String status_string(int status) { +		switch (status) { +		case Good: +			return "good"; +		case Bad: +			return "open"; +		} +		return "unknown"; +	} + +	public void arm() { +		if (serial == null) +			return; +		try { +			start_serial(); +			serial.printf("a %d %d\n", launcher_serial, launcher_channel); +			serial.flush_output(); +		} catch (InterruptedException ie) { +		} finally { +			try { +				stop_serial(); +			} catch (InterruptedException ie) { +			} +		} +	} + +	public void fire() { +		if (serial == null) +			return; +		try { +			start_serial(); +			serial.printf("i %d %d\n", launcher_serial, launcher_channel); +			serial.flush_output(); +		} catch (InterruptedException ie) { +		} finally { +			try { +				stop_serial(); +			} catch (InterruptedException ie) { +			} +		} +	} + +	public void close() { +		try { +			stop_serial(); +		} catch (InterruptedException ie) { +		} +		serial.close(); +		serial = null; +	} + +	public void set_frame(Frame frame) { +		serial.set_frame(frame); +	} + +	public void set_remote(int in_serial, int in_channel) { +		launcher_serial = in_serial; +		launcher_channel = in_channel; +	} + +	public AltosLaunch(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + +		device = in_device; +		serial = new AltosSerial(device); +	} +}
\ No newline at end of file diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java new file mode 100644 index 00000000..47365e03 --- /dev/null +++ b/altosui/AltosLaunchUI.java @@ -0,0 +1,517 @@ +/* + * 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. + */ + +package altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +class FireButton extends JButton { +	protected void processMouseEvent(MouseEvent e) { +		super.processMouseEvent(e); +		switch (e.getID()) { +		case MouseEvent.MOUSE_PRESSED: +			if (actionListener != null) +				actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_down")); +			break; +		case MouseEvent.MOUSE_RELEASED: +			if (actionListener != null) +				actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_up")); +			break; +		} +	} + +	public FireButton(String s) { +		super(s); +	} +} + +public class AltosLaunchUI +	extends JDialog +	implements ActionListener +{ +	AltosDevice	device; +	JFrame		owner; +	JLabel		label; + +	int		radio_channel; +	JLabel		radio_channel_label; +	JTextField	radio_channel_text; + +	int		launcher_serial; +	JLabel		launcher_serial_label; +	JTextField	launcher_serial_text; + +	int		launcher_channel; +	JLabel		launcher_channel_label; +	JTextField	launcher_channel_text; + +	JLabel		armed_label; +	JLabel		armed_status_label; +	JLabel		igniter; +	JLabel		igniter_status_label; +	JToggleButton	arm; +	FireButton	fire; +	javax.swing.Timer	arm_timer; +	javax.swing.Timer	fire_timer; + +	boolean		firing; +	boolean		armed; +	int		armed_status; +	int		igniter_status; +	int		rssi; + +	final static int	arm_timeout = 1 * 1000; +	final static int	fire_timeout = 250; + +	int		armed_count; + +	LinkedBlockingQueue<String>	command_queue; + +	class LaunchHandler implements Runnable { +		AltosLaunch	launch; +		JFrame		owner; + +		void send_exception(Exception e) { +			final Exception	f_e = e; +			Runnable r = new Runnable() { +					public void run() { +						launch_exception(f_e); +					} +				}; +			SwingUtilities.invokeLater(r); +		} + +		public void run () { +			try { +				launch = new AltosLaunch(device); +			} catch (Exception e) { +				send_exception(e); +				return; +			} +			launch.set_frame(owner); +			launch.set_remote(launcher_serial, launcher_channel); + +			for (;;) { +				Runnable	r; + +				try { +					String		command = command_queue.take(); +					String		reply = null; + +					if (command.equals("get_status")) { +						launch.status(); +						reply = "status"; +						armed_status = launch.armed; +						igniter_status = launch.igniter; +						rssi = launch.rssi; +					} else if (command.equals("set_remote")) { +						launch.set_remote(launcher_serial, launcher_channel); +						reply = "remote set"; +					} else if (command.equals("arm")) { +						launch.arm(); +						reply = "armed"; +					} else if (command.equals("fire")) { +						launch.fire(); +						reply = "fired"; +					} else if (command.equals("quit")) { +						launch.close(); +						break; +					} else { +						throw new ParseException(String.format("invalid command %s", command), 0); +					} +					final String f_reply = reply; +					r = new Runnable() { +							public void run() { +								launch_reply(f_reply); +							} +						}; +					SwingUtilities.invokeLater(r); +				} catch (Exception e) { +					send_exception(e); +				} +			} +		} + +		public LaunchHandler(JFrame in_owner) { +			owner = in_owner; +		} +	} + +	void launch_exception(Exception e) { +		if (e instanceof FileNotFoundException) { +			JOptionPane.showMessageDialog(owner, +						      ((FileNotFoundException) e).getMessage(), +						      "Cannot open target device", +						      JOptionPane.ERROR_MESSAGE); +		} else if (e instanceof AltosSerialInUseException) { +			JOptionPane.showMessageDialog(owner, +						      String.format("Device \"%s\" already in use", +								    device.toShortString()), +						      "Device in use", +						      JOptionPane.ERROR_MESSAGE); +		} else if (e instanceof IOException) { +			IOException ee = (IOException) e; +			JOptionPane.showMessageDialog(owner, +						      device.toShortString(), +						      ee.getLocalizedMessage(), +						      JOptionPane.ERROR_MESSAGE); +		} else { +			JOptionPane.showMessageDialog(owner, +						      String.format("Connection to \"%s\" failed", +								    device.toShortString()), +						      "Connection Failed", +						      JOptionPane.ERROR_MESSAGE); +		} +		close(); +	} + +	void launch_reply(String reply) { +		if (reply == null) +			return; +		if (reply.equals("remote set")) +			poll_launch_status(); +		if (reply.equals("status")) { +			set_launch_status(); +		} +	} + +	void set_arm_text() { +		if (arm.isSelected()) +			arm.setText(String.format("%d", armed_count)); +		else +			arm.setText("Arm"); +	} + +	void start_arm_timer() { +		armed_count = 30; +		set_arm_text(); +	} + +	void stop_arm_timer() { +		armed_count = 0; +		armed = false; +		arm.setSelected(false); +		fire.setEnabled(false); +		set_arm_text(); +	} + +	void cancel () { +		fire.setEnabled(false); +		firing = false; +		stop_arm_timer(); +	} + +	void send_command(String command) { +		try { +			command_queue.put(command); +		} catch (Exception ex) { +			launch_exception(ex); +		} +	} + +	boolean	getting_status = false; + +	void set_launch_status() { +		getting_status = false; +		armed_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(armed_status))); +		igniter_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(igniter_status))); +	} + +	void poll_launch_status() { +		if (!getting_status && !firing && !armed) { +			getting_status = true; +			send_command("get_status"); +		} +	} + +	void fired() { +		firing = false; +		cancel(); +	} + +	void close() { +		send_command("quit"); +		arm_timer.stop(); +		setVisible(false); +		dispose(); +	} + +	void tick_arm_timer() { +		if (armed_count > 0) { +			--armed_count; +			if (armed_count <= 0) { +				armed_count = 0; +				cancel(); +			} else { +				if (!firing) { +					send_command("arm"); +					set_arm_text(); +				} +			} +		} +		poll_launch_status(); +	} + +	void arm() { +		if (arm.isSelected()) { +			fire.setEnabled(true); +			start_arm_timer(); +			if (!firing) +				send_command("arm"); +			armed = true; +		} else +			cancel(); +	} + +	void fire_more() { +		if (firing) +			send_command("fire"); +	} + +	void fire_down() { +		if (arm.isEnabled() && arm.isSelected() && armed_count > 0) { +			firing = true; +			fire_more(); +			fire_timer.restart(); +		} +	} + +	void fire_up() { +		firing = false; +		fire_timer.stop(); +	} + +	void set_radio() { +		try { +			radio_channel = Integer.parseInt(radio_channel_text.getText()); +		} catch (NumberFormatException ne) { +			radio_channel_text.setText(String.format("%d", radio_channel)); +		} +	} + +	void set_serial() { +		try { +			launcher_serial = Integer.parseInt(launcher_serial_text.getText()); +			AltosPreferences.set_launcher_serial(launcher_serial); +			send_command("set_remote"); +		} catch (NumberFormatException ne) { +			launcher_serial_text.setText(String.format("%d", launcher_serial)); +		} +	} + +	void set_channel() { +		try { +			launcher_channel = Integer.parseInt(launcher_channel_text.getText()); +			AltosPreferences.set_launcher_serial(launcher_channel); +			send_command("set_remote"); +		} catch (NumberFormatException ne) { +			launcher_channel_text.setText(String.format("%d", launcher_channel)); +		} +	} + +	public void actionPerformed(ActionEvent e) { +		String cmd = e.getActionCommand(); +		System.out.printf("cmd %s\n", cmd); +		if (cmd.equals("armed") || cmd.equals("igniter")) { +			stop_arm_timer(); +		} + +		if (cmd.equals("arm")) +			arm(); +		if (cmd.equals("tick_arm")) +			tick_arm_timer(); +		if (cmd.equals("close")) +			close(); +		if (cmd.equals("fire_down")) +			fire_down(); +		if (cmd.equals("fire_up")) +			fire_up(); +		if (cmd.equals("tick_fire")) +			fire_more(); +		if (cmd.equals("new_serial")) +			set_serial(); +		if (cmd.equals("new_channel")) +			set_channel(); +	} + +	/* A window listener to catch closing events and tell the config code */ +	class ConfigListener extends WindowAdapter { +		AltosLaunchUI	ui; + +		public ConfigListener(AltosLaunchUI this_ui) { +			ui = this_ui; +		} + +		public void windowClosing(WindowEvent e) { +			ui.actionPerformed(new ActionEvent(e.getSource(), +							   ActionEvent.ACTION_PERFORMED, +							   "close")); +		} +	} + +	private boolean open() { +		command_queue = new LinkedBlockingQueue<String>(); + +		device = AltosDeviceDialog.show(owner, Altos.product_any); +		if (device != null) { +				LaunchHandler	handler = new LaunchHandler(owner); +				Thread		t = new Thread(handler); +				t.start(); +				return true; +		} +		return false; +	} + +	public AltosLaunchUI(JFrame in_owner) { + +		launcher_channel = AltosPreferences.launcher_channel(); +		launcher_serial = AltosPreferences.launcher_serial(); +		owner = in_owner; +		armed_status = AltosLaunch.Unknown; +		igniter_status = AltosLaunch.Unknown; + +		if (!open()) +			return; + +		Container		pane = getContentPane(); +		GridBagConstraints	c = new GridBagConstraints(); +		Insets			i = new Insets(4,4,4,4); + +		arm_timer = new javax.swing.Timer(arm_timeout, this); +		arm_timer.setActionCommand("tick_arm"); +		arm_timer.restart(); + +		fire_timer = new javax.swing.Timer(fire_timeout, this); +		fire_timer.setActionCommand("tick_fire"); + +		owner = in_owner; + +		pane.setLayout(new GridBagLayout()); + +		c.fill = GridBagConstraints.NONE; +		c.anchor = GridBagConstraints.CENTER; +		c.insets = i; +		c.weightx = 1; +		c.weighty = 1; + +		c.gridx = 0; +		c.gridy = 0; +		c.gridwidth = 2; +		c.anchor = GridBagConstraints.CENTER; +		label = new JLabel ("Launch Controller"); +		pane.add(label, c); + +		c.gridx = 0; +		c.gridy = 1; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		launcher_serial_label = new JLabel("Launcher Serial"); +		pane.add(launcher_serial_label, c); + +		c.gridx = 1; +		c.gridy = 1; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		launcher_serial_text = new JTextField(7); +		launcher_serial_text.setText(String.format("%d", launcher_serial)); +		launcher_serial_text.setActionCommand("new_serial"); +		launcher_serial_text.addActionListener(this); +		pane.add(launcher_serial_text, c); + +		c.gridx = 0; +		c.gridy = 2; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		launcher_channel_label = new JLabel("Launcher Channel"); +		pane.add(launcher_channel_label, c); + +		c.gridx = 1; +		c.gridy = 2; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		launcher_channel_text = new JTextField(7); +		launcher_channel_text.setText(String.format("%d", launcher_channel)); +		launcher_channel_text.setActionCommand("new_channel"); +		launcher_channel_text.addActionListener(this); +		pane.add(launcher_channel_text, c); + +		c.gridx = 0; +		c.gridy = 3; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		armed_label = new JLabel ("Armed"); +		pane.add(armed_label, c); + +		c.gridx = 1; +		c.gridy = 3; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		armed_status_label = new JLabel(); +		pane.add(armed_status_label, c); + +		c.gridx = 0; +		c.gridy = 4; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		igniter = new JLabel ("Igniter"); +		pane.add(igniter, c); + +		c.gridx = 1; +		c.gridy = 4; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.WEST; +		igniter_status_label = new JLabel(); +		pane.add(igniter_status_label, c); + +		c.gridx = 0; +		c.gridy = 5; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.CENTER; +		arm = new JToggleButton ("Arm"); +		pane.add(arm, c); +		arm.addActionListener(this); +		arm.setActionCommand("arm"); +		arm.setEnabled(true); + +		c.gridx = 1; +		c.gridy = 5; +		c.gridwidth = 1; +		c.anchor = GridBagConstraints.CENTER; +		fire = new FireButton ("Fire"); +		fire.setEnabled(false); +		pane.add(fire, c); +		fire.addActionListener(this); +		fire.setActionCommand("fire"); + +		pack(); +		setLocationRelativeTo(owner); + +		addWindowListener(new ConfigListener(this)); + +		setVisible(true); +	} +}
\ No newline at end of file diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 716559ab..48aed441 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -58,6 +58,12 @@ class AltosPreferences {  	/* font size preferences name */  	final static String fontSizePreference = "FONT-SIZE"; +	/* Launcher serial preference name */ +	final static String launcherSerialPreference = "LAUNCHER-SERIAL"; + +	/* Launcher channel prefernce name */ +	final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; +	  	/* Default logdir is ~/TeleMetrum */  	final static String logdirName = "TeleMetrum"; @@ -143,6 +149,9 @@ class AltosPreferences {  			node.put(String.format(description_format, i), frequencies[i].description);  		}  	} +	static int launcher_serial; + +	static int launcher_channel;  	public static void init() {  		preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -176,6 +185,10 @@ class AltosPreferences {  		font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium);  		Altos.set_fonts(font_size); +		launcher_serial = preferences.getInt(launcherSerialPreference, 0); + +		launcher_channel = preferences.getInt(launcherChannelPreference, 0); +  		String firmwaredir_string = preferences.get(firmwaredirPreference, null);  		if (firmwaredir_string != null)  			firmwaredir = new File(firmwaredir_string); @@ -390,6 +403,32 @@ class AltosPreferences {  		return serial_debug;  	} +	public static void set_launcher_serial(int new_launcher_serial) { +		launcher_serial = new_launcher_serial; +		System.out.printf("set launcher serial to %d\n", new_launcher_serial); +		synchronized (preferences) { +			preferences.putInt(launcherSerialPreference, launcher_serial); +			flush_preferences(); +		} +	} + +	public static int launcher_serial() { +		return launcher_serial; +	} + +	public static void set_launcher_channel(int new_launcher_channel) { +		launcher_channel = new_launcher_channel; +		System.out.printf("set launcher channel to %d\n", new_launcher_channel); +		synchronized (preferences) { +			preferences.putInt(launcherChannelPreference, launcher_channel); +			flush_preferences(); +		} +	} + +	public static int launcher_channel() { +		return launcher_channel; +	} +	  	public static Preferences bt_devices() {  		return preferences.node("bt_devices");  	} diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index bce4b32c..df5c51d4 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -130,8 +130,7 @@ public class AltosScanUI  	void scan_exception(Exception e) {  		if (e instanceof FileNotFoundException) {  			JOptionPane.showMessageDialog(owner, -						      String.format("Cannot open device \"%s\"", -								    device.toShortString()), +						      ((FileNotFoundException) e).getMessage(),  						      "Cannot open target device",  						      JOptionPane.ERROR_MESSAGE);  		} else if (e instanceof AltosSerialInUseException) { @@ -326,8 +325,7 @@ public class AltosScanUI  			return true;  		} catch (FileNotFoundException ee) {  			JOptionPane.showMessageDialog(owner, -						      String.format("Cannot open device \"%s\"", -								    device.toShortString()), +						      ee.getMessage(),  						      "Cannot open target device",  						      JOptionPane.ERROR_MESSAGE);  		} catch (AltosSerialInUseException si) { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 0a531aa9..4cf306d0 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -323,8 +323,10 @@ public class AltosSerial implements Runnable {  		}  		altos = device.open();  		if (altos == null) { +			final String	message = device.getErrorString();  			close(); -			throw new FileNotFoundException(device.toShortString()); +			throw new FileNotFoundException(String.format("%s (%s)", +								      device.toShortString(), message));  		}  		if (debug)  			System.out.printf("Open %s\n", device.getPath()); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 27c41838..3e5bcf43 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -52,8 +52,7 @@ public class AltosUI extends JFrame {  				new AltosFlightUI(voice, reader, device.getSerial());  		} catch (FileNotFoundException ee) {  			JOptionPane.showMessageDialog(AltosUI.this, -						      String.format("Cannot open device \"%s\"", -								    device.toShortString()), +						      ee.getMessage(),  						      "Cannot open target device",  						      JOptionPane.ERROR_MESSAGE);  		} catch (AltosSerialInUseException si) { @@ -210,6 +209,13 @@ public class AltosUI extends JFrame {  			});  		b.setToolTipText("Check flight readiness of altimeter in idle mode"); +		b = addButton(3, 2, "Launch Controller"); +		b.addActionListener(new ActionListener() { +				public void actionPerformed(ActionEvent e) { +					LaunchController(); +				} +			}); +  		setTitle("AltOS");  		pane.doLayout(); @@ -272,6 +278,10 @@ public class AltosUI extends JFrame {  		new AltosSiteMapPreload(AltosUI.this);  	} +	void LaunchController() { +		new AltosLaunchUI(AltosUI.this); +	} +  	/*  	 * Replay a flight from telemetry data  	 */ @@ -345,7 +355,7 @@ public class AltosUI extends JFrame {  			else  				return new AltosTelemetryIterable(in);  		} catch (FileNotFoundException fe) { -			System.out.printf("Cannot open '%s'\n", filename); +			System.out.printf("%s\n", fe.getMessage());  			return null;  		}  	} @@ -355,7 +365,7 @@ public class AltosUI extends JFrame {  		try {  			return new AltosCSV(file);  		} catch (FileNotFoundException fe) { -			System.out.printf("Cannot open '%s'\n", filename); +			System.out.printf("%s\n", fe.getMessage());  			return null;  		}  	} @@ -365,7 +375,7 @@ public class AltosUI extends JFrame {  		try {  			return new AltosKML(file);  		} catch (FileNotFoundException fe) { -			System.out.printf("Cannot open '%s'\n", filename); +			System.out.printf("%s\n", fe.getMessage());  			return null;  		}  	} diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index dc746a64..b11a3934 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -39,6 +39,13 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {  	} +	public String getErrorString() { +		altos_error	error = new altos_error(); + +		libaltos.altos_get_last_error(error); +		return String.format("%s (%d)", error.getString(), error.getCode()); +	} +  	public SWIGTYPE_p_altos_file open() {  		return libaltos.altos_open(this);  	} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index ba1c830c..c4d1e611 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -68,6 +68,8 @@ altosui_JAVA = \  	AltosIdleMonitorUI.java \  	AltosIgnite.java \  	AltosIgniteUI.java \ +	AltosLaunch.java \ +	AltosLaunchUI.java \  	AltosInfoTable.java \  	AltosKML.java \  	AltosLanded.java \ @@ -116,7 +118,8 @@ altosui_JAVA = \  	AltosGraphUI.java \  	AltosDataChooser.java \  	AltosVersion.java \ -	AltosVoice.java +	AltosVoice.java \ +	$(altosui_BT)  JFREECHART_CLASS= \      jfreechart.jar diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index d1f445bd..48e00a44 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -49,6 +49,22 @@ altos_fini(void)  {  } +static struct altos_error last_error; + +static void +altos_set_last_error(int code, char *string) +{ +	last_error.code = code; +	strncpy(last_error.string, string, sizeof (last_error.string) -1); +	last_error.string[sizeof(last_error.string)-1] = '\0'; +} + +PUBLIC void +altos_get_last_error(struct altos_error *error) +{ +	*error = last_error; +} +  #ifdef DARWIN  #undef USE_POLL @@ -96,6 +112,12 @@ struct altos_file {  	int				in_read;  }; +static void +altos_set_last_posix_error(void) +{ +	altos_set_last_error(errno, strerror(errno)); +} +  PUBLIC struct altos_file *  altos_open(struct altos_device *device)  { @@ -103,12 +125,18 @@ altos_open(struct altos_device *device)  	int			ret;  	struct termios		term; -	if (!file) +	if (!file) { +		altos_set_last_posix_error();  		return NULL; +	} + +//	altos_set_last_error(12, "yeah yeah, failed again"); +//	free(file); +//	return NULL;  	file->fd = open(device->path, O_RDWR | O_NOCTTY);  	if (file->fd < 0) { -		perror(device->path); +		altos_set_last_posix_error();  		free(file);  		return NULL;  	} @@ -117,7 +145,7 @@ altos_open(struct altos_device *device)  #else  	file->out_fd = open(device->path, O_RDWR | O_NOCTTY);  	if (file->out_fd < 0) { -		perror(device->path); +		altos_set_last_posix_error();  		close(file->fd);  		free(file);  		return NULL; @@ -125,7 +153,7 @@ altos_open(struct altos_device *device)  #endif  	ret = tcgetattr(file->fd, &term);  	if (ret < 0) { -		perror("tcgetattr"); +		altos_set_last_posix_error();  		close(file->fd);  #ifndef USE_POLL  		close(file->out_fd); @@ -143,7 +171,7 @@ altos_open(struct altos_device *device)  #endif  	ret = tcsetattr(file->fd, TCSAFLUSH, &term);  	if (ret < 0) { -		perror("tcsetattr"); +		altos_set_last_posix_error();  		close(file->fd);  #ifndef USE_POLL  		close(file->out_fd); @@ -195,8 +223,10 @@ altos_flush(struct altos_file *file)  #else  		ret = write (file->out_fd, file->out_data, file->out_used);  #endif -		if (ret < 0) +		if (ret < 0) { +			altos_set_last_posix_error();  			return -errno; +		}  		if (ret) {  			memmove(file->out_data, file->out_data + ret,  				file->out_used - ret); @@ -248,7 +278,7 @@ altos_fill(struct altos_file *file, int timeout)  		fd[1].events = POLLIN;  		ret = poll(fd, 2, timeout);  		if (ret < 0) { -			perror("altos_getchar"); +			altos_set_last_posix_error();  			return LIBALTOS_ERROR;  		}  		if (ret == 0) @@ -261,7 +291,7 @@ altos_fill(struct altos_file *file, int timeout)  		{  			ret = read(file->fd, file->in_data, USB_BUF_SIZE);  			if (ret < 0) { -				perror("altos_getchar"); +				altos_set_last_posix_error();  				return LIBALTOS_ERROR;  			}  			file->in_read = 0; @@ -598,7 +628,6 @@ altos_list_finish(struct altos_list *usbdevs)  	free(usbdevs);  } -#if HAS_BLUETOOTH  struct altos_bt_list {  	inquiry_info	*ii;  	int		sock; @@ -701,8 +730,10 @@ altos_bt_open(struct altos_bt_device *device)  	if (!file)  		goto no_file;  	file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); -	if (file->fd < 0) +	if (file->fd < 0) { +		altos_set_last_posix_error();  		goto no_sock; +	}  	addr.rc_family = AF_BLUETOOTH;  	addr.rc_channel = 1; @@ -712,7 +743,7 @@ altos_bt_open(struct altos_bt_device *device)  			 (struct sockaddr *)&addr,  			 sizeof(addr));  	if (status < 0) { -		perror("connect"); +		altos_set_last_posix_error();  		goto no_link;  	}  	sleep(1); @@ -730,7 +761,6 @@ no_sock:  no_file:  	return NULL;  } -#endif /* HAS_BLUETOOTH */  #endif @@ -844,6 +874,48 @@ altos_list_finish(struct altos_list *list)  	free(list);  } +struct altos_bt_list { +	int		sock; +	int		dev_id; +	int		rsp; +	int		num_rsp; +}; + +#define INQUIRY_MAX_RSP	255 + +struct altos_bt_list * +altos_bt_list_start(int inquiry_time) +{ +	return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, +		   struct altos_bt_device *device) +{ +	return 0; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ +} + +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ +	strncpy(device->name, name, sizeof (device->name)); +	device->name[sizeof(device->name)-1] = '\0'; +	strncpy(device->addr, addr, sizeof (device->addr)); +	device->addr[sizeof(device->addr)-1] = '\0'; +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ +	return NULL; +} +  #endif @@ -872,6 +944,21 @@ struct altos_file {  	OVERLAPPED			ov_write;  }; +static void +altos_set_last_windows_error(void) +{ +	DWORD	error = GetLastError(); +	TCHAR	message[1024]; +	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, +		      0, +		      error, +		      0, +		      message, +		      sizeof (message) / sizeof (TCHAR), +		      NULL); +	altos_set_last_error(error, message); +} +  PUBLIC struct altos_list *  altos_list_start(void)  { @@ -882,7 +969,7 @@ altos_list_start(void)  	list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,  					     DIGCF_ALLCLASSES|DIGCF_PRESENT);  	if (list->dev_info == INVALID_HANDLE_VALUE) { -		printf("SetupDiGetClassDevs failed %ld\n", GetLastError()); +		altos_set_last_windows_error();  		free(list);  		return NULL;  	} @@ -916,6 +1003,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)  					       DICS_FLAG_GLOBAL, 0, DIREG_DEV,  					       KEY_READ);  		if (dev_key == INVALID_HANDLE_VALUE) { +			altos_set_last_windows_error();  			printf("cannot open device registry key\n");  			continue;  		} @@ -926,6 +1014,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)  		result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,  					 symbolic, &symbolic_len);  		if (result != 0) { +			altos_set_last_windows_error();  			printf("cannot find SymbolicName value\n");  			RegCloseKey(dev_key);  			continue; @@ -948,6 +1037,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)  					 port, &port_len);  		RegCloseKey(dev_key);  		if (result != 0) { +			altos_set_last_windows_error();  			printf("failed to get PortName\n");  			continue;  		} @@ -963,6 +1053,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device)  						     sizeof(friendlyname),  						     &friendlyname_len))  		{ +			altos_set_last_windows_error();  			printf("Failed to get friendlyname\n");  			continue;  		} @@ -975,8 +1066,10 @@ altos_list_next(struct altos_list *list, struct altos_device *device)  		return 1;  	}  	result = GetLastError(); -	if (result != ERROR_NO_MORE_ITEMS) +	if (result != ERROR_NO_MORE_ITEMS) { +		altos_set_last_windows_error();  		printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); +	}  	return 0;  } @@ -995,8 +1088,10 @@ altos_queue_read(struct altos_file *file)  		return LIBALTOS_SUCCESS;  	if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { -		if (GetLastError() != ERROR_IO_PENDING) +		if (GetLastError() != ERROR_IO_PENDING) { +			altos_set_last_windows_error();  			return LIBALTOS_ERROR; +		}  		file->pend_read = TRUE;  	} else {  		file->pend_read = FALSE; @@ -1021,8 +1116,10 @@ altos_wait_read(struct altos_file *file, int timeout)  	ret = WaitForSingleObject(file->ov_read.hEvent, timeout);  	switch (ret) {  	case WAIT_OBJECT_0: -		if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) +		if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) { +			altos_set_last_windows_error();  			return LIBALTOS_ERROR; +		}  		file->pend_read = FALSE;  		file->in_read = 0;  		file->in_used = got; @@ -1066,15 +1163,20 @@ altos_flush(struct altos_file *file)  	while (used) {  		if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { -			if (GetLastError() != ERROR_IO_PENDING) +			if (GetLastError() != ERROR_IO_PENDING) { +				altos_set_last_windows_error();  				return LIBALTOS_ERROR; +			}  			ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);  			switch (ret) {  			case WAIT_OBJECT_0: -				if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) +				if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) { +					altos_set_last_windows_error();  					return LIBALTOS_ERROR; +				}  				break;  			default: +				altos_set_last_windows_error();  				return LIBALTOS_ERROR;  			}  		} @@ -1102,6 +1204,7 @@ altos_open(struct altos_device *device)  				  0, NULL, OPEN_EXISTING,  				  FILE_FLAG_OVERLAPPED, NULL);  	if (file->handle == INVALID_HANDLE_VALUE) { +		altos_set_last_windows_error();  		free(file);  		return NULL;  	} @@ -1117,6 +1220,7 @@ altos_open(struct altos_device *device)  	dcbSerialParams.DCBlength = sizeof(dcbSerialParams);  	if (!GetCommState(file->handle, &dcbSerialParams)) { +		altos_set_last_windows_error();  		CloseHandle(file->handle);  		free(file);  		return NULL; @@ -1126,6 +1230,7 @@ altos_open(struct altos_device *device)  	dcbSerialParams.StopBits = ONESTOPBIT;  	dcbSerialParams.Parity = NOPARITY;  	if (!SetCommState(file->handle, &dcbSerialParams)) { +		altos_set_last_windows_error();  		CloseHandle(file->handle);  		free(file);  		return NULL; @@ -1180,4 +1285,38 @@ altos_getchar(struct altos_file *file, int timeout)  	return file->in_data[file->in_read++];  } +struct altos_bt_list * +altos_bt_list_start(int inquiry_time) +{ +	return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, +		   struct altos_bt_device *device) +{ +	return 0; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ +	free(bt_list); +} + +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ +	strncpy(device->name, name, sizeof (device->name)); +	device->name[sizeof(device->name)-1] = '\0'; +	strncpy(device->addr, addr, sizeof (device->addr)); +	device->addr[sizeof(device->addr)-1] = '\0'; +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ +	return NULL; +} +  #endif diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 363a84fd..f90fbb87 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -51,6 +51,11 @@ struct altos_bt_device {  	//%mutable;  }; +struct altos_error { +	int				code; +	char				string[1024]; +}; +  #define LIBALTOS_SUCCESS	0  #define LIBALTOS_ERROR		-1  #define LIBALTOS_TIMEOUT	-2 @@ -62,6 +67,9 @@ altos_init(void);  PUBLIC void  altos_fini(void); +PUBLIC void +altos_get_last_error(struct altos_error *error); +  PUBLIC struct altos_list *  altos_list_start(void); @@ -93,9 +101,6 @@ altos_flush(struct altos_file *file);  PUBLIC int  altos_getchar(struct altos_file *file, int timeout); -// #define HAS_BLUETOOTH 1 -#if HAS_BLUETOOTH -  PUBLIC struct altos_bt_list *  altos_bt_list_start(int inquiry_time); @@ -111,6 +116,4 @@ altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device);  PUBLIC struct altos_file *  altos_bt_open(struct altos_bt_device *device); -#endif -  #endif /* _LIBALTOS_H_ */ diff --git a/configure.ac b/configure.ac index 27d56751..959f3b4d 100644 --- a/configure.ac +++ b/configure.ac @@ -18,8 +18,8 @@ dnl  dnl Process this file with autoconf to create configure.  AC_PREREQ(2.57) -AC_INIT([altos], 1.0.1) -AC_CONFIG_SRCDIR([src/ao.h]) +AC_INIT([altos], 1.0.9.0) +AC_CONFIG_SRCDIR([src/core/ao.h])  AM_INIT_AUTOMAKE([foreign dist-bzip2])  AM_MAINTAINER_MODE diff --git a/src/Makefile b/src/Makefile index 018f0c5c..5da7c855 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,13 @@  # AltOS build  #  # -CC=sdcc + +vpath make-altitude util +vpath make-kalman util +vpath kalman.5c kalman +vpath kalman_filter.5c kalman +vpath load_csv.5c kalman +vpath matrix.5c kalman  include Version @@ -12,9 +18,10 @@ SUBDIRS=\  	telemini-v1.0 telenano-v0.1 \  	telebt-v0.0 telebt-v0.1 \  	telemetrum-v0.1-sky telemetrum-v0.1-sirf \ -	tidongle test +	telelaunch-v0.1 \ +	tidongle test telescience-v0.1 telepyro-v0.1 -all: all-recursive +all: all-local all-recursive  RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive @@ -27,8 +34,21 @@ $(RECURSIVE_TARGETS):  distclean:	clean -clean: clean-recursive +clean: clean-local clean-recursive  install: install-recursive  uninstall: + +all-recursive: all-local + +all-local: altitude.h ao_kalman.h + +altitude.h: make-altitude +	nickle $< > $@ + +ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c +	bash $< kalman > $@ + +clean-local: +	rm -f altitude.h ao_kalman.h diff --git a/src/Makefile.proto b/src/Makefile.proto deleted file mode 100644 index 8f98d354..00000000 --- a/src/Makefile.proto +++ /dev/null @@ -1,380 +0,0 @@ -# -# AltOS build -# -# -vpath %.c .. -vpath %.h .. -vpath make-altitude .. -vpath make-kalman .. -vpath kalman.5c ../kalman -vpath kalman_filter.5c ../kalman -vpath load_csv.5c ../kalman -vpath matrix.5c ../kalman -vpath ao-make-product.5c .. - -CC=sdcc - -ifndef VERSION -include ../Version -endif - -CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) - -CODESIZE ?= 0x8000 - -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ -	--xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff - -INC = \ -	ao.h \ -	ao_pins.h \ -	cc1111.h \ -	altitude.h \ -	ao_kalman.h \ -	25lc1024.h - -# -# Common AltOS sources -# -ALTOS_SRC = \ -	ao_cmd.c \ -	ao_dma.c \ -	ao_mutex.c \ -	ao_panic.c \ -	ao_task.c \ -	ao_timer.c \ -	ao_romconfig.c \ -	_bp.c - -# -# Shared AltOS drivers -# -ALTOS_DRIVER_SRC = \ -	ao_config.c \ -	ao_led.c \ -	ao_radio.c \ -	ao_stdio.c - -BEEP_DRIVER_SRC = \ -	ao_beep.c - -USB_DRIVER_SRC = \ -	ao_usb.c - -TELE_COMMON_SRC = \ -	ao_packet.c - -# -# Receiver code -# -TELE_RECEIVER_SRC =\ -	ao_monitor.c \ -	ao_gps_print.c \ -	ao_packet_master.c \ -	ao_state.c \ -	ao_rssi.c - -# -# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) -# - -TELE_DRIVER_SRC = \ -	ao_convert.c - -# -# Serial port driver -# -SERIAL_DRIVER_SRC = \ -	ao_serial.c - -# -# Spi bus driver -# -SPI_DRIVER_SRC = \ -	ao_spi.c - -# -# Debug dongle driver (only on TI) -# -DBG_SRC = \ -	ao_dbg.c - -# -# Drivers only on TeleMetrum -# -TM_DRIVER_SRC = \ -	ao_adc.c \ -	ao_gps_report.c \ -	ao_ignite.c \ -	ao_packet_slave.c \ -	$(BEEP_DRIVER_SRC) \ -	$(USB_DRIVER_SRC) - -# -# 25LC1024 driver source -EE_DRIVER_SRC = \ -	ao_storage.c \ -	ao_ee.c - -# -# AT45DB161D driver source - -FLASH_DRIVER_SRC = \ -	ao_storage.c \ -	ao_flash.c - -# -# Numonyx M25P80 driver source -# - -M25_DRIVER_SRC = \ -	ao_storage.c \ -	ao_m25.c - -# -# SiRF driver source -# -SIRF_DRIVER_SRC = \ -	ao_gps_sirf.c - -# -# Skytraq driver source -# -SKY_DRIVER_SRC = \ -	ao_gps_skytraq.c - - -# -# BTM-182 driver source -# -BTM_DRIVER_SRC = \ -	ao_btm.c - -# -# Companion port driver source -# -COMPANION_SRC = \ -	ao_companion.c - -# -# Tasks run on TeleMetrum -# -TM_TASK_SRC = \ -	ao_flight.c \ -	ao_sample.c \ -	ao_kalman.c \ -	ao_log.c \ -	ao_log_big.c \ -	ao_report.c \ -	ao_telemetry.c - -TM_MAIN_SRC = \ -	ao_telemetrum.c - -# -# Base sources for TeleMetrum -# -TM_BASE_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_DRIVER_SRC) \ -	$(SERIAL_DRIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(TM_DRIVER_SRC) \ -	$(TM_TASK_SRC) \ -	$(TM_MAIN_SRC) - -# -# Sources for TeleMini -TMINI_DRIVER_SRC = \ -	ao_adc.c \ -	ao_ignite.c \ -	ao_config.c \ -	ao_storage.c \ -	ao_packet_slave.c \ -	ao_intflash.c - -TMINI_TASK_SRC = \ -	ao_flight.c \ -	ao_sample.c \ -	ao_kalman.c \ -	ao_log.c \ -	ao_log_tiny.c \ -	ao_report.c \ -	ao_telemetry.c - -TMINI_MAIN_SRC = \ -	ao_telemini.c - -TMINI_BASE_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_DRIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(TMINI_DRIVER_SRC) \ -	$(TMINI_TASK_SRC) \ -	$(TMINI_MAIN_SRC) - -# -# Sources for TeleNano -TNANO_DRIVER_SRC = \ -	ao_adc.c \ -	ao_config.c \ -	ao_storage.c \ -	ao_packet_slave.c \ -	ao_intflash.c - -TNANO_TASK_SRC = \ -	ao_flight_nano.c \ -	ao_sample.c \ -	ao_kalman.c \ -	ao_log.c \ -	ao_log_tiny.c \ -	ao_report.c \ -	ao_telemetry.c - -TNANO_MAIN_SRC = \ -	ao_telenano.c - -TNANO_BASE_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_DRIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(TNANO_DRIVER_SRC) \ -	$(TNANO_TASK_SRC) \ -	$(TNANO_MAIN_SRC) - -# -# Sources for TeleBluetooth -# - -TBT_MAIN_SRC = \ -	ao_telebt.c - -TBT_BASE_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_RECEIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(SERIAL_DRIVER_SRC) \ -	$(USB_DRIVER_SRC) \ -	$(BTM_DRIVER_SRC) \ -	$(DBG_SRC) \ -	$(TBT_MAIN_SRC) - -TBT_V_0_1_SRC = \ -	$(TBT_BASE_SRC) \ -	$(SPI_DRIVER_SRC) \ -	$(M25_DRIVER_SRC) \ -	$(BEEP_DRIVER_SRC) \ -	ao_log_telem.c - -# -# TI Dongle sources -# -TI_MAIN_SRC = \ -	ao_tidongle.c - -# -# All sources for the TI debug dongle -# -TI_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_RECEIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(USB_DRIVER_SRC) \ -	$(TI_MAIN_SRC) \ -	$(DBG_SRC) - -TT_MAIN_SRC = \ -	ao_teleterra.c -# -# All sources for TeleTerra -# -TT_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_RECEIVER_SRC) \ -	$(TELE_DRIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(USB_DRIVER_SRC) \ -	$(TT_MAIN_SRC) - - -# -# Sources for TeleDongle -# - -TD_MAIN_SRC = \ -	ao_teledongle.c - -TD_SRC = \ -	$(ALTOS_SRC) \ -	$(ALTOS_DRIVER_SRC) \ -	$(TELE_RECEIVER_SRC) \ -	$(TELE_COMMON_SRC) \ -	$(USB_DRIVER_SRC) \ -	$(TD_MAIN_SRC) - -include Makefile.defs - -CFLAGS += $(PRODUCT_DEF) -I. - -NICKLE=nickle -CHECK_STACK=sh ../check-stack - -REL=$(SRC:.c=.rel) ao_product.rel -ADB=$(REL:.rel=.adb) -ASM=$(REL:.rel=.asm) -LNK=$(REL:.rel=.lnk) -LST=$(REL:.rel=.lst) -RST=$(REL:.rel=.rst) -SYM=$(REL:.rel=.sym) - -PCDB=$(PROG:.ihx=.cdb) -PLNK=$(PROG:.ihx=.lnk) -PMAP=$(PROG:.ihx=.map) -PMEM=$(PROG:.ihx=.mem) -PAOM=$(PROG:.ihx=) - -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) - -%.rel : %.c $(INC) -	$(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< - -all: ../$(PROG) - -../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto -	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. -	$(call quiet,CHECK_STACK) ../ao.h $(PMEM) - -../altitude.h: make-altitude -	nickle $< > $@ - -../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c -	sh $< > $@ - -ao_product.h: ao-make-product.5c ../Version -	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -$(REL): ao_product.h - -distclean:	clean - -clean: -	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) -	rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) -	rm -f ao_product.h -	rm -f ../$(PROG) - -install: - -uninstall: diff --git a/src/ao_aes.c b/src/ao_aes.c new file mode 100644 index 00000000..d50fecfb --- /dev/null +++ b/src/ao_aes.c @@ -0,0 +1,142 @@ +/* + * 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" + +#if !HAS_AES +#error Must define HAS_AES 1 +#endif + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t	ao_aes_done; +__xdata uint8_t	ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ +	S0CON = 0; +	if (ENCCCS & ENCCCS_RDY) { +		ao_aes_done = 1; +		ao_wakeup(&ao_aes_done); +	} +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ +	ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ +	ao_dma_set_transfer(ao_aes_dma_in, +			    in, +			    &ENCDIXADDR, +			    AO_AES_LEN, +			    DMA_CFG0_WORDSIZE_8 | +			    DMA_CFG0_TMODE_SINGLE | +			    DMA_CFG0_TRIGGER_ENC_DW, +			    DMA_CFG1_SRCINC_1 | +			    DMA_CFG1_DESTINC_0 | +			    DMA_CFG1_PRIORITY_LOW); +	ao_dma_start(ao_aes_dma_in); +	ao_aes_done = 0; +	ENCCCS = ENCCCS_MODE_CBC_MAC | +		ENCCCS_CMD_LOAD_KEY; +	ENCCCS |= ENCCCS_START; +	__critical while (!ao_aes_done) +		ao_sleep(&ao_aes_done); +} + +void +ao_aes_zero_iv(void) +{ +	uint8_t	b; + +	ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; +	for (b = 0; b < AO_AES_LEN; b++) +		ENCDI = 0; +} + +void +ao_aes_run(__xdata uint8_t *in, +	   __xdata uint8_t *out) +{ +	uint8_t	b; +	if (in) { +		ao_dma_set_transfer(ao_aes_dma_in, +				    in, +				    &ENCDIXADDR, +				    AO_AES_LEN, +				    DMA_CFG0_WORDSIZE_8 | +				    DMA_CFG0_TMODE_SINGLE | +				    DMA_CFG0_TRIGGER_ENC_DW, +				    DMA_CFG1_SRCINC_1 | +				    DMA_CFG1_DESTINC_0 | +				    DMA_CFG1_PRIORITY_LOW); +	} +	if (out) { +		ao_dma_set_transfer(ao_aes_dma_out, +				    &ENCDOXADDR, +				    out, +				    AO_AES_LEN, +				    DMA_CFG0_WORDSIZE_8 | +				    DMA_CFG0_TMODE_SINGLE | +				    DMA_CFG0_TRIGGER_ENC_UP, +				    DMA_CFG1_SRCINC_0 | +				    DMA_CFG1_DESTINC_1 | +				    DMA_CFG1_PRIORITY_LOW); +	} +	switch (ao_aes_current_mode) { +	case ao_aes_mode_cbc_mac: +		if (out) +			b = (ENCCCS_MODE_CBC | +			     ENCCCS_CMD_ENCRYPT); +		else +			b = (ENCCCS_MODE_CBC_MAC | +			     ENCCCS_CMD_ENCRYPT); +		break; +	default: +		return; +	} +	ao_aes_done = 0; +	if (in) +		ao_dma_start(ao_aes_dma_in); +	if (out) +		ao_dma_start(ao_aes_dma_out); +	ENCCCS = b; +	ENCCCS |= ENCCCS_START; +	if (out) { +		__critical while (!ao_aes_dma_out_done) +			ao_sleep(&ao_aes_dma_out_done); +	} else { +		__critical while (!ao_aes_done) +			ao_sleep(&ao_aes_done); +	} +} + +void +ao_aes_init(void) +{ +	ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); +	ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); +	S0CON = 0; +	ENCIE = 1; +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c new file mode 100644 index 00000000..41fbbe1f --- /dev/null +++ b/src/ao_radio_cmac.c @@ -0,0 +1,406 @@ +/* + * 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" + +#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_set_monitor(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_set_monitor(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); +} + +static __xdata struct ao_launch_command	command; +static __xdata struct ao_launch_query	query; +static pdata uint16_t	launch_serial; +static pdata uint8_t	launch_channel; +static pdata uint16_t	tick_offset; + +static void +launch_args(void) __reentrant +{ +	ao_cmd_decimal(); +	launch_serial = ao_cmd_lex_i; +	ao_cmd_decimal(); +	launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ +	uint8_t	i; +	int8_t	r = AO_RADIO_CMAC_OK; + +	tick_offset = ao_time(); +	for (i = 0; i < 10; i++) { +		printf ("."); flush(); +		command.tick = ao_time(); +		command.serial = launch_serial; +		command.cmd = AO_LAUNCH_QUERY; +		command.channel = launch_channel; +		ao_radio_cmac_send(&command, sizeof (command)); +		r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); +		if (r == AO_RADIO_CMAC_OK) +			break; +	} +	tick_offset -= query.tick; +	printf("\n"); flush(); +	return r; +} + +static void +launch_report_cmd(void) __reentrant +{ +	int8_t		r; + +	launch_args(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	r = launch_query(); +	switch (r) { +	case AO_RADIO_CMAC_OK: +		if (query.valid) { +			switch (query.arm_status) { +			case ao_igniter_ready: +			case ao_igniter_active: +				printf ("Armed: "); +				break; +			default: +				printf("Disarmed: "); +			} +			switch (query.igniter_status) { +			default: +				printf("unknown\n"); +				break; +			case ao_igniter_ready: +				printf("igniter good\n"); +				break; +			case ao_igniter_open: +				printf("igniter bad\n"); +				break; +			} +		} else { +			printf("Invalid channel %d\n", launch_channel); +		} +		printf("Rssi: %d\n", ao_radio_cmac_rssi); +		break; +	default: +		printf("Error %d\n", r); +		break; +	} +} + +static void +launch_arm(void) __reentrant +{ +	command.tick = ao_time() - tick_offset; +	command.serial = launch_serial; +	command.cmd = AO_LAUNCH_ARM; +	command.channel = launch_channel; +	ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ +	command.tick = ao_time() - tick_offset; +	command.serial = launch_serial; +	command.cmd = AO_LAUNCH_FIRE; +	command.channel = 0; +	ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ +	static __xdata struct ao_launch_command	command; +	uint8_t		secs; +	uint8_t		i; +	int8_t		r; + +	launch_args(); +	ao_cmd_decimal(); +	secs = ao_cmd_lex_i; +	if (ao_cmd_status != ao_cmd_success) +		return; +	r = launch_query(); +	if (r != AO_RADIO_CMAC_OK) { +		printf("query failed %d\n", r); +		return; +	} + +	for (i = 0; i < 4; i++) { +		printf("arm %d\n", i); flush(); +		launch_arm(); +	} + +	secs = secs * 10 - 5; +	if (secs > 100) +		secs = 100; +	for (i = 0; i < secs; i++) { +		printf("fire %d\n", i); flush(); +		launch_ignite(); +		ao_delay(AO_MS_TO_TICKS(100)); +	} +} + +static void +launch_arm_cmd(void) __reentrant +{ +	uint8_t	i; +	int8_t  r; +	launch_args(); +	r = launch_query(); +	if (r != AO_RADIO_CMAC_OK) { +		printf("query failed %d\n", r); +		return; +	} +	for (i = 0; i < 4; i++) +		launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ +	uint8_t i; +	launch_args(); +	for (i = 0; i < 4; i++) +		launch_ignite(); +} + +static __code struct ao_cmds ao_radio_cmac_cmds[] = { +	{ radio_cmac_send_cmd,	"s <length>\0Send AES-CMAC packet. Bytes to send follow on next line" }, +	{ radio_cmac_recv_cmd,	"S <length> <timeout>\0Receive AES-CMAC packet. Timeout in ms" }, +	{ launch_report_cmd,    "l <serial> <channel>\0Get remote launch status" }, +	{ launch_fire_cmd,	"f <serial> <channel> <secs>\0Fire remote igniter" }, +	{ launch_arm_cmd,	"a <serial> <channel>\0Arm remote igniter" }, +	{ launch_ignite_cmd,	"i <serial> <channel>\0Pulse remote igniter" }, +	{ 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ +	ao_cmd_register(&ao_radio_cmac_cmds[0]); +} diff --git a/src/ao_main.c b/src/ao_telelaunch.c index 25acccfc..506431de 100644 --- a/src/ao_main.c +++ b/src/ao_telelaunch.c @@ -1,5 +1,5 @@  /* - * Copyright © 2009 Keith Packard <keithp@keithp.com> + * 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 @@ -16,6 +16,7 @@   */  #include "ao.h" +#include "ao_pins.h"  void  main(void) @@ -23,21 +24,23 @@ main(void)  	ao_clock_init();  	/* Turn on the red LED until the system is stable */ -	ao_led_init(); +	ao_led_init(LEDS_AVAILABLE);  	ao_led_on(AO_LED_RED);  	ao_timer_init();  	ao_adc_init();  	ao_beep_init();  	ao_cmd_init(); -	ao_ee_init(); -	ao_flight_init(); -	ao_log_init(); -	ao_report_init(); +	ao_spi_init(); +	ao_storage_init();  	ao_usb_init(); -	ao_serial_init(); -	ao_gps_init(); -	ao_telemetry_init();  	ao_radio_init(); +#if HAS_DBG +	ao_dbg_init(); +#endif +	ao_aes_init(); +	ao_radio_cmac_init(); +	ao_launch_init(); +	ao_config_init();  	ao_start_scheduler();  } diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile new file mode 100644 index 00000000..93295166 --- /dev/null +++ b/src/avr-demo/Makefile @@ -0,0 +1,105 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ +	ao.h \ +	ao_pins.h \ +	altitude.h \ +	ao_kalman.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ +	ao_cmd.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_serial_avr.c \ +	ao_avr_stdio.c \ +	ao_stdio.c \ +	ao_task.c \ +	ao_timer.c \ +	ao_led.c \ +	ao_usb_avr.c \ +	ao_lcd.c + +PRODUCT=AvrDemo-v0.0 +MCU=atmega32u4 +PRODUCT_DEF=-DAVR_DEMO +IDPRODUCT=0x000a +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues + +NICKLE=nickle + +PROG=avr-demo + +SRC=$(ALTOS_SRC) ao_demo.c ao_debug_avr.c +OBJ=$(SRC:.c=.o) + +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): Makefile $(OBJ) +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + +$(PROG).hex: $(PROG) +	avr-size $(PROG) +	$(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex +	$(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude +	nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h +	$(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean:	clean + +clean: +	rm -f $(OBJ) +	rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h
\ No newline at end of file diff --git a/src/avr-demo/ao_demo.c b/src/avr-demo/ao_demo.c new file mode 100644 index 00000000..756dd0d4 --- /dev/null +++ b/src/avr-demo/ao_demo.c @@ -0,0 +1,52 @@ +/* + * 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" + +struct ao_task demo_task; + +void +ao_demo(void) +{ +	for (;;) { +		ao_led_toggle(AO_LED_RED); +		printf ("hello %d\n", ao_time()); +		ao_delay(AO_MS_TO_TICKS(200)); +	} +} + +int +main(void) +{ +	ao_clock_init(); + +	ao_serial_init(); + +	ao_led_init(LEDS_AVAILABLE); +	ao_avr_stdio_init(); +	printf ("stdio initialized\n"); +//	ao_debug_init(); +	ao_timer_init(); +	ao_cmd_init(); +	ao_usb_init(); +	ao_lcd_init(); + +//	ao_add_task(&demo_task, ao_demo, "demo"); +	/* Turn on the LED until the system is stable */ +	ao_start_scheduler(); +	return 0; +} diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c new file mode 100644 index 00000000..8c0cade0 --- /dev/null +++ b/src/avr/ao_adc_avr.c @@ -0,0 +1,168 @@ +/* + * 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" + +volatile __xdata struct ao_adc	ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t		ao_adc_head; + +#ifdef TELESCIENCE +const uint8_t	adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { +	0x00, +	0x01, +	0x04, +	0x05, +	0x06, +	0x07, +	0x20, +	0x21, +	0x22, +	0x23, +	0x24, +	0x25, +}; +#endif + +#ifdef TELEPYRO +const uint8_t	adc_channels[AO_TELEPYRO_NUM_ADC] = { +	0x00,	/* ADC0  v_batt */ +	0x04,	/* ADC4  sense_a */ +	0x05,	/* ADC5  sense_b */ +	0x06,	/* ADC6  sense_c */ +	0x07,	/* ADC7  sense_d */ +	0x23,	/* ADC11 sense_e */ +	0x22,	/* ADC10 sense_f */ +	0x21,	/* ADC9 sense_g */ +	0x20,	/* ADC8 sense_h */ +}; +#endif + +#define NUM_ADC	(sizeof (adc_channels) / sizeof (adc_channels[0])) + +static uint8_t	ao_adc_channel; + +#define ADC_CHANNEL_LOW(c)	(((c) & 0x1f) << MUX0) +#define ADC_CHANNEL_HIGH(c)	((((c) & 0x20) >> 5) << MUX5) + +#define ADCSRA_INIT	((1 << ADEN) |		/* Enable ADC */ 		\ +			 (0 << ADATE) |		/* No auto ADC trigger */ 	\ +			 (1 << ADIF) |		/* Clear interrupt */		\ +			 (0 << ADIE) |		/* Enable interrupt */		\ +			 (6 << ADPS0))		/* Prescale clock by 64 */ + +#define ADCSRB_INIT	((0 << ADHSM) |		/* No high-speed mode */ \ +			 (0 << ACME) |		/* Some comparitor thing */ \ +			 (0 << ADTS0))		/* Free running mode (don't care) */ + +static void +ao_adc_start(void) +{ +	uint8_t	channel = adc_channels[ao_adc_channel]; +	ADMUX = ((0 << REFS1) |				/* AVcc reference */ +		 (1 << REFS0) |				/* AVcc reference */ +		 (1 << ADLAR) |				/* Left-shift results */ +		 (ADC_CHANNEL_LOW(channel)));		/* Select channel */ + +	ADCSRB = (ADCSRB_INIT | +		  ADC_CHANNEL_HIGH(channel));		/* High channel bit */ + +	ADCSRA = (ADCSRA_INIT | +		  (1 << ADSC) | +		  (1 << ADIE));				/* Start conversion */ +} + +ISR(ADC_vect) +{ +	uint16_t	value; + +	/* Must read ADCL first or the value there will be lost */ +	value = ADCL; +	value |= (ADCH << 8); +	ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; +	if (++ao_adc_channel < NUM_ADC) +		ao_adc_start(); +	else { +		ADCSRA = ADCSRA_INIT; +		ao_adc_ring[ao_adc_head].tick = ao_time(); +		ao_adc_head = ao_adc_ring_next(ao_adc_head); +		ao_wakeup((void *) &ao_adc_head); +		ao_cpu_sleep_disable = 0; +	} +} + +void +ao_adc_poll(void) +{ +	ao_cpu_sleep_disable = 1; +	ao_adc_channel = 0; +	ao_adc_start(); +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ +	uint8_t	i = ao_adc_ring_prev(ao_adc_head); +	memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +static void +ao_adc_dump(void) __reentrant +{ +	static __xdata struct ao_adc	packet; +	uint8_t i; +	ao_adc_get(&packet); +#ifdef TELEPYRO +	printf("ADMUX:  %02x\n", ADMUX); +	printf("ADCSRA: %02x\n", ADCSRA); +	printf("ADCSRB: %02x\n", ADCSRB); +	printf("DIDR0:  %02x\n", DIDR0); +	printf("DIDR2:  %02x\n", DIDR2); +	printf("PORTF:  %02x\n", PORTF); +	printf("DDRF:   %02x\n", DDRF); +	printf("PINF:   %02x\n", PINF); +#endif +	printf("tick: %5u",  packet.tick); +	for (i = 0; i < NUM_ADC; i++) +		printf (" %2d: %5u", i, packet.adc[i]); + + +#ifdef TELEPYRO +	ADMUX = 0x60; +	ADCSRB = 0x00; +	ADCSRA = 0xc6; +	while (ADCSRA & 0x40) +		; +	printf ("ADCL:  %02x\n", ADCL); +	printf ("ADCH:  %02x\n", ADCH); +	printf ("\n"); +#endif +} + +__code struct ao_cmds ao_adc_cmds[] = { +	{ ao_adc_dump,	"a\0Display current ADC values" }, +	{ 0, NULL }, +}; + +void +ao_adc_init(void) +{ +	DIDR0 = 0xf3; +	DIDR2 = 0x3f; +	ADCSRB = ADCSRB_INIT; +	ADCSRA = ADCSRA_INIT; +	ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h new file mode 100644 index 00000000..c695a725 --- /dev/null +++ b/src/avr/ao_arch.h @@ -0,0 +1,158 @@ +/* + * 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. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/sleep.h> + +#ifdef AVR_DEMO +#define TEENSY 1 +#endif + +#if TEENSY +#define F_CPU 16000000UL	// 16 MHz +#else +#define F_CPU  8000000UL	// 8 MHz +#endif + +/* + * AVR definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE	128 + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare	__attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot()	/* XXX */ + +#define ao_arch_nop()		asm("nop") + +#define ao_arch_interrupt(n)	/* nothing */ + +#undef putchar +#undef getchar +#define putchar(c)	ao_putchar(c) +#define getchar		ao_getchar + +extern void putchar(char c); +extern char getchar(void); +extern void ao_avr_stdio_init(void); + +extern const uint16_t ao_serial_number; + +#define AVR_PUSH8(stack, val)	(*((stack)--) = (val)) + +extern uint8_t	ao_cpu_sleep_disable; + +#define ao_arch_task_globals	uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_members\ +	uint8_t *sp;			/* saved stack pointer */ + +#define ao_arch_init_stack(task, start) do {			\ +	uint8_t		*sp = task->stack + AO_STACK_SIZE - 1;	\ +	uint16_t	a = (uint16_t) start; 			\ +	int		i;					\ +								\ +	/* Return address */					\ +	AVR_PUSH8(sp, a);					\ +	AVR_PUSH8(sp, (a >> 8));				\ +								\ +	/* Clear register values */				\ +	i = 32;							\ +	while (i--)						\ +		AVR_PUSH8(sp, 0);				\ +								\ +	/* SREG with interrupts enabled */			\ +	AVR_PUSH8(sp, 0x80);					\ +	task->sp = sp;						\ +} while (0); +	 +#define ao_arch_save_regs() do {					\ +		asm("push r31" "\n\t" "push r30");			\ +		asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ +		asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ +		asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ +		asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ +		asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ +		asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ +		cli();							\ +		asm("in r0, __SREG__" "\n\t" "push r0");		\ +		sei();							\ +	} while (0) + +#define ao_arch_save_stack() do {					\ +		uint8_t	sp_l, sp_h;					\ +		asm("in %0,__SP_L__" : "=&r" (sp_l) );			\ +		asm("in %0,__SP_H__" : "=&r" (sp_h) );			\ +		ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \ +	} while (0) + +#define ao_arch_isr_stack()	/* nothing */ + +#define ao_arch_cpu_idle() do {			\ +		if (!ao_cpu_sleep_disable)	\ +			sleep_cpu();		\ +	} while (0) + +#define ao_arch_restore_stack() do { \ +		uint8_t	sp_l, sp_h;					\ +		sp_l = (uint16_t) ao_cur_task->sp;			\ +		sp_h = ((uint16_t) ao_cur_task->sp) >> 8;		\ +		cli();							\ +		asm("out __SP_H__,%0" : : "r" (sp_h) );			\ +		asm("out __SP_L__,%0" : : "r" (sp_l) );			\ +		asm("pop r0"	"\n\t"					\ +		    "out __SREG__, r0");				\ +		asm("pop r0" "\n\t" "pop r1" "\n\t" "pop r2" "\n\t" "pop r3" "\n\t" "pop r4"); \ +		asm("pop r5" "\n\t" "pop r6" "\n\t" "pop r7" "\n\t" "pop r8" "\n\t" "pop r9"); \ +		asm("pop r10" "\n\t" "pop r11" "\n\t" "pop r12" "\n\t" "pop r13" "\n\t" "pop r14"); \ +		asm("pop r15" "\n\t" "pop r16" "\n\t" "pop r17" "\n\t" "pop r18" "\n\t" "pop r19"); \ +		asm("pop r20" "\n\t" "pop r21" "\n\t" "pop r22" "\n\t" "pop r23" "\n\t" "pop r24"); \ +		asm("pop r25" "\n\t" "pop r26" "\n\t" "pop r27" "\n\t" "pop r28" "\n\t" "pop r29"); \ +		asm("pop r30" "\n\t" "pop r31");			\ +		asm("ret");						\ +	} while(0) + +#define ao_arch_critical(b) do { cli(); b; sei(); } while (0) + +#define AO_TELESCIENCE_NUM_ADC	12 + +struct ao_adc { +	uint16_t	tick;		/* tick when the sample was read */ +	uint16_t	adc[AO_TELESCIENCE_NUM_ADC];	/* samples */ +}; + +#define AO_ADC_RING	16 + +#endif /* _AO_ARCH_H_ */ + diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c new file mode 100644 index 00000000..ba562dbf --- /dev/null +++ b/src/avr/ao_avr_stdio.c @@ -0,0 +1,52 @@ +/* + * 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" + +int +stdio_put(char c, FILE *stream) +{ +	if (ao_cur_task && ao_num_stdios) +		putchar(c); +	else +	{ +		if (c == '\n') +			stdio_put('\r', stream); +		loop_until_bit_is_set(UCSR1A, UDRE1); +		UDR1 = c; +	} + +	return 0; +} + +int +stdio_get(FILE *stream) +{ +	return (int) getchar() & 0xff; +} + +static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); + +void +ao_avr_stdio_init(void) +{ +	stdout = &mystdout; +	stdin = &mystdin; +	printf("%d stdios registered\n", ao_num_stdios); +} diff --git a/src/avr/ao_clock.c b/src/avr/ao_clock.c new file mode 100644 index 00000000..0d42b6d5 --- /dev/null +++ b/src/avr/ao_clock.c @@ -0,0 +1,77 @@ +/* + * 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" + +/* + * AltOS always cranks the clock to the max frequency + */ + +void +ao_clock_init(void) +{ +	/* disable RC clock */ +	CLKSEL0 &= ~(1 << RCE); + +	/* Disable PLL */ +	PLLCSR &= ~(1 << PLLE); + +	/* Enable external clock */ +	CLKSEL0 |= (1 << EXTE); + +	/* wait for external clock to be ready */ +	while ((CLKSTA & (1 << EXTON)) == 0) +		; + +	/* select external clock */ +	CLKSEL0 |= (1 << CLKS); + +	/* Disable the clock prescaler */ +	cli(); +	CLKPR = (1 << CLKPCE); + +	/* Always run the system clock at 8MHz */ +#if AVR_CLOCK > 12000000UL +	CLKPR = 1; +#else +	CLKPR = 0; +#endif +	sei(); + +	/* Set up the PLL to use the crystal */ + +	/* Use primary system clock as PLL source */ +	PLLFRQ = ((0 << PINMUX) |	/* Use primary clock */ +		  (0 << PLLUSB) |	/* No divide by 2 for USB */ +		  (0 << PLLTM0) |	/* Disable high speed timer */ +		  (0x4 << PDIV0));	/* 48MHz PLL clock */ + +	/* Set the frequency of the crystal */ +#if AVR_CLOCK > 12000000UL +	PLLCSR |= (1 << PINDIV);	/* For 16MHz crystal on Teensy board */ +#else +	PLLCSR &= ~(1 << PINDIV);	/* For 8MHz crystal on TeleScience board */ +#endif + +	/* Enable the PLL */ +	PLLCSR |= (1 << PLLE); +	while (!(PLLCSR & (1 << PLOCK))) +		; + +	set_sleep_mode(SLEEP_MODE_IDLE); +	sleep_enable(); +} diff --git a/src/avr/ao_debug_avr.c b/src/avr/ao_debug_avr.c new file mode 100644 index 00000000..2e41e15a --- /dev/null +++ b/src/avr/ao_debug_avr.c @@ -0,0 +1,78 @@ +/* + * 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" + +void +uart_send(char c) +{ +	loop_until_bit_is_set(UCSR1A, UDRE1); +	UDR1 = c; +} + +int +uart_put(char c, FILE *stream) +{ +	if (c == '\n') +		uart_send('\r'); +	uart_send(c); +	return 0; +} + +int +uart_get(FILE *stream) +{ +	loop_until_bit_is_set(UCSR1A, RXC1); +	return (int) UDR1 & 0xff; +} + +void +uart_init(uint16_t baud) +{ +	PRR1 &= ~(1 << PRUSART1); +	UBRR1L = baud; +	UBRR1H = baud >> 8; +	UCSR1A = 0; +	UCSR1B = ((1 << RXEN1) |	/* Enable receiver */ +		  (1 << TXEN1));	/* Enable transmitter */ +	UCSR1C = ((0 << UMSEL10) |	/* Asynchronous mode */ +		  (0 << UPM10) |	/* No parity */ +		  (0 << USBS1) |	/* 1 stop bit */ +		  (3 << UCSZ10) |	/* 8 bit characters */ +		  (0 << UCPOL1));	/* MBZ for async mode */ +} + +static FILE mystdout = FDEV_SETUP_STREAM(uart_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, uart_get, _FDEV_SETUP_READ); + +void	ao_debug_init(void) +{ +	uart_init(F_CPU / (16UL * 9600UL) - 1); + +	stdout = &mystdout; +	stdin = &mystdin; + +	if (DDRB & AO_LED_RED) { +		printf ("oops, starting all over\n"); +		for (;;) +			; +	} +	DDRB |= (1 << 7); +	PORTB |= (1 << 7); +	printf ("debug initialized\n"); +} diff --git a/src/avr/ao_led.c b/src/avr/ao_led.c new file mode 100644 index 00000000..91dfb85e --- /dev/null +++ b/src/avr/ao_led.c @@ -0,0 +1,67 @@ +/* + * 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; 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" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT	PORTB +#define LED_DDR		DDRB + +void +ao_led_on(uint8_t colors) +{ +	LED_PORT |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ +	LED_PORT &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ +	LED_PORT = (LED_PORT & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ +	LED_PORT ^= (colors & ao_led_enable); +} + +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) +{ +	ao_led_enable = enable; +	if ((LED_DDR & enable)) { +		printf ("oops! restarted\n"); +		ao_panic(AO_PANIC_REBOOT); +	} +	LED_PORT &= ~enable; +	LED_DDR |= enable; +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h new file mode 100644 index 00000000..6b72530b --- /dev/null +++ b/src/avr/ao_pins.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef AVR_DEMO +	#define AO_LED_RED		(1<<7) +	#define LEDS_AVAILABLE		(AO_LED_RED) +	#define USE_SERIAL_STDIN	1 +	#define HAS_USB			1 +	#define PACKET_HAS_SLAVE	0 +	#define HAS_SERIAL_1		1 +	#define TEENSY			1 +	#define AVR_VCC_5V	       	1 +	#define AVR_VCC_3V3		0 +	#define AVR_CLOCK		16000000UL +	#define HAS_BEEP		0 +#endif + +#ifdef TELESCIENCE +	#define LEDS_AVAILABLE		0 +	#define HAS_USB			1 +	#define HAS_LOG			1 +	#define TEENSY			0 +	#define USE_SERIAL_STDIN	1 +	#define HAS_SERIAL_1		1 +	#define HAS_USB			1 +	#define HAS_ADC			1 +	#define PACKET_HAS_SLAVE	0 +	#define HAS_BEEP		0 + +	#define AVR_VCC_5V	       	0 +	#define AVR_VCC_3V3		1 +	#define AVR_CLOCK		8000000UL + +	#define SPI_CS_PORT		PORTE +	#define SPI_CS_DIR		DDRE +	#define M25_CS_MASK		(1 << PORTE6) +	#define M25_MAX_CHIPS		1 + +	#define SPI_SLAVE_CS_PORT	PORTB +	#define SPI_SLAVE_CS_PIN	PINB +	#define SPI_SLAVE_CS_PIN_NO	PINB0 + +	#define SPI_SLAVE_PIN_0_3	1 +	#define SPI_SLAVE_PIN_2_5	0 +#endif + +#ifdef TELEPYRO +	#define LEDS_AVAILABLE		0 +	#define HAS_USB			1 +	#define HAS_LOG			0 +	#define TEENSY			0 +	#define USE_SERIAL_STDIN	1 +	#define HAS_SERIAL_1		1 +	#define HAS_USB			1 +	#define HAS_ADC			1 +	#define PACKET_HAS_SLAVE	0 +	#define HAS_BEEP		0 + +	#define AVR_VCC_5V	       	0 +	#define AVR_VCC_3V3		1 +	#define AVR_CLOCK		8000000UL + +	#define SPI_SLAVE_CS_PORT	PORTB +	#define SPI_SLAVE_CS_PIN	PINB +	#define SPI_SLAVE_CS_PIN_NO	PINB0 + +	#define SPI_SLAVE_PIN_0_3	1 +	#define SPI_SLAVE_PIN_2_5	0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/ao_log_telem.c b/src/avr/ao_romconfig.c index 1b472efe..bbb677e2 100644 --- a/src/ao_log_telem.c +++ b/src/avr/ao_romconfig.c @@ -17,14 +17,4 @@  #include "ao.h" -void -ao_log_write_erase(uint8_t pos) -{ -	(void) pos; -} - -uint8_t -ao_log_present(void) -{ -	return 0; -} +const uint16_t ao_serial_number = 0; diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c new file mode 100644 index 00000000..2fe39755 --- /dev/null +++ b/src/avr/ao_serial_avr.c @@ -0,0 +1,166 @@ +/* + * 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" + +__xdata struct ao_fifo	ao_usart1_rx_fifo; +__xdata struct ao_fifo	ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ +	if (c == '\n') +		ao_debug_out('\r'); +	loop_until_bit_is_set(UCSR1A, UDRE1); +	UDR1 = c; +} + +ISR(USART1_RX_vect) +{ +	if (!ao_fifo_full(ao_usart1_rx_fifo)) +		ao_fifo_insert(ao_usart1_rx_fifo, UDR1); +	ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN +	ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ +	if (!ao_fifo_empty(ao_usart1_tx_fifo) && +	    !ao_serial_tx1_started) +	{ +		ao_serial_tx1_started = 1; +		ao_fifo_remove(ao_usart1_tx_fifo, UDR1); +	} +} + +ISR(USART1_UDRE_vect) +{ +	ao_serial_tx1_started = 0; +	ao_serial_tx1_start(); +	ao_wakeup(&ao_usart1_tx_fifo); +} + +char +ao_serial_getchar(void) __critical +{ +	char	c; +	cli(); +	while (ao_fifo_empty(ao_usart1_rx_fifo)) +		ao_sleep(&ao_usart1_rx_fifo); +	ao_fifo_remove(ao_usart1_rx_fifo, c); +	sei(); +	return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ +	char	c; +	cli(); +	if (ao_fifo_empty(ao_usart1_rx_fifo)) { +		sei(); +		return AO_READ_AGAIN; +	} +	ao_fifo_remove(ao_usart1_rx_fifo,c); +	sei(); +	return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ +	cli(); +	while (ao_fifo_full(ao_usart1_tx_fifo)) +		ao_sleep(&ao_usart1_tx_fifo); +	ao_fifo_insert(ao_usart1_tx_fifo, c); +	ao_serial_tx1_start(); +	sei(); +} + +void +ao_serial_drain(void) __critical +{ +	cli(); +	while (!ao_fifo_empty(ao_usart1_tx_fifo)) +		ao_sleep(&ao_usart1_tx_fifo); +	sei(); +} + +static const struct { +	uint16_t ubrr; +} ao_serial_speeds[] = { +	/* [AO_SERIAL_SPEED_4800] = */ { +		F_CPU / (16UL * 4800UL) - 1 +	}, +	/* [AO_SERIAL_SPEED_9600] = */ { +		F_CPU / (16UL * 9600UL) - 1 +	}, +	/* [AO_SERIAL_SPEED_19200] = */ { +		F_CPU / (16UL * 19200UL) - 1 +	}, +	/* [AO_SERIAL_SPEED_57600] = */ { +		F_CPU / (16UL * 57600UL) - 1 +	}, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ +	ao_serial_drain(); +	if (speed > AO_SERIAL_SPEED_57600) +		return; +	UBRR1L = ao_serial_speeds[speed].ubrr; +	UBRR1H = ao_serial_speeds[speed].ubrr >> 8; +} + +void +ao_serial_init(void) +{ +	/* Ensure the uart is powered up */ + +	PRR1 &= ~(1 << PRUSART1); + +	/* Pick a 9600 baud rate */ +	ao_serial_set_speed(AO_SERIAL_SPEED_9600); + +	UCSR1A = 0; +	UCSR1C = ((0 << UMSEL10) |	/* Asynchronous mode */ +		  (0 << UPM10) |	/* No parity */ +		  (0 << USBS1) |	/* 1 stop bit */ +		  (3 << UCSZ10) |	/* 8 bit characters */ +		  (0 << UCPOL1));	/* MBZ for async mode */ +	UCSR1B = ((1 << RXEN1) |	/* Enable receiver */ +		  (1 << TXEN1) |	/* Enable transmitter */ +		  (1 << RXCIE1) |	/* Enable receive interrupts */ +		  (1 << UDRIE1));	/* Enable transmit empty interrupts */ +#if 0 +#if USE_SERIAL_STDIN +	int8_t	i; +	i = ao_add_stdio(ao_serial_pollchar, +			 ao_serial_putchar, +			 NULL); +	printf("Register serial stdio as %d\n", i); +#endif +#endif +} diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c new file mode 100644 index 00000000..76f574c6 --- /dev/null +++ b/src/avr/ao_spi_slave.c @@ -0,0 +1,115 @@ +/* + * 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" + +uint8_t +ao_spi_read(uint8_t *buf, uint8_t len) +{ +	while (len--) { +		while (!(SPSR & (1 << SPIF))) +			if ((PINB & (1 << PINB0))) +				return 0; +		*buf++ = SPDR; +	} +	return 1; +} + +void +ao_spi_write(uint8_t *buf, uint8_t len) +{ +	while (len--) { +		SPDR = *buf++; +		while (!(SPSR & (1 << SPIF))) +			if ((PINB & (1 << PINB0))) +				return; +	} +	/* Clear pending SPIF bit by reading */ +	(void) SPDR; +} + +static uint8_t ao_spi_slave_running; + +ISR(PCINT0_vect) +{ +	cli(); +#if SPI_SLAVE_PIN_0_3 +	if ((PINB & (1 << PORTB0)) == 0) +#endif +#if SPI_SLAVE_PIN_2_5 +	if ((PINB & (1 << PORTB2)) == 0) +#endif +	{ +		if (!ao_spi_slave_running) { +			ao_spi_slave_running = 1; +			ao_spi_slave(); +		} +	} else { +		ao_spi_slave_running = 0; +	} +	sei(); +} + +void +ao_spi_slave_init(void) +{ +	/* We'd like to have a pull-up on SS so that disconnecting the +	 * TM would cause any SPI transaction to abort. However, when +	 * I tried that, SPI transactions would spontaneously abort, +	 * making me assume that we needed a less aggressive pull-up +	 * than is offered inside the AVR +	 */ +#if SPI_SLAVE_PIN_0_3 +	PCMSK0 |= (1 << PCINT0);	/* Enable PCINT0 pin change */ +	PCICR |= (1 << PCIE0);		/* Enable pin change interrupt */ + +	DDRB = ((DDRB & 0xf0) | +		(1 << 3) |		/* MISO, output */ +		(0 << 2) |		/* MOSI, input */ +		(0 << 1) |		/* SCK, input */ +		(0 << 0));		/* SS, input */ + +	PORTB = ((PORTB & 0xf0) | +		 (1 << 3) |		/* MISO, output */ +		 (0 << 2) |		/* MOSI, no pull-up */ +		 (0 << 1) |		/* SCK, no pull-up */ +		 (0 << 0));		/* SS, no pull-up */ +#endif +#if SPI_SLAVE_PIN_2_5 +	PCMSK0 |= (1 << PCINT2);	/* Enable PCINT2 pin change */ +	PCICR |= (1 << PCIE0);		/* Enable pin change interrupt */ + +	DDRB = ((DDRB & 0xf0) | +		(0 << 5) |		/* SCK, input */ +		(1 << 4) |		/* MISO, output */ +		(0 << 3) |		/* MOSI, input */ +		(0 << 2));		/* SS, input */ + +	PORTB = ((PORTB & 0xf0) | +		 (0 << 5) |		/* SCK, no pull-up */ +		 (1 << 4) |		/* MISO, output */ +		 (0 << 3) |		/* MOSI, no pull-up */ +		 (0 << 2));		/* SS, no pull-up */ +#endif	 + +	SPCR = (0 << SPIE) |		/* Disable SPI interrupts */ +		(1 << SPE) |		/* Enable SPI */ +		(0 << DORD) |		/* MSB first */ +		(0 << MSTR) |		/* Slave mode */ +		(0 << CPOL) |		/* Clock low when idle */ +		(0 << CPHA);		/* Sample at leading clock edge */ +} diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c new file mode 100644 index 00000000..6ed708ff --- /dev/null +++ b/src/avr/ao_spi_usart.c @@ -0,0 +1,112 @@ +/* + * 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" + +/* + * Atmega32u4 USART in MSPIM (master SPI mode) + */ + +__xdata uint8_t	ao_spi_mutex; + +/* Send bytes over SPI. + * + * This just polls; the SPI is set to go as fast as possible, + * so using interrupts would take way too long + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ +	uint8_t	*d = block; + +	ao_mutex_get(&ao_spi_mutex); +	while (len--) { +		while (!(UCSR1A & (1 << UDRE1))); +		UDR1 = *d++; +		while (!(UCSR1A & (1 << RXC1))); +		(void) UDR1; +	} +	ao_mutex_put(&ao_spi_mutex); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ +	uint8_t	*d = block; + +	ao_mutex_get(&ao_spi_mutex); +	while (len--) { +		while (!(UCSR1A & (1 << UDRE1))); +		UDR1 = 0; +		while (!(UCSR1A & (1 << RXC1))); +		*d++ = UDR1; +	} +	ao_mutex_put(&ao_spi_mutex); +} + +/* + * 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 + */ + +#define XCK1_DDR	DDRD +#define XCK1_PORT	PORTD +#define XCK1		PORTD5 +#define XMS1_DDR	DDRE +#define XMS1_PORT	PORTE +#define XMS1		PORTE6 + +void +ao_spi_init(void) +{ +	/* Ensure the USART is powered */ +	PRR1 &= ~(1 << PRUSART1); + +	/* +	 * Set pin directions +	 */ +	XCK1_DDR |= (1 << XCK1); + +	/* Clear chip select (which is negated) */ +	XMS1_PORT |= (1 < XMS1); +	XMS1_DDR |= (1 << XMS1); + +	/* Set baud register to zero (required before turning transmitter on) */ +	UBRR1 = 0; + +	UCSR1C = ((0x3 << UMSEL10) |	/* Master SPI mode */ +		  (0 << UCSZ10) |	/* SPI mode 0 */ +		  (0 << UCPOL1));	/* SPI mode 0 */ + +	/* Enable transmitter and receiver */ +	UCSR1B = ((1 << RXEN1) | +		  (1 << TXEN1)); + +	/* It says that 0 is a legal value; we'll see... */ +	UBRR1 = 0; +} diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c new file mode 100644 index 00000000..eef14345 --- /dev/null +++ b/src/avr/ao_timer.c @@ -0,0 +1,89 @@ +/* + * 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; 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" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ +	uint16_t	v; +	ao_arch_critical( +		v = ao_tick_count; +		); +	return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ +	ao_alarm(ticks); +	ao_sleep(&ao_forever); +} + +#define T1_CLOCK_DIVISOR	8	/* 24e6/8 = 3e6 */ +#define T1_SAMPLE_TIME		30000	/* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t	ao_adc_interval = 1; +volatile __data uint8_t	ao_adc_count; +#endif + +void +ao_debug_out(char c); + +ISR(TIMER1_COMPA_vect) +{ +	++ao_tick_count; +#if HAS_ADC +	if (++ao_adc_count == ao_adc_interval) { +		ao_adc_count = 0; +		ao_adc_poll(); +	} +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ +	ao_adc_interval = interval; +	ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ +	TCCR1A = ((0 << WGM11) |	/* CTC mode, OCR1A */ +		  (0 << WGM10));	/* CTC mode, OCR1A */ +	TCCR1B = ((0 << ICNC1) |	/* no input capture noise canceler */ +		  (0 << ICES1) |	/* input capture on falling edge (don't care) */ +		  (0 << WGM13) |	/* CTC mode, OCR1A */ +		  (1 << WGM12) |	/* CTC mode, OCR1A */ +		  (3 << CS10));		/* clk/64 from prescaler */ + +#if TEENSY +	OCR1A = 2500;			/* 16MHz clock */ +#else +	OCR1A = 1250;			/* 8MHz clock */ +#endif + +	TIMSK1 = (1 << OCIE1A);		/* Interrupt on compare match */ +} diff --git a/src/ao_usb.h b/src/avr/ao_usb.h index 6633dafc..6633dafc 100644 --- a/src/ao_usb.h +++ b/src/avr/ao_usb.h diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c new file mode 100644 index 00000000..74bdea23 --- /dev/null +++ b/src/avr/ao_usb_avr.c @@ -0,0 +1,688 @@ +/* + * 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_usb.h" + +#define USB_DEBUG 0 + +#if USB_DEBUG +#define debug(format, args...)	printf(format, ## args) +#else +#define debug(format, args...) +#endif + +struct ao_task __xdata ao_usb_task; + +struct ao_usb_setup { +	uint8_t		dir_type_recip; +	uint8_t		request; +	uint16_t	value; +	uint16_t	index; +	uint16_t	length; +} __xdata ao_usb_setup; + +static __xdata uint8_t 	ao_usb_ep0_state; +static const uint8_t * __xdata ao_usb_ep0_in_data; +static __xdata uint8_t 	ao_usb_ep0_in_len; +static __xdata uint8_t	ao_usb_ep0_in_pending; +static __xdata uint8_t	ao_usb_addr_pending; +static __xdata uint8_t	ao_usb_ep0_in_buf[2]; +static __xdata uint8_t 	ao_usb_ep0_out_len; +static __xdata uint8_t *__xdata ao_usb_ep0_out_data; + +static __xdata uint8_t	ao_usb_in_flushed; +static __xdata uint8_t	ao_usb_running; +static __xdata uint8_t	ao_usb_configuration; +static __xdata uint8_t	ueienx_0; + +void +ao_usb_set_address(uint8_t address) +{ +	UDADDR = (0 << ADDEN) | address; +	ao_usb_addr_pending = 1; +} + +#define EP_SIZE(s)	((s) == 64 ? 0x30 :	\ +			((s) == 32 ? 0x20 :	\ +			((s) == 16 ? 0x10 :	\ +			             0x00))) + +static void +ao_usb_dump_ep(uint8_t ep) +{ +	UENUM = ep; +	debug ("EP %d: UECONX %02x UECFG0X %02x UECFG1X %02x UEIENX %02x UESTA0X %02x UESTA1X %02X\n", +		ep, UECONX, UECFG0X, UECFG1X, UEIENX, UESTA0X, UESTA1X); +} + +static void +ao_usb_set_ep0(void) +{ +	debug ("set_ep0\n"); +	/* Set the CONTROL max packet size, single buffered */ +	UENUM = 0; +	UECONX = (1 << EPEN);					/* Enable */ + +	UECFG0X = ((0 << EPTYPE0) |				/* Control */ +		   (0 << EPDIR));				/* Out (ish) */ + +	UECFG1X = (EP_SIZE(AO_USB_CONTROL_SIZE) |		/* Size */ +		   (0 << EPBK0) |				/* Single bank */ +		   (1 << ALLOC)); + +	ueienx_0 = ((1 << RXSTPE) |				/* Enable SETUP interrupt */ +		    (1 << RXOUTE));				/* Enable OUT interrupt */ + +//	ao_usb_dump_ep(0); +	ao_usb_addr_pending = 0; +} + +static void +ao_usb_set_configuration(void) +{ +	/* Set the IN max packet size, double buffered */ +	UENUM = AO_USB_IN_EP; +	UECONX = (1 << EPEN);					/* Enable */ + +	UECFG0X = ((2 << EPTYPE0) |				/* Bulk */ +		   (1 << EPDIR));				/* In */ + +	UECFG1X = (EP_SIZE(AO_USB_IN_SIZE) |			/* Size */ +		   (1 << EPBK0) |				/* Double bank */ +		   (1 << ALLOC));				/* Allocate */ + +#if 0 +	UEIENX = ((1 << TXINE));				/* Enable IN complete interrupt */ +#endif + +	ao_usb_dump_ep(AO_USB_IN_EP); + +	/* Set the OUT max packet size, double buffered */ +	UENUM = AO_USB_OUT_EP; +	UECONX |= (1 << EPEN);					/* Enable */ + +	UECFG0X = ((2 << EPTYPE0) |				/* Bulk */ +		   (0 << EPDIR));				/* Out */ + +	UECFG1X = (EP_SIZE(AO_USB_OUT_SIZE) |			/* Size */ +		   (1 << EPBK0) |				/* Double bank */ +		   (1 << ALLOC));				/* Allocate */ + +	UEIENX = ((1 << RXOUTE));				/* Enable OUT complete interrupt */ + +	ao_usb_dump_ep(AO_USB_OUT_EP); +	ao_usb_running = 1; +} + +ISR(USB_GEN_vect) +{ +	ao_wakeup(&ao_usb_task); +} + + +__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ +	const uint8_t		*__xdata descriptor; +	__xdata uint8_t		type = value >> 8; +	__xdata uint8_t		index = value; + +	descriptor = ao_usb_descriptors; +	while (descriptor[0] != 0) { +		if (descriptor[1] == type && index-- == 0) { +			if (type == AO_USB_DESC_CONFIGURATION) +				ao_usb_ep0_in_len = descriptor[2]; +			else +				ao_usb_ep0_in_len = descriptor[0]; +			ao_usb_ep0_in_data = descriptor; +			break; +		} +		descriptor += descriptor[0]; +	} +} + +static void +ao_usb_ep0_set_in_pending(uint8_t in_pending) +{ +	ao_usb_ep0_in_pending = in_pending; + +	if (in_pending) +		ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE));	/* Enable IN interrupt */ +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ +	__xdata uint8_t this_len; + +	cli(); +	UENUM = 0; +	if (!(UEINTX & (1 << TXINI))) { +		debug("EP0 not accepting IN data\n"); +		ao_usb_ep0_set_in_pending(1); +	} else { +		this_len = ao_usb_ep0_in_len; +		if (this_len > AO_USB_CONTROL_SIZE) +			this_len = AO_USB_CONTROL_SIZE; + +		ao_usb_ep0_in_len -= this_len; + +		/* Set IN interrupt enable */ +		if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) +			ao_usb_ep0_set_in_pending(0); +		else +			ao_usb_ep0_set_in_pending(1); + +		debug ("Flush EP0 len %d:", this_len); +		while (this_len--) { +			uint8_t	c = *ao_usb_ep0_in_data++; +			debug(" %02x", c); +			UEDATX = c; +		} +		debug ("\n"); + +		/* Clear the TXINI bit to send the packet */ +		UEINTX &= ~(1 << TXINI); +	} +	sei(); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(uint8_t len, uint8_t ack) +{ +	if (len > ao_usb_ep0_out_len) +		len = ao_usb_ep0_out_len; +	ao_usb_ep0_out_len -= len; + +//	debug ("EP0 UEINTX %02x UEBCLX %d UEBCHX %d\n", +//		UEINTX, UEBCLX, UEBCHX); +	/* Pull all of the data out of the packet */ +	debug ("Fill EP0 len %d:", len); +	UENUM = 0; +	while (len--) { +		uint8_t	c = UEDATX; +		*ao_usb_ep0_out_data++ = c; +		debug (" %02x", c); +	} +	debug ("\n"); + +	/* ACK the packet */ +	UEINTX &= ~ack; +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ +	ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_setup(void) +{ +	/* Pull the setup packet out of the fifo */ +	ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; +	ao_usb_ep0_out_len = 8; +	ao_usb_ep0_fill(8, (1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI)); +	if (ao_usb_ep0_out_len != 0) { +		debug ("invalid setup packet length\n"); +		return; +	} + +	/* Figure out how to ACK the setup packet */ +	if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { +		if (ao_usb_setup.length) +			ao_usb_ep0_state = AO_USB_EP0_DATA_IN; +		else +			ao_usb_ep0_state = AO_USB_EP0_IDLE; +	} else { +		if (ao_usb_setup.length) +			ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; +		else +			ao_usb_ep0_state = AO_USB_EP0_IDLE; +	} +/* +	UENUM = 0; +	if (ao_usb_ep0_state == AO_USB_EP0_IDLE) +		USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; +	else +		USBCS0 = USBCS0_CLR_OUTPKT_RDY; +*/ + +	ao_usb_ep0_in_data = ao_usb_ep0_in_buf; +	ao_usb_ep0_in_len = 0; +	switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { +	case AO_USB_TYPE_STANDARD: +		debug ("Standard setup packet\n"); +		switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { +		case AO_USB_RECIP_DEVICE: +			debug ("Device setup packet\n"); +			switch(ao_usb_setup.request) { +			case AO_USB_REQ_GET_STATUS: +				debug ("get status\n"); +				ao_usb_ep0_queue_byte(0); +				ao_usb_ep0_queue_byte(0); +				break; +			case AO_USB_REQ_SET_ADDRESS: +				debug ("set address %d\n", ao_usb_setup.value); +				ao_usb_set_address(ao_usb_setup.value); +				break; +			case AO_USB_REQ_GET_DESCRIPTOR: +				debug ("get descriptor %d\n", ao_usb_setup.value); +				ao_usb_get_descriptor(ao_usb_setup.value); +				break; +			case AO_USB_REQ_GET_CONFIGURATION: +				debug ("get configuration %d\n", ao_usb_configuration); +				ao_usb_ep0_queue_byte(ao_usb_configuration); +				break; +			case AO_USB_REQ_SET_CONFIGURATION: +				ao_usb_configuration = ao_usb_setup.value; +				debug ("set configuration %d\n", ao_usb_configuration); +				ao_usb_set_configuration(); +				break; +			} +			break; +		case AO_USB_RECIP_INTERFACE: +#ifndef AVR +			#pragma disable_warning 110 +#endif +			debug ("Interface setup packet\n"); +			switch(ao_usb_setup.request) { +			case AO_USB_REQ_GET_STATUS: +				ao_usb_ep0_queue_byte(0); +				ao_usb_ep0_queue_byte(0); +				break; +			case AO_USB_REQ_GET_INTERFACE: +				ao_usb_ep0_queue_byte(0); +				break; +			case AO_USB_REQ_SET_INTERFACE: +				break; +			} +			break; +		case AO_USB_RECIP_ENDPOINT: +			debug ("Endpoint setup packet\n"); +			switch(ao_usb_setup.request) { +			case AO_USB_REQ_GET_STATUS: +				ao_usb_ep0_queue_byte(0); +				ao_usb_ep0_queue_byte(0); +				break; +			} +			break; +		} +		break; +	case AO_USB_TYPE_CLASS: +		debug ("Class setup packet\n"); +		switch (ao_usb_setup.request) { +		case SET_LINE_CODING: +			debug ("set line coding\n"); +			ao_usb_ep0_out_len = 7; +			ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; +			break; +		case GET_LINE_CODING: +			debug ("get line coding\n"); +			ao_usb_ep0_in_len = 7; +			ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; +			break; +		case SET_CONTROL_LINE_STATE: +			break; +		} +		break; +	} +	if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { +		if (ao_usb_setup.length < ao_usb_ep0_in_len) +			ao_usb_ep0_in_len = ao_usb_setup.length; +		debug ("Start ep0 in delivery %d\n", ao_usb_ep0_in_len); +		ao_usb_ep0_set_in_pending(1); +	} +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ +	uint8_t	intx, udint; + +	debug ("usb task started\n"); +	ao_usb_ep0_state = AO_USB_EP0_IDLE; +	for (;;) { +		cli(); +		for (;;) { +			udint = UDINT; +			UDINT = 0; +//			debug ("UDINT %02x\n", udint); +			if (udint & (1 << EORSTI)) { +				ao_usb_configuration = 0; +				ao_usb_set_ep0(); +			} +			UENUM = 0; +			intx = UEINTX; +//			debug ("UEINTX %02x\n", intx); +			if (intx & ((1 << RXSTPI) | (1 << RXOUTI))) +				break; +			if ((intx & (1 << TXINI))) { +				if (ao_usb_ep0_in_pending) +					break; +				else +				{ +					if (ao_usb_addr_pending) { +						UDADDR |= (1 << ADDEN); +						ao_usb_addr_pending = 0; +					} +					ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE));	/* Disable IN interrupt */ +				} +			} +//			debug ("usb task sleeping...\n"); +			UENUM = 0; +			UEIENX = ueienx_0; +			ao_sleep(&ao_usb_task); +		} +		sei(); +//		debug ("UEINTX for ep0 is %02x\n", intx); +		if (intx & (1 << RXSTPI)) { +			ao_usb_ep0_setup(); +		} +		if (intx & (1 << RXOUTI)) { +			ao_usb_ep0_fill(UEBCLX, (1 << RXOUTI)); +			ao_usb_ep0_set_in_pending(1); +		} +		if (intx & (1 << TXINI) && ao_usb_ep0_in_pending) { +			debug ("continue sending ep0 IN data\n"); +			ao_usb_ep0_flush(); +		} +	} +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ +	for (;;) { +		/* Check if the current buffer is writable */ +		UENUM = AO_USB_IN_EP; +		if (UEINTX & (1 << RWAL)) +			break; + +		cli(); +		/* Wait for an IN buffer to be ready */ +		for (;;) { +			UENUM = AO_USB_IN_EP; +			if ((UEINTX & (1 << TXINI))) +				break; +			UEIENX = (1 << TXINE); +			ao_sleep(&ao_usb_in_flushed); +		} +		/* Ack the interrupt */ +		UEINTX &= ~(1 << TXINI); +		sei(); +	} +} + +/* Queue the current IN buffer for transmission */ +static void +ao_usb_in_send(void) +{ +	UENUM = AO_USB_IN_EP; +	UEINTX &= ~(1 << FIFOCON); +} + +void +ao_usb_flush(void) __critical +{ +	if (!ao_usb_running) +		return; + +	/* Anytime we've sent a character since +	 * the last time we flushed, we'll need +	 * to send a packet -- the only other time +	 * we would send a packet is when that +	 * packet was full, in which case we now +	 * want to send an empty packet +	 */ +	if (!ao_usb_in_flushed) { +		ao_usb_in_flushed = 1; +		ao_usb_in_wait(); +		ao_usb_in_send(); +	} +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ +	if (!ao_usb_running) +		return; + +	ao_usb_in_wait(); + +	/* Queue a byte */ +	UENUM = AO_USB_IN_EP; +	UEDATX = c; + +	/* Send the packet when full */ +	if ((UEINTX & (1 << RWAL)) == 0) +		ao_usb_in_send(); +	ao_usb_in_flushed = 0; +} + +static char +_ao_usb_pollchar(void) +{ +	char c; +	uint8_t	intx; + +	if (!ao_usb_running) +		return AO_READ_AGAIN; + +	for (;;) { +		UENUM = AO_USB_OUT_EP; +		intx = UEINTX; +		debug("usb_pollchar UEINTX %02d\n", intx); +		if (intx & (1 << RWAL)) +			break; + +		if (intx & (1 << FIFOCON)) { +			/* Ack the last packet */ +			UEINTX = (uint8_t) ~(1 << FIFOCON); +		} + +		/* Check to see if a packet has arrived */ +		if ((intx & (1 << RXOUTI)) == 0) { +			UENUM = AO_USB_OUT_EP; +			UEIENX = (1 << RXOUTE); +			return AO_READ_AGAIN; +		} + +		/* Ack the interrupt */ +		UEINTX = ~(1 << RXOUTI); +	} + +	/* Pull a character out of the fifo */ +	c = UEDATX; +	return c; +} + +char +ao_usb_pollchar(void) +{ +	char	c; +	cli(); +	c = _ao_usb_pollchar(); +	sei(); +	return c; +} + +char +ao_usb_getchar(void) __critical +{ +	char	c; + +	cli(); +	while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) +		ao_sleep(&ao_stdin_ready); +	sei(); +	return c; +} + +uint16_t	control_count; +uint16_t	in_count; +uint16_t	out_count; + +/* Endpoint interrupt */ +ISR(USB_COM_vect) +{ +	uint8_t	old_num = UENUM; +	uint8_t	i = UEINT; + +#ifdef AO_LED_RED +	ao_led_toggle(AO_LED_RED); +#endif +	UEINT = 0; +	if (i & (1 << 0)) { +		UENUM = 0; +		UEIENX = 0; +		ao_wakeup(&ao_usb_task); +		++control_count; +	} +	if (i & (1 << AO_USB_IN_EP)) { +		UENUM = AO_USB_IN_EP; +		UEIENX = 0; +		ao_wakeup(&ao_usb_in_flushed); +		in_count++; +	} +	if (i & (1 << AO_USB_OUT_EP)) { +		UENUM = AO_USB_OUT_EP; +		UEIENX = 0; +		ao_wakeup(&ao_stdin_ready); +		++out_count; +	} +	UENUM = old_num; +} + +#if AVR_VCC_5V +#define AO_PAD_REGULATOR_INIT	(1 << UVREGE)	/* Turn on pad regulator */ +#endif +#if AVR_VCC_3V3 +/* TeleScience V0.1 has a hardware bug -- UVcc is hooked up, but UCap is not + * Make this work by running power through UVcc to the USB system + */ +#define AO_PAD_REGULATOR_INIT	(1 << UVREGE)	/* Turn off pad regulator */ +#endif + +#if AVR_CLOCK == 16000000UL +#define AO_USB_PLL_INPUT_PRESCALER	(1 << PINDIV)	/* Divide 16MHz clock by 2 */ +#endif +#if AVR_CLOCK == 8000000UL +#define AO_USB_PLL_INPUT_PRESCALER	0		/* Don't divide clock */ +#endif + +void +ao_usb_disable(void) +{ +	/* Unplug from the bus */ +	UDCON = (1 << DETACH); + +	/* Disable the interface */ +	USBCON = 0; + +	/* Disable the PLL */ +	PLLCSR = 0; + +	/* Turn off the pad regulator */ +	UHWCON = 0; +} + +#define AO_USB_CON ((1 << USBE) |	/* USB enable */ \ +		    (0 << RSTCPU) |	/* do not reset CPU */	\ +		    (0 << LSM) |	/* Full speed mode */	\ +		    (0 << RMWKUP))	/* no remote wake-up */ \ + +void +ao_usb_enable(void) +{ +	/* Configure pad regulator */ +	UHWCON = AO_PAD_REGULATOR_INIT; + +	/* Enable USB device, but freeze the clocks until initialized */ +	USBCON = AO_USB_CON | (1 <<FRZCLK); + +	/* Enable PLL with appropriate divider */ +	PLLCSR = AO_USB_PLL_INPUT_PRESCALER | (1 << PLLE); + +	/* Wait for PLL to lock */ +	loop_until_bit_is_set(PLLCSR, (1 << PLOCK)); + +	/* Enable USB, enable the VBUS pad */ +	USBCON = AO_USB_CON | (1 << OTGPADE); + +	/* Enable global interrupts */ +	UDIEN = (1 << EORSTE);		/* End of reset interrupt */ + +	ao_usb_configuration = 0; + +	debug ("ao_usb_enable\n"); + +	debug ("UHWCON %02x USBCON %02x PLLCSR %02x UDIEN %02x\n", +	       UHWCON, USBCON, PLLCSR, UDIEN); +	UDCON = (0 << DETACH);	/* Clear the DETACH bit to plug into the bus */ +} + +#if USB_DEBUG +struct ao_task __xdata ao_usb_echo_task; + +static void +ao_usb_echo(void) +{ +	char	c; + +	for (;;) { +		c = ao_usb_getchar(); +		ao_usb_putchar(c); +		ao_usb_flush(); +	} +} +#endif + +static void +ao_usb_irq(void) +{ +	printf ("control: %d out: %d in: %d\n", +		control_count, out_count, in_count); +} + +__code struct ao_cmds ao_usb_cmds[] = { +	{ ao_usb_irq, "i\0Show USB interrupt counts" }, +	{ 0, NULL } +}; + +void +ao_usb_init(void) +{ +	ao_usb_enable(); + +	debug ("ao_usb_init\n"); +	ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); +#if USB_DEBUG +	ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); +#endif +	ao_cmd_register(&ao_usb_cmds[0]); +	ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +} diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 new file mode 100644 index 00000000..8de4a9b2 --- /dev/null +++ b/src/cc1111/Makefile.cc1111 @@ -0,0 +1,27 @@ +CC=sdcc + +CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) + +CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product + +CODESIZE ?= 0x8000 + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ +	--xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff + +REL=$(SRC:.c=.rel) ao_product.rel +ADB=$(REL:.rel=.adb) +ASM=$(REL:.rel=.asm) +LNK=$(REL:.rel=.lnk) +LST=$(REL:.rel=.lst) +RST=$(REL:.rel=.rst) +SYM=$(REL:.rel=.sym) + +PCDB=$(PROG:.ihx=.cdb) +PLNK=$(PROG:.ihx=.lnk) +PMAP=$(PROG:.ihx=.map) +PMEM=$(PROG:.ihx=.mem) +PAOM=$(PROG:.ihx=) + +%.rel : %.c $(INC) +	$(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< diff --git a/src/_bp.c b/src/cc1111/_bp.c index 6bf135bc..6bf135bc 100644 --- a/src/_bp.c +++ b/src/cc1111/_bp.c diff --git a/src/ao_adc.c b/src/cc1111/ao_adc.c index 786dfd11..6aa6e018 100644 --- a/src/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -41,7 +41,11 @@ ao_adc_poll(void)  void  ao_adc_get(__xdata struct ao_adc *packet)  { +#if HAS_FLIGHT  	uint8_t	i = ao_adc_ring_prev(ao_sample_adc); +#else +	uint8_t	i = ao_adc_ring_prev(ao_adc_head); +#endif  	memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc));  } diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h new file mode 100644 index 00000000..8a41791f --- /dev/null +++ b/src/cc1111/ao_arch.h @@ -0,0 +1,207 @@ +/* + * 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. + */ + +/* + * CC1111 definitions and code fragments for AltOS + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "cc1111.h" + +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a)	((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* Stack runs from above the allocated __data space to 0xfe, which avoids + * writing to 0xff as that triggers the stack overflow indicator + */ +#define AO_STACK_START	0x90 +#define AO_STACK_END	0xfe +#define AO_STACK_SIZE	(AO_STACK_END - AO_STACK_START + 1) + +#define ao_arch_reboot() do {					\ +	WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64;	\ +	ao_delay(AO_SEC_TO_TICKS(2));				\ +	} while (0) +	 +#define ao_arch_nop()	_asm nop _endasm +#define ao_arch_interrupt(n)	__interrupt n + +#define ao_arch_naked_declare	__naked +#define ao_arch_naked_define	__naked + +/* CC1111-specific drivers */ + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION	2 + +extern __code __at (0x00a0) uint16_t ao_romconfig_version; +extern __code __at (0x00a2) uint16_t ao_romconfig_check; +extern __code __at (0x00a4) uint16_t ao_serial_number; +extern __code __at (0x00a6) uint32_t ao_radio_cal; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#define ao_arch_task_members\ +	uint8_t	stack_count;		/* amount of saved stack */ + +/* Initialize stack */ +#define ao_arch_init_stack(task, start) {			\ +	uint8_t __xdata *stack = task->stack;			\ +	uint8_t	t;						\ +	*stack++ = ((uint16_t) start);		/* 0 */		\ +	*stack++ = ((uint16_t) start) >> 8;	/* 1 */		\ +								\ +	/* and the stuff saved by ao_switch */			\ +	*stack++ = 0;				/* 2 acc */   	\ +	*stack++ = 0x80;			/* 3 IE */ 	\ +								\ +	/*  4 DPL 						\ +	 *  5 DPH 						\ +	 *  6 B 						\ +	 *  7 R2 						\ +	 *  8 R3 						\ +	 *  9 R4 						\ +	 * 10 R5 						\ +	 * 11 R6 						\ +	 * 12 R7 						\ +	 * 13 R0 						\ +	 * 14 R1 						\ +	 * 15 PSW 						\ +	 * 16 BP 						\ +	 */ 							\ +	for (t = 0; t < 13; t++) 				\ +		*stack++ = 0; 					\ +	task->stack_count = 17;					\ +	} + + +   +/* Save current context */ + +#define ao_arch_save_regs()						\ +	_asm								\ +	/* Push ACC first, as when restoring the context it must be restored \ +	 * last (it is used to set the IE register). */			\ +	push	ACC							\ +	/* Store the IE register then enable interrupts. */		\ +	push	_IEN0							\ +	setb	_EA							\ +	push	DPL							\ +	push	DPH							\ +	push	b							\ +	push	ar2							\ +	push	ar3							\ +	push	ar4							\ +	push	ar5							\ +	push	ar6							\ +	push	ar7							\ +	push	ar0							\ +	push	ar1							\ +	push	PSW							\ +	_endasm;							\ +	PSW = 0;							\ +	_asm								\ +	push	_bp							\ +	_endasm + +#define ao_arch_save_stack() { 						\ +		uint8_t stack_len;					\ +		__data uint8_t *stack_ptr;				\ +		__xdata uint8_t *save_ptr;				\ +		/* Save the current stack */				\ +		stack_len = SP - (AO_STACK_START - 1);			\ +		ao_cur_task->stack_count = stack_len;			\ +		stack_ptr = (uint8_t __data *) AO_STACK_START;		\ +		save_ptr = (uint8_t __xdata *) ao_cur_task->stack;	\ +		do							\ +			*save_ptr++ = *stack_ptr++;			\ +		while (--stack_len);					\ +	} + +#define ao_arch_isr_stack()						\ +	/* Empty the stack; might as well let interrupts have the whole thing */ \ +	(SP = AO_STACK_START - 1) + +#define ao_arch_cpu_idle()	(PCON = PCON_IDLE) + +#define ao_arch_restore_stack() {					\ +		uint8_t stack_len;					\ +		__data uint8_t *stack_ptr;				\ +		__xdata uint8_t *save_ptr;				\ +									\ +		/* Restore the old stack */				\ +		stack_len = ao_cur_task->stack_count;			\ +		SP = AO_STACK_START - 1 + stack_len;			\ +									\ +		stack_ptr = (uint8_t __data *) AO_STACK_START;		\ +		save_ptr = (uint8_t __xdata *) ao_cur_task->stack;	\ +		do							\ +			*stack_ptr++ = *save_ptr++;			\ +		while (--stack_len);					\ +									\ +		_asm							\ +		pop		_bp					\ +		pop		PSW					\ +		pop		ar1					\ +		pop		ar0					\ +		pop		ar7					\ +		pop		ar6					\ +		pop		ar5					\ +		pop		ar4					\ +		pop		ar3					\ +		pop		ar2					\ +		pop		b					\ +		pop		DPH					\ +		pop		DPL					\ +		/* The next byte of the stack is the IE register.  Only the global \ +		   enable bit forms part of the task context.  Pop off the IE then set \ +		   the global enable bit to match that of the stored IE register. */ \ +		pop		ACC					\ +		JB		ACC.7,0098$				\ +		CLR		_EA					\ +		LJMP	0099$						\ +		0098$:							\ +			SETB		_EA				\ +		0099$:							\ +		/* Finally pop off the ACC, which was the first register saved. */ \ +		pop		ACC					\ +		ret							\ +		_endasm;						\ +} + +#define ao_arch_critical(b) __critical { b } + +struct ao_adc { +	uint16_t	tick;		/* tick when the sample was read */ +	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 */ +}; + +#define AO_ADC_RING	32 + +#endif /* _AO_ARCH_H_ */ diff --git a/src/ao_beep.c b/src/cc1111/ao_beep.c index 3642f4c6..3642f4c6 100644 --- a/src/ao_beep.c +++ b/src/cc1111/ao_beep.c diff --git a/src/ao_dbg.c b/src/cc1111/ao_dbg.c index d4c9567f..d4c9567f 100644 --- a/src/ao_dbg.c +++ b/src/cc1111/ao_dbg.c diff --git a/src/ao_dma.c b/src/cc1111/ao_dma.c index 6052964a..6052964a 100644 --- a/src/ao_dma.c +++ b/src/cc1111/ao_dma.c diff --git a/src/ao_ignite.c b/src/cc1111/ao_ignite.c index 5238beb4..289263ab 100644 --- a/src/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -17,34 +17,6 @@  #include "ao.h" -#if IGNITE_ON_P2 -#define AO_IGNITER_DROGUE	P2_3 -#define AO_IGNITER_MAIN		P2_4 -#define AO_IGNITER_DIR		P2DIR -#define AO_IGNITER_DROGUE_BIT	(1 << 3) -#define AO_IGNITER_MAIN_BIT	(1 << 4) -#endif - -#if IGNITE_ON_P0 -#define AO_IGNITER_DROGUE	P0_5 -#define AO_IGNITER_MAIN		P0_4 -#define AO_IGNITER_DIR		P0DIR -#define AO_IGNITER_DROGUE_BIT	(1 << 5) -#define AO_IGNITER_MAIN_BIT	(1 << 4) -#endif - -/* test these values with real igniters */ -#define AO_IGNITER_OPEN		1000 -#define AO_IGNITER_CLOSED	7000 -#define AO_IGNITER_FIRE_TIME	AO_MS_TO_TICKS(50) -#define AO_IGNITER_CHARGE_TIME	AO_MS_TO_TICKS(2000) - -struct ao_ignition { -	uint8_t	request; -	uint8_t fired; -	uint8_t firing; -}; -  __xdata struct ao_ignition ao_ignition[2];  void diff --git a/src/ao_intflash.c b/src/cc1111/ao_intflash.c index d76d954e..d76d954e 100644 --- a/src/ao_intflash.c +++ b/src/cc1111/ao_intflash.c diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c new file mode 100644 index 00000000..a593d0b2 --- /dev/null +++ b/src/cc1111/ao_launch.c @@ -0,0 +1,209 @@ +/* + * 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" + +__xdata uint16_t ao_launch_ignite; + +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...)  +#endif + +static void +ao_launch_run(void) +{ +	for (;;) { +		while (!ao_launch_ignite) +			ao_sleep(&ao_launch_ignite); +		ao_ignition[ao_igniter_drogue].firing = 1; +		ao_ignition[ao_igniter_main].firing = 1; +		AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +		AO_IGNITER_DROGUE = 1; +		while (ao_launch_ignite) { +			ao_launch_ignite = 0; +			ao_delay(AO_MS_TO_TICKS(500)); +		} +		AO_IGNITER_DROGUE = 0; +		ao_ignition[ao_igniter_drogue].firing = 0; +		ao_ignition[ao_igniter_main].firing = 0; +	} +} + +static void +ao_launch_status(void) +{ +	uint8_t	i; +	for (;;) { +		ao_delay(AO_SEC_TO_TICKS(1)); +		if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { +			if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { +				for (i = 0; i < 5; i++) { +					ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); +					ao_delay(AO_MS_TO_TICKS(100)); +				} +			} else { +				ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +			} +		} +	} +} + +static __pdata uint8_t	ao_launch_armed; +static __pdata uint16_t	ao_launch_arm_time; + +static void +ao_launch(void) +{ +	static __xdata struct ao_launch_command	command; +	static __xdata struct ao_launch_query	query; +	int16_t	time_difference; + +	ao_led_off(AO_LED_RED); +	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +	for (;;) { +		flush(); +		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_QUERY: +			if (command.serial != ao_serial_number) { +				PRINTD ("serial number mismatch\n"); +				break; +			} + +			if (command.channel == 0) { +				query.valid = 1; +				query.arm_status = ao_igniter_status(ao_igniter_drogue); +				query.igniter_status = ao_igniter_status(ao_igniter_main); +			} else { +				query.valid = 0; +			} +			query.tick = ao_time(); +			query.serial = ao_serial_number; +			query.channel = command.channel; +			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_ARM: +			if (command.serial != ao_serial_number) { +				PRINTD ("serial number mismatch\n"); +				break; +			} + +			if (command.channel != 0) +				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_launch_armed = 1; +			ao_launch_arm_time = ao_time(); +			break; +		case AO_LAUNCH_FIRE: +			if (!ao_launch_armed) { +				PRINTD ("not armed\n"); +				break; +			} +			if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { +				PRINTD ("late launch arm_time %d time %d\n", +					ao_launch_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_launch_ignite = 1; +			ao_wakeup(&ao_launch_ignite); +			break; +		} +	} +} + +void +ao_launch_test(void) +{ +	switch (ao_igniter_status(ao_igniter_drogue)) { +	case ao_igniter_ready: +	case ao_igniter_active: +		printf ("Armed: "); +		switch (ao_igniter_status(ao_igniter_main)) { +		default: +			printf("unknown status\n"); +			break; +		case ao_igniter_ready: +			printf("igniter good\n"); +			break; +		case ao_igniter_open: +			printf("igniter bad\n"); +			break; +		} +		break; +	default: +		printf("Disarmed\n"); +	} +} + +void +ao_launch_manual(void) +{ +	ao_cmd_white(); +	if (!ao_match_word("DoIt")) +		return; +	ao_cmd_white(); +	ao_launch_ignite = 1; +	ao_wakeup(&ao_launch_ignite); +} + +static __xdata struct ao_task ao_launch_task; +static __xdata struct ao_task ao_launch_ignite_task; +static __xdata struct ao_task ao_launch_status_task; + +__code struct ao_cmds ao_launch_cmds[] = { +	{ ao_launch_test,	"t\0Test launch continuity" }, +	{ ao_launch_manual,	"i <key>\0Fire igniter. <key> is doit with D&I" }, +	{ 0, NULL } +}; + +void +ao_launch_init(void) +{ +	AO_IGNITER_DROGUE = 0; +	AO_IGNITER_MAIN = 0; +	AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +	ao_cmd_register(&ao_launch_cmds[0]); +	ao_add_task(&ao_launch_task, ao_launch, "launch listener"); +	ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); +	ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); +} diff --git a/src/ao_led.c b/src/cc1111/ao_led.c index 5beed58d..5beed58d 100644 --- a/src/ao_led.c +++ b/src/cc1111/ao_led.c diff --git a/src/ao_packet.c b/src/cc1111/ao_packet.c index f627e02b..f627e02b 100644 --- a/src/ao_packet.c +++ b/src/cc1111/ao_packet.c diff --git a/src/ao_packet_master.c b/src/cc1111/ao_packet_master.c index b0fdf5a8..0d0be30e 100644 --- a/src/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -80,13 +80,16 @@ ao_packet_master(void)  	ao_packet_master_time = ao_time();  	ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT;  	while (ao_packet_enable) { +		uint8_t	r;  		memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN);  		ao_packet_send();  		if (ao_tx_packet.len)  			ao_packet_master_busy();  		ao_packet_master_check_busy();  		ao_alarm(ao_packet_master_delay); -		if (ao_packet_recv()) { +		r = ao_packet_recv(); +		ao_clear_alarm(); +		if (r) {  			/* if we can transmit data, do so */  			if (ao_packet_tx_used && ao_tx_packet.len == 0)  				continue; @@ -95,6 +98,7 @@ ao_packet_master(void)  			ao_packet_master_sleeping = 1;  			ao_alarm(ao_packet_master_delay);  			ao_sleep(&ao_packet_master_sleeping); +			ao_clear_alarm();  			ao_packet_master_sleeping = 0;  		}  	} diff --git a/src/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c index 9f14052a..9f14052a 100644 --- a/src/ao_packet_slave.c +++ b/src/cc1111/ao_packet_slave.c diff --git a/src/ao_pins.h b/src/cc1111/ao_pins.h index e1f5459f..723f1500 100644 --- a/src/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -27,6 +27,7 @@  	#define HAS_ADC			1  	#define USE_SERIAL_STDIN	0  	#define HAS_EEPROM		1 +	#define HAS_LOG			1  	#define USE_INTERNAL_FLASH	0  	#define HAS_DBG			1  	#define DBG_ON_P1 		1 @@ -59,6 +60,7 @@  	#define USE_SERIAL_STDIN	0  	#define HAS_ADC			1  	#define HAS_EEPROM		1 +	#define HAS_LOG			1  	#define USE_INTERNAL_FLASH	0  	#define HAS_DBG			1  	#define DBG_ON_P1 		1 @@ -95,6 +97,7 @@  	#define HAS_ADC			0  	#define HAS_DBG			1  	#define HAS_EEPROM		0 +	#define HAS_LOG			0  	#define DBG_ON_P1		1  	#define DBG_ON_P0 		0  	#define IGNITE_ON_P2		0 @@ -108,6 +111,8 @@  	#define SPI_CS_ON_P0		0  	#define HAS_IGNITE		0  	#define HAS_MONITOR		1 +	#define HAS_RSSI		1 +	#define HAS_AES			1  #endif  #if defined(TELEMINI_V_1_0) @@ -119,6 +124,7 @@  	#define USE_SERIAL_STDIN	0  	#define HAS_ADC			1  	#define HAS_EEPROM		1 +	#define HAS_LOG			1  	#define USE_INTERNAL_FLASH	1  	#define HAS_DBG			0  	#define IGNITE_ON_P2		0 @@ -145,6 +151,7 @@  	#define USE_SERIAL_STDIN	0  	#define HAS_ADC			1  	#define HAS_EEPROM		1 +	#define HAS_LOG			1  	#define USE_INTERNAL_FLASH	1  	#define HAS_DBG			0  	#define IGNITE_ON_P2		0 @@ -171,6 +178,7 @@  	#define HAS_ADC			1  	#define HAS_DBG			0  	#define HAS_EEPROM		1 +	#define HAS_LOG			1  	#define USE_INTERNAL_FLASH	0  	#define DBG_ON_P1 		0  	#define DBG_ON_P0 		1 @@ -199,6 +207,7 @@  	#define HAS_ADC			0  	#define HAS_DBG			0  	#define HAS_EEPROM		0 +	#define HAS_LOG			0  	#define DBG_ON_P1		0  	#define DBG_ON_P0 		1  	#define IGNITE_ON_P2		0 @@ -212,6 +221,8 @@  	#define SPI_CS_ON_P0		1  	#define HAS_IGNITE		0  	#define HAS_MONITOR		1 +	#define HAS_RSSI		1 +	#define HAS_AES			1  #endif  #if defined(TIDONGLE) @@ -223,6 +234,7 @@  	#define HAS_ADC			0  	#define HAS_DBG			1  	#define HAS_EEPROM		0 +	#define HAS_LOG			0  	#define DBG_ON_P1		0  	#define DBG_ON_P0		1  	#define IGNITE_ON_P2		0 @@ -235,6 +247,8 @@  	#define SPI_CS_ON_P0		1  	#define HAS_IGNITE		0  	#define HAS_MONITOR		1 +	#define HAS_RSSI		1 +	#define HAS_AES			1  #endif  #if defined(TELEBT_V_0_0) @@ -246,6 +260,7 @@  	#define HAS_ADC			0  	#define HAS_DBG			1  	#define HAS_EEPROM		0 +	#define HAS_LOG			0  	#define HAS_BTM			1  	#define DBG_ON_P1 		0  	#define DBG_ON_P0 		1 @@ -259,11 +274,14 @@  	#define SPI_CS_ON_P1		1  	#define SPI_CS_ON_P0		0  	#define HAS_IGNITE		0 +	#define HAS_IGNITE_REPORT	1  	#define BT_LINK_ON_P2		1  	#define BT_LINK_ON_P1		0  	#define BT_LINK_PIN_INDEX	7  	#define BT_LINK_PIN		P2_1  	#define HAS_MONITOR		1 +	#define HAS_RSSI		0 +	#define HAS_AES			1  #endif  #if defined(TELEBT_V_0_1) @@ -278,6 +296,7 @@  	#define HAS_ADC			0  	#define HAS_DBG			1  	#define HAS_EEPROM		1 +	#define HAS_LOG			1  	#define USE_INTERNAL_FLASH	0  	#define HAS_BTM			1  	#define DBG_ON_P1 		1 @@ -295,11 +314,45 @@  	#define M25_MAX_CHIPS		1  	#define HAS_ACCEL		0  	#define HAS_IGNITE		0 +	#define HAS_IGNITE_REPORT	1  	#define BT_LINK_ON_P2		0  	#define BT_LINK_ON_P1		1  	#define BT_LINK_PIN_INDEX	7  	#define BT_LINK_PIN		P1_7  	#define HAS_MONITOR		1 +	#define HAS_RSSI		0 +	#define HAS_AES			1 +#endif + +#if defined(TELELAUNCH_V_0_1) +	#define HAS_FLIGHT		0 +	#define HAS_USB			1 +	#define HAS_BEEP		1 +	#define HAS_GPS			0 +	#define HAS_SERIAL_1		1 +	#define USE_SERIAL_STDIN	0 +	#define HAS_ADC			1 +	#define HAS_DBG			0 +	#define HAS_EEPROM		1 +	#define HAS_LOG			0 +	#define USE_INTERNAL_FLASH	1 +	#define DBG_ON_P1 		0 +	#define DBG_ON_P0 		1 +	#define IGNITE_ON_P2		1 +	#define IGNITE_ON_P0		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	1 +	#define HAS_ACCEL_REF		0 +	#define SPI_CS_ON_P1		1 +	#define SPI_CS_ON_P0		0 +	#define HAS_ACCEL		0 +	#define HAS_IGNITE		1 +	#define HAS_MONITOR		0 +	#define HAS_AES			1  #endif  #if DBG_ON_P1 @@ -380,6 +433,10 @@  #error Please define HAS_EEPROM  #endif +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif +  #if HAS_EEPROM  #ifndef USE_INTERNAL_FLASH  #error Please define USE_INTERNAL_FLASH @@ -394,6 +451,10 @@  #error Please define HAS_IGNITE  #endif +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif +  #ifndef PACKET_HAS_MASTER  #error Please define PACKET_HAS_MASTER  #endif @@ -405,4 +466,49 @@  #ifndef HAS_MONITOR  #error Please define HAS_MONITOR  #endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE	P2_3 +#define AO_IGNITER_MAIN		P2_4 +#define AO_IGNITER_DIR		P2DIR +#define AO_IGNITER_DROGUE_BIT	(1 << 3) +#define AO_IGNITER_MAIN_BIT	(1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE	P0_5 +#define AO_IGNITER_MAIN		P0_4 +#define AO_IGNITER_DIR		P0DIR +#define AO_IGNITER_DROGUE_BIT	(1 << 5) +#define AO_IGNITER_MAIN_BIT	(1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN		1000 +#define AO_IGNITER_CLOSED	7000 +#define AO_IGNITER_FIRE_TIME	AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME	AO_MS_TO_TICKS(2000) +  #endif /* _AO_PINS_H_ */ diff --git a/src/ao_radio.c b/src/cc1111/ao_radio.c index 00816b33..75f241d4 100644 --- a/src/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -367,21 +367,9 @@ ao_radio_recv_abort(void)  __xdata ao_radio_rdf_value = 0x55;  void -ao_radio_rdf(int ms) +ao_radio_rdf(uint8_t pkt_len)  {  	uint8_t i; -	uint8_t pkt_len; - -	/* -	 * Compute the packet length as follows: -	 * -	 * 2000 bps (for a 1kHz tone) -	 * so, for 'ms' milliseconds, we need -	 * 2 * ms bits, or ms / 4 bytes -	 */ -	if (ms > (255 * 4)) -		ms = 255 * 4; -	pkt_len = ms >> 2;  	ao_radio_abort = 0;  	ao_radio_get(pkt_len); diff --git a/src/ao_reboot.c b/src/cc1111/ao_reboot.c index 8c47b893..8c47b893 100644 --- a/src/ao_reboot.c +++ b/src/cc1111/ao_reboot.c diff --git a/src/ao_romconfig.c b/src/cc1111/ao_romconfig.c index f3fe61b1..f3fe61b1 100644 --- a/src/ao_romconfig.c +++ b/src/cc1111/ao_romconfig.c diff --git a/src/ao_serial.c b/src/cc1111/ao_serial.c index 82370c64..82370c64 100644 --- a/src/ao_serial.c +++ b/src/cc1111/ao_serial.c diff --git a/src/ao_spi.c b/src/cc1111/ao_spi.c index fbe613c7..fbe613c7 100644 --- a/src/ao_spi.c +++ b/src/cc1111/ao_spi.c diff --git a/src/ao_timer.c b/src/cc1111/ao_timer.c index c977fbc8..aadee71e 100644 --- a/src/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -31,6 +31,7 @@ ao_delay(uint16_t ticks)  {  	ao_alarm(ticks);  	ao_sleep(&ao_forever); +	ao_clear_alarm();  }  #define T1_CLOCK_DIVISOR	8	/* 24e6/8 = 3e6 */ diff --git a/src/ao_usb.c b/src/cc1111/ao_usb.c index 08cb7390..08cb7390 100644 --- a/src/ao_usb.c +++ b/src/cc1111/ao_usb.c diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/cc1111/ao_usb.h @@ -0,0 +1,100 @@ +/* + * 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; 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_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK	(0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK	(0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK	(0x1f) + +#define AO_USB_DIR_OUT			0 +#define AO_USB_DIR_IN			(1 << 7) + +#define AO_USB_TYPE_STANDARD		0 +#define AO_USB_TYPE_CLASS		(1 << 5) +#define AO_USB_TYPE_VENDOR		(2 << 5) +#define AO_USB_TYPE_RESERVED		(3 << 5) + +#define AO_USB_RECIP_DEVICE		0 +#define AO_USB_RECIP_INTERFACE		1 +#define AO_USB_RECIP_ENDPOINT		2 +#define AO_USB_RECIP_OTHER		3 + +/* standard requests */ +#define	AO_USB_REQ_GET_STATUS		0x00 +#define AO_USB_REQ_CLEAR_FEATURE	0x01 +#define AO_USB_REQ_SET_FEATURE		0x03 +#define AO_USB_REQ_SET_ADDRESS		0x05 +#define AO_USB_REQ_GET_DESCRIPTOR	0x06 +#define AO_USB_REQ_SET_DESCRIPTOR	0x07 +#define AO_USB_REQ_GET_CONFIGURATION	0x08 +#define AO_USB_REQ_SET_CONFIGURATION	0x09 +#define AO_USB_REQ_GET_INTERFACE	0x0A +#define AO_USB_REQ_SET_INTERFACE	0x0B +#define AO_USB_REQ_SYNCH_FRAME		0x0C + +#define AO_USB_DESC_DEVICE		1 +#define AO_USB_DESC_CONFIGURATION	2 +#define AO_USB_DESC_STRING		3 +#define AO_USB_DESC_INTERFACE		4 +#define AO_USB_DESC_ENDPOINT		5 +#define AO_USB_DESC_DEVICE_QUALIFIER	6 +#define AO_USB_DESC_OTHER_SPEED		7 +#define AO_USB_DESC_INTERFACE_POWER	8 + +#define AO_USB_GET_DESC_TYPE(x)		(((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x)	((x)&0xFF) + +#define AO_USB_CONTROL_EP	0 +#define AO_USB_INT_EP		1 +#define AO_USB_OUT_EP		4 +#define AO_USB_IN_EP		5 +#define AO_USB_CONTROL_SIZE	32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE		64 +#define AO_USB_OUT_SIZE		64 + +#define AO_USB_EP0_IDLE		0 +#define AO_USB_EP0_DATA_IN	1 +#define AO_USB_EP0_DATA_OUT	2 + +#define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE      0x24 +#define CS_ENDPOINT       0x25 + +#define SET_LINE_CODING         0x20 +#define GET_LINE_CODING         0x21 +#define SET_CONTROL_LINE_STATE  0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { +	uint32_t	rate; +	uint8_t		char_format; +	uint8_t		parity; +	uint8_t		data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/cc1111.h b/src/cc1111/cc1111.h index e52aa79f..11ea8bbb 100644 --- a/src/cc1111.h +++ b/src/cc1111/cc1111.h @@ -768,7 +768,7 @@ struct cc_dma_channel {  # define DMA_CFG0_TRIGGER_ADC_CH7	28  # define DMA_CFG0_TRIGGER_I2STX		28  # define DMA_CFG0_TRIGGER_ENC_DW	29 -# define DMA_CFG0_TRIGGER_DNC_UP	30 +# define DMA_CFG0_TRIGGER_ENC_UP	30  # define DMA_CFG1_SRCINC_MASK		(3 << 6)  # define DMA_CFG1_SRCINC_0		(0 << 6) @@ -1303,4 +1303,26 @@ __xdata __at (0xdf3c) uint8_t RF_PKTSTATUS;  __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC;  #define RF_VCO_VC_DAC_OFF	0x3d +/* AES engine */ + +__sfr at 0xB1 ENCDI; +__sfr at 0xB2 ENCDO; +__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; + +__sfr at 0xB3 ENCCCS; + +#define ENCCCS_MODE_CBC		(0 << 4) +#define ENCCCS_MODE_CFB		(1 << 4) +#define ENCCCS_MODE_OFB		(2 << 4) +#define ENCCCS_MODE_CTR		(3 << 4) +#define ENCCCS_MODE_ECB		(4 << 4) +#define ENCCCS_MODE_CBC_MAC	(5 << 4) +#define ENCCCS_RDY		(1 << 3) +#define ENCCCS_CMD_ENCRYPT	(0 << 1) +#define ENCCCS_CMD_DECRYPT	(1 << 1) +#define ENCCCS_CMD_LOAD_KEY	(2 << 1) +#define ENCCCS_CMD_LOAD_IV	(3 << 1) +#define ENCCCS_START		(1 << 0) +  #endif diff --git a/src/altitude.h b/src/core/altitude.h index a278bbc6..a278bbc6 100644 --- a/src/altitude.h +++ b/src/core/altitude.h diff --git a/src/ao.h b/src/core/ao.h index 8ac9ac3d..04610fea 100644 --- a/src/ao.h +++ b/src/core/ao.h @@ -22,27 +22,22 @@  #include <stdio.h>  #include <string.h>  #include <stddef.h> -#include "cc1111.h"  #include "ao_pins.h" +#include <ao_arch.h>  #define TRUE 1  #define FALSE 0  /* Convert a __data pointer into an __xdata pointer */ -#define DATA_TO_XDATA(a)	((void __xdata *) ((uint8_t) (a) | 0xff00)) - -/* Stack runs from above the allocated __data space to 0xfe, which avoids - * writing to 0xff as that triggers the stack overflow indicator - */ -#define AO_STACK_START	0x90 -#define AO_STACK_END	0xfe -#define AO_STACK_SIZE	(AO_STACK_END - AO_STACK_START + 1) +#ifndef DATA_TO_XDATA +#define DATA_TO_XDATA(a)	(a) +#endif  /* An AltOS task */  struct ao_task {  	__xdata void *wchan;		/* current wait channel (NULL if running) */  	uint16_t alarm;			/* abort ao_sleep time */ -	uint8_t	stack_count;		/* amount of saved stack */ +	ao_arch_task_members		/* any architecture-specific fields */  	uint8_t task_id;		/* unique id */  	__code char *name;		/* task name */  	uint8_t	stack[AO_STACK_SIZE];	/* saved stack */ @@ -73,9 +68,13 @@ ao_wakeup(__xdata void *wchan);  void  ao_alarm(uint16_t delay); +/* Clear any pending alarm */ +void +ao_clear_alarm(void); +  /* Yield the processor to another task */  void -ao_yield(void) __naked; +ao_yield(void) ao_arch_naked_declare;  /* Add a task to the run queue */  void @@ -136,7 +135,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical;  /* Timer interrupt */  void -ao_timer_isr(void) __interrupt 9; +ao_timer_isr(void) ao_arch_interrupt(9);  /* Initialize the timer */  void @@ -149,35 +148,13 @@ ao_clock_init(void);  /*   * One set of samples read from the A/D converter or telemetry   */ -struct ao_adc { -	uint16_t	tick;		/* tick when the sample was read */ -	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 */ -}; - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif  #if HAS_ADC -#if HAS_ACCEL -#ifndef HAS_ACCEL_REF -#error Please define HAS_ACCEL_REF -#endif -#else -#define HAS_ACCEL_REF 0 -#endif -  /*   * ao_adc.c   */ -#define AO_ADC_RING	32  #define ao_adc_ring_next(n)	(((n) + 1) & (AO_ADC_RING - 1))  #define ao_adc_ring_prev(n)	(((n) - 1) & (AO_ADC_RING - 1)) @@ -207,7 +184,7 @@ ao_adc_get(__xdata struct ao_adc *packet);  /* The A/D interrupt handler */  void -ao_adc_isr(void) __interrupt 1; +ao_adc_isr(void) ao_arch_interrupt(1);  /* Initialize the A/D converter */  void @@ -299,25 +276,6 @@ void  ao_led_init(uint8_t enable);  /* - * ao_romconfig.c - */ - -#define AO_ROMCONFIG_VERSION	2 - -extern __code __at (0x00a0) uint16_t ao_romconfig_version; -extern __code __at (0x00a2) uint16_t ao_romconfig_check; -extern __code __at (0x00a4) uint16_t ao_serial_number; -extern __code __at (0x00a6) uint32_t ao_radio_cal; - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif - -/*   * ao_usb.c   */ @@ -342,7 +300,7 @@ ao_usb_flush(void);  #if HAS_USB  /* USB interrupt handler */  void -ao_usb_isr(void) __interrupt 6; +ao_usb_isr(void) ao_arch_interrupt(6);  #endif  /* Enable the USB controller */ @@ -357,6 +315,10 @@ ao_usb_disable(void);  void  ao_usb_init(void); +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif +  /*   * ao_cmd.c   */ @@ -384,6 +346,12 @@ ao_cmd_put16(uint16_t v);  void  ao_cmd_white(void); +int8_t +ao_cmd_hexchar(char c); + +void +ao_cmd_hexbyte(void); +  void  ao_cmd_hex(void); @@ -446,7 +414,7 @@ ao_dma_abort(uint8_t id);  /* DMA interrupt routine */  void -ao_dma_isr(void) __interrupt 8; +ao_dma_isr(void) ao_arch_interrupt(8);  /*   * ao_mutex.c @@ -927,10 +895,10 @@ ao_dbg_init(void);  #endif  void -ao_serial_rx1_isr(void) __interrupt 3; +ao_serial_rx1_isr(void) ao_arch_interrupt(3);  void -ao_serial_tx1_isr(void) __interrupt 14; +ao_serial_tx1_isr(void) ao_arch_interrupt(14);  char  ao_serial_getchar(void) __critical; @@ -1003,6 +971,27 @@ void  ao_spi_init(void);  /* + * ao_spi_slave.c + */ + +uint8_t +ao_spi_read(uint8_t *buf, uint8_t len); + +void +ao_spi_write(uint8_t *buf, uint8_t len); + +void +ao_spi_slave_init(void); + +/* This must be defined by the product; it will get called when chip + * select goes low, at which point it should use ao_spi_read and + * ao_spi_write to deal with the request + */ + +void +ao_spi_slave(void); + +/*   * ao_telemetry.c   */  #define AO_MAX_CALLSIGN			8 @@ -1133,6 +1122,30 @@ struct ao_telemetry_companion {  	/* 32 */  }; +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO		0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { +	uint16_t				serial;		/*  0 */ +	uint16_t				tick;		/*  2 */ +	uint8_t					type;		/*  4 */ +	uint8_t					samples;	/*  5 number samples */ + +	int16_t					baro[12];	/* 6 samples */ +	/* 32 */ +}; +  union ao_telemetry_all {  	struct ao_telemetry_generic		generic;  	struct ao_telemetry_sensor		sensor; @@ -1140,6 +1153,7 @@ union ao_telemetry_all {  	struct ao_telemetry_location		location;  	struct ao_telemetry_satellite		satellite;  	struct ao_telemetry_companion		companion; +	struct ao_telemetry_baro		baro;  };  /* @@ -1251,14 +1265,6 @@ struct ao_telemetry_tiny {  	char			callsign[AO_MAX_CALLSIGN];  }; -/* - * ao_radio_recv tacks on rssi and status bytes - */ - -struct ao_telemetry_raw_recv { -	uint8_t			packet[AO_MAX_TELEMETRY + 2]; -}; -  struct ao_telemetry_orig_recv {  	struct ao_telemetry_orig	telemetry_orig;  	int8_t				rssi; @@ -1271,11 +1277,25 @@ struct ao_telemetry_tiny_recv {  	uint8_t				status;  }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { +	uint8_t			packet[AO_MAX_TELEMETRY + 2]; +}; +  /* Set delay between telemetry reports (0 to disable) */ +#ifdef AO_SEND_ALL_BARO +#define AO_TELEMETRY_INTERVAL_PAD	AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_FLIGHT	AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER	AO_MS_TO_TICKS(100) +#else  #define AO_TELEMETRY_INTERVAL_PAD	AO_MS_TO_TICKS(1000)  #define AO_TELEMETRY_INTERVAL_FLIGHT	AO_MS_TO_TICKS(100)  #define AO_TELEMETRY_INTERVAL_RECOVER	AO_MS_TO_TICKS(1000) +#endif  void  ao_telemetry_set_interval(uint16_t interval); @@ -1302,7 +1322,7 @@ extern __xdata uint8_t ao_radio_done;  extern __xdata uint8_t ao_radio_mutex;  void -ao_radio_general_isr(void) __interrupt 16; +ao_radio_general_isr(void) ao_arch_interrupt(16);  void  ao_radio_get(uint8_t len); @@ -1321,8 +1341,18 @@ ao_radio_recv(__xdata void *data, uint8_t size) __reentrant;  void  ao_radio_recv_abort(void); +/* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + +#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) +  void -ao_radio_rdf(int ms); +ao_radio_rdf(uint8_t pkt_len);  void  ao_radio_rdf_abort(void); @@ -1339,6 +1369,21 @@ ao_radio_init(void);  extern const char const * const ao_state_names[]; +#define AO_MONITOR_RING	8 + +union ao_monitor { +		struct ao_telemetry_raw_recv	raw; +		struct ao_telemetry_orig_recv	orig; +		struct ao_telemetry_tiny_recv	tiny; +}; + +extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n)	(((n) + 1) & (AO_MONITOR_RING - 1)) + +extern __data uint8_t ao_monitoring; +extern __data uint8_t ao_monitor_head; +  void  ao_monitor(void); @@ -1401,9 +1446,19 @@ enum ao_igniter_status {  	ao_igniter_open,	/* open circuit detected */  }; +struct ao_ignition { +	uint8_t	request; +	uint8_t fired; +	uint8_t firing; +}; + +extern __xdata struct ao_ignition ao_ignition[2]; +  enum ao_igniter_status  ao_igniter_status(enum ao_igniter igniter); +extern __pdata uint8_t ao_igniter_present; +  void  ao_ignite_set_pins(void); @@ -1415,7 +1470,8 @@ ao_igniter_init(void);   */  #define AO_CONFIG_MAJOR	1 -#define AO_CONFIG_MINOR	8 +#define AO_CONFIG_MINOR	9 +#define AO_AES_LEN 16  struct ao_config {  	uint8_t		major; @@ -1432,6 +1488,7 @@ struct ao_config {  	uint8_t		pad_orientation;	/* minor version 6 */  	uint32_t	radio_setting;		/* minor version 7 */  	uint8_t		radio_enable;		/* minor version 8 */ +	uint8_t		aes_key[AO_AES_LEN];	/* minor version 9 */  };  #define AO_IGNITE_MODE_DUAL		0 @@ -1600,11 +1657,164 @@ struct ao_companion_setup {  };  extern __pdata uint8_t				ao_companion_running; -extern __xdata struct ao_companion_setup	ao_companion_setup;  extern __xdata uint8_t				ao_companion_mutex; +extern __xdata struct ao_companion_command	ao_companion_command; +extern __xdata struct ao_companion_setup	ao_companion_setup;  extern __xdata uint16_t				ao_companion_data[AO_COMPANION_MAX_CHANNELS];  void  ao_companion_init(void); +/* ao_lcd.c */ +   +void +ao_lcd_init(void); + +/* ao_aes.c */ + +__xdata uint8_t ao_aes_mutex; + +/* AES keys and blocks are 128 bits */ + +enum ao_aes_mode { +	ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_zero_iv(void); + +void +ao_aes_run(__xdata uint8_t *in, +	   __xdata uint8_t *out); + +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); + +/* ao_launch.c */ + +struct ao_launch_command { +	uint16_t	tick; +	uint16_t	serial; +	uint8_t		cmd; +	uint8_t		channel; +	uint16_t	unused; +}; + +#define AO_LAUNCH_QUERY		1 + +struct ao_launch_query { +	uint16_t	tick; +	uint16_t	serial; +	uint8_t		channel; +	uint8_t		valid; +	uint8_t		arm_status; +	uint8_t		igniter_status; +}; + +#define AO_LAUNCH_ARM		2 +#define AO_LAUNCH_FIRE		3 + +void +ao_launch_init(void); + +/* + * ao_log_single.c + */ + +#define AO_LOG_TELESCIENCE_START	((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA		((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC	12 + +struct ao_log_telescience { +	uint8_t		type; +	uint8_t		csum; +	uint16_t	tick; +	uint16_t	tm_tick; +	uint8_t		tm_state; +	uint8_t		unused; +	uint16_t	adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +#define AO_LOG_SINGLE_SIZE		32 + +union ao_log_single { +	struct ao_log_telescience	telescience; +	union ao_telemetry_all		telemetry; +	uint8_t				bytes[AO_LOG_SINGLE_SIZE]; +}; + +extern __xdata union ao_log_single	ao_log_single_write_data; +extern __xdata union ao_log_single	ao_log_single_read_data; + +void +ao_log_single_extra_query(void); + +void +ao_log_single_list(void); + +void +ao_log_single_main(void); + +uint8_t +ao_log_single_write(void); + +uint8_t +ao_log_single_read(uint32_t pos); + +void +ao_log_single_start(void); + +void +ao_log_single_stop(void); + +void +ao_log_single_restart(void); + +void +ao_log_single_set(void); + +void +ao_log_single_delete(void); + +void +ao_log_single_init(void); + +void +ao_log_single(void); + +/* + * ao_pyro_slave.c + */ + +#define AO_TELEPYRO_NUM_ADC	9 +  #endif /* _AO_H_ */ diff --git a/src/ao_cmd.c b/src/core/ao_cmd.c index 1442ebea..d0a46633 100644 --- a/src/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -22,7 +22,7 @@ __pdata uint32_t ao_cmd_lex_u32;  __pdata char	ao_cmd_lex_c;  __pdata enum ao_cmd_status ao_cmd_status; -#define CMD_LEN	32 +#define CMD_LEN	48  static __xdata char	cmd_line[CMD_LEN];  static __pdata uint8_t	cmd_len; @@ -32,7 +32,7 @@ static void  put_string(__code char *s)  {  	char	c; -	while (c = *s++) +	while ((c = *s++))  		putchar(c);  } @@ -128,22 +128,48 @@ ao_cmd_white(void)  		ao_cmd_lex();  } +int8_t +ao_cmd_hexchar(char c) +{ +	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); +	return -1; +} + +void +ao_cmd_hexbyte(void) +{ +	uint8_t i; +	int8_t	n; + +	ao_cmd_lex_i = 0; +	ao_cmd_white(); +	for (i = 0; i < 2; i++) { +		n = ao_cmd_hexchar(ao_cmd_lex_c); +		if (n < 0) { +			ao_cmd_status = ao_cmd_syntax_error; +			break; +		} +		ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; +		ao_cmd_lex(); +	} +} +  void  ao_cmd_hex(void)  {  	__pdata uint8_t	r = ao_cmd_lex_error; -	uint8_t	n; +	int8_t	n;  	ao_cmd_lex_i = 0;  	ao_cmd_white();  	for(;;) { -		if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') -			n = (ao_cmd_lex_c - '0'); -		else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') -			n = (ao_cmd_lex_c - 'a' + 10); -		else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') -			n = (ao_cmd_lex_c - 'A' + 10); -		else +		n = ao_cmd_hexchar(ao_cmd_lex_c); +		if (n < 0)  			break;  		ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n;  		r = ao_cmd_success; @@ -188,13 +214,6 @@ ao_match_word(__code char *word)  }  static void -eol(void) -{ -	while (ao_cmd_lex_c != '\n') -		ao_cmd_lex(); -} - -static void  echo(void)  {  	ao_cmd_hex(); @@ -208,8 +227,7 @@ ao_reboot(void)  	ao_cmd_white();  	if (!ao_match_word("eboot"))  		return; -	WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; -	ao_delay(AO_SEC_TO_TICKS(2)); +	ao_arch_reboot();  	ao_panic(AO_PANIC_REBOOT);  } @@ -219,7 +237,7 @@ version(void)  	printf("manufacturer     %s\n", ao_manufacturer);  	printf("product          %s\n", ao_product);  	printf("serial-number    %u\n", ao_serial_number); -#if HAS_EEPROM +#if HAS_LOG  	printf("log-format       %u\n", ao_log_format);  #endif  	printf("software-version %s\n", ao_version); @@ -254,6 +272,7 @@ report(void)  	case ao_cmd_syntax_error:  		puts("Syntax error");  		ao_cmd_status = 0; +	default:  		break;  	}  } diff --git a/src/ao_config.c b/src/core/ao_config.c index 0c10e608..a653bed2 100644 --- a/src/ao_config.c +++ b/src/core/ao_config.c @@ -47,7 +47,9 @@ _ao_config_put(void)  	ao_storage_setup();  	ao_storage_erase(ao_storage_config);  	ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); +#if HAS_FLIGHT  	ao_log_write_erase(0); +#endif  	ao_storage_flush();  } @@ -72,11 +74,14 @@ _ao_config_get(void)  	if (ao_config.major != AO_CONFIG_MAJOR) {  		ao_config.major = AO_CONFIG_MAJOR;  		ao_config.minor = 0; + +		/* Version 0 stuff */  		ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY;  		ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL;  		memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign));  		memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN,  		       sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); +		ao_config_dirty = 1;  	}  	if (ao_config.minor < AO_CONFIG_MINOR) {  		/* Fixups for minor version 1 */ @@ -102,6 +107,8 @@ _ao_config_get(void)  			ao_config.radio_setting = ao_config.radio_cal;  		if (ao_config.minor < 8)  			ao_config.radio_enable = TRUE; +		if (ao_config.minor < 9) +			memset(&ao_config.aes_key, 0, AO_AES_LEN);  		ao_config.minor = AO_CONFIG_MINOR;  		ao_config_dirty = 1;  	} @@ -301,7 +308,7 @@ ao_config_radio_cal_set(void) __reentrant  	_ao_config_edit_finish();  } -#if HAS_EEPROM +#if HAS_LOG  void  ao_config_log_show(void) __reentrant  { @@ -329,7 +336,7 @@ ao_config_log_set(void) __reentrant  		_ao_config_edit_finish();  	}  } -#endif /* HAS_EEPROM */ +#endif /* HAS_LOG */  #if HAS_IGNITE  void @@ -412,6 +419,33 @@ ao_config_radio_enable_set(void) __reentrant  	_ao_config_edit_finish();  } +#if HAS_AES +void +ao_config_key_show(void) __reentrant +{ +	uint8_t	i; +	printf("AES key: "); +	for (i = 0; i < AO_AES_LEN; i++) +		printf ("%02x", ao_config.aes_key[i]); +	printf("\n"); +} + +void +ao_config_key_set(void) __reentrant +{ +	uint8_t i; + +	_ao_config_edit_start(); +	for (i = 0; i < AO_AES_LEN; i++) { +		ao_cmd_hexbyte(); +		if (ao_cmd_status != ao_cmd_success) +			break; +		ao_config.aes_key[i] = ao_cmd_lex_i; +	} +	_ao_config_edit_finish(); +} +#endif +  struct ao_config_var {  	__code char	*str;  	void		(*set)(void) __reentrant; @@ -448,7 +482,7 @@ __code struct ao_config_var ao_config_vars[] = {  #endif /* HAS_ACCEL */  	{ "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",  	  ao_config_radio_cal_set,  	ao_config_radio_cal_show }, -#if HAS_EEPROM +#if HAS_LOG  	{ "l <size>\0Flight log size in kB",  	  ao_config_log_set,		ao_config_log_show },  #endif @@ -460,6 +494,10 @@ __code struct ao_config_var ao_config_vars[] = {  	{ "o <0 antenna up, 1 antenna down>\0Set pad orientation",  	  ao_config_pad_orientation_set,ao_config_pad_orientation_show },  #endif +#if HAS_AES +	{ "k <32 hex digits>\0Set AES encryption key", +	  ao_config_key_set, ao_config_key_show }, +#endif  	{ "s\0Show",  	  ao_config_show,		0 },  #if HAS_EEPROM diff --git a/src/ao_convert.c b/src/core/ao_convert.c index 0969f107..0969f107 100644 --- a/src/ao_convert.c +++ b/src/core/ao_convert.c diff --git a/src/ao_convert_test.c b/src/core/ao_convert_test.c index e2c28b73..e2c28b73 100644 --- a/src/ao_convert_test.c +++ b/src/core/ao_convert_test.c diff --git a/src/ao_ee_fake.c b/src/core/ao_ee_fake.c index b0c1d61e..b0c1d61e 100644 --- a/src/ao_ee_fake.c +++ b/src/core/ao_ee_fake.c diff --git a/src/ao_flight.c b/src/core/ao_flight.c index 85c1825b..a5cf7468 100644 --- a/src/ao_flight.c +++ b/src/core/ao_flight.c @@ -34,7 +34,7 @@  /* Main flight thread. */  __pdata enum ao_flight_state	ao_flight_state;	/* current flight state */ -__pdata uint16_t		ao_launch_tick;		/* time of launch detect */ +__pdata uint16_t		ao_boost_tick;		/* time of launch detect */  /*   * track min/max data over a long interval to detect @@ -151,7 +151,7 @@ ao_flight(void)  				)  			{  				ao_flight_state = ao_flight_boost; -				ao_launch_tick = ao_sample_tick; +				ao_boost_tick = ao_sample_tick;  				/* start logging data */  				ao_log_start(); @@ -184,7 +184,7 @@ ao_flight(void)  			 * (15 seconds) has past.  			 */  			if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || -			    (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) +			    (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX)  			{  #if HAS_ACCEL  				ao_flight_state = ao_flight_fast; @@ -205,7 +205,8 @@ ao_flight(void)  			{  				ao_flight_state = ao_flight_coast;  				ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -			} +			} else +				goto check_re_boost;  			break;  #endif  		case ao_flight_coast: @@ -237,6 +238,16 @@ ao_flight(void)  				ao_flight_state = ao_flight_drogue;  				ao_wakeup(DATA_TO_XDATA(&ao_flight_state));  			} +#if HAS_ACCEL +			else { +			check_re_boost: +				if (ao_accel > AO_MSS_TO_ACCEL(20)) { +					ao_boost_tick = ao_sample_tick; +					ao_flight_state = ao_flight_boost; +					ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); +				} +			} +#endif  			break;  		case ao_flight_drogue: diff --git a/src/ao_flight_nano.c b/src/core/ao_flight_nano.c index 2e332b12..2e332b12 100644 --- a/src/ao_flight_nano.c +++ b/src/core/ao_flight_nano.c diff --git a/src/ao_gps_print.c b/src/core/ao_gps_print.c index fcdedd30..fcdedd30 100644 --- a/src/ao_gps_print.c +++ b/src/core/ao_gps_print.c diff --git a/src/ao_gps_report.c b/src/core/ao_gps_report.c index e57f8744..e57f8744 100644 --- a/src/ao_gps_report.c +++ b/src/core/ao_gps_report.c diff --git a/src/ao_host.h b/src/core/ao_host.h index 65c25fe5..65c25fe5 100644 --- a/src/ao_host.h +++ b/src/core/ao_host.h diff --git a/src/ao_kalman.c b/src/core/ao_kalman.c index ee01949e..ee01949e 100644 --- a/src/ao_kalman.c +++ b/src/core/ao_kalman.c diff --git a/src/ao_log.c b/src/core/ao_log.c index 6d3ad535..6d3ad535 100644 --- a/src/ao_log.c +++ b/src/core/ao_log.c diff --git a/src/ao_log_big.c b/src/core/ao_log_big.c index 74d94c4b..74d94c4b 100644 --- a/src/ao_log_big.c +++ b/src/core/ao_log_big.c diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c new file mode 100644 index 00000000..9e90bd82 --- /dev/null +++ b/src/core/ao_log_single.c @@ -0,0 +1,198 @@ +/* + * 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. + */ + +/* + * ao_log_single.c + * + * Stores a sequence of fixed-size (32 byte) chunks + * without splitting memory up into separate flights + */ + +#include "ao.h" +#include "ao_product.h" + +static __xdata struct ao_task ao_log_single_task; + +__xdata uint8_t 	ao_log_running; +__xdata uint8_t		ao_log_mutex; +__pdata uint32_t	ao_log_start_pos; +__pdata uint32_t	ao_log_end_pos; +__pdata uint32_t	ao_log_current_pos; + +__xdata union ao_log_single ao_log_single_write_data; +__xdata union ao_log_single ao_log_single_read_data; + +uint8_t +ao_log_single_write(void) +{ +	uint8_t wrote = 0; + +	ao_mutex_get(&ao_log_mutex); { +		if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) +			ao_log_single_stop(); +		if (ao_log_running) { +			wrote = 1; +			ao_storage_write(ao_log_current_pos, +					 &ao_log_single_write_data, +					 AO_LOG_SINGLE_SIZE); +			ao_log_current_pos += AO_LOG_SINGLE_SIZE; +		} +	} ao_mutex_put(&ao_log_mutex); +	return wrote; +} + +static uint8_t +ao_log_single_valid(void) +{ +	__xdata uint8_t	*d = ao_log_single_read_data.bytes; +	uint8_t	i; +	for (i = 0; i < AO_LOG_SINGLE_SIZE; i++) +		if (*d++ != 0xff) +			return 1; +	return 0; +} + +uint8_t +ao_log_single_read(uint32_t pos) +{ +	if (!ao_storage_read(pos, &ao_log_single_read_data, AO_LOG_SINGLE_SIZE)) +		return 0; +	return ao_log_single_valid(); +} + +void +ao_log_single_start(void) +{ +	if (!ao_log_running) { +		ao_log_running = 1; +		ao_wakeup(&ao_log_running); +	} +} + +void +ao_log_single_stop(void) +{ +	if (ao_log_running) { +		ao_log_running = 0; +	} +} + +void +ao_log_single_restart(void) +{ +	/* Find end of data */ +	ao_log_end_pos = ao_storage_config; +	for (ao_log_current_pos = 0; +	     ao_log_current_pos < ao_storage_config; +	     ao_log_current_pos += ao_storage_block) +	{ +		if (!ao_log_single_read(ao_log_current_pos)) +			break; +	} +	if (ao_log_current_pos > 0) { +		ao_log_current_pos -= ao_storage_block; +		for (; ao_log_current_pos < ao_storage_config; +		     ao_log_current_pos += sizeof (struct ao_log_telescience)) +		{ +			if (!ao_log_single_read(ao_log_current_pos)) +				break; +		} +	} +} + +void +ao_log_single_set(void) +{ +	printf("Logging currently %s\n", ao_log_running ? "on" : "off"); +	ao_cmd_hex(); +	if (ao_cmd_status == ao_cmd_success) { +		if (ao_cmd_lex_i) { +			printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); +			ao_log_single_start(); +		} else { +			printf ("Log stopped at %ld\n", ao_log_current_pos); +			ao_log_single_stop(); +		} +	} +	ao_cmd_status = ao_cmd_success; +} + +void +ao_log_single_delete(void) +{ +	uint32_t	pos; + +	ao_cmd_hex(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	if (ao_cmd_lex_i != 1) { +		ao_cmd_status = ao_cmd_syntax_error; +		printf("No such flight: %d\n", ao_cmd_lex_i); +		return; +	} +	ao_log_single_stop(); +	for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { +		if (!ao_log_single_read(pos)) +			break; +		ao_storage_erase(pos); +	} +	ao_log_current_pos = ao_log_start_pos = 0; +	if (pos == 0) +		printf("No such flight: %d\n", ao_cmd_lex_i); +	else +		printf ("Erased\n"); +} + +uint8_t +ao_log_full(void) +{ +	return ao_log_current_pos >= ao_log_end_pos; +} + +uint8_t +ao_log_present(void) +{ +	return ao_log_single_read(0); +} + +static void +ao_log_single_query(void) +{ +	printf("Logging enabled: %d\n", ao_log_running); +	printf("Log start: %ld\n", ao_log_start_pos); +	printf("Log cur: %ld\n", ao_log_current_pos); +	printf("Log end: %ld\n", ao_log_end_pos); +	ao_log_single_extra_query(); +} + +const struct ao_cmds ao_log_single_cmds[] = { +	{ ao_log_single_set,	"L <0 off, 1 on>\0Set logging mode" }, +	{ ao_log_single_list,	"l\0List stored flight logs" }, +	{ ao_log_single_delete, "d 1\0Delete all stored flights" }, +	{ ao_log_single_query, "q\0Query log status" }, +	{ 0,	NULL }, +}; + +void +ao_log_single_init(void) +{ +	ao_log_running = 0; + +	ao_cmd_register(&ao_log_single_cmds[0]); + +	ao_add_task(&ao_log_single_task, ao_log_single, "log"); +} diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c new file mode 100644 index 00000000..096ad919 --- /dev/null +++ b/src/core/ao_log_telem.c @@ -0,0 +1,127 @@ +/* + * 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" + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; + +static __data uint8_t			ao_log_monitor_pos; +__pdata enum ao_flight_state		ao_flight_state; +__pdata int16_t				ao_max_height;	/* max of ao_height */ +__pdata int16_t				sense_d, sense_m; +__pdata uint8_t				ao_igniter_present; + +static void +ao_log_telem_track() { +	if (ao_monitoring == sizeof (union ao_telemetry_all)) { +		switch (ao_log_single_write_data.telemetry.generic.type) { +		case AO_TELEMETRY_SENSOR_TELEMETRUM: +		case AO_TELEMETRY_SENSOR_TELEMINI: +			/* fall through ... */ +		case AO_TELEMETRY_SENSOR_TELENANO: +			if (ao_log_single_write_data.telemetry.generic.type == AO_TELEMETRY_SENSOR_TELENANO) { +				ao_igniter_present = 0; +			} else { +				sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; +				sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; +				ao_igniter_present = 1; +			} +			if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { +				ao_max_height = ao_log_single_write_data.telemetry.sensor.height; +			} +			if (ao_log_single_write_data.telemetry.sensor.state != ao_flight_state) { +				ao_flight_state = ao_log_single_write_data.telemetry.sensor.state; +				if (ao_flight_state == ao_flight_pad) +					ao_max_height = 0; +				ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); +			} +		} +	} +} + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ +	int16_t	value; + +	switch (igniter) { +	case ao_igniter_drogue: +		value = sense_d; +		break; +	case ao_igniter_main: +		value = sense_m; +		break; +	default: +		value = 0; +		break; +	} +	if (value < AO_IGNITER_OPEN) +		return ao_igniter_open; +	else if (value > AO_IGNITER_CLOSED) +		return ao_igniter_ready; +	else +		return ao_igniter_unknown; +} + +void +ao_log_single(void) +{ +	ao_storage_setup(); + +	/* This can take a while, so let the rest +	 * of the system finish booting before we start +	 */ +	ao_delay(AO_SEC_TO_TICKS(2)); + +	ao_log_running = 1; +	ao_log_single_restart(); +	ao_flight_state = ao_flight_startup; +	for (;;) { +		while (!ao_log_running) +			ao_sleep(&ao_log_running); + +		ao_log_monitor_pos = ao_monitor_head; +		while (ao_log_running) { +			/* Write samples to EEPROM */ +			while (ao_log_monitor_pos != ao_monitor_head) { +				memcpy(&ao_log_single_write_data.telemetry, +				       &ao_monitor_ring[ao_log_monitor_pos], +				       AO_LOG_SINGLE_SIZE); +				ao_log_single_write(); +				ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); +				ao_log_telem_track(); +			} +			/* Wait for more telemetry data to arrive */ +			ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); +		} +	} +} + +void +ao_log_single_list(void) +{ +	if (ao_log_current_pos != 0) +		printf("flight 1 start %x end %x\n", +		       0, +		       (uint16_t) ((ao_log_current_pos + 0xff) >> 8)); +	printf ("done\n"); +} + +void +ao_log_single_extra_query(void) +{ +} diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c new file mode 100644 index 00000000..31eda381 --- /dev/null +++ b/src/core/ao_log_telescience.c @@ -0,0 +1,117 @@ +/* + * 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_product.h" + +static uint8_t	ao_log_adc_pos; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; + +static void +ao_log_telescience_csum(void) __reentrant +{ +	__xdata uint8_t *b = ao_log_single_write_data.bytes; +	uint8_t	sum = 0x5a; +	uint8_t	i; + +	ao_log_single_write_data.telescience.csum = 0; +	for (i = 0; i < sizeof (struct ao_log_telescience); i++) +		sum += *b++; +	ao_log_single_write_data.telescience.csum = -sum; +} + +void +ao_log_single(void) +{ +	ao_storage_setup(); + +	/* This can take a while, so let the rest +	 * of the system finish booting before we start +	 */ +	ao_delay(AO_SEC_TO_TICKS(10)); + +	ao_log_single_restart(); +	for (;;) { +		while (!ao_log_running) +			ao_sleep(&ao_log_running); + +		ao_log_start_pos = ao_log_current_pos; +		ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_START; +		ao_log_single_write_data.telescience.tick = ao_time(); +		ao_log_single_write_data.telescience.adc[0] = ao_companion_command.serial; +		ao_log_single_write_data.telescience.adc[1] = ao_companion_command.flight; +		ao_log_telescience_csum(); +		ao_log_single_write(); +		/* Write the whole contents of the ring to the log +		 * when starting up. +		 */ +		ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); +		ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; +		while (ao_log_running) { +			/* Write samples to EEPROM */ +			while (ao_log_adc_pos != ao_adc_head) { +				ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; +				memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, +				       AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); +				ao_log_telescience_csum(); +				ao_log_single_write(); +				ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); +			} +			/* Wait for more ADC data to arrive */ +			ao_sleep((void *) &ao_adc_head); +		} +		memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); +	} +} + +void +ao_log_single_list(void) +{ +	uint32_t	pos; +	uint32_t	start = 0; +	uint8_t		flight = 0; + +	for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { +		if (pos >= ao_storage_config || +		    !ao_log_single_read(pos) || +		    ao_log_single_read_data.telescience.type == AO_LOG_TELESCIENCE_START) +		{ +			if (pos != start) { +				printf("flight %d start %x end %x\n", +				       flight, +				       (uint16_t) (start >> 8), +				       (uint16_t) ((pos + 0xff) >> 8)); flush(); +			} +			if (ao_log_single_read_data.telescience.type != AO_LOG_TELESCIENCE_START) +				break; +			start = pos; +			flight++; +		} +	} +	printf ("done\n"); +} + +void +ao_log_single_extra_query(void) +{ +	printf("log data tick: %04x\n", ao_log_single_write_data.telescience.tick); +	printf("TM data tick: %04x\n", ao_log_single_write_data.telescience.tm_tick); +	printf("TM state: %d\n", ao_log_single_write_data.telescience.tm_state); +	printf("TM serial: %d\n", ao_companion_command.serial); +	printf("TM flight: %d\n", ao_companion_command.flight); +} diff --git a/src/ao_log_tiny.c b/src/core/ao_log_tiny.c index d5a3b99f..d5a3b99f 100644 --- a/src/ao_log_tiny.c +++ b/src/core/ao_log_tiny.c diff --git a/src/ao_monitor.c b/src/core/ao_monitor.c index 69eb58e8..56d7604d 100644 --- a/src/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,18 +22,10 @@  #error Must define HAS_MONITOR to 1  #endif -__xdata uint8_t ao_monitoring; +__data uint8_t ao_monitoring;  __pdata uint8_t ao_monitor_led; -#define AO_MONITOR_RING	8 - -__xdata union ao_monitor { -		struct ao_telemetry_raw_recv	raw; -		struct ao_telemetry_orig_recv	orig; -		struct ao_telemetry_tiny_recv	tiny; -} ao_monitor_ring[AO_MONITOR_RING]; - -#define ao_monitor_ring_next(n)	(((n) + 1) & (AO_MONITOR_RING - 1)) +__xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING];  __data uint8_t	ao_monitor_head; @@ -45,7 +37,7 @@ ao_monitor_get(void)  	for (;;) {  		switch (ao_monitoring) {  		case 0: -			ao_sleep(&ao_monitoring); +			ao_sleep(DATA_TO_XDATA(&ao_monitoring));  			continue;  		case AO_MONITORING_ORIG:  			size = sizeof (struct ao_telemetry_orig_recv); @@ -63,7 +55,15 @@ ao_monitor_get(void)  			continue;  		ao_monitor_head = ao_monitor_ring_next(ao_monitor_head);  		ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); -		ao_led_toggle(ao_monitor_led); +	} +} + +void +ao_monitor_blink(void) +{ +	for (;;) { +		ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); +		ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100));  	}  } @@ -159,7 +159,9 @@ ao_monitor_put(void)  				ao_gps_print(&recv_orig.telemetry_orig.gps);  				ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking);  				putchar('\n'); +#if HAS_RSSI  				ao_rssi_set(rssi); +#endif  			} else {  				printf("CRC INVALID RSSI %3d\n", rssi);  			} @@ -222,7 +224,9 @@ ao_monitor_put(void)  				       recv_tiny.telemetry_tiny.flight_vel,  				       recv_tiny.telemetry_tiny.flight_pres);  #endif +#if HAS_RSSI  				ao_rssi_set(rssi); +#endif  			} else {  				printf("CRC INVALID RSSI %3d\n", rssi);  			} @@ -236,6 +240,12 @@ ao_monitor_put(void)  				printf("%02x", byte);  			}  			printf("%02x\n", sum); +#if HAS_RSSI +			if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { +				rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; +				ao_rssi_set(rssi); +			} +#endif  			break;  		}  		ao_usb_flush(); @@ -244,6 +254,7 @@ ao_monitor_put(void)  __xdata struct ao_task ao_monitor_get_task;  __xdata struct ao_task ao_monitor_put_task; +__xdata struct ao_task ao_monitor_blink_task;  void  ao_set_monitor(uint8_t monitoring) @@ -251,7 +262,7 @@ ao_set_monitor(uint8_t monitoring)  	if (ao_monitoring)  		ao_radio_recv_abort();  	ao_monitoring = monitoring; -	ao_wakeup(&ao_monitoring); +	ao_wakeup(DATA_TO_XDATA(&ao_monitoring));  }  static void @@ -274,4 +285,6 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant  	ao_cmd_register(&ao_monitor_cmds[0]);  	ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get");  	ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +	if (ao_monitor_led) +		ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink");  } diff --git a/src/ao_mutex.c b/src/core/ao_mutex.c index c82a7d57..c82a7d57 100644 --- a/src/ao_mutex.c +++ b/src/core/ao_mutex.c diff --git a/src/ao_panic.c b/src/core/ao_panic.c index fdada201..244917a8 100644 --- a/src/ao_panic.c +++ b/src/core/ao_panic.c @@ -24,6 +24,10 @@  #if !HAS_BEEP  #define ao_beep(x)  #endif +#if !LEDS_AVAILABLE +#define ao_led_on(x) +#define ao_led_off(x) +#endif  static void  ao_panic_delay(uint8_t n) @@ -33,7 +37,7 @@ ao_panic_delay(uint8_t n)  	while (n--)  		while (--j)  			while (--i) -				_asm nop _endasm; +				ao_arch_nop();  }  void @@ -53,7 +57,10 @@ ao_panic(uint8_t reason)  		}  		ao_beep(AO_BEEP_OFF);  		ao_panic_delay(2); + +#ifdef SDCC  #pragma disable_warning 126 +#endif  		for (n = 0; n < reason; n++) {  			ao_led_on(AO_LED_RED);  			ao_beep(AO_BEEP_MID); diff --git a/src/ao_product.c b/src/core/ao_product.c index fb59580b..fb59580b 100644 --- a/src/ao_product.c +++ b/src/core/ao_product.c diff --git a/src/ao_report.c b/src/core/ao_report.c index 3cf558e1..70f0b49d 100644 --- a/src/ao_report.c +++ b/src/core/ao_report.c @@ -109,7 +109,7 @@ ao_report_altitude(void)  	}  } -#if HAS_IGNITE +#if HAS_IGNITE_REPORT  static uint8_t  ao_report_igniter_ready(enum ao_igniter igniter)  { @@ -119,7 +119,13 @@ ao_report_igniter_ready(enum ao_igniter igniter)  static void  ao_report_continuity(void) __reentrant  { -	uint8_t	c = (ao_report_igniter_ready(ao_igniter_drogue) | +	uint8_t	c; + +#if !HAS_IGNITE +	if (!ao_igniter_present) +		return; +#endif +	c = (ao_report_igniter_ready(ao_igniter_drogue) |  		     (ao_report_igniter_ready(ao_igniter_main) << 1));  	if (c) {  		while (c--) { @@ -133,6 +139,7 @@ ao_report_continuity(void) __reentrant  			low(AO_MS_TO_TICKS(20));  		}  	} +#if HAS_LOG  	if (ao_log_full()) {  		pause(AO_MS_TO_TICKS(100));  		c = 2; @@ -143,9 +150,7 @@ ao_report_continuity(void) __reentrant  			mid(AO_MS_TO_TICKS(100));  		}  	} -	c = 50; -	while (c-- && ao_flight_state == ao_flight_pad) -		pause(AO_MS_TO_TICKS(100)); +#endif  }  #endif @@ -157,11 +162,16 @@ ao_report(void)  		if (ao_flight_state == ao_flight_landed)  			ao_report_altitude();  		ao_report_beep(); -#if HAS_IGNITE +#if HAS_IGNITE_REPORT  		if (ao_flight_state == ao_flight_idle)  			ao_report_continuity(); -		while (ao_flight_state == ao_flight_pad) +		while (ao_flight_state == ao_flight_pad) { +			uint8_t	c;  			ao_report_continuity(); +			c = 50; +			while (c-- && ao_flight_state == ao_flight_pad) +				pause(AO_MS_TO_TICKS(100)); +		}  #endif  		__critical {  			while (ao_report_state == ao_flight_state) diff --git a/src/ao_rssi.c b/src/core/ao_rssi.c index e3964d2d..e3964d2d 100644 --- a/src/ao_rssi.c +++ b/src/core/ao_rssi.c diff --git a/src/ao_sample.c b/src/core/ao_sample.c index b2b8e9f6..b2b8e9f6 100644 --- a/src/ao_sample.c +++ b/src/core/ao_sample.c diff --git a/src/ao_state.c b/src/core/ao_state.c index ed197aa5..ed197aa5 100644 --- a/src/ao_state.c +++ b/src/core/ao_state.c diff --git a/src/ao_stdio.c b/src/core/ao_stdio.c index c0138a30..c0138a30 100644 --- a/src/ao_stdio.c +++ b/src/core/ao_stdio.c diff --git a/src/ao_storage.c b/src/core/ao_storage.c index 6ffca0e5..6ffca0e5 100644 --- a/src/ao_storage.c +++ b/src/core/ao_storage.c diff --git a/src/ao_task.c b/src/core/ao_task.c index f5850fa4..a19a6a6f 100644 --- a/src/ao_task.c +++ b/src/core/ao_task.c @@ -24,10 +24,13 @@ __data uint8_t ao_num_tasks;  __data uint8_t ao_cur_task_index;  __xdata struct ao_task *__data ao_cur_task; +#ifdef ao_arch_task_globals +ao_arch_task_globals +#endif +  void  ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant  { -	uint8_t	__xdata *stack;  	uint8_t task_id;  	uint8_t t;  	if (ao_num_tasks == AO_NUM_TASKS) @@ -42,90 +45,28 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam  	ao_tasks[ao_num_tasks++] = task;  	task->task_id = task_id;  	task->name = name; +	task->wchan = NULL;  	/*  	 * Construct a stack frame so that it will 'return'  	 * to the start of the task  	 */ -	stack = task->stack; - -	*stack++ = ((uint16_t) start);		/* 0 */ -	*stack++ = ((uint16_t) start) >> 8;	/* 1 */ - -	/* and the stuff saved by ao_switch */ -	*stack++ = 0;				/* 2 acc */   -	*stack++ = 0x80;			/* 3 IE */ - -	/*  4 DPL -	 *  5 DPH -	 *  6 B -	 *  7 R2 -	 *  8 R3 -	 *  9 R4 -	 * 10 R5 -	 * 11 R6 -	 * 12 R7 -	 * 13 R0 -	 * 14 R1 -	 * 15 PSW -	 * 16 BP -	 */ -	for (t = 0; t < 13; t++) -		*stack++ = 0; - -	task->stack_count = 17; -	task->wchan = NULL; +	ao_arch_init_stack(task, start);  }  /* Task switching function. This must not use any stack variables */  void -ao_yield(void) __naked +ao_yield(void) ao_arch_naked_define  { - -	/* Save current context */ -	_asm -		/* Push ACC first, as when restoring the context it must be restored -		 * last (it is used to set the IE register). */ -		push	ACC -		/* Store the IE register then enable interrupts. */ -		push	_IEN0 -		setb	_EA -		push	DPL -		push	DPH -		push	b -		push	ar2 -		push	ar3 -		push	ar4 -		push	ar5 -		push	ar6 -		push	ar7 -		push	ar0 -		push	ar1 -		push	PSW -	_endasm; -	PSW = 0; -	_asm -		push	_bp -	_endasm; +	ao_arch_save_regs();  	if (ao_cur_task_index == AO_NO_TASK_INDEX)  		ao_cur_task_index = ao_num_tasks-1;  	else  	{ -		uint8_t stack_len; -		__data uint8_t *stack_ptr; -		__xdata uint8_t *save_ptr; -		/* Save the current stack */ -		stack_len = SP - (AO_STACK_START - 1); -		ao_cur_task->stack_count = stack_len; -		stack_ptr = (uint8_t __data *) AO_STACK_START; -		save_ptr = (uint8_t __xdata *) ao_cur_task->stack; -		do -			*save_ptr++ = *stack_ptr++; -		while (--stack_len); +		ao_arch_save_stack();  	} -	/* Empty the stack; might as well let interrupts have the whole thing */ -	SP = AO_STACK_START - 1; +	ao_arch_isr_stack();  	/* Find a task to run. If there isn't any runnable task,  	 * this loop will run forever, which is just fine @@ -151,65 +92,21 @@ ao_yield(void) __naked  			}  			/* Enter lower power mode when there isn't anything to do */ -			if (ao_next_task_index == ao_cur_task_index) -				PCON = PCON_IDLE; +			if (ao_next_task_index == ao_cur_task_index) { +				ao_arch_cpu_idle(); +			}  		}  	} - -	{ -		uint8_t stack_len; -		__data uint8_t *stack_ptr; -		__xdata uint8_t *save_ptr; - -		/* Restore the old stack */ -		stack_len = ao_cur_task->stack_count; -		SP = AO_STACK_START - 1 + stack_len; - -		stack_ptr = (uint8_t __data *) AO_STACK_START; -		save_ptr = (uint8_t __xdata *) ao_cur_task->stack; -		do -			*stack_ptr++ = *save_ptr++; -		while (--stack_len); -	} - -	_asm -		pop		_bp -		pop		PSW -		pop		ar1 -		pop		ar0 -		pop		ar7 -		pop		ar6 -		pop		ar5 -		pop		ar4 -		pop		ar3 -		pop		ar2 -		pop		b -		pop		DPH -		pop		DPL -		/* The next byte of the stack is the IE register.  Only the global -		enable bit forms part of the task context.  Pop off the IE then set -		the global enable bit to match that of the stored IE register. */ -		pop		ACC -		JB		ACC.7,0098$ -		CLR		_EA -		LJMP	0099$ -	0098$: -		SETB		_EA -	0099$: -		/* Finally pop off the ACC, which was the first register saved. */ -		pop		ACC -		ret -	_endasm; +	ao_arch_restore_stack();  }  uint8_t  ao_sleep(__xdata void *wchan)  { -	__critical { +	ao_arch_critical(  		ao_cur_task->wchan = wchan; -	} +		);  	ao_yield(); -	ao_cur_task->alarm = 0;  	if (ao_cur_task->wchan) {  		ao_cur_task->wchan = NULL;  		return 1; @@ -238,14 +135,22 @@ ao_alarm(uint16_t delay)  }  void -ao_exit(void) __critical +ao_clear_alarm(void)  { -	uint8_t	i; -	ao_num_tasks--; -	for (i = ao_cur_task_index; i < ao_num_tasks; i++) -		ao_tasks[i] = ao_tasks[i+1]; -	ao_cur_task_index = AO_NO_TASK_INDEX; -	ao_yield(); +	ao_cur_task->alarm = 0; +} + +void +ao_exit(void) +{ +	ao_arch_critical( +		uint8_t	i; +		ao_num_tasks--; +		for (i = ao_cur_task_index; i < ao_num_tasks; i++) +			ao_tasks[i] = ao_tasks[i+1]; +		ao_cur_task_index = AO_NO_TASK_INDEX; +		ao_yield(); +		);  	/* we'll never get back here */  } @@ -253,16 +158,13 @@ void  ao_task_info(void)  {  	uint8_t	i; -	uint8_t pc_loc;  	__xdata struct ao_task *task;  	for (i = 0; i < ao_num_tasks; i++) {  		task = ao_tasks[i]; -		pc_loc = task->stack_count - 17; -		printf("%12s: wchan %04x pc %04x\n", +		printf("%12s: wchan %04x\n",  		       task->name, -		       (int16_t) task->wchan, -		       (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); +		       (int16_t) task->wchan);  	}  } diff --git a/src/ao_telem.h b/src/core/ao_telem.h index 1a8da291..1a8da291 100644 --- a/src/ao_telem.h +++ b/src/core/ao_telem.h diff --git a/src/ao_telemetry.c b/src/core/ao_telemetry.c index c7338a58..c2707e7d 100644 --- a/src/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -94,6 +94,30 @@ ao_send_sensor(void)  	ao_radio_send(&telemetry, sizeof (telemetry));  } +static uint8_t		ao_baro_sample; + +#ifdef AO_SEND_ALL_BARO +static void +ao_send_baro(void) +{ +	uint8_t		sample = ao_sample_adc; +	uint8_t		samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + +	if (samples > 12) { +		ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); +		samples = 12; +	} +	telemetry.generic.tick = ao_adc_ring[sample].tick; +	telemetry.generic.type = AO_TELEMETRY_BARO; +	telemetry.baro.samples = samples; +	for (sample = 0; sample < samples; sample++) { +		telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; +		ao_baro_sample = ao_adc_ring_next(ao_baro_sample); +	} +	ao_radio_send(&telemetry, sizeof (telemetry)); +} +#endif +  static void  ao_send_configuration(void)  { @@ -193,6 +217,9 @@ ao_telemetry(void)  		while (ao_telemetry_interval) { +#ifdef AO_SEND_ALL_BARO +			ao_send_baro(); +#endif  			ao_send_sensor();  #if HAS_COMPANION  			if (ao_companion_running) @@ -203,12 +230,14 @@ ao_telemetry(void)  			ao_send_location();  			ao_send_satellite();  #endif +#ifndef AO_SEND_ALL_BARO  			if (ao_rdf &&  			    (int16_t) (ao_time() - ao_rdf_time) >= 0)  			{  				ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; -				ao_radio_rdf(AO_RDF_LENGTH_MS); +				ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS));  			} +#endif  			time += ao_telemetry_interval;  			delay = time - ao_time();  			if (delay > 0) diff --git a/src/ao_ee.c b/src/drivers/ao_25lc1024.c index a2fe8dc1..738f8ce6 100644 --- a/src/ao_ee.c +++ b/src/drivers/ao_25lc1024.c @@ -16,7 +16,7 @@   */  #include "ao.h" -#include "25lc1024.h" +#include "ao_25lc1024.h"  #define EE_BLOCK_SIZE	((uint16_t) (256))  #define EE_BLOCK_SHIFT	8 diff --git a/src/25lc1024.h b/src/drivers/ao_25lc1024.h index 44e52387..44e52387 100644 --- a/src/25lc1024.h +++ b/src/drivers/ao_25lc1024.h diff --git a/src/ao_flash.c b/src/drivers/ao_at45db161d.c index bb40f6f7..aee9877a 100644 --- a/src/ao_flash.c +++ b/src/drivers/ao_at45db161d.c @@ -16,7 +16,7 @@   */  #include "ao.h" -#include "at45db161d.h" +#include "ao_at45db161d.h"  /* Total bytes of available storage */  __pdata uint32_t	ao_storage_total; diff --git a/src/at45db161d.h b/src/drivers/ao_at45db161d.h index 9ee6f1b6..9ee6f1b6 100644 --- a/src/at45db161d.h +++ b/src/drivers/ao_at45db161d.h diff --git a/src/ao_btm.c b/src/drivers/ao_btm.c index 44155ec1..5eb78815 100644 --- a/src/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -20,6 +20,87 @@  int8_t			ao_btm_stdio;  __xdata uint8_t		ao_btm_connected; +#define BT_DEBUG 0 + +#if BT_DEBUG +__xdata char		ao_btm_buffer[256]; +int			ao_btm_ptr; +char			ao_btm_dir; + +static void +ao_btm_add_char(char c) +{ +	if (ao_btm_ptr < sizeof (ao_btm_buffer)) +		ao_btm_buffer[ao_btm_ptr++] = c; +} + +static void +ao_btm_log_char(char c, char dir) +{ +	if (dir != ao_btm_dir) { +		ao_btm_add_char(dir); +		ao_btm_dir = dir; +	} +	ao_btm_add_char(c); +} + +static void +ao_btm_log_out_char(char c) +{ +	ao_btm_log_char(c, '>'); +} + +static void +ao_btm_log_in_char(char c) +{ +	ao_btm_log_char(c, '<'); +} + +/* + * Dump everything received from the bluetooth device during startup + */ +static void +ao_btm_dump(void) +{ +	int i; +	char c; + +	for (i = 0; i < ao_btm_ptr; i++) { +		c = ao_btm_buffer[i]; +		if (c < ' ' && c != '\n') +			printf("\\%03o", ((int) c) & 0xff); +		else +			putchar(ao_btm_buffer[i]); +	} +	putchar('\n'); +} + +static void +ao_btm_speed(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_lex_u32 == 57600) +		ao_serial_set_speed(AO_SERIAL_SPEED_57600); +	else if (ao_cmd_lex_u32 == 19200) +		ao_serial_set_speed(AO_SERIAL_SPEED_19200); +	else +		ao_cmd_status = ao_cmd_syntax_error; +} + +__code struct ao_cmds ao_btm_cmds[] = { +	{ ao_btm_dump,		"d\0Dump btm buffer." }, +	{ ao_btm_speed,		"s <19200,57600>\0Set btm serial speed." }, +	{ 0, NULL }, +}; + +#define ao_btm_log_init()	ao_cmd_register(&ao_btm_cmds[0]) + +#else +#define ao_btm_log_in_char(c) +#define ao_btm_log_out_char(c) +#define ao_btm_log_init() +#endif +  #define AO_BTM_MAX_REPLY	16  __xdata char		ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -39,6 +120,7 @@ ao_btm_get_line(void)  	for (;;) {  		while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { +			ao_btm_log_in_char(c);  			if (ao_btm_reply_len < sizeof (ao_btm_reply))  				ao_btm_reply[ao_btm_reply_len++] = c;  			if (c == '\r' || c == '\n') @@ -85,6 +167,7 @@ ao_btm_echo(uint8_t echo)  void  ao_btm_putchar(char c)  { +	ao_btm_log_out_char(c);  	ao_serial_putchar(c);  	ao_delay(1);  } @@ -166,10 +249,6 @@ ao_btm(void)  	 */  	ao_delay(AO_SEC_TO_TICKS(3)); -#if HAS_BEEP -	ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif -  	/*  	 * The first time we connect, the BTM-180 comes up at 19200 baud.  	 * After that, it will remember and come up at 57600 baud. So, see @@ -299,4 +378,5 @@ ao_btm_init (void)  #endif  	ao_add_task(&ao_btm_task, ao_btm, "bt"); +	ao_btm_log_init();  } diff --git a/src/ao_companion.c b/src/drivers/ao_companion.c index 4c8f4269..2e587f8e 100644 --- a/src/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -30,7 +30,7 @@  #define COMPANION_SELECT()	do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0)  #define COMPANION_DESELECT()	do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) -static __xdata struct ao_companion_command	ao_companion_command; +__xdata struct ao_companion_command		ao_companion_command;  __xdata struct ao_companion_setup		ao_companion_setup;  __xdata uint16_t	ao_companion_data[AO_COMPANION_MAX_CHANNELS]; diff --git a/src/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c index f2abbf84..f2abbf84 100644 --- a/src/ao_gps_sirf.c +++ b/src/drivers/ao_gps_sirf.c diff --git a/src/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 7ac26946..7ac26946 100644 --- a/src/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c new file mode 100644 index 00000000..5bc89bbd --- /dev/null +++ b/src/drivers/ao_lcd.c @@ -0,0 +1,281 @@ +/* + * 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" + +#define LCD_PORT	PORTB +#define LCD_DDR		DDRB + +#define PIN_RS		4 +#define PIN_E		5 +#define PIN_RW		6 + +void +ao_lcd_set_bits(uint8_t bits) +{ +#if 0 +	printf("\tLCD data %x RS %d R/W %d E %d\n", +	       bits & 0xf, +	       (bits & (1 << PIN_RS)) ? 1 : 0, +	       (bits & (1 << PIN_RW)) ? 1 : 0, +	       (bits & (1 << PIN_E)) ? 1 : 0); +#endif +	LCD_PORT = bits; +#if 0 +	ao_delay(1); +	if (bits & (1 << PIN_RW)) +		printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_get_nibble(uint8_t rs) +{ +	uint8_t	data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); +	uint8_t n; + +	DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); +	ao_lcd_set_bits(data); +	ao_lcd_set_bits(data | (1 << PIN_E)); +	n = PINB & 0xf; +	ao_lcd_set_bits(data); +	return n; +} + +uint8_t +ao_lcd_get_status(void) +{ +	uint8_t	high, low; +	uint8_t data; + +	high = ao_lcd_get_nibble(0); +	low = ao_lcd_get_nibble(0); +	data = (high << 4) | low; +	printf ("\tLCD status %02x\n", data); +	return data; +} + +uint8_t +ao_lcd_get_data(void) +{ +	uint8_t	high, low; +	uint8_t data; + +	high = ao_lcd_get_nibble(1); +	low = ao_lcd_get_nibble(1); +	data = (high << 4) | low; +	printf ("\tLCD data %02x\n", data); +	return data; +} + +void +ao_lcd_wait_idle(void) +{ +	uint8_t	status; +	uint8_t	count = 0; + +	do { +		status = ao_lcd_get_status(); +		count++; +		if (count > 100) { +			printf("idle timeout\n"); +			break; +		} +	} while (0);	/* status & 0x80); */ +} + +void +ao_lcd_send_nibble(uint8_t rs, uint8_t data) +{ +	data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); +	DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); +	ao_lcd_set_bits(data); +	ao_lcd_set_bits(data | (1 << PIN_E)); +	ao_lcd_set_bits(data); +} + +static uint16_t	ao_lcd_time = 3; + +void +ao_lcd_delay(void) +{ +	volatile uint16_t	count; + +	for (count = 0; count < ao_lcd_time; count++) +		; +} + +void +ao_lcd_send_ins(uint8_t data) +{ +//	printf("send ins %02x\n", data); +//	ao_lcd_wait_idle(); +//	ao_delay(1); +	ao_lcd_delay(); +	ao_lcd_send_nibble(0, data >> 4); +	ao_lcd_send_nibble(0, data & 0xf); +} + +void +ao_lcd_send_data(uint8_t data) +{ +//	printf ("send data %02x\n", data); +//	ao_lcd_wait_idle(); +	ao_lcd_delay(); +	ao_lcd_send_nibble(1, data >> 4); +	ao_lcd_send_nibble(1, data & 0x0f); +} + +void +ao_lcd_send_string(char *string) +{ +	uint8_t	c; + +	while ((c = (uint8_t) *string++)) +		ao_lcd_send_data(c); +} + +#define AO_LCD_POWER_CONTROL	0x54 + +void +ao_lcd_contrast_set(uint8_t contrast) +{ +	ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); +	ao_lcd_send_ins(0x70 | (contrast & 0xf)); +} + +void +ao_lcd_clear(void) +{ +	ao_lcd_send_ins(0x01); +	ao_delay(1); +	/* Entry mode */ +	ao_lcd_send_ins(0x04 | 0x02); +} + +void +ao_lcd_start(void) +{ +	/* get to 4bit mode */ +	ao_lcd_send_nibble(0, 0x3); +	ao_lcd_send_nibble(0, 0x3); +	ao_lcd_send_nibble(0, 0x3); +	ao_lcd_send_nibble(0, 0x2); + +	/* function set */ +	ao_lcd_send_ins(0x28); +	/* function set, instruction table 1 */ +	ao_lcd_send_ins(0x29); + +	/* freq set */ +	ao_lcd_send_ins(0x14); + +	/* Power/icon/contrast control*/ +	ao_lcd_send_ins(AO_LCD_POWER_CONTROL); + +	/* Follower control */ +	ao_lcd_send_ins(0x6d); +	ao_delay(AO_MS_TO_TICKS(200)); + +	/* contrast set */ +	ao_lcd_contrast_set(0x18); + +	/* Display on */ +	ao_lcd_send_ins(0x08 | 0x04); + +	/* Clear */ +	ao_lcd_clear(); + +} + +void +ao_lcd_contrast(void) +{ +	ao_cmd_hex(); +	if (ao_cmd_status == ao_cmd_success) { +		printf("setting contrast to %02x\n", ao_cmd_lex_i); +		ao_lcd_contrast_set(ao_cmd_lex_i & 0x3f); +	} +} + +static uint8_t +ao_cmd_hex_nibble(void) +{ +	if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') +		return ao_cmd_lex_c - '0'; +	if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') +		return ao_cmd_lex_c - ('a' - 10); +	if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') +		return ao_cmd_lex_c - ('A' - 10); +	ao_cmd_status = ao_cmd_syntax_error; +	return 0; +} + +void +ao_lcd_string(void) +{ +	uint8_t	col = 0; +	uint8_t	c; + +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	ao_lcd_send_ins(0x80 | (ao_cmd_lex_i ? 0x40 : 0x00)); +	ao_cmd_white(); +	while (ao_cmd_lex_c != '\n') { +		c = ao_cmd_lex_c; +		if (c == '\\') { +			ao_cmd_lex(); +			c = ao_cmd_hex_nibble() << 4; +			ao_cmd_lex(); +			c |= ao_cmd_hex_nibble(); +		} +		ao_lcd_send_data(c); +		ao_cmd_lex(); +		col++; +	} +	while (col < 16) { +		ao_lcd_send_data(' '); +		col++; +	} +} + +void +ao_lcd_delay_set(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status == ao_cmd_success) { +		printf("setting LCD delay to %d\n", ao_cmd_lex_i); +		ao_lcd_time = ao_cmd_lex_i; +	} +} + +__code struct ao_cmds ao_lcd_cmds[] = { +	{ ao_lcd_start, "S\0Start LCD" }, +	{ ao_lcd_contrast, "C <contrast>\0Set LCD contrast" }, +	{ ao_lcd_string, "s <line> <string>\0Send string to LCD" }, +	{ ao_lcd_delay_set, "t <delay>\0Set LCD delay" }, +	{ 0, NULL }, +}; + +void +ao_lcd_init(void) +{ +	DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); +	PORTB = 0; +	ao_cmd_register(&ao_lcd_cmds[0]); +} diff --git a/src/ao_m25.c b/src/drivers/ao_m25.c index d7208273..28cb1dd7 100644 --- a/src/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -376,5 +376,7 @@ ao_storage_device_init(void)  	/* Set up chip select wires */  	SPI_CS_PORT |= M25_CS_MASK;	/* raise all CS pins */  	SPI_CS_DIR |= M25_CS_MASK;	/* set CS pins as outputs */ +#ifdef SPI_CS_SEL  	SPI_CS_SEL &= ~M25_CS_MASK;	/* set CS pins as GPIO */ +#endif  } diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c new file mode 100644 index 00000000..e6c73a3c --- /dev/null +++ b/src/drivers/ao_pyro_slave.c @@ -0,0 +1,51 @@ +/* + * 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_product.h" + +struct ao_companion_command	ao_companion_command; + +static const struct ao_companion_setup	ao_telepyro_setup = { +	.board_id 		= AO_idProduct_NUMBER, +	.board_id_inverse	= ~AO_idProduct_NUMBER, +	.update_period		= 50, +	.channels		= AO_TELEPYRO_NUM_ADC, +}; + +void ao_spi_slave(void) +{ +	if (!ao_spi_read((uint8_t *) &ao_companion_command, +			 sizeof (ao_companion_command))) +		return; + +	/* Figure out the outbound data */ +	switch (ao_companion_command.command) { +	case AO_COMPANION_SETUP: +		ao_spi_write((uint8_t *) &ao_telepyro_setup, +			     sizeof (ao_telepyro_setup)); +		break; +	case AO_COMPANION_FETCH: +		ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, +			     AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); +		break; +	case AO_COMPANION_NOTIFY: +		break; +	default: +		return; +	} +} diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c new file mode 100644 index 00000000..e902318f --- /dev/null +++ b/src/drivers/ao_science_slave.c @@ -0,0 +1,62 @@ +/* + * 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_product.h" + +struct ao_companion_command	ao_companion_command; + +static const struct ao_companion_setup	ao_telescience_setup = { +	.board_id 		= AO_idProduct_NUMBER, +	.board_id_inverse	= ~AO_idProduct_NUMBER, +	.update_period		= 50, +	.channels		= AO_LOG_TELESCIENCE_NUM_ADC, +}; + +void ao_spi_slave(void) +{ +	if (!ao_spi_read((uint8_t *) &ao_companion_command, +			 sizeof (ao_companion_command))) +		return; + +	/* Figure out the outbound data */ +	switch (ao_companion_command.command) { +	case AO_COMPANION_SETUP: +		ao_spi_write((uint8_t *) &ao_telescience_setup, +			     sizeof (ao_telescience_setup)); +		break; +	case AO_COMPANION_FETCH: +		ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, +			     AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); +		break; +	case AO_COMPANION_NOTIFY: +		break; +	default: +		return; +	} + +	ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; +	if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { +		ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; +		if (ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { +			if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) +				ao_log_single_start(); +			else +				ao_log_single_stop(); +		} +	} +} diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt new file mode 100644 index 00000000..46c87db0 --- /dev/null +++ b/src/product/Makefile.telebt @@ -0,0 +1,98 @@ +# +# TeleBT build file +# +# Define TELEBT_VER, TELEBT_DEF, TELEBT_INC and TELEBT_SRC +# and include this file + +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 \ +	cc1111.h \ +	ao_product.h \ +	$(TELEBT_INC) + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_gps_print.c \ +	ao_monitor.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_state.c \ +	ao_stdio.c \ +	ao_task.c + +CC1111_SRC = \ +	ao_aes.c \ +	ao_dbg.c \ +	ao_dma.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_master.c \ +	ao_radio.c \ +	ao_radio_cmac.c \ +	ao_romconfig.c \ +	ao_serial.c \ +	ao_timer.c \ +	ao_usb.c \ +	_bp.c + +DRIVER_SRC = \ +	ao_btm.c + +PRODUCT_SRC = \ +	ao_telebt.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) \ +	$(TELEBT_SRC) + +PROG = telebt-v$(TELEBT_VER)-$(VERSION).ihx +PRODUCT=TeleBT-v$(TELEBT_VER) +PRODUCT_DEF=-DTELEBT_V_$(TELEBT_DEF) +IDPRODUCT=0x000e + +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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle new file mode 100644 index 00000000..56182b84 --- /dev/null +++ b/src/product/Makefile.teledongle @@ -0,0 +1,98 @@ +# +# TeleDongle build file +# +# The various teledongle versions differ only +# in minor pin variations +# so the per-board makefiles simply define +# TD_VER, TD_DEF and include +# this file + +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 \ +	cc1111.h \ +	ao_product.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_gps_print.c \ +	ao_monitor.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_rssi.c \ +	ao_state.c \ +	ao_stdio.c \ +	ao_task.c + +CC1111_SRC = \ +	ao_aes.c \ +	ao_dbg.c \ +	ao_dma.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_master.c \ +	ao_radio.c \ +	ao_radio_cmac.c \ +	ao_romconfig.c \ +	ao_timer.c \ +	ao_usb.c \ +	_bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ +	ao_teledongle.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROG = teledongle-v$(TD_VER)-$(VERSION).ihx +PRODUCT=TeleDongle-v$(TD_VER) +PRODUCT_DEF=-DTELEDONGLE_V_$(TD_DEF) +IDPRODUCT=0x000c + +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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch new file mode 100644 index 00000000..5da42e46 --- /dev/null +++ b/src/product/Makefile.telelaunch @@ -0,0 +1,101 @@ +# +# TeleLaunch build file +# +# define TELELAUNCH_VER, TELELAUNCH_DEF +# this file + +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 \ +	cc1111.h \ +	ao_product.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_convert.c \ +	ao_launch.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_stdio.c \ +	ao_storage.c \ +	ao_task.c + +CC1111_SRC = \ +	ao_adc.c \ +	ao_aes.c \ +	ao_beep.c \ +	ao_dbg.c \ +	ao_dma.c \ +	ao_ignite.c \ +	ao_intflash.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_slave.c \ +	ao_radio.c \ +	ao_radio_cmac.c \ +	ao_romconfig.c \ +	ao_serial.c \ +	ao_spi.c \ +	ao_timer.c \ +	ao_usb.c \ +	_bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ +	ao_telelaunch.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx +PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) +PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum new file mode 100644 index 00000000..2759ac52 --- /dev/null +++ b/src/product/Makefile.telemetrum @@ -0,0 +1,111 @@ +# +# TeleMetrum build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +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 \ +	cc1111.h \ +	altitude.h \ +	ao_kalman.h \ +	ao_product.h \ +	$(TM_INC) + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_convert.c \ +	ao_gps_report.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_stdio.c \ +	ao_storage.c \ +	ao_task.c \ +	ao_flight.c \ +	ao_sample.c \ +	ao_kalman.c \ +	ao_log.c \ +	ao_log_big.c \ +	ao_report.c \ +	ao_telemetry.c + +CC1111_SRC = \ +	ao_adc.c \ +	ao_beep.c \ +	ao_dbg.c \ +	ao_dma.c \ +	ao_ignite.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_slave.c \ +	ao_radio.c \ +	ao_romconfig.c \ +	ao_serial.c \ +	ao_spi.c \ +	ao_timer.c \ +	ao_usb.c \ +	_bp.c + +DRIVER_SRC = \ +	$(TM_SRC) + +PRODUCT_SRC = \ +	ao_telemetrum.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx +PRODUCT=TeleMetrum-v$(TM_VER) +PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) +IDPRODUCT=0x000b + +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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini new file mode 100644 index 00000000..7f251897 --- /dev/null +++ b/src/product/Makefile.telemini @@ -0,0 +1,100 @@ +# +# TeleMini build file +# +# Define TELEMINI_VER and TELEMINI_DEF and then +# include this file + +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 \ +	cc1111.h \ +	ao_product.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_convert.c \ +	ao_flight.c \ +	ao_kalman.c \ +	ao_log.c \ +	ao_log_tiny.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_report.c \ +	ao_sample.c \ +	ao_stdio.c \ +	ao_storage.c \ +	ao_task.c \ +	ao_telemetry.c + +CC1111_SRC = \ +	ao_adc.c \ +	ao_dma.c \ +	ao_ignite.c \ +	ao_intflash.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_slave.c \ +	ao_radio.c \ +	ao_romconfig.c \ +	ao_timer.c \ +	_bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ +	ao_telemini.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROG = telemini-v$(TELEMINI_VER)-$(VERSION).ihx +PRODUCT=TeleMini-v$(TELEMINI_VER) +PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) +IDPRODUCT=0x000a +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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano new file mode 100644 index 00000000..c47e95ff --- /dev/null +++ b/src/product/Makefile.telenano @@ -0,0 +1,99 @@ +# +# TeleNano build file +# +# Define TELENANO_VER and TELENANO_DEF and then +# include this file + +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 \ +	cc1111.h \ +	ao_product.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_convert.c \ +	ao_flight_nano.c \ +	ao_kalman.c \ +	ao_log.c \ +	ao_log_tiny.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_report.c \ +	ao_sample.c \ +	ao_stdio.c \ +	ao_storage.c \ +	ao_task.c \ +	ao_telemetry.c + +CC1111_SRC = \ +	ao_adc.c \ +	ao_dma.c \ +	ao_intflash.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_slave.c \ +	ao_radio.c \ +	ao_romconfig.c \ +	ao_timer.c \ +	_bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ +	ao_telenano.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROG = telenano-v$(TELENANO_VER)-$(VERSION).ihx +PRODUCT=TeleNano-v$(TELENANO_VER) +PRODUCT_DEF=-DTELENANO_V_$(TELENANO_DEF) +IDPRODUCT=0x000a +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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/ao_telebt.c b/src/product/ao_telebt.c index 85565172..9e409db7 100644 --- a/src/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,14 +37,23 @@ main(void)  	ao_storage_init();  #endif  	ao_usb_init(); -	ao_monitor_init(AO_LED_GREEN, TRUE); -	ao_rssi_init(AO_LED_RED); +	ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); +#if HAS_LOG +	ao_report_init(); +#endif  	ao_radio_init();  	ao_packet_master_init();  	ao_btm_init(); +#if HAS_LOG +	ao_log_single_init(); +#endif  #if HAS_DBG  	ao_dbg_init();  #endif +#if HAS_AES +	ao_aes_init(); +	ao_radio_cmac_init(); +#endif  	ao_config_init();  	ao_start_scheduler();  } diff --git a/src/ao_teledongle.c b/src/product/ao_teledongle.c index 008b200a..b8be9f45 100644 --- a/src/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -35,6 +35,8 @@ main(void)  #if HAS_DBG  	ao_dbg_init();  #endif +	ao_aes_init(); +	ao_radio_cmac_init();  	ao_config_init();  	ao_start_scheduler();  } diff --git a/src/ao_telemetrum.c b/src/product/ao_telemetrum.c index f560740a..f560740a 100644 --- a/src/ao_telemetrum.c +++ b/src/product/ao_telemetrum.c diff --git a/src/ao_telemini.c b/src/product/ao_telemini.c index fa23de01..fa23de01 100644 --- a/src/ao_telemini.c +++ b/src/product/ao_telemini.c diff --git a/src/ao_telenano.c b/src/product/ao_telenano.c index d91983d0..d91983d0 100644 --- a/src/ao_telenano.c +++ b/src/product/ao_telenano.c diff --git a/src/ao_adc_fake.c b/src/product/ao_telepyro.c index 6ca88d4e..a2b8f83c 100644 --- a/src/ao_adc_fake.c +++ b/src/product/ao_telepyro.c @@ -1,5 +1,5 @@  /* - * Copyright © 2009 Keith Packard <keithp@keithp.com> + * 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 @@ -17,11 +17,20 @@  #include "ao.h" -volatile __xdata struct ao_adc	ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t		ao_adc_head; - -/* Stub for systems which have no ADC */ -void -ao_adc_poll(void) +int +main(void)  { +	ao_clock_init(); + +	PORTE |= (1 << 6); +	DDRE |= (1 << 6); + +	ao_avr_stdio_init(); +	ao_timer_init(); +	ao_cmd_init(); +	ao_spi_slave_init(); +	ao_usb_init(); +	ao_adc_init(); +	ao_start_scheduler(); +	return 0;  } diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c new file mode 100644 index 00000000..45b6d40e --- /dev/null +++ b/src/product/ao_telescience.c @@ -0,0 +1,39 @@ +/* + * 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" + +int +main(void) +{ +	ao_clock_init(); + +	PORTE |= (1 << 6); +	DDRE |= (1 << 6); + +	ao_avr_stdio_init(); +	ao_timer_init(); +	ao_cmd_init(); +	ao_spi_init(); +	ao_spi_slave_init(); +	ao_storage_init(); +	ao_usb_init(); +	ao_adc_init(); +	ao_log_single_init(); +	ao_start_scheduler(); +	return 0; +} diff --git a/src/ao_teleterra.c b/src/product/ao_teleterra.c index d696b914..d696b914 100644 --- a/src/ao_teleterra.c +++ b/src/product/ao_teleterra.c diff --git a/src/ao_test.c b/src/product/ao_test.c index 14c2eb75..14c2eb75 100644 --- a/src/ao_test.c +++ b/src/product/ao_test.c diff --git a/src/ao_tidongle.c b/src/product/ao_tidongle.c index 3b7c2733..5adbb05c 100644 --- a/src/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -34,6 +34,8 @@ main(void)  	ao_rssi_init(AO_LED_RED);  	ao_radio_init();  	ao_dbg_init(); +	ao_aes_init(); +	ao_radio_cmac_init();  	ao_config_init();  	/* Bring up the USB link */  	P1DIR |= 1; diff --git a/src/telebt-v0.0/Makefile b/src/telebt-v0.0/Makefile index d8867b19..e89639ab 100644 --- a/src/telebt-v0.0/Makefile +++ b/src/telebt-v0.0/Makefile @@ -1 +1,9 @@ -include ../Makefile.proto +# +# TeleBT v0.0 build +# + +TELEBT_VER=0.0 +TELEBT_DEF=0_0 + +include ../product/Makefile.telebt + diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs deleted file mode 100644 index f0bb5e0c..00000000 --- a/src/telebt-v0.0/Makefile.defs +++ /dev/null @@ -1,8 +0,0 @@ -PROG = telebt-v0.0-$(VERSION).ihx - -SRC = \ -	$(TBT_BASE_SRC) - -PRODUCT=TeleBT-v0.0 -PRODUCT_DEF=-DTELEBT_V_0_0 -IDPRODUCT=0x000e diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index d8867b19..90cd3cac 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -1 +1,21 @@ -include ../Makefile.proto +# +# TeleBT v0.1 build +# + +TELEBT_VER=0.1 +TELEBT_DEF=0_1 + +TELEBT_INC = \ +	ao_25lc1024.h + +TELEBT_SRC = \ +	ao_beep.c \ +	ao_log_single.c \ +	ao_log_telem.c \ +	ao_report.c \ +	ao_spi.c \ +	ao_storage.c \ +	ao_m25.c + +include ../product/Makefile.telebt + diff --git a/src/telebt-v0.1/Makefile.defs b/src/telebt-v0.1/Makefile.defs deleted file mode 100644 index 50657c83..00000000 --- a/src/telebt-v0.1/Makefile.defs +++ /dev/null @@ -1,8 +0,0 @@ -PROG = telebt-v0.1-$(VERSION).ihx - -SRC = \ -	$(TBT_V_0_1_SRC) - -PRODUCT=TeleBT-v0.1 -PRODUCT_DEF=-DTELEBT_V_0_1 -IDPRODUCT=0x000e diff --git a/src/teledongle-v0.1/.sdcdbrc b/src/teledongle-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/teledongle-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/teledongle-v0.1/Makefile b/src/teledongle-v0.1/Makefile index d8867b19..48425107 100644 --- a/src/teledongle-v0.1/Makefile +++ b/src/teledongle-v0.1/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleDongle v0.2 build +# + +TD_VER=0.1 +TD_DEF=0_1 + +include ../product/Makefile.teledongle diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs deleted file mode 100644 index ceb80b7a..00000000 --- a/src/teledongle-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = teledongle-v0.1-$(VERSION).ihx - -SRC = \ -	$(TD_SRC) \ -	$(DBG_SRC) - -PRODUCT=TeleDongle-v0.1 -PRODUCT_DEF=-DTELEDONGLE_V_0_1 -IDPRODUCT=0x000c diff --git a/src/teledongle-v0.2/Makefile b/src/teledongle-v0.2/Makefile index d8867b19..ce4ab437 100644 --- a/src/teledongle-v0.2/Makefile +++ b/src/teledongle-v0.2/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleDongle v0.2 build +# + +TD_VER=0.2 +TD_DEF=0_2 + +include ../product/Makefile.teledongle
\ No newline at end of file diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs deleted file mode 100644 index ea9713b6..00000000 --- a/src/teledongle-v0.2/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = teledongle-v0.2-$(VERSION).ihx - -SRC = \ -	$(TD_SRC) \ -	$(DBG_SRC) - -PRODUCT=TeleDongle-v0.2 -PRODUCT_DEF=-DTELEDONGLE_V_0_2 -IDPRODUCT=0x000c diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore new file mode 100644 index 00000000..d25d7ad9 --- /dev/null +++ b/src/telelaunch-v0.1/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sky* +ao_product.h diff --git a/src/telelaunch-v0.1/.sdcdbrc b/src/telelaunch-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telelaunch-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile b/src/telelaunch-v0.1/Makefile new file mode 100644 index 00000000..b0d9d165 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile @@ -0,0 +1,4 @@ +TELELAUNCH_VER=0.1 +TELELAUNCH_DEF=0_1 + +include ../product/Makefile.telelaunch diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs new file mode 100644 index 00000000..56f5730b --- /dev/null +++ b/src/telelaunch-v0.1/Makefile.defs @@ -0,0 +1,14 @@ +PROG = telelaunch-v0.1-$(VERSION).ihx + +SRC = \ +	$(TLAUNCH_BASE_SRC) \ +	$(SPI_DRIVER_SRC) \ +	$(EE_DRIVER_SRC) \ +	ao_launch.c \ +	ao_aes.c \ +	ao_radio_cmac.c \ +	$(DBG_SRC) + +PRODUCT=TeleLaunch-v0.1 +PRODUCT_DEF=-DTELELAUNCH_V_0_1 +IDPRODUCT=0x000f diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile index d8867b19..00cdc9c5 100644 --- a/src/telemetrum-v0.1-sirf/Makefile +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v0.1 with SkyTraq GPS build +# + +TM_VER=0.1 +TM_DEF=0_1 + +TM_INC = \ +	ao_25lc1024.h + +TM_SRC = \ +	ao_gps_sirf.c \ +	ao_25lc1024.c + +include ../product/Makefile.telemetrum + diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs deleted file mode 100644 index ac8dcdb9..00000000 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ /dev/null @@ -1,12 +0,0 @@ -PROG = telemetrum-v0.1-sirf-$(VERSION).ihx - -SRC = \ -	$(TM_BASE_SRC) \ -	$(SPI_DRIVER_SRC) \ -	$(EE_DRIVER_SRC) \ -	$(SIRF_DRIVER_SRC) \ -	$(DBG_SRC) - -PRODUCT=TeleMetrum-v0.1-SiRF -PRODUCT_DEF=-DTELEMETRUM_V_0_1 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index d8867b19..e3c61db6 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v0.1 with SkyTraq GPS build +# + +TM_VER=0.1 +TM_DEF=0_1 + +TM_INC = \ +	ao_25lc1024.h + +TM_SRC = \ +	ao_gps_skytraq.c \ +	ao_25lc1024.c + +include ../product/Makefile.telemetrum + diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs deleted file mode 100644 index e032d1eb..00000000 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ /dev/null @@ -1,12 +0,0 @@ -PROG = telemetrum-v0.1-sky-$(VERSION).ihx - -SRC = \ -	$(TM_BASE_SRC) \ -	$(SPI_DRIVER_SRC) \ -	$(EE_DRIVER_SRC) \ -	$(SKY_DRIVER_SRC) \ -	$(DBG_SRC) - -PRODUCT=TeleMetrum-v0.1 -PRODUCT_DEF=-DTELEMETRUM_V_0_1 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.0/Makefile b/src/telemetrum-v1.0/Makefile index d8867b19..4aae84c8 100644 --- a/src/telemetrum-v1.0/Makefile +++ b/src/telemetrum-v1.0/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v1.0 build +# + +TM_VER=1.0 +TM_DEF=1_0 + +TM_INC = \ +	ao_at45db161d.h + +TM_SRC = \ +	ao_companion.c \ +	ao_gps_skytraq.c \ +	ao_at45db161d.c + +include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs deleted file mode 100644 index 5eefc392..00000000 --- a/src/telemetrum-v1.0/Makefile.defs +++ /dev/null @@ -1,13 +0,0 @@ -PROG = telemetrum-v1.0-$(VERSION).ihx - -SRC = \ -	$(TM_BASE_SRC) \ -	$(SPI_DRIVER_SRC) \ -	$(FLASH_DRIVER_SRC) \ -	$(SKY_DRIVER_SRC) \ -	$(COMPANION_SRC) \ -	$(DBG_SRC) - -PRODUCT=TeleMetrum-v1.0 -PRODUCT_DEF=-DTELEMETRUM_V_1_0 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile index d8867b19..4bea03db 100644 --- a/src/telemetrum-v1.1/Makefile +++ b/src/telemetrum-v1.1/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# AltOS build +# +# + +TM_VER=1.1 +TM_DEF=1_1 + +TM_INC = + +TM_SRC = \ +	ao_companion.c \ +	ao_gps_skytraq.c \ +	ao_m25.c + +include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs deleted file mode 100644 index 3c8b8793..00000000 --- a/src/telemetrum-v1.1/Makefile.defs +++ /dev/null @@ -1,13 +0,0 @@ -PROG = telemetrum-v1.1-$(VERSION).ihx - -SRC = \ -	$(TM_BASE_SRC) \ -	$(SPI_DRIVER_SRC) \ -	$(M25_DRIVER_SRC) \ -	$(SKY_DRIVER_SRC) \ -	$(COMPANION_SRC) \ -	$(DBG_SRC) - -PRODUCT=TeleMetrum-v1.1 -PRODUCT_DEF=-DTELEMETRUM_V_1_1 -IDPRODUCT=0x000b diff --git a/src/telemini-v1.0/Makefile b/src/telemini-v1.0/Makefile index d8867b19..4f1c8b51 100644 --- a/src/telemini-v1.0/Makefile +++ b/src/telemini-v1.0/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleMini build file +# + +TELEMINI_VER=1.0 +TELEMINI_DEF=1_0 + +include ../product/Makefile.telemini diff --git a/src/telemini-v1.0/Makefile.defs b/src/telemini-v1.0/Makefile.defs deleted file mode 100644 index 0e91f2fc..00000000 --- a/src/telemini-v1.0/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telemini-v1.0-$(VERSION).ihx - -SRC = \ -	$(TMINI_BASE_SRC) - -PRODUCT=TeleMini-v1.0 -PRODUCT_DEF=-DTELEMINI_V_1_0 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/telenano-v0.1/Makefile b/src/telenano-v0.1/Makefile index d8867b19..2714c1e9 100644 --- a/src/telenano-v0.1/Makefile +++ b/src/telenano-v0.1/Makefile @@ -1 +1,9 @@ -include ../Makefile.proto +# +# TeleNano build file +# + +TELENANO_VER=0.1 +TELENANO_DEF=0_1 + +include ../product/Makefile.telenano + diff --git a/src/telenano-v0.1/Makefile.defs b/src/telenano-v0.1/Makefile.defs deleted file mode 100644 index 34cf69d1..00000000 --- a/src/telenano-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telenano-v0.1-$(VERSION).ihx - -SRC = \ -	$(TNANO_BASE_SRC) - -PRODUCT=TeleNano-v0.1 -PRODUCT_DEF=-DTELENANO_V_0_1 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile new file mode 100644 index 00000000..2f664fcb --- /dev/null +++ b/src/telepyro-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ +	ao.h \ +	ao_usb.h \ +	ao_pins.h \ +	altitude.h + +ALTOS_SRC = \ +	ao_clock.c \ +	ao_cmd.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_product.c \ +	ao_stdio.c \ +	ao_task.c \ +	ao_timer.c \ +	ao_led.c \ +	ao_avr_stdio.c \ +	ao_romconfig.c \ +	ao_usb_avr.c \ +	ao_adc_avr.c \ +	ao_pyro_slave.c \ +	ao_spi_slave.c + +PRODUCT=TelePyro-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELEPYRO +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telepyro-v0.1 + +SRC=$(ALTOS_SRC) ao_telepyro.c +OBJ=$(SRC:.c=.o) + +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) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) +	$(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) +	avr-size $(PROG) +	$(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex +	$(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude +	nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h +	$(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean:	clean + +clean: +	rm -f $(OBJ) +	rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile new file mode 100644 index 00000000..a6797cbe --- /dev/null +++ b/src/telescience-v0.1/Makefile @@ -0,0 +1,112 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ +	ao.h \ +	ao_usb.h \ +	ao_pins.h \ +	altitude.h + +# +# Common AltOS sources +# +TELESCIENCE_STORAGE= \ +	ao_m25.c \ +	ao_spi_usart.c \ +	ao_storage.c \ + +ALTOS_SRC = \ +	ao_clock.c \ +	ao_cmd.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_product.c \ +	ao_stdio.c \ +	ao_task.c \ +	ao_timer.c \ +	ao_led.c \ +	ao_avr_stdio.c \ +	ao_romconfig.c \ +	ao_usb_avr.c \ +	ao_adc_avr.c \ +	ao_science_slave.c \ +	ao_spi_slave.c \ +	ao_log_single.c \ +	ao_log_telescience.c \ +	$(TELESCIENCE_STORAGE) + +PRODUCT=TeleScience-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELESCIENCE +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telescience-v0.1 + +SRC=$(ALTOS_SRC) ao_telescience.c +OBJ=$(SRC:.c=.o) + +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) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) +	$(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) +	avr-size $(PROG) +	$(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex +	$(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude +	nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h +	$(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean:	clean + +clean: +	rm -f $(OBJ) +	rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h diff --git a/src/test/Makefile b/src/test/Makefile index 33203ffd..333850e4 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,9 +1,8 @@ -vpath % .. -vpath % ../kalman +vpath % ..:../core:../drivers  PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test -CFLAGS=-I.. -I. +CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g  all: $(PROGS) @@ -13,22 +12,19 @@ clean:  install:  ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h -	cc -g -o $@ $< +	cc $(CFLAGS) -o $@ $<  ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kalman.c altitude.h ao_kalman.h -	cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c +	cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c  ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kalman.c altitude.h ao_kalman.h -	cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c +	cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c  ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h -	cc -g -o $@ $< +	cc $(CFLAGS) -o $@ $<  ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h -	cc -g -o $@ $< +	cc $(CFLAGS) -o $@ $<  ao_convert_test: ao_convert_test.c ao_convert.c altitude.h -	cc -g -o $@ $< - -../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c -	sh $< > $@ +	cc $(CFLAGS) -o $@ $< diff --git a/src/ao_flight_test.c b/src/test/ao_flight_test.c index 56733c89..56733c89 100644 --- a/src/ao_flight_test.c +++ b/src/test/ao_flight_test.c diff --git a/src/ao_gps_test.c b/src/test/ao_gps_test.c index 93d7a9ab..93d7a9ab 100644 --- a/src/ao_gps_test.c +++ b/src/test/ao_gps_test.c diff --git a/src/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index a78fae0f..a78fae0f 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index d8867b19..057e420b 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -1 +1,94 @@ -include ../Makefile.proto +# +# TIDongle build file +# + +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 \ +	cc1111.h \ +	ao_product.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_gps_print.c \ +	ao_monitor.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_rssi.c \ +	ao_state.c \ +	ao_stdio.c \ +	ao_task.c + +CC1111_SRC = \ +	ao_aes.c \ +	ao_dbg.c \ +	ao_dma.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_packet_master.c \ +	ao_radio.c \ +	ao_radio_cmac.c \ +	ao_romconfig.c \ +	ao_timer.c \ +	ao_usb.c \ +	_bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ +	ao_tidongle.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROG = tidongle-$(VERSION).ihx +PRODUCT=TIDongle +PRODUCT_DEF=-DTIDONGLE +IDPRODUCT=0x000a + +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) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) +	rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) +	rm -f ao_product.h +	rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs deleted file mode 100644 index 0e13cb20..00000000 --- a/src/tidongle/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = tidongle-$(VERSION).ihx - -SRC = \ -	$(TI_SRC) - -PRODUCT=TIDongle - -PRODUCT_DEF=-DTIDONGLE -IDPRODUCT=0x000a diff --git a/src/ao-make-product.5c b/src/util/ao-make-product.5c index 5f2eb8e8..5f2eb8e8 100644 --- a/src/ao-make-product.5c +++ b/src/util/ao-make-product.5c diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem new file mode 100644 index 00000000..c73edbd1 --- /dev/null +++ b/src/util/check-avr-mem @@ -0,0 +1,9 @@ +#!/bin/sh +nm "$@" | +grep ' N _end' | +awk '{ iram = strtonum("0x" $1) % 0x10000; +if ( iram > 0xaff) { +	printf ("%d bytes of ram more than %d available\n", iram, 0xaff); +	exit(1); +} else +	exit(0); }' diff --git a/src/check-stack b/src/util/check-stack index 1e8044e0..1e8044e0 100755 --- a/src/check-stack +++ b/src/util/check-stack diff --git a/src/gps-cksum b/src/util/gps-cksum index a08153bf..a08153bf 100755 --- a/src/gps-cksum +++ b/src/util/gps-cksum diff --git a/src/make-altitude b/src/util/make-altitude index 716aa8a8..716aa8a8 100644 --- a/src/make-altitude +++ b/src/util/make-altitude diff --git a/src/make-kalman b/src/util/make-kalman index 9ac35134..397d6020 100644 --- a/src/make-kalman +++ b/src/util/make-kalman @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/bash -cd ../kalman +cd $1 2> /dev/null 1>&2  SIGMA_BOTH="-M 2 -H 6 -A 2"  SIGMA_BARO="-M 2 -H 6 -A 2" diff --git a/src/sirf-cksum b/src/util/sirf-cksum index b905f318..b905f318 100755 --- a/src/sirf-cksum +++ b/src/util/sirf-cksum diff --git a/src/skytraq-cksum b/src/util/skytraq-cksum index ab0464a7..ab0464a7 100644 --- a/src/skytraq-cksum +++ b/src/util/skytraq-cksum  | 
