xdemorse-1.3.orig/ 0000755 0001750 0001750 00000000000 11112236641 012427 5 ustar pg4i pg4i xdemorse-1.3.orig/AUTHORS 0000644 0001750 0001750 00000000047 10620614547 013510 0 ustar pg4i pg4i Neoklis Kyriazis
Ham Radio Call: 5B4AZ
xdemorse-1.3.orig/configure.in 0000644 0001750 0001750 00000001161 11111453671 014742 0 ustar pg4i pg4i dnl Process this file with autoconf to produce a configure script.
AC_INIT(configure.in)
AM_INIT_AUTOMAKE(xdemorse, 1.3)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
AC_ISC_POSIX
AC_PROG_CC
AM_PROG_CC_STDC
AC_HEADER_STDC
pkg_modules="gtk+-2.0 >= 2.0.0"
PKG_CHECK_MODULES(PACKAGE, [$pkg_modules])
AC_SUBST(PACKAGE_CFLAGS)
AC_SUBST(PACKAGE_LIBS)
GETTEXT_PACKAGE=xdemorse
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package.])
dnl Add the languages which your application supports here.
ALL_LINGUAS=""
AM_GLIB_GNU_GETTEXT
AC_OUTPUT([
Makefile
src/Makefile
po/Makefile.in
])
xdemorse-1.3.orig/autogen.sh 0000755 0001750 0001750 00000010574 10714016655 014447 0 ustar pg4i pg4i #!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
DIE=0
if [ -n "$GNOME2_DIR" ]; then
ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS"
LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH"
PATH="$GNOME2_DIR/bin:$PATH"
export PATH
export LD_LIBRARY_PATH
fi
(test -f $srcdir/configure.in) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level package directory"
exit 1
}
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`autoconf' installed."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(grep "^AC_PROG_INTLTOOL" $srcdir/configure.in >/dev/null) && {
(intltoolize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`intltool' installed."
echo "You can get it from:"
echo " ftp://ftp.gnome.org/pub/GNOME/"
DIE=1
}
}
(grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.in >/dev/null) && {
(xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`xml-i18n-toolize' installed."
echo "You can get it from:"
echo " ftp://ftp.gnome.org/pub/GNOME/"
DIE=1
}
}
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`libtool' installed."
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
}
(grep "^AM_GLIB_GNU_GETTEXT" $srcdir/configure.in >/dev/null) && {
(grep "sed.*POTFILES" $srcdir/configure.in) > /dev/null || \
(glib-gettextize --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`glib' installed."
echo "You can get it from: ftp://ftp.gtk.org/pub/gtk"
DIE=1
}
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`automake' installed."
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
DIE=1
NO_AUTOMAKE=yes
}
# if no automake, don't bother testing for aclocal
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
echo "installed doesn't appear recent enough."
echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
if test -z "$*"; then
echo "**Warning**: I am going to run \`configure' with no arguments."
echo "If you wish to pass any to it, please specify them on the"
echo \`$0\'" command line."
echo
fi
case $CC in
xlc )
am_opt=--include-deps;;
esac
for coin in `find $srcdir -name configure.in -print`
do
dr=`dirname $coin`
if test -f $dr/NO-AUTO-GEN; then
echo skipping $dr -- flagged as no auto-gen
else
echo processing $dr
( cd $dr
aclocalinclude="$ACLOCAL_FLAGS"
if grep "^AM_GLIB_GNU_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running glib-gettextize... Ignore non-fatal messages."
echo "no" | glib-gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AC_PROG_INTLTOOL" configure.in >/dev/null; then
echo "Running intltoolize..."
intltoolize --copy --force --automake
fi
if grep "^AM_PROG_XML_I18N_TOOLS" configure.in >/dev/null; then
echo "Running xml-i18n-toolize..."
xml-i18n-toolize --copy --force --automake
fi
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
if test -z "$NO_LIBTOOLIZE" ; then
echo "Running libtoolize..."
libtoolize --force --copy
fi
fi
echo "Running aclocal $aclocalinclude ..."
aclocal $aclocalinclude
if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
echo "Running autoheader..."
autoheader
fi
echo "Running automake --gnu $am_opt ..."
automake --add-missing --gnu $am_opt
echo "Running autoconf ..."
autoconf
)
fi
done
conf_flags="--enable-maintainer-mode"
if test x$NOCONFIGURE = x; then
echo Running $srcdir/configure $conf_flags "$@" ...
$srcdir/configure $conf_flags "$@" \
&& echo Now type \`make\' to compile. || exit 1
else
echo Skipping configure process.
fi
xdemorse-1.3.orig/xdemorse.glade 0000644 0001750 0001750 00000063761 11111311621 015257 0 ustar pg4i pg4i
4
True
Xdemorse
GTK_WINDOW_TOPLEVEL
GTK_WIN_POS_CENTER
False
False
False
True
False
False
GDK_WINDOW_TYPE_HINT_NORMAL
GDK_GRAVITY_NORTH_WEST
True
False
True
False
0
4
True
0
0.5
GTK_SHADOW_ETCHED_IN
4
True
True
GTK_POLICY_NEVER
GTK_POLICY_ALWAYS
GTK_SHADOW_IN
GTK_CORNER_TOP_LEFT
600
256
True
True
False
False
False
GTK_JUSTIFY_LEFT
GTK_WRAP_WORD
True
0
0
0
0
0
0
True
False
0
2
True
True
GTK_RELIEF_NORMAL
True
False
False
True
0.5
0.5
0
0
2
2
2
2
True
False
2
True
gtk-apply
4
0.5
0.5
0
0
0
False
False
True
Receive
True
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
0
0
PANGO_ELLIPSIZE_NONE
-1
False
0
0
False
False
0
True
True
2
True
True
GTK_RELIEF_NORMAL
True
True
0.5
0.5
0
0
2
2
2
2
True
False
2
True
gtk-clear
4
0.5
0.5
0
0
0
False
False
True
Clear window
True
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
0
0
PANGO_ELLIPSIZE_NONE
-1
False
0
0
False
False
0
True
True
label_item
0
True
True
True
False
0
4
True
0
0.5
GTK_SHADOW_ETCHED_IN
True
0.5
0.5
1
1
2
2
2
2
264
89
True
GDK_BUTTON_PRESS_MASK
True
Scope
False
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
0
0
PANGO_ELLIPSIZE_NONE
-1
False
0
label_item
0
True
True
True
False
0
True
False
0
4
True
0
0.5
GTK_SHADOW_ETCHED_IN
True
True
1
0
False
GTK_UPDATE_ALWAYS
False
False
20 10 60 1 10 0
True
True
Auto wpm
True
GTK_RELIEF_NORMAL
True
True
False
True
label_item
0
True
True
4
True
0
0.5
GTK_SHADOW_ETCHED_IN
True
True
1
0
False
GTK_UPDATE_ALWAYS
False
False
50 0 100 1 10 0
True
Threshold
False
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
0
0
PANGO_ELLIPSIZE_NONE
-1
False
0
label_item
0
True
True
0
False
False
4
True
0
0.5
GTK_SHADOW_ETCHED_IN
True
0.5
0.5
1
1
2
2
2
2
258
89
True
GDK_BUTTON_PRESS_MASK
True
Waterfall
False
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
0
0
PANGO_ELLIPSIZE_NONE
-1
False
0
label_item
0
True
True
0
True
True
0
True
True
4
True
Xdemorse
GTK_WINDOW_TOPLEVEL
GTK_WIN_POS_MOUSE
True
True
False
True
False
False
GDK_WINDOW_TYPE_HINT_DIALOG
GDK_GRAVITY_NORTH_WEST
True
False
True
True
False
0
True
GTK_BUTTONBOX_END
2
True
True
True
gtk-quit
True
GTK_RELIEF_NORMAL
True
0
2
True
True
True
gtk-ok
True
GTK_RELIEF_NORMAL
True
-5
0
False
True
GTK_PACK_END
4
True
0
0.5
GTK_SHADOW_ETCHED_IN
True
False
0
True
gtk-dialog-error
6
0.5
0.5
0
0
0
False
False
True
Generic Error Message pop-up
False
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
4
0
PANGO_ELLIPSIZE_NONE
-1
False
0
0
False
False
True
Error!
False
False
GTK_JUSTIFY_LEFT
False
False
0.5
0.5
0
0
PANGO_ELLIPSIZE_NONE
-1
False
0
label_item
0
True
True
xdemorse-1.3.orig/doc/ 0000755 0001750 0001750 00000000000 11112217630 013171 5 ustar pg4i pg4i xdemorse-1.3.orig/doc/xdemorse.html 0000644 0001750 0001750 00000040346 11111451514 015714 0 ustar pg4i pg4i
xdemorse User Manual
xdemorse User Manual
- Introduction
- Features
- Compilation
- Command line options
- Operation
- Bugs and annoyances
- Version history
- Copying
1.
Introduction
xdemorse is a X/GTK+ application for decoding Morse code signals
into text. xdemorse detects the "dihs" and "dahs" that make a Morse
code character via the computer's sound card, which can be
connected to a radio receiver tuned to a CW Morse code transmission
or to a tone generator. The input signal is processed by a Goertzel
tone detector algorithm which produces "mark" or "space" (signal/no
signal) outputs and the resulting stream of Morse code "elements"
is decoded into an ASCII character for printing to the Text
viewer.
2. Features
Goertzel tone
detector
xdemorse was designed from the beginning to be simple and
efficient, decoding Morse code using (almost) only integer
arithmetic and simple processing methods. It uses the computer's
sound card to read the "dit" and "dah" elements that make the Morse
coded characters by implementing an integer Goertzel tone detector
algorithm, which measures the level of sound signals from a radio
receiver or tone generator. This Goertzel tone detector is centered
on a nominal frequency of 500 Hz, which is lower than the more
common 700-800 Hz BFO setting, because my PSK31 applications have
to work with a 500 Hz audio tone due to various limitations. I have
chosen to run my Morse decoding applications on the same BFO
setting, to avoid regular changes to my receiver.
The Mark/Space (key-down - key-up) condition is detected using
an edge detector which give a positive spike for a mark->space
transition and a negative spike for a space->mark
transition.
Error and noise
tolerance
xdemorse has a certain level of tolerance towards operator errors
(bad "fist") regarding deviation from the standard duration of the
various elements that make up the Morse code. It can also reject to
some extend the effects of interference and noise by ignoring marks
or spaces shorter than a certain fraction of the unit Morse code
element. Below is a table of the basic Morse code elements and the
range of durations that xdemorse can deal with:
Morse Element Duration xdemorse
-------------------------------------------------
dit 1 units 1/2-2 units
dah 3 units 2-4 units
Inter-elem space 1 units 1/2-2 units
Inter-char space 3 units 2-4 units
Inter-word space > 5 units > 4 units
The Morse code characters, punctuation marks and special signals
that xdemorse can currently recognize are in the file
doc/Morse-code.txt. Extra characters etc can be added to the
collection by inserting the hex equivalent of the decoded Morse
code character in the xdemorse.h header file before compilation.
Please see detailed explanation in that file.
"Waterfall" display with
CAT
xdemorse has a "Waterfall" (audio spectrum) display derived from a
FFT of the receiver's audio output. A vertical red line indicates
the center frequency of the tone detector. When tuning a signal
manually, its trace should be centered on this line for best
results. Clicking with the center button on the display reverses
the background/foreground colors of the display.
xdemorse has built-in CAT capability but only for the Yaesu
FT847 or FT857, the only rigs I have. This is an unfortunate
limitation but an attempt to convert xdemorse to using the "hamlib"
library was unsuccessful for various reasons. The waterfall display
can be used to tune in a signal by clicking with the left mouse
button near its trace. xdemorse will scan a small section of the
display either side of the mouse pointer, looking for the strongest
trace and then tune the receiver so that the signal is centered on
the red line. Since the FT847/FT857 has only a 10 Hz resolution
when tuned by the CAT, there can be an error of +-5 Hz in the
tuning of a signal. Other errors resulting from the finite
resolution of the FFT can increase the tuning discrepancy and since
xdemorse has a sharp tone detector, it may be necessary to
fine-tune the receiver manually for best results.
Sound-card
set-up
xdemorse automatically sets up the sound card and tries to set the
input and recording/capture level to the RECORD_LEV entry in
xdemorse.h. If it fails it will give an appropriate warning and the
mixer levels for line input and recording level must be set up
manually using a mixer app like 'aumix'.
For proper operation the level of the input audio signal must be
adjusted from the receiver or the tone generator, using the 'scope'
display at the bottom left of the main window. If the audio signal
is taken from an outlet that provides a fixed audio level, then the
#define RECORD_LEV entry in xdemorse.h will need to be edited by
trial and error and xdemorse re-compiled, until the signal plotted
in the scope display is about 80% of the height of the scope
frame.
3.
Compilation
Please note that I use Arch
Linux AMD64 which is a "bleeding edge" type distribution, so
there may be compilation and/or run time difficulties if you are
using a relatively old distro. This is mostly true of the basic
dependencies like GTK+ 2 and Glade-2, and there can also be sound
card incompatibility problems at run time.
To compile the package the first time, run the "autogen.sh"
script in the package's top directory. The "configure" script as
produced by Glade-2 specifies the gcc flags as "-g -O2", but if you
want to specify different flags, you will have to run "configure"
with the CFLAGS option, e.g. ./configure CFLAGS="-Wall -O2
-march=i686" or whatever flags of your choice.
Run "make" to produce the executable binary "xdemorse" in src/.
This can then be copied to a suitable location, usually
/usr/local/bin or /usr/bin. You can of course run "make install"
which will install the binary into /usr/local/bin by default. You
can change this to a different location, e.g. /usr/bin, by
including the --prefix=/usr option when running "configure". To
recompile the package, you must run "make distclean" in the top
directory to clean up the package and then run the "configure"
script and "make install".
There is this hypertext documentation file which you can copy to
a location of your choice. There is also a default configuration
file .xdemorserc in the 'default" subdirectory. This must be copied
to your home directory and edited to match your setup. If you have
problems identifying your sound card mixer devices (recording
source, recording level etc) run "xdemorse -l" in a terminal to get
a list of mixer device names.
4. Command line
options:
xdemorse [-hlv]
-h: Print this usage information and exit.
-l: List mixer device names and exit.
-v: Print version number and exit.
5. Operation
Before xdemorse is used to decode Morse signals, the input level to
the sound card must be set up correctly. For this, the radio
receiver or tone generator must be connected to the "line" input of
the sound card with a suitable cable and connectors, with either
the left or right channel connected to the receiver's o/p if in
stereo mode, or if in mono mode normally the left channel input.
The receiver's output level is adjusted so that the maximum signal
input level, as shown in the 'scope' display at the bottom left of
the main window, is about 80% of the scope's window height. The
receiver should be tuned to a strong, clean CW transmission, with
the AGC setting in the fast position and IF/AF bandwidth in the
narrowest setting. Please note that the receiver should be tuned
accurately to the incoming signal so that the BFO note is 500Hz.
This can be done by slowly tuning the receiver, with a tuning step
of 1Hz if available, so that the INPUT SIGNAL display in the scope
is at a maximum. The waterfall display is also very useful for
tuning, since a signal trace tuned to be exactly under the red
middle line of the waterfall will result in a 500 Hz BFO
frequency.
By default xdemorse starts with Morse code speed set to 20 wpm
and the detector threshold set at 50. These are shown in the two
spin-wheel widgets at the right of the scope window. As xdemorse
begins to decode Morse coded signals, it estimates the sending
speed and adapts to it, indicating the actual speed in the 'Speed'
spin-wheel. If the Morse transmission is a lot faster or slower
than the indicated speed, it may not be decoded correctly and
manual changing of the speed setting will be needed to fix the
problem. Auto adaptation to incoming Morse speed can be disabled
with the "Auto wpm" check button.
To decode Morse code from a communications receiver, set the BFO
so that the tone of the CW signal is near to 500 Hz and then start
xdemorse. Assuming that keying is not too bad (operator's 'fist' is
reasonably good) then decoded characters should appear in the
'Receive Window' of xdemorse. Some changes to the speed and/or
squelch setting may be helpful and experience will show the best
setting for the latter. A maximum tuning step of 1 Hz should be
selected on digital receivers and tuning should be slow. A narrow
CW filter is an advantage although very narrow (less than 300-400
Hz) IF or dsp/AF filters tend to ring and cause spurious
characters, mainly E's to be printed on the screen.
Please note that the 'scope' display of xdemorse-fft has two
functions, it can display the input signal waveform or the output
from the Mark/Space (signal/no-signal) detector. The first function
is the default and it can be selected, stopped or started by
clicking in the scope window with the left button of the mouse. The
second function can be selected, stopped or started by clicking in
the scope window with the right button of the mouse. The middle
button stops whatever function is selected. Clicking on the FFT
display with the middle button reverses background/foreground
colors.
Generally xdemorse has a fairly wide tolerance of sending errors
(bad fists or noise) but in practice it has proved to be difficult
to correctly decode CW signals on the amateur bands, with the main
problem appearing to be bad keying habits. Sometimes
inter-character spacing is too small so two or more characters are
taken as one and therefore cannot be decoded correctly. Characters
not recognized by xdemorse are indicated by an asterisk * on the
screen. Word spacing also seems to be inconsistent with many hams
resulting in fragmented or fused words.
Finally a list of all characters, punctuation marks and special
signals recognized by xdemorse are listed in the doc/Morse-code.txt
file. Additional characters can be entered in two tables in the
xdemorse.h header file before compilation, following the
instructions in there.
6. Bugs and annoyances
I have fixed whatever bugs I came across testing xdemorse but there
may be some hiding, waiting for the right conditions to appear.
The Morse code decoding algorithm may need further improvements
to make it more tolerant to errors and noise and the mark/space
detection process may need to be improved to reduce spurious output
due to noise interference.
7. Version
history
Version 0.1: First beta release of this basic Morse
decoding X/GTK+ application, which is based on the console Morse
decoding tool 'demorse'.
Version 0.2: Added a simple "Oscilloscope" display of the
incoming waveform or the Detector output.
Version 0.3: Added a simple FFT-based "Waterfall" display
of the receiver's audio spectrum. The Waterfall display
incorporates CAT functions for the FT847 or FT857 transceiver
allowing netting of the receiver by clicking on the trace of a
signal.
Version 0.4: Replaced the original software synchronous
tone detector with a Goertzel tone detector, since it has slightly
better performance.
Version 0.5: Changed Mark/Space tone detection from
thresholding the signal level to detecting the mark->space and
space->mark transition edge. Seems to give more reliable
decoding.
Version 0.6: Added a display function for the output of
the Goertzel signal detector. This is displayed int the "scope"
window at the left lower corner of the xdemorse window.
Version 0.7: Changed the detector scheme to a Mark/Space
transition (edge) detector which works by counting the number of
consecutive signal samples (steps) that change by more than 5% in
the same direction (up or down). If the number of steps is more
than a given threshold (default 60% of the Morse element duration)
then this is taken to indicate a rising or falling edge. This seems
to work better than the previous slope detection scheme. Also added
a few extra command line options to specify parameters for
demorse's operation.
Version 0.8 Added a parser to read a runtime
configuration file from the user's home directory. This file
(~/.xdemorse) must be edited to match the user's setup. The command
line options for specifying the various parameters xdemorse needs
have been removed. Also its no longer necessary to make any changes
to the xdemorse.h header.
Version 0.9 After a bug report from Juha Vierinen
regarding seg faulting of xnec2c, my graphical adaptation of NEC2,
I changed all "sprintf" commands to "snprintf" to avoid buffer
overruns. Following on the above changes, I revised all similar
situations in xdemorse source code and changed all "sprintf"
commands to "snprintf" just in case. While going through the
xdemorse source code, I also fixed some minor bugs like typos and
tidied error messages and other aspects of the GUI.
Version 1.0 After a bug report from Pino Zollo ZP4KFX, I
modified the waterfall display function to avoid a divide by zero
condition that caused a SIGFPE crash.
Version 1.1 After a bug report from Pino Zollo ZP4KFX
regarding GUI problems with my Hellschreiber program xfhell, I made
some changes to the GUI code in most of my GTK2 applications.
Version 1.2 After a bug report from Pino Zollo ZP4KFX,
regarding failure of "xdemorse" to start the Morse decoding loop
after reading its configuration file, I have modified the functions
that read this file so that more detailed error messages are
printed if entries are malformed.
I added 3 new entries to the ~/.xdemorserc config file to allow a
wider range of max and min Morse speeds and to define the initial
Morse speed (WPM) at start-up. I also added a "Receive" button in
the GUI to start and stop xdemorse as needed.
Version 1.3 Made the page size of spin buttons 0 to make
setting of spin button values compatible with GTK 2.4.
8. Copying This
software package is released under the GNU Public License. Please
see the COPYING file for more details.
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:
August 16 2002.
Last modified: Mon Mar 31 16:13:49 EEST 2003
xdemorse-1.3.orig/doc/Morsecode.txt 0000644 0001750 0001750 00000007155 10767763033 015704 0 ustar pg4i pg4i MORSE CODE
Alphabet
Letter Composed of: Sounds Like Letter Composed of: Sounds Like
A . _ didah N _ . dahdit
B _ . . . dahdididit O _ _ _ dahdahdah
C _ . _ . dahdidahdit P . _ _ . didahdahdit
D _ . . dahdidit Q _ _ . _ dahdahdidah
E . dit R . _ . didahdit
F . . _ . dididahdit S . . . dididit
G _ _ . dahdahdit T _ dah
H . . . . didididit U . . _ dididah
I . . didit V . . . _ didididah
J . _ _ _ didahdahdah W . _ _ didahdah
K _ . _ dahdidah X _ . . _ dahdididah
L . _ . . didahdidit Y _ . _ _ dahdidahdah
M _ _ dahdah Z _ _ . . dahdahdidit
________________________________________________________________________________
Numerals
Number Composed of: Sounds Like
1 . _ _ _ _ didahdahdahdah
2 . . _ _ _ dididahdahdah
3 . . . _ _ didididahdah
4 . . . . _ dididididah
5 . . . . . dididididit
6 _ . . . . dahdidididit
7 _ _ . . . dahdahdididit
8 _ _ _ . . dahdahdahdidit
9 _ _ _ _ . dahdahdahdahdit
0 _ _ _ _ _ dahdahdahdahdah
________________________________________________________________________________
Punctuation
Character Composed of: Sounds Like
Period . . _ . _ . _ didahdidahdidah
Comma , _ _ . . _ _ dahdahdididahdah
Colon : _ _ _ . . . dahdahdahdididit
Question mark ? . . _ _ . . dididahdahdidit
Apostrophe ' . _ _ _ _ . didahdahdahdahdit
Hyphen - _ . . . . _ dahdididididah
Fraction bar / _ . . _ . dahdididahdit
Parentheses ( ) _ . _ _ . _ dahdidahdahdidah
Quotation marks " . _ . . _ . didahdididahdit
Semicolon ; _ . _ . _ . dahdidahdidahdit
Dollar sign $ . . . _ . . _ didididahdididah
_______________________________________________________________________________
Special Signals
Character Symbol Composed of: Sounds Like
End of message (AR) # . _ . _ . didahdidahdit
End of Work (VA) < . . . _ . _ didididahdidah
Attention ! _ . _ . _ dahdidahdidah
Wait sign (AS) @ . _ . . . didahdididi
Selective call (KN) ] _ . _ _ . dahditdahdahdit
Break = _ . . . _ dahditditditdah
Invitation to transmit (K) _ . _ dahdidah
Test letter (V) . . . _ didididah
Received, ok (R) . _ . didahdit
Error ~ . . . . . . . . didididididididit
_______________________________________________________________________________
xdemorse-1.3.orig/default/ 0000755 0001750 0001750 00000000000 11003604177 014055 5 ustar pg4i pg4i xdemorse-1.3.orig/default/.xdemorserc 0000644 0001750 0001750 00000007435 10772460231 016245 0 ustar pg4i pg4i ########### xdemorse RUNTIME CONFIGURATION FILE: xdemorserc #########
# #
# PLEASE NOTE! In order to keep the parser for this file simple, #
# the runtime configuration entries below must all be present and #
# in the order presented, since they are all read-in in a fixed #
# sequence. Blank lines or those starting with a # or white space #
# are ignored. #
# #
#####################################################################
#
####### SOUND-CARD CONFIGURATION #######
#
# Please look in /usr/include/soundcard.h
# (search for SOUND_DEVICE_NAMES) to find valid device names.
#
# Mixer device: Default is /dev/mixer
/dev/mixer
#
# Capture DSP device: Default is /dev/dsp
/dev/dsp
#
# The sampling speed of the sound card's DSP. This should as
# far as possible be the native speed of the DSP to avoid
# resampling, as it seems resampling distorts the signal.
48000
#
# Audio capture/recording source: Default is line.
# Alternative is usually mic or line1 etc.
line
#
# Audio recording level device: Default is igain.
# Alternative is usually reclev or rec.
igain
#
# Recording/Capture level: Useful range ~10-100. Default is 64.
# The correct value must be found by testing, see xdemorse.html.
64
#
# Sound card mode: (STEREO | MONO). My default is STEREO because
# I have two sources (receivers) connected to the sound card.
STEREO
#
# Channel in use by xdemorse: (LEFT | RIGHT). My default is RIGHT.
# When in MONO mode, this field is ignored. On my system at
# least, only the left channel works in MONO.
RIGHT
#
####### End of SOUND-CARD CONFIGURATION #######
#
####### xdemorse RUNTIME CONFIGURATION #######
#
# Maximum Morse speed to decode. xdemorse is internally limited to
# the range 6-60 Words per Minute, but you might want to limit the
# maximum speed to a lower value, as this also reduces susceptibility
# to radio noise which can "drag" the current WPM to high values, if
# Auto speed detection and tracking is enabled. Default is 40 wpm
40
#
# Minimum Morse speed to decode. xdemorse is internally limited to
# the range 6-60 Words per Minute, but you might want to limit the
# minimum speed since a very low setting can "lock" the Auto speed
# detection and tracking to this low value. Default is 10 wpm
10
#
# Initial Morse decoding speed WPM. Should be between above limits!
20
#
# Word-wrap line length. Default is 60
55
#
# Serial port device for FT847 CAT: Default is /dev/tts/0
# IN MY SETUP! Please specify the serial port device you
# intend to use for CAT control of your tranceiver. PLEASE NOTE:
# CAT is available only for the YAESU FT-847 and FT857 which I own.
# If you are using some other tranceiver, there is no need to edit
# these entries BUT DO NOT ACTIVATE CAT as xfhell WILL ABORT!
/dev/tts/2
#
# Serial port device for FT857 CAT: Default is /dev/tts/1
# IN MY SETUP! Please specify the serial port device you
# intend to use for CAT control of your tranceiver. PLEASE NOTE:
# CAT is available only for the YAESU FT-847 and FT857 which I own.
# If you are using some other tranceiver, there is no need to edit
# these entries BUT DO NOT ACTIVATE CAT as xfhell WILL ABORT!
/dev/tts/0
#
# Enable CAT for Yaesu FT847 OR FT857 transceivers.
# Setting is FT847 or FT857 or NONE if you have some
# other transceiver or don't want CAT.
FT847
#
# BFO Tone frequency. This is the frequency of the receiver's
# audio output when a CW signal is tuned in the center of the
# IF passband. Because xdemorse uses integer arithmatic to
# detect the signal and to display the waterfall (by using
# an integer FFT algorithm), this value will be rounded
# in xdemorse to a value that keeps the above functions at
# a reasonable accuracy.
500
#
xdemorse-1.3.orig/README 0000644 0001750 0001750 00000000062 10713316544 013314 0 ustar pg4i pg4i Please read the user manual in the doc/ directory
xdemorse-1.3.orig/ChangeLog 0000644 0001750 0001750 00000000062 10713316544 014206 0 ustar pg4i pg4i Please read the user manual in the doc/ directory
xdemorse-1.3.orig/po/ 0000755 0001750 0001750 00000000000 11111453775 013055 5 ustar pg4i pg4i xdemorse-1.3.orig/po/POTFILES.in 0000644 0001750 0001750 00000000162 10714016655 014631 0 ustar pg4i pg4i # List of source files containing translatable strings.
src/main.c
src/interface.c
src/callbacks.c
src/support.c
xdemorse-1.3.orig/po/Makefile.in.in 0000644 0001750 0001750 00000017724 11111453703 015531 0 ustar pg4i pg4i # Makefile for program source directory in GNU NLS utilities package.
# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper
#
# This file file be copied and used freely without restrictions. It can
# be used in projects which are not available under the GNU Public License
# but which still want to provide support for the GNU gettext functionality.
# Please note that the actual code is *not* freely available.
#
# - Modified by Owen Taylor to use GETTEXT_PACKAGE
# instead of PACKAGE and to look for po2tbl in ./ not in intl/
#
# - Modified by jacob berkman to install
# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
PACKAGE = @PACKAGE@
VERSION = @VERSION@
SHELL = /bin/sh
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@
datadir = @datadir@
libdir = @libdir@
localedir = $(libdir)/locale
gnulocaledir = $(datadir)/locale
gettextsrcdir = $(datadir)/glib-2.0/gettext/po
subdir = po
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@
CC = @CC@
GENCAT = @GENCAT@
GMSGFMT = @GMSGFMT@
MSGFMT = @MSGFMT@
MSGFMT_OPTS = @MSGFMT_OPTS@
XGETTEXT = @XGETTEXT@
MSGMERGE = msgmerge
DEFS = @DEFS@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
INCLUDES = -I.. -I$(top_srcdir)/intl
COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
SOURCES =
POFILES = @POFILES@
GMOFILES = @GMOFILES@
DISTFILES = LINGUAS ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \
$(POFILES) $(GMOFILES) $(SOURCES)
POTFILES = \
CATALOGS = @CATALOGS@
CATOBJEXT = @CATOBJEXT@
INSTOBJEXT = @INSTOBJEXT@
.SUFFIXES:
.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
.c.o:
$(COMPILE) $<
.po.pox:
$(MAKE) $(GETTEXT_PACKAGE).pot
$(MSGMERGE) $< $(srcdir)/$(GETTEXT_PACKAGE).pot -o $*.pox
.po.mo:
$(MSGFMT) -o $@ $<
.po.gmo:
file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
&& rm -f $$file && $(GMSGFMT) $(MSGFMT_OPTS) -o $$file $<
.po.cat:
sed -f ../intl/po2msg.sed < $< > $*.msg \
&& rm -f $@ && $(GENCAT) $@ $*.msg
all: all-@USE_NLS@
all-yes: $(CATALOGS)
all-no:
$(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES)
$(XGETTEXT) --default-domain=$(GETTEXT_PACKAGE) --directory=$(top_srcdir) \
--add-comments --keyword=_ --keyword=N_ \
--flag=g_strdup_printf:1:c-format \
--flag=g_string_printf:2:c-format \
--flag=g_string_append_printf:2:c-format \
--flag=g_error_new:3:c-format \
--flag=g_set_error:4:c-format \
--flag=g_markup_printf_escaped:1:c-format \
--flag=g_log:3:c-format \
--flag=g_print:1:c-format \
--flag=g_printerr:1:c-format \
--flag=g_printf:1:c-format \
--flag=g_fprintf:2:c-format \
--flag=g_sprintf:2:c-format \
--flag=g_snprintf:3:c-format \
--flag=g_scanner_error:2:c-format \
--flag=g_scanner_warn:2:c-format \
--files-from=$(srcdir)/POTFILES.in \
&& test ! -f $(GETTEXT_PACKAGE).po \
|| ( rm -f $(srcdir)/$(GETTEXT_PACKAGE).pot \
&& mv $(GETTEXT_PACKAGE).po $(srcdir)/$(GETTEXT_PACKAGE).pot )
install: install-exec install-data
install-exec:
install-data: install-data-@USE_NLS@
install-data-no: all
install-data-yes: all
if test -r "$(MKINSTALLDIRS)"; then \
$(MKINSTALLDIRS) $(DESTDIR)$(datadir); \
else \
$(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \
fi
@catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
case "$$cat" in \
*.gmo) destdir=$(gnulocaledir);; \
*) destdir=$(localedir);; \
esac; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \
if test -r "$(MKINSTALLDIRS)"; then \
$(MKINSTALLDIRS) $$dir; \
else \
$(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \
fi; \
if test -r $$cat; then \
$(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \
else \
$(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
echo "installing $(srcdir)/$$cat as" \
"$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \
fi; \
if test -r $$cat.m; then \
$(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \
else \
if test -r $(srcdir)/$$cat.m ; then \
$(INSTALL_DATA) $(srcdir)/$$cat.m \
$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
echo "installing $(srcdir)/$$cat as" \
"$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \
else \
true; \
fi; \
fi; \
done
if test "$(PACKAGE)" = "glib"; then \
if test -r "$(MKINSTALLDIRS)"; then \
$(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \
else \
$(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(gettextsrcdir); \
fi; \
$(INSTALL_DATA) $(srcdir)/Makefile.in.in \
$(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
else \
: ; \
fi
# Define this as empty until I found a useful application.
installcheck:
uninstall:
catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \
rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \
done
if test "$(PACKAGE)" = "glib"; then \
rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
fi
check: all
dvi info tags TAGS ID:
mostlyclean:
rm -f core core.* *.pox $(GETTEXT_PACKAGE).po *.old.po cat-id-tbl.tmp
rm -fr *.o
clean: mostlyclean
distclean: clean
rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
maintainer-clean: distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
rm -f $(GMOFILES)
distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir)
dist distdir: update-po $(DISTFILES)
dists="$(DISTFILES)"; \
for file in $$dists; do \
ln $(srcdir)/$$file $(distdir) 2> /dev/null \
|| cp -p $(srcdir)/$$file $(distdir); \
done
update-po: Makefile
$(MAKE) $(GETTEXT_PACKAGE).pot
tmpdir=`pwd`; \
cd $(srcdir); \
catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
echo "$$lang:"; \
if $(MSGMERGE) $$lang.po $(GETTEXT_PACKAGE).pot -o $$tmpdir/$$lang.new.po; then \
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
rm -f $$tmpdir/$$lang.new.po; \
else \
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
:; \
else \
echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
rm -f $$tmpdir/$$lang.new.po; \
exit 1; \
fi; \
fi; \
else \
echo "msgmerge for $$cat failed!"; \
rm -f $$tmpdir/$$lang.new.po; \
fi; \
done
# POTFILES is created from POTFILES.in by stripping comments, empty lines
# and Intltool tags (enclosed in square brackets), and appending a full
# relative path to them
POTFILES: POTFILES.in
( if test 'x$(srcdir)' != 'x.'; then \
posrcprefix='$(top_srcdir)/'; \
else \
posrcprefix="../"; \
fi; \
rm -f $@-t $@ \
&& (sed -e '/^#/d' \
-e "s/^\[.*\] +//" \
-e '/^[ ]*$$/d' \
-e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
| sed -e '$$s/\\$$//') > $@-t \
&& chmod a-w $@-t \
&& mv $@-t $@ )
Makefile: Makefile.in.in ../config.status POTFILES
cd .. \
&& CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
$(SHELL) ./config.status
# Tell versions [3.59,3.63) of GNU make not to export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
xdemorse-1.3.orig/po/ChangeLog 0000644 0001750 0001750 00000000000 10714016655 014615 0 ustar pg4i pg4i xdemorse-1.3.orig/NEWS 0000644 0001750 0001750 00000000030 10713301303 013111 0 ustar pg4i pg4i No news - good news ;-)
xdemorse-1.3.orig/Makefile.am 0000644 0001750 0001750 00000001210 10714016655 014465 0 ustar pg4i pg4i ## Process this file with automake to produce Makefile.in
SUBDIRS = src po
EXTRA_DIST = \
autogen.sh \
xdemorse.glade \
xdemorse.gladep
install-data-local:
@$(NORMAL_INSTALL)
if test -d $(srcdir)/pixmaps; then \
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/pixmaps; \
for pixmap in $(srcdir)/pixmaps/*; do \
if test -f $$pixmap; then \
$(INSTALL_DATA) $$pixmap $(DESTDIR)$(pkgdatadir)/pixmaps; \
fi \
done \
fi
dist-hook:
if test -d pixmaps; then \
mkdir $(distdir)/pixmaps; \
for pixmap in pixmaps/*; do \
if test -f $$pixmap; then \
cp -p $$pixmap $(distdir)/pixmaps; \
fi \
done \
fi
xdemorse-1.3.orig/src/ 0000755 0001750 0001750 00000000000 11112236652 013220 5 ustar pg4i pg4i xdemorse-1.3.orig/src/display.c 0000644 0001750 0001750 00000016167 10772442133 015050 0 ustar pg4i pg4i /* display.c
*
* Display functions for xdemorse application
*/
/*
* xdemorse: An application to decode Morse code signals to text
*
* Copyright (C) 2002 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#include "xdemorse.h"
/* Signal scope */
extern GtkWidget
*gbl_waterfall,
*gbl_scope;
/* Unit element as fragments/element */
extern int unit_elem;
/* fft in/out buffers */
extern int
*fft_in_r,
*fft_out_r,
*fft_out_i;
/* Average bin values */
int gbl_bin_ave[FFT_SIZE/2];
/* Waterfall window pixbuf */
extern GdkPixbuf *gbl_wfall_pixbuf;
extern guchar *gbl_wfall_pixels;
extern gint
gbl_wfall_rowstride,
gbl_wfall_n_channels,
gbl_wfall_width,
gbl_wfall_height;
/* Runtime config data */
extern rc_data_t rc_data;
/*------------------------------------------------------------------------*/
/* Display_Detector()
*
* Updates the Detector scope display
*/
void
Display_Detector( int plot )
{
/* Points to plot */
static GdkPoint points[256];
static int points_idx = 0;
int temp;
/* Save values to be plotted */
points[points_idx].y = 87 - plot;
if( points[points_idx].y < 3 )
points[points_idx].y = 3;
if( points[points_idx].y > 87 )
points[points_idx].y = 87;
points[points_idx].x = points_idx+3;
/* Recycle buffer idx when full and plot */
if( ++points_idx == 256 )
{
/* Draw scope background */
gdk_draw_rectangle( gbl_scope->window,
gbl_scope->style->white_gc,
TRUE, 4, 3, 255, 85 );
/* Draw scope frame */
gdk_draw_rectangle( gbl_scope->window,
gbl_scope->style->black_gc,
FALSE, 3, 2, 256, 86 );
/* Plot signal graph */
gdk_draw_lines( gbl_scope->window,
gbl_scope->style->black_gc,
points, 256 );
points_idx = 0;
/* Draw Mark/Space threshold references */
temp = 87 - (84*rc_data.det_thr)/100;
gdk_draw_line( gbl_scope->window,
gbl_scope->style->black_gc,
3, temp, 258, temp );
} /* if( ++points_idx == 256 ) */
} /* Display_Detector() */
/*------------------------------------------------------------------------*/
/* Display_Signal()
*
* Updates the Signal scope display
*/
void
Display_Signal( int plot )
{
/* Points to plot */
static GdkPoint points[256];
static int points_idx = 0;
/* Save values to be plotted (SCALED) */
points[points_idx].y = 86 - plot/64;
if( points[points_idx].y < 3 )
points[points_idx].y = 3;
points[points_idx].x = points_idx+3;
/* Recycle buffer idx when full and plot */
if( ++points_idx == 256 )
{
/* Draw scope background */
gdk_draw_rectangle( gbl_scope->window,
gbl_scope->style->white_gc,
TRUE, 4, 3, 255, 85 );
/* Draw scope frame */
gdk_draw_rectangle( gbl_scope->window,
gbl_scope->style->black_gc,
FALSE, 3, 2, 256, 86 );
/* Plot signal graph */
gdk_draw_lines( gbl_scope->window,
gbl_scope->style->black_gc,
points, 256 );
points_idx = 0;
} /* if( ++points_idx == DRAWABLE_LEN ) */
} /* Display_Signal */
/*------------------------------------------------------------------------*/
/* Display_Waterfall()
*
* Displays audio spectrum as "waterfall"
*/
void
Display_Waterfall(void)
{
int
idh, idv, /* Index to hor. and vert. position in warterfall */
pixel_val, /* Greyscale value of pixel derived from fft o/p */
fft_idx; /* Index to fft output array */
/* Constant needed to draw red line in waterfall */
static int red_line = WFALL_WIDTH/2;
int
bin_val, /* Value of fft output "bin" */
bin_max; /* Maximum value of fft bins */
/* Sliding window average of bin max values */
static int ave_max = 1000;
/* Pointer to current pixel */
static guchar *pix;
/* Draw a vertical red line in waterfall at detector's freq. */
pix = gbl_wfall_pixels + gbl_wfall_rowstride + gbl_wfall_n_channels;
pix += gbl_wfall_n_channels * red_line;
pix[0] = 0xff;
pix[1] = pix[2] = 0;
/* Copy each line of waterfall to next one */
for( idv = gbl_wfall_height-2; idv > 0; idv-- )
{
pix = gbl_wfall_pixels + gbl_wfall_rowstride * idv + gbl_wfall_n_channels;
for( idh = 0; idh < WFALL_WIDTH; idh++ )
{
pix[0] = pix[ -gbl_wfall_rowstride];
pix[1] = pix[1-gbl_wfall_rowstride];
pix[2] = pix[2-gbl_wfall_rowstride];
pix += gbl_wfall_n_channels;
}
}
/* Got to top left +1 hor. +1 vert. of pixbuf */
pix = gbl_wfall_pixels + gbl_wfall_rowstride + gbl_wfall_n_channels;
/* First column of display (DC) not used */
gbl_bin_ave[0] = 0;
/* Do the FFT on input array */
Ifft( FFT_SIZE );
bin_max = 0;
for( fft_idx = 0; fft_idx < FFT_SIZE/2; fft_idx++ )
{
/* Calculate signal power at each frequency (bin) */
fft_out_r[fft_idx] /=8;
fft_out_i[fft_idx] /=8;
bin_val =
fft_out_r[fft_idx]*fft_out_r[fft_idx] +
fft_out_i[fft_idx]*fft_out_i[fft_idx];
/* Calculate average bin values */
gbl_bin_ave[fft_idx] = ( (gbl_bin_ave[fft_idx] *
(BINMAX_AVE_WIN-1) + bin_val) / BINMAX_AVE_WIN );
/* Record max bin value */
if( bin_max < bin_val )
bin_max = bin_val;
/* Scale pixel values to 255 depending on ave max value */
pixel_val = (255 * bin_val) / ave_max;
if( pixel_val > 255 ) pixel_val = 255;
int lim = (2*WFALL_WIDTH)/FFT_SIZE;
/* Duplicate pixels if fft size < waterfall width */
for( idh = 0; idh < lim; idh++ )
{
/* Reverse video is toggled by right click on waterfall */
if( isFlagSet(REVERSE_VIDEO) )
pix[0] = pix[1] = pix[2] = pixel_val;
else
pix[0] = pix[1] = pix[2] = 255 - pixel_val;
pix += gbl_wfall_n_channels;
}
} /* for( fft_idx = 0; fft_idx < fft_end; fft_idx++ ) */
/* Calculate sliding window average of max bin value */
ave_max = (ave_max*(BINMAX_AVE_WIN-1) + bin_max)/BINMAX_AVE_WIN;
if( !ave_max ) ave_max = 1;
/* At last draw waterfall */
gtk_widget_queue_draw( gbl_waterfall );
} /* Display_Waterfall() */
/*------------------------------------------------------------------------*/
/* Clear_Pixbuf()
*
* Initializes pixbuf of Waterfall window
*/
void
Clear_Pixbuf( void )
{
int i;
guchar *p1, *p2;
gdk_pixbuf_fill( gbl_wfall_pixbuf, 0xffffffff );
/* Draw a box around pixbuf */
p1 = gbl_wfall_pixels;
p2 = gbl_wfall_pixels + (gbl_wfall_height-1)*gbl_wfall_rowstride;
for( i = 0; i < gbl_wfall_width; i++ )
{
p1[0] = p1[1] = p1[2] = 0;
p1 += gbl_wfall_n_channels;
p2[0] = p2[1] = p2[2] = 0;
p2 += gbl_wfall_n_channels;
}
p1 = gbl_wfall_pixels+gbl_wfall_rowstride;
p2 = gbl_wfall_pixels+gbl_wfall_rowstride + (gbl_wfall_width-1)*gbl_wfall_n_channels;
for( i = 0; i < gbl_wfall_height-1; i++ )
{
p1[0] = p1[1] = p1[2] = 0;
p1 += gbl_wfall_rowstride;
p2[0] = p2[1] = p2[2] = 0;
p2 += gbl_wfall_rowstride;
}
gtk_widget_queue_draw( gbl_waterfall );
} /* Clear_Pixbuf() */
/*------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/callbacks.h 0000644 0001750 0001750 00000005304 10772753512 015324 0 ustar pg4i pg4i #include
void
on_main_window_destroy (GtkObject *object,
gpointer user_data);
gboolean
on_main_window_delete_event (GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
void
on_clear_clicked (GtkButton *button,
gpointer user_data);
gboolean
on_scope_expose_event (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data);
gboolean
on_scope_button_press_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
void
on_speed_changed (GtkEditable *editable,
gpointer user_data);
void
on_wpm_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_squelch_changed (GtkEditable *editable,
gpointer user_data);
gboolean
on_waterfall_expose_event (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data);
gboolean
on_waterfall_button_press_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
void
on_err_quit_clicked (GtkButton *button,
gpointer user_data);
void
on_err_ok_button_clicked (GtkButton *button,
gpointer user_data);
void
on_error_dialog_destroy (GtkObject *object,
gpointer user_data);
gboolean
on_error_dialog_delete_event (GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
void
on_waterfall_size_allocate (GtkWidget *widget,
GdkRectangle *allocation,
gpointer user_data);
void
on_rx_togglebutton_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
xdemorse-1.3.orig/src/interface.c 0000644 0001750 0001750 00000035623 11111311621 015322 0 ustar pg4i pg4i /*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include
#include "callbacks.h"
#include "interface.h"
#include "support.h"
#define GLADE_HOOKUP_OBJECT(component,widget,name) \
g_object_set_data_full (G_OBJECT (component), name, \
gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
g_object_set_data (G_OBJECT (component), name, widget)
GtkWidget*
create_main_window (void)
{
GtkWidget *main_window;
GtkWidget *vbox1;
GtkWidget *frame2;
GtkWidget *rx_scrolledwindow;
GtkWidget *rx_textview;
GtkWidget *hbox4;
GtkWidget *rx_togglebutton;
GtkWidget *alignment3;
GtkWidget *hbox5;
GtkWidget *image2;
GtkWidget *label9;
GtkWidget *clear;
GtkWidget *alignment4;
GtkWidget *hbox6;
GtkWidget *image3;
GtkWidget *label10;
GtkWidget *hbox1;
GtkWidget *frame1;
GtkWidget *alignment2;
GtkWidget *scope;
GtkWidget *label1;
GtkWidget *hbox2;
GtkWidget *vbox2;
GtkWidget *frame4;
GtkObject *speed_adj;
GtkWidget *speed;
GtkWidget *wpm;
GtkWidget *frame5;
GtkObject *squelch_adj;
GtkWidget *squelch;
GtkWidget *label8;
GtkWidget *frame7;
GtkWidget *alignment1;
GtkWidget *waterfall;
GtkWidget *label7;
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (main_window), 4);
gtk_window_set_title (GTK_WINDOW (main_window), _("Xdemorse"));
gtk_window_set_position (GTK_WINDOW (main_window), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (main_window), FALSE);
vbox1 = gtk_vbox_new (FALSE, 0);
gtk_widget_show (vbox1);
gtk_container_add (GTK_CONTAINER (main_window), vbox1);
frame2 = gtk_frame_new (NULL);
gtk_widget_show (frame2);
gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame2), 4);
rx_scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (rx_scrolledwindow);
gtk_container_add (GTK_CONTAINER (frame2), rx_scrolledwindow);
gtk_container_set_border_width (GTK_CONTAINER (rx_scrolledwindow), 4);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (rx_scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (rx_scrolledwindow), GTK_SHADOW_IN);
rx_textview = gtk_text_view_new ();
gtk_widget_show (rx_textview);
gtk_container_add (GTK_CONTAINER (rx_scrolledwindow), rx_textview);
gtk_widget_set_size_request (rx_textview, 600, 256);
gtk_text_view_set_editable (GTK_TEXT_VIEW (rx_textview), FALSE);
gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW (rx_textview), FALSE);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (rx_textview), GTK_WRAP_WORD);
hbox4 = gtk_hbox_new (FALSE, 0);
gtk_widget_show (hbox4);
gtk_frame_set_label_widget (GTK_FRAME (frame2), hbox4);
rx_togglebutton = gtk_toggle_button_new ();
gtk_widget_show (rx_togglebutton);
gtk_box_pack_start (GTK_BOX (hbox4), rx_togglebutton, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (rx_togglebutton), 2);
alignment3 = gtk_alignment_new (0.5, 0.5, 0, 0);
gtk_widget_show (alignment3);
gtk_container_add (GTK_CONTAINER (rx_togglebutton), alignment3);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment3), 2, 2, 2, 2);
hbox5 = gtk_hbox_new (FALSE, 2);
gtk_widget_show (hbox5);
gtk_container_add (GTK_CONTAINER (alignment3), hbox5);
image2 = gtk_image_new_from_stock ("gtk-apply", GTK_ICON_SIZE_BUTTON);
gtk_widget_show (image2);
gtk_box_pack_start (GTK_BOX (hbox5), image2, FALSE, FALSE, 0);
label9 = gtk_label_new_with_mnemonic (_("Receive"));
gtk_widget_show (label9);
gtk_box_pack_start (GTK_BOX (hbox5), label9, FALSE, FALSE, 0);
clear = gtk_button_new ();
gtk_widget_show (clear);
gtk_box_pack_start (GTK_BOX (hbox4), clear, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (clear), 2);
alignment4 = gtk_alignment_new (0.5, 0.5, 0, 0);
gtk_widget_show (alignment4);
gtk_container_add (GTK_CONTAINER (clear), alignment4);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment4), 2, 2, 2, 2);
hbox6 = gtk_hbox_new (FALSE, 2);
gtk_widget_show (hbox6);
gtk_container_add (GTK_CONTAINER (alignment4), hbox6);
image3 = gtk_image_new_from_stock ("gtk-clear", GTK_ICON_SIZE_BUTTON);
gtk_widget_show (image3);
gtk_box_pack_start (GTK_BOX (hbox6), image3, FALSE, FALSE, 0);
label10 = gtk_label_new_with_mnemonic (_("Clear window"));
gtk_widget_show (label10);
gtk_box_pack_start (GTK_BOX (hbox6), label10, FALSE, FALSE, 0);
hbox1 = gtk_hbox_new (FALSE, 0);
gtk_widget_show (hbox1);
gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
frame1 = gtk_frame_new (NULL);
gtk_widget_show (frame1);
gtk_box_pack_start (GTK_BOX (hbox1), frame1, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame1), 4);
alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1);
gtk_widget_show (alignment2);
gtk_container_add (GTK_CONTAINER (frame1), alignment2);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 2, 2, 2, 2);
scope = gtk_drawing_area_new ();
gtk_widget_show (scope);
gtk_container_add (GTK_CONTAINER (alignment2), scope);
gtk_widget_set_size_request (scope, 264, 89);
gtk_widget_set_events (scope, GDK_BUTTON_PRESS_MASK);
label1 = gtk_label_new (_("Scope"));
gtk_widget_show (label1);
gtk_frame_set_label_widget (GTK_FRAME (frame1), label1);
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_widget_show (hbox2);
gtk_box_pack_start (GTK_BOX (hbox1), hbox2, TRUE, TRUE, 0);
vbox2 = gtk_vbox_new (FALSE, 0);
gtk_widget_show (vbox2);
gtk_box_pack_start (GTK_BOX (hbox2), vbox2, FALSE, FALSE, 0);
frame4 = gtk_frame_new (NULL);
gtk_widget_show (frame4);
gtk_box_pack_start (GTK_BOX (vbox2), frame4, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame4), 4);
speed_adj = gtk_adjustment_new (20, 10, 60, 1, 10, 0);
speed = gtk_spin_button_new (GTK_ADJUSTMENT (speed_adj), 1, 0);
gtk_widget_show (speed);
gtk_container_add (GTK_CONTAINER (frame4), speed);
wpm = gtk_check_button_new_with_mnemonic (_("Auto wpm"));
gtk_widget_show (wpm);
gtk_frame_set_label_widget (GTK_FRAME (frame4), wpm);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wpm), TRUE);
frame5 = gtk_frame_new (NULL);
gtk_widget_show (frame5);
gtk_box_pack_start (GTK_BOX (vbox2), frame5, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame5), 4);
squelch_adj = gtk_adjustment_new (50, 0, 100, 1, 10, 0);
squelch = gtk_spin_button_new (GTK_ADJUSTMENT (squelch_adj), 1, 0);
gtk_widget_show (squelch);
gtk_container_add (GTK_CONTAINER (frame5), squelch);
label8 = gtk_label_new (_("Threshold"));
gtk_widget_show (label8);
gtk_frame_set_label_widget (GTK_FRAME (frame5), label8);
frame7 = gtk_frame_new (NULL);
gtk_widget_show (frame7);
gtk_box_pack_start (GTK_BOX (hbox2), frame7, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame7), 4);
alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1);
gtk_widget_show (alignment1);
gtk_container_add (GTK_CONTAINER (frame7), alignment1);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 2, 2, 2, 2);
waterfall = gtk_drawing_area_new ();
gtk_widget_show (waterfall);
gtk_container_add (GTK_CONTAINER (alignment1), waterfall);
gtk_widget_set_size_request (waterfall, 258, 89);
gtk_widget_set_events (waterfall, GDK_BUTTON_PRESS_MASK);
label7 = gtk_label_new (_("Waterfall"));
gtk_widget_show (label7);
gtk_frame_set_label_widget (GTK_FRAME (frame7), label7);
g_signal_connect ((gpointer) main_window, "destroy",
G_CALLBACK (on_main_window_destroy),
NULL);
g_signal_connect ((gpointer) main_window, "delete_event",
G_CALLBACK (on_main_window_delete_event),
NULL);
g_signal_connect ((gpointer) rx_togglebutton, "toggled",
G_CALLBACK (on_rx_togglebutton_toggled),
NULL);
g_signal_connect ((gpointer) clear, "clicked",
G_CALLBACK (on_clear_clicked),
NULL);
g_signal_connect ((gpointer) scope, "expose_event",
G_CALLBACK (on_scope_expose_event),
NULL);
g_signal_connect ((gpointer) scope, "button_press_event",
G_CALLBACK (on_scope_button_press_event),
NULL);
g_signal_connect ((gpointer) speed, "changed",
G_CALLBACK (on_speed_changed),
NULL);
g_signal_connect ((gpointer) wpm, "toggled",
G_CALLBACK (on_wpm_toggled),
NULL);
g_signal_connect ((gpointer) squelch, "changed",
G_CALLBACK (on_squelch_changed),
NULL);
g_signal_connect ((gpointer) waterfall, "expose_event",
G_CALLBACK (on_waterfall_expose_event),
NULL);
g_signal_connect ((gpointer) waterfall, "button_press_event",
G_CALLBACK (on_waterfall_button_press_event),
NULL);
g_signal_connect ((gpointer) waterfall, "size_allocate",
G_CALLBACK (on_waterfall_size_allocate),
NULL);
/* Store pointers to all widgets, for use by lookup_widget(). */
GLADE_HOOKUP_OBJECT_NO_REF (main_window, main_window, "main_window");
GLADE_HOOKUP_OBJECT (main_window, vbox1, "vbox1");
GLADE_HOOKUP_OBJECT (main_window, frame2, "frame2");
GLADE_HOOKUP_OBJECT (main_window, rx_scrolledwindow, "rx_scrolledwindow");
GLADE_HOOKUP_OBJECT (main_window, rx_textview, "rx_textview");
GLADE_HOOKUP_OBJECT (main_window, hbox4, "hbox4");
GLADE_HOOKUP_OBJECT (main_window, rx_togglebutton, "rx_togglebutton");
GLADE_HOOKUP_OBJECT (main_window, alignment3, "alignment3");
GLADE_HOOKUP_OBJECT (main_window, hbox5, "hbox5");
GLADE_HOOKUP_OBJECT (main_window, image2, "image2");
GLADE_HOOKUP_OBJECT (main_window, label9, "label9");
GLADE_HOOKUP_OBJECT (main_window, clear, "clear");
GLADE_HOOKUP_OBJECT (main_window, alignment4, "alignment4");
GLADE_HOOKUP_OBJECT (main_window, hbox6, "hbox6");
GLADE_HOOKUP_OBJECT (main_window, image3, "image3");
GLADE_HOOKUP_OBJECT (main_window, label10, "label10");
GLADE_HOOKUP_OBJECT (main_window, hbox1, "hbox1");
GLADE_HOOKUP_OBJECT (main_window, frame1, "frame1");
GLADE_HOOKUP_OBJECT (main_window, alignment2, "alignment2");
GLADE_HOOKUP_OBJECT (main_window, scope, "scope");
GLADE_HOOKUP_OBJECT (main_window, label1, "label1");
GLADE_HOOKUP_OBJECT (main_window, hbox2, "hbox2");
GLADE_HOOKUP_OBJECT (main_window, vbox2, "vbox2");
GLADE_HOOKUP_OBJECT (main_window, frame4, "frame4");
GLADE_HOOKUP_OBJECT (main_window, speed, "speed");
GLADE_HOOKUP_OBJECT (main_window, wpm, "wpm");
GLADE_HOOKUP_OBJECT (main_window, frame5, "frame5");
GLADE_HOOKUP_OBJECT (main_window, squelch, "squelch");
GLADE_HOOKUP_OBJECT (main_window, label8, "label8");
GLADE_HOOKUP_OBJECT (main_window, frame7, "frame7");
GLADE_HOOKUP_OBJECT (main_window, alignment1, "alignment1");
GLADE_HOOKUP_OBJECT (main_window, waterfall, "waterfall");
GLADE_HOOKUP_OBJECT (main_window, label7, "label7");
return main_window;
}
GtkWidget*
create_error_dialog (void)
{
GtkWidget *error_dialog;
GtkWidget *dialog_vbox1;
GtkWidget *frame6;
GtkWidget *hbox3;
GtkWidget *image1;
GtkWidget *error_message;
GtkWidget *label6;
GtkWidget *dialog_action_area1;
GtkWidget *err_quit_button;
GtkWidget *err_ok_button;
error_dialog = gtk_dialog_new ();
gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 4);
gtk_window_set_title (GTK_WINDOW (error_dialog), _("Xdemorse"));
gtk_window_set_position (GTK_WINDOW (error_dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_modal (GTK_WINDOW (error_dialog), TRUE);
gtk_window_set_type_hint (GTK_WINDOW (error_dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
dialog_vbox1 = GTK_DIALOG (error_dialog)->vbox;
gtk_widget_show (dialog_vbox1);
frame6 = gtk_frame_new (NULL);
gtk_widget_show (frame6);
gtk_box_pack_start (GTK_BOX (dialog_vbox1), frame6, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (frame6), 4);
hbox3 = gtk_hbox_new (FALSE, 0);
gtk_widget_show (hbox3);
gtk_container_add (GTK_CONTAINER (frame6), hbox3);
image1 = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_DIALOG);
gtk_widget_show (image1);
gtk_box_pack_start (GTK_BOX (hbox3), image1, FALSE, FALSE, 0);
error_message = gtk_label_new (_("Generic Error Message pop-up"));
gtk_widget_show (error_message);
gtk_box_pack_start (GTK_BOX (hbox3), error_message, FALSE, FALSE, 0);
gtk_misc_set_padding (GTK_MISC (error_message), 4, 0);
label6 = gtk_label_new (_("Error!"));
gtk_widget_show (label6);
gtk_frame_set_label_widget (GTK_FRAME (frame6), label6);
dialog_action_area1 = GTK_DIALOG (error_dialog)->action_area;
gtk_widget_show (dialog_action_area1);
gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
err_quit_button = gtk_button_new_from_stock ("gtk-quit");
gtk_widget_show (err_quit_button);
gtk_dialog_add_action_widget (GTK_DIALOG (error_dialog), err_quit_button, 0);
gtk_container_set_border_width (GTK_CONTAINER (err_quit_button), 2);
GTK_WIDGET_SET_FLAGS (err_quit_button, GTK_CAN_DEFAULT);
err_ok_button = gtk_button_new_from_stock ("gtk-ok");
gtk_widget_show (err_ok_button);
gtk_dialog_add_action_widget (GTK_DIALOG (error_dialog), err_ok_button, GTK_RESPONSE_OK);
gtk_container_set_border_width (GTK_CONTAINER (err_ok_button), 2);
GTK_WIDGET_SET_FLAGS (err_ok_button, GTK_CAN_DEFAULT);
g_signal_connect ((gpointer) error_dialog, "destroy",
G_CALLBACK (on_error_dialog_destroy),
NULL);
g_signal_connect ((gpointer) error_dialog, "delete_event",
G_CALLBACK (on_error_dialog_delete_event),
NULL);
g_signal_connect ((gpointer) err_quit_button, "clicked",
G_CALLBACK (on_err_quit_clicked),
NULL);
g_signal_connect ((gpointer) err_ok_button, "clicked",
G_CALLBACK (on_err_ok_button_clicked),
NULL);
/* Store pointers to all widgets, for use by lookup_widget(). */
GLADE_HOOKUP_OBJECT_NO_REF (error_dialog, error_dialog, "error_dialog");
GLADE_HOOKUP_OBJECT_NO_REF (error_dialog, dialog_vbox1, "dialog_vbox1");
GLADE_HOOKUP_OBJECT (error_dialog, frame6, "frame6");
GLADE_HOOKUP_OBJECT (error_dialog, hbox3, "hbox3");
GLADE_HOOKUP_OBJECT (error_dialog, image1, "image1");
GLADE_HOOKUP_OBJECT (error_dialog, error_message, "error_message");
GLADE_HOOKUP_OBJECT (error_dialog, label6, "label6");
GLADE_HOOKUP_OBJECT_NO_REF (error_dialog, dialog_action_area1, "dialog_action_area1");
GLADE_HOOKUP_OBJECT (error_dialog, err_quit_button, "err_quit_button");
GLADE_HOOKUP_OBJECT (error_dialog, err_ok_button, "err_ok_button");
return error_dialog;
}
xdemorse-1.3.orig/src/detect.c 0000644 0001750 0001750 00000013434 10772450177 014654 0 ustar pg4i pg4i /* detect.c
*
* Signal detection functions of xdemorse application
*/
/*
* xdemorse: An application to decode Morse code signals to text
*
* Copyright (C) 2002 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#include "xdemorse.h"
#include "detect.h"
/* Runtime config data */
extern rc_data_t rc_data;
/*------------------------------------------------------------------------*/
/* Get_Fragment()
*
* Detects the cw beat frequency signal o/p from the radio
* receiver and determines the status, (mark or space) of a
* 'fragment' (a small fraction, ~1/8) of a Morse code element.
* Signal detection is done by using a Goertzel algorithm.
*/
int
Get_Fragment( void )
{
int
frag_lev, /* Level of the Morse signal 'fragment' */
frag_timer, /* Counter for timing duration of fragment */
block_size, /* Block size (N) of the Goertzel algorithm */
up_steps, /* Num of consecutive increasing signal levels */
dn_steps, /* Num of consecutive decreasing signal levels */
idx;
/* Variables for the Goertzel algorithm */
double q0, q1, q2;
/* Goertzel block size depends on Morse speed */
block_size = detector_data.frag_len * rc_data.unit_elem;
/* Buffer dsp samples of input signal for a fragment */
for(frag_timer = 0; frag_timer < detector_data.frag_len; frag_timer++ )
{
/* Get next signal sample from buffer, abort on error */
detector_data.samples_buff[detector_data.samples_buff_idx] =
Signal_Sample();
if( isFlagSet(DSP_IO_ERROR) )
return(-1);
/* Advance/Reset circular buffers' index */
if( ++detector_data.samples_buff_idx >= detector_data.samples_buff_len )
detector_data.samples_buff_idx = 0;
} /* for( frag_timer = 0; frag_timer < frag_len ... */
/** Calculate signal fragment level over a block **/
/* Backstep buffer index for use of samples */
detector_data.samples_buff_idx -= block_size;
if( detector_data.samples_buff_idx < 0 )
detector_data.samples_buff_idx += detector_data.samples_buff_len;
/* Calculate fragment level using Goertzel algorithm */
q1 = q2 = 0.0;
for( idx = 0; idx < block_size; idx++ )
{
q0 = detector_data.coeff * q1 - q2 +
detector_data.samples_buff[detector_data.samples_buff_idx];
q2 = q1;
q1 = q0;
/* Reset circular buffers' index */
if( ++detector_data.samples_buff_idx >= detector_data.samples_buff_len )
detector_data.samples_buff_idx = 0;
}
/* Scalar magnitude of input signal scaled by block size */
q1 /= (double)block_size;
q2 /= (double)block_size;
frag_lev = (int)(q1*q1 + q2*q2 - q1*q2*detector_data.coeff);
/* Save signal power level to circular buffer */
detector_data.sig_level_buff[detector_data.sig_level_idx] = frag_lev;
if( ++detector_data.sig_level_idx >= rc_data.max_unit )
detector_data.sig_level_idx = 0;
/* Backstep buffer index for use of fragment levels */
detector_data.sig_level_idx -= rc_data.unit_elem;
if( detector_data.sig_level_idx < 0 )
detector_data.sig_level_idx += rc_data.max_unit;
/* Count the number of "steps" in the signal's edge that are
* in the same direction (increasing or decreasing amplitude) */
up_steps = dn_steps = 0;
for( idx = 1; idx < rc_data.unit_elem; idx++ )
{
int tmp1, tmp2;
/* Compare successive signal levels */
tmp1 = detector_data.sig_level_buff[detector_data.sig_level_idx];
if( ++detector_data.sig_level_idx >= rc_data.max_unit )
detector_data.sig_level_idx = 0;
tmp2 = detector_data.sig_level_buff[detector_data.sig_level_idx];
/* Successive levels are compared for more
* than STEP_THRESHOLD difference up or down */
if( STEP_THRESHOLD*tmp1 < 100*tmp2 )
up_steps++;
else if( 100*tmp1 > STEP_THRESHOLD*tmp2 )
dn_steps++;
}
if( ++detector_data.sig_level_idx >= rc_data.max_unit )
detector_data.sig_level_idx = 0;
/* Set tone status. */
if( 100*up_steps > rc_data.det_thr*(rc_data.unit_elem-1) )
Set_Flag( MARK_TONE );
else
if( 100*dn_steps > rc_data.det_thr*(rc_data.unit_elem-1) )
Clear_Flag( MARK_TONE );
/* Display signal graph (scope) */
if( isFlagSet(DISPLAY_DETECTOR) )
Display_Detector( (87*up_steps)/rc_data.unit_elem );
else
if( isFlagSet(DISPLAY_SIGNAL) )
Display_Signal( frag_lev );
return( frag_lev );
} /* End of Get_Fragment() */
/*------------------------------------------------------------------------*/
/* Initialize_Detector()
*
* Initializes variables and allocates buffers
* for the Goertzel tone detector
*/
gboolean
Initialize_Detector( void )
{
double w =
2.0 * M_PI * (double)rc_data.tone_freq /
(double)rc_data.dsp_speed;
detector_data.cosw = cos(w);
detector_data.sinw = sin(w);
detector_data.coeff = 2.0 * detector_data.cosw;
detector_data.samples_buff_idx = 0;
detector_data.sig_level_idx = 0;
detector_data.frag_len =
( rc_data.dsp_speed * CYCLES_PER_FRAG ) / rc_data.tone_freq;
detector_data.samples_buff_len =
(CYCLES_PER_FRAG *rc_data.max_unit *rc_data.dsp_speed) / rc_data.tone_freq;
size_t alloc =
(CYCLES_PER_FRAG *rc_data.max_unit *rc_data.dsp_speed) / rc_data.tone_freq;
if( !mem_alloc((void *)&detector_data.samples_buff, alloc) )
return( FALSE );
alloc = sizeof(int) * rc_data.max_unit;
if( !mem_alloc( (void *)&detector_data.sig_level_buff, alloc) )
return( FALSE );
return( TRUE );
} /* Initialize_Detector() */
/*------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/support.c 0000644 0001750 0001750 00000007127 11111311621 015074 0 ustar pg4i pg4i /*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include "support.h"
GtkWidget*
lookup_widget (GtkWidget *widget,
const gchar *widget_name)
{
GtkWidget *parent, *found_widget;
for (;;)
{
if (GTK_IS_MENU (widget))
parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
else
parent = widget->parent;
if (!parent)
parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
if (parent == NULL)
break;
widget = parent;
}
found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
widget_name);
if (!found_widget)
g_warning ("Widget not found: %s", widget_name);
return found_widget;
}
static GList *pixmaps_directories = NULL;
/* Use this function to set the directory containing installed pixmaps. */
void
add_pixmap_directory (const gchar *directory)
{
pixmaps_directories = g_list_prepend (pixmaps_directories,
g_strdup (directory));
}
/* This is an internally used function to find pixmap files. */
static gchar*
find_pixmap_file (const gchar *filename)
{
GList *elem;
/* We step through each of the pixmaps directory to find it. */
elem = pixmaps_directories;
while (elem)
{
gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data,
G_DIR_SEPARATOR_S, filename);
if (g_file_test (pathname, G_FILE_TEST_EXISTS))
return pathname;
g_free (pathname);
elem = elem->next;
}
return NULL;
}
/* This is an internally used function to create pixmaps. */
GtkWidget*
create_pixmap (GtkWidget *widget,
const gchar *filename)
{
gchar *pathname = NULL;
GtkWidget *pixmap;
if (!filename || !filename[0])
return gtk_image_new ();
pathname = find_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return gtk_image_new ();
}
pixmap = gtk_image_new_from_file (pathname);
g_free (pathname);
return pixmap;
}
/* This is an internally used function to create pixmaps. */
GdkPixbuf*
create_pixbuf (const gchar *filename)
{
gchar *pathname = NULL;
GdkPixbuf *pixbuf;
GError *error = NULL;
if (!filename || !filename[0])
return NULL;
pathname = find_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return NULL;
}
pixbuf = gdk_pixbuf_new_from_file (pathname, &error);
if (!pixbuf)
{
fprintf (stderr, "Failed to load pixbuf file: %s: %s\n",
pathname, error->message);
g_error_free (error);
}
g_free (pathname);
return pixbuf;
}
/* This is used to set ATK action descriptions. */
void
glade_set_atk_action_description (AtkAction *action,
const gchar *action_name,
const gchar *description)
{
gint n_actions, i;
n_actions = atk_action_get_n_actions (action);
for (i = 0; i < n_actions; i++)
{
if (!strcmp (atk_action_get_name (action, i), action_name))
atk_action_set_description (action, i, description);
}
}
xdemorse-1.3.orig/src/fft.c 0000644 0001750 0001750 00000005313 10772444377 014165 0 ustar pg4i pg4i /* fft.c
*
* FFT functions of xdemorse-fft application
*/
/*
* xdemorse: An application to decode Morse code signals to text
*
* Copyright (C) 2002 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#include "xdemorse.h"
/* fft in/out buffers */
int
*fft_in_r,
*fft_out_r,
*fft_out_i;
/* Scaled-up, integer, sin/cos tables */
static int
*isin,
*icos;
/*------------------------------------------------------------------------*/
/* Ifft_init()
*
* Initializes Ifft()
*/
void
Ifft_init( int fft_size )
{
int i;
double w, tpi;
/* Allocate fft buffers */
i = sizeof(int) * fft_size;
mem_alloc( (void *)&fft_in_r, i );
mem_alloc( (void *)&isin, i );
mem_alloc( (void *)&icos, i );
i = sizeof(int) * fft_size / 2;
mem_alloc( (void *)&fft_out_r, i );
mem_alloc( (void *)&fft_out_i, i );
/* Make sin/cos tables */
tpi = 2.0 * M_PI;
for( i = 0; i < fft_size; i++ )
{
w = tpi * (double)i / (double)fft_size;
isin[i] = (int)(32.0 * sin(w) + 0.5);
icos[i] = (int)(32.0 * cos(w) + 0.5);
}
} /* Ifft_init() */
/*------------------------------------------------------------------------*/
/* Ifft()
*
* Simple, integer-only, FFT function
*/
void
Ifft( int fft_size )
{
int i, j, w;
/* In-phase and quadrature summation */
int sum_i, sum_q;
int k = fft_size/2;
/* Calculate output bins */
for( i = 0; i < k; i++ )
{
sum_i = sum_q = w = 0;
/* Summate input values */
for( j = 0; j < fft_size; j++ )
{
w += i;
if( w >= fft_size )
w -= fft_size;
sum_i += fft_in_r[j] * isin[w];
sum_q += fft_in_r[j] * icos[w];
}
/* Normalized summations to bins */
fft_out_r[i] = sum_i/fft_size;
fft_out_i[i] = sum_q/fft_size;
} /* for( i = 0; i < k; i++ ) */
} /* Ifft() */
/*------------------------------------------------------------------------*/
gboolean mem_alloc( void **ptr, int req )
{
*ptr = malloc( req );
if( *ptr == NULL )
{
perror( "xdemorse: Memory allocation request:" );
Error_Dialog(
"Memory allocation request failed"
"Quit xdemorse and correct" );
return( FALSE );
}
bzero( *ptr, req );
return( TRUE );
} /* End of void mem_alloc() */
/*------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/callbacks.c 0000644 0001750 0001750 00000013477 10772754057 015336 0 ustar pg4i pg4i #ifdef HAVE_CONFIG_H
# include
#endif
#include
#include "callbacks.h"
#include "interface.h"
#include "support.h"
#include "xdemorse.h"
/* Speed and squelch spin buttond */
extern GtkSpinButton
*gbl_speed,
*gbl_squelch;
/* Global widgets */
extern GtkWidget
*gbl_rx_scrolledwindow,
*gbl_scope,
*gbl_scope_label;
GtkWidget *error_dialog = NULL;
/* Text buffer for text viewer */
GtkTextBuffer *gbl_rx_text_buffer;
/* Runtime config data */
extern rc_data_t rc_data;
/* Waterfall window pixbuf */
extern GdkPixbuf *gbl_wfall_pixbuf;
extern guchar *gbl_wfall_pixels;
extern gint
gbl_wfall_rowstride,
gbl_wfall_n_channels,
gbl_wfall_width,
gbl_wfall_height;
/* Error_Dialog()
*
* Opens an error dialog box
*/
void
Error_Dialog( char *message )
{
GtkWidget *label;
if( error_dialog != NULL ) return;
error_dialog = create_error_dialog();
label = lookup_widget( error_dialog, "error_message" );
gtk_label_set_text( GTK_LABEL(label), message );
gtk_widget_show( error_dialog );
}
void
on_main_window_destroy(
GtkObject *object,
gpointer user_data)
{
Cleanup();
gtk_main_quit();
}
gboolean
on_main_window_delete_event(
GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
return FALSE;
}
gboolean
on_scope_expose_event(
GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
/* Draw scope background */
gdk_draw_rectangle( widget->window,
widget->style->white_gc,
TRUE, 4, 4, 255, 80 );
/* Draw scope frame */
gdk_draw_rectangle( widget->window,
widget->style->black_gc,
FALSE, 3, 3, 256, 81 );
gtk_label_set_text( GTK_LABEL(gbl_scope_label), "Signal Input" );
return TRUE;
}
gboolean
on_scope_button_press_event(
GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
switch( event->button )
{
case 1: /* Button 1 pressed */
Toggle_Flag( DISPLAY_SIGNAL );
Clear_Flag( DISPLAY_DETECTOR );
break;
case 2: /* Button 3 pressed */
Clear_Flag( DISPLAY_SIGNAL );
Clear_Flag( DISPLAY_DETECTOR );
break;
case 3: /* Button 2 pressed */
Toggle_Flag( DISPLAY_DETECTOR );
Clear_Flag( DISPLAY_SIGNAL );
} /* switch( event->button ) */
/* Set scope label */
if( isFlagSet(DISPLAY_SIGNAL) )
gtk_label_set_text( GTK_LABEL(gbl_scope_label), "Signal Input" );
else
if( isFlagSet(DISPLAY_DETECTOR) )
gtk_label_set_text( GTK_LABEL(gbl_scope_label), "Detector Output" );
else
gtk_label_set_text( GTK_LABEL(gbl_scope_label), "Stopped" );
return TRUE;
}
void
on_speed_changed(
GtkEditable *editable,
gpointer user_data)
{
rc_data.unit_elem = gtk_spin_button_get_value_as_int( gbl_speed );
rc_data.unit_elem = (60 * rc_data.tone_freq) /
(50 * CYCLES_PER_FRAG * rc_data.unit_elem);
}
void
on_squelch_changed(
GtkEditable *editable,
gpointer user_data)
{
rc_data.det_thr = (int)gtk_spin_button_get_value( gbl_squelch );
}
void
on_err_quit_clicked(
GtkButton *button,
gpointer user_data)
{
Cleanup();
gtk_main_quit();
}
void
on_clear_clicked(
GtkButton *button,
gpointer user_data)
{
gtk_text_buffer_set_text( gbl_rx_text_buffer, "", -1 );
}
gboolean
on_waterfall_expose_event(
GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
if( gbl_wfall_pixbuf == NULL )
return( TRUE );
gdk_draw_pixbuf(
widget->window, NULL, gbl_wfall_pixbuf,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height,
GDK_RGB_DITHER_NONE, 0, 0 );
return TRUE;
}
gboolean
on_waterfall_button_press_event(
GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
if( event->button == 1 )
{
if( isFlagSet(CAT_SETUP) )
Tune_Tcvr( event->x );
}
else
Toggle_Flag( REVERSE_VIDEO );
return TRUE;
}
void
on_err_ok_button_clicked(
GtkButton *button,
gpointer user_data)
{
gtk_widget_destroy( error_dialog );
}
void
on_wpm_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
if( gtk_toggle_button_get_active(togglebutton) )
Set_Flag( ADAPT_SPEED );
else
Clear_Flag( ADAPT_SPEED );
}
void
on_error_dialog_destroy (GtkObject *object,
gpointer user_data)
{
error_dialog = NULL;
}
gboolean
on_error_dialog_delete_event (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
return TRUE;
}
void
on_waterfall_size_allocate (GtkWidget *widget,
GdkRectangle *allocation,
gpointer user_data)
{
/* Destroy existing pixbuff */
if( gbl_wfall_pixbuf != NULL )
{
g_object_unref( G_OBJECT(gbl_wfall_pixbuf) );
gbl_wfall_pixbuf = NULL;
}
/* Create waterfall pixbuf */
gbl_wfall_pixbuf = gdk_pixbuf_new(
GDK_COLORSPACE_RGB, FALSE, 8,
allocation->width, allocation->height );
if( gbl_wfall_pixbuf == NULL )
{
Error_Dialog( "Failed to create pixbuf for waterfall" );
return;
}
gbl_wfall_pixels = gdk_pixbuf_get_pixels( gbl_wfall_pixbuf );
gbl_wfall_width = gdk_pixbuf_get_width ( gbl_wfall_pixbuf );
gbl_wfall_height = gdk_pixbuf_get_height( gbl_wfall_pixbuf );
gbl_wfall_rowstride = gdk_pixbuf_get_rowstride( gbl_wfall_pixbuf );
gbl_wfall_n_channels = gdk_pixbuf_get_n_channels( gbl_wfall_pixbuf );
Clear_Pixbuf();
}
void
on_rx_togglebutton_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
if( gtk_toggle_button_get_active(togglebutton) &&
isFlagSet(ENABLE_RECEIVE) )
gtk_idle_add( Print_Character, "RX" );
else
g_idle_remove_by_data( "RX" );
}
xdemorse-1.3.orig/src/interface.h 0000644 0001750 0001750 00000000212 11111311621 015311 0 ustar pg4i pg4i /*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
GtkWidget* create_main_window (void);
GtkWidget* create_error_dialog (void);
xdemorse-1.3.orig/src/main.c 0000644 0001750 0001750 00000040142 10773350052 014314 0 ustar pg4i pg4i /*
* Initial main.c file generated by Glade. Edit as required.
* Glade will not overwrite this file.
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include "interface.h"
#include "support.h"
#include "xdemorse.h"
/* xdemorse main window */
GtkWidget *main_window;
/* Global widgets */
GtkWidget
*gbl_rx_scrolledwindow,
*gbl_scope,
*gbl_waterfall,
*gbl_scope_label;
/* Speed and squelch spin button */
GtkSpinButton
*gbl_speed,
*gbl_squelch;
/* Text buffer for text viewer */
GtkTextBuffer *gbl_rx_text_buffer;
int
dsp_fd, /* File descriptor of dsp device */
mix_fd; /* File descriptor of mixer device */
/* Signal handler */
static void sig_handler( int signal );
/* Runtime config data */
rc_data_t rc_data;
/* Waterfall window pixbuf */
GdkPixbuf *gbl_wfall_pixbuf = NULL;
guchar *gbl_wfall_pixels;
gint
gbl_wfall_rowstride,
gbl_wfall_n_channels,
gbl_wfall_width,
gbl_wfall_height;
/*------------------------------------------------------------------------*/
int
main (int argc, char *argv[])
{
/* Main window */
GtkWidget *main_window;
/* Command line option returned by getopt() */
int option;
/* getopt() variables */
extern char *optarg;
extern int optind, opterr, optopt;
/* New and old actions for sigaction() */
struct sigaction sa_new, sa_old;
/* Initialize new actions */
sa_new.sa_handler = sig_handler;
sigemptyset( &sa_new.sa_mask );
sa_new.sa_flags = 0;
/* Register function to handle signals */
sigaction( SIGINT, &sa_new, &sa_old );
sigaction( SIGSEGV, &sa_new, 0 );
sigaction( SIGFPE, &sa_new, 0 );
sigaction( SIGTERM, &sa_new, 0 );
sigaction( SIGABRT, &sa_new, 0 );
gtk_set_locale ();
gtk_init (&argc, &argv);
Set_Flag( ADAPT_SPEED | DISPLAY_SIGNAL);
rc_data.unit_elem = 15;
/* Process command line options */
while( (option = getopt(argc, argv, "hlv") ) != -1 )
switch( option )
{
case 'h': /* Print usage and exit */
Usage();
exit( 0 );
case 'l': /* Print available mixer devices */
{
/* Sound device names from souncard.h */
char *dev_name[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
int device;
puts("Printing out mixer device names" );
for( device = 0; device < SOUND_MIXER_NRDEVICES; device++ )
puts( dev_name[device] );
exit( 0 );
}
case 'v': /* Print version */
printf( "%s %s\n", PACKAGE, VERSION );
exit( 0 );
default: /* Print usage and exit */
Usage();
exit( -1 );
} /* End of switch( option ) */
/*
* The following code was added by Glade to create one of each component
* (except popup menus), just so that you see something after building
* the project. Delete any components that you don't want shown initially.
*/
main_window = create_main_window ();
gtk_window_set_title( GTK_WINDOW(main_window), PACKAGE"-"VERSION );
/* Get Rx text buffer and scroller */
gbl_rx_text_buffer = gtk_text_view_get_buffer
( GTK_TEXT_VIEW(lookup_widget(main_window, "rx_textview")) );
gbl_rx_scrolledwindow = lookup_widget( main_window, "rx_scrolledwindow" );
/* Get widgets and spin buttons */
gbl_scope = lookup_widget( main_window, "scope" );
gbl_waterfall = lookup_widget( main_window, "waterfall" );
gbl_scope_label = lookup_widget( main_window, "label1" );
gbl_speed = GTK_SPIN_BUTTON( lookup_widget(main_window, "speed") );
gbl_squelch = GTK_SPIN_BUTTON( lookup_widget(main_window, "squelch") );
rc_data.det_thr = (int)gtk_spin_button_get_value( gbl_squelch );
rc_data.spd_wpm = (int)gtk_spin_button_get_value( gbl_speed );
gtk_widget_show (main_window);
/* Initialize FFT */
Ifft_init( FFT_SIZE );
/* Load runtime config file, abort on error */
gtk_idle_add( Load_Config, NULL );
gtk_main ();
return 0;
}
/*------------------------------------------------------------------------*/
/* Load_Config()
*
* Loads the xdemorserc configuration file
*/
gboolean
Load_Config( gpointer data )
{
char
rc_fpath[64], /* File path to xdemorserc */
line[81]; /* Buffer for Load_Line */
/* Config file pointer */
FILE *xdemorserc;
/* Setup file path to xdemorserc */
snprintf( rc_fpath, 64, "%s/.xdemorserc", getenv("HOME") );
/* Open xdemorserc file */
xdemorserc = fopen( rc_fpath, "r" );
if( xdemorserc == NULL )
{
perror( rc_fpath );
Error_Dialog(
"Failed to open xdemorserc file\n"
"Quit xdemorse and correct" );
return( FALSE );
}
/*** Read runtime configuration data ***/
/* Read mixer dev, abort if EOF */
if( Load_Line(line, xdemorserc, "Mixer Device" ) != SUCCESS )
return( FALSE );
strncpy( rc_data.mix_dev, line, 20 );
rc_data.mix_dev[20] = '\0';
/* Read input DSP dev, abort if EOF */
if( Load_Line(line, xdemorserc, "Input DSP Device") != SUCCESS )
return( FALSE );
strncpy( rc_data.dsp_dev, line, 20 );
rc_data.dsp_dev[20] = '\0';
/* Read DSP speed Samples/sec, abort if EOF */
if( Load_Line(line, xdemorserc, "DSP Speed" ) != SUCCESS )
return( FALSE );
rc_data.dsp_speed = atoi( line );
/* Read recording source, abort if EOF */
if( Load_Line(line, xdemorserc, "Recording Source") != SUCCESS )
return( FALSE );
strncpy( rc_data.rec_src, line, 20 );
rc_data.rec_src[20] = '\0';
/* Read Recording level device, abort if EOF */
if( Load_Line(line, xdemorserc, "Recording Level Device") != SUCCESS )
return( FALSE );
strncpy( rc_data.inp_lev, line, 20 );
rc_data.inp_lev[20] = '\0';
/* Read Recording level, abort if EOF */
if( Load_Line(line, xdemorserc, "Recording Level") != 0 )
return( FALSE );
rc_data.rec_lev = atoi( line );
/* Read stero/mono mode, abort if EOF */
if( Load_Line(line, xdemorserc, "Stero|Mono Mode") != SUCCESS )
return( FALSE );
line[6] = '\0';
if( strcmp(line, "STEREO") == 0 )
rc_data.num_chn = 2;
else if( strcmp(line, "MONO") == 0 )
rc_data.num_chn = 1;
else
{
Error_Dialog(
"Error reading Stereo or Mono mode\n"
"Quit and correct xdemorserc" );
return( FALSE );
}
/* Read channel used, abort if EOF */
if( Load_Line(line, xdemorserc, "Left|Right Channel") != SUCCESS )
return( FALSE );
line[5] = '\0';
if( strcmp(line, "LEFT") == 0 )
rc_data.use_chn = 0;
else if( strcmp(line, "RIGHT") == SUCCESS )
rc_data.use_chn = 1;
else
{
Error_Dialog(
"Error reading Stereo channel to use\n"
"Quit and correct xdemorserc" );
return( FALSE );
}
/* Read max WPM, abort if EOF */
if( Load_Line(line, xdemorserc, "Maximum WPM") != SUCCESS )
return( FALSE );
rc_data.min_unit = atoi( line );
/* Read min WPM, abort if EOF */
if( Load_Line(line, xdemorserc, "Minimum WPM") != SUCCESS )
return( FALSE );
rc_data.max_unit = atoi( line );
/* Check range of Morse speeds. At this point max_unit
* holds minimum wpm and min_unit holds maximum wpm */
if( (rc_data.max_unit < MIN_SPEED) ||
(rc_data.min_unit > MAX_SPEED) )
{
Error_Dialog(
"Morse code speed (WPM)\n"
"range is out of limits\n"
"Quit and correct xdemorserc" );
return( FALSE );
}
/* Set spinbutton range */
gtk_spin_button_set_range( gbl_speed,
(gdouble)rc_data.max_unit, (gdouble)rc_data.min_unit );
/* Read and check initial WPM, abort if EOF */
if( Load_Line(line, xdemorserc, "Initial WPM") != SUCCESS )
return( FALSE );
int wpm = atoi( line );
/* Check initial Morse speed. At this point max_unit
* holds minimum wpm and min_unit holds maximum wpm */
if( (wpm > rc_data.min_unit) ||
(wpm < rc_data.max_unit) )
{
Error_Dialog(
"Initial Morse code speed (WPM)\n"
"is out of specified range\n"
"Quit and correct xdemorserc" );
return( FALSE );
}
/* Read word wrap column, abort if EOF */
if( Load_Line(line, xdemorserc, "Word Wrap Column") != SUCCESS )
return( FALSE );
rc_data.wrd_wrp = atoi( line );
/* Read FT-847 serial port device, abort if EOF */
if( Load_Line(line, xdemorserc, "FT-847 Serial Port") != SUCCESS )
return( FALSE );
strncpy( rc_data.ft847_serial, line, 31 );
rc_data.ft847_serial[31] = '\0';
/* Read FT-857 serial port device, abort if EOF */
if( Load_Line(line, xdemorserc, "FT-857 Serial Port") != SUCCESS )
return( FALSE );
strncpy( rc_data.ft857_serial, line, 31 );
rc_data.ft857_serial[31] = '\0';
/* Read CAT enable flag, abort if EOF */
if( Load_Line(line, xdemorserc, "CAT Enable") != SUCCESS )
return( FALSE );
if( strcmp(line, "FT847") == 0 )
rc_data.tcvr_type = FT847;
else if( strcmp(line, "FT857") == 0 )
rc_data.tcvr_type = FT857;
else if( strcmp(line, "NONE") == 0 )
rc_data.tcvr_type = NONE;
else
{
rc_data.tcvr_type = NONE;
Error_Dialog(
"Error reading Transceiver type\n"
"Quit and correct xdemorserc" );
}
/* Read input tone (Rx BFO) frequency */
if( Load_Line(line, xdemorserc, "Input Tone") != SUCCESS )
return( FALSE );
rc_data.tone_freq = atoi( line );
/* The tone freq must be rounded so that the fft_stride
* is an integer otherwise the waterfall is not accurate */
rc_data.fft_stride = rc_data.dsp_speed/rc_data.tone_freq/4;
rc_data.tone_freq = rc_data.dsp_speed/rc_data.fft_stride/4;
/* Calculate parameters that depend on above */
rc_data.max_unit = (60*rc_data.tone_freq) /
(50*CYCLES_PER_FRAG*rc_data.max_unit);
rc_data.min_unit = (60*rc_data.tone_freq) /
(50*CYCLES_PER_FRAG*rc_data.min_unit);
gtk_spin_button_set_value( gbl_speed, (gdouble)wpm );
rc_data.unit_elem =
(60 * rc_data.tone_freq) / (50 * CYCLES_PER_FRAG * wpm);
rc_data.red_line = FFT_SIZE / 4;
/* Select Transceiver type */
switch( rc_data.tcvr_type )
{
case FT847:
Set_Flag( ENABLE_CAT | ENABLE_CAT_847 );
Open_Tcvr_Serial();
break;
case FT857:
Set_Flag( ENABLE_CAT | ENABLE_CAT_857 );
Open_Tcvr_Serial();
break;
case NONE:
Clear_Flag( ENABLE_CAT );
}
/* Allocate memory to recv samples buffer */
rc_data.buffer_idx = rc_data.buffer_size = BUFFER_SIZE * rc_data.num_chn;
rc_data.buffer = malloc( (size_t)rc_data.buffer_size );
if( rc_data.buffer == NULL )
{
Error_Dialog(
"Memory allocation for buffer failed\n"
"Quit xdemorse and correct" );
return( FALSE );
}
fclose( xdemorserc );
/* Enable receiving Morse code */
if( Setup_Sound_Card() && Initialize_Detector() )
Set_Flag( ENABLE_RECEIVE );
return( FALSE );
} /* End of Load_Config() */
/*------------------------------------------------------------------*/
/* Load_Line()
*
* Loads a line from a file, aborts on failure. Lines beginning
* with a '#' are ignored as comments. At the end of file EOF is
* returned. Lines assumed maximum 80 characters long.
*/
int
Load_Line( char *buff, FILE *pfile, char *messg )
{
int
num_chr, /* Number of characters read, excluding lf/cr */
chr; /* Character read by getc() */
char err_msg[128];
/* Prepare error message */
snprintf( err_msg, 128,
"Error reading %s\n"
"Premature EOF (End Of File)", messg );
/* Clear buffer at start */
buff[0] = '\0';
num_chr = 0;
/* Get next character, return error if chr = EOF */
if( (chr = fgetc(pfile)) == EOF )
{
fprintf( stderr, "xdemorse: %s\n", err_msg );
Error_Dialog( err_msg );
return( EOF );
}
/* Ignore commented lines, white spaces and eol/cr */
while(
(chr == '#') ||
(chr == ' ') ||
(chr == HT ) ||
(chr == CR ) ||
(chr == LF ) )
{
/* Go to the end of line (look for LF or CR) */
while( (chr != CR) && (chr != LF) )
/* Get next character, return error if chr = EOF */
if( (chr = fgetc(pfile)) == EOF )
{
fprintf( stderr, "xdemorse: %s\n", err_msg );
Error_Dialog( err_msg );
return( EOF );
}
/* Dump any CR/LF remaining */
while( (chr == CR) || (chr == LF) )
/* Get next character, return error if chr = EOF */
if( (chr = fgetc(pfile)) == EOF )
{
fprintf( stderr, "xdemorse: %s\n", err_msg );
Error_Dialog( err_msg );
return( EOF );
}
} /* End of while( (chr == '#') || ... */
/* Continue reading characters from file till
* number of characters = 80 or EOF or CR/LF */
while( num_chr < 80 )
{
/* If LF/CR reached before filling buffer, return line */
if( (chr == LF) || (chr == CR) ) break;
/* Enter new character to line buffer */
buff[num_chr++] = chr;
/* Get next character */
if( (chr = fgetc(pfile)) == EOF )
{
/* Terminate buffer as a string if chr = EOF */
buff[num_chr] = '\0';
return( SUCCESS );
}
/* Abort if end of line not reached at 80 char. */
if( (num_chr == 80) && (chr != LF) && (chr != CR) )
{
/* Terminate buffer as a string */
buff[num_chr] = '\0';
snprintf( err_msg, 128,
"Error reading %s\n"
"Line longer than 80 characters", messg );
fprintf( stderr, "xdemorse: %s\n%s\n", err_msg, buff );
Error_Dialog( err_msg );
return( ERROR );
}
} /* End of while( num_chr < max_chr ) */
/* Terminate buffer as a string */
buff[num_chr] = '\0';
return( SUCCESS );
} /* End of Load_Line() */
/*------------------------------------------------------------------*/
/* Print_Character()
*
* Prints a character to a text view port
*/
gboolean
Print_Character( gpointer data )
{
/* Text buffer marker */
static GtkTextIter iter;
GtkAdjustment *adjustment;
char
dec_char, /* Decoded Morse character */
char2text[2]; /* Convert char to string */
/* Number of chars printed on a line */
static int line_idx = 0;
/* Print decoded characters with word wrap */
if( (dec_char = Get_Character()) )
{
/* Do word wrapping */
if( (line_idx++ > rc_data.wrd_wrp) &&
(dec_char == ' ') )
{
dec_char = '\n';
line_idx = 0;
}
/* Convert char to 'text' */
char2text[0] = dec_char;
char2text[1] = '\0';
/* Print character */
gtk_text_buffer_get_iter_at_offset( gbl_rx_text_buffer, &iter,
gtk_text_buffer_get_char_count
(gbl_rx_text_buffer) );
gtk_text_buffer_insert( gbl_rx_text_buffer, &iter,
char2text, -1 );
/* Scroll Text View to bottom on LF */
if( (dec_char == '\n') )
{
adjustment = gtk_scrolled_window_get_vadjustment
( GTK_SCROLLED_WINDOW(gbl_rx_scrolledwindow) );
gtk_adjustment_set_value( adjustment, adjustment->upper );
}
} /* if( dec_char = Get_Character() ) */
if( isFlagClear(DSP_IO_ERROR) )
return( TRUE );
else
return( FALSE );
} /* Print_Character() */
/*------------------------------------------------------------------------*/
/* Usage()
*
* Prints usage information
*/
void
Usage( void )
{
fprintf( stderr, "%s\n",
"Usage: demorse [-hv]" );
fprintf( stderr, "%s\n",
" -h: Print this usage information and exit");
fprintf( stderr, "%s\n",
" -v: Print version number and exit");
} /* End of Usage() */
/*------------------------------------------------------------------------*/
/* sig_handler()
*
* Signal Action Handler function
*/
static void sig_handler( int signal )
{
/* Wrap up and quit */
Cleanup();
fprintf( stderr, "\n" );
switch( signal )
{
case SIGINT :
fprintf( stderr, "%s\n", "xdemorse: Exiting via User Interrupt" );
exit( signal );
case SIGSEGV :
fprintf( stderr, "%s\n", "xdemorse: Segmentation Fault" );
exit( signal );
case SIGFPE :
fprintf( stderr, "%s\n", "xdemorse: Floating Point Exception" );
exit( signal );
case SIGABRT :
fprintf( stderr, "%s\n", "xdemorse: Abort Signal received" );
exit( signal );
case SIGTERM :
fprintf( stderr, "%s\n", "xdemorse: Termination Request received" );
exit( signal );
}
} /* End of sig_handler() */
/*------------------------------------------------------------------------*/
/* Functions for testing and setting/clearing flow control flags
*
* See xdemorse.h for definition of flow control flags
*/
/* An int variable holding the single-bit flags */
static int Flags = 0;
int
isFlagSet( int flag )
{
return( (Flags & flag) == flag );
}
int
isFlagClear( int flag )
{
return( (~Flags & flag) == flag );
}
void
Set_Flag( int flag )
{
Flags |= flag;
}
void
Clear_Flag( int flag )
{
Flags &= ~flag;
}
void
Toggle_Flag( int flag )
{
Flags ^= flag;
}
/*------------------------------------------------------------------------*/
/* Cleanup()
*
* Cleans up before quitting
*/
void
Cleanup( void )
{
/* Release sound card */
if( dsp_fd > 0 )
{
close( dsp_fd );
dsp_fd = 0;
}
if( mix_fd > 0 )
{
close( mix_fd );
mix_fd = 0;
}
Close_Tcvr_Serial();
} /* Cleanup( void ) */
/*------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/cat.c 0000644 0001750 0001750 00000022737 10772442133 014152 0 ustar pg4i pg4i /* cat.c
*
* Yaesu FT847 CAT control functions for the xdemorse application
*/
/*
* xdemorse: An application to decode and display
* Morse code signals using the computer's sound card.
*
* Copyright (C) 2003 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#include "xdemorse.h"
#include
/* Average bin values */
extern int gbl_bin_ave[];
/* Command codes for FT847 CAT */
unsigned char
CAT_ON[] = { 0x00, 0, 0, 0, 0x00 },
CAT_OFF[] = { 0x00, 0, 0, 0, 0x80 },
PTT_ON[] = { 0x00, 0, 0, 0, 0x08 },
PTT_OFF[] = { 0x00, 0, 0, 0, 0x88 },
MODE_LSB[] = { 0x00, 0, 0, 0, 0x07 },
MODE_USB[] = { 0x01, 0, 0, 0, 0x07 },
MODE_CW[] = { 0x02, 0, 0, 0, 0x07 },
MODE_CWR[] = { 0x03, 0, 0, 0, 0x07 },
MODE_CWN[] = { 0x82, 0, 0, 0, 0x07 },
MODE_CWNR[] = { 0x83, 0, 0, 0, 0x07 },
MODE_DIG[] = { 0x0a, 0, 0, 0, 0x07 },
MODE_PKT[] = { 0x0c, 0, 0, 0, 0x07 },
RX_STATUS[] = { 0x00, 0, 0, 0, 0xE7 },
MAIN_VFO[] = { 0x00, 0, 0, 0, 0x03 };
#define WRITE_RX_VFO 0x01
/* Runtime config data */
extern rc_data_t rc_data;
/*------------------------------------------------------------------------*/
/* Serial port File descriptor */
static int tcvr_serial_fd = 0;
/* Original serial port options */
static struct termios tcvr_serial_old_options;
/* Open_Tcvr_Serial()
*
* Opens Tcvr's Serial Port device, returns the file
* descriptor tcvr_serial_fd on success or exits on error
*/
void
Open_Tcvr_Serial( void )
{
struct termios new_options; /* New serial port options */
struct flock lockinfo; /* File lock information */
/* For testing serial port */
unsigned char test;
/* Serial port name */
char serial_port[15];
/* Abort if serial already open */
if( isFlagSet(CAT_SETUP) )
return;
/* Open Serial device, exit on error */
if( isFlagSet(ENABLE_CAT_847) )
strcpy( serial_port, rc_data.ft847_serial );
else
if( isFlagSet(ENABLE_CAT_857) )
strcpy( serial_port, rc_data.ft857_serial );
tcvr_serial_fd = open( serial_port, O_RDWR | O_NOCTTY );
if( tcvr_serial_fd < 0 )
{
char message[32];
perror( serial_port );
snprintf( message, 32, "Failed to open %s", serial_port );
Error_Dialog( message );
Set_Flag( SERIAL_IO_ERROR );
return;
}
/* Attempt to lock entire Serial port device file */
lockinfo.l_type = F_WRLCK;
lockinfo.l_whence = SEEK_SET;
lockinfo.l_start = 0;
lockinfo.l_len = 0;
/* If Serial device is already locked, abort */
if( fcntl( tcvr_serial_fd, F_SETLK, &lockinfo ) < 0 )
{
char message[60];
fcntl( tcvr_serial_fd, F_GETLK, &lockinfo );
snprintf( message, 60,
"Failed to lock %s\n"
"Device locked by pid %d",
serial_port, lockinfo.l_pid );
Error_Dialog( message );
Set_Flag( SERIAL_IO_ERROR );
return;
}
/* Save the current serial port options */
tcgetattr( tcvr_serial_fd, &tcvr_serial_old_options );
/* Read the current serial port options */
tcgetattr( tcvr_serial_fd, &new_options );
/* Set the i/o baud rates */
if( isFlagSet(ENABLE_CAT_847) )
{
cfsetispeed( &new_options, B57600 );
cfsetospeed( &new_options, B57600 );
}
else
if( isFlagSet(ENABLE_CAT_857) )
{
cfsetispeed( &new_options, B38400 );
cfsetospeed( &new_options, B38400 );
}
/* Set options for 'raw' I/O mode */
new_options.c_iflag &=
~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON );
new_options.c_oflag &= ~( OPOST | OLCUC | ONLCR | OCRNL | ONOCR | ONLRET );
new_options.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
new_options.c_cflag &= ~( CSIZE | PARENB );
new_options.c_cflag |= ( CS8 | CLOCAL | CREAD | CSTOPB );
/* Setup read() timeout to .2 sec */
new_options.c_cc[ VMIN ] = 0;
new_options.c_cc[ VTIME ] = 2;
/* Setup the new options for the port */
tcsetattr( tcvr_serial_fd, TCSAFLUSH, &new_options );
/* Enable CAT */
if( isFlagSet(ENABLE_CAT) )
Write_Tcvr_Command(CAT_ON);
/* Test the serial port */
Write_Tcvr_Command( RX_STATUS );
Read_Tcvr_Serial( &test, 1 );
if( isFlagClear(SERIAL_IO_ERROR) )
Set_Flag( CAT_SETUP );
else
{
tcsetattr( tcvr_serial_fd, TCSANOW, &tcvr_serial_old_options );
close( tcvr_serial_fd );
tcvr_serial_fd = 0;
}
} /* End of Open_Tcvr_Serial() */
/*-------------------------------------------------------------------------*/
/* Read_Tcvr_Serial()
*
* Reading Data from the Tcvr's Serial Port
*/
void
Read_Tcvr_Serial( unsigned char *cmnd, int block_size )
{
/* Error condition */
if( read(tcvr_serial_fd, cmnd, block_size) < block_size )
{
tcflush( tcvr_serial_fd, TCIOFLUSH );
Set_Flag( SERIAL_IO_ERROR );
Error_Dialog( "Serial port Rx I/O error" );
}
} /* End of Read_Tcvr_Serial() */
/*-------------------------------------------------------------------------*/
/* Write_Tcvr_Command()
*
* Writes a command (status change)
* to the Yaesu Tranceiver
*/
void
Write_Tcvr_Command( unsigned char *cmnd )
{
tcflush( tcvr_serial_fd, TCIOFLUSH );
if( write( tcvr_serial_fd, cmnd, 5 ) < 5 ) /* Error condition */
{
tcflush( tcvr_serial_fd, TCIOFLUSH );
Set_Flag( SERIAL_IO_ERROR );
Error_Dialog( "Serial port Tx I/O error" );
return;
}
/* Give time to CAT to do its thing */
usleep(1000);
} /* End of Write_Tcvr_Command() */
/*-------------------------------------------------------------------------*/
/* Close_Tcvr_Serial()
*
* Restore old options and close the Serial port
*/
void
Close_Tcvr_Serial( void )
{
if( isFlagSet(CAT_SETUP) )
{
if( isFlagSet(ENABLE_CAT_847) )
Write_Tcvr_Command( CAT_OFF );
tcsetattr( tcvr_serial_fd, TCSANOW, &tcvr_serial_old_options );
close( tcvr_serial_fd );
tcvr_serial_fd = 0;
}
Clear_Flag( CAT_SETUP );
} /* End of Close_Tcvr_Serial() */
/*-------------------------------------------------------------------------*/
/* Tune_Tcvr()
*
* Tunes the transceiver to the frequency of the strongest
* signal near a mouse click in the waterfall window
*/
void
Tune_Tcvr( double x )
{
int
from, to, /* Range to scan for a max bin value */
bin_max, /* Max bin value found in this range */
max_idx, /* fft idx at which the max is found */
fft_idx, /* Idx used to search fft bin values */
tcvr_freq, /* Transceiver's Rx frequency */
audio_freq; /* Audio frequency in waterfal window */
/* Calculate fft index corresponding to pointer x in waterfall window */
fft_idx = (((int)(x-0.5))*FFT_SIZE) / (2*WFALL_WIDTH);
/* Look above and below click point for max bin val */
from = fft_idx - 10;
if( from < 0 )
from = 0;
to = fft_idx + 10;
if( to >= FFT_SIZE/2 )
to = FFT_SIZE/2;
/* Find max bin value around click point */
bin_max = 0;
max_idx = fft_idx;
for( fft_idx = from; fft_idx < to; fft_idx++ )
if( bin_max < gbl_bin_ave[fft_idx] )
{
bin_max = gbl_bin_ave[fft_idx];
max_idx = fft_idx;
}
/* Audio freq. corresponding to fft index */
audio_freq = (2 * max_idx * rc_data.tone_freq) / WFALL_WIDTH;
/* Read current Rx frequency */
tcvr_freq = Read_Rx_Freq();
/* Calculate and write Rx freq. to center audio on AUDIO_FREQUENCY */
Write_Rx_Freq(tcvr_freq + audio_freq - rc_data.tone_freq);
} /* Tune_Tcvr() */
/*-------------------------------------------------------------------------*/
/* Read_Rx_Freq()
*
* Reads the Rx freq of the Yaesu transceiver.
*/
int
Read_Rx_Freq( void )
{
/* A 5-char string for sending and receiving */
/* 5-byte strings to and from the transceiver */
unsigned char cmnd_parm[5];
int freq;
bzero( cmnd_parm, 5 );
/* Abort if CAT disabled */
if( isFlagClear(CAT_SETUP) )
return(-1);
/* Read Rx frequency */
Write_Tcvr_Command( MAIN_VFO );
if( isFlagSet(SERIAL_IO_ERROR) )
return(-2);
Read_Tcvr_Serial( cmnd_parm, 5 );
if( isFlagSet(SERIAL_IO_ERROR) )
return(-3);
/* Decode frequency data to 10Hz */
freq = 0;
freq += (cmnd_parm[0] & 0xF0) >> 4;
freq *= 10;
freq += cmnd_parm[0] & 0x0F;
freq *= 10;
freq += (cmnd_parm[1] & 0xF0) >> 4;
freq *= 10;
freq += cmnd_parm[1] & 0x0F;
freq *= 10;
freq += (cmnd_parm[2] & 0xF0) >> 4;
freq *= 10;
freq += cmnd_parm[2] & 0x0F;
freq *= 10;
freq += (cmnd_parm[3] & 0xF0) >> 4;
freq *= 10;
freq += cmnd_parm[3] & 0x0F;
freq *= 10;
freq += (cmnd_parm[4] & 0xF0) >> 4;
return( freq );
} /* End of Read_Rx_Freq() */
/*------------------------------------------------------------------------*/
/* Write_Rx_Freq()
*
* Writes the Rx freq to the Yaesu FT-847 transceiver.
*/
void
Write_Rx_Freq( int freq )
{
/* A 5-char string for sending and receiving */
/* 5-byte strings to and from the transceiver */
unsigned char cmnd_parm[5];
/* Buffer used for converting freq. to string */
char freq_buff[9];
int idx; /* Index for loops etc */
bzero( cmnd_parm, 5 );
/* Set Rx frequency */
snprintf( freq_buff, 9, "%08d", freq/10 );
for( idx = 0; idx < 4; idx++ )
{
cmnd_parm[idx] = (freq_buff[2*idx] - '0') << 4;
cmnd_parm[idx] |= (freq_buff[2*idx+1] - '0');
}
cmnd_parm[4] = WRITE_RX_VFO;
Write_Tcvr_Command( cmnd_parm );
} /* End of Write_Rx_Freq() */
/*-------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/Makefile.am 0000644 0001750 0001750 00000001000 10772435546 015261 0 ustar pg4i pg4i ## Process this file with automake to produce Makefile.in
INCLUDES = \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
@PACKAGE_CFLAGS@
bin_PROGRAMS = xdemorse
xdemorse_SOURCES = \
main.c xdemorse.h \
cat.c xdemorse.h \
detect.c detect.h \
decode.c xdemorse.h \
display.c xdemorse.h \
fft.c xdemorse.h \
sound.c xdemorse.h \
support.c support.h \
interface.c interface.h \
callbacks.c callbacks.h
xdemorse_LDADD = @PACKAGE_LIBS@
xdemorse-1.3.orig/src/decode.c 0000644 0001750 0001750 00000020604 10772715723 014625 0 ustar pg4i pg4i /* decode.c
*
* Morse code decoding functions of xdemorse application
*/
/*
* xdemorse: An application to decode Morse code signals to text
*
* Copyright (C) 2002 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#include "xdemorse.h"
/* Speed and squelch spin buttond */
extern GtkSpinButton
*gbl_speed,
*gbl_squelch;
static int
space_elem_cnt = 0, /* Number of space elements processed */
space_frag_cnt = 0, /* Number of space fragments processed */
mark_elem_cnt = 0, /* Number of mark elements processed */
mark_frag_cnt = 0; /* Number of mark fragments processed */
/* Runtime config data */
extern rc_data_t rc_data;
/*------------------------------------------------------------------------*/
/* Get_Character()
*
* Decodes a Morse code character from the
* sequence of marks (dits and dahs) and spaces
*/
char
Get_Character( void )
{
static int
mark_cnt = 0, /* Count of Mark fragments detected */
space_cnt = 0, /* Count of Space fragments detected */
context = 0, /* What context Morse decoding is in */
hex_code = 0x01; /* Hex equivalent of Morse character */
/* Hex equivalent of Morse code is formed by left-shifting */
/* 1 or 0 into hex_code. The 0x01 initial value marks the */
/* beginning of the bit field, 1 being a dit and 0 a dash. */
/* Get the level of a fragment from tone detector. A fragment */
/* is a small fraction of a morse code element, there are from */
/* 10 to 30 frags/element depending on Morse speed (30-10 w.p.m) */
Get_Fragment();
if( isFlagSet(DSP_IO_ERROR) )
return(0);
/* Increment mark or space count */
if( isFlagSet(MARK_TONE) )
mark_cnt++;
else
space_cnt++;
/* If a mark element is too long, limit count */
if( mark_cnt > rc_data.unit_elem * 8 )
mark_cnt = rc_data.unit_elem * 8;
/* If a space element is too long, limit count */
if( space_cnt > rc_data.unit_elem * 16 )
space_cnt = rc_data.unit_elem * 16;
/* Process mark and space element counts to decode Morse */
switch( context )
{
case MARK_SIGNAL: /* Process mark element */
/* If fragment is a mark */
if( isFlagSet(MARK_TONE) )
{
/* If mark element is too long */
/* reset and wait for a space */
if( mark_cnt >= (rc_data.unit_elem * 8) )
{
/* Clear space counter */
space_cnt = 0;
/* Clear hex character code */
hex_code = 0x01;
/* Wait for a space fragment */
context = WAIT_FOR_SPACE;
} /* if( mark_cnt >= rc_data.unit_elem * 8 ) */
} /* if( isFlagSet(MARK_TONE) ) */
else
{
/* Clear space count to 1 */
space_cnt = 1;
/* Switch to processing inter-element space */
context = ELEM_SPACE;
}
break;
case ELEM_SPACE: /* Process inter-element space */
/* If space reaches 1/2 units its an inter-element space */
if( ((space_cnt * 2) >= rc_data.unit_elem) ||
isFlagSet(MARK_TONE) )
{
/* If mark is < 2 units its a dit else a dash */
if( (mark_cnt < rc_data.unit_elem * 2) )
{
/* Insert dit and increment mark frag and elem count */
hex_code = (hex_code << 1) | 0x01;
mark_frag_cnt += mark_cnt;
mark_elem_cnt += 1; /* A dit is 1 element long */
}
else
{
/* Insert dash and increment mark frag and elem count */
hex_code <<= 1;
mark_frag_cnt += mark_cnt;
mark_elem_cnt += 3; /* A dash is 3 elements long */
} /* if( mark_cnt < rc_data.unit_elem * 2 ) */
/* Clear mark count */
mark_cnt = 0;
/* Wait for inter-char space count */
if( isFlagClear(MARK_TONE) )
context = CHAR_SPACE;
else
{
space_cnt = 0;
context = MARK_SIGNAL;
}
} /* if( (space_cnt * 2) >= rc_data.unit_elem || ) */
break;
case CHAR_SPACE: /* Wait for inter-char space */
/* If fragment is space */
if( isFlagClear(MARK_TONE) )
{
/* If space reaches 2 units its inter-character */
if( space_cnt >= (rc_data.unit_elem * 2) )
{
/* Switch to waiting for inter-word space */
context = WAIT_WORD_SPACE;
/* Return decoded Morse char */
return( Hex_to_Ascii(&hex_code) );
}
} /* if( isFlagClear(MARK_TONE) ) */
else /* Its the end of inter-element space */
{
/* Count up space frags and elements */
space_frag_cnt += space_cnt;
space_elem_cnt++; /* Inter-element space */
/* Clear space cnt and process marks */
space_cnt = 0;
context = MARK_SIGNAL;
}
break;
case WAIT_WORD_SPACE: /* Wait for an inter-word space */
/* If fragment is space */
if( isFlagClear(MARK_TONE) )
{
/* If space count reaches 5, its word space */
if( space_cnt >= (rc_data.unit_elem * 5) )
context = WORD_SPACE;
} /* if( isFlagClear(MARK_TONE) ) */
else /* Its the end of inter-character space */
{
/* Adapt to incoming signal */
Adapt_Decoder();
/* Switch to processing mark signal */
space_cnt = 0;
context = MARK_SIGNAL;
}
break;
case WORD_SPACE: /* Process Inter-word space */
/* If fragment is space */
if( isFlagClear(MARK_TONE) )
{
if( space_cnt >= (rc_data.unit_elem * 7) )
{
context = WAIT_FOR_MARK;
return( ' ' );
}
}
else
{
/* Adapt to incoming signal */
Adapt_Decoder();
/* Switch to processing mark signal */
space_cnt = 0;
context = MARK_SIGNAL;
return( ' ' );
}
case WAIT_FOR_MARK: /* Process no-signal space */
/* If fragment is mark switch to processing marks */
if( isFlagSet(MARK_TONE) )
{
space_cnt = 0;
context = MARK_SIGNAL;
}
break;
case WAIT_FOR_SPACE: /* Wait for space after long dash */
/* If fragment is space, switch to counting space */
if( isFlagClear(MARK_TONE) )
{
space_cnt = 1;
mark_cnt = 0;
context = WAIT_FOR_MARK;
}
break;
default: /* Set context if none */
if( isFlagSet(MARK_TONE) )
context = MARK_SIGNAL;
else
context = WAIT_FOR_MARK;
} /* End of switch( context ) */
return( 0 );
} /* End of Get_Character() */
/*------------------------------------------------------------------------*/
/* Adapt_Decoder()
*
* Adjusts Morse speed from measurements on the incoming signal
*/
void
Adapt_Decoder( void )
{
int
speed, /* Morse speed in wpm */
speed_err; /* Morse speed error */
/* Calculate Morse speed */
if( mark_elem_cnt &&
mark_frag_cnt &&
space_elem_cnt &&
space_frag_cnt )
{
if( isFlagSet(ADAPT_SPEED) )
{
/* Estimate Morse speed from space and mark counts */
speed_err = (mark_frag_cnt + space_frag_cnt) /
(mark_elem_cnt + space_elem_cnt)
- rc_data.unit_elem;
/* Morse speed limits (60-6 wpm) */
if( (rc_data.unit_elem > rc_data.min_unit) && (speed_err < 0) )
rc_data.unit_elem--;
if( (rc_data.unit_elem < rc_data.max_unit) && (speed_err > 0) )
rc_data.unit_elem++;
/* Display speed in wpm */
speed = ( 60 * rc_data.tone_freq ) /
( 50 * CYCLES_PER_FRAG * rc_data.unit_elem );
gtk_spin_button_set_value( gbl_speed, (gdouble) speed );
} /* if( isFlagSet(ADAPT_SPEED) ) */
} /* if( mark_elem_cnt && space_elem_cnt && space_frag_cnt ) */
/* Clear counters */
space_elem_cnt = space_frag_cnt = 0;
mark_elem_cnt = mark_frag_cnt = 0;
} /* Adapt_Decoder() */
/*------------------------------------------------------------------------*/
/* Hex_to_Ascii()
*
* Converts the hex equivalent of
* a Morse code character to ASCII
*/
char
Hex_to_Ascii( int *hex_code )
{
/* Table of ASCII characters available in Morse code */
static char
morse_ascii_char[ NUMBER_OF_CHAR + 1 ] = MORSE_ASCII_CHAR;
/* Table of hex equivalent of Morse characters */
static unsigned char
morse_hex_char[ NUMBER_OF_CHAR ] = MORSE_HEX_CODE;
int idx; /* Loop index */
/* Look for a match in hex table */
for( idx = 0; idx < NUMBER_OF_CHAR; idx++ )
if( *hex_code == morse_hex_char[ idx ] )
break;
/* Clear hex code after conversion */
*hex_code = 0x01;
/* Return ascii equivalent of hex code */
return( morse_ascii_char[ idx ] );
} /* End of Hex_to_Ascii() */
/*------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/support.h 0000644 0001750 0001750 00000003722 11111311621 015076 0 ustar pg4i pg4i /*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
/*
* Standard gettext macros.
*/
#ifdef ENABLE_NLS
# include
# undef _
# define _(String) dgettext (PACKAGE, String)
# define Q_(String) g_strip_context ((String), gettext (String))
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define Q_(String) g_strip_context ((String), (String))
# define N_(String) (String)
#endif
/*
* Public Functions.
*/
/*
* This function returns a widget in a component created by Glade.
* Call it with the toplevel widget in the component (i.e. a window/dialog),
* or alternatively any widget in the component, and the name of the widget
* you want returned.
*/
GtkWidget* lookup_widget (GtkWidget *widget,
const gchar *widget_name);
/* Use this function to set the directory containing installed pixmaps. */
void add_pixmap_directory (const gchar *directory);
/*
* Private Functions.
*/
/* This is used to create the pixmaps used in the interface. */
GtkWidget* create_pixmap (GtkWidget *widget,
const gchar *filename);
/* This is used to create the pixbufs used in the interface. */
GdkPixbuf* create_pixbuf (const gchar *filename);
/* This is used to set ATK action descriptions. */
void glade_set_atk_action_description (AtkAction *action,
const gchar *action_name,
const gchar *description);
xdemorse-1.3.orig/src/sound.c 0000644 0001750 0001750 00000022005 10772450054 014520 0 ustar pg4i pg4i /* sound.c
*
* Soundcard handling functions of xdemorse application
*/
/*
* xdemorse: An application to decode and display
* Morse code signals using a computer's sound card
*
* Copyright (C) 2002 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#include "xdemorse.h"
extern int
dsp_fd, /* File descriptor of DSP device */
mix_fd; /* File descriptor of mixer device */
/* fft in buffer */
extern int *fft_in_r;
/* Runtime config data */
extern rc_data_t rc_data;
/*------------------------------------------------------------------------*/
/* Setup_Sound_Card()
*
* Sets up mixer and DSP devices
*/
gboolean
Setup_Sound_Card( void )
{
int
new_recsrc, /* New recording source (RECORD_SRC) */
dsp_speed, /* DSP sampling speed as in xdemorse.h */
frag_size, /* DSP buffer (fragment) size in kb */
level, /* Rec/Volume level request to mixer */
num_chan, /* Stereo(=2) or Mono(=1) selection */
sample_fmt, /* DSP sample format, 8-bit unsigned */
itmp;
/* Mixer device to be set-up (input or reclev) */
unsigned int device;
/* Error messages */
char message[90];
/* Sound device names from souncard.h */
char *dev_name[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
/* File lock information */
struct flock lockinfo;
/*** Open and lock mixer and dsp devices ***/
/* Open mixer device, abort on error */
if( (mix_fd = open(rc_data.mix_dev, O_RDONLY, 0)) == -1 )
{
perror( rc_data.mix_dev );
snprintf( message, 90,
"Unable to open mixer device %s\n"
"Quit and correct xdemorserc", rc_data.mix_dev );
Error_Dialog( message );
return(FALSE);
}
/* Attempt to lock entire mixer device file */
lockinfo.l_type = F_RDLCK;
lockinfo.l_whence = SEEK_SET;
lockinfo.l_start = 0;
lockinfo.l_len = 0;
/* If mixer device is already locked, abort */
if( fcntl( mix_fd, F_SETLK, &lockinfo ) < 0 )
{
perror( rc_data.mix_dev );
fcntl( mix_fd, F_GETLK, &lockinfo );
fprintf( stderr, "xdemorse: Lock %s: Device is locked by pid %d\n",
rc_data.mix_dev, lockinfo.l_pid );
snprintf( message, 90,
"Unable to lock %s\n"
"Device locked by pid %d\n"
"Quit and correct xdemorserc",
rc_data.mix_dev, lockinfo.l_pid );
Error_Dialog( message );
return(FALSE);
}
/* Open DSP device, abort on error */
if( (dsp_fd = open(rc_data.dsp_dev, O_RDONLY, 0)) == -1 )
{
perror( rc_data.dsp_dev );
snprintf( message, 90,
"Unable to open dsp device %s\n"
"Quit and correct xdemorserc", rc_data.dsp_dev);
Error_Dialog( message );
return(FALSE);
}
/* Attempt to lock entire DSP device file */
lockinfo.l_type = F_RDLCK;
lockinfo.l_whence = SEEK_SET;
lockinfo.l_start = 0;
lockinfo.l_len = 0;
/* If DSP device is already locked, abort */
if( fcntl( dsp_fd, F_SETLK, &lockinfo ) < 0 )
{
perror( rc_data.dsp_dev );
fcntl( dsp_fd, F_GETLK, &lockinfo );
fprintf( stderr, "xdemorse: Lock %s: Device is locked by pid %d\n",
rc_data.dsp_dev, lockinfo.l_pid );
snprintf( message, 90,
"Unable to lock %s\n"
"Device locked by pid %d"
"Quit and correct xdemorserc",
rc_data.dsp_dev, lockinfo.l_pid );
Error_Dialog( message );
return(FALSE);
}
/*** Setup sound card parameters ***/
/* Find number of recording source matching source name */
for( new_recsrc = 0; new_recsrc < SOUND_MIXER_NRDEVICES; new_recsrc++ )
if( strcmp( dev_name[new_recsrc], rc_data.rec_src ) == 0 )
break;
/* Make recording source mask */
itmp = 1 << new_recsrc;
/* Attempt to select recording source, abort on error */
if( ioctl(mix_fd, SOUND_MIXER_WRITE_RECSRC, &itmp) == -1 )
{
perror("xdemorse: SOUND_MIXER_WRITE_RECSRC");
snprintf( message, 90,
"Failed to select Recording\n"
"Source: %s\n"
"Quit and correct xdemorserc", rc_data.rec_src );
Error_Dialog( message );
return(FALSE);
}
if( itmp != 1 << new_recsrc )
{
snprintf( message, 90,
"Failed to select Recording\n"
"Source: %s\n"
"Quit and correct xdemorserc", rc_data.rec_src );
Error_Dialog( message );
return(FALSE);
}
/* Zero level of recording source to silence (my) speakers */
level = 0;
if( ioctl(mix_fd, MIXER_WRITE(new_recsrc), &level) == -1 )
{
perror("xdemorse: Setting Recording source level");
snprintf( message, 90,
"Failed to set %s level\n"
"Quit and correct xdemorserc", rc_data.rec_src );
Error_Dialog( message );
return(FALSE);
}
if( level != 0 )
{
snprintf( message, 90,
"Failed to set %s level\n"
"Quit and correct xdemorserc", rc_data.rec_src );
Error_Dialog( message );
return(FALSE);
}
/* Find recording level device */
for( device = 0; device < SOUND_MIXER_NRDEVICES; device++ )
if( strcmp( dev_name[device], rc_data.inp_lev ) == 0 )
break;
if( device == SOUND_MIXER_NRDEVICES )
{
snprintf( message, 90,
"Failed to select Recording\n"
" Level device: %s\n"
"Quit and correct xdemorserc", rc_data.inp_lev );
Error_Dialog( message );
return(FALSE);
}
/* Write recording level to mixer, abort on error */
level = itmp = rc_data.rec_lev | (rc_data.rec_lev << 8);
if( ioctl(mix_fd, MIXER_WRITE(device), &level) == -1 )
{
perror("xdemorse: Setting Recording level");
Error_Dialog(
"Failed to set Recording level\n"
"Quit and correct xdemorserc" );
return(FALSE);
}
if( level != itmp )
{
Error_Dialog(
"Failed to set Recording level\n"
"Quit and correct xdemorserc" );
return(FALSE);
}
/* Set fragment size according to stereo/mono mode */
itmp = 1; frag_size = 0;
num_chan = rc_data.num_chn;
while( (itmp << frag_size) != BUFFER_SIZE ) frag_size++;
itmp += num_chan << 18;
ioctl( dsp_fd, SNDCTL_DSP_SETFRAGMENT, &frag_size );
/* Set sample format to unsigned 8-bit, abort on error */
sample_fmt = AFMT_U8;
if( ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &sample_fmt) == -1 )
{
perror( "xdemorse: SNDCTL_DSP_SETFMT");
Error_Dialog(
"Failed to set dsp format: AFMT_U8\n"
"Quit and correct xdemorserc" );
return(FALSE);
}
if( sample_fmt != AFMT_U8 )
{
Error_Dialog(
"Failed to set dsp format: AFMT_U8\n"
"Quit and correct xdemorserc" );
return(FALSE);
}
/* Set stereo/mono mode */
itmp = num_chan;
if( ioctl(dsp_fd, SNDCTL_DSP_CHANNELS, &itmp) == -1 )
perror("SNDCTL_DSP_CHANNELS");
/* Setup DSP sampling speed, abort on error */
dsp_speed = rc_data.dsp_speed;
if( ioctl(dsp_fd, SNDCTL_DSP_SPEED, &dsp_speed) == -1 )
{
perror( "xdemorse: SNDCTL_DSP_SPEED");
snprintf( message, 90,
"Failed to set DSP speed to %d\n"
"Quit and correct xdemorserc", rc_data.dsp_speed );
Error_Dialog( message );
return(FALSE);
}
if( dsp_speed != rc_data.dsp_speed )
{
snprintf( message, 90,
"Failed to set DSP speed to %d\n"
"Quit and correct xdemorserc", rc_data.dsp_speed );
Error_Dialog( message );
return(FALSE);
}
return( TRUE );
} /* End of Setup_Sound_Card() */
/*------------------------------------------------------------------------*/
/* Get_Signal_Sample()
*
* Gets the next DSP sample of the signal input
*/
int
Signal_Sample(void)
{
/* Number of samples read from dsp */
int sample_cnt;
static int
fft_idx = 0, /* fft input buffer idx */
cnt = 0; /* Count of calls to this function */
/* New DSP sample of audio input */
int sample;
/* Refill dsp samples buffer when needed */
if( rc_data.buffer_idx >= rc_data.buffer_size )
{
/* Start buffer index according to stereo/mono mode */
if( rc_data.num_chn == 1 ) /* Mono */
rc_data.buffer_idx = 0;
else
rc_data.buffer_idx = rc_data.use_chn;
/* Read audio samples from DSP, abort on error */
if( (sample_cnt = read(dsp_fd, rc_data.buffer, rc_data.buffer_size)) == -1 )
{
perror( "xdemorse: dsp read()" );
Error_Dialog(
"Error reading from dsp device\n"
"Quit xdemorse and correct" );
Set_Flag( DSP_IO_ERROR );
}
if( sample_cnt != rc_data.buffer_size )
{
Error_Dialog(
"Error reading from dsp device\n"
"Quit xdemorse and correct" );
Set_Flag( DSP_IO_ERROR );
}
} /* End of if( buffer_idx >= buffer_size ) */
/* Remove neutral value (128) from samples */
sample = rc_data.buffer[ rc_data.buffer_idx ] - 128;
/* Display waterfall when input buffer full */
/* rc_data.fft_stride samples added for each input element */
if( cnt == 0 )
fft_in_r[fft_idx] = sample;
else
fft_in_r[fft_idx] += sample;
if( ++cnt >= rc_data.fft_stride )
{
fft_idx++;
cnt = 0;
}
if( fft_idx >= FFT_SIZE )
{
fft_idx = 0;
Display_Waterfall();
}
/* Increment according to mono/stereo mode */
rc_data.buffer_idx += rc_data.num_chn;
return( sample );
} /* End of Get_Signal_Sample() */
/*------------------------------------------------------------------------*/
xdemorse-1.3.orig/src/detect.h 0000644 0001750 0001750 00000002350 10772437702 014653 0 ustar pg4i pg4i /* detect.h
*
* Header file for detect.c
*/
/*
* xdemorse: An application to decode Morse signals to text
*
* Copyright (C) 2001 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#ifndef DETECT_H
#define DETECT_H 1
/* Buffers and data needed by tone detector */
struct detector_data
{
int
frag_len,
samples_buff_len, /* Length of DSP samples buffer */
samples_buff_idx; /* Sample buffer index */
/* Circular signal level buffer and index for edge detector */
int
sig_level_idx,
*sig_level_buff;
/* Variables for the Goertzel algorithm */
double cosw, sinw, coeff;
/* Circular signal samples buffer for Goertzel detector */
char *samples_buff;
} detector_data;
#endif /* End of detect.h */
xdemorse-1.3.orig/src/xdemorse.h 0000644 0001750 0001750 00000016611 10772752136 015237 0 ustar pg4i pg4i /* xdemorse.h
*
* Header file for xdemorse
*/
/*
* xdemorse: An application to decode Morse signals to text
*
* Copyright (C) 2001 Neoklis Kyriazis
*
* 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:
*
* http://www.gnu.org/copyleft/gpl.txt
*/
#ifndef XDEMORSE_H
#define XDEMORSE_H 1
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/************ CUSTOMIZE THESE DEFINITIONS FOR YOUR NEEDS *************/
/* Definitions for Morse code conversion to ascii */
#define NUMBER_OF_CHAR 55 /* Number of chars in ASCII table */
/* ASCII equivalents to Morse hex code. Last */
/* one (*) used for unrecognized characters. */
#define MORSE_ASCII_CHAR \
{ 'A','B','C','D','E','F','G','H','I','J','K','L','M', \
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', \
'1','2','3','4','5','6','7','8','9','0','.',',',':', \
'?','\'','-','/','(','"',';','$','#','<','!','@',']',\
'=','~',' ','*' }
/* Hex equivalents to Morse code chars above except (*). */
/* Formed by starting with a 1 and following with a 0 for */
/* dash and 1 for dit e.g: A = ditdah = 101 = Hex 0x06. */
#define MORSE_HEX_CODE \
{ 0x06,0x17,0x15,0x0b,0x03,0x1d,0x09,0x1f,0x07,0x18,0x0a,0x1b,0x04,\
0x05,0x08,0x19,0x12,0x0d,0x0f,0x02,0x0e,0x1e,0x0c,0x16,0x14,0x13,\
0x30,0x38,0x3c,0x3e,0x3f,0x2f,0x27,0x23,0x21,0x20,0x6a,0x4c,0x47,\
0x73,0x61,0x5e,0x2d,0x52,0x6d,0x55,0xf6,0x35,0x7a,0x2a,0x37,0x29,\
0x2e,0xff,0x01 }
/***************** END OF CUSTOMIZABLE SECTION ***********************/
/* Signal Detector parameter definitions */
#define BUFFER_SIZE 1024 /* Size of buffer for signal samples */
#define WFALL_WIDTH 256 /* Width of Waterfall drawingarea */
#define CYCLES_PER_FRAG 2 /* Cycles of signal/signal fragment */
#define BINMAX_AVE_WIN 5 /* Length of bin max averaging window */
#define FFT_SIZE 512 /* Size of fft input/output arrays */
#define FFT_SIZE2 256 /* Size/2 of fft input/output arrays */
#define GOERTZEL_SCALE 1024 /* Scale factor for integer Goertzel algorithm*/
#define STEP_THRESHOLD 105 /* % diff between successive sig levels */
#define MAX_SPEED 60 /* Maximum allowed Morse unit (dot) length */
#define MIN_SPEED 6 /* Minimum allowed Morse unit (dot) length */
/* Transceiver type */
#define FT847 1
#define FT857 2
#define NONE 0
/* Definitions of contexts (stages) in Morse decoding process */
#define MARK_SIGNAL 0x000001 /* Count fragments of a mark element */
#define ELEM_SPACE 0x000002 /* Count frag. of inter-element space */
#define CHAR_SPACE 0x000004 /* Count fragments of inter-char space */
#define WAIT_WORD_SPACE 0x000008 /* Wait for an inter-word space */
#define WORD_SPACE 0x000010 /* Count fragments of inter-word space */
#define WAIT_FOR_MARK 0x000020 /* Count fragments of no-signal space */
#define WAIT_FOR_SPACE 0x000040 /* Wait for a space after a long dash */
#define MARK_TONE 0x000080 /* Input signal is mark tone (key down)*/
/* Definitions of flags for various actions */
#define ADAPT_SPEED 0x000100 /* Enable speed tracking */
#define MAN_THRESHOLD 0x000200 /* Enable manual detector threshold */
#define WORD_WRAP 0x000400 /* Enable word wrapping */
#define DISPLAY_SIGNAL 0x000800 /* Display output of signal detector */
#define DISPLAY_DETECTOR 0x001000 /* Display output of signal detector */
#define DSP_IO_ERROR 0x002000 /* Error reading from dsp */
#define REVERSE_VIDEO 0x004000 /* Reverse waterfall video */
#define ENABLE_CAT 0x008000 /* Enable CAT for transceiver */
#define CAT_SETUP 0x010000 /* CAT is set up */
#define ENABLE_CAT_847 0x020000 /* Enable CAT for FT847 */
#define ENABLE_CAT_857 0x040000 /* Enable CAT for FT857 */
#define SERIAL_IO_ERROR 0x080000 /* Error occured in serial i/o */
#define LONG_SPACE 0x100000 /* Long period of space (no tone) */
#define ENABLE_RECEIVE 0x200000 /* Enable reception of Morse code */
/* Channel to be used in audio capture */
#define LEFT 0 /* Left channel */
#define RIGHT 1 /* Right channel */
/* Special characters */
#define LF 0x0A /* Line Feed */
#define CR 0x0D /* Carriage Return */
#define HT 0x09 /* Horizontal Tab */
/* Return values */
#define ERROR 1 /* Error condition */
#define SUCCESS 0 /* No error condition */
/*-------------------------------------------------------------------*/
/* Runtine configuration data */
typedef struct
{
char
mix_dev[21], /* Mixer device name */
dsp_dev[21], /* DSP device name */
rec_src[21], /* Recording/capture source */
inp_lev[21]; /* Input level contol name */
/* Transceiver serial devices */
char
ft847_serial[32],
ft857_serial[32];
/* Transceiver type 1=FT847 2=FT867 0=NONE */
int tcvr_type;
int
num_chn, /* Number of audio channels (2=stereo, 1=mono) */
use_chn, /* Channel in use: 0=left, 1=right */
rec_lev, /* Recording/Capture level */
dsp_speed; /* DSP speed samples/sec */
int
tone_freq, /* Receiver BFO Tone freq */
red_line, /* Waterfall BFO Tone freq marker line */
fft_stride; /* Stride of fft over input samples */
int
unit_elem, /* Morse unit element (dot) length */
max_unit, /* Maximum length of unit element */
min_unit, /* Minimum length of unit element */
spd_wpm, /* Current Morse speed words/min */
wrd_wrp, /* Maximum line length if word wrap enabled */
det_thr; /* Signal threshold for Mark/Space separation */
/* Signal/dsp samples buffer */
unsigned char *buffer;
int
buffer_idx, /* Index to signal samples buffer */
buffer_size; /* Buffer size according to stereo/mono mode */
} rc_data_t;
/*-------------------------------------------------------------------*/
/* Function prototypes produced by cproto */
/* callbacks.c */
void Error_Dialog(char *message);
/* cat.c */
void Open_Tcvr_Serial(void);
void Read_Tcvr_Serial(unsigned char *cmnd, int block_size);
void Write_Tcvr_Command(unsigned char *cmnd);
void Close_Tcvr_Serial(void);
void Tune_Tcvr(double x);
int Read_Rx_Freq(void);
void Write_Rx_Freq(int freq);
/* decode.c */
char Get_Character(void);
void Adapt_Decoder(void);
char Hex_to_Ascii(int *hex_code);
/* detect.c */
int Get_Fragment(void);
gboolean Initialize_Detector( void );
/* display.c */
void Display_Detector(int plot);
void Display_Signal(int plot);
void Display_Waterfall(void);
void Clear_Pixbuf(void);
/* fft.c */
void Ifft_init(int fft_size);
void Ifft(int fft_size);
gboolean mem_alloc(void **ptr, int req);
/* main.c */
int main(int argc, char *argv[]);
gboolean Print_Character(gpointer data);
int Load_Line(char *buff, FILE *pfile, char *messg);
gboolean Load_Config(gpointer data);
void Usage(void);
int isFlagSet(int flag);
int isFlagClear(int flag);
void Set_Flag(int flag);
void Clear_Flag(int flag);
void Toggle_Flag(int flag);
void Cleanup(void);
/* sound.c */
gboolean Setup_Sound_Card(void);
int Signal_Sample(void);
#endif /* End of xdemorse.h */