forked from cellular-infrastructure/osmocom-analog
Add MPT1327 / Regionet43 (Buendelfunk) network
This commit is contained in:
parent
ef88fea8a0
commit
8d4d48aa08
|
@ -66,6 +66,7 @@ src/jtacs/jtacs
|
|||
src/r2000/radiocom2000
|
||||
src/imts/imts
|
||||
src/imts/imts-dialer
|
||||
src/mpt1327/mpt1327
|
||||
src/jolly/jollycom
|
||||
src/eurosignal/eurosignal
|
||||
src/tv/osmotv
|
||||
|
|
3
README
3
README
|
@ -14,6 +14,7 @@ generated simultaniously using SDR. Currently supported networks:
|
|||
* JTACS (Japanese version of TACS)
|
||||
* Radiocom 2000 (French network)
|
||||
* IMTS / MTS ((Improved) Mobile Telephone Service)
|
||||
* MPT1327 (Trunked Radio) aka known as 'Buendelfunk'
|
||||
* Eurosignal (ERuRD paging service)
|
||||
* JollyCom (Unofficial network, invented by the author)
|
||||
* C-Netz BSC (Connecting to a C-Netz Base Station)
|
||||
|
@ -23,6 +24,7 @@ Additionally the following communication services are implemented:
|
|||
* TV Transmitter with test Images
|
||||
* Radio transmitter / receiver
|
||||
* Analog Modem Emulation (AM7911)
|
||||
* German classic 'Zeitansage' (time announcement)
|
||||
|
||||
|
||||
USE AT YOUR OWN RISK!
|
||||
|
@ -68,3 +70,4 @@ which seems not to exist anymore...
|
|||
Peter, Peter and Friedhelm and Stephan for providing documentation and hardware
|
||||
for C-Netz Base Station and other C-Netz documents.
|
||||
|
||||
Carsten Wollesen for donating MPT1327 radios and programming tools.
|
||||
|
|
|
@ -97,6 +97,7 @@ AC_OUTPUT(
|
|||
src/jtacs/Makefile
|
||||
src/r2000/Makefile
|
||||
src/imts/Makefile
|
||||
src/mpt1327/Makefile
|
||||
src/jolly/Makefile
|
||||
src/eurosignal/Makefile
|
||||
src/tv/Makefile
|
||||
|
|
|
@ -108,6 +108,7 @@ Implemented networks:
|
|||
<li><a href="amps.html">AMPS - Advanced Mobile Phone Service</a> (USA)</li>
|
||||
<li><a href="tacs.html">TACS / JTACS - Total Access Communication System</a> (UK/Italy/Japan)</li>
|
||||
<li><a href="radiocom2000.html">Radiocom 2000</a> (France)</li>
|
||||
<li><a href="mpt1327.html">MPT1327/Regionet43 (Bündelfunk)</a> (Europe)</li>
|
||||
<li><a href="eurosignal.html">Eurosignal</a> (Europe)</li>
|
||||
</ul>
|
||||
</td></tr></table></center>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="style.css" rel="stylesheet" type="text/css" />
|
||||
<title>osmocom-analog</title>
|
||||
</head>
|
||||
<body>
|
||||
<center><table><tr><td>
|
||||
|
||||
<h2><center>MPT1327</center></h2>
|
||||
|
||||
<center><!--img src="radiocom2000.jpg"/--></center>
|
||||
|
||||
<center><h1>*this doc is under construction*</h1></center>
|
||||
|
||||
<ul>
|
||||
<li><a href="#history">History</a>
|
||||
<li><a href="#howitworks">How it works</a>
|
||||
<li><a href="#basestation">Setup of a base station</a>
|
||||
</ul>
|
||||
|
||||
<p class="toppic">
|
||||
<a name="history"></a>
|
||||
History
|
||||
</p>
|
||||
|
||||
<p class="toppic">
|
||||
<a name="howitworks"></a>
|
||||
How it works
|
||||
</p>
|
||||
|
||||
<p class="toppic">
|
||||
<a name="basestation"></a>
|
||||
Setup of a base station
|
||||
</p>
|
||||
|
||||
<hr><center>[<a href="index.html">Back to main page</a>]</center><hr>
|
||||
</td></tr></table></center>
|
||||
</body>
|
||||
</html>
|
|
@ -51,6 +51,7 @@ SUBDIRS += \
|
|||
jtacs \
|
||||
r2000 \
|
||||
imts \
|
||||
mpt1327 \
|
||||
jolly \
|
||||
eurosignal \
|
||||
tv \
|
||||
|
|
|
@ -16,7 +16,6 @@ jollycom_LDADD = \
|
|||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libsquelch/libsquelch.a \
|
||||
$(top_builddir)/src/libdtmf/libdtmf.a \
|
||||
|
|
|
@ -50,6 +50,7 @@ struct debug_cat {
|
|||
{ "amps", "\033[1;34m" },
|
||||
{ "r2000", "\033[1;34m" },
|
||||
{ "imts", "\033[1;34m" },
|
||||
{ "mpt1327", "\033[1;34m" },
|
||||
{ "jollycom", "\033[1;34m" },
|
||||
{ "eurosignal", "\033[1;34m" },
|
||||
{ "frame", "\033[0;36m" },
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
bin_PROGRAMS = \
|
||||
mpt1327
|
||||
|
||||
mpt1327_SOURCES = \
|
||||
mpt1327.c \
|
||||
dsp.c \
|
||||
message.c \
|
||||
main.c
|
||||
mpt1327_LDADD = \
|
||||
$(COMMON_LA) \
|
||||
../anetz/libgermanton.a \
|
||||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libsquelch/libsquelch.a \
|
||||
$(top_builddir)/src/libdtmf/libdtmf.a \
|
||||
$(top_builddir)/src/libtimer/libtimer.a \
|
||||
$(top_builddir)/src/libsamplerate/libsamplerate.a \
|
||||
$(top_builddir)/src/libemphasis/libemphasis.a \
|
||||
$(top_builddir)/src/libfsk/libfsk.a \
|
||||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
||||
if HAVE_ALSA
|
||||
mpt1327_LDADD += \
|
||||
$(top_builddir)/src/libsound/libsound.a \
|
||||
$(ALSA_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_SDR
|
||||
mpt1327_LDADD += \
|
||||
$(top_builddir)/src/libsdr/libsdr.a \
|
||||
$(top_builddir)/src/libam/libam.a \
|
||||
$(top_builddir)/src/libfft/libfft.a \
|
||||
$(UHD_LIBS) \
|
||||
$(SOAPY_LIBS)
|
||||
endif
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
/* audio processing
|
||||
*
|
||||
* (C) 2021 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define CHAN mpt1327->sender.kanal
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "mpt1327.h"
|
||||
#include "dsp.h"
|
||||
#include "message.h"
|
||||
|
||||
#define PI M_PI
|
||||
|
||||
/* signaling */
|
||||
#define MAX_DEVIATION 2500.0
|
||||
#define MAX_MODULATION 2550.0
|
||||
#define SPEECH_DEVIATION 1500.0 /* deviation of speech (no emphasis) */
|
||||
#define TX_PEAK_FSK (1500.0 / SPEECH_DEVIATION)
|
||||
#define BIT_RATE 1200.0
|
||||
#define BIT_ADJUST 0.1 /* how much do we adjust bit clock on frequency change */
|
||||
#define F0 1800.0
|
||||
#define F1 1200.0
|
||||
#define MAX_DISPLAY 1.4 /* something above speech level */
|
||||
|
||||
/* carrier loss detection */
|
||||
#define MUTE_TIME 0.1 /* time to mute after loosing signal */
|
||||
|
||||
void dsp_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int fsk_send_bit(void *inst);
|
||||
static void fsk_receive_bit(void *inst, int bit, double quality, double level);
|
||||
|
||||
/* Init FSK of transceiver */
|
||||
int dsp_init_sender(mpt1327_t *mpt1327, double squelch_db)
|
||||
{
|
||||
int rc;
|
||||
|
||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for Transceiver.\n");
|
||||
|
||||
/* init squelch */
|
||||
squelch_init(&mpt1327->squelch, mpt1327->sender.kanal, squelch_db, MUTE_TIME, MUTE_TIME);
|
||||
|
||||
/* set modulation parameters */
|
||||
sender_set_fm(&mpt1327->sender, MAX_DEVIATION, MAX_MODULATION, SPEECH_DEVIATION, MAX_DISPLAY);
|
||||
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation)\n", TX_PEAK_FSK, SPEECH_DEVIATION * TX_PEAK_FSK / 1e3);
|
||||
|
||||
/* init fsk */
|
||||
if (fsk_mod_init(&mpt1327->fsk_mod, mpt1327, fsk_send_bit, mpt1327->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 1, 0) < 0) {
|
||||
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (fsk_demod_init(&mpt1327->fsk_demod, mpt1327, fsk_receive_bit, mpt1327->sender.samplerate, BIT_RATE, F0, F1, BIT_ADJUST) < 0) {
|
||||
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mpt1327->dmp_frame_level = display_measurements_add(&mpt1327->sender.dispmeas, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||
mpt1327->dmp_frame_quality = display_measurements_add(&mpt1327->sender.dispmeas, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||
|
||||
/* repeater */
|
||||
rc = jitter_create(&mpt1327->repeater_dejitter, mpt1327->sender.samplerate / 5);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DDSP, DEBUG_ERROR, "Failed to create and init repeater buffer!\n");
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dsp_cleanup_sender(mpt1327);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Cleanup transceiver instance. */
|
||||
void dsp_cleanup_sender(mpt1327_t *mpt1327)
|
||||
{
|
||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for Transceiver.\n");
|
||||
|
||||
fsk_mod_cleanup(&mpt1327->fsk_mod);
|
||||
fsk_demod_cleanup(&mpt1327->fsk_demod);
|
||||
|
||||
jitter_destroy(&mpt1327->repeater_dejitter);
|
||||
}
|
||||
|
||||
/* Check for SYNC bits, then collect data bits */
|
||||
static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
||||
{
|
||||
mpt1327_t *mpt1327 = (mpt1327_t *)inst;
|
||||
int i;
|
||||
|
||||
/* normalize FSK level */
|
||||
level /= TX_PEAK_FSK;
|
||||
|
||||
// printf("bit=%d quality=%.4f\n", bit, quality);
|
||||
if (!mpt1327->rx_in_sync) {
|
||||
mpt1327->rx_sync = (mpt1327->rx_sync << 1) | bit;
|
||||
|
||||
/* level and quality */
|
||||
mpt1327->rx_level[mpt1327->rx_count & 0xff] = level;
|
||||
mpt1327->rx_quality[mpt1327->rx_count & 0xff] = quality;
|
||||
mpt1327->rx_count++;
|
||||
|
||||
/* check if sync pattern match */
|
||||
if (mpt1327->rx_sync != mpt1327->sync_word)
|
||||
return;
|
||||
|
||||
/* average level and quality */
|
||||
level = quality = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
level += mpt1327->rx_level[(mpt1327->rx_count - 1 - i) & 0xff];
|
||||
quality += mpt1327->rx_quality[(mpt1327->rx_count - 1 - i) & 0xff];
|
||||
}
|
||||
level /= 16.0; quality /= 16.0;
|
||||
// printf("sync (level = %.2f, quality = %.2f\n", level, quality);
|
||||
|
||||
/* do not accept garbage */
|
||||
if (quality < 0.65)
|
||||
return;
|
||||
|
||||
/* rest sync register */
|
||||
mpt1327->rx_sync = 0;
|
||||
mpt1327->rx_in_sync = 1;
|
||||
mpt1327->rx_count = 0;
|
||||
|
||||
/* mute audio from now on */
|
||||
mpt1327->rx_mute = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* read bits */
|
||||
mpt1327->rx_bits = (mpt1327->rx_bits << 1) | (bit & 1);
|
||||
mpt1327->rx_level[mpt1327->rx_count] = level;
|
||||
mpt1327->rx_quality[mpt1327->rx_count] = quality;
|
||||
if (++mpt1327->rx_count != 64)
|
||||
return;
|
||||
|
||||
/* check parity */
|
||||
if (mpt1327_checkbits(mpt1327->rx_bits, NULL) != (mpt1327->rx_bits & 0xffff)) {
|
||||
PDEBUG(DDSP, DEBUG_NOTICE, "Received corrupt codeword or noise.\n");
|
||||
mpt1327->rx_in_sync = 0;
|
||||
mpt1327->rx_mute = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* reset counter for next frame */
|
||||
mpt1327->rx_count = 0;
|
||||
|
||||
/* average level and quality */
|
||||
level = quality = 0;
|
||||
for (i = 0; i < 64; i++) {
|
||||
level += mpt1327->rx_level[i];
|
||||
quality += mpt1327->rx_quality[i];
|
||||
}
|
||||
level /= 64.0; quality /= 64.0;
|
||||
|
||||
/* update measurements */
|
||||
display_measurements_update(mpt1327->dmp_frame_level, level * 100.0, 0.0);
|
||||
display_measurements_update(mpt1327->dmp_frame_quality, quality * 100.0, 0.0);
|
||||
|
||||
/* convert level so that received level at TX_PEAK_FSK results in 1.0 (100%) */
|
||||
mpt1327_receive_codeword(mpt1327, mpt1327->rx_bits, quality, level);
|
||||
}
|
||||
|
||||
/* Process received audio stream from radio unit. */
|
||||
void sender_receive(sender_t *sender, sample_t *samples, int length, double __attribute__((unused)) rf_level_db)
|
||||
{
|
||||
mpt1327_t *mpt1327 = (mpt1327_t *) sender;
|
||||
sample_t *spl;
|
||||
int pos;
|
||||
int i;
|
||||
int was_mute = mpt1327->rx_mute; /* remember, so always mute whole chunk */
|
||||
int was_pressel_on = mpt1327->pressel_on;
|
||||
|
||||
/* if channel is off, do nothing */
|
||||
if (mpt1327->dsp_mode == DSP_MODE_OFF) {
|
||||
/* measure squelch even if channel is turned off */
|
||||
if (!isinf(mpt1327->squelch.threshold_db))
|
||||
squelch(&mpt1327->squelch, rf_level_db, (double)length / (double)mpt1327->sender.samplerate);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fsk signal */
|
||||
fsk_demod_receive(&mpt1327->fsk_demod, samples, length);
|
||||
|
||||
/* on traffic channel mute and indicate signal strength */
|
||||
if (mpt1327->dsp_mode == DSP_MODE_TRAFFIC) {
|
||||
/* process signal mute/loss, also for signalling tone */
|
||||
if (!isinf(mpt1327->squelch.threshold_db)) {
|
||||
/* use squelch to unmute and reset call timer */
|
||||
switch (squelch(&mpt1327->squelch, rf_level_db, (double)length / (double)mpt1327->sender.samplerate)) {
|
||||
case SQUELCH_LOSS:
|
||||
case SQUELCH_MUTE:
|
||||
memset(samples, 0, sizeof(*samples) * length);
|
||||
break;
|
||||
default:
|
||||
mpt1327_signal_indication(mpt1327);
|
||||
}
|
||||
} else {
|
||||
/* muting audio while pressel is off */
|
||||
if (!was_pressel_on || !mpt1327->pressel_on)
|
||||
memset(samples, 0, sizeof(*samples) * length);
|
||||
}
|
||||
/* muting audio while receiving frame */
|
||||
if (was_mute || mpt1327->rx_mute)
|
||||
memset(samples, 0, sizeof(*samples) * length);
|
||||
}
|
||||
|
||||
if (mpt1327->dsp_mode == DSP_MODE_TRAFFIC) {
|
||||
/* if repeater mode, store sample in jitter buffer */
|
||||
if (mpt1327->repeater)
|
||||
jitter_save(&mpt1327->repeater_dejitter, samples, length);
|
||||
|
||||
if (mpt1327->unit && mpt1327->unit->callref) {
|
||||
int count;
|
||||
|
||||
count = samplerate_downsample(&mpt1327->sender.srstate, samples, length);
|
||||
spl = mpt1327->sender.rxbuf;
|
||||
pos = mpt1327->sender.rxbuf_pos;
|
||||
for (i = 0; i < count; i++) {
|
||||
spl[pos++] = samples[i];
|
||||
if (pos == 160) {
|
||||
call_up_audio(mpt1327->unit->callref, spl, 160);
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
mpt1327->sender.rxbuf_pos = pos;
|
||||
} else
|
||||
mpt1327->sender.rxbuf_pos = 0;
|
||||
} else
|
||||
mpt1327->sender.rxbuf_pos = 0;
|
||||
}
|
||||
|
||||
static int fsk_send_bit(void *inst)
|
||||
{
|
||||
mpt1327_t *mpt1327 = (mpt1327_t *)inst;
|
||||
|
||||
/* send frame bit (prio) */
|
||||
if (!mpt1327->tx_bit_num || mpt1327->tx_count == mpt1327->tx_bit_num) {
|
||||
/* request frame */
|
||||
mpt1327->tx_bit_num = mpt1327_send_codeword(mpt1327, &mpt1327->tx_bits);
|
||||
if (mpt1327->tx_bit_num == 0) {
|
||||
return -1;
|
||||
}
|
||||
mpt1327->tx_count = 0;
|
||||
}
|
||||
return (mpt1327->tx_bits >> (63 - mpt1327->tx_count++)) & 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Provide stream of audio toward radio unit */
|
||||
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length)
|
||||
{
|
||||
mpt1327_t *mpt1327 = (mpt1327_t *) sender;
|
||||
|
||||
if (mpt1327->dsp_mode == DSP_MODE_OFF) {
|
||||
memset(power, 0, length);
|
||||
memset(samples, 0, sizeof(*samples) * length);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(power, 1, length);
|
||||
|
||||
if (mpt1327->dsp_mode == DSP_MODE_TRAFFIC) {
|
||||
jitter_load(&mpt1327->sender.dejitter, samples, length);
|
||||
/* if repeater mode, sum samples from jitter buffer to samples */
|
||||
if (mpt1327->repeater) {
|
||||
sample_t uplink[length];
|
||||
int i;
|
||||
jitter_load(&mpt1327->repeater_dejitter, uplink, length);
|
||||
for (i = 0; i < length; i++)
|
||||
samples[i] += uplink[i];
|
||||
}
|
||||
} else
|
||||
memset(samples, 0, sizeof(*samples) * length);
|
||||
|
||||
/* If there is something to modulate (pending TX frame),
|
||||
* overwrite audio with FSK audio. */
|
||||
fsk_mod_send(&mpt1327->fsk_mod, samples, length, 0);
|
||||
}
|
||||
|
||||
const char *mpt1327_dsp_mode_name(enum dsp_mode mode)
|
||||
{
|
||||
static char invalid[16];
|
||||
|
||||
switch (mode) {
|
||||
case DSP_MODE_OFF:
|
||||
return "OFF";
|
||||
case DSP_MODE_TRAFFIC:
|
||||
return "TRAFFIC";
|
||||
case DSP_MODE_CONTROL:
|
||||
return "CONTROL";
|
||||
}
|
||||
|
||||
sprintf(invalid, "invalid(%d)", mode);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
void mpt1327_set_dsp_mode(mpt1327_t *mpt1327, enum dsp_mode mode, int repeater)
|
||||
{
|
||||
//NOTE: DO NOT RESET FRAME, because mode may change before frame has been sent!
|
||||
|
||||
if (mode == DSP_MODE_CONTROL)
|
||||
mpt1327->sync_word = 0xc4d7;
|
||||
if (mode == DSP_MODE_TRAFFIC)
|
||||
mpt1327->sync_word = 0x3b28;
|
||||
|
||||
if (repeater)
|
||||
jitter_reset(&mpt1327->repeater_dejitter);
|
||||
mpt1327->repeater = repeater;
|
||||
|
||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", mpt1327_dsp_mode_name(mpt1327->dsp_mode), mpt1327_dsp_mode_name(mode));
|
||||
mpt1327->dsp_mode = mode;
|
||||
}
|
||||
|
||||
void mpt1327_reset_sync(mpt1327_t *mpt1327)
|
||||
{
|
||||
mpt1327->rx_in_sync = 0;
|
||||
mpt1327->rx_sync = 0;
|
||||
mpt1327->rx_mute = 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
void dsp_init(void);
|
||||
int dsp_init_sender(mpt1327_t *mpt1327, double squelch_db);
|
||||
void dsp_cleanup_sender(mpt1327_t *mpt1327);
|
||||
void mpt1327_set_dsp_mode(mpt1327_t *mpt1327, enum dsp_mode mode, int repeater);
|
||||
void mpt1327_reset_sync(mpt1327_t *mpt1327);;
|
||||
|
|
@ -0,0 +1,398 @@
|
|||
/* MPT1327 main
|
||||
*
|
||||
* (C) 2021 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libmobile/main_mobile.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../anetz/freiton.h"
|
||||
#include "../anetz/besetztton.h"
|
||||
#include "../liboptions/options.h"
|
||||
#include "mpt1327.h"
|
||||
#include "dsp.h"
|
||||
#include "message.h"
|
||||
|
||||
/* settings */
|
||||
int num_freq = 0;
|
||||
static int num_chan_type = 0;
|
||||
static double squelch_db = -INFINITY;
|
||||
static enum mpt1327_band band = BAND_REGIONET43_SUB1;
|
||||
static enum mpt1327_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_TC };
|
||||
static int16_t sys = -1;
|
||||
static int wt = 10;
|
||||
static int per = 5;
|
||||
static int pon = 1;
|
||||
static int timeout = 30;
|
||||
|
||||
void print_image(void) {}
|
||||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
main_mobile_print_help(arg0, "-O ... | -I ... ");
|
||||
/* - - */
|
||||
printf(" -B --band <name> | list\n");
|
||||
printf(" Select frequency Band (default = '%s')\n", mpt1327_band_name(band));
|
||||
printf(" -T --channel-type <channel type> | list\n");
|
||||
printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0]));
|
||||
printf(" -O --operator <OPID> <NDD> <LAB>\n");
|
||||
printf(" -> decimal, '0x' for hex or all binary digits\n");
|
||||
printf(" Give System Identity Code of regional network (1st bit = 0)\n");
|
||||
printf(" OPID: Operator Identity (7 binary digits)\n");
|
||||
printf(" -> Check subscription data of mobile unit\n");
|
||||
printf(" NDD: Network Dependent Data (4 binary digts)\n");
|
||||
printf(" -> Check subscription data of mobile unit (must be '0001' or greater)\n");
|
||||
printf(" -> Change it to force re-registering of mobile unit.\n");
|
||||
printf(" LAB: Label for multiple control channels (3 binary digits)\n");
|
||||
printf(" -> Use '001' to allow all categories\n");
|
||||
printf(" -N --net <NET> <NDD> <LAB>\n");
|
||||
printf(" -> decimal, '0x' for hex or all binary digits\n");
|
||||
printf(" Give System Identity Code of national network (1st bit = 1)\n");
|
||||
printf(" NET: Network Identity (2 binary digits)\n");
|
||||
printf(" -> Check subscription data of mobile unit (must be '000000001' or greater)\n");
|
||||
printf(" -> Change it to force re-registering of mobile unit.\n");
|
||||
printf(" NDD: Network Dependent Data (9 binary digts)\n");
|
||||
printf(" LAB: Label for multiple control channels (3 binary digits)\n");
|
||||
printf(" -> Use '001' to allow all categories\n");
|
||||
printf(" -S --sysdef wt=5 | wt=10 | wt=15\n");
|
||||
printf(" Number of slots the Radio Unit waits for response. A slot lasts about\n");
|
||||
printf(" 107 ms. (default = %d)\n", wt);
|
||||
printf(" -S --sysdef per=<secs> | per=0\n");
|
||||
printf(" Interval of periodic messages from the Radio Unit while transmitting\n");
|
||||
printf(" speech. Use 1..31 to enable and 0 to disable. Also the 'timeout' value\n");
|
||||
printf(" must be greater than value given here. (default = %d)\n", per);
|
||||
printf(" -S --sysdef pon=1 | pon=0\n");
|
||||
printf(" The Radio Unit must send 'Pressel On' message to unmute the uplink.\n");
|
||||
printf(" If disabled, squelch must be enabled. (default = %d)\n", pon);
|
||||
printf(" -S --sysdef timeout=<secs> | timeout=off\n");
|
||||
printf(" The Traffic Channel is released, if no radio transmits for given amount of time.\n");
|
||||
printf(" (default = %d)\n", timeout);
|
||||
printf(" -Q --squelch <dB> | auto\n");
|
||||
printf(" Use given RF level to detect transmission on Traffic Channel, if\n");
|
||||
printf(" 'Pressel On' is disabled.\n");
|
||||
printf(" and stays below this level, the connection is released.\n");
|
||||
printf(" Use 'auto' to do automatic noise floor calibration to detect loss.\n");
|
||||
printf(" Only works with SDR! (disabled by default)\n");
|
||||
|
||||
printf("\nstation-id: Give 7 digits of Radio Unit's prefix/ident, you don't need to\n");
|
||||
printf(" enter it for every start of this program.\n");
|
||||
main_mobile_print_hotkeys();
|
||||
printf("Press 'i' key to dump list of seen Radio Units.\n");
|
||||
}
|
||||
|
||||
static void add_options(void)
|
||||
{
|
||||
main_mobile_add_options();
|
||||
option_add('B', "band", 1);
|
||||
option_add('T', "channel-type", 1);
|
||||
option_add('O', "operator", 3);
|
||||
option_add('N', "net", 3);
|
||||
option_add('S', "sysdef", 1);
|
||||
option_add('Q', "squelch", 1);
|
||||
}
|
||||
|
||||
static int read_sys(const char *param, const char *value, int digits)
|
||||
{
|
||||
int result = 0;
|
||||
int i;
|
||||
|
||||
if ((int)strlen(value) < digits) {
|
||||
result = strtoul(value, NULL, 0);
|
||||
if (result >= (1 << digits)) {
|
||||
fprintf(stderr, "Given '%s' value is out of range for %d binary digits, use '-h' for help!\n", param, digits);
|
||||
return -EINVAL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((int)strlen(value) > digits) {
|
||||
fprintf(stderr, "Given '%s' value must have exactly %d binary digits, use '-h' for help!\n", param, digits);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)strlen(value); i++) {
|
||||
if (value[i] < '0' || value[i] > '1') {
|
||||
fprintf(stderr, "Given '%s' value must only have binary digits of '0' or '1', use '-h' for help!\n", param);
|
||||
return -EINVAL;
|
||||
}
|
||||
result = (result << 1) | (value[i] - '0');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int handle_options(int short_option, int argi, char **argv)
|
||||
{
|
||||
int rc;
|
||||
const char *p;
|
||||
|
||||
switch (short_option) {
|
||||
case 'B':
|
||||
if (!strcmp(argv[argi], "list")) {
|
||||
mpt1327_band_list();
|
||||
return 0;
|
||||
}
|
||||
rc = mpt1327_band_by_short_name(argv[argi]);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Given band '%s' is illegal, use '-h' for help!\n", argv[argi]);
|
||||
return -EINVAL;
|
||||
}
|
||||
band = rc;
|
||||
break;
|
||||
case 'T':
|
||||
if (!strcmp(argv[argi], "list")) {
|
||||
mpt1327_channel_list();
|
||||
return 0;
|
||||
}
|
||||
rc = mpt1327_channel_by_short_name(argv[argi]);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", argv[argi]);
|
||||
return -EINVAL;
|
||||
}
|
||||
OPT_ARRAY(num_chan_type, chan_type, rc)
|
||||
break;
|
||||
case 'O':
|
||||
sys = 0x0000;
|
||||
rc = read_sys("OID", argv[argi + 0], 7);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
sys = sys | (rc << 7);
|
||||
rc = read_sys("NDD", argv[argi + 1], 4);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
sys = sys | (rc << 3);
|
||||
rc = read_sys("LAB", argv[argi + 2], 3);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
sys = sys | rc;
|
||||
break;
|
||||
case 'N':
|
||||
sys = 0x4000;
|
||||
rc = read_sys("NET", argv[argi + 0], 2);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
sys = sys | (rc << 12);
|
||||
rc = read_sys("NDD", argv[argi + 1], 9);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
sys = sys | (rc << 3);
|
||||
rc = read_sys("LAB", argv[argi + 2], 3);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
sys = sys | rc;
|
||||
break;
|
||||
case 'S':
|
||||
p = strchr(argv[argi], '=');
|
||||
if (!p) {
|
||||
fprintf(stderr, "Given sysdef parameter '%s' requires '=' character to set value, use '-h' for help!\n", argv[argi]);
|
||||
return -EINVAL;
|
||||
}
|
||||
p++;
|
||||
if (!strncasecmp(argv[argi], "wt=", p - argv[argi])) {
|
||||
wt = atoi(p);
|
||||
if (wt != 5 && wt != 10 && wt != 15) {
|
||||
sysdef_oor:
|
||||
fprintf(stderr, "Given sysdef parameter '%s' out of range, use '-h' for help!\n", argv[argi]);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else
|
||||
if (!strncasecmp(argv[argi], "per=", p - argv[argi])) {
|
||||
per = atoi(p);
|
||||
if (per < 0 || per >31)
|
||||
goto sysdef_oor;
|
||||
} else
|
||||
if (!strncasecmp(argv[argi], "pon=", p - argv[argi])) {
|
||||
pon = atoi(p);
|
||||
if (pon != 0 && pon != 1)
|
||||
goto sysdef_oor;
|
||||
} else
|
||||
if (!strncasecmp(argv[argi], "timeout=", p - argv[argi])) {
|
||||
timeout = atoi(p);
|
||||
} else
|
||||
{
|
||||
fprintf(stderr, "Given sysdef parameter '%s' unknown, use '-h' for help!\n", argv[argi]);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
if (!strcasecmp(argv[argi], "auto"))
|
||||
squelch_db = 0.0;
|
||||
else
|
||||
squelch_db = atof(argv[argi]);
|
||||
break;
|
||||
default:
|
||||
return main_mobile_handle_options(short_option, argi, argv);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc, argi;
|
||||
const char *station_id = "";
|
||||
int mandatory = 0;
|
||||
int i;
|
||||
|
||||
/* init tones */
|
||||
init_freiton();
|
||||
init_besetzton();
|
||||
// init_ansage();
|
||||
|
||||
console_digits = "0123456789*#";
|
||||
main_mobile_init();
|
||||
|
||||
/* handle options / config file */
|
||||
add_options();
|
||||
rc = options_config_file(argc, argv, "~/.osmocom/analog/mpt1327.conf", handle_options);
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
argi = options_command_line(argc, argv, handle_options);
|
||||
if (argi <= 0)
|
||||
return argi;
|
||||
|
||||
if (argi < argc) {
|
||||
station_id = argv[argi];
|
||||
if (strlen(station_id) != 7) {
|
||||
printf("Given station ID '%s' does not have 4 digits\n", station_id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!num_kanal) {
|
||||
printf("No channel (\"Kanal\") is specified, I suggest channel 1.\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (use_sdr) {
|
||||
/* set audiodev */
|
||||
for (i = 0; i < num_kanal; i++)
|
||||
audiodev[i] = "sdr";
|
||||
num_audiodev = num_kanal;
|
||||
/* set channel types for more than 1 channel */
|
||||
if (num_kanal > 1 && num_chan_type == 0) {
|
||||
chan_type[0] = CHAN_TYPE_CC;
|
||||
for (i = 1; i < num_kanal; i++)
|
||||
chan_type[i] = CHAN_TYPE_TC;
|
||||
num_chan_type = num_kanal;
|
||||
}
|
||||
|
||||
}
|
||||
if (num_kanal == 1 && num_audiodev == 0)
|
||||
num_audiodev = 1; /* use default */
|
||||
if (num_kanal != num_audiodev) {
|
||||
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
if (num_kanal == 1 && num_chan_type == 0)
|
||||
num_chan_type = 1; /* use default */
|
||||
if (num_kanal != num_chan_type) {
|
||||
fprintf(stderr, "You need to specify as many channel types as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (sys < 0) {
|
||||
fprintf(stderr, "No System Identity Code is specified, make them match with your radio unit.\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (isinf(squelch_db) && pon == 0) {
|
||||
fprintf(stderr, "'Pressel On' message (PON) and squelch are turned off. Enable one of them.\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (!isinf(squelch_db) && pon == 1) {
|
||||
fprintf(stderr, "'Pressel On' message (PON) and squelch are turned on. Disable one of them.\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (pon && timeout <= per) {
|
||||
fprintf(stderr, "The defined timeout value is lower than the Periodic message interval (PER). Define a greater timeout.\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (pon && (timeout && !per)) {
|
||||
fprintf(stderr, "You must enable Periodic message interval (PER), if you use timeout (and have no squelch).\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (!pon && !timeout) {
|
||||
fprintf(stderr, "Warning: 'Pressel On' message (PON) and timeout is both disabled. There will be no way to detect loss of Radio Unit.\n\n");
|
||||
}
|
||||
|
||||
if (do_de_emphasis || do_pre_emphasis) {
|
||||
printf("Don't use pre-/de-emphasis, it is not used for Speech, nor for signaling.\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
|
||||
if (mandatory) {
|
||||
print_help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no SDR, no squelch */
|
||||
if (!use_sdr && !isinf(squelch_db)) {
|
||||
fprintf(stderr, "Cannot use squelch without SDR! Analog receivers don't give use RSSI.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("Using Sysdef 0x%04x:\n", sys);
|
||||
if (!(sys & 0x4000)) {
|
||||
printf("OID=%d NDD=%d LAB=%d\n", (sys >> 7) & 0x7f, (sys >> 3) & 0xf, sys & 0x7);
|
||||
} else {
|
||||
printf("NET=%d NDD=%d LAB=%d\n", (sys >> 12) & 0x3, (sys >> 3) & 0x1ff, sys & 0x7);
|
||||
}
|
||||
|
||||
/* inits */
|
||||
fm_init(fast_math);
|
||||
dsp_init();
|
||||
init_codeword();
|
||||
init_sysdef(sys, wt, per, pon, timeout);
|
||||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
rc = mpt1327_create(band, kanal[i], chan_type[i], audiodev[i], use_sdr, samplerate, rx_gain, tx_gain, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, squelch_db);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create transceiver instance. Quitting!\n");
|
||||
goto fail;
|
||||
}
|
||||
printf("base station on channel %s ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz. (%s %.3f MHz offset)\n", kanal[i], mpt1327_channel2freq(band, atoi(kanal[i]), 0) / 1e6, mpt1327_channel2freq(band, atoi(kanal[i]), 1) / 1e6, mpt1327_band_name(band), mpt1327_channel2freq(band, atoi(kanal[i]), 2) / 1e6);
|
||||
}
|
||||
|
||||
mpt1327_check_channels();
|
||||
|
||||
main_mobile("mpt1327", &quit, latency, interval, NULL, station_id, 7);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
while (sender_head)
|
||||
mpt1327_destroy(sender_head);
|
||||
|
||||
/* exits */
|
||||
fm_exit();
|
||||
flush_units();
|
||||
|
||||
options_free();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,566 @@
|
|||
/* message transcoding
|
||||
*
|
||||
* (C) 2021 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include "../libdebug/debug.h"
|
||||
#include "message.h"
|
||||
|
||||
static struct mpt1327_parameter_names {
|
||||
const char *name;
|
||||
const char *description;
|
||||
} mpt1327_parameter_names[] = {
|
||||
{ "<constant>", "Constant" },
|
||||
{ "PFIX", "Group Prefix" },
|
||||
{ "IDENT1", "Called Party Number" },
|
||||
{ "D", "Data Call" },
|
||||
{ "CHAN", "Channel Number" },
|
||||
{ "IDENT2", "Calling Party Number" },
|
||||
{ "(N)", "Aloha Number" },
|
||||
{ "P", "Parity" },
|
||||
{ "CAT", "Category" },
|
||||
{ "TYPE", "Type" },
|
||||
{ "FUNC", "Function" },
|
||||
{ "CHAN4", "Last 4 Bits of Channel Number" },
|
||||
{ "WT", "Delay Parameter" },
|
||||
{ "RSVD", "Reserved" },
|
||||
{ "(M)", "Address Qualifier" },
|
||||
{ "QUAL", "Qualifies FUNC" },
|
||||
{ "DT", "Data" },
|
||||
{ "LEVEL", "Priority level" },
|
||||
{ "EXT", "Extended Addressing" },
|
||||
{ "FLAG1", "Flag 1" },
|
||||
{ "FLAG2", "Flag 2" },
|
||||
{ "PARAMETERS", "Parameters" },
|
||||
{ "SD", "Speech and/or Data" },
|
||||
{ "DIV", "Diversion" },
|
||||
{ "INFO", "Info" },
|
||||
{ "STATUS", "Status" },
|
||||
{ "SLOTS", "Slots for Data Message" },
|
||||
{ "POINT", "Demand Acknowledgement" },
|
||||
{ "CHECK", "Availability Check" },
|
||||
{ "E", "Emergency Call" },
|
||||
{ "AD", "Data is appended" },
|
||||
{ "DESC", "Type of Data" },
|
||||
{ "A", "B" },
|
||||
{ "B", "B" },
|
||||
{ "SPARE", "Spare" },
|
||||
{ "REVS", "Bit Reversals" },
|
||||
{ "OPER", NULL },
|
||||
{ "SYS", NULL },
|
||||
{ "CONT", NULL },
|
||||
{ "SYSDEF", NULL },
|
||||
{ "PER", NULL },
|
||||
{ "IVAL", NULL },
|
||||
{ "PON", NULL },
|
||||
{ "ID", NULL },
|
||||
{ "ADJSITE", NULL },
|
||||
{ "SOL", NULL },
|
||||
{ "LEN", NULL },
|
||||
{ "PREFIX2", NULL },
|
||||
{ "KIND", NULL },
|
||||
{ "PORT", NULL },
|
||||
{ "FAD", NULL },
|
||||
{ "INTER", NULL },
|
||||
{ "HADT", NULL },
|
||||
{ "MODEM", NULL },
|
||||
{ "O/R", NULL },
|
||||
{ "RATE", NULL },
|
||||
{ "TRANS", NULL },
|
||||
{ "RNITEL", NULL },
|
||||
{ "TNITEL", NULL },
|
||||
{ "JOB", NULL },
|
||||
{ "REASON", NULL },
|
||||
{ "ATRANS", NULL },
|
||||
{ "EFLAGS", NULL },
|
||||
{ "TASK", NULL },
|
||||
{ "ONES", NULL },
|
||||
{ "ITENUM", NULL },
|
||||
{ "USERDATA", NULL },
|
||||
{ "I/G", NULL },
|
||||
{ "MORE", NULL },
|
||||
{ "LASTBIT", NULL },
|
||||
{ "FRAGL", NULL },
|
||||
{ "RTRANS", NULL },
|
||||
{ "W/F", NULL },
|
||||
{ "P/N", NULL },
|
||||
{ "DN", NULL },
|
||||
{ "SPRE", NULL },
|
||||
{ "SX", NULL },
|
||||
{ "CAUSE", NULL },
|
||||
{ "I/T", NULL },
|
||||
{ "RESP", NULL },
|
||||
{ "TOC", NULL },
|
||||
{ "CCS", "Codeword Completion Sequence" },
|
||||
{ "LET", "Link Establishmen Time" },
|
||||
{ "PREAMBLE", NULL },
|
||||
{ "PARAMETERS1", NULL },
|
||||
{ "PARAMETERS2", NULL },
|
||||
{ "BCD11", "11 Digits encoded as BCD" },
|
||||
{ "RSA", NULL },
|
||||
{ "FCW", NULL },
|
||||
{ "SP", NULL },
|
||||
{ "EXCHANGE", NULL },
|
||||
{ "Number", NULL },
|
||||
{ "GF", NULL },
|
||||
{ "PFIXT", NULL },
|
||||
{ "IDENTT", NULL },
|
||||
{ "FORM", NULL },
|
||||
{ "PFIX2", NULL },
|
||||
};
|
||||
|
||||
char *mpt1327_bcd = "0123456789R*#RR"; /* last digit is NULL */
|
||||
|
||||
static struct definitions {
|
||||
int specific_only;
|
||||
enum mpt1327_codeword_dir dir;
|
||||
enum mpt1327_codeword_type type;
|
||||
char *def;
|
||||
const char *short_name;
|
||||
const char *long_name;
|
||||
} definitions[] = {
|
||||
/* Filler */
|
||||
{ 1, MPT_DOWN, MPT_FILLER, "0 RSVD:47=00000000000000000000000000000000000000000000000 P:16", "filler", "Filler Data" },
|
||||
/* GTC Message */
|
||||
{ 0, MPT_DOWN, MPT_GTC, "1 PFIX:7 IDENT1:13 0 D:1 CHAN:10 IDENT2:13 (N):2 P:16", "GTC", "Go To Traffic Channel" },
|
||||
/* Category '000' Messages: Aloha Messages (Type '00') */
|
||||
{ 0, MPT_DOWN, MPT_ALH, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=000 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALH", "Aloha: Any single codeword message invited" },
|
||||
{ 0, MPT_DOWN, MPT_ALHS, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=001 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALHS", "Aloha: Messages invited, except RQD" },
|
||||
{ 0, MPT_DOWN, MPT_ALHD, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=010 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALHD", "Aloha: Messages invited, except RQS" },
|
||||
{ 0, MPT_DOWN, MPT_ALHE, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=011 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALHE", "Aloha: Emergency requests (RQE) only invited" },
|
||||
{ 0, MPT_DOWN, MPT_ALHR, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=100 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALHR", "Aloha: Registration (RQR) or emergency requests (RQE) invited" },
|
||||
{ 0, MPT_DOWN, MPT_ALHX, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=101 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALHX", "Aloha: Messages invited, except RQR" },
|
||||
{ 0, MPT_DOWN, MPT_ALHF, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=00 FUNC:3=110 CHAN4:4 WT:3 RSVD:2 (M):5 (N):4 P:16", "ALHF", "Aloha: Fall-back mode" },
|
||||
/* Category '000' Messages: Acknowledgement Messages (Type '01') */
|
||||
{ 0, MPT_BOTH, MPT_ACK, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=000 IDENT2:13 QUAL:1 (N):4 P:16", "ACK", "Ack: General acknowledgement" },
|
||||
{ 0, MPT_BOTH, MPT_ACKI, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=001 IDENT2:13 QUAL:1 (N):4 P:16", "ACKI", "Ack: Intermediate acknowledgement, more signalling to follow" },
|
||||
{ 0, MPT_BOTH, MPT_ACKQ, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=010 IDENT2:13 QUAL:1 (N):4 P:16", "ACKQ", "Ack: Acknowledge, call queued" },
|
||||
{ 0, MPT_BOTH, MPT_ACKX, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=011 IDENT2:13 QUAL:1 (N):4 P:16", "ACKX", "Ack: Acknowledge, message rejected" },
|
||||
{ 0, MPT_BOTH, MPT_ACKV, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=100 IDENT2:13 QUAL:1 (N):4 P:16", "ACKV", "Ack: Acknowledge, called unit unavailable" },
|
||||
{ 0, MPT_BOTH, MPT_ACKE, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=101 IDENT2:13 QUAL:1 (N):4 P:16", "ACKE", "Ack: Acknowledge emergency call" },
|
||||
{ 0, MPT_BOTH, MPT_ACKT, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=110 IDENT2:13 QUAL:1 (N):4 P:16", "ACKT", "Ack: Acknowledge, try on given address" },
|
||||
{ 0, MPT_BOTH, MPT_ACKB, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=01 FUNC:3=111 IDENT2:13 QUAL:1 (N):4 P:16", "ACKB", "Ack: Acknowledge, call-back, or negative acknowledgement" },
|
||||
/* Category '000' Messages: Request Messages (Type '10') */
|
||||
{ 0, MPT_UP, MPT_RQS, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=000 IDENT2:13 DT:1 LEVEL:1 EXT:1 FLAG1:1 FLAG2:1 P:16", "RQS", "Request: Request Simple call" },
|
||||
{ 0, MPT_UP, MPT_RQSpare, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=001 PARAMETERS:18 P:16", "RQSpstr", "Request: Spare. Available for customisation" },
|
||||
{ 0, MPT_UP, MPT_RQX, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=010 IDENT2:13 RSVD:5 P:16", "RQX", "Request: Request call cancel / abort transaction" },
|
||||
{ 0, MPT_UP, MPT_RQT, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=011 IDENT2:13 SD:2 DIV:1 FLAG1:1 FLAG2:1 P:16", "RQT", "Request: Request call diversion" },
|
||||
{ 0, MPT_UP, MPT_RQE, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=100 IDENT2:13 D:1 RSVD:1 EXT:1 FLAG1:1 FLAG2:1 P:16", "RQE", "Request: Request emergency call" },
|
||||
{ 0, MPT_UP, MPT_RQR, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=101 INFO:15 RSVD:3 P:16", "RQR", "Request: Request to register" },
|
||||
{ 0, MPT_UP, MPT_RQQ, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=110 IDENT2:13 STATUS:5 P:16", "RQQ", "Request: Request status transaction" },
|
||||
{ 0, MPT_UP, MPT_RQC, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=111 IDENT2:13 SLOTS:2 EXT:1 FLAG1:1 FLAG2:1 P:16", "RQC", "Request: Request to send short data message" },
|
||||
/* Category '000' Messages: Ahoy Messages (Type '10') */
|
||||
{ 0, MPT_DOWN, MPT_AHY, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=000 IDENT2:13 D:1 POINT:1 CHECK:1 E:1 AD:1 P:16", "AHY", "Ahoy: General availability check" },
|
||||
{ 0, MPT_DOWN, MPT_AHYSpare, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=001 PARAMETERS:18 P:16", "AHYSpare", "Ahoy: Spare for customisation" },
|
||||
{ 0, MPT_DOWN, MPT_AHYX, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=010 IDENT2:13 POINT:5 P:16", "AHYX", "Ahoy: Cancel alert/waiting state" },
|
||||
{ 0, MPT_DOWN, MPT_AHYP, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=101 IDENT2:13 RSVD:5 P:16", "AHYP", "Ahoy: Called Unit Presence Monitoring" },
|
||||
{ 0, MPT_DOWN, MPT_AHYQ, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=110 IDENT2:13 STATUS:5 P:16", "AHYQ", "Ahoy: Status message" },
|
||||
{ 0, MPT_DOWN, MPT_AHYC, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=10 FUNC:3=111 IDENT2:13 SLOTS:2 DESC:3 P:16", "AHYC", "Ahoy: Short data invitation" },
|
||||
/* Category '000' Messages: Miscellaneous Control Messages (Type '11') */
|
||||
{ 0, MPT_DOWN, MPT_MARK, "1 CHAN4:4 A:1 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=000 B:18 P:16", "MARK", "Misc: Control channel marker" },
|
||||
{ 0, MPT_BOTH, MPT_MAINT, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=11 FUNC:3=001 CHAN:10 OPER:3 RSVD:5 P:16", "MAINT", "Misc: Call maintenance message" },
|
||||
{ 0, MPT_DOWN, MPT_CLEAR, "1 CHAN:10 CONT:10 1 CAT:3=000 TYPE:2=11 FUNC:3=010 RSVD:4 SPARE:2 REVS:12=101010101010 P:16", "CLEAR", "Misc: Clear down from allocated channel" },
|
||||
{ 0, MPT_DOWN, MPT_MOVE, "1 PFIX:7 IDENT1:13 1 CAT:3=000 TYPE:2=11 FUNC:3=011 CONT:10 (M):5 RSVD:2 SPARE:1 P:16", "MOVE", "Misc: Move to specified control channel" },
|
||||
{ 0, MPT_DOWN, MPT_BCAST0, "1 SYSDEF:5=00000 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=100 CHAN:10 SPARE:2 RSVD:6 P:16", "BCAST", "Misc: Broadcast message: Announce control channel" },
|
||||
{ 0, MPT_DOWN, MPT_BCAST1, "1 SYSDEF:5=00001 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=100 CHAN:10 SPARE:2 RSVD:6 P:16", "BCAST", "Misc: Broadcast message: Withdraw control channel" },
|
||||
{ 0, MPT_DOWN, MPT_BCAST2, "1 SYSDEF:5=00010 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=100 PER:1 IVAL:5 PON:1 ID:1 RSVD:2 SPARE:8 P:16", "BCAST", "Misc: Broadcast message: Specify call maintenance parameter" },
|
||||
{ 0, MPT_DOWN, MPT_BCAST3, "1 SYSDEF:5=00011 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=100 RSVD:4 SPARE:14 P:16", "BCAST", "Misc: Broadcast message: Specify registration parameters" },
|
||||
{ 0, MPT_DOWN, MPT_BCAST4, "1 SYSDEF:5=00100 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=100 CHAN:10 SPARE:2 RSVD:2 ADJSITE:4 P:16", "BCAST", "Misc: Broadcast message: Broadcast adjected site control channel number" },
|
||||
{ 0, MPT_DOWN, MPT_BCAST5, "1 SYSDEF:5=00101 SYS:15 1 CAT:3=000 TYPE:2=11 FUNC:3=100 CHAN:10 SPARE:2 RSVD:2 ADJSITE:4 P:16", "BCAST", "Misc: Broadcast message: Vote now advice" },
|
||||
/* Category '001' Messages */
|
||||
{ 0, MPT_DOWN, MPT_SAMO, "1 PFIX:7 IDENT1:13 1 CAT:3=001 TYPE:1=0 PARAMETERS:22 P:16", "SAMO", "Sam: Outbound Single Address Message" },
|
||||
{ 0, MPT_UP, MPT_SAMIU, "1 PFIX:7 IDENT1:13 1 CAT:3=001 TYPE:1=0 SOL:1=1 PARAMETERS:21 P:16", "SAMIU", "Sam: Inbound Unsolicited Single Address Message" },
|
||||
{ 0, MPT_UP, MPT_SAMIS, "1 PARAMETERS1:20 1 CAT:3=001 TYPE:1=0 SOL:1=0 DESC:3 PARAMETERS2:18 P:16", "SAMIS", "Sam: Inbound Solicited Single Address Message" },
|
||||
{ 0, MPT_BOTH, MPT_HEAD, "1 PFIX:7 IDENT1:13 1 CAT:3=001 TYPE:1=1 LEN:2 PREFIX2:7 IDENT2:13 P:16", "HEAD", "Short Data Message Header" },
|
||||
/*0Category '010' Messages */
|
||||
{ 0, MPT_UP, MPT_RQD, "1 PFIX:7 IDENT1:13 1 CAT:3=010 KIND:1=1 PORT:3 FAD:1 IDENT2:13 INTER:1 LEVEL:1 HADT:1 E:1 MODEM:1 P:16", "RQD", "Request Standard Data Communication" },
|
||||
{ 0, MPT_DOWN, MPT_AHYD, "1 PFIX:7 IDENT1:13 1 CAT:3=010 KIND:1=1 PORT:3 RSVD:1 IDENT2:13 INTER:1 POINT:1 HADT:1 E:1 AD:1 P:16", "AHYD", "Availability Check for Standard Data" },
|
||||
{ 0, MPT_DOWN, MPT_GTT, "1 PFIX:7 IDENT1:13 1 CAT:3=010 KIND:1=0 CHAN:10 O/R:1 RATE:1 TRANS:10 P:16", "GTT", "Go To Transaction" },
|
||||
{ 0, MPT_UP, MPT_DRUGI, "1 PFIX:7 IDENT1:13 1 CAT:3=010 KIND:1=0 RNITEL:6 TNITEL:6 TRANS:10 P:16", "DRUGI", "Standard Data Random access, Radio Unit General Information" },
|
||||
/* Category '101' Messages */
|
||||
{ 0, MPT_BOTH, MPT_DACKD, "1 PFIX:7 IDENT1:13 1 CAT:3=101 KIND:1=0 JOB:4=0101 RSVD:5 REASON:3 TRANS:10 P:16", "DACKD", "Standard Data general purpose acknowlegement" },
|
||||
{ 0, MPT_DOWN, MPT_DACK_DAL, "1 ATRANS:10 RTRANS:10 1 CAT:3=101 KIND:1=0 JOB:4=0000 W/F:3 P/N:1 RSVD:2 DN:5 TNITEL:6 ITENUM:1 P:16", "DACK+DAL", "Standard Data Codeword + DAL" },
|
||||
{ 0, MPT_DOWN, MPT_DACK_DALG, "1 ATRANS:10 RTRANS:10 1 CAT:3=101 KIND:1=0 JOB:4=0001 W/F:3 P/N:1 RSVD:2 DN:5 TNITEL:6 ITENUM:1 P:16", "DACK+DALG", "Standard Data Codeword + DALG" },
|
||||
{ 0, MPT_DOWN, MPT_DACK_DALN, "1 ATRANS:10 RTRANS:10 1 CAT:3=101 KIND:1=0 JOB:4=0010 W/F:3 P/N:1 RSVD:2 DN:5 TNITEL:6 ITENUM:1 P:16", "DACK+DALN", "Standard Data Codeword + DALN" },
|
||||
{ 0, MPT_BOTH, MPT_DACK_GO, "1 ATRANS:10 RTRANS:10 1 CAT:3=101 KIND:1=0 JOB:4=0011 RSVD:3 P/N:1 RSVD:1 RNITEL:6 TNITEL:6 ITENUM:1 P:16", "DACK+'GO'", "Standard Data Codeword + 'GO'" },
|
||||
{ 0, MPT_BOTH, MPT_DACKZ, "1 ATRANS:10 SPRE:10 1 CAT:3=101 KIND:1=0 JOB:4=0100 SX:3 SPRE:7 CAUSE:8 P:16", "DACKZ", "Standard Data Acknowledgement for expedited data" },
|
||||
{ 0, MPT_DOWN, MPT_DAHY, "1 TRANS:10 RSVD:10 1 CAT:3=101 KIND:1=0 JOB:4=1000 RSVD:10 SPARE:8 P:16", "DAHY", "Standard Data General ahoy" },
|
||||
{ 0, MPT_DOWN, MPT_DAHYZ, "1 SPRE:10 RSVD:10 1 CAT:3=101 KIND:1=0 JOB:4=1100 SX:3 SPRE:7 CAUSE:8 P:16", "DAHYZ", "Standard Data ahoy containing expedited data" },
|
||||
{ 0, MPT_DOWN, MPT_DAHYX, "1 PFIX:7 IDENT1:13 1 CAT:3=101 KIND:1=0 JOB:4=1110 I/T:1 RESP:1 SPRE:3 TOC:3 TRANS:10 P:16", "DHAYX", "Standard Data ahoy containing expedited data" },
|
||||
{ 0, MPT_BOTH, MPT_RLA, "1 TRANS:10 RSVD:10 1 CAT:3=101 KIND:1=0 JOB:4=1111 RSVD:12 SPARE:6 P:16", "RLA", "Repeat last ACK" },
|
||||
{ 0, MPT_UP, MPT_DRQG, "1 TRANS:10 SPARE:7 RSVD:3 1 CAT:3=101 KIND:1=0 JOB:4=1010 RSVD:18 P:16", "DRQG", "Repeat group message" },
|
||||
{ 0, MPT_UP, MPT_DRQZ, "1 TRANS:10 SPRE:10 1 CAT:3=101 KIND:1=0 JOB:4=1100 SX:3 SPRE:7 CAUSE:8 P:16", "DRQZ", "Request containing expedited data" },
|
||||
{ 0, MPT_UP, MPT_DRQX, "1 PFIX:7 IDENT1:13 1 CAT:3=101 KIND:1=0 JOB:4=1110 SPRE:5 TOC:3 TRANS:10 P:16", "DRQX", "Request to close a transaction" },
|
||||
{ 0, MPT_BOTH, MPT_SACK, "1 ATRANS:10 EFLAGS:10 1 CAT:3=101 KIND:1=1 TASK:1=0 RSVD:2 EFLAGS:13 ONES:4 AD:1 ITENUM:1 P:16", "SACK", "Standard Data Selective Acknowledgement Header" },
|
||||
{ 0, MPT_BOTH, MPT_SITH_I, "1 TRANS:10 USERDATA:10 1 CAT:3=101 KIND:1=1 TASK:1=1 I/G:1=0 MORE:1 LASTBIT:6 FRAGL:6 TNITEL:6 ITENUM:1 P:16", "SITH", "Standard Data Address Codeword (Individual) Dataitem" },
|
||||
{ 0, MPT_DOWN, MPT_SITH_G, "1 TRANS:10 USERDATA:10 1 CAT:3=101 KIND:1=1 TASK:1=1 I/G:1=1 MORE:1 LASTBIT:6 FRAGL:8 RSVD:4 ITENUM:1 P:16", "SITH", "Standard Data Address Codeword (Group) Dataitem" },
|
||||
/* Startup & CCSC */
|
||||
{ 1, MPT_DOWN, MPT_START_SYNC, "LET:32=00000000000000000000000000000000 PREAMBLE:16=1010101010101010 1100010011010111", "Startup", "Startup sequence on CC" },
|
||||
{ 0, MPT_DOWN, MPT_CCSC, "0 SYS:15 CCS:16 PREAMBLE:16=1010101010101010 P:16", "CCSC/DCSC", "System Identification" },
|
||||
{ 1, MPT_DOWN, MPT_START_SYNT, "LET:32=00000000000000000000000000000000 PREAMBLE:16=1010101010101010 0011101100101000", "SYNT", "Startup sequence on TC" },
|
||||
|
||||
/* Data codewords following ACKT(QUAL=0) address codeword */
|
||||
{ 1, MPT_DOWN, MPT_ACKT_DT1, "0 RSA:1 FCW:2 BCD11:44 P:16", "ACKT Data 1", "Ack: Acknowledge, try on given address; Data Word 1" },
|
||||
{ 1, MPT_DOWN, MPT_ACKT_DT2, "0 RSVD:10 SP:1=0 PARAMETERS:36 P:16", "ACKT Data 2", "Ack: Acknowledge, try on given address; Data Word 2" },
|
||||
{ 1, MPT_DOWN, MPT_ACKT_DT3, "0 RSVD:10 SP:1=1 RSVD:21 EXCHANGE:2 Number:13 P:16", "ACKT Data 3", "Ack: Acknowledge, try on given address; Data Word 3" },
|
||||
{ 1, MPT_DOWN, MPT_ACKT_DT4, "0 RSVD:26 GF:1 PFIXT:7 IDENTT:13 P:16", "ACKT Data 4", "Ack: Acknowledge, try on given address; Data Word 4" },
|
||||
/* Data codeword following AHY address codeword */
|
||||
{ 1, MPT_DOWN, MPT_AHY_DT, "0 FORM:3=000 RSVD:24 PFIX2:7 IDENT2:13 P:16", "AHY Data", "Ahoy: General availability check; Data Word" },
|
||||
/* Data codeword following AHYQ address codeword */
|
||||
{ 1, MPT_DOWN, MPT_AHYQ_DT, "0 RSVD:27 PFIX:7 IDENT2:13 P:16", "AHYQ Data", "Ahoy: Status message; Data Word" },
|
||||
/* Data codewords appended to SAMIS, Mode 1 */
|
||||
{ 1, MPT_UP, MPT_SAMIS_DT, "0 RSVD:3 BCD11:44 P:16", "SAMIS Data", "Sam: Inbound Solicited Single Address Message; Data Word" },
|
||||
/* Data codeword(s) following HEAD address codeword */
|
||||
{ 1, MPT_DOWN, MPT_HEAD_DT, "0 RSA:1 PARAMETERS:46 P:16", "HEAD Data", "Short Data Message Header; Data Word" },
|
||||
/* Data codeword following AHYD address codeword */
|
||||
{ 1, MPT_DOWN, MPT_AHYD_DT, "0 FORM:3=000 RSVD:24 PFIX2:7 IDENT2:13 P:16", "AHYD Data", "Availability Check for Standard Data; Data Word" },
|
||||
/* Data codeword following Standard Data Acknowledgement Header SACK */
|
||||
{ 1, MPT_DOWN, MPT_SACK_DT, "0 ONES:4 EFLAGS:40 RSVD:3 P:16", "SACK Data", "Standard Data Selective Acknowledgement; Data Word" },
|
||||
};
|
||||
|
||||
static struct mpt1327_defintion {
|
||||
int specific_only;
|
||||
enum mpt1327_codeword_dir dir;
|
||||
enum mpt1327_codeword_type type;
|
||||
const char *short_name;
|
||||
const char *long_name;
|
||||
uint64_t bits, mask;
|
||||
enum mpt1327_parameters params[64];
|
||||
} mpt1327_definitions[_NUM_MPT_DEFINITIONS];
|
||||
|
||||
static void _CHECK_MAX_BITS(int bits, const char *name)
|
||||
{
|
||||
if (bits == 64) {
|
||||
fprintf(stderr, "Message '%s' exceeds 64 bits, please fix!\n", name);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void init_codeword(void)
|
||||
{
|
||||
uint64_t bits, mask;
|
||||
int num_bits;
|
||||
enum mpt1327_parameters params[64];
|
||||
char *param_text, *next_param, *param, *param_bits, *param_const;
|
||||
int i, j, p, b;
|
||||
|
||||
if (sizeof(definitions) / sizeof(definitions[0]) != _NUM_MPT_DEFINITIONS) {
|
||||
fprintf(stderr, "definitions[] has different size than enum mpt1327_codeword_type, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
if (sizeof(mpt1327_parameter_names) / sizeof(mpt1327_parameter_names[0]) != _NUM_MPT_PARAMETERS) {
|
||||
fprintf(stderr, "mpt1327_parameter_names[] has different size than enum mpt1352_parameters, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* parse all message definitions */
|
||||
for (i = 0; i < _NUM_MPT_DEFINITIONS; i++) {
|
||||
bits = mask = 0;
|
||||
num_bits = 0;
|
||||
param_text = next_param = strdup(definitions[i].def);
|
||||
while ((param = strsep(&next_param, " "))) {
|
||||
if (param[0] >= '0' && param[0] <= '9') {
|
||||
/* param is a constant */
|
||||
while (*param) {
|
||||
if (*param < '0' || *param > '1') {
|
||||
fprintf(stderr, "Constant '%s' does not consists of '0' or '1' only, please fix!\n", param);
|
||||
abort();
|
||||
}
|
||||
_CHECK_MAX_BITS(num_bits, definitions[i].short_name);
|
||||
if ((*param++ & 1))
|
||||
bits |= 0x8000000000000000 >> num_bits;
|
||||
mask |= 0x8000000000000000 >> num_bits;
|
||||
params[num_bits] = 0;
|
||||
num_bits++;
|
||||
}
|
||||
} else {
|
||||
/* param is a parameter */
|
||||
param_bits = strchr(param, ':');
|
||||
if (!param_bits) {
|
||||
fprintf(stderr, "Param '%s' does not have a ':' to define number of bits, please fix!\n", param);
|
||||
abort();
|
||||
}
|
||||
*param_bits++ = '\0';
|
||||
/* get parameter from param text */
|
||||
for (p = 0; p < _NUM_MPT_PARAMETERS; p++) {
|
||||
if (!strcmp(mpt1327_parameter_names[p].name, param))
|
||||
break;
|
||||
}
|
||||
if (p == _NUM_MPT_PARAMETERS) {
|
||||
fprintf(stderr, "Param '%s' is not found in list of parameter names, please fix!\n", param);
|
||||
p = 0;
|
||||
}
|
||||
if (p > _NUM_MPT_PARAMETERS) {
|
||||
fprintf(stderr, "There are more parameters than definitons, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
/* get constant for parameter, if given */
|
||||
param_const = strchr(param_bits, '=');
|
||||
if (param_const) {
|
||||
*param_const++ = '\0';
|
||||
if ((int)strlen(param_const) != atoi(param_bits)) {
|
||||
fprintf(stderr, "Param '%s' has %s bits, but constant '%s' does not, please fix!\n", param, param_bits, param_const);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
for (b = 0; b < atoi(param_bits); b++) {
|
||||
_CHECK_MAX_BITS(num_bits, definitions[i].short_name);
|
||||
if (param_const) {
|
||||
if (param_const[b] < '0' || param_const[b] > '1') {
|
||||
fprintf(stderr, "Param '%s' has a constant '%s', but must only consist of '0' or '1', please fix!\n", param, param_const);
|
||||
abort();
|
||||
}
|
||||
if (param_const[b] == '1')
|
||||
bits |= 0x8000000000000000 >> num_bits;
|
||||
mask |= 0x8000000000000000 >> num_bits;
|
||||
}
|
||||
params[num_bits] = p;
|
||||
num_bits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(param_text);
|
||||
if (num_bits != 64) {
|
||||
fprintf(stderr, "Message '%s' (has %d bits) is not exactly 64 bits, please fix!\n", definitions[i].short_name, num_bits);
|
||||
abort();
|
||||
}
|
||||
#if 0
|
||||
printf("Message definition for '%s'\n", definitions[i].short_name);
|
||||
printf("%s\n", definitions[i].def);
|
||||
for (b = 0; b < 64; b++)
|
||||
printf("mask=%d data=%d name=%s\n", (mask >> (63 - b)) & 1, (bits >> (63 - b)) & 1, mpt1327_parameter_names[params[b]].name);
|
||||
#endif
|
||||
/* check type */
|
||||
if ((int)definitions[i].type != i) {
|
||||
fprintf(stderr, "Message '%s' has type %d, but index is %d. Type and index must match, please fix!\n", definitions[i].short_name, definitions[i].type, i);
|
||||
abort();
|
||||
}
|
||||
/* store codeword definition */
|
||||
mpt1327_definitions[i].specific_only = definitions[i].specific_only;
|
||||
mpt1327_definitions[i].dir = definitions[i].dir;
|
||||
mpt1327_definitions[i].type = definitions[i].type;
|
||||
mpt1327_definitions[i].short_name = definitions[i].short_name;
|
||||
mpt1327_definitions[i].long_name = definitions[i].long_name;
|
||||
mpt1327_definitions[i].bits = bits;
|
||||
mpt1327_definitions[i].mask = mask;
|
||||
memcpy(mpt1327_definitions[i].params, params, sizeof(params));
|
||||
/* check for duplicate message types */
|
||||
for (j = 0; j < i; j++)
|
||||
if (mpt1327_definitions[j].type == definitions[i].type)
|
||||
break;
|
||||
if (j < i) {
|
||||
fprintf(stderr, "Message '%s' is duplicated (index %d and %d have same message type), please fix!\n", definitions[i].short_name, j, i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate check bits, ispired by olle@toolcrypt.org (snable) */
|
||||
uint16_t mpt1327_checkbits(uint64_t bits, uint16_t *parityp)
|
||||
{
|
||||
uint16_t check = 0x0000, parity = 0;
|
||||
int bit;
|
||||
int b;
|
||||
|
||||
/* calculate check at upper 15 bits */
|
||||
for (b = 0; b < 48; b++) {
|
||||
bit = (bits >> (63 - b)) & 1;
|
||||
parity ^= bit;
|
||||
if (bit != (check >> 15))
|
||||
check ^= 0x6815;
|
||||
check <<= 1;
|
||||
}
|
||||
|
||||
/* invert lowest check bit (of 15 upper bits) */
|
||||
check ^= 0x0002;
|
||||
|
||||
/* finish parity and append as lest bit (bit 0) */
|
||||
for (b = 1; b < 16; b++)
|
||||
parity ^= (check >> b) & 1;
|
||||
check ^= parity;
|
||||
|
||||
if (parityp)
|
||||
*parityp = parity;
|
||||
return check;
|
||||
}
|
||||
|
||||
static void debug_codeword(const char *prefix, int i, uint64_t bits, int enc)
|
||||
{
|
||||
uint64_t value;
|
||||
char text[1024];
|
||||
int column;
|
||||
int b;
|
||||
|
||||
if (debuglevel > DEBUG_INFO)
|
||||
return;
|
||||
|
||||
switch (mpt1327_definitions[i].type) {
|
||||
case MPT_START_SYNC:
|
||||
case MPT_CCSC:
|
||||
case MPT_START_SYNT:
|
||||
case MPT_ALH:
|
||||
case MPT_ALHS:
|
||||
case MPT_ALHD:
|
||||
case MPT_ALHE:
|
||||
case MPT_ALHR:
|
||||
case MPT_ALHX:
|
||||
case MPT_ALHF:
|
||||
case MPT_BCAST0:
|
||||
case MPT_BCAST1:
|
||||
case MPT_BCAST2:
|
||||
case MPT_BCAST3:
|
||||
case MPT_BCAST4:
|
||||
case MPT_BCAST5:
|
||||
if (enc && debuglevel > DEBUG_DEBUG)
|
||||
return;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
PDEBUG(DFRAME, DEBUG_INFO, "%s Codeword %s: %s\n", prefix, mpt1327_definitions[i].short_name, mpt1327_definitions[i].long_name);
|
||||
column = 0;
|
||||
for (b = 0; b < 64; b++) {
|
||||
/* if we have first parameter or we swith to next parameter */
|
||||
if (b == 0 || mpt1327_definitions[i].params[b] != mpt1327_definitions[i].params[b - 1]) {
|
||||
value = 0;
|
||||
if (b != 0)
|
||||
text[column++] = ' ';
|
||||
if (mpt1327_definitions[i].params[b]) {
|
||||
strcpy(text + column, mpt1327_parameter_names[mpt1327_definitions[i].params[b]].name);
|
||||
column += strlen(mpt1327_parameter_names[mpt1327_definitions[i].params[b]].name);
|
||||
text[column++] = '=';
|
||||
}
|
||||
}
|
||||
value = (value << 1) | ((bits >> (63 - b)) & 1);
|
||||
text[column++] = ((bits >> (63 - b)) & 1) + '0';
|
||||
#if 0
|
||||
if (b == 63 || mpt1327_definitions[i].params[b] != mpt1327_definitions[i].params[b + 1]) {
|
||||
sprintf(text + column, "(%" PRIu64 ")", value);
|
||||
column += strlen(text + column);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
text[column] = '\0';
|
||||
PDEBUG(DFRAME, DEBUG_INFO, "%s\n", text);
|
||||
}
|
||||
|
||||
uint64_t mpt1327_encode_codeword(mpt1327_codeword_t *codeword)
|
||||
{
|
||||
uint64_t params[_NUM_MPT_PARAMETERS];
|
||||
uint64_t bits;
|
||||
int i, b;
|
||||
|
||||
/* check all codeword definitions */
|
||||
for (i = 0; i < _NUM_MPT_DEFINITIONS; i++) {
|
||||
if (mpt1327_definitions[i].type == codeword->type)
|
||||
break;
|
||||
}
|
||||
if (i == _NUM_MPT_DEFINITIONS) {
|
||||
fprintf(stderr, "Codeword not found for type %d, please fix!\n", codeword->type);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* fill parameters */
|
||||
memcpy(params, codeword->params, sizeof(params));
|
||||
bits = 0;
|
||||
for (b = 63; b >= 0; b--) {
|
||||
if ((params[mpt1327_definitions[i].params[b]] & 1))
|
||||
bits |= (0x8000000000000000 >> b);
|
||||
params[mpt1327_definitions[i].params[b]] >>= 1;
|
||||
}
|
||||
|
||||
/* set constants */
|
||||
bits = (bits & ~mpt1327_definitions[i].mask) | mpt1327_definitions[i].bits;
|
||||
|
||||
/* calculate MPT_CCS (See MTP1327 Appendix 3) */
|
||||
if (codeword->type == MPT_CCSC) {
|
||||
uint64_t ccs = 0xaaaac4d400000000 | ((codeword->params[MPT_SYS] & 0x7fff) << 17);
|
||||
uint16_t parity;
|
||||
assumption_wrong:
|
||||
ccs = (ccs & 0xffffffffffff0000) | mpt1327_checkbits(ccs, &parity);
|
||||
if (parity == 0) {
|
||||
ccs |= 0x10000;
|
||||
goto assumption_wrong;
|
||||
}
|
||||
bits = (bits & 0xffff0000ffffffff) | (((ccs ^ 0x2) & 0x1fffe) << 31);
|
||||
}
|
||||
|
||||
/* add parity, if not forced by definition */
|
||||
if (!(mpt1327_definitions[i].mask & 0xffff))
|
||||
bits = (bits & 0xffffffffffff0000) | mpt1327_checkbits(bits, NULL);
|
||||
|
||||
debug_codeword("Transmitting", i, bits, 1);
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
int mpt1327_decode_codeword(mpt1327_codeword_t *codeword, int specific, enum mpt1327_codeword_dir dir, uint64_t bits)
|
||||
{
|
||||
int i, b;
|
||||
|
||||
memset(codeword, 0, sizeof(*codeword));
|
||||
codeword->dir = dir;
|
||||
|
||||
/* check all codeword definitions */
|
||||
for (i = 0; i < _NUM_MPT_DEFINITIONS; i++) {
|
||||
/* skip if direction does not match */
|
||||
if (dir != mpt1327_definitions[i].dir && mpt1327_definitions[i].dir != MPT_BOTH)
|
||||
continue;
|
||||
if (specific >= 0) {
|
||||
/* select where type matches */
|
||||
if (mpt1327_definitions[i].type == (unsigned int)specific)
|
||||
break;
|
||||
} else {
|
||||
/* ignore message definitions that require specifiying codeword type */
|
||||
if (mpt1327_definitions[i].specific_only)
|
||||
continue;
|
||||
/* select where masked bits match */
|
||||
if (mpt1327_definitions[i].bits == (bits & mpt1327_definitions[i].mask))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == _NUM_MPT_DEFINITIONS) {
|
||||
char debug[256];
|
||||
PDEBUG(DFRAME, DEBUG_NOTICE, "Received unknown codeword or loopback from transmitter side.\n");
|
||||
for (b = 0; b < 64; b++)
|
||||
debug[b] = ((bits >> (63 - b)) & 1) + '0';
|
||||
debug[b] = '\0';
|
||||
PDEBUG(DFRAME, DEBUG_DEBUG, "%s\n", debug);
|
||||
return -EINVAL;
|
||||
}
|
||||
codeword->type = mpt1327_definitions[i].type;
|
||||
codeword->short_name = mpt1327_definitions[i].short_name;
|
||||
codeword->long_name = mpt1327_definitions[i].long_name;
|
||||
|
||||
/* fill parameters */
|
||||
for (b = 0; b < 64; b++) {
|
||||
codeword->params[mpt1327_definitions[i].params[b]] <<= 1;
|
||||
if ((bits & (0x8000000000000000 >> b)))
|
||||
codeword->params[mpt1327_definitions[i].params[b]] |= 1;
|
||||
}
|
||||
|
||||
debug_codeword("Receiving", i, bits, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
|
||||
#define IDENT_ALLI 8191 /* System-wide ident */
|
||||
#define IDENT_TSCI 8190 /* Ident of TSC */
|
||||
#define IDENT_IPFIXI 8189 /* Interprefix ident */
|
||||
#define IDENT_SDMI 8188 /* Short data message ident */
|
||||
#define IDENT_DIVERTI 8187 /* Divert ident */
|
||||
#define IDENT_INCI 8186 /* Include ident */
|
||||
#define IDENT_REGI 8185 /* Registration ident */
|
||||
#define IDENT_PSTNSI1 8121 /* Short-form PSTN idents */
|
||||
#define IDENT_NETSI1 8121 /* Short-form data Network idents */
|
||||
#define IDENT_DNI 8103 /* Data Network gateway ident */
|
||||
#define IDENT_PABXI 8102 /* PABX gateway ident */
|
||||
#define IDENT_PSTNGI 8101 /* General PSTN gateway ident */
|
||||
#define IDENT_DUMMYI 0 /* Dummy ident */
|
||||
|
||||
#define OPER_PRESSEL_ON 0
|
||||
#define OPER_PRESSEL_OFF 1
|
||||
#define OPER_PERIODIC 2
|
||||
#define OPER_DISCONNECT 3
|
||||
#define OPER_SPARE 4
|
||||
#define OPER_RESERVED 5
|
||||
#define OPER_CLEAR 6
|
||||
#define OPER_DISABLE 7
|
||||
|
||||
enum mpt1327_codeword_dir {
|
||||
MPT_DOWN,
|
||||
MPT_UP,
|
||||
MPT_BOTH,
|
||||
};
|
||||
|
||||
enum mpt1327_codeword_type {
|
||||
MPT_FILLER = 0,
|
||||
MPT_GTC,
|
||||
MPT_ALH,
|
||||
MPT_ALHS,
|
||||
MPT_ALHD,
|
||||
MPT_ALHE,
|
||||
MPT_ALHR,
|
||||
MPT_ALHX,
|
||||
MPT_ALHF,
|
||||
MPT_ACK,
|
||||
MPT_ACKI,
|
||||
MPT_ACKQ,
|
||||
MPT_ACKX,
|
||||
MPT_ACKV,
|
||||
MPT_ACKE,
|
||||
MPT_ACKT,
|
||||
MPT_ACKB,
|
||||
MPT_RQS,
|
||||
MPT_RQSpare,
|
||||
MPT_RQX,
|
||||
MPT_RQT,
|
||||
MPT_RQE,
|
||||
MPT_RQR,
|
||||
MPT_RQQ,
|
||||
MPT_RQC,
|
||||
MPT_AHY,
|
||||
MPT_AHYSpare,
|
||||
MPT_AHYX,
|
||||
MPT_AHYP,
|
||||
MPT_AHYQ,
|
||||
MPT_AHYC,
|
||||
MPT_MARK,
|
||||
MPT_MAINT,
|
||||
MPT_CLEAR,
|
||||
MPT_MOVE,
|
||||
MPT_BCAST0,
|
||||
MPT_BCAST1,
|
||||
MPT_BCAST2,
|
||||
MPT_BCAST3,
|
||||
MPT_BCAST4,
|
||||
MPT_BCAST5,
|
||||
MPT_SAMO,
|
||||
MPT_SAMIU,
|
||||
MPT_SAMIS,
|
||||
MPT_HEAD,
|
||||
MPT_RQD,
|
||||
MPT_AHYD,
|
||||
MPT_GTT,
|
||||
MPT_DRUGI,
|
||||
MPT_DACKD,
|
||||
MPT_DACK_DAL,
|
||||
MPT_DACK_DALG,
|
||||
MPT_DACK_DALN,
|
||||
MPT_DACK_GO,
|
||||
MPT_DACKZ,
|
||||
MPT_DAHY,
|
||||
MPT_DAHYZ,
|
||||
MPT_DAHYX,
|
||||
MPT_RLA,
|
||||
MPT_DRQG,
|
||||
MPT_DRQZ,
|
||||
MPT_DRQX,
|
||||
MPT_SACK,
|
||||
MPT_SITH_I,
|
||||
MPT_SITH_G,
|
||||
MPT_START_SYNC,
|
||||
MPT_CCSC,
|
||||
MPT_START_SYNT,
|
||||
MPT_ACKT_DT1,
|
||||
MPT_ACKT_DT2,
|
||||
MPT_ACKT_DT3,
|
||||
MPT_ACKT_DT4,
|
||||
MPT_AHY_DT,
|
||||
MPT_AHYQ_DT,
|
||||
MPT_SAMIS_DT,
|
||||
MPT_HEAD_DT,
|
||||
MPT_AHYD_DT,
|
||||
MPT_SACK_DT,
|
||||
_NUM_MPT_DEFINITIONS
|
||||
};
|
||||
|
||||
enum mpt1327_parameters {
|
||||
MPT_CONSTANT = 0,
|
||||
MPT_PFIX,
|
||||
MPT_IDENT1,
|
||||
MPT_D,
|
||||
MPT_CHAN,
|
||||
MPT_IDENT2,
|
||||
MPT_N,
|
||||
MPT_P,
|
||||
MPT_CAT,
|
||||
MPT_TYPE,
|
||||
MPT_FUNC,
|
||||
MPT_CHAN4,
|
||||
MPT_WT,
|
||||
MPT_RSVD,
|
||||
MPT_M,
|
||||
MPT_QUAL,
|
||||
MPT_DT,
|
||||
MPT_LEVEL,
|
||||
MPT_EXT,
|
||||
MPT_FLAG1,
|
||||
MPT_FLAG2,
|
||||
MPT_PARAMETERS,
|
||||
MPT_SD,
|
||||
MPT_DIV,
|
||||
MPT_INFO,
|
||||
MPT_STATUS,
|
||||
MPT_SLOTS,
|
||||
MPT_POINT,
|
||||
MPT_CHECK,
|
||||
MPT_E,
|
||||
MPT_AD,
|
||||
MPT_DESC,
|
||||
MPT_A,
|
||||
MPT_B,
|
||||
MPT_SPARE,
|
||||
MPT_REVS,
|
||||
MPT_OPER,
|
||||
MPT_SYS,
|
||||
MPT_CONT,
|
||||
MPT_SYSDEF,
|
||||
MPT_PER,
|
||||
MPT_IVAL,
|
||||
MPT_PON,
|
||||
MPT_ID,
|
||||
MPT_ADJSITE,
|
||||
MPT_SOL,
|
||||
MPT_LEN,
|
||||
MPT_PREFIX2,
|
||||
MPT_KIND,
|
||||
MPT_PORT,
|
||||
MPT_FAD,
|
||||
MPT_INTER,
|
||||
MPT_HADT,
|
||||
MPT_MODEM,
|
||||
MPT_O_R,
|
||||
MPT_RATE,
|
||||
MPT_TRANS,
|
||||
MPT_RNITEL,
|
||||
MPT_TNITEL,
|
||||
MPT_JOB,
|
||||
MPT_REASON,
|
||||
MPT_ATRANS,
|
||||
MPT_EFLAGS,
|
||||
MPT_TASK,
|
||||
MPT_ONES,
|
||||
MPT_ITENUM,
|
||||
MPT_USERDATA,
|
||||
MPT_I_G,
|
||||
MPT_MORE,
|
||||
MPT_LASTBIT,
|
||||
MPT_FRAGL,
|
||||
MPT_RTRANS,
|
||||
MPT_W_F,
|
||||
MPT_P_N,
|
||||
MPT_DN,
|
||||
MPT_SPRE,
|
||||
MPT_SX,
|
||||
MPT_CAUSE,
|
||||
MPT_I_T,
|
||||
MPT_RESP,
|
||||
MPT_TOC,
|
||||
MPT_CCS,
|
||||
MPT_LET,
|
||||
MPT_PREAMBLE,
|
||||
MPT_PARAMETERS1,
|
||||
MPT_PARAMETERS2,
|
||||
MPT_BCD11,
|
||||
MPT_RSA,
|
||||
MPT_FCW,
|
||||
MPT_SP,
|
||||
MPT_EXCHANGE,
|
||||
MPT_Number,
|
||||
MPT_GF,
|
||||
MPT_PFIXT,
|
||||
MPT_IDENTT,
|
||||
MPT_FORM,
|
||||
MPT_PFIX2,
|
||||
_NUM_MPT_PARAMETERS
|
||||
};
|
||||
|
||||
extern char *mpt1327_bcd;
|
||||
|
||||
typedef struct mpt1327_codeword {
|
||||
enum mpt1327_codeword_dir dir;
|
||||
enum mpt1327_codeword_type type;
|
||||
const char *short_name, *long_name;
|
||||
uint64_t params[_NUM_MPT_PARAMETERS];
|
||||
} mpt1327_codeword_t;
|
||||
|
||||
void init_codeword(void);
|
||||
uint16_t mpt1327_checkbits(uint64_t bits, uint16_t *parityp);
|
||||
uint64_t mpt1327_encode_codeword(mpt1327_codeword_t *codeword);
|
||||
int mpt1327_decode_codeword(mpt1327_codeword_t *codeword, int specific, enum mpt1327_codeword_dir dir, uint64_t bits);
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,155 @@
|
|||
#include "../libsquelch/squelch.h"
|
||||
#include "../libfsk/fsk.h"
|
||||
#include "../libmobile/sender.h"
|
||||
|
||||
enum mpt1327_band {
|
||||
BAND_MPT1343_SUB1 = 0,
|
||||
BAND_MPT1343_SUB2,
|
||||
BAND_REGIONET43_SUB1,
|
||||
BAND_REGIONET43_SUB2,
|
||||
};
|
||||
|
||||
enum mpt1327_chan_type {
|
||||
CHAN_TYPE_CC, /* control channel */
|
||||
CHAN_TYPE_TC, /* traffic channel */
|
||||
CHAN_TYPE_CC_TC, /* combined CC + TC */
|
||||
};
|
||||
|
||||
enum mpt1327_state {
|
||||
STATE_NULL = 0,
|
||||
STATE_IDLE,
|
||||
STATE_BUSY,
|
||||
};
|
||||
|
||||
enum dsp_mode {
|
||||
DSP_MODE_OFF = 0, /* no transmission, no reception */
|
||||
DSP_MODE_CONTROL, /* send/receive codewords */
|
||||
DSP_MODE_TRAFFIC, /* send/receive codewords and audio */
|
||||
};
|
||||
|
||||
enum mpt1327_sched_state {
|
||||
/* states on control channel */
|
||||
SCHED_STATE_CC_IDLE,
|
||||
SCHED_STATE_CC_STARTUP,
|
||||
SCHED_STATE_CC_CCSC,
|
||||
SCHED_STATE_CC_ADDR,
|
||||
SCHED_STATE_CC_DATA,
|
||||
/* states on traffic channel */
|
||||
SCHED_STATE_TC_IDLE,
|
||||
SCHED_STATE_TC_SYNT,
|
||||
SCHED_STATE_TC_ADDR,
|
||||
SCHED_STATE_TC_DATA,
|
||||
};
|
||||
|
||||
enum mpt1327_called_type {
|
||||
CALLED_TYPE_UNIT, /* call to radio unit / line unit / group */
|
||||
CALLED_TYPE_INTERPFX, /* same as above with different prefix */
|
||||
CALLED_TYPE_SYSTEM, /* system wide call */
|
||||
CALLED_TYPE_PBX_SHORT, /* call to short PBX extenstion */
|
||||
CALLED_TYPE_PBX_LONG, /* call to long PBX extenstion */
|
||||
CALLED_TYPE_PSTN_PRE, /* call to PSTN with prearranged number */
|
||||
CALLED_TYPE_PSTN_LONG1, /* call to PSTN with 1..9 digits */
|
||||
CALLED_TYPE_PSTN_LONG2, /* call to PSTN with 10..31 digits */
|
||||
};
|
||||
|
||||
typedef struct mpt1327_sysdef {
|
||||
uint16_t sys; /* system idenity */
|
||||
int wt;
|
||||
int per;
|
||||
int pon;
|
||||
double timeout;
|
||||
int framelength;
|
||||
int bcast_slots;
|
||||
} mpt1327_sysdef_t;
|
||||
|
||||
typedef struct mpt1327_tx_sched {
|
||||
enum mpt1327_sched_state state; /* what was currently scheduled */
|
||||
int frame_length; /* number of slots in frame */
|
||||
int frame_count; /* current slot number */
|
||||
int dummy_slot; /* set, if next slot uses a dummy AHY */
|
||||
int bcast_count; /* counts slots until sending broadcast */
|
||||
} mpt1327_tx_sched_t;
|
||||
|
||||
typedef struct mpt1327_rx_sched {
|
||||
int data_num; /* set if N data words are awaited */
|
||||
int data_count; /* count data words */
|
||||
int data_word; /* what data word to parse */
|
||||
uint8_t data_prefix; /* unit that requires that data word */
|
||||
uint16_t data_ident;
|
||||
} mpt1327_rx_sched_t;
|
||||
|
||||
struct mpt1327;
|
||||
|
||||
typedef struct mpt1327_unit {
|
||||
struct mpt1327_unit *next;
|
||||
uint64_t state;
|
||||
int repeat; /* number of repeating messages / retries after timeout */
|
||||
struct timer timer; /* timeout waiting for unit response */
|
||||
struct mpt1327 *tc; /* link to transceiver */
|
||||
uint8_t prefix; /* unit's prefix */
|
||||
uint16_t ident; /* unit's ident */
|
||||
uint8_t called_prefix;
|
||||
uint16_t called_ident;
|
||||
enum mpt1327_called_type called_type;
|
||||
char called_number[33]; /* 0+number+'\0' */
|
||||
uint32_t callref; /* PBX/PSTN link to call control */
|
||||
} mpt1327_unit_t;
|
||||
|
||||
typedef struct mpt1327 {
|
||||
sender_t sender;
|
||||
enum mpt1327_band band;
|
||||
enum mpt1327_chan_type chan_type;
|
||||
|
||||
/* sender's states */
|
||||
enum mpt1327_state state; /* current sender's state */
|
||||
struct timer timer; /* inactivity timer to clear channel */
|
||||
mpt1327_unit_t *unit; /* link to unit */
|
||||
|
||||
/* display measurements */
|
||||
dispmeasparam_t *dmp_frame_level;
|
||||
dispmeasparam_t *dmp_frame_quality;
|
||||
dispmeasparam_t *dmp_super_level;
|
||||
dispmeasparam_t *dmp_super_quality;
|
||||
|
||||
/* scheduler states */
|
||||
mpt1327_tx_sched_t tx_sched; /* downlink scheduler states, see above */
|
||||
mpt1327_rx_sched_t rx_sched; /* uplink scheduler states, see above */
|
||||
|
||||
/* dsp states */
|
||||
int repeater; /* in repeater mode the received audio is repeated */
|
||||
jitter_t repeater_dejitter; /* forwarding audio */
|
||||
int pressel_on; /* set if somebody transmitting on TC */
|
||||
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
||||
fsk_mod_t fsk_mod; /* fsk processing */
|
||||
fsk_demod_t fsk_demod;
|
||||
uint16_t sync_word; /* current sync word for channel */
|
||||
uint16_t rx_sync; /* shift register to detect sync */
|
||||
int rx_in_sync; /* if we are in sync and receive bits */
|
||||
int rx_mute; /* set, if currently receiving a message */
|
||||
uint64_t rx_bits; /* receive frame (one extra byte to terminate string) */
|
||||
int rx_count; /* next bit to receive */
|
||||
double rx_level[256]; /* level infos */
|
||||
double rx_quality[256]; /* quality infos */
|
||||
uint64_t tx_bits; /* carries bits of one frame to transmit */
|
||||
int tx_bit_num; /* number of bits to tansmit, or 0, if no transmission */
|
||||
int tx_count; /* next bit to transmit */
|
||||
squelch_t squelch; /* squelch detection process */
|
||||
} mpt1327_t;
|
||||
|
||||
void init_sysdef (uint16_t sys, int wt, int per, int pon, int timeout);
|
||||
void flush_units(void);
|
||||
double mpt1327_channel2freq(enum mpt1327_band band, int channel, int uplink);
|
||||
const char *mpt1327_band_name(enum mpt1327_band band);
|
||||
void mpt1327_band_list(void);
|
||||
int mpt1327_band_by_short_name(const char *short_name);
|
||||
void mpt1327_channel_list(void);
|
||||
int mpt1327_channel_by_short_name(const char *short_name);
|
||||
const char *chan_type_short_name(enum mpt1327_chan_type chan_type);
|
||||
const char *chan_type_long_name(enum mpt1327_chan_type chan_type);
|
||||
int mpt1327_create(enum mpt1327_band band, const char *kanal, enum mpt1327_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double tx_gain, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, double squelch_db);
|
||||
void mpt1327_check_channels(void);
|
||||
void mpt1327_destroy(sender_t *sender);
|
||||
void mpt1327_receive_codeword(mpt1327_t *mpt1327, uint64_t bits, double quality, double level);
|
||||
int mpt1327_send_codeword(mpt1327_t *mpt1327, uint64_t *bits);
|
||||
void mpt1327_signal_indication(mpt1327_t *mpt1327);
|
||||
|
Loading…
Reference in New Issue