mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-02-03 09:44:01 -05:00
Imported the dsd library from gr-dsd. Make it a library actually removing useless dependencies
This commit is contained in:
parent
6b6b4d0b0d
commit
0978e17f2e
@ -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)
|
||||
|
22
cmake/Modules/FindLibMbe.cmake
Normal file
22
cmake/Modules/FindLibMbe.cmake
Normal file
@ -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
Normal file
3
dsd/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "samples"]
|
||||
path = samples
|
||||
url = https://github.com/szechyjs/dsd-samples.git
|
98
dsd/CHANGELOG
Normal file
98
dsd/CHANGELOG
Normal file
@ -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
Normal file
71
dsd/CMakeLists.txt
Normal file
@ -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
Normal file
29
dsd/COPYRIGHT
Normal file
@ -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
Normal file
30
dsd/DSD_Author.pgp
Normal file
@ -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
Normal file
561
dsd/README.md
Normal file
@ -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.
|
20
dsd/cmake/FindLibMbe.cmake
Normal file
20
dsd/cmake/FindLibMbe.cmake
Normal file
@ -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)
|
21
dsd/cmake/FindLibSndFile.cmake
Normal file
21
dsd/cmake/FindLibSndFile.cmake
Normal file
@ -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)
|
130
dsd/cmake/git_revision.cmake
Normal file
130
dsd/cmake/git_revision.cmake
Normal file
@ -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()
|
38
dsd/cmake/git_revision.cmake.in
Normal file
38
dsd/cmake/git_revision.cmake.in
Normal file
@ -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()
|
23
dsd/cmake_uninstall.cmake.in
Normal file
23
dsd/cmake_uninstall.cmake.in
Normal file
@ -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
Normal file
32
dsd/config.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* System target
|
||||
*/
|
||||
#define BSD // bsd/linux audio interface
|
||||
//#define SOLARIS // solaris audio interface, untested
|
||||
|
||||
/*
|
||||
* noisy debug/development options
|
||||
*/
|
||||
//#define X2TDMA_DUMP // cach and sync bits dump
|
||||
//#define DMR_DUMP
|
||||
//#define DSTAR_DUMP // dstar frame dump
|
||||
//#define NXDN_DUMP
|
||||
//#define UPSAMPLE_DEBUG
|
||||
//#define PROVOICE_DUMP
|
3
dsd/configure
vendored
Executable file
3
dsd/configure
vendored
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "There is no configure script, just run make"
|
293
dsd/descramble.h
Normal file
293
dsd/descramble.h
Normal file
@ -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
Normal file
64
dsd/dmr_const.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MAIN
|
||||
extern const int rW[36];
|
||||
extern const int rX[36];
|
||||
extern const int rY[36];
|
||||
extern const int rZ[36];
|
||||
|
||||
#else
|
||||
/*
|
||||
* DMR AMBE interleave schedule
|
||||
*/
|
||||
const int rW[36] = {
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 2,
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 2, 0, 2
|
||||
};
|
||||
|
||||
const int rX[36] = {
|
||||
23, 10, 22, 9, 21, 8,
|
||||
20, 7, 19, 6, 18, 5,
|
||||
17, 4, 16, 3, 15, 2,
|
||||
14, 1, 13, 0, 12, 10,
|
||||
11, 9, 10, 8, 9, 7,
|
||||
8, 6, 7, 5, 6, 4
|
||||
};
|
||||
|
||||
const int rY[36] = {
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 3, 0, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3
|
||||
};
|
||||
|
||||
const int rZ[36] = {
|
||||
5, 3, 4, 2, 3, 1,
|
||||
2, 0, 1, 13, 0, 12,
|
||||
22, 11, 21, 10, 20, 9,
|
||||
19, 8, 18, 7, 17, 6,
|
||||
16, 5, 15, 4, 14, 3,
|
||||
13, 2, 12, 1, 11, 0
|
||||
};
|
||||
|
||||
#endif
|
240
dsd/dmr_data.c
Normal file
240
dsd/dmr_data.c
Normal file
@ -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
Normal file
382
dsd/dmr_voice.c
Normal file
@ -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
Normal file
159
dsd/dsd.h
Normal file
@ -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
Normal file
440
dsd/dsd_audio.c
Normal file
@ -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
|
||||
}
|
36
dsd/dsd_cleanupexit.c
Normal file
36
dsd/dsd_cleanupexit.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
26
dsd/dsd_cleanupexit.h
Normal file
26
dsd/dsd_cleanupexit.h
Normal file
@ -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
Normal file
295
dsd/dsd_dibit.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "dsd.h"
|
||||
|
||||
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
Normal file
362
dsd/dsd_file.c
Normal file
@ -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
Normal file
116
dsd/dsd_filters.c
Normal file
@ -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
Normal file
474
dsd/dsd_frame.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
830
dsd/dsd_frame_sync.c
Normal file
830
dsd/dsd_frame_sync.c
Normal file
@ -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);
|
||||
}
|
71
dsd/dsd_livescanner.c
Normal file
71
dsd/dsd_livescanner.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
26
dsd/dsd_livescanner.h
Normal file
26
dsd/dsd_livescanner.h
Normal file
@ -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
Normal file
737
dsd/dsd_main.c
Normal file
@ -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
Normal file
151
dsd/dsd_mbe.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
60
dsd/dsd_nocarrier.c
Normal file
60
dsd/dsd_nocarrier.c
Normal file
@ -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);
|
||||
}
|
26
dsd/dsd_nocarrier.h
Normal file
26
dsd/dsd_nocarrier.h
Normal file
@ -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
Normal file
82
dsd/dsd_opts.c
Normal file
@ -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
Normal file
107
dsd/dsd_opts.h
Normal file
@ -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
Normal file
90
dsd/dsd_serial.c
Normal file
@ -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
Normal file
123
dsd/dsd_state.c
Normal file
@ -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
Normal file
109
dsd/dsd_state.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#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
Normal file
279
dsd/dsd_symbol.c
Normal file
@ -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
Normal file
68
dsd/dsd_upsample.c
Normal file
@ -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
Normal file
163
dsd/dstar.c
Normal file
@ -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
Normal file
129
dsd/dstar_const.h
Normal file
@ -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
Normal file
76
dsd/dstar_header.c
Normal file
@ -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
|
||||
}
|
6
dsd/dstar_header.h
Normal file
6
dsd/dstar_header.h
Normal file
@ -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
Normal file
91
dsd/fcs.h
Normal file
@ -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
Normal file
2
dsd/git_ver.c.in
Normal file
@ -0,0 +1,2 @@
|
||||
#define _GIT_TAG "@GIT_TAG@"
|
||||
const char GIT_TAG[] = _GIT_TAG;
|
1
dsd/git_ver.h
Normal file
1
dsd/git_ver.h
Normal file
@ -0,0 +1 @@
|
||||
extern const char GIT_TAG[];
|
124
dsd/nxdn96.c
Normal file
124
dsd/nxdn96.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include "dsd.h"
|
||||
#include "nxdn96_const.h"
|
||||
|
||||
void
|
||||
processNXDN96 (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int i, j, k, dibit;
|
||||
|
||||
char ambe_fr[4][24];
|
||||
const int *w, *x, *y, *z;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
printf ("VOICE e:");
|
||||
}
|
||||
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
for (i = 0; i < 222; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
#ifdef NXDN_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
if (k < 3)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
w = nW;
|
||||
x = nX;
|
||||
y = nY;
|
||||
z = nZ;
|
||||
for (i = 0; i < 36; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("%c", dibit + 48);
|
||||
#endif
|
||||
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||
ambe_fr[*y][*z] = (1 & dibit); // bit 0
|
||||
w++;
|
||||
x++;
|
||||
y++;
|
||||
z++;
|
||||
}
|
||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||
#ifdef NXDN_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < 3; j++) // we skip the last voice frame until frame sync can work with < 24 symbols
|
||||
{
|
||||
w = nW;
|
||||
x = nX;
|
||||
y = nY;
|
||||
z = nZ;
|
||||
for (i = 0; i < 36; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("%c", dibit + 48);
|
||||
#endif
|
||||
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||
ambe_fr[*y][*z] = (1 & dibit); // bit 0
|
||||
w++;
|
||||
x++;
|
||||
y++;
|
||||
z++;
|
||||
}
|
||||
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
|
||||
#ifdef NXDN_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (k < 3)
|
||||
{
|
||||
for (i = 0; i < 18; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
#ifdef NXDN_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 30; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("%c", dibit + 48);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NXDN_DUMP
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
}
|
62
dsd/nxdn96_const.h
Normal file
62
dsd/nxdn96_const.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NXDN AMBE interleave schedule
|
||||
*/
|
||||
|
||||
#ifndef _MAIN
|
||||
extern const int nW[36];
|
||||
extern const int nX[36];
|
||||
extern const int nY[36];
|
||||
extern const int nZ[36];
|
||||
|
||||
#else
|
||||
|
||||
const int nW[36] = { 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 2,
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 2, 0, 2
|
||||
};
|
||||
|
||||
const int nX[36] = { 23, 10, 22, 9, 21, 8,
|
||||
20, 7, 19, 6, 18, 5,
|
||||
17, 4, 16, 3, 15, 2,
|
||||
14, 1, 13, 0, 12, 10,
|
||||
11, 9, 10, 8, 9, 7,
|
||||
8, 6, 7, 5, 6, 4
|
||||
};
|
||||
|
||||
const int nY[36] = { 0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 3, 0, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3
|
||||
};
|
||||
|
||||
const int nZ[36] = { 5, 3, 4, 2, 3, 1,
|
||||
2, 0, 1, 13, 0, 12,
|
||||
22, 11, 21, 10, 20, 9,
|
||||
19, 8, 18, 7, 17, 6,
|
||||
16, 5, 15, 4, 14, 3,
|
||||
13, 2, 12, 1, 11, 0
|
||||
};
|
||||
|
||||
#endif
|
66
dsd/nxdn_const.h
Normal file
66
dsd/nxdn_const.h
Normal file
@ -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
Normal file
36
dsd/nxdn_data.c
Normal file
@ -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
Normal file
59
dsd/nxdn_voice.c
Normal file
@ -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
Normal file
160
dsd/p25_lcw.c
Normal file
@ -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
Normal file
89
dsd/p25p1_const.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MAIN
|
||||
|
||||
extern const int iW[72];
|
||||
extern const int iX[72];
|
||||
extern const int iY[72];
|
||||
extern const int iZ[72];
|
||||
|
||||
#else
|
||||
/*
|
||||
* P25 Phase1 IMBE interleave schedule
|
||||
*/
|
||||
|
||||
const int iW[72] = {
|
||||
0, 2, 4, 1, 3, 5,
|
||||
0, 2, 4, 1, 3, 6,
|
||||
0, 2, 4, 1, 3, 6,
|
||||
0, 2, 4, 1, 3, 6,
|
||||
0, 2, 4, 1, 3, 6,
|
||||
0, 2, 4, 1, 3, 6,
|
||||
0, 2, 5, 1, 3, 6,
|
||||
0, 2, 5, 1, 3, 6,
|
||||
0, 2, 5, 1, 3, 7,
|
||||
0, 2, 5, 1, 3, 7,
|
||||
0, 2, 5, 1, 4, 7,
|
||||
0, 3, 5, 2, 4, 7
|
||||
};
|
||||
|
||||
const int iX[72] = {
|
||||
22, 20, 10, 20, 18, 0,
|
||||
20, 18, 8, 18, 16, 13,
|
||||
18, 16, 6, 16, 14, 11,
|
||||
16, 14, 4, 14, 12, 9,
|
||||
14, 12, 2, 12, 10, 7,
|
||||
12, 10, 0, 10, 8, 5,
|
||||
10, 8, 13, 8, 6, 3,
|
||||
8, 6, 11, 6, 4, 1,
|
||||
6, 4, 9, 4, 2, 6,
|
||||
4, 2, 7, 2, 0, 4,
|
||||
2, 0, 5, 0, 13, 2,
|
||||
0, 21, 3, 21, 11, 0
|
||||
};
|
||||
|
||||
const int iY[72] = {
|
||||
1, 3, 5, 0, 2, 4,
|
||||
1, 3, 6, 0, 2, 4,
|
||||
1, 3, 6, 0, 2, 4,
|
||||
1, 3, 6, 0, 2, 4,
|
||||
1, 3, 6, 0, 2, 4,
|
||||
1, 3, 6, 0, 2, 5,
|
||||
1, 3, 6, 0, 2, 5,
|
||||
1, 3, 6, 0, 2, 5,
|
||||
1, 3, 6, 0, 2, 5,
|
||||
1, 3, 7, 0, 2, 5,
|
||||
1, 4, 7, 0, 3, 5,
|
||||
2, 4, 7, 1, 3, 5
|
||||
};
|
||||
|
||||
const int iZ[72] = {
|
||||
21, 19, 1, 21, 19, 9,
|
||||
19, 17, 14, 19, 17, 7,
|
||||
17, 15, 12, 17, 15, 5,
|
||||
15, 13, 10, 15, 13, 3,
|
||||
13, 11, 8, 13, 11, 1,
|
||||
11, 9, 6, 11, 9, 14,
|
||||
9, 7, 4, 9, 7, 12,
|
||||
7, 5, 2, 7, 5, 10,
|
||||
5, 3, 0, 5, 3, 8,
|
||||
3, 1, 5, 3, 1, 6,
|
||||
1, 14, 3, 1, 22, 4,
|
||||
22, 12, 1, 22, 20, 2
|
||||
};
|
||||
#endif
|
318
dsd/p25p1_hdu.c
Normal file
318
dsd/p25p1_hdu.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
91
dsd/p25p1_heuristics.h
Normal file
91
dsd/p25p1_heuristics.h
Normal file
@ -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
Normal file
298
dsd/p25p1_ldu1.c
Normal file
@ -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
Normal file
355
dsd/p25p1_ldu2.c
Normal file
@ -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
Normal file
158
dsd/p25p1_tdulc.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "dsd.h"
|
||||
|
||||
void
|
||||
processTDULC (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
char lcinfo[57], lcformat[9], mfid[9];
|
||||
int dibit, count;
|
||||
|
||||
lcformat[8] = 0;
|
||||
mfid[8] = 0;
|
||||
lcinfo[56] = 0;
|
||||
|
||||
skipDibit (opts, state, 25);
|
||||
count = 57;
|
||||
|
||||
dibit = getDibit (opts, state);
|
||||
lcformat[0] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcformat[1] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcformat[2] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcformat[3] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcformat[4] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcformat[5] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcformat[6] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcformat[7] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
mfid[0] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
mfid[1] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
mfid[2] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
mfid[3] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 6);
|
||||
|
||||
dibit = getDibit (opts, state);
|
||||
mfid[4] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
mfid[5] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
mfid[6] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
mfid[7] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 1);
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[0] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[1] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[2] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[3] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[4] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[5] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[6] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[7] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 6);
|
||||
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[8] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[9] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[10] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[11] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[12] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[13] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[14] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[15] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[16] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[17] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[18] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[19] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 6);
|
||||
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[20] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[21] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[22] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[23] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[24] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[25] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[26] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[27] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[28] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[29] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[30] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[31] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 6);
|
||||
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[32] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[33] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 1);
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[34] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[35] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[36] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[37] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[38] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[39] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[40] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[41] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[42] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[43] = (1 & dibit) + 48; // bit 0
|
||||
skipDibit (opts, state, 6);
|
||||
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[44] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[45] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[46] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[47] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[48] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[49] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[50] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[51] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[52] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[53] = (1 & dibit) + 48; // bit 0
|
||||
dibit = getDibit (opts, state);
|
||||
lcinfo[54] = (1 & (dibit >> 1)) + 48; // bit 1
|
||||
lcinfo[55] = (1 & dibit) + 48; // bit 0
|
||||
|
||||
skipDibit (opts, state, 91);
|
||||
|
||||
processP25lcw (opts, state, lcformat, mfid, lcinfo);
|
||||
}
|
519
dsd/provoice.c
Normal file
519
dsd/provoice.c
Normal file
@ -0,0 +1,519 @@
|
||||
#include "dsd.h"
|
||||
#include "provoice_const.h"
|
||||
|
||||
void
|
||||
processProVoice (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
int i, j, dibit;
|
||||
|
||||
char imbe7100_fr1[7][24];
|
||||
char imbe7100_fr2[7][24];
|
||||
const int *w, *x;
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
printf ("VOICE e:");
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
// lid
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
// imbe frames 1,2 first half
|
||||
w = pW;
|
||||
x = pX;
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
}
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
// spacer bits
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
// imbe frames 1,2 second half
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
}
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 5;
|
||||
x -= 5;
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
}
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 5;
|
||||
x -= 5;
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
|
||||
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
|
||||
|
||||
// spacer bits
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
// imbe frames 3,4 first half
|
||||
w = pW;
|
||||
x = pX;
|
||||
for (i = 0; i < 11; i++)
|
||||
{
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
}
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
// spacer bits
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
printf ("_");
|
||||
#endif
|
||||
|
||||
// imbe frames 3,4 second half
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
}
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 5;
|
||||
x -= 5;
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 6;
|
||||
x -= 6;
|
||||
for (j = 0; j < 6; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
}
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr1[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("_");
|
||||
#endif
|
||||
w -= 5;
|
||||
x -= 5;
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
imbe7100_fr2[*w][*x] = dibit;
|
||||
w++;
|
||||
x++;
|
||||
}
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
|
||||
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
|
||||
|
||||
// spacer bits
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
#endif
|
||||
dibit = getDibit (opts, state);
|
||||
#ifdef PROVOICE_DUMP
|
||||
printf ("%i", dibit);
|
||||
printf (" ");
|
||||
#endif
|
||||
|
||||
if (opts->errorbars == 1)
|
||||
{
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
81
dsd/provoice_const.h
Normal file
81
dsd/provoice_const.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _MAIN
|
||||
|
||||
extern const int pW[142];
|
||||
extern const int pX[142];
|
||||
|
||||
#else
|
||||
/*
|
||||
* ProVoice IMBE interleave schedule
|
||||
*/
|
||||
|
||||
const int pW[142] = {
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 3, 4, 5, 6,
|
||||
1, 2, 3, 4, 5, 6,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
1, 2, 3, 4, 5, 6,
|
||||
1, 2, 3, 4, 5,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 4, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 3, 5, 6,
|
||||
0, 1, 2, 4, 5, 6,
|
||||
1, 2, 3, 4, 5, 6,
|
||||
1, 2, 3, 4, 6
|
||||
};
|
||||
|
||||
const int pX[142] = {
|
||||
18, 18, 17, 16, 7, 21,
|
||||
15, 15, 14, 13, 4, 18,
|
||||
12, 12, 11, 10, 1, 15,
|
||||
9, 9, 8, 7, 13, 12,
|
||||
6, 6, 5, 4, 10, 9,
|
||||
3, 3, 2, 1, 7, 6,
|
||||
0, 0, 22, 13, 4, 3,
|
||||
21, 20, 19, 10, 1, 0,
|
||||
17, 17, 16, 15, 6, 20,
|
||||
14, 14, 13, 12, 3, 17,
|
||||
11, 11, 10, 9, 0, 14,
|
||||
8, 8, 7, 6, 12, 11,
|
||||
5, 5, 4, 3, 9, 8,
|
||||
2, 2, 1, 0, 6, 5,
|
||||
23, 22, 21, 12, 3, 2,
|
||||
20, 19, 18, 9, 0,
|
||||
16, 16, 15, 14, 5, 19,
|
||||
13, 13, 12, 11, 2, 16,
|
||||
10, 10, 9, 8, 14, 13,
|
||||
7, 7, 6, 5, 11, 10,
|
||||
4, 4, 3, 2, 8, 7,
|
||||
1, 1, 0, 14, 5, 4,
|
||||
22, 21, 20, 11, 2, 1,
|
||||
19, 18, 17, 8, 22
|
||||
};
|
||||
#endif
|
62
dsd/x2tdma_const.h
Normal file
62
dsd/x2tdma_const.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2010 DSD Author
|
||||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* X2TDMA AMBE interleave schedule
|
||||
*/
|
||||
|
||||
#ifndef _MAIN
|
||||
extern const int aW[36];
|
||||
extern const int aX[36];
|
||||
extern const int aY[36];
|
||||
extern const int aZ[36];
|
||||
|
||||
#else
|
||||
|
||||
const int aW[36] = { 0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 2,
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 2, 0, 2
|
||||
};
|
||||
|
||||
const int aX[36] = { 23, 10, 22, 9, 21, 8,
|
||||
20, 7, 19, 6, 18, 5,
|
||||
17, 4, 16, 3, 15, 2,
|
||||
14, 1, 13, 0, 12, 10,
|
||||
11, 9, 10, 8, 9, 7,
|
||||
8, 6, 7, 5, 6, 4
|
||||
};
|
||||
|
||||
const int aY[36] = { 0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 3, 0, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3
|
||||
};
|
||||
|
||||
const int aZ[36] = { 5, 3, 4, 2, 3, 1,
|
||||
2, 0, 1, 13, 0, 12,
|
||||
22, 11, 21, 10, 20, 9,
|
||||
19, 8, 18, 7, 17, 6,
|
||||
16, 5, 15, 4, 14, 3,
|
||||
13, 2, 12, 1, 11, 0
|
||||
};
|
||||
|
||||
#endif
|
241
dsd/x2tdma_data.c
Normal file
241
dsd/x2tdma_data.c
Normal file
@ -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
Normal file
642
dsd/x2tdma_voice.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user