version 1.3

This commit is contained in:
Jared Szechy
2011-08-21 03:31:35 -04:00
commit 59f8d3890e
36 changed files with 8441 additions and 0 deletions

37
CHANGELOG Normal file
View File

@@ -0,0 +1,37 @@
1.3 New features:
Decodes voice from ProVoice signals (requires -fp option)
algid and kid are now shown in hex notation
Fixed bugs:
auto output gain now has faster rise time
MoTDMA is now correctly labeled X2-TDMA
1.2 New features:
Decodes voice for DMR standard (including MOTOTRBO)
Full metadata (src, talkgroup, lcinfo, mfid, lcformat, mi, algid, keyid) for X2-TDMA
TDMA slot identification for X2-TDMA/DMR/MOTOTRBO
Identifies non-voice frame types for X2-TDMA/DMR/MOTOTRBO
Frame only (no voice yet) support for 9600 baud NXDN
Auto leveling audio output gain (default) and -g option for fixed gain
GFSK modulation optimizations and improved C4FM/GFSK/QPSK auto detect
Fixed bugs:
nac was showing wrong ID
p25 metadata (lcinfo, mfid, lfcormat, mi, keyid, algid, lsd) are now
printed out in the correct bit order (MSB -> LSB), was reversed.
fixed serveral bugs in dsd_upsample.c, with improved quality
1.1 New features:
Scanner control options to allow scan resume during certain TDULC
Improved upsampling function audio quality
Greatly improved handling of X2-TDMA frames
Much faster QPSK decision point tracking by default
Fixed bugs:
playMbeFiles was not output to .wav file when -w was given
Now correctly detects/handles Mot and P25 talkgroup formats
PDU frames were not detected
1.0.3 Fixed buggy C4FM/QPSK auto detection and added -A option to adjust it.
1.0 Initial release

14
COPYRIGHT Normal file
View File

@@ -0,0 +1,14 @@
Copyright (C) 2010 DSD Author
GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

30
DSD_Author.pgp Normal file
View File

@@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.10
mQENBEufusYBCADN1SNkRkQzdLM02MCjen8KQmfuA38MrQIV0dZLpPJcn1+hsvZZ
KWvpUiWCNw1ClGRsJAT5cjonndi1PV7tpzQz+CyMqSP5OwR40eTJBoZhl74hdmU8
QvcKkJ32khSsOXMo60NHk5iIMDELzOGqq57NHhbunj6NtYog2mR5+WT37JLCvF/q
dvYl2KkRwEHD76/b/O1CyheiiqNMGBb13zPN0qO/PRlENSgViLcDh9qVj4ETNNS6
zMlP4D4pa07iED4Ua31wiXI04ReznnmvMqzQb8uFbg7d98F3bZpsbNURbmsFHMhj
c9qw65nzaMa3OHfZ3Qwl4XRlNqEzZrclIZADABEBAAG0DW1iZWxpYiBBdXRob3KJ
ATgEEwECACIFAkufusYCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEE+Y
6GPqXv4sI/4H/RsumInT5GtDdBTgxt3lERqc5GF8tI5CAQX9DUMMkKxQ306Fgb4M
ISYdepgL6BlbtSyMdKpKsDLScNA6YXER4gMU1nhhyBulqj41kAfsVbG8hiTBy5Ri
FTo36HrC//Zj1MlaTCB8Rl6B6IftAHIb1U+Gda3WnLDe+R5Pym/76TqeYx23PnJl
V+qfrkjbNyOb2bttyko2iccm9DSq/I1OF0Ufz3P60ssUwHW/b2S6WOXRxiZIq0sz
8pAweUFCxIMWo+XYlSpRtwpebfx+JoHJKdW1cSCgY9jwVsOZO1zxc8P+jr3ByiIR
ZPd0PfBt/AHuC6Hmw9nC12e49+4qsHkj50S5AQ0ES5+6xgEIALf60WjqHm552FIX
KqmG0TIrXpCsYoTWzDdO5j0Ro6fmg9U48BqDH5aS4YRvuyPE7q6DGYEnXF5EIPtU
FhUk4FMmez5eMg91UW4Qjqx8M3reoBROYocM5Nfbc9w7St8+3oRS6rUBIh/B6o4O
kEjkoW3R7O3uFpC53Oi9IVhx/joWxhi430RrUTig5CQzuPFTAHd3xJVE6Pv44nsY
/PsOhBLu2Z3kRkvjcGbsGDlAl2bDEobzQdsqXDD8gJkF5W4IeBKvRC54SE0FSm57
G1gadhZ7vT4DWQZvYYKXR+AE7FTcopoAFHdapYokOGLHCguabyeZ5q7+s7J4nddL
p5yq8ikAEQEAAYkBHwQYAQIACQUCS5+6xgIbDAAKCRBPmOhj6l7+LPi6B/sEkDkm
Qs/aTz9HDANBAbTuDZTY4WBbkPdFos3xxC2Z/TH5m4bfHEkvNk5WD+j+vYB3exAc
uBi7ZiqibRpap4kiAiKKCRXOyvmEmrjKB5wOWbRpkdTeEdPcpsQ4dDDw1ZUKwzjN
1jI/9GOgq49nAGdlU59f3IdPut6oQNq9vrtanTq2xHVN/rOhV9GLE6gLX1YWkpIH
zYSUheGPsnv4sWRsQDTB7xmF+6RZzjmauKNwsGFscX1TenOWtUbYb9qFCwvNMOSk
51sEaD6PK6wWTXMqQlgjaoGqh1ZaePgT0QTh1W/bvOD0fL5NEToJl2h/lBSvO+ez
R9B++dt5JX9BMxAH
=puA7
-----END PGP PUBLIC KEY BLOCK-----

109
Makefile Normal file
View File

@@ -0,0 +1,109 @@
# Copyright (C) 2010 DSD Author
# GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
CC = gcc
CFLAGS = -O2
INCLUDES = -I. -I/usr/local/include -I/usr/include
LIBS = -L/usr/local/lib -lm -lmbe
INSTALL=install
AR=ar
RANLIB=ranlib
DEST_BASE=/usr/local
DEST_INC=${DEST_BASE}/include
DEST_LIB=${DEST_BASE}/lib
DEST_BIN=${DEST_BASE}/bin
OBJS = dsd_main.o dsd_symbol.o dsd_dibit.o dsd_frame_sync.o dsd_file.o dsd_audio.o dsd_serial.o dsd_frame.o dsd_mbe.o dsd_upsample.o p25p1_hdu.o p25p1_ldu1.o p25p1_ldu2.o p25p1_tdulc.o p25_lcw.o x2tdma_voice.o x2tdma_data.o dstar.o nxdn96.o dmr_voice.o dmr_data.o provoice.o
all: dsd
build: all
dsd_main.o: dsd_main.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_main.c -o dsd_main.o
dsd_symbol.o: dsd_symbol.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_symbol.c -o dsd_symbol.o
dsd_dibit.o: dsd_dibit.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_dibit.c -o dsd_dibit.o
dsd_frame_sync.o: dsd_frame_sync.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_frame_sync.c -o dsd_frame_sync.o
dsd_file.o: dsd_file.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_file.c -o dsd_file.o
dsd_audio.o: dsd_audio.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_audio.c -o dsd_audio.o
dsd_serial.o: dsd_serial.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_serial.c -o dsd_serial.o
dsd_frame.o: dsd_frame.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_frame.c -o dsd_frame.o
dsd_mbe.o: dsd_mbe.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_mbe.c -o dsd_mbe.o
dsd_upsample.o: dsd_upsample.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dsd_upsample.c -o dsd_upsample.o
p25p1_hdu.o: p25p1_hdu.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c p25p1_hdu.c -o p25p1_hdu.o
p25p1_ldu1.o: p25p1_ldu1.c p25p1_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c p25p1_ldu1.c -o p25p1_ldu1.o
p25p1_ldu2.o: p25p1_ldu2.c p25p1_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c p25p1_ldu2.c -o p25p1_ldu2.o
p25p1_tdulc.o: p25p1_tdulc.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c p25p1_tdulc.c -o p25p1_tdulc.o
p25_lcw.o: p25_lcw.c dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c p25_lcw.c -o p25_lcw.o
x2tdma_voice.o: x2tdma_voice.c x2tdma_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c x2tdma_voice.c -o x2tdma_voice.o
x2tdma_data.o: x2tdma_data.c x2tdma_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c x2tdma_data.c -o x2tdma_data.o
dstar.o: dstar.c dstar_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dstar.c -o dstar.o
nxdn96.o: nxdn96.c nxdn96_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c nxdn96.c -o nxdn96.o
dmr_voice.o: dmr_voice.c dmr_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dmr_voice.c -o dmr_voice.o
dmr_data.o: dmr_data.c dmr_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c dmr_data.c -o dmr_data.o
provoice.o: provoice.c provoice_const.h dsd.h config.h
$(CC) $(CFLAGS) $(INCLUDES) -c provoice.c -o provoice.o
dsd: $(OBJS) dsd.h config.h
$(CC) $(CFLAGS) $(LIBS) -o dsd $(OBJS)
clean:
rm -f *.o
rm -f dsd
install: dsd
$(INSTALL) dsd $(DEST_BIN)
chgrp uucp $(DEST_BIN)/dsd
chmod g+s $(DEST_BIN)/dsd

520
README Normal file
View File

