Imported the dsd library from gr-dsd. Make it a library actually removing useless dependencies

pull/6/head
f4exb 2016-04-07 02:00:54 +02:00
rodzic 6b6b4d0b0d
commit 0978e17f2e
65 zmienionych plików z 10561 dodań i 0 usunięć

Wyświetl plik

@ -48,6 +48,7 @@ find_package(PkgConfig)
find_package(Boost)
find_package(FFTW3F)
find_package(LibMbe)
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|x86")
SET(USE_SIMD "SSE2" CACHE STRING "Use SIMD instructions")
@ -372,6 +373,10 @@ qt5_use_modules(sdrangel Widgets Multimedia)
add_subdirectory(plugins)
if(LIBMBE_FOUND)
add_subdirectory(dsd)
endif(LIBMBE_FOUND)
if(LIBUSB_FOUND AND UNIX)
add_subdirectory(fcdhid)
add_subdirectory(fcdlib)

Wyświetl plik

@ -0,0 +1,22 @@
# Find libmbe
FIND_PATH(LIBMBE_INCLUDE_DIR mbelib.h)
SET(LIBMBE_NAMES ${LIBMBE_NAMES} mbe libmbe)
FIND_LIBRARY(LIBMBE_LIBRARY NAMES ${LIBMBE_NAMES} PATH)
IF (LIBMBE_INCLUDE_DIR AND LIBMBE_LIBRARY)
SET(LIBMBE_FOUND TRUE)
ENDIF (LIBMBE_INCLUDE_DIR AND LIBMBE_LIBRARY)
IF (LIBMBE_FOUND)
IF (NOT LibMbe_FIND_QUIETLY)
MESSAGE (STATUS "Found LibMbe: ${LIBMBE_LIBRARY}")
ENDIF (NOT LibMbe_FIND_QUIETLY)
ELSE (LIBMBE_FOUND)
IF (LibMbe_FIND_REQUIRED)
MESSAGE (FATAL_ERROR "Could not find mbe")
ENDIF (LibMbe_FIND_REQUIRED)
ENDIF (LIBMBE_FOUND)
mark_as_advanced(LIBMBE_INCLUDE_DIR LIBMBE_LIBRARY)

3
dsd/.gitmodules vendored 100644
Wyświetl plik

@ -0,0 +1,3 @@
[submodule "samples"]
path = samples
url = https://github.com/szechyjs/dsd-samples.git

98
dsd/CHANGELOG 100644
Wyświetl plik

@ -0,0 +1,98 @@
1.7.0-dev
New features:
CMake build system replaces Makefile
Use libsndfile for reading and writing audio files
Initial DSTAR voice support
1.6.0
New features:
Auto mutes P25 encrypted signals by default.
Raised cosine filters.
Fixed bugs:
Changed the crazy dibit buffer which filled for ever until it
ran out of allocated memory then caused a segmentation error. The
buffer is now allowed to fill to 90% before being returned to the
initial pointer value where it over writes the old samples, it
seems to work ok and no segmentation errors now.
Input level is now calculated differently, before when it reported 50%
the soundcard would be fully overloaded. With the new method aim for 30% inlvl.
1.4.1
New features:
Several new sync types for existing formats now recognized:
Decodes voice from NXDN 4800 (6.25kHz) signals
Decodes voice from NXDN 9600 (12.5kHz) repeater output
Decodes voice from DMR/MotoTRBO simplex/repeater input
Decodes voice from X2-TDMA simplex/repeater input
Fixed bugs:
renamed "input:" to "inlvl:" to reduce confusion. This value
indicates the audio input level, NOT the "decode success
rate". Voice decode errors are indicated by the errorbars "=".
1.4
New features:
Decodes voice from NXDN 9600 (12.5 kHz) simplex/repeater input
NXDN96 frames enabled by default
Improved resistance to NXDN96 sync false positives
Fixed bugs:
.wav file header updated after playing .imb/.amb data files
.imb/.amb files now have correct tgid in filename
1.3.1 New features:
Support for ProVoice EA sync
CTRL-C is now caught so .wav files can be properly closed
DSD now shows mbelib version as well as it's own version
-R resume option now triggers on any TSDU so control channels can be left
in conventional scanlists.
Auto output gain now has 0.5 second hold time for faster error burst recovery
(was 1.5 seconds)
Audio output upsampling function simplified and improved
Fixed bugs:
DSD_Author.pgp now has correct public key (was copy of mbelib_Author key)
TGID and SRC are now cleared after TDULC or TDU.
Voice error counter is now reset in noCarrier()
TGID and SRC were not displaying for X2-TDMA frames
Fixed buffer issue in resumeScan()
Fixed error in .wav file headers preventing playback on some apps
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

71
dsd/CMakeLists.txt 100644
Wyświetl plik

