Initial Commit - Copy from Altus Metrum AltOS
This commit is contained in:
4
ao-tools/ao-view/.gitignore
vendored
Normal file
4
ao-tools/ao-view/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.o
|
||||
aoview
|
||||
aoview_glade.h
|
||||
aoview_flite
|
38
ao-tools/ao-view/Makefile.am
Normal file
38
ao-tools/ao-view/Makefile.am
Normal file
@@ -0,0 +1,38 @@
|
||||
VERSION=$(shell git describe)
|
||||
|
||||
AO_VIEW_CFLAGS=-I$(top_srcdir)/ao-tools/lib
|
||||
AO_VIEW_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
|
||||
AM_CFLAGS=$(WARN_CFLAGS) $(AO_VIEW_CFLAGS) $(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@
|
||||
|
||||
bin_PROGRAMS=ao-view
|
||||
|
||||
ao_view_DEPENDENCIES=$(AO_VIEW_LIBS)
|
||||
ao_view_LDADD=$(GNOME_LIBS) $(FLITE_LIBS) $(ALSA_LIBS) $(AO_VIEW_LIBS) $(LIBUSB_LIBS)
|
||||
|
||||
ao_view_SOURCES = \
|
||||
aoview_main.c \
|
||||
aoview_dev_dialog.c \
|
||||
aoview_serial.c \
|
||||
aoview_monitor.c \
|
||||
aoview_state.c \
|
||||
aoview_convert.c \
|
||||
aoview_log.c \
|
||||
aoview_table.c \
|
||||
aoview_util.c \
|
||||
aoview_file.c \
|
||||
aoview_eeprom.c \
|
||||
aoview_voice.c \
|
||||
aoview_replay.c \
|
||||
aoview_label.c \
|
||||
aoview_flite.c \
|
||||
aoview_channel.c \
|
||||
aoview.h
|
||||
|
||||
BUILT_SOURCES = aoview_glade.h
|
||||
|
||||
CLEANFILES = aoview_glade.h
|
||||
|
||||
man_MANS=ao-view.1
|
||||
|
||||
aoview_glade.h: aoview.glade
|
||||
sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@
|
50
ao-tools/ao-view/ao-view.1
Normal file
50
ao-tools/ao-view/ao-view.1
Normal file
@@ -0,0 +1,50 @@
|
||||
.\"
|
||||
.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation; either version 2 of the License, or
|
||||
.\" (at your option) any later version.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it will be useful, but
|
||||
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
.\" General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License along
|
||||
.\" with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
.\"
|
||||
.\"
|
||||
.TH AO-VIEW 1 "ao-view" ""
|
||||
.SH NAME
|
||||
ao-view \- Rocket flight monitor
|
||||
.SH SYNOPSIS
|
||||
.B "ao-view"
|
||||
[\--tty \fItty-device\fP]
|
||||
.SH DESCRIPTION
|
||||
.I ao-view
|
||||
connects to a TeleDongle or TeleMetrum device through a USB serial device.
|
||||
It provides a user interface to monitor, record and review rocket flight data.
|
||||
.SH OPTIONS
|
||||
The usual Gtk+ command line options can be used, along with
|
||||
.IP "\--tty"
|
||||
This selects a target device to connect at startup time to.
|
||||
The target device may also be selected through the user interface.
|
||||
.SH USAGE
|
||||
When connected to a TeleDongle device, ao-view turns on the radio
|
||||
receiver and listens for telemetry packets. It displays the received
|
||||
telemetry data, and reports flight status via voice synthesis. All
|
||||
received telemetry information is recorded to a file.
|
||||
.P
|
||||
When connected to a TeleMetrum device, ao-view downloads the eeprom
|
||||
data and stores it in a file.
|
||||
.SH FILES
|
||||
All data log files are recorded into a user-specified directory
|
||||
(default ~/AltOS). Files are named using the current date, the serial
|
||||
number of the reporting device, the flight number recorded in the data
|
||||
and either '.telem' for telemetry data or '.eeprom' for eeprom data.
|
||||
.SH "SEE ALSO"
|
||||
ao-load(1), ao-eeprom(1)
|
||||
.SH AUTHOR
|
||||
Keith Packard
|
845
ao-tools/ao-view/aoview.glade
Normal file
845
ao-tools/ao-view/aoview.glade
Normal file
@@ -0,0 +1,845 @@
|
||||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.16 -->
|
||||
<!-- interface-naming-policy project-wide -->
|
||||
<widget class="GtkWindow" id="aoview">
|
||||
<property name="width_request">900</property>
|
||||
<property name="height_request">700</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">AltOS View</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<widget class="GtkMenuBar" id="menubar1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_File</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem1">
|
||||
<property name="label">gtk-new</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem2">
|
||||
<property name="label">gtk-open</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem3">
|
||||
<property name="label">gtk-save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem4">
|
||||
<property name="label">gtk-save-as</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem5">
|
||||
<property name="label">gtk-quit</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="gtk_main_quit"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Edit</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem6">
|
||||
<property name="label">gtk-cut</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem7">
|
||||
<property name="label">gtk-copy</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem8">
|
||||
<property name="label">gtk-paste</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem9">
|
||||
<property name="label">gtk-delete</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Device</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu4">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="ao_connect">
|
||||
<property name="label" translatable="yes">_Connect to device</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate_item" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
|
||||
<signal name="activate" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-connect</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="ao_disconnect">
|
||||
<property name="label" translatable="yes">_Disconnect</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-disconnect</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="seperator">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="ao_savelog">
|
||||
<property name="label" translatable="yes">_Save EEPROM data</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate_item" handler="gtk_widget_show" object="device_connect_dialog" after="yes"/>
|
||||
<signal name="activate" handler="gtk_widget_show" object="device_connect_dialog"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image5">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-save</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="ao_replay">
|
||||
<property name="label" translatable="yes">_Replay</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate_item" handler="gtk_widget_show" object="ao_replay_dialog" after="yes"/>
|
||||
<signal name="activate" handler="gtk_widget_show" object="ao_replay_dialog"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image6">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-media-play</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Log</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu5">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="log_new">
|
||||
<property name="label" translatable="yes">_New log</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image3">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-new</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="file_configure">
|
||||
<property name="label" translatable="yes">_Configure Log</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">False</property>
|
||||
<signal name="activate" handler="gtk_widget_show" object="file_chooser_dialog" after="yes"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="image4">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-preferences</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Voice</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu6">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkCheckMenuItem" id="voice_enable">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Enable _Voice</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="active">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="channel_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Channel</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu7">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_0">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 0 (434.550MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 1 (434.650MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 2 (434.750MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 3 (434.850MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 4 (434.950MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 5 (435.050MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 6 (435.150MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 7 (435.250MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 8 (435.350MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkRadioMenuItem" id="channel_9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Channel 9 (435.450MHz)</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">channel_0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Help</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="imagemenuitem10">
|
||||
<property name="label">gtk-about</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="gtk_widget_show" object="about_dialog" after="yes"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkTable" id="table1">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">4</property>
|
||||
<property name="row_spacing">3</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="height_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Height (m)</property>
|
||||
<property name="justify">center</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="state_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">State</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="rssi_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">RSSI (dBm)</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="height_value">
|
||||
<property name="visible">True</property>
|
||||
<property name="ypad">2</property>
|
||||
<property name="label" translatable="yes">0</property>
|
||||
<property name="selectable">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="state_value">
|
||||
<property name="visible">True</property>
|
||||
<property name="ypad">2</property>
|
||||
<property name="label" translatable="yes">pad</property>
|
||||
<property name="selectable">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="rssi_value">
|
||||
<property name="visible">True</property>
|
||||
<property name="ypad">2</property>
|
||||
<property name="label" translatable="yes">-50</property>
|
||||
<property name="selectable">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="speed_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Speed (m/s)</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="right_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="speed_value">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">0</property>
|
||||
<property name="selectable">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="dataview_0">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_expanders">False</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="dataview_1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_expanders">False</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="dataview_2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="show_expanders">False</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkDialog" id="device_connect_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="dev_list">
|
||||
<property name="width_request">300</property>
|
||||
<property name="height_request">100</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_clickable">False</property>
|
||||
<property name="rules_hint">True</property>
|
||||
<property name="search_column">0</property>
|
||||
<property name="show_expanders">False</property>
|
||||
<property name="level_indentation">1</property>
|
||||
<property name="enable_grid_lines">both</property>
|
||||
<property name="enable_tree_lines">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="cancel_button">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="response_id">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="gtk_widget_hide" object="device_connect_dialog" after="yes"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="connect_button">
|
||||
<property name="label">gtk-connect</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkFileChooserDialog" id="file_chooser_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Configure Log Directory</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="has_separator">False</property>
|
||||
<property name="action">select-folder</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area2">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="file_configure_cancel">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="gtk_widget_hide" object="file_chooser_dialog"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="file_configure_ok">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkMessageDialog" id="file_fail_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Failed to create log</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="transient_for">aoview</property>
|
||||
<property name="message_type">error</property>
|
||||
<property name="buttons">close</property>
|
||||
<property name="text">Cannot create log file</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area4">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkMessageDialog" id="dev_open_fail_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Failed to open device</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="transient_for">aoview</property>
|
||||
<property name="message_type">error</property>
|
||||
<property name="buttons">close</property>
|
||||
<property name="text">Cannot open device</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area6">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkAboutDialog" id="about_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">About AoView</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="transient_for">aoview</property>
|
||||
<property name="has_separator">False</property>
|
||||
<property name="program_name">AoView</property>
|
||||
<property name="copyright" translatable="yes">Copyright © 2009 Keith Packard</property>
|
||||
<property name="comments" translatable="yes">AltOS data capture and display.</property>
|
||||
<property name="website">http://altusmetrum.org</property>
|
||||
<property name="license" translatable="yes">AoView is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
||||
|
||||
AoView 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 AoView; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</property>
|
||||
<property name="authors">Keith Packard <keithp@keithp.com></property>
|
||||
<property name="wrap_license">True</property>
|
||||
<signal name="close" handler="gtk_widget_hide" object="about_dialog" after="yes"/>
|
||||
<signal name="response" handler="gtk_widget_hide" object="about_dialog" after="yes"/>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area7">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkMessageDialog" id="ao_save_done">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">EEPROM save complete</property>
|
||||
<property name="type_hint">normal</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="transient_for">aoview</property>
|
||||
<property name="buttons">close</property>
|
||||
<property name="text">Saving EEPROM data as</property>
|
||||
<property name="secondary_text"><filename></property>
|
||||
<signal name="close" handler="gtk_widget_hide" object="ao_save_done"/>
|
||||
<signal name="response" handler="gtk_widget_hide" object="ao_save_done"/>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox11">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area11">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkFileChooserDialog" id="ao_replay_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="transient_for">aoview</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox10">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area10">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="ao_replay_cancel">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="gtk_widget_hide" object="ao_replay_dialog"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="ao_replay_ok">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
270
ao-tools/ao-view/aoview.h
Normal file
270
ao-tools/ao-view/aoview.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#ifndef _AOVIEW_H_
|
||||
#define _AOVIEW_H_
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glade/glade.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
|
||||
struct aostate {
|
||||
struct cc_telem data;
|
||||
|
||||
/* derived data */
|
||||
|
||||
struct cc_telem prev_data;
|
||||
|
||||
double report_time;
|
||||
|
||||
gboolean ascent; /* going up? */
|
||||
|
||||
int ground_altitude;
|
||||
int height;
|
||||
double speed;
|
||||
double acceleration;
|
||||
double battery;
|
||||
double temperature;
|
||||
double main_sense;
|
||||
double drogue_sense;
|
||||
double baro_speed;
|
||||
|
||||
int max_height;
|
||||
double max_acceleration;
|
||||
double max_speed;
|
||||
|
||||
struct cc_gps gps;
|
||||
struct cc_gps_tracking gps_tracking;
|
||||
|
||||
int gps_valid;
|
||||
double pad_lat;
|
||||
double pad_lon;
|
||||
double pad_alt;
|
||||
double pad_lat_total;
|
||||
double pad_lon_total;
|
||||
double pad_alt_total;
|
||||
int npad;
|
||||
int prev_npad;
|
||||
|
||||
double distance;
|
||||
double bearing;
|
||||
int gps_height;
|
||||
|
||||
int speak_tick;
|
||||
int speak_altitude;
|
||||
};
|
||||
|
||||
extern struct aostate aostate;
|
||||
|
||||
/* GPS is 'stable' when we've seen at least this many samples */
|
||||
#define MIN_PAD_SAMPLES 10
|
||||
|
||||
void
|
||||
aoview_monitor_disconnect(void);
|
||||
|
||||
gboolean
|
||||
aoview_monitor_connect(char *tty);
|
||||
|
||||
gboolean
|
||||
aoview_monitor_parse(const char *line);
|
||||
|
||||
void
|
||||
aoview_monitor_set_channel(int channel);
|
||||
|
||||
void
|
||||
aoview_monitor_reset(void);
|
||||
|
||||
struct aoview_serial *
|
||||
aoview_serial_open(const char *tty);
|
||||
|
||||
void
|
||||
aoview_serial_close(struct aoview_serial *serial);
|
||||
|
||||
typedef void (*aoview_serial_callback)(gpointer user_data, struct aoview_serial *serial, gint revents);
|
||||
|
||||
void
|
||||
aoview_serial_set_callback(struct aoview_serial *serial,
|
||||
aoview_serial_callback func);
|
||||
|
||||
void
|
||||
aoview_serial_printf(struct aoview_serial *serial, char *format, ...);
|
||||
|
||||
int
|
||||
aoview_serial_read(struct aoview_serial *serial, char *buf, int len);
|
||||
|
||||
int
|
||||
aoview_serial_getc(struct aoview_serial *serial);
|
||||
|
||||
void
|
||||
aoview_dev_dialog_init(GladeXML *xml);
|
||||
|
||||
void
|
||||
aoview_state_notify(struct cc_telem *data);
|
||||
|
||||
void
|
||||
aoview_state_new(void);
|
||||
|
||||
void
|
||||
aoview_state_init(GladeXML *xml);
|
||||
|
||||
int16_t
|
||||
aoview_pres_to_altitude(int16_t pres);
|
||||
|
||||
int16_t
|
||||
aoview_altitude_to_pres(int16_t alt);
|
||||
|
||||
char *
|
||||
aoview_fullname (char *dir, char *file);
|
||||
|
||||
char *
|
||||
aoview_basename(char *file);
|
||||
|
||||
GtkTreeViewColumn *
|
||||
aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width);
|
||||
|
||||
int
|
||||
aoview_mkdir(char *dir);
|
||||
|
||||
void
|
||||
aoview_log_init(GladeXML *xml);
|
||||
|
||||
void
|
||||
aoview_log_set_serial(int serial);
|
||||
|
||||
int
|
||||
aoview_log_get_serial(void);
|
||||
|
||||
void
|
||||
aoview_log_printf(char *format, ...);
|
||||
|
||||
void
|
||||
aoview_log_new(void);
|
||||
|
||||
void
|
||||
aoview_table_start(void);
|
||||
|
||||
void
|
||||
aoview_table_add_row(int column, char *label, char *format, ...);
|
||||
|
||||
void
|
||||
aoview_table_finish(void);
|
||||
|
||||
void
|
||||
aoview_table_init(GladeXML *xml);
|
||||
|
||||
void
|
||||
aoview_table_clear(void);
|
||||
|
||||
struct aoview_file;
|
||||
|
||||
extern char *aoview_file_dir;
|
||||
|
||||
void
|
||||
aoview_file_finish(struct aoview_file *file);
|
||||
|
||||
gboolean
|
||||
aoview_file_start(struct aoview_file *file);
|
||||
|
||||
const char *
|
||||
aoview_file_name(struct aoview_file *file);
|
||||
|
||||
void
|
||||
aoview_file_set_serial(struct aoview_file *file, int serial);
|
||||
|
||||
int
|
||||
aoview_file_get_serial(struct aoview_file *file);
|
||||
|
||||
void
|
||||
aoview_file_printf(struct aoview_file *file, char *format, ...);
|
||||
|
||||
void
|
||||
aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap);
|
||||
|
||||
struct aoview_file *
|
||||
aoview_file_new(char *ext);
|
||||
|
||||
void
|
||||
aoview_file_destroy(struct aoview_file *file);
|
||||
|
||||
void
|
||||
aoview_file_init(GladeXML *xml);
|
||||
|
||||
/* aoview_eeprom.c */
|
||||
|
||||
gboolean
|
||||
aoview_eeprom_save(const char *device);
|
||||
|
||||
void
|
||||
aoview_eeprom_init(GladeXML *xml);
|
||||
|
||||
/* aoview_voice.c */
|
||||
void aoview_voice_open(void);
|
||||
|
||||
void aoview_voice_close(void);
|
||||
|
||||
void aoview_voice_speak(char *format, ...);
|
||||
|
||||
/* aoview_label.c */
|
||||
|
||||
void aoview_label_init(GladeXML *xml);
|
||||
|
||||
void
|
||||
aoview_label_show(struct aostate *state);
|
||||
|
||||
/* aoview_flite.c */
|
||||
|
||||
FILE *
|
||||
aoview_flite_start(void);
|
||||
|
||||
void
|
||||
aoview_flite_stop(void);
|
||||
|
||||
/* aoview_main.c */
|
||||
|
||||
extern char *aoview_tty;
|
||||
|
||||
/* aoview_channel.c */
|
||||
|
||||
int
|
||||
aoview_channel_current(void);
|
||||
|
||||
void
|
||||
aoview_channel_init(GladeXML *xml);
|
||||
|
||||
#endif /* _AOVIEW_H_ */
|
91
ao-tools/ao-view/aoview_channel.c
Normal file
91
ao-tools/ao-view/aoview_channel.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
|
||||
#define NUM_CHANNEL 10
|
||||
|
||||
static GtkRadioMenuItem *channel_item[NUM_CHANNEL];
|
||||
|
||||
int
|
||||
aoview_channel_current(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < NUM_CHANNEL; c++)
|
||||
if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(channel_item[c])))
|
||||
return c;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_channel_notify(int channel)
|
||||
{
|
||||
if (0 <= channel && channel < NUM_CHANNEL)
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_item[channel]), TRUE);
|
||||
}
|
||||
|
||||
#define ALTOS_CHANNEL_PATH "/apps/aoview/channel"
|
||||
|
||||
static void
|
||||
aoview_channel_change(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
gboolean enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
|
||||
int c = (int) data;
|
||||
GConfClient *gconf_client;
|
||||
GError *error;
|
||||
|
||||
if (enabled) {
|
||||
aoview_monitor_set_channel(c);
|
||||
gconf_client = gconf_client_get_default();
|
||||
gconf_client_set_int(gconf_client, ALTOS_CHANNEL_PATH, c, &error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aoview_channel_init(GladeXML *xml)
|
||||
{
|
||||
int c;
|
||||
GConfClient *gconf_client;
|
||||
|
||||
for (c = 0; c < NUM_CHANNEL; c++) {
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "channel_%d", c);
|
||||
channel_item[c] = GTK_RADIO_MENU_ITEM(glade_xml_get_widget(xml, name));
|
||||
assert(channel_item[c]);
|
||||
g_signal_connect(G_OBJECT(channel_item[c]), "toggled",
|
||||
G_CALLBACK(aoview_channel_change),
|
||||
(gpointer) c);
|
||||
}
|
||||
gconf_client = gconf_client_get_default();
|
||||
c = 0;
|
||||
if (gconf_client)
|
||||
{
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
c = gconf_client_get_int(gconf_client,
|
||||
ALTOS_CHANNEL_PATH,
|
||||
&error);
|
||||
if (error)
|
||||
c = 0;
|
||||
}
|
||||
aoview_channel_notify(c);
|
||||
}
|
67
ao-tools/ao-view/aoview_convert.c
Normal file
67
ao-tools/ao-view/aoview_convert.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static int16_t altitude_table[] = {
|
||||
#include "altitude.h"
|
||||
};
|
||||
|
||||
#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS)
|
||||
#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1)
|
||||
|
||||
int16_t
|
||||
aoview_pres_to_altitude(int16_t pres)
|
||||
{
|
||||
uint8_t o;
|
||||
int16_t part;
|
||||
|
||||
if (pres < 0)
|
||||
pres = 0;
|
||||
o = pres >> ALT_FRAC_BITS;
|
||||
part = pres & ALT_FRAC_MASK;
|
||||
|
||||
return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) +
|
||||
(int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS;
|
||||
}
|
||||
|
||||
int16_t
|
||||
aoview_altitude_to_pres(int16_t alt)
|
||||
{
|
||||
int16_t span, sub_span;
|
||||
uint8_t l, h, m;
|
||||
int32_t pres;
|
||||
|
||||
l = 0;
|
||||
h = NALT - 1;
|
||||
while ((h - l) != 1) {
|
||||
m = (l + h) >> 1;
|
||||
if (altitude_table[m] < alt)
|
||||
h = m;
|
||||
else
|
||||
l = m;
|
||||
}
|
||||
span = altitude_table[l] - altitude_table[h];
|
||||
sub_span = altitude_table[l] - alt;
|
||||
pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span;
|
||||
if (pres > 32767)
|
||||
pres = 32767;
|
||||
if (pres < 0)
|
||||
pres = 0;
|
||||
return (int16_t) pres;
|
||||
}
|
174
ao-tools/ao-view/aoview_dev_dialog.c
Normal file
174
ao-tools/ao-view/aoview_dev_dialog.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static void
|
||||
aoview_dev_dialog_map(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkTreeView *dev_list = data;
|
||||
GtkListStore *list_store;
|
||||
GtkTreeIter iter;
|
||||
int ndev, n;
|
||||
struct cc_usbdevs *devs;
|
||||
struct cc_usbdev *dev;
|
||||
|
||||
list_store = gtk_list_store_new(3,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_STRING);
|
||||
|
||||
devs = cc_usbdevs_scan();
|
||||
if (devs) {
|
||||
for (n = 0; n < devs->ndev; n++) {
|
||||
dev = devs->dev[n];
|
||||
gtk_list_store_append(list_store, &iter);
|
||||
gtk_list_store_set(list_store, &iter,
|
||||
0, dev->product,
|
||||
1, dev->serial,
|
||||
2, dev->tty,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
gtk_tree_view_set_model (dev_list, GTK_TREE_MODEL(list_store));
|
||||
g_object_unref(G_OBJECT(list_store));
|
||||
gtk_tree_view_columns_autosize(dev_list);
|
||||
cc_usbdevs_free(devs);
|
||||
}
|
||||
|
||||
static GtkMessageDialog *dev_open_fail_dialog;
|
||||
|
||||
static void
|
||||
aoview_dev_open_failed(char *name)
|
||||
{
|
||||
char *utf8_file;
|
||||
utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
|
||||
if (!utf8_file)
|
||||
utf8_file = name;
|
||||
gtk_message_dialog_format_secondary_text(dev_open_fail_dialog,
|
||||
"\"%s\"", utf8_file);
|
||||
if (utf8_file != name)
|
||||
g_free(utf8_file);
|
||||
gtk_dialog_run(GTK_DIALOG(dev_open_fail_dialog));
|
||||
gtk_widget_hide(GTK_WIDGET(dev_open_fail_dialog));
|
||||
}
|
||||
|
||||
gboolean dialog_save_log;
|
||||
|
||||
static void
|
||||
aoview_dev_selected(GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *string;
|
||||
gtk_tree_model_get(model, iter,
|
||||
2, &string,
|
||||
-1);
|
||||
if (dialog_save_log) {
|
||||
dialog_save_log = FALSE;
|
||||
if (!aoview_eeprom_save(string))
|
||||
aoview_dev_open_failed(string);
|
||||
} else {
|
||||
if (!aoview_monitor_connect(string))
|
||||
aoview_dev_open_failed(string);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *dialog;
|
||||
|
||||
static void
|
||||
aoview_dev_dialog_connect(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkTreeView *dev_list = data;
|
||||
GtkListStore *list_store;
|
||||
GtkTreeSelection *tree_selection;
|
||||
|
||||
list_store = GTK_LIST_STORE(gtk_tree_view_get_model(dev_list));
|
||||
tree_selection = gtk_tree_view_get_selection(dev_list);
|
||||
gtk_tree_selection_selected_foreach(tree_selection,
|
||||
aoview_dev_selected,
|
||||
data);
|
||||
gtk_widget_hide(dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_dev_disconnect(GtkWidget *widget)
|
||||
{
|
||||
aoview_monitor_disconnect();
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_dev_savelog(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
dialog_save_log = TRUE;
|
||||
gtk_widget_show(dialog);
|
||||
}
|
||||
|
||||
#define _(a) a
|
||||
|
||||
void
|
||||
aoview_dev_dialog_init(GladeXML *xml)
|
||||
{
|
||||
GtkTreeView *dev_list;
|
||||
GtkWidget *connect_button;
|
||||
GtkTreeSelection *dev_selection;
|
||||
GtkWidget *ao_disconnect;
|
||||
GtkWidget *ao_savelog;
|
||||
|
||||
dialog = glade_xml_get_widget(xml, "device_connect_dialog");
|
||||
assert(dialog);
|
||||
|
||||
dev_list = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dev_list"));
|
||||
assert(dev_list);
|
||||
|
||||
aoview_add_plain_text_column(dev_list, _("Product"), 0, 16);
|
||||
aoview_add_plain_text_column(dev_list, _("Serial"), 1, 8);
|
||||
aoview_add_plain_text_column(dev_list, _("Device"), 2, 13);
|
||||
|
||||
dev_selection = gtk_tree_view_get_selection(dev_list);
|
||||
gtk_tree_selection_set_mode(dev_selection, GTK_SELECTION_SINGLE);
|
||||
|
||||
g_signal_connect(G_OBJECT(dialog), "map",
|
||||
G_CALLBACK(aoview_dev_dialog_map),
|
||||
dev_list);
|
||||
|
||||
connect_button = glade_xml_get_widget(xml, "connect_button");
|
||||
assert(connect_button);
|
||||
|
||||
g_signal_connect(G_OBJECT(connect_button), "clicked",
|
||||
G_CALLBACK(aoview_dev_dialog_connect),
|
||||
dev_list);
|
||||
|
||||
|
||||
ao_disconnect = glade_xml_get_widget(xml, "ao_disconnect");
|
||||
assert(ao_disconnect);
|
||||
|
||||
g_signal_connect(G_OBJECT(ao_disconnect), "activate",
|
||||
G_CALLBACK(aoview_dev_disconnect),
|
||||
ao_disconnect);
|
||||
|
||||
ao_savelog = glade_xml_get_widget(xml, "ao_savelog");
|
||||
assert(ao_savelog);
|
||||
|
||||
g_signal_connect(G_OBJECT(ao_savelog), "activate",
|
||||
G_CALLBACK(aoview_dev_savelog),
|
||||
dialog);
|
||||
dev_open_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "dev_open_fail_dialog"));
|
||||
assert(dev_open_fail_dialog);
|
||||
}
|
160
ao-tools/ao-view/aoview_eeprom.c
Normal file
160
ao-tools/ao-view/aoview_eeprom.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
#define EEPROM_LEN 1024
|
||||
|
||||
static struct aoview_file *eeprom_file;
|
||||
static char eeprom_line[EEPROM_LEN + 1];
|
||||
static int eeprom_pos;
|
||||
static GtkMessageDialog *eeprom_save_done;
|
||||
static GtkWidget *eeprom_save_close;
|
||||
static gboolean eeprom_save_shown;
|
||||
|
||||
static void
|
||||
aoview_eeprom_disconnect(struct aoview_serial *serial)
|
||||
{
|
||||
aoview_file_finish(eeprom_file);
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_eeprom_done(struct aoview_serial *serial)
|
||||
{
|
||||
gtk_window_set_title(GTK_WINDOW(eeprom_save_done),
|
||||
"EEPROM data saved");
|
||||
gtk_message_dialog_set_markup(eeprom_save_done,
|
||||
"<b>EEPROM data saved as</b>");
|
||||
if (!eeprom_save_shown)
|
||||
gtk_widget_show(GTK_WIDGET(eeprom_save_done));
|
||||
eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done));
|
||||
if (eeprom_save_close)
|
||||
gtk_widget_set_sensitive(eeprom_save_close, TRUE);
|
||||
aoview_eeprom_disconnect(serial);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
aoview_eeprom_parse(struct aoview_serial *serial,
|
||||
char *line)
|
||||
{
|
||||
char cmd;
|
||||
int tick;
|
||||
int a;
|
||||
int b;
|
||||
int serial_number;
|
||||
const char *name;
|
||||
char *utf8_name;
|
||||
|
||||
if (!strcmp(line, "end")) {
|
||||
aoview_eeprom_done(serial);
|
||||
return FALSE;
|
||||
}
|
||||
if (sscanf(line, "serial-number %u", &serial_number) == 1) {
|
||||
aoview_file_set_serial(eeprom_file, serial_number);
|
||||
} else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) {
|
||||
if (cmd == 'F')
|
||||
aoview_file_set_flight(eeprom_file, b);
|
||||
aoview_file_printf(eeprom_file, "%s\n", line);
|
||||
if (cmd == 'S' && a == 8) {
|
||||
aoview_eeprom_done(serial);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!eeprom_save_shown)
|
||||
{
|
||||
name = aoview_file_name(eeprom_file);
|
||||
if (name) {
|
||||
utf8_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
|
||||
if (!utf8_name)
|
||||
utf8_name = (char *) name;
|
||||
gtk_widget_set_sensitive(eeprom_save_close, FALSE);
|
||||
gtk_window_set_title(GTK_WINDOW(eeprom_save_done),
|
||||
"Saving EEPROM data");
|
||||
gtk_message_dialog_set_markup(eeprom_save_done,
|
||||
"<b>Saving EEPROM data as</b>");
|
||||
gtk_message_dialog_format_secondary_text(eeprom_save_done, "%s",
|
||||
utf8_name);
|
||||
if (utf8_name != name)
|
||||
g_free(utf8_name);
|
||||
gtk_container_check_resize(GTK_CONTAINER(eeprom_save_done));
|
||||
gtk_widget_show(GTK_WIDGET(eeprom_save_done));
|
||||
eeprom_save_shown = TRUE;
|
||||
eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done));
|
||||
if (eeprom_save_close)
|
||||
gtk_widget_set_sensitive(eeprom_save_close, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_eeprom_callback(gpointer user_data,
|
||||
struct aoview_serial *serial,
|
||||
gint revents)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (revents & (G_IO_HUP|G_IO_ERR)) {
|
||||
aoview_eeprom_disconnect(serial);
|
||||
return;
|
||||
}
|
||||
if (revents & G_IO_IN) {
|
||||
for (;;) {
|
||||
c = aoview_serial_getc(serial);
|
||||
if (c == -1)
|
||||
break;
|
||||
if (c == '\r')
|
||||
continue;
|
||||
if (c == '\n') {
|
||||
eeprom_line[eeprom_pos] = '\0';
|
||||
if (eeprom_pos)
|
||||
if (!aoview_eeprom_parse(serial, eeprom_line))
|
||||
break;
|
||||
eeprom_pos = 0;
|
||||
} else if (eeprom_pos < EEPROM_LEN)
|
||||
eeprom_line[eeprom_pos++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
aoview_eeprom_save(const char *device)
|
||||
{
|
||||
struct aoview_serial *serial;
|
||||
|
||||
gtk_widget_hide(GTK_WIDGET(eeprom_save_done));
|
||||
eeprom_save_shown = FALSE;
|
||||
serial = aoview_serial_open(device);
|
||||
if (!serial)
|
||||
return FALSE;
|
||||
aoview_serial_set_callback(serial, aoview_eeprom_callback);
|
||||
aoview_serial_printf(serial, "v\nl\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_eeprom_init(GladeXML *xml)
|
||||
{
|
||||
eeprom_file = aoview_file_new("eeprom");
|
||||
assert(eeprom_file);
|
||||
|
||||
eeprom_save_done = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "ao_save_done"));
|
||||
assert(eeprom_save_done);
|
||||
|
||||
}
|
236
ao-tools/ao-view/aoview_file.c
Normal file
236
ao-tools/ao-view/aoview_file.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
char *aoview_file_dir;
|
||||
|
||||
#define ALTOS_DIR_PATH "/apps/aoview/log_dir"
|
||||
#define DEFAULT_DIR "AltOS"
|
||||
|
||||
struct aoview_file {
|
||||
char *ext;
|
||||
FILE *file;
|
||||
char *name;
|
||||
int failed;
|
||||
int serial;
|
||||
int flight;
|
||||
int sequence;
|
||||
};
|
||||
|
||||
static void
|
||||
aoview_file_save_conf(void)
|
||||
{
|
||||
GConfClient *gconf_client;
|
||||
|
||||
gconf_client = gconf_client_get_default();
|
||||
if (gconf_client)
|
||||
{
|
||||
gconf_client_set_string(gconf_client,
|
||||
ALTOS_DIR_PATH,
|
||||
aoview_file_dir,
|
||||
NULL);
|
||||
g_object_unref(G_OBJECT(gconf_client));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_file_configure(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkFileChooser *chooser = data;
|
||||
aoview_file_dir = gtk_file_chooser_get_filename(chooser);
|
||||
aoview_file_save_conf();
|
||||
gtk_widget_hide(GTK_WIDGET(chooser));
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_finish(struct aoview_file *file)
|
||||
{
|
||||
if (file->file) {
|
||||
fclose(file->file);
|
||||
file->file = NULL;
|
||||
free(file->name);
|
||||
file->name = NULL;
|
||||
}
|
||||
file->failed = 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
aoview_file_name(struct aoview_file *file)
|
||||
{
|
||||
return file->name;
|
||||
}
|
||||
|
||||
static GtkMessageDialog *file_fail_dialog;
|
||||
|
||||
static void
|
||||
aoview_file_open_failed(char *name)
|
||||
{
|
||||
char *utf8_file;
|
||||
utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
|
||||
if (!utf8_file)
|
||||
utf8_file = name;
|
||||
gtk_message_dialog_format_secondary_text(file_fail_dialog,
|
||||
"\"%s\"", utf8_file);
|
||||
if (utf8_file != name)
|
||||
g_free(utf8_file);
|
||||
gtk_widget_show(GTK_WIDGET(file_fail_dialog));
|
||||
}
|
||||
|
||||
gboolean
|
||||
aoview_file_start(struct aoview_file *file)
|
||||
{
|
||||
char base[50];
|
||||
char seq[20];
|
||||
struct tm tm;
|
||||
time_t now;
|
||||
char *full;
|
||||
int r;
|
||||
|
||||
if (file->file)
|
||||
return TRUE;
|
||||
|
||||
if (file->failed)
|
||||
return FALSE;
|
||||
|
||||
full = cc_make_filename(file->serial, file->flight, file->ext);
|
||||
file->file = fopen(full, "w");
|
||||
if (!file->file) {
|
||||
aoview_file_open_failed(full);
|
||||
free(full);
|
||||
file->failed = 1;
|
||||
return FALSE;
|
||||
} else {
|
||||
setlinebuf(file->file);
|
||||
file->name = full;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap)
|
||||
{
|
||||
if (!aoview_file_start(file))
|
||||
return;
|
||||
vfprintf(file->file, format, ap);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_printf(struct aoview_file *file, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
aoview_file_vprintf(file, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
struct aoview_file *
|
||||
aoview_file_new(char *ext)
|
||||
{
|
||||
struct aoview_file *file;
|
||||
|
||||
file = calloc (1, sizeof (struct aoview_file));
|
||||
if (!file)
|
||||
return NULL;
|
||||
file->ext = strdup(ext);
|
||||
if (!file->ext) {
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_destroy(struct aoview_file *file)
|
||||
{
|
||||
if (file->file)
|
||||
fclose(file->file);
|
||||
if (file->name)
|
||||
free(file->name);
|
||||
free(file->ext);
|
||||
free(file);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_set_serial(struct aoview_file *file, int serial)
|
||||
{
|
||||
if (serial != file->serial)
|
||||
aoview_file_finish(file);
|
||||
file->serial = serial;
|
||||
}
|
||||
|
||||
int
|
||||
aoview_file_get_serial(struct aoview_file *file)
|
||||
{
|
||||
return file->serial;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_set_flight(struct aoview_file *file, int flight)
|
||||
{
|
||||
if (flight != file->flight)
|
||||
aoview_file_finish(file);
|
||||
file->flight = flight;
|
||||
}
|
||||
|
||||
int
|
||||
aoview_file_get_flight(struct aoview_file *file)
|
||||
{
|
||||
return file->flight;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_file_init(GladeXML *xml)
|
||||
{
|
||||
GConfClient *gconf_client;
|
||||
char *file_dir = NULL;
|
||||
GtkFileChooser *file_chooser_dialog;
|
||||
GtkWidget *file_configure_ok;
|
||||
|
||||
g_type_init();
|
||||
gconf_client = gconf_client_get_default();
|
||||
if (gconf_client)
|
||||
{
|
||||
file_dir = gconf_client_get_string(gconf_client,
|
||||
ALTOS_DIR_PATH,
|
||||
NULL);
|
||||
g_object_unref(G_OBJECT(gconf_client));
|
||||
}
|
||||
if (!file_dir) {
|
||||
aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR);
|
||||
aoview_file_save_conf();
|
||||
} else {
|
||||
aoview_file_dir = strdup(file_dir);
|
||||
}
|
||||
|
||||
file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog"));
|
||||
assert(file_chooser_dialog);
|
||||
gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir);
|
||||
|
||||
file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok");
|
||||
assert(file_configure_ok);
|
||||
|
||||
g_signal_connect(G_OBJECT(file_configure_ok), "clicked",
|
||||
G_CALLBACK(aoview_file_configure),
|
||||
file_chooser_dialog);
|
||||
|
||||
|
||||
file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog"));
|
||||
assert(file_fail_dialog);
|
||||
}
|
142
ao-tools/ao-view/aoview_flite.c
Normal file
142
ao-tools/ao-view/aoview_flite.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <flite/flite.h>
|
||||
#include "aoview.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
cst_voice *register_cmu_us_kal16();
|
||||
cst_voice *register_cmu_us_kal();
|
||||
|
||||
static cst_voice *voice;
|
||||
|
||||
static FILE *pipe_write;
|
||||
static GThread *aoview_flite_thread;
|
||||
|
||||
static snd_pcm_t *alsa_handle;
|
||||
|
||||
gpointer
|
||||
aoview_flite_task(gpointer data)
|
||||
{
|
||||
FILE *input = data;
|
||||
char line[1024];
|
||||
cst_wave *wave;
|
||||
int rate;
|
||||
int channels;
|
||||
int err;
|
||||
char *samples;
|
||||
int num_samples;
|
||||
|
||||
err = snd_pcm_open(&alsa_handle, "default",
|
||||
SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "alsa open failed %s\n",
|
||||
strerror(-err));
|
||||
alsa_handle = NULL;
|
||||
}
|
||||
rate = 0;
|
||||
channels = 0;
|
||||
while (fgets(line, sizeof (line) - 1, input) != NULL) {
|
||||
if (!alsa_handle)
|
||||
continue;
|
||||
wave = flite_text_to_wave(line, voice);
|
||||
if (wave->sample_rate != rate ||
|
||||
wave->num_channels != channels)
|
||||
{
|
||||
rate = wave->sample_rate;
|
||||
channels = wave->num_channels;
|
||||
err = snd_pcm_set_params(alsa_handle,
|
||||
SND_PCM_FORMAT_S16,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
channels,
|
||||
rate,
|
||||
1,
|
||||
100000);
|
||||
if (err < 0)
|
||||
fprintf(stderr, "alsa set_params error %s\n",
|
||||
strerror(-err));
|
||||
}
|
||||
err = snd_pcm_prepare(alsa_handle);
|
||||
if (err < 0)
|
||||
fprintf(stderr, "alsa pcm_prepare error %s\n",
|
||||
strerror(-err));
|
||||
samples = (char *) wave->samples;
|
||||
num_samples = wave->num_samples;
|
||||
while (num_samples > 0) {
|
||||
err = snd_pcm_writei(alsa_handle,
|
||||
samples, num_samples);
|
||||
if (err <= 0) {
|
||||
fprintf(stderr, "alsa write error %s\n",
|
||||
strerror(-err));
|
||||
break;
|
||||
}
|
||||
num_samples -= err;
|
||||
samples += err * 2 * channels;
|
||||
}
|
||||
snd_pcm_drain(alsa_handle);
|
||||
delete_wave(wave);
|
||||
}
|
||||
snd_pcm_close(alsa_handle);
|
||||
alsa_handle = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_flite_stop(void)
|
||||
{
|
||||
int status;
|
||||
if (pipe_write) {
|
||||
fclose(pipe_write);
|
||||
pipe_write = NULL;
|
||||
}
|
||||
if (aoview_flite_thread) {
|
||||
g_thread_join(aoview_flite_thread);
|
||||
aoview_flite_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
aoview_flite_start(void)
|
||||
{
|
||||
static once;
|
||||
int p[2];
|
||||
GError *error;
|
||||
FILE *pipe_read;
|
||||
|
||||
if (!once) {
|
||||
flite_init();
|
||||
#if HAVE_REGISTER_CMU_US_KAL16
|
||||
voice = register_cmu_us_kal16();
|
||||
#else
|
||||
#if HAVE_REGISTER_CMU_US_KAL
|
||||
voice = register_cmu_us_kal();
|
||||
#endif
|
||||
#endif
|
||||
if (!voice) {
|
||||
perror("register voice");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aoview_flite_stop();
|
||||
pipe(p);
|
||||
pipe_read = fdopen(p[0], "r");
|
||||
pipe_write = fdopen(p[1], "w");
|
||||
g_thread_create(aoview_flite_task, pipe_read, TRUE, &error);
|
||||
return pipe_write;
|
||||
}
|
74
ao-tools/ao-view/aoview_label.c
Normal file
74
ao-tools/ao-view/aoview_label.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
char *initial_value;
|
||||
GtkLabel *widget;
|
||||
} label_widgets[] = {
|
||||
{ "height_label", "Height (m)", NULL },
|
||||
{ "state_label", "State", NULL },
|
||||
{ "rssi_label", "RSSI (dBm)", NULL },
|
||||
{ "speed_label", "Speed (m/s)", NULL },
|
||||
{ "height_value", "0", NULL },
|
||||
{ "state_value", "pad", NULL },
|
||||
{ "rssi_value", "-50", NULL },
|
||||
{ "speed_value", "0", NULL },
|
||||
};
|
||||
|
||||
static void
|
||||
aoview_label_assign(GtkLabel *widget, char *value)
|
||||
{
|
||||
char *markup;
|
||||
|
||||
markup = g_markup_printf_escaped("<span font_weight=\"bold\" size=\"xx-large\">%s</span>", value);
|
||||
gtk_label_set_markup(widget, markup);
|
||||
g_free(markup);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_label_show(struct aostate *state)
|
||||
{
|
||||
char line[1024];
|
||||
sprintf(line, "%d", state->height);
|
||||
aoview_label_assign(label_widgets[4].widget, line);
|
||||
|
||||
aoview_label_assign(label_widgets[5].widget, state->data.state);
|
||||
|
||||
sprintf(line, "%d", state->data.rssi);
|
||||
aoview_label_assign(label_widgets[6].widget, line);
|
||||
|
||||
if (state->ascent)
|
||||
sprintf(line, "%6.0f", fabs(state->speed));
|
||||
else
|
||||
sprintf(line, "%6.0f", fabs(state->baro_speed));
|
||||
aoview_label_assign(label_widgets[7].widget, line);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_label_init(GladeXML *xml)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizeof(label_widgets)/sizeof(label_widgets[0]); i++) {
|
||||
label_widgets[i].widget = GTK_LABEL(glade_xml_get_widget(xml, label_widgets[i].name));
|
||||
aoview_label_assign(label_widgets[i].widget, label_widgets[i].initial_value);
|
||||
assert(label_widgets[i].widget);
|
||||
}
|
||||
}
|
83
ao-tools/ao-view/aoview_log.c
Normal file
83
ao-tools/ao-view/aoview_log.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static struct aoview_file *aoview_log;
|
||||
|
||||
void
|
||||
aoview_log_new(void)
|
||||
{
|
||||
aoview_file_finish(aoview_log);
|
||||
aoview_state_new();
|
||||
}
|
||||
|
||||
void
|
||||
aoview_log_set_serial(int serial)
|
||||
{
|
||||
aoview_file_set_serial(aoview_log, serial);
|
||||
}
|
||||
|
||||
int
|
||||
aoview_log_get_serial(void)
|
||||
{
|
||||
return aoview_file_get_serial(aoview_log);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_log_set_flight(int flight)
|
||||
{
|
||||
aoview_file_set_flight(aoview_log, flight);
|
||||
}
|
||||
|
||||
int
|
||||
aoview_log_get_flight(void)
|
||||
{
|
||||
return aoview_file_get_flight(aoview_log);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_log_printf(char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
aoview_file_vprintf(aoview_log, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_log_new_item(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
aoview_file_finish(aoview_log);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_log_init(GladeXML *xml)
|
||||
{
|
||||
GtkWidget *log_new;
|
||||
|
||||
aoview_log = aoview_file_new("telem");
|
||||
assert(aoview_log);
|
||||
|
||||
log_new = glade_xml_get_widget(xml, "log_new");
|
||||
assert(log_new);
|
||||
g_signal_connect(G_OBJECT(log_new), "activate",
|
||||
G_CALLBACK(aoview_log_new_item),
|
||||
NULL);
|
||||
}
|
114
ao-tools/ao-view/aoview_main.c
Normal file
114
ao-tools/ao-view/aoview_main.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static const char aoview_glade[] = {
|
||||
#include "aoview_glade.h"
|
||||
};
|
||||
|
||||
static void usage(void) {
|
||||
printf("aoview [--device|-d device_file]");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void destroy_event(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
char *aoview_tty = NULL;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GladeXML *xml = NULL;
|
||||
GtkWidget *mainwindow;
|
||||
GtkAboutDialog *about_dialog;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "tty", 1, 0, 'T'},
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
for (;;) {
|
||||
int c, temp;
|
||||
|
||||
c = getopt_long_only(argc, argv, "T:", long_options, &temp);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'T':
|
||||
aoview_tty = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
g_thread_init(NULL);
|
||||
gtk_init(&argc, &argv);
|
||||
glade_init();
|
||||
|
||||
xml = glade_xml_new_from_buffer(aoview_glade, sizeof (aoview_glade), NULL, NULL);
|
||||
|
||||
/* connect the signals in the interface */
|
||||
glade_xml_signal_autoconnect(xml);
|
||||
|
||||
/* Hook up the close button. */
|
||||
mainwindow = glade_xml_get_widget(xml, "aoview");
|
||||
assert(mainwindow);
|
||||
|
||||
g_signal_connect (G_OBJECT(mainwindow), "destroy",
|
||||
G_CALLBACK(destroy_event), NULL);
|
||||
|
||||
about_dialog = GTK_ABOUT_DIALOG(glade_xml_get_widget(xml, "about_dialog"));
|
||||
assert(about_dialog);
|
||||
gtk_about_dialog_set_version(about_dialog, AOVIEW_VERSION);
|
||||
|
||||
aoview_voice_init(xml);
|
||||
|
||||
aoview_channel_init(xml);
|
||||
|
||||
aoview_dev_dialog_init(xml);
|
||||
|
||||
aoview_state_init(xml);
|
||||
|
||||
aoview_file_init(xml);
|
||||
|
||||
aoview_log_init(xml);
|
||||
|
||||
aoview_table_init(xml);
|
||||
|
||||
aoview_eeprom_init(xml);
|
||||
|
||||
aoview_replay_init(xml);
|
||||
|
||||
aoview_label_init(xml);
|
||||
|
||||
if (aoview_tty) {
|
||||
if (!aoview_monitor_connect(aoview_tty)) {
|
||||
perror(aoview_tty);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
aoview_voice_speak("rocket flight monitor ready\n");
|
||||
|
||||
gtk_main();
|
||||
|
||||
return 0;
|
||||
}
|
109
ao-tools/ao-view/aoview_monitor.c
Normal file
109
ao-tools/ao-view/aoview_monitor.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static struct aoview_serial *monitor_serial;
|
||||
|
||||
#define MONITOR_LEN 1024
|
||||
|
||||
static char monitor_line[MONITOR_LEN + 1];
|
||||
static int monitor_pos;
|
||||
|
||||
void
|
||||
aoview_monitor_disconnect(void)
|
||||
{
|
||||
if (monitor_serial) {
|
||||
aoview_serial_close(monitor_serial);
|
||||
monitor_serial = NULL;
|
||||
}
|
||||
aoview_log_new();
|
||||
}
|
||||
|
||||
gboolean
|
||||
aoview_monitor_parse(const char *input_line)
|
||||
{
|
||||
struct cc_telem telem;
|
||||
|
||||
if (!cc_telem_parse(input_line, &telem))
|
||||
return FALSE;
|
||||
aoview_state_notify(&telem);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_monitor_callback(gpointer user_data,
|
||||
struct aoview_serial *serial,
|
||||
gint revents)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (revents & (G_IO_HUP|G_IO_ERR)) {
|
||||
aoview_monitor_disconnect();
|
||||
return;
|
||||
}
|
||||
if (revents & G_IO_IN) {
|
||||
for (;;) {
|
||||
c = aoview_serial_getc(serial);
|
||||
if (c == -1)
|
||||
break;
|
||||
if (c == '\r')
|
||||
continue;
|
||||
if (c == '\n') {
|
||||
monitor_line[monitor_pos] = '\0';
|
||||
if (monitor_pos) {
|
||||
if (aoview_monitor_parse(monitor_line)) {
|
||||
aoview_log_set_serial(aostate.data.serial);
|
||||
aoview_log_set_flight(aostate.data.flight);
|
||||
if (aoview_log_get_serial())
|
||||
aoview_log_printf ("%s\n", monitor_line);
|
||||
}
|
||||
}
|
||||
monitor_pos = 0;
|
||||
} else if (monitor_pos < MONITOR_LEN)
|
||||
monitor_line[monitor_pos++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aoview_monitor_set_channel(int channel)
|
||||
{
|
||||
if (monitor_serial) {
|
||||
aoview_serial_printf(monitor_serial, "m 0\n");
|
||||
aoview_serial_printf(monitor_serial, "c r %d\n", channel);
|
||||
aoview_serial_printf(monitor_serial, "m 1\n");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
aoview_monitor_connect(char *tty)
|
||||
{
|
||||
int channel;
|
||||
aoview_monitor_disconnect();
|
||||
monitor_serial = aoview_serial_open(tty);
|
||||
if (!monitor_serial)
|
||||
return FALSE;
|
||||
aoview_table_clear();
|
||||
aoview_state_reset();
|
||||
channel = aoview_channel_current();
|
||||
aoview_monitor_set_channel(channel);
|
||||
aoview_serial_set_callback(monitor_serial,
|
||||
aoview_monitor_callback);
|
||||
return TRUE;
|
||||
}
|
148
ao-tools/ao-view/aoview_replay.c
Normal file
148
ao-tools/ao-view/aoview_replay.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
static GtkFileChooser *replay_dialog;
|
||||
static GtkWidget *replay_ok;
|
||||
static FILE *replay_file;
|
||||
static int replay_tick;
|
||||
|
||||
static int
|
||||
find_tick(char *line, gboolean *is_pad)
|
||||
{
|
||||
char *state = strstr(line, "STATE");
|
||||
if (!state)
|
||||
return -1;
|
||||
state = strchr(state, ' ');
|
||||
if (!state)
|
||||
return -1;
|
||||
while (*state == ' ')
|
||||
state++;
|
||||
*is_pad = strncmp(state, "pad", 3) == 0;
|
||||
while (*state && !isdigit(*state))
|
||||
state++;
|
||||
return atoi(state);
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_replay_close(void)
|
||||
{
|
||||
if (replay_file) {
|
||||
fclose(replay_file);
|
||||
replay_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static char replay_line[1024];
|
||||
|
||||
static gboolean
|
||||
aoview_replay_read(gpointer data);
|
||||
|
||||
static gboolean
|
||||
aoview_replay_execute(gpointer data)
|
||||
{
|
||||
aoview_monitor_parse(replay_line);
|
||||
g_idle_add(aoview_replay_read, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
aoview_replay_read(gpointer data)
|
||||
{
|
||||
int tick;
|
||||
gboolean is_pad;
|
||||
|
||||
if (!replay_file)
|
||||
return FALSE;
|
||||
if (fgets(replay_line, sizeof (replay_line), replay_file)) {
|
||||
tick = find_tick(replay_line, &is_pad);
|
||||
if (tick >= 0 && replay_tick >= 0 && !is_pad) {
|
||||
while (tick < replay_tick)
|
||||
tick += 65536;
|
||||
g_timeout_add((tick - replay_tick) * 10,
|
||||
aoview_replay_execute,
|
||||
NULL);
|
||||
} else {
|
||||
aoview_replay_execute(NULL);
|
||||
}
|
||||
replay_tick = tick;
|
||||
} else {
|
||||
aoview_replay_close();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_replay_open(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
char *replay_file_name;
|
||||
GtkWidget *dialog;
|
||||
|
||||
aoview_replay_close();
|
||||
replay_file_name = gtk_file_chooser_get_filename(replay_dialog);
|
||||
replay_file = fopen(replay_file_name, "r");
|
||||
if (!replay_file) {
|
||||
dialog = gtk_message_dialog_new(GTK_WINDOW(replay_dialog),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"Error loading file '%s': %s",
|
||||
replay_file_name, g_strerror(errno));
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
} else {
|
||||
replay_tick = -1;
|
||||
aoview_state_reset();
|
||||
aoview_replay_read(NULL);
|
||||
}
|
||||
gtk_widget_hide(GTK_WIDGET(replay_dialog));
|
||||
}
|
||||
|
||||
void
|
||||
aoview_replay_init(GladeXML *xml)
|
||||
{
|
||||
GtkFileFilter *telem_filter;
|
||||
GtkFileFilter *all_filter;
|
||||
GtkFileFilter *log_filter;
|
||||
|
||||
telem_filter = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(telem_filter, "*.telem");
|
||||
gtk_file_filter_set_name(telem_filter, "Telemetry Files");
|
||||
|
||||
log_filter = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(log_filter, "*.log");
|
||||
gtk_file_filter_set_name(log_filter, "Log Files");
|
||||
|
||||
all_filter = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(all_filter, "*");
|
||||
gtk_file_filter_set_name(all_filter, "All Files");
|
||||
|
||||
replay_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "ao_replay_dialog"));
|
||||
assert(replay_dialog);
|
||||
gtk_file_chooser_set_current_folder(replay_dialog, aoview_file_dir);
|
||||
gtk_file_chooser_add_filter(replay_dialog, telem_filter);
|
||||
gtk_file_chooser_add_filter(replay_dialog, log_filter);
|
||||
gtk_file_chooser_add_filter(replay_dialog, all_filter);
|
||||
|
||||
replay_ok = glade_xml_get_widget(xml, "ao_replay_ok");
|
||||
assert(replay_ok);
|
||||
g_signal_connect(G_OBJECT(replay_ok), "clicked",
|
||||
G_CALLBACK(aoview_replay_open),
|
||||
replay_dialog);
|
||||
}
|
271
ao-tools/ao-view/aoview_serial.c
Normal file
271
ao-tools/ao-view/aoview_serial.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
#include <termios.h>
|
||||
|
||||
#define AOVIEW_SERIAL_IN_BUF 64
|
||||
#define AOVIEW_SERIAL_OUT_BUF 64
|
||||
|
||||
struct aoview_buf {
|
||||
char *buf;
|
||||
int off;
|
||||
int count;
|
||||
int size;
|
||||
};
|
||||
|
||||
static int
|
||||
aoview_buf_write(struct aoview_buf *buf, char *data, int len)
|
||||
{
|
||||
if (buf->count + len > buf->size) {
|
||||
int new_size = buf->size * 2;
|
||||
if (new_size == 0)
|
||||
new_size = 1024;
|
||||
if (buf->buf)
|
||||
buf->buf = realloc (buf->buf, new_size);
|
||||
else
|
||||
buf->buf = malloc (new_size);
|
||||
buf->size = new_size;
|
||||
}
|
||||
memcpy(buf->buf + buf->count, data, len);
|
||||
buf->count += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
aoview_buf_read(struct aoview_buf *buf, char *data, int len)
|
||||
{
|
||||
if (len > buf->count - buf->off)
|
||||
len = buf->count - buf->off;
|
||||
memcpy (data, buf->buf + buf->off, len);
|
||||
buf->off += len;
|
||||
if (buf->off == buf->count)
|
||||
buf->off = buf->count = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
aoview_buf_getc(struct aoview_buf *buf)
|
||||
{
|
||||
char b;
|
||||
int r;
|
||||
|
||||
r = aoview_buf_read(buf, &b, 1);
|
||||
if (r == 1)
|
||||
return (int) b;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_buf_flush(struct aoview_buf *buf, int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (buf->count > buf->off) {
|
||||
ret = write(fd, buf->buf + buf->off, buf->count - buf->off);
|
||||
if (ret > 0) {
|
||||
buf->off += ret;
|
||||
if (buf->off == buf->count)
|
||||
buf->off = buf->count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_buf_fill(struct aoview_buf *buf, int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while (buf->count >= buf->size) {
|
||||
int new_size = buf->size * 2;
|
||||
buf->buf = realloc (buf->buf, new_size);
|
||||
buf->size = new_size;
|
||||
}
|
||||
|
||||
ret = read(fd, buf->buf + buf->count, buf->size - buf->count);
|
||||
if (ret > 0)
|
||||
buf->count += ret;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_buf_init(struct aoview_buf *buf)
|
||||
{
|
||||
buf->buf = malloc (buf->size = 1024);
|
||||
buf->count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_buf_fini(struct aoview_buf *buf)
|
||||
{
|
||||
free(buf->buf);
|
||||
}
|
||||
|
||||
struct aoview_serial {
|
||||
GSource source;
|
||||
int fd;
|
||||
struct termios save_termios;
|
||||
struct aoview_buf in_buf;
|
||||
struct aoview_buf out_buf;
|
||||
GPollFD poll_fd;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
aoview_serial_printf(struct aoview_serial *serial, char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
/* sprintf to a local buffer */
|
||||
va_start(ap, format);
|
||||
ret = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
if (ret > sizeof(buf)) {
|
||||
fprintf(stderr, "printf overflow for format %s\n",
|
||||
format);
|
||||
}
|
||||
|
||||
/* flush local buffer to the wire */
|
||||
aoview_buf_write(&serial->out_buf, buf, ret);
|
||||
aoview_buf_flush(&serial->out_buf, serial->fd);
|
||||
}
|
||||
|
||||
int
|
||||
aoview_serial_read(struct aoview_serial *serial, char *buf, int len)
|
||||
{
|
||||
return aoview_buf_read(&serial->in_buf, buf, len);
|
||||
}
|
||||
|
||||
int
|
||||
aoview_serial_getc(struct aoview_serial *serial)
|
||||
{
|
||||
return aoview_buf_getc(&serial->in_buf);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
serial_prepare(GSource *source, gint *timeout)
|
||||
{
|
||||
struct aoview_serial *serial = (struct aoview_serial *) source;
|
||||
*timeout = -1;
|
||||
|
||||
if (serial->out_buf.count)
|
||||
serial->poll_fd.events |= G_IO_OUT;
|
||||
else
|
||||
serial->poll_fd.events &= ~G_IO_OUT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
serial_check(GSource *source)
|
||||
{
|
||||
struct aoview_serial *serial = (struct aoview_serial *) source;
|
||||
gint revents = serial->poll_fd.revents;
|
||||
|
||||
if (revents & G_IO_NVAL)
|
||||
return FALSE;
|
||||
if (revents & G_IO_IN)
|
||||
return TRUE;
|
||||
if (revents & G_IO_OUT)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
serial_dispatch(GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct aoview_serial *serial = (struct aoview_serial *) source;
|
||||
aoview_serial_callback func = (aoview_serial_callback) callback;
|
||||
gint revents = serial->poll_fd.revents;
|
||||
|
||||
if (revents & G_IO_IN)
|
||||
aoview_buf_fill(&serial->in_buf, serial->fd);
|
||||
|
||||
if (revents & G_IO_OUT)
|
||||
aoview_buf_flush(&serial->out_buf, serial->fd);
|
||||
|
||||
if (func)
|
||||
(*func)(user_data, serial, revents);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
serial_finalize(GSource *source)
|
||||
{
|
||||
struct aoview_serial *serial = (struct aoview_serial *) source;
|
||||
|
||||
aoview_buf_fini(&serial->in_buf);
|
||||
aoview_buf_fini(&serial->out_buf);
|
||||
tcsetattr(serial->fd, TCSAFLUSH, &serial->save_termios);
|
||||
close (serial->fd);
|
||||
}
|
||||
|
||||
static GSourceFuncs serial_funcs = {
|
||||
serial_prepare,
|
||||
serial_check,
|
||||
serial_dispatch,
|
||||
serial_finalize
|
||||
};
|
||||
|
||||
struct aoview_serial *
|
||||
aoview_serial_open(const char *tty)
|
||||
{
|
||||
struct aoview_serial *serial;
|
||||
struct termios termios;
|
||||
|
||||
serial = (struct aoview_serial *) g_source_new(&serial_funcs, sizeof (struct aoview_serial));
|
||||
aoview_buf_init(&serial->in_buf);
|
||||
aoview_buf_init(&serial->out_buf);
|
||||
serial->fd = open (tty, O_RDWR | O_NONBLOCK);
|
||||
if (serial->fd < 0) {
|
||||
g_source_destroy(&serial->source);
|
||||
return NULL;
|
||||
}
|
||||
tcgetattr(serial->fd, &termios);
|
||||
serial->save_termios = termios;
|
||||
cfmakeraw(&termios);
|
||||
tcsetattr(serial->fd, TCSAFLUSH, &termios);
|
||||
|
||||
aoview_serial_printf(serial, "E 0\n");
|
||||
tcdrain(serial->fd);
|
||||
usleep(15*1000);
|
||||
tcflush(serial->fd, TCIFLUSH);
|
||||
serial->poll_fd.fd = serial->fd;
|
||||
serial->poll_fd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
|
||||
g_source_attach(&serial->source, NULL);
|
||||
g_source_add_poll(&serial->source,&serial->poll_fd);
|
||||
aoview_serial_set_callback(serial, NULL);
|
||||
return serial;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_serial_close(struct aoview_serial *serial)
|
||||
{
|
||||
g_source_remove_poll(&serial->source, &serial->poll_fd);
|
||||
close(serial->fd);
|
||||
g_source_destroy(&serial->source);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_serial_set_callback(struct aoview_serial *serial,
|
||||
aoview_serial_callback func)
|
||||
{
|
||||
g_source_set_callback(&serial->source, (GSourceFunc) func, serial, NULL);
|
||||
}
|
372
ao-tools/ao-view/aoview_state.c
Normal file
372
ao-tools/ao-view/aoview_state.c
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
#include <math.h>
|
||||
|
||||
static inline double sqr(double a) { return a * a; };
|
||||
|
||||
static void
|
||||
aoview_great_circle (double start_lat, double start_lon,
|
||||
double end_lat, double end_lon,
|
||||
double *dist, double *bearing)
|
||||
{
|
||||
const double rad = M_PI / 180;
|
||||
const double earth_radius = 6371.2 * 1000; /* in meters */
|
||||
double lat1 = rad * start_lat;
|
||||
double lon1 = rad * -start_lon;
|
||||
double lat2 = rad * end_lat;
|
||||
double lon2 = rad * -end_lon;
|
||||
|
||||
double d_lat = lat2 - lat1;
|
||||
double d_lon = lon2 - lon1;
|
||||
|
||||
/* From http://en.wikipedia.org/wiki/Great-circle_distance */
|
||||
double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) +
|
||||
sqr(cos(lat1) * sin(lat2) -
|
||||
sin(lat1) * cos(lat2) * cos(d_lon)));
|
||||
double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon);
|
||||
double d = atan2(vdn,vdd);
|
||||
double course;
|
||||
|
||||
if (cos(lat1) < 1e-20) {
|
||||
if (lat1 > 0)
|
||||
course = M_PI;
|
||||
else
|
||||
course = -M_PI;
|
||||
} else {
|
||||
if (d < 1e-10)
|
||||
course = 0;
|
||||
else
|
||||
course = acos((sin(lat2)-sin(lat1)*cos(d)) /
|
||||
(sin(d)*cos(lat1)));
|
||||
if (sin(lon2-lon1) > 0)
|
||||
course = 2 * M_PI-course;
|
||||
}
|
||||
*dist = d * earth_radius;
|
||||
*bearing = course * 180/M_PI;
|
||||
}
|
||||
|
||||
static void
|
||||
aoview_state_add_deg(int column, char *label, double deg, char pos, char neg)
|
||||
{
|
||||
double int_part;
|
||||
double min;
|
||||
char sign = pos;
|
||||
|
||||
if (deg < 0) {
|
||||
deg = -deg;
|
||||
sign = neg;
|
||||
}
|
||||
int_part = floor (deg);
|
||||
min = (deg - int_part) * 60.0;
|
||||
aoview_table_add_row(column, label, "%d°%lf'%c",
|
||||
(int) int_part, min, sign);
|
||||
|
||||
}
|
||||
|
||||
static char *ascent_states[] = {
|
||||
"boost",
|
||||
"fast",
|
||||
"coast",
|
||||
0,
|
||||
};
|
||||
|
||||
static double
|
||||
aoview_time(void)
|
||||
{
|
||||
struct timespec now;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return (double) now.tv_sec + (double) now.tv_nsec / 1.0e9;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill out the derived data fields
|
||||
*/
|
||||
static void
|
||||
aoview_state_derive(struct cc_telem *data, struct aostate *state)
|
||||
{
|
||||
int i;
|
||||
double new_height;
|
||||
double height_change;
|
||||
double time_change;
|
||||
double accel_counts_per_mss;
|
||||
int tick_count;
|
||||
|
||||
state->report_time = aoview_time();
|
||||
|
||||
state->prev_data = state->data;
|
||||
state->prev_npad = state->npad;
|
||||
state->data = *data;
|
||||
tick_count = data->tick;
|
||||
if (tick_count < state->prev_data.tick)
|
||||
tick_count += 65536;
|
||||
time_change = (tick_count - state->prev_data.tick) / 100.0;
|
||||
|
||||
state->ground_altitude = aoview_pres_to_altitude(data->ground_pres);
|
||||
new_height = aoview_pres_to_altitude(data->flight_pres) - state->ground_altitude;
|
||||
height_change = new_height - state->height;
|
||||
state->height = new_height;
|
||||
if (time_change)
|
||||
state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0;
|
||||
accel_counts_per_mss = ((data->accel_minus_g - data->accel_plus_g) / 2.0) / 9.80665;
|
||||
state->acceleration = (data->ground_accel - data->flight_accel) / accel_counts_per_mss;
|
||||
state->speed = data->flight_vel / (accel_counts_per_mss * 100.0);
|
||||
state->temperature = cc_thermometer_to_temperature(data->temp);
|
||||
state->drogue_sense = cc_ignitor_to_voltage(data->drogue);
|
||||
state->main_sense = cc_ignitor_to_voltage(data->main);
|
||||
state->battery = cc_battery_to_voltage(data->batt);
|
||||
if (!strcmp(data->state, "pad")) {
|
||||
if (data->gps.gps_locked && data->gps.nsat >= 4) {
|
||||
state->npad++;
|
||||
state->pad_lat_total += data->gps.lat;
|
||||
state->pad_lon_total += data->gps.lon;
|
||||
state->pad_alt_total += data->gps.alt;
|
||||
if (state->npad > 1) {
|
||||
state->pad_lat = (state->pad_lat * 31 + data->gps.lat) / 32.0;
|
||||
state->pad_lon = (state->pad_lon * 31 + data->gps.lon) / 32.0;
|
||||
state->pad_alt = (state->pad_alt * 31 + data->gps.alt) / 32.0;
|
||||
} else {
|
||||
state->pad_lat = data->gps.lat;
|
||||
state->pad_lon = data->gps.lon;
|
||||
state->pad_alt = data->gps.alt;
|
||||
}
|
||||
}
|
||||
}
|
||||
state->ascent = FALSE;
|
||||
for (i = 0; ascent_states[i]; i++)
|
||||
if (!strcmp(data->state, ascent_states[i]))
|
||||
state->ascent = TRUE;
|
||||
|
||||
/* Only look at accelerometer data on the way up */
|
||||
if (state->ascent && state->acceleration > state->max_acceleration)
|
||||
state->max_acceleration = state->acceleration;
|
||||
if (state->ascent && state->speed > state->max_speed)
|
||||
state->max_speed = state->speed;
|
||||
|
||||
if (state->height > state->max_height)
|
||||
state->max_height = state->height;
|
||||
state->gps.gps_locked = data->gps.gps_locked;
|
||||
state->gps.gps_connected = data->gps.gps_connected;
|
||||
if (data->gps.gps_locked) {
|
||||
state->gps = data->gps;
|
||||
state->gps_valid = 1;
|
||||
if (state->npad)
|
||||
aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon,
|
||||
&state->distance, &state->bearing);
|
||||
}
|
||||
if (data->gps_tracking.channels)
|
||||
state->gps_tracking = data->gps_tracking;
|
||||
if (state->npad) {
|
||||
state->gps_height = state->gps.alt - state->pad_alt;
|
||||
} else {
|
||||
state->gps_height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aoview_speak_state(struct aostate *state)
|
||||
{
|
||||
if (strcmp(state->data.state, state->prev_data.state)) {
|
||||
aoview_voice_speak("%s\n", state->data.state);
|
||||
if (!strcmp(state->data.state, "drogue"))
|
||||
aoview_voice_speak("apogee %d meters\n",
|
||||
(int) state->max_height);
|
||||
if (!strcmp(state->prev_data.state, "boost"))
|
||||
aoview_voice_speak("max speed %d meters per second\n",
|
||||
(int) state->max_speed);
|
||||
}
|
||||
if (state->prev_npad < MIN_PAD_SAMPLES && state->npad >= MIN_PAD_SAMPLES)
|
||||
aoview_voice_speak("g p s ready\n");
|
||||
}
|
||||
|
||||
void
|
||||
aoview_speak_height(struct aostate *state)
|
||||
{
|
||||
aoview_voice_speak("%d meters\n", state->height);
|
||||
}
|
||||
|
||||
struct aostate aostate;
|
||||
|
||||
static guint aostate_timeout;
|
||||
|
||||
#define COMPASS_LIMIT(n) ((n * 22.5) + 22.5/2)
|
||||
|
||||
static char *compass_points[] = {
|
||||
"north",
|
||||
"north north east",
|
||||
"north east",
|
||||
"east north east",
|
||||
"east",
|
||||
"east south east",
|
||||
"south east",
|
||||
"south south east",
|
||||
"south",
|
||||
"south south west",
|
||||
"south west",
|
||||
"west south west",
|
||||
"west",
|
||||
"west north west",
|
||||
"north west",
|
||||
"north north west",
|
||||
};
|
||||
|
||||
static char *
|
||||
aoview_compass_point(double bearing)
|
||||
{
|
||||
int i;
|
||||
while (bearing < 0)
|
||||
bearing += 360.0;
|
||||
while (bearing >= 360.0)
|
||||
bearing -= 360.0;
|
||||
|
||||
i = floor ((bearing - 22.5/2) / 22.5 + 0.5);
|
||||
if (i < 0) i = 0;
|
||||
if (i >= sizeof (compass_points) / sizeof (compass_points[0]))
|
||||
i = 0;
|
||||
return compass_points[i];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
aoview_state_timeout(gpointer data)
|
||||
{
|
||||
double now = aoview_time();
|
||||
|
||||
if (strlen(aostate.data.state) > 0 && strcmp(aostate.data.state, "pad") != 0)
|
||||
aoview_speak_height(&aostate);
|
||||
if (now - aostate.report_time >= 20 || !strcmp(aostate.data.state, "landed")) {
|
||||
if (!aostate.ascent) {
|
||||
if (fabs(aostate.baro_speed) < 20 && aostate.height < 100)
|
||||
aoview_voice_speak("rocket landed safely\n");
|
||||
else
|
||||
aoview_voice_speak("rocket may have crashed\n");
|
||||
if (aostate.gps_valid) {
|
||||
aoview_voice_speak("rocket reported %s of pad distance %d meters\n",
|
||||
aoview_compass_point(aostate.bearing),
|
||||
(int) aostate.distance);
|
||||
}
|
||||
}
|
||||
aostate_timeout = 0;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
aoview_state_reset(void)
|
||||
{
|
||||
memset(&aostate, '\0', sizeof (aostate));
|
||||
}
|
||||
|
||||
void
|
||||
aoview_state_notify(struct cc_telem *data)
|
||||
{
|
||||
struct aostate *state = &aostate;
|
||||
aoview_state_derive(data, state);
|
||||
aoview_table_start();
|
||||
|
||||
if (state->npad >= MIN_PAD_SAMPLES)
|
||||
aoview_table_add_row(0, "Ground state", "ready");
|
||||
else
|
||||
aoview_table_add_row(0, "Ground state", "waiting for gps (%d)",
|
||||
MIN_PAD_SAMPLES - state->npad);
|
||||
aoview_table_add_row(0, "Rocket state", "%s", state->data.state);
|
||||
aoview_table_add_row(0, "Callsign", "%s", state->data.callsign);
|
||||
aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial);
|
||||
aoview_table_add_row(0, "Rocket flight", "%d", state->data.flight);
|
||||
|
||||
aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi);
|
||||
aoview_table_add_row(0, "Height", "%6dm", state->height);
|
||||
aoview_table_add_row(0, "Max height", "%6dm", state->max_height);
|
||||
aoview_table_add_row(0, "Acceleration", "%7.1fm/s²", state->acceleration);
|
||||
aoview_table_add_row(0, "Max acceleration", "%7.1fm/s²", state->max_acceleration);
|
||||
aoview_table_add_row(0, "Speed", "%7.1fm/s", state->ascent ? state->speed : state->baro_speed);
|
||||
aoview_table_add_row(0, "Max Speed", "%7.1fm/s", state->max_speed);
|
||||
aoview_table_add_row(0, "Temperature", "%6.2f°C", state->temperature);
|
||||
aoview_table_add_row(0, "Battery", "%5.2fV", state->battery);
|
||||
aoview_table_add_row(0, "Drogue", "%5.2fV", state->drogue_sense);
|
||||
aoview_table_add_row(0, "Main", "%5.2fV", state->main_sense);
|
||||
aoview_table_add_row(0, "Pad altitude", "%dm", state->ground_altitude);
|
||||
aoview_table_add_row(1, "Satellites", "%d", state->gps.nsat);
|
||||
if (state->gps.gps_locked) {
|
||||
aoview_table_add_row(1, "GPS", "locked");
|
||||
} else if (state->gps.gps_connected) {
|
||||
aoview_table_add_row(1, "GPS", "unlocked");
|
||||
} else {
|
||||
aoview_table_add_row(1, "GPS", "not available");
|
||||
}
|
||||
if (state->gps_valid) {
|
||||
aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S');
|
||||
aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W');
|
||||
aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt);
|
||||
aoview_table_add_row(1, "GPS height", "%d", state->gps_height);
|
||||
aoview_table_add_row(1, "GPS date", "%04d-%02d-%02d",
|
||||
state->gps.gps_time.year,
|
||||
state->gps.gps_time.month,
|
||||
state->gps.gps_time.day);
|
||||
aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d",
|
||||
state->gps.gps_time.hour,
|
||||
state->gps.gps_time.minute,
|
||||
state->gps.gps_time.second);
|
||||
}
|
||||
if (state->gps.gps_extended) {
|
||||
aoview_table_add_row(1, "GPS ground speed", "%7.1fm/s %d°",
|
||||
state->gps.ground_speed,
|
||||
state->gps.course);
|
||||
aoview_table_add_row(1, "GPS climb rate", "%7.1fm/s",
|
||||
state->gps.climb_rate);
|
||||
aoview_table_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)",
|
||||
state->gps.hdop, state->gps.h_error, state->gps.v_error);
|
||||
}
|
||||
if (state->npad) {
|
||||
aoview_table_add_row(1, "Distance from pad", "%5.0fm", state->distance);
|
||||
aoview_table_add_row(1, "Direction from pad", "%4.0f°", state->bearing);
|
||||
aoview_state_add_deg(1, "Pad latitude", state->pad_lat, 'N', 'S');
|
||||
aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W');
|
||||
aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt);
|
||||
}
|
||||
if (state->gps.gps_connected) {
|
||||
int nsat_vis = 0;
|
||||
int c;
|
||||
|
||||
aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels);
|
||||
for (c = 0; c < state->gps_tracking.channels; c++) {
|
||||
aoview_table_add_row(2, "Satellite id,C/N0",
|
||||
"%3d,%2d",
|
||||
state->gps_tracking.sats[c].svid,
|
||||
state->gps_tracking.sats[c].c_n0);
|
||||
}
|
||||
}
|
||||
aoview_table_finish();
|
||||
aoview_label_show(state);
|
||||
aoview_speak_state(state);
|
||||
if (!aostate_timeout && strcmp(state->data.state, "pad") != 0)
|
||||
aostate_timeout = g_timeout_add_seconds(10, aoview_state_timeout, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_state_new(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
aoview_state_init(GladeXML *xml)
|
||||
{
|
||||
aoview_state_new();
|
||||
}
|
84
ao-tools/ao-view/aoview_table.c
Normal file
84
ao-tools/ao-view/aoview_table.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
#define NCOL 3
|
||||
|
||||
static GtkTreeView *dataview[NCOL];
|
||||
static GtkListStore *datalist[NCOL];
|
||||
|
||||
void
|
||||
aoview_table_start(void)
|
||||
{
|
||||
int col;
|
||||
for (col = 0; col < NCOL; col++)
|
||||
datalist[col] = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_table_add_row(int col, char *label, char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
GtkTreeIter iter;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buf, sizeof (buf), format, ap);
|
||||
va_end(ap);
|
||||
gtk_list_store_append(datalist[col], &iter);
|
||||
gtk_list_store_set(datalist[col], &iter,
|
||||
0, label,
|
||||
1, buf,
|
||||
-1);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_table_finish(void)
|
||||
{
|
||||
int col;
|
||||
for (col = 0; col < NCOL; col++) {
|
||||
gtk_tree_view_set_model(dataview[col], GTK_TREE_MODEL(datalist[col]));
|
||||
g_object_unref(G_OBJECT(datalist[col]));
|
||||
gtk_tree_view_columns_autosize(dataview[col]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aoview_table_clear(void)
|
||||
{
|
||||
int col;
|
||||
for (col = 0; col < NCOL; col++)
|
||||
gtk_tree_view_set_model(dataview[col], NULL);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_table_init(GladeXML *xml)
|
||||
{
|
||||
int col;
|
||||
|
||||
for (col = 0; col < NCOL; col++) {
|
||||
char name[32];
|
||||
sprintf(name, "dataview_%d", col);
|
||||
dataview[col] = GTK_TREE_VIEW(glade_xml_get_widget(xml, name));
|
||||
assert(dataview[col]);
|
||||
|
||||
aoview_add_plain_text_column(dataview[col], "Field", 0, 20);
|
||||
aoview_add_plain_text_column(dataview[col], "Value", 1, 32);
|
||||
}
|
||||
}
|
92
ao-tools/ao-view/aoview_util.c
Normal file
92
ao-tools/ao-view/aoview_util.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
char *
|
||||
aoview_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;
|
||||
}
|
||||
|
||||
char *
|
||||
aoview_basename(char *file)
|
||||
{
|
||||
char *b;
|
||||
|
||||
b = strrchr(file, '/');
|
||||
if (!b)
|
||||
return file;
|
||||
return b + 1;
|
||||
}
|
||||
|
||||
int
|
||||
aoview_mkdir(char *dir)
|
||||
{
|
||||
char *slash;
|
||||
char *d;
|
||||
char *part;
|
||||
|
||||
d = dir;
|
||||
for (;;) {
|
||||
slash = strchr (d, '/');
|
||||
if (!slash)
|
||||
slash = d + strlen(d);
|
||||
if (!*slash)
|
||||
break;
|
||||
part = strndup(dir, slash - dir);
|
||||
if (!access(part, F_OK))
|
||||
if (mkdir(part, 0777) < 0)
|
||||
return -errno;
|
||||
free(part);
|
||||
d = slash + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GtkTreeViewColumn *
|
||||
aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width)
|
||||
{
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL);
|
||||
g_object_set(renderer, "width-chars", width, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (title, renderer,
|
||||
"text", model_column,
|
||||
NULL);
|
||||
gtk_tree_view_column_set_resizable (column, FALSE);
|
||||
gtk_tree_view_append_column (view, column);
|
||||
|
||||
return column;
|
||||
}
|
123
ao-tools/ao-view/aoview_voice.c
Normal file
123
ao-tools/ao-view/aoview_voice.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright © 2009 Keith Packard <keithp@keithp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "aoview.h"
|
||||
|
||||
#if HAVE_FLITE
|
||||
#include <stdarg.h>
|
||||
|
||||
FILE *aoview_flite;
|
||||
|
||||
void aoview_voice_open(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!aoview_flite)
|
||||
aoview_flite = aoview_flite_start();
|
||||
}
|
||||
|
||||
void aoview_voice_close(void)
|
||||
{
|
||||
if (aoview_flite) {
|
||||
aoview_flite_stop();
|
||||
aoview_flite = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void aoview_voice_speak(char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (aoview_flite) {
|
||||
va_start(ap, format);
|
||||
vfprintf(aoview_flite, format, ap);
|
||||
fflush(aoview_flite);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void aoview_voice_open(void)
|
||||
{
|
||||
}
|
||||
|
||||
void aoview_voice_close(void)
|
||||
{
|
||||
}
|
||||
|
||||
void aoview_voice_speak(char *format, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static GtkCheckMenuItem *voice_enable;
|
||||
|
||||
#define ALTOS_VOICE_PATH "/apps/aoview/voice"
|
||||
|
||||
static void
|
||||
aoview_voice_enable(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
gboolean enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
|
||||
GError *error;
|
||||
GConfClient *gconf_client;
|
||||
|
||||
if (enabled) {
|
||||
aoview_voice_open();
|
||||
aoview_voice_speak("enable voice\n");
|
||||
} else {
|
||||
aoview_voice_speak("disable voice\n");
|
||||
aoview_voice_close();
|
||||
}
|
||||
gconf_client = gconf_client_get_default();
|
||||
gconf_client_set_bool(gconf_client,
|
||||
ALTOS_VOICE_PATH,
|
||||
enabled,
|
||||
&error);
|
||||
}
|
||||
|
||||
void
|
||||
aoview_voice_init(GladeXML *xml)
|
||||
{
|
||||
gboolean enabled;
|
||||
GConfClient *gconf_client;
|
||||
|
||||
voice_enable = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "voice_enable"));
|
||||
assert(voice_enable);
|
||||
|
||||
gconf_client = gconf_client_get_default();
|
||||
enabled = TRUE;
|
||||
if (gconf_client)
|
||||
{
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
enabled = gconf_client_get_bool(gconf_client,
|
||||
ALTOS_VOICE_PATH,
|
||||
&error);
|
||||
if (error)
|
||||
enabled = TRUE;
|
||||
}
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(voice_enable), enabled);
|
||||
if (enabled)
|
||||
aoview_voice_open();
|
||||
|
||||
g_signal_connect(G_OBJECT(voice_enable), "toggled",
|
||||
G_CALLBACK(aoview_voice_enable),
|
||||
voice_enable);
|
||||
}
|
27
ao-tools/ao-view/design
Normal file
27
ao-tools/ao-view/design
Normal file
@@ -0,0 +1,27 @@
|
||||
Requirements:
|
||||
real-time display of telemetry
|
||||
off-line display of logged data
|
||||
Logging of telemetry
|
||||
Capture of logged data to disk
|
||||
|
||||
Input data:
|
||||
accelerometer
|
||||
barometer
|
||||
thermometer
|
||||
gps
|
||||
drogue and main continuity
|
||||
battery voltage
|
||||
time
|
||||
reported flight state
|
||||
reported events
|
||||
|
||||
Computed data:
|
||||
velocity (from accelerometer)
|
||||
altitude
|
||||
range
|
||||
direction
|
||||
|
||||
Displays:
|
||||
numeric display of current rocket status
|
||||
(graphics come later)
|
||||
text message log
|
Reference in New Issue
Block a user