@@ -0,0 +1,520 @@
Digital Speech Decoder 1.3
Copyright (C) 2010 DSD Author
GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
DSD is able to decode several digital voice formats from discriminator
tap audio and synthesize the decoded speech. Speech
synthesis requires mbelib, which is a separate package. DSD 1.3
requires mbelib 1.1 or later.
Supported formats in version 1.3:
P25 Phase 1 Widely deployed radio standard used in public safety
and amateur radio.
Support includes decoding and synthesis of speech,
display of all link control info, and the ability to save
and replay .imb data files
ProVoice EDACS Digital voice format used by public safety and
amateur radio.
Support includes decoding and synthesis of speech and
the ability to save and replay .imb data files.
Note: not enabled by default, use -fp to enable.
X2-TDMA Two slot TDMA system currently being deployed by several
public safety organizations. Based on the DMR
standard with extensions for P25 style signaling.
Support includes decoding and synthesis of speech,
display of all link control info, and the ability to save
and replay .amb data files
DMR/MOTOTRBO "Digital Mobile Radio" Eurpoean two slot TDMA standard.
MOTOTRBO is a popular implementation of this standard.
Support includes decoding and synthesis of speech and
the ability to save and replay .amb data files.
Development (no speech) support only:
NXDN (9600) Digital radio standard used by NEXEDGE and IDAS brands.
Development support only. DSD recognizes frames and can
extract the voice bits but speech is not yet decoded.
The issue is likely either an unusual interleave pattern
or a pseudo-random bit mask initialized by a "color code"
Note: not enabled by default, use -fn to enable.
D-STAR Amateur radio digital voice standard
Development support only. DSD recognized frames and can
extract the voice bits but speech is not yet decoded.
D-STAR likely uses a version of AMBE not yet supported by
mbelib. The voice bit interleave pattern also needs to be
determined.
Note: not enabled by default, use -fn to enable.
Unsupported formats in version 1.3 considered for future development:
P25 Phase 2 This is not yet a published standard. Full support is
expected once the standard is published and there are
systems operating to test against. Phase 2 will use
a vocoder supported by mbelib.
OpenSKY It is possible that the four slot version uses a vocoder
supported by mbelib. The two slot version does not.
NXDN (4800) This should be supportable as soon as we have .wav files
or access to a radio programmed in this format.
Supported demodulation optimizations in version 1.3:
C4FM Continuous envelope 2 or 4 level FSK with relatively
sharp transitions between symbols. Used by most P25
systems.
Optimizations include calibrating decision points only
during sync, 4/10 sample window per symbol, and symbol
edge timing calibration.
GFSK Continuous envelope 2 or 4 level FSK with a narrower
Gaussian/"raised cosine" filter that affects transitions
between symbols. Used by DMR/MOTOTRBO, NXDN and many
others. Noisy C4FM signals may be detected as GFSK
but this is ok, the optimization changes will help with
noisy signals.
Optimizations are similar to C4FM except symbol transitions
are only kept out of the middle 4 samples and only the
middle two samples are used.
QPSK Quadrature Phase Shift Keying (and variants) used in
some P25 systems and all known X2-TDMA systems. May be
advertised under the marketing term "LSM"
Optimizations include continuous decision point
calibration, using middle two samples, and using the
symbol midpoint "spike" for symbol timing.
Installation
DSD should easily compile on any Linux or *BSD system with gcc.
Just untar and run "make" or "make install". There are some debugging/
development options in config.h that normal users will want to leave
disabled as they can severely impact performance.
Operation
There are two main operating modes, "Live scanner" and "Play files"
Usage: dsd [options] Live scanner mode
Live Scanner mode takes 48KHz/16 bit mono audio samples from a
sound card input and decodes speech in real time. Options are provided
for controling information display and saving mbe data files.
The synthesized speech can be output to a soundcard and/or a
.wav file.
Usage: dsd [options] -r <files> Read/Play saved mbe data from file(s)
Play files mode reads mbe data from files specified on the command
line (including wildcards) and synthesizes speech from those files.
The synthesized speech can be output to a soundcard and/or a
.wav file. The -r command line options is used to activate Play files
mode.
Display modes
There are two main display modes in Live scanner mode. "Errorbars"
and "Datascope".
Errorbars mode output for P25 Phase 1 looks like this:
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -p25p1 mod: C4FM input: 38% nac: 5C2 src: 0 tg: 32464 TDU
Sync: -p25p1 mod: C4FM input: 38% nac: 5C2 src: 0 tg: 32464 HDU
Sync: -p25p1 mod: C4FM input: 42% nac: 5C2 src: 0 tg: 32464 LDU1 e:
Sync: (-p25p1) mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 (LDU2) e:
Sync: -p25p1 mod: C4FM input: 38% nac: 5C2 src: 52610 tg: 32464 LDU1 e:
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e:
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e:
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e:
Sync: -p25p1 mod: C4FM input: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e:
"Sync" indicates the frame type detected and whether the polarity is
positive or negative. DSD automatically detects and handles either
polarity except for DMR/MOTOTRBO/X2-TDMA which unfortunatley use both
sync polarities.
Most combinations of transmitter, receiver and soundcard show netagive
(-) polarity for X2-TDMA signals and (+) polarity for DMR/MOTOTRBO so
those are the defaults.
********
You may need to use the -x option to select non-inverted polarity if
you are not getting usable X2-TDMA/MOTOTRBO/DMR speech. As they use both
normal and inverted sync it is not possible to detect polariy
automatically.
********
"mod" indicates the current demodulation optimizations.
"input" indicates the audio input level. QPSK signals tend to appear
much "wider" than C4FM from a discriminator tap so it is important
to set your input gain using a QPSK signal if you plan to montir them.
It is not necessary nor desirable to get to 100%, in fact your sound
card may max out below 100%. It is best to use the Datascope mode for
setting input gain (see below). Typical values with good results are
40% for C4FM and 66% for QPSK.
"nac" is the P25 Phase 1 Network Access Code. This is a 12 bit field
in each P25 Phase 1 header. It should not be confused with the 16
bit System ID used in non-p25 trunking control channels.
"src" is the radio id of the trasmitting subscriber unit.
"tg" is the talkgroup derived from link control information.
"HDU/LDU1/LDU2/TDU/TDULC" are P25 Phase 1 frame types, referred to as
frame subtype within DSD.
"e:" is the beginning of the errorbars display. Each "=" indicates a
detected error within the voice data. "R" and "M" indicat that a voice
frame was repeated or muted due to excessive errors.
Values in parentheses () indicate an assumption (soft decision) was
made based on the previous frame.
Errorbars mode output for X2-TDMA looks like this:
Sync: -X2-TDMA mod: QPSK input: 59% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
Sync: -X2-TDMA mod: QPSK input: 47% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
Sync: -X2-TDMA mod: QPSK input: 43% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
Sync: (-X2-TDMA) mod: QPSK input: 28% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
DMR/MOTOTRBO display is similar except it does not yet show source
and talkgroup information.
As of version 1.2 DSD shows which specific TDMA slots are active (with
capital SLOT letters) and which slot is currently being monitored (with
square brackets []. Noisy/degraded signals will affect the accuracy
of this display.
The frame subtypes (Voice/LC etc) are shown based on the DMR standard
types.
Datascope mode output looks like this:
Demod mode: C4FM Nac: 8C3
Frame Type: P25 Phase 1 Talkgroup: 16528
Frame Subtype: LDU1 Source: 0
TDMA activity: slot0 slot1 Voice errors:
+----------------------------------------------------------------+
| # ^ !| ^ # |
| * | * |
| * | * |
| * | * * |
| * * | * * |
| * * | ** * |
| * ** | ** * |
| ** ** | ** * |
| ** ** | ** * |
| ** ** | ** * |
+----------------------------------------------------------------+
C4FM Example
Demod mode: C4FM Nac: 126
Frame Type: P25 Phase 1 Talkgroup: 25283
Frame Subtype: LDU2 Source: 0
TDMA activity: slot0 slot1 Voice errors:
+----------------------------------------------------------------+
| # ^ ! ^ # |
| * | |
| * | |
| ** | |
| ** | * |
| * ** | * * |
| ** ** | * * |
| *** ** | ** * |
| *** ** | *** * |
| *** **** | **** * * |
+----------------------------------------------------------------+
QPSK Example
At the top is various information about the signal, similar to the
information provided in Errorbars mode. The large box is similar to
a spectrum analyzer viewing the channel bandwidth.
The horizontal axis is the input audio level, minimum on the left and
maximum on the right. The vertical axis is the number of samples
seend at each audio level.
The "*" symbols represent the number of audio
samples that were at each level during the aggregation period.
(default = 36 symbols) The -S options controls the aggregation period
as well as the QPSK tracking symbol buffer, so changing that will affect
QPSK performance as well as the Datascope display.
As you can see from the figures above, clean C4FM signals tend to have
four very sharply defined audio levels. The datascope pattern also
tends to be faily stable with minor shifts left and right as the
receiver tries to frequency track any DC offset.
QPSK signals on the other hand tend to appear much broader (and artifact
of how they are distored by FM PLL discriminators). They also tend
to vary wildly in width and centering. This is especially true when
monitoring simulcast systems. Muliple QPSK signals interfere much more
dramatically with an FM discriminator than C4FM signals.
*******
For this reason it is important to isolate your receiver to one
transmitter tower, _especially_ for QPSK signals.
*******
The "#" symbols indicate the detected min/max values that are used
to calibrate the symbol decision points. These are indicated by
"!" for the center decision point and "^" for the mid decision points.
Display Options
There are several options to control the type and quantity of
information displayed in Errorbars mode:
-e Show Frame Info and errorbars (default)
-pe Show p25 encryption sync bits
-pl Show p25 link control bits
-ps Show p25 status bits and low speed data
-pt Show p25 talkgroup info
-q Don't show Frame Info/errorbars
-s Datascope (disables other display options)
-t Show symbol timing during sync
-v <num> Frame information Verbosity
-z <num> Frame rate for datascope
Most of these options are self explanitory. Symbol timing is a noisy
option that allows you to view the quality of the frame sync samples
and accuracy of the symbol timing adjustments.
Symbol Timing display looks like this:
Symbol Timing:
----------
----------
----------
----------
----------
-+++++++++ 1
+---------- 0
----------
++++++++++ 0
++++++++++
---------- 0
----------
++++++++++ 0
++++++++++
++++++++++
++++++++++
---------- 0
++++++++++ 0
---------- 0
++++++++++ 0
++++++++++
++++++++++
++++++++++
++++++++++
C4FM example
Symbol Timing:
+---------
----------
----------
----------
-----X---- 5
--+++O++++- 4
----------
----X----- 4
++++O++--- 4
--++O++++- 4
----X----- 4
----------
++++O+++-- 4
-+++O+++-- 4
--++O+++-- 4
--++O+++-- 4
----------
++++O++++- 4
----------
++++O+++-- 4
-+++O++++- 4
-+++O+++++ 4
-+++O++--- 4
--++O+++-- 4
QPSK example
Symbol timing is only displayed for symbols during the frame sync
period. Each horizontal line represents the 10 audio samples for each
symbol. "-" indicates an audio sample below the center reference level
and "+" represents a sample above center. "X" indicates a low spike
below a reference threshold (reference minimum for C4FM and 80%
of reference minimum for QPSK). "O" represents a high spike above
the high reference threshold. The numbers to the right indicate which
sample position the targeted transition occurred (+/- for C4FM or
spike high/low for QPSK). The number of audio samples for the next
symbol are adjusted to get this value closer to the target (0 for
C4FM and 4 for QPSK). This shows how DSD maintains accurate symbol
timing. Symbol timing adjustments are only made during sync, which
is the only time reliable transitions can be observed.
In both examples above the symbol timing was off by one sample at
the beginning of the frame sync period and was adjusted. Generally
if you see any spike values "X/O" in C4FM mode, or lots of them in
QPSK mode it indicates noise on the input signal.
Input/Output Options
-i <device> Audio input device (default is /dev/audio)
-o <device> Audio output device (default is /dev/audio)
-d <dir> Create mbe data files, use this directory
-g <num> Audio output gain (default = 0 = auto)
-n Do not send synthesized speech to audio output device
-w <file> Output synthesized speech to a .wav file
The audio in device can be a sound card OR a .wav file if the file
is in the exact format 48k/16bits/mono/pcm. Audio in should be an
unfilterd discriminator tap signal.
The audio out device should be a sound card (use the -w options to
output to a .wav file).
If the audio in device is the same as the audio out device, the
synthesized speech has to be upsampled to the 48k sample rate required
for input. A fast upsample function is provided but still leaves some
artifacts.
********
The best sound and minimum cpu usage is achieved with separate sound
cards for input and output
********
if you specify different input/output devices DSD will use 8k as the
output sample rate and the lack of resampling results in much better
audio as well as lowe cpu consumption.
If you are using onboard "AC97" sound device you may find that DSD uses
much more cpu than expected, in some cases more than is available.
This is because many AC97 sound devices are designed to rely on CPU
processing power instead of hardware. You may also find that 8k sample
rate output is upsampled in the driver using a very basic algorithim
resulting in severe distortion. The solution is to use a real hardware
sound device (pci card, usb device etc).
As of version 1.2 DSD now automatically levels the output audio. This
greately improves readability and eliminates the painful effects of
noise bursts. You can specify a fixed audio output gain with the -g
option.
Scanner control options:
-B <num> Serial port baud rate (default=115200)
-C <device> Serial port for scanner control (default=/dev/ttyUSB0)
-R <num> Resume scan after <num> TDULC frames or any PDU
On some P25 systems Packet Data Units (PDU) are sent on the same
frequencies used for voice traffic. If done constantly this can
be a severe hinderance to scanning the system in conventional
mode. The -R option enables sending a "resume scan" command to
a scanner connected to a serial port. Use -B and -C to set the baud
rate and serial port device if necessary.
Decoder options
-fa Auto-detect frame type (default)
-f1 Decode only P25 Phase 1
-fd Decode only D-STAR* (no audio)
-fn Decode only NXDN96* (no audio)
-fp Decode only ProVoice*
-fr Decode only DMR/MOTOTRBO
-fx Decode only X2-TDMA
-ma Auto-select modulation optimizations (default)
-mc Use only C4FM modulation optimizations
-mg Use only GFSK modulation optimizations
-mq Use only QPSK modulation optimizations
-u <num> Unvoiced speech quality (default=3)
-xx Expect non-inverted X2-TDMA signal
-xr Expect inverted DMR/MOTOTRBO signal
NXDN and D-STAR are not enabled by default as they are for development
testing only and have shorter frame sync patterns that are prone to
false triggering.
MBE speech synthesis is broken down into two main types of sounds,
"Voiced" and "Unvoiced". Voiced speech bands are synthesized with
a single sine wave centered in the frequency band with the appropriate
phase and amplitude.
Unvoiced speech is supposed to be generated with a noise source, 256
point DFT a number of band filters, followed by a 256 point inverse DFT.
For computational simplicity mbelib uses a different method. For each
unvoiced speech band, a number of sine waves are generated, each with a
different random initial phase. The number of waves used per band is
controlled by the -u option. A setting of 4 would approximate the
performance of the 256 point DFT method as the maximum number of voice
bands is 56, and very low frequencies are not synthesized. Values less
than 3 have a noticable lack of unvoiced speech and/or artifacts. The
defualt of 3 provides good speech quality with reasonable cpu use.
Increasing the quality above the default rapidly consumes more CPU for
increasingly diminishing returns.
Advanced decoder options
-A <num> QPSK modulation auto detection threshold (default=26)
-S <num> Symbol buffer size for QPSK decision point tracking
(default=36)
-M <num> Min/Max buffer size for QPSK decision point tracking
(default=15)
Encryption
********
Decryption of speech is NOT supported, even if you lawfully posess the
encryption keys. Decryption support will not be added in the future as
the authors wish to steer as far away from the legal issues associated
with encryption as possible.
********
We realize that there are many legitemate and lawful uses of decryption
software including system/interoperability testing and lawful monitoring.
This software is distributed under a liberal BSD license so there is
nothing to stop others from supplying patches, forking this project or
incorporating it into a commercial product and adding decryption support.
There is support for displaying the encryption sync bits transmitted in
the clear on P25 Phase 1 systems. These bits do not allow for the
decryption of signals without the secret encryption keys. The
encryption sync bits are useful for determining whether a signal is
encrypted vs merely noisy or degraded. As the encryption sync bits
typically include long strings of zeros when a transmission is not
encrypted they can also be used to visually estimate bit error rates.

32
config.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* System target
*/
#define BSD // bsd/linux audio interface
//#define SOLARIS // solaris audio interface, untested
/*
* noisy debug/development options
*/
//#define X2TDMA_DUMP // cach and sync bits dump
//#define DMR_DUMP
//#define DSTAR_DUMP // dstar frame dump
//#define NXDN_DUMP
//#define UPSAMPLE_DEBUG
//#define PROVOICE_DUMP

3
configure vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
echo "There is no configure script, just run make"

64
dmr_const.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MAIN
extern const int rW[36];
extern const int rX[36];
extern const int rY[36];
extern const int rZ[36];
#else
/*
* DMR AMBE interleave schedule
*/
const int rW[36] = {
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 2,
0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2
};
const int rX[36] = {
23, 10, 22, 9, 21, 8,
20, 7, 19, 6, 18, 5,
17, 4, 16, 3, 15, 2,
14, 1, 13, 0, 12, 10,
11, 9, 10, 8, 9, 7,
8, 6, 7, 5, 6, 4
};
const int rY[36] = {
0, 2, 0, 2, 0, 2,
0, 2, 0, 3, 0, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3
};
const int rZ[36] = {
5, 3, 4, 2, 3, 1,
2, 0, 1, 13, 0, 12,
22, 11, 21, 10, 20, 9,
19, 8, 18, 7, 17, 6,
16, 5, 15, 4, 14, 3,
13, 2, 12, 1, 11, 0
};
#endif

251
dmr_data.c Normal file
View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
processDMRdata (dsd_opts * opts, dsd_state * state)
{
int i, dibit;
int *dibit_p;
char sync[25];
char syncdata[25];
char cachdata[13];
char cc[5];
char bursttype[5];
#ifdef DMR_DUMP
int k;
char syncbits[49];
char cachbits[25];
#endif
cc[4] = 0;
bursttype[4] = 0;
dibit_p = state->dibit_buf_p - 90;
// CACH
for (i = 0; i < 12; i++)
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cachdata[i] = dibit;
if (i == 2)
{
state->currentslot = (1 & (dibit >> 1)); // bit 1
if (state->currentslot == 0)
{
state->slot0light[0] = '[';
state->slot0light[6] = ']';
state->slot1light[0] = ' ';
state->slot1light[6] = ' ';
}
else
{
state->slot1light[0] = '[';
state->slot1light[6] = ']';
state->slot0light[0] = ' ';
state->slot0light[6] = ' ';
}
}
}
cachdata[12] = 0;
#ifdef DMR_DUMP
k = 0;
for (i = 0; i < 12; i++)
{
dibit = cachdata[i];
cachbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
cachbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
cachbits[24] = 0;
printf ("%s ", cachbits);
#endif
// current slot
dibit_p += 49;
// slot type
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cc[0] = (1 & (dibit >> 1)) + 48; // bit 1
cc[1] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cc[2] = (1 & (dibit >> 1)) + 48; // bit 1
cc[3] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
bursttype[0] = (1 & (dibit >> 1)) + 48; // bit 1
bursttype[1] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
bursttype[2] = (1 & (dibit >> 1)) + 48; // bit 1
bursttype[3] = (1 & dibit) + 48; // bit 0
// parity bit
dibit_p++;
if (strcmp (bursttype, "0000") == 0)
{
sprintf (state->fsubtype, " PI Header ");
}
else if (strcmp (bursttype, "0001") == 0)
{
sprintf (state->fsubtype, " VOICE Header ");
}
else if (strcmp (bursttype, "0010") == 0)
{
sprintf (state->fsubtype, " TLC ");
}
else if (strcmp (bursttype, "0011") == 0)
{
sprintf (state->fsubtype, " CSBK ");
}
else if (strcmp (bursttype, "0100") == 0)
{
sprintf (state->fsubtype, " MBC Header ");
}
else if (strcmp (bursttype, "0101") == 0)
{
sprintf (state->fsubtype, " MBC ");
}
else if (strcmp (bursttype, "0110") == 0)
{
sprintf (state->fsubtype, " DATA Header ");
}
else if (strcmp (bursttype, "0111") == 0)
{
sprintf (state->fsubtype, " RATE 1/2 DATA");
}
else if (strcmp (bursttype, "1000") == 0)
{
sprintf (state->fsubtype, " RATE 3/4 DATA");
}
else if (strcmp (bursttype, "1001") == 0)
{
sprintf (state->fsubtype, " Slot idle ");
}
else if (strcmp (bursttype, "1010") == 0)
{
sprintf (state->fsubtype, " Rate 1 DATA ");
}
else
{
sprintf (state->fsubtype, " ");
}
// signaling data or sync
for (i = 0; i < 24; i++)
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
#ifdef DMR_DUMP
k = 0;
for (i = 0; i < 24; i++)
{
dibit = syncdata[i];
syncbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
syncbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
syncbits[48] = 0;
printf ("%s ", syncbits);
#endif
if (strcmp (sync, DMR_DATA_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[slot0]");
}
else
{
sprintf (state->slot1light, "[slot1]");
}
}
else if (strcmp (sync, DMR_VOICE_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[SLOT0]");
}
else
{
sprintf (state->slot1light, "[SLOT1]");
}
}
if (opts->errorbars == 1)
{
printf ("%s %s ", state->slot0light, state->slot1light);
}
// current slot second half, cach, next slot 1st half
skipDibit (opts, state, 120);
if (opts->errorbars == 1)
{
if (strcmp (state->fsubtype, " ") == 0)
{
printf (" Unknown burst type: %s\n", bursttype);
}
else
{
printf ("%s\n", state->fsubtype);
}
}
}

376
dmr_voice.c Normal file
View File

@@ -0,0 +1,376 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
#include "dmr_const.h"
void
processDMRvoice (dsd_opts * opts, dsd_state * state)
{
// extracts AMBE frames from DMR frame
int i, j, dibit;
int *dibit_p;
char ambe_fr[4][24];
char ambe_fr2[4][24];
char ambe_fr3[4][24];
const int *w, *x, *y, *z;
char sync[25];
char syncdata[25];
char cachdata[13];
int mutecurrentslot;
#ifdef DMR_DUMP
int k;
char syncbits[49];
char cachbits[25];
#endif
mutecurrentslot = 0;
dibit_p = state->dibit_buf_p - 144;
for (j = 0; j < 6; j++)
{
// 2nd half of previous slot
for (i = 0; i < 54; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
}
}
// CACH
for (i = 0; i < 12; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
}
cachdata[i] = dibit;
if (i == 2)
{
state->currentslot = (1 & (dibit >> 1)); // bit 1
if (state->currentslot == 0)
{
state->slot0light[0] = '[';
state->slot0light[6] = ']';
state->slot1light[0] = ' ';
state->slot1light[6] = ' ';
}
else
{
state->slot1light[0] = '[';
state->slot1light[6] = ']';
state->slot0light[0] = ' ';
state->slot0light[6] = ' ';
}
}
}
cachdata[12] = 0;
#ifdef DMR_DUMP
k = 0;
for (i = 0; i < 12; i++)
{
dibit = cachdata[i];
cachbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
cachbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
cachbits[24] = 0;
printf ("%s ", cachbits);
#endif
// current slot frame 1
w = rW;
x = rX;
y = rY;
z = rZ;
for (i = 0; i < 36; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
}
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
// current slot frame 2 first half
w = rW;
x = rX;
y = rY;
z = rZ;
for (i = 0; i < 18; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
}
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
// signaling data or sync
for (i = 0; i < 24; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
}
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
if (strcmp (sync, DMR_DATA_SYNC) == 0)
{
mutecurrentslot = 1;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[slot0]");
}
else
{
sprintf (state->slot1light, "[slot1]");
}
}
else if (strcmp (sync, DMR_VOICE_SYNC) == 0)
{
mutecurrentslot = 0;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[SLOT0]");
}
else
{
sprintf (state->slot1light, "[SLOT1]");
}
}
if ((j == 0) && (opts->errorbars == 1))
{
printf ("%s %s VOICE e:", state->slot0light, state->slot1light);
}
#ifdef DMR_DUMP
k = 0;
for (i = 0; i < 24; i++)
{
dibit = syncdata[i];
syncbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
syncbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
syncbits[48] = 0;
printf ("%s ", syncbits);
#endif
// current slot frame 2 second half
for (i = 0; i < 18; i++)
{
dibit = getDibit (opts, state);
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
if (mutecurrentslot == 0)
{
if (state->firstframe == 1)
{ // we don't know if anything received before the first sync after no carrier is valid
state->firstframe = 0;
}
else
{
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
}
}
// current slot frame 3
w = rW;
x = rX;
y = rY;
z = rZ;
for (i = 0; i < 36; i++)
{
dibit = getDibit (opts, state);
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
if (mutecurrentslot == 0)
{
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
}
// CACH
for (i = 0; i < 12; i++)
{
dibit = getDibit (opts, state);
cachdata[i] = dibit;
}
cachdata[12] = 0;
#ifdef DMR_DUMP
k = 0;
for (i = 0; i < 12; i++)
{
dibit = cachdata[i];
cachbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
cachbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
cachbits[24] = 0;
printf ("%s ", cachbits);
#endif
// next slot
skipDibit (opts, state, 54);
// signaling data or sync
for (i = 0; i < 24; i++)
{
dibit = getDibit (opts, state);
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
if (strcmp (sync, DMR_DATA_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot1light, " slot1 ");
}
else
{
sprintf (state->slot0light, " slot0 ");
}
}
else if (strcmp (sync, DMR_VOICE_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot1light, " SLOT1 ");
}
else
{
sprintf (state->slot0light, " SLOT0 ");
}
}
#ifdef DMR_DUMP
k = 0;
for (i = 0; i < 24; i++)
{
dibit = syncdata[i];
syncbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
syncbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
syncbits[48] = 0;
printf ("%s ", syncbits);
#endif
if (j == 5)
{
// 2nd half next slot
skipDibit (opts, state, 54);
// CACH
skipDibit (opts, state, 12);
// first half current slot
skipDibit (opts, state, 54);
}
}
if (opts->errorbars == 1)
{
printf ("\n");
}
}

218
dsd.h Normal file
View File

@@ -0,0 +1,218 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define __USE_XOPEN
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef SOLARIS
#include <sys/audioio.h>
#endif
#ifdef BSD
#include <sys/soundcard.h>
#endif
#include <math.h>
#include <mbelib.h>
typedef struct
{
int onesymbol;
char mbe_in_file[1024];
FILE *mbe_in_f;
int errorbars;
int datascope;
int symboltiming;
int verbose;
int p25enc;
int p25lc;
int p25status;
int p25tg;
int scoperate;
char audio_in_dev[1024];
int audio_in_fd;
char audio_out_dev[1024];
int audio_out_fd;
int split;
int playoffset;
char mbe_out_dir[1024];
char mbe_out_file[1024];
FILE *mbe_out_f;
float audio_gain;
int audio_out;
char wav_out_file[1024];
FILE *wav_out_f;
int wav_out_fd;
int serial_baud;
char serial_dev[1024];
int serial_fd;
int resume;
int frame_dstar;
int frame_x2tdma;
int frame_p25p1;
int frame_nxdn;
int frame_dmr;
int frame_provoice;
int mod_c4fm;
int mod_qpsk;
int mod_gfsk;
int uvquality;
int inverted_x2tdma;
int inverted_dmr;
int mod_threshold;
int ssize;
int msize;
int playfiles;
int delay;
} dsd_opts;
typedef struct
{
int *dibit_buf;
int *dibit_buf_p;
int repeat;
short *audio_out_buf;
short *audio_out_buf_p;
float *audio_out_float_buf;
float *audio_out_float_buf_p;
float audio_out_temp_buf[160];
float *audio_out_temp_buf_p;
int audio_out_idx;
int audio_out_idx2;
int center;
int jitter;
int synctype;
int min;
int max;
int lmid;
int umid;
int minref;
int maxref;
int lastsample;
int sbuf[128];
int sidx;
int maxbuf[1024];
int minbuf[1024];
int midx;
char err_str[64];
char fsubtype[16];
char ftype[16];
int symbolcnt;
int rf_mod;
int numflips;
int lastsynctype;
int lastp25type;
int offset;
int carrier;
char tg[25][16];
int tgcount;
int lasttg;
int lastsrc;
int nac;
int errs;
int errs2;
int mbe_file_type;
int optind;
int numtdulc;
int firstframe;
char slot0light[8];
char slot1light[8];
float aout_gain;
float aout_max_buf[200];
float *aout_max_buf_p;
int aout_max_buf_idx;
int samplesPerSymbol;
int symbolCenter;
char algid[9];
char keyid[17];
int currentslot;
mbe_parms *cur_mp;
mbe_parms *prev_mp;
mbe_parms *prev_mp_enhanced;
} dsd_state;
/*
* Frame sync patterns
*/
#define INV_FRAME_SYNC "333331331133111131311111"
#define FRAME_SYNC "111113113311333313133333"
#define X2TDMA_VOICE_SYNC "113131333331313331113311"
#define X2TDMA_DATA_SYNC "331313111113131113331133"
#define DSTAR_SYNC "313131313133131113313111"
#define INV_DSTAR_SYNC "131313131311313331131333"
#define INV_NXDN96_SYNC "313133113131111333"
#define NXDN96_SYNC "131311331313333111"
#define DMR_DATA_SYNC "313333111331131131331131"
#define DMR_VOICE_SYNC "131111333113313313113313"
#define INV_PROVOICE_SYNC "31313111333133133311331133113311"
#define PROVOICE_SYNC "13131333111311311133113311331133"
/*
* function prototypes
*/
void processDMRdata (dsd_opts * opts, dsd_state * state);
void processDMRvoice (dsd_opts * opts, dsd_state * state);
void processAudio (dsd_opts * opts, dsd_state * state);
void writeSynthesizedVoice (dsd_opts * opts, dsd_state * state);
void playSynthesizedVoice (dsd_opts * opts, dsd_state * state);
void openAudioOutDevice (dsd_opts * opts, int speed);
void openAudioInDevice (dsd_opts * opts);
int getDibit (dsd_opts * opts, dsd_state * state);
void skipDibit (dsd_opts * opts, dsd_state * state, int count);
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
void saveAmbe2250Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
int readImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
int readAmbe2250Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
void openMbeInFile (dsd_opts * opts, dsd_state * state);
void closeMbeOutFile (dsd_opts * opts, dsd_state * state);
void openMbeOutFile (dsd_opts * opts, dsd_state * state);
void openWavOutFile (dsd_opts * opts, dsd_state * state);
void printFrameInfo (dsd_opts * opts, dsd_state * state);
void processFrame (dsd_opts * opts, dsd_state * state);
void printFrameSync (dsd_opts * opts, dsd_state * state, char *frametype, int offset, char *modulation);
int getFrameSync (dsd_opts * opts, dsd_state * state);
int comp (const void *a, const void *b);
void noCarrier (dsd_opts * opts, dsd_state * state);
void initOpts (dsd_opts * opts);
void initState (dsd_state * state);
void usage ();
void liveScanner (dsd_opts * opts, dsd_state * state);
int main (int argc, char **argv);
void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv);
void processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24]);
void openSerial (dsd_opts * opts, dsd_state * state);
void resumeScan (dsd_opts * opts, dsd_state * state);
int getSymbol (dsd_opts * opts, dsd_state * state, int have_sync);
void upsample (dsd_state * state, float invalue);
void processDSTAR (dsd_opts * opts, dsd_state * state);
void processNXDN96 (dsd_opts * opts, dsd_state * state);
void processP25lcw (dsd_opts * opts, dsd_state * state, char *lcformat, char *mfid, char *lcinfo);
void processHDU (dsd_opts * opts, dsd_state * state);
void processLDU1 (dsd_opts * opts, dsd_state * state);
void processLDU2 (dsd_opts * opts, dsd_state * state);
void processTDULC (dsd_opts * opts, dsd_state * state);
void processProVoice (dsd_opts * opts, dsd_state * state);
void processX2TDMAdata (dsd_opts * opts, dsd_state * state);
void processX2TDMAvoice (dsd_opts * opts, dsd_state * state);