@ -0,0 +1,71 @@
project(dsd)
set(dsd_SOURCES
dmr_data.c
dmr_voice.c
dsd_audio.c
dsd_cleanupexit.c
dsd_dibit.c
# dsd_file.c
dsd_filters.c
dsd_frame_sync.c
dsd_frame.c
dsd_livescanner.c
dsd_mbe.c
dsd_nocarrier.c
dsd_opts.c
dsd_symbol.c
dsd_upsample.c
dstar_header.c
dstar.c
nxdn_data.c
nxdn_voice.c
nxdn96.c
p25_lcw.c
p25p1_hdu.c
p25p1_ldu1.c
p25p1_ldu2.c
p25p1_tdulc.c
provoice.c
x2tdma_data.c
x2tdma_voice.c
)
set(dsd_HEADERS
config.h
descramble.h
dmr_const.h
dsd_cleanupexit.h
dsd_livescanner.h
dsd_nocarrier.h
dsd_opts.h
dsd_state.h
dsd.h
dstar_const.h
dstar_header.h
fcs.h
nxdn_const.h
nxdn96_const.h
p25p1_const.h
p25p1_heuristics.h
provoice_const.h
x2tdma_const.h
)
include_directories(
${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${LIBMBE_INCLUDE_DIR}
)
SET(LIBS ${LIBS} ${LIBMBE_LIBRARY})
add_definitions(-DQT_SHARED)
add_library(dsd SHARED
${dsd_SOURCES}
)
target_link_libraries(dsd ${LIBS})
install(TARGETS dsd DESTINATION lib)

29
dsd/COPYRIGHT 100644
Wyświetl plik

@ -0,0 +1,29 @@
dstar_header.c/h, descramble.h, and fcs.h are under the following license:
dstar_header.c/h and fcs.h: Copyright (C) 2010 by Kristoff Bonne, ON1ARF
descramble.h: Copyright (C) 2011 by Jonathan Naylor, G4KLX
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
All other code is under the following license:
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/DSD_Author.pgp 100644
Wyświetl plik

@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.10
mQENBEufuqsBCADAtWFE1qE3xqJE4xggUn6id0fVulM7y+rSH1VPxo7Ps9duc/O9
VegEx8+N5KphDROS4RgHxMiS1O8Qy5Hpq4gEp6RvLNj3s+0DMwqRZoA0tBCkNmvF
K7sF+GncrOu/NZkDIZ8emN9NWWeWynWJvuM2H5HQA9yCq+YTFae5sgyr3APC3xh4
OkTuVMcclGTJdVrISlNBDpo/AZLJ/nV0SgITpiZVsI4RSNiQPP1kX+2fIDEAwtxN
3HIDyegDoX36cOItsb05zHkLxoUoZnWoxMvV3rwnqXg5cr6PWfiwgqWd0avl1sg6
abpR6MKV68OCpTkqMrDIXJJrM2sTz+ZB2bBtABEBAAG0CkRTRCBBdXRob3KJATgE
EwECACIFAkufuqsCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPqiY10/
HX/Q11UH/0ZutGQWLZyZD5ZqVdBeYEf6IKhKhaC2vD/+5zUJ2cIgT5xJVTPCKN7X
sygBANJc9GyPRYRvQecdcTHR5B+wUKCPeibv9iQuU3v7Uqb5edXEh2b4jOMWNvHJ
l3lqBdUefuQdbc2xXCPgn+GkyexXEBsVF3hCzWV9r4bCpY57iWUYZZT0wAbN81hz
jPKCCRmF+gZUUufxyhUGq/+eAKeUll6lgG5Ms2YKOlUMphfMav45qgWZHj1DASOV
wPsiIVUaC6+GtHTTzHYRL05ydxxduX+yyKDO1emCE4fx1n3jdwToHLRrC1ui+AJM
Q1s+bp+bGmMYaYaKc/JtNHcN8mbWyCK5AQ0ES5+6qwEIAJvPrnv2QO5Be3FRsnYL
qbA1h/Lj0SjnuimaiNOzCYFIYtusLpyWjwWUnOEXdw5FoExqUStOHJ557SDG/zFB
qy+DsNC9ncSRZ5U2tUQUtt50m2lpYvoy/sVf3oN+IsyZ5hZpiAwrxlyMC/aoGR3C
6ZlLkZ42azNCmEmoBniIxQ+XwhwkLMRsOnqLoFyXB9CcDFIXeEhZkVWZT0B5+20f
yGSBDJ6VcIAASoaIyvSwU9l/DT7D/s0J8WnZQZmRdrsZ3Ikj0Sv/4D2MJnCVJTSw
DHq5Sf7DmUq/WD0iWRLEXWmPt9w3WxP4imhtmIpICxCDoeQUTkqFpOTf29sVcpPt
838AEQEAAYkBHwQYAQIACQUCS5+6qwIbDAAKCRD6omNdPx1/0O8ECADAcPORjGFl
RnIrsgiVMp82GQ7hnZZxktU1WVVx8EsPTT1DD79nIoeKI+UcenzuOGyTX7DGcy+P
rWntUbt2ZygPTbP5Wu6zd845y9EzjxQ5q0vDF4oAefQptwqGDVeO/KBv9cZLbnih
VEjQELgC/rVB7nd5p83EL5vb8qL/Eiu65stxwZ3QOT9pp2bsAPk6LJWWnVqJroKI
Pc6KWG7n6mMJPbhFmE8Ld2lcNlSKQwLHIxDocL2GAqh5S5hJeGg2oLMFpy0g2Ron
643w0zPfpKC15TlnkJDCIgtRlHovrs42Qkypz9y3e8yOL9O0RLYIKbuKw4mNR3cT
OdeV+TjfiZ5I
=2oe6
-----END PGP PUBLIC KEY BLOCK-----

561
dsd/README.md 100644
Wyświetl plik

@ -0,0 +1,561 @@
# Digital Speech Decoder 1.7.0-dev
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.
### Supported formats
#### 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.
#### NXDN
Digital radio standard used by NEXEDGE and IDAS brands.
Supports both 9600 baud (12.5 kHz) and
4800 baud (6.25 kHz) digital voice.
Support includes decoding and synthesis of speech and
the ability to save and replay .amb data files.
#### D-STAR
Amateur radio digital voice standard
This is an earlier version of the AMBE codec than the one
used by most of the protocols. Support for this was added by
various developers.
### Unsupported formats in version 1.6 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.
### Supported demodulation optimizations in version 1.6:
#### 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.
There are some debugging/development options in `config.h` that
normal users will want to leave disabled as they can severely
impact performance.
### Requirements
* cmake
* mbelib
* sndfile
### Example building instructions on Ubuntu:
````
sudo apt-get update
sudo apt-get install git make cmake # Update packages
git clone <URL of git repository> # Something like: git@github.com:USERNAME/dsd.git
cd dsd # Move into source folder
mkdir build # Create build directory
cd build # Move to build directory
cmake .. # Create Makefile for current system
make # Compiles DSD
sudo make install # Installs DSD to the system
````
## 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 inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 0 tg: 32464 TDULC
Sync: -P25p1 mod: C4FM inlvl: 38% nac: 5C2 src: 0 tg: 32464 TDU
Sync: -P25p1 mod: C4FM inlvl: 38% nac: 5C2 src: 0 tg: 32464 HDU
Sync: -P25p1 mod: C4FM inlvl: 42% nac: 5C2 src: 0 tg: 32464 LDU1 e:
Sync: (-P25p1) mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 (LDU2) e:
Sync: -P25p1 mod: C4FM inlvl: 38% nac: 5C2 src: 52610 tg: 32464 LDU1 e:
Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e:
Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU1 e:
Sync: -P25p1 mod: C4FM inlvl: 39% nac: 5C2 src: 52610 tg: 32464 LDU2 e:
Sync: -P25p1 mod: C4FM inlvl: 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.
* "inlvl" 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 inlvl: 59% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
Sync: -X2-TDMA mod: QPSK inlvl: 47% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
Sync: -X2-TDMA mod: QPSK inlvl: 43% src: 17211 tg: 197 [SLOT0] slot1 VOICE e:
Sync: (-X2-TDMA) mod: QPSK inlvl: 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/file> Audio input device/file (default is /dev/audio)
-o <device> Audio output device (default is /dev/audio)
-d <dir> Create mbe data files, use this directory
-r <files> Read/Play saved mbe data from file(s)
-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 or TSDU
````
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*
-fi Decode only NXDN48* (6.25 kHz) / IDAS*
-fn Decode only NXDN96 (12.5 kHz)
-fp Decode only ProVoice*
-fr Decode only DMR/MOTOTRBO
-fx Decode only X2-TDMA
-l Disable Filters (not recommended)
-ma Auto-select modulation optimizations (default)
-mc Use only C4FM modulation optimizations
-mg Use only GFSK modulation optimizations
-mq Use only QPSK modulation optimizations
-pu Unmute Encrypted P25
-u <num> Unvoiced speech quality (default=3)
-xx Expect non-inverted X2-TDMA signal
-xr Expect inverted DMR/MOTOTRBO signal
````
\* denotes frame types that cannot be auto-detected.
ProVoice and NXDN48 not auto-detected as use different symbol
rates (9600 and 2400) than most formats (4800).
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.

Wyświetl plik

@ -0,0 +1,20 @@
# Find libmbe
FIND_PATH(LIBMBE_INCLUDE_DIR mbelib.h)
SET(LIBMBE_NAMES ${LIBMBE_NAMES} mbe libmbe)
FIND_LIBRARY(LIBMBE_LIBRARY NAMES ${LIBMBE_NAMES} PATH)
IF (LIBMBE_INCLUDE_DIR AND LIBMBE_LIBRARY)
SET(LIBMBE_FOUND TRUE)
ENDIF (LIBMBE_INCLUDE_DIR AND LIBMBE_LIBRARY)
IF (LIBMBE_FOUND)
IF (NOT LibMbe_FIND_QUIETLY)
MESSAGE (STATUS "Found LibMbe: ${LIBMBE_LIBRARY}")
ENDIF (NOT LibMbe_FIND_QUIETLY)
ELSE (LIBMBE_FOUND)
IF (LibMbe_FIND_REQUIRED)
MESSAGE (FATAL_ERROR "Could not find mbe")
ENDIF (LibMbe_FIND_REQUIRED)
ENDIF (LIBMBE_FOUND)

Wyświetl plik

@ -0,0 +1,21 @@
# Find libsndfile
FIND_PATH(LIBSNDFILE_INCLUDE_DIR sndfile.h)
SET(LIBSNDFILE_NAMES ${LIBSNDFILE_NAMES} sndfile libsndfile)
FIND_LIBRARY(LIBSNDFILE_LIBRARY NAMES ${LIBSNDFILE_NAMES} PATH)
IF (LIBSNDFILE_INCLUDE_DIR AND LIBSNDFILE_LIBRARY)
SET(LIBSNDFILE_FOUND TRUE)
ENDIF (LIBSNDFILE_INCLUDE_DIR AND LIBSNDFILE_LIBRARY)
IF (LIBSNDFILE_FOUND)
IF (NOT LibSndFile_FIND_QUIETLY)
MESSAGE (STATUS "Found LibSndFile: ${LIBSNDFILE_LIBRARY}")
ENDIF (NOT LibSndFile_FIND_QUIETLY)
add_definitions(-DUSE_LIBSNDFILE)
ELSE (LIBSNDFILE_FOUND)
IF (LibSndFile_FIND_REQUIRED)
MESSAGE (FATAL_ERROR "Could not find sndfile")
ENDIF (LibSndFile_FIND_REQUIRED)
ENDIF (LIBSNDFILE_FOUND)

Wyświetl plik

@ -0,0 +1,130 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_head_revision _refspecvar _hashvar)
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
# We have reached the root directory, we are not in git
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
return()
endif()
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
endwhile()
# check if this is a submodule
if(NOT IS_DIRECTORY ${GIT_DIR})
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${GIT_DIR}/HEAD")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
configure_file("cmake/git_revision.cmake.in"
"${GIT_DATA}/grabRef.cmake"
@ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(COMMAND
"${GIT_EXECUTABLE}"
describe
${hash}
${ARGN}
WORKING_DIRECTORY
"${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var} "${out}" PARENT_SCOPE)
endfunction()

Wyświetl plik

@ -0,0 +1,38 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
set(HEAD_HASH "${HEAD_REF}")
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

Wyświetl plik

@ -0,0 +1,23 @@
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
cmake_policy(SET CMP0007 OLD)
list(REVERSE files)
foreach (file ${files})
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
if (EXISTS "$ENV{DESTDIR}${file}")
execute_process(
COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
OUTPUT_VARIABLE rm_out
RESULT_VARIABLE rm_retval
)
if(NOT ${rm_retval} EQUAL 0)
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
endif (NOT ${rm_retval} EQUAL 0)
else (EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif (EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

32
dsd/config.h 100644
Wyświetl plik

@ -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
dsd/configure vendored 100755
Wyświetl plik

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

293
dsd/descramble.h 100644
Wyświetl plik

@ -0,0 +1,293 @@
/* descramble.h */
// Functions for processing the radio-header:
// descramble
// deinterleave
// FECdecoder
// (C) 2011 Jonathan Naylor G4KLX
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
// This code was originally written by JOnathan Naylor, G4KLX, as part
// of the "pcrepeatercontroller" project
// More info:
// http://groups.yahoo.com/group/pcrepeatercontroller
// Changes:
// Convert C++ to C
// Version 20111106: initial release
#include <stdio.h>
#include <string.h>
// function traceBack
int traceBack (int * out, int * m_pathMemory0, int * m_pathMemory1, int * m_pathMemory2, int * m_pathMemory3) {
enum FEC_STATE { S0, S1, S2, S3 } state;
int loop;
int length=0;
state=S0;
for (loop=329; loop >= 0; loop--, length++) {
switch (state) {
case S0: // if state S0
if (m_pathMemory0[loop]) {
state = S2; // lower path
} else {
state = S0; // upper path
}; // end else - if
out[loop]=0;
break;
case S1: // if state S1
if (m_pathMemory1[loop]) {
state = S2; // lower path
} else {
state = S0; // upper path
}; // end else - if
out[loop]=1;
break;
case S2: // if state S2
if (m_pathMemory2[loop]) {
state = S3; // lower path
} else {
state = S1; // upper path
}; // end else - if
out[loop]=0;
break;
case S3: // if state S3
if (m_pathMemory3[loop]) {
state = S3; // lower path
} else {
state = S1; // upper path
}; // end else - if
out[loop]=1;
break;
}; // end switch
}; // end for
return(length);
}; // end function
// function viterbiDecode
void viterbiDecode (int n, int *data, int *m_pathMemory0, int *m_pathMemory1, int *m_pathMemory2, int *m_pathMemory3, int *m_pathMetric) {
int tempMetric[4];
int metric[8];
int loop;
int m1;
int m2;
metric[0]=(data[1]^0)+(data[0]^0);
metric[1]=(data[1]^1)+(data[0]^1);
metric[2]=(data[1]^1)+(data[0]^0);
metric[3]=(data[1]^0)+(data[0]^1);
metric[4]=(data[1]^1)+(data[0]^1);
metric[5]=(data[1]^0)+(data[0]^0);
metric[6]=(data[1]^0)+(data[0]^1);
metric[7]=(data[1]^1)+(data[0]^0);
// Pres. state = S0, Prev. state = S0 & S2
m1=metric[0]+m_pathMetric[0];
m2=metric[4]+m_pathMetric[2];
if (m1<m2) {
m_pathMemory0[n]=0;
tempMetric[0]=m1;
} else {
m_pathMemory0[n]=1;
tempMetric[0]=m2;
}; // end else - if
// Pres. state = S1, Prev. state = S0 & S2
m1=metric[1]+m_pathMetric[0];
m2=metric[5]+m_pathMetric[2];
if (m1<m2) {
m_pathMemory1[n]=0;
tempMetric[1]=m1;
} else {
m_pathMemory1[n]=1;
tempMetric[1]=m2;
}; // end else - if
// Pres. state = S2, Prev. state = S2 & S3
m1=metric[2]+m_pathMetric[1];
m2=metric[6]+m_pathMetric[3];
if (m1<m2) {
m_pathMemory2[n]=0;
tempMetric[2]=m1;
} else {
m_pathMemory2[n]=1;
tempMetric[2]=m2;
}
// Pres. state = S3, Prev. state = S1 & S3
m1=metric[3]+m_pathMetric[1];
m2=metric[7]+m_pathMetric[3];
if (m1 < m2) {
m_pathMemory3[n]=0;
tempMetric[3]=m1;
} else {
m_pathMemory3[n]=1;
tempMetric[3]=m2;
}; // end else - if
for (loop=0;loop<4;loop++) {
m_pathMetric[loop]=tempMetric[loop];
}; // end for
}; // end function ViterbiDecode
// function FECdecoder
// returns outlen
int FECdecoder (int * in, int * out) {
int outLen;
int m_pathMemory0[330]; memset(m_pathMemory0,0,330*sizeof(int));
int m_pathMemory1[330]; memset(m_pathMemory1,0,330*sizeof(int));
int m_pathMemory2[330]; memset(m_pathMemory2,0,330*sizeof(int));
int m_pathMemory3[330]; memset(m_pathMemory3,0,330*sizeof(int));
int m_pathMetric[4];
int loop,loop2;
int n=0;
for (loop=0;loop<4;loop++) {
m_pathMetric[loop]=0;
}; // end for
for (loop2=0;loop2<660;loop2+=2, n++) {
int data[2];
if (in[loop2]) {
data[1]=1;
} else {
data[1]=0;
}; // end else - if
if (in[loop2+1]) {
data[0]=1;
} else {
data[0]=0;
}; // end else - if
viterbiDecode(n, data, m_pathMemory0, m_pathMemory1, m_pathMemory2, m_pathMemory3, m_pathMetric);
}; // end for
outLen=traceBack(out, m_pathMemory0, m_pathMemory1, m_pathMemory2, m_pathMemory3);
// Swap endian-ness
// code removed (done converting bits into octets), done in main program
//for (loop=0;loop<330;loop+=8) {
// int temp;
// temp=out[loop];out[loop]=out[loop+7];out[loop+7]=temp;
// temp=out[loop+1];out[loop+1]=out[loop+6];out[loop+6]=temp;
// temp=out[loop+2];out[loop+2]=out[loop+5];out[loop+5]=temp;
// temp=out[loop+3];out[loop+3]=out[loop+4];out[loop+4]=temp;
//}
return(outLen);
}; // end function FECdecoder
// function deinterleave
void deinterleave (int * in, int * out) {
int k=0;
int loop=0;
// function starts here
// init vars
k=0;
for (loop=0;loop<660;loop++) {
out[k]=in[loop];
k += 24;
if (k >= 672) {
k -= 671;
} else if (k >= 660) {
k -= 647;
}; // end elsif - if
}; // end for
}; // end function deinterleave
/// function scramble
void scramble (int * in,int * out) {
static const int SCRAMBLER_TABLE_BITS[] = {
0,0,0,0,1,1,1,0,1,1,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,
0,0,1,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,
1,1,0,1,0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,1,0,1,0,
1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,
0,0,0,1,1,1,0,1,1,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,
0,1,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,1,
1,0,1,0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,1,0,1,0,1,
1,1,1,1,0,1,0,0,1,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,
0,0,1,1,1,0,1,1,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,
1,0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,1,1,
0,1,0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,1,0,1,0,1,1,
1,1,1,0,1,0,0,1,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,
0,1,1,1,0,1,1,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,
0,0,1,1,0,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,1,1,0,
1,0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,1,0,1,0,1,1,1,
1,1,0,1,0,0,1,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,
1,1,1,0,1,1,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,
0,1,1,0,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,1,1,0,1,
0,1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,1,0,1,0,1,1,1,1,
1,0,1,0,0,1,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,
1,1,0,1,1,1,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,
1,1,0,0,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,1,1,0,1,0,
1,0,0,1,1,1,0,0,1,1,1,1,0,1,1,0};
const int SCRAMBLER_TABLE_BITS_LENGTH=720;
int loop=0;
int m_count=0;
for (loop=0; loop < 660; loop++) {
out[loop] = in[loop] ^ SCRAMBLER_TABLE_BITS[m_count++];
if (m_count >= SCRAMBLER_TABLE_BITS_LENGTH) {
m_count = 0U;
}; // end if
}; // end for
}; // end function scramble

64
dsd/dmr_const.h 100644
Wyświetl plik

@ -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

240
dsd/dmr_data.c 100644
Wyświetl plik

@ -0,0 +1,240 @@
/*
* 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_BS_DATA_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_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);
}
}
}

382
dsd/dmr_voice.c 100644
Wyświetl plik

@ -0,0 +1,382 @@
/*
* 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;
int msMode;
#ifdef DMR_DUMP
int k;
char syncbits[49];
char cachbits[25];
#endif
mutecurrentslot = 0;
msMode = 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_BS_DATA_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0))
{
mutecurrentslot = 1;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[slot0]");
}
else
{
sprintf (state->slot1light, "[slot1]");
}
}
else if ((strcmp (sync, DMR_BS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_VOICE_SYNC) == 0))
{
mutecurrentslot = 0;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[SLOT0]");
}
else
{
sprintf (state->slot1light, "[SLOT1]");
}
}
if ((strcmp (sync, DMR_MS_VOICE_SYNC) == 0) || (strcmp (sync, DMR_MS_DATA_SYNC) == 0))
{
msMode = 1;
}
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_BS_DATA_SYNC) == 0) || (msMode == 1))
{
if (state->currentslot == 0)
{
sprintf (state->slot1light, " slot1 ");
}
else
{
sprintf (state->slot0light, " slot0 ");
}
}
else if (strcmp (sync, DMR_BS_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");
}
}

159
dsd/dsd.h 100644
Wyświetl plik

@ -0,0 +1,159 @@
#ifndef DSD_H
#define DSD_H
/*
* 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 <signal.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
#if defined(BSD) && !defined(__APPLE__)
#include <sys/soundcard.h>
#endif
#include <math.h>
#include <mbelib.h>
#include <sndfile.h>
#include "p25p1_heuristics.h"
#define SAMPLE_RATE_IN 48000
#define SAMPLE_RATE_OUT 8000
#ifdef USE_PORTAUDIO
#include "portaudio.h"
#define PA_FRAMES_PER_BUFFER 64
//Buffer needs to be large enough to prevent input buffer overruns while DSD is doing other struff (like outputting voice)
//else you get skipped samples which result in incomplete/erronous decodes and a mountain of error messages.
#define PA_LATENCY_IN 0.500
//Buffer needs to be large enough to prevent output buffer underruns while DSD is doing other stuff (like decoding input)
//else you get choppy audio and in 'extreme' cases errors.
//Buffer also needs to be as small as possible so we don't have a lot of audio delay.
#define PA_LATENCY_OUT 0.100
#endif
/*
* global variables
*/
int exitflag;
#include "dsd_opts.h"
#include "dsd_state.h"
#include "dsd_livescanner.h"
/*
* Frame sync patterns
*/
#define INV_P25P1_SYNC "333331331133111131311111"
#define P25P1_SYNC "111113113311333313133333"
#define X2TDMA_BS_VOICE_SYNC "113131333331313331113311"
#define X2TDMA_BS_DATA_SYNC "331313111113131113331133"
#define X2TDMA_MS_DATA_SYNC "313113333111111133333313"
#define X2TDMA_MS_VOICE_SYNC "131331111333333311111131"
#define DSTAR_HD "131313131333133113131111"
#define INV_DSTAR_HD "313131313111311331313333"
#define DSTAR_SYNC "313131313133131113313111"
#define INV_DSTAR_SYNC "131313131311313331131333"
#define NXDN_MS_DATA_SYNC "313133113131111333"
#define INV_NXDN_MS_DATA_SYNC "131311331313333111"
#define NXDN_MS_VOICE_SYNC "313133113131113133"
#define INV_NXDN_MS_VOICE_SYNC "131311331313331311"
#define INV_NXDN_BS_DATA_SYNC "131311331313333131"
#define NXDN_BS_DATA_SYNC "313133113131111313"
#define INV_NXDN_BS_VOICE_SYNC "131311331313331331"
#define NXDN_BS_VOICE_SYNC "313133113131113113"
#define DMR_BS_DATA_SYNC "313333111331131131331131"
#define DMR_BS_VOICE_SYNC "131111333113313313113313"
#define DMR_MS_DATA_SYNC "311131133313133331131113"
#define DMR_MS_VOICE_SYNC "133313311131311113313331"
#define INV_PROVOICE_SYNC "31313111333133133311331133113311"
#define PROVOICE_SYNC "13131333111311311133113311331133"
#define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311"
#define PROVOICE_EA_SYNC "31131311331331111133131311311133"
/*
* 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);
int get_dibit_and_analog_signal (dsd_opts * opts, dsd_state * state, int * out_analog_signal);
void skipDibit (dsd_opts * opts, dsd_state * state, int count);
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
void saveAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
int readImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
int readAmbe2450Data (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 closeWavOutFile (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 usage ();
void sigfun (int sig);
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 processNXDNVoice (dsd_opts * opts, dsd_state * state);
void processNXDNData (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 processTDU (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);
void processDSTAR_HD (dsd_opts * opts, dsd_state * state);
short dmr_filter(short sample);
short nxdn_filter(short sample);
#endif // DSD_H

440
dsd/dsd_audio.c 100644
Wyświetl plik

@ -0,0 +1,440 @@
/*
* 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 > 24)
{
state->aout_max_buf_idx = 0;
state->aout_max_buf_p = state->aout_max_buf;
}
// lookup max history
for (i = 0; i < 25; 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;
}
if(opts->audio_gain >= 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)
{
#ifdef USE_LIBSNDFILE
int n;
short aout_buf[160];
short *aout_buf_p;
// for(n=0; n<160; n++)
// printf("%d ", ((short*)(state->audio_out_temp_buf))[n]);
// printf("\n");
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) 32767)
{
*state->audio_out_temp_buf_p = (float) 32767;
}
else if (*state->audio_out_temp_buf_p < (float) -32768)
{
*state->audio_out_temp_buf_p = (float) -32768;
}
*aout_buf_p = (short) *state->audio_out_temp_buf_p;
aout_buf_p++;
state->audio_out_temp_buf_p++;
}
sf_write_short(opts->wav_out_f, aout_buf, 160);
/*
int n;
short aout_buf[160];
short *aout_buf_p;
ssize_t result;
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++;
}
result = write (opts->wav_out_fd, aout_buf, 320);
fflush (opts->wav_out_f);
state->wav_out_bytes += 320;
*/
#endif
}
void
playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
{
ssize_t result;
if (state->audio_out_idx > opts->delay)
{
// output synthesized speech to sound card
if (opts->audio_out_fd == -1)
{
memcpy(state->output_buffer + state->output_offset, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2));
state->output_offset += state->audio_out_idx;
}
else
{
result = 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)
{
// get info of device/file
struct stat stat_buf;
if(stat(opts->audio_out_dev, &stat_buf) != 0) {
printf("Error, couldn't open %s\n", opts->audio_out_dev);
exit(1);
}
if( !(S_ISCHR(stat_buf.st_mode) || S_ISBLK(stat_buf.st_mode))) { // this is not a device
printf("Error, %s is not a device. use -w filename for wav output.\n", opts->audio_out_dev);
exit(1);
}
#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
#if defined(BSD) && !defined(__APPLE__) && defined(USE_LIBSNDFILE)
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;
exit(1);
}
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 USE_LIBSNDFILE
// get info of device/file
struct stat stat_buf;
if (stat(opts->audio_in_dev, &stat_buf) != 0) {
printf("Error, couldn't open %s\n", opts->audio_in_dev);
exit(1);
}
if(S_ISREG(stat_buf.st_mode)) { // is this a regular file? then process with libsndfile.
opts->audio_in_type = 1;
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->channels = 1;
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
if(opts->audio_in_file == NULL) {
printf ("Error, couldn't open file %s\n", opts->audio_in_dev);
exit(1);
}
}
else { // this is a device, use old handling
opts->audio_in_type = 0;
#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 %s\n", opts->audio_in_dev);
exit(1);
}
// 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
#if defined(BSD) && !defined(__APPLE__)
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);
}
#endif
}

Wyświetl plik

@ -0,0 +1,36 @@
/*
* 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_cleanupexit.h"
#include "dsd_nocarrier.h"
#include "dsd.h"
void
cleanupAndExit (dsd_opts * opts, dsd_state * state)
{
noCarrier (opts, state);
#ifdef USE_LIBSNDFILE
if (opts->wav_out_f != NULL)
{
closeWavOutFile (opts, state);
}
#endif
printf ("Exiting.\n");
exit (0);
}

Wyświetl plik

@ -0,0 +1,26 @@
/*
* 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 INCLUDE_DSD_CLEANUPEXIT_H_
#define INCLUDE_DSD_CLEANUPEXIT_H_
#include "dsd_opts.h"
#include "dsd_state.h"
void cleanupAndExit(dsd_opts * opts, dsd_state * state);
#endif /* INCLUDE_DSD_CLEANUPEXIT_H_ */

295
dsd/dsd_dibit.c 100644
Wyświetl plik

@ -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"
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++;
}
if (state->dibit_buf_p > state->dibit_buf + 900000)
{
state->dibit_buf_p = state->dibit_buf + 200;
}
// determine dibit state
if ((state->synctype == 6) || (state->synctype == 14)|| (state->synctype == 18))
{
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)|| (state->synctype == 19))
{
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);
}
}

