From fc2e5beb9173663e1e37a9b5a7b6eea1046222f7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Dec 2012 11:11:39 -0800 Subject: altos: Log baro readings for MicroPeak This logs barometric data every 192ms (more or less) to the 504 remaining bytes of internal EEPROM storage in the ATtiny85. This provides 48.192 seconds of logging. Signed-off-by: Keith Packard --- src/micropeak/Makefile | 12 ++-- src/micropeak/ao_log_micro.c | 65 ++++++++++------------ src/micropeak/ao_log_micro.h | 19 ++++--- src/micropeak/ao_micropeak.c | 129 +++++++------------------------------------ src/micropeak/ao_micropeak.h | 56 +++++++++++++++++++ 5 files changed, 121 insertions(+), 160 deletions(-) create mode 100644 src/micropeak/ao_micropeak.h diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 0c48ed66..82944cb1 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -20,13 +20,6 @@ ifndef VERSION include ../Version endif -# Support for a logging EEPROM -# -#EEPROM_SRC=ao_async.c \ -# ao_i2c_attiny.c \ -# ao_at24c.c -# - ALTOS_SRC = \ ao_micropeak.c \ ao_spi_attiny.c \ @@ -39,7 +32,8 @@ ALTOS_SRC = \ ao_notask.c \ ao_eeprom_tiny.c \ ao_panic.c \ - $(EEPROM_SRC) + ao_log_micro.c \ + ao_async.c INC=\ ao.h \ @@ -48,6 +42,8 @@ INC=\ ao_arch_funcs.h \ ao_exti.h \ ao_ms5607.h \ + ao_log_micro.h \ + ao_micropeak.h \ altitude-pa.h IDPRODUCT=0 diff --git a/src/micropeak/ao_log_micro.c b/src/micropeak/ao_log_micro.c index eda0d1d2..40a7a35d 100644 --- a/src/micropeak/ao_log_micro.c +++ b/src/micropeak/ao_log_micro.c @@ -16,58 +16,53 @@ */ #include +#include #include #include -#if HAS_EEPROM - -ao_pos_t ao_log_micro_pos; +static uint16_t ao_log_offset = STARTING_LOG_OFFSET; void -ao_log_micro_data(uint32_t data) +ao_log_micro_save(void) { - ao_storage_write(ao_log_micro_pos, &data, sizeof (data)); - ao_log_micro_pos += sizeof (data); + uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); + ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); + ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); + ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); } -uint32_t ao_log_last_ground; -uint32_t ao_log_last_done; - -uint8_t -ao_log_micro_scan(void) +void +ao_log_micro_restore(void) { - uint32_t data; - ao_pos_t pos; + ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); + ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); +} - ao_storage_read(0, &data, sizeof (data)); - if ((data & AO_LOG_MICRO_MASK) != AO_LOG_MICRO_GROUND) - return 0; +void +ao_log_micro_data(void) +{ + uint16_t low_bits = pa; - ao_log_last_ground = data & ~(AO_LOG_MICRO_MASK); - for (pos = 4; pos < ao_storage_total; pos += 4) { - ao_storage_read(pos, &data, sizeof (data)); - if ((data & AO_LOG_MICRO_MASK) == AO_LOG_MICRO_GROUND) { - ao_log_last_done = data & ~(AO_LOG_MICRO_MASK); - return 1; - } + if (ao_log_offset < MAX_LOG_OFFSET) { + ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); + ao_log_offset += sizeof (low_bits); } - return 0; } void ao_log_micro_dump(void) { - ao_pos_t pos; - uint8_t data[4]; - uint8_t i; + uint16_t n_samples; + uint16_t nbytes; + uint8_t byte; + uint16_t b; - for (pos = 0; pos < ao_storage_total; pos += 4) { - ao_storage_read(pos, data, 4); - for (i = 0; i < 4; i++) - ao_async_byte(data[i]); - if (data[3] == (uint8_t) (AO_LOG_MICRO_GROUND >> 24)) - break; + ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); + nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; + ao_async_byte('M'); + ao_async_byte('P'); + for (b = 0; b < nbytes; b++) { + ao_eeprom_read(b, &byte, 1); + ao_async_byte(byte); } } - -#endif diff --git a/src/micropeak/ao_log_micro.h b/src/micropeak/ao_log_micro.h index 15b2d178..976852ee 100644 --- a/src/micropeak/ao_log_micro.h +++ b/src/micropeak/ao_log_micro.h @@ -18,19 +18,20 @@ #ifndef _AO_LOG_MICRO_H_ #define _AO_LOG_MICRO_H_ -#define AO_LOG_MICRO_GROUND (0l << 24) -#define AO_LOG_MICRO_DATA (1l << 24) -#define AO_LOG_MICRO_DONE (0xaal << 24) -#define AO_LOG_MICRO_MASK (0xffl << 24) +#define PA_GROUND_OFFSET 0 +#define PA_MIN_OFFSET 4 +#define N_SAMPLES_OFFSET 8 +#define STARTING_LOG_OFFSET 10 +#define MAX_LOG_OFFSET 512 void -ao_log_micro_data(uint32_t data); +ao_log_micro_save(void); -extern uint32_t ao_log_last_ground; -extern uint32_t ao_log_last_done; +void +ao_log_micro_restore(void); -uint8_t -ao_log_micro_scan(void); +void +ao_log_micro_data(void); void ao_log_micro_dump(void); diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c index 525cfa42..3bbc7eea 100644 --- a/src/micropeak/ao_micropeak.c +++ b/src/micropeak/ao_micropeak.c @@ -16,22 +16,22 @@ */ #include +#include #include #include static struct ao_ms5607_sample sample; static struct ao_ms5607_value value; -static uint32_t pa; -static uint32_t pa_sum; -static uint32_t pa_avg; -static int32_t pa_diff; -static uint32_t pa_ground; -static uint32_t pa_min; -static uint32_t pa_interval_min, pa_interval_max; -static alt_t ground_alt, max_alt; +uint32_t pa; +uint32_t pa_avg; +uint32_t pa_ground; +uint32_t pa_min; +alt_t ground_alt, max_alt; alt_t ao_max_height; +static uint32_t pa_sum; + static void ao_pa_get(void) { @@ -40,22 +40,6 @@ ao_pa_get(void) pa = value.pres; } -#define FILTER_SHIFT 3 -#define SAMPLE_SLEEP AO_MS_TO_TICKS(96) - -/* 16 sample, or about two seconds worth */ -#define GROUND_AVG_SHIFT 4 -#define GROUND_AVG (1 << GROUND_AVG_SHIFT) - -/* Pressure change (in Pa) to detect boost */ -#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ - -/* Wait after power on before doing anything to give the user time to assemble the rocket */ -#define BOOST_DELAY AO_SEC_TO_TICKS(30) - -/* Pressure change (in Pa) to detect landing */ -#define LAND_DETECT 12 /* 1m at sea level, 1.2m at 2000m */ - static void ao_compute_height(void) { @@ -64,90 +48,30 @@ ao_compute_height(void) ao_max_height = max_alt - ground_alt; } -#if !HAS_EEPROM - -#define PA_GROUND_OFFSET 0 -#define PA_MIN_OFFSET 4 -#define N_SAMPLES_OFFSET 8 -#define STARTING_LOG_OFFSET 10 -#define MAX_LOG_OFFSET 512 - -static uint16_t ao_log_offset = STARTING_LOG_OFFSET; - -void -ao_save_flight(void) -{ - uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); - ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); - ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); - ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); -} - -void -ao_restore_flight(void) -{ - ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); - ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); -} - -void -ao_log_micro(void) -{ - uint16_t low_bits = pa; - - if (ao_log_offset < MAX_LOG_OFFSET) { - ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); - ao_log_offset += sizeof (low_bits); - } -} -#endif - int main(void) { int16_t sample_count; uint16_t time; -#if HAS_EEPROM - uint8_t dump_eeprom = 0; -#endif + uint32_t pa_interval_min, pa_interval_max; + int32_t pa_diff; + ao_led_init(LEDS_AVAILABLE); ao_timer_init(); -#if HAS_EEPROM - - /* Set MOSI and CLK as inputs with pull-ups */ - DDRB &= ~(1 << 0) | (1 << 2); - PORTB |= (1 << 0) | (1 << 2); - - /* Check to see if either MOSI or CLK are pulled low by the - * user shorting them to ground. If so, dump the eeprom out - * via the LED. Wait for the shorting wire to go away before - * continuing. - */ - while ((PINB & ((1 << 0) | (1 << 2))) != ((1 << 0) | (1 << 2))) - dump_eeprom = 1; - PORTB &= ~(1 << 0) | (1 << 2); - - ao_i2c_init(); -#endif - ao_restore_flight(); - ao_compute_height(); - /* Give the person a second to get their finger out of the way */ - ao_delay(AO_MS_TO_TICKS(1000)); - ao_report_altitude(); - + /* Init external hardware */ ao_spi_init(); ao_ms5607_init(); ao_ms5607_setup(); -#if HAS_EEPROM - ao_storage_init(); - - /* Check to see if there's a flight recorded in memory */ - if (dump_eeprom && ao_log_micro_scan()) - ao_log_micro_dump(); -#endif + /* Give the person a second to get their finger out of the way */ + ao_delay(AO_MS_TO_TICKS(1000)); + ao_log_micro_restore(); + ao_compute_height(); + ao_report_altitude(); + ao_log_micro_dump(); + ao_delay(BOOST_DELAY); /* Wait for motion, averaging values to get ground pressure */ time = ao_time(); @@ -182,10 +106,6 @@ main(void) pa_ground >>= FILTER_SHIFT; -#if HAS_EEPROM - ao_log_micro_data(AO_LOG_MICRO_GROUND | pa_ground); -#endif - /* Now sit around until the pressure is stable again and record the max */ sample_count = 0; @@ -200,12 +120,8 @@ main(void) ao_pa_get(); if ((sample_count & 3) == 0) ao_led_off(AO_LED_REPORT); -#if HAS_EEPROM - ao_log_micro_data(AO_LOG_MICRO_DATA | pa); -#else if (sample_count & 1) - ao_log_micro(); -#endif + ao_log_micro_data(); pa_avg = pa_avg - (pa_avg >> FILTER_SHIFT) + pa; if (pa_avg < pa_min) pa_min = pa_avg; @@ -228,10 +144,7 @@ main(void) } } pa_min >>= FILTER_SHIFT; -#if HAS_EEPROM - ao_log_micro_data(AO_LOG_MICRO_DONE | pa_min); -#endif - ao_save_flight(); + ao_log_micro_save(); ao_compute_height(); ao_report_altitude(); for (;;) { diff --git a/src/micropeak/ao_micropeak.h b/src/micropeak/ao_micropeak.h new file mode 100644 index 00000000..e408d7c5 --- /dev/null +++ b/src/micropeak/ao_micropeak.h @@ -0,0 +1,56 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MICROPEAK_H_ +#define _AO_MICROPEAK_H_ + +#define FILTER_SHIFT 3 +#define SAMPLE_SLEEP AO_MS_TO_TICKS(96) + +/* 16 sample, or about two seconds worth */ +#define GROUND_AVG_SHIFT 4 +#define GROUND_AVG (1 << GROUND_AVG_SHIFT) + +/* Pressure change (in Pa) to detect boost */ +#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ + +/* Wait after power on before doing anything to give the user time to assemble the rocket */ +#define BOOST_DELAY AO_SEC_TO_TICKS(30) + +/* Pressure change (in Pa) to detect landing */ +#define LAND_DETECT 12 /* 1m at sea level, 1.2m at 2000m */ + +/* Current sensor pressure value */ +extern uint32_t pa; + +/* IIR filtered pressure value */ +extern uint32_t pa_avg; + +/* Average pressure value on ground */ +extern uint32_t pa_ground; + +/* Minimum recorded filtered pressure value */ +extern uint32_t pa_min; + +/* Pressure values converted to altitudes */ +extern alt_t ground_alt, max_alt; + +/* max_alt - ground_alt */ +extern alt_t ao_max_height; + +#endif + -- cgit v1.2.3 From 23dc9a63ae8bc982d9352cfb7a3f508d8a08c374 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Dec 2012 22:58:49 -0800 Subject: altos: Make micropeak 'serial' interface work I prototyped the mpserial interface on a breadboard and tuned the circuit to register the LED correctly. Then adjusted the serial code to send bits at the right speed and format. The logging contents are now in hexdecimal with a CCITT CRC-16 computed to verify correct reception. Signed-off-by: Keith Packard --- src/micropeak/Makefile | 2 +- src/micropeak/ao_async.c | 43 +++++++++++++++++++++++++++++----- src/micropeak/ao_async.h | 6 +++++ src/micropeak/ao_log_micro.c | 55 +++++++++++++++++++++++++++++++++++++++++++- src/micropeak/ao_micropeak.c | 1 + 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 82944cb1..ff0a4499 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -50,7 +50,7 @@ IDPRODUCT=0 PRODUCT=MicroPeak-v0.1 PRODUCT_DEF=-DMICROPEAK CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers -CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DATTINY +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY NICKLE=nickle diff --git a/src/micropeak/ao_async.c b/src/micropeak/ao_async.c index 04bba9e8..3556f54c 100644 --- a/src/micropeak/ao_async.c +++ b/src/micropeak/ao_async.c @@ -21,20 +21,51 @@ #define AO_ASYNC_BAUD 38400l #define AO_ASYNC_DELAY (uint8_t) (1000000l / AO_ASYNC_BAUD) +#define LED_PORT PORTB + +void +ao_async_start(void) +{ + LED_PORT |= (1 << AO_LED_SERIAL); +} + +void +ao_async_stop(void) +{ + LED_PORT &= ~(1 << AO_LED_SERIAL); +} + void ao_async_byte(uint8_t byte) { uint8_t b; uint16_t w; - /* start bit */ - - /* start data stop */ - w = 0x001 | (byte << 1) | 0x000; + /* start data stop */ + w = (0x000 << 0) | (byte << 1) | (0x001 << 9); + ao_arch_block_interrupts(); for (b = 0; b < 10; b++) { - ao_led_set((w & 1) << AO_LED_SERIAL); + uint8_t v = LED_PORT & ~(1 << AO_LED_SERIAL); + v |= (w & 1) << AO_LED_SERIAL; + LED_PORT = v; w >>= 1; - ao_delay_us(26); + + /* Carefully timed to hit around 9600 baud */ + asm volatile ("nop"); + asm volatile ("nop"); + + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); } + ao_arch_release_interrupts(); } diff --git a/src/micropeak/ao_async.h b/src/micropeak/ao_async.h index a06d2e1a..1b239712 100644 --- a/src/micropeak/ao_async.h +++ b/src/micropeak/ao_async.h @@ -18,6 +18,12 @@ #ifndef _AO_ASYNC_H_ #define _AO_ASYNC_H_ +void +ao_async_start(void); + +void +ao_async_stop(void); + void ao_async_byte(uint8_t byte); diff --git a/src/micropeak/ao_log_micro.c b/src/micropeak/ao_log_micro.c index 40a7a35d..d665efb5 100644 --- a/src/micropeak/ao_log_micro.c +++ b/src/micropeak/ao_log_micro.c @@ -49,6 +49,46 @@ ao_log_micro_data(void) } } +#define POLY 0x8408 + +static uint16_t +ao_log_micro_crc(uint16_t crc, uint8_t byte) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + if ((crc & 0x0001) ^ (byte & 0x0001)) + crc = (crc >> 1) ^ POLY; + else + crc = crc >> 1; + byte >>= 1; + } + return crc; +} + +static void +ao_log_hex_nibble(uint8_t b) +{ + if (b < 10) + ao_async_byte('0' + b); + else + ao_async_byte('a' - 10 + b); +} + +static void +ao_log_hex(uint8_t b) +{ + ao_log_hex_nibble(b>>4); + ao_log_hex_nibble(b&0xf); +} + +static void +ao_log_newline(void) +{ + ao_async_byte('\r'); + ao_async_byte('\n'); +} + void ao_log_micro_dump(void) { @@ -56,13 +96,26 @@ ao_log_micro_dump(void) uint16_t nbytes; uint8_t byte; uint16_t b; + uint16_t crc = 0xffff; ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); + if (n_samples == 0xffff) + n_samples = 0; nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; + ao_async_start(); ao_async_byte('M'); ao_async_byte('P'); for (b = 0; b < nbytes; b++) { + if ((b & 0xf) == 0) + ao_log_newline(); ao_eeprom_read(b, &byte, 1); - ao_async_byte(byte); + ao_log_hex(byte); + crc = ao_log_micro_crc(crc, byte); } + ao_log_newline(); + crc = ~crc; + ao_log_hex(crc >> 8); + ao_log_hex(crc); + ao_log_newline(); + ao_async_stop(); } diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c index 3bbc7eea..f579a09a 100644 --- a/src/micropeak/ao_micropeak.c +++ b/src/micropeak/ao_micropeak.c @@ -19,6 +19,7 @@ #include #include #include +#include static struct ao_ms5607_sample sample; static struct ao_ms5607_value value; -- cgit v1.2.3 From d7d35b0bd86b912c43a21a275347fca201079847 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Dec 2012 00:39:37 -0800 Subject: altos: Add distinct LED pattern before writing log data Otherwise, the whole log looks like a an extra altitude digit. Signed-off-by: Keith Packard --- src/micropeak/ao_micropeak.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c index f579a09a..82012800 100644 --- a/src/micropeak/ao_micropeak.c +++ b/src/micropeak/ao_micropeak.c @@ -49,6 +49,17 @@ ao_compute_height(void) ao_max_height = max_alt - ground_alt; } +static void +ao_pips(void) +{ + uint8_t i; + for (i = 0; i < 10; i++) { + ao_led_toggle(AO_LED_REPORT); + ao_delay(AO_MS_TO_TICKS(80)); + } + ao_delay(AO_MS_TO_TICKS(200)); +} + int main(void) { @@ -71,6 +82,7 @@ main(void) ao_log_micro_restore(); ao_compute_height(); ao_report_altitude(); + ao_pips(); ao_log_micro_dump(); ao_delay(BOOST_DELAY); -- cgit v1.2.3 From 669cde8a87d88ceae89e369c1d38b88c9f8198cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 25 Dec 2012 14:19:19 -0800 Subject: Move libaltos to top level This will let it be shared by the new MicroPeak gui Signed-off-by: Keith Packard --- Makefile.am | 2 +- altosui/Makefile.am | 36 +- altosui/libaltos/.gitignore | 12 - altosui/libaltos/Makefile-standalone | 126 ---- altosui/libaltos/Makefile.am | 54 -- altosui/libaltos/cjnitest.c | 71 -- altosui/libaltos/libaltos.c | 1311 --------------------------------- altosui/libaltos/libaltos.dylib | Bin 41648 -> 0 bytes altosui/libaltos/libaltos.h | 119 --- altosui/libaltos/libaltos.i0 | 5 - configure.ac | 3 +- libaltos/.gitignore | 12 + libaltos/Makefile-standalone | 126 ++++ libaltos/Makefile.am | 54 ++ libaltos/cjnitest.c | 71 ++ libaltos/libaltos.c | 1316 ++++++++++++++++++++++++++++++++++ libaltos/libaltos.dylib | Bin 0 -> 41648 bytes libaltos/libaltos.h | 119 +++ libaltos/libaltos.i0 | 5 + 19 files changed, 1724 insertions(+), 1718 deletions(-) delete mode 100644 altosui/libaltos/.gitignore delete mode 100644 altosui/libaltos/Makefile-standalone delete mode 100644 altosui/libaltos/Makefile.am delete mode 100644 altosui/libaltos/cjnitest.c delete mode 100644 altosui/libaltos/libaltos.c delete mode 100755 altosui/libaltos/libaltos.dylib delete mode 100644 altosui/libaltos/libaltos.h delete mode 100644 altosui/libaltos/libaltos.i0 create mode 100644 libaltos/.gitignore create mode 100644 libaltos/Makefile-standalone create mode 100644 libaltos/Makefile.am create mode 100644 libaltos/cjnitest.c create mode 100644 libaltos/libaltos.c create mode 100755 libaltos/libaltos.dylib create mode 100644 libaltos/libaltos.h create mode 100644 libaltos/libaltos.i0 diff --git a/Makefile.am b/Makefile.am index aaa0ae14..2e45aff0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src doc altoslib altosui ao-tools ao-utils altosdroid +SUBDIRS=src doc altoslib libaltos altosui ao-tools ao-utils altosdroid EXTRA_DIST = ChangeLog diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 306a396e..a42426cd 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=libaltos + JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation @@ -6,7 +6,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" bin_SCRIPTS=altosui @@ -233,13 +233,13 @@ $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) jar cfm $@ Manifest.txt \ $(ICONJAR) \ -C classes altosui \ - -C libaltos libaltosJNI + -C ../libaltos libaltosJNI $(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICONS) jar cfm $@ Manifest-fat.txt \ $(ICONJAR) \ -C classes altosui \ - -C libaltos libaltosJNI + -C ../libaltos libaltosJNI Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ @@ -256,43 +256,43 @@ altosui: Makefile altosui-test: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "./*:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@ + echo 'exec java -cp "./*:../libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ altosui-jdb: Makefile echo "#!/bin/sh" > $@ - echo 'exec jdb -classpath "classes:libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="libaltos/.libs" altosui/AltosUI "$$@"' >> $@ + echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ chmod +x $@ libaltos.so: build-libaltos -rm -f "$@" - $(LN_S) libaltos/.libs/"$@" . + $(LN_S) ../libaltos/.libs/"$@" . libaltos.dylib: -rm -f "$@" - $(LN_S) libaltos/"$@" . + $(LN_S) ../libaltos/"$@" . -altos.dll: libaltos/altos.dll +altos.dll: ../libaltos/altos.dll -rm -f "$@" - $(LN_S) libaltos/"$@" . + $(LN_S) ../libaltos/"$@" . -altos64.dll: libaltos/altos64.dll +altos64.dll: ../libaltos/altos64.dll -rm -f "$@" - $(LN_S) libaltos/"$@" . + $(LN_S) ../libaltos/"$@" . -libaltos/.libs/libaltos.so: build-libaltos +../libaltos/.libs/libaltos.so: build-libaltos -libaltos/altos.dll: build-altos-dll +../libaltos/altos.dll: build-altos-dll -libaltos/altos64.dll: build-altos64-dll +../libaltos/altos64.dll: build-altos64-dll build-libaltos: - +cd libaltos && make libaltos.la + +cd ../libaltos && make libaltos.la build-altos-dll: - +cd libaltos && make altos.dll + +cd ../libaltos && make altos.dll build-altos64-dll: - +cd libaltos && make altos64.dll + +cd ../libaltos && make altos64.dll $(ALTOSLIB_CLASS): -rm -f "$@" diff --git a/altosui/libaltos/.gitignore b/altosui/libaltos/.gitignore deleted file mode 100644 index c490e6f8..00000000 --- a/altosui/libaltos/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -*.so -*.lo -*.la -*.java -*.class -.libs/ -classlibaltos.stamp -libaltos_wrap.c -libaltosJNI -cjnitest -libaltos.swig -swig_bindings/ diff --git a/altosui/libaltos/Makefile-standalone b/altosui/libaltos/Makefile-standalone deleted file mode 100644 index 4e438050..00000000 --- a/altosui/libaltos/Makefile-standalone +++ /dev/null @@ -1,126 +0,0 @@ -OS:=$(shell uname) - -# -# Linux -# -ifeq ($(OS),Linux) - -JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include - -OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) - -OS_APP_CFLAGS=$(OS_LIB_CFLAGS) - -OS_LDFLAGS= - -LIBNAME=libaltos.so -EXEEXT= -endif - -# -# Darwin (Mac OS X) -# -ifeq ($(OS),Darwin) - -OS_LIB_CFLAGS=\ - -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \ - --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \ - -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \ - -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ - -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers -OS_APP_CFLAGS=$(OS_LIB_CFLAGS) - -OS_LDFLAGS =\ - -framework IOKit -framework CoreFoundation - -LIBNAME=libaltos.dylib -EXEEXT= - -endif - -# -# Windows -# -ifneq (,$(findstring MINGW,$(OS))) - -CC=gcc - -OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL -OS_APP_CFLAGS = -DWINDOWS -mconsole - -OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \ - -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias - -LIBNAME=altos.dll - -EXEEXT=.exe - -endif - -.SUFFIXES: .java .class - -CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" - -SWIG_DIR=swig_bindings/java -SWIG_FILE=$(SWIG_DIR)/libaltos.swig -SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c - -JNI_DIR=libaltosJNI -JNI_FILE=$(JNI_DIR)/libaltosJNI.java -JNI_SRCS=$(JNI_FILE) \ - $(JNI_DIR)/SWIGTYPE_p_altos_file.java \ - $(JNI_DIR)/SWIGTYPE_p_altos_list.java \ - $(JNI_DIR)/altos_device.java \ - $(JNI_DIR)/libaltos.java - -JAVAFILES=\ - $(JNI_SRCS) - -CLASSFILES = $(JAVAFILES:%.java=%.class) - -JAVAFLAGS=-Xlint:unchecked - -CJNITEST=cjnitest$(EXEEXT) - -all: $(LIBNAME) $(CJNITEST) $(CLASSFILES) - -.java.class: - javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java - -CFLAGS=$(OS_LIB_CFLAGS) -O -I. - -LDFLAGS=$(OS_LDFLAGS) - -HEADERS=libaltos.h -SRCS = libaltos.c $(SWIG_WRAP) -OBJS = $(SRCS:%.c=%.o) -LIBS = $(DARWIN_LIBS) - -$(CJNITEST): cjnitest.c $(LIBNAME) - $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS) - -$(LIBNAME): $(OBJS) - $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) - -clean: - rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o - rm -rf swig_bindings libaltosJNI - -distclean: clean - -$(JNI_FILE): libaltos.i0 $(HEADERS) - mkdir -p $(SWIG_DIR) - mkdir -p libaltosJNI - sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE) - swig -java -package libaltosJNI $(SWIG_FILE) - cp swig_bindings/java/*.java libaltosJNI - -$(SWIG_WRAP): $(JNI_FILE) - -ifeq ($(OS),Linux) -install: $(LIBNAME) - install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) - -endif - -.NOTPARALLEL: diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am deleted file mode 100644 index b5ab1ddb..00000000 --- a/altosui/libaltos/Makefile.am +++ /dev/null @@ -1,54 +0,0 @@ -JAVAC=javac -AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -AM_JAVACFLAGS=-encoding UTF-8 - -altoslibdir=$(libdir)/altos - -altoslib_LTLIBRARIES=libaltos.la - -libaltos_la_LDFLAGS = -version-info 1:0:1 - -libaltos_la_SOURCES=\ - libaltos.c \ - libaltos_wrap.c - -noinst_PROGRAMS=cjnitest - -cjnitest_LDADD=libaltos.la - -LIBS=-lbluetooth - -HFILES=libaltos.h - -SWIG_FILE=libaltos.swig - -CLASSDIR=libaltosJNI - -$(SWIG_FILE): libaltos.i0 $(HFILES) - sed 's;//%;%;' libaltos.i0 $(HFILES) > $(SWIG_FILE) - -all-local: classlibaltos.stamp - -libaltos_wrap.c: classlibaltos.stamp - -classlibaltos.stamp: $(SWIG_FILE) - swig -java -package libaltosJNI $(SWIG_FILE) - mkdir -p libaltosJNI - $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \ - touch classlibaltos.stamp - -MINGCC32=i686-w64-mingw32-gcc -MINGCC64=x86_64-w64-mingw32-gcc -MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE) -MINGLIBS=-lsetupapi - -fat: altos.dll altos64.dll - -altos.dll: $(libaltos_la_SOURCES) - $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) - -altos64.dll: $(libaltos_la_SOURCES) - $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) - -clean-local: - -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c deleted file mode 100644 index f0fe78f7..00000000 --- a/altosui/libaltos/cjnitest.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include "libaltos.h" - -static void -altos_puts(struct altos_file *file, char *string) -{ - char c; - - while ((c = *string++)) - altos_putchar(file, c); -} - -main () -{ - struct altos_device device; - struct altos_list *list; - struct altos_bt_device bt_device; - struct altos_bt_list *bt_list; - - altos_init(); - list = altos_list_start(); - while (altos_list_next(list, &device)) { - struct altos_file *file; - int c; - - printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product, - device.name, device.serial, device.path); - - file = altos_open(&device); - if (!file) { - printf("altos_open failed\n"); - continue; - } - altos_puts(file,"v\nc s\n"); - altos_flush(file); - while ((c = altos_getchar(file, 100)) >= 0) { - putchar (c); - } - if (c != LIBALTOS_TIMEOUT) - printf ("getchar returns %d\n", c); - altos_close(file); - } - altos_list_finish(list); -#if HAS_BLUETOOTH - bt_list = altos_bt_list_start(8); - while (altos_bt_list_next(bt_list, &bt_device)) { - printf ("%s %s\n", bt_device.name, bt_device.addr); - if (strncmp(bt_device.name, "TeleBT", 6) == 0) { - struct altos_file *file; - - int c; - file = altos_bt_open(&bt_device); - if (!file) { - printf("altos_bt_open failed\n"); - continue; - } - altos_puts(file,"v\nc s\n"); - altos_flush(file); - while ((c = altos_getchar(file, 100)) >= 0) { - putchar(c); - } - if (c != LIBALTOS_TIMEOUT) - printf("getchar returns %d\n", c); - altos_close(file); - } - } - altos_bt_list_finish(bt_list); -#endif - altos_fini(); - return 0; -} diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c deleted file mode 100644 index ab6ca878..00000000 --- a/altosui/libaltos/libaltos.c +++ /dev/null @@ -1,1311 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "libaltos.h" -#include -#include -#include - -#define USB_VENDOR_FSF 0xfffe -#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF -#define USB_PRODUCT_ALTUSMETRUM 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MAX 0x00ff - -#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ - (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ - (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) - -#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" - -#define USE_POLL - -PUBLIC int -altos_init(void) -{ - return LIBALTOS_SUCCESS; -} - -PUBLIC void -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 - -/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */ -static char * -altos_strndup (const char *s, size_t n) -{ - size_t len = strlen (s); - char *ret; - - if (len <= n) - return strdup (s); - ret = malloc(n + 1); - strncpy(ret, s, n); - ret[n] = '\0'; - return ret; -} - -#else -#define altos_strndup strndup -#endif - -#ifdef POSIX_TTY - -#include -#include -#include -#include -#include - -#define USB_BUF_SIZE 64 - -struct altos_file { - int fd; -#ifdef USE_POLL - int pipe[2]; -#else - int out_fd; -#endif - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - 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) -{ - struct altos_file *file = calloc (sizeof (struct altos_file), 1); - int ret; - struct termios term; - - 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) { - altos_set_last_posix_error(); - free(file); - return NULL; - } -#ifdef USE_POLL - pipe(file->pipe); -#else - file->out_fd = open(device->path, O_RDWR | O_NOCTTY); - if (file->out_fd < 0) { - altos_set_last_posix_error(); - close(file->fd); - free(file); - return NULL; - } -#endif - ret = tcgetattr(file->fd, &term); - if (ret < 0) { - altos_set_last_posix_error(); - close(file->fd); -#ifndef USE_POLL - close(file->out_fd); -#endif - free(file); - return NULL; - } - cfmakeraw(&term); -#ifdef USE_POLL - term.c_cc[VMIN] = 1; - term.c_cc[VTIME] = 0; -#else - term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; -#endif - ret = tcsetattr(file->fd, TCSAFLUSH, &term); - if (ret < 0) { - altos_set_last_posix_error(); - close(file->fd); -#ifndef USE_POLL - close(file->out_fd); -#endif - free(file); - return NULL; - } - return file; -} - -PUBLIC void -altos_close(struct altos_file *file) -{ - if (file->fd != -1) { - int fd = file->fd; - file->fd = -1; -#ifdef USE_POLL - write(file->pipe[1], "\r", 1); -#else - close(file->out_fd); - file->out_fd = -1; -#endif - close(fd); - } -} - -PUBLIC void -altos_free(struct altos_file *file) -{ - altos_close(file); - free(file); -} - -PUBLIC int -altos_flush(struct altos_file *file) -{ - if (file->out_used && 0) { - printf ("flush \""); - fwrite(file->out_data, 1, file->out_used, stdout); - printf ("\"\n"); - } - while (file->out_used) { - int ret; - - if (file->fd < 0) - return -EBADF; -#ifdef USE_POLL - ret = write (file->fd, file->out_data, file->out_used); -#else - ret = write (file->out_fd, file->out_data, file->out_used); -#endif - if (ret < 0) { - altos_set_last_posix_error(); - return -last_error.code; - } - if (ret) { - memmove(file->out_data, file->out_data + ret, - file->out_used - ret); - file->out_used -= ret; - } - } - return 0; -} - -PUBLIC int -altos_putchar(struct altos_file *file, char c) -{ - int ret; - - if (file->out_used == USB_BUF_SIZE) { - ret = altos_flush(file); - if (ret) { - return ret; - } - } - file->out_data[file->out_used++] = c; - ret = 0; - if (file->out_used == USB_BUF_SIZE) - ret = altos_flush(file); - return ret; -} - -#ifdef USE_POLL -#include -#endif - -static int -altos_fill(struct altos_file *file, int timeout) -{ - int ret; -#ifdef USE_POLL - struct pollfd fd[2]; -#endif - - if (timeout == 0) - timeout = -1; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; -#ifdef USE_POLL - fd[0].fd = file->fd; - fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; - fd[1].fd = file->pipe[0]; - fd[1].events = POLLIN; - ret = poll(fd, 2, timeout); - if (ret < 0) { - altos_set_last_posix_error(); - return LIBALTOS_ERROR; - } - if (ret == 0) - return LIBALTOS_TIMEOUT; - - if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL)) - return LIBALTOS_ERROR; - if (fd[0].revents & POLLIN) -#endif - { - ret = read(file->fd, file->in_data, USB_BUF_SIZE); - if (ret < 0) { - altos_set_last_posix_error(); - return LIBALTOS_ERROR; - } - file->in_read = 0; - file->in_used = ret; -#ifndef USE_POLL - if (ret == 0 && timeout > 0) - return LIBALTOS_TIMEOUT; -#endif - } - } - if (file->in_used && 0) { - printf ("fill \""); - fwrite(file->in_data, 1, file->in_used, stdout); - printf ("\"\n"); - } - return 0; -} - -PUBLIC int -altos_getchar(struct altos_file *file, int timeout) -{ - int ret; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; - ret = altos_fill(file, timeout); - if (ret) - return ret; - } - return file->in_data[file->in_read++]; -} - -#endif /* POSIX_TTY */ - -/* - * Scan for Altus Metrum devices by looking through /sys - */ - -#ifdef LINUX - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static char * -cc_fullname (char *dir, char *file) -{ - char *new; - int dlen = strlen (dir); - int flen = strlen (file); - int slen = 0; - - if (dir[dlen-1] != '/') - slen = 1; - new = malloc (dlen + slen + flen + 1); - if (!new) - return 0; - strcpy(new, dir); - if (slen) - strcat (new, "/"); - strcat(new, file); - return new; -} - -static char * -cc_basename(char *file) -{ - char *b; - - b = strrchr(file, '/'); - if (!b) - return file; - return b + 1; -} - -static char * -load_string(char *dir, char *file) -{ - char *full = cc_fullname(dir, file); - char line[4096]; - char *r; - FILE *f; - int rlen; - - f = fopen(full, "r"); - free(full); - if (!f) - return NULL; - r = fgets(line, sizeof (line), f); - fclose(f); - if (!r) - return NULL; - rlen = strlen(r); - if (r[rlen-1] == '\n') - r[rlen-1] = '\0'; - return strdup(r); -} - -static int -load_hex(char *dir, char *file) -{ - char *line; - char *end; - long i; - - line = load_string(dir, file); - if (!line) - return -1; - i = strtol(line, &end, 16); - free(line); - if (end == line) - return -1; - return i; -} - -static int -load_dec(char *dir, char *file) -{ - char *line; - char *end; - long i; - - line = load_string(dir, file); - if (!line) - return -1; - i = strtol(line, &end, 10); - free(line); - if (end == line) - return -1; - return i; -} - -static int -dir_filter_tty_colon(const struct dirent *d) -{ - return strncmp(d->d_name, "tty:", 4) == 0; -} - -static int -dir_filter_tty(const struct dirent *d) -{ - return strncmp(d->d_name, "tty", 3) == 0; -} - -struct altos_usbdev { - char *sys; - char *tty; - char *manufacturer; - char *product_name; - int serial; /* AltOS always uses simple integer serial numbers */ - int idProduct; - int idVendor; -}; - -static char * -usb_tty(char *sys) -{ - char *base; - int num_configs; - int config; - struct dirent **namelist; - int interface; - int num_interfaces; - char endpoint_base[20]; - char *endpoint_full; - char *tty_dir; - int ntty; - char *tty; - - base = cc_basename(sys); - num_configs = load_hex(sys, "bNumConfigurations"); - num_interfaces = load_hex(sys, "bNumInterfaces"); - for (config = 1; config <= num_configs; config++) { - for (interface = 0; interface < num_interfaces; interface++) { - sprintf(endpoint_base, "%s:%d.%d", - base, config, interface); - endpoint_full = cc_fullname(sys, endpoint_base); - - /* Check for tty:ttyACMx style names - */ - ntty = scandir(endpoint_full, &namelist, - dir_filter_tty_colon, - alphasort); - if (ntty > 0) { - free(endpoint_full); - tty = cc_fullname("/dev", namelist[0]->d_name + 4); - free(namelist); - return tty; - } - - /* Check for tty/ttyACMx style names - */ - tty_dir = cc_fullname(endpoint_full, "tty"); - free(endpoint_full); - ntty = scandir(tty_dir, &namelist, - dir_filter_tty, - alphasort); - free (tty_dir); - if (ntty > 0) { - tty = cc_fullname("/dev", namelist[0]->d_name); - free(namelist); - return tty; - } - } - } - return NULL; -} - -static struct altos_usbdev * -usb_scan_device(char *sys) -{ - struct altos_usbdev *usbdev; - - usbdev = calloc(1, sizeof (struct altos_usbdev)); - if (!usbdev) - return NULL; - usbdev->sys = strdup(sys); - usbdev->manufacturer = load_string(sys, "manufacturer"); - usbdev->product_name = load_string(sys, "product"); - usbdev->serial = load_dec(sys, "serial"); - usbdev->idProduct = load_hex(sys, "idProduct"); - usbdev->idVendor = load_hex(sys, "idVendor"); - usbdev->tty = usb_tty(sys); - return usbdev; -} - -static void -usbdev_free(struct altos_usbdev *usbdev) -{ - free(usbdev->sys); - free(usbdev->manufacturer); - free(usbdev->product_name); - /* this can get used as a return value */ - if (usbdev->tty) - free(usbdev->tty); - free(usbdev); -} - -#define USB_DEVICES "/sys/bus/usb/devices" - -static int -dir_filter_dev(const struct dirent *d) -{ - const char *n = d->d_name; - char c; - - while ((c = *n++)) { - if (isdigit(c)) - continue; - if (c == '-') - continue; - if (c == '.' && n != d->d_name + 1) - continue; - return 0; - } - return 1; -} - -struct altos_list { - struct altos_usbdev **dev; - int current; - int ndev; -}; - -struct altos_list * -altos_list_start(void) -{ - int e; - struct dirent **ents; - char *dir; - struct altos_usbdev *dev; - struct altos_list *devs; - int n; - - devs = calloc(1, sizeof (struct altos_list)); - if (!devs) - return NULL; - - n = scandir (USB_DEVICES, &ents, - dir_filter_dev, - alphasort); - if (!n) - return 0; - for (e = 0; e < n; e++) { - dir = cc_fullname(USB_DEVICES, ents[e]->d_name); - dev = usb_scan_device(dir); - free(dir); - if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { - if (devs->dev) - devs->dev = realloc(devs->dev, - (devs->ndev + 1) * sizeof (struct usbdev *)); - else - devs->dev = malloc (sizeof (struct usbdev *)); - devs->dev[devs->ndev++] = dev; - } - } - free(ents); - devs->current = 0; - return devs; -} - -int -altos_list_next(struct altos_list *list, struct altos_device *device) -{ - struct altos_usbdev *dev; - if (list->current >= list->ndev) - return 0; - dev = list->dev[list->current]; - strcpy(device->name, dev->product_name); - device->vendor = dev->idVendor; - device->product = dev->idProduct; - strcpy(device->path, dev->tty); - device->serial = dev->serial; - list->current++; - return 1; -} - -void -altos_list_finish(struct altos_list *usbdevs) -{ - int i; - - if (!usbdevs) - return; - for (i = 0; i < usbdevs->ndev; i++) - usbdev_free(usbdevs->dev[i]); - free(usbdevs); -} - -struct altos_bt_list { - inquiry_info *ii; - 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) -{ - struct altos_bt_list *bt_list; - - bt_list = calloc(1, sizeof (struct altos_bt_list)); - if (!bt_list) - goto no_bt_list; - - bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info)); - if (!bt_list->ii) - goto no_ii; - bt_list->dev_id = hci_get_route(NULL); - if (bt_list->dev_id < 0) - goto no_dev_id; - - bt_list->sock = hci_open_dev(bt_list->dev_id); - if (bt_list->sock < 0) - goto no_sock; - - bt_list->num_rsp = hci_inquiry(bt_list->dev_id, - inquiry_time, - INQUIRY_MAX_RSP, - NULL, - &bt_list->ii, - IREQ_CACHE_FLUSH); - if (bt_list->num_rsp < 0) - goto no_rsp; - - bt_list->rsp = 0; - return bt_list; - -no_rsp: - close(bt_list->sock); -no_sock: -no_dev_id: - free(bt_list->ii); -no_ii: - free(bt_list); -no_bt_list: - return NULL; -} - -int -altos_bt_list_next(struct altos_bt_list *bt_list, - struct altos_bt_device *device) -{ - inquiry_info *ii; - - if (bt_list->rsp >= bt_list->num_rsp) - return 0; - - ii = &bt_list->ii[bt_list->rsp]; - ba2str(&ii->bdaddr, device->addr); - memset(&device->name, '\0', sizeof (device->name)); - if (hci_read_remote_name(bt_list->sock, &ii->bdaddr, - sizeof (device->name), - device->name, 0) < 0) { - strcpy(device->name, "[unknown]"); - } - bt_list->rsp++; - return 1; -} - -void -altos_bt_list_finish(struct altos_bt_list *bt_list) -{ - close(bt_list->sock); - free(bt_list->ii); - 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) -{ - struct sockaddr_rc addr = { 0 }; - int s, status; - struct altos_file *file; - - file = calloc(1, sizeof (struct altos_file)); - if (!file) - goto no_file; - file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (file->fd < 0) { - altos_set_last_posix_error(); - goto no_sock; - } - - addr.rc_family = AF_BLUETOOTH; - addr.rc_channel = 1; - str2ba(device->addr, &addr.rc_bdaddr); - - status = connect(file->fd, - (struct sockaddr *)&addr, - sizeof(addr)); - if (status < 0) { - altos_set_last_posix_error(); - goto no_link; - } - sleep(1); - -#ifdef USE_POLL - pipe(file->pipe); -#else - file->out_fd = dup(file->fd); -#endif - return file; -no_link: - close(s); -no_sock: - free(file); -no_file: - return NULL; -} - -#endif - -#ifdef DARWIN - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct altos_list { - io_iterator_t iterator; -}; - -static int -get_string(io_object_t object, CFStringRef entry, char *result, int result_len) -{ - CFTypeRef entry_as_string; - Boolean got_string; - - entry_as_string = IORegistryEntrySearchCFProperty (object, - kIOServicePlane, - entry, - kCFAllocatorDefault, - kIORegistryIterateRecursively); - if (entry_as_string) { - got_string = CFStringGetCString(entry_as_string, - result, result_len, - kCFStringEncodingASCII); - - CFRelease(entry_as_string); - if (got_string) - return 1; - } - return 0; -} - -static int -get_number(io_object_t object, CFStringRef entry, int *result) -{ - CFTypeRef entry_as_number; - Boolean got_number; - - entry_as_number = IORegistryEntrySearchCFProperty (object, - kIOServicePlane, - entry, - kCFAllocatorDefault, - kIORegistryIterateRecursively); - if (entry_as_number) { - got_number = CFNumberGetValue(entry_as_number, - kCFNumberIntType, - result); - if (got_number) - return 1; - } - return 0; -} - -PUBLIC struct altos_list * -altos_list_start(void) -{ - struct altos_list *list = calloc (sizeof (struct altos_list), 1); - CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); - io_iterator_t tdIterator; - io_object_t tdObject; - kern_return_t ret; - int i; - - ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); - if (ret != kIOReturnSuccess) - return NULL; - return list; -} - -PUBLIC int -altos_list_next(struct altos_list *list, struct altos_device *device) -{ - io_object_t object; - char serial_string[128]; - - for (;;) { - object = IOIteratorNext(list->iterator); - if (!object) - return 0; - - if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) || - !get_number (object, CFSTR(kUSBProductID), &device->product)) - continue; - if (device->vendor != 0xfffe) - continue; - if (device->product < 0x000a || 0x0013 < device->product) - continue; - if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) && - get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) && - get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { - device->serial = atoi(serial_string); - return 1; - } - } -} - -PUBLIC void -altos_list_finish(struct altos_list *list) -{ - IOObjectRelease (list->iterator); - 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 - - -#ifdef WINDOWS - -#include -#include -#include - -struct altos_list { - HDEVINFO dev_info; - int index; -}; - -#define USB_BUF_SIZE 64 - -struct altos_file { - HANDLE handle; - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - int in_read; - OVERLAPPED ov_read; - BOOL pend_read; - OVERLAPPED ov_write; -}; - -static void -_altos_set_last_windows_error(char *file, int line) -{ - DWORD error = GetLastError(); - TCHAR message[1024]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, - 0, - error, - 0, - message, - sizeof (message) / sizeof (TCHAR), - NULL); - if (error != ERROR_SUCCESS) - printf ("%s:%d %s\n", file, line, message); - altos_set_last_error(error, message); -} - -#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__) - -PUBLIC struct altos_list * -altos_list_start(void) -{ - struct altos_list *list = calloc(1, sizeof (struct altos_list)); - - if (!list) - return NULL; - list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, - DIGCF_ALLCLASSES|DIGCF_PRESENT); - if (list->dev_info == INVALID_HANDLE_VALUE) { - altos_set_last_windows_error(); - free(list); - return NULL; - } - list->index = 0; - return list; -} - -PUBLIC int -altos_list_next(struct altos_list *list, struct altos_device *device) -{ - SP_DEVINFO_DATA dev_info_data; - BYTE port[128]; - DWORD port_len; - char friendlyname[256]; - BYTE symbolic[256]; - DWORD symbolic_len; - HKEY dev_key; - unsigned int vid, pid; - int serial; - HRESULT result; - DWORD friendlyname_type; - DWORD friendlyname_len; - - dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); - while(SetupDiEnumDeviceInfo(list->dev_info, list->index, - &dev_info_data)) - { - list->index++; - - dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data, - 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; - } - - /* Fetch symbolic name for this device and parse out - * the vid/pid/serial info */ - symbolic_len = sizeof(symbolic); - 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; - } - vid = pid = serial = 0; - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, - "%04X", &vid); - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, - "%04X", &pid); - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, - "%d", &serial); - if (!USB_IS_ALTUSMETRUM(vid, pid)) { - RegCloseKey(dev_key); - continue; - } - - /* Fetch the com port name */ - port_len = sizeof (port); - result = RegQueryValueEx(dev_key, "PortName", NULL, NULL, - port, &port_len); - RegCloseKey(dev_key); - if (result != 0) { - altos_set_last_windows_error(); - printf("failed to get PortName\n"); - continue; - } - - /* Fetch the device description which is the device name, - * with firmware that has unique USB ids */ - friendlyname_len = sizeof (friendlyname); - if(!SetupDiGetDeviceRegistryProperty(list->dev_info, - &dev_info_data, - SPDRP_FRIENDLYNAME, - &friendlyname_type, - (BYTE *)friendlyname, - sizeof(friendlyname), - &friendlyname_len)) - { - altos_set_last_windows_error(); - printf("Failed to get friendlyname\n"); - continue; - } - device->vendor = vid; - device->product = pid; - device->serial = serial; - strcpy(device->name, friendlyname); - - strcpy(device->path, (char *) port); - return 1; - } - result = GetLastError(); - if (result != ERROR_NO_MORE_ITEMS) { - altos_set_last_windows_error(); - printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); - } - return 0; -} - -PUBLIC void -altos_list_finish(struct altos_list *list) -{ - SetupDiDestroyDeviceInfoList(list->dev_info); - free(list); -} - -static int -altos_queue_read(struct altos_file *file) -{ - DWORD got; - if (file->pend_read) - return LIBALTOS_SUCCESS; - - if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { - if (GetLastError() != ERROR_IO_PENDING) { - altos_set_last_windows_error(); - return LIBALTOS_ERROR; - } - file->pend_read = TRUE; - } else { - file->pend_read = FALSE; - file->in_read = 0; - file->in_used = got; - } - return LIBALTOS_SUCCESS; -} - -static int -altos_wait_read(struct altos_file *file, int timeout) -{ - DWORD ret; - DWORD got; - - if (!file->pend_read) - return LIBALTOS_SUCCESS; - - if (!timeout) - timeout = INFINITE; - - ret = WaitForSingleObject(file->ov_read.hEvent, timeout); - switch (ret) { - case WAIT_OBJECT_0: - 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; - break; - case WAIT_TIMEOUT: - return LIBALTOS_TIMEOUT; - break; - default: - return LIBALTOS_ERROR; - } - return LIBALTOS_SUCCESS; -} - -static int -altos_fill(struct altos_file *file, int timeout) -{ - int ret; - - if (file->in_read < file->in_used) - return LIBALTOS_SUCCESS; - - file->in_read = file->in_used = 0; - - ret = altos_queue_read(file); - if (ret) - return ret; - ret = altos_wait_read(file, timeout); - if (ret) - return ret; - - return LIBALTOS_SUCCESS; -} - -PUBLIC int -altos_flush(struct altos_file *file) -{ - DWORD put; - unsigned char *data = file->out_data; - int used = file->out_used; - DWORD ret; - - while (used) { - if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { - if (GetLastError() != ERROR_IO_PENDING) { - altos_set_last_windows_error(); - printf ("\tflush write error\n"); - 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)) { - altos_set_last_windows_error(); - printf ("\tflush result error\n"); - return LIBALTOS_ERROR; - } - break; - default: - altos_set_last_windows_error(); - printf ("\tflush wait error\n"); - return LIBALTOS_ERROR; - } - } - data += put; - used -= put; - } - file->out_used = 0; - return LIBALTOS_SUCCESS; -} - -PUBLIC struct altos_file * -altos_open(struct altos_device *device) -{ - struct altos_file *file = calloc (1, sizeof (struct altos_file)); - char full_name[64]; - COMMTIMEOUTS timeouts; - - if (!file) - return NULL; - - strcpy(full_name, "\\\\.\\"); - strcat(full_name, device->path); - file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - if (file->handle == INVALID_HANDLE_VALUE) { - altos_set_last_windows_error(); - printf ("cannot open %s\n", full_name); - free(file); - return NULL; - } - file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; - timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */ - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 0; - SetCommTimeouts(file->handle, &timeouts); - - return file; -} - -PUBLIC void -altos_close(struct altos_file *file) -{ - if (file->handle != INVALID_HANDLE_VALUE) { - CloseHandle(file->handle); - file->handle = INVALID_HANDLE_VALUE; - SetEvent(file->ov_read.hEvent); - SetEvent(file->ov_write.hEvent); - CloseHandle(file->ov_read.hEvent); - CloseHandle(file->ov_write.hEvent); - } -} - -PUBLIC void -altos_free(struct altos_file *file) -{ - altos_close(file); - free(file); -} - -PUBLIC int -altos_putchar(struct altos_file *file, char c) -{ - int ret; - - if (file->out_used == USB_BUF_SIZE) { - ret = altos_flush(file); - if (ret) - return ret; - } - file->out_data[file->out_used++] = c; - if (file->out_used == USB_BUF_SIZE) - return altos_flush(file); - return LIBALTOS_SUCCESS; -} - -PUBLIC int -altos_getchar(struct altos_file *file, int timeout) -{ - int ret; - while (file->in_read == file->in_used) { - if (file->handle == INVALID_HANDLE_VALUE) - return LIBALTOS_ERROR; - ret = altos_fill(file, timeout); - if (ret) - return ret; - } - 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.dylib b/altosui/libaltos/libaltos.dylib deleted file mode 100755 index 1038817d..00000000 Binary files a/altosui/libaltos/libaltos.dylib and /dev/null differ diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h deleted file mode 100644 index f90fbb87..00000000 --- a/altosui/libaltos/libaltos.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _LIBALTOS_H_ -#define _LIBALTOS_H_ - -#include - -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef BUILD_STATIC -# ifdef BUILD_DLL -# define PUBLIC __declspec(dllexport) -# else -# define PUBLIC __declspec(dllimport) -# endif -# endif /* BUILD_STATIC */ -#endif - -#ifndef PUBLIC -# define PUBLIC -#endif - -struct altos_device { - //%immutable; - int vendor; - int product; - int serial; - char name[256]; - char path[256]; - //%mutable; -}; - -struct altos_bt_device { - //%immutable; - char name[256]; - char addr[20]; - //%mutable; -}; - -struct altos_error { - int code; - char string[1024]; -}; - -#define LIBALTOS_SUCCESS 0 -#define LIBALTOS_ERROR -1 -#define LIBALTOS_TIMEOUT -2 - -/* Returns 0 for success, < 0 on error */ -PUBLIC int -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); - -/* Returns 1 for success, zero on end of list */ -PUBLIC int -altos_list_next(struct altos_list *list, struct altos_device *device); - -PUBLIC void -altos_list_finish(struct altos_list *list); - -PUBLIC struct altos_file * -altos_open(struct altos_device *device); - -PUBLIC void -altos_close(struct altos_file *file); - -PUBLIC void -altos_free(struct altos_file *file); - -/* Returns < 0 for error */ -PUBLIC int -altos_putchar(struct altos_file *file, char c); - -/* Returns < 0 for error */ -PUBLIC int -altos_flush(struct altos_file *file); - -/* Returns < 0 for error or timeout. timeout of 0 == wait forever */ -PUBLIC int -altos_getchar(struct altos_file *file, int timeout); - -PUBLIC struct altos_bt_list * -altos_bt_list_start(int inquiry_time); - -PUBLIC int -altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); - -PUBLIC void -altos_bt_list_finish(struct altos_bt_list *list); - -PUBLIC void -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 /* _LIBALTOS_H_ */ diff --git a/altosui/libaltos/libaltos.i0 b/altosui/libaltos/libaltos.i0 deleted file mode 100644 index d06468f5..00000000 --- a/altosui/libaltos/libaltos.i0 +++ /dev/null @@ -1,5 +0,0 @@ -%module libaltos -%{ -#include "libaltos.h" -%} - diff --git a/configure.ac b/configure.ac index bee9480d..e3b1185f 100644 --- a/configure.ac +++ b/configure.ac @@ -149,7 +149,8 @@ altoslib/Makefile altosui/Makefile altosui/AltosVersion.java altosui/Info.plist -altosui/libaltos/Makefile +libaltos/Makefile +micropeak/Makefile altosdroid/Makefile altosdroid/local.properties ao-tools/Makefile diff --git a/libaltos/.gitignore b/libaltos/.gitignore new file mode 100644 index 00000000..c490e6f8 --- /dev/null +++ b/libaltos/.gitignore @@ -0,0 +1,12 @@ +*.so +*.lo +*.la +*.java +*.class +.libs/ +classlibaltos.stamp +libaltos_wrap.c +libaltosJNI +cjnitest +libaltos.swig +swig_bindings/ diff --git a/libaltos/Makefile-standalone b/libaltos/Makefile-standalone new file mode 100644 index 00000000..4e438050 --- /dev/null +++ b/libaltos/Makefile-standalone @@ -0,0 +1,126 @@ +OS:=$(shell uname) + +# +# Linux +# +ifeq ($(OS),Linux) + +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include + +OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +OS_APP_CFLAGS=$(OS_LIB_CFLAGS) + +OS_LDFLAGS= + +LIBNAME=libaltos.so +EXEEXT= +endif + +# +# Darwin (Mac OS X) +# +ifeq ($(OS),Darwin) + +OS_LIB_CFLAGS=\ + -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \ + --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \ + -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \ + -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ + -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers +OS_APP_CFLAGS=$(OS_LIB_CFLAGS) + +OS_LDFLAGS =\ + -framework IOKit -framework CoreFoundation + +LIBNAME=libaltos.dylib +EXEEXT= + +endif + +# +# Windows +# +ifneq (,$(findstring MINGW,$(OS))) + +CC=gcc + +OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL +OS_APP_CFLAGS = -DWINDOWS -mconsole + +OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \ + -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias + +LIBNAME=altos.dll + +EXEEXT=.exe + +endif + +.SUFFIXES: .java .class + +CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" + +SWIG_DIR=swig_bindings/java +SWIG_FILE=$(SWIG_DIR)/libaltos.swig +SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c + +JNI_DIR=libaltosJNI +JNI_FILE=$(JNI_DIR)/libaltosJNI.java +JNI_SRCS=$(JNI_FILE) \ + $(JNI_DIR)/SWIGTYPE_p_altos_file.java \ + $(JNI_DIR)/SWIGTYPE_p_altos_list.java \ + $(JNI_DIR)/altos_device.java \ + $(JNI_DIR)/libaltos.java + +JAVAFILES=\ + $(JNI_SRCS) + +CLASSFILES = $(JAVAFILES:%.java=%.class) + +JAVAFLAGS=-Xlint:unchecked + +CJNITEST=cjnitest$(EXEEXT) + +all: $(LIBNAME) $(CJNITEST) $(CLASSFILES) + +.java.class: + javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java + +CFLAGS=$(OS_LIB_CFLAGS) -O -I. + +LDFLAGS=$(OS_LDFLAGS) + +HEADERS=libaltos.h +SRCS = libaltos.c $(SWIG_WRAP) +OBJS = $(SRCS:%.c=%.o) +LIBS = $(DARWIN_LIBS) + +$(CJNITEST): cjnitest.c $(LIBNAME) + $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS) + +$(LIBNAME): $(OBJS) + $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) + +clean: + rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o + rm -rf swig_bindings libaltosJNI + +distclean: clean + +$(JNI_FILE): libaltos.i0 $(HEADERS) + mkdir -p $(SWIG_DIR) + mkdir -p libaltosJNI + sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE) + swig -java -package libaltosJNI $(SWIG_FILE) + cp swig_bindings/java/*.java libaltosJNI + +$(SWIG_WRAP): $(JNI_FILE) + +ifeq ($(OS),Linux) +install: $(LIBNAME) + install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) + +endif + +.NOTPARALLEL: diff --git a/libaltos/Makefile.am b/libaltos/Makefile.am new file mode 100644 index 00000000..b5ab1ddb --- /dev/null +++ b/libaltos/Makefile.am @@ -0,0 +1,54 @@ +JAVAC=javac +AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) +AM_JAVACFLAGS=-encoding UTF-8 + +altoslibdir=$(libdir)/altos + +altoslib_LTLIBRARIES=libaltos.la + +libaltos_la_LDFLAGS = -version-info 1:0:1 + +libaltos_la_SOURCES=\ + libaltos.c \ + libaltos_wrap.c + +noinst_PROGRAMS=cjnitest + +cjnitest_LDADD=libaltos.la + +LIBS=-lbluetooth + +HFILES=libaltos.h + +SWIG_FILE=libaltos.swig + +CLASSDIR=libaltosJNI + +$(SWIG_FILE): libaltos.i0 $(HFILES) + sed 's;//%;%;' libaltos.i0 $(HFILES) > $(SWIG_FILE) + +all-local: classlibaltos.stamp + +libaltos_wrap.c: classlibaltos.stamp + +classlibaltos.stamp: $(SWIG_FILE) + swig -java -package libaltosJNI $(SWIG_FILE) + mkdir -p libaltosJNI + $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \ + touch classlibaltos.stamp + +MINGCC32=i686-w64-mingw32-gcc +MINGCC64=x86_64-w64-mingw32-gcc +MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE) +MINGLIBS=-lsetupapi + +fat: altos.dll altos64.dll + +altos.dll: $(libaltos_la_SOURCES) + $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) + +altos64.dll: $(libaltos_la_SOURCES) + $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) + +clean-local: + -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll diff --git a/libaltos/cjnitest.c b/libaltos/cjnitest.c new file mode 100644 index 00000000..f0fe78f7 --- /dev/null +++ b/libaltos/cjnitest.c @@ -0,0 +1,71 @@ +#include +#include "libaltos.h" + +static void +altos_puts(struct altos_file *file, char *string) +{ + char c; + + while ((c = *string++)) + altos_putchar(file, c); +} + +main () +{ + struct altos_device device; + struct altos_list *list; + struct altos_bt_device bt_device; + struct altos_bt_list *bt_list; + + altos_init(); + list = altos_list_start(); + while (altos_list_next(list, &device)) { + struct altos_file *file; + int c; + + printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product, + device.name, device.serial, device.path); + + file = altos_open(&device); + if (!file) { + printf("altos_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); + altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar (c); + } + if (c != LIBALTOS_TIMEOUT) + printf ("getchar returns %d\n", c); + altos_close(file); + } + altos_list_finish(list); +#if HAS_BLUETOOTH + bt_list = altos_bt_list_start(8); + while (altos_bt_list_next(bt_list, &bt_device)) { + printf ("%s %s\n", bt_device.name, bt_device.addr); + if (strncmp(bt_device.name, "TeleBT", 6) == 0) { + struct altos_file *file; + + int c; + file = altos_bt_open(&bt_device); + if (!file) { + printf("altos_bt_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); + altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar(c); + } + if (c != LIBALTOS_TIMEOUT) + printf("getchar returns %d\n", c); + altos_close(file); + } + } + altos_bt_list_finish(bt_list); +#endif + altos_fini(); + return 0; +} diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c new file mode 100644 index 00000000..d7b266cf --- /dev/null +++ b/libaltos/libaltos.c @@ -0,0 +1,1316 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "libaltos.h" +#include +#include +#include + +#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" + +#define USE_POLL + +PUBLIC int +altos_init(void) +{ + return LIBALTOS_SUCCESS; +} + +PUBLIC void +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 + +/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */ +static char * +altos_strndup (const char *s, size_t n) +{ + size_t len = strlen (s); + char *ret; + + if (len <= n) + return strdup (s); + ret = malloc(n + 1); + strncpy(ret, s, n); + ret[n] = '\0'; + return ret; +} + +#else +#define altos_strndup strndup +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; +#ifdef USE_POLL + int pipe[2]; +#else + int out_fd; +#endif + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + 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) +{ + struct altos_file *file = calloc (sizeof (struct altos_file), 1); + int ret; + struct termios term; + + 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) { + altos_set_last_posix_error(); + free(file); + return NULL; + } +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->out_fd < 0) { + altos_set_last_posix_error(); + close(file->fd); + free(file); + return NULL; + } +#endif + ret = tcgetattr(file->fd, &term); + if (ret < 0) { + altos_set_last_posix_error(); + close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif + free(file); + return NULL; + } + cfmakeraw(&term); +#ifdef USE_POLL + term.c_cc[VMIN] = 1; + term.c_cc[VTIME] = 0; +#else + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; +#endif + ret = tcsetattr(file->fd, TCSAFLUSH, &term); + if (ret < 0) { + altos_set_last_posix_error(); + close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif + free(file); + return NULL; + } + return file; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->fd != -1) { + int fd = file->fd; + file->fd = -1; +#ifdef USE_POLL + write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + close(fd); + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + free(file); +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + if (file->out_used && 0) { + printf ("flush \""); + fwrite(file->out_data, 1, file->out_used, stdout); + printf ("\"\n"); + } + while (file->out_used) { + int ret; + + if (file->fd < 0) + return -EBADF; +#ifdef USE_POLL + ret = write (file->fd, file->out_data, file->out_used); +#else + ret = write (file->out_fd, file->out_data, file->out_used); +#endif + if (ret < 0) { + altos_set_last_posix_error(); + return -last_error.code; + } + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } + return 0; +} + +PUBLIC int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == USB_BUF_SIZE) { + ret = altos_flush(file); + if (ret) { + return ret; + } + } + file->out_data[file->out_used++] = c; + ret = 0; + if (file->out_used == USB_BUF_SIZE) + ret = altos_flush(file); + return ret; +} + +#ifdef USE_POLL +#include +#endif + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; +#ifdef USE_POLL + struct pollfd fd[2]; +#endif + + if (timeout == 0) + timeout = -1; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; + ret = poll(fd, 2, timeout); + if (ret < 0) { + altos_set_last_posix_error(); + return LIBALTOS_ERROR; + } + if (ret == 0) + return LIBALTOS_TIMEOUT; + + if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL)) + return LIBALTOS_ERROR; + if (fd[0].revents & POLLIN) +#endif + { + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret < 0) { + altos_set_last_posix_error(); + return LIBALTOS_ERROR; + } + file->in_read = 0; + file->in_used = ret; +#ifndef USE_POLL + if (ret == 0 && timeout > 0) + return LIBALTOS_TIMEOUT; +#endif + } + } + if (file->in_used && 0) { + printf ("fill \""); + fwrite(file->in_data, 1, file->in_used, stdout); + printf ("\"\n"); + } + return 0; +} + +PUBLIC int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* POSIX_TTY */ + +/* + * Scan for Altus Metrum devices by looking through /sys + */ + +#ifdef LINUX + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +static char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} + +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product_name; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; + +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + + } + } + return NULL; +} + +static struct altos_usbdev * +usb_scan_device(char *sys) +{ + struct altos_usbdev *usbdev; + char *tty; + + tty = usb_tty(sys); + if (!tty) + return NULL; + usbdev = calloc(1, sizeof (struct altos_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product_name = load_string(sys, "product"); + usbdev->serial = load_dec(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = tty; + return usbdev; +} + +static void +usbdev_free(struct altos_usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product_name); + /* this can get used as a return value */ + if (usbdev->tty) + free(usbdev->tty); + free(usbdev); +} + +#define USB_DEVICES "/sys/bus/usb/devices" + +static int +dir_filter_dev(const struct dirent *d) +{ + const char *n = d->d_name; + char c; + + while ((c = *n++)) { + if (isdigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && n != d->d_name + 1) + continue; + return 0; + } + return 1; +} + +struct altos_list { + struct altos_usbdev **dev; + int current; + int ndev; +}; + +struct altos_list * +altos_list_start(void) +{ + int e; + struct dirent **ents; + char *dir; + struct altos_usbdev *dev; + struct altos_list *devs; + int n; + + devs = calloc(1, sizeof (struct altos_list)); + if (!devs) + return NULL; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = cc_fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + if (!dev) + continue; + free(dir); + if (devs->dev) + devs->dev = realloc(devs->dev, + (devs->ndev + 1) * sizeof (struct usbdev *)); + else + devs->dev = malloc (sizeof (struct usbdev *)); + devs->dev[devs->ndev++] = dev; + } + free(ents); + devs->current = 0; + return devs; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + struct altos_usbdev *dev; + if (list->current >= list->ndev) { + return 0; + } + dev = list->dev[list->current]; + strcpy(device->name, dev->product_name); + device->vendor = dev->idVendor; + device->product = dev->idProduct; + strcpy(device->path, dev->tty); + device->serial = dev->serial; + list->current++; + return 1; +} + +void +altos_list_finish(struct altos_list *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} + +struct altos_bt_list { + inquiry_info *ii; + 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) +{ + struct altos_bt_list *bt_list; + + bt_list = calloc(1, sizeof (struct altos_bt_list)); + if (!bt_list) + goto no_bt_list; + + bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info)); + if (!bt_list->ii) + goto no_ii; + bt_list->dev_id = hci_get_route(NULL); + if (bt_list->dev_id < 0) + goto no_dev_id; + + bt_list->sock = hci_open_dev(bt_list->dev_id); + if (bt_list->sock < 0) + goto no_sock; + + bt_list->num_rsp = hci_inquiry(bt_list->dev_id, + inquiry_time, + INQUIRY_MAX_RSP, + NULL, + &bt_list->ii, + IREQ_CACHE_FLUSH); + if (bt_list->num_rsp < 0) + goto no_rsp; + + bt_list->rsp = 0; + return bt_list; + +no_rsp: + close(bt_list->sock); +no_sock: +no_dev_id: + free(bt_list->ii); +no_ii: + free(bt_list); +no_bt_list: + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + inquiry_info *ii; + + if (bt_list->rsp >= bt_list->num_rsp) + return 0; + + ii = &bt_list->ii[bt_list->rsp]; + ba2str(&ii->bdaddr, device->addr); + memset(&device->name, '\0', sizeof (device->name)); + if (hci_read_remote_name(bt_list->sock, &ii->bdaddr, + sizeof (device->name), + device->name, 0) < 0) { + strcpy(device->name, "[unknown]"); + } + bt_list->rsp++; + return 1; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ + close(bt_list->sock); + free(bt_list->ii); + 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) +{ + struct sockaddr_rc addr = { 0 }; + int s, status; + struct altos_file *file; + + file = calloc(1, sizeof (struct altos_file)); + if (!file) + goto no_file; + file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (file->fd < 0) { + altos_set_last_posix_error(); + goto no_sock; + } + + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = 1; + str2ba(device->addr, &addr.rc_bdaddr); + + status = connect(file->fd, + (struct sockaddr *)&addr, + sizeof(addr)); + if (status < 0) { + altos_set_last_posix_error(); + goto no_link; + } + sleep(1); + +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = dup(file->fd); +#endif + return file; +no_link: + close(s); +no_sock: + free(file); +no_file: + return NULL; +} + +#endif + +#ifdef DARWIN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct altos_list { + io_iterator_t iterator; +}; + +static int +get_string(io_object_t object, CFStringRef entry, char *result, int result_len) +{ + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); + + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; +} + +static int +get_number(io_object_t object, CFStringRef entry, int *result) +{ + CFTypeRef entry_as_number; + Boolean got_number; + + entry_as_number = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_number) { + got_number = CFNumberGetValue(entry_as_number, + kCFNumberIntType, + result); + if (got_number) + return 1; + } + return 0; +} + +PUBLIC struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc (sizeof (struct altos_list), 1); + CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); + io_iterator_t tdIterator; + io_object_t tdObject; + kern_return_t ret; + int i; + + ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); + if (ret != kIOReturnSuccess) + return NULL; + return list; +} + +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + io_object_t object; + char serial_string[128]; + + for (;;) { + object = IOIteratorNext(list->iterator); + if (!object) + return 0; + + if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) || + !get_number (object, CFSTR(kUSBProductID), &device->product)) + continue; + if (device->vendor != 0xfffe) + continue; + if (device->product < 0x000a || 0x0013 < device->product) + continue; + if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) && + get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) && + get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { + device->serial = atoi(serial_string); + return 1; + } + } +} + +PUBLIC void +altos_list_finish(struct altos_list *list) +{ + IOObjectRelease (list->iterator); + 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 + + +#ifdef WINDOWS + +#include +#include +#include + +struct altos_list { + HDEVINFO dev_info; + int index; +}; + +#define USB_BUF_SIZE 64 + +struct altos_file { + HANDLE handle; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; + OVERLAPPED ov_read; + BOOL pend_read; + OVERLAPPED ov_write; +}; + +static void +_altos_set_last_windows_error(char *file, int line) +{ + DWORD error = GetLastError(); + TCHAR message[1024]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + 0, + error, + 0, + message, + sizeof (message) / sizeof (TCHAR), + NULL); + if (error != ERROR_SUCCESS) + printf ("%s:%d %s\n", file, line, message); + altos_set_last_error(error, message); +} + +#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__) + +PUBLIC struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc(1, sizeof (struct altos_list)); + + if (!list) + return NULL; + list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, + DIGCF_ALLCLASSES|DIGCF_PRESENT); + if (list->dev_info == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); + free(list); + return NULL; + } + list->index = 0; + return list; +} + +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + SP_DEVINFO_DATA dev_info_data; + BYTE port[128]; + DWORD port_len; + char friendlyname[256]; + BYTE symbolic[256]; + DWORD symbolic_len; + HKEY dev_key; + unsigned int vid, pid; + int serial; + HRESULT result; + DWORD friendlyname_type; + DWORD friendlyname_len; + + dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); + while(SetupDiEnumDeviceInfo(list->dev_info, list->index, + &dev_info_data)) + { + list->index++; + + dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data, + 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; + } + + /* Fetch symbolic name for this device and parse out + * the vid/pid/serial info */ + symbolic_len = sizeof(symbolic); + 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; + } + vid = pid = serial = 0; + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, + "%04X", &vid); + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + "%04X", &pid); + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + "%d", &serial); + + /* Fetch the com port name */ + port_len = sizeof (port); + result = RegQueryValueEx(dev_key, "PortName", NULL, NULL, + port, &port_len); + RegCloseKey(dev_key); + if (result != 0) { + altos_set_last_windows_error(); + printf("failed to get PortName\n"); + continue; + } + + /* Fetch the device description which is the device name, + * with firmware that has unique USB ids */ + friendlyname_len = sizeof (friendlyname); + if(!SetupDiGetDeviceRegistryProperty(list->dev_info, + &dev_info_data, + SPDRP_FRIENDLYNAME, + &friendlyname_type, + (BYTE *)friendlyname, + sizeof(friendlyname), + &friendlyname_len)) + { + altos_set_last_windows_error(); + printf("Failed to get friendlyname\n"); + continue; + } + device->vendor = vid; + device->product = pid; + device->serial = serial; + strcpy(device->name, friendlyname); + + strcpy(device->path, (char *) port); + return 1; + } + result = GetLastError(); + if (result != ERROR_NO_MORE_ITEMS) { + altos_set_last_windows_error(); + printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); + } + return 0; +} + +PUBLIC void +altos_list_finish(struct altos_list *list) +{ + SetupDiDestroyDeviceInfoList(list->dev_info); + free(list); +} + +static int +altos_queue_read(struct altos_file *file) +{ + DWORD got; + if (file->pend_read) + return LIBALTOS_SUCCESS; + + if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { + if (GetLastError() != ERROR_IO_PENDING) { + altos_set_last_windows_error(); + return LIBALTOS_ERROR; + } + file->pend_read = TRUE; + } else { + file->pend_read = FALSE; + file->in_read = 0; + file->in_used = got; + } + return LIBALTOS_SUCCESS; +} + +static int +altos_wait_read(struct altos_file *file, int timeout) +{ + DWORD ret; + DWORD got; + + if (!file->pend_read) + return LIBALTOS_SUCCESS; + + if (!timeout) + timeout = INFINITE; + + ret = WaitForSingleObject(file->ov_read.hEvent, timeout); + switch (ret) { + case WAIT_OBJECT_0: + 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; + break; + case WAIT_TIMEOUT: + return LIBALTOS_TIMEOUT; + break; + default: + return LIBALTOS_ERROR; + } + return LIBALTOS_SUCCESS; +} + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; + + if (file->in_read < file->in_used) + return LIBALTOS_SUCCESS; + + file->in_read = file->in_used = 0; + + ret = altos_queue_read(file); + if (ret) + return ret; + ret = altos_wait_read(file, timeout); + if (ret) + return ret; + + return LIBALTOS_SUCCESS; +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + DWORD put; + unsigned char *data = file->out_data; + int used = file->out_used; + DWORD ret; + + while (used) { + if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { + if (GetLastError() != ERROR_IO_PENDING) { + altos_set_last_windows_error(); + printf ("\tflush write error\n"); + 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)) { + altos_set_last_windows_error(); + printf ("\tflush result error\n"); + return LIBALTOS_ERROR; + } + break; + default: + altos_set_last_windows_error(); + printf ("\tflush wait error\n"); + return LIBALTOS_ERROR; + } + } + data += put; + used -= put; + } + file->out_used = 0; + return LIBALTOS_SUCCESS; +} + +PUBLIC struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (1, sizeof (struct altos_file)); + char full_name[64]; + COMMTIMEOUTS timeouts; + + if (!file) + return NULL; + + strcpy(full_name, "\\\\.\\"); + strcat(full_name, device->path); + file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + if (file->handle == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); + printf ("cannot open %s\n", full_name); + free(file); + return NULL; + } + file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */ + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + SetCommTimeouts(file->handle, &timeouts); + + return file; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->handle != INVALID_HANDLE_VALUE) { + CloseHandle(file->handle); + file->handle = INVALID_HANDLE_VALUE; + SetEvent(file->ov_read.hEvent); + SetEvent(file->ov_write.hEvent); + CloseHandle(file->ov_read.hEvent); + CloseHandle(file->ov_write.hEvent); + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + free(file); +} + +PUBLIC int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == USB_BUF_SIZE) { + ret = altos_flush(file); + if (ret) + return ret; + } + file->out_data[file->out_used++] = c; + if (file->out_used == USB_BUF_SIZE) + return altos_flush(file); + return LIBALTOS_SUCCESS; +} + +PUBLIC int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->handle == INVALID_HANDLE_VALUE) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + 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/libaltos/libaltos.dylib b/libaltos/libaltos.dylib new file mode 100755 index 00000000..1038817d Binary files /dev/null and b/libaltos/libaltos.dylib differ diff --git a/libaltos/libaltos.h b/libaltos/libaltos.h new file mode 100644 index 00000000..f90fbb87 --- /dev/null +++ b/libaltos/libaltos.h @@ -0,0 +1,119 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _LIBALTOS_H_ +#define _LIBALTOS_H_ + +#include + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef BUILD_STATIC +# ifdef BUILD_DLL +# define PUBLIC __declspec(dllexport) +# else +# define PUBLIC __declspec(dllimport) +# endif +# endif /* BUILD_STATIC */ +#endif + +#ifndef PUBLIC +# define PUBLIC +#endif + +struct altos_device { + //%immutable; + int vendor; + int product; + int serial; + char name[256]; + char path[256]; + //%mutable; +}; + +struct altos_bt_device { + //%immutable; + char name[256]; + char addr[20]; + //%mutable; +}; + +struct altos_error { + int code; + char string[1024]; +}; + +#define LIBALTOS_SUCCESS 0 +#define LIBALTOS_ERROR -1 +#define LIBALTOS_TIMEOUT -2 + +/* Returns 0 for success, < 0 on error */ +PUBLIC int +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); + +/* Returns 1 for success, zero on end of list */ +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device); + +PUBLIC void +altos_list_finish(struct altos_list *list); + +PUBLIC struct altos_file * +altos_open(struct altos_device *device); + +PUBLIC void +altos_close(struct altos_file *file); + +PUBLIC void +altos_free(struct altos_file *file); + +/* Returns < 0 for error */ +PUBLIC int +altos_putchar(struct altos_file *file, char c); + +/* Returns < 0 for error */ +PUBLIC int +altos_flush(struct altos_file *file); + +/* Returns < 0 for error or timeout. timeout of 0 == wait forever */ +PUBLIC int +altos_getchar(struct altos_file *file, int timeout); + +PUBLIC struct altos_bt_list * +altos_bt_list_start(int inquiry_time); + +PUBLIC int +altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); + +PUBLIC void +altos_bt_list_finish(struct altos_bt_list *list); + +PUBLIC void +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 /* _LIBALTOS_H_ */ diff --git a/libaltos/libaltos.i0 b/libaltos/libaltos.i0 new file mode 100644 index 00000000..d06468f5 --- /dev/null +++ b/libaltos/libaltos.i0 @@ -0,0 +1,5 @@ +%module libaltos +%{ +#include "libaltos.h" +%} + -- cgit v1.2.3 From bf8e1b6eecb2bae12ffdbd730bd6ec12ccdaf23a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 25 Dec 2012 14:23:29 -0800 Subject: Start building MicroPeak GUI tool Download, save and analyze MicroPeak flight data Signed-off-by: Keith Packard --- micropeak/Makefile.am | 115 +++++++++++++++++++ micropeak/MicroData.java | 270 +++++++++++++++++++++++++++++++++++++++++++++ micropeak/MicroGraph.java | 105 ++++++++++++++++++ micropeak/MicroPeak.java | 138 +++++++++++++++++++++++ micropeak/MicroSerial.java | 46 ++++++++ micropeak/MicroUSB.java | 103 +++++++++++++++++ 6 files changed, 777 insertions(+) create mode 100644 micropeak/Makefile.am create mode 100644 micropeak/MicroData.java create mode 100644 micropeak/MicroGraph.java create mode 100644 micropeak/MicroPeak.java create mode 100644 micropeak/MicroSerial.java create mode 100644 micropeak/MicroUSB.java diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am new file mode 100644 index 00000000..a3ecac72 --- /dev/null +++ b/micropeak/Makefile.am @@ -0,0 +1,115 @@ +JAVAROOT=classes +AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation + +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" + +bin_SCRIPTS=micropeak + +micropeakdir=$(datadir)/java + +micropeak_JAVA= \ + MicroPeak.java \ + MicroData.java \ + MicroGraph.java \ + MicroSerial.java \ + MicroUSB.java + +JFREECHART_CLASS= \ + jfreechart.jar + +JCOMMON_CLASS=\ + jcommon.jar + +JAR=micropeak.jar + +FATJAR=micropeak-fat.jar + +LIBALTOS= \ + libaltos.so \ + libaltos.dylib \ + altos.dll + +ALTOSLIB_CLASS=\ + AltosLib.jar + +all-local: micropeak-test $(JAR) + +clean-local: + -rm -rf classes $(JAR) $(FATJAR) \ + $(ALTOSLIB_CLASS) \ + $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt \ + micropeak micropeak-test macosx linux windows + +micropeak: Makefile + echo "#!/bin/sh" > $@ + echo 'exec java -cp "$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="$(altoslibdir)" -jar "$(micropeakdir)/micropeak.jar" "$$@"' >> $@ + chmod +x $@ + +micropeak-test: Makefile + echo "#!/bin/sh" > $@ + echo 'exec java -cp "./*:../libaltos/*:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar micropeak.jar "$$@"' >> $@ + chmod +x $@ + +$(JAR): classmicropeak.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) + jar cfm $@ Manifest.txt \ + $(ICONJAR) \ + -C classes org \ + -C ../libaltos libaltosJNI + +$(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS) + jar cfm $@ Manifest-fat.txt \ + $(ICONJAR) \ + -C classes org \ + -C ../libaltos libaltosJNI + + +libaltos.so: build-libaltos + -rm -f "$@" + $(LN_S) ../libaltos/.libs/"$@" . + +libaltos.dylib: + -rm -f "$@" + $(LN_S) ../libaltos/"$@" . + +altos.dll: ../libaltos/altos.dll + -rm -f "$@" + $(LN_S) ../libaltos/"$@" . + +altos64.dll: ../libaltos/altos64.dll + -rm -f "$@" + $(LN_S) ../libaltos/"$@" . + +../libaltos/.libs/libaltos.so: build-libaltos + +../libaltos/altos.dll: build-altos-dll + +../libaltos/altos64.dll: build-altos64-dll + +build-libaltos: + +cd ../libaltos && make libaltos.la +build-altos-dll: + +cd ../libaltos && make altos.dll + +build-altos64-dll: + +cd ../libaltos && make altos64.dll + +$(ALTOSLIB_CLASS): + -rm -f "$@" + $(LN_S) ../altoslib/"$@" . + +$(JFREECHART_CLASS): + -rm -f "$@" + $(LN_S) "$(JFREECHART)"/"$@" . + +$(JCOMMON_CLASS): + -rm -f "$@" + $(LN_S) "$(JCOMMON)"/"$@" . + +Manifest.txt: Makefile + echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ + echo "Class-Path: AltosLib.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ + +Manifest-fat.txt: + echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ + echo "Class-Path: AltosLib.jar jcommon.jar jfreechart.jar" >> $@ + diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java new file mode 100644 index 00000000..783ae40f --- /dev/null +++ b/micropeak/MicroData.java @@ -0,0 +1,270 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.lang.*; +import java.io.*; +import java.util.*; +import org.altusmetrum.AltosLib.*; + +public class MicroData { + public int ground_pressure; + public int min_pressure; + public int[] pressures; + private double time_step; + private double ground_altitude; + private ArrayList bytes; + + + class FileEndedException extends Exception { + } + + class NonHexcharException extends Exception { + } + + class InvalidCrcException extends Exception { + } + + private int getc(InputStream f) throws IOException, FileEndedException { + int c = f.read(); + + if (c == -1) + throw new FileEndedException(); + bytes.add(c); + return c; + } + + private int get_nonwhite(InputStream f) throws IOException, FileEndedException { + int c; + + for (;;) { + c = getc(f); + if (!Character.isWhitespace(c)) + return c; + } + } + + private int get_hexc(InputStream f) throws IOException, FileEndedException, NonHexcharException { + int c = get_nonwhite(f); + + 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; + throw new NonHexcharException(); + } + + private static final int POLY = 0x8408; + + private int log_crc(int crc, int b) { + int i; + + for (i = 0; i < 8; i++) { + if (((crc & 0x0001) ^ (b & 0x0001)) != 0) + crc = (crc >> 1) ^ POLY; + else + crc = crc >> 1; + b >>= 1; + } + return crc & 0xffff; + } + + int file_crc; + + private int get_hex(InputStream f) throws IOException, FileEndedException, NonHexcharException { + int a = get_hexc(f); + int b = get_hexc(f); + + int h = (a << 4) + b; + + file_crc = log_crc(file_crc, h); + return h; + } + + private boolean find_header(InputStream f) throws IOException { + try { + for (;;) { + if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P') + return true; + } + } catch (FileEndedException fe) { + return false; + } + } + + private int get_32(InputStream f) throws IOException, FileEndedException, NonHexcharException { + int v = 0; + for (int i = 0; i < 4; i++) { + v += get_hex(f) << (i * 8); + } + return v; + } + + private int get_16(InputStream f) throws IOException, FileEndedException, NonHexcharException { + int v = 0; + for (int i = 0; i < 2; i++) { + v += get_hex(f) << (i * 8); + } + return v; + } + + private int swap16(int i) { + return ((i << 8) & 0xff00) | ((i >> 8) & 0xff); + } + + public boolean crc_valid; + + int mix_in (int high, int low) { + return high - (high & 0xffff) + low; + } + + boolean closer (int target, int a, int b) { + return Math.abs (target - a) < Math.abs(target - b); + } + + public double altitude(int i) { + return AltosConvert.pressure_to_altitude(pressures[i]); + } + + int fact(int n) { + if (n == 0) + return 1; + return n * fact(n-1); + } + + int choose(int n, int k) { + return fact(n) / (fact(k) * fact(n-k)); + } + + + public double avg_altitude(int center, int dist) { + int start = center - dist; + int stop = center + dist; + + if (start < 0) + start = 0; + if (stop >= pressures.length) + stop = pressures.length - 1; + + double sum = 0; + double div = 0; + + int n = dist * 2; + + for (int i = start; i <= stop; i++) { + int k = i - (center - dist); + int c = choose (n, k); + + sum += c * pressures[i]; + div += c; + } + + double pres = sum / div; + + double alt = AltosConvert.pressure_to_altitude(pres); + return alt; + } + + public double height(int i) { + return altitude(i) - ground_altitude; + } + + static final int speed_avg = 3; + static final int accel_avg = 5; + + private double avg_speed(int center, int dist) { + if (center == 0) + return 0; + + double ai = avg_altitude(center, dist); + double aj = avg_altitude(center - 1, dist); + double s = (ai - aj) / time_step; + + return s; + } + + public double speed(int i) { + return avg_speed(i, speed_avg); + } + + public double acceleration(int i) { + if (i == 0) + return 0; + return (avg_speed(i, accel_avg) - avg_speed(i-1, accel_avg)) / time_step; + } + + public double time(int i) { + return i * time_step; + } + + public void save (OutputStream f) throws IOException { + for (int c : bytes) + f.write(c); + } + + public MicroData (InputStream f) throws IOException { + bytes = new ArrayList(); + if (!find_header(f)) + throw new IOException(); + try { + file_crc = 0xffff; + ground_pressure = get_32(f); + min_pressure = get_32(f); + int nsamples = get_16(f); + pressures = new int[nsamples + 1]; + + ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); + int cur = ground_pressure; + pressures[0] = cur; + for (int i = 0; i < nsamples; i++) { + int k = get_16(f); + int same = mix_in(cur, k); + int up = mix_in(cur + 0x10000, k); + int down = mix_in(cur - 0x10000, k); + + if (closer (cur, same, up)) { + if (closer (cur, same, down)) + cur = same; + else + cur = down; + } else { + if (closer (cur, up, down)) + cur = up; + else + cur = down; + } + + pressures[i+1] = cur; + } + + int current_crc = swap16(~file_crc & 0xffff); + int crc = get_16(f); + + crc_valid = crc == current_crc; + + time_step = 0.192; + } catch (FileEndedException fe) { + throw new IOException(); + } catch (NonHexcharException ne) { + throw new IOException(); + } + } + +} diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java new file mode 100644 index 00000000..aac14b9a --- /dev/null +++ b/micropeak/MicroGraph.java @@ -0,0 +1,105 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.AltosLib.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +public class MicroGraph { + + XYPlot plot; + JFreeChart chart; + ChartPanel panel; + NumberAxis xAxis; + XYSeries heightSeries; + XYSeries speedSeries; + XYSeries accelSeries; + + MicroData data; + + public JPanel panel() { + return panel; + } + + private void addSeries(XYSeries series, int index, String label, String units) { + XYSeriesCollection dataset = new XYSeriesCollection(series); + NumberAxis axis = new NumberAxis(String.format("%s (%s)", label, units)); + XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); + + renderer.setPlot(plot); + renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", units), + new java.text.DecimalFormat("0.00"), + new java.text.DecimalFormat("0.00"))); + plot.setRangeAxis(index, axis); + plot.setDataset(index, dataset); + plot.setRenderer(index, renderer); + plot.mapDatasetToRangeAxis(index, index); + } + + public MicroGraph(MicroData data) { + + this.data = data; + + heightSeries = new XYSeries("Height"); + speedSeries = new XYSeries("Speed"); + accelSeries = new XYSeries("Acceleration"); + + for (int i = 0; i < data.pressures.length; i++) { + double x = data.time(i); + heightSeries.add(x, data.height(i)); + speedSeries.add(x, data.speed(i)); + accelSeries.add(x, data.acceleration(i)); + } + + xAxis = new NumberAxis("Time (s)"); + + xAxis.setAutoRangeIncludesZero(true); + + plot = new XYPlot(); + plot.setDomainAxis(xAxis); + plot.setOrientation(PlotOrientation.VERTICAL); + plot.setDomainPannable(true); + plot.setRangePannable(true); + + addSeries(heightSeries, 0, "Height", "m"); + addSeries(speedSeries, 1, "Speed", "m/s"); + addSeries(accelSeries, 2, "Acceleration", "m/s²"); + + chart = new JFreeChart("Flight", JFreeChart.DEFAULT_TITLE_FONT, + plot, true); + + ChartUtilities.applyCurrentTheme(chart); + panel = new ChartPanel(chart); + panel.setMouseWheelEnabled(true); + panel.setPreferredSize(new java.awt.Dimension(800, 500)); + } +} \ No newline at end of file diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java new file mode 100644 index 00000000..82d926fb --- /dev/null +++ b/micropeak/MicroPeak.java @@ -0,0 +1,138 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import org.altusmetrum.AltosLib.*; + +public class MicroPeak extends JFrame implements ActionListener, ItemListener { + + File filename; + MicroGraph graph; + MicroData data; + Container pane; + + private void OpenFile(File filename) { + try { + FileInputStream input = new FileInputStream(filename); + try { + data = new MicroData(input); + graph = new MicroGraph(data); + pane.add(graph.panel); + } catch (IOException ioe) { + } + try { + input.close(); + } catch (IOException ioe) { + } + } catch (FileNotFoundException fne) { + } + } + + private void SelectFile() { + } + + private void DownloadData() { + java.util.List devices = MicroUSB.list(); + for (MicroUSB device : devices) + System.out.printf("device %s\n", device.toString()); + } + + public void actionPerformed(ActionEvent ev) { + System.out.printf("action %s %s\n", ev.getActionCommand(), ev.paramString()); + if ("Exit".equals(ev.getActionCommand())) + System.exit(0); + else if ("Open".equals(ev.getActionCommand())) + SelectFile(); + else if ("New".equals(ev.getActionCommand())) + new MicroPeak(); + else if ("Download".equals(ev.getActionCommand())) + DownloadData(); + } + + public void itemStateChanged(ItemEvent e) { + } + + public MicroPeak(File filename) { + + this.filename = filename; + + pane = getContentPane(); + +// JLabel label = new JLabel ("Hello, World"); +// pane.add(label); + + setSize(800, 500); + + setTitle("MicroPeak"); + + JMenuBar menuBar = new JMenuBar(); + setJMenuBar(menuBar); + + JMenu fileMenu = new JMenu("File"); + menuBar.add(fileMenu); + + JMenuItem newAction = new JMenuItem("New"); + fileMenu.add(newAction); + newAction.addActionListener(this); + + JMenuItem openAction = new JMenuItem("Open"); + fileMenu.add(openAction); + openAction.addActionListener(this); + + JMenuItem downloadAction = new JMenuItem("Download"); + fileMenu.add(downloadAction); + downloadAction.addActionListener(this); + + JMenuItem exitAction = new JMenuItem("Exit"); + fileMenu.add(exitAction); + exitAction.addActionListener(this); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + if (filename != null) + this.OpenFile(filename); + setVisible(true); + } + + public MicroPeak() { + this(null); + } + + public static void main(final String[] args) { + boolean opened = false; + + for (int i = 0; i < args.length; i++) { + new MicroPeak(new File(args[i])); + opened = true; + } + if (!opened) + new MicroPeak(); + } +} \ No newline at end of file diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java new file mode 100644 index 00000000..afe55532 --- /dev/null +++ b/micropeak/MicroSerial.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; +import java.util.*; +import java.io.*; +import libaltosJNI.*; + +public class MicroSerial extends InputStream { + SWIGTYPE_p_altos_file file; + + public int read() { + return libaltos.altos_getchar(file, 0); + } + + public void close() { + if (file != null) { + libaltos.altos_close(file); + file = null; + } + } + + public MicroSerial(MicroUSB usb) throws FileNotFoundException { + file = usb.open(); + if (file == null) { + final String message = usb.getErrorString(); + throw new FileNotFoundException(String.format("%s (%s)", + usb.toShortString(), + message)); + } + } +} diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java new file mode 100644 index 00000000..d48610fe --- /dev/null +++ b/micropeak/MicroUSB.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; +import java.util.*; +import libaltosJNI.*; + +public class MicroUSB extends altos_device { + + static boolean initialized = false; + static boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + try { + System.loadLibrary("altos64"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e2) { + loaded_library = false; + } + } + initialized = true; + } + return loaded_library; + } + + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%-20.20s %4d %s", + name, getSerial(), getPath()); + } + + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + name, getSerial(), getPath()); + + } + + 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); + } + + private boolean isMicro() { + if (getVendor() != 0x0403) + return false; + if (getProduct() != 0x6001) + return false; + return true; + } + + static java.util.List list() { + if (!load_library()) + return null; + + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + for (;;) { + MicroUSB device = new MicroUSB(); + if (libaltos.altos_list_next(list, device) == 0) + break; + if (device.isMicro()) + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + return device_list; + } +} \ No newline at end of file -- cgit v1.2.3 From 9da9adc2718928de2af65a68cddbcc636cc3e9e8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 25 Dec 2012 14:45:49 -0800 Subject: Add file chooser for MicroPeak Needs reasonable directory tracking Signed-off-by: Keith Packard --- micropeak/Makefile.am | 1 + micropeak/MicroFileChooser.java | 65 +++++++++++++++++++++++++++++++++++++++++ micropeak/MicroGraph.java | 19 +++++++----- micropeak/MicroPeak.java | 57 +++++++++++++++++++++--------------- 4 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 micropeak/MicroFileChooser.java diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index a3ecac72..32be9070 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -12,6 +12,7 @@ micropeak_JAVA= \ MicroData.java \ MicroGraph.java \ MicroSerial.java \ + MicroFileChooser.java \ MicroUSB.java JFREECHART_CLASS= \ diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java new file mode 100644 index 00000000..0fd63a27 --- /dev/null +++ b/micropeak/MicroFileChooser.java @@ -0,0 +1,65 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.*; +import org.altusmetrum.AltosLib.*; + +public class MicroFileChooser extends JFileChooser { + JFrame frame; + String filename; + File file; + + public String filename() { + return filename; + } + + public File file() { + return file; + } + + public InputStream runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) { + file = getSelectedFile(); + if (file == null) + return null; + filename = file.getName(); + try { + return new FileInputStream(file); + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + fe.getMessage(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + return null; + } + + public MicroFileChooser(JFrame in_frame) { + frame = in_frame; + setDialogTitle("Select MicroPeak Data File"); + setFileFilter(new FileNameExtensionFilter("MicroPeak data file", + "mpd")); + } +} diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index aac14b9a..9192cad9 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -65,6 +65,18 @@ public class MicroGraph { plot.mapDatasetToRangeAxis(index, index); } + public void setData (MicroData data) { + heightSeries.clear(); + speedSeries.clear(); + accelSeries.clear(); + for (int i = 0; i < data.pressures.length; i++) { + double x = data.time(i); + heightSeries.add(x, data.height(i)); + speedSeries.add(x, data.speed(i)); + accelSeries.add(x, data.acceleration(i)); + } + } + public MicroGraph(MicroData data) { this.data = data; @@ -73,13 +85,6 @@ public class MicroGraph { speedSeries = new XYSeries("Speed"); accelSeries = new XYSeries("Acceleration"); - for (int i = 0; i < data.pressures.length; i++) { - double x = data.time(i); - heightSeries.add(x, data.height(i)); - speedSeries.add(x, data.speed(i)); - accelSeries.add(x, data.acceleration(i)); - } - xAxis = new NumberAxis("Time (s)"); xAxis.setAutoRangeIncludesZero(true); diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 82d926fb..cd09c475 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -32,24 +32,31 @@ public class MicroPeak extends JFrame implements ActionListener, ItemListener { MicroData data; Container pane; + private void RunFile(InputStream input) { + try { + data = new MicroData(input); + graph.setData(data); + } catch (IOException ioe) { + } + try { + input.close(); + } catch (IOException ioe) { + } + } + private void OpenFile(File filename) { try { - FileInputStream input = new FileInputStream(filename); - try { - data = new MicroData(input); - graph = new MicroGraph(data); - pane.add(graph.panel); - } catch (IOException ioe) { - } - try { - input.close(); - } catch (IOException ioe) { - } + RunFile (new FileInputStream(filename)); } catch (FileNotFoundException fne) { } } private void SelectFile() { + MicroFileChooser chooser = new MicroFileChooser(this); + InputStream input = chooser.runDialog(); + + if (input != null) + RunFile(input); } private void DownloadData() { @@ -73,17 +80,12 @@ public class MicroPeak extends JFrame implements ActionListener, ItemListener { public void itemStateChanged(ItemEvent e) { } - public MicroPeak(File filename) { + public MicroPeak() { this.filename = filename; pane = getContentPane(); -// JLabel label = new JLabel ("Hello, World"); -// pane.add(label); - - setSize(800, 500); - setTitle("MicroPeak"); JMenuBar menuBar = new JMenuBar(); @@ -116,20 +118,27 @@ public class MicroPeak extends JFrame implements ActionListener, ItemListener { } }); - if (filename != null) - this.OpenFile(filename); + graph = new MicroGraph(data); + pane.add(graph.panel); + pane.doLayout(); + pane.validate(); + doLayout(); + validate(); + Insets i = getInsets(); + Dimension ps = pane.getPreferredSize(); + ps.width += i.left + i.right; + ps.height += i.top + i.bottom; + setPreferredSize(ps); + setSize(ps); setVisible(true); } - public MicroPeak() { - this(null); - } - public static void main(final String[] args) { boolean opened = false; for (int i = 0; i < args.length; i++) { - new MicroPeak(new File(args[i])); + MicroPeak m = new MicroPeak(); + m.OpenFile(new File(args[i])); opened = true; } if (!opened) -- cgit v1.2.3 From daf8776f8646ba187f1a17f7aae797503bed3f2a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 28 Dec 2012 16:34:48 -0800 Subject: Lots more work on the MicroPeak application Signed-off-by: Keith Packard --- icon/micropeak-128.png | Bin 0 -> 4394 bytes icon/micropeak-16.png | Bin 0 -> 534 bytes icon/micropeak-256.png | Bin 0 -> 8055 bytes icon/micropeak-32.png | Bin 0 -> 1072 bytes icon/micropeak-48.png | Bin 0 -> 1662 bytes icon/micropeak-64.png | Bin 0 -> 2240 bytes micropeak/Makefile.am | 24 ++++ micropeak/MicroFontListener.java | 22 ++++ micropeak/MicroFrame.java | 74 +++++++++++ micropeak/MicroPeak.java | 2 +- micropeak/MicroPreferences.java | 221 +++++++++++++++++++++++++++++++++ micropeak/MicroPreferencesBackend.java | 101 +++++++++++++++ micropeak/MicroSerial.java | 5 +- micropeak/MicroUIListener.java | 22 ++++ 14 files changed, 469 insertions(+), 2 deletions(-) create mode 100644 icon/micropeak-128.png create mode 100644 icon/micropeak-16.png create mode 100644 icon/micropeak-256.png create mode 100644 icon/micropeak-32.png create mode 100644 icon/micropeak-48.png create mode 100644 icon/micropeak-64.png create mode 100644 micropeak/MicroFontListener.java create mode 100644 micropeak/MicroFrame.java create mode 100644 micropeak/MicroPreferences.java create mode 100644 micropeak/MicroPreferencesBackend.java create mode 100644 micropeak/MicroUIListener.java diff --git a/icon/micropeak-128.png b/icon/micropeak-128.png new file mode 100644 index 00000000..f045dc6a Binary files /dev/null and b/icon/micropeak-128.png differ diff --git a/icon/micropeak-16.png b/icon/micropeak-16.png new file mode 100644 index 00000000..d8140802 Binary files /dev/null and b/icon/micropeak-16.png differ diff --git a/icon/micropeak-256.png b/icon/micropeak-256.png new file mode 100644 index 00000000..b96d4706 Binary files /dev/null and b/icon/micropeak-256.png differ diff --git a/icon/micropeak-32.png b/icon/micropeak-32.png new file mode 100644 index 00000000..d34c5c12 Binary files /dev/null and b/icon/micropeak-32.png differ diff --git a/icon/micropeak-48.png b/icon/micropeak-48.png new file mode 100644 index 00000000..86dc4f7f Binary files /dev/null and b/icon/micropeak-48.png differ diff --git a/icon/micropeak-64.png b/icon/micropeak-64.png new file mode 100644 index 00000000..6ca7c2eb Binary files /dev/null and b/icon/micropeak-64.png differ diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 32be9070..2cfd2ad3 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -10,9 +10,14 @@ micropeakdir=$(datadir)/java micropeak_JAVA= \ MicroPeak.java \ MicroData.java \ + MicroFrame.java \ MicroGraph.java \ MicroSerial.java \ MicroFileChooser.java \ + MicroPreferences.java \ + MicroPreferencesBackend.java \ + MicroFontListener.java \ + MicroUIListener.java \ MicroUSB.java JFREECHART_CLASS= \ @@ -33,6 +38,25 @@ LIBALTOS= \ ALTOSLIB_CLASS=\ AltosLib.jar +# Icons +ICONDIR=$(top_srcdir)/icon + +JAVA_ICONS=\ + $(ICONDIR)/micropeak-16.png \ + $(ICONDIR)/micropeak-32.png \ + $(ICONDIR)/micropeak-48.png \ + $(ICONDIR)/micropeak-64.png \ + $(ICONDIR)/micropeak-128.png \ + $(ICONDIR)/micropeak-256.png + +# icon base names for jar +ICONJAR= -C $(ICONDIR) micropeak-16.png \ + -C $(ICONDIR) micropeak-32.png \ + -C $(ICONDIR) micropeak-48.png \ + -C $(ICONDIR) micropeak-64.png \ + -C $(ICONDIR) micropeak-128.png \ + -C $(ICONDIR) micropeak-256.png + all-local: micropeak-test $(JAR) clean-local: diff --git a/micropeak/MicroFontListener.java b/micropeak/MicroFontListener.java new file mode 100644 index 00000000..a902584c --- /dev/null +++ b/micropeak/MicroFontListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +public interface MicroFontListener { + void font_size_changed(int font_size); +} diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java new file mode 100644 index 00000000..a9b9a37a --- /dev/null +++ b/micropeak/MicroFrame.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +class MicroFrameListener extends WindowAdapter { + public void windowClosing (WindowEvent e) { + MicroPreferences.unregister_ui_listener((MicroFrame) e.getWindow()); + } +} + +public class MicroFrame extends JFrame implements MicroUIListener { + + public void ui_changed(String look_and_feel) { + SwingUtilities.updateComponentTreeUI(this); + this.pack(); + } + + static final String[] icon_names = { + "/micropeak-16.png", + "/micropeak-32.png", + "/micropeak-48.png", + "/micropeak-64.png", + "/micropeak-128.png", + "/micropeak-256.png" + }; + + public void set_icon() { + ArrayList icons = new ArrayList(); + + for (int i = 0; i < icon_names.length; i++) { + java.net.URL imgURL = MicroPeak.class.getResource(icon_names[i]); + if (imgURL != null) + icons.add(new ImageIcon(imgURL).getImage()); + } + + setIconImages(icons); + } + + public MicroFrame() { + super(); + MicroPreferences.set_component(this); + MicroPreferences.register_ui_listener(this); + addWindowListener(new MicroFrameListener()); + set_icon(); + } + + public MicroFrame(String name) { + super(name); + MicroPreferences.set_component(this); + MicroPreferences.register_ui_listener(this); + addWindowListener(new MicroFrameListener()); + set_icon(); + } +} diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index cd09c475..c9074348 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -25,7 +25,7 @@ import java.util.concurrent.*; import java.util.*; import org.altusmetrum.AltosLib.*; -public class MicroPeak extends JFrame implements ActionListener, ItemListener { +public class MicroPeak extends MicroFrame implements ActionListener, ItemListener { File filename; MicroGraph graph; diff --git a/micropeak/MicroPreferences.java b/micropeak/MicroPreferences.java new file mode 100644 index 00000000..70c2557c --- /dev/null +++ b/micropeak/MicroPreferences.java @@ -0,0 +1,221 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import java.util.*; +import java.awt.Component; +import javax.swing.*; +import java.awt.*; +import org.altusmetrum.AltosLib.*; + +public class MicroPreferences extends AltosPreferences { + + static final int tab_elt_pad = 5; + + static Font label_font; + static Font value_font; + static Font status_font; + static Font table_label_font; + static Font table_value_font; + + final static int font_size_small = 1; + final static int font_size_medium = 2; + final static int font_size_large = 3; + + static void set_fonts(int size) { + int brief_size; + int table_size; + int status_size; + + switch (size) { + case font_size_small: + brief_size = 16; + status_size = 18; + table_size = 11; + break; + default: + case font_size_medium: + brief_size = 22; + status_size = 24; + table_size = 14; + break; + case font_size_large: + brief_size = 26; + status_size = 30; + table_size = 17; + break; + } + label_font = new Font("Dialog", Font.PLAIN, brief_size); + value_font = new Font("Monospaced", Font.PLAIN, brief_size); + status_font = new Font("SansSerif", Font.BOLD, status_size); + table_label_font = new Font("SansSerif", Font.PLAIN, table_size); + table_value_font = new Font("Monospaced", Font.PLAIN, table_size); + } + + /* font size preferences name */ + final static String fontSizePreference = "FONT-SIZE"; + + /* Look&Feel preference name */ + final static String lookAndFeelPreference = "LOOK-AND-FEEL"; + + /* UI Component to pop dialogs up */ + static Component component; + + static LinkedList font_listeners; + + static int font_size = font_size_medium; + + static LinkedList ui_listeners; + + static String look_and_feel = null; + + /* Serial debug */ + static boolean serial_debug; + + public static void init() { + AltosPreferences.init(new MicroPreferencesBackend()); + + font_listeners = new LinkedList(); + + font_size = backend.getInt(fontSizePreference, font_size_medium); + set_fonts(font_size); + look_and_feel = backend.getString(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); + + ui_listeners = new LinkedList(); + serial_debug = backend.getBoolean(serialDebugPreference, false); + } + + static { init(); } + + static void set_component(Component in_component) { + component = in_component; + } + + private static boolean check_dir(File dir) { + if (!dir.exists()) { + if (!dir.mkdirs()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Cannot create directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + } else if (!dir.isDirectory()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Is not a directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + /* Configure the log directory. This is where all telemetry and eeprom files + * will be written to, and where replay will look for telemetry files + */ + public static void ConfigureLog() { + JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); + + logdir_chooser.setDialogTitle("Configure Data Logging Directory"); + logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { + File dir = logdir_chooser.getSelectedFile(); + if (check_dir(dir)) + set_logdir(dir); + } + } + public static int font_size() { + synchronized (backend) { + return font_size; + } + } + + static void set_fonts() { + } + + public static void set_font_size(int new_font_size) { + synchronized (backend) { + font_size = new_font_size; + backend.putInt(fontSizePreference, font_size); + flush_preferences(); + set_fonts(font_size); + for (MicroFontListener l : font_listeners) + l.font_size_changed(font_size); + } + } + + public static void register_font_listener(MicroFontListener l) { + synchronized (backend) { + font_listeners.add(l); + } + } + + public static void unregister_font_listener(MicroFontListener l) { + synchronized (backend) { + font_listeners.remove(l); + } + } + + public static void set_look_and_feel(String new_look_and_feel) { + try { + UIManager.setLookAndFeel(new_look_and_feel); + } catch (Exception e) { + } + synchronized(backend) { + look_and_feel = new_look_and_feel; + backend.putString(lookAndFeelPreference, look_and_feel); + flush_preferences(); + for (MicroUIListener l : ui_listeners) + l.ui_changed(look_and_feel); + } + } + + public static String look_and_feel() { + synchronized (backend) { + return look_and_feel; + } + } + + public static void register_ui_listener(MicroUIListener l) { + synchronized(backend) { + ui_listeners.add(l); + } + } + + public static void unregister_ui_listener(MicroUIListener l) { + synchronized (backend) { + ui_listeners.remove(l); + } + } + public static void set_serial_debug(boolean new_serial_debug) { + synchronized (backend) { + serial_debug = new_serial_debug; + backend.putBoolean(serialDebugPreference, serial_debug); + flush_preferences(); + } + } + + public static boolean serial_debug() { + synchronized (backend) { + return serial_debug; + } + } + +} diff --git a/micropeak/MicroPreferencesBackend.java b/micropeak/MicroPreferencesBackend.java new file mode 100644 index 00000000..7d92f6be --- /dev/null +++ b/micropeak/MicroPreferencesBackend.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2012 Mike Beattie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.File; +import java.util.prefs.*; +import org.altusmetrum.AltosLib.*; +import javax.swing.filechooser.FileSystemView; + +public class MicroPreferencesBackend implements AltosPreferencesBackend { + + private Preferences _preferences = null; + + public MicroPreferencesBackend() { + _preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + } + + public MicroPreferencesBackend(Preferences in_preferences) { + _preferences = in_preferences; + } + + public String getString(String key, String def) { + return _preferences.get(key, def); + } + public void putString(String key, String value) { + _preferences.put(key, value); + } + + public int getInt(String key, int def) { + return _preferences.getInt(key, def); + } + public void putInt(String key, int value) { + _preferences.putInt(key, value); + } + + public double getDouble(String key, double def) { + return _preferences.getDouble(key, def); + } + public void putDouble(String key, double value) { + _preferences.putDouble(key, value); + } + + public boolean getBoolean(String key, boolean def) { + return _preferences.getBoolean(key, def); + } + public void putBoolean(String key, boolean value) { + _preferences.putBoolean(key, value); + } + + public boolean nodeExists(String key) { + try { + return _preferences.nodeExists(key); + } catch (BackingStoreException be) { + return false; + } + } + + public AltosPreferencesBackend node(String key) { + return new MicroPreferencesBackend(_preferences.node(key)); + } + + public String[] keys() { + try { + return _preferences.keys(); + } catch (BackingStoreException be) { + return null; + } + } + + public void remove(String key) { + _preferences.remove(key); + } + + public void flush() { + try { + _preferences.flush(); + } catch (BackingStoreException ee) { + System.err.printf("Cannot save preferences\n"); + } + } + + public File homeDirectory() { + /* Use the file system view default directory */ + return FileSystemView.getFileSystemView().getDefaultDirectory(); + } +} diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index afe55532..8546276e 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -24,7 +24,10 @@ public class MicroSerial extends InputStream { SWIGTYPE_p_altos_file file; public int read() { - return libaltos.altos_getchar(file, 0); + int c = libaltos.altos_getchar(file, 0); + if (MicroPreferences.serial_debug) + System.out.printf("%c", c); + return c; } public void close() { diff --git a/micropeak/MicroUIListener.java b/micropeak/MicroUIListener.java new file mode 100644 index 00000000..9aed8dae --- /dev/null +++ b/micropeak/MicroUIListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +public interface MicroUIListener { + public void ui_changed(String look_and_feel); +} -- cgit v1.2.3 From 03496dc47372c40f7faae1766b0e729a1feeab7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 31 Dec 2012 11:32:56 -0800 Subject: Create altosuilib to share code between altosui and micropeak Need to convert altosui to using it, but that shouldn't be hard Signed-off-by: Keith Packard --- Makefile.am | 2 +- altosuilib/AltosConfigureUI.java | 393 ++++++++++++++++++++++++++++++ altosuilib/AltosFontListener.java | 22 ++ altosuilib/AltosUIDialog.java | 59 +++++ altosuilib/AltosUIFrame.java | 82 +++++++ altosuilib/AltosUILib.java | 93 +++++++ altosuilib/AltosUIListener.java | 22 ++ altosuilib/AltosUIPreferences.java | 180 ++++++++++++++ altosuilib/AltosUIPreferencesBackend.java | 101 ++++++++ altosuilib/AltosUIVersion.java.in | 22 ++ altosuilib/AltosUnitsListener.java | 22 ++ altosuilib/Makefile.am | 41 ++++ configure.ac | 2 + 13 files changed, 1040 insertions(+), 1 deletion(-) create mode 100644 altosuilib/AltosConfigureUI.java create mode 100644 altosuilib/AltosFontListener.java create mode 100644 altosuilib/AltosUIDialog.java create mode 100644 altosuilib/AltosUIFrame.java create mode 100644 altosuilib/AltosUILib.java create mode 100644 altosuilib/AltosUIListener.java create mode 100644 altosuilib/AltosUIPreferences.java create mode 100644 altosuilib/AltosUIPreferencesBackend.java create mode 100644 altosuilib/AltosUIVersion.java.in create mode 100644 altosuilib/AltosUnitsListener.java create mode 100644 altosuilib/Makefile.am diff --git a/Makefile.am b/Makefile.am index 2e45aff0..e8945d90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src doc altoslib libaltos altosui ao-tools ao-utils altosdroid +SUBDIRS=src doc altoslib libaltos altosuilib altosui ao-tools ao-utils altosdroid EXTRA_DIST = ChangeLog diff --git a/altosuilib/AltosConfigureUI.java b/altosuilib/AltosConfigureUI.java new file mode 100644 index 00000000..a4b644bf --- /dev/null +++ b/altosuilib/AltosConfigureUI.java @@ -0,0 +1,393 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import javax.swing.*; +import javax.swing.event.*; + +class DelegatingRenderer implements ListCellRenderer { + + // ... + public static void install(JComboBox comboBox) { + DelegatingRenderer renderer = new DelegatingRenderer(comboBox); + renderer.initialise(); + comboBox.setRenderer(renderer); + } + + // ... + private final JComboBox comboBox; + + // ... + private ListCellRenderer delegate; + + // ... + private DelegatingRenderer(JComboBox comboBox) { + this.comboBox = comboBox; + } + + // ... + private void initialise() { + delegate = new JComboBox().getRenderer(); + comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent evt) { + delegate = new JComboBox().getRenderer(); + } + }); + } + + // ... + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + + return delegate.getListCellRendererComponent(list, + ((UIManager.LookAndFeelInfo) value).getName(), + index, isSelected, cellHasFocus); + } +} + +public class AltosConfigureUI + extends AltosUIDialog + implements DocumentListener +{ + JFrame owner; + Container pane; + + JRadioButton enable_voice; + JButton test_voice; + JButton close; + + JButton configure_log; + JTextField log_directory; + + JLabel callsign_label; + JTextField callsign_value; + + JRadioButton imperial_units; + + JLabel font_size_label; + JComboBox font_size_value; + + JLabel look_and_feel_label; + JComboBox look_and_feel_value; + + JRadioButton serial_debug; + + JButton manage_bluetooth; + JButton manage_frequencies; + + int row; + + final static String[] font_size_names = { "Small", "Medium", "Large" }; + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + if (callsign_value != null) + AltosUIPreferences.set_callsign(callsign_value.getText()); + } + + public void insertUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public void removeUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public GridBagConstraints constraints (int x, int width, int fill) { + GridBagConstraints c = new GridBagConstraints(); + Insets insets = new Insets(4, 4, 4, 4); + + c.insets = insets; + c.fill = fill; + if (width == 3) + c.anchor = GridBagConstraints.CENTER; + else + c.anchor = GridBagConstraints.WEST; + c.gridx = x; + c.gridwidth = width; + c.gridy = row; + return c; + } + + public GridBagConstraints constraints(int x, int width) { + return constraints(x, width, GridBagConstraints.NONE); + } + + public void add_voice() { +// GridBagConstraints c = new GridBagConstraints(); +// +// /* Voice settings */ +// c.gridx = 0; +// c.gridy = row; +// c.gridwidth = 1; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(new JLabel("Voice"), c); +// +// enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); +// enable_voice.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// JRadioButton item = (JRadioButton) e.getSource(); +// boolean enabled = item.isSelected(); +// AltosUIPreferences.set_voice(enabled); +// if (enabled) +// voice.speak_always("Enable voice."); +// else +// voice.speak_always("Disable voice."); +// } +// }); +// c.gridx = 1; +// c.gridy = row; +// c.gridwidth = 1; +// c.weightx = 1; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(enable_voice, c); +// enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); +// +// c.gridx = 2; +// c.gridy = row++; +// c.gridwidth = 1; +// c.weightx = 1; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.EAST; +// test_voice = new JButton("Test Voice"); +// test_voice.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// voice.speak("That's one small step for man; one giant leap for mankind."); +// } +// }); +// pane.add(test_voice, c); +// test_voice.setToolTipText("Play a stock audio clip to check volume"); +// row++; + } + + public void add_log_dir() { + /* Log directory settings */ + pane.add(new JLabel("Log Directory"), constraints(0, 1)); + + configure_log = new JButton(AltosUIPreferences.logdir().getPath()); + configure_log.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosUIPreferences.ConfigureLog(); + configure_log.setText(AltosUIPreferences.logdir().getPath()); + } + }); + pane.add(configure_log, constraints(1, 2)); + configure_log.setToolTipText("Which directory flight logs are stored in"); + row++; + } + + public void add_callsign() { +// /* Callsign setting */ +// pane.add(new JLabel("Callsign"), constraints(0, 1)); +// +// callsign_value = new JTextField(AltosUIPreferences.callsign()); +// callsign_value.getDocument().addDocumentListener(this); +// callsign_value.setToolTipText("Callsign sent in packet mode"); +// pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH)); +// row++; + } + + public void add_units() { + /* Imperial units setting */ + pane.add(new JLabel("Imperial Units"), constraints(0, 1)); + + imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units()); + imperial_units.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosUIPreferences.set_imperial_units(enabled); + } + }); + imperial_units.setToolTipText("Use Imperial units instead of metric"); + pane.add(imperial_units, constraints(1, 2)); + row++; + } + + public void add_font_size() { + /* Font size setting */ + pane.add(new JLabel("Font size"), constraints(0, 1)); + + font_size_value = new JComboBox(font_size_names); + int font_size = AltosUIPreferences.font_size(); + font_size_value.setSelectedIndex(font_size - AltosUILib.font_size_small); + font_size_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int size = font_size_value.getSelectedIndex() + AltosUILib.font_size_small; + + AltosUIPreferences.set_font_size(size); + } + }); + pane.add(font_size_value, constraints(1, 2, GridBagConstraints.BOTH)); + font_size_value.setToolTipText("Font size used in telemetry window"); + row++; + } + + public void add_look_and_feel() { + /* Look & Feel setting */ + pane.add(new JLabel("Look & feel"), constraints(0, 1)); + + /* + class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer { + + public LookAndFeelRenderer() { + super(); + } + + public Component getListCellRendererComponent( + JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + setText(((UIManager.LookAndFeelInfo) value).getName()); + return this; + } + } + */ + + final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); + + look_and_feel_value = new JComboBox(look_and_feels); + + DelegatingRenderer.install(look_and_feel_value); + + String look_and_feel = AltosUIPreferences.look_and_feel(); + for (int i = 0; i < look_and_feels.length; i++) + if (look_and_feel.equals(look_and_feels[i].getClassName())) + look_and_feel_value.setSelectedIndex(i); + + look_and_feel_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int id = look_and_feel_value.getSelectedIndex(); + + AltosUIPreferences.set_look_and_feel(look_and_feels[id].getClassName()); + } + }); + pane.add(look_and_feel_value, constraints(1, 2, GridBagConstraints.BOTH)); + look_and_feel_value.setToolTipText("Look&feel used for new windows"); + row++; + } + + public void add_serial_debug() { + GridBagConstraints c = new GridBagConstraints(); + + /* Serial debug setting */ + pane.add(new JLabel("Serial Debug"), constraints(0, 1)); + + serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); + serial_debug.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosUIPreferences.set_serial_debug(enabled); + } + }); + serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); + } + + public void add_bluetooth() { +// GridBagConstraints c = new GridBagConstraints(); +// c.gridx = 1; +// c.gridy = row++; +// c.gridwidth = 3; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(serial_debug, c); +// +// manage_bluetooth = new JButton("Manage Bluetooth"); +// manage_bluetooth.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// AltosBTManage.show(owner, AltosBTKnown.bt_known()); +// } +// }); +// c.gridx = 0; +// c.gridy = row; +// c.gridwidth = 2; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(manage_bluetooth, c); + } + + public void add_frequencies() { +// GridBagConstraints c = new GridBagConstraints(); +// manage_frequencies = new JButton("Manage Frequencies"); +// manage_frequencies.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// AltosConfigFreqUI.show(owner); +// } +// }); +// manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); +// c.gridx = 2; +// c.gridx = 2; +// c.gridy = row++; +// c.gridwidth = 2; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(manage_frequencies, c); + } + + public AltosConfigureUI(JFrame in_owner) { + super(in_owner, "Configure AltosUI", false); + + owner = in_owner; + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + row = 0; + + /* Nice label at the top */ + pane.add(new JLabel ("Configure AltOS UI"), + constraints(0, 3)); + row++; + + pane.add(new JLabel (String.format("AltOS version %s", AltosUIVersion.version)), + constraints(0, 3)); + row++; + + add_voice(); + add_log_dir(); + add_callsign(); + add_units(); + add_font_size(); + add_look_and_feel(); + add_bluetooth(); + add_frequencies(); + + /* And a close button at the bottom */ + close = new JButton("Close"); + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + pane.add(close, constraints(0, 3)); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} diff --git a/altosuilib/AltosFontListener.java b/altosuilib/AltosFontListener.java new file mode 100644 index 00000000..ef543264 --- /dev/null +++ b/altosuilib/AltosFontListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +public interface AltosFontListener { + void font_size_changed(int font_size); +} diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java new file mode 100644 index 00000000..c0c33ba6 --- /dev/null +++ b/altosuilib/AltosUIDialog.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +class AltosUIDialogListener extends WindowAdapter { + public void windowClosing (WindowEvent e) { + AltosUIPreferences.unregister_ui_listener((AltosUIDialog) e.getWindow()); + } +} + +public class AltosUIDialog extends JDialog implements AltosUIListener { + + public void ui_changed(String look_and_feel) { + SwingUtilities.updateComponentTreeUI(this); + this.pack(); + } + + public AltosUIDialog() { + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosUIDialogListener()); + } + + public AltosUIDialog(Frame frame, String label, boolean modal) { + super(frame, label, modal); + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosUIDialogListener()); + } + + public AltosUIDialog(Dialog dialog, String label, boolean modal) { + super(dialog, label, modal); + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosUIDialogListener()); + } + + public AltosUIDialog(Frame frame, boolean modal) { + super(frame, modal); + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosUIDialogListener()); + } +} diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java new file mode 100644 index 00000000..409aea2e --- /dev/null +++ b/altosuilib/AltosUIFrame.java @@ -0,0 +1,82 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +class AltosUIFrameListener extends WindowAdapter { + public void windowClosing (WindowEvent e) { + AltosUIPreferences.unregister_ui_listener((AltosUIFrame) e.getWindow()); + } +} + +public class AltosUIFrame extends JFrame implements AltosUIListener { + + public void ui_changed(String look_and_feel) { + SwingUtilities.updateComponentTreeUI(this); + this.pack(); + } + + static String[] altos_icon_names = { + "/altus-metrum-16.png", + "/altus-metrum-32.png", + "/altus-metrum-48.png", + "/altus-metrum-64.png", + "/altus-metrum-128.png", + "/altus-metrum-256.png" + }; + + static public String[] icon_names; + + static public void set_icon_names(String[] new_icon_names) { icon_names = new_icon_names; } + + public String[] icon_names() { + if (icon_names == null) + set_icon_names(altos_icon_names); + return icon_names; + } + + public void set_icon() { + ArrayList icons = new ArrayList(); + String[] icon_names = icon_names(); + + for (int i = 0; i < icon_names.length; i++) { + java.net.URL imgURL = AltosUIFrame.class.getResource(icon_names[i]); + if (imgURL != null) + icons.add(new ImageIcon(imgURL).getImage()); + } + setIconImages(icons); + } + + + public AltosUIFrame() { + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosUIFrameListener()); + set_icon(); + } + + public AltosUIFrame(String name) { + super(name); + AltosUIPreferences.register_ui_listener(this); + addWindowListener(new AltosUIFrameListener()); + set_icon(); + } +} diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java new file mode 100644 index 00000000..717678ba --- /dev/null +++ b/altosuilib/AltosUILib.java @@ -0,0 +1,93 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.awt.*; +import libaltosJNI.*; + +import org.altusmetrum.AltosLib.*; + +public class AltosUILib extends AltosLib { + + static final int tab_elt_pad = 5; + + static Font label_font; + static Font value_font; + static Font status_font; + static Font table_label_font; + static Font table_value_font; + + final static int font_size_small = 1; + final static int font_size_medium = 2; + final static int font_size_large = 3; + + static void set_fonts(int size) { + int brief_size; + int table_size; + int status_size; + + switch (size) { + case font_size_small: + brief_size = 16; + status_size = 18; + table_size = 11; + break; + default: + case font_size_medium: + brief_size = 22; + status_size = 24; + table_size = 14; + break; + case font_size_large: + brief_size = 26; + status_size = 30; + table_size = 17; + break; + } + label_font = new Font("Dialog", Font.PLAIN, brief_size); + value_font = new Font("Monospaced", Font.PLAIN, brief_size); + status_font = new Font("SansSerif", Font.BOLD, status_size); + table_label_font = new Font("SansSerif", Font.PLAIN, table_size); + table_value_font = new Font("Monospaced", Font.PLAIN, table_size); + } + + static final int text_width = 20; + + static public boolean initialized = false; + static public boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + try { + System.loadLibrary("altos64"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e2) { + loaded_library = false; + } + } + initialized = true; + } + return loaded_library; + } +} diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java new file mode 100644 index 00000000..f4127f58 --- /dev/null +++ b/altosuilib/AltosUIListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +public interface AltosUIListener { + public void ui_changed(String look_and_feel); +} diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java new file mode 100644 index 00000000..485cb582 --- /dev/null +++ b/altosuilib/AltosUIPreferences.java @@ -0,0 +1,180 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.io.*; +import java.util.*; +import java.awt.Component; +import javax.swing.*; +import org.altusmetrum.AltosLib.*; + +public class AltosUIPreferences extends AltosPreferences { + + /* font size preferences name */ + final static String fontSizePreference = "FONT-SIZE"; + + /* Look&Feel preference name */ + final static String lookAndFeelPreference = "LOOK-AND-FEEL"; + + /* UI Component to pop dialogs up */ + static Component component; + + static LinkedList font_listeners; + + static int font_size = AltosUILib.font_size_medium; + + static LinkedList ui_listeners; + + static String look_and_feel = null; + + /* Serial debug */ + public static boolean serial_debug; + + public static void init() { + AltosPreferences.init(new AltosUIPreferencesBackend()); + + font_listeners = new LinkedList(); + + font_size = backend.getInt(fontSizePreference, AltosUILib.font_size_medium); + AltosUILib.set_fonts(font_size); + look_and_feel = backend.getString(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); + + ui_listeners = new LinkedList(); + serial_debug = backend.getBoolean(serialDebugPreference, false); + AltosLink.set_debug(serial_debug); + } + + static { init(); } + + public static void set_component(Component in_component) { + component = in_component; + } + + private static boolean check_dir(File dir) { + if (!dir.exists()) { + if (!dir.mkdirs()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Cannot create directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + } else if (!dir.isDirectory()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Is not a directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + /* Configure the log directory. This is where all telemetry and eeprom files + * will be written to, and where replay will look for telemetry files + */ + public static void ConfigureLog() { + JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); + + logdir_chooser.setDialogTitle("Configure Data Logging Directory"); + logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { + File dir = logdir_chooser.getSelectedFile(); + if (check_dir(dir)) + set_logdir(dir); + } + } + public static int font_size() { + synchronized (backend) { + return font_size; + } + } + + static void set_fonts() { + } + + public static void set_font_size(int new_font_size) { + synchronized (backend) { + font_size = new_font_size; + backend.putInt(fontSizePreference, font_size); + flush_preferences(); + AltosUILib.set_fonts(font_size); + for (AltosFontListener l : font_listeners) + l.font_size_changed(font_size); + } + } + + public static void register_font_listener(AltosFontListener l) { + synchronized (backend) { + font_listeners.add(l); + } + } + + public static void unregister_font_listener(AltosFontListener l) { + synchronized (backend) { + font_listeners.remove(l); + } + } + + public static void set_look_and_feel(String new_look_and_feel) { + try { + UIManager.setLookAndFeel(new_look_and_feel); + } catch (Exception e) { + } + synchronized(backend) { + look_and_feel = new_look_and_feel; + backend.putString(lookAndFeelPreference, look_and_feel); + flush_preferences(); + for (AltosUIListener l : ui_listeners) + l.ui_changed(look_and_feel); + } + } + + public static String look_and_feel() { + synchronized (backend) { + return look_and_feel; + } + } + + public static void register_ui_listener(AltosUIListener l) { + synchronized(backend) { + ui_listeners.add(l); + } + } + + public static void unregister_ui_listener(AltosUIListener l) { + synchronized (backend) { + ui_listeners.remove(l); + } + } + public static void set_serial_debug(boolean new_serial_debug) { + AltosLink.set_debug(new_serial_debug); + synchronized (backend) { + serial_debug = new_serial_debug; + backend.putBoolean(serialDebugPreference, serial_debug); + flush_preferences(); + } + } + + public static boolean serial_debug() { + synchronized (backend) { + return serial_debug; + } + } + +} diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java new file mode 100644 index 00000000..c6c05e55 --- /dev/null +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2012 Mike Beattie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.io.File; +import java.util.prefs.*; +import org.altusmetrum.AltosLib.*; +import javax.swing.filechooser.FileSystemView; + +public class AltosUIPreferencesBackend implements AltosPreferencesBackend { + + private Preferences _preferences = null; + + public AltosUIPreferencesBackend() { + _preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + } + + public AltosUIPreferencesBackend(Preferences in_preferences) { + _preferences = in_preferences; + } + + public String getString(String key, String def) { + return _preferences.get(key, def); + } + public void putString(String key, String value) { + _preferences.put(key, value); + } + + public int getInt(String key, int def) { + return _preferences.getInt(key, def); + } + public void putInt(String key, int value) { + _preferences.putInt(key, value); + } + + public double getDouble(String key, double def) { + return _preferences.getDouble(key, def); + } + public void putDouble(String key, double value) { + _preferences.putDouble(key, value); + } + + public boolean getBoolean(String key, boolean def) { + return _preferences.getBoolean(key, def); + } + public void putBoolean(String key, boolean value) { + _preferences.putBoolean(key, value); + } + + public boolean nodeExists(String key) { + try { + return _preferences.nodeExists(key); + } catch (BackingStoreException be) { + return false; + } + } + + public AltosPreferencesBackend node(String key) { + return new AltosUIPreferencesBackend(_preferences.node(key)); + } + + public String[] keys() { + try { + return _preferences.keys(); + } catch (BackingStoreException be) { + return null; + } + } + + public void remove(String key) { + _preferences.remove(key); + } + + public void flush() { + try { + _preferences.flush(); + } catch (BackingStoreException ee) { + System.err.printf("Cannot save preferences\n"); + } + } + + public File homeDirectory() { + /* Use the file system view default directory */ + return FileSystemView.getFileSystemView().getDefaultDirectory(); + } +} diff --git a/altosuilib/AltosUIVersion.java.in b/altosuilib/AltosUIVersion.java.in new file mode 100644 index 00000000..6fb3b38b --- /dev/null +++ b/altosuilib/AltosUIVersion.java.in @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +public class AltosUIVersion { + public final static String version = "@VERSION@"; +} diff --git a/altosuilib/AltosUnitsListener.java b/altosuilib/AltosUnitsListener.java new file mode 100644 index 00000000..22c66cd4 --- /dev/null +++ b/altosuilib/AltosUnitsListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +public interface AltosUnitsListener { + public void units_changed(); +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am new file mode 100644 index 00000000..26aee7c4 --- /dev/null +++ b/altosuilib/Makefile.am @@ -0,0 +1,41 @@ +AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation + +JAVAROOT=bin + +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:../altoslib/*:../libaltos:$(FREETTS)/*:/usr/share/java/*" + +SRC=. +BIN=bin/org/altusmetrum/AltosUILib + +AltosUILibdir = $(datadir)/java + +AltosUILib_JAVA = \ + AltosConfigureUI.java \ + AltosFontListener.java \ + AltosUIDialog.java \ + AltosUIFrame.java \ + AltosUILib.java \ + AltosUIListener.java \ + AltosUIPreferencesBackend.java \ + AltosUIPreferences.java \ + AltosUIVersion.java \ + AltosUnitsListener.java + +JAR=AltosUILib.jar + +all-local: $(JAR) + +clean-local: + -rm -rf bin $(JAR) + +install-AltosUILibJAVA: $(JAR) + @$(NORMAL_INSTALL) + test -z "$(AltosUILibdir)" || $(MKDIR_P) "$(DESTDIR)$(AltosUILibdir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(AltosUILibdir)/$(JAR)"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(AltosUILibdir)" + +bin: + mkdir -p bin + +$(JAR): classAltosUILib.stamp + jar cf $@ -C bin org diff --git a/configure.ac b/configure.ac index 55dd20ec..6ad2591c 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,8 @@ AM_CONDITIONAL([LIBSTLINK], [test x$HAVE_STLINK != xno]) AC_OUTPUT([ Makefile altoslib/Makefile +altosuilib/Makefile +altosuilib/AltosUIVersion.java altosui/Makefile altosui/AltosVersion.java altosui/Info.plist -- cgit v1.2.3 From 6db192898eebf750c4d51516eff7916bc4da493b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 31 Dec 2012 11:38:53 -0800 Subject: altoslib: Add units change notification list This allows the UI to automatically respond to changes in the preferred units. Signed-off-by: Keith Packard --- altoslib/AltosPreferences.java | 21 +++++++++++++++++++++ altoslib/AltosUnitsListener.java | 22 ++++++++++++++++++++++ altoslib/Makefile.am | 1 + 3 files changed, 44 insertions(+) create mode 100644 altoslib/AltosUnitsListener.java diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 47196d6e..e50b9b5c 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -367,6 +367,8 @@ public class AltosPreferences { set_common_frequencies(new_frequencies); } + static LinkedList units_listeners; + public static boolean imperial_units() { synchronized(backend) { return AltosConvert.imperial_units; @@ -379,5 +381,24 @@ public class AltosPreferences { backend.putBoolean(unitsPreference, imperial_units); flush_preferences(); } + if (units_listeners != null) { + for (AltosUnitsListener l : units_listeners) { + l.units_changed(imperial_units); + } + } + } + + public static void register_units_listener(AltosUnitsListener l) { + synchronized(backend) { + if (units_listeners == null) + units_listeners = new LinkedList(); + units_listeners.add(l); + } + } + + public static void unregister_units_listener(AltosUnitsListener l) { + synchronized(backend) { + units_listeners.remove(l); + } } } diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java new file mode 100644 index 00000000..50a00cdf --- /dev/null +++ b/altoslib/AltosUnitsListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public interface AltosUnitsListener { + public void units_changed(boolean imperial_units); +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 0086bc65..1b03c925 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -69,6 +69,7 @@ AltosLib_JAVA = \ $(SRC)/AltosTelemetryRecordSensor.java \ $(SRC)/AltosTelemetryRecordMegaSensor.java \ $(SRC)/AltosTelemetryRecordMegaData.java \ + $(SRC)/AltosUnitsListener.java \ $(SRC)/AltosMs5607.java \ $(SRC)/AltosIMU.java \ $(SRC)/AltosMag.java \ -- cgit v1.2.3 From 56a1210a7b04a3623d19ec282f26fecc79c126dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 31 Dec 2012 11:42:57 -0800 Subject: micropeak: Use altosuilib This removes a pile of code stolen from altosui Signed-off-by: Keith Packard --- micropeak/.gitignore | 6 + micropeak/Makefile.am | 22 ++-- micropeak/MicroFileChooser.java | 2 + micropeak/MicroFontListener.java | 22 ---- micropeak/MicroFrame.java | 45 +------ micropeak/MicroGraph.java | 82 +++++++++--- micropeak/MicroPeak.java | 21 +++- micropeak/MicroPreferences.java | 221 --------------------------------- micropeak/MicroPreferencesBackend.java | 101 --------------- micropeak/MicroSerial.java | 4 +- micropeak/MicroUIListener.java | 22 ---- 11 files changed, 109 insertions(+), 439 deletions(-) create mode 100644 micropeak/.gitignore delete mode 100644 micropeak/MicroFontListener.java delete mode 100644 micropeak/MicroPreferences.java delete mode 100644 micropeak/MicroPreferencesBackend.java delete mode 100644 micropeak/MicroUIListener.java diff --git a/micropeak/.gitignore b/micropeak/.gitignore new file mode 100644 index 00000000..fc99b31c --- /dev/null +++ b/micropeak/.gitignore @@ -0,0 +1,6 @@ +*.jar +Manifest.txt +classes +*.stamp +micropeak +micropeak-test diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 2cfd2ad3..fde981a6 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -1,7 +1,7 @@ JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" bin_SCRIPTS=micropeak @@ -14,10 +14,6 @@ micropeak_JAVA= \ MicroGraph.java \ MicroSerial.java \ MicroFileChooser.java \ - MicroPreferences.java \ - MicroPreferencesBackend.java \ - MicroFontListener.java \ - MicroUIListener.java \ MicroUSB.java JFREECHART_CLASS= \ @@ -38,6 +34,9 @@ LIBALTOS= \ ALTOSLIB_CLASS=\ AltosLib.jar +ALTOSUILIB_CLASS=\ + AltosUILib.jar + # Icons ICONDIR=$(top_srcdir)/icon @@ -62,6 +61,7 @@ all-local: micropeak-test $(JAR) clean-local: -rm -rf classes $(JAR) $(FATJAR) \ $(ALTOSLIB_CLASS) \ + $(ALTOSUILIB_CLASS) \ $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt \ micropeak micropeak-test macosx linux windows @@ -75,13 +75,13 @@ micropeak-test: Makefile echo 'exec java -cp "./*:../libaltos/*:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar micropeak.jar "$$@"' >> $@ chmod +x $@ -$(JAR): classmicropeak.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) +$(JAR): classmicropeak.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) jar cfm $@ Manifest.txt \ $(ICONJAR) \ -C classes org \ -C ../libaltos libaltosJNI -$(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS) +$(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(JAVA_ICONS) jar cfm $@ Manifest-fat.txt \ $(ICONJAR) \ -C classes org \ @@ -122,6 +122,10 @@ $(ALTOSLIB_CLASS): -rm -f "$@" $(LN_S) ../altoslib/"$@" . +$(ALTOSUILIB_CLASS): + -rm -f "$@" + $(LN_S) ../altosuilib/"$@" . + $(JFREECHART_CLASS): -rm -f "$@" $(LN_S) "$(JFREECHART)"/"$@" . @@ -132,9 +136,9 @@ $(JCOMMON_CLASS): Manifest.txt: Makefile echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ - echo "Class-Path: AltosLib.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ + echo "Class-Path: AltosLib.jar AltosUILib.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ - echo "Class-Path: AltosLib.jar jcommon.jar jfreechart.jar" >> $@ + echo "Class-Path: AltosLib.jar AltosUILib.jar jcommon.jar jfreechart.jar" >> $@ diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java index 0fd63a27..d2540987 100644 --- a/micropeak/MicroFileChooser.java +++ b/micropeak/MicroFileChooser.java @@ -21,6 +21,7 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class MicroFileChooser extends JFileChooser { JFrame frame; @@ -61,5 +62,6 @@ public class MicroFileChooser extends JFileChooser { setDialogTitle("Select MicroPeak Data File"); setFileFilter(new FileNameExtensionFilter("MicroPeak data file", "mpd")); + setCurrentDirectory(AltosUIPreferences.logdir()); } } diff --git a/micropeak/MicroFontListener.java b/micropeak/MicroFontListener.java deleted file mode 100644 index a902584c..00000000 --- a/micropeak/MicroFontListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -public interface MicroFontListener { - void font_size_changed(int font_size); -} diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java index a9b9a37a..03e3af0c 100644 --- a/micropeak/MicroFrame.java +++ b/micropeak/MicroFrame.java @@ -21,21 +21,10 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; +import org.altusmetrum.altosuilib.*; -class MicroFrameListener extends WindowAdapter { - public void windowClosing (WindowEvent e) { - MicroPreferences.unregister_ui_listener((MicroFrame) e.getWindow()); - } -} - -public class MicroFrame extends JFrame implements MicroUIListener { - - public void ui_changed(String look_and_feel) { - SwingUtilities.updateComponentTreeUI(this); - this.pack(); - } - - static final String[] icon_names = { +public class MicroFrame extends AltosUIFrame { + static String[] micro_icon_names = { "/micropeak-16.png", "/micropeak-32.png", "/micropeak-48.png", @@ -44,31 +33,5 @@ public class MicroFrame extends JFrame implements MicroUIListener { "/micropeak-256.png" }; - public void set_icon() { - ArrayList icons = new ArrayList(); - - for (int i = 0; i < icon_names.length; i++) { - java.net.URL imgURL = MicroPeak.class.getResource(icon_names[i]); - if (imgURL != null) - icons.add(new ImageIcon(imgURL).getImage()); - } - - setIconImages(icons); - } - - public MicroFrame() { - super(); - MicroPreferences.set_component(this); - MicroPreferences.register_ui_listener(this); - addWindowListener(new MicroFrameListener()); - set_icon(); - } - - public MicroFrame(String name) { - super(name); - MicroPreferences.set_component(this); - MicroPreferences.register_ui_listener(this); - addWindowListener(new MicroFrameListener()); - set_icon(); - } + static { set_icon_names(micro_icon_names); } } diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index 9192cad9..38f54fe0 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -34,15 +34,47 @@ import org.jfree.chart.labels.*; import org.jfree.data.xy.*; import org.jfree.data.*; -public class MicroGraph { +class MicroSeries extends XYSeries { + NumberAxis axis; + String label; + String units; + Color color; + + String label() { + return String.format("%s (%s)", label, units); + } + + void set_units(String units) { + this.units = units; + + axis.setLabel(label()); + } + + public MicroSeries (String label, String units, Color color) { + super(label); + this.label = label; + this.units = units; + this.color = color; + + axis = new NumberAxis(label()); + axis.setLabelPaint(color); + axis.setTickLabelPaint(color); + } +} + +public class MicroGraph implements AltosUnitsListener { XYPlot plot; JFreeChart chart; ChartPanel panel; NumberAxis xAxis; - XYSeries heightSeries; - XYSeries speedSeries; - XYSeries accelSeries; + MicroSeries heightSeries; + MicroSeries speedSeries; + MicroSeries accelSeries; + + static final private Color red = new Color(194,31,31); + static final private Color green = new Color(31,194,31); + static final private Color blue = new Color(31,31,194); MicroData data; @@ -50,40 +82,50 @@ public class MicroGraph { return panel; } - private void addSeries(XYSeries series, int index, String label, String units) { + private MicroSeries addSeries(int index, String label, String units, Color color) { + MicroSeries series = new MicroSeries(label, units, color); XYSeriesCollection dataset = new XYSeriesCollection(series); - NumberAxis axis = new NumberAxis(String.format("%s (%s)", label, units)); XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); + renderer.setSeriesPaint(0, color); renderer.setPlot(plot); renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", units), new java.text.DecimalFormat("0.00"), new java.text.DecimalFormat("0.00"))); - plot.setRangeAxis(index, axis); + plot.setRangeAxis(index, series.axis); plot.setDataset(index, dataset); plot.setRenderer(index, renderer); plot.mapDatasetToRangeAxis(index, index); + return series; } - public void setData (MicroData data) { + public void resetData() { heightSeries.clear(); speedSeries.clear(); accelSeries.clear(); for (int i = 0; i < data.pressures.length; i++) { double x = data.time(i); - heightSeries.add(x, data.height(i)); - speedSeries.add(x, data.speed(i)); - accelSeries.add(x, data.acceleration(i)); + heightSeries.add(x, AltosConvert.height.value(data.height(i))); + speedSeries.add(x, AltosConvert.speed.value(data.speed(i))); + accelSeries.add(x, AltosConvert.accel.value(data.acceleration(i))); } } - public MicroGraph(MicroData data) { - + public void setData (MicroData data) { this.data = data; + resetData(); + } - heightSeries = new XYSeries("Height"); - speedSeries = new XYSeries("Speed"); - accelSeries = new XYSeries("Acceleration"); + public void units_changed(boolean imperial_units) { + if (data != null) { + heightSeries.set_units(AltosConvert.height.show_units()); + speedSeries.set_units(AltosConvert.speed.show_units()); + accelSeries.set_units(AltosConvert.accel.show_units()); + resetData(); + } + } + + public MicroGraph() { xAxis = new NumberAxis("Time (s)"); @@ -95,9 +137,9 @@ public class MicroGraph { plot.setDomainPannable(true); plot.setRangePannable(true); - addSeries(heightSeries, 0, "Height", "m"); - addSeries(speedSeries, 1, "Speed", "m/s"); - addSeries(accelSeries, 2, "Acceleration", "m/s²"); + heightSeries = addSeries(0, "Height", AltosConvert.height.show_units(), red); + speedSeries = addSeries(1, "Speed", AltosConvert.speed.show_units(), green); + accelSeries = addSeries(2, "Acceleration", AltosConvert.accel.show_units(), blue); chart = new JFreeChart("Flight", JFreeChart.DEFAULT_TITLE_FONT, plot, true); @@ -106,5 +148,7 @@ public class MicroGraph { panel = new ChartPanel(chart); panel.setMouseWheelEnabled(true); panel.setPreferredSize(new java.awt.Dimension(800, 500)); + + AltosPreferences.register_units_listener(this); } } \ No newline at end of file diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index c9074348..463238c8 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -24,6 +24,7 @@ import java.io.*; import java.util.concurrent.*; import java.util.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class MicroPeak extends MicroFrame implements ActionListener, ItemListener { @@ -59,6 +60,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene RunFile(input); } + private void Preferences() { + new AltosConfigureUI(this); + } + private void DownloadData() { java.util.List devices = MicroUSB.list(); for (MicroUSB device : devices) @@ -66,7 +71,6 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } public void actionPerformed(ActionEvent ev) { - System.out.printf("action %s %s\n", ev.getActionCommand(), ev.paramString()); if ("Exit".equals(ev.getActionCommand())) System.exit(0); else if ("Open".equals(ev.getActionCommand())) @@ -75,6 +79,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene new MicroPeak(); else if ("Download".equals(ev.getActionCommand())) DownloadData(); + else if ("Preferences".equals(ev.getActionCommand())) + Preferences(); } public void itemStateChanged(ItemEvent e) { @@ -82,7 +88,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene public MicroPeak() { - this.filename = filename; + AltosUIPreferences.set_component(this); pane = getContentPane(); @@ -106,6 +112,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene fileMenu.add(downloadAction); downloadAction.addActionListener(this); + JMenuItem preferencesAction = new JMenuItem("Preferences"); + fileMenu.add(preferencesAction); + preferencesAction.addActionListener(this); + JMenuItem exitAction = new JMenuItem("Exit"); fileMenu.add(exitAction); exitAction.addActionListener(this); @@ -118,7 +128,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } }); - graph = new MicroGraph(data); + graph = new MicroGraph(); pane.add(graph.panel); pane.doLayout(); pane.validate(); @@ -136,6 +146,11 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene public static void main(final String[] args) { boolean opened = false; + try { + UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel()); + } catch (Exception e) { + } + for (int i = 0; i < args.length; i++) { MicroPeak m = new MicroPeak(); m.OpenFile(new File(args[i])); diff --git a/micropeak/MicroPreferences.java b/micropeak/MicroPreferences.java deleted file mode 100644 index 70c2557c..00000000 --- a/micropeak/MicroPreferences.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -import java.io.*; -import java.util.*; -import java.awt.Component; -import javax.swing.*; -import java.awt.*; -import org.altusmetrum.AltosLib.*; - -public class MicroPreferences extends AltosPreferences { - - static final int tab_elt_pad = 5; - - static Font label_font; - static Font value_font; - static Font status_font; - static Font table_label_font; - static Font table_value_font; - - final static int font_size_small = 1; - final static int font_size_medium = 2; - final static int font_size_large = 3; - - static void set_fonts(int size) { - int brief_size; - int table_size; - int status_size; - - switch (size) { - case font_size_small: - brief_size = 16; - status_size = 18; - table_size = 11; - break; - default: - case font_size_medium: - brief_size = 22; - status_size = 24; - table_size = 14; - break; - case font_size_large: - brief_size = 26; - status_size = 30; - table_size = 17; - break; - } - label_font = new Font("Dialog", Font.PLAIN, brief_size); - value_font = new Font("Monospaced", Font.PLAIN, brief_size); - status_font = new Font("SansSerif", Font.BOLD, status_size); - table_label_font = new Font("SansSerif", Font.PLAIN, table_size); - table_value_font = new Font("Monospaced", Font.PLAIN, table_size); - } - - /* font size preferences name */ - final static String fontSizePreference = "FONT-SIZE"; - - /* Look&Feel preference name */ - final static String lookAndFeelPreference = "LOOK-AND-FEEL"; - - /* UI Component to pop dialogs up */ - static Component component; - - static LinkedList font_listeners; - - static int font_size = font_size_medium; - - static LinkedList ui_listeners; - - static String look_and_feel = null; - - /* Serial debug */ - static boolean serial_debug; - - public static void init() { - AltosPreferences.init(new MicroPreferencesBackend()); - - font_listeners = new LinkedList(); - - font_size = backend.getInt(fontSizePreference, font_size_medium); - set_fonts(font_size); - look_and_feel = backend.getString(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); - - ui_listeners = new LinkedList(); - serial_debug = backend.getBoolean(serialDebugPreference, false); - } - - static { init(); } - - static void set_component(Component in_component) { - component = in_component; - } - - private static boolean check_dir(File dir) { - if (!dir.exists()) { - if (!dir.mkdirs()) { - JOptionPane.showMessageDialog(component, - dir.getName(), - "Cannot create directory", - JOptionPane.ERROR_MESSAGE); - return false; - } - } else if (!dir.isDirectory()) { - JOptionPane.showMessageDialog(component, - dir.getName(), - "Is not a directory", - JOptionPane.ERROR_MESSAGE); - return false; - } - return true; - } - - /* Configure the log directory. This is where all telemetry and eeprom files - * will be written to, and where replay will look for telemetry files - */ - public static void ConfigureLog() { - JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); - - logdir_chooser.setDialogTitle("Configure Data Logging Directory"); - logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { - File dir = logdir_chooser.getSelectedFile(); - if (check_dir(dir)) - set_logdir(dir); - } - } - public static int font_size() { - synchronized (backend) { - return font_size; - } - } - - static void set_fonts() { - } - - public static void set_font_size(int new_font_size) { - synchronized (backend) { - font_size = new_font_size; - backend.putInt(fontSizePreference, font_size); - flush_preferences(); - set_fonts(font_size); - for (MicroFontListener l : font_listeners) - l.font_size_changed(font_size); - } - } - - public static void register_font_listener(MicroFontListener l) { - synchronized (backend) { - font_listeners.add(l); - } - } - - public static void unregister_font_listener(MicroFontListener l) { - synchronized (backend) { - font_listeners.remove(l); - } - } - - public static void set_look_and_feel(String new_look_and_feel) { - try { - UIManager.setLookAndFeel(new_look_and_feel); - } catch (Exception e) { - } - synchronized(backend) { - look_and_feel = new_look_and_feel; - backend.putString(lookAndFeelPreference, look_and_feel); - flush_preferences(); - for (MicroUIListener l : ui_listeners) - l.ui_changed(look_and_feel); - } - } - - public static String look_and_feel() { - synchronized (backend) { - return look_and_feel; - } - } - - public static void register_ui_listener(MicroUIListener l) { - synchronized(backend) { - ui_listeners.add(l); - } - } - - public static void unregister_ui_listener(MicroUIListener l) { - synchronized (backend) { - ui_listeners.remove(l); - } - } - public static void set_serial_debug(boolean new_serial_debug) { - synchronized (backend) { - serial_debug = new_serial_debug; - backend.putBoolean(serialDebugPreference, serial_debug); - flush_preferences(); - } - } - - public static boolean serial_debug() { - synchronized (backend) { - return serial_debug; - } - } - -} diff --git a/micropeak/MicroPreferencesBackend.java b/micropeak/MicroPreferencesBackend.java deleted file mode 100644 index 7d92f6be..00000000 --- a/micropeak/MicroPreferencesBackend.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2012 Mike Beattie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -import java.io.File; -import java.util.prefs.*; -import org.altusmetrum.AltosLib.*; -import javax.swing.filechooser.FileSystemView; - -public class MicroPreferencesBackend implements AltosPreferencesBackend { - - private Preferences _preferences = null; - - public MicroPreferencesBackend() { - _preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); - } - - public MicroPreferencesBackend(Preferences in_preferences) { - _preferences = in_preferences; - } - - public String getString(String key, String def) { - return _preferences.get(key, def); - } - public void putString(String key, String value) { - _preferences.put(key, value); - } - - public int getInt(String key, int def) { - return _preferences.getInt(key, def); - } - public void putInt(String key, int value) { - _preferences.putInt(key, value); - } - - public double getDouble(String key, double def) { - return _preferences.getDouble(key, def); - } - public void putDouble(String key, double value) { - _preferences.putDouble(key, value); - } - - public boolean getBoolean(String key, boolean def) { - return _preferences.getBoolean(key, def); - } - public void putBoolean(String key, boolean value) { - _preferences.putBoolean(key, value); - } - - public boolean nodeExists(String key) { - try { - return _preferences.nodeExists(key); - } catch (BackingStoreException be) { - return false; - } - } - - public AltosPreferencesBackend node(String key) { - return new MicroPreferencesBackend(_preferences.node(key)); - } - - public String[] keys() { - try { - return _preferences.keys(); - } catch (BackingStoreException be) { - return null; - } - } - - public void remove(String key) { - _preferences.remove(key); - } - - public void flush() { - try { - _preferences.flush(); - } catch (BackingStoreException ee) { - System.err.printf("Cannot save preferences\n"); - } - } - - public File homeDirectory() { - /* Use the file system view default directory */ - return FileSystemView.getFileSystemView().getDefaultDirectory(); - } -} diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index 8546276e..a1a77a1d 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -16,16 +16,18 @@ */ package org.altusmetrum.micropeak; + import java.util.*; import java.io.*; import libaltosJNI.*; +import org.altusmetrum.altosuilib.*; public class MicroSerial extends InputStream { SWIGTYPE_p_altos_file file; public int read() { int c = libaltos.altos_getchar(file, 0); - if (MicroPreferences.serial_debug) + if (AltosUIPreferences.serial_debug) System.out.printf("%c", c); return c; } diff --git a/micropeak/MicroUIListener.java b/micropeak/MicroUIListener.java deleted file mode 100644 index 9aed8dae..00000000 --- a/micropeak/MicroUIListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -public interface MicroUIListener { - public void ui_changed(String look_and_feel); -} -- cgit v1.2.3 From 2bd6aca54fc465995d6985c8799cd0d016c9a543 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 31 Dec 2012 14:17:26 -0800 Subject: micropeak: Add flight stats pane Shows graph or stats in alternate panes Signed-off-by: Keith Packard --- altosuilib/AltosUILib.java | 18 ++-- micropeak/Makefile.am | 2 + micropeak/MicroData.java | 100 ++++++++++++++++++++++ micropeak/MicroPeak.java | 15 +++- micropeak/MicroStats.java | 184 +++++++++++++++++++++++++++++++++++++++++ micropeak/MicroStatsTable.java | 138 +++++++++++++++++++++++++++++++ 6 files changed, 445 insertions(+), 12 deletions(-) create mode 100644 micropeak/MicroStats.java create mode 100644 micropeak/MicroStatsTable.java diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java index 717678ba..5d5f9aaa 100644 --- a/altosuilib/AltosUILib.java +++ b/altosuilib/AltosUILib.java @@ -24,17 +24,17 @@ import org.altusmetrum.AltosLib.*; public class AltosUILib extends AltosLib { - static final int tab_elt_pad = 5; + public static final int tab_elt_pad = 5; - static Font label_font; - static Font value_font; - static Font status_font; - static Font table_label_font; - static Font table_value_font; + public static Font label_font; + public static Font value_font; + public static Font status_font; + public static Font table_label_font; + public static Font table_value_font; - final static int font_size_small = 1; - final static int font_size_medium = 2; - final static int font_size_large = 3; + final public static int font_size_small = 1; + final public static int font_size_medium = 2; + final public static int font_size_large = 3; static void set_fonts(int size) { int brief_size; diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index fde981a6..e0de690c 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -13,6 +13,8 @@ micropeak_JAVA= \ MicroFrame.java \ MicroGraph.java \ MicroSerial.java \ + MicroStats.java \ + MicroStatsTable.java \ MicroFileChooser.java \ MicroUSB.java diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 783ae40f..ec9b83d8 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -22,6 +22,87 @@ import java.io.*; import java.util.*; import org.altusmetrum.AltosLib.*; +abstract class MicroIterator implements Iterator { + int i; + MicroData data; + + public boolean hasNext() { + return i < data.pressures.length; + } + + public MicroIterator (MicroData data) { + this.data = data; + i = 0; + } + + public void remove() { + } +} + +class MicroHeightIterator extends MicroIterator { + public Double next() { + return data.height(i++); + } + + public MicroHeightIterator(MicroData data) { + super(data); + } +} + +class MicroHeightIterable implements Iterable { + MicroData data; + + public Iterator iterator() { + return new MicroHeightIterator(data); + } + + public MicroHeightIterable(MicroData data) { + this.data = data; + } +} + +class MicroSpeedIterator extends MicroIterator { + public Double next() { + return data.speed(i++); + } + public MicroSpeedIterator(MicroData data) { + super(data); + } +} + +class MicroSpeedIterable implements Iterable { + MicroData data; + + public Iterator iterator() { + return new MicroSpeedIterator(data); + } + + public MicroSpeedIterable(MicroData data) { + this.data = data; + } +} + +class MicroAccelIterator extends MicroIterator { + public Double next() { + return data.acceleration(i++); + } + public MicroAccelIterator(MicroData data) { + super(data); + } +} + +class MicroAccelIterable implements Iterable { + MicroData data; + + public Iterator iterator() { + return new MicroAccelIterator(data); + } + + public MicroAccelIterable(MicroData data) { + this.data = data; + } +} + public class MicroData { public int ground_pressure; public int min_pressure; @@ -143,6 +224,18 @@ public class MicroData { return AltosConvert.pressure_to_altitude(pressures[i]); } + public Iterable heights() { + return new MicroHeightIterable(this); + } + + public Iterable speeds() { + return new MicroSpeedIterable(this); + } + + public Iterable accels() { + return new MicroAccelIterable(this); + } + int fact(int n) { if (n == 0) return 1; @@ -266,5 +359,12 @@ public class MicroData { throw new IOException(); } } + + public MicroData() { + ground_pressure = 101000; + min_pressure = 101000; + pressures = new int[1]; + pressures[0] = 101000; + } } diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 463238c8..c69f7167 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -30,13 +30,16 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene File filename; MicroGraph graph; + MicroStatsTable stats; MicroData data; - Container pane; + Container container; + JTabbedPane pane; private void RunFile(InputStream input) { try { data = new MicroData(input); graph.setData(data); + stats.setData(data); } catch (IOException ioe) { } try { @@ -90,7 +93,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene AltosUIPreferences.set_component(this); - pane = getContentPane(); + container = getContentPane(); + pane = new JTabbedPane(); setTitle("MicroPeak"); @@ -129,9 +133,14 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene }); graph = new MicroGraph(); - pane.add(graph.panel); + stats = new MicroStatsTable(); + pane.add(graph.panel, "Graph"); + pane.add(stats, "Statistics"); pane.doLayout(); pane.validate(); + container.add(pane); + container.doLayout(); + container.validate(); doLayout(); validate(); Insets i = getInsets(); diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java new file mode 100644 index 00000000..6ae8a2b2 --- /dev/null +++ b/micropeak/MicroStats.java @@ -0,0 +1,184 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroStats { + double coast_height; + double coast_time; + + double apogee_height; + double apogee_time; + + double landed_height; + double landed_time; + + double max_speed; + double max_accel; + + MicroData data; + + void find_landing() { + landed_height = 0; + + int t = 0; + for (double height : data.heights()) { + landed_height = height; + t++; + } + landed_time = data.time(t); + + t = 0; + boolean above = false; + for (double height : data.heights()) { + if (height > landed_height + 10) { + above = true; + } else { + if (above && height < landed_height + 2) { + above = false; + landed_time = data.time(t); + } + } + t++; + } + } + + void find_apogee() { + apogee_height = 0; + apogee_time = 0; + + int t = 0; + for (double height : data.heights()) { + if (height > apogee_height) { + apogee_height = height; + apogee_time = data.time(t); + } + t++; + } + } + + void find_coast() { + coast_height = 0; + coast_time = 0; + + int t = 0; + for (double accel : data.accels()) { + if (accel < -9.8) + break; + t++; + } + coast_time = data.time(t); + + int coast_t = t; + t = 0; + for (double height : data.heights()) { + if (t >= coast_t) { + coast_height = height; + break; + } + t++; + } + } + + void find_max_speed() { + max_speed = 0; + int t = 0; + for (double speed : data.speeds()) { + if (data.time(t) > apogee_time) + break; + if (speed > max_speed) + max_speed = speed; + t++; + } + } + + void find_max_accel() { + max_accel = 0; + + int t = 0; + for (double accel : data.accels()) { + if (data.time(t) > apogee_time) + break; + if (accel > max_accel) + max_accel = accel; + t++; + } + } + + double boost_duration() { + return coast_time; + } + + double boost_height() { + return coast_height; + } + + double boost_speed() { + return coast_height / coast_time; + } + + double boost_accel() { + return boost_speed() / boost_duration(); + } + + double coast_duration() { + return apogee_time - coast_time; + } + + double coast_height() { + return apogee_height - coast_height; + } + + double coast_speed() { + return coast_height() / coast_duration(); + } + + double coast_accel() { + return coast_speed() / coast_duration(); + } + + double descent_duration() { + return landed_time - apogee_time; + } + + double descent_height() { + return apogee_height - landed_height; + } + + double descent_speed() { + return descent_height() / descent_duration(); + } + + public MicroStats(MicroData data) { + + this.data = data; + + find_coast(); + find_apogee(); + find_landing(); + find_max_speed(); + find_max_accel(); + } + + public MicroStats() { + this(new MicroData()); + } +} diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java new file mode 100644 index 00000000..f373e25d --- /dev/null +++ b/micropeak/MicroStatsTable.java @@ -0,0 +1,138 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroStatsTable extends JComponent { + GridBagLayout layout; + + class MicroStat { + JLabel label; + JTextField[] texts; + + public void set_values(String ... values) { + for (int j = 0; j < values.length; j++) { + texts[j].setText(values[j]); + } + } + + public MicroStat(GridBagLayout layout, int y, String label_text, String ... values) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); + c.weighty = 1; + + label = new JLabel(label_text); + label.setFont(AltosUILib.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + texts = new JTextField[values.length]; + for (int j = 0; j < values.length; j++) { + JTextField value = new JTextField(values[j]); + value.setFont(AltosUILib.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + texts[j] = value; + c.gridx = j+1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + } + + MicroStat max_height, max_speed; + MicroStat max_accel, avg_accel; + MicroStat boost_duration; + MicroStat coast_duration; + MicroStat descent_speed; + MicroStat descent_duration; + MicroStat flight_time; + + public void setStats(MicroStats stats) { + max_height.set_values(String.format("%5.0f m", stats.apogee_height), + String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.apogee_height))); + max_speed.set_values(String.format("%5.0f m/s", stats.max_speed), + String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)), + String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); + max_accel.set_values(String.format("%5.0f m/s²", stats.max_accel), + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), + String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_accel))); + avg_accel.set_values(String.format("%5.0f m/s²", stats.boost_accel(), + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), + String.format("%5.0f G", AltosConvert.meters_to_g(stats.boost_accel())))); + boost_duration.set_values(String.format("%6.1f s", stats.boost_duration())); + coast_duration.set_values(String.format("%6.1f s", stats.coast_duration())); + descent_speed.set_values(String.format("%5.0f m/s", stats.descent_speed()), + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); + descent_duration.set_values(String.format("%6.1f s", stats.descent_duration())); + flight_time.set_values(String.format("%6.1f s", stats.landed_time)); + } + + public void setData(MicroData data) { + setStats(new MicroStats(data)); + } + + public MicroStatsTable(MicroStats stats) { + layout = new GridBagLayout(); + + setLayout(layout); + int y = 0; + max_height = new MicroStat(layout, y++, "Maximum height", + String.format("%5.0f m", stats.apogee_height), + String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.apogee_height))); + max_speed = new MicroStat(layout, y++, "Maximum speed", + String.format("%5.0f m/s", stats.max_speed), + String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)), + String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); + max_accel = new MicroStat(layout, y++, "Maximum boost acceleration", + String.format("%5.0f m/s²", stats.max_accel), + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), + String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_accel))); + avg_accel = new MicroStat(layout, y++, "Average boost acceleration", + String.format("%5.0f m/s²", stats.boost_accel(), + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), + String.format("%5.0f G", AltosConvert.meters_to_g(stats.boost_accel())))); + boost_duration = new MicroStat(layout, y++, "Boost duration", + String.format("%6.0f s", stats.boost_duration())); + coast_duration = new MicroStat(layout, y++, "Coast duration", + String.format("%6.1f s", stats.coast_duration())); + descent_speed = new MicroStat(layout, y++, "Descent rate", + String.format("%5.0f m/s", stats.descent_speed()), + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); + descent_duration = new MicroStat(layout, y++, "Descent duration", + String.format("%6.1f s", stats.descent_duration())); + flight_time = new MicroStat(layout, y++, "Flight Time", + String.format("%6.0f s", stats.landed_time)); + } + + public MicroStatsTable() { + this(new MicroStats()); + } + +} \ No newline at end of file -- cgit v1.2.3 From 434e946aa79b5a7e60799f996887bc6467889b92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 31 Dec 2012 14:22:37 -0800 Subject: Allow CC1120 to sit on other SPI busses Reading the incoming data bypasses the SPI API and touches the SPI data register directly; which port that is needs to be specified in the pins file Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 8 ++++---- src/megadongle-v0.1/ao_pins.h | 3 ++- src/megametrum-v0.1/ao_pins.h | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 63d2f955..d9b2e5bf 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -834,8 +834,8 @@ ao_radio_rx_isr(void) { uint8_t d; - d = stm_spi2.dr; - stm_spi2.dr = 0; + d = AO_CC1120_SPI.dr; + AO_CC1120_SPI.dr = 0; if (rx_ignore == 0) { if (rx_data_cur >= rx_data_count) ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); @@ -922,10 +922,10 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_wake = 0; ao_radio_mcu_wake = 0; - stm_spi2.cr2 = 0; + AO_CC1120_SPI.cr2 = 0; /* clear any RXNE */ - (void) stm_spi2.dr; + (void) AO_CC1120_SPI.dr; /* Have the radio signal when the preamble quality goes high */ ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED); diff --git a/src/megadongle-v0.1/ao_pins.h b/src/megadongle-v0.1/ao_pins.h index 5a5eaa30..c766a48c 100644 --- a/src/megadongle-v0.1/ao_pins.h +++ b/src/megadongle-v0.1/ao_pins.h @@ -135,9 +135,10 @@ #define AO_CC1120_SPI_CS_PORT (&stm_gpioa) #define AO_CC1120_SPI_CS_PIN 0 #define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1120_SPI stm_spi2 #define AO_CC1120_INT_PORT (&stm_gpioc) -#define AO_CC1120_INT_PIN 14 +#define AO_CC1120_INT_PIN 13 #define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioc) #define AO_CC1120_MCU_WAKEUP_PIN (0) diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index b1a70ea2..64da41a9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -281,6 +281,7 @@ struct ao_adc { #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 #define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1120_SPI stm_spi2 #define AO_CC1120_INT_PORT (&stm_gpioc) #define AO_CC1120_INT_PIN 14 -- cgit v1.2.3 From d83587c3c66b730cc54ca153714eee520ee40b2c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 15:30:11 -0800 Subject: micropeak is code complete now. Added save and download functionality. Removed 'new' from file menu. Signed-off-by: Keith Packard --- altoslib/AltosLib.java | 1 + altosuilib/AltosDevice.java | 30 +++++++ altosuilib/AltosDeviceDialog.java | 163 ++++++++++++++++++++++++++++++++++++++ altosuilib/AltosUSBDevice.java | 112 ++++++++++++++++++++++++++ altosuilib/Makefile.am | 3 + libaltos/libaltos.c | 4 + micropeak/Makefile.am | 3 + micropeak/MicroData.java | 15 +++- micropeak/MicroDeviceDialog.java | 50 ++++++++++++ micropeak/MicroDownload.java | 139 ++++++++++++++++++++++++++++++++ micropeak/MicroGraph.java | 5 ++ micropeak/MicroPeak.java | 81 +++++++++++++++---- micropeak/MicroSave.java | 102 ++++++++++++++++++++++++ micropeak/MicroSerial.java | 12 ++- micropeak/MicroUSB.java | 19 +++-- 15 files changed, 708 insertions(+), 31 deletions(-) create mode 100644 altosuilib/AltosDevice.java create mode 100644 altosuilib/AltosDeviceDialog.java create mode 100644 altosuilib/AltosUSBDevice.java create mode 100644 micropeak/MicroDeviceDialog.java create mode 100644 micropeak/MicroDownload.java create mode 100644 micropeak/MicroSave.java diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 07516aeb..67138450 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -97,6 +97,7 @@ public class AltosLib { public final static int product_any = 0x10000; public final static int product_basestation = 0x10000 + 1; public final static int product_altimeter = 0x10000 + 2; + public final static int product_micropeak_serial = 0x10000 + 3; /* Bluetooth "identifier" (bluetooth sucks) */ public final static String bt_product_telebt = "TeleBT"; diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java new file mode 100644 index 00000000..69b025ba --- /dev/null +++ b/altosuilib/AltosDevice.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import libaltosJNI.*; + +public interface AltosDevice { + public abstract String toString(); + public abstract String toShortString(); + 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/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java new file mode 100644 index 00000000..82620b8b --- /dev/null +++ b/altosuilib/AltosDeviceDialog.java @@ -0,0 +1,163 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionListener { + + private AltosDevice value; + private JList list; + private JButton cancel_button; + private JButton select_button; + private JButton manage_bluetooth_button; + private Frame frame; + private int product; + + public AltosDevice getValue() { + return value; + } + + public abstract AltosDevice[] devices(); + + private void update_devices() { + AltosDevice[] devices = devices(); + list.setListData(devices); + select_button.setEnabled(devices.length > 0); + } + + public AltosDeviceDialog (Frame in_frame, Component location, int in_product) { + super(in_frame, "Device Selection", true); + + product = in_product; + frame = in_frame; + value = null; + + AltosDevice[] devices = devices(); + + cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_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"); + select_button.addActionListener(this); + if (devices.length == 0) + select_button.setEnabled(false); + getRootPane().setDefaultButton(select_button); + + list = new JList(devices) { + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + }; + + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + select_button.doClick(); //emulate button click + } + } + }); + JScrollPane listScroller = new JScrollPane(list); + listScroller.setPreferredSize(new Dimension(400, 80)); + listScroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(list); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(listScroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + //Lay out the buttons from left to right. + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); + buttonPane.add(Box.createHorizontalGlue()); + buttonPane.add(cancel_button); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); +// buttonPane.add(manage_bluetooth_button); +// buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(select_button); + + //Put everything together, using the content pane's BorderLayout. + Container contentPane = getContentPane(); + contentPane.add(listPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.PAGE_END); + + //Initialize values. + if (devices != null && devices.length != 0) + list.setSelectedValue(devices[0], true); + pack(); + setLocationRelativeTo(location); + } + + //Handle clicks on the Set and Cancel buttons. + public void actionPerformed(ActionEvent e) { + if ("select".equals(e.getActionCommand())) + value = (AltosDevice)(list.getSelectedValue()); +// if ("manage".equals(e.getActionCommand())) { +// AltosBTManage.show(frame, AltosBTKnown.bt_known()); +// update_devices(); +// return; +// } + setVisible(false); + } + +} diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java new file mode 100644 index 00000000..2f4e0dc6 --- /dev/null +++ b/altosuilib/AltosUSBDevice.java @@ -0,0 +1,112 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.util.*; +import libaltosJNI.*; + +public class AltosUSBDevice extends altos_device implements AltosDevice { + + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%-20.20s %4d %s", + name, getSerial(), getPath()); + } + + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + name, getSerial(), getPath()); + + } + + 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); + } + + private boolean isAltusMetrum() { + if (getVendor() != AltosUILib.vendor_altusmetrum) + return false; + if (getProduct() < AltosUILib.product_altusmetrum_min) + return false; + if (getProduct() > AltosUILib.product_altusmetrum_max) + return false; + return true; + } + + public boolean matchProduct(int want_product) { + + if (!isAltusMetrum()) + return false; + + if (want_product == AltosUILib.product_any) + return true; + + if (want_product == AltosUILib.product_basestation) + return matchProduct(AltosUILib.product_teledongle) || + matchProduct(AltosUILib.product_teleterra) || + matchProduct(AltosUILib.product_telebt) || + matchProduct(AltosUILib.product_megadongle); + + if (want_product == AltosUILib.product_altimeter) + return matchProduct(AltosUILib.product_telemetrum) || + matchProduct(AltosUILib.product_megametrum); + + int have_product = getProduct(); + + if (have_product == AltosUILib.product_altusmetrum) /* old devices match any request */ + return true; + + if (want_product == have_product) + return true; + + return false; + } + + static java.util.List list(int product) { + if (!AltosUILib.load_library()) + return null; + + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + for (;;) { + AltosUSBDevice device = new AltosUSBDevice(); + if (libaltos.altos_list_next(list, device) == 0) + break; + if (device.matchProduct(product)) + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + return device_list; + } +} \ No newline at end of file diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 26aee7c4..e2ff8cb5 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -11,6 +11,9 @@ AltosUILibdir = $(datadir)/java AltosUILib_JAVA = \ AltosConfigureUI.java \ + AltosDevice.java \ + AltosDeviceDialog.java \ + AltosUSBDevice.java \ AltosFontListener.java \ AltosUIDialog.java \ AltosUIFrame.java \ diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c index d7b266cf..6e884c80 100644 --- a/libaltos/libaltos.c +++ b/libaltos/libaltos.c @@ -116,6 +116,7 @@ altos_open(struct altos_device *device) return NULL; } + printf ("open\n"); // altos_set_last_error(12, "yeah yeah, failed again"); // free(file); // return NULL; @@ -148,6 +149,8 @@ altos_open(struct altos_device *device) return NULL; } cfmakeraw(&term); + cfsetospeed(&term, B9600); + cfsetispeed(&term, B9600); #ifdef USE_POLL term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; @@ -609,6 +612,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) { struct altos_usbdev *dev; if (list->current >= list->ndev) { + printf ("end\n"); return 0; } dev = list->dev[list->current]; diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index e0de690c..a54b78a5 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -10,12 +10,15 @@ micropeakdir=$(datadir)/java micropeak_JAVA= \ MicroPeak.java \ MicroData.java \ + MicroDownload.java \ MicroFrame.java \ MicroGraph.java \ + MicroSave.java \ MicroSerial.java \ MicroStats.java \ MicroStatsTable.java \ MicroFileChooser.java \ + MicroDeviceDialog.java \ MicroUSB.java JFREECHART_CLASS= \ diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index ec9b83d8..8ccd5fd8 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -110,6 +110,7 @@ public class MicroData { private double time_step; private double ground_altitude; private ArrayList bytes; + String name; class FileEndedException extends Exception { @@ -310,12 +311,18 @@ public class MicroData { public void save (OutputStream f) throws IOException { for (int c : bytes) f.write(c); + f.write('\n'); } - public MicroData (InputStream f) throws IOException { + public void set_name(String name) { + this.name = name; + } + + public MicroData (InputStream f, String name) throws IOException, InterruptedException { + this.name = name; bytes = new ArrayList(); if (!find_header(f)) - throw new IOException(); + throw new IOException("No MicroPeak data header found"); try { file_crc = 0xffff; ground_pressure = get_32(f); @@ -354,9 +361,9 @@ public class MicroData { time_step = 0.192; } catch (FileEndedException fe) { - throw new IOException(); + throw new IOException("File Ended Unexpectedly"); } catch (NonHexcharException ne) { - throw new IOException(); + throw new IOException("Non hexadecimal character found"); } } diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java new file mode 100644 index 00000000..7b8a630c --- /dev/null +++ b/micropeak/MicroDeviceDialog.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import org.altusmetrum.altosuilib.*; + +public class MicroDeviceDialog extends AltosDeviceDialog { + + public AltosDevice[] devices() { + java.util.List list = MicroUSB.list(); + int num_devices = list.size(); + AltosDevice[] devices = new AltosDevice[num_devices]; + + for (int i = 0; i < num_devices; i++) + devices[i] = list.get(i); + return devices; + } + + public MicroDeviceDialog (Frame in_frame, Component location) { + super(in_frame, location, 0); + } + + public static AltosDevice show (Component frameComp) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + MicroDeviceDialog dialog; + + dialog = new MicroDeviceDialog (frame, frameComp); + dialog.setVisible(true); + return dialog.getValue(); + } +} diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java new file mode 100644 index 00000000..2e328b4a --- /dev/null +++ b/micropeak/MicroDownload.java @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener { + MicroPeak owner; + Container pane; + AltosDevice device; + JButton cancel; + MicroData data; + MicroSerial serial; + + private void done_internal() { + setVisible(false); + if (data != null) { + owner = owner.SetData(data); + MicroSave save = new MicroSave(owner, data); + if (save.runDialog()) + owner.SetName(data.name); + } + dispose(); + } + + public void done() { + Runnable r = new Runnable() { + public void run() { + try { + done_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + public void run() { + try { + data = new MicroData(serial, device.toShortString()); + serial.close(); + } catch (FileNotFoundException fe) { + } catch (IOException ioe) { + } catch (InterruptedException ie) { + } + done(); + } + + Thread serial_thread; + + public void start() { + try { + serial = new MicroSerial(device); + } catch (FileNotFoundException fe) { + return; + } + serial_thread = new Thread(this); + serial_thread.start(); + } + + public void actionPerformed(ActionEvent ae) { + System.out.printf ("command %s\n", ae.getActionCommand()); + if (serial_thread != null) { + System.out.printf ("Interrupting serial_thread\n"); + serial.close(); + serial_thread.interrupt(); + } + } + + public MicroDownload(MicroPeak owner, AltosDevice device) { + super (owner, "Download MicroPeak Data", false); + + GridBagConstraints c; + Insets il = new Insets(4,4,4,4); + Insets ir = new Insets(4,4,4,4); + + this.owner = owner; + this.device = device; + + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + JLabel device_label = new JLabel("Device:"); + pane.add(device_label, c); + + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = 0; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + JLabel device_value = new JLabel(device.toString()); + pane.add(device_value, c); + + cancel = new JButton("Cancel"); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 1; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ic = new Insets(4,4,4,4); + c.insets = ic; + pane.add(cancel, c); + + cancel.addActionListener(this); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + this.start(); + } +} diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index 38f54fe0..b9b084f8 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -111,8 +111,13 @@ public class MicroGraph implements AltosUnitsListener { } } + public void setName (String name) { + chart.setTitle(name); + } + public void setData (MicroData data) { this.data = data; + chart.setTitle(data.name); resetData(); } diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index c69f7167..5e375057 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -34,13 +34,36 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene MicroData data; Container container; JTabbedPane pane; + static int number_of_windows; - private void RunFile(InputStream input) { + MicroPeak SetData(MicroData data) { + MicroPeak mp = this; + if (this.data != null) { + mp = new MicroPeak(); + return mp.SetData(data); + } + this.data = data; + graph.setData(data); + stats.setData(data); + setTitle(data.name); + return this; + } + + void SetName(String name) { + graph.setName(name); + setTitle(name); + } + + private void RunFile(InputStream input, String name) { try { - data = new MicroData(input); - graph.setData(data); - stats.setData(data); + MicroData data = new MicroData(input, name); + SetData(data); } catch (IOException ioe) { + JOptionPane.showMessageDialog(this, + ioe.getMessage(), + "File Read Error", + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { } try { input.close(); @@ -50,8 +73,12 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene private void OpenFile(File filename) { try { - RunFile (new FileInputStream(filename)); + RunFile (new FileInputStream(filename), filename.getName()); } catch (FileNotFoundException fne) { + JOptionPane.showMessageDialog(this, + fne.getMessage(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); } } @@ -60,30 +87,44 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene InputStream input = chooser.runDialog(); if (input != null) - RunFile(input); + RunFile(input, chooser.filename); } private void Preferences() { new AltosConfigureUI(this); } - + private void DownloadData() { - java.util.List devices = MicroUSB.list(); - for (MicroUSB device : devices) - System.out.printf("device %s\n", device.toString()); + AltosDevice device = MicroDeviceDialog.show(this); + + if (device != null) + new MicroDownload(this, device); } + private void Save() { + if (data == null) { + JOptionPane.showMessageDialog(this, + "No data available", + "No data", + JOptionPane.INFORMATION_MESSAGE); + return; + } + MicroSave save = new MicroSave (this, data); + if (save.runDialog()) + SetName(data.name); + } + public void actionPerformed(ActionEvent ev) { if ("Exit".equals(ev.getActionCommand())) System.exit(0); else if ("Open".equals(ev.getActionCommand())) SelectFile(); - else if ("New".equals(ev.getActionCommand())) - new MicroPeak(); else if ("Download".equals(ev.getActionCommand())) DownloadData(); else if ("Preferences".equals(ev.getActionCommand())) Preferences(); + else if ("Save a Copy".equals(ev.getActionCommand())) + Save(); } public void itemStateChanged(ItemEvent e) { @@ -91,6 +132,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene public MicroPeak() { + ++number_of_windows; + AltosUIPreferences.set_component(this); container = getContentPane(); @@ -104,10 +147,6 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene JMenu fileMenu = new JMenu("File"); menuBar.add(fileMenu); - JMenuItem newAction = new JMenuItem("New"); - fileMenu.add(newAction); - newAction.addActionListener(this); - JMenuItem openAction = new JMenuItem("Open"); fileMenu.add(openAction); openAction.addActionListener(this); @@ -116,6 +155,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene fileMenu.add(downloadAction); downloadAction.addActionListener(this); + JMenuItem saveAction = new JMenuItem("Save a Copy"); + fileMenu.add(saveAction); + saveAction.addActionListener(this); + JMenuItem preferencesAction = new JMenuItem("Preferences"); fileMenu.add(preferencesAction); preferencesAction.addActionListener(this); @@ -128,7 +171,11 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - System.exit(0); + setVisible(false); + dispose(); + --number_of_windows; + if (number_of_windows == 0) + System.exit(0); } }); diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java new file mode 100644 index 00000000..cb4b4221 --- /dev/null +++ b/micropeak/MicroSave.java @@ -0,0 +1,102 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroSave extends JFileChooser { + + JFrame frame; + MicroData data; + + public boolean runDialog() { + int ret; + + for (;;) { + ret = showSaveDialog(frame); + if (ret != APPROVE_OPTION) + return false; + File file; + String filename; + file = getSelectedFile(); + if (file == null) + continue; + if (!file.getName().contains(".")) { + String fullname = file.getPath(); + file = new File(fullname.concat(".mpd")); + } + filename = file.getName(); + if (file.exists()) { + if (file.isDirectory()) { + JOptionPane.showMessageDialog(frame, + String.format("\"%s\" is a directory", + filename), + "Directory", + JOptionPane.ERROR_MESSAGE); + continue; + } + int r = JOptionPane.showConfirmDialog(frame, + String.format("\"%s\" already exists. Overwrite?", + filename), + "Overwrite file?", + JOptionPane.YES_NO_OPTION); + if (r != JOptionPane.YES_OPTION) + continue; + + if (!file.canWrite()) { + JOptionPane.showMessageDialog(frame, + String.format("\"%s\" is not writable", + filename), + "File not writable", + JOptionPane.ERROR_MESSAGE); + continue; + } + } + try { + FileOutputStream fos = new FileOutputStream(file); + data.save(fos); + fos.close(); + data.set_name(filename); + return true; + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + fe.getMessage(), + "Cannot create file", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ioe) { + } + } + } + + public MicroSave(JFrame frame, MicroData data) { + this.frame = frame; + this.data = data; + setDialogTitle("Save MicroPeak Data File"); + setFileFilter(new FileNameExtensionFilter("MicroPeak data file", + "mpd")); + setCurrentDirectory(AltosUIPreferences.logdir()); + } +} diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index a1a77a1d..15ef8582 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -27,6 +27,10 @@ public class MicroSerial extends InputStream { public int read() { int c = libaltos.altos_getchar(file, 0); + if (Thread.interrupted()) + return -1; + if (c == -1) + return -1; if (AltosUIPreferences.serial_debug) System.out.printf("%c", c); return c; @@ -39,12 +43,12 @@ public class MicroSerial extends InputStream { } } - public MicroSerial(MicroUSB usb) throws FileNotFoundException { - file = usb.open(); + public MicroSerial(AltosDevice device) throws FileNotFoundException { + file = device.open(); if (file == null) { - final String message = usb.getErrorString(); + final String message = device.getErrorString(); throw new FileNotFoundException(String.format("%s (%s)", - usb.toShortString(), + device.toShortString(), message)); } } diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index d48610fe..244f7bc0 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -16,10 +16,12 @@ */ package org.altusmetrum.micropeak; + import java.util.*; import libaltosJNI.*; +import org.altusmetrum.altosuilib.*; -public class MicroUSB extends altos_device { +public class MicroUSB extends altos_device implements AltosDevice { static boolean initialized = false; static boolean loaded_library = false; @@ -48,16 +50,16 @@ public class MicroUSB extends altos_device { String name = getName(); if (name == null) name = "Altus Metrum"; - return String.format("%-20.20s %4d %s", - name, getSerial(), getPath()); + return String.format("%-20.20s %s", + name, getPath()); } public String toShortString() { String name = getName(); if (name == null) name = "Altus Metrum"; - return String.format("%s %d %s", - name, getSerial(), getPath()); + return String.format("%s %s", + name, getPath()); } @@ -75,11 +77,15 @@ public class MicroUSB extends altos_device { private boolean isMicro() { if (getVendor() != 0x0403) return false; - if (getProduct() != 0x6001) + if (getProduct() != 0x6015) return false; return true; } + public boolean matchProduct(int product) { + return isMicro(); + } + static java.util.List list() { if (!load_library()) return null; @@ -92,6 +98,7 @@ public class MicroUSB extends altos_device { MicroUSB device = new MicroUSB(); if (libaltos.altos_list_next(list, device) == 0) break; + System.out.printf("Device %s\n", device.toString()); if (device.isMicro()) device_list.add(device); } -- cgit v1.2.3 From 982b272920fcb444fd399941cabe613d8ac7104b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 16:57:31 -0800 Subject: micropeak: Fix chart colors Need to apply custom colors after setting the theme Signed-off-by: Keith Packard --- micropeak/MicroGraph.java | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index b9b084f8..c5580634 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -72,9 +72,12 @@ public class MicroGraph implements AltosUnitsListener { MicroSeries speedSeries; MicroSeries accelSeries; - static final private Color red = new Color(194,31,31); - static final private Color green = new Color(31,194,31); - static final private Color blue = new Color(31,31,194); + static final private Color height_color = new Color(194,31,31); + static final private Color speed_color = new Color(31,194,31); + static final private Color accel_color = new Color(31,31,194); + static final private Color gridline_color = new Color(0, 0, 0); + static final private Color border_color = new Color(255, 255, 255); + static final private Color background_color = new Color(255, 255, 255); MicroData data; @@ -142,14 +145,22 @@ public class MicroGraph implements AltosUnitsListener { plot.setDomainPannable(true); plot.setRangePannable(true); - heightSeries = addSeries(0, "Height", AltosConvert.height.show_units(), red); - speedSeries = addSeries(1, "Speed", AltosConvert.speed.show_units(), green); - accelSeries = addSeries(2, "Acceleration", AltosConvert.accel.show_units(), blue); - chart = new JFreeChart("Flight", JFreeChart.DEFAULT_TITLE_FONT, plot, true); ChartUtilities.applyCurrentTheme(chart); + + heightSeries = addSeries(0, "Height", AltosConvert.height.show_units(), height_color); + speedSeries = addSeries(1, "Speed", AltosConvert.speed.show_units(), speed_color); + accelSeries = addSeries(2, "Acceleration", AltosConvert.accel.show_units(), accel_color); + + plot.setDomainGridlinePaint(gridline_color); + plot.setRangeGridlinePaint(gridline_color); + plot.setBackgroundPaint(background_color); + plot.setBackgroundAlpha((float) 1); + + chart.setBackgroundPaint(background_color); + chart.setBorderPaint(border_color); panel = new ChartPanel(chart); panel.setMouseWheelEnabled(true); panel.setPreferredSize(new java.awt.Dimension(800, 500)); -- cgit v1.2.3 From d94ceed48be439f368d597bf06ed1e8adc4ef46b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 17:10:55 -0800 Subject: micropeak: Add 'Close' menu item. Fix start location Let the window system pick a spot to place the application windows. This avoids having them all sit on top of one another. Signed-off-by: Keith Packard --- micropeak/MicroPeak.java | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 5e375057..17eae228 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -114,9 +114,19 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene SetName(data.name); } + private void Close() { + setVisible(false); + dispose(); + --number_of_windows; + if (number_of_windows == 0) + System.exit(0); + } + public void actionPerformed(ActionEvent ev) { if ("Exit".equals(ev.getActionCommand())) System.exit(0); + else if ("Close".equals(ev.getActionCommand())) + Close(); else if ("Open".equals(ev.getActionCommand())) SelectFile(); else if ("Download".equals(ev.getActionCommand())) @@ -163,6 +173,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene fileMenu.add(preferencesAction); preferencesAction.addActionListener(this); + JMenuItem closeAction = new JMenuItem("Close"); + fileMenu.add(closeAction); + closeAction.addActionListener(this); + JMenuItem exitAction = new JMenuItem("Exit"); fileMenu.add(exitAction); exitAction.addActionListener(this); @@ -171,11 +185,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - setVisible(false); - dispose(); - --number_of_windows; - if (number_of_windows == 0) - System.exit(0); + Close(); } }); @@ -194,8 +204,9 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene Dimension ps = pane.getPreferredSize(); ps.width += i.left + i.right; ps.height += i.top + i.bottom; - setPreferredSize(ps); +// setPreferredSize(ps); setSize(ps); + setLocationByPlatform(true); setVisible(true); } -- cgit v1.2.3 From 3ac109132d1878abbd277ae21215716326404781 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 18:20:23 -0800 Subject: Build installable versions of MicroPeak GUI Makes windows/mac/linux versions. Windows version appears to work on Wine at least. Signed-off-by: Keith Packard --- configure.ac | 1 + icon/altus-metrum.ico | Bin 15086 -> 285478 bytes icon/micro-peak.ico | Bin 0 -> 285478 bytes micropeak/Info.plist.in | 45 ++++++++ micropeak/Makefile.am | 79 ++++++++++++- .../Contents/MacOS/JavaApplicationStub | Bin 0 -> 61296 bytes micropeak/MicroPeak.app/Contents/PkgInfo | 1 + .../Contents/Resources/AltosUIIcon.icns | Bin 0 -> 129010 bytes micropeak/micropeak-fat | 4 + micropeak/micropeak-windows.nsi | 123 +++++++++++++++++++++ 10 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 icon/micro-peak.ico create mode 100644 micropeak/Info.plist.in create mode 100755 micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub create mode 100644 micropeak/MicroPeak.app/Contents/PkgInfo create mode 100644 micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns create mode 100755 micropeak/micropeak-fat create mode 100644 micropeak/micropeak-windows.nsi diff --git a/configure.ac b/configure.ac index 6ad2591c..312f9678 100644 --- a/configure.ac +++ b/configure.ac @@ -153,6 +153,7 @@ altosui/AltosVersion.java altosui/Info.plist libaltos/Makefile micropeak/Makefile +micropeak/Info.plist altosdroid/Makefile altosdroid/local.properties ao-tools/Makefile diff --git a/icon/altus-metrum.ico b/icon/altus-metrum.ico index e32b4f1e..bedf04ef 100644 Binary files a/icon/altus-metrum.ico and b/icon/altus-metrum.ico differ diff --git a/icon/micro-peak.ico b/icon/micro-peak.ico new file mode 100644 index 00000000..b672aa04 Binary files /dev/null and b/icon/micro-peak.ico differ diff --git a/micropeak/Info.plist.in b/micropeak/Info.plist.in new file mode 100644 index 00000000..d3c17a49 --- /dev/null +++ b/micropeak/Info.plist.in @@ -0,0 +1,45 @@ + + + + + CFBundleName + MicroPeak + CFBundleVersion + @VERSION@ + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + JavaApplicationStub + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleIdentifier + org.altusmetrum.altosui + CFBundleSignature + Altu + CFBundleGetInfoString + MicroPeak UI version @VERSION@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + MicroPeak.icns + Java + + MainClass + org.altusmetrum.micropeak.MicroPeak + JVMVersion + 1.5+ + ClassPath + + $JAVAROOT/micropeak.jar + + VMOptions + + -Xms512M + -Xmx512M + -Dosgi.clean=true + + + + diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index a54b78a5..2dd9c69c 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -34,6 +34,7 @@ FATJAR=micropeak-fat.jar LIBALTOS= \ libaltos.so \ libaltos.dylib \ + altos64.dll \ altos.dll ALTOSLIB_CLASS=\ @@ -61,15 +62,58 @@ ICONJAR= -C $(ICONDIR) micropeak-16.png \ -C $(ICONDIR) micropeak-128.png \ -C $(ICONDIR) micropeak-256.png +WINDOWS_ICON=$(ICONDIR)/micro-peak.ico + all-local: micropeak-test $(JAR) clean-local: -rm -rf classes $(JAR) $(FATJAR) \ + $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) \ $(ALTOSLIB_CLASS) \ $(ALTOSUILIB_CLASS) \ $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt \ micropeak micropeak-test macosx linux windows +LINUX_DIST=MicroPeak-Linux-$(VERSION).tar.bz2 +MACOSX_DIST=MicroPeak-Mac-$(VERSION).zip +WINDOWS_DIST=MicroPeak-Windows-$(VERSION_DASH).exe + +FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) + +LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) +LINUX_EXTRA=micropeak-fat + +MACOSX_INFO_PLIST=Info.plist +MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) + +WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) + +if FATINSTALL + +FATTARGET=$(FATDIR)/$(VERSION) + +LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST) +MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST) +WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST) + +fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET) + +$(LINUX_DIST_TARGET): $(LINUX_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +$(MACOSX_DIST_TARGET): $(MACOSX_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +else +fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) +endif + micropeak: Makefile echo "#!/bin/sh" > $@ echo 'exec java -cp "$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="$(altoslibdir)" -jar "$(micropeakdir)/micropeak.jar" "$$@"' >> $@ @@ -80,6 +124,12 @@ micropeak-test: Makefile echo 'exec java -cp "./*:../libaltos/*:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar micropeak.jar "$$@"' >> $@ chmod +x $@ +install-micropeakJAVA: micropeak.jar + @$(NORMAL_INSTALL) + test -z "$(micropeakdir)" || $(MKDIR_P) "$(DESTDIR)$(micropeakdir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(micropeakdir)/micropeak.jar'"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(micropeakdir)" + $(JAR): classmicropeak.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) jar cfm $@ Manifest.txt \ $(ICONJAR) \ @@ -92,7 +142,6 @@ $(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_ -C classes org \ -C ../libaltos libaltosJNI - libaltos.so: build-libaltos -rm -f "$@" $(LN_S) ../libaltos/.libs/"$@" . @@ -139,6 +188,34 @@ $(JCOMMON_CLASS): -rm -f "$@" $(LN_S) "$(JCOMMON)"/"$@" . +$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA) + -rm -f $@ + -rm -rf linux + mkdir -p linux/MicroPeak + cp -p $(LINUX_FILES) linux/MicroPeak + cp -p micropeak-fat linux/MicroPeak/micropeak + chmod +x linux/MicroPeak/micropeak + tar cjf $@ -C linux MicroPeak + +$(MACOSX_DIST): $(MACOSX_FILES) + -rm -f $@ + -rm -rf macosx + mkdir macosx + cp -a MicroPeak.app macosx/ + cp -p Info.plist macosx/MicroPeak.app/Contents + mkdir -p macosx/MicroPeak macosx/MicroPeak.app/Contents/Resources/Java + cp -p $(FATJAR) macosx/MicroPeak.app/Contents/Resources/Java/micropeak.jar + cp -p libaltos.dylib macosx/MicroPeak.app/Contents/Resources/Java + cp -p $(ALTOSLIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java + cp -p $(ALTOSUILIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java + cp -p $(JFREECHART_CLASS) macosx/MicroPeak.app/Contents/Resources/Java + cp -p $(JCOMMON_CLASS) macosx/MicroPeak.app/Contents/Resources/Java + cd macosx && zip -r ../$@ MicroPeak.app MicroPeak + +$(WINDOWS_DIST): $(WINDOWS_FILES) micropeak-windows.nsi + -rm -f $@ + makensis -Omicropeak-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" micropeak-windows.nsi + Manifest.txt: Makefile echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ echo "Class-Path: AltosLib.jar AltosUILib.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ diff --git a/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub b/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub new file mode 100755 index 00000000..c661d3e1 Binary files /dev/null and b/micropeak/MicroPeak.app/Contents/MacOS/JavaApplicationStub differ diff --git a/micropeak/MicroPeak.app/Contents/PkgInfo b/micropeak/MicroPeak.app/Contents/PkgInfo new file mode 100644 index 00000000..8a43480f --- /dev/null +++ b/micropeak/MicroPeak.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPLAM.O diff --git a/micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns b/micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns new file mode 100644 index 00000000..fe49f362 Binary files /dev/null and b/micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns differ diff --git a/micropeak/micropeak-fat b/micropeak/micropeak-fat new file mode 100755 index 00000000..ace7548d --- /dev/null +++ b/micropeak/micropeak-fat @@ -0,0 +1,4 @@ +#!/bin/sh +me=`which "$0"` +dir=`dirname "$me"` +exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/micropeak-fat.jar "$@" diff --git a/micropeak/micropeak-windows.nsi b/micropeak/micropeak-windows.nsi new file mode 100644 index 00000000..425048bd --- /dev/null +++ b/micropeak/micropeak-windows.nsi @@ -0,0 +1,123 @@ +!addplugindir Instdrv/NSIS/Plugins +; Definitions for Java 1.6 Detection +!define JRE_VERSION "1.6" +!define JRE_ALTERNATE "1.7" +!define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586-p.exe" +!define PRODUCT_NAME "Altus Metrum Windows Software" + +Name "Altus Metrum MicroPeak Installer" + +; Default install directory +InstallDir "$PROGRAMFILES\AltusMetrum" + +; Tell the installer where to re-install a new version +InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir" + +LicenseText "GNU General Public License Version 2" +LicenseData "../COPYING" + +; Need admin privs for Vista or Win7 +RequestExecutionLevel admin + +ShowInstDetails Show + +ComponentText "Altus Metrum MicroPeak Software Installer" + +Function GetJRE + MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION} 32-bit, it will now \ + be downloaded and installed" + + StrCpy $2 "$TEMP\Java Runtime Environment.exe" + nsisdl::download /TIMEOUT=30000 ${JRE_URL} $2 + Pop $R0 ;Get the return value + StrCmp $R0 "success" +3 + MessageBox MB_OK "Download failed: $R0" + Quit + ExecWait $2 + Delete $2 +FunctionEnd + + +Function DetectJRE + ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \ + "CurrentVersion" + StrCmp $2 ${JRE_VERSION} done + + StrCmp $2 ${JRE_ALTERNATE} done + + Call GetJRE + + done: +FunctionEnd + +; Pages to present + +Page license +Page components +Page directory +Page instfiles + +UninstPage uninstConfirm +UninstPage instfiles + +; And the stuff to install + +Section "MicroPeak Application" + Call DetectJRE + + SetOutPath $INSTDIR + + File "micropeak-fat.jar" + File "AltosLib.jar" + File "AltosUILib.jar" + File "jfreechart.jar" + File "jcommon.jar" + + File "*.dll" + + File "../icon/*.ico" + + CreateShortCut "$SMPROGRAMS\MicroPeak.lnk" "$SYSDIR\javaw.exe" "-jar micropeak-fat.jar" "$INSTDIR\micro-peak.ico" +SectionEnd + +Section "MicroPeak Desktop Shortcut" + CreateShortCut "$DESKTOP\MicroPeak.lnk" "$INSTDIR\micropeak-fat.jar" "" "$INSTDIR\micro-peak.ico" +SectionEnd + +Section "Documentation" + + SetOutPath $INSTDIR + + File "../doc/micropeak.pdf" +SectionEnd + +Section "Uninstaller" + + ; Deal with the uninstaller + + SetOutPath $INSTDIR + + ; Write the install path to the registry + WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR" + + ; Write the uninstall keys for windows + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1" + + WriteUninstaller "uninstall.exe" +SectionEnd + +Section "Uninstall" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" + DeleteRegKey HKLM "Software\AltusMetrum" + + Delete "$INSTDIR\*.*" + RMDir "$INSTDIR" + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\MicroPeak.lnk" + Delete "$DESKTOP\MicroPeak.lnk" + +SectionEnd -- cgit v1.2.3 From 4dae5b876b089c17c87c72df2ad2fa5ec4f1657c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 23:03:29 -0800 Subject: Build micropeak by default Signed-off-by: Keith Packard --- Makefile.am | 2 +- micropeak/MicroDownload.java | 2 -- micropeak/MicroUSB.java | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index e8945d90..7328c04e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src doc altoslib libaltos altosuilib altosui ao-tools ao-utils altosdroid +SUBDIRS=src doc altoslib libaltos altosuilib altosui micropeak ao-tools ao-utils altosdroid EXTRA_DIST = ChangeLog diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index 2e328b4a..e04d6790 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -81,9 +81,7 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList } public void actionPerformed(ActionEvent ae) { - System.out.printf ("command %s\n", ae.getActionCommand()); if (serial_thread != null) { - System.out.printf ("Interrupting serial_thread\n"); serial.close(); serial_thread.interrupt(); } diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index 244f7bc0..908ac51b 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -98,7 +98,6 @@ public class MicroUSB extends altos_device implements AltosDevice { MicroUSB device = new MicroUSB(); if (libaltos.altos_list_next(list, device) == 0) break; - System.out.printf("Device %s\n", device.toString()); if (device.isMicro()) device_list.add(device); } -- cgit v1.2.3 From 103eaa674be7582437aa850f0fd82788e10f244b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 23:10:04 -0800 Subject: micropeak: Check CRC on downloaded Signed-off-by: Keith Packard --- micropeak/MicroDownload.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index e04d6790..28a7550d 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -37,10 +37,17 @@ public class MicroDownload extends AltosUIDialog implements Runnable, ActionList private void done_internal() { setVisible(false); if (data != null) { - owner = owner.SetData(data); - MicroSave save = new MicroSave(owner, data); - if (save.runDialog()) - owner.SetName(data.name); + if (data.crc_valid) { + owner = owner.SetData(data); + MicroSave save = new MicroSave(owner, data); + if (save.runDialog()) + owner.SetName(data.name); + } else { + JOptionPane.showMessageDialog(owner, + "Flight data corrupted", + "Download Failed", + JOptionPane.ERROR_MESSAGE); + } } dispose(); } -- cgit v1.2.3 From 9efc57e4052e3c11218973f7666ad18ea5cf2a5a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 Jan 2013 23:15:14 -0800 Subject: Rename AltosConfigureUI to AltosUIConfigure Leave AltosConfigureUI for AltosUI Signed-off-by: Keith Packard --- altosuilib/AltosConfigureUI.java | 393 --------------------------------------- altosuilib/AltosUIConfigure.java | 393 +++++++++++++++++++++++++++++++++++++++ altosuilib/Makefile.am | 2 +- micropeak/MicroPeak.java | 2 +- 4 files changed, 395 insertions(+), 395 deletions(-) delete mode 100644 altosuilib/AltosConfigureUI.java create mode 100644 altosuilib/AltosUIConfigure.java diff --git a/altosuilib/AltosConfigureUI.java b/altosuilib/AltosConfigureUI.java deleted file mode 100644 index a4b644bf..00000000 --- a/altosuilib/AltosConfigureUI.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib; - -import java.awt.*; -import java.awt.event.*; -import java.beans.*; -import javax.swing.*; -import javax.swing.event.*; - -class DelegatingRenderer implements ListCellRenderer { - - // ... - public static void install(JComboBox comboBox) { - DelegatingRenderer renderer = new DelegatingRenderer(comboBox); - renderer.initialise(); - comboBox.setRenderer(renderer); - } - - // ... - private final JComboBox comboBox; - - // ... - private ListCellRenderer delegate; - - // ... - private DelegatingRenderer(JComboBox comboBox) { - this.comboBox = comboBox; - } - - // ... - private void initialise() { - delegate = new JComboBox().getRenderer(); - comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() { - - public void propertyChange(PropertyChangeEvent evt) { - delegate = new JComboBox().getRenderer(); - } - }); - } - - // ... - public Component getListCellRendererComponent(JList list, - Object value, int index, boolean isSelected, boolean cellHasFocus) { - - return delegate.getListCellRendererComponent(list, - ((UIManager.LookAndFeelInfo) value).getName(), - index, isSelected, cellHasFocus); - } -} - -public class AltosConfigureUI - extends AltosUIDialog - implements DocumentListener -{ - JFrame owner; - Container pane; - - JRadioButton enable_voice; - JButton test_voice; - JButton close; - - JButton configure_log; - JTextField log_directory; - - JLabel callsign_label; - JTextField callsign_value; - - JRadioButton imperial_units; - - JLabel font_size_label; - JComboBox font_size_value; - - JLabel look_and_feel_label; - JComboBox look_and_feel_value; - - JRadioButton serial_debug; - - JButton manage_bluetooth; - JButton manage_frequencies; - - int row; - - final static String[] font_size_names = { "Small", "Medium", "Large" }; - - /* DocumentListener interface methods */ - public void changedUpdate(DocumentEvent e) { - if (callsign_value != null) - AltosUIPreferences.set_callsign(callsign_value.getText()); - } - - public void insertUpdate(DocumentEvent e) { - changedUpdate(e); - } - - public void removeUpdate(DocumentEvent e) { - changedUpdate(e); - } - - public GridBagConstraints constraints (int x, int width, int fill) { - GridBagConstraints c = new GridBagConstraints(); - Insets insets = new Insets(4, 4, 4, 4); - - c.insets = insets; - c.fill = fill; - if (width == 3) - c.anchor = GridBagConstraints.CENTER; - else - c.anchor = GridBagConstraints.WEST; - c.gridx = x; - c.gridwidth = width; - c.gridy = row; - return c; - } - - public GridBagConstraints constraints(int x, int width) { - return constraints(x, width, GridBagConstraints.NONE); - } - - public void add_voice() { -// GridBagConstraints c = new GridBagConstraints(); -// -// /* Voice settings */ -// c.gridx = 0; -// c.gridy = row; -// c.gridwidth = 1; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(new JLabel("Voice"), c); -// -// enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); -// enable_voice.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// JRadioButton item = (JRadioButton) e.getSource(); -// boolean enabled = item.isSelected(); -// AltosUIPreferences.set_voice(enabled); -// if (enabled) -// voice.speak_always("Enable voice."); -// else -// voice.speak_always("Disable voice."); -// } -// }); -// c.gridx = 1; -// c.gridy = row; -// c.gridwidth = 1; -// c.weightx = 1; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(enable_voice, c); -// enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); -// -// c.gridx = 2; -// c.gridy = row++; -// c.gridwidth = 1; -// c.weightx = 1; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.EAST; -// test_voice = new JButton("Test Voice"); -// test_voice.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// voice.speak("That's one small step for man; one giant leap for mankind."); -// } -// }); -// pane.add(test_voice, c); -// test_voice.setToolTipText("Play a stock audio clip to check volume"); -// row++; - } - - public void add_log_dir() { - /* Log directory settings */ - pane.add(new JLabel("Log Directory"), constraints(0, 1)); - - configure_log = new JButton(AltosUIPreferences.logdir().getPath()); - configure_log.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - AltosUIPreferences.ConfigureLog(); - configure_log.setText(AltosUIPreferences.logdir().getPath()); - } - }); - pane.add(configure_log, constraints(1, 2)); - configure_log.setToolTipText("Which directory flight logs are stored in"); - row++; - } - - public void add_callsign() { -// /* Callsign setting */ -// pane.add(new JLabel("Callsign"), constraints(0, 1)); -// -// callsign_value = new JTextField(AltosUIPreferences.callsign()); -// callsign_value.getDocument().addDocumentListener(this); -// callsign_value.setToolTipText("Callsign sent in packet mode"); -// pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH)); -// row++; - } - - public void add_units() { - /* Imperial units setting */ - pane.add(new JLabel("Imperial Units"), constraints(0, 1)); - - imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units()); - imperial_units.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JRadioButton item = (JRadioButton) e.getSource(); - boolean enabled = item.isSelected(); - AltosUIPreferences.set_imperial_units(enabled); - } - }); - imperial_units.setToolTipText("Use Imperial units instead of metric"); - pane.add(imperial_units, constraints(1, 2)); - row++; - } - - public void add_font_size() { - /* Font size setting */ - pane.add(new JLabel("Font size"), constraints(0, 1)); - - font_size_value = new JComboBox(font_size_names); - int font_size = AltosUIPreferences.font_size(); - font_size_value.setSelectedIndex(font_size - AltosUILib.font_size_small); - font_size_value.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int size = font_size_value.getSelectedIndex() + AltosUILib.font_size_small; - - AltosUIPreferences.set_font_size(size); - } - }); - pane.add(font_size_value, constraints(1, 2, GridBagConstraints.BOTH)); - font_size_value.setToolTipText("Font size used in telemetry window"); - row++; - } - - public void add_look_and_feel() { - /* Look & Feel setting */ - pane.add(new JLabel("Look & feel"), constraints(0, 1)); - - /* - class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer { - - public LookAndFeelRenderer() { - super(); - } - - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - setText(((UIManager.LookAndFeelInfo) value).getName()); - return this; - } - } - */ - - final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); - - look_and_feel_value = new JComboBox(look_and_feels); - - DelegatingRenderer.install(look_and_feel_value); - - String look_and_feel = AltosUIPreferences.look_and_feel(); - for (int i = 0; i < look_and_feels.length; i++) - if (look_and_feel.equals(look_and_feels[i].getClassName())) - look_and_feel_value.setSelectedIndex(i); - - look_and_feel_value.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int id = look_and_feel_value.getSelectedIndex(); - - AltosUIPreferences.set_look_and_feel(look_and_feels[id].getClassName()); - } - }); - pane.add(look_and_feel_value, constraints(1, 2, GridBagConstraints.BOTH)); - look_and_feel_value.setToolTipText("Look&feel used for new windows"); - row++; - } - - public void add_serial_debug() { - GridBagConstraints c = new GridBagConstraints(); - - /* Serial debug setting */ - pane.add(new JLabel("Serial Debug"), constraints(0, 1)); - - serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); - serial_debug.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JRadioButton item = (JRadioButton) e.getSource(); - boolean enabled = item.isSelected(); - AltosUIPreferences.set_serial_debug(enabled); - } - }); - serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); - } - - public void add_bluetooth() { -// GridBagConstraints c = new GridBagConstraints(); -// c.gridx = 1; -// c.gridy = row++; -// c.gridwidth = 3; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(serial_debug, c); -// -// manage_bluetooth = new JButton("Manage Bluetooth"); -// manage_bluetooth.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// AltosBTManage.show(owner, AltosBTKnown.bt_known()); -// } -// }); -// c.gridx = 0; -// c.gridy = row; -// c.gridwidth = 2; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(manage_bluetooth, c); - } - - public void add_frequencies() { -// GridBagConstraints c = new GridBagConstraints(); -// manage_frequencies = new JButton("Manage Frequencies"); -// manage_frequencies.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// AltosConfigFreqUI.show(owner); -// } -// }); -// manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); -// c.gridx = 2; -// c.gridx = 2; -// c.gridy = row++; -// c.gridwidth = 2; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(manage_frequencies, c); - } - - public AltosConfigureUI(JFrame in_owner) { - super(in_owner, "Configure AltosUI", false); - - owner = in_owner; - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - row = 0; - - /* Nice label at the top */ - pane.add(new JLabel ("Configure AltOS UI"), - constraints(0, 3)); - row++; - - pane.add(new JLabel (String.format("AltOS version %s", AltosUIVersion.version)), - constraints(0, 3)); - row++; - - add_voice(); - add_log_dir(); - add_callsign(); - add_units(); - add_font_size(); - add_look_and_feel(); - add_bluetooth(); - add_frequencies(); - - /* And a close button at the bottom */ - close = new JButton("Close"); - close.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - pane.add(close, constraints(0, 3)); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } -} diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java new file mode 100644 index 00000000..ef44f0be --- /dev/null +++ b/altosuilib/AltosUIConfigure.java @@ -0,0 +1,393 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib; + +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import javax.swing.*; +import javax.swing.event.*; + +class DelegatingRenderer implements ListCellRenderer { + + // ... + public static void install(JComboBox comboBox) { + DelegatingRenderer renderer = new DelegatingRenderer(comboBox); + renderer.initialise(); + comboBox.setRenderer(renderer); + } + + // ... + private final JComboBox comboBox; + + // ... + private ListCellRenderer delegate; + + // ... + private DelegatingRenderer(JComboBox comboBox) { + this.comboBox = comboBox; + } + + // ... + private void initialise() { + delegate = new JComboBox().getRenderer(); + comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent evt) { + delegate = new JComboBox().getRenderer(); + } + }); + } + + // ... + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + + return delegate.getListCellRendererComponent(list, + ((UIManager.LookAndFeelInfo) value).getName(), + index, isSelected, cellHasFocus); + } +} + +public class AltosUIConfigure + extends AltosUIDialog + implements DocumentListener +{ + JFrame owner; + Container pane; + + JRadioButton enable_voice; + JButton test_voice; + JButton close; + + JButton configure_log; + JTextField log_directory; + + JLabel callsign_label; + JTextField callsign_value; + + JRadioButton imperial_units; + + JLabel font_size_label; + JComboBox font_size_value; + + JLabel look_and_feel_label; + JComboBox look_and_feel_value; + + JRadioButton serial_debug; + + JButton manage_bluetooth; + JButton manage_frequencies; + + int row; + + final static String[] font_size_names = { "Small", "Medium", "Large" }; + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + if (callsign_value != null) + AltosUIPreferences.set_callsign(callsign_value.getText()); + } + + public void insertUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public void removeUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public GridBagConstraints constraints (int x, int width, int fill) { + GridBagConstraints c = new GridBagConstraints(); + Insets insets = new Insets(4, 4, 4, 4); + + c.insets = insets; + c.fill = fill; + if (width == 3) + c.anchor = GridBagConstraints.CENTER; + else + c.anchor = GridBagConstraints.WEST; + c.gridx = x; + c.gridwidth = width; + c.gridy = row; + return c; + } + + public GridBagConstraints constraints(int x, int width) { + return constraints(x, width, GridBagConstraints.NONE); + } + + public void add_voice() { +// GridBagConstraints c = new GridBagConstraints(); +// +// /* Voice settings */ +// c.gridx = 0; +// c.gridy = row; +// c.gridwidth = 1; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(new JLabel("Voice"), c); +// +// enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); +// enable_voice.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// JRadioButton item = (JRadioButton) e.getSource(); +// boolean enabled = item.isSelected(); +// AltosUIPreferences.set_voice(enabled); +// if (enabled) +// voice.speak_always("Enable voice."); +// else +// voice.speak_always("Disable voice."); +// } +// }); +// c.gridx = 1; +// c.gridy = row; +// c.gridwidth = 1; +// c.weightx = 1; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(enable_voice, c); +// enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); +// +// c.gridx = 2; +// c.gridy = row++; +// c.gridwidth = 1; +// c.weightx = 1; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.EAST; +// test_voice = new JButton("Test Voice"); +// test_voice.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// voice.speak("That's one small step for man; one giant leap for mankind."); +// } +// }); +// pane.add(test_voice, c); +// test_voice.setToolTipText("Play a stock audio clip to check volume"); +// row++; + } + + public void add_log_dir() { + /* Log directory settings */ + pane.add(new JLabel("Log Directory"), constraints(0, 1)); + + configure_log = new JButton(AltosUIPreferences.logdir().getPath()); + configure_log.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosUIPreferences.ConfigureLog(); + configure_log.setText(AltosUIPreferences.logdir().getPath()); + } + }); + pane.add(configure_log, constraints(1, 2)); + configure_log.setToolTipText("Which directory flight logs are stored in"); + row++; + } + + public void add_callsign() { +// /* Callsign setting */ +// pane.add(new JLabel("Callsign"), constraints(0, 1)); +// +// callsign_value = new JTextField(AltosUIPreferences.callsign()); +// callsign_value.getDocument().addDocumentListener(this); +// callsign_value.setToolTipText("Callsign sent in packet mode"); +// pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH)); +// row++; + } + + public void add_units() { + /* Imperial units setting */ + pane.add(new JLabel("Imperial Units"), constraints(0, 1)); + + imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units()); + imperial_units.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosUIPreferences.set_imperial_units(enabled); + } + }); + imperial_units.setToolTipText("Use Imperial units instead of metric"); + pane.add(imperial_units, constraints(1, 2)); + row++; + } + + public void add_font_size() { + /* Font size setting */ + pane.add(new JLabel("Font size"), constraints(0, 1)); + + font_size_value = new JComboBox(font_size_names); + int font_size = AltosUIPreferences.font_size(); + font_size_value.setSelectedIndex(font_size - AltosUILib.font_size_small); + font_size_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int size = font_size_value.getSelectedIndex() + AltosUILib.font_size_small; + + AltosUIPreferences.set_font_size(size); + } + }); + pane.add(font_size_value, constraints(1, 2, GridBagConstraints.BOTH)); + font_size_value.setToolTipText("Font size used in telemetry window"); + row++; + } + + public void add_look_and_feel() { + /* Look & Feel setting */ + pane.add(new JLabel("Look & feel"), constraints(0, 1)); + + /* + class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer { + + public LookAndFeelRenderer() { + super(); + } + + public Component getListCellRendererComponent( + JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + setText(((UIManager.LookAndFeelInfo) value).getName()); + return this; + } + } + */ + + final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); + + look_and_feel_value = new JComboBox(look_and_feels); + + DelegatingRenderer.install(look_and_feel_value); + + String look_and_feel = AltosUIPreferences.look_and_feel(); + for (int i = 0; i < look_and_feels.length; i++) + if (look_and_feel.equals(look_and_feels[i].getClassName())) + look_and_feel_value.setSelectedIndex(i); + + look_and_feel_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int id = look_and_feel_value.getSelectedIndex(); + + AltosUIPreferences.set_look_and_feel(look_and_feels[id].getClassName()); + } + }); + pane.add(look_and_feel_value, constraints(1, 2, GridBagConstraints.BOTH)); + look_and_feel_value.setToolTipText("Look&feel used for new windows"); + row++; + } + + public void add_serial_debug() { + GridBagConstraints c = new GridBagConstraints(); + + /* Serial debug setting */ + pane.add(new JLabel("Serial Debug"), constraints(0, 1)); + + serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); + serial_debug.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosUIPreferences.set_serial_debug(enabled); + } + }); + serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); + } + + public void add_bluetooth() { +// GridBagConstraints c = new GridBagConstraints(); +// c.gridx = 1; +// c.gridy = row++; +// c.gridwidth = 3; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(serial_debug, c); +// +// manage_bluetooth = new JButton("Manage Bluetooth"); +// manage_bluetooth.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// AltosBTManage.show(owner, AltosBTKnown.bt_known()); +// } +// }); +// c.gridx = 0; +// c.gridy = row; +// c.gridwidth = 2; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(manage_bluetooth, c); + } + + public void add_frequencies() { +// GridBagConstraints c = new GridBagConstraints(); +// manage_frequencies = new JButton("Manage Frequencies"); +// manage_frequencies.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// AltosConfigFreqUI.show(owner); +// } +// }); +// manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); +// c.gridx = 2; +// c.gridx = 2; +// c.gridy = row++; +// c.gridwidth = 2; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(manage_frequencies, c); + } + + public AltosUIConfigure(JFrame in_owner) { + super(in_owner, "Configure AltosUI", false); + + owner = in_owner; + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + row = 0; + + /* Nice label at the top */ + pane.add(new JLabel ("Configure AltOS UI"), + constraints(0, 3)); + row++; + + pane.add(new JLabel (String.format("AltOS version %s", AltosUIVersion.version)), + constraints(0, 3)); + row++; + + add_voice(); + add_log_dir(); + add_callsign(); + add_units(); + add_font_size(); + add_look_and_feel(); + add_bluetooth(); + add_frequencies(); + + /* And a close button at the bottom */ + close = new JButton("Close"); + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + pane.add(close, constraints(0, 3)); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index e2ff8cb5..d93d9415 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -10,7 +10,7 @@ BIN=bin/org/altusmetrum/AltosUILib AltosUILibdir = $(datadir)/java AltosUILib_JAVA = \ - AltosConfigureUI.java \ + AltosUIConfigure.java \ AltosDevice.java \ AltosDeviceDialog.java \ AltosUSBDevice.java \ diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 17eae228..544f3ae0 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -91,7 +91,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } private void Preferences() { - new AltosConfigureUI(this); + new AltosUIConfigure(this); } private void DownloadData() { -- cgit v1.2.3 From 8a5666bcf4949b846589c000e1620afe39593f57 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:06:22 -0800 Subject: libaltos: Remove a couple of spurious debug printfs Signed-off-by: Keith Packard --- libaltos/libaltos.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c index 6e884c80..24c20179 100644 --- a/libaltos/libaltos.c +++ b/libaltos/libaltos.c @@ -116,7 +116,6 @@ altos_open(struct altos_device *device) return NULL; } - printf ("open\n"); // altos_set_last_error(12, "yeah yeah, failed again"); // free(file); // return NULL; @@ -612,7 +611,6 @@ altos_list_next(struct altos_list *list, struct altos_device *device) { struct altos_usbdev *dev; if (list->current >= list->ndev) { - printf ("end\n"); return 0; } dev = list->dev[list->current]; -- cgit v1.2.3 From 5ce43661834920c3a8f3a1b6e1c555fb952b512d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:06:41 -0800 Subject: altosui: Use altosuilib for configuration Start moving to shared UI code Signed-off-by: Keith Packard --- altosui/AltosConfigureUI.java | 358 ++++----------------------------------- altosui/Makefile.am | 28 +-- altosuilib/AltosUIConfigure.java | 153 ++--------------- altosuilib/Makefile.am | 27 ++- 4 files changed, 82 insertions(+), 484 deletions(-) diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index c576b052..0e411b03 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -22,86 +22,17 @@ import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; - -class DelegatingRenderer implements ListCellRenderer { - - // ... - public static void install(JComboBox comboBox) { - DelegatingRenderer renderer = new DelegatingRenderer(comboBox); - renderer.initialise(); - comboBox.setRenderer(renderer); - } - - // ... - private final JComboBox comboBox; - - // ... - private ListCellRenderer delegate; - - // ... - private DelegatingRenderer(JComboBox comboBox) { - this.comboBox = comboBox; - } - - // ... - private void initialise() { - delegate = new JComboBox().getRenderer(); - comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() { - - public void propertyChange(PropertyChangeEvent evt) { - delegate = new JComboBox().getRenderer(); - } - }); - } - - // ... - public Component getListCellRendererComponent(JList list, - Object value, int index, boolean isSelected, boolean cellHasFocus) { - - return delegate.getListCellRendererComponent(list, - ((UIManager.LookAndFeelInfo) value).getName(), - index, isSelected, cellHasFocus); - } -} +import org.altusmetrum.altosuilib.*; public class AltosConfigureUI - extends AltosDialog + extends AltosUIConfigure implements DocumentListener { - JFrame owner; AltosVoice voice; - Container pane; - - JRadioButton enable_voice; - JButton test_voice; - JButton close; - - JButton configure_log; - JTextField log_directory; - - JLabel callsign_label; - JTextField callsign_value; - - JRadioButton imperial_units; - - JLabel font_size_label; - JComboBox font_size_value; - JLabel look_and_feel_label; - JComboBox look_and_feel_value; - - JRadioButton serial_debug; - - JButton manage_bluetooth; - JButton manage_frequencies; - - final static String[] font_size_names = { "Small", "Medium", "Large" }; + public JTextField callsign_value; /* DocumentListener interface methods */ - public void changedUpdate(DocumentEvent e) { - AltosUIPreferences.set_callsign(callsign_value.getText()); - } - public void insertUpdate(DocumentEvent e) { changedUpdate(e); } @@ -110,49 +41,17 @@ public class AltosConfigureUI changedUpdate(e); } - public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) { - super(in_owner, "Configure AltosUI", false); - - GridBagConstraints c; - - Insets insets = new Insets(4, 4, 4, 4); - - int row = 0; - - owner = in_owner; - voice = in_voice; - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.insets = insets; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - - /* Nice label at the top */ - c.gridx = 0; - c.gridy = row++; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - pane.add(new JLabel ("Configure AltOS UI"), c); + public void changedUpdate(DocumentEvent e) { + if (callsign_value != null) + AltosUIPreferences.set_callsign(callsign_value.getText()); + } - c.gridx = 0; - c.gridy = row++; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - pane.add(new JLabel (String.format("AltOS version %s", AltosVersion.version)), c); + public void add_voice() { /* Voice settings */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Voice"), c); + pane.add(new JLabel("Voice"), constraints(0, 1)); - enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); + JRadioButton enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); enable_voice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JRadioButton item = (JRadioButton) e.getSource(); @@ -164,246 +63,57 @@ public class AltosConfigureUI voice.speak_always("Disable voice."); } }); - c.gridx = 1; - c.gridy = row; - c.gridwidth = 1; - c.weightx = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(enable_voice, c); + pane.add(enable_voice, constraints(1, 1)); enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); - c.gridx = 2; - c.gridy = row++; - c.gridwidth = 1; - c.weightx = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.EAST; - test_voice = new JButton("Test Voice"); + JButton test_voice = new JButton("Test Voice"); test_voice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { voice.speak("That's one small step for man; one giant leap for mankind."); } }); - pane.add(test_voice, c); + pane.add(test_voice, constraints(2, 1)); test_voice.setToolTipText("Play a stock audio clip to check volume"); + row++; + } - /* Log directory settings */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Log Directory"), c); - - configure_log = new JButton(AltosUIPreferences.logdir().getPath()); - configure_log.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - AltosUIPreferences.ConfigureLog(); - configure_log.setText(AltosUIPreferences.logdir().getPath()); - } - }); - c.gridx = 1; - c.gridy = row++; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - pane.add(configure_log, c); - configure_log.setToolTipText("Which directory flight logs are stored in"); - + public void add_callsign() { /* Callsign setting */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Callsign"), c); + pane.add(new JLabel("Callsign"), constraints(0, 1)); - callsign_value = new JTextField(AltosUIPreferences.callsign()); + JTextField callsign_value = new JTextField(AltosUIPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); - c.gridx = 1; - c.gridy = row++; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - pane.add(callsign_value, c); callsign_value.setToolTipText("Callsign sent in packet mode"); + pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH)); + row++; + } - /* Imperial units setting */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Imperial Units"), c); - - imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units()); - imperial_units.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JRadioButton item = (JRadioButton) e.getSource(); - boolean enabled = item.isSelected(); - AltosUIPreferences.set_imperial_units(enabled); - } - }); - imperial_units.setToolTipText("Use Imperial units instead of metric"); - - c.gridx = 1; - c.gridy = row++; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(imperial_units, c); - - /* Font size setting */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Font size"), c); - - font_size_value = new JComboBox(font_size_names); - int font_size = AltosUIPreferences.font_size(); - font_size_value.setSelectedIndex(font_size - Altos.font_size_small); - font_size_value.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int size = font_size_value.getSelectedIndex() + Altos.font_size_small; - - AltosUIPreferences.set_font_size(size); - } - }); - c.gridx = 1; - c.gridy = row++; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - pane.add(font_size_value, c); - font_size_value.setToolTipText("Font size used in telemetry window"); - - /* Look & Feel setting */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Look & feel"), c); - - /* - class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer { - - public LookAndFeelRenderer() { - super(); - } - - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - setText(((UIManager.LookAndFeelInfo) value).getName()); - return this; - } - } - */ - - final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); - - look_and_feel_value = new JComboBox(look_and_feels); - - DelegatingRenderer.install(look_and_feel_value); - - String look_and_feel = AltosUIPreferences.look_and_feel(); - for (int i = 0; i < look_and_feels.length; i++) - if (look_and_feel.equals(look_and_feels[i].getClassName())) - look_and_feel_value.setSelectedIndex(i); - - look_and_feel_value.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int id = look_and_feel_value.getSelectedIndex(); - - AltosUIPreferences.set_look_and_feel(look_and_feels[id].getClassName()); - } - }); - c.gridx = 1; - c.gridy = row++; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - pane.add(look_and_feel_value, c); - look_and_feel_value.setToolTipText("Look&feel used for new windows"); - - /* Serial debug setting */ - c.gridx = 0; - c.gridy = row; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Serial Debug"), c); - - serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); - serial_debug.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JRadioButton item = (JRadioButton) e.getSource(); - boolean enabled = item.isSelected(); - AltosUIPreferences.set_serial_debug(enabled); - } - }); - serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); - - c.gridx = 1; - c.gridy = row++; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(serial_debug, c); - - manage_bluetooth = new JButton("Manage Bluetooth"); + public void add_bluetooth() { + JButton manage_bluetooth = new JButton("Manage Bluetooth"); manage_bluetooth.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { AltosBTManage.show(owner, AltosBTKnown.bt_known()); } }); - c.gridx = 0; - c.gridy = row; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(manage_bluetooth, c); + pane.add(manage_bluetooth, constraints(0, 2)); + /* in the same row as add_frequencies, so don't bump row */ + } - manage_frequencies = new JButton("Manage Frequencies"); + public void add_frequencies() { + JButton manage_frequencies = new JButton("Manage Frequencies"); manage_frequencies.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { AltosConfigFreqUI.show(owner); } }); manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); - c.gridx = 2; - c.gridx = 2; - c.gridy = row++; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(manage_frequencies, c); + pane.add(manage_frequencies, constraints(2, 1)); + row++; + } - /* And a close button at the bottom */ - close = new JButton("Close"); - close.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - c.gridx = 0; - c.gridy = row++; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - pane.add(close, c); + public AltosConfigureUI(JFrame owner, AltosVoice voice) { + super(owner); - pack(); - setLocationRelativeTo(owner); - setVisible(true); + this.voice = voice; } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index a42426cd..494539ae 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -6,7 +6,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="./*:$(JAVAROOT):../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" bin_SCRIPTS=altosui @@ -109,6 +109,9 @@ FREETTS_CLASS= \ ALTOSLIB_CLASS=\ AltosLib.jar +ALTOSUILIB_CLASS=\ + altosuilib.jar + LIBALTOS= \ libaltos.so \ libaltos.dylib \ @@ -172,7 +175,7 @@ LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2 MACOSX_DIST=Altos-Mac-$(VERSION).zip WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe -FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) +FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) LINUX_EXTRA=altosui-fat @@ -187,7 +190,7 @@ all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb clean-local: -rm -rf classes $(JAR) $(FATJAR) \ - $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(ALTOSLIB_CLASS) $(FREETTS_CLASS) \ + $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) \ $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test altosui-jdb macosx linux @@ -229,13 +232,13 @@ install-altosuiJAVA: altosui.jar classes/altosui: mkdir -p classes/altosui -$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) +$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICONS) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) jar cfm $@ Manifest.txt \ $(ICONJAR) \ -C classes altosui \ -C ../libaltos libaltosJNI -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICONS) +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICONS) jar cfm $@ Manifest-fat.txt \ $(ICONJAR) \ -C classes altosui \ @@ -243,25 +246,25 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(FREETTS_CLASS Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: AltosLib.jar $(FREETTS)/freetts.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ + echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS)/freetts.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: AltosLib.jar freetts.jar jcommon.jar jfreechart.jar" >> $@ + echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) freetts.jar jcommon.jar jfreechart.jar" >> $@ altosui: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ + echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ chmod +x $@ altosui-test: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "./*:../libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ + echo 'exec java -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ altosui-jdb: Makefile echo "#!/bin/sh" > $@ - echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ + echo 'exec jdb -classpath "classes:./*:../libaltos:$(FREETTS)/freetts.jar:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ chmod +x $@ libaltos.so: build-libaltos @@ -298,6 +301,10 @@ $(ALTOSLIB_CLASS): -rm -f "$@" $(LN_S) ../altoslib/"$@" . +$(ALTOSUILIB_CLASS): + -rm -f "$@" + $(LN_S) ../altosuilib/"$@" . + $(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . @@ -329,6 +336,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java cp -p $(ALTOSLIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java + cp -p $(ALTOSUILIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java cp -p $(FREETTS_CLASS) macosx/AltosUI.app/Contents/Resources/Java cp -p $(JFREECHART_CLASS) macosx/AltosUI.app/Contents/Resources/Java cp -p $(JCOMMON_CLASS) macosx/AltosUI.app/Contents/Resources/Java diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index ef44f0be..6c9a841e 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -66,52 +66,14 @@ class DelegatingRenderer implements ListCellRenderer { public class AltosUIConfigure extends AltosUIDialog - implements DocumentListener { - JFrame owner; - Container pane; + public JFrame owner; + public Container pane; - JRadioButton enable_voice; - JButton test_voice; - JButton close; - - JButton configure_log; - JTextField log_directory; - - JLabel callsign_label; - JTextField callsign_value; - - JRadioButton imperial_units; - - JLabel font_size_label; - JComboBox font_size_value; - - JLabel look_and_feel_label; - JComboBox look_and_feel_value; - - JRadioButton serial_debug; - - JButton manage_bluetooth; - JButton manage_frequencies; - - int row; + public int row; final static String[] font_size_names = { "Small", "Medium", "Large" }; - /* DocumentListener interface methods */ - public void changedUpdate(DocumentEvent e) { - if (callsign_value != null) - AltosUIPreferences.set_callsign(callsign_value.getText()); - } - - public void insertUpdate(DocumentEvent e) { - changedUpdate(e); - } - - public void removeUpdate(DocumentEvent e) { - changedUpdate(e); - } - public GridBagConstraints constraints (int x, int width, int fill) { GridBagConstraints c = new GridBagConstraints(); Insets insets = new Insets(4, 4, 4, 4); @@ -120,6 +82,8 @@ public class AltosUIConfigure c.fill = fill; if (width == 3) c.anchor = GridBagConstraints.CENTER; + else if (x == 2) + c.anchor = GridBagConstraints.EAST; else c.anchor = GridBagConstraints.WEST; c.gridx = x; @@ -133,59 +97,13 @@ public class AltosUIConfigure } public void add_voice() { -// GridBagConstraints c = new GridBagConstraints(); -// -// /* Voice settings */ -// c.gridx = 0; -// c.gridy = row; -// c.gridwidth = 1; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(new JLabel("Voice"), c); -// -// enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); -// enable_voice.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// JRadioButton item = (JRadioButton) e.getSource(); -// boolean enabled = item.isSelected(); -// AltosUIPreferences.set_voice(enabled); -// if (enabled) -// voice.speak_always("Enable voice."); -// else -// voice.speak_always("Disable voice."); -// } -// }); -// c.gridx = 1; -// c.gridy = row; -// c.gridwidth = 1; -// c.weightx = 1; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(enable_voice, c); -// enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); -// -// c.gridx = 2; -// c.gridy = row++; -// c.gridwidth = 1; -// c.weightx = 1; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.EAST; -// test_voice = new JButton("Test Voice"); -// test_voice.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// voice.speak("That's one small step for man; one giant leap for mankind."); -// } -// }); -// pane.add(test_voice, c); -// test_voice.setToolTipText("Play a stock audio clip to check volume"); -// row++; } public void add_log_dir() { /* Log directory settings */ pane.add(new JLabel("Log Directory"), constraints(0, 1)); - configure_log = new JButton(AltosUIPreferences.logdir().getPath()); + final JButton configure_log = new JButton(AltosUIPreferences.logdir().getPath()); configure_log.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { AltosUIPreferences.ConfigureLog(); @@ -198,21 +116,13 @@ public class AltosUIConfigure } public void add_callsign() { -// /* Callsign setting */ -// pane.add(new JLabel("Callsign"), constraints(0, 1)); -// -// callsign_value = new JTextField(AltosUIPreferences.callsign()); -// callsign_value.getDocument().addDocumentListener(this); -// callsign_value.setToolTipText("Callsign sent in packet mode"); -// pane.add(callsign_value, constraints(1, 2, GridBagConstraints.BOTH)); -// row++; } public void add_units() { /* Imperial units setting */ pane.add(new JLabel("Imperial Units"), constraints(0, 1)); - imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units()); + JRadioButton imperial_units = new JRadioButton("Enable", AltosUIPreferences.imperial_units()); imperial_units.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JRadioButton item = (JRadioButton) e.getSource(); @@ -229,7 +139,7 @@ public class AltosUIConfigure /* Font size setting */ pane.add(new JLabel("Font size"), constraints(0, 1)); - font_size_value = new JComboBox(font_size_names); + final JComboBox font_size_value = new JComboBox(font_size_names); int font_size = AltosUIPreferences.font_size(); font_size_value.setSelectedIndex(font_size - AltosUILib.font_size_small); font_size_value.addActionListener(new ActionListener() { @@ -271,7 +181,7 @@ public class AltosUIConfigure final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); - look_and_feel_value = new JComboBox(look_and_feels); + final JComboBox look_and_feel_value = new JComboBox(look_and_feels); DelegatingRenderer.install(look_and_feel_value); @@ -298,7 +208,7 @@ public class AltosUIConfigure /* Serial debug setting */ pane.add(new JLabel("Serial Debug"), constraints(0, 1)); - serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); + JRadioButton serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); serial_debug.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JRadioButton item = (JRadioButton) e.getSource(); @@ -307,47 +217,18 @@ public class AltosUIConfigure } }); serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); + c.gridx = 1; + c.gridy = row++; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(serial_debug, c); } public void add_bluetooth() { -// GridBagConstraints c = new GridBagConstraints(); -// c.gridx = 1; -// c.gridy = row++; -// c.gridwidth = 3; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(serial_debug, c); -// -// manage_bluetooth = new JButton("Manage Bluetooth"); -// manage_bluetooth.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// AltosBTManage.show(owner, AltosBTKnown.bt_known()); -// } -// }); -// c.gridx = 0; -// c.gridy = row; -// c.gridwidth = 2; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(manage_bluetooth, c); } public void add_frequencies() { -// GridBagConstraints c = new GridBagConstraints(); -// manage_frequencies = new JButton("Manage Frequencies"); -// manage_frequencies.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// AltosConfigFreqUI.show(owner); -// } -// }); -// manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); -// c.gridx = 2; -// c.gridx = 2; -// c.gridy = row++; -// c.gridwidth = 2; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(manage_frequencies, c); } public AltosUIConfigure(JFrame in_owner) { @@ -378,7 +259,7 @@ public class AltosUIConfigure add_frequencies(); /* And a close button at the bottom */ - close = new JButton("Close"); + JButton close = new JButton("Close"); close.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setVisible(false); diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index d93d9415..d4aa0116 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -2,14 +2,13 @@ AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation JAVAROOT=bin -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:../altoslib/*:../libaltos:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../altoslib/*:../libaltos:/usr/share/java/*" SRC=. -BIN=bin/org/altusmetrum/AltosUILib -AltosUILibdir = $(datadir)/java +altosuilibdir = $(datadir)/java -AltosUILib_JAVA = \ +altosuilib_JAVA = \ AltosUIConfigure.java \ AltosDevice.java \ AltosDeviceDialog.java \ @@ -24,21 +23,21 @@ AltosUILib_JAVA = \ AltosUIVersion.java \ AltosUnitsListener.java -JAR=AltosUILib.jar +JAR=altosuilib.jar all-local: $(JAR) clean-local: - -rm -rf bin $(JAR) + -rm -rf $(JAVAROOT) $(JAR) -install-AltosUILibJAVA: $(JAR) +install-altosuilibjava: $(JAR) @$(NORMAL_INSTALL) - test -z "$(AltosUILibdir)" || $(MKDIR_P) "$(DESTDIR)$(AltosUILibdir)" - echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(AltosUILibdir)/$(JAR)"; \ - $(INSTALL_DATA) "$<" "$(DESTDIR)$(AltosUILibdir)" + test -z "$(altosuilibdir)" || $(MKDIR_P) "$(DESTDIR)$(altosuilibdir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuilibdir)/$(JAR)"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuilibdir)" -bin: - mkdir -p bin +$(JAVAROOT): + mkdir -p $(JAVAROOT) -$(JAR): classAltosUILib.stamp - jar cf $@ -C bin org +$(JAR): classaltosuilib.stamp + jar cf $@ -C $(JAVAROOT) . -- cgit v1.2.3 From 605b752080827bb59fcff5af9f1eab9fd5dad76b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:09:10 -0800 Subject: altosui: Remove AltosVersion.java Version data now stored in AltosUIVersion.java Signed-off-by: Keith Packard --- altosui/AltosVersion.java.in | 22 ---------------------- altosui/Makefile.am | 1 - configure.ac | 1 - 3 files changed, 24 deletions(-) delete mode 100644 altosui/AltosVersion.java.in diff --git a/altosui/AltosVersion.java.in b/altosui/AltosVersion.java.in deleted file mode 100644 index b0b3c0cf..00000000 --- a/altosui/AltosVersion.java.in +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -public class AltosVersion { - public final static String version = "@VERSION@"; -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 494539ae..b3aa1f55 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -87,7 +87,6 @@ altosui_JAVA = \ AltosGraphTime.java \ AltosGraphUI.java \ AltosDataChooser.java \ - AltosVersion.java \ AltosVoice.java \ $(altosui_BT) diff --git a/configure.ac b/configure.ac index 312f9678..ee685344 100644 --- a/configure.ac +++ b/configure.ac @@ -149,7 +149,6 @@ altoslib/Makefile altosuilib/Makefile altosuilib/AltosUIVersion.java altosui/Makefile -altosui/AltosVersion.java altosui/Info.plist libaltos/Makefile micropeak/Makefile -- cgit v1.2.3 From 8af405f1ac4d1b930f10465fd0270a49176f16d1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:31:35 -0800 Subject: altosui: Use shared AltosDeviceDialog Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 1 + altosui/AltosBTKnown.java | 1 + altosui/AltosConfig.java | 5 +- altosui/AltosConfigTD.java | 4 +- altosui/AltosDebug.java | 1 + altosui/AltosDeviceDialog.java | 185 --------------------------------- altosui/AltosDeviceUIDialog.java | 70 +++++++++++++ altosui/AltosEepromManage.java | 3 +- altosui/AltosFlash.java | 1 + altosui/AltosFlashUI.java | 3 +- altosui/AltosIdleMonitorUI.java | 3 +- altosui/AltosIgniteUI.java | 3 +- altosui/AltosLaunch.java | 1 + altosui/AltosLaunchUI.java | 3 +- altosui/AltosScanUI.java | 3 +- altosui/AltosSerial.java | 1 + altosui/AltosSerialInUseException.java | 1 + altosui/AltosUI.java | 3 +- altosui/AltosUSBDevice.java | 1 + altosui/Makefile.am | 3 +- altosuilib/AltosDeviceDialog.java | 35 +++---- 21 files changed, 114 insertions(+), 217 deletions(-) delete mode 100644 altosui/AltosDeviceDialog.java create mode 100644 altosui/AltosDeviceUIDialog.java diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 03e7cbec..222b3c97 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -17,6 +17,7 @@ package altosui; import libaltosJNI.*; +import org.altusmetrum.altosuilib.*; public class AltosBTDevice extends altos_bt_device implements AltosDevice { diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java index ae04ac8c..606c0349 100644 --- a/altosui/AltosBTKnown.java +++ b/altosui/AltosBTKnown.java @@ -18,6 +18,7 @@ package altosui; import java.util.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosBTKnown implements Iterable { LinkedList devices = new LinkedList(); diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index e1ffebb4..1cd61a89 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -21,8 +21,9 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.AltosLib.*; import java.text.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosConfig implements ActionListener { @@ -270,7 +271,7 @@ public class AltosConfig implements ActionListener { public AltosConfig(JFrame given_owner) { owner = given_owner; - device = AltosDeviceDialog.show(owner, Altos.product_any); + device = AltosDeviceUIDialog.show(owner, Altos.product_any); if (device != null) { try { serial_line = new AltosSerial(device); diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index e7b9b81f..794f8103 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -21,8 +21,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; - import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosConfigTD implements ActionListener { @@ -315,7 +315,7 @@ public class AltosConfigTD implements ActionListener { version = new string_ref("unknown"); product = new string_ref("unknown"); - device = AltosDeviceDialog.show(owner, Altos.product_basestation); + device = AltosDeviceUIDialog.show(owner, Altos.product_basestation); if (device != null) { try { serial_line = new AltosSerial(device); diff --git a/altosui/AltosDebug.java b/altosui/AltosDebug.java index 16b10c3a..482f4c36 100644 --- a/altosui/AltosDebug.java +++ b/altosui/AltosDebug.java @@ -18,6 +18,7 @@ package altosui; import java.io.*; +import org.altusmetrum.altosuilib.*; public class AltosDebug extends AltosSerial { diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java deleted file mode 100644 index 0aeadae6..00000000 --- a/altosui/AltosDeviceDialog.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; - -public class AltosDeviceDialog extends AltosDialog implements ActionListener { - - private AltosDevice value; - private JList list; - private JButton cancel_button; - private JButton select_button; - private JButton manage_bluetooth_button; - private Frame frame; - private int product; - - private AltosDevice getValue() { - return value; - } - - private AltosDevice[] devices() { - java.util.List usb_devices = AltosUSBDevice.list(product); - int num_devices = usb_devices.size(); - java.util.List bt_devices = AltosBTKnown.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); - int off = usb_devices.size(); - for (int j = 0; j < bt_devices.size(); j++) - devices[off + j] = bt_devices.get(j); - return devices; - } - - private void update_devices() { - AltosDevice[] devices = devices(); - list.setListData(devices); - select_button.setEnabled(devices.length > 0); - } - - private AltosDeviceDialog (Frame in_frame, Component location, int in_product) { - super(in_frame, "Device Selection", true); - - product = in_product; - frame = in_frame; - value = null; - - AltosDevice[] devices = devices(); - - cancel_button = new JButton("Cancel"); - cancel_button.setActionCommand("cancel"); - cancel_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"); - select_button.addActionListener(this); - if (devices.length == 0) - select_button.setEnabled(false); - getRootPane().setDefaultButton(select_button); - - list = new JList(devices) { - //Subclass JList to workaround bug 4832765, which can cause the - //scroll pane to not let the user easily scroll up to the beginning - //of the list. An alternative would be to set the unitIncrement - //of the JScrollBar to a fixed value. You wouldn't get the nice - //aligned scrolling, but it should work. - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, - int direction) { - int row; - if (orientation == SwingConstants.VERTICAL && - direction < 0 && (row = getFirstVisibleIndex()) != -1) { - Rectangle r = getCellBounds(row, row); - if ((r.y == visibleRect.y) && (row != 0)) { - Point loc = r.getLocation(); - loc.y--; - int prevIndex = locationToIndex(loc); - Rectangle prevR = getCellBounds(prevIndex, prevIndex); - - if (prevR == null || prevR.y >= r.y) { - return 0; - } - return prevR.height; - } - } - return super.getScrollableUnitIncrement( - visibleRect, orientation, direction); - } - }; - - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - list.setLayoutOrientation(JList.HORIZONTAL_WRAP); - list.setVisibleRowCount(-1); - list.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - select_button.doClick(); //emulate button click - } - } - }); - JScrollPane listScroller = new JScrollPane(list); - listScroller.setPreferredSize(new Dimension(400, 80)); - listScroller.setAlignmentX(LEFT_ALIGNMENT); - - //Create a container so that we can add a title around - //the scroll pane. Can't add a title directly to the - //scroll pane because its background would be white. - //Lay out the label and scroll pane from top to bottom. - JPanel listPane = new JPanel(); - listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); - - JLabel label = new JLabel("Select Device"); - label.setLabelFor(list); - listPane.add(label); - listPane.add(Box.createRigidArea(new Dimension(0,5))); - listPane.add(listScroller); - listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - - //Lay out the buttons from left to right. - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); - buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); - buttonPane.add(Box.createHorizontalGlue()); - buttonPane.add(cancel_button); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(manage_bluetooth_button); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(select_button); - - //Put everything together, using the content pane's BorderLayout. - Container contentPane = getContentPane(); - contentPane.add(listPane, BorderLayout.CENTER); - contentPane.add(buttonPane, BorderLayout.PAGE_END); - - //Initialize values. - if (devices != null && devices.length != 0) - list.setSelectedValue(devices[0], true); - pack(); - setLocationRelativeTo(location); - } - - //Handle clicks on the Set and Cancel buttons. - public void actionPerformed(ActionEvent e) { - if ("select".equals(e.getActionCommand())) - value = (AltosDevice)(list.getSelectedValue()); - if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame, AltosBTKnown.bt_known()); - update_devices(); - return; - } - setVisible(false); - } - - public static AltosDevice show (Component frameComp, int product) { - - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosDeviceDialog dialog; - - dialog = new AltosDeviceDialog(frame, frameComp, product); - dialog.setVisible(true); - return dialog.getValue(); - } -} diff --git a/altosui/AltosDeviceUIDialog.java b/altosui/AltosDeviceUIDialog.java new file mode 100644 index 00000000..7ed599a3 --- /dev/null +++ b/altosui/AltosDeviceUIDialog.java @@ -0,0 +1,70 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package altosui; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import org.altusmetrum.altosuilib.*; + +public class AltosDeviceUIDialog extends AltosDeviceDialog { + + public AltosDevice[] devices() { + java.util.List usb_devices = AltosUSBDevice.list(product); + int num_devices = usb_devices.size(); + java.util.List bt_devices = AltosBTKnown.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); + int off = usb_devices.size(); + for (int j = 0; j < bt_devices.size(); j++) + devices[off + j] = bt_devices.get(j); + return devices; + } + + public void add_bluetooth() { + JButton manage_bluetooth_button = new JButton("Manage Bluetooth"); + manage_bluetooth_button.setActionCommand("manage"); + manage_bluetooth_button.addActionListener(this); + buttonPane.add(manage_bluetooth_button); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + } + + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + if ("manage".equals(e.getActionCommand())) { + AltosBTManage.show(frame, AltosBTKnown.bt_known()); + update_devices(); + } + } + + public AltosDeviceUIDialog (Frame in_frame, Component location, int in_product) { + super(in_frame, location, in_product); + } + + public static AltosDevice show (Component frameComp, int product) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosDeviceUIDialog dialog; + + dialog = new AltosDeviceUIDialog(frame, frameComp, product); + dialog.setVisible(true); + return dialog.getValue(); + } +} diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index b8de77da..cc9adb0c 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -22,6 +22,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosEepromManage implements ActionListener { @@ -197,7 +198,7 @@ public class AltosEepromManage implements ActionListener { //boolean running = false; frame = given_frame; - device = AltosDeviceDialog.show(frame, Altos.product_any); + device = AltosDeviceUIDialog.show(frame, Altos.product_any); remote = false; diff --git a/altosui/AltosFlash.java b/altosui/AltosFlash.java index 313af70b..7a98ee14 100644 --- a/altosui/AltosFlash.java +++ b/altosui/AltosFlash.java @@ -20,6 +20,7 @@ package altosui; import java.awt.event.*; import javax.swing.*; import java.io.*; +import org.altusmetrum.altosuilib.*; public class AltosFlash { File file; diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 3ccfa76c..878150f6 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -23,6 +23,7 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; +import org.altusmetrum.altosuilib.*; public class AltosFlashUI extends AltosDialog @@ -175,7 +176,7 @@ public class AltosFlashUI } boolean select_debug_dongle() { - debug_dongle = AltosDeviceDialog.show(frame, Altos.product_any); + debug_dongle = AltosDeviceUIDialog.show(frame, Altos.product_any); if (debug_dongle == null) return false; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 6f696009..6d3450b6 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -23,6 +23,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener { AltosDevice device; @@ -90,7 +91,7 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay public AltosIdleMonitorUI(JFrame in_owner) throws FileNotFoundException, AltosSerialInUseException, TimeoutException, InterruptedException { - device = AltosDeviceDialog.show(in_owner, Altos.product_any); + device = AltosDeviceUIDialog.show(in_owner, Altos.product_any); remote = false; if (!device.matchProduct(Altos.product_altimeter)) remote = true; diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index ec331259..f1742203 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -24,6 +24,7 @@ import java.io.*; import java.text.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosIgniteUI extends AltosDialog @@ -304,7 +305,7 @@ public class AltosIgniteUI private boolean open() { command_queue = new LinkedBlockingQueue(); - device = AltosDeviceDialog.show(owner, Altos.product_any); + device = AltosDeviceUIDialog.show(owner, Altos.product_any); if (device != null) { IgniteHandler handler = new IgniteHandler(owner); Thread t = new Thread(handler); diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java index de19221e..0bad80aa 100644 --- a/altosui/AltosLaunch.java +++ b/altosui/AltosLaunch.java @@ -20,6 +20,7 @@ package altosui; import java.io.*; import java.util.concurrent.*; import java.awt.*; +import org.altusmetrum.altosuilib.*; public class AltosLaunch { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 39b986c0..68c978dc 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -23,6 +23,7 @@ import javax.swing.*; import java.io.*; import java.text.*; import java.util.concurrent.*; +import org.altusmetrum.altosuilib.*; class FireButton extends JButton { protected void processMouseEvent(MouseEvent e) { @@ -370,7 +371,7 @@ public class AltosLaunchUI private boolean open() { command_queue = new LinkedBlockingQueue(); - device = AltosDeviceDialog.show(owner, Altos.product_any); + device = AltosDeviceUIDialog.show(owner, Altos.product_any); if (device != null) { LaunchHandler handler = new LaunchHandler(owner); Thread t = new Thread(handler); diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 2a6e140a..6a8db0e0 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -26,6 +26,7 @@ import java.util.*; import java.text.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; class AltosScanResult { String callsign; @@ -327,7 +328,7 @@ public class AltosScanUI } private boolean open() { - device = AltosDeviceDialog.show(owner, Altos.product_basestation); + device = AltosDeviceUIDialog.show(owner, Altos.product_basestation); if (device == null) return false; try { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 771fdd5d..78d862d0 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -26,6 +26,7 @@ import java.util.*; import java.awt.*; import javax.swing.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; import libaltosJNI.*; diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java index 7380f331..932a3684 100644 --- a/altosui/AltosSerialInUseException.java +++ b/altosui/AltosSerialInUseException.java @@ -16,6 +16,7 @@ */ package altosui; +import org.altusmetrum.altosuilib.*; public class AltosSerialInUseException extends Exception { public AltosDevice device; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index dcc0de60..a385b8b3 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -23,6 +23,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosUI extends AltosFrame { public AltosVoice voice = new AltosVoice(); @@ -241,7 +242,7 @@ public class AltosUI extends AltosFrame { } private void ConnectToDevice() { - AltosDevice device = AltosDeviceDialog.show(AltosUI.this, + AltosDevice device = AltosDeviceUIDialog.show(AltosUI.this, Altos.product_basestation); if (device != null) diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index 3af7a7fa..5c6a8976 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -18,6 +18,7 @@ package altosui; import java.util.*; import libaltosJNI.*; +import org.altusmetrum.altosuilib.*; public class AltosUSBDevice extends altos_device implements AltosDevice { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index b3aa1f55..593eeb0a 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -32,8 +32,7 @@ altosui_JAVA = \ AltosCSVUI.java \ AltosDebug.java \ AltosDescent.java \ - AltosDeviceDialog.java \ - AltosDevice.java \ + AltosDeviceUIDialog.java \ AltosUSBDevice.java \ AltosDisplayThread.java \ AltosEepromDelete.java \ diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 82620b8b..cde545a7 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -27,22 +27,24 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL private JList list; private JButton cancel_button; private JButton select_button; - private JButton manage_bluetooth_button; - private Frame frame; - private int product; - + public Frame frame; + public int product; + public JPanel buttonPane; + public AltosDevice getValue() { return value; } public abstract AltosDevice[] devices(); - private void update_devices() { + public void update_devices() { AltosDevice[] devices = devices(); list.setListData(devices); select_button.setEnabled(devices.length > 0); } + public void add_bluetooth() { } + public AltosDeviceDialog (Frame in_frame, Component location, int in_product) { super(in_frame, "Device Selection", true); @@ -56,10 +58,6 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL cancel_button.setActionCommand("cancel"); cancel_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"); select_button.addActionListener(this); @@ -126,14 +124,15 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); //Lay out the buttons from left to right. - JPanel buttonPane = new JPanel(); + buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); -// buttonPane.add(manage_bluetooth_button); -// buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + + add_bluetooth(); + buttonPane.add(select_button); //Put everything together, using the content pane's BorderLayout. @@ -150,14 +149,12 @@ public abstract class AltosDeviceDialog extends AltosUIDialog implements ActionL //Handle clicks on the Set and Cancel buttons. public void actionPerformed(ActionEvent e) { - if ("select".equals(e.getActionCommand())) + if ("select".equals(e.getActionCommand())) { value = (AltosDevice)(list.getSelectedValue()); -// if ("manage".equals(e.getActionCommand())) { -// AltosBTManage.show(frame, AltosBTKnown.bt_known()); -// update_devices(); -// return; -// } - setVisible(false); + setVisible(false); + } + if ("cancel".equals(e.getActionCommand())) + setVisible(false); } } -- cgit v1.2.3 From ae09bd641a86970763380f3028f987ffcb791020 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:33:36 -0800 Subject: altosui: Use shared AltosFontListener class Signed-off-by: Keith Packard --- altosui/AltosFlightUI.java | 1 + altosui/AltosFontListener.java | 22 ---------------------- altosui/AltosUIPreferences.java | 1 + altosui/Makefile.am | 1 - 4 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 altosui/AltosFontListener.java diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 43df705e..604ea658 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -22,6 +22,7 @@ import java.awt.event.*; import javax.swing.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; diff --git a/altosui/AltosFontListener.java b/altosui/AltosFontListener.java deleted file mode 100644 index 0dda0f29..00000000 --- a/altosui/AltosFontListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -public interface AltosFontListener { - void font_size_changed(int font_size); -} diff --git a/altosui/AltosUIPreferences.java b/altosui/AltosUIPreferences.java index f6ee7e06..9c56d031 100644 --- a/altosui/AltosUIPreferences.java +++ b/altosui/AltosUIPreferences.java @@ -22,6 +22,7 @@ import java.util.*; import java.awt.Component; import javax.swing.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosUIPreferences extends AltosPreferences { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 593eeb0a..1bd98c1c 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -50,7 +50,6 @@ altosui_JAVA = \ AltosFlightStatus.java \ AltosFlightStatusUpdate.java \ AltosFlightUI.java \ - AltosFontListener.java \ AltosFreqList.java \ AltosHexfile.java \ Altos.java \ -- cgit v1.2.3 From f0bbd3e2571336b5f5872759b5010148325efbaa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:40:13 -0800 Subject: altosui: Use shared AltosUIFrame and AltosUIDialog Signed-off-by: Keith Packard --- altosui/AltosBTManage.java | 3 +- altosui/AltosCSVUI.java | 3 +- altosui/AltosConfigFreqUI.java | 5 +-- altosui/AltosConfigPyroUI.java | 3 +- altosui/AltosConfigTDUI.java | 3 +- altosui/AltosConfigUI.java | 3 +- altosui/AltosDialog.java | 59 --------------------------------- altosui/AltosEepromMonitor.java | 3 +- altosui/AltosEepromSelect.java | 3 +- altosui/AltosFlashUI.java | 2 +- altosui/AltosFlightUI.java | 2 +- altosui/AltosFrame.java | 71 ---------------------------------------- altosui/AltosGraphUI.java | 3 +- altosui/AltosIdleMonitorUI.java | 2 +- altosui/AltosIgniteUI.java | 2 +- altosui/AltosLaunchUI.java | 2 +- altosui/AltosRomconfigUI.java | 3 +- altosui/AltosScanUI.java | 2 +- altosui/AltosSiteMapPreload.java | 3 +- altosui/AltosUI.java | 2 +- altosui/Makefile.am | 4 +-- 21 files changed, 31 insertions(+), 152 deletions(-) delete mode 100644 altosui/AltosDialog.java delete mode 100644 altosui/AltosFrame.java diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 9a28d72b..b7b632a7 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -23,8 +23,9 @@ import javax.swing.*; import javax.swing.plaf.basic.*; import java.util.*; import java.util.concurrent.*; +import org.altusmetrum.altosuilib.*; -public class AltosBTManage extends AltosDialog implements ActionListener, Iterable { +public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; Frame frame; LinkedList listeners; diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index 1d024086..83bf16a7 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -22,9 +22,10 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosCSVUI - extends AltosDialog + extends AltosUIDialog implements ActionListener { JFileChooser csv_chooser; diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index 918748f7..75101e3d 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -22,8 +22,9 @@ import java.awt.event.*; import javax.swing.*; import java.util.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; -class AltosEditFreqUI extends AltosDialog implements ActionListener { +class AltosEditFreqUI extends AltosUIDialog implements ActionListener { Frame frame; JTextField frequency; JTextField description; @@ -158,7 +159,7 @@ class AltosEditFreqUI extends AltosDialog implements ActionListener { } } -public class AltosConfigFreqUI extends AltosDialog implements ActionListener { +public class AltosConfigFreqUI extends AltosUIDialog implements ActionListener { Frame frame; LinkedList listeners; diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index 17adb15f..5cdaf564 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -22,9 +22,10 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosConfigPyroUI - extends AltosDialog + extends AltosUIDialog implements ItemListener, DocumentListener { AltosConfigUI owner; diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 532a49fa..54073843 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -22,9 +22,10 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosConfigTDUI - extends AltosDialog + extends AltosUIDialog implements ActionListener, ItemListener, DocumentListener { diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 95780e2b..599ed051 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -22,9 +22,10 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; public class AltosConfigUI - extends AltosDialog + extends AltosUIDialog implements ActionListener, ItemListener, DocumentListener, AltosConfigValues { diff --git a/altosui/AltosDialog.java b/altosui/AltosDialog.java deleted file mode 100644 index c2a9d6e6..00000000 --- a/altosui/AltosDialog.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -class AltosDialogListener extends WindowAdapter { - public void windowClosing (WindowEvent e) { - AltosUIPreferences.unregister_ui_listener((AltosDialog) e.getWindow()); - } -} - -public class AltosDialog extends JDialog implements AltosUIListener { - - public void ui_changed(String look_and_feel) { - SwingUtilities.updateComponentTreeUI(this); - this.pack(); - } - - public AltosDialog() { - AltosUIPreferences.register_ui_listener(this); - addWindowListener(new AltosDialogListener()); - } - - public AltosDialog(Frame frame, String label, boolean modal) { - super(frame, label, modal); - AltosUIPreferences.register_ui_listener(this); - addWindowListener(new AltosDialogListener()); - } - - public AltosDialog(Dialog dialog, String label, boolean modal) { - super(dialog, label, modal); - AltosUIPreferences.register_ui_listener(this); - addWindowListener(new AltosDialogListener()); - } - - public AltosDialog(Frame frame, boolean modal) { - super(frame, modal); - AltosUIPreferences.register_ui_listener(this); - addWindowListener(new AltosDialogListener()); - } -} diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index 251344e9..8eae5eb8 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -20,8 +20,9 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; +import org.altusmetrum.altosuilib.*; -public class AltosEepromMonitor extends AltosDialog { +public class AltosEepromMonitor extends AltosUIDialog { Container pane; Box box; diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index d8b8693d..c0886212 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -22,6 +22,7 @@ import javax.swing.border.*; import java.awt.*; import java.awt.event.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; class AltosEepromItem implements ActionListener { AltosEepromLog log; @@ -50,7 +51,7 @@ class AltosEepromItem implements ActionListener { } } -public class AltosEepromSelect extends AltosDialog implements ActionListener { +public class AltosEepromSelect extends AltosUIDialog implements ActionListener { //private JList list; private JFrame frame; JButton ok; diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 878150f6..921207bc 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -26,7 +26,7 @@ import java.util.concurrent.*; import org.altusmetrum.altosuilib.*; public class AltosFlashUI - extends AltosDialog + extends AltosUIDialog implements ActionListener { Container pane; diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 604ea658..e2dc06bd 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -24,7 +24,7 @@ import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; import org.altusmetrum.altosuilib.*; -public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { +public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; AltosFlightReader reader; AltosDisplayThread thread; diff --git a/altosui/AltosFrame.java b/altosui/AltosFrame.java deleted file mode 100644 index 731a29b4..00000000 --- a/altosui/AltosFrame.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import java.util.*; - -class AltosFrameListener extends WindowAdapter { - public void windowClosing (WindowEvent e) { - AltosUIPreferences.unregister_ui_listener((AltosFrame) e.getWindow()); - } -} - -public class AltosFrame extends JFrame implements AltosUIListener { - - public void ui_changed(String look_and_feel) { - SwingUtilities.updateComponentTreeUI(this); - this.pack(); - } - - static final String[] icon_names = { - "/altus-metrum-16.png", - "/altus-metrum-32.png", - "/altus-metrum-48.png", - "/altus-metrum-64.png", - "/altus-metrum-128.png", - "/altus-metrum-256.png" - }; - - public void set_icon() { - ArrayList icons = new ArrayList(); - - for (int i = 0; i < icon_names.length; i++) { - java.net.URL imgURL = AltosUI.class.getResource(icon_names[i]); - if (imgURL != null) - icons.add(new ImageIcon(imgURL).getImage()); - } - - setIconImages(icons); - } - - public AltosFrame() { - AltosUIPreferences.register_ui_listener(this); - addWindowListener(new AltosFrameListener()); - set_icon(); - } - - public AltosFrame(String name) { - super(name); - AltosUIPreferences.register_ui_listener(this); - addWindowListener(new AltosFrameListener()); - set_icon(); - } -} diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index b7c2e92e..d6891ffa 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -10,12 +10,13 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.ui.RefineryUtilities; -public class AltosGraphUI extends AltosFrame +public class AltosGraphUI extends AltosUIFrame { JTabbedPane pane; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 6d3450b6..1b3dd547 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -25,7 +25,7 @@ import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; import org.altusmetrum.altosuilib.*; -public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener { +public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener { AltosDevice device; JTabbedPane pane; AltosPad pad; diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index f1742203..c1378eb9 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -27,7 +27,7 @@ import org.altusmetrum.AltosLib.*; import org.altusmetrum.altosuilib.*; public class AltosIgniteUI - extends AltosDialog + extends AltosUIDialog implements ActionListener { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 68c978dc..7e7ed010 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -46,7 +46,7 @@ class FireButton extends JButton { } public class AltosLaunchUI - extends AltosDialog + extends AltosUIDialog implements ActionListener { AltosDevice device; diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java index d4a5ef6d..5fc786e2 100644 --- a/altosui/AltosRomconfigUI.java +++ b/altosui/AltosRomconfigUI.java @@ -20,9 +20,10 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; +import org.altusmetrum.altosuilib.*; public class AltosRomconfigUI - extends AltosDialog + extends AltosUIDialog implements ActionListener { Container pane; diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 6a8db0e0..14b52310 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -122,7 +122,7 @@ class AltosScanResults extends LinkedList implements ListModel } public class AltosScanUI - extends AltosDialog + extends AltosUIDialog implements ActionListener { AltosUI owner; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 33849c66..f4dcc903 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -26,6 +26,7 @@ import java.text.*; import java.lang.Math; import java.net.URL; import java.net.URLConnection; +import org.altusmetrum.altosuilib.*; class AltosMapPos extends Box { AltosUI owner; @@ -205,7 +206,7 @@ class AltosSites extends Thread { } } -public class AltosSiteMapPreload extends AltosDialog implements ActionListener, ItemListener { +public class AltosSiteMapPreload extends AltosUIDialog implements ActionListener, ItemListener { AltosUI owner; AltosSiteMap map; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index a385b8b3..70142a93 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -25,7 +25,7 @@ import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; import org.altusmetrum.altosuilib.*; -public class AltosUI extends AltosFrame { +public class AltosUI extends AltosUIFrame { public AltosVoice voice = new AltosVoice(); public static boolean load_library(Frame frame) { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 1bd98c1c..368233d1 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -6,7 +6,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="./*:$(JAVAROOT):../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):./*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" bin_SCRIPTS=altosui @@ -76,8 +76,6 @@ altosui_JAVA = \ AltosSiteMapTile.java \ AltosUI.java \ AltosUIListener.java \ - AltosFrame.java \ - AltosDialog.java \ AltosWriter.java \ AltosDataPointReader.java \ AltosDataPoint.java \ -- cgit v1.2.3 From dc404bee7163a369eb1d95e0942b676bd3f95574 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:41:42 -0800 Subject: altosui: Use shared AltosUIListener Signed-off-by: Keith Packard --- altosui/AltosUIListener.java | 22 ---------------------- altosui/Makefile.am | 1 - 2 files changed, 23 deletions(-) delete mode 100644 altosui/AltosUIListener.java diff --git a/altosui/AltosUIListener.java b/altosui/AltosUIListener.java deleted file mode 100644 index 7ee62afc..00000000 --- a/altosui/AltosUIListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; - -public interface AltosUIListener { - public void ui_changed(String look_and_feel); -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 368233d1..b97222de 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -75,7 +75,6 @@ altosui_JAVA = \ AltosSiteMapCache.java \ AltosSiteMapTile.java \ AltosUI.java \ - AltosUIListener.java \ AltosWriter.java \ AltosDataPointReader.java \ AltosDataPoint.java \ -- cgit v1.2.3 From eb670e9b7576563d747ae5c9416371f145455ec1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 09:50:09 -0800 Subject: altosui: Remove duplicate AltosUSBDevice Signed-off-by: Keith Packard --- altosui/AltosUSBDevice.java | 112 ----------------------------------------- altosui/Makefile.am | 1 - altosuilib/AltosUSBDevice.java | 4 +- 3 files changed, 2 insertions(+), 115 deletions(-) delete mode 100644 altosui/AltosUSBDevice.java diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java deleted file mode 100644 index 5c6a8976..00000000 --- a/altosui/AltosUSBDevice.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; -import java.util.*; -import libaltosJNI.*; -import org.altusmetrum.altosuilib.*; - -public class AltosUSBDevice extends altos_device implements AltosDevice { - - public String toString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; - return String.format("%-20.20s %4d %s", - name, getSerial(), getPath()); - } - - public String toShortString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; - return String.format("%s %d %s", - name, getSerial(), getPath()); - - } - - 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); - } - - private boolean isAltusMetrum() { - if (getVendor() != Altos.vendor_altusmetrum) - return false; - if (getProduct() < Altos.product_altusmetrum_min) - return false; - if (getProduct() > Altos.product_altusmetrum_max) - return false; - return true; - } - - public boolean matchProduct(int want_product) { - - if (!isAltusMetrum()) - return false; - - if (want_product == Altos.product_any) - return true; - - if (want_product == Altos.product_basestation) - return matchProduct(Altos.product_teledongle) || - matchProduct(Altos.product_teleterra) || - matchProduct(Altos.product_telebt) || - matchProduct(Altos.product_megadongle); - - if (want_product == Altos.product_altimeter) - return matchProduct(Altos.product_telemetrum) || - matchProduct(Altos.product_megametrum); - - int have_product = getProduct(); - - if (have_product == Altos.product_altusmetrum) /* old devices match any request */ - return true; - - if (want_product == have_product) - return true; - - return false; - } - - static java.util.List list(int product) { - if (!Altos.load_library()) - return null; - - SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - - ArrayList device_list = new ArrayList(); - if (list != null) { - for (;;) { - AltosUSBDevice device = new AltosUSBDevice(); - if (libaltos.altos_list_next(list, device) == 0) - break; - if (device.matchProduct(product)) - device_list.add(device); - } - libaltos.altos_list_finish(list); - } - - return device_list; - } -} \ No newline at end of file diff --git a/altosui/Makefile.am b/altosui/Makefile.am index b97222de..539e14f6 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -33,7 +33,6 @@ altosui_JAVA = \ AltosDebug.java \ AltosDescent.java \ AltosDeviceUIDialog.java \ - AltosUSBDevice.java \ AltosDisplayThread.java \ AltosEepromDelete.java \ AltosEepromDownload.java \ diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 2f4e0dc6..bab16fb0 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -50,7 +50,7 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return libaltos.altos_open(this); } - private boolean isAltusMetrum() { + public boolean isAltusMetrum() { if (getVendor() != AltosUILib.vendor_altusmetrum) return false; if (getProduct() < AltosUILib.product_altusmetrum_min) @@ -89,7 +89,7 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return false; } - static java.util.List list(int product) { + static public java.util.List list(int product) { if (!AltosUILib.load_library()) return null; -- cgit v1.2.3 From 0933f2ed5791cfdc28242cd60be3942556f4ed20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 10:48:56 -0800 Subject: altoslib: Remove unused fake product_micropeak_serial Code cleanups have made this no longer useful Signed-off-by: Keith Packard --- altoslib/AltosLib.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 67138450..07516aeb 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -97,7 +97,6 @@ public class AltosLib { public final static int product_any = 0x10000; public final static int product_basestation = 0x10000 + 1; public final static int product_altimeter = 0x10000 + 2; - public final static int product_micropeak_serial = 0x10000 + 3; /* Bluetooth "identifier" (bluetooth sucks) */ public final static String bt_product_telebt = "TeleBT"; -- cgit v1.2.3 From 93d640de65a1ecedfef89c96521c21632f96f372 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 11:22:11 -0800 Subject: micropoint: Add MicroDataPoint This holds height/speed/accel data all in one place Signed-off-by: Keith Packard --- micropeak/Makefile.am | 1 + micropeak/MicroData.java | 77 +++++++------------------------------------ micropeak/MicroDataPoint.java | 39 ++++++++++++++++++++++ micropeak/MicroGraph.java | 9 +++-- micropeak/MicroStats.java | 68 +++++++++++++------------------------- 5 files changed, 78 insertions(+), 116 deletions(-) create mode 100644 micropeak/MicroDataPoint.java diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 2dd9c69c..26431bd5 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -10,6 +10,7 @@ micropeakdir=$(datadir)/java micropeak_JAVA= \ MicroPeak.java \ MicroData.java \ + MicroDataPoint.java \ MicroDownload.java \ MicroFrame.java \ MicroGraph.java \ diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 8ccd5fd8..2afd3cd7 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -22,7 +22,7 @@ import java.io.*; import java.util.*; import org.altusmetrum.AltosLib.*; -abstract class MicroIterator implements Iterator { +class MicroIterator implements Iterator { int i; MicroData data; @@ -30,6 +30,10 @@ abstract class MicroIterator implements Iterator { return i < data.pressures.length; } + public MicroDataPoint next() { + return new MicroDataPoint(data, i++); + } + public MicroIterator (MicroData data) { this.data = data; i = 0; @@ -39,66 +43,15 @@ abstract class MicroIterator implements Iterator { } } -class MicroHeightIterator extends MicroIterator { - public Double next() { - return data.height(i++); - } - - public MicroHeightIterator(MicroData data) { - super(data); - } -} - -class MicroHeightIterable implements Iterable { - MicroData data; - - public Iterator iterator() { - return new MicroHeightIterator(data); - } - - public MicroHeightIterable(MicroData data) { - this.data = data; - } -} - -class MicroSpeedIterator extends MicroIterator { - public Double next() { - return data.speed(i++); - } - public MicroSpeedIterator(MicroData data) { - super(data); - } -} - -class MicroSpeedIterable implements Iterable { - MicroData data; - - public Iterator iterator() { - return new MicroSpeedIterator(data); - } - - public MicroSpeedIterable(MicroData data) { - this.data = data; - } -} +class MicroIterable implements Iterable { -class MicroAccelIterator extends MicroIterator { - public Double next() { - return data.acceleration(i++); - } - public MicroAccelIterator(MicroData data) { - super(data); - } -} - -class MicroAccelIterable implements Iterable { MicroData data; - public Iterator iterator() { - return new MicroAccelIterator(data); + public Iterator iterator() { + return new MicroIterator(data); } - public MicroAccelIterable(MicroData data) { + public MicroIterable(MicroData data) { this.data = data; } } @@ -225,16 +178,8 @@ public class MicroData { return AltosConvert.pressure_to_altitude(pressures[i]); } - public Iterable heights() { - return new MicroHeightIterable(this); - } - - public Iterable speeds() { - return new MicroSpeedIterable(this); - } - - public Iterable accels() { - return new MicroAccelIterable(this); + public Iterable points() { + return new MicroIterable(this); } int fact(int n) { diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java new file mode 100644 index 00000000..3fd1e641 --- /dev/null +++ b/micropeak/MicroDataPoint.java @@ -0,0 +1,39 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +public class MicroDataPoint { + public double time; + public double height; + public double speed; + public double accel; + + public MicroDataPoint (double height, double speed, double accel, double time) { + this.height = height; + this.speed = speed; + this.accel = accel; + this.time = time; + } + + public MicroDataPoint(MicroData data, int i) { + this(data.height(i), + data.speed(i), + data.acceleration(i), + data.time(i)); + } +} \ No newline at end of file diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index c5580634..8330a67b 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -106,11 +106,10 @@ public class MicroGraph implements AltosUnitsListener { heightSeries.clear(); speedSeries.clear(); accelSeries.clear(); - for (int i = 0; i < data.pressures.length; i++) { - double x = data.time(i); - heightSeries.add(x, AltosConvert.height.value(data.height(i))); - speedSeries.add(x, AltosConvert.speed.value(data.speed(i))); - accelSeries.add(x, AltosConvert.accel.value(data.acceleration(i))); + for (MicroDataPoint point : data.points()) { + heightSeries.add(point.time, AltosConvert.height.value(point.height)); + speedSeries.add(point.time, AltosConvert.speed.value(point.speed)); + accelSeries.add(point.time, AltosConvert.accel.value(point.accel)); } } diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java index 6ae8a2b2..056fac7d 100644 --- a/micropeak/MicroStats.java +++ b/micropeak/MicroStats.java @@ -39,25 +39,21 @@ public class MicroStats { void find_landing() { landed_height = 0; - int t = 0; - for (double height : data.heights()) { - landed_height = height; - t++; + for (MicroDataPoint point : data.points()) { + landed_height = point.height; + landed_time = point.time; } - landed_time = data.time(t); - t = 0; boolean above = false; - for (double height : data.heights()) { - if (height > landed_height + 10) { + for (MicroDataPoint point : data.points()) { + if (point.height > landed_height + 10) { above = true; } else { - if (above && height < landed_height + 2) { + if (above && point.height < landed_height + 2) { above = false; - landed_time = data.time(t); + landed_time = point.time; } } - t++; } } @@ -65,13 +61,11 @@ public class MicroStats { apogee_height = 0; apogee_time = 0; - int t = 0; - for (double height : data.heights()) { - if (height > apogee_height) { - apogee_height = height; - apogee_time = data.time(t); + for (MicroDataPoint point : data.points()) { + if (point.height > apogee_height) { + apogee_height = point.height; + apogee_time = point.time; } - t++; } } @@ -79,47 +73,31 @@ public class MicroStats { coast_height = 0; coast_time = 0; - int t = 0; - for (double accel : data.accels()) { - if (accel < -9.8) + for (MicroDataPoint point : data.points()) { + if (point.accel < -9.8) break; - t++; - } - coast_time = data.time(t); - - int coast_t = t; - t = 0; - for (double height : data.heights()) { - if (t >= coast_t) { - coast_height = height; - break; - } - t++; + coast_time = point.time; + coast_height = point.height; } } void find_max_speed() { max_speed = 0; - int t = 0; - for (double speed : data.speeds()) { - if (data.time(t) > apogee_time) + for (MicroDataPoint point : data.points()) { + if (point.time > apogee_time) break; - if (speed > max_speed) - max_speed = speed; - t++; + if (point.speed > max_speed) + max_speed = point.speed; } } void find_max_accel() { max_accel = 0; - - int t = 0; - for (double accel : data.accels()) { - if (data.time(t) > apogee_time) + for (MicroDataPoint point : data.points()) { + if (point.time > apogee_time) break; - if (accel > max_accel) - max_accel = accel; - t++; + if (point.accel > max_accel) + max_accel = point.accel; } } -- cgit v1.2.3 From 2c423d9287c6b9ea7233f5e3430682cb1c865da1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 11:44:32 -0800 Subject: micropeak: Add CSV export Signed-off-by: Keith Packard --- micropeak/Makefile.am | 1 + micropeak/MicroData.java | 4 ++ micropeak/MicroDataPoint.java | 7 ++- micropeak/MicroExport.java | 106 ++++++++++++++++++++++++++++++++++++++++++ micropeak/MicroPeak.java | 22 ++++++++- 5 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 micropeak/MicroExport.java diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 26431bd5..f5f8ccd9 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -12,6 +12,7 @@ micropeak_JAVA= \ MicroData.java \ MicroDataPoint.java \ MicroDownload.java \ + MicroExport.java \ MicroFrame.java \ MicroGraph.java \ MicroSave.java \ diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 2afd3cd7..836d3c35 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -221,6 +221,10 @@ public class MicroData { return alt; } + public double pressure(int i) { + return pressures[i]; + } + public double height(int i) { return altitude(i) - ground_altitude; } diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java index 3fd1e641..c58708e6 100644 --- a/micropeak/MicroDataPoint.java +++ b/micropeak/MicroDataPoint.java @@ -19,11 +19,13 @@ package org.altusmetrum.micropeak; public class MicroDataPoint { public double time; + public double pressure; public double height; public double speed; public double accel; - public MicroDataPoint (double height, double speed, double accel, double time) { + public MicroDataPoint (double pressure, double height, double speed, double accel, double time) { + this.pressure = pressure; this.height = height; this.speed = speed; this.accel = accel; @@ -31,7 +33,8 @@ public class MicroDataPoint { } public MicroDataPoint(MicroData data, int i) { - this(data.height(i), + this(data.pressure(i), + data.height(i), data.speed(i), data.acceleration(i), data.time(i)); diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java new file mode 100644 index 00000000..06a03469 --- /dev/null +++ b/micropeak/MicroExport.java @@ -0,0 +1,106 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroExport extends JFileChooser { + + JFrame frame; + MicroData data; + + public boolean runDialog() { + int ret; + + setSelectedFile(new File(AltosLib.replace_extension(data.name, ".csv"))); + for (;;) { + ret = showSaveDialog(frame); + if (ret != APPROVE_OPTION) + return false; + File file; + String filename; + file = getSelectedFile(); + if (file == null) + continue; + if (!file.getName().contains(".")) { + String fullname = file.getPath(); + file = new File(fullname.concat(".csv")); + } + filename = file.getName(); + if (file.exists()) { + if (file.isDirectory()) { + JOptionPane.showMessageDialog(frame, + String.format("\"%s\" is a directory", + filename), + "Directory", + JOptionPane.ERROR_MESSAGE); + continue; + } + int r = JOptionPane.showConfirmDialog(frame, + String.format("\"%s\" already exists. Overwrite?", + filename), + "Overwrite file?", + JOptionPane.YES_NO_OPTION); + if (r != JOptionPane.YES_OPTION) + continue; + + if (!file.canWrite()) { + JOptionPane.showMessageDialog(frame, + String.format("\"%s\" is not writable", + filename), + "File not writable", + JOptionPane.ERROR_MESSAGE); + continue; + } + } + try { + FileWriter fw = new FileWriter(file); + PrintWriter pw = new PrintWriter(fw); + pw.printf(" Time, Press, Height, Speed, Accel\n"); + for (MicroDataPoint point : data.points()) { + pw.printf("%5.2f,%6.0f,%7.1f,%7.2f,%7.2f\n", + point.time, point.pressure, point.height, point.speed, point.accel); + } + fw.close(); + return true; + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + fe.getMessage(), + "Cannot create file", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ioe) { + } + } + } + + public MicroExport(JFrame frame, MicroData data) { + this.frame = frame; + this.data = data; + setDialogTitle("Export MicroPeak Data File"); + setFileFilter(new FileNameExtensionFilter("MicroPeak CSV file", + "csv")); + setCurrentDirectory(AltosUIPreferences.logdir()); + } +} diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 544f3ae0..f2f09a10 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -101,12 +101,15 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene new MicroDownload(this, device); } - private void Save() { - if (data == null) { + private void no_data() { JOptionPane.showMessageDialog(this, "No data available", "No data", JOptionPane.INFORMATION_MESSAGE); + } + private void Save() { + if (data == null) { + no_data(); return; } MicroSave save = new MicroSave (this, data); @@ -114,6 +117,15 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene SetName(data.name); } + private void Export() { + if (data == null) { + no_data(); + return; + } + MicroExport export = new MicroExport (this, data); + export.runDialog(); + } + private void Close() { setVisible(false); dispose(); @@ -131,6 +143,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene SelectFile(); else if ("Download".equals(ev.getActionCommand())) DownloadData(); + else if ("Export".equals(ev.getActionCommand())) + Export(); else if ("Preferences".equals(ev.getActionCommand())) Preferences(); else if ("Save a Copy".equals(ev.getActionCommand())) @@ -169,6 +183,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene fileMenu.add(saveAction); saveAction.addActionListener(this); + JMenuItem exportAction = new JMenuItem("Export"); + fileMenu.add(exportAction); + exportAction.addActionListener(this); + JMenuItem preferencesAction = new JMenuItem("Preferences"); fileMenu.add(preferencesAction); preferencesAction.addActionListener(this); -- cgit v1.2.3 From 31fa139578a86821844e3e2efb1a84bdea4f1370 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 12:24:44 -0800 Subject: micropeak: Add view of raw data in GUI Looks just like the export file Signed-off-by: Keith Packard --- micropeak/Makefile.am | 1 + micropeak/MicroExport.java | 4 ++-- micropeak/MicroPeak.java | 4 ++++ micropeak/MicroRaw.java | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 micropeak/MicroRaw.java diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index f5f8ccd9..89ff2fb3 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -15,6 +15,7 @@ micropeak_JAVA= \ MicroExport.java \ MicroFrame.java \ MicroGraph.java \ + MicroRaw.java \ MicroSave.java \ MicroSerial.java \ MicroStats.java \ diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java index 06a03469..219184da 100644 --- a/micropeak/MicroExport.java +++ b/micropeak/MicroExport.java @@ -78,9 +78,9 @@ public class MicroExport extends JFileChooser { try { FileWriter fw = new FileWriter(file); PrintWriter pw = new PrintWriter(fw); - pw.printf(" Time, Press, Height, Speed, Accel\n"); + pw.printf(" Time, Press, Height, Speed, Accel\n"); for (MicroDataPoint point : data.points()) { - pw.printf("%5.2f,%6.0f,%7.1f,%7.2f,%7.2f\n", + pw.printf("%6.3f,%6.0f,%7.1f,%7.2f,%7.2f\n", point.time, point.pressure, point.height, point.speed, point.accel); } fw.close(); diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index f2f09a10..290511e7 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -31,6 +31,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene File filename; MicroGraph graph; MicroStatsTable stats; + MicroRaw raw; MicroData data; Container container; JTabbedPane pane; @@ -45,6 +46,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene this.data = data; graph.setData(data); stats.setData(data); + raw.setData(data); setTitle(data.name); return this; } @@ -209,8 +211,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene graph = new MicroGraph(); stats = new MicroStatsTable(); + raw = new MicroRaw(); pane.add(graph.panel, "Graph"); pane.add(stats, "Statistics"); + pane.add(raw, "Raw Data"); pane.doLayout(); pane.validate(); container.add(pane); diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java new file mode 100644 index 00000000..6b006f32 --- /dev/null +++ b/micropeak/MicroRaw.java @@ -0,0 +1,41 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroRaw extends TextArea { + + public void setData(MicroData data) { + setRows(data.pressures.length); + setText(" Time, Press, Height, Speed, Accel\n"); + for (MicroDataPoint point : data.points()) { + append(String.format( + "%6.3f,%6.0f,%7.1f,%7.2f,%7.2f\n", + point.time, point.pressure, point.height, point.speed, point.accel)); + } + } + + public MicroRaw() { + super(1, 30); + setFont(AltosUILib.table_value_font); + } +} -- cgit v1.2.3 From 1979063928f1cdfc75c01ec098164c2822a5138d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 16:07:49 -0800 Subject: altosuilib: Fix install issues on Linux altosuilib.jar wasn't getting installed micropeak was using the wrong name Signed-off-by: Keith Packard --- altosuilib/Makefile.am | 6 +++--- micropeak/Makefile.am | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index d4aa0116..da5fb848 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -30,11 +30,11 @@ all-local: $(JAR) clean-local: -rm -rf $(JAVAROOT) $(JAR) -install-altosuilibjava: $(JAR) +install-altosuilibJAVA: $(JAR) @$(NORMAL_INSTALL) test -z "$(altosuilibdir)" || $(MKDIR_P) "$(DESTDIR)$(altosuilibdir)" - echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuilibdir)/$(JAR)"; \ - $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuilibdir)" + echo " $(INSTALL_DATA)" "$(JAR)" "'$(DESTDIR)$(altosuilibdir)/$(JAR)"; \ + $(INSTALL_DATA) "$(JAR)" "$(DESTDIR)$(altosuilibdir)" $(JAVAROOT): mkdir -p $(JAVAROOT) diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 89ff2fb3..c452db97 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -44,7 +44,7 @@ ALTOSLIB_CLASS=\ AltosLib.jar ALTOSUILIB_CLASS=\ - AltosUILib.jar + altosuilib.jar # Icons ICONDIR=$(top_srcdir)/icon @@ -221,9 +221,9 @@ $(WINDOWS_DIST): $(WINDOWS_FILES) micropeak-windows.nsi Manifest.txt: Makefile echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ - echo "Class-Path: AltosLib.jar AltosUILib.jar $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ + echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(JCOMMON)/jcommon.jar $(JFREECHART)/jfreechart.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: org.altusmetrum.micropeak.MicroPeak' > $@ - echo "Class-Path: AltosLib.jar AltosUILib.jar jcommon.jar jfreechart.jar" >> $@ + echo "Class-Path: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) jcommon.jar jfreechart.jar" >> $@ -- cgit v1.2.3 From 9e4c5b0a6ed3594cff6ab71398c172daa7c67177 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 16:19:33 -0800 Subject: micropeak: Use JTextArea instead of TextArea Looks nicer and doesn't appear to have the same weird clipping problem Signed-off-by: Keith Packard --- micropeak/MicroGraph.java | 23 ++++++++++++----------- micropeak/MicroPeak.java | 3 ++- micropeak/MicroRaw.java | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index 8330a67b..d2e86f9f 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -106,10 +106,12 @@ public class MicroGraph implements AltosUnitsListener { heightSeries.clear(); speedSeries.clear(); accelSeries.clear(); - for (MicroDataPoint point : data.points()) { - heightSeries.add(point.time, AltosConvert.height.value(point.height)); - speedSeries.add(point.time, AltosConvert.speed.value(point.speed)); - accelSeries.add(point.time, AltosConvert.accel.value(point.accel)); + if (data != null) { + for (MicroDataPoint point : data.points()) { + heightSeries.add(point.time, AltosConvert.height.value(point.height)); + speedSeries.add(point.time, AltosConvert.speed.value(point.speed)); + accelSeries.add(point.time, AltosConvert.accel.value(point.accel)); + } } } @@ -119,17 +121,16 @@ public class MicroGraph implements AltosUnitsListener { public void setData (MicroData data) { this.data = data; - chart.setTitle(data.name); + if (data != null) + setName(data.name); resetData(); } public void units_changed(boolean imperial_units) { - if (data != null) { - heightSeries.set_units(AltosConvert.height.show_units()); - speedSeries.set_units(AltosConvert.speed.show_units()); - accelSeries.set_units(AltosConvert.accel.show_units()); - resetData(); - } + heightSeries.set_units(AltosConvert.height.show_units()); + speedSeries.set_units(AltosConvert.speed.show_units()); + accelSeries.set_units(AltosConvert.accel.show_units()); + resetData(); } public MicroGraph() { diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 290511e7..d4252fa9 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -214,7 +214,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene raw = new MicroRaw(); pane.add(graph.panel, "Graph"); pane.add(stats, "Statistics"); - pane.add(raw, "Raw Data"); + JScrollPane scroll = new JScrollPane(raw); + pane.add(scroll, "Raw Data"); pane.doLayout(); pane.validate(); container.add(pane); diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index 6b006f32..f5bea76f 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -22,7 +22,7 @@ import javax.swing.*; import org.altusmetrum.AltosLib.*; import org.altusmetrum.altosuilib.*; -public class MicroRaw extends TextArea { +public class MicroRaw extends JTextArea { public void setData(MicroData data) { setRows(data.pressures.length); -- cgit v1.2.3 From 722dc277dee915dcd09d3d65c0ee19173b114ef7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 16:30:44 -0800 Subject: micropeak: Change graph tooltip units on the fly Make sure the tooltips show the right units when they change Signed-off-by: Keith Packard --- micropeak/MicroGraph.java | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index d2e86f9f..84320be3 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -39,15 +39,19 @@ class MicroSeries extends XYSeries { String label; String units; Color color; + XYItemRenderer renderer; - String label() { - return String.format("%s (%s)", label, units); - } - void set_units(String units) { this.units = units; - axis.setLabel(label()); + axis.setLabel(String.format("%s (%s)", label, units)); + + StandardXYToolTipGenerator ttg; + + ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", units), + new java.text.DecimalFormat("0.00"), + new java.text.DecimalFormat("0.00")); + renderer.setBaseToolTipGenerator(ttg); } public MicroSeries (String label, String units, Color color) { @@ -56,9 +60,13 @@ class MicroSeries extends XYSeries { this.units = units; this.color = color; - axis = new NumberAxis(label()); + axis = new NumberAxis(); axis.setLabelPaint(color); axis.setTickLabelPaint(color); + + renderer = new XYLineAndShapeRenderer(true, false); + renderer.setSeriesPaint(0, color); + set_units(units); } } @@ -88,16 +96,11 @@ public class MicroGraph implements AltosUnitsListener { private MicroSeries addSeries(int index, String label, String units, Color color) { MicroSeries series = new MicroSeries(label, units, color); XYSeriesCollection dataset = new XYSeriesCollection(series); - XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); - renderer.setSeriesPaint(0, color); - renderer.setPlot(plot); - renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", units), - new java.text.DecimalFormat("0.00"), - new java.text.DecimalFormat("0.00"))); + series.renderer.setPlot(plot); plot.setRangeAxis(index, series.axis); plot.setDataset(index, dataset); - plot.setRenderer(index, renderer); + plot.setRenderer(index, series.renderer); plot.mapDatasetToRangeAxis(index, index); return series; } -- cgit v1.2.3 From 36e9603f74b85776ac049758021b51909161aeb1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 3 Jan 2013 17:30:29 -0800 Subject: micropeak: Add Mac OS Info.plist file needed to build a Mac OS X application Signed-off-by: Keith Packard --- micropeak/Info.plist | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 micropeak/Info.plist diff --git a/micropeak/Info.plist b/micropeak/Info.plist new file mode 100644 index 00000000..5705cc1a --- /dev/null +++ b/micropeak/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleName + MicroPeak + CFBundleVersion + 1.1.9.2 + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + JavaApplicationStub + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleIdentifier + org.altusmetrum.altosui + CFBundleSignature + Altu + CFBundleGetInfoString + MicroPeak UI version 1.1.9.2 + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + MicroPeak.icns + Java + + MainClass + org.altusmetrum.micropeak.MicroPeak + JVMVersion + 1.5+ + ClassPath + + $JAVAROOT/micropeak.jar + + VMOptions + + -Xms512M + -Xmx512M + -Dosgi.clean=true + + + + -- cgit v1.2.3 From f20781010a6560b7b359af269c502d098917c446 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 3 Jan 2013 17:31:01 -0800 Subject: micropeak: Add command line export option micropeak --export will create full of useful data. Signed-off-by: Keith Packard --- micropeak/MicroData.java | 9 ++++ micropeak/MicroExport.java | 15 +++---- micropeak/MicroFileChooser.java | 18 ++------ micropeak/MicroPeak.java | 94 ++++++++++++++++++++++++++++++++--------- micropeak/MicroSave.java | 10 +++-- 5 files changed, 100 insertions(+), 46 deletions(-) diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 836d3c35..fdfb2dc4 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -263,6 +263,15 @@ public class MicroData { f.write('\n'); } + public void export (Writer f) throws IOException { + PrintWriter pw = new PrintWriter(f); + pw.printf(" Time, Press, Height, Speed, Accel\n"); + for (MicroDataPoint point : points()) { + pw.printf("%6.3f,%6.0f,%7.1f,%7.2f,%7.2f\n", + point.time, point.pressure, point.height, point.speed, point.accel); + } + } + public void set_name(String name) { this.name = name; } diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java index 219184da..4b83bb4d 100644 --- a/micropeak/MicroExport.java +++ b/micropeak/MicroExport.java @@ -31,6 +31,12 @@ public class MicroExport extends JFileChooser { JFrame frame; MicroData data; + public static void export(File file, MicroData data) throws FileNotFoundException, IOException { + FileWriter fw = new FileWriter(file); + data.export(fw); + fw.close(); + } + public boolean runDialog() { int ret; @@ -76,14 +82,7 @@ public class MicroExport extends JFileChooser { } } try { - FileWriter fw = new FileWriter(file); - PrintWriter pw = new PrintWriter(fw); - pw.printf(" Time, Press, Height, Speed, Accel\n"); - for (MicroDataPoint point : data.points()) { - pw.printf("%6.3f,%6.0f,%7.1f,%7.2f,%7.2f\n", - point.time, point.pressure, point.height, point.speed, point.accel); - } - fw.close(); + export(file, data); return true; } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(frame, diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java index d2540987..21ddb0f8 100644 --- a/micropeak/MicroFileChooser.java +++ b/micropeak/MicroFileChooser.java @@ -36,24 +36,12 @@ public class MicroFileChooser extends JFileChooser { return file; } - public InputStream runDialog() { + public File runDialog() { int ret; ret = showOpenDialog(frame); - if (ret == APPROVE_OPTION) { - file = getSelectedFile(); - if (file == null) - return null; - filename = file.getName(); - try { - return new FileInputStream(file); - } catch (FileNotFoundException fe) { - JOptionPane.showMessageDialog(frame, - fe.getMessage(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } - } + if (ret == APPROVE_OPTION) + return getSelectedFile(); return null; } diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index d4252fa9..185fa67e 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -56,40 +56,41 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene setTitle(name); } - private void RunFile(InputStream input, String name) { + private static MicroData ReadFile(File filename) throws IOException, FileNotFoundException { + MicroData data = null; + FileInputStream fis = new FileInputStream(filename); try { - MicroData data = new MicroData(input, name); - SetData(data); - } catch (IOException ioe) { - JOptionPane.showMessageDialog(this, - ioe.getMessage(), - "File Read Error", - JOptionPane.ERROR_MESSAGE); + data = new MicroData((InputStream) fis, filename.getName()); } catch (InterruptedException ie) { + data = null; + } finally { + fis.close(); } - try { - input.close(); - } catch (IOException ioe) { - } + return data; } private void OpenFile(File filename) { try { - RunFile (new FileInputStream(filename), filename.getName()); + SetData(ReadFile(filename)); } catch (FileNotFoundException fne) { JOptionPane.showMessageDialog(this, fne.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); + } catch (IOException ioe) { + JOptionPane.showMessageDialog(this, + ioe.getMessage(), + "File Read Error", + JOptionPane.ERROR_MESSAGE); } } private void SelectFile() { MicroFileChooser chooser = new MicroFileChooser(this); - InputStream input = chooser.runDialog(); + File file = chooser.runDialog(); - if (input != null) - RunFile(input, chooser.filename); + if (file != null) + OpenFile(file); } private void Preferences() { @@ -109,6 +110,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene "No data", JOptionPane.INFORMATION_MESSAGE); } + private void Save() { if (data == null) { no_data(); @@ -128,6 +130,30 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene export.runDialog(); } + private static void CommandGraph(File file) { + MicroPeak m = new MicroPeak(); + m.OpenFile(file); + } + + private static void CommandExport(File file) { + try { + MicroData d = ReadFile(file); + if (d != null) { + File csv = new File(AltosLib.replace_extension(file.getPath(), ".csv")); + try { + System.out.printf ("Export \"%s\" to \"%s\"\n", file.getPath(), csv.getPath()); + MicroExport.export(csv, d); + } catch (FileNotFoundException fe) { + System.err.printf("Cannot create file \"%s\" (%s)\n", csv.getName(), fe.getMessage()); + } catch (IOException ie) { + System.err.printf("Cannot write file \"%s\" (%s)\n", csv.getName(), ie.getMessage()); + } + } + } catch (IOException ie) { + System.err.printf("Cannot read file \"%s\" (%s)\n", file.getName(), ie.getMessage()); + } + } + private void Close() { setVisible(false); dispose(); @@ -233,8 +259,17 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene setVisible(true); } + public static void help(int code) { + System.out.printf("Usage: micropeak [OPTION] ... [FILE]...\n"); + System.out.printf(" Options:\n"); + System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n"); + System.out.printf(" --graph\tgraph a flight\n"); + System.exit(code); + } + public static void main(final String[] args) { boolean opened = false; + boolean graphing = true; try { UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel()); @@ -242,11 +277,30 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } for (int i = 0; i < args.length; i++) { - MicroPeak m = new MicroPeak(); - m.OpenFile(new File(args[i])); - opened = true; + System.out.printf ("Arg %d: %s\n", i, args[i]); + if (args[i].equals("--help")) + help(0); + else if (args[i].equals("--export")) + graphing = false; + else if (args[i].equals("--graph")) + graphing = true; + else if (args[i].startsWith("--")) + help(1); + else { + File file = new File(args[i]); + try { + if (graphing) + CommandGraph(file); + else + CommandExport(file); + opened = true; + } catch (Exception e) { + System.err.printf("Error processing \"%s\": %s\n", + file.getName(), e.getMessage()); + } + } } if (!opened) new MicroPeak(); } -} \ No newline at end of file +} diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index cb4b4221..2664f170 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -32,6 +32,12 @@ public class MicroSave extends JFileChooser { JFrame frame; MicroData data; + public static void save(File file, MicroData data) throws FileNotFoundException, IOException { + FileOutputStream fos = new FileOutputStream(file); + data.save(fos); + fos.close(); + } + public boolean runDialog() { int ret; @@ -76,9 +82,7 @@ public class MicroSave extends JFileChooser { } } try { - FileOutputStream fos = new FileOutputStream(file); - data.save(fos); - fos.close(); + save(file, data); data.set_name(filename); return true; } catch (FileNotFoundException fe) { -- cgit v1.2.3 From 81088b42b3ea899c8d1b3f09ee4fe24378fa03c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 3 Jan 2013 17:40:19 -0800 Subject: micropeak: Export in lots of units meters, feet, mach and gs Signed-off-by: Keith Packard --- micropeak/MicroData.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index fdfb2dc4..d3c8c43e 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -265,10 +265,19 @@ public class MicroData { public void export (Writer f) throws IOException { PrintWriter pw = new PrintWriter(f); - pw.printf(" Time, Press, Height, Speed, Accel\n"); + pw.printf(" Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(ft/s), Speed(mach), Accel(m/s²), Accel(ft/s²), Accel(g)\n"); for (MicroDataPoint point : points()) { - pw.printf("%6.3f,%6.0f,%7.1f,%7.2f,%7.2f\n", - point.time, point.pressure, point.height, point.speed, point.accel); + pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%12.2f,%12.4f,%12.2f,%13.2f,%10.4f\n", + point.time, + point.pressure, + point.height, + AltosConvert.meters_to_feet(point.height), + point.speed, + AltosConvert.meters_to_feet(point.speed), + AltosConvert.meters_to_mach(point.speed), + point.accel, + AltosConvert.meters_to_feet(point.accel), + AltosConvert.meters_to_g(point.accel)); } } -- cgit v1.2.3 From ca284d8bef2f4bd360eaec58048ba9abdafc55bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 3 Jan 2013 18:14:40 -0800 Subject: micropeak: Use data.export for Raw display. Change to MPH data.export already knows how to format stuff, so use that to construct the raw data presentation for the GUI too. Signed-off-by: Keith Packard --- altoslib/AltosSpeed.java | 6 +++--- micropeak/MicroData.java | 6 +++--- micropeak/MicroRaw.java | 14 ++++++++------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java index af63ed17..4e2daf5a 100644 --- a/altoslib/AltosSpeed.java +++ b/altoslib/AltosSpeed.java @@ -21,19 +21,19 @@ public class AltosSpeed extends AltosUnits { public double value(double v) { if (AltosConvert.imperial_units) - return AltosConvert.meters_to_feet(v); + return AltosConvert.meters_to_mph(v); return v; } public String show_units() { if (AltosConvert.imperial_units) - return "ft/s"; + return "mph"; return "m/s"; } public String say_units() { if (AltosConvert.imperial_units) - return "feet per second"; + return "miles per hour"; return "meters per second"; } diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index d3c8c43e..f1204e11 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -265,15 +265,15 @@ public class MicroData { public void export (Writer f) throws IOException { PrintWriter pw = new PrintWriter(f); - pw.printf(" Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(ft/s), Speed(mach), Accel(m/s²), Accel(ft/s²), Accel(g)\n"); + pw.printf(" Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(mph), Speed(mach), Accel(m/s²), Accel(ft/s²), Accel(g)\n"); for (MicroDataPoint point : points()) { - pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%12.2f,%12.4f,%12.2f,%13.2f,%10.4f\n", + pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%11.2f,%12.4f,%12.2f,%13.2f,%10.4f\n", point.time, point.pressure, point.height, AltosConvert.meters_to_feet(point.height), point.speed, - AltosConvert.meters_to_feet(point.speed), + AltosConvert.meters_to_mph(point.speed), AltosConvert.meters_to_mach(point.speed), point.accel, AltosConvert.meters_to_feet(point.accel), diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index f5bea76f..dd480bfe 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -18,6 +18,7 @@ package org.altusmetrum.micropeak; import java.awt.*; +import java.io.*; import javax.swing.*; import org.altusmetrum.AltosLib.*; import org.altusmetrum.altosuilib.*; @@ -25,12 +26,13 @@ import org.altusmetrum.altosuilib.*; public class MicroRaw extends JTextArea { public void setData(MicroData data) { - setRows(data.pressures.length); - setText(" Time, Press, Height, Speed, Accel\n"); - for (MicroDataPoint point : data.points()) { - append(String.format( - "%6.3f,%6.0f,%7.1f,%7.2f,%7.2f\n", - point.time, point.pressure, point.height, point.speed, point.accel)); + StringWriter sw = new StringWriter(); + try { + data.export(sw); + setRows(data.pressures.length + 1); + setText(sw.toString()); + } catch (IOException ie) { + setText(String.format("Error writing data: %s", ie.getMessage())); } } -- cgit v1.2.3 From 746ae98829a0fc15577ae0f7b506112178f481e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Jan 2013 10:35:20 -0800 Subject: Add separate code path for listing FTDI devices This lets the library do different things for FTDI devices, as is required on Windows (for instance) Signed-off-by: Keith Packard --- libaltos/libaltos.c | 102 ++++++++++++++++++++++++++++++++++++++++------------ libaltos/libaltos.h | 3 ++ 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c index 24c20179..505b3147 100644 --- a/libaltos/libaltos.c +++ b/libaltos/libaltos.c @@ -606,6 +606,12 @@ altos_list_start(void) return devs; } +PUBLIC struct altos_list * +altos_ftdi_list_start(void) +{ + return altos_list_start(); +} + int altos_list_next(struct altos_list *list, struct altos_device *device) { @@ -785,6 +791,7 @@ no_file: struct altos_list { io_iterator_t iterator; + int ftdi; }; static int @@ -842,8 +849,21 @@ altos_list_start(void) int i; ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); - if (ret != kIOReturnSuccess) + if (ret != kIOReturnSuccess) { + free(list); return NULL; + } + list->ftdi = 0; + return list; +} + +PUBLIC struct altos_list * +altos_ftdi_list_start(void) +{ + struct altos_list *list = altos_list_start(); + + if (list) + list->ftdi = 1; return list; } @@ -861,10 +881,15 @@ altos_list_next(struct altos_list *list, struct altos_device *device) if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) || !get_number (object, CFSTR(kUSBProductID), &device->product)) continue; - if (device->vendor != 0xfffe) - continue; - if (device->product < 0x000a || 0x0013 < device->product) - continue; + if (list->ftdi) { + if (device->vendor != 0x0403) + continue; + } else { + if (device->vendor != 0xfffe) + continue; + if (device->product < 0x000a || 0x0013 < device->product) + continue; + } if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) && get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) && get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { @@ -935,6 +960,7 @@ altos_bt_open(struct altos_bt_device *device) struct altos_list { HDEVINFO dev_info; int index; + int ftdi; }; #define USB_BUF_SIZE 64 @@ -985,6 +1011,26 @@ altos_list_start(void) return NULL; } list->index = 0; + list->ftdi = 0; + return list; +} + +PUBLIC struct altos_list * +altos_ftdi_list_start(void) +{ + struct altos_list *list = calloc(1, sizeof (struct altos_list)); + + if (!list) + return NULL; + list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL, + DIGCF_ALLCLASSES|DIGCF_PRESENT); + if (list->dev_info == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); + free(list); + return NULL; + } + list->index = 0; + list->ftdi = 1; return list; } @@ -1019,24 +1065,30 @@ altos_list_next(struct altos_list *list, struct altos_device *device) continue; } - /* Fetch symbolic name for this device and parse out - * the vid/pid/serial info */ - symbolic_len = sizeof(symbolic); - 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; + if (list->ftdi) { + vid = 0x0403; + pid = 0x6015; + serial = 0; + } else { + /* Fetch symbolic name for this device and parse out + * the vid/pid/serial info */ + symbolic_len = sizeof(symbolic); + 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; + } + vid = pid = serial = 0; + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, + "%04X", &vid); + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + "%04X", &pid); + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + "%d", &serial); } - vid = pid = serial = 0; - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, - "%04X", &vid); - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, - "%04X", &pid); - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, - "%d", &serial); /* Fetch the com port name */ port_len = sizeof (port); @@ -1203,6 +1255,7 @@ altos_open(struct altos_device *device) struct altos_file *file = calloc (1, sizeof (struct altos_file)); char full_name[64]; COMMTIMEOUTS timeouts; + DCB dcb; if (!file) return NULL; @@ -1228,6 +1281,11 @@ altos_open(struct altos_device *device) timeouts.WriteTotalTimeoutConstant = 0; SetCommTimeouts(file->handle, &timeouts); + if (GetCommState(file->handle, &dcb)) { + dcb.BaudRate = CBR_9600; + (void) SetCommState(file->handle, &dcb); + } + return file; } diff --git a/libaltos/libaltos.h b/libaltos/libaltos.h index f90fbb87..6d43159b 100644 --- a/libaltos/libaltos.h +++ b/libaltos/libaltos.h @@ -73,6 +73,9 @@ altos_get_last_error(struct altos_error *error); PUBLIC struct altos_list * altos_list_start(void); +PUBLIC struct altos_list * +altos_ftdi_list_start(void); + /* Returns 1 for success, zero on end of list */ PUBLIC int altos_list_next(struct altos_list *list, struct altos_device *device); -- cgit v1.2.3 From 70c7674b53d77e9995a235bb2dc455cb53d9e81e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Jan 2013 10:36:40 -0800 Subject: micropeak: Remove debug printf for command line Signed-off-by: Keith Packard --- micropeak/MicroPeak.java | 1 - 1 file changed, 1 deletion(-) diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 185fa67e..5d128dfd 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -277,7 +277,6 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } for (int i = 0; i < args.length; i++) { - System.out.printf ("Arg %d: %s\n", i, args[i]); if (args[i].equals("--help")) help(0); else if (args[i].equals("--export")) -- cgit v1.2.3 From e7e71e2042f2bfc24adcc57cecfe26368eb03e8a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Jan 2013 10:36:50 -0800 Subject: micropeak: Move raw view caret to top. Make raw text uneditable Signed-off-by: Keith Packard --- micropeak/MicroRaw.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index dd480bfe..8546cffb 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -34,10 +34,12 @@ public class MicroRaw extends JTextArea { } catch (IOException ie) { setText(String.format("Error writing data: %s", ie.getMessage())); } + setCaretPosition(0); } public MicroRaw() { super(1, 30); setFont(AltosUILib.table_value_font); + setEditable(false); } } -- cgit v1.2.3 From 20d54cae1eeca6c5d05bfacbafd77c8aa72247c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Jan 2013 10:37:30 -0800 Subject: micropeak: Use new libaltos entry point for FTDI devices Signed-off-by: Keith Packard --- micropeak/MicroUSB.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index 908ac51b..f56d81d4 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -50,7 +50,7 @@ public class MicroUSB extends altos_device implements AltosDevice { String name = getName(); if (name == null) name = "Altus Metrum"; - return String.format("%-20.20s %s", + return String.format("%-24.24s %s", name, getPath()); } @@ -90,7 +90,7 @@ public class MicroUSB extends altos_device implements AltosDevice { if (!load_library()) return null; - SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + SWIGTYPE_p_altos_list list = libaltos.altos_ftdi_list_start(); ArrayList device_list = new ArrayList(); if (list != null) { -- cgit v1.2.3 From 0c9eecfae02e8499e7c3d53a4386f026c54b04cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Jan 2013 10:38:20 -0800 Subject: micropeak: Create .dmg file for apple. Create micropeak-jdb script Signed-off-by: Keith Packard --- micropeak/Makefile.am | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index c452db97..ea7385a7 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -67,7 +67,7 @@ ICONJAR= -C $(ICONDIR) micropeak-16.png \ WINDOWS_ICON=$(ICONDIR)/micro-peak.ico -all-local: micropeak-test $(JAR) +all-local: micropeak-test micropeak-jdb $(JAR) clean-local: -rm -rf classes $(JAR) $(FATJAR) \ @@ -78,7 +78,7 @@ clean-local: micropeak micropeak-test macosx linux windows LINUX_DIST=MicroPeak-Linux-$(VERSION).tar.bz2 -MACOSX_DIST=MicroPeak-Mac-$(VERSION).zip +MACOSX_DIST=MicroPeak-Mac-$(VERSION).dmg WINDOWS_DIST=MicroPeak-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) @@ -122,6 +122,11 @@ micropeak: Makefile echo 'exec java -cp "$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="$(altoslibdir)" -jar "$(micropeakdir)/micropeak.jar" "$$@"' >> $@ chmod +x $@ +micropeak-jdb: Makefile + echo "#!/bin/sh" > $@ + echo 'exec jdb -classpath "classes:./*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" org.altusmetrum.micropeak.MicroPeak "$$@"' >> $@ + chmod +x $@ + micropeak-test: Makefile echo "#!/bin/sh" > $@ echo 'exec java -cp "./*:../libaltos/*:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="../libaltos/.libs" -jar micropeak.jar "$$@"' >> $@ @@ -206,14 +211,14 @@ $(MACOSX_DIST): $(MACOSX_FILES) mkdir macosx cp -a MicroPeak.app macosx/ cp -p Info.plist macosx/MicroPeak.app/Contents - mkdir -p macosx/MicroPeak macosx/MicroPeak.app/Contents/Resources/Java + mkdir -p macosx/MicroPeak.app/Contents/Resources/Java cp -p $(FATJAR) macosx/MicroPeak.app/Contents/Resources/Java/micropeak.jar cp -p libaltos.dylib macosx/MicroPeak.app/Contents/Resources/Java cp -p $(ALTOSLIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java cp -p $(ALTOSUILIB_CLASS) macosx/MicroPeak.app/Contents/Resources/Java cp -p $(JFREECHART_CLASS) macosx/MicroPeak.app/Contents/Resources/Java cp -p $(JCOMMON_CLASS) macosx/MicroPeak.app/Contents/Resources/Java - cd macosx && zip -r ../$@ MicroPeak.app MicroPeak + genisoimage -D -V MicroPeak-$(VERSION) -no-pad -r -apple -o $@ macosx $(WINDOWS_DIST): $(WINDOWS_FILES) micropeak-windows.nsi -rm -f $@ -- cgit v1.2.3 From d663da13db60e1200535282ee1a0ea6305cad98c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Jan 2013 10:59:26 -0800 Subject: micropeak: Suggest filenames for saving data Uses the format '---flight-.mpd' Signed-off-by: Keith Packard --- micropeak/Makefile.am | 1 + micropeak/MicroFile.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ micropeak/MicroSave.java | 1 + 3 files changed, 47 insertions(+) create mode 100644 micropeak/MicroFile.java diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index ea7385a7..19b23a0f 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -13,6 +13,7 @@ micropeak_JAVA= \ MicroDataPoint.java \ MicroDownload.java \ MicroExport.java \ + MicroFile.java \ MicroFrame.java \ MicroGraph.java \ MicroRaw.java \ diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java new file mode 100644 index 00000000..13d48380 --- /dev/null +++ b/micropeak/MicroFile.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import java.util.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroFile { + + public static File make(File directory, int year, int month, int day) { + for (int sequence = 1;; sequence++) { + String s = String.format("%04d-%02d-%02d-flight-%03d.mpd", + year, month, day, sequence); + File file = new File(directory, s); + if (!file.exists()) + return file; + } + } + + public static File make(File directory) { + Calendar cal = Calendar.getInstance(); + return make(directory, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH)); + } + + public static File make() { + return make(AltosUIPreferences.logdir()); + } +} \ No newline at end of file diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index 2664f170..7879ff90 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -102,5 +102,6 @@ public class MicroSave extends JFileChooser { setFileFilter(new FileNameExtensionFilter("MicroPeak data file", "mpd")); setCurrentDirectory(AltosUIPreferences.logdir()); + setSelectedFile(MicroFile.make()); } } -- cgit v1.2.3 From 0f05b1996122b6c6bce81ca33e85c2a65c3ded18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Jan 2013 12:52:25 -0800 Subject: micropeak: Create Mac OS X package Includes the FTDI driver and the MicroPeak app Signed-off-by: Keith Packard --- libaltos/Makefile-standalone | 15 ++++++- libaltos/libaltos.dylib | Bin 41648 -> 41596 bytes micropeak/FTDI.tar.gz | Bin 0 -> 251029 bytes micropeak/Info.plist | 45 --------------------- micropeak/Info.plist.in | 7 +++- micropeak/Makefile.am | 4 +- .../Contents/Resources/AltosUIIcon.icns | Bin 129010 -> 0 bytes .../Contents/Resources/MicroPeak.icns | Bin 0 -> 133711 bytes 8 files changed, 22 insertions(+), 49 deletions(-) create mode 100644 micropeak/FTDI.tar.gz delete mode 100644 micropeak/Info.plist delete mode 100644 micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns create mode 100644 micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns diff --git a/libaltos/Makefile-standalone b/libaltos/Makefile-standalone index 4e438050..a1f9f5bc 100644 --- a/libaltos/Makefile-standalone +++ b/libaltos/Makefile-standalone @@ -22,9 +22,20 @@ endif # ifeq ($(OS),Darwin) +#OS_LIB_CFLAGS=\ +# -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \ +# --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \ +# -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \ +# -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ +# -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers + +XCODE=/Applications/Xcode.app +SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk +MINVERSION=10.5 + OS_LIB_CFLAGS=\ - -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \ - --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \ + -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 -isysroot $(SDK) \ + -mmacosx-version-min=10.5 \ -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \ -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers diff --git a/libaltos/libaltos.dylib b/libaltos/libaltos.dylib index 1038817d..cfbd3f54 100755 Binary files a/libaltos/libaltos.dylib and b/libaltos/libaltos.dylib differ diff --git a/micropeak/FTDI.tar.gz b/micropeak/FTDI.tar.gz new file mode 100644 index 00000000..cd08ecf2 Binary files /dev/null and b/micropeak/FTDI.tar.gz differ diff --git a/micropeak/Info.plist b/micropeak/Info.plist deleted file mode 100644 index 5705cc1a..00000000 --- a/micropeak/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleName - MicroPeak - CFBundleVersion - 1.1.9.2 - CFBundleAllowMixedLocalizations - true - CFBundleExecutable - JavaApplicationStub - CFBundleDevelopmentRegion - English - CFBundlePackageType - APPL - CFBundleIdentifier - org.altusmetrum.altosui - CFBundleSignature - Altu - CFBundleGetInfoString - MicroPeak UI version 1.1.9.2 - CFBundleInfoDictionaryVersion - 6.0 - CFBundleIconFile - MicroPeak.icns - Java - - MainClass - org.altusmetrum.micropeak.MicroPeak - JVMVersion - 1.5+ - ClassPath - - $JAVAROOT/micropeak.jar - - VMOptions - - -Xms512M - -Xmx512M - -Dosgi.clean=true - - - - diff --git a/micropeak/Info.plist.in b/micropeak/Info.plist.in index d3c17a49..40984c5a 100644 --- a/micropeak/Info.plist.in +++ b/micropeak/Info.plist.in @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleIdentifier - org.altusmetrum.altosui + org.altusmetrum.micropeak CFBundleSignature Altu CFBundleGetInfoString @@ -34,6 +34,11 @@ $JAVAROOT/micropeak.jar + Properties + + apple.laf.useScreenMenuBar + true + VMOptions -Xms512M diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 19b23a0f..38945e82 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -88,7 +88,8 @@ LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) LINUX_EXTRA=micropeak-fat MACOSX_INFO_PLIST=Info.plist -MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) +MACOSX_DRIVER=FTDI.tar.gz +MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) @@ -212,6 +213,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) mkdir macosx cp -a MicroPeak.app macosx/ cp -p Info.plist macosx/MicroPeak.app/Contents + tar xzf $(MACOSX_DRIVER) -C macosx mkdir -p macosx/MicroPeak.app/Contents/Resources/Java cp -p $(FATJAR) macosx/MicroPeak.app/Contents/Resources/Java/micropeak.jar cp -p libaltos.dylib macosx/MicroPeak.app/Contents/Resources/Java diff --git a/micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns b/micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns deleted file mode 100644 index fe49f362..00000000 Binary files a/micropeak/MicroPeak.app/Contents/Resources/AltosUIIcon.icns and /dev/null differ diff --git a/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns b/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns new file mode 100644 index 00000000..9ba83bf5 Binary files /dev/null and b/micropeak/MicroPeak.app/Contents/Resources/MicroPeak.icns differ -- cgit v1.2.3 From 2582e9b45bb81ff70fbd5c8581370c8c1b5bd5e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Jan 2013 13:00:00 -0800 Subject: micropeak: Add ReadMe.rtf to Mac distribution There are *two* steps to installing MicroPeak on Mac OSX. Best help out the poor user by explaining that. Signed-off-by: Keith Packard --- micropeak/Makefile.am | 4 +++- micropeak/ReadMe-Mac.rtf | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 micropeak/ReadMe-Mac.rtf diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 38945e82..b80cabf2 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -89,7 +89,8 @@ LINUX_EXTRA=micropeak-fat MACOSX_INFO_PLIST=Info.plist MACOSX_DRIVER=FTDI.tar.gz -MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) +MACOSX_README=ReadMe-Mac.rtf +MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) $(MACOSX_DRIVER) $(MACOSX_README) WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) @@ -212,6 +213,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) -rm -rf macosx mkdir macosx cp -a MicroPeak.app macosx/ + cp -a $(MACOSX_README) macosx/ReadMe.rtf cp -p Info.plist macosx/MicroPeak.app/Contents tar xzf $(MACOSX_DRIVER) -C macosx mkdir -p macosx/MicroPeak.app/Contents/Resources/Java diff --git a/micropeak/ReadMe-Mac.rtf b/micropeak/ReadMe-Mac.rtf new file mode 100644 index 00000000..64bbdeb6 --- /dev/null +++ b/micropeak/ReadMe-Mac.rtf @@ -0,0 +1,19 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf510 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww10800\viewh8400\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural + +\f0\fs24 \cf0 Installing MicroPeak software for Mac OS X computers\ +\ +There are two files included in the Mac OS X distribution:\ +\ + 1) The MicroPeak application\ +\ + 2) The FTDI device drivers\ +\ +As with most Mac OS X applications, install MicroPeak by dragging it from the distribution disk image to a suitable place on your computer.\ +\ +To communicate with the MicroPeak serial adapter, you need to installed the FTDI device drivers, which is done by double-clicking on the FTDIUSBSerialDriver package file. That will guide you through the installation process.\ +\ +Thanks for choosing AltusMetrum products!} \ No newline at end of file -- cgit v1.2.3 From d409417ff8e9ed9d406bf1c04542a4ecb574768b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Jan 2013 13:20:25 -0800 Subject: altosui: Create .dmg file for Mac OS X installations Easier for users than a zip file Signed-off-by: Keith Packard --- altosui/Makefile.am | 13 ++++++------ altosui/ReadMe-Mac.rtf | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 altosui/ReadMe-Mac.rtf diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 539e14f6..4c5d8132 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -165,7 +165,7 @@ DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(TEMPLATE_DOC) # Distribution targets LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2 -MACOSX_DIST=Altos-Mac-$(VERSION).zip +MACOSX_DIST=Altos-Mac-$(VERSION).dmg WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) @@ -174,7 +174,7 @@ LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) LINUX_EXTRA=altosui-fat MACOSX_INFO_PLIST=Info.plist -MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) +MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) ReadMe-Mac.rtf MACOSX_EXTRA=$(FIRMWARE) WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) @@ -319,13 +319,14 @@ $(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA) chmod +x linux/AltOS/altosui tar cjf $@ -C linux AltOS -$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) +$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) Makefile -rm -f $@ -rm -rf macosx mkdir macosx cp -a AltosUI.app macosx/ + cp -a ReadMe-Mac.rtf macosx/ReadMe.rtf cp -p Info.plist macosx/AltosUI.app/Contents - mkdir -p macosx/AltOS macosx/AltosUI.app/Contents/Resources/Java + mkdir -p macosx/AltOS-$(VERSION) macosx/AltosUI.app/Contents/Resources/Java cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java cp -p $(ALTOSLIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java @@ -333,8 +334,8 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) cp -p $(FREETTS_CLASS) macosx/AltosUI.app/Contents/Resources/Java cp -p $(JFREECHART_CLASS) macosx/AltosUI.app/Contents/Resources/Java cp -p $(JCOMMON_CLASS) macosx/AltosUI.app/Contents/Resources/Java - cp -p $(MACOSX_EXTRA) macosx/AltOS - cd macosx && zip -r ../$@ AltosUI.app AltOS + cp -p $(MACOSX_EXTRA) macosx/AltOS-$(VERSION) + genisoimage -D -V AltOS-$(VERSION) -no-pad -r -apple -o $@ macosx $(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi -rm -f $@ diff --git a/altosui/ReadMe-Mac.rtf b/altosui/ReadMe-Mac.rtf new file mode 100644 index 00000000..8a95262c --- /dev/null +++ b/altosui/ReadMe-Mac.rtf @@ -0,0 +1,56 @@ +{\rtf1\ansi\deff3\adeflang1025 +{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset128 Liberation Serif{\*\falt Times New Roman};}{\f4\fswiss\fprq2\fcharset128 Arial;}{\f5\fnil\fprq2\fcharset128 SimSun;}{\f6\fnil\fprq2\fcharset128 Raghindi;}{\f7\fnil\fprq0\fcharset128 Raghindi;}} +{\colortbl;\red0\green0\blue0;\red128\green128\blue128;} +{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033 Normal;} +{\*\cs15\snext15 Numbering Symbols;} +{\s16\sbasedon0\snext17\sb240\sa120\keepn\hich\af5\dbch\af6\afs28\loch\f4\fs28 Heading;} +{\s17\sbasedon0\snext17\sb0\sa120 Text body;} +{\s18\sbasedon17\snext18\sb0\sa120\dbch\af7 List;} +{\s19\sbasedon0\snext19\sb120\sa120\noline\i\dbch\af7\afs24\ai\fs24 Caption;} +{\s20\sbasedon0\snext20\noline\dbch\af7 Index;} +}{\*\listtable{\list\listtemplateid1 +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'00);}{\levelnumbers\'01;}\fi-360\li720} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'01.;}{\levelnumbers\'01;}\fi-360\li1080} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'02.;}{\levelnumbers\'01;}\fi-360\li1440} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'03.;}{\levelnumbers\'01;}\fi-360\li1800} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'04.;}{\levelnumbers\'01;}\fi-360\li2160} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'05.;}{\levelnumbers\'01;}\fi-360\li2520} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'06.;}{\levelnumbers\'01;}\fi-360\li2880} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'07.;}{\levelnumbers\'01;}\fi-360\li3240} +{\listlevel\levelnfc0\leveljc0\levelstartat1\levelfollow0{\leveltext \'02\'08.;}{\levelnumbers\'01;}\fi-360\li3600}\listid1} +{\list\listtemplateid2 +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-432\li432} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-576\li576} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-720\li720} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-864\li864} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-1008\li1008} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-1152\li1152} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-1296\li1296} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-1440\li1440} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow0{\leveltext \'00;}{\levelnumbers;}\fi-1584\li1584}\listid2} +}{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}{\info{\creatim\yr2013\mo1\dy6\hr13\min7}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern3500}}\deftab709 + +{\*\pgdsctbl +{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Default;}} +\formshade\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc +\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +Installing AltOS software for Mac OS X Computers} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +The AltOS distribution for Mac OS X consists of:} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\listtext\pard\plain 1)\tab}\ilvl0\ls1 \li720\ri0\lin720\rin0\fi-360{\rtlch \ltrch\loch +The AltosUI application} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\listtext\pard\plain 2)\tab}\ilvl0\ls1 \li720\ri0\lin720\rin0\fi-360{\rtlch \ltrch\loch +Current AltOS firmware for Altus Metrum products} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +Install the AltosUI application by dragging it to your Applications folder (or wherever else you want to install it).} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +} +\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\hich\af5\langfe2052\dbch\af6\afs24\alang1081\loch\f3\fs24\lang1033{\rtlch \ltrch\loch +The AltOS firmware can be used to update your Altus Metrum products to the latest firmware version, you can copy it to your disk if you like, or simply use it directly from the installation disk image.} +\par } \ No newline at end of file -- cgit v1.2.3 From 42733d2823b1ecf54c03881fc120067868c0ff4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 9 Jan 2013 15:23:46 -0800 Subject: altoslib: Don't smash existing GPS pad alt after boost Leave the existing GPS pad altitude value in place after boost by checking to see if it was ever computed before resetting it to the barometric pad altitude. This makes GPS height values relative to the pad. Signed-off-by: Keith Packard --- altoslib/AltosState.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 218c598a..4f59c840 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -200,10 +200,10 @@ public class AltosState { } ngps++; } - } else - pad_alt = ground_altitude; - - data.new_gps = false; + } else { + if (ngps == 0) + pad_alt = ground_altitude; + } gps_waiting = MIN_PAD_SAMPLES - npad; if (gps_waiting < 0) -- cgit v1.2.3 From f715b5da3424adacc5a7f1e001e1dd7fa6f50385 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 9 Jan 2013 15:29:01 -0800 Subject: altoslib: Clean up AltosRecord clone methods Make the AltosRecord version abstract and then implement suitable versions in each subclass by creating copying constructors for each class. Signed-off-by: Keith Packard --- altoslib/AltosRecord.java | 12 ++---------- altoslib/AltosRecordMM.java | 10 +++++++--- altoslib/AltosRecordNone.java | 4 ++++ altoslib/AltosRecordTM.java | 8 +++++--- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index 09169515..2c4b6fa5 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -126,6 +126,8 @@ public abstract class AltosRecord implements Comparable , Cloneable return tick - o.tick; } + abstract public AltosRecord clone(); + public void copy(AltosRecord old) { seen = old.seen; version = old.version; @@ -144,16 +146,6 @@ public abstract class AltosRecord implements Comparable , Cloneable kalman_height = old.kalman_height; } - public AltosRecord clone() { - try { - AltosRecord n = (AltosRecord) super.clone(); - n.copy(this); - return n; - } catch (CloneNotSupportedException e) { - return null; - } - } - public AltosRecord() { seen = 0; version = 0; diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java index 9f529234..546f3055 100644 --- a/altoslib/AltosRecordMM.java +++ b/altoslib/AltosRecordMM.java @@ -131,10 +131,10 @@ public class AltosRecordMM extends AltosRecord { mag = old.mag; } + + public AltosRecordMM clone() { - AltosRecordMM n = (AltosRecordMM) super.clone(); - n.copy(this); - return n; + return new AltosRecordMM(this); } void make_missing() { @@ -167,6 +167,10 @@ public class AltosRecordMM extends AltosRecord { make_missing(); } + public AltosRecordMM(AltosRecordMM old) { + copy(old); + } + public AltosRecordMM() { super(); make_missing(); diff --git a/altoslib/AltosRecordNone.java b/altoslib/AltosRecordNone.java index ca0a5fe3..d4ea305f 100644 --- a/altoslib/AltosRecordNone.java +++ b/altoslib/AltosRecordNone.java @@ -28,6 +28,10 @@ public class AltosRecordNone extends AltosRecord { super.copy(old); } + public AltosRecordNone clone() { + return new AltosRecordNone(this); + } + public AltosRecordNone() { super(); } diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java index 9530be31..f6ed4966 100644 --- a/altoslib/AltosRecordTM.java +++ b/altoslib/AltosRecordTM.java @@ -149,9 +149,7 @@ public class AltosRecordTM extends AltosRecord { } public AltosRecordTM clone() { - AltosRecordTM n = (AltosRecordTM) super.clone(); - n.copy(this); - return n; + return new AltosRecordTM(this); } void make_missing() { @@ -177,6 +175,10 @@ public class AltosRecordTM extends AltosRecord { make_missing(); } + public AltosRecordTM(AltosRecordTM old) { + copy(old); + } + public AltosRecordTM() { super(); make_missing(); -- cgit v1.2.3 From acff2f466031fd1a8533fc315411c3734a8bacc6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:27:32 -0800 Subject: altos: Time out reading packet data from cc1120 after 100ms Sometimes the radio will give a spurious wakeup indicating that a preamble seems to have arrived, but no packet data will appear. In this case, abandon the packet reception and go back to waiting for a preamble again. This releases the SPI bus for other users and also avoids missing packets. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 63d2f955..35be54a4 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -862,6 +862,7 @@ ao_radio_rx_wait(void) do { if (ao_radio_mcu_wake) ao_radio_check_marc_status(); + ao_alarm(AO_MS_TO_TICKS(100)); ao_arch_block_interrupts(); rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && @@ -873,6 +874,7 @@ ao_radio_rx_wait(void) } rx_waiting = 0; ao_arch_release_interrupts(); + ao_clear_alarm(); } while (ao_radio_mcu_wake); if (ao_radio_abort) return 0; -- cgit v1.2.3 From 12a9bd0479db25cbe45c0385913315cc1e0bc892 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:26:20 -0800 Subject: libaltos: Need to check for tty/ttyACMx before ttyACMx Otherwise, we'll find 'tty' when looking for 'ttyACMx' and no good will come from that Signed-off-by: Keith Packard --- libaltos/libaltos.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c index 505b3147..ca56746a 100644 --- a/libaltos/libaltos.c +++ b/libaltos/libaltos.c @@ -478,26 +478,26 @@ usb_tty(char *sys) return tty; } - /* Check for ttyACMx style names + /* Check for tty/ttyACMx style names */ - ntty = scandir(endpoint_full, &namelist, + tty_dir = cc_fullname(endpoint_full, "tty"); + ntty = scandir(tty_dir, &namelist, dir_filter_tty, alphasort); + free (tty_dir); if (ntty > 0) { - free(endpoint_full); tty = cc_fullname("/dev", namelist[0]->d_name); + free(endpoint_full); free(namelist); return tty; } - /* Check for tty/ttyACMx style names + /* Check for ttyACMx style names */ - tty_dir = cc_fullname(endpoint_full, "tty"); - free(endpoint_full); - ntty = scandir(tty_dir, &namelist, + ntty = scandir(endpoint_full, &namelist, dir_filter_tty, alphasort); - free (tty_dir); + free(endpoint_full); if (ntty > 0) { tty = cc_fullname("/dev", namelist[0]->d_name); free(namelist); -- cgit v1.2.3 From e94f9547a566c74c30b6321bc073b8bdcb071604 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:34:24 -0800 Subject: Fix up 'make fat' to build all libs and micropeak too There are now three libraries to build for both altosui and micropeak. Signed-off-by: Keith Packard --- Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 7328c04e..59cddb9f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,5 +15,8 @@ dist-hook: ChangeLog fat: cd src && $(MAKE) all cd doc && $(MAKE) all - cd altosui/libaltos && $(MAKE) all + cd libaltos && $(MAKE) all + cd altoslib && $(MAKE) all + cd altosuilib && $(MAKE) all cd altosui && $(MAKE) fat + cd micropeak && $(MAKE) fat -- cgit v1.2.3 From 505ef49a041740fe7cbb5c537b68d22e5fb6c0be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:37:18 -0800 Subject: micropeak: Report recorded apogee instead of searching flight data This makes sure we report the true apogee value instead of looking for the maximum height value in the flight data, in case the flight recording ended before the apogee was reached. Signed-off-by: Keith Packard --- micropeak/MicroData.java | 12 ++++++++++++ micropeak/MicroStats.java | 11 ++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index f1204e11..71919ddb 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -229,6 +229,18 @@ public class MicroData { return altitude(i) - ground_altitude; } + public double apogee_pressure() { + return min_pressure; + } + + public double apogee_altitude() { + return AltosConvert.pressure_to_altitude(apogee_pressure()); + } + + public double apogee_height() { + return apogee_altitude() - ground_altitude; + } + static final int speed_avg = 3; static final int accel_avg = 5; diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java index 056fac7d..90e9dd1f 100644 --- a/micropeak/MicroStats.java +++ b/micropeak/MicroStats.java @@ -58,12 +58,17 @@ public class MicroStats { } void find_apogee() { - apogee_height = 0; + apogee_height = data.apogee_height(); + double searched_apogee = 0; apogee_time = 0; + /* This just finds the apogee time -- we've recorded the + * peak altitude separately in eeprom, and that could + * have occurred after the eeprom was full. + */ for (MicroDataPoint point : data.points()) { - if (point.height > apogee_height) { - apogee_height = point.height; + if (point.height > searched_apogee) { + searched_apogee = point.height; apogee_time = point.time; } } -- cgit v1.2.3 From 98e74150040e444ed6480ef3d107caa54c205ef9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:38:15 -0800 Subject: micropeak: Demonstrate how to hide various parts of the graph This just shows how to disable a series and axis; it's not used here. Signed-off-by: Keith Packard --- micropeak/MicroGraph.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index 84320be3..5aa127bb 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -54,6 +54,11 @@ class MicroSeries extends XYSeries { renderer.setBaseToolTipGenerator(ttg); } + void set_enable(boolean enable) { + renderer.setSeriesVisible(0, enable); + axis.setVisible(enable); + } + public MicroSeries (String label, String units, Color color) { super(label); this.label = label; @@ -116,6 +121,7 @@ public class MicroGraph implements AltosUnitsListener { accelSeries.add(point.time, AltosConvert.accel.value(point.accel)); } } +// accelSeries.set_enable(false); } public void setName (String name) { -- cgit v1.2.3 From c3e807ffcd34d514f36bc11adbae9337991a1743 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:41:35 -0800 Subject: micropeak: Create 'micropeak' script correctly Add altoslibdir, remove -cp argument Signed-off-by: Keith Packard --- micropeak/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index b80cabf2..95c95f40 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -1,6 +1,8 @@ JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation +altoslibdir=$(libdir)/altos + CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" bin_SCRIPTS=micropeak @@ -122,7 +124,7 @@ endif micropeak: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar" -Djava.library.path="$(altoslibdir)" -jar "$(micropeakdir)/micropeak.jar" "$$@"' >> $@ + echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(micropeakdir)/micropeak.jar" "$$@"' >> $@ chmod +x $@ micropeak-jdb: Makefile -- cgit v1.2.3 From 9f6b1570277c326c00d5da274f608fbdeb91c911 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 21:42:23 -0800 Subject: micropeak: Note when libaltos fails Not getting any device list back from MicroUSB means the library wasn't found, so pop up a dialog box explaining the situation. Signed-off-by: Keith Packard --- micropeak/MicroDeviceDialog.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java index 7b8a630c..23195dac 100644 --- a/micropeak/MicroDeviceDialog.java +++ b/micropeak/MicroDeviceDialog.java @@ -27,6 +27,15 @@ public class MicroDeviceDialog extends AltosDeviceDialog { public AltosDevice[] devices() { java.util.List list = MicroUSB.list(); + + if (list == null) { + JOptionPane.showMessageDialog(frame, + "libaltos failed to load", + "Helper Library Failed", + JOptionPane.ERROR_MESSAGE); + return new AltosDevice[0]; + } + int num_devices = list.size(); AltosDevice[] devices = new AltosDevice[num_devices]; -- cgit v1.2.3 From 962e3bd0461f187cd599ba54e7129c84f97d4c4d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 22:11:36 -0800 Subject: altosui,micropeak: Link altoslib.jar and altosuilib.jar before compiling The symlinks for the libraries have to be present before compiling stuff. Signed-off-by: Keith Packard --- micropeak/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 95c95f40..4a7aaaa1 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -155,6 +155,8 @@ $(FATJAR): classmicropeak.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(ALTOSUILIB_ -C classes org \ -C ../libaltos libaltosJNI +classaltosui.stamp: $(ALTOSLIB_CLASS) $(ALTOSUILIB_CLASS) + libaltos.so: build-libaltos -rm -f "$@" $(LN_S) ../libaltos/.libs/"$@" . -- cgit v1.2.3 From 85baf657e7ea6debbed9effc6f8daff7ef09a5d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Jan 2013 23:42:41 -0800 Subject: altosui: Reference altosuilib.jar and altoslib.jar from original dirs The symlinks may not be created when the build is getting run as the dependencies aren't in place (thanks, automake). Signed-off-by: Keith Packard --- altosui/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 4c5d8132..7d000f7b 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -6,7 +6,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):./*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../altoslib/*:../altosuilib/*:../libaltos:$(JCOMMON)/jcommon.jar:$(JFREECHART)/jfreechart.jar:$(FREETTS)/freetts.jar" bin_SCRIPTS=altosui -- cgit v1.2.3 From d374d6be7eb040457f4df6c38b5d057f26ee741c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Jan 2013 09:45:31 -0800 Subject: micropeak: Record samples before boost detect This saves a ring of 16 samples while waiting for boost, and then goes back through those looking for the first sample higher than the ground and writes the remaining ones to the log so that we get a more complete log of the flight Signed-off-by: Keith Packard --- src/micropeak/ao_micropeak.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c index 82012800..f361aa26 100644 --- a/src/micropeak/ao_micropeak.c +++ b/src/micropeak/ao_micropeak.c @@ -60,6 +60,12 @@ ao_pips(void) ao_delay(AO_MS_TO_TICKS(200)); } +#define NUM_PA_HIST 16 + +#define SKIP_PA_HIST(i,j) (((i) + (j)) & (NUM_PA_HIST - 1)) + +static uint32_t pa_hist[NUM_PA_HIST]; + int main(void) { @@ -67,6 +73,7 @@ main(void) uint16_t time; uint32_t pa_interval_min, pa_interval_max; int32_t pa_diff; + uint8_t h, i; ao_led_init(LEDS_AVAILABLE); ao_timer_init(); @@ -91,6 +98,7 @@ main(void) ao_pa_get(); pa_avg = pa_ground = pa << FILTER_SHIFT; sample_count = 0; + h = 0; for (;;) { time += SAMPLE_SLEEP; if (sample_count == 0) @@ -99,6 +107,8 @@ main(void) ao_pa_get(); if (sample_count == 0) ao_led_off(AO_LED_REPORT); + pa_hist[h] = pa; + h = SKIP_PA_HIST(h,1); pa_avg = pa_avg - (pa_avg >> FILTER_SHIFT) + pa; pa_diff = pa_ground - pa_avg; @@ -119,6 +129,19 @@ main(void) pa_ground >>= FILTER_SHIFT; + /* Go back and find the first sample a decent interval above the ground */ + pa_min = pa_ground - LAND_DETECT; + for (i = SKIP_PA_HIST(h,2); i != h; i = SKIP_PA_HIST(i,2)) { + if (pa_hist[i] < pa_min) + break; + } + + /* Log the remaining samples so we get a complete history since leaving the ground */ + for (; i != h; i = SKIP_PA_HIST(i,2)) { + pa = pa_hist[i]; + ao_log_micro_data(); + } + /* Now sit around until the pressure is stable again and record the max */ sample_count = 0; -- cgit v1.2.3