365
dsd_audio.c Normal file
View File

@@ -0,0 +1,365 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
processAudio (dsd_opts * opts, dsd_state * state)
{
int i, n;
float aout_abs, max, gainfactor, gaindelta, maxbuf;
if (opts->audio_gain == (float) 0)
{
// detect max level
max = 0;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
aout_abs = fabsf (*state->audio_out_temp_buf_p);
if (aout_abs > max)
{
max = aout_abs;
}
state->audio_out_temp_buf_p++;
}
*state->aout_max_buf_p = max;
state->aout_max_buf_p++;
state->aout_max_buf_idx++;
if (state->aout_max_buf_idx > 74)
{
state->aout_max_buf_idx = 0;
state->aout_max_buf_p = state->aout_max_buf;
}
// lookup max history
for (i = 0; i < 75; i++)
{
maxbuf = state->aout_max_buf[i];
if (maxbuf > max)
{
max = maxbuf;
}
}
// determine optimal gain level
if (max > (float) 0)
{
gainfactor = ((float) 30000 / max);
}
else
{
gainfactor = (float) 50;
}
if (gainfactor < state->aout_gain)
{
state->aout_gain = gainfactor;
gaindelta = (float) 0;
}
else
{
if (gainfactor > (float) 50)
{
gainfactor = (float) 50;
}
gaindelta = gainfactor - state->aout_gain;
if (gaindelta > ((float) 0.05 * state->aout_gain))
{
gaindelta = ((float) 0.05 * state->aout_gain);
}
}
gaindelta /= (float) 160;
}
else
{
gaindelta = (float) 0;
}
// adjust output gain
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
*state->audio_out_temp_buf_p = (state->aout_gain + ((float) n * gaindelta)) * (*state->audio_out_temp_buf_p);
state->audio_out_temp_buf_p++;
}
state->aout_gain += ((float) 160 * gaindelta);
// copy audio datat to output buffer and upsample if necessary
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
if (opts->split == 0)
{
for (n = 0; n < 160; n++)
{
upsample (state, *state->audio_out_temp_buf_p);
state->audio_out_temp_buf_p++;
state->audio_out_float_buf_p += 6;
state->audio_out_idx += 6;
state->audio_out_idx2 += 6;
}
state->audio_out_float_buf_p -= (960 + opts->playoffset);
// copy to output (short) buffer
for (n = 0; n < 960; n++)
{
if (*state->audio_out_float_buf_p > (float) 32760)
{
*state->audio_out_float_buf_p = (float) 32760;
}
else if (*state->audio_out_float_buf_p < (float) -32760)
{
*state->audio_out_float_buf_p = (float) -32760;
}
*state->audio_out_buf_p = (short) *state->audio_out_float_buf_p;
state->audio_out_buf_p++;
state->audio_out_float_buf_p++;
}
state->audio_out_float_buf_p += opts->playoffset;
}
else
{
for (n = 0; n < 160; n++)
{
if (*state->audio_out_temp_buf_p > (float) 32760)
{
*state->audio_out_temp_buf_p = (float) 32760;
}
else if (*state->audio_out_temp_buf_p < (float) -32760)
{
*state->audio_out_temp_buf_p = (float) -32760;
}
*state->audio_out_buf_p = (short) *state->audio_out_temp_buf_p;
state->audio_out_buf_p++;
state->audio_out_temp_buf_p++;
state->audio_out_idx++;
state->audio_out_idx2++;
}
}
}
void
writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
{
int n;
short aout_buf[160];
short *aout_buf_p;
aout_buf_p = aout_buf;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
if (*state->audio_out_temp_buf_p > (float) 32760)
{
*state->audio_out_temp_buf_p = (float) 32760;
}
else if (*state->audio_out_temp_buf_p < (float) -32760)
{
*state->audio_out_temp_buf_p = (float) -32760;
}
*aout_buf_p = (short) *state->audio_out_temp_buf_p;
aout_buf_p++;
state->audio_out_temp_buf_p++;
}
write (opts->wav_out_fd, aout_buf, 320);
fflush (opts->wav_out_f);
}
void
playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
{
if (state->audio_out_idx > opts->delay)
{
// output synthesized speech to sound card
write (opts->audio_out_fd, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2));
state->audio_out_idx = 0;
}
if (state->audio_out_idx2 >= 800000)
{
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_idx2 = 0;
}
}
void
openAudioOutDevice (dsd_opts * opts, int speed)
{
#ifdef SOLARIS
sample_info_t aset, aget;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{
printf ("Error, couldn't open %s\n", opts->audio_out_dev);
exit (1);
}
// get current
ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset);
aset.record.sample_rate = speed;
aset.play.sample_rate = speed;
aset.record.channels = 1;
aset.play.channels = 1;
aset.record.precision = 16;
aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR;
if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
{
printf ("Error setting sample device parameters\n");
exit (1);
}
#endif
#ifdef BSD
int fmt;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{
printf ("Error, couldn't open %s\n", opts->audio_out_dev);
opts->audio_out = 0;
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
{
printf ("ioctl reset error \n");
}
fmt = speed;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
printf ("ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
printf ("ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
printf ("ioctl setfmt error \n");
}
#endif
printf ("Audio Out Device: %s\n", opts->audio_out_dev);
}
void
openAudioInDevice (dsd_opts * opts)
{
#ifdef SOLARIS
sample_info_t aset, aget;
int rgain;
rgain = 64;
if (opts->split == 1)
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY);
}
else
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
}
if (opts->audio_in_fd == -1)
{
printf ("Error, couldn't open /dev/audio\n");
}
// get current
ioctl (opts->audio_in_fd, AUDIO_GETINFO, &aset);
aset.record.sample_rate = 48000;
aset.play.sample_rate = 48000;
aset.record.channels = 1;
aset.play.channels = 1;
aset.record.precision = 16;
aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR;
aset.record.port = AUDIO_LINE_IN;
aset.record.gain = rgain;
if (ioctl (opts->audio_in_fd, AUDIO_SETINFO, &aset) == -1)
{
printf ("Error setting sample device parameters\n");
exit (1);
}
#endif
#ifdef BSD
int fmt;
if (opts->split == 1)
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY);
}
else
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
}
if (opts->audio_in_fd == -1)
{
printf ("Error, couldn't open %s\n", opts->audio_in_dev);
opts->audio_out = 0;
}
fmt = 0;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0)
{
printf ("ioctl reset error \n");
}
fmt = 48000;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
printf ("ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
printf ("ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
printf ("ioctl setfmt error \n");
}
#endif
if (opts->split == 1)
{
printf ("Audio In Device: %s\n", opts->audio_in_dev);
}
else
{
printf ("Audio In/Out Device: %s\n", opts->audio_in_dev);
}
}

290
dsd_dibit.c Normal file
View File

@@ -0,0 +1,290 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
int
getDibit (dsd_opts * opts, dsd_state * state)
{
// returns one dibit value
int i, j, o, symbol;
int sbuf2[128];
int spectrum[64];
char modulation[8];
int lmin, lmax, lsum;
state->numflips = 0;
symbol = getSymbol (opts, state, 1);
state->sbuf[state->sidx] = symbol;
for (i = 0; i < opts->ssize; i++)
{
sbuf2[i] = state->sbuf[i];
}
qsort (sbuf2, opts->ssize, sizeof (int), comp);
// continuous update of min/max in rf_mod=1 (QPSK) mode
// in c4fm min/max must only be updated during sync
if (state->rf_mod == 1)
{
lmin = (sbuf2[0] + sbuf2[1]) / 2;
lmax = (sbuf2[(opts->ssize - 1)] + sbuf2[(opts->ssize - 2)]) / 2;
state->minbuf[state->midx] = lmin;
state->maxbuf[state->midx] = lmax;
if (state->midx == (opts->msize - 1))
{
state->midx = 0;
}
else
{
state->midx++;
}
lsum = 0;
for (i = 0; i < opts->msize; i++)
{
lsum += state->minbuf[i];
}
state->min = lsum / opts->msize;
lsum = 0;
for (i = 0; i < opts->msize; i++)
{
lsum += state->maxbuf[i];
}
state->max = lsum / opts->msize;
state->center = ((state->max) + (state->min)) / 2;
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
state->maxref = ((state->max) * 0.80);
state->minref = ((state->min) * 0.80);
}
else
{
state->maxref = state->max;
state->minref = state->min;
}
if (state->sidx == (opts->ssize - 1))
{
state->sidx = 0;
if (opts->datascope == 1)
{
if (state->rf_mod == 0)
{
sprintf (modulation, "C4FM");
}
else if (state->rf_mod == 1)
{
sprintf (modulation, "QPSK");
}
else if (state->rf_mod == 2)
{
sprintf (modulation, "GFSK");
}
for (i = 0; i < 64; i++)
{
spectrum[i] = 0;
}
for (i = 0; i < opts->ssize; i++)
{
o = (sbuf2[i] + 32768) / 1024;
spectrum[o]++;
}
if (state->symbolcnt > (4800 / opts->scoperate))
{
state->symbolcnt = 0;
printf ("\n");
printf ("Demod mode: %s Nac: %4X\n", modulation, state->nac);
printf ("Frame Type: %s Talkgroup: %7i\n", state->ftype, state->lasttg);
printf ("Frame Subtype: %s Source: %12i\n", state->fsubtype, state->lastsrc);
printf ("TDMA activity: %s %s Voice errors: %s\n", state->slot0light, state->slot1light, state->err_str);
printf ("+----------------------------------------------------------------+\n");
for (i = 0; i < 10; i++)
{
printf ("|");
for (j = 0; j < 64; j++)
{
if (i == 0)
{
if ((j == ((state->min) + 32768) / 1024) || (j == ((state->max) + 32768) / 1024))
{
printf ("#");
}
else if ((j == ((state->lmid) + 32768) / 1024) || (j == ((state->umid) + 32768) / 1024))
{
printf ("^");
}
else if (j == (state->center + 32768) / 1024)
{
printf ("!");
}
else
{
if (j == 32)
{
printf ("|");
}
else
{
printf (" ");
}
}
}
else
{
if (spectrum[j] > 9 - i)
{
printf ("*");
}
else
{
if (j == 32)
{
printf ("|");
}
else
{
printf (" ");
}
}
}
}
printf ("|\n");
}
printf ("+----------------------------------------------------------------+\n");
}
}
}
else
{
state->sidx++;
}
// determine dibit state
if ((state->synctype == 6) || (state->synctype == 14))
{
if (symbol > state->center)
{
*state->dibit_buf_p = 1;
state->dibit_buf_p++;
return (0);
}
else
{
*state->dibit_buf_p = 3;
state->dibit_buf_p++;
return (1);
}
}
else if ((state->synctype == 7) || (state->synctype == 15))
{
if (symbol > state->center)
{
*state->dibit_buf_p = 1;
state->dibit_buf_p++;
return (1);
}
else
{
*state->dibit_buf_p = 3;
state->dibit_buf_p++;
return (0);
}
}
else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) || (state->synctype == 9) || (state->synctype == 11) || (state->synctype == 13))
{
if (symbol > state->center)
{
if (symbol > state->umid)
{
*state->dibit_buf_p = 1; // store non-inverted values in dibit_buf
state->dibit_buf_p++;
return (3);
}
else
{
*state->dibit_buf_p = 0;
state->dibit_buf_p++;
return (2);
}
}
else
{
if (symbol < state->lmid)
{
*state->dibit_buf_p = 3;
state->dibit_buf_p++;
return (1);
}
else
{
*state->dibit_buf_p = 2;
state->dibit_buf_p++;
return (0);
}
}
}
else
{
if (symbol > state->center)
{
if (symbol > state->umid)
{
*state->dibit_buf_p = 1;
state->dibit_buf_p++;
return (1);
}
else
{
*state->dibit_buf_p = 0;
state->dibit_buf_p++;
return (0);
}
}
else
{
if (symbol < state->lmid)
{
*state->dibit_buf_p = 3;
state->dibit_buf_p++;
return (3);
}
else
{
*state->dibit_buf_p = 2;
state->dibit_buf_p++;
return (2);
}
}
}
}
void
skipDibit (dsd_opts * opts, dsd_state * state, int count)
{
short sample;
int i;
for (i = 0; i < (count); i++)
{
sample = getDibit (opts, state);
}
}

331
dsd_file.c Normal file
View File

@@ -0,0 +1,331 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
{
int i, j, k;
unsigned char b;
unsigned char err;
err = (unsigned char) state->errs2;
fputc (err, opts->mbe_out_f);
k = 0;
for (i = 0; i < 11; i++)
{
b = 0;
for (j = 0; j < 8; j++)
{
b = b << 1;
b = b + imbe_d[k];
k++;
}
fputc (b, opts->mbe_out_f);
}
fflush (opts->mbe_out_f);
}
void
saveAmbe2250Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
{
int i, j, k;
unsigned char b;
unsigned char err;
err = (unsigned char) state->errs2;
fputc (err, opts->mbe_out_f);
k = 0;
for (i = 0; i < 6; i++)
{
b = 0;
for (j = 0; j < 8; j++)
{
b = b << 1;
b = b + ambe_d[k];
k++;
}
fputc (b, opts->mbe_out_f);
}
b = ambe_d[48];
fputc (b, opts->mbe_out_f);
fflush (opts->mbe_out_f);
}
int
readImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
{
int i, j, k;
unsigned char b;
state->errs2 = fgetc (opts->mbe_in_f);
state->errs = state->errs2;
k = 0;
for (i = 0; i < 11; i++)
{
b = fgetc (opts->mbe_in_f);
if (feof (opts->mbe_in_f))
{
return (1);
}
for (j = 0; j < 8; j++)
{
imbe_d[k] = (b & 128) >> 7;
b = b << 1;
b = b & 255;
k++;
}
}
return (0);
}
int
readAmbe2250Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
{
int i, j, k;
unsigned char b;
state->errs2 = fgetc (opts->mbe_in_f);
state->errs = state->errs2;
k = 0;
for (i = 0; i < 6; i++)
{
b = fgetc (opts->mbe_in_f);
if (feof (opts->mbe_in_f))
{
return (1);
}
for (j = 0; j < 8; j++)
{
ambe_d[k] = (b & 128) >> 7;
b = b << 1;
b = b & 255;
k++;
}
}
b = fgetc (opts->mbe_in_f);
ambe_d[48] = b;
return (0);
}
void
openMbeInFile (dsd_opts * opts, dsd_state * state)
{
char cookie[5];
opts->mbe_in_f = fopen (opts->mbe_in_file, "ro");
if (opts->mbe_in_f == NULL)
{
printf ("Error: could not open %s\n", opts->mbe_in_file);
}
// read cookie
cookie[0] = fgetc (opts->mbe_in_f);
cookie[1] = fgetc (opts->mbe_in_f);
cookie[2] = fgetc (opts->mbe_in_f);
cookie[3] = fgetc (opts->mbe_in_f);
cookie[4] = 0;
if (strstr (cookie, ".amb") != NULL)
{
state->mbe_file_type = 1;
}
else if (strstr (cookie, ".imb") != NULL)
{
state->mbe_file_type = 0;
}
else
{
state->mbe_file_type = -1;
printf ("Error - unrecognized file type\n");
}
}
void
closeMbeOutFile (dsd_opts * opts, dsd_state * state)
{
char shell[255], newfilename[64], ext[5], datestr[32];
char tgid[17];
int sum, i, j;
int talkgroup;
struct tm timep;
if (opts->mbe_out_f != NULL)
{
if ((state->synctype == 0) || (state->synctype == 1) || (state->synctype == 14) || (state->synctype == 15))
{
sprintf (ext, ".imb");
strptime (opts->mbe_out_file, "%s.imb", &timep);
}
else
{
sprintf (ext, ".amb");
strptime (opts->mbe_out_file, "%s.amb", &timep);
}
for (i = 0; i < 17; i++)
{
tgid[i] = 0;
}
if (state->tgcount > 0)
{
for (i = 0; i < 16; i++)
{
sum = 0;
for (j = 0; j < state->tgcount; j++)
{
sum = sum + state->tg[j][i] - 48;
}
tgid[i] = (char) (((float) sum / (float) state->tgcount) + 48.5);
}
talkgroup = (int) strtol (tgid, NULL, 2);
}
else
{
talkgroup = 0;
}
fflush (opts->mbe_out_f);
fclose (opts->mbe_out_f);
opts->mbe_out_f = NULL;
strftime (datestr, 31, "%Y-%m-%d-%H%M%S", &timep);
sprintf (newfilename, "nac%X-%s-tg%i%s", state->nac, datestr, talkgroup, ext);
sprintf (shell, "mv %s %s", opts->mbe_out_file, newfilename);
system (shell);
}
}
void
openMbeOutFile (dsd_opts * opts, dsd_state * state)
{
struct timeval tv;
int i, j;
char ext[5];
if ((state->synctype == 0) || (state->synctype == 1) || (state->synctype == 14) || (state->synctype == 15))
{
sprintf (ext, ".imb");
}
else
{
sprintf (ext, ".amb");
}
// reset talkgroup id buffer
for (i = 0; i < 12; i++)
{
for (j = 0; j < 25; j++)
{
state->tg[j][i] = 0;
}
}
state->tgcount = 0;
gettimeofday (&tv, NULL);
sprintf (opts->mbe_out_file, "%i%s", (int) tv.tv_sec, ext);
opts->mbe_out_f = fopen (opts->mbe_out_file, "w");
if (opts->mbe_out_f == NULL)
{
printf ("Error, couldn't open %s\n", opts->mbe_out_file);
}
// write magic
fprintf (opts->mbe_out_f, "%s", ext);
fflush (opts->mbe_out_f);
}
void
openWavOutFile (dsd_opts * opts, dsd_state * state)
{
opts->wav_out_f = fopen (opts->wav_out_file, "w");
if (opts->wav_out_f == NULL)
{
printf ("Error - could not open wav output file %s\n", opts->wav_out_file);
return;
}
opts->wav_out_fd = fileno (opts->wav_out_f);
fprintf (opts->wav_out_f, "RIFF");
// total length
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fprintf (opts->wav_out_f, "WAVE");
fprintf (opts->wav_out_f, "fmt ");
// length of format chunk
fputc (16, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// always 0x1
fputc (1, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// channels
fputc (1, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// sample rate
fputc (64, opts->wav_out_f);
fputc (31, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// bytes per second
fputc (176, opts->wav_out_f);
fputc (62, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// bytes/sample
fputc (2, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// bits/sample
fputc (16, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// data chunk header
fprintf (opts->wav_out_f, "data");
// length of data
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (127, opts->wav_out_f);
fflush (opts->wav_out_f);
}

421
dsd_frame.c Normal file
View File

@@ -0,0 +1,421 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
printFrameInfo (dsd_opts * opts, dsd_state * state)
{
int level;
level = (int) (((float) state->max / (float) 32768) * (float) 100);
if (opts->verbose > 0)
{
printf ("input: %2i%% ", level);
}
if (state->nac != 0)
{
printf ("nac: %4X ", state->nac);
}
if (opts->verbose > 1)
{
printf ("src: %8i ", state->lastsrc);
}
printf ("tg: %5i ", state->lasttg);
}
void
processFrame (dsd_opts * opts, dsd_state * state)
{
int i, j, dibit;
char duid[3];
char nac[13];
int level;
duid[2] = 0;
j = 0;
if (state->rf_mod == 1)
{
state->maxref = (state->max * 0.80);
state->minref = (state->min * 0.80);
}
else
{
state->maxref = state->max;
state->minref = state->min;
}
if ((state->synctype == 8) || (state->synctype == 9))
{
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) (((float) state->max / (float) 32768) * (float) 100);
printf ("input: %2i%% ", level);
}
}
state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processNXDN96 (opts, state);
return;
}
else if ((state->synctype == 6) || (state->synctype == 7))
{
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) (((float) state->max / (float) 32768) * (float) 100);
printf ("input: %2i%% ", level);
}
}
state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processDSTAR (opts, state);
return;
}
else if ((state->synctype >= 10) && (state->synctype <= 13))
{
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) (((float) state->max / (float) 32768) * (float) 100);
printf ("input: %2i%% ", level);
}
}
if ((state->synctype == 11) || (state->synctype == 12))
{
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processDMRvoice (opts, state);
}
else
{
closeMbeOutFile (opts, state);
state->err_str[0] = 0;
processDMRdata (opts, state);
}
return;
}
else if ((state->synctype >= 2) && (state->synctype <= 5))
{
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
}
if ((state->synctype == 3) || (state->synctype == 4))
{
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processX2TDMAvoice (opts, state);
}
else
{
closeMbeOutFile (opts, state);
state->err_str[0] = 0;
processX2TDMAdata (opts, state);
}
return;
}
else if ((state->synctype == 14) || (state->synctype == 15))
{
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) (((float) state->max / (float) 32768) * (float) 100);
printf ("input: %2i%% ", level);
}
}
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processProVoice (opts, state);
return;
}
else
{
j = 0;
for (i = 0; i < 6; i++)
{
dibit = getDibit (opts, state);
nac[j] = (1 & (dibit >> 1)) + 48; // bit 1
j++;
nac[j] = (1 & dibit) + 48; // bit 0
j++;
}
nac[12] = 0;
state->nac = strtol (nac, NULL, 2);
for (i = 0; i < 2; i++)
{
duid[i] = getDibit (opts, state) + 48;
}
}
if (strcmp (duid, "00") == 0)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" HDU\n");
}
state->cur_mp->repeat = 0;
if (opts->mbe_out_dir[0] != 0)
{
closeMbeOutFile (opts, state);
openMbeOutFile (opts, state);
}
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
state->lastp25type = 2;
sprintf (state->fsubtype, " HDU ");
processHDU (opts, state);
}
else if (strcmp (duid, "11") == 0)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" LDU1 ");
}
if (opts->mbe_out_dir[0] != 0)
{
if (opts->mbe_out_f == NULL)
{
openMbeOutFile (opts, state);
}
}
state->lastp25type = 1;
sprintf (state->fsubtype, " LDU1 ");
state->numtdulc = 0;
processLDU1 (opts, state);
}
else if (strcmp (duid, "22") == 0)
{
if (state->lastp25type != 1)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" Ignoring LDU2 not preceeded by LDU1\n");
}
state->lastp25type = 0;
sprintf (state->fsubtype, " ");
}
else
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" LDU2 ");
}
if (opts->mbe_out_dir[0] != 0)
{
if (opts->mbe_out_f == NULL)
{
openMbeOutFile (opts, state);
}
}
state->lastp25type = 2;
sprintf (state->fsubtype, " LDU2 ");
state->numtdulc = 0;
processLDU2 (opts, state);
}
}
else if (strcmp (duid, "33") == 0)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" TDULC\n");
}
state->cur_mp->repeat = 0;
if (opts->mbe_out_dir[0] != 0)
{
closeMbeOutFile (opts, state);
}
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
state->tgcount = 0;
state->lastp25type = 0;
sprintf (state->fsubtype, " TDULC ");
state->numtdulc++;
if ((opts->resume > 0) && (state->numtdulc > opts->resume))
{
resumeScan (opts, state);
}
processTDULC (opts, state);
state->err_str[0] = 0;
}
else if (strcmp (duid, "03") == 0)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" TDU\n");
}
state->cur_mp->repeat = 0;
if (opts->mbe_out_dir[0] != 0)
{
closeMbeOutFile (opts, state);
}
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
state->tgcount = 0;
state->lastp25type = 0;
state->err_str[0] = 0;
sprintf (state->fsubtype, " TDU ");
skipDibit (opts, state, 40);
}
else if (strcmp (duid, "13") == 0)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" TSDU\n");
}
state->lastp25type = 3;
sprintf (state->fsubtype, " TSDU ");
skipDibit (opts, state, 328);
}
else if (strcmp (duid, "30") == 0)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" PDU\n");
if (opts->resume > 0)
{
resumeScan (opts, state);
}
}
if (opts->mbe_out_dir[0] != 0)
{
if (opts->mbe_out_f == NULL)
{
openMbeOutFile (opts, state);
}
}
state->lastp25type = 4;
sprintf (state->fsubtype, " PDU ");
}
// try to guess based on previous frame if unknown type
else if (state->lastp25type == 1)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf ("(LDU2) ");
}
if (opts->mbe_out_dir[0] != 0)
{
if (opts->mbe_out_f == NULL)
{
openMbeOutFile (opts, state);
}
}
state->lastp25type = 0;
sprintf (state->fsubtype, "(LDU2) ");
state->numtdulc = 0;
processLDU2 (opts, state);
}
else if (state->lastp25type == 2)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf ("(LDU1) ");
}
if (opts->mbe_out_dir[0] != 0)
{
if (opts->mbe_out_f == NULL)
{
openMbeOutFile (opts, state);
}
}
state->lastp25type = 0;
sprintf (state->fsubtype, "(LDU1) ");
state->numtdulc = 0;
processLDU1 (opts, state);
}
else if (state->lastp25type == 3)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" (TSDU)\n");
}
state->lastp25type = 0;
sprintf (state->fsubtype, "(TSDU) ");
skipDibit (opts, state, 328);
}
else if (state->lastp25type == 4)
{
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" (PDU)\n");
}
state->lastp25type = 0;
}
else
{
state->lastp25type = 0;
sprintf (state->fsubtype, " ");
if (opts->errorbars == 1)
{
printFrameInfo (opts, state);
printf (" duid:%s *Unknown DUID*\n", duid);
}
}
}