362
dsd/dsd_file.c 100644
Wyświetl plik

@ -0,0 +1,362 @@
/*
* 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
saveAmbe2450Data (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
readAmbe2450Data (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 & 1);
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;
int result;
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);
}
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);
}
tgid[16] = 0;
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);
result = system (shell);
state->tgcount = 0;
for (i = 0; i < 25; i++)
{
for (j = 0; j < 16; j++)
{
state->tg[i][j] = 48;
}
}
}
}
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");
SF_INFO info;
info.samplerate = 8000;
info.channels = 1;
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
opts->wav_out_f = sf_open (opts->wav_out_file, SFM_WRITE, &info);
if (opts->wav_out_f == NULL)
{
printf ("Error - could not open wav output file %s\n", opts->wav_out_file);
return;
}
// state->wav_out_bytes = 0;
}
void
closeWavOutFile (dsd_opts * opts, dsd_state * state)
{
sf_close(opts->wav_out_f);
/*
int length;
if (opts->wav_out_f != NULL)
{
rewind (opts->wav_out_f);
length = state->wav_out_bytes;
fprintf (opts->wav_out_f, "RIFF");
// total length
fputc (((36 + length) & 0xff), opts->);
fputc ((((36 + length) >> 8) & 0xff), opts->wav_out_f);
fputc ((((36 + length) >> 16) & 0xff), opts->wav_out_f);
fputc ((((36 + length) >> 24) & 0xff), 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 (128, opts->wav_out_f);
fputc (62, opts->wav_out_f);
fputc (0, opts->wav_out_f);
fputc (0, opts->wav_out_f);
// block align
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 ((length & 0xff), opts->wav_out_f);
fputc (((length >> 8) & 0xff), opts->wav_out_f);
fputc (((length >> 16) & 0xff), opts->wav_out_f);
fputc (((length >> 24) & 0xff), opts->wav_out_f);
fflush (opts->wav_out_f);
}
*/
}