691
dsd_frame_sync.c Normal file
View File

@@ -0,0 +1,691 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
printFrameSync (dsd_opts * opts, dsd_state * state, char *frametype, int offset, char *modulation)
{
if (opts->verbose > 0)
{
printf ("Sync: %s ", frametype);
}
if (opts->verbose > 2)
{
printf ("o: %4i ", offset);
}
if (opts->verbose > 1)
{
printf ("mod: %s ", modulation);
}
if (opts->verbose > 2)
{
printf ("g: %f ", state->aout_gain);
}
}
int
getFrameSync (dsd_opts * opts, dsd_state * state)
{
/* detects frame sync and returns frame type
* 0 = +p25p1
* 1 = -p25p1
* 2 = +X2-TDMA (non inverted signal data frame)
* 3 = +X2-TDMA (inverted signal voice frame)
* 4 = -X2-TDMA (non inverted signal voice frame)
* 5 = -X2-TDMA (inverted signal data frame)
* 6 = +D-STAR
* 7 = -D-STAR
* 8 = +NXDN96
* 9 = -NXDN96
* 10 = +DMR (non inverted singlan data frame)
* 11 = -DMR (inverted signal voice frame)
* 12 = +DMR (non inverted signal voice frame)
* 13 = -DMR (inverted signal data frame)
* 14 = +ProVoice
* 15 = -ProVoice
*/
int i, j, t, o, dibit, sync, symbol, synctest_pos, lastt;
char synctest[25];
char synctest18[19];
char synctest32[33];
char modulation[8];
char *synctest_p;
char synctest_buf[10240];
int lmin, lmax, lidx;
int lbuf[24], lbuf2[24];
int lsum;
char spectrum[64];
// detect frame sync
t = 0;
synctest[24] = 0;
synctest18[18] = 0;
synctest32[32] = 0;
synctest_pos = 0;
synctest_p = synctest_buf;
sync = 0;
lmin = 0;
lmax = 0;
lidx = 0;
lastt = 0;
state->numflips = 0;
if ((opts->symboltiming == 1) && (state->carrier == 1))
{
printf ("\nSymbol Timing:\n");
}
while (sync == 0)
{
t++;
symbol = getSymbol (opts, state, 0);
lbuf[lidx] = symbol;
state->sbuf[state->sidx] = symbol;
if (lidx == 23)
{
lidx = 0;
}
else
{
lidx++;
}
if (state->sidx == (opts->ssize - 1))
{
state->sidx = 0;
}
else
{
state->sidx++;
}
if (lastt == 23)
{
lastt = 0;
if (state->numflips > opts->mod_threshold)
{
if (opts->mod_qpsk == 1)
{
state->rf_mod = 1;
}
}
else if (state->numflips > 18)
{
if (opts->mod_gfsk == 1)
{
state->rf_mod = 2;
}
}
else
{
if (opts->mod_c4fm == 1)
{
state->rf_mod = 0;
}
}
state->numflips = 0;
}
else
{
lastt++;
}
//determine dibit state
if (symbol > 0)
{
*state->dibit_buf_p = 1;
state->dibit_buf_p++;
dibit = 49;
}
else
{
*state->dibit_buf_p = 3;
state->dibit_buf_p++;
dibit = 51;
}
/*
printf("%c", dibit);
if (t == 768)
{
printf("\n");
t=0;
}
*/
*synctest_p = dibit;
if (t >= 24)
{
for (i = 0; i < 24; i++)
{
lbuf2[i] = lbuf[i];
}
qsort (lbuf2, 24, sizeof (int), comp);
lmin = (lbuf2[2] + lbuf2[3] + lbuf2[4]) / 3;
lmax = (lbuf2[21] + lbuf2[20] + lbuf2[19]) / 3;
if (state->rf_mod == 1)
{
state->minbuf[state->midx] = lmin;
state->maxbuf[state->midx] = lmax;
if (state->midx == (opts->msize - 1))
{
state->midx = 0;
}
else
{
state->midx++;
}
lsum = 0;
for (i = 0; i < opts->msize; i++)
{
lsum += state->minbuf[i];
}
state->min = lsum / opts->msize;
lsum = 0;
for (i = 0; i < opts->msize; i++)
{
lsum += state->maxbuf[i];
}
state->max = lsum / opts->msize;
state->center = ((state->max) + (state->min)) / 2;
state->maxref = ((state->max) * 0.80);
state->minref = ((state->min) * 0.80);
}
else
{
state->maxref = state->max;
state->minref = state->min;
}
if (state->rf_mod == 0)
{
sprintf (modulation, "C4FM");
}
else if (state->rf_mod == 1)
{
sprintf (modulation, "QPSK");
}
else if (state->rf_mod == 2)
{
sprintf (modulation, "GFSK");
}
if (opts->datascope == 1)
{
if (lidx == 0)
{
for (i = 0; i < 64; i++)
{
spectrum[i] = 0;
}
for (i = 0; i < 24; i++)
{
o = (lbuf2[i] + 32768) / 1024;
spectrum[o]++;
}
if (state->symbolcnt > (4800 / opts->scoperate))
{
state->symbolcnt = 0;
printf ("\n");
printf ("Demod mode: %s Nac: %4X\n", modulation, state->nac);
printf ("Frame Type: %s Talkgroup: %7i\n", state->ftype, state->lasttg);
printf ("Frame Subtype: %s Source: %12i\n", state->fsubtype, state->lastsrc);
printf ("TDMA activity: %s %s Voice errors: %s\n", state->slot0light, state->slot1light, state->err_str);
printf ("+----------------------------------------------------------------+\n");
for (i = 0; i < 10; i++)
{
printf ("|");
for (j = 0; j < 64; j++)
{
if (i == 0)
{
if ((j == ((state->min) + 32768) / 1024) || (j == ((state->max) + 32768) / 1024))
{
printf ("#");
}
else if (j == (state->center + 32768) / 1024)
{
printf ("!");
}
else
{
if (j == 32)
{
printf ("|");
}
else
{
printf (" ");
}
}
}
else
{
if (spectrum[j] > 9 - i)
{
printf ("*");
}
else
{
if (j == 32)
{
printf ("|");
}
else
{
printf (" ");
}
}
}
}
printf ("|\n");
}
printf ("+----------------------------------------------------------------+\n");
}
}
}
strncpy (synctest, (synctest_p - 23), 24);
if (opts->frame_p25p1 == 1)
{
if (strcmp (synctest, FRAME_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " P25 Phase 1 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +p25p1 ", synctest_pos + 1, modulation);
}
state->lastsynctype = 0;
return (0);
}
if (strcmp (synctest, INV_FRAME_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " P25 Phase 1 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -p25p1 ", synctest_pos + 1, modulation);
}
state->lastsynctype = 1;
return (1);
}
}
if (opts->frame_x2tdma == 1)
{
if (strcmp (synctest, X2TDMA_DATA_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + (lmax)) / 2;
state->min = ((state->min) + (lmin)) / 2;
if (opts->inverted_x2tdma == 0)
{
// data frame
sprintf (state->ftype, " X2-TDMA ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +X2-TDMA ", synctest_pos + 1, modulation);
}
state->lastsynctype = 2;
return (2);
}
else
{
// inverted voice frame
sprintf (state->ftype, " X2-TDMA ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -X2-TDMA ", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 3)
{
state->firstframe = 1;
}
state->lastsynctype = 3;
return (3);
}
}
if (strcmp (synctest, X2TDMA_VOICE_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (opts->inverted_x2tdma == 0)
{
// voice frame
sprintf (state->ftype, " X2-TDMA ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +X2-TDMA ", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 4)
{
state->firstframe = 1;
}
state->lastsynctype = 4;
return (4);
}
else
{
// inverted data frame
sprintf (state->ftype, " X2-TDMA ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -X2-TDMA ", synctest_pos + 1, modulation);
}
state->lastsynctype = 5;
return (5);
}
}
}
if (opts->frame_dmr == 1)
{
if (strcmp (synctest, DMR_DATA_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + (lmax)) / 2;
state->min = ((state->min) + (lmin)) / 2;
if (opts->inverted_dmr == 0)
{
// data frame
sprintf (state->ftype, " DMR ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 10;
return (10);
}
else
{
// inverted voice frame
sprintf (state->ftype, " DMR ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -DMR ", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 11)
{
state->firstframe = 1;
}
state->lastsynctype = 11;
return (11);
}
}
if (strcmp (synctest, DMR_VOICE_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (opts->inverted_dmr == 0)
{
// voice frame
sprintf (state->ftype, " DMR ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +DMR ", synctest_pos + 1, modulation);
}
if (state->lastsynctype != 12)
{
state->firstframe = 1;
}
state->lastsynctype = 12;
return (12);
}
else
{
// inverted data frame
sprintf (state->ftype, " DMR ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 13;
return (13);
}
}
}
if (opts->frame_provoice == 1)
{
strncpy (synctest32, (synctest_p - 31), 32);
if (strcmp (synctest32, PROVOICE_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " ProVoice ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -ProVoice ", synctest_pos + 1, modulation);
}
state->lastsynctype = 14;
return (14);
}
else if (strcmp (synctest32, INV_PROVOICE_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " ProVoice ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -ProVoice ", synctest_pos + 1, modulation);
}
state->lastsynctype = 15;
return (15);
}
}
if (opts->frame_nxdn == 1)
{
strncpy (synctest18, (synctest_p - 17), 18);
if (strcmp (synctest18, NXDN96_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " NXDN96 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation);
}
state->lastsynctype = 8;
return (8);
}
if (strcmp (synctest18, INV_NXDN96_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " NXDN96 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation);
}
state->lastsynctype = 9;
return (9);
}
}
if (opts->frame_dstar == 1)
{
if (strcmp (synctest, DSTAR_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " D-STAR ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +D-STAR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 6;
return (6);
}
if (strcmp (synctest, INV_DSTAR_SYNC) == 0)
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " D-STAR ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -D-STAR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 7;
return (7);
}
}
if ((t == 24) && (state->lastsynctype != -1))
{
if ((state->lastsynctype == 0) && ((state->lastp25type == 1) || (state->lastp25type == 2)))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + (lmax)) / 2;
state->min = ((state->min) + (lmin)) / 2;
sprintf (state->ftype, "(P25 Phase 1)");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(+p25p1) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
return (0);
}
else if ((state->lastsynctype == 1) && ((state->lastp25type == 1) || (state->lastp25type == 2)))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(P25 Phase 1)");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(-p25p1) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
return (1);
}
else if ((state->lastsynctype == 3) && (strcmp (synctest, X2TDMA_VOICE_SYNC) != 0))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(X2-TDMA) ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(-X2-TDMA) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
return (3);
}
else if ((state->lastsynctype == 4) && (strcmp (synctest, X2TDMA_DATA_SYNC) != 0))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(X2-TDMA) ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(+X2-TDMA) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
return (4);
}
else if ((state->lastsynctype == 11) && (strcmp (synctest, DMR_VOICE_SYNC) != 0))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(-DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
return (11);
}
else if ((state->lastsynctype == 12) && (strcmp (synctest, DMR_DATA_SYNC) != 0))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, "(DMR) ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, "(+DMR) ", synctest_pos + 1, modulation);
}
state->lastsynctype = -1;
return (12);
}
}
}
if (synctest_pos < 10200)
{
synctest_pos++;
synctest_p++;
}
else
{
// buffer reset
synctest_pos = 0;
synctest_p = synctest_buf;
noCarrier (opts, state);
}
if (state->carrier == 1)
{
if (synctest_pos >= 1800)
{
if (opts->errorbars == 1)
{
if (opts->verbose > 1)
{
printf ("Sync: no sync\n");
}
}
noCarrier (opts, state);
return (-1);
}
}
}
return (-1);
}

635
dsd_main.c Normal file
View File

@@ -0,0 +1,635 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#define _MAIN
#include "dsd.h"
#include "p25p1_const.h"
#include "x2tdma_const.h"
#include "dstar_const.h"
#include "nxdn96_const.h"
#include "dmr_const.h"
#include "provoice_const.h"
int
comp (const void *a, const void *b)
{
if (*((const int *) a) == *((const int *) b))
return 0;
else if (*((const int *) a) < *((const int *) b))
return -1;
else
return 1;
}
void
noCarrier (dsd_opts * opts, dsd_state * state)
{
state->dibit_buf_p = state->dibit_buf + 200;
memset (state->dibit_buf, 0, sizeof (int) * 200);
if (opts->mbe_out_f != NULL)
{
closeMbeOutFile (opts, state);
}
state->jitter = -1;
state->lastsynctype = -1;
state->carrier = 0;
state->max = 15000;
state->min = -15000;
state->center = 0;
state->err_str[0] = 0;
sprintf (state->fsubtype, " ");
sprintf (state->ftype, " ");
state->lasttg = 0;
state->lastsrc = 0;
state->lastp25type = 0;
state->repeat = 0;
state->nac = 0;
state->numtdulc = 0;
sprintf (state->slot0light, " slot0 ");
sprintf (state->slot1light, " slot1 ");
state->firstframe = 0;
if (opts->audio_gain == (float) 0)
{
state->aout_gain = 25;
}
memset (state->aout_max_buf, 0, sizeof (float) * 200);
state->aout_max_buf_p = state->aout_max_buf;
state->aout_max_buf_idx = 0;
sprintf (state->algid, "________");
sprintf (state->keyid, "________________");
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
}
void
initOpts (dsd_opts * opts)
{
opts->onesymbol = 10;
opts->mbe_in_file[0] = 0;
opts->mbe_in_f = NULL;
opts->errorbars = 1;
opts->datascope = 0;
opts->symboltiming = 0;
opts->verbose = 2;
opts->p25enc = 0;
opts->p25lc = 0;
opts->p25status = 0;
opts->p25tg = 0;
opts->scoperate = 15;
sprintf (opts->audio_in_dev, "/dev/audio");
opts->audio_in_fd = -1;
sprintf (opts->audio_out_dev, "/dev/audio");
opts->audio_out_fd = -1;
opts->split = 0;
opts->playoffset = 0;
opts->mbe_out_dir[0] = 0;
opts->mbe_out_file[0] = 0;
opts->mbe_out_f = NULL;
opts->audio_gain = 0;
opts->audio_out = 1;
opts->wav_out_file[0] = 0;
opts->wav_out_f = NULL;
opts->wav_out_fd = -1;
opts->serial_baud = 115200;
sprintf (opts->serial_dev, "/dev/ttyUSB0");
opts->resume = 0;
opts->frame_dstar = 0;
opts->frame_x2tdma = 1;
opts->frame_p25p1 = 1;
opts->frame_nxdn = 0;
opts->frame_dmr = 1;
opts->frame_provoice = 0;
opts->mod_c4fm = 1;
opts->mod_qpsk = 1;
opts->mod_gfsk = 1;
opts->uvquality = 3;
opts->inverted_x2tdma = 1; // most transmitter + scanner + sound card combinations show inverted signals for this
opts->inverted_dmr = 0; // most transmitter + scanner + sound card combinations show non-inverted signals for this
opts->mod_threshold = 26;
opts->ssize = 36;
opts->msize = 15;
opts->playfiles = 0;
opts->delay = 0;
}
void
initState (dsd_state * state)
{
int i, j;
state->dibit_buf = malloc (sizeof (int) * 1000000);
state->dibit_buf_p = state->dibit_buf + 200;
memset (state->dibit_buf, 0, sizeof (int) * 200);
state->repeat = 0;
state->audio_out_buf = malloc (sizeof (short) * 1000000);
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_buf_p = state->audio_out_buf + 100;
state->audio_out_float_buf = malloc (sizeof (float) * 1000000);
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_idx = 0;
state->audio_out_idx2 = 0;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
state->center = 0;
state->jitter = -1;
state->synctype = -1;
state->min = -15000;
state->max = 15000;
state->lmid = 0;
state->umid = 0;
state->minref = -12000;
state->maxref = 12000;
state->lastsample = 0;
for (i = 0; i < 128; i++)
{
state->sbuf[i] = 0;
}
state->sidx = 0;
for (i = 0; i < 1024; i++)
{
state->maxbuf[i] = 15000;
}
for (i = 0; i < 1024; i++)
{
state->minbuf[i] = -15000;
}
state->midx = 0;
state->err_str[0] = 0;
sprintf (state->fsubtype, " ");
sprintf (state->ftype, " ");
state->symbolcnt = 0;
state->rf_mod = 0;
state->numflips = 0;
state->lastsynctype = -1;
state->lastp25type = 0;
state->offset = 0;
state->carrier = 0;
for (j = 0; i < 25; j++)
{
for (i = 0; j < 16; i++)
{
state->tg[i][j] = 0;
}
}
state->tgcount = 0;
state->lasttg = 0;
state->lastsrc = 0;
state->nac = 0;
state->errs = 0;
state->errs2 = 0;
state->mbe_file_type = -1;
state->optind = 0;
state->numtdulc = 0;
state->firstframe = 0;
sprintf (state->slot0light, " slot0 ");
sprintf (state->slot1light, " slot1 ");
state->aout_gain = 25;
memset (state->aout_max_buf, 0, sizeof (float) * 200);
state->aout_max_buf_p = state->aout_max_buf;
state->aout_max_buf_idx = 0;
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
sprintf (state->algid, "________");
sprintf (state->keyid, "________________");
state->currentslot = 0;
state->cur_mp = malloc (sizeof (mbe_parms));
state->prev_mp = malloc (sizeof (mbe_parms));
state->prev_mp_enhanced = malloc (sizeof (mbe_parms));
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
}
void
usage ()
{
printf ("Digital Speech Decoder 1.3\n");
printf ("\n");
printf ("Usage:\n");
printf (" dsd [options] Live scanner mode\n");
printf (" dsd [options] -r <files> Read/Play saved mbe data from file(s)\n");
printf (" dsd -h Show help\n");
printf ("\n");
printf ("Display Options:\n");
printf (" -e Show Frame Info and errorbars (default)\n");
printf (" -pe Show p25 encryption sync bits\n");
printf (" -pl Show p25 link control bits\n");
printf (" -ps Show p25 status bits and low speed data\n");
printf (" -pt Show p25 talkgroup info\n");
printf (" -q Don't show Frame Info/errorbars\n");
printf (" -s Datascope (disables other display options)\n");
printf (" -t Show symbol timing during sync\n");
printf (" -v <num> Frame information Verbosity\n");
printf (" -z <num> Frame rate for datascope\n");
printf ("\n");
printf ("Input/Output options:\n");
printf (" -i <device> Audio input device (default is /dev/audio)\n");
printf (" -o <device> Audio output device (default is /dev/audio)\n");
printf (" -d <dir> Create mbe data files, use this directory\n");
printf (" -g <num> Audio output gain (default = 0 = auto)\n");
printf (" -n Do not send synthesized speech to audio output device\n");
printf (" -w <file> Output synthesized speech to a .wav file\n");
printf ("\n");
printf ("Scanner control options:\n");
printf (" -B <num> Serial port baud rate (default=115200)\n");
printf (" -C <device> Serial port for scanner control (default=/dev/ttyUSB0)\n");
printf (" -R <num> Resume scan after <num> TDULC frames or any PDU\n");
printf ("\n");
printf ("Decoder options:\n");
printf (" -fa Auto-detect frame type (default)\n");
printf (" -f1 Decode only P25 Phase 1\n");
printf (" -fd Decode only D-STAR* (no audio)\n");
printf (" -fn Decode only NXDN96* (no audio)\n");
printf (" -fp Decode only ProVoice*\n");
printf (" -fr Decode only DMR/MOTOTRBO\n");
printf (" -fx Decode only X2-TDMA\n");
printf (" -ma Auto-select modulation optimizations (default)\n");
printf (" -mc Use only C4FM modulation optimizations\n");
printf (" -mg Use only GFSK modulation optimizations\n");
printf (" -mq Use only QPSK modulation optimizations\n");
printf (" -u <num> Unvoiced speech quality (default=3)\n");
printf (" -xx Expect non-inverted X2-TDMA signal\n");
printf (" -xr Expect inverted DMR/MOTOTRBO signal\n");
printf ("\n");
printf (" * denotes frame types that cannot be auto-detected.\n");
printf ("\n");
printf ("Advanced decoder options:\n");
printf (" -A <num> QPSK modulation auto detection threshold (default=26)\n");
printf (" -S <num> Symbol buffer size for QPSK decision point tracking\n");
printf (" (default=36)\n");
printf (" -M <num> Min/Max buffer size for QPSK decision point tracking\n");
printf (" (default=15)\n");
exit (0);
}
void
liveScanner (dsd_opts * opts, dsd_state * state)
{
while (1)
{
noCarrier (opts, state);
state->synctype = getFrameSync (opts, state);
// recalibrate center/umid/lmid
state->center = ((state->max) + (state->min)) / 2;
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
while (state->synctype != -1)
{
processFrame (opts, state);
state->synctype = getFrameSync (opts, state);
// recalibrate center/umid/lmid
state->center = ((state->max) + (state->min)) / 2;
state->umid = (((state->max) - state->center) * 5 / 8) + state->center;
state->lmid = (((state->min) - state->center) * 5 / 8) + state->center;
}
}
}
int
main (int argc, char **argv)
{
int c;
extern char *optarg;
extern int optind, opterr, optopt;
dsd_opts opts;
dsd_state state;
initOpts (&opts);
initState (&state);
while ((c = getopt (argc, argv, "hep:qstv:z:i:o:d:g:nw:B:C:R:f:m:u:x:A:S:M:r")) != -1)
{
opterr = 0;
switch (c)
{
case 'h':
usage ();
exit (0);
case 'e':
opts.errorbars = 1;
opts.datascope = 0;
break;
case 'p':
if (optarg[0] == 'e')
{
opts.p25enc = 1;
}
else if (optarg[0] == 'l')
{
opts.p25lc = 1;
}
else if (optarg[0] == 's')
{
opts.p25status = 1;
}
else if (optarg[0] == 't')
{
opts.p25tg = 1;
}
break;
case 'q':
opts.errorbars = 0;
opts.verbose = 0;
break;
case 's':
opts.errorbars = 0;
opts.p25enc = 0;
opts.p25lc = 0;
opts.p25status = 0;
opts.p25tg = 0;
opts.datascope = 1;
opts.symboltiming = 0;
break;
case 't':
opts.symboltiming = 1;
opts.errorbars = 1;
opts.datascope = 0;
break;
case 'v':
sscanf (optarg, "%d", &opts.verbose);
break;
case 'z':
sscanf (optarg, "%d", &opts.scoperate);
opts.errorbars = 0;
opts.p25enc = 0;
opts.p25lc = 0;
opts.p25status = 0;
opts.p25tg = 0;
opts.datascope = 1;
opts.symboltiming = 0;
printf ("Setting datascope frame rate to %i frame per second.\n", opts.scoperate);
break;
case 'i':
sscanf (optarg, "%s", opts.audio_in_dev);
break;
case 'o':
sscanf (optarg, "%s", opts.audio_out_dev);
break;
case 'd':
sscanf (optarg, "%s", opts.mbe_out_dir);
printf ("Writing mbe data files to directory %s\n", opts.mbe_out_dir);
break;
case 'g':
sscanf (optarg, "%f", &opts.audio_gain);
if (opts.audio_gain <= (float) 0)
{
opts.audio_gain = (float) 0;
printf ("Enabling audio out auto-gain\n");
}
else
{
printf ("Setting audio out gain to %f\n", opts.audio_gain);
state.aout_gain = opts.audio_gain;
}
break;
case 'n':
opts.audio_out = 0;
printf ("Disabling audio output to soundcard.\n");
break;
case 'w':
sscanf (optarg, "%s", opts.wav_out_file);
printf ("Writing audio to file %s\n", opts.wav_out_file);
openWavOutFile (&opts, &state);
break;
case 'B':
sscanf (optarg, "%d", &opts.serial_baud);
break;
case 'C':
sscanf (optarg, "%s", opts.serial_dev);
break;
case 'R':
sscanf (optarg, "%d", &opts.resume);
printf ("Enabling scan resume after %i TDULC frames\n", opts.resume);
break;
case 'f':
if (optarg[0] == 'a')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 1;
opts.frame_p25p1 = 1;
opts.frame_nxdn = 0;
opts.frame_dmr = 1;
opts.frame_provoice = 0;
}
else if (optarg[0] == 'd')
{
opts.frame_dstar = 1;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
printf ("Decoding only D-STAR frames.\n");
}
else if (optarg[0] == 'x')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 1;
opts.frame_p25p1 = 0;
opts.frame_nxdn = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
printf ("Decoding only X2-TDMA frames.\n");
}
else if (optarg[0] == 'p')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 1;
state.samplesPerSymbol = 5;
state.symbolCenter = 2;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
printf ("Enabling only GFSK modulation optimizations.\n");
printf ("Decoding only ProVoice frames.\n");
}
else if (optarg[0] == '1')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 1;
opts.frame_nxdn = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
printf ("Decoding only P25 Phase 1 frames.\n");
}
else if (optarg[0] == 'n')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn = 1;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
printf ("Decoding only NXDN 9600 baud frames.\n");
}
else if (optarg[0] == 'r')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn = 0;
opts.frame_dmr = 1;
opts.frame_provoice = 0;
printf ("Decoding only DMR/MOTOTRBO frames.\n");
}
break;
case 'm':
if (optarg[0] == 'a')
{
opts.mod_c4fm = 1;
opts.mod_qpsk = 1;
opts.mod_gfsk = 1;
state.rf_mod = 0;
}
else if (optarg[0] == 'c')
{
opts.mod_c4fm = 1;
opts.mod_qpsk = 0;
opts.mod_gfsk = 0;
state.rf_mod = 0;
printf ("Enabling only C4FM modulation optimizations.\n");
}
else if (optarg[0] == 'g')
{
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
printf ("Enabling only GFSK modulation optimizations.\n");
}
else if (optarg[0] == 'q')
{
opts.mod_c4fm = 0;
opts.mod_qpsk = 1;
opts.mod_gfsk = 0;
state.rf_mod = 1;
printf ("Enabling only QPSK modulation optimizations.\n");
}
break;
case 'u':
sscanf (optarg, "%i", &opts.uvquality);
if (opts.uvquality < 1)
{
opts.uvquality = 1;
}
else if (opts.uvquality > 64)
{
opts.uvquality = 64;
}
printf ("Setting unvoice speech quality to %i waves per band.\n", opts.uvquality);
break;
case 'x':
if (optarg[0] == 'x')
{
opts.inverted_x2tdma = 0;
printf ("Expecting non-inverted X2-TDMA signals.\n");
}
else if (optarg[0] == 'r')
{
opts.inverted_dmr = 1;
printf ("Expecting inverted DMR/MOTOTRBO signals.\n");
}
break;
case 'A':
sscanf (optarg, "%i", &opts.mod_threshold);
printf ("Setting C4FM/QPSK auto detection threshold to %i\n", opts.mod_threshold);
break;
case 'S':
sscanf (optarg, "%i", &opts.ssize);
if (opts.ssize > 128)
{
opts.ssize = 128;
}
else if (opts.ssize < 1)
{
opts.ssize = 1;
}
printf ("Setting QPSK symbol buffer to %i\n", opts.ssize);
break;
case 'M':
sscanf (optarg, "%i", &opts.msize);
if (opts.msize > 1024)
{
opts.msize = 1024;
}
else if (opts.msize < 1)
{
opts.msize = 1;
}
printf ("Setting QPSK Min/Max buffer to %i\n", opts.msize);
break;
case 'r':
opts.playfiles = 1;
opts.errorbars = 0;
opts.datascope = 0;
state.optind = optind;
break;
default:
usage ();
exit (0);
}
}
if (opts.resume > 0)
{
openSerial (&opts, &state);
}
if (opts.playfiles == 1)
{
opts.split = 1;
opts.playoffset = 0;
opts.delay = 0;
openAudioOutDevice (&opts, 8000);
}
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
{
opts.split = 1;
opts.playoffset = 0;
opts.delay = 0;
openAudioOutDevice (&opts, 8000);
openAudioInDevice (&opts);
}
else
{
opts.split = 0;
opts.playoffset = 38;
opts.delay = 0;
openAudioInDevice (&opts);
opts.audio_out_fd = opts.audio_in_fd;
}
if (opts.playfiles == 1)
{
playMbeFiles (&opts, &state, argc, argv);
}
else
{
liveScanner (&opts, &state);
}
return (0);
}

122
dsd_mbe.c Normal file
View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
{
int i;
char imbe_d[88];
char ambe_d[49];
for (i = state->optind; i < argc; i++)
{
sprintf (opts->mbe_in_file, argv[i]);
openMbeInFile (opts, state);
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
printf ("playing %s\n", opts->mbe_in_file);
while (feof (opts->mbe_in_f) == 0)
{
if (state->mbe_file_type == 0)
{
readImbe4400Data (opts, state, imbe_d);
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
processAudio (opts, state);
if (opts->wav_out_fd != -1)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}
else if (state->mbe_file_type == 1)
{
readAmbe2250Data (opts, state, ambe_d);
mbe_processAmbe2250Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
processAudio (opts, state);
if (opts->wav_out_fd != -1)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}
}
}
}
void
processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24])
{
int i;
char imbe_d[88];
char ambe_d[49];
for (i = 0; i < 88; i++)
{
imbe_d[i] = 0;
}
if ((state->synctype == 0) || (state->synctype == 1))
{
mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
if (opts->mbe_out_f != NULL)
{
saveImbe4400Data (opts, state, imbe_d);
}
}
else if ((state->synctype == 14) || (state->synctype == 15))
{
mbe_processImbe7100x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe7100_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
if (opts->mbe_out_f != NULL)
{
saveImbe4400Data (opts, state, imbe_d);
}
}
else
{
mbe_processAmbe3600x2250Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
if (opts->mbe_out_f != NULL)
{
saveAmbe2250Data (opts, state, ambe_d);
}
}
if (opts->errorbars == 1)
{
printf ("%s", state->err_str);
}
processAudio (opts, state);
if (opts->wav_out_fd != -1)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}

88
dsd_serial.c Normal file
View File

@@ -0,0 +1,88 @@
#include <termios.h>
#include "dsd.h"
void
openSerial (dsd_opts * opts, dsd_state * state)
{
struct termios tty;
speed_t baud;
printf ("Opening serial port %s and setting baud to %i\n", opts->serial_dev, opts->serial_baud);
opts->serial_fd = open (opts->serial_dev, O_WRONLY);
if (opts->serial_fd == -1)
{
printf ("Error, couldn't open %s\n", opts->serial_dev);
exit (1);
}
tty.c_cflag = 0;
switch (opts->serial_baud)
{
case 1200:
baud = B1200;
case 2400:
baud = B2400;
case 4800:
baud = B4800;
case 9600:
baud = B9600;
break;
case 19200:
baud = B19200;
break;
case 38400:
baud = B38400;
break;
case 57600:
baud = B57600;
break;
case 115200:
baud = B115200;
break;
case 230400:
baud = B230400;
break;
}
if (opts->serial_baud > 0)
{
cfsetospeed (&tty, baud);
cfsetispeed (&tty, baud);
}
tty.c_cflag |= (tty.c_cflag & ~CSIZE) | CS8;
tty.c_iflag = IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cflag &= ~CRTSCTS;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag &= ~CSTOPB;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 5;
tcsetattr (opts->serial_fd, TCSANOW, &tty);
}
void
resumeScan (dsd_opts * opts, dsd_state * state)
{
char cmd[7];
if (opts->serial_fd > 0)
{
sprintf (cmd, "\rKEY00\r");
write (opts->serial_fd, cmd, 7);
cmd[0] = 2;
cmd[1] = 75;
cmd[2] = 15;
cmd[3] = 3;
cmd[4] = 93;
cmd[5] = 0;
write (opts->serial_fd, cmd, 5);
state->numtdulc = 0;
}
}

180
dsd_symbol.c Normal file
View File

@@ -0,0 +1,180 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
int
getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
{
short sample;
int i, sum, symbol, count;
sum = 0;
count = 0;
for (i = 0; i < state->samplesPerSymbol; i++)
{
// timing control
if ((i == 0) && (have_sync == 0))
{
if (state->rf_mod == 1)
{
if ((state->jitter >= 0) && (state->jitter < state->symbolCenter))
{
i++; // fall back
}
else if ((state->jitter > state->symbolCenter) && (state->jitter < 10))
{
i--; // catch up
}
}
else if (state->rf_mod == 2)
{
if ((state->jitter >= state->symbolCenter - 1) && (state->jitter <= state->symbolCenter))
{
i--;
}
else if ((state->jitter >= state->symbolCenter + 1) && (state->jitter <= state->symbolCenter + 2))
{
i++;
}
}
else if (state->rf_mod == 0)
{
if ((state->jitter > 0) && (state->jitter <= state->symbolCenter))
{
i--; // catch up
}
else if ((state->jitter > state->symbolCenter) && (state->jitter < state->samplesPerSymbol))
{
i++; // fall back
}
}
state->jitter = -1;
}
read (opts->audio_in_fd, &sample, 2);
if ((sample > state->max) && (have_sync == 1) && (state->rf_mod == 0))
{
sample = state->max;
}
else if ((sample < state->min) && (have_sync == 1) && (state->rf_mod == 0))
{
sample = state->min;
}
if (sample > state->center)
{
if (state->lastsample < state->center)
{
state->numflips += 1;
}
if (sample > (state->maxref * 1.25))
{
if (state->lastsample < (state->maxref * 1.25))
{
state->numflips += 1;
}
if ((state->jitter < 0) && (state->rf_mod == 1))
{ // first spike out of place
state->jitter = i;
}
if ((opts->symboltiming == 1) && (have_sync == 0) && (state->lastsynctype != -1))
{
printf ("O");
}
}
else
{
if ((opts->symboltiming == 1) && (have_sync == 0) && (state->lastsynctype != -1))
{
printf ("+");
}
if ((state->jitter < 0) && (state->lastsample < state->center) && (state->rf_mod != 1))
{ // first transition edge
state->jitter = i;
}
}
}
else
{ // sample < 0
if (state->lastsample > state->center)
{
state->numflips += 1;
}
if (sample < (state->minref * 1.25))
{
if (state->lastsample > (state->minref * 1.25))
{
state->numflips += 1;
}
if ((state->jitter < 0) && (state->rf_mod == 1))
{ // first spike out of place
state->jitter = i;
}
if ((opts->symboltiming == 1) && (have_sync == 0) && (state->lastsynctype != -1))
{
printf ("X");
}
}
else
{
if ((opts->symboltiming == 1) && (have_sync == 0) && (state->lastsynctype != -1))
{
printf ("-");
}
if ((state->jitter < 0) && (state->lastsample > state->center) && (state->rf_mod != 1))
{ // first transition edge
state->jitter = i;
}
}
}
if (state->samplesPerSymbol == 5)
{
if ((i >= 2) && (i <= 2))
{
sum += sample;
count++;
}
}
else
{
if (((i >= state->symbolCenter - 1) && (i <= state->symbolCenter + 2) && (state->rf_mod == 0)) || (((i == state->symbolCenter) || (i == state->symbolCenter + 1)) && (state->rf_mod != 0)))
{
sum += sample;
count++;
}
}
state->lastsample = sample;
}
symbol = (sum / count);
if ((opts->symboltiming == 1) && (have_sync == 0) && (state->lastsynctype != -1))
{
if (state->jitter >= 0)
{
printf (" %i\n", state->jitter);
}
else
{
printf ("\n");
}
}
state->symbolcnt++;
return (symbol);
}