116
dsd/dsd_filters.c 100644
Wyświetl plik

@ -0,0 +1,116 @@
// DMR filter
#define NZEROS 60
float ngain = 7.423339364f;
static float xv[NZEROS+1];
float xcoeffs[] =
{ -0.0083649323f, -0.0265444850f, -0.0428141462f, -0.0537571943f,
-0.0564141052f, -0.0489161045f, -0.0310068662f, -0.0043393881f,
+0.0275375106f, +0.0595423283f, +0.0857543325f, +0.1003565948f,
+0.0986944931f, +0.0782804830f, +0.0395670487f, -0.0136691535f,
-0.0744390415f, -0.1331834575f, -0.1788967208f, -0.2005995448f,
-0.1889627181f, -0.1378439993f, -0.0454976231f, +0.0847488694f,
+0.2444859269f, +0.4209222342f, +0.5982295474f, +0.7593684540f,
+0.8881539892f, +0.9712773915f, +0.9999999166f, +0.9712773915f,
+0.8881539892f, +0.7593684540f, +0.5982295474f, +0.4209222342f,
+0.2444859269f, +0.0847488694f, -0.0454976231f, -0.1378439993f,
-0.1889627181f, -0.2005995448f, -0.1788967208f, -0.1331834575f,
-0.0744390415f, -0.0136691535f, +0.0395670487f, +0.0782804830f,
+0.0986944931f, +0.1003565948f, +0.0857543325f, +0.0595423283f,
+0.0275375106f, -0.0043393881f, -0.0310068662f, -0.0489161045f,
-0.0564141052f, -0.0537571943f, -0.0428141462f, -0.0265444850f,
-0.0083649323f,
};
// NXDN filter
#define NXZEROS 134
float nxgain = 15.95930463f;
static float nxv[NXZEROS+1];
float nxcoeffs[] =
{ +0.031462429f, +0.031747267f, +0.030401148f, +0.027362877f,
+0.022653298f, +0.016379869f, +0.008737200f, +0.000003302f,
-0.009468531f, -0.019262057f, -0.028914291f, -0.037935027f,
-0.045828927f, -0.052119261f, -0.056372283f, -0.058221106f,
-0.057387924f, -0.053703443f, -0.047122444f, -0.037734535f,
-0.025769308f, -0.011595336f, +0.004287292f, +0.021260954f,
+0.038610717f, +0.055550276f, +0.071252765f, +0.084885375f,
+0.095646450f, +0.102803611f, +0.105731303f, +0.103946126f,
+0.097138329f, +0.085197939f, +0.068234131f, +0.046586711f,
+0.020828821f, -0.008239664f, -0.039608255f, -0.072081234f,
-0.104311776f, -0.134843790f, -0.162160200f, -0.184736015f,
-0.201094346f, -0.209863285f, -0.209831516f, -0.200000470f,
-0.179630919f, -0.148282051f, -0.105841323f, -0.052543664f,
+0.011020985f, +0.083912428f, +0.164857408f, +0.252278939f,
+0.344336996f, +0.438979335f, +0.534000832f, +0.627109358f,
+0.715995947f, +0.798406824f, +0.872214756f, +0.935487176f,
+0.986548646f, +1.024035395f, +1.046939951f, +1.054644241f,
+1.046939951f, +1.024035395f, +0.986548646f, +0.935487176f,
+0.872214756f, +0.798406824f, +0.715995947f, +0.627109358f,
+0.534000832f, +0.438979335f, +0.344336996f, +0.252278939f,
+0.164857408f, +0.083912428f, +0.011020985f, -0.052543664f,
-0.105841323f, -0.148282051f, -0.179630919f, -0.200000470f,
-0.209831516f, -0.209863285f, -0.201094346f, -0.184736015f,
-0.162160200f, -0.134843790f, -0.104311776f, -0.072081234f,
-0.039608255f, -0.008239664f, +0.020828821f, +0.046586711f,
+0.068234131f, +0.085197939f, +0.097138329f, +0.103946126f,
+0.105731303f, +0.102803611f, +0.095646450f, +0.084885375f,
+0.071252765f, +0.055550276f, +0.038610717f, +0.021260954f,
+0.004287292f, -0.011595336f, -0.025769308f, -0.037734535f,
-0.047122444f, -0.053703443f, -0.057387924f, -0.058221106f,
-0.056372283f, -0.052119261f, -0.045828927f, -0.037935027f,
-0.028914291f, -0.019262057f, -0.009468531f, +0.000003302f,
+0.008737200f, +0.016379869f, +0.022653298f, +0.027362877f,
+0.030401148f, +0.031747267f, +0.031462429f,
};
short dsd_input_filter(short sample, int mode);
short
dmr_filter(short sample)
{
return dsd_input_filter(sample, 1);
}
short
nxdn_filter(short sample)
{
return dsd_input_filter(sample, 2);
}
short
dsd_input_filter(short sample, int mode)
{
float sum; int i;
float gain;
int zeros;
float *v, *coeffs;
switch(mode) {
case 1:
gain = ngain;
v = xv;
coeffs = xcoeffs;
zeros = NZEROS;
break;
case 2:
gain = nxgain;
v = nxv;
coeffs = nxcoeffs;
zeros = NXZEROS;
break;
default:
return sample;
}
for (i = 0; i < zeros; i++)
v[i] = v[i+1];
v[zeros] = sample; // unfiltered sample in
sum = 0.0f;
for (i = 0; i <= zeros; i++)
sum += (coeffs[i] * v[i]);
return sum / ngain; // filtered sample out
}

474
dsd/dsd_frame.c 100644
Wyświetl plik