171
dsd_upsample.c Normal file
View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
upsample (dsd_state * state, float invalue)
{
int i, j, sum;
float *outbuf1, a, b, c, d;
float phasestart, phaseend, resamplestart, resampleend, phasestep, resampleamp2;
float resamplemin, resamplemax;
if (state->audio_out_idx2 > 23)
{
outbuf1 = state->audio_out_float_buf_p;
outbuf1--;
c = *outbuf1;
outbuf1 -= 6;
b = *outbuf1;
outbuf1 -= 6;
a = *outbuf1;
d = (invalue);
resamplemin = 32767;
resamplemax = -32768;
if (a < resamplemin)
{
resamplemin = a;
}
if (a > resamplemax)
{
resamplemax = a;
}
if (b < resamplemin)
{
resamplemin = b;
}
if (b > resamplemax)
{
resamplemax = b;
}
if (c < resamplemin)
{
resamplemin = c;
}
if (c > resamplemax)
{
resamplemax = c;
}
if (d < resamplemin)
{
resamplemin = d;
}
if (d > resamplemax)
{
resamplemax = d;
}
resampleamp2 = ((float) resamplemax - (float) resamplemin) / (float) 2;
#ifdef UPSAMPLE_DEBUG
printf ("a:%f b:%f c:%f d:%f resamplemin:%f resamplemax:%f resampleamp2:%f\n", a, b, c, d, resamplemin, resamplemax, resampleamp2);
#endif
if (resampleamp2 == 0)
{
resamplestart = (float) 0;
resampleend = (float) 0;
}
else
{
resamplestart = (((float) b - (float) resamplemin) / resampleamp2) - (float) 1.0;
resampleend = (((float) c - (float) resamplemin) / resampleamp2) - (float) 1.0;
}
if (resamplestart < -1)
{
resamplestart = (float) -1;
}
else if (resamplestart > (float) 1)
{
resamplestart = (float) 1;
}
if (resampleend < -1)
{
resampleend = (float) -1;
}
else if (resampleend > (float) 1)
{
resampleend = (float) 1;
}
phasestart = asinf (resamplestart);
phaseend = asinf (resampleend);
phasestep = (phaseend - phasestart) / 6;
#ifdef UPSAMPLE_DEBUG
printf ("resamplestart:%f, resampleend:%f, phasestart:%f, phaseend:%f, phasestep:%f\n", resamplestart, resampleend, phasestart, phaseend, phasestep);
#endif
// rewrite samples between b and c
outbuf1 = state->audio_out_float_buf_p;
outbuf1 -= 6;
for (i = 1; i < 6; i++)
{
*outbuf1 = (resamplemin + resampleamp2 + (resampleamp2 * sin (phasestart + (phasestep * (float) i))));
#ifdef UPSAMPLE_DEBUG
printf ("audio_out_idx2:%i outbuf:%f\n", state->audio_out_idx2, *outbuf1);
#endif
outbuf1++;
}
#ifdef UPSAMPLE_DEBUG
printf ("(c):%f\n", *outbuf1);
#endif
// write d
outbuf1 += 6;
*outbuf1 = d;
#ifdef UPSAMPLE_DEBUG
printf ("audio_out_idx2:%i outbuf(d):%f\n", state->audio_out_idx2, *outbuf1);
#endif
outbuf1++;
// smooth
outbuf1 -= 36;
for (j = 0; j < 12; j++)
{
for (i = 0; i < 12; i++)
{
sum = 0;
outbuf1--;
sum += *outbuf1;
outbuf1++;
sum += *outbuf1;
outbuf1++;
sum += *outbuf1;
outbuf1--;
*outbuf1 = (sum / (float) 3);
outbuf1++;
}
outbuf1 -= 11;
}
}
else
{
outbuf1 = state->audio_out_float_buf_p;
outbuf1--;
c = *outbuf1;
*outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166));
outbuf1++;
*outbuf1 = invalue;
}
}

79
dstar.c Normal file
View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Note: D-STAR support is very incomplete and does not work yet
* It is unknown if the ambe3600x2250 decoder is even compatible with D-STAR
* voice frames. If it is then the interleave pattern needs to be determined.
* GMSK modulation optimizations will also required to get a usable bit error
* rate. This was included mainly as an example of how other systmes might
* be supported.
*/
#include "dsd.h"
#include "dstar_const.h"
void
processDSTAR (dsd_opts * opts, dsd_state * state)
{
// extracts AMBE frames from D-STAR voice frame
int i, j, dibit;
char ambe_fr[4][24];
char dstar[300];
const int *w, *x;
if (opts->errorbars == 1)
{
printf ("e:");
}
#ifdef DSTAR_DUMP
printf ("\n");
#endif
for (j = 0; j < 210; j++) // 210 is very long but used for debugging
{
// voice frame
w = dW;
x = dX;
for (i = 0; i < 72; i++)
{
dibit = getDibit (opts, state);
dstar[i] = dibit + 48;
ambe_fr[*w][*x] = (1 & dibit);
w++;
x++;
}
dstar[i] = 32;
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
// data frame
for (i = 73; i < 97; i++)
{
dstar[i] = getDibit (opts, state) + 48;
}
dstar[i] = 0;
#ifdef DSTAR_DUMP
printf ("%s\n", dstar);
#endif
}
if (opts->errorbars == 1)
{
printf ("\n");
}
}

311
dstar_const.h Normal file
View File

@@ -0,0 +1,311 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* dstar interleave experiments
*/
#ifndef _MAIN
extern const int dW[72];
extern const int dX[72];
#else
/*
* 4x18
*/
/*
const int dW[72] = {
0,0,1,2,
0,0,1,2,
0,0,1,2,
0,0,1,2,
0,0,1,3,
0,0,1,3,
0,1,1,3,
0,1,1,3,
0,1,1,3,
0,1,1,3,
0,1,1,3,
0,1,2,3,
0,1,2,3,
0,1,2,3,
0,1,2,3,
0,1,2,3,
0,1,2,3,
0,1,2,3
};
const int dX[72] = {
23,5,10,3,
22,4,9,2,
21,3,8,1,
20,2,7,0,
19,1,6,13,
18,0,5,12,
17,22,4,11,
16,21,3,10,
15,20,2,9,
14,19,1,8,
13,18,0,7,
12,17,10,6,
11,16,9,5,
10,15,8,4,
9,14,7,3,
8,13,6,2,
7,12,5,1,
6,11,4,0
};
*/
/*
* 3x24 alt
*/
const int dW[72] = {
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 3,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
1, 0, 2,
0, 3, 2,
};
const int dX[72] = {
22, 22, 12,
21, 21, 11,
20, 20, 10,
19, 19, 9,
18, 18, 8,
17, 17, 7,
16, 16, 6,
15, 15, 5,
14, 14, 4,
13, 13, 3,
12, 12, 2,
11, 11, 1,
10, 10, 0,
9, 9, 10,
8, 8, 9,
7, 7, 8,
6, 6, 7,
5, 5, 6,
4, 4, 5,
3, 3, 4,
2, 2, 3,
1, 1, 2,
0, 0, 1,
23, 13, 0
};
/*
* 3x24
*/
/*
const int dW[72] = {
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,2,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,1,3,
0,2,3,
};
const int dX[72] = {
23,22,9,
22,21,8,
21,20,7,
20,19,6,
19,18,5,
18,17,4,
17,16,3,
16,15,2,
15,14,1,
14,13,0,
13,12,13,
12,11,12,
11,10,11,
10,9,10,
9,8,9,
8,7,8,
7,6,7,
6,5,6,
5,4,5,
4,3,4,
3,2,3,
2,1,2,
1,0,1,
0,10,0
};
*/
/*
* 2x36
*/
/*
const int dW[72] = {
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,1,
0,2,
0,2,
0,2,
0,2,
0,2,
0,2,
0,2,
0,2,
0,2,
0,2,
0,2,
0,3,
0,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3,
1,3
};
const int dX[72] = {
23,10,
22,9,
21,8,
20,7,
19,6,
18,5,
17,4,
16,3,
15,2,
14,1,
13,0,
12,10,
11,9,
10,8,
9,7,
8,6,
7,5,
6,4,
5,3,
4,2,
3,1,
2,0,
1,13,
0,12,
22,11,
21,10,
20,9,
19,8,
18,7,
17,6,
16,5,
15,4,
14,3,
13,2,
12,1,
11,0
};
*/
/*
* non-interleaved
*/
/*
const int dW[72] = {
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
1,1,1,1,1,1,
1,1,1,1,1,1,
1,1,1,1,1,1,
1,1,1,1,1,2,
2,2,2,2,2,2,
2,2,2,2,3,3,
3,3,3,3,3,3,
3,3,3,3,3,3
};
const int dX[72] = {
23,22,21,20,19,18,
17,16,15,14,13,12,
11,10,9,8,7,6,
5,4,3,2,1,0,
22,21,20,19,18,17,
16,15,14,13,12,11,
10,9,8,7,6,5,
4,3,2,1,0,10,
9,8,7,6,5,4,
3,2,1,0,13,12,
11,10,9,8,7,6,
5,4,3,2,1,0
};
*/
#endif

124
nxdn96.c Normal file
View File

@@ -0,0 +1,124 @@
#include "dsd.h"
#include "nxdn96_const.h"
void
processNXDN96 (dsd_opts * opts, dsd_state * state)
{
int i, j, k, dibit;
char ambe_fr[4][24];
const int *w, *x, *y, *z;
if (opts->errorbars == 1)
{
printf ("VOICE e:");
}
#ifdef NXDN_DUMP
printf ("\n");
#endif
for (k = 0; k < 4; k++)
{
for (i = 0; i < 222; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
}
#ifdef NXDN_DUMP
printf (" ");
#endif
if (k < 3)
{
for (j = 0; j < 4; j++)
{
w = nW;
x = nX;
y = nY;
z = nZ;
for (i = 0; i < 36; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
#ifdef NXDN_DUMP
printf (" ");
#endif
}
}
else
{
for (j = 0; j < 3; j++) // we skip the last voice frame until frame sync can work with < 24 symbols
{
w = nW;
x = nX;
y = nY;
z = nZ;
for (i = 0; i < 36; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
#ifdef NXDN_DUMP
printf (" ");
#endif
}
}
if (k < 3)
{
for (i = 0; i < 18; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
}
#ifdef NXDN_DUMP
printf (" ");
#endif
}
else
{
for (i = 0; i < 30; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
}
}
}
#ifdef NXDN_DUMP
printf ("\n");
#endif
if (opts->errorbars == 1)
{
printf ("\n");
}
}

62
nxdn96_const.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* NXDN AMBE interleave schedule
*/
#ifndef _MAIN
extern const int nW[36];
extern const int nX[36];
extern const int nY[36];
extern const int nZ[36];
#else
const int nW[36] = { 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 2,
0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2
};
const int nX[36] = { 23, 10, 22, 9, 21, 8,
20, 7, 19, 6, 18, 5,
17, 4, 16, 3, 15, 2,
14, 1, 13, 0, 12, 10,
11, 9, 10, 8, 9, 7,
8, 6, 7, 5, 6, 4
};
const int nY[36] = { 0, 2, 0, 2, 0, 2,
0, 2, 0, 3, 0, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3
};
const int nZ[36] = { 5, 3, 4, 2, 3, 1,
2, 0, 1, 13, 0, 12,
22, 11, 21, 10, 20, 9,
19, 8, 18, 7, 17, 6,
16, 5, 15, 4, 14, 3,
13, 2, 12, 1, 11, 0
};
#endif

162
p25_lcw.c Normal file
View File

@@ -0,0 +1,162 @@
#include "dsd.h"
void
processP25lcw (dsd_opts * opts, dsd_state * state, char *lcformat, char *mfid, char *lcinfo)
{
char tgid[17], tmpstr[255];
long talkgroup, source;
int i, j;
tgid[16] = 0;
if (opts->p25lc == 1)
{
printf ("lcformat: %s mfid: %s lcinfo: %s ", lcformat, mfid, lcinfo);
if (opts->p25tg == 0)
{
printf ("\n");
}
}
if (strcmp (lcformat, "00000100") == 0)
{
// first tg is the active channel
if (state->tgcount < 24)
{
// update tg buffer
j = 0;
for (i = 40; i < 52; i++)
{
state->tg[state->tgcount][j] = lcinfo[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
tmpstr[16] = 0;
state->tgcount = state->tgcount + 1;
}
// first one again for tg display
j = 0;
for (i = 40; i < 52; i++)
{
tmpstr[j] = lcinfo[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
tmpstr[16] = 0;
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
state->lasttg = talkgroup;
if (opts->p25tg == 1)
{
printf ("tg: %li ", talkgroup);
// the remaining 3 appear to be other active tg's on the system
j = 0;
for (i = 28; i < 40; i++)
{
tmpstr[j] = lcinfo[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
printf ("%li ", talkgroup);
j = 0;
for (i = 16; i < 28; i++)
{
tmpstr[j] = lcinfo[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
printf ("%li ", talkgroup);
j = 0;
for (i = 4; i < 16; i++)
{
tmpstr[j] = lcinfo[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
printf ("%li\n", talkgroup);
}
}
else if (strcmp (lcformat, "00000000") == 0)
{
j = 0;
if (strcmp (mfid, "10010000") == 0)
{
for (i = 20; i < 32; i++)
{
if (state->tgcount < 24)
{
state->tg[state->tgcount][j] = lcinfo[i];
}
tmpstr[j] = lcinfo[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
}
else
{
for (i = 16; i < 32; i++)
{
if (state->tgcount < 24)
{
state->tg[state->tgcount][j] = lcinfo[i];
}
tmpstr[j] = lcinfo[i];
j++;
}
}
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
state->lasttg = talkgroup;
if (opts->p25tg == 1)
{
printf ("tg: %li ", talkgroup);
}
j = 0;
for (i = 32; i < 56; i++)
{
tmpstr[j] = lcinfo[i];
j++;
}
tmpstr[24] = 0;
source = strtol (tmpstr, NULL, 2);
state->lastsrc = source;
if (opts->p25tg == 1)
{
printf ("src: %li emr: %c\n", source, lcinfo[0]);
}
}
else if ((opts->p25tg == 1) && (opts->p25lc == 1))
{
printf ("\n");
}
}

89
p25p1_const.h Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MAIN
extern const int iW[72];
extern const int iX[72];
extern const int iY[72];
extern const int iZ[72];
#else
/*
* P25 Phase1 IMBE interleave schedule
*/
const int iW[72] = {
0, 2, 4, 1, 3, 5,
0, 2, 4, 1, 3, 6,
0, 2, 4, 1, 3, 6,
0, 2, 4, 1, 3, 6,
0, 2, 4, 1, 3, 6,
0, 2, 4, 1, 3, 6,
0, 2, 5, 1, 3, 6,
0, 2, 5, 1, 3, 6,
0, 2, 5, 1, 3, 7,
0, 2, 5, 1, 3, 7,
0, 2, 5, 1, 4, 7,
0, 3, 5, 2, 4, 7
};
const int iX[72] = {
22, 20, 10, 20, 18, 0,
20, 18, 8, 18, 16, 13,
18, 16, 6, 16, 14, 11,
16, 14, 4, 14, 12, 9,
14, 12, 2, 12, 10, 7,
12, 10, 0, 10, 8, 5,
10, 8, 13, 8, 6, 3,
8, 6, 11, 6, 4, 1,
6, 4, 9, 4, 2, 6,
4, 2, 7, 2, 0, 4,
2, 0, 5, 0, 13, 2,
0, 21, 3, 21, 11, 0
};
const int iY[72] = {
1, 3, 5, 0, 2, 4,
1, 3, 6, 0, 2, 4,
1, 3, 6, 0, 2, 4,
1, 3, 6, 0, 2, 4,
1, 3, 6, 0, 2, 4,
1, 3, 6, 0, 2, 5,
1, 3, 6, 0, 2, 5,
1, 3, 6, 0, 2, 5,
1, 3, 6, 0, 2, 5,
1, 3, 7, 0, 2, 5,
1, 4, 7, 0, 3, 5,
2, 4, 7, 1, 3, 5
};
const int iZ[72] = {
21, 19, 1, 21, 19, 9,
19, 17, 14, 19, 17, 7,
17, 15, 12, 17, 15, 5,
15, 13, 10, 15, 13, 3,
13, 11, 8, 13, 11, 1,
11, 9, 6, 11, 9, 14,
9, 7, 4, 9, 7, 12,
7, 5, 2, 7, 5, 10,
5, 3, 0, 5, 3, 8,
3, 1, 5, 3, 1, 6,
1, 14, 3, 1, 22, 4,
22, 12, 1, 22, 20, 2
};
#endif

312
p25p1_hdu.c Normal file
View File

@@ -0,0 +1,312 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
processHDU (dsd_opts * opts, dsd_state * state)
{
char mi[73], mfid[9], algid[9], kid[17], tgid[17], tmpstr[255];
int dibit, count, i, j;
long talkgroup;
int algidhex, kidhex;
mi[72] = 0;
mfid[8] = 0;
algid[8] = 0;
kid[16] = 0;
tgid[16] = 0;
skipDibit (opts, state, 25);
count = 57;
dibit = getDibit (opts, state);
mi[0] = (1 & (dibit >> 1)) + 48; // bit 1
mi[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[2] = (1 & (dibit >> 1)) + 48; // bit 1
mi[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[4] = (1 & (dibit >> 1)) + 48; // bit 1
mi[5] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[6] = (1 & (dibit >> 1)) + 48; // bit 1
mi[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[8] = (1 & (dibit >> 1)) + 48; // bit 1
mi[9] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[10] = (1 & (dibit >> 1)) + 48; // bit 1
mi[11] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 7);
dibit = getDibit (opts, state);
mi[12] = (1 & (dibit >> 1)) + 48; // bit 1
mi[13] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[14] = (1 & (dibit >> 1)) + 48; // bit 1
mi[15] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[16] = (1 & (dibit >> 1)) + 48; // bit 1
mi[17] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[18] = (1 & (dibit >> 1)) + 48; // bit 1
mi[19] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[20] = (1 & (dibit >> 1)) + 48; // bit 1
mi[21] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[22] = (1 & (dibit >> 1)) + 48; // bit 1
mi[23] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[24] = (1 & (dibit >> 1)) + 48; // bit 1
mi[25] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[26] = (1 & (dibit >> 1)) + 48; // bit 1
mi[27] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[28] = (1 & (dibit >> 1)) + 48; // bit 1
mi[29] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[30] = (1 & (dibit >> 1)) + 48; // bit 1
mi[31] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[32] = (1 & (dibit >> 1)) + 48; // bit 1
mi[33] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[34] = (1 & (dibit >> 1)) + 48; // bit 1
mi[35] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 7);
dibit = getDibit (opts, state);
mi[36] = (1 & (dibit >> 1)) + 48; // bit 1
mi[37] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[38] = (1 & (dibit >> 1)) + 48; // bit 1
mi[39] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[40] = (1 & (dibit >> 1)) + 48; // bit 1
mi[41] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[42] = (1 & (dibit >> 1)) + 48; // bit 1
mi[43] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[44] = (1 & (dibit >> 1)) + 48; // bit 1
mi[45] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[46] = (1 & (dibit >> 1)) + 48; // bit 1
mi[47] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[48] = (1 & (dibit >> 1)) + 48; // bit 1
mi[49] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[50] = (1 & (dibit >> 1)) + 48; // bit 1
mi[51] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[52] = (1 & (dibit >> 1)) + 48; // bit 1
mi[53] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[54] = (1 & (dibit >> 1)) + 48; // bit 1
mi[55] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[56] = (1 & (dibit >> 1)) + 48; // bit 1
mi[57] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[58] = (1 & (dibit >> 1)) + 48; // bit 1
mi[59] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 7);
dibit = getDibit (opts, state);
mi[60] = (1 & (dibit >> 1)) + 48; // bit 1
mi[61] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[62] = (1 & (dibit >> 1)) + 48; // bit 1
mi[63] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[64] = (1 & (dibit >> 1)) + 48; // bit 1
mi[65] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mi[66] = (1 & (dibit >> 1)) + 48; // bit 1
mi[67] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[68] = (1 & (dibit >> 1)) + 48; // bit 1
mi[69] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[70] = (1 & (dibit >> 1)) + 48; // bit 1
mi[71] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mfid[0] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[2] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[4] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[5] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mfid[6] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
algid[0] = (1 & (dibit >> 1)) + 48; // bit 1
algid[1] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 1);
dibit = getDibit (opts, state);
algid[2] = (1 & (dibit >> 1)) + 48; // bit 1
algid[3] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
algid[4] = (1 & (dibit >> 1)) + 48; // bit 1
algid[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
algid[6] = (1 & (dibit >> 1)) + 48; // bit 1
algid[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[0] = (1 & (dibit >> 1)) + 48; // bit 1
kid[1] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
kid[2] = (1 & (dibit >> 1)) + 48; // bit 1
kid[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[4] = (1 & (dibit >> 1)) + 48; // bit 1
kid[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[6] = (1 & (dibit >> 1)) + 48; // bit 1
kid[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
kid[8] = (1 & (dibit >> 1)) + 48; // bit 1
kid[9] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[10] = (1 & (dibit >> 1)) + 48; // bit 1
kid[11] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[12] = (1 & (dibit >> 1)) + 48; // bit 1
kid[13] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
kid[14] = (1 & (dibit >> 1)) + 48; // bit 1
kid[15] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 1);
dibit = getDibit (opts, state);
tgid[0] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
tgid[2] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[3] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
tgid[4] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
tgid[6] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
tgid[8] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[9] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
tgid[10] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[11] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
tgid[12] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[13] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
tgid[14] = (1 & (dibit >> 1)) + 48; // bit 1
tgid[15] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 160);
if (opts->p25enc == 1)
{
algidhex = strtol (algid, NULL, 2);
kidhex = strtol (kid, NULL, 2);
printf ("mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex);
}
if (opts->p25lc == 1)
{
printf ("mfid: %s tgid: %s ", mfid, tgid);
if (opts->p25tg == 0)
{
printf ("\n");
}
}
j = 0;
if (strcmp (mfid, "10010000") == 0)
{
for (i = 4; i < 16; i++)
{
if (state->tgcount < 24)
{
state->tg[state->tgcount][j] = tgid[i];
}
tmpstr[j] = tgid[i];
j++;
}
tmpstr[12] = 48;
tmpstr[13] = 48;
tmpstr[14] = 48;
tmpstr[15] = 48;
}
else
{
for (i = 0; i < 16; i++)
{
if (state->tgcount < 24)
{
state->tg[state->tgcount][j] = tgid[i];
}
tmpstr[j] = tgid[i];
j++;
}
}
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
state->lasttg = talkgroup;
if (opts->p25tg == 1)
{
printf ("tg: %li\n", talkgroup);
}
}

295
p25p1_ldu1.c Normal file
View File

@@ -0,0 +1,295 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
#include "p25p1_const.h"
void
processLDU1 (dsd_opts * opts, dsd_state * state)
{
// extracts IMBE frames rom LDU frame
int i, j, k, dibit, stats, count, scount;
char imbe_fr[8][23];
char lcformat[9], mfid[9], lcinfo[57], lsd1[9], lsd2[9], status[25];
const int *w, *x, *y, *z;
lcformat[8] = 0;
mfid[8] = 0;
lcinfo[56] = 0;
lsd1[8] = 0;
lsd2[8] = 0;
status[24] = 0;
skipDibit (opts, state, 3);
status[0] = getDibit (opts, state) + 48;
skipDibit (opts, state, 21);
count = 57;
scount = 1;
if (opts->errorbars == 1)
{
printf ("e:");
}
// separate imbe frames and deinterleave
stats = 21; // we skip the status dibits that occur every 36 symbols
// the first IMBE frame starts 14 symbols before next status
// so we start counter at 22
for (i = 0; i < 9; i++)
{ // 9 IMBE frames per LDU
w = iW;
x = iX;
y = iY;
z = iZ;
for (j = 0; j < 72; j++)
{
if (stats == 35)
{
status[scount] = getDibit (opts, state) + 48;
scount++;
stats = 1;
count++;
}
else
{
stats++;
}
dibit = getDibit (opts, state);
count++;
imbe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
imbe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
processMbeFrame (opts, state, imbe_fr, NULL, NULL);
// skip over non imbe data sometimes between frames
if ((i < 4) || (i == 8))
{
k = 0;
}
else if (i == 7)
{
//k=16;
k = 0;
}
else
{
k = 20;
}
for (j = 0; j < k; j++)
{
if (stats == 35)
{
status[scount] = getDibit (opts, state) + 48;
scount++;
count++;
stats = 1;
}
else
{
stats++;
}
skipDibit (opts, state, 1);
count++;
}
if (i == 1)
{
dibit = getDibit (opts, state);
lcformat[0] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcformat[2] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcformat[4] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[5] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcformat[6] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[0] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[2] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[3] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
status[scount] = getDibit (opts, state) + 48;
scount++;
dibit = getDibit (opts, state);
mfid[4] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[6] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[0] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[1] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[2] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[4] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[6] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 10;
}
else if (i == 2)
{
dibit = getDibit (opts, state);
lcinfo[8] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[9] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[10] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[11] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[12] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[13] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[14] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[15] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[16] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[17] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[18] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[19] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[20] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[21] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[22] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[23] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[24] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[25] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[26] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[27] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[28] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[29] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[30] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[31] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 32;
}
else if (i == 3)
{
dibit = getDibit (opts, state);
lcinfo[32] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[33] = (1 & dibit) + 48; // bit 0
status[scount] = getDibit (opts, state) + 48;
scount++;
dibit = getDibit (opts, state);
lcinfo[34] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[35] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[36] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[37] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[38] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[39] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[40] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[41] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[42] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[43] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[44] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[45] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[46] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[47] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[48] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[49] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
lcinfo[50] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[51] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[52] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[53] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[54] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[55] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 19;
}
else if (i == 7)
{
dibit = getDibit (opts, state);
lsd1[0] = (1 & (dibit >> 1)) + 48; // bit 1
lsd1[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd1[2] = (1 & (dibit >> 1)) + 48; // bit 1
lsd1[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd1[4] = (1 & (dibit >> 1)) + 48; // bit 1
lsd1[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd1[6] = (1 & (dibit >> 1)) + 48; // bit 1
lsd1[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 4);
dibit = getDibit (opts, state);
lsd2[0] = (1 & (dibit >> 1)) + 48; // bit 1
lsd2[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd2[2] = (1 & (dibit >> 1)) + 48; // bit 1
lsd2[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd2[4] = (1 & (dibit >> 1)) + 48; // bit 1
lsd2[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd2[6] = (1 & (dibit >> 1)) + 48; // bit 1
lsd2[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 4);
stats = 33;
}
}
// trailing status symbol
status[scount] = getDibit (opts, state) + 48;
scount++;
if (opts->errorbars == 1)
{
printf ("\n");
}
if (opts->p25status == 1)
{
printf ("status: %s lsd1: %s lsd2: %s\n", status, lsd1, lsd2);
}
processP25lcw (opts, state, lcformat, mfid, lcinfo);
}

352
p25p1_ldu2.c Normal file
View File

@@ -0,0 +1,352 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
#include "p25p1_const.h"
void
processLDU2 (dsd_opts * opts, dsd_state * state)
{
// extracts IMBE frames rom LDU frame
int i, j, k, dibit, stats, count, scount;
char imbe_fr[8][23];
char mi[73], algid[9], kid[17], lsd3[9], lsd4[9], status[25];
const int *w, *x, *y, *z;
int algidhex, kidhex;
status[24] = 0;
mi[72] = 0;
algid[8] = 0;
kid[16] = 0;
lsd3[8] = 0;
lsd4[8] = 0;
skipDibit (opts, state, 3);
status[0] = getDibit (opts, state) + 48;
skipDibit (opts, state, 21);
scount = 1;
count = 57;
if (opts->errorbars == 1)
{
printf ("e:");
}
// separate imbe frames and deinterleave
stats = 21;
// we skip the status dibits that occur every 36 symbols
// the first IMBE frame starts 14 symbols before next status
// so we start counter at 22
for (i = 0; i < 9; i++)
{ // 9 IMBE frames per LDU
w = iW;
x = iX;
y = iY;
z = iZ;
for (j = 0; j < 72; j++)
{
if (stats == 35)
{
status[scount] = getDibit (opts, state) + 48;
scount++;
stats = 1;
count++;
}
else
{
stats++;
}
dibit = getDibit (opts, state);
count++;
imbe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
imbe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
processMbeFrame (opts, state, imbe_fr, NULL, NULL);
// skip over non imbe data sometimes between frames
if ((i < 5) || (i == 8))
{
k = 0;
}
else if (i == 7)
{
//k=16;
k = 0;
}
else
{
k = 20;
}
for (j = 0; j < k; j++)
{
if (stats == 35)
{
status[scount] = getDibit (opts, state) + 48;
scount++;
count++;
stats = 1;
}
else
{
stats++;
}
skipDibit (opts, state, 1);
count++;
}
if (i == 1)
{
dibit = getDibit (opts, state);
mi[0] = (1 & (dibit >> 1)) + 48; // bit 1
mi[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[2] = (1 & (dibit >> 1)) + 48; // bit 1
mi[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[4] = (1 & (dibit >> 1)) + 48; // bit 1
mi[5] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[6] = (1 & (dibit >> 1)) + 48; // bit 1
mi[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[8] = (1 & (dibit >> 1)) + 48; // bit 1
mi[9] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[10] = (1 & (dibit >> 1)) + 48; // bit 1
mi[11] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
status[scount] = getDibit (opts, state) + 48;
scount++;
dibit = getDibit (opts, state);
mi[12] = (1 & (dibit >> 1)) + 48; // bit 1
mi[13] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[14] = (1 & (dibit >> 1)) + 48; // bit 1
mi[15] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[16] = (1 & (dibit >> 1)) + 48; // bit 1
mi[17] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[18] = (1 & (dibit >> 1)) + 48; // bit 1
mi[19] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[20] = (1 & (dibit >> 1)) + 48; // bit 1
mi[21] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[22] = (1 & (dibit >> 1)) + 48; // bit 1
mi[23] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 10;
}
else if (i == 2)
{
dibit = getDibit (opts, state);
mi[24] = (1 & (dibit >> 1)) + 48; // bit 1
mi[25] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[26] = (1 & (dibit >> 1)) + 48; // bit 1
mi[27] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[28] = (1 & (dibit >> 1)) + 48; // bit 1
mi[29] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[30] = (1 & (dibit >> 1)) + 48; // bit 1
mi[31] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[32] = (1 & (dibit >> 1)) + 48; // bit 1
mi[33] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[34] = (1 & (dibit >> 1)) + 48; // bit 1
mi[35] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[36] = (1 & (dibit >> 1)) + 48; // bit 1
mi[37] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[38] = (1 & (dibit >> 1)) + 48; // bit 1
mi[39] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[40] = (1 & (dibit >> 1)) + 48; // bit 1
mi[41] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[42] = (1 & (dibit >> 1)) + 48; // bit 1
mi[43] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[44] = (1 & (dibit >> 1)) + 48; // bit 1
mi[45] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[46] = (1 & (dibit >> 1)) + 48; // bit 1
mi[47] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 32;
}
else if (i == 3)
{
dibit = getDibit (opts, state);
mi[48] = (1 & (dibit >> 1)) + 48; // bit 1
mi[49] = (1 & dibit) + 48; // bit 0
status[scount] = getDibit (opts, state) + 48;
scount++;
dibit = getDibit (opts, state);
mi[50] = (1 & (dibit >> 1)) + 48; // bit 1
mi[51] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[52] = (1 & (dibit >> 1)) + 48; // bit 1
mi[53] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[54] = (1 & (dibit >> 1)) + 48; // bit 1
mi[55] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[56] = (1 & (dibit >> 1)) + 48; // bit 1
mi[57] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[58] = (1 & (dibit >> 1)) + 48; // bit 1
mi[59] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[60] = (1 & (dibit >> 1)) + 48; // bit 1
mi[61] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[62] = (1 & (dibit >> 1)) + 48; // bit 1
mi[63] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[64] = (1 & (dibit >> 1)) + 48; // bit 1
mi[65] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
mi[66] = (1 & (dibit >> 1)) + 48; // bit 1
mi[67] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[68] = (1 & (dibit >> 1)) + 48; // bit 1
mi[69] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mi[70] = (1 & (dibit >> 1)) + 48; // bit 1
mi[71] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 19;
}
else if (i == 4)
{
dibit = getDibit (opts, state);
algid[0] = (1 & (dibit >> 1)) + 48; // bit 1
algid[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
algid[2] = (1 & (dibit >> 1)) + 48; // bit 1
algid[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
algid[4] = (1 & (dibit >> 1)) + 48; // bit 1
algid[5] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
algid[6] = (1 & (dibit >> 1)) + 48; // bit 1
algid[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[0] = (1 & (dibit >> 1)) + 48; // bit 1
kid[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[2] = (1 & (dibit >> 1)) + 48; // bit 1
kid[3] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
dibit = getDibit (opts, state);
kid[4] = (1 & (dibit >> 1)) + 48; // bit 1
kid[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[6] = (1 & (dibit >> 1)) + 48; // bit 1
kid[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[8] = (1 & (dibit >> 1)) + 48; // bit 1
kid[9] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 1);
status[scount] = getDibit (opts, state) + 48;
scount++;
skipDibit (opts, state, 1);
dibit = getDibit (opts, state);
kid[10] = (1 & (dibit >> 1)) + 48; // bit 1
kid[11] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[12] = (1 & (dibit >> 1)) + 48; // bit 1
kid[13] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
kid[14] = (1 & (dibit >> 1)) + 48; // bit 1
kid[15] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 2);
stats = 6;
}
else if (i == 7)
{
dibit = getDibit (opts, state);
lsd3[0] = (1 & (dibit >> 1)) + 48; // bit 1
lsd3[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd3[2] = (1 & (dibit >> 1)) + 48; // bit 1
lsd3[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd3[4] = (1 & (dibit >> 1)) + 48; // bit 1
lsd3[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd3[6] = (1 & (dibit >> 1)) + 48; // bit 1
lsd3[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 4);
dibit = getDibit (opts, state);
lsd4[0] = (1 & (dibit >> 1)) + 48; // bit 1
lsd4[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd4[2] = (1 & (dibit >> 1)) + 48; // bit 1
lsd4[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd4[4] = (1 & (dibit >> 1)) + 48; // bit 1
lsd4[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lsd4[6] = (1 & (dibit >> 1)) + 48; // bit 1
lsd4[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 4);
stats = 33;
}
}
//trailing status symbol
status[scount] = getDibit (opts, state) + 48;
scount++;
if (opts->errorbars == 1)
{
printf ("\n");
}
if (opts->p25status == 1)
{
printf ("status: %s lsd3: %s lsd4: %s\n", status, lsd3, lsd4);
}
if (opts->p25enc == 1)
{
algidhex = strtol (algid, NULL, 2);
kidhex = strtol (kid, NULL, 2);
printf ("mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex);
}
}

158
p25p1_tdulc.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
processTDULC (dsd_opts * opts, dsd_state * state)
{
char lcinfo[57], lcformat[9], mfid[9];
int dibit, count;
lcformat[8] = 0;
mfid[8] = 0;
lcinfo[56] = 0;
skipDibit (opts, state, 25);
count = 57;
dibit = getDibit (opts, state);
lcformat[0] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcformat[2] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcformat[4] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcformat[6] = (1 & (dibit >> 1)) + 48; // bit 1
lcformat[7] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[0] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[2] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[3] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
mfid[4] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
mfid[6] = (1 & (dibit >> 1)) + 48; // bit 1
mfid[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 1);
dibit = getDibit (opts, state);
lcinfo[0] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[1] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[2] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[3] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[4] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[5] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[6] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[7] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
lcinfo[8] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[9] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[10] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[11] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[12] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[13] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[14] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[15] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[16] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[17] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[18] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[19] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
lcinfo[20] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[21] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[22] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[23] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[24] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[25] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[26] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[27] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[28] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[29] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[30] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[31] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
lcinfo[32] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[33] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 1);
dibit = getDibit (opts, state);
lcinfo[34] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[35] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[36] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[37] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[38] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[39] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[40] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[41] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[42] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[43] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 6);
dibit = getDibit (opts, state);
lcinfo[44] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[45] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[46] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[47] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[48] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[49] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[50] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[51] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[52] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[53] = (1 & dibit) + 48; // bit 0
dibit = getDibit (opts, state);
lcinfo[54] = (1 & (dibit >> 1)) + 48; // bit 1
lcinfo[55] = (1 & dibit) + 48; // bit 0
skipDibit (opts, state, 91);
processP25lcw (opts, state, lcformat, mfid, lcinfo);
}

519
provoice.c Normal file
View File

@@ -0,0 +1,519 @@
#include "dsd.h"
#include "provoice_const.h"
void
processProVoice (dsd_opts * opts, dsd_state * state)
{
int i, j, dibit;
char imbe7100_fr1[7][24];
char imbe7100_fr2[7][24];
const int *w, *x;
if (opts->errorbars == 1)
{
printf ("VOICE e:");
}
for (i = 0; i < 64; i++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
// lid
for (i = 0; i < 16; i++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
for (i = 0; i < 64; i++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
// imbe frames 1,2 first half
w = pW;
x = pX;
for (i = 0; i < 11; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
}
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 4; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
// spacer bits
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
printf (" ");
#endif
// imbe frames 1,2 second half
for (j = 0; j < 2; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
for (i = 0; i < 3; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
for (i = 0; i < 7; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
// spacer bits
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
printf (" ");
#endif
for (i = 0; i < 16; i++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
// imbe frames 3,4 first half
w = pW;
x = pX;
for (i = 0; i < 11; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
}
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 4; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
// spacer bits
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
printf ("_");
#endif
// imbe frames 3,4 second half
for (j = 0; j < 2; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
for (i = 0; i < 3; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
for (i = 0; i < 7; i++)
{
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 6;
x -= 6;
for (j = 0; j < 6; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
}
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr1[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf ("_");
#endif
w -= 5;
x -= 5;
for (j = 0; j < 5; j++)
{
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
imbe7100_fr2[*w][*x] = dibit;
w++;
x++;
}
#ifdef PROVOICE_DUMP
printf (" ");
#endif
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
// spacer bits
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
#endif
dibit = getDibit (opts, state);
#ifdef PROVOICE_DUMP
printf ("%i", dibit);
printf (" ");
#endif
if (opts->errorbars == 1)
{
printf ("\n");
}
}

81
provoice_const.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MAIN
extern const int pW[142];
extern const int pX[142];
#else
/*
* ProVoice IMBE interleave schedule
*/
const int pW[142] = {
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 3, 5, 6,
0, 1, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 3, 5, 6,
1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 4, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 3, 5, 6,
0, 1, 2, 4, 5, 6,
1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 6
};
const int pX[142] = {
18, 18, 17, 16, 7, 21,
15, 15, 14, 13, 4, 18,
12, 12, 11, 10, 1, 15,
9, 9, 8, 7, 13, 12,
6, 6, 5, 4, 10, 9,
3, 3, 2, 1, 7, 6,
0, 0, 22, 13, 4, 3,
21, 20, 19, 10, 1, 0,
17, 17, 16, 15, 6, 20,
14, 14, 13, 12, 3, 17,
11, 11, 10, 9, 0, 14,
8, 8, 7, 6, 12, 11,
5, 5, 4, 3, 9, 8,
2, 2, 1, 0, 6, 5,
23, 22, 21, 12, 3, 2,
20, 19, 18, 9, 0,
16, 16, 15, 14, 5, 19,
13, 13, 12, 11, 2, 16,
10, 10, 9, 8, 14, 13,
7, 7, 6, 5, 11, 10,
4, 4, 3, 2, 8, 7,
1, 1, 0, 14, 5, 4,
22, 21, 20, 11, 2, 1,
19, 18, 17, 8, 22
};
#endif

62
x2tdma_const.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* X2TDMA AMBE interleave schedule
*/
#ifndef _MAIN
extern const int aW[36];
extern const int aX[36];
extern const int aY[36];
extern const int aZ[36];
#else
const int aW[36] = { 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 2,
0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2
};
const int aX[36] = { 23, 10, 22, 9, 21, 8,
20, 7, 19, 6, 18, 5,
17, 4, 16, 3, 15, 2,
14, 1, 13, 0, 12, 10,
11, 9, 10, 8, 9, 7,
8, 6, 7, 5, 6, 4
};
const int aY[36] = { 0, 2, 0, 2, 0, 2,
0, 2, 0, 3, 0, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3,
1, 3, 1, 3, 1, 3
};
const int aZ[36] = { 5, 3, 4, 2, 3, 1,
2, 0, 1, 13, 0, 12,
22, 11, 21, 10, 20, 9,
19, 8, 18, 7, 17, 6,
16, 5, 15, 4, 14, 3,
13, 2, 12, 1, 11, 0
};
#endif

252
x2tdma_data.c Normal file
View File

@@ -0,0 +1,252 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
void
processX2TDMAdata (dsd_opts * opts, dsd_state * state)
{
int i, dibit;
int *dibit_p;
char sync[25];
char syncdata[25];
char cachdata[13];
char cc[4];
int aiei;
char bursttype[5];
#ifdef X2TDMA_DUMP
int k;
char syncbits[49];
char cachbits[25];
#endif
cc[3] = 0;
bursttype[4] = 0;
dibit_p = state->dibit_buf_p - 90;
// CACH
for (i = 0; i < 12; i++)
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
cachdata[i] = dibit;
if (i == 2)
{
state->currentslot = (1 & (dibit >> 1)); // bit 1
if (state->currentslot == 0)
{
state->slot0light[0] = '[';
state->slot0light[6] = ']';
state->slot1light[0] = ' ';
state->slot1light[6] = ' ';
}
else
{
state->slot1light[0] = '[';
state->slot1light[6] = ']';
state->slot0light[0] = ' ';
state->slot0light[6] = ' ';
}
}
}
cachdata[12] = 0;
#ifdef X2TDMA_DUMP
k = 0;
for (i = 0; i < 12; i++)
{
dibit = cachdata[i];
cachbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
cachbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
cachbits[24] = 0;
printf ("%s ", cachbits);
#endif
// current slot
dibit_p += 49;
// slot type
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
cc[0] = (1 & (dibit >> 1)) + 48; // bit 1
cc[1] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
cc[2] = (1 & (dibit >> 1)) + 48; // bit 1
aiei = (1 & dibit); // bit 0
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
bursttype[0] = (1 & (dibit >> 1)) + 48; // bit 1
bursttype[1] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
bursttype[2] = (1 & (dibit >> 1)) + 48; // bit 1
bursttype[3] = (1 & dibit) + 48; // bit 0
// parity bit
dibit_p++;
if (strcmp (bursttype, "0000") == 0)
{
sprintf (state->fsubtype, " PI Header ");
}
else if (strcmp (bursttype, "0001") == 0)
{
sprintf (state->fsubtype, " VOICE Header ");
}
else if (strcmp (bursttype, "0010") == 0)
{
sprintf (state->fsubtype, " TLC ");
}
else if (strcmp (bursttype, "0011") == 0)
{
sprintf (state->fsubtype, " CSBK ");
}
else if (strcmp (bursttype, "0100") == 0)
{
sprintf (state->fsubtype, " MBC Header ");
}
else if (strcmp (bursttype, "0101") == 0)
{
sprintf (state->fsubtype, " MBC ");
}
else if (strcmp (bursttype, "0110") == 0)
{
sprintf (state->fsubtype, " DATA Header ");
}
else if (strcmp (bursttype, "0111") == 0)
{
sprintf (state->fsubtype, " RATE 1/2 DATA");
}
else if (strcmp (bursttype, "1000") == 0)
{
sprintf (state->fsubtype, " RATE 3/4 DATA");
}
else if (strcmp (bursttype, "1001") == 0)
{
sprintf (state->fsubtype, " Slot idle ");
}
else if (strcmp (bursttype, "1010") == 0)
{
sprintf (state->fsubtype, " Rate 1 DATA ");
}
else
{
sprintf (state->fsubtype, " ");
}
// signaling data or sync
for (i = 0; i < 24; i++)
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
#ifdef X2TDMA_DUMP
k = 0;
for (i = 0; i < 24; i++)
{
dibit = syncdata[i];
syncbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
syncbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
syncbits[48] = 0;
printf ("%s ", syncbits);
#endif
if (strcmp (sync, X2TDMA_DATA_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[slot0]");
}
else
{
sprintf (state->slot1light, "[slot1]");
}
}
else if (strcmp (sync, X2TDMA_VOICE_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[SLOT0]");
}
else
{
sprintf (state->slot1light, "[SLOT1]");
}
}
if (opts->errorbars == 1)
{
printf ("%s %s ", state->slot0light, state->slot1light);
}
// current slot second half, cach, next slot 1st half
skipDibit (opts, state, 120);
if (opts->errorbars == 1)
{
if (strcmp (state->fsubtype, " ") == 0)
{
printf (" Unknown burst type: %s\n", bursttype);
}
else
{
printf ("%s\n", state->fsubtype);
}
}
}

635
x2tdma_voice.c Normal file
View File

@@ -0,0 +1,635 @@
/*
* Copyright (C) 2010 DSD Author
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "dsd.h"
#include "x2tdma_const.h"
void
processX2TDMAvoice (dsd_opts * opts, dsd_state * state)
{
// extracts AMBE frames from X2TDMA frame
int i, j, dibit;
int *dibit_p;
char ambe_fr[4][24];
char ambe_fr2[4][24];
char ambe_fr3[4][24];
const int *w, *x, *y, *z;
char sync[25];
char syncdata[25];
char lcformat[9], mfid[9], lcinfo[57];
char cachdata[13];
char parity;
int eeei, aiei;
char mi[73];
int burstd;
int mutecurrentslot;
int algidhex, kidhex;
#ifdef X2TDMA_DUMP
int k;
char cachbits[25];
char syncbits[49];
#endif
lcformat[8] = 0;
mfid[8] = 0;
lcinfo[56] = 0;
sprintf (mi, "________________________________________________________________________");
eeei = 0;
aiei = 0;
burstd = 0;
mutecurrentslot = 0;
dibit_p = state->dibit_buf_p - 144;
for (j = 0; j < 6; j++)
{
// 2nd half of previous slot
for (i = 0; i < 54; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
}
}
// CACH
for (i = 0; i < 12; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
}
cachdata[i] = dibit;
if (i == 2)
{
state->currentslot = (1 & (dibit >> 1)); // bit 1
if (state->currentslot == 0)
{
state->slot0light[0] = '[';
state->slot0light[6] = ']';
state->slot1light[0] = ' ';
state->slot1light[6] = ' ';
}
else
{
state->slot1light[0] = '[';
state->slot1light[6] = ']';
state->slot0light[0] = ' ';
state->slot0light[6] = ' ';
}
}
}
cachdata[12] = 0;
#ifdef X2TDMA_DUMP
k = 0;
for (i = 0; i < 12; i++)
{
dibit = cachdata[i];
cachbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
cachbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
cachbits[24] = 0;
printf ("%s ", cachbits);
#endif
// current slot frame 1
w = aW;
x = aX;
y = aY;
z = aZ;
for (i = 0; i < 36; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
}
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
// current slot frame 2 first half
w = aW;
x = aX;
y = aY;
z = aZ;
for (i = 0; i < 18; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
}
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
// signaling data or sync
for (i = 0; i < 24; i++)
{
if (j > 0)
{
dibit = getDibit (opts, state);
}
else
{
dibit = *dibit_p;
dibit_p++;
if (opts->inverted_x2tdma == 1)
{
dibit = (dibit ^ 2);
}
}
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
if (strcmp (sync, X2TDMA_DATA_SYNC) == 0)
{
mutecurrentslot = 1;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[slot0]");
}
else
{
sprintf (state->slot1light, "[slot1]");
}
}
else if (strcmp (sync, X2TDMA_VOICE_SYNC) == 0)
{
mutecurrentslot = 0;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[SLOT0]");
}
else
{
sprintf (state->slot1light, "[SLOT1]");
}
}
if ((j == 0) && (opts->errorbars == 1))
{
printf ("%s %s VOICE e:", state->slot0light, state->slot1light);
}
#ifdef X2TDMA_DUMP
k = 0;
for (i = 0; i < 24; i++)
{
dibit = syncdata[i];
syncbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
syncbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
syncbits[48] = 0;
printf ("%s ", syncbits);
#endif
if (j == 1)
{
eeei = (1 & syncdata[1]); // bit 0
aiei = (1 & (syncdata[2] >> 1)); // bit 1
if ((eeei == 0) && (aiei == 0))
{
lcformat[0] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
mfid[3] = (1 & syncdata[4]) + 48; // bit 0
lcinfo[6] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
lcinfo[16] = (1 & syncdata[5]) + 48; // bit 0
lcinfo[26] = (1 & (syncdata[6] >> 1)) + 48; // bit 1
lcinfo[36] = (1 & syncdata[6]) + 48; // bit 0
lcinfo[46] = (1 & (syncdata[7] >> 1)) + 48; // bit 1
parity = (1 & syncdata[7]) + 48; // bit 0
lcformat[1] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
mfid[4] = (1 & syncdata[8]) + 48; // bit 0
lcinfo[7] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
lcinfo[17] = (1 & syncdata[9]) + 48; // bit 0
lcinfo[27] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
lcinfo[37] = (1 & syncdata[10]) + 48; // bit 0
lcinfo[47] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
parity = (1 & syncdata[11]) + 48; // bit 0
lcformat[2] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
mfid[5] = (1 & syncdata[12]) + 48; // bit 0
lcinfo[8] = (1 & (syncdata[13] >> 1)) + 48; // bit 1
lcinfo[18] = (1 & syncdata[13]) + 48; // bit 0
lcinfo[28] = (1 & (syncdata[14] >> 1)) + 48; // bit 1
lcinfo[38] = (1 & syncdata[14]) + 48; // bit 0
lcinfo[48] = (1 & (syncdata[15] >> 1)) + 48; // bit 1
parity = (1 & syncdata[15]) + 48; // bit 0
lcformat[3] = (1 & (syncdata[16] >> 1)) + 48; // bit 1
mfid[6] = (1 & syncdata[16]) + 48; // bit 0
lcinfo[9] = (1 & (syncdata[17] >> 1)) + 48; // bit 1
lcinfo[19] = (1 & syncdata[17]) + 48; // bit 0
lcinfo[29] = (1 & (syncdata[18] >> 1)) + 48; // bit 1
lcinfo[39] = (1 & syncdata[18]) + 48; // bit 0
lcinfo[49] = (1 & (syncdata[19] >> 1)) + 48; // bit 1
parity = (1 & syncdata[19]) + 48; // bit 0
}
else
{
mi[0] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
mi[11] = (1 & syncdata[4]) + 48; // bit 0
mi[22] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
mi[32] = (1 & syncdata[5]) + 48; // bit 0
mi[42] = (1 & (syncdata[6] >> 1)) + 48; // bit 1
mi[52] = (1 & syncdata[6]) + 48; // bit 0
mi[62] = (1 & (syncdata[7] >> 1)) + 48; // bit 1
parity = (1 & syncdata[7]) + 48; // bit 0
mi[1] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
mi[12] = (1 & syncdata[8]) + 48; // bit 0
mi[23] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
mi[33] = (1 & syncdata[9]) + 48; // bit 0
mi[43] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
mi[53] = (1 & syncdata[10]) + 48; // bit 0
mi[63] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
parity = (1 & syncdata[11]) + 48; // bit 0
mi[2] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
mi[13] = (1 & syncdata[12]) + 48; // bit 0
mi[24] = (1 & (syncdata[13] >> 1)) + 48; // bit 1
mi[34] = (1 & syncdata[13]) + 48; // bit 0
mi[44] = (1 & (syncdata[14] >> 1)) + 48; // bit 1
mi[54] = (1 & syncdata[14]) + 48; // bit 0
mi[64] = (1 & (syncdata[15] >> 1)) + 48; // bit 1
parity = (1 & syncdata[15]) + 48; // bit 0
mi[3] = (1 & (syncdata[16] >> 1)) + 48; // bit 1
mi[14] = (1 & syncdata[16]) + 48; // bit 0
mi[25] = (1 & (syncdata[17] >> 1)) + 48; // bit 1
mi[35] = (1 & syncdata[17]) + 48; // bit 0
mi[45] = (1 & (syncdata[18] >> 1)) + 48; // bit 1
mi[55] = (1 & syncdata[18]) + 48; // bit 0
mi[65] = (1 & (syncdata[19] >> 1)) + 48; // bit 1
parity = (1 & syncdata[19]) + 48; // bit 0
}
}
else if (j == 2)
{
if ((eeei == 0) && (aiei == 0))
{
lcformat[4] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
mfid[7] = (1 & syncdata[4]) + 48; // bit 0
lcinfo[10] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
lcinfo[20] = (1 & syncdata[5]) + 48; // bit 0
lcinfo[30] = (1 & (syncdata[6] >> 1)) + 48; // bit 1
lcinfo[40] = (1 & syncdata[6]) + 48; // bit 0
lcinfo[50] = (1 & (syncdata[7] >> 1)) + 48; // bit 1
parity = (1 & syncdata[7]) + 48; // bit 0
lcformat[5] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
lcinfo[0] = (1 & syncdata[8]) + 48; // bit 0
lcinfo[11] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
lcinfo[21] = (1 & syncdata[9]) + 48; // bit 0
lcinfo[31] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
lcinfo[41] = (1 & syncdata[10]) + 48; // bit 0
lcinfo[51] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
parity = (1 & syncdata[11]) + 48; // bit 0
lcformat[6] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
lcinfo[1] = (1 & syncdata[12]) + 48; // bit 0
lcinfo[12] = (1 & (syncdata[13] >> 1)) + 48; // bit 1
lcinfo[22] = (1 & syncdata[13]) + 48; // bit 0
lcinfo[32] = (1 & (syncdata[14] >> 1)) + 48; // bit 1
lcinfo[42] = (1 & syncdata[14]) + 48; // bit 0
lcinfo[52] = (1 & (syncdata[15] >> 1)) + 48; // bit 1
parity = (1 & syncdata[15]) + 48; // bit 0
lcformat[7] = (1 & (syncdata[16] >> 1)) + 48; // bit 1
lcinfo[2] = (1 & syncdata[16]) + 48; // bit 0
lcinfo[13] = (1 & (syncdata[17] >> 1)) + 48; // bit 1
lcinfo[23] = (1 & syncdata[17]) + 48; // bit 0
lcinfo[33] = (1 & (syncdata[18] >> 1)) + 48; // bit 1
lcinfo[43] = (1 & syncdata[18]) + 48; // bit 0
lcinfo[53] = (1 & (syncdata[19] >> 1)) + 48; // bit 1
parity = (1 & syncdata[19]) + 48; // bit 0
}
else
{
mi[4] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
mi[15] = (1 & syncdata[4]) + 48; // bit 0
mi[26] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
mi[36] = (1 & syncdata[5]) + 48; // bit 0
mi[46] = (1 & (syncdata[6] >> 1)) + 48; // bit 1
mi[56] = (1 & syncdata[6]) + 48; // bit 0
mi[66] = (1 & (syncdata[7] >> 1)) + 48; // bit 1
parity = (1 & syncdata[7]) + 48; // bit 0
mi[5] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
mi[16] = (1 & syncdata[8]) + 48; // bit 0
mi[27] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
mi[37] = (1 & syncdata[9]) + 48; // bit 0
mi[47] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
mi[57] = (1 & syncdata[10]) + 48; // bit 0
mi[67] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
parity = (1 & syncdata[11]) + 48; // bit 0
mi[6] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
mi[17] = (1 & syncdata[12]) + 48; // bit 0
mi[28] = (1 & (syncdata[13] >> 1)) + 48; // bit 1
mi[38] = (1 & syncdata[13]) + 48; // bit 0
mi[48] = (1 & (syncdata[14] >> 1)) + 48; // bit 1
mi[58] = (1 & syncdata[14]) + 48; // bit 0
mi[68] = (1 & (syncdata[15] >> 1)) + 48; // bit 1
parity = (1 & syncdata[15]) + 48; // bit 0
mi[7] = (1 & (syncdata[16] >> 1)) + 48; // bit 1
mi[18] = (1 & syncdata[16]) + 48; // bit 0
mi[29] = (1 & (syncdata[17] >> 1)) + 48; // bit 1
mi[39] = (1 & syncdata[17]) + 48; // bit 0
mi[49] = (1 & (syncdata[18] >> 1)) + 48; // bit 1
mi[59] = (1 & syncdata[18]) + 48; // bit 0
mi[69] = (1 & (syncdata[19] >> 1)) + 48; // bit 1
parity = (1 & syncdata[19]) + 48; // bit 0
}
}
else if (j == 3)
{
burstd = (1 & syncdata[1]); // bit 0
state->algid[0] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
state->algid[1] = (1 & syncdata[4]) + 48; // bit 0
state->algid[2] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
state->algid[3] = (1 & syncdata[5]) + 48; // bit 0
if (burstd == 0)
{
state->algid[4] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
state->algid[5] = (1 & syncdata[8]) + 48; // bit 0
state->algid[6] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
state->algid[7] = (1 & syncdata[9]) + 48; // bit 0
state->keyid[0] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
state->keyid[1] = (1 & syncdata[10]) + 48; // bit 0
state->keyid[2] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
state->keyid[3] = (1 & syncdata[11]) + 48; // bit 0
state->keyid[4] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
state->keyid[5] = (1 & syncdata[12]) + 48; // bit 0
state->keyid[6] = (1 & (syncdata[13] >> 1)) + 48; // bit 1
state->keyid[7] = (1 & syncdata[13]) + 48; // bit 0
state->keyid[8] = (1 & (syncdata[14] >> 1)) + 48; // bit 1
state->keyid[9] = (1 & syncdata[14]) + 48; // bit 0
state->keyid[10] = (1 & (syncdata[15] >> 1)) + 48; // bit 1
state->keyid[11] = (1 & syncdata[15]) + 48; // bit 0
state->keyid[12] = (1 & (syncdata[16] >> 1)) + 48; // bit 1
state->keyid[13] = (1 & syncdata[16]) + 48; // bit 0
state->keyid[14] = (1 & (syncdata[17] >> 1)) + 48; // bit 1
state->keyid[15] = (1 & syncdata[17]) + 48; // bit 0
}
else
{
sprintf (state->algid, "________");
sprintf (state->keyid, "________________");
}
}
else if (j == 4)
{
if ((eeei == 0) && (aiei == 0))
{
mfid[0] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
lcinfo[3] = (1 & syncdata[4]) + 48; // bit 0
lcinfo[14] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
lcinfo[24] = (1 & syncdata[5]) + 48; // bit 0
lcinfo[34] = (1 & (syncdata[6] >> 1)) + 48; // bit 1
lcinfo[44] = (1 & syncdata[6]) + 48; // bit 0
lcinfo[54] = (1 & (syncdata[7] >> 1)) + 48; // bit 1
parity = (1 & syncdata[7]) + 48; // bit 0
mfid[1] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
lcinfo[4] = (1 & syncdata[8]) + 48; // bit 0
lcinfo[15] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
lcinfo[25] = (1 & syncdata[9]) + 48; // bit 0
lcinfo[35] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
lcinfo[45] = (1 & syncdata[10]) + 48; // bit 0
lcinfo[55] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
parity = (1 & syncdata[11]) + 48; // bit 0
mfid[2] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
lcinfo[5] = (1 & syncdata[12]) + 48; // bit 0
}
else
{
mi[8] = (1 & (syncdata[4] >> 1)) + 48; // bit 1
mi[19] = (1 & syncdata[4]) + 48; // bit 0
mi[30] = (1 & (syncdata[5] >> 1)) + 48; // bit 1
mi[40] = (1 & syncdata[5]) + 48; // bit 0
mi[50] = (1 & (syncdata[6] >> 1)) + 48; // bit 1
mi[60] = (1 & syncdata[6]) + 48; // bit 0
mi[70] = (1 & (syncdata[7] >> 1)) + 48; // bit 1
parity = (1 & syncdata[7]) + 48; // bit 0
mi[9] = (1 & (syncdata[8] >> 1)) + 48; // bit 1
mi[20] = (1 & syncdata[8]) + 48; // bit 0
mi[31] = (1 & (syncdata[9] >> 1)) + 48; // bit 1
mi[41] = (1 & syncdata[9]) + 48; // bit 0
mi[51] = (1 & (syncdata[10] >> 1)) + 48; // bit 1
mi[61] = (1 & syncdata[10]) + 48; // bit 0
mi[71] = (1 & (syncdata[11] >> 1)) + 48; // bit 1
parity = (1 & syncdata[11]) + 48; // bit 0
mi[10] = (1 & (syncdata[12] >> 1)) + 48; // bit 1
mi[21] = (1 & syncdata[12]) + 48; // bit 0
}
}
// current slot frame 2 second half
for (i = 0; i < 18; i++)
{
dibit = getDibit (opts, state);
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
if (mutecurrentslot == 0)
{
if (state->firstframe == 1)
{ // we don't know if anything received before the first sync after no carrier is valid
state->firstframe = 0;
}
else
{
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
}
}
// current slot frame 3
w = aW;
x = aX;
y = aY;
z = aZ;
for (i = 0; i < 36; i++)
{
dibit = getDibit (opts, state);
ambe_fr3[*w][*x] = (1 & (dibit >> 1)); // bit 1
ambe_fr3[*y][*z] = (1 & dibit); // bit 0
w++;
x++;
y++;
z++;
}
if (mutecurrentslot == 0)
{
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
}
// CACH
for (i = 0; i < 12; i++)
{
dibit = getDibit (opts, state);
cachdata[i] = dibit;
}
cachdata[12] = 0;
#ifdef X2TDMA_DUMP
k = 0;
for (i = 0; i < 12; i++)
{
dibit = cachdata[i];
cachbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
cachbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
cachbits[24] = 0;
printf ("%s ", cachbits);
#endif
// next slot
skipDibit (opts, state, 54);
// signaling data or sync
for (i = 0; i < 24; i++)
{
dibit = getDibit (opts, state);
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
if (strcmp (sync, X2TDMA_DATA_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot1light, " slot1 ");
}
else
{
sprintf (state->slot0light, " slot0 ");
}
}
else if (strcmp (sync, X2TDMA_VOICE_SYNC) == 0)
{
if (state->currentslot == 0)
{
sprintf (state->slot1light, " SLOT1 ");
}
else
{
sprintf (state->slot0light, " SLOT0 ");
}
}
#ifdef X2TDMA_DUMP
k = 0;
for (i = 0; i < 24; i++)
{
dibit = syncdata[i];
syncbits[k] = (1 & (dibit >> 1)) + 48; // bit 1
k++;
syncbits[k] = (1 & dibit) + 48; // bit 0
k++;
}
syncbits[48] = 0;
printf ("%s ", syncbits);
#endif
if (j == 5)
{
// 2nd half next slot
skipDibit (opts, state, 54);
// CACH
skipDibit (opts, state, 12);
// first half current slot
skipDibit (opts, state, 54);
}
}
if (opts->errorbars == 1)
{
printf ("\n");
}
if (mutecurrentslot == 0)
{
if ((eeei == 0) && (aiei == 0))
{
processP25lcw (opts, state, lcformat, mfid, lcinfo);
}
if (opts->p25enc == 1)
{
algidhex = strtol (state->algid, NULL, 2);
kidhex = strtol (state->keyid, NULL, 2);
printf ("mi: %s algid: $%x kid: $%x\n", mi, algidhex, kidhex);
}
}
}