@ -0,0 +1,474 @@
/*
* 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"
#if !defined(NULL)
#define NULL 0
#endif
void
printFrameInfo (dsd_opts * opts, dsd_state * state)
{
int level;
level = (int) state->max / 164;
if (opts->verbose > 0)
{
printf ("inlvl: %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->rf_mod = 2;
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " VOICE ");
processNXDNVoice (opts, state);
return;
}
else if ((state->synctype == 16) || (state->synctype == 17))
{
state->rf_mod = 2;
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " DATA ");
processNXDNData (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) state->max / 164;
printf ("inlvl: %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 == 18) || (state->synctype == 19))
{
state->nac = 0;
state->lastsrc = 0;
state->lasttg = 0;
if (opts->errorbars == 1)
{
if (opts->verbose > 0)
{
level = (int) state->max / 164;
printf ("inlvl: %2i%% ", level);
}
}
state->nac = 0;
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
{
openMbeOutFile (opts, state);
}
sprintf (state->fsubtype, " DATA ");
processDSTAR_HD (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) state->max / 164;
printf ("inlvl: %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;
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) state->max / 164;
printf ("inlvl: %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");
}
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");
}
if (opts->mbe_out_dir[0] != 0)
{
closeMbeOutFile (opts, state);
}
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
state->lasttg = 0;
state->lastsrc = 0;
state->lastp25type = 0;
state->err_str[0] = 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");
}
if (opts->mbe_out_dir[0] != 0)
{
closeMbeOutFile (opts, state);
}
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
state->lasttg = 0;
state->lastsrc = 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");
}
if (opts->resume > 0)
{
resumeScan (opts, state);
}
state->lasttg = 0;
state->lastsrc = 0;
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);
}
}
}

Wyświetl plik

@ -0,0 +1,830 @@
/*
* 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 "dsd_cleanupexit.h"
#include "dsd_nocarrier.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 = +NXDN (non inverted voice frame)
* 9 = -NXDN (inverted voice frame)
* 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
* 16 = +NXDN (non inverted data frame)
* 17 = -NXDN (inverted data frame)
* 18 = +D-STAR_HD
* 19 = -D-STAR_HD
*/
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];
for (i = 18; i < 24; i++)
{
lbuf[i] = 0;
lbuf2[i] = 0;
}
// detect frame sync
t = 0;
synctest[24] = 0;
synctest18[18] = 0;
synctest32[32] = 0;
synctest_pos = 0;
synctest_p = synctest_buf + 10;
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++;
}
if (state->dibit_buf_p > state->dibit_buf + 900000)
{
state->dibit_buf_p = state->dibit_buf + 200;
}
//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;
}
*synctest_p = dibit;
if (t >= 18)
{
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, P25P1_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_P25P1_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_BS_DATA_SYNC) == 0) || (strcmp (synctest, X2TDMA_MS_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_BS_VOICE_SYNC) == 0) || (strcmp (synctest, X2TDMA_MS_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_MS_DATA_SYNC) == 0) || (strcmp (synctest, DMR_BS_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_MS_VOICE_SYNC) == 0) || (strcmp (synctest, DMR_BS_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) || (strcmp (synctest32, PROVOICE_EA_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) || (strcmp (synctest32, INV_PROVOICE_EA_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_nxdn96 == 1) || (opts->frame_nxdn48 == 1))
{
strncpy (synctest18, (synctest_p - 17), 18);
if ((strcmp (synctest18, NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_VOICE_SYNC) == 0))
{
if ((state->lastsynctype == 8) || (state->lastsynctype == 16))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->samplesPerSymbol == 20)
{
sprintf (state->ftype, " NXDN48 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation);
}
}
else
{
sprintf (state->ftype, " NXDN96 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation);
}
}
state->lastsynctype = 8;
return (8);
}
else
{
state->lastsynctype = 8;
}
}
else if ((strcmp (synctest18, INV_NXDN_BS_VOICE_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_VOICE_SYNC) == 0))
{
if ((state->lastsynctype == 9) || (state->lastsynctype == 17))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->samplesPerSymbol == 20)
{
sprintf (state->ftype, " NXDN48 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation);
}
}
else
{
sprintf (state->ftype, " NXDN96 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation);
}
}
state->lastsynctype = 9;
return (9);
}
else
{
state->lastsynctype = 9;
}
}
else if ((strcmp (synctest18, NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, NXDN_MS_DATA_SYNC) == 0))
{
if ((state->lastsynctype == 8) || (state->lastsynctype == 16))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
if (state->samplesPerSymbol == 20)
{
sprintf (state->ftype, " NXDN48 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +NXDN48 ", synctest_pos + 1, modulation);
}
}
else
{
sprintf (state->ftype, " NXDN96 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +NXDN96 ", synctest_pos + 1, modulation);
}
}
state->lastsynctype = 16;
return (16);
}
else
{
state->lastsynctype = 16;
}
}
else if ((strcmp (synctest18, INV_NXDN_BS_DATA_SYNC) == 0) || (strcmp (synctest18, INV_NXDN_MS_DATA_SYNC) == 0))
{
if ((state->lastsynctype == 9) || (state->lastsynctype == 17))
{
state->carrier = 1;
state->offset = synctest_pos;
state->max = ((state->max) + lmax) / 2;
state->min = ((state->min) + lmin) / 2;
sprintf (state->ftype, " NXDN ");
if (state->samplesPerSymbol == 20)
{
sprintf (state->ftype, " NXDN48 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation);
}
}
else
{
sprintf (state->ftype, " NXDN96 ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation);
}
}
state->lastsynctype = 17;
return (17);
}
else
{
state->lastsynctype = 17;
}
}
}
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 (strcmp (synctest, DSTAR_HD) == 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_HD ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " +D-STAR_HD ", synctest_pos + 1, modulation);
}
state->lastsynctype = 18;
return (18);
}
if (strcmp (synctest, INV_DSTAR_HD) == 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_HD ");
if (opts->errorbars == 1)
{
printFrameSync (opts, state, " -D-STAR_HD ", synctest_pos + 1, modulation);
}
state->lastsynctype = 19;
return (19);
}
}
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_BS_VOICE_SYNC) != 0) || (strcmp (synctest, X2TDMA_MS_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_BS_DATA_SYNC) != 0) || (strcmp (synctest, X2TDMA_MS_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_BS_VOICE_SYNC) != 0) || (strcmp (synctest, DMR_MS_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_BS_DATA_SYNC) != 0) || (strcmp (synctest, DMR_MS_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 (exitflag == 1)
{
cleanupAndExit (opts, state);
}
if (synctest_pos < 10200)
{
synctest_pos++;
synctest_p++;
}
else
{
// buffer reset
synctest_pos = 0;
synctest_p = synctest_buf;
noCarrier (opts, state);
}
if (state->lastsynctype != 1)
{
if (synctest_pos >= 1800)
{
if ((opts->errorbars == 1) && (opts->verbose > 1) && (state->carrier == 1))
{
printf ("Sync: no sync\n");
}
noCarrier (opts, state);
return (-1);
}
}
}
return (-1);
}

Wyświetl plik

@ -0,0 +1,71 @@
/*
* 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 <string.h>
#include "dsd.h"
#include "dsd_nocarrier.h"
void liveScanner(dsd_opts * opts, dsd_state * state)
{
#ifdef USE_PORTAUDIO
if(opts->audio_in_type == 2)
{
PaError err = Pa_StartStream( opts->audio_in_pa_stream );
if( err != paNoError )
{
fprintf( stderr, "An error occured while starting the portaudio input stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return;
}
}
#endif
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);
#ifdef TRACE_DSD
state->debug_prefix = 'S';
#endif
state->synctype = getFrameSync(opts, state);
#ifdef TRACE_DSD
state->debug_prefix = '\0';
#endif
// 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;
}
}
}

Wyświetl plik

@ -0,0 +1,26 @@
/*
* 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 INCLUDE_DSD_LIVESCANNER_H_
#define INCLUDE_DSD_LIVESCANNER_H_
#include "dsd_opts.h"
#include "dsd_state.h"
void liveScanner (dsd_opts * opts, dsd_state * state);
#endif /* INCLUDE_DSD_LIVESCANNER_H_ */

737
dsd/dsd_main.c 100644
Wyświetl plik

@ -0,0 +1,737 @@
/*
* 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 "nxdn_const.h"
#include "dmr_const.h"
#include "provoice_const.h"
#include "git_ver.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->errs = 0;
state->errs2 = 0;
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_nxdn48 = 0;
opts->frame_nxdn96 = 1;
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;
opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 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->wav_out_bytes = 0;
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 (i = 0; i < 25; i++)
{
for (j = 0; j < 16; j++)
{
state->tg[i][j] = 48;
}
}
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);
state->p25kid = 0;
}
void
usage ()
{
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 (" -r <files> Read/Play saved mbe data from file(s)\n");
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\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 or TSDU\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\n");
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
printf (" -fn Decode only NXDN96 (12.5 kHz)\n");
printf (" -fp Decode only ProVoice*\n");
printf (" -fr Decode only DMR/MOTOTRBO\n");
printf (" -fx Decode only X2-TDMA\n");
printf (" -l Disable DMR/MOTOTRBO and NXDN input filtering\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 (" -pu Unmute Encrypted P25\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)
{
if (opts->audio_in_fd == -1)
{
if (pthread_mutex_lock(&state->input_mutex))
{
printf("liveScanner -> Unable to lock mutex\n");
}
}
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;
}
}
}
void
cleanupAndExit (dsd_opts * opts, dsd_state * state)
{
noCarrier (opts, state);
if (opts->wav_out_f != NULL)
{
closeWavOutFile (opts, state);
}
printf ("Exiting.\n");
exit (0);
}
void
sigfun (int sig)
{
exitflag = 1;
signal (SIGINT, SIG_DFL);
}
int
main (int argc, char **argv)
{
int c;
extern char *optarg;
extern int optind, opterr, optopt;
dsd_opts opts;
dsd_state state;
char versionstr[25];
mbe_printVersion (versionstr);
printf ("Digital Speech Decoder 1.7.0-dev (build:%s)\n", GIT_TAG);
printf ("mbelib version %s\n", versionstr);
initOpts (&opts);
initState (&state);
exitflag = 0;
signal (SIGINT, sigfun);
while ((c = getopt (argc, argv, "hep:qstv:z:i:o:d:g:nw:B:C:R:f:m:u:x:A:S:M:rl")) != -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;
}
else if (optarg[0] == 'u')
{
opts.unmute_encrypted_p25 = 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':
strncpy(opts.audio_in_dev, optarg, 1023);
opts.audio_in_dev[1023] = '\0';
break;
case 'o':
strncpy(opts.audio_out_dev, optarg, 1023);
opts.audio_out_dev[1023] = '\0';
break;
case 'd':
strncpy(opts.mbe_out_dir, optarg, 1023);
opts.mbe_out_dir[1023] = '\0';
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 )
{
printf ("Disabling audio out gain setting\n");
}
else 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':
strncpy(opts.wav_out_file, optarg, 1023);
opts.wav_out_file[1023] = '\0';
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':
strncpy(opts.serial_dev, optarg, 1023);
opts.serial_dev[1023] = '\0';
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 = 1;
opts.frame_x2tdma = 1;
opts.frame_p25p1 = 1;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 1;
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_nxdn48 = 0;
opts.frame_nxdn96 = 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_nxdn48 = 0;
opts.frame_nxdn96 = 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_nxdn48 = 0;
opts.frame_nxdn96 = 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 ("Setting symbol rate to 9600 / second\n");
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_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
printf ("Decoding only P25 Phase 1 frames.\n");
}
else if (optarg[0] == 'i')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn48 = 1;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
state.samplesPerSymbol = 20;
state.symbolCenter = 10;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
printf ("Setting symbol rate to 2400 / second\n");
printf ("Enabling only GFSK modulation optimizations.\n");
printf ("Decoding only NXDN 4800 baud frames.\n");
}
else if (optarg[0] == 'n')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 1;
opts.frame_dmr = 0;
opts.frame_provoice = 0;
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 NXDN 9600 baud frames.\n");
}
else if (optarg[0] == 'r')
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 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;
case 'l':
opts.use_cosine_filter = 0;
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;
if(strlen(opts.wav_out_file) > 0) {
openWavOutFile (&opts, &state);
}
else {
openAudioOutDevice (&opts, 8000);
}
}
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
{
opts.split = 1;
opts.playoffset = 0;
opts.delay = 0;
if(strlen(opts.wav_out_file) > 0) {
openWavOutFile (&opts, &state);
}
else {
openAudioOutDevice (&opts, 8000);
}
openAudioInDevice (&opts);
}
else
{
opts.split = 0;
opts.playoffset = 25; // 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);
}
cleanupAndExit (&opts, &state);
return (0);
}

151
dsd/dsd_mbe.c 100644
Wyświetl plik

@ -0,0 +1,151 @@
/*
* 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 "dsd_cleanupexit.h"
void
playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
{
#ifdef USE_LIBSNDFILE
int i;
char imbe_d[88];
char ambe_d[49];
for (i = state->optind; i < argc; i++)
{
sprintf (opts->mbe_in_file, "%s", 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_f != NULL)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out != 1)
{
playSynthesizedVoice (opts, state);
}
}
else if (state->mbe_file_type == 1)
{
readAmbe2450Data (opts, state, ambe_d);
mbe_processAmbe2450Dataf (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_f != NULL)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}
if (exitflag == 1)
{
cleanupAndExit (opts, state);
}
}
}
#endif
}
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];
#ifdef AMBE_PACKET_OUT
char ambe_d_str[50];
#endif
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 if ((state->synctype == 6) || (state->synctype == 7))
{
mbe_processAmbe3600x2400Framef (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)
{
saveAmbe2450Data (opts, state, ambe_d);
}
}
else
{
mbe_processAmbe3600x2450Framef (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);
#ifdef AMBE_PACKET_OUT
for(i=0; i<49; i++) {
ambe_d_str[i] = ambe_d[i] + '0';
}
ambe_d_str[49] = '\0';
// print binary string
fprintf(stderr, "\n?\t?\t%s\t", ambe_d_str);
// print error data
fprintf(stderr, "E1: %d; E2: %d; S: %s", state->errs, state->errs2, state->err_str);
#endif
if (opts->mbe_out_f != NULL)
{
saveAmbe2450Data (opts, state, ambe_d);
}
}
if (opts->errorbars == 1)
{
printf ("%s", state->err_str);
}
processAudio (opts, state);
#ifdef USE_LIBSNDFILE
if (opts->wav_out_f != NULL)
{
writeSynthesizedVoice (opts, state);
}
#endif
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}

Wyświetl plik

@ -0,0 +1,60 @@
/*
* 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 <string.h>
#include "dsd_nocarrier.h"
#include "dsd.h"
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->errs = 0;
state->errs2 = 0;
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);
}

Wyświetl plik

@ -0,0 +1,26 @@
/*
* 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 INCLUDE_DSD_NOCARRIER_H_
#define INCLUDE_DSD_NOCARRIER_H_
#include "dsd_opts.h"
#include "dsd_state.h"
void noCarrier(dsd_opts * opts, dsd_state * state);
#endif /* INCLUDE_DSD_NOCARRIER_H_ */

82
dsd/dsd_opts.c 100644
Wyświetl plik

@ -0,0 +1,82 @@
/*
* 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_opts.h"
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; // with audio_out_type = 0 and this fd = -1 it will use the bufferized (in-memory) version
#ifdef USE_PORTAUDIO
opts->audio_in_pa_stream = NULL;
#endif
sprintf(opts->audio_out_dev, "/dev/audio");
opts->audio_out_fd = -1; // with audio_out_type = 0 and this fd = -1 it will use the bufferized (in-memory)version
#ifdef USE_PORTAUDIO
opts->audio_out_pa_stream = NULL;
#endif
opts->split = 0;
opts->upsample = 0;
opts->playoffset = 0;
opts->mbe_out_dir[0] = 0;
opts->mbe_out_file[0] = 0;
opts->mbe_out_path[0] = 0;
opts->mbe_out_f = NULL;
opts->audio_gain = 0;
opts->audio_out = 1;
opts->wav_out_file[0] = 0;
#ifdef USE_LIBSNDFILE
opts->wav_out_f = NULL;
#endif
//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_nxdn48 = 0;
opts->frame_nxdn96 = 1;
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;
opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 0;
}

107
dsd/dsd_opts.h 100644
Wyświetl plik

@ -0,0 +1,107 @@
/*
* 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 INCLUDE_DSD_OPTS_H_
#define INCLUDE_DSD_OPTS_H_
#include "config.h"
#include <stdio.h>
#ifdef USE_LIBSNDFILE
#include <sndfile.h>
#endif
// Portaudio is not needed for bufferized (in-memory) operations
#ifdef USE_PORTAUDIO
#include "portaudio.h"
#endif
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;
#ifdef USE_LIBSNDFILE
SNDFILE *audio_in_file;
SF_INFO *audio_in_file_info;
#endif
#ifdef USE_PORTAUDIO
PaStream* audio_in_pa_stream;
#endif
int audio_in_type; // 0 for device, 1 for file, 2 for portaudio
char audio_out_dev[1024];
int audio_out_fd;
#ifdef USE_LIBSNDFILE
SNDFILE *audio_out_file;
SF_INFO *audio_out_file_info;
#endif
#ifdef USE_PORTAUDIO
PaStream* audio_out_pa_stream;
#endif
int audio_out_type; // 0 for device, 1 for file, 2 for portaudio
int split;
int upsample; //!< Force audio output upsampling to 48kHz
int playoffset;
char mbe_out_dir[1024];
char mbe_out_file[1024];
char mbe_out_path[1024];
FILE *mbe_out_f;
float audio_gain;
int audio_out;
char wav_out_file[1024];
#ifdef USE_LIBSNDFILE
SNDFILE *wav_out_f;
#endif
//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_nxdn48;
int frame_nxdn96;
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;
int use_cosine_filter;
int unmute_encrypted_p25;
} dsd_opts;
void initOpts (dsd_opts * opts);
#endif /* INCLUDE_DSD_OPTS_H_ */

90
dsd/dsd_serial.c 100644
Wyświetl plik

@ -0,0 +1,90 @@
#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;
baud = B115200;
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[16];
ssize_t result;
if (opts->serial_fd > 0)
{
sprintf (cmd, "\rKEY00\r");
result = write (opts->serial_fd, cmd, 7);
cmd[0] = 2;
cmd[1] = 75;
cmd[2] = 15;
cmd[3] = 3;
cmd[4] = 93;
cmd[5] = 0;
result = write (opts->serial_fd, cmd, 5);
state->numtdulc = 0;
}
}

123
dsd/dsd_state.c 100644
Wyświetl plik

@ -0,0 +1,123 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "dsd_state.h"
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->wav_out_bytes = 0;
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 (i = 0; i < 25; i++)
{
for (j = 0; j < 16; j++)
{
state->tg[i][j] = 48;
}
}
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);
state->p25kid = 0;
state->debug_audio_errors = 0;
state->debug_header_errors = 0;
state->debug_header_critical_errors = 0;
#ifdef TRACE_DSD
state->debug_sample_index = 0;
state->debug_label_file = NULL;
state->debug_label_dibit_file = NULL;
state->debug_label_imbe_file = NULL;
#endif
initialize_p25_heuristics(&state->p25_heuristics);
}

109
dsd/dsd_state.h 100644
Wyświetl plik

@ -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.
*/
#ifndef INCLUDE_DSD_STATE_H_
#define INCLUDE_DSD_STATE_H_
#include <pthread.h>
#include <mbelib.h>
#include "p25p1_heuristics.h"
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 wav_out_bytes;
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;
int p25kid;
pthread_mutex_t input_mutex;
pthread_cond_t input_ready;
const float *input_samples;
int input_length;
int input_offset;
pthread_mutex_t output_mutex;
pthread_cond_t output_ready;
short *output_buffer;
int output_offset;
float *output_samples;
int output_num_samples;
int output_length;
int output_finished;
} dsd_state;
void initState (dsd_state * state);
#endif /* INCLUDE_DSD_STATE_H_ */

279
dsd/dsd_symbol.c 100644
Wyświetl plik

@ -0,0 +1,279 @@
/*
* 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 "dsd_cleanupexit.h"
int
getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
{
short sample;
int i, sum, symbol, count;
ssize_t result;
sum = 0;
count = 0;
for (i = 0; i < state->samplesPerSymbol; i++)
{
// timing control
if ((i == 0) && (have_sync == 0))
{
if (state->samplesPerSymbol == 20)
{
if ((state->jitter >= 7) && (state->jitter <= 10))
{
i--;
}
else if ((state->jitter >= 11) && (state->jitter <= 14))
{
i++;
}
}
else 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;
}
if(opts->audio_in_type == 0) {
if (opts->audio_in_fd == -1)
{
while (state->input_length == 0)
{
// If the buffer is empty, wait for more samples to arrive.
if (pthread_cond_wait(&state->input_ready, &state->input_mutex))
{
printf("getSymbol -> Error waiting for condition\n");
}
}
// Get the next sample from the buffer, converting from float to short.
sample = (short) (state->input_samples[state->input_offset++] * 32768);
if (state->input_offset == state->input_length)
{
int i;
// We've reached the end of the buffer. Wait for more next time.
state->input_length = 0;
if (pthread_mutex_lock(&state->output_mutex))
{
printf("Unable to lock mutex\n");
}
state->output_num_samples = state->output_offset;
if (state->output_num_samples > state->output_length) {
state->output_num_samples = state->output_length;
}
for (i = 0; i < state->output_length - state->output_num_samples; i++)
{
state->output_samples[i] = 0;
}
for (; i < state->output_length; i++)
{
state->output_samples[i] = state->output_buffer[i - (state->output_length - state->output_num_samples)] / 32768.0;
}
state->output_offset -= state->output_num_samples;
for (i = 0; i < state->output_offset; i++)
{
state->output_buffer[i] = state->output_buffer[i + state->output_num_samples];
}
state->output_finished = 1;
// Wake up general_work
if (pthread_cond_signal(&state->output_ready))
{
printf("Unable to signal\n");
}
if (pthread_mutex_unlock(&state->output_mutex))
{
printf("Unable to unlock mutex\n");
}
}
}
else
{
result = read (opts->audio_in_fd, &sample, 2);
}
}
#ifdef USE_LIBSNDFILE
else {
result = sf_read_short(opts->audio_in_file, &sample, 1);
if(result == 0) {
cleanupAndExit (opts, state);
}
}
#endif
// printf("res: %zd\n, offset: %lld", result, sf_seek(opts->audio_in_file, 0, SEEK_CUR));
if (opts->use_cosine_filter)
{
if (state->lastsynctype >= 10 && state->lastsynctype <= 13)
sample = dmr_filter(sample);
else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||
state->lastsynctype == 16 || state->lastsynctype == 17)
sample = nxdn_filter(sample);
}
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 == 20)
{
if ((i >= 9) && (i <= 11))
{
sum += sample;
count++;
}
}
if (state->samplesPerSymbol == 5)
{
if (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);
}

68
dsd/dsd_upsample.c 100644
Wyświetl plik

@ -0,0 +1,68 @@
/*
* 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, c, d;
outbuf1 = state->audio_out_float_buf_p;
outbuf1--;
c = *outbuf1;
d = invalue;
// basic triangle interpolation
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 = d;
outbuf1++;
if (state->audio_out_idx2 > 24)
{
// smoothing
outbuf1 -= 16;
for (j = 0; j < 4; j++)
{
for (i = 0; i < 6; i++)
{
sum = 0;
outbuf1 -= 2;
sum += *outbuf1;
outbuf1 += 2;
sum += *outbuf1;
outbuf1 += 2;
sum += *outbuf1;
outbuf1 -= 2;
*outbuf1 = (sum / (float) 3);
outbuf1++;
}
outbuf1 -= 8;
}
}
}

163
dsd/dstar.c 100644
Wyświetl plik

@ -0,0 +1,163 @@
/*
* 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 fairly complete at this point.
* The ambe3600x2450 decoder is similar butnot compatible with D-STAR voice frames.
* The dstar interleave pattern is different as well.
* GMSK modulation optimizations will also required to get a usable bit error
*/
#include "dsd.h"
#include "dstar_const.h"
#include "dstar_header.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];
unsigned char data[9];
unsigned int bits[4];
int framecount;
int sync_missed = 0;
unsigned char slowdata[4];
unsigned int bitbuffer = 0;
const int *w, *x;
if (opts->errorbars == 1) {
printf("e:");
}
#ifdef DSTAR_DUMP
printf ("\n");
#endif
if (state->synctype == 18) {
framecount = 0;
state->synctype = 6;
} else if (state->synctype == 19) {
framecount = 0;
state->synctype = 7;
} else {
framecount = 1; //just saw a sync frame; there should be 20 not 21 till the next
}
while (sync_missed < 3) {
memset(ambe_fr, 0, 96);
// voice frame
w = dW;
x = dX;
for (i = 0; i < 72; i++) {
dibit = getDibit(opts, state);
bitbuffer <<= 1;
if (dibit == 1) {
bitbuffer |= 0x01;
}
if ((bitbuffer & 0x00FFFFFF) == 0x00AAB468) {
// we're slipping bits
printf("sync in voice after i=%d, restarting\n", i);
//ugh just start over
i = 0;
w = dW;
x = dX;
framecount = 1;
continue;
}
ambe_fr[*w][*x] = (1 & dibit);
w++;
x++;
}
processMbeFrame(opts, state, NULL, ambe_fr, NULL);
// data frame - 24 bits
for (i = 73; i < 97; i++) {
dibit = getDibit(opts, state);
bitbuffer <<= 1;
if (dibit == 1) {
bitbuffer |= 0x01;
}
if ((bitbuffer & 0x00FFFFFF) == 0x00AAB468) {
// looking if we're slipping bits
if (i != 96) {
printf("sync after i=%d\n", i);
i = 96;
}
}
}
slowdata[0] = (bitbuffer >> 16) & 0x000000FF;
slowdata[1] = (bitbuffer >> 8) & 0x000000FF;
slowdata[2] = (bitbuffer) & 0x000000FF;
slowdata[3] = 0;
if ((bitbuffer & 0x00FFFFFF) == 0x00AAB468) {
//We got sync!
//printf("Sync on framecount = %d\n", framecount);
sync_missed = 0;
} else if ((bitbuffer & 0x00FFFFFF) == 0xAAAAAA) {
//End of transmission
printf("End of transmission\n");
goto end;
} else if (framecount % 21 == 0) {
printf("Missed sync on framecount = %d, value = %x/%x/%x\n",
framecount, slowdata[0], slowdata[1], slowdata[2]);
sync_missed++;
} else if (framecount != 0 && (bitbuffer & 0x00FFFFFF) != 0x000000) {
slowdata[0] ^= 0x70;
slowdata[1] ^= 0x4f;
slowdata[2] ^= 0x93;
//printf("unscrambled- %s",slowdata);
} else if (framecount == 0) {
//printf("never scrambled-%s\n",slowdata);
}
framecount++;
}
end: if (opts->errorbars == 1) {
printf("\n");
}
}
void processDSTAR_HD(dsd_opts * opts, dsd_state * state) {
int i, j;
int radioheaderbuffer[660];
for (j = 0; j < 660; j++) {
radioheaderbuffer[j] = getDibit(opts, state);
}
// Note: These routines contain GPLed code. Remove if you object to that.
// Due to this, they are in a separate source file.
dstar_header_decode(radioheaderbuffer);
//We officially have sync now, so just pass on to the above routine:
processDSTAR(opts, state);
}

129
dsd/dstar_const.h 100644
Wyświetl plik

@ -0,0 +1,129 @@
/*
* 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
const int dW[72] = {
// 0-11
0, 0,
3, 2,
1, 1,
0, 0,
1, 1,
0, 0,
// 12-23
3, 2,
1, 1,
3, 2,
1, 1,
0, 0,
3, 2,
// 24-35
0, 0,
3, 2,
1, 1,
0, 0,
1, 1,
0, 0,
// 36-47
3, 2,
1, 1,
3, 2,
1, 1,
0, 0,
3, 2,
// 48-59
0, 0,
3, 2,
1, 1,
0, 0,
1, 1,
0, 0,
// 60-71
3, 2,
1, 1,
3, 3,
2, 1,
0, 0,
3, 3,
};
const int dX[72] = {
// 0-11
10, 22,
11, 9,
10, 22,
11, 23,
8, 20,
9, 21,
// 12-23
10, 8,
9, 21,
8, 6,
7, 19,
8, 20,
9, 7,
// 24-35
6, 18,
7, 5,
6, 18,
7, 19,
4, 16,
5, 17,
// 36-47
6, 4,
5, 17,
4, 2,
3, 15,
4, 16,
5, 3,
// 48-59
2, 14,
3, 1,
2, 14,
3, 15,
0, 12,
1, 13,
// 60-71
2, 0,
1, 13,
0, 12,
10, 11,
0, 12,
1, 13,
};
#endif

76
dsd/dstar_header.c 100644
Wyświetl plik

@ -0,0 +1,76 @@
/*
*
* This code is taken largely from on1arf's GMSK code. Original copyright below:
*
*
* Copyright (C) 2011 by Kristoff Bonne, ON1ARF
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "fcs.h"
#include "descramble.h"
#include "dstar_header.h"
void dstar_header_decode(int radioheaderbuffer[660]) {
int radioheaderbuffer2[660];
unsigned char radioheader[41];
int octetcount, bitcount, loop;
unsigned char bit2octet[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
unsigned int FCSinheader;
unsigned int FCScalculated;
int len;
scramble(radioheaderbuffer, radioheaderbuffer2);
deinterleave(radioheaderbuffer2, radioheaderbuffer);
len = FECdecoder(radioheaderbuffer, radioheaderbuffer2);
memset(radioheader, 0, 41);
// note we receive 330 bits, but we only use 328 of them (41 octets)
// bits 329 and 330 are unused
octetcount = 0;
bitcount = 0;
for (loop = 0; loop < 328; loop++) {
if (radioheaderbuffer2[loop]) {
radioheader[octetcount] |= bit2octet[bitcount];
};
bitcount++;
// increase octetcounter and reset bitcounter every 8 bits
if (bitcount >= 8) {
octetcount++;
bitcount = 0;
}
}
// print header
printf("\nDSTAR HEADER: ");
//printf("FLAG1: %02X - FLAG2: %02X - FLAG3: %02X\n", radioheader[0],
// radioheader[1], radioheader[2]);
printf("RPT 2: %c%c%c%c%c%c%c%c ", radioheader[3], radioheader[4],
radioheader[5], radioheader[6], radioheader[7], radioheader[8],
radioheader[9], radioheader[10]);
printf("RPT 1: %c%c%c%c%c%c%c%c ", radioheader[11], radioheader[12],
radioheader[13], radioheader[14], radioheader[15], radioheader[16],
radioheader[17], radioheader[18]);
printf("YOUR: %c%c%c%c%c%c%c%c ", radioheader[19], radioheader[20],
radioheader[21], radioheader[22], radioheader[23], radioheader[24],
radioheader[25], radioheader[26]);
printf("MY: %c%c%c%c%c%c%c%c/%c%c%c%c\n", radioheader[27],
radioheader[28], radioheader[29], radioheader[30], radioheader[31],
radioheader[32], radioheader[33], radioheader[34], radioheader[35],
radioheader[36], radioheader[37], radioheader[38]);
//FCSinheader = ((radioheader[39] << 8) | radioheader[40]) & 0xFFFF;
//FCScalculated = calc_fcs((unsigned char*) radioheader, 39);
//printf("Check sum = %04X ", FCSinheader);
//if (FCSinheader == FCScalculated) {
// printf("(OK)\n");
//} else {
// printf("(NOT OK- Calculated FCS = %04X)\n", FCScalculated);
//}; // end else - if
}

Wyświetl plik

@ -0,0 +1,6 @@
/* This is the header file for dstar_header.c, which is under the GPL. */
#ifndef _DSTAR_HEADER_H
#define _DSTAR_HEADER_H
void dstar_header_decode(int radioheaderbuffer[660]);
#endif /* _DSTAR_HEADER_H */

91
dsd/fcs.h 100644
Wyświetl plik

@ -0,0 +1,91 @@
/* fcs.h */
// Viterbi decoder using Traceback method.
// Original Source was written by Sho Tamaoki and Tom Wada
// See http://www.lsi.ie.u-ryukyu.ac.jp/~sho/midterm/
// Modified by Satoshi Yasuda 7m3tjz/ad6gz
// Modified by Jonathan Nayor, G4KLX (C) 2009
// Converted from C++ to C by Kristoff Bonne, ON1ARF
/*
* Copyright (C) 2010 by Kristoff Bonne, ON1ARF
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdint.h>
static const unsigned short ccittTab[] = {
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78};
uint16_t calc_fcs (unsigned char * dvstartframe, int size) {
// this function calculated the CRC-values of a DSTAR digital
// voice frame. It calculates this value on octets 0 up to 38 of the D-STAR
// radio header (fields flag1, flag2, flag3, destination, departure, companion,
// own1 and own2)
uint16_t m_crc;
m_crc=0xFFFF;
int loop;
unsigned short tmp;
for (loop=0; loop < size; loop++) {
tmp = (m_crc & 0x00ff) ^ dvstartframe[loop];
m_crc = (m_crc >> 8) ^ ccittTab[tmp];
}; // end for
// calculate and save crc-value in fields 54 and 55 of dvframe
m_crc = ~m_crc;
tmp = m_crc;
m_crc = (m_crc << 8) | (tmp >> 8 & 0xFF);
// done
return(m_crc);
}; // end function

2
dsd/git_ver.c.in 100644
Wyświetl plik

@ -0,0 +1,2 @@
#define _GIT_TAG "@GIT_TAG@"
const char GIT_TAG[] = _GIT_TAG;

1
dsd/git_ver.h 100644
Wyświetl plik

@ -0,0 +1 @@
extern const char GIT_TAG[];

124
dsd/nxdn96.c 100644
Wyświetl plik

@ -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
dsd/nxdn96_const.h 100644
Wyświetl plik

@ -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

66
dsd/nxdn_const.h 100644
Wyświetl plik

@ -0,0 +1,66 @@
/*
* 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 nW[36];
extern const int nX[36];
extern const int nY[36];
extern const int nZ[36];
extern const char nxdnpr[145];
#else
/*
* pseudorandom bit sequence
*/
const char nxdnpr[145] = { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1 };
/*
* NXDN AMBE interleave schedule
*/
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

36
dsd/nxdn_data.c 100644
Wyświetl plik

@ -0,0 +1,36 @@
#include "dsd.h"
void
processNXDNData (dsd_opts * opts, dsd_state * state)
{
int i, dibit;
if (opts->errorbars == 1)
{
printf ("DATA ");
}
for (i = 0; i < 30; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
}
#ifdef NXDN_DUMP
printf (" ");
#endif
for (i = 0; i < 144; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
}
if (opts->errorbars == 1)
{
printf ("\n");
}
}

59
dsd/nxdn_voice.c 100644
Wyświetl plik

@ -0,0 +1,59 @@
#include "dsd.h"
#include "nxdn_const.h"
void
processNXDNVoice (dsd_opts * opts, dsd_state * state)
{
int i, j, dibit;
char ambe_fr[4][24];
const int *w, *x, *y, *z;
const char *pr;
if (opts->errorbars == 1)
{
printf ("VOICE e:");
}
for (i = 0; i < 30; i++)
{
dibit = getDibit (opts, state);
#ifdef NXDN_DUMP
printf ("%c", dibit + 48);
#endif
}
#ifdef NXDN_DUMP
printf (" ");
#endif
pr = nxdnpr;
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] = *pr ^ (1 & (dibit >> 1)); // bit 1
pr++;
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 (opts->errorbars == 1)
{
printf ("\n");
}
}

160
dsd/p25_lcw.c 100644
Wyświetl plik

@ -0,0 +1,160 @@
#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
j = 0;
for (i = 40; i < 52; 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;
tmpstr[16] = 0;
talkgroup = strtol (tmpstr, NULL, 2);
state->lasttg = talkgroup;
if (state->tgcount < 24)
{
state->tgcount = state->tgcount + 1;
}
if (opts->p25tg == 1)
{
printf ("tg: %li ", 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 (state->tgcount < 24)
{
state->tgcount = state->tgcount + 1;
}
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
dsd/p25p1_const.h 100644
Wyświetl plik

@ -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

318
dsd/p25p1_hdu.c 100644
Wyświetl plik

@ -0,0 +1,318 @@
/*
* 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);
state->p25kid = strtol(kid, NULL, 2);
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 (state->tgcount < 24)
{
state->tgcount = state->tgcount + 1;
}
if (opts->p25tg == 1)
{
printf ("tg: %li\n", talkgroup);
}
}

Wyświetl plik

@ -0,0 +1,91 @@
#ifndef P25P1_HEURISTICS_H_030dd3530b7546abbb56f8dd1e66a2f6
#define P25P1_HEURISTICS_H_030dd3530b7546abbb56f8dd1e66a2f6
#define HEURISTICS_SIZE 200
typedef struct
{
int values[HEURISTICS_SIZE];
float means[HEURISTICS_SIZE];
int index;
int count;
float sum;
float var_sum;
} SymbolHeuristics;
typedef struct
{
unsigned int bit_count;
unsigned int bit_error_count;
SymbolHeuristics symbols[4][4];
} P25Heuristics;
typedef struct
{
int value;
int dibit;
int corrected_dibit;
int sequence_broken;
} AnalogSignal;
#ifdef __cplusplus
extern "C"{
#endif
/**
* Initializes the heuristics state.
* \param heuristics The P25Heuristics structure to initialize.
*/
void initialize_p25_heuristics(P25Heuristics* heuristics);
/**
* Important method that estimates the most likely symbol for a given analog signal value and previous dibit.
* This is called by the digitizer.
* \param rf_mod Indicates the modulation used. The previous dibit is only used on C4FM.
* \param heuristics Pointer to the P25Heuristics module with all the needed state information.
* \param previous_dibit The previous dibit.
* \param analog_value The signal's analog value we want to interpret as a dibit.
* \param dibit Address were to store the estimated dibit.
* \return A boolean set to true if we are able to estimate a dibit. The reason why we might not be able
* to estimate it is because we don't have enough information to model the Gaussians (not enough data
* has been passed to contribute_to_heuristics).
*/
int estimate_symbol(int rf_mod, P25Heuristics* heuristics, int previous_dibit, int analog_value, int* dibit);
/**
* Log some useful information on the heuristics state.
*/
void debug_print_heuristics(P25Heuristics* heuristics);
/**
* This method contributes valuable information from dibits whose value we are confident is correct. We take
* the dibits and corresponding analog signal values to model the Gaussians for each dibit (and previous
* dibit if enabled).
* \param rf_mod Indicates the modulation used. The previous dibit is only used on C4FM.
* \param heuristics Pointer to the P25Heuristics module with all the needed state information.
* \param analog_signal_array Sequence of AnalogSignal which contain the cleared dibits and analog values.
* \param count number of cleared dibits passed (= number of elements to use from analog_signal_array).
*/
void contribute_to_heuristics(int rf_mod, P25Heuristics* heuristics, AnalogSignal* analog_signal_array, int count);
/**
* Updates the estimate for the BER (bit error rate). Mind this is method is not called for every single
* bit in the data stream but only for those bits over which we have an estimate of its error rate,
* specifically the bits that are protected by Reed-Solomon codes.
* \param heuristics The heuristics state.
* \param bits The number of bits we have read.
* \param errors The number of errors we estimate in those bits.
*/
void update_error_stats(P25Heuristics* heuristics, int bits, int errors);
/**
* Returns the estimate for the BER (bit error rate).
* \return The estimated BER. This is just the percentage of errors over the processed bits.
*/
float get_P25_BER_estimate(P25Heuristics* heuristics);
#ifdef __cplusplus
}
#endif
#endif // P25P1_HEURISTICS_H_030dd3530b7546abbb56f8dd1e66a2f6

298
dsd/p25p1_ldu1.c 100644
Wyświetl plik

@ -0,0 +1,298 @@
/*
* 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++;
}
if (state->p25kid == 0 || opts->unmute_encrypted_p25 == 1)
{
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);
}

355
dsd/p25p1_ldu2.c 100644
Wyświetl plik

@ -0,0 +1,355 @@
/*
* 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++;
}
if (state->p25kid == 0 || opts->unmute_encrypted_p25 == 1)
{
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
dsd/p25p1_tdulc.c 100644
Wyświetl plik

@ -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
dsd/provoice.c 100644
Wyświetl plik

@ -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");
}
}

Wyświetl plik

@ -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
dsd/x2tdma_const.h 100644
Wyświetl plik

@ -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

241
dsd/x2tdma_data.c 100644
Wyświetl plik

@ -0,0 +1,241 @@
/*
* 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_BS_DATA_SYNC) == 0) || (strcmp (sync, X2TDMA_BS_DATA_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);
}
}
}

642
dsd/x2tdma_voice.c 100644
Wyświetl plik

@ -0,0 +1,642 @@
/*
* 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;
int msMode;
#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;
msMode = 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_BS_DATA_SYNC) == 0) || (strcmp (sync, X2TDMA_MS_DATA_SYNC) == 0))
{
mutecurrentslot = 1;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[slot0]");
}
else
{
sprintf (state->slot1light, "[slot1]");
}
}
else if ((strcmp (sync, X2TDMA_BS_VOICE_SYNC) == 0) || (strcmp (sync, X2TDMA_MS_VOICE_SYNC) == 0))
{
mutecurrentslot = 0;
if (state->currentslot == 0)
{
sprintf (state->slot0light, "[SLOT0]");
}
else
{
sprintf (state->slot1light, "[SLOT1]");
}
}
if ((strcmp (sync, X2TDMA_MS_VOICE_SYNC) == 0) || (strcmp (sync, X2TDMA_MS_DATA_SYNC) == 0))
{
msMode = 1;
}
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_BS_DATA_SYNC) == 0) || (msMode == 1))
{
if (state->currentslot == 0)
{
sprintf (state->slot1light, " slot1 ");
}
else
{
sprintf (state->slot0light, " slot0 ");
}
}
else if (strcmp (sync, X2TDMA_BS_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);
}
}
}