Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

337 changed files with 138628 additions and 156825 deletions

12
.gitignore vendored
View File

@ -19,8 +19,8 @@ compile
.deps
.libs
.dirstamp
src/liblogging/liblogging.a
src/liboptions/liboptions.a
src/libdebug/libdebug.a
src/libmobile/libmobile.a
src/libdisplay/libdisplay.a
src/libimage/libimage.a
@ -31,6 +31,7 @@ src/libjitter/libjitter.a
src/libsquelch/libsquelch.a
src/libhagelbarger/libhagelbarger.a
src/libdtmf/libdtmf.a
src/libtimer/libtimer.a
src/libsamplerate/libsamplerate.a
src/libscrambler/libscrambler.a
src/libemphasis/libemphasis.a
@ -47,6 +48,8 @@ src/libclipper/libclipper.a
src/libserial/libserial.a
src/libv27/libv27.a
src/libmtp/libmtp.a
src/libosmocc/libosmocc.a
src/libg711/libg711.a
src/libaaimage/libaaimage.a
src/anetz/libgermanton.a
src/anetz/anetz
@ -59,8 +62,8 @@ src/nmt/nmt
src/amps/libusatone.a
src/amps/libamps.a
src/amps/amps
src/amps/tacs
src/amps/jtacs
src/tacs/tacs
src/jtacs/jtacs
src/r2000/radiocom2000
src/imts/imts
src/imts/imts-dialer
@ -68,7 +71,6 @@ src/mpt1327/mpt1327
src/jolly/jollycom
src/eurosignal/eurosignal
src/pocsag/pocsag
src/golay/golay
src/fuenf/5-ton-folge
src/tv/osmotv
src/radio/osmoradio
@ -78,8 +80,6 @@ src/sim/cnetz_sim
src/magnetic/cnetz_magnetic
src/fuvst/fuvst
src/fuvst/fuvst_sniffer
src/dcf77/dcf77
src/mate/matesimulator
extra/cnetz_memory_card_generator
src/test/test_filter
src/test/test_sendevolumenregler

28
INSTALL
View File

@ -1,30 +1,24 @@
You need to have the following packages install:
* libosmocore, core libraries for various osmocom related projects
* libosmo-cc, call control interface library, to interconnect applications
* automake, gcc for compilation
* libasound2 for sound card support, which is what you need!
* libsoapysdr or libuhd (developer) to support SDR
* -> SoapySDR modules to support your SDR hardware
* libimagamagick version >= 7 (developer) optionally for TV image display
Install libosmocore:
See: https://osmocom.org/projects/libosmocore/wiki/Libosmocore
Install libosmo-cc:
$ git clone https://gitea.osmocom.org/osmocom/libosmo-cc.git
$ cd libosmocore/
$ autoreconf -i
$./configure
$ make
s udo make install
$ sudo ldconfig -i
$ cd ..
Generate "configure":
$ autoreconf -if
Run "configure":
Install osmocom-analog:
$ autoreconf -i
$ ./configure
Build and install:
$ make
$ sudo make install
$ make install

14
README
View File

@ -24,13 +24,11 @@ Additionally the following communication services are implemented:
* TV Transmitter with test Images
* Radio transmitter / receiver
* Analog Modem Emulation 'Datenklo' (AM7911)
* Analog Modem Emulation (AM7911)
* German classic 'Zeitansage' (talking clock)
* POCSAG transmitter / receiver
* Golay/GSC transmitter / receiver
* DCF77 time signal transmitter and receiver with weather info
* C-Netz SIM emulator
* C-Netz magnetic card emulator
* 5-Ton-Folge + Sirenensteuerung
USE AT YOUR OWN RISK!
@ -69,10 +67,10 @@ providing memory cards to be programmed for older C-Netz phone.
Dieter Spaar providing TACS recordings to verify and debug TACS support.
Hans Wigger providing Radiocom 2000 recordings, to reverse-enigineer the
standard, which seems not to exist anymore...
Hans Wigger providing Radiocom 2000 recordings, to reverse-enigeer the standard,
which seems not to exist anymore...
Peter, Peter, Friedhelm and Stephan for providing documentation and hardware
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.

View File

@ -1,5 +1,7 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT([abcnetz],[m4_esyscmd(./git-version-gen .tarball-version)],[jolly@eversberg.eu])
AC_INIT([abcnetz],
m4_esyscmd([./git-version-gen .tarball-version]),
[jolly@eversberg.eu])
AM_INIT_AUTOMAKE([dist-bzip2])
@ -15,6 +17,9 @@ AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_RANLIB
dnl checks for header files
AC_HEADER_STDC
dnl Checks for typedefs, structures and compiler characteristics
AC_CANONICAL_HOST
@ -22,9 +27,6 @@ AC_CANONICAL_HOST
AC_CHECK_LIB([m], [main], [], [echo "Failed to find lib!" ; exit -1])
AC_CHECK_LIB([pthread], [main], [], [echo "Failed to find lib!" ; exit -1])
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.6.0)
PKG_CHECK_MODULES(LIBOSMOCC, libosmocc >= 2.0.0)
with_sdr=no
soapy_0_8_0_or_higher=
AC_ARG_WITH([alsa], [AS_HELP_STRING([--with-alsa], [compile with Alsa driver @<:@default=check@:>@]) ], [], [with_alsa="check"])
@ -58,8 +60,9 @@ AS_IF([test "x$with_alsa" != "xyes" -a "x$with_sdr" != "xyes"],[AC_MSG_NOTICE( W
SOAPY_CFLAGS="$soapy_0_8_0_or_higher"
AC_CONFIG_FILES([src/liblogging/Makefile
AC_OUTPUT(
src/liboptions/Makefile
src/libdebug/Makefile
src/libmobile/Makefile
src/libdisplay/Makefile
src/libimage/Makefile
@ -70,6 +73,7 @@ AC_CONFIG_FILES([src/liblogging/Makefile
src/libsquelch/Makefile
src/libhagelbarger/Makefile
src/libdtmf/Makefile
src/libtimer/Makefile
src/libsamplerate/Makefile
src/libscrambler/Makefile
src/libemphasis/Makefile
@ -86,19 +90,22 @@ AC_CONFIG_FILES([src/liblogging/Makefile
src/libserial/Makefile
src/libv27/Makefile
src/libmtp/Makefile
src/libosmocc/Makefile
src/libg711/Makefile
src/libaaimage/Makefile
src/anetz/Makefile
src/bnetz/Makefile
src/cnetz/Makefile
src/nmt/Makefile
src/amps/Makefile
src/tacs/Makefile
src/jtacs/Makefile
src/r2000/Makefile
src/imts/Makefile
src/mpt1327/Makefile
src/jolly/Makefile
src/eurosignal/Makefile
src/pocsag/Makefile
src/golay/Makefile
src/fuenf/Makefile
src/tv/Makefile
src/radio/Makefile
@ -107,12 +114,9 @@ AC_CONFIG_FILES([src/liblogging/Makefile
src/sim/Makefile
src/magnetic/Makefile
src/fuvst/Makefile
src/dcf77/Makefile
src/mate/Makefile
src/test/Makefile
src/Makefile
extra/Makefile
Makefile])
AC_OUTPUT
Makefile)

View File

@ -54,7 +54,7 @@ A caller must not know the location of the phone anymore to reach the right base
<li>Channel spacing: 10 KHz and optionally 12.5 KHz
<li>Voice modulation: FM
<li>Signaling modulation: carrier FSK
<li>Frequency deviation: 2.5 KHz (FSK); 2.4 or 4 KHz (Voice)
<li>Frequency deviation: 2.5 KHz (FSK); 4 KHz (Voice)
<li>Mobile station transmit power: 50 mW up to 15 Watts
<li>Base station transmit power: 25 Watts
<li>Features: Speech Compandor, Audio scrambling

View File

@ -129,10 +129,8 @@ Additional features:
<li><a href="magnetic.html">C-Netz Magnetic Card</a></li>
<li>Zeitansage (German talking clock)</li>
<li>C-Netz FuVSt (MSC to control a real base station)</li>
<li>POCSAG (paging system)</li>
<li>Golay / GSC (paging system)</li>
<li>POCSAG</li>
<li>5-Ton-Ruf (firefighter's pagers and siren control)</li>
<li>DCF77 The German longwave time signal transmitter/receiver</li>
</ul>
</td></tr></table></center>

View File

@ -66,7 +66,7 @@ Create a virtual machine with the following settings:
<ul>
<li>Create a virtual machine with Ubuntu (64-bit)
<li>Choose memory size of at least 2 GB
<li>Create a virtual hard drive with 25 GB
<li>Create a virtual hard drive with at least 10 GB
<li>Emulate sound with output and input
<li>Select USB 3.0 (xHCI) Controller
</ul>
@ -162,18 +162,6 @@ Installing osmocom-analog
</p>
<p>
You need two libraries, the first is "libosmocore". It is included with Ubuntu/Debian:
</p>
<pre>
# sudo apt install libosmocore-dev
</pre>
<p>
The next library is "libosmo-cc". It is not included with Ubuntu/Debian, so you need to install it from GIT.
Use GIT to clone latest source repository. First you need to install GIT.
</p>
@ -185,83 +173,31 @@ Use GIT to clone latest source repository. First you need to install GIT.
</pre>
<p>
Then you can clone libosmo-cc from <a href="https://gitea.osmocom.org/cc/libosmo-cc">https://gitea.osmocom.org/cc/libosmo-cc</a> in your home directory.
Then you can clone osmocom-analog from <a href="git://git.osmocom.org/osmocom-analog">git://git.osmocom.org/osmocom-analog</a> in your home directory.
</p>
<pre>
# cd ~
# git clone https://gitea.osmocom.org/cc/libosmo-cc
Cloning into 'libosmo-cc'...
...
</pre>
<p>
Before you can compile, you need to install <b>"autoconf"</b>, <b>"gcc"</b> and <b>"make"</b>, and <b>"libtool"</b>.
</p>
<pre>
# sudo apt install autoconf gcc make libtool
</pre>
<p>
Change to the repository directory and run <b>"autoreconf -if"</b> once. This is only needed the first time compiling. It will generate the configure script.
</p>
<pre>
# cd libosmo-cc
# autoreconf -if
...
#
</pre>
<p>
Run configure script. It will generate the make files depending on your supported libraries.
</p>
<pre>
# ./configure
</pre>
<p>
Run <b>"make"</b> and <b>"make install"</b> to build and install osmocom-analog. Don't forget to run <b>"ldconfig"</b>, so you library database does know it.
</p>
<pre>
# make clean # always do this after you pulled from GIT server
# make
...
# sudo make install
...
# sudo ldconfig
# cd ..
</pre>
<p>
Use GIT to clone latest source repository. First you need to install GIT.
</p>
<p>
Then you can clone osmocom-analog from <a href="https://gitea.osmocom.org/cellular-infrastructure/osmocom-analog">https://gitea.osmocom.org/cellular-infrastructure/osmocom-analog</a> in your home directory.
</p>
<pre>
# cd ~
# git clone https://gitea.osmocom.org/cellular-infrastructure/osmocom-analog
# git clone git://git.osmocom.org/osmocom-analog
Cloning into 'osmocom-analog'...
...
</pre>
<p>
Before you can compile, you need to install <b>"autoconf"</b>, <b>"gcc"</b> and <b>"make"</b>.
</p>
<pre>
# sudo apt install autoconf
# sudo apt install gcc
# sudo apt install make
</pre>
</pre>
<p>
@ -306,10 +242,6 @@ configure: Compiling with FUSE
</pre>
<p style="background-color: yellow;">
If you get something like "sytax error near unexpected token `ALSA,`", check, if pkg-config is installed. If you just installed it, run "autoreconf -if" again and then "./configure".
</p>
<p>
Run <b>"make"</b> and <b>"make install"</b> to build and install osmocom-analog.
</p>
@ -321,7 +253,6 @@ Run <b>"make"</b> and <b>"make install"</b> to build and install osmocom-analog.
...
# sudo make install
...
# cd ..
</pre>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

View File

@ -158,12 +158,6 @@ Be sure to print it without scaling!
<center><img src="mag1.jpg"/></center>
<p>
Also there is a KiCad version with the coil on PCB and space for battery holder:
</p>
<center><img src="mag5.jpg"/></center>
<p>
Leave the fuses of the ATTINY85 as it is shipped by default.
The fuses are set to use the internal 8 MHz clock with scaling to 1 MHz.
@ -289,8 +283,6 @@ The Security code must be a 16 bit unsigned integer, entered in decimal notation
BSA 44 Service Cards
</p>
<center><img src="mag3.jpg"/></center>
<p>
When inserting (simulating) a service card, a BSA44 phone will show "Wartungskarte" on its LC display.
Turn off the phone and then turn it on again, but leave card inserted and power connected.

View File

@ -293,7 +293,7 @@ Build Your Own SIM Card
You find the PCB drawings inside the "layout" directory of the git repository.
Be sure to print it without scaling!
Check if the printed size matches an ISO card.
Also there are the source files for the 'Eagle' and 'KiCad' layout programs.
Also there is the source files for the 'Eagle' layout program, if you like to change it.
</p>
<p>
@ -427,12 +427,10 @@ Turn on the phone and you will be asked for a PIN.
Enter the PIN 9991 to alter the first subscriber data.
Enter the PIN 9992 .. 9998 to alter second to eighth subscriber data.
The subscriber data is shown in the telephone directory and can be altered by changing the numbers in that directory.
Also the SIM software version is shown on entry 06 of the telephone directory, but it cannot be changed.
The Bosch OF 7 does not like to store numbers less than 3 digits. Put zeroes in front, if you want to store a value less than 1000.
</p>
<p>
The default subscriber data and SIM version and where to change them in the telephone directory:
The default subscriber data and where to change them in the telephone directory:
<br><br>
<table class="sim">
<tr><th>Entry</th><th>Name</th><th>Number</th></tr>
@ -441,12 +439,9 @@ The default subscriber data and SIM version and where to change them in the tele
<tr><td>03</td><td>Kartenkennung</td><td>3</td></tr>
<tr><td>04</td><td>Sonderheitsschl.</td><td>0</td></tr>
<tr><td>05</td><td>Wartungsschl.</td><td>65535</td></tr>
<tr><td>06</td><td>SIM software version</td><td>xxx **</td></tr>
</table>
<br>
(*) When PIN 9991 was entered.
<br>
(**) This value represents the software version and cannot be changed.
</p>
@ -468,8 +463,6 @@ To program one of the following service cards, change the subscriber data to the
<tr><td>Philips Miniporty<br><a href="monitorkarte.pdf">extended cell monitor</a></td><td>-</td><td>-</td><td>-</td><td>900</td><td>2729</td></tr>
<tr><td>Philips Porty<br>service mode</td><td>0</td><td>0</td><td>0</td><td>2304</td><td>-</td></tr>
<tr><td>Philips Porty<br>cell monitor</td><td>-</td><td>-</td><td>-</td><td>898</td><td>-</td></tr>
<tr><td>AEG Telecar C<br>service mode</td><td>-</td><td>-</td><td>-</td><td>144 or 911</td><td>-</td></tr>
<tr><td>AEG Telecar C<br>cell monitor</td><td>-</td><td>-</td><td>-</td><td>899</td><td>-</td></tr>
</table>
</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

@ -15,7 +15,7 @@ To get a list of all options, run the base station software (E.g bnetz) with no
</p>
<p class="toppic">
Sound interface using ALSA
Sound interface
</p>
<p>
@ -64,69 +64,6 @@ If you prefer card 2, device 0, add '-a hw:2,0' or '--audio-device hw:2,0' to th
</pre>
<p class="toppic">
Prevent Puleaudio from occupying a sound adapter
</p>
<p>
In some cases, pulseaudio occupies the sound interface, so that it cannot be used via ALSA API.
"Device or resource busy" will be reported by the application.
One way would be to stop pulseaudio daemon, if there is only a single audio device available.
If an extra sound device, like an USB stick shall be used, we can just block it for pulseaudio, using udev rule.
</p>
<p>
First, we need to check the device ID using lsusb (USB) or lspci (PCI):
</p>
<pre>
# lsusb
...
Bus 001 Device 030: ID 0bda:4937 Realtek Semiconductor Corp. Realtek Audio USB
...
</pre>
<p>
In this case there is an USB stick with vendor ID "0bda" and device ID "4937".
If nano is our favorite editor, we add a new udev rule (sudo or be root):
</p>
<pre>
# nano /etc/udev/rules.d/89-pulseaudio-ignore_0bda_4937.rules
</pre>
<p>
Choose any index (like 89), but be sure that it must be lower than any other pulseaudio rule, if there is any at all. Add some name that explains exactly what device is blocked, but feel free to user any other name.
</p>
<p>
Add this line to block the device shown above, but use the right IDs:
</p>
<pre>
ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4937", ENV{PULSE_IGNORE}="1"
</pre>
<p>
When using PCI, you need to reboot.
When using USB, unplug it and then load the new rules before replugging it:
</p>
<pre>
udevadm control --reload-rules
</pre>
<p>
To verify that the rule works, check if the device is available using "pavucontrol".
Do that before and after, to see the effect.
</p>
<p class="toppic">
Basic level adjustment
</p>

View File

@ -7,7 +7,6 @@ cnetz_memory_card_generator_SOURCES = \
main.c
cnetz_memory_card_generator_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS)
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/liboptions/liboptions.a

View File

@ -22,7 +22,7 @@
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <../src/liblogging/logging.h>
#include <../src/libdebug/debug.h>
#include <../src/liboptions/options.h>
int num_kanal = 1;
@ -196,8 +196,7 @@ int main(int argc, char *argv[])
int argi;
int i;
loglevel = LOGL_INFO;
logging_init();
debuglevel = DEBUG_INFO;
add_options();
@ -256,5 +255,3 @@ inval_sub:
return 0;
}
void osmo_cc_set_log_cat(void) {}

View File

@ -17,13 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* NOTE: Reset must be an input pin, not the reset of the controller.
* The clock pulse must be detected during reset.
*/
#if defined(__AVR_ATtiny85__)
#define RST_PIN 2
#define CLK_PIN 3
#define DATA_PIN 4
#error UNTESTED!
#else
#define CLK_PIN 5
#define RST_PIN 6
@ -31,14 +29,15 @@
#endif
uint8_t card_data[] = {
/* Example: Service card for AEG OLYMPIA. */
0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x38,
0x78, 0x28, 0x07, 0x8c, 0xc7, 0x03, 0xfe, 0xfd,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4b, 0x90,
0x5f, 0x25, 0x07, 0x0c, 0x00, 0x00, 0xfe, 0xfd,
0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
volatile uint8_t *rst_in, *clk_in, *data_in, *data_out, *data_mode;
@ -71,8 +70,6 @@ void setup()
data_out = portOutputRegister(port);
data_in = portInputRegister(port);
*data_mode |= data_bit; /* output */
/* wait for reset */
while (!(*rst_in & rst_bit));
}
uint8_t byte_count;
@ -81,14 +78,22 @@ uint8_t bit_count;
void loop()
{
reset:
/* initial reset state */
byte_count = 0;
bit_count = 0;
*data_out |= data_bit; /* high */
/* now we have reset, so we wait for the first clock pulse */
while (!(*clk_in & clk_bit));
while ((*clk_in & clk_bit));
/* wait for reset to become low, if not already before first clock pulse (AEG phone) */
/* wait for reset pulse */
while (!(*rst_in & rst_bit));
/* now we have reset, so we wait for clock pulse */
while (!(*clk_in & clk_bit)) {
/* if we lost reset, go to start */
if (!(*rst_in & rst_bit))
goto reset;
}
while ((*clk_in & clk_bit)) {
/* if we lost reset, go to start */
if (!(*rst_in & rst_bit))
goto reset;
}
while ((*rst_in & rst_bit));
next_bit:

View File

@ -1,87 +0,0 @@
(module LOGO (layer F.Cu)
(at 0 0)
(fp_text reference "G***" (at 0 0) (layer F.SilkS) hide
(effects (font (thickness 0.3)))
)
(fp_text value "LOGO" (at 0.75 0) (layer F.SilkS) hide
(effects (font (thickness 0.3)))
)
(fp_poly (pts (xy 3.066152 -6.121191) (xy 3.428893 -6.120766) (xy 3.752319 -6.119859) (xy 4.038875 -6.118399) (xy 4.291009 -6.116313) (xy 4.511168 -6.113530) (xy 4.701799 -6.109980) (xy 4.865348 -6.105590)
(xy 5.004263 -6.100290) (xy 5.120991 -6.094008) (xy 5.217978 -6.086672) (xy 5.297671 -6.078211) (xy 5.362518 -6.068554) (xy 5.414965 -6.057629) (xy 5.457458 -6.045365) (xy 5.492446 -6.031691)
(xy 5.522375 -6.016535) (xy 5.549692 -5.999825) (xy 5.576844 -5.981491) (xy 5.606277 -5.961461) (xy 5.621560 -5.951464) (xy 5.802237 -5.806446) (xy 5.943182 -5.626144) (xy 6.008480 -5.504621)
(xy 6.081889 -5.348111) (xy 6.081889 5.065889) (xy 6.008480 5.222399) (xy 5.886481 5.426964) (xy 5.729099 5.591065) (xy 5.622219 5.668819) (xy 5.590776 5.689726) (xy 5.562762 5.708887)
(xy 5.535715 5.726375) (xy 5.507170 5.742266) (xy 5.474661 5.756634) (xy 5.435724 5.769553) (xy 5.387896 5.781099) (xy 5.328710 5.791346) (xy 5.255703 5.800368) (xy 5.166409 5.808240)
(xy 5.058365 5.815037) (xy 4.929106 5.820832) (xy 4.776167 5.825702) (xy 4.597084 5.829720) (xy 4.389392 5.832960) (xy 4.150626 5.835498) (xy 3.878322 5.837408) (xy 3.570016 5.838765)
(xy 3.223242 5.839643) (xy 2.835536 5.840116) (xy 2.404434 5.840260) (xy 1.927471 5.840149) (xy 1.402182 5.839857) (xy 0.826103 5.839459) (xy 0.196769 5.839030) (xy 0.001126 5.838908)
(xy -0.535567 5.838462) (xy -1.058045 5.837786) (xy -1.563427 5.836894) (xy -2.048833 5.835799) (xy -2.511382 5.834517) (xy -2.948193 5.833062) (xy -3.356385 5.831447) (xy -3.733077 5.829687)
(xy -4.075389 5.827796) (xy -4.380439 5.825788) (xy -4.645347 5.823678) (xy -4.867232 5.821480) (xy -5.043214 5.819207) (xy -5.170410 5.816875) (xy -5.245941 5.814497) (xy -5.266077 5.812913)
(xy -5.491258 5.740750) (xy -5.690423 5.620986) (xy -5.856268 5.458485) (xy -5.911083 5.383451) (xy -5.933608 5.350592) (xy -5.954232 5.321477) (xy -5.973038 5.293611) (xy -5.990111 5.264501)
(xy -6.005534 5.231654) (xy -6.019391 5.192575) (xy -6.031764 5.144771) (xy -6.042737 5.085749) (xy -6.052394 5.013016) (xy -6.060819 4.924076) (xy -6.068093 4.816438) (xy -6.074302 4.687607)
(xy -6.079529 4.535089) (xy -6.083857 4.356392) (xy -6.087369 4.149022) (xy -6.090149 3.910484) (xy -6.092281 3.638287) (xy -6.093847 3.329935) (xy -6.094932 2.982935) (xy -6.095619 2.594794)
(xy -6.095991 2.163018) (xy -6.096131 1.685114) (xy -6.096124 1.158588) (xy -6.096053 0.580947) (xy -6.096001 -0.050304) (xy -6.096000 -0.141111) (xy -6.096043 -0.779900) (xy -6.096116 -1.364739)
(xy -6.096137 -1.898120) (xy -6.096052 -2.256360) (xy -5.814193 -2.256360) (xy -5.814125 -1.757197) (xy -5.813966 -1.208271) (xy -5.813819 -0.607124) (xy -5.813777 -0.141111) (xy -5.813854 0.499116)
(xy -5.814015 1.085355) (xy -5.814159 1.620064) (xy -5.814184 2.105699) (xy -5.813989 2.544718) (xy -5.813470 2.939576) (xy -5.812526 3.292731) (xy -5.811055 3.606639) (xy -5.808956 3.883758)
(xy -5.806125 4.126544) (xy -5.802462 4.337453) (xy -5.797865 4.518944) (xy -5.792230 4.673472) (xy -5.785457 4.803495) (xy -5.777444 4.911469) (xy -5.768088 4.999850) (xy -5.757287 5.071097)
(xy -5.744940 5.127665) (xy -5.730944 5.172012) (xy -5.715199 5.206594) (xy -5.697600 5.233868) (xy -5.678048 5.256290) (xy -5.656439 5.276319) (xy -5.632672 5.296410) (xy -5.606645 5.319020)
(xy -5.586384 5.338304) (xy -5.561771 5.364561) (xy -5.541081 5.388626) (xy -5.521883 5.410597) (xy -5.501747 5.430569) (xy -5.478242 5.448637) (xy -5.448937 5.464897) (xy -5.411403 5.479446)
(xy -5.363209 5.492377) (xy -5.301924 5.503789) (xy -5.225118 5.513775) (xy -5.130361 5.522432) (xy -5.015222 5.529855) (xy -4.877271 5.536141) (xy -4.714078 5.541384) (xy -4.523212 5.545681)
(xy -4.302242 5.549127) (xy -4.048739 5.551819) (xy -3.760271 5.553851) (xy -3.434409 5.555319) (xy -3.068722 5.556320) (xy -2.660779 5.556948) (xy -2.208151 5.557300) (xy -1.708406 5.557471)
(xy -1.159115 5.557557) (xy -0.557847 5.557654) (xy -0.012178 5.557812) (xy 0.631245 5.558012) (xy 1.220601 5.558088) (xy 1.758268 5.558023) (xy 2.246624 5.557799) (xy 2.688045 5.557398)
(xy 3.084909 5.556803) (xy 3.439595 5.555995) (xy 3.754479 5.554958) (xy 4.031940 5.553673) (xy 4.274354 5.552123) (xy 4.484100 5.550290) (xy 4.663554 5.548156) (xy 4.815095 5.545704)
(xy 4.941100 5.542915) (xy 5.043947 5.539772) (xy 5.126012 5.536258) (xy 5.189674 5.532355) (xy 5.237311 5.528044) (xy 5.271300 5.523308) (xy 5.293600 5.518255) (xy 5.468036 5.437528)
(xy 5.619157 5.309399) (xy 5.722084 5.169645) (xy 5.799667 5.037667) (xy 5.799667 -5.319888) (xy 5.722084 -5.451866) (xy 5.654063 -5.548879) (xy 5.572372 -5.640625) (xy 5.538639 -5.671399)
(xy 5.514868 -5.692021) (xy 5.493943 -5.710917) (xy 5.473421 -5.728161) (xy 5.450859 -5.743829) (xy 5.423815 -5.757996) (xy 5.389844 -5.770737) (xy 5.346504 -5.782127) (xy 5.291352 -5.792243)
(xy 5.221946 -5.801158) (xy 5.135842 -5.808948) (xy 5.030596 -5.815689) (xy 4.903768 -5.821456) (xy 4.752912 -5.826324) (xy 4.575587 -5.830368) (xy 4.369349 -5.833663) (xy 4.131755 -5.836285)
(xy 3.860363 -5.838309) (xy 3.552729 -5.839811) (xy 3.206411 -5.840864) (xy 2.818965 -5.841546) (xy 2.387948 -5.841930) (xy 1.910918 -5.842093) (xy 1.385432 -5.842109) (xy 0.809046 -5.842054)
(xy 0.179318 -5.842003) (xy 0.000000 -5.842000) (xy -0.647201 -5.842068) (xy -1.240388 -5.842208) (xy -1.781990 -5.842324) (xy -2.274439 -5.842319) (xy -2.720163 -5.842096) (xy -3.121593 -5.841560)
(xy -3.481159 -5.840613) (xy -3.801291 -5.839160) (xy -4.084419 -5.837103) (xy -4.332972 -5.834346) (xy -4.549381 -5.830793) (xy -4.736077 -5.826347) (xy -4.895488 -5.820912) (xy -5.030045 -5.814390)
(xy -5.142178 -5.806687) (xy -5.234316 -5.797705) (xy -5.308891 -5.787347) (xy -5.368331 -5.775518) (xy -5.415068 -5.762121) (xy -5.451530 -5.747058) (xy -5.480148 -5.730235) (xy -5.503352 -5.711554)
(xy -5.523572 -5.690918) (xy -5.543238 -5.668232) (xy -5.564779 -5.643398) (xy -5.586748 -5.620162) (xy -5.614426 -5.594245) (xy -5.639774 -5.572614) (xy -5.662894 -5.552810) (xy -5.683888 -5.532378)
(xy -5.702857 -5.508859) (xy -5.719902 -5.479799) (xy -5.735127 -5.442739) (xy -5.748633 -5.395223) (xy -5.760521 -5.334795) (xy -5.770893 -5.258997) (xy -5.779852 -5.165373) (xy -5.787498 -5.051467)
(xy -5.793934 -4.914820) (xy -5.799262 -4.752978) (xy -5.803583 -4.563482) (xy -5.806999 -4.343877) (xy -5.809612 -4.091705) (xy -5.811524 -3.804509) (xy -5.812836 -3.479834) (xy -5.813650 -3.115222)
(xy -5.814069 -2.708216) (xy -5.814193 -2.256360) (xy -6.096052 -2.256360) (xy -6.096021 -2.382538) (xy -6.095685 -2.820485) (xy -6.095047 -3.214456) (xy -6.094021 -3.566944) (xy -6.092526 -3.880442)
(xy -6.090477 -4.157444) (xy -6.087792 -4.400443) (xy -6.084386 -4.611933) (xy -6.080176 -4.794408) (xy -6.075080 -4.950361) (xy -6.069013 -5.082285) (xy -6.061892 -5.192675) (xy -6.053634 -5.284023)
(xy -6.044156 -5.358823) (xy -6.033373 -5.419569) (xy -6.021202 -5.468754) (xy -6.007561 -5.508872) (xy -5.992366 -5.542416) (xy -5.975533 -5.571880) (xy -5.956978 -5.599757) (xy -5.936619 -5.628541)
(xy -5.914372 -5.660725) (xy -5.911207 -5.665485) (xy -5.776472 -5.825354) (xy -5.604536 -5.962390) (xy -5.418666 -6.059831) (xy -5.400964 -6.065986) (xy -5.378659 -6.071628) (xy -5.349305 -6.076783)
(xy -5.310456 -6.081478) (xy -5.259665 -6.085739) (xy -5.194485 -6.089592) (xy -5.112469 -6.093065) (xy -5.011172 -6.096183) (xy -4.888146 -6.098973) (xy -4.740946 -6.101462) (xy -4.567124 -6.103675)
(xy -4.364234 -6.105640) (xy -4.129829 -6.107382) (xy -3.861462 -6.108929) (xy -3.556688 -6.110306) (xy -3.213060 -6.111541) (xy -2.828131 -6.112659) (xy -2.399454 -6.113686) (xy -1.924583 -6.114651)
(xy -1.401071 -6.115578) (xy -0.826472 -6.116494) (xy -0.198339 -6.117426) (xy -0.072960 -6.117607) (xy 0.577063 -6.118577) (xy 1.173088 -6.119493) (xy 1.717563 -6.120284) (xy 2.212933 -6.120878)
(xy 2.661648 -6.121204) (xy 3.066152 -6.121191) )(layer F.SilkS) (width 0.010000)
)
(fp_poly (pts (xy 0.388056 -5.224861) (xy 0.926284 -5.151909) (xy 1.442169 -5.030009) (xy 1.931989 -4.860185) (xy 2.269161 -4.707442) (xy 2.385467 -4.646290) (xy 2.515386 -4.573424) (xy 2.649910 -4.494458)
(xy 2.780026 -4.415003) (xy 2.896725 -4.340672) (xy 2.990997 -4.277077) (xy 3.053830 -4.229830) (xy 3.076223 -4.204760) (xy 3.054679 -4.181883) (xy 2.996572 -4.134523) (xy 2.911693 -4.070406)
(xy 2.843389 -4.020972) (xy 2.588378 -3.819391) (xy 2.327603 -3.576761) (xy 2.072524 -3.305783) (xy 1.834598 -3.019161) (xy 1.625286 -2.729598) (xy 1.505020 -2.537285) (xy 1.380316 -2.322904)
(xy 1.142496 -2.442260) (xy 0.832858 -2.574342) (xy 0.519563 -2.658740) (xy 0.184960 -2.699984) (xy 0.127000 -2.702934) (xy -0.253898 -2.695011) (xy -0.612890 -2.637152) (xy -0.957530 -2.527568)
(xy -1.290385 -2.367282) (xy -1.454436 -2.258755) (xy -1.632699 -2.113583) (xy -1.812300 -1.944640) (xy -1.980365 -1.764801) (xy -2.124018 -1.586940) (xy -2.226171 -1.431496) (xy -2.390141 -1.085856)
(xy -2.501199 -0.729720) (xy -2.559954 -0.368118) (xy -2.567011 -0.006082) (xy -2.522977 0.351358) (xy -2.428460 0.699171) (xy -2.284065 1.032326) (xy -2.090401 1.345792) (xy -1.857529 1.624740)
(xy -1.581126 1.879192) (xy -1.286102 2.083481) (xy -0.963395 2.243070) (xy -0.657253 2.348609) (xy -0.558411 2.374336) (xy -0.462583 2.392205) (xy -0.355847 2.403564) (xy -0.224279 2.409764)
(xy -0.053956 2.412154) (xy 0.000000 2.412321) (xy 0.240604 2.407938) (xy 0.442234 2.391658) (xy 0.621727 2.360022) (xy 0.795921 2.309569) (xy 0.981650 2.236841) (xy 1.089842 2.188395)
(xy 1.296608 2.092863) (xy 1.385999 2.252932) (xy 1.674923 2.720001) (xy 1.994558 3.141962) (xy 2.343638 3.517301) (xy 2.702425 3.830121) (xy 2.796896 3.907276) (xy 2.869966 3.973160)
(xy 2.913014 4.019593) (xy 2.920358 4.036818) (xy 2.890949 4.061096) (xy 2.824331 4.106288) (xy 2.731997 4.164778) (xy 2.673266 4.200547) (xy 2.185366 4.462492) (xy 1.685599 4.669552)
(xy 1.174901 4.821510) (xy 0.654210 4.918150) (xy 0.124462 4.959255) (xy -0.413406 4.944609) (xy -0.507003 4.936422) (xy -1.021420 4.859022) (xy -1.521966 4.728701) (xy -2.004900 4.548065)
(xy -2.466482 4.319721) (xy -2.902970 4.046276) (xy -3.310625 3.730336) (xy -3.685705 3.374508) (xy -4.024470 2.981398) (xy -4.323179 2.553614) (xy -4.573789 2.102556) (xy -4.783501 1.612640)
(xy -4.939426 1.111284) (xy -5.042121 0.602317) (xy -5.092138 0.089570) (xy -5.090033 -0.423127) (xy -5.036358 -0.931945) (xy -4.931668 -1.433053) (xy -4.776518 -1.922622) (xy -4.571461 -2.396821)
(xy -4.317052 -2.851821) (xy -4.013845 -3.283791) (xy -3.749271 -3.596340) (xy -3.382862 -3.955827) (xy -2.981063 -4.275414) (xy -2.549031 -4.553070) (xy -2.091924 -4.786766) (xy -1.614902 -4.974470)
(xy -1.123122 -5.114152) (xy -0.621743 -5.203781) (xy -0.115923 -5.241328) (xy 0.388056 -5.224861) )(layer F.SilkS) (width 0.010000)
)
(fp_poly (pts (xy 3.871625 -3.467031) (xy 3.936780 -3.388271) (xy 4.011992 -3.292079) (xy 4.090056 -3.188391) (xy 4.163767 -3.087143) (xy 4.225919 -2.998272) (xy 4.269307 -2.931714) (xy 4.286725 -2.897407)
(xy 4.286321 -2.895141) (xy 4.256882 -2.877822) (xy 4.194588 -2.844925) (xy 4.158744 -2.826659) (xy 3.950167 -2.701112) (xy 3.732023 -2.533119) (xy 3.515113 -2.332872) (xy 3.310237 -2.110568)
(xy 3.128198 -1.876398) (xy 3.084732 -1.813015) (xy 2.876739 -1.451909) (xy 2.720513 -1.075306) (xy 2.615119 -0.687924) (xy 2.559623 -0.294477) (xy 2.553090 0.100317) (xy 2.594586 0.491743)
(xy 2.683176 0.875084) (xy 2.817926 1.245625) (xy 2.997901 1.598649) (xy 3.222167 1.929440) (xy 3.489789 2.233281) (xy 3.799833 2.505457) (xy 3.963878 2.623760) (xy 4.057511 2.688520)
(xy 4.130173 2.741777) (xy 4.171370 2.775690) (xy 4.176889 2.782893) (xy 4.159358 2.818264) (xy 4.112213 2.884836) (xy 4.043629 2.972966) (xy 3.961777 3.073010) (xy 3.874832 3.175325)
(xy 3.790967 3.270269) (xy 3.718356 3.348198) (xy 3.665171 3.399470) (xy 3.641219 3.414889) (xy 3.607900 3.400100) (xy 3.542981 3.361487) (xy 3.467445 3.312042) (xy 3.101674 3.029765)
(xy 2.770771 2.705500) (xy 2.477816 2.343901) (xy 2.225892 1.949622) (xy 2.018078 1.527317) (xy 1.857455 1.081641) (xy 1.773671 0.753207) (xy 1.740101 0.543137) (xy 1.718323 0.295285)
(xy 1.708507 0.027101) (xy 1.710821 -0.243961) (xy 1.725435 -0.500449) (xy 1.752517 -0.724913) (xy 1.758994 -0.762000) (xy 1.856772 -1.162283) (xy 1.999581 -1.564167) (xy 2.180636 -1.952063)
(xy 2.393154 -2.310382) (xy 2.496438 -2.456741) (xy 2.663059 -2.660010) (xy 2.863628 -2.872909) (xy 3.082493 -3.080547) (xy 3.304004 -3.268031) (xy 3.501693 -3.413279) (xy 3.765487 -3.589728)
(xy 3.871625 -3.467031) )(layer F.SilkS) (width 0.010000)
)
(fp_poly (pts (xy 4.708743 -2.093743) (xy 4.715703 -2.086271) (xy 4.732652 -2.047799) (xy 4.761169 -1.970683) (xy 4.797375 -1.866741) (xy 4.837394 -1.747787) (xy 4.877349 -1.625636) (xy 4.913364 -1.512106)
(xy 4.941562 -1.419010) (xy 4.958066 -1.358165) (xy 4.960324 -1.340693) (xy 4.934857 -1.323406) (xy 4.877100 -1.284341) (xy 4.826000 -1.249815) (xy 4.607190 -1.069768) (xy 4.431450 -0.857898)
(xy 4.300458 -0.620760) (xy 4.215893 -0.364908) (xy 4.179433 -0.096895) (xy 4.192756 0.176724) (xy 4.257542 0.449397) (xy 4.340061 0.647631) (xy 4.405102 0.752448) (xy 4.500803 0.875917)
(xy 4.613103 1.002252) (xy 4.727941 1.115669) (xy 4.831254 1.200380) (xy 4.834353 1.202538) (xy 4.913261 1.257086) (xy 4.810446 1.552466) (xy 4.751037 1.717503) (xy 4.699070 1.850800)
(xy 4.657218 1.946047) (xy 4.628156 1.996937) (xy 4.619134 2.003778) (xy 4.593095 1.989948) (xy 4.533783 1.954143) (xy 4.473461 1.916380) (xy 4.335424 1.815149) (xy 4.183457 1.681269)
(xy 4.033324 1.530091) (xy 3.900793 1.376964) (xy 3.848574 1.307997) (xy 3.668412 1.009181) (xy 3.537673 0.689345) (xy 3.456452 0.354911) (xy 3.424846 0.012297) (xy 3.442951 -0.332076)
(xy 3.510863 -0.671788) (xy 3.628678 -1.000421) (xy 3.796493 -1.311553) (xy 3.809056 -1.330900) (xy 3.897570 -1.452007) (xy 4.004725 -1.577172) (xy 4.123758 -1.700762) (xy 4.247908 -1.817143)
(xy 4.370412 -1.920682) (xy 4.484510 -2.005745) (xy 4.583439 -2.066698) (xy 4.660437 -2.097909) (xy 4.708743 -2.093743) )(layer F.SilkS) (width 0.010000)
)
)

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"auto_track_width": false,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "magnetkarte.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -1,440 +0,0 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": true,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": true,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.12,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": true,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rule_severitieslegacy_courtyards_overlap": true,
"rule_severitieslegacy_no_courtyard_defined": false,
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.01,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"solder_paste_clearance": 0.0,
"solder_paste_margin_ratio": -0.0,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0,
0.25,
0.4,
0.6
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "magnetkarte.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.25,
"pin_symbol_size": 0.0,
"text_offset_ratio": 0.08
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "Pcbnew",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"b78e3980-fa91-4747-8504-806b364bf4af",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"auto_track_width": false,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "simkarte.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -1,436 +0,0 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.12,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"filename": "board_design_settings.json",
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rule_severitieslegacy_courtyards_overlap": true,
"rule_severitieslegacy_no_courtyard_defined": false,
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.024999999999999998,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0,
0.25,
0.4
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "simkarte.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.25,
"pin_symbol_size": 0.0,
"text_offset_ratio": 0.08
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "Pcbnew",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"d4e970ed-dbe6-470b-b0b4-94ae90c6a705",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +0,0 @@
(module SIM-Pads (layer F.Cu) (tedit 62963936)
(fp_text reference REF** (at 0 0.5) (layer F.SilkS) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value SIM-Pads (at 0 -0.5) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start 85.6 3) (end 85.6 50.98) (layer B.SilkS) (width 0.12))
(fp_line (start 82.6 53.98) (end 3 53.98) (layer B.SilkS) (width 0.12))
(fp_line (start 3 0) (end 82.55 0) (layer B.SilkS) (width 0.12))
(fp_line (start 0 50.98) (end 0 3) (layer B.SilkS) (width 0.12))
(fp_line (start 30.957107 29.187107) (end 28.957107 31.187107) (layer B.SilkS) (width 0.12))
(fp_line (start 3 0) (end 82.55 0) (layer F.SilkS) (width 0.12))
(fp_line (start 85.6 3) (end 85.6 50.98) (layer F.SilkS) (width 0.12))
(fp_line (start 82.6 53.98) (end 3 53.98) (layer F.SilkS) (width 0.12))
(fp_line (start 0 50.98) (end 0 3) (layer F.SilkS) (width 0.12))
(fp_line (start 30.957107 29.187107) (end 28.957107 31.187107) (layer F.SilkS) (width 0.12))
(fp_line (start 31.25 28.48) (end 31.25 17.48) (layer F.SilkS) (width 0.12))
(fp_line (start 7.25 16.48) (end 30.25 16.48) (layer F.SilkS) (width 0.12))
(fp_line (start 6.25 30.48) (end 6.25 17.48) (layer F.SilkS) (width 0.12))
(fp_line (start 7.25 31.48) (end 28.25 31.48) (layer F.SilkS) (width 0.12))
(fp_line (start 7.25 16.48) (end 30.25 16.48) (layer B.SilkS) (width 0.12))
(fp_line (start 6.25 30.48) (end 6.25 17.48) (layer B.SilkS) (width 0.12))
(fp_line (start 7.25 31.48) (end 28.25 31.48) (layer B.SilkS) (width 0.12))
(fp_line (start 31.25 28.48) (end 31.25 17.48) (layer B.SilkS) (width 0.12))
(fp_arc (start 82.6 3) (end 82.6 0) (angle 90) (layer B.SilkS) (width 0.12))
(fp_arc (start 82.6 50.98) (end 85.6 50.98) (angle 90) (layer B.SilkS) (width 0.12))
(fp_arc (start 3 50.98) (end 3 53.98) (angle 90) (layer B.SilkS) (width 0.12))
(fp_arc (start 28.25 30.48) (end 28.25 31.48) (angle -45) (layer B.SilkS) (width 0.12))
(fp_arc (start 30.25 28.48) (end 31.25 28.48) (angle 45) (layer B.SilkS) (width 0.12))
(fp_arc (start 30.25 17.48) (end 30.25 16.48) (angle 90) (layer B.SilkS) (width 0.12))
(fp_arc (start 3 3) (end 0 3) (angle 90) (layer B.SilkS) (width 0.12))
(fp_arc (start 28.25 30.48) (end 28.25 31.48) (angle -45) (layer F.SilkS) (width 0.12))
(fp_arc (start 30.25 28.48) (end 31.25 28.48) (angle 45) (layer F.SilkS) (width 0.12))
(fp_arc (start 30.25 17.48) (end 30.25 16.48) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 7.25 30.48) (end 7.25 31.48) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 7.25 17.48) (end 6.25 17.48) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 82.6 50.98) (end 85.6 50.98) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 82.6 3) (end 82.6 0) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 3 50.98) (end 3 53.98) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 3 3) (end 0 3) (angle 90) (layer F.SilkS) (width 0.12))
(fp_arc (start 7.25 17.48) (end 6.25 17.48) (angle 90) (layer B.SilkS) (width 0.12))
(fp_arc (start 7.25 30.48) (end 7.25 31.48) (angle 90) (layer B.SilkS) (width 0.12))
(pad 8 smd rect (at 18.87 27.7) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 7 smd rect (at 18.87 25.16) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 6 smd rect (at 18.87 22.62) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 5 smd rect (at 18.87 20.08) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at 11.25 27.7) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at 11.25 25.16) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at 11.25 22.62) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
(pad 1 smd rect (at 11.25 20.08) (size 2 1.7) (layers F.Cu F.Paste F.Mask))
)

View File

@ -1,50 +0,0 @@
(footprint "SO-8_falschrum" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 5EA5315B)
(descr "SO, 8 Pin (https://www.ti.com/lit/ml/msop001a/msop001a.pdf), generated with kicad-footprint-generator ipc_gullwing_generator.py")
(tags "SO SO")
(attr smd)
(fp_text reference "REF**" (at 0 -4.05) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp e6d2e267-164d-4afc-8b48-cd1aff90b7d4)
)
(fp_text value "SO-8_falschrum" (at 0 4.05) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp c06efada-401e-4dfe-b3d2-3a3e07849a0a)
)
(fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp f6b8865c-5ba6-45e6-a65d-a1b68be210e7)
)
(fp_line (start -2.76 -2.465) (end -4.45 -2.465) (layer "F.SilkS") (width 0.12) (tstamp 74239588-025d-4278-bb20-8aaa7c3084df))
(fp_line (start 2.76 3.21) (end 2.76 2.465) (layer "F.SilkS") (width 0.12) (tstamp 782bb1cd-d060-47ff-abe3-37addae7ab1b))
(fp_line (start 0 -3.21) (end -2.76 -3.21) (layer "F.SilkS") (width 0.12) (tstamp a37ee151-4fcc-4d66-943d-e5b1c2e17868))
(fp_line (start -2.76 3.21) (end -2.76 2.465) (layer "F.SilkS") (width 0.12) (tstamp af41f2a4-51e3-4dbb-b929-81c444ac7fff))
(fp_line (start 0 3.21) (end 2.76 3.21) (layer "F.SilkS") (width 0.12) (tstamp c79336f7-374b-471c-a2b2-c23ba36a59b5))
(fp_line (start 0 -3.21) (end 2.76 -3.21) (layer "F.SilkS") (width 0.12) (tstamp cf87a8a5-e65f-4d3a-8572-2d19d388ce69))
(fp_line (start 0 3.21) (end -2.76 3.21) (layer "F.SilkS") (width 0.12) (tstamp d48ee01a-e5c2-4b22-aaa6-a1cb107fbac3))
(fp_line (start -2.76 -3.21) (end -2.76 -2.465) (layer "F.SilkS") (width 0.12) (tstamp d861ecda-fd97-4619-9c2d-6c4f7c60cca0))
(fp_line (start 2.76 -3.21) (end 2.76 -2.465) (layer "F.SilkS") (width 0.12) (tstamp dc7ef0e4-bd3f-4bae-b16a-6091a2fbe1a5))
(fp_line (start 4.7 -3.35) (end -4.7 -3.35) (layer "F.CrtYd") (width 0.05) (tstamp 5f316919-0561-48cc-af6d-627207b632ec))
(fp_line (start -4.7 3.35) (end 4.7 3.35) (layer "F.CrtYd") (width 0.05) (tstamp 6020986c-655c-453e-a057-f214cc9d30ae))
(fp_line (start -4.7 -3.35) (end -4.7 3.35) (layer "F.CrtYd") (width 0.05) (tstamp 6794d844-873d-41de-8a23-157904a72b2b))
(fp_line (start 4.7 3.35) (end 4.7 -3.35) (layer "F.CrtYd") (width 0.05) (tstamp d7967734-f1e1-4546-a5ab-b7258f5f3f2a))
(fp_line (start -2.65 -2.1) (end -1.65 -3.1) (layer "F.Fab") (width 0.1) (tstamp 48790e43-f2fc-44b0-8322-5388cb8e0681))
(fp_line (start 2.65 3.1) (end -2.65 3.1) (layer "F.Fab") (width 0.1) (tstamp 7c60e013-b5db-4162-a3bc-3c3e55a92637))
(fp_line (start -1.65 -3.1) (end 2.65 -3.1) (layer "F.Fab") (width 0.1) (tstamp 89f17c59-8ae8-458d-9e98-a1d8017d430e))
(fp_line (start 2.65 -3.1) (end 2.65 3.1) (layer "F.Fab") (width 0.1) (tstamp d0cb6892-437f-41c0-a652-f027fe7a96eb))
(fp_line (start -2.65 3.1) (end -2.65 -2.1) (layer "F.Fab") (width 0.1) (tstamp ea99ab82-687a-410b-9f25-f99eecf53974))
(pad "1" smd roundrect (at 3.5 -1.905) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp 3ef16b5b-8b97-445d-864d-105eb1aa6c46))
(pad "2" smd roundrect (at 3.5 -0.635) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp e4871953-02b6-4389-a5ea-7cc4f8748acd))
(pad "3" smd roundrect (at 3.5 0.635) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp 9a059f78-4982-44b4-9c5e-072b9705c642))
(pad "4" smd roundrect (at 3.5 1.905) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp c02f2849-6a0e-4f4d-bf38-717a4b6fd135))
(pad "5" smd roundrect (at -3.5 1.905) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp b4cd1ee4-67da-4549-8e85-46e00c6d8f0b))
(pad "6" smd roundrect (at -3.5 0.635) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp 5515138e-0099-4ddf-8a64-f565476c169d))
(pad "7" smd roundrect (at -3.5 -0.635) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp 697f93e2-a0be-4cf3-b7ec-1bdeabd8a6ad))
(pad "8" smd roundrect (at -3.5 -1.905) (size 1.9 0.6) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) (tstamp 8018f35d-7a92-4135-8a83-0670bf6a5459))
(model "${KICAD6_3DMODEL_DIR}/Package_SO.3dshapes/SO-8_5.3x6.2mm_P1.27mm.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@ -1,87 +0,0 @@
(module LOGO (layer F.Cu)
(at 0 0)
(fp_text reference "G***" (at 0 0) (layer F.SilkS) hide
(effects (font (thickness 0.3)))
)
(fp_text value "LOGO" (at 0.75 0) (layer F.SilkS) hide
(effects (font (thickness 0.3)))
)
(fp_poly (pts (xy 3.066152 -6.121191) (xy 3.428893 -6.120766) (xy 3.752319 -6.119859) (xy 4.038875 -6.118399) (xy 4.291009 -6.116313) (xy 4.511168 -6.113530) (xy 4.701799 -6.109980) (xy 4.865348 -6.105590)
(xy 5.004263 -6.100290) (xy 5.120991 -6.094008) (xy 5.217978 -6.086672) (xy 5.297671 -6.078211) (xy 5.362518 -6.068554) (xy 5.414965 -6.057629) (xy 5.457458 -6.045365) (xy 5.492446 -6.031691)
(xy 5.522375 -6.016535) (xy 5.549692 -5.999825) (xy 5.576844 -5.981491) (xy 5.606277 -5.961461) (xy 5.621560 -5.951464) (xy 5.802237 -5.806446) (xy 5.943182 -5.626144) (xy 6.008480 -5.504621)
(xy 6.081889 -5.348111) (xy 6.081889 5.065889) (xy 6.008480 5.222399) (xy 5.886481 5.426964) (xy 5.729099 5.591065) (xy 5.622219 5.668819) (xy 5.590776 5.689726) (xy 5.562762 5.708887)
(xy 5.535715 5.726375) (xy 5.507170 5.742266) (xy 5.474661 5.756634) (xy 5.435724 5.769553) (xy 5.387896 5.781099) (xy 5.328710 5.791346) (xy 5.255703 5.800368) (xy 5.166409 5.808240)
(xy 5.058365 5.815037) (xy 4.929106 5.820832) (xy 4.776167 5.825702) (xy 4.597084 5.829720) (xy 4.389392 5.832960) (xy 4.150626 5.835498) (xy 3.878322 5.837408) (xy 3.570016 5.838765)
(xy 3.223242 5.839643) (xy 2.835536 5.840116) (xy 2.404434 5.840260) (xy 1.927471 5.840149) (xy 1.402182 5.839857) (xy 0.826103 5.839459) (xy 0.196769 5.839030) (xy 0.001126 5.838908)
(xy -0.535567 5.838462) (xy -1.058045 5.837786) (xy -1.563427 5.836894) (xy -2.048833 5.835799) (xy -2.511382 5.834517) (xy -2.948193 5.833062) (xy -3.356385 5.831447) (xy -3.733077 5.829687)
(xy -4.075389 5.827796) (xy -4.380439 5.825788) (xy -4.645347 5.823678) (xy -4.867232 5.821480) (xy -5.043214 5.819207) (xy -5.170410 5.816875) (xy -5.245941 5.814497) (xy -5.266077 5.812913)
(xy -5.491258 5.740750) (xy -5.690423 5.620986) (xy -5.856268 5.458485) (xy -5.911083 5.383451) (xy -5.933608 5.350592) (xy -5.954232 5.321477) (xy -5.973038 5.293611) (xy -5.990111 5.264501)
(xy -6.005534 5.231654) (xy -6.019391 5.192575) (xy -6.031764 5.144771) (xy -6.042737 5.085749) (xy -6.052394 5.013016) (xy -6.060819 4.924076) (xy -6.068093 4.816438) (xy -6.074302 4.687607)
(xy -6.079529 4.535089) (xy -6.083857 4.356392) (xy -6.087369 4.149022) (xy -6.090149 3.910484) (xy -6.092281 3.638287) (xy -6.093847 3.329935) (xy -6.094932 2.982935) (xy -6.095619 2.594794)
(xy -6.095991 2.163018) (xy -6.096131 1.685114) (xy -6.096124 1.158588) (xy -6.096053 0.580947) (xy -6.096001 -0.050304) (xy -6.096000 -0.141111) (xy -6.096043 -0.779900) (xy -6.096116 -1.364739)
(xy -6.096137 -1.898120) (xy -6.096052 -2.256360) (xy -5.814193 -2.256360) (xy -5.814125 -1.757197) (xy -5.813966 -1.208271) (xy -5.813819 -0.607124) (xy -5.813777 -0.141111) (xy -5.813854 0.499116)
(xy -5.814015 1.085355) (xy -5.814159 1.620064) (xy -5.814184 2.105699) (xy -5.813989 2.544718) (xy -5.813470 2.939576) (xy -5.812526 3.292731) (xy -5.811055 3.606639) (xy -5.808956 3.883758)
(xy -5.806125 4.126544) (xy -5.802462 4.337453) (xy -5.797865 4.518944) (xy -5.792230 4.673472) (xy -5.785457 4.803495) (xy -5.777444 4.911469) (xy -5.768088 4.999850) (xy -5.757287 5.071097)
(xy -5.744940 5.127665) (xy -5.730944 5.172012) (xy -5.715199 5.206594) (xy -5.697600 5.233868) (xy -5.678048 5.256290) (xy -5.656439 5.276319) (xy -5.632672 5.296410) (xy -5.606645 5.319020)
(xy -5.586384 5.338304) (xy -5.561771 5.364561) (xy -5.541081 5.388626) (xy -5.521883 5.410597) (xy -5.501747 5.430569) (xy -5.478242 5.448637) (xy -5.448937 5.464897) (xy -5.411403 5.479446)
(xy -5.363209 5.492377) (xy -5.301924 5.503789) (xy -5.225118 5.513775) (xy -5.130361 5.522432) (xy -5.015222 5.529855) (xy -4.877271 5.536141) (xy -4.714078 5.541384) (xy -4.523212 5.545681)
(xy -4.302242 5.549127) (xy -4.048739 5.551819) (xy -3.760271 5.553851) (xy -3.434409 5.555319) (xy -3.068722 5.556320) (xy -2.660779 5.556948) (xy -2.208151 5.557300) (xy -1.708406 5.557471)
(xy -1.159115 5.557557) (xy -0.557847 5.557654) (xy -0.012178 5.557812) (xy 0.631245 5.558012) (xy 1.220601 5.558088) (xy 1.758268 5.558023) (xy 2.246624 5.557799) (xy 2.688045 5.557398)
(xy 3.084909 5.556803) (xy 3.439595 5.555995) (xy 3.754479 5.554958) (xy 4.031940 5.553673) (xy 4.274354 5.552123) (xy 4.484100 5.550290) (xy 4.663554 5.548156) (xy 4.815095 5.545704)
(xy 4.941100 5.542915) (xy 5.043947 5.539772) (xy 5.126012 5.536258) (xy 5.189674 5.532355) (xy 5.237311 5.528044) (xy 5.271300 5.523308) (xy 5.293600 5.518255) (xy 5.468036 5.437528)
(xy 5.619157 5.309399) (xy 5.722084 5.169645) (xy 5.799667 5.037667) (xy 5.799667 -5.319888) (xy 5.722084 -5.451866) (xy 5.654063 -5.548879) (xy 5.572372 -5.640625) (xy 5.538639 -5.671399)
(xy 5.514868 -5.692021) (xy 5.493943 -5.710917) (xy 5.473421 -5.728161) (xy 5.450859 -5.743829) (xy 5.423815 -5.757996) (xy 5.389844 -5.770737) (xy 5.346504 -5.782127) (xy 5.291352 -5.792243)
(xy 5.221946 -5.801158) (xy 5.135842 -5.808948) (xy 5.030596 -5.815689) (xy 4.903768 -5.821456) (xy 4.752912 -5.826324) (xy 4.575587 -5.830368) (xy 4.369349 -5.833663) (xy 4.131755 -5.836285)
(xy 3.860363 -5.838309) (xy 3.552729 -5.839811) (xy 3.206411 -5.840864) (xy 2.818965 -5.841546) (xy 2.387948 -5.841930) (xy 1.910918 -5.842093) (xy 1.385432 -5.842109) (xy 0.809046 -5.842054)
(xy 0.179318 -5.842003) (xy 0.000000 -5.842000) (xy -0.647201 -5.842068) (xy -1.240388 -5.842208) (xy -1.781990 -5.842324) (xy -2.274439 -5.842319) (xy -2.720163 -5.842096) (xy -3.121593 -5.841560)
(xy -3.481159 -5.840613) (xy -3.801291 -5.839160) (xy -4.084419 -5.837103) (xy -4.332972 -5.834346) (xy -4.549381 -5.830793) (xy -4.736077 -5.826347) (xy -4.895488 -5.820912) (xy -5.030045 -5.814390)
(xy -5.142178 -5.806687) (xy -5.234316 -5.797705) (xy -5.308891 -5.787347) (xy -5.368331 -5.775518) (xy -5.415068 -5.762121) (xy -5.451530 -5.747058) (xy -5.480148 -5.730235) (xy -5.503352 -5.711554)
(xy -5.523572 -5.690918) (xy -5.543238 -5.668232) (xy -5.564779 -5.643398) (xy -5.586748 -5.620162) (xy -5.614426 -5.594245) (xy -5.639774 -5.572614) (xy -5.662894 -5.552810) (xy -5.683888 -5.532378)
(xy -5.702857 -5.508859) (xy -5.719902 -5.479799) (xy -5.735127 -5.442739) (xy -5.748633 -5.395223) (xy -5.760521 -5.334795) (xy -5.770893 -5.258997) (xy -5.779852 -5.165373) (xy -5.787498 -5.051467)
(xy -5.793934 -4.914820) (xy -5.799262 -4.752978) (xy -5.803583 -4.563482) (xy -5.806999 -4.343877) (xy -5.809612 -4.091705) (xy -5.811524 -3.804509) (xy -5.812836 -3.479834) (xy -5.813650 -3.115222)
(xy -5.814069 -2.708216) (xy -5.814193 -2.256360) (xy -6.096052 -2.256360) (xy -6.096021 -2.382538) (xy -6.095685 -2.820485) (xy -6.095047 -3.214456) (xy -6.094021 -3.566944) (xy -6.092526 -3.880442)
(xy -6.090477 -4.157444) (xy -6.087792 -4.400443) (xy -6.084386 -4.611933) (xy -6.080176 -4.794408) (xy -6.075080 -4.950361) (xy -6.069013 -5.082285) (xy -6.061892 -5.192675) (xy -6.053634 -5.284023)
(xy -6.044156 -5.358823) (xy -6.033373 -5.419569) (xy -6.021202 -5.468754) (xy -6.007561 -5.508872) (xy -5.992366 -5.542416) (xy -5.975533 -5.571880) (xy -5.956978 -5.599757) (xy -5.936619 -5.628541)
(xy -5.914372 -5.660725) (xy -5.911207 -5.665485) (xy -5.776472 -5.825354) (xy -5.604536 -5.962390) (xy -5.418666 -6.059831) (xy -5.400964 -6.065986) (xy -5.378659 -6.071628) (xy -5.349305 -6.076783)
(xy -5.310456 -6.081478) (xy -5.259665 -6.085739) (xy -5.194485 -6.089592) (xy -5.112469 -6.093065) (xy -5.011172 -6.096183) (xy -4.888146 -6.098973) (xy -4.740946 -6.101462) (xy -4.567124 -6.103675)
(xy -4.364234 -6.105640) (xy -4.129829 -6.107382) (xy -3.861462 -6.108929) (xy -3.556688 -6.110306) (xy -3.213060 -6.111541) (xy -2.828131 -6.112659) (xy -2.399454 -6.113686) (xy -1.924583 -6.114651)
(xy -1.401071 -6.115578) (xy -0.826472 -6.116494) (xy -0.198339 -6.117426) (xy -0.072960 -6.117607) (xy 0.577063 -6.118577) (xy 1.173088 -6.119493) (xy 1.717563 -6.120284) (xy 2.212933 -6.120878)
(xy 2.661648 -6.121204) (xy 3.066152 -6.121191) )(layer F.SilkS) (width 0.010000)
)
(fp_poly (pts (xy 0.388056 -5.224861) (xy 0.926284 -5.151909) (xy 1.442169 -5.030009) (xy 1.931989 -4.860185) (xy 2.269161 -4.707442) (xy 2.385467 -4.646290) (xy 2.515386 -4.573424) (xy 2.649910 -4.494458)
(xy 2.780026 -4.415003) (xy 2.896725 -4.340672) (xy 2.990997 -4.277077) (xy 3.053830 -4.229830) (xy 3.076223 -4.204760) (xy 3.054679 -4.181883) (xy 2.996572 -4.134523) (xy 2.911693 -4.070406)
(xy 2.843389 -4.020972) (xy 2.588378 -3.819391) (xy 2.327603 -3.576761) (xy 2.072524 -3.305783) (xy 1.834598 -3.019161) (xy 1.625286 -2.729598) (xy 1.505020 -2.537285) (xy 1.380316 -2.322904)
(xy 1.142496 -2.442260) (xy 0.832858 -2.574342) (xy 0.519563 -2.658740) (xy 0.184960 -2.699984) (xy 0.127000 -2.702934) (xy -0.253898 -2.695011) (xy -0.612890 -2.637152) (xy -0.957530 -2.527568)
(xy -1.290385 -2.367282) (xy -1.454436 -2.258755) (xy -1.632699 -2.113583) (xy -1.812300 -1.944640) (xy -1.980365 -1.764801) (xy -2.124018 -1.586940) (xy -2.226171 -1.431496) (xy -2.390141 -1.085856)
(xy -2.501199 -0.729720) (xy -2.559954 -0.368118) (xy -2.567011 -0.006082) (xy -2.522977 0.351358) (xy -2.428460 0.699171) (xy -2.284065 1.032326) (xy -2.090401 1.345792) (xy -1.857529 1.624740)
(xy -1.581126 1.879192) (xy -1.286102 2.083481) (xy -0.963395 2.243070) (xy -0.657253 2.348609) (xy -0.558411 2.374336) (xy -0.462583 2.392205) (xy -0.355847 2.403564) (xy -0.224279 2.409764)
(xy -0.053956 2.412154) (xy 0.000000 2.412321) (xy 0.240604 2.407938) (xy 0.442234 2.391658) (xy 0.621727 2.360022) (xy 0.795921 2.309569) (xy 0.981650 2.236841) (xy 1.089842 2.188395)
(xy 1.296608 2.092863) (xy 1.385999 2.252932) (xy 1.674923 2.720001) (xy 1.994558 3.141962) (xy 2.343638 3.517301) (xy 2.702425 3.830121) (xy 2.796896 3.907276) (xy 2.869966 3.973160)
(xy 2.913014 4.019593) (xy 2.920358 4.036818) (xy 2.890949 4.061096) (xy 2.824331 4.106288) (xy 2.731997 4.164778) (xy 2.673266 4.200547) (xy 2.185366 4.462492) (xy 1.685599 4.669552)
(xy 1.174901 4.821510) (xy 0.654210 4.918150) (xy 0.124462 4.959255) (xy -0.413406 4.944609) (xy -0.507003 4.936422) (xy -1.021420 4.859022) (xy -1.521966 4.728701) (xy -2.004900 4.548065)
(xy -2.466482 4.319721) (xy -2.902970 4.046276) (xy -3.310625 3.730336) (xy -3.685705 3.374508) (xy -4.024470 2.981398) (xy -4.323179 2.553614) (xy -4.573789 2.102556) (xy -4.783501 1.612640)
(xy -4.939426 1.111284) (xy -5.042121 0.602317) (xy -5.092138 0.089570) (xy -5.090033 -0.423127) (xy -5.036358 -0.931945) (xy -4.931668 -1.433053) (xy -4.776518 -1.922622) (xy -4.571461 -2.396821)
(xy -4.317052 -2.851821) (xy -4.013845 -3.283791) (xy -3.749271 -3.596340) (xy -3.382862 -3.955827) (xy -2.981063 -4.275414) (xy -2.549031 -4.553070) (xy -2.091924 -4.786766) (xy -1.614902 -4.974470)
(xy -1.123122 -5.114152) (xy -0.621743 -5.203781) (xy -0.115923 -5.241328) (xy 0.388056 -5.224861) )(layer F.SilkS) (width 0.010000)
)
(fp_poly (pts (xy 3.871625 -3.467031) (xy 3.936780 -3.388271) (xy 4.011992 -3.292079) (xy 4.090056 -3.188391) (xy 4.163767 -3.087143) (xy 4.225919 -2.998272) (xy 4.269307 -2.931714) (xy 4.286725 -2.897407)
(xy 4.286321 -2.895141) (xy 4.256882 -2.877822) (xy 4.194588 -2.844925) (xy 4.158744 -2.826659) (xy 3.950167 -2.701112) (xy 3.732023 -2.533119) (xy 3.515113 -2.332872) (xy 3.310237 -2.110568)
(xy 3.128198 -1.876398) (xy 3.084732 -1.813015) (xy 2.876739 -1.451909) (xy 2.720513 -1.075306) (xy 2.615119 -0.687924) (xy 2.559623 -0.294477) (xy 2.553090 0.100317) (xy 2.594586 0.491743)
(xy 2.683176 0.875084) (xy 2.817926 1.245625) (xy 2.997901 1.598649) (xy 3.222167 1.929440) (xy 3.489789 2.233281) (xy 3.799833 2.505457) (xy 3.963878 2.623760) (xy 4.057511 2.688520)
(xy 4.130173 2.741777) (xy 4.171370 2.775690) (xy 4.176889 2.782893) (xy 4.159358 2.818264) (xy 4.112213 2.884836) (xy 4.043629 2.972966) (xy 3.961777 3.073010) (xy 3.874832 3.175325)
(xy 3.790967 3.270269) (xy 3.718356 3.348198) (xy 3.665171 3.399470) (xy 3.641219 3.414889) (xy 3.607900 3.400100) (xy 3.542981 3.361487) (xy 3.467445 3.312042) (xy 3.101674 3.029765)
(xy 2.770771 2.705500) (xy 2.477816 2.343901) (xy 2.225892 1.949622) (xy 2.018078 1.527317) (xy 1.857455 1.081641) (xy 1.773671 0.753207) (xy 1.740101 0.543137) (xy 1.718323 0.295285)
(xy 1.708507 0.027101) (xy 1.710821 -0.243961) (xy 1.725435 -0.500449) (xy 1.752517 -0.724913) (xy 1.758994 -0.762000) (xy 1.856772 -1.162283) (xy 1.999581 -1.564167) (xy 2.180636 -1.952063)
(xy 2.393154 -2.310382) (xy 2.496438 -2.456741) (xy 2.663059 -2.660010) (xy 2.863628 -2.872909) (xy 3.082493 -3.080547) (xy 3.304004 -3.268031) (xy 3.501693 -3.413279) (xy 3.765487 -3.589728)
(xy 3.871625 -3.467031) )(layer F.SilkS) (width 0.010000)
)
(fp_poly (pts (xy 4.708743 -2.093743) (xy 4.715703 -2.086271) (xy 4.732652 -2.047799) (xy 4.761169 -1.970683) (xy 4.797375 -1.866741) (xy 4.837394 -1.747787) (xy 4.877349 -1.625636) (xy 4.913364 -1.512106)
(xy 4.941562 -1.419010) (xy 4.958066 -1.358165) (xy 4.960324 -1.340693) (xy 4.934857 -1.323406) (xy 4.877100 -1.284341) (xy 4.826000 -1.249815) (xy 4.607190 -1.069768) (xy 4.431450 -0.857898)
(xy 4.300458 -0.620760) (xy 4.215893 -0.364908) (xy 4.179433 -0.096895) (xy 4.192756 0.176724) (xy 4.257542 0.449397) (xy 4.340061 0.647631) (xy 4.405102 0.752448) (xy 4.500803 0.875917)
(xy 4.613103 1.002252) (xy 4.727941 1.115669) (xy 4.831254 1.200380) (xy 4.834353 1.202538) (xy 4.913261 1.257086) (xy 4.810446 1.552466) (xy 4.751037 1.717503) (xy 4.699070 1.850800)
(xy 4.657218 1.946047) (xy 4.628156 1.996937) (xy 4.619134 2.003778) (xy 4.593095 1.989948) (xy 4.533783 1.954143) (xy 4.473461 1.916380) (xy 4.335424 1.815149) (xy 4.183457 1.681269)
(xy 4.033324 1.530091) (xy 3.900793 1.376964) (xy 3.848574 1.307997) (xy 3.668412 1.009181) (xy 3.537673 0.689345) (xy 3.456452 0.354911) (xy 3.424846 0.012297) (xy 3.442951 -0.332076)
(xy 3.510863 -0.671788) (xy 3.628678 -1.000421) (xy 3.796493 -1.311553) (xy 3.809056 -1.330900) (xy 3.897570 -1.452007) (xy 4.004725 -1.577172) (xy 4.123758 -1.700762) (xy 4.247908 -1.817143)
(xy 4.370412 -1.920682) (xy 4.484510 -2.005745) (xy 4.583439 -2.066698) (xy 4.660437 -2.097909) (xy 4.708743 -2.093743) )(layer F.SilkS) (width 0.010000)
)
)

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
(module tp_for_sim (layer F.Cu) (tedit 62960959)
(fp_text reference REF** (at 0 0.5) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value tp_for_sim (at 0 -0.5) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 smd roundrect (at 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
)

View File

@ -1,8 +1,8 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = \
liblogging \
liboptions \
libdebug \
libmobile \
libdisplay \
libsample \
@ -14,6 +14,7 @@ SUBDIRS = \
libsquelch \
libhagelbarger \
libdtmf \
libtimer \
libsamplerate \
libscrambler \
libemphasis \
@ -27,6 +28,8 @@ SUBDIRS = \
libserial \
libv27 \
libmtp \
libosmocc \
libg711 \
libaaimage
if HAVE_ALSA
@ -45,22 +48,21 @@ SUBDIRS += \
cnetz \
nmt \
amps \
tacs \
jtacs \
r2000 \
imts \
mpt1327 \
jolly \
eurosignal \
pocsag \
golay \
fuenf \
tv \
radio \
zeitansage \
sim \
magnetic \
fuvst \
dcf77 \
mate
fuvst
if HAVE_ALSA
if HAVE_FUSE

View File

@ -1,51 +1,51 @@
AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes)
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
bin_PROGRAMS = \
amps tacs jtacs
amps
noinst_LIBRARIES = libamps.a libusatone.a
libamps_a_SOURCES = \
main_common.c \
amps_tacs_main.c \
amps.c \
transaction.c \
frame.c \
dsp.c \
sysinfo.c \
esn.c
sysinfo.c
libusatone_a_SOURCES = \
usa_tones.c \
usa_noanswer.c \
usa_outoforder.c \
usa_invalidnumber.c \
usa_congestion.c
tones.c \
noanswer.c \
outoforder.c \
invalidnumber.c \
congestion.c
amps_SOURCES = \
amps_stations.c \
amps_image.c \
amps_main.c
stations.c \
image.c \
main.c
amps_LDADD = \
$(COMMON_LA) \
libamps.a \
libusatone.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/libcompandor/libcompandor.a \
$(top_builddir)/src/libgoertzel/libgoertzel.a \
$(top_builddir)/src/libjitter/libjitter.a \
$(top_builddir)/src/libtimer/libtimer.a \
$(top_builddir)/src/libsamplerate/libsamplerate.a \
$(top_builddir)/src/libemphasis/libemphasis.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 \
$(top_builddir)/src/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
-lm
if HAVE_ALSA
@ -63,88 +63,3 @@ amps_LDADD += \
$(SOAPY_LIBS)
endif
tacs_SOURCES = \
tacs_tones.c \
tacs_outoforder.c \
tacs_stations.c \
tacs_image.c \
tacs_main.c
tacs_LDADD = \
$(COMMON_LA) \
libamps.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
$(top_builddir)/src/libcompandor/libcompandor.a \
$(top_builddir)/src/libgoertzel/libgoertzel.a \
$(top_builddir)/src/libjitter/libjitter.a \
$(top_builddir)/src/libsamplerate/libsamplerate.a \
$(top_builddir)/src/libemphasis/libemphasis.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/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
-lm
if HAVE_ALSA
tacs_LDADD += \
$(top_builddir)/src/libsound/libsound.a \
$(ALSA_LIBS)
endif
if HAVE_SDR
tacs_LDADD += \
$(top_builddir)/src/libsdr/libsdr.a \
$(top_builddir)/src/libam/libam.a \
$(top_builddir)/src/libfft/libfft.a \
$(UHD_LIBS) \
$(SOAPY_LIBS)
endif
jtacs_SOURCES = \
jtacs_tones.c \
jtacs_stations.c \
jtacs_image.c \
jtacs_main.c
jtacs_LDADD = \
$(COMMON_LA) \
libamps.a \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libmobile/libmobile.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
$(top_builddir)/src/libcompandor/libcompandor.a \
$(top_builddir)/src/libgoertzel/libgoertzel.a \
$(top_builddir)/src/libjitter/libjitter.a \
$(top_builddir)/src/libsamplerate/libsamplerate.a \
$(top_builddir)/src/libemphasis/libemphasis.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/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
-lm
if HAVE_ALSA
jtacs_LDADD += \
$(top_builddir)/src/libsound/libsound.a \
$(ALSA_LIBS)
endif
if HAVE_SDR
jtacs_LDADD += \
$(top_builddir)/src/libsdr/libsdr.a \
$(top_builddir)/src/libam/libam.a \
$(top_builddir)/src/libfft/libfft.a \
$(UHD_LIBS) \
$(SOAPY_LIBS)
endif

View File

@ -43,30 +43,26 @@
#include <string.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
#include "../libmobile/console.h"
#include <osmocom/cc/message.h>
#include "../libosmocc/message.h"
#include "amps.h"
#include "dsp.h"
#include "frame.h"
#include "stations.h"
#include "esn.h"
#include "main.h"
/* Uncomment this to test SAT via loopback */
//#define DEBUG_VC
#define SAT_TO1 5,0 /* 5 sec to detect after setup */
#define SAT_TO2 5,0 /* 5 sec lost until abort (specs say 5) */
#define PAGE_TRIES 2 /* how many times to page the phone */
#define PAGE_TO1 8,0 /* max time to wait for paging reply */
#define PAGE_TO2 4,0 /* max time to wait for last paging reply */
#define ALERT_TRIES 3 /* how many times to alert the phone */
#define ALERT_TO 0,600000 /* max time to wait for alert confirm */
#define ANSWER_TO 60,0 /* max time to wait for answer */
#define RELEASE_TIMER 5,0 /* max time to send release messages */
#define SAT_TO1 5.0 /* 5 sec to detect after setup */
#define SAT_TO2 5.0 /* 5 sec lost until abort (specs say 5) */
#define PAGE_TRIES 2 /* how many times to page the phone */
#define PAGE_TO1 8.0 /* max time to wait for paging reply */
#define PAGE_TO2 4.0 /* max time to wait for last paging reply */
#define ALERT_TO 60.0 /* max time to wait for answer */
#define RELEASE_TIMER 5.0 /* max time to send release messages */
/* Convert channel number to frequency number of base station.
Set 'uplink' to 1 to get frequency of mobile station. */
@ -75,7 +71,6 @@ double amps_channel2freq(int channel, int uplink)
double freq;
if (!tacs) {
/* AMPS */
if (uplink == 2)
return -45.000 * 1e6;
@ -91,7 +86,6 @@ double amps_channel2freq(int channel, int uplink)
if (uplink)
freq -= 45.000;
} else if (!jtacs) {
/* TACS */
if (uplink == 2)
return -45.000 * 1e6;
@ -104,23 +98,14 @@ double amps_channel2freq(int channel, int uplink)
if (uplink)
freq -= 45.000;
} else {
/* JTACS */
/* see "ARIB_STD-T64-C.S0057-0v1.0.pdf" */
if (uplink == 2)
return 55.000 * 1e6;
return -55.000 * 1e6;
/* 799 channels */
if (channel >= 1 && channel <= 799)
freq = 860.0125 + (channel - 1) * 0.0125;
else if (channel >= 801 && channel <= 1039)
freq = 843.0125 + (channel - 801) * 0.0125;
else if (channel >= 1041 && channel <= 1199)
freq = 832.0125 + (channel - 1041) * 0.0125;
else if (channel >= 1201 && channel <= 1600)
freq = 838.0125 + (channel - 1201) * 0.0125;
else
if (channel < 1 || channel > 799)
return 0;
freq = 860.0125 + (channel - 1) * 0.025;
if (uplink)
freq += 55.000;
@ -132,19 +117,13 @@ double amps_channel2freq(int channel, int uplink)
enum amps_chan_type amps_channel2type(int channel)
{
if (!tacs) {
/* AMPS */
if (channel >= 313 && channel <= 354)
return CHAN_TYPE_CC;
} else if (!jtacs) {
/* TACS */
} else {
if (channel >= 23 && channel <= 43)
return CHAN_TYPE_CC;
if (channel >= 323 && channel <= 343)
return CHAN_TYPE_CC;
} else {
/* JTACS */
if (channel >= 418 && channel <= 456)
return CHAN_TYPE_CC;
}
return CHAN_TYPE_VC;
@ -153,7 +132,6 @@ enum amps_chan_type amps_channel2type(int channel)
const char *amps_channel2band(int channel)
{
if (!tacs) {
/* AMPS */
if (channel >= 991 && channel <= 1023)
return "A''";
if (channel >= 1 && channel <= 333)
@ -164,15 +142,11 @@ const char *amps_channel2band(int channel)
return "A'";
if (channel >= 717 && channel <= 799)
return "B'";
} else if (!jtacs) {
/* TACS */
} else {
if (channel >= 1 && channel <= 300)
return "A";
if (channel >= 301 && channel <= 600)
return "B";
} else {
/* JTACS */
return "A";
}
return "<invalid>";
@ -226,12 +200,12 @@ void amps_number2min(const char *number, uint32_t *min1, uint16_t *min2)
}
if (!tacs) {
/* MIN1 (amps) */
/* MIN1 */
*min1 = ((uint32_t)(digit2binary(number[0]) * 100 + digit2binary(number[1]) * 10 + digit2binary(number[2]) - 111)) << 14;
*min1 |= digit2binary(number[3]) << 10;
*min1 |= digit2binary(number[4]) * 100 + digit2binary(number[5]) * 10 + digit2binary(number[6]) - 111;
} else {
/* MIN1 (tacs/jtacs) */
/* MIN1 */
*min1 = digit2binary(number[0]) << 20;
*min1 |= (digit2binary(number[1]) * 100 + digit2binary(number[2]) * 10 + digit2binary(number[3]) - 111) << 10;
*min1 |= digit2binary(number[4]) * 100 + digit2binary(number[5]) * 10 + digit2binary(number[6]) - 111;
@ -242,8 +216,6 @@ void amps_number2min(const char *number, uint32_t *min1, uint16_t *min2)
*/
/* TACS: convert MIN1 and MIN2 to AREA-XXXXXXX
*/
/* JTACS: convert MIN1 and MIN2 to NET-XXXXXXX (NET = mobile network code, always 440)
*/
const char *amps_min22number(uint16_t min2)
{
static char number[4];
@ -266,7 +238,7 @@ const char *amps_min12number(uint32_t min1)
static char number[8];
if (!tacs) {
/* MIN1 (amps) */
/* MIN1 */
if ((min1 >> 14) > 999)
strcpy(number, "???");
else {
@ -286,7 +258,7 @@ const char *amps_min12number(uint32_t min1)
number[6] = binary2digit(((min1 & 0x3ff) % 10) + 1);
}
} else {
/* MIN1 (tacs/jtacs) */
/* MIN1 */
if ((min1 >> 20) < 1 || (min1 >> 20) > 10)
number[0] = '?';
else
@ -342,7 +314,7 @@ const char *amps_scm(uint8_t scm)
return text;
}
static const char *amps_mpci(uint8_t mpci)
const char *amps_mpci(uint8_t mpci)
{
switch (mpci) {
case 0:
@ -359,7 +331,7 @@ static const char *amps_mpci(uint8_t mpci)
}
static const char *amps_state_name(enum amps_state state)
const char *amps_state_name(enum amps_state state)
{
static char invalid[16];
@ -396,7 +368,7 @@ static void amps_new_state(amps_t *amps, enum amps_state new_state)
{
if (amps->state == new_state)
return;
LOGP_CHAN(DAMPS, LOGL_DEBUG, "State change: %s -> %s\n", amps_state_name(amps->state), amps_state_name(new_state));
PDEBUG_CHAN(DAMPS, DEBUG_DEBUG, "State change: %s -> %s\n", amps_state_name(amps->state), amps_state_name(new_state));
amps->state = new_state;
amps_display_status();
}
@ -430,7 +402,7 @@ int amps_channel_by_short_name(const char *short_name)
for (i = 0; amps_channels[i].short_name; i++) {
if (!strcasecmp(amps_channels[i].short_name, short_name)) {
LOGP(DAMPS, LOGL_INFO, "Selecting channel '%s' = %s\n", amps_channels[i].short_name, amps_channels[i].long_name);
PDEBUG(DAMPS, DEBUG_INFO, "Selecting channel '%s' = %s\n", amps_channels[i].short_name, amps_channels[i].long_name);
return amps_channels[i].chan_type;
}
}
@ -519,7 +491,7 @@ static amps_t *search_pc(void)
}
/* Create transceiver instance and link to a list. */
int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int send_callerid, int tolerant, int loopback)
int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback)
{
sender_t *sender;
amps_t *amps;
@ -529,15 +501,13 @@ int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *de
/* check for channel number */
if (amps_channel2freq(atoi(kanal), 0) == 0) {
LOGP(DAMPS, LOGL_ERROR, "Channel number %s invalid.\n", kanal);
if (jtacs)
LOGP(DAMPS, LOGL_ERROR, "Try an even channel number, like 440.\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Channel number %s invalid.\n", kanal);
return -EINVAL;
}
/* no paging channel (without control channel) support */
if (chan_type == CHAN_TYPE_PC) {
LOGP(DAMPS, LOGL_ERROR, "Dedicated paging channel currently not supported. Please select CC/PC or CC/PC/VC instead.\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Dedicated paging channel currently not supported. Please select CC/PC or CC/PC/VC instead.\n");
return -EINVAL;
}
@ -546,7 +516,7 @@ int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *de
for (sender = sender_head; sender; sender = sender->next) {
amps = (amps_t *)sender;
if (amps->chan_type == CHAN_TYPE_PC || amps->chan_type == CHAN_TYPE_CC_PC || amps->chan_type == CHAN_TYPE_CC_PC_VC) {
LOGP(DAMPS, LOGL_ERROR, "Only one paging channel is currently supported. Please check your channel types.\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Only one paging channel is currently supported. Please check your channel types.\n");
return -EINVAL;
}
}
@ -555,63 +525,58 @@ int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *de
/* check if channel type matches channel number */
ct = amps_channel2type(atoi(kanal));
if (ct == CHAN_TYPE_CC && chan_type != CHAN_TYPE_PC && chan_type != CHAN_TYPE_CC_PC && chan_type != CHAN_TYPE_CC_PC_VC) {
LOGP(DAMPS, LOGL_NOTICE, "Channel number %s belongs to a control channel, but your channel type '%s' requires to be on a voice channel number. Some phone may reject this, but all my phones don't.\n", kanal, chan_type_long_name(chan_type));
PDEBUG(DAMPS, DEBUG_NOTICE, "Channel number %s belongs to a control channel, but your channel type '%s' requires to be on a voice channel number. Some phone may reject this, but all my phones don't.\n", kanal, chan_type_long_name(chan_type));
}
if (ct == CHAN_TYPE_VC && chan_type != CHAN_TYPE_VC) {
LOGP(DAMPS, LOGL_ERROR, "Channel number %s belongs to a voice channel, but your channel type '%s' requires to be on a control channel number. Please use correct channel.\n", kanal, chan_type_long_name(chan_type));
return -EINVAL;
}
/* only even channels */
if (jtacs && chan_type != CHAN_TYPE_VC && (atoi(kanal) & 1)) {
LOGP(DAMPS, LOGL_ERROR, "Control channel on JTACS system seem not to work with odd channel numbers. Please use even channel number.\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Channel number %s belongs to a voice channel, but your channel type '%s' requires to be on a control channel number. Please use correct channel.\n", kanal, chan_type_long_name(chan_type));
return -EINVAL;
}
/* check if sid machtes channel band */
band = amps_channel2band(atoi(kanal));
if (band[0] == 'A' && (sid & 1) == 0 && chan_type != CHAN_TYPE_VC) {
LOGP(DAMPS, LOGL_ERROR, "Channel number %s belongs to system A, but your %s %d is even and belongs to system B. Please give odd %s.\n", kanal, (!tacs) ? "SID" : "AID", sid, (!tacs) ? "SID" : "AID");
PDEBUG(DAMPS, DEBUG_ERROR, "Channel number %s belongs to system A, but your %s %d is even and belongs to system B. Please give odd %s.\n", kanal, (!tacs) ? "SID" : "AID", sid, (!tacs) ? "SID" : "AID");
return -EINVAL;
}
if (band[0] == 'B' && (sid & 1) == 1 && chan_type != CHAN_TYPE_VC) {
LOGP(DAMPS, LOGL_ERROR, "Channel number %s belongs to system B, but your %s %d is odd and belongs to system A. Please give even %s.\n", kanal, (!tacs) ? "SID" : "AID", sid, (!tacs) ? "SID" : "AID");
PDEBUG(DAMPS, DEBUG_ERROR, "Channel number %s belongs to system B, but your %s %d is odd and belongs to system A. Please give even %s.\n", kanal, (!tacs) ? "SID" : "AID", sid, (!tacs) ? "SID" : "AID");
return -EINVAL;
}
/* check if we use combined voice channel hack */
if (chan_type == CHAN_TYPE_CC_PC_VC) {
LOGP(DAMPS, LOGL_NOTICE, "You selected '%s'. This is a hack, but the only way to use control channel and voice channel on one transceiver. Some phones may reject this, but all my phones don't.\n", chan_type_long_name(chan_type));
PDEBUG(DAMPS, DEBUG_NOTICE, "You selected '%s'. This is a hack, but the only way to use control channel and voice channel on one transceiver. Some phones may reject this, but all my phones don't.\n", chan_type_long_name(chan_type));
}
/* check if we selected a voice channel that i outside 20 MHz band */
if (chan_type == CHAN_TYPE_VC && atoi(kanal) > 666) {
LOGP(DAMPS, LOGL_NOTICE, "You selected '%s' on channel #%s. Older phones do not support channels above #666.\n", chan_type_long_name(chan_type), kanal);
PDEBUG(DAMPS, DEBUG_NOTICE, "You selected '%s' on channel #%s. Older phones do not support channels above #666.\n", chan_type_long_name(chan_type), kanal);
}
amps = calloc(1, sizeof(amps_t));
if (!amps) {
LOGP(DAMPS, LOGL_ERROR, "No memory!\n");
PDEBUG(DAMPS, DEBUG_ERROR, "No memory!\n");
return -ENOMEM;
}
LOGP(DAMPS, LOGL_DEBUG, "Creating 'AMPS' instance for channel = %s of band %s (sample rate %d).\n", kanal, band, samplerate);
PDEBUG(DAMPS, DEBUG_DEBUG, "Creating 'AMPS' instance for channel = %s of band %s (sample rate %d).\n", kanal, band, samplerate);
/* init general part of transceiver */
rc = sender_create(&amps->sender, kanal, amps_channel2freq(atoi(kanal), 0), amps_channel2freq(atoi(kanal), 1), device, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
if (rc < 0) {
LOGP(DAMPS, LOGL_ERROR, "Failed to init transceiver process!\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init transceiver process!\n");
goto error;
}
amps->chan_type = chan_type;
memcpy(&amps->si, si, sizeof(amps->si));
amps->sat = sat;
amps->send_callerid = send_callerid;
if (polarity < 0)
amps->flip_polarity = 1;
amps->pre_emphasis = pre_emphasis;
amps->de_emphasis = de_emphasis;
/* the AMPS uses a frequency rage of 300..3000 Hz, but we still use the default low pass filter, which is not too far above */
rc = init_emphasis(&amps->estate, samplerate, CUT_OFF_EMPHASIS_DEFAULT, CUT_OFF_HIGHPASS_DEFAULT, CUT_OFF_LOWPASS_DEFAULT);
if (rc < 0)
@ -620,7 +585,7 @@ int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *de
/* init audio processing */
rc = dsp_init_sender(amps, tolerant);
if (rc < 0) {
LOGP(DAMPS, LOGL_ERROR, "Failed to init audio processing!\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init audio processing!\n");
goto error;
}
@ -635,7 +600,7 @@ int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *de
// amps_new_state(amps, STATE_BUSY);
#endif
LOGP(DAMPS, LOGL_NOTICE, "Created channel #%s (System %s) of type '%s' = %s\n", kanal, band, chan_type_short_name(chan_type), chan_type_long_name(chan_type));
PDEBUG(DAMPS, DEBUG_NOTICE, "Created channel #%s (System %s) of type '%s' = %s\n", kanal, band, chan_type_short_name(chan_type), chan_type_long_name(chan_type));
return 0;
@ -651,11 +616,11 @@ void amps_destroy(sender_t *sender)
amps_t *amps = (amps_t *) sender;
transaction_t *trans;
LOGP(DAMPS, LOGL_DEBUG, "Destroying 'AMPS' instance for channel = %s.\n", sender->kanal);
PDEBUG(DAMPS, DEBUG_DEBUG, "Destroying 'AMPS' instance for channel = %s.\n", sender->kanal);
while ((trans = amps->trans_list)) {
const char *number = amps_min2number(trans->min1, trans->min2);
LOGP(DAMPS, LOGL_NOTICE, "Removing pending transaction for subscriber '%s'\n", number);
PDEBUG(DAMPS, DEBUG_NOTICE, "Removing pending transaction for subscriber '%s'\n", number);
destroy_transaction(trans);
}
@ -673,7 +638,7 @@ void amps_go_idle(amps_t *amps)
return;
if (amps->trans_list) {
LOGP(DAMPS, LOGL_ERROR, "Releasing but still having transaction, please fix!\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Releasing but still having transaction, please fix!\n");
if (amps->trans_list->callref)
call_up_release(amps->trans_list->callref, CAUSE_NORMAL);
destroy_transaction(amps->trans_list);
@ -682,14 +647,14 @@ void amps_go_idle(amps_t *amps)
amps_new_state(amps, STATE_IDLE);
if (amps->chan_type != CHAN_TYPE_VC) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Entering IDLE state, sending Overhead/Filler frames on %s.\n", chan_type_long_name(amps->chan_type));
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Entering IDLE state, sending Overhead/Filler frames on %s.\n", chan_type_long_name(amps->chan_type));
if (amps->sender.loopback)
frame_length = 441; /* bits after sync (FOCC) */
else
frame_length = 247; /* bits after sync (RECC) */
amps_set_dsp_mode(amps, DSP_MODE_FRAME_RX_FRAME_TX, frame_length);
} else {
LOGP_CHAN(DAMPS, LOGL_INFO, "Entering IDLE state (sending silence / no RF) on %s.\n", chan_type_long_name(amps->chan_type));
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Entering IDLE state (sending silence / no RF) on %s.\n", chan_type_long_name(amps->chan_type));
amps_set_dsp_mode(amps, DSP_MODE_OFF, 0);
}
}
@ -699,8 +664,8 @@ static void amps_release(transaction_t *trans, uint8_t cause)
{
amps_t *amps = trans->amps;
osmo_timer_del(&trans->timer);
osmo_timer_schedule(&trans->timer, RELEASE_TIMER);
timer_stop(&trans->timer);
timer_start(&trans->timer, RELEASE_TIMER);
trans_new_state(trans, TRANS_CALL_RELEASE);
trans->chan = 0;
trans->msg_type = 0;
@ -712,28 +677,28 @@ static void amps_release(transaction_t *trans, uint8_t cause)
trans->callref = 0;
}
/* change DSP mode to transmit release */
if (amps->dsp_mode == DSP_MODE_AUDIO_RX_AUDIO_TX || amps->dsp_mode == DSP_MODE_AUDIO_RX_SILENCE_TX || amps->dsp_mode == DSP_MODE_OFF)
if (amps->dsp_mode == DSP_MODE_AUDIO_RX_AUDIO_TX || amps->dsp_mode == DSP_MODE_OFF)
amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_FRAME_TX, 0);
}
/*
* receive signaling
*/
void amps_rx_signaling_tone(amps_t *amps, int tone, double quality)
{
transaction_t *trans = amps->trans_list;
if (trans == NULL) {
LOGP_CHAN(DAMPS, LOGL_ERROR, "Signaling Tone without transaction, please fix!\n");
PDEBUG_CHAN(DAMPS, DEBUG_ERROR, "Signaling Tone without transaction, please fix!\n");
return;
}
if (tone)
LOGP_CHAN(DAMPS, LOGL_INFO, "Detected Signaling Tone with quality=%.0f.\n", quality * 100.0);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Detected Signaling Tone with quality=%.0f.\n", quality * 100.0);
else
LOGP_CHAN(DAMPS, LOGL_INFO, "Lost Signaling Tone signal\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Lost Signaling Tone signal\n");
switch (trans->state) {
case TRANS_CALL_MO_ASSIGN_CONFIRM: // should not happen
case TRANS_CALL:
if (!tone)
break;
@ -741,35 +706,32 @@ void amps_rx_signaling_tone(amps_t *amps, int tone, double quality)
case TRANS_CALL_RELEASE:
case TRANS_CALL_RELEASE_SEND:
/* also loosing singaling tone indicates release confirm (after alerting) */
osmo_timer_del(&trans->timer);
timer_stop(&trans->timer);
if (trans->callref)
call_up_release(trans->callref, CAUSE_NORMAL);
destroy_transaction(trans);
amps_go_idle(amps);
break;
case TRANS_CALL_MT_ASSIGN_CONFIRM: // should not happen
case TRANS_CALL_MT_ALERT: // should not happen
case TRANS_CALL_MT_ALERT_SEND: // should not happen
case TRANS_CALL_MT_ALERT_CONFIRM:
case TRANS_CALL_MT_ALERT:
if (tone) {
osmo_timer_del(&trans->timer);
timer_stop(&trans->timer);
call_up_alerting(trans->callref);
amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_AUDIO_TX, 0);
trans_new_state(trans, TRANS_CALL_MT_ANSWER_WAIT);
osmo_timer_schedule(&trans->timer, ANSWER_TO);
trans_new_state(trans, TRANS_CALL_MT_ALERT_SEND);
timer_start(&trans->timer, ALERT_TO);
}
break;
case TRANS_CALL_MT_ANSWER_WAIT:
case TRANS_CALL_MT_ALERT_SEND:
if (!tone) {
osmo_timer_del(&trans->timer);
timer_stop(&trans->timer);
if (!trans->sat_detected)
osmo_timer_schedule(&trans->timer, SAT_TO1);
timer_start(&trans->timer, SAT_TO1);
call_up_answer(trans->callref, amps_min2number(trans->min1, trans->min2));
trans_new_state(trans, TRANS_CALL);
}
break;
default:
LOGP_CHAN(DAMPS, LOGL_ERROR, "Signaling Tone without active call, please fix!\n");
PDEBUG_CHAN(DAMPS, DEBUG_ERROR, "Signaling Tone without active call, please fix!\n");
}
}
@ -777,63 +739,60 @@ void amps_rx_sat(amps_t *amps, int tone, double quality)
{
transaction_t *trans = amps->trans_list;
if (trans == NULL) {
LOGP_CHAN(DAMPS, LOGL_ERROR, "SAT signal without transaction, please fix!\n");
PDEBUG_CHAN(DAMPS, DEBUG_ERROR, "SAT signal without transaction, please fix!\n");
return;
}
/* irgnoring SAT loss on release */
if (trans->state == TRANS_CALL_RELEASE
|| trans->state == TRANS_CALL_RELEASE_SEND)
return;
/* only SAT with these states */
if (trans->state != TRANS_CALL_MO_ASSIGN_CONFIRM
&& trans->state != TRANS_CALL_MT_ASSIGN_CONFIRM
if (trans->state != TRANS_CALL
&& trans->state != TRANS_CALL_MT_ALERT
&& trans->state != TRANS_CALL_MT_ALERT_SEND
&& trans->state != TRANS_CALL_MT_ALERT_CONFIRM
&& trans->state != TRANS_CALL_MT_ANSWER_WAIT
&& trans->state != TRANS_CALL) {
LOGP_CHAN(DAMPS, LOGL_ERROR, "SAT signal without active call, please fix!\n");
&& trans->state != TRANS_CALL_MT_ALERT_SEND) {
PDEBUG_CHAN(DAMPS, DEBUG_ERROR, "SAT signal without active call, please fix!\n");
return;
}
if (tone) {
LOGP(DAMPS, LOGL_INFO, "Detected SAT signal with quality=%.0f.\n", quality * 100.0);
PDEBUG(DAMPS, DEBUG_INFO, "Detected SAT signal with quality=%.0f.\n", quality * 100.0);
trans->sat_detected = 1;
} else {
LOGP(DAMPS, LOGL_INFO, "Lost SAT signal\n");
PDEBUG(DAMPS, DEBUG_INFO, "Lost SAT signal\n");
trans->sat_detected = 0;
}
/* initial SAT received */
if (tone && trans->state == TRANS_CALL_MO_ASSIGN_CONFIRM) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Confirm from mobile (SAT) received\n");
osmo_timer_del(&trans->timer);
trans_new_state(trans, TRANS_CALL);
amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_AUDIO_TX, 0);
}
if (tone && trans->state == TRANS_CALL_MT_ASSIGN_CONFIRM) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Confirm from mobile (SAT) received\n");
osmo_timer_del(&trans->timer);
trans->alert_retry = 1;
trans_new_state(trans, TRANS_CALL_MT_ALERT);
amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_FRAME_TX, 0);
}
/* no SAT during alerting */
if (trans->state == TRANS_CALL_MT_ALERT
|| trans->state == TRANS_CALL_MT_ALERT_SEND)
return;
if (tone) {
osmo_timer_del(&trans->timer);
timer_stop(&trans->timer);
} else {
if (!trans->dtx)
osmo_timer_schedule(&trans->timer, SAT_TO2);
timer_start(&trans->timer, SAT_TO2);
else
osmo_timer_del(&trans->timer);
timer_stop(&trans->timer);
}
if (amps->sender.loopback)
return;
}
static void timeout_sat(amps_t *amps, double duration)
{
if (!amps->trans_list) {
PDEBUG_CHAN(DAMPS, DEBUG_ERROR, "SAT timeout, but no transaction, please fix!\n");
return;
}
if (duration == SAT_TO1)
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Timeout after %.0f seconds not receiving SAT signal.\n", duration);
else
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Timeout after %.0f seconds loosing SAT signal.\n", duration);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Release call towards network.\n");
amps_release(amps->trans_list, CAUSE_TEMPFAIL);
}
/* receive message from phone on RECC */
void amps_rx_recc(amps_t *amps, uint8_t scm, uint8_t mpci, uint32_t esn, uint32_t min1, uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order, const char *dialing)
{
@ -844,51 +803,50 @@ void amps_rx_recc(amps_t *amps, uint8_t scm, uint8_t mpci, uint32_t esn, uint32_
/* check if we are busy, so we ignore all signaling */
if (amps->state == STATE_BUSY) {
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Ignoring RECC messages from phone while using this channel for voice.\n");
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Ignoring RECC messages from phone while using this channel for voice.\n");
return;
}
if (order == 13 && (ordq == 0 || ordq == 1 || ordq == 2 || ordq == 3) && msg_type == 0) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Registration %s (ESN = %s, %s, %s)\n", callerid, esn_to_string(esn), amps_scm(scm), amps_mpci(mpci));
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Registration %s (ESN = %08x, %s, %s)\n", callerid, esn, amps_scm(scm), amps_mpci(mpci));
_register:
numbering(callerid, &carrier, &country, &national_number);
if (carrier)
LOGP_CHAN(DAMPS, LOGL_INFO, " -> Home carrier: %s\n", carrier);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, " -> Home carrier: %s\n", carrier);
if (country)
LOGP_CHAN(DAMPS, LOGL_INFO, " -> Home country: %s\n", country);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, " -> Home country: %s\n", country);
if (national_number)
LOGP_CHAN(DAMPS, LOGL_INFO, " -> Home number: %s\n", national_number);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, " -> Home number: %s\n", national_number);
trans = create_transaction(amps, TRANS_REGISTER_ACK, min1, min2, esn, msg_type, ordq, order, 0);
if (!trans) {
LOGP(DAMPS, LOGL_ERROR, "Failed to create transaction\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
return;
}
console_inscription(callerid);
} else
if (order == 13 && ordq == 3 && msg_type == 1) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Registration - Power Down %s (ESN = %s, %s, %s)\n", callerid, esn_to_string(esn), amps_scm(scm), amps_mpci(mpci));
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Registration - Power Down %s (ESN = %08x, %s, %s)\n", callerid, esn, amps_scm(scm), amps_mpci(mpci));
goto _register;
} else
if (order == 0 && ordq == 0 && msg_type == 0) {
if (!dialing)
LOGP_CHAN(DAMPS, LOGL_INFO, "Paging reply %s (ESN = %s, %s, %s)\n", callerid, esn_to_string(esn), amps_scm(scm), amps_mpci(mpci));
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Paging reply %s (ESN = %08x, %s, %s)\n", callerid, esn, amps_scm(scm), amps_mpci(mpci));
else
LOGP_CHAN(DAMPS, LOGL_INFO, "Call %s -> %s (ESN = %s, %s, %s)\n", callerid, dialing, esn_to_string(esn), amps_scm(scm), amps_mpci(mpci));
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call %s -> %s (ESN = %08x, %s, %s)\n", callerid, dialing, esn, amps_scm(scm), amps_mpci(mpci));
trans = search_transaction_number(amps, min1, min2);
if (!trans && !dialing) {
LOGP(DAMPS, LOGL_NOTICE, "Paging reply, but call is already gone, rejecting call\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "Paging reply, but call is already gone, rejecting call\n");
goto reject;
}
if (trans && dialing)
LOGP(DAMPS, LOGL_NOTICE, "There is already a transaction for this phone. Cloning?\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "There is already a transaction for this phone. Cloning?\n");
vc = search_free_vc();
if (!vc) {
LOGP(DAMPS, LOGL_NOTICE, "No free channel, rejecting call\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "No free channel, rejecting call\n");
reject:
if (!trans) {
trans = create_transaction(amps, TRANS_CALL_REJECT, min1, min2, esn, 0, 0, 3, 0);
if (!trans) {
LOGP(DAMPS, LOGL_ERROR, "Failed to create transaction\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
return;
}
} else {
@ -904,7 +862,7 @@ reject:
trans = create_transaction(amps, TRANS_CALL_MO_ASSIGN, min1, min2, esn, 0, 0, 0, atoi(vc->sender.kanal));
strncpy(trans->dialing, dialing, sizeof(trans->dialing) - 1);
if (!trans) {
LOGP(DAMPS, LOGL_ERROR, "Failed to create transaction\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
return;
}
} else {
@ -914,13 +872,13 @@ reject:
/* if we support DTX and also the phone does, we set DTX state of transaction */
if (amps->si.word2.dtx) {
if ((scm & 4)) {
LOGP(DAMPS, LOGL_INFO, " -> Use DTX for this call\n");
PDEBUG(DAMPS, DEBUG_INFO, " -> Use DTX for this call\n");
trans->dtx = 1;
} else
LOGP(DAMPS, LOGL_INFO, " -> Requested DTX, but not supported by phone\n");
PDEBUG(DAMPS, DEBUG_INFO, " -> Requested DTX, but not supported by phone\n");
}
} else
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Unsupported RECC messages: ORDER: %d ORDQ: %d MSG TYPE: %d (See Table 4 of specs.)\n", order, ordq, msg_type);
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Unsupported RECC messages: ORDER: %d ORDQ: %d MSG TYPE: %d (See Table 4 of specs.)\n", order, ordq, msg_type);
}
/*
@ -941,7 +899,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
/* 2. check if the subscriber is attached */
// if (!find_db(min1, min2)) {
// LOGP(DAMPS, LOGL_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
// PDEBUG(DAMPS, DEBUG_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
// return -CAUSE_OUTOFORDER;
// }
@ -954,43 +912,38 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
break;
}
if (sender) {
LOGP(DAMPS, LOGL_NOTICE, "Outgoing call to busy number, rejecting!\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
return -CAUSE_BUSY;
}
/* 4. check if all senders are busy, return NOCHANNEL */
if (!search_free_vc()) {
LOGP(DAMPS, LOGL_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
return -CAUSE_NOCHANNEL;
}
/* 5. check if we have (currently) no paging channel, return NOCHANNEL */
amps = search_pc();
if (!amps) {
LOGP(DAMPS, LOGL_NOTICE, "Outgoing call, but paging channel (control channel) is currently busy, rejecting!\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "Outgoing call, but paging channel (control channel) is currently busy, rejecting!\n");
return -CAUSE_NOCHANNEL;
}
LOGP_CHAN(DAMPS, LOGL_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
/* 6. trying to page mobile station */
trans = create_transaction(amps, TRANS_PAGE, min1, min2, 0, 0, 0, 0, 0);
if (!trans) {
LOGP(DAMPS, LOGL_ERROR, "Failed to create transaction\n");
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
return -CAUSE_TEMPFAIL;
}
trans->callref = callref;
trans->page_retry = 1;
if (caller_type == TYPE_INTERNATIONAL) {
trans->caller_id[0] = '+';
strncpy(trans->caller_id + 1, caller_id, sizeof(trans->caller_id) - 2);
} else
strncpy(trans->caller_id, caller_id, sizeof(trans->caller_id) - 1);
return 0;
}
void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter)
void call_down_answer(int __attribute__((unused)) callref)
{
}
@ -1004,7 +957,7 @@ void call_down_disconnect(int callref, int cause)
amps_t *amps;
transaction_t *trans;
LOGP(DAMPS, LOGL_INFO, "Call has been disconnected by network.\n");
PDEBUG(DAMPS, DEBUG_INFO, "Call has been disconnected by network.\n");
for (sender = sender_head; sender; sender = sender->next) {
amps = (amps_t *) sender;
@ -1014,7 +967,7 @@ void call_down_disconnect(int callref, int cause)
break;
}
if (!sender) {
LOGP(DAMPS, LOGL_NOTICE, "Outgoing disconnect, but no callref!\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n");
call_up_release(callref, CAUSE_INVALCALLREF);
return;
}
@ -1024,17 +977,14 @@ void call_down_disconnect(int callref, int cause)
switch (amps->dsp_mode) {
case DSP_MODE_AUDIO_RX_AUDIO_TX:
case DSP_MODE_AUDIO_RX_FRAME_TX:
if (trans->state == TRANS_CALL_MT_ASSIGN_CONFIRM
|| trans->state == TRANS_CALL_MT_ALERT
|| trans->state == TRANS_CALL_MT_ALERT_SEND
|| trans->state == TRANS_CALL_MT_ALERT_CONFIRM
|| trans->state == TRANS_CALL_MT_ANSWER_WAIT) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Call control disconnect on voice channel while alerting, releasing towards mobile station.\n");
if (trans->state == TRANS_CALL_MT_ALERT
|| trans->state == TRANS_CALL_MT_ALERT_SEND) {
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call control disconnect on voice channel while alerting, releasing towards mobile station.\n");
amps_release(trans, cause);
}
return;
default:
LOGP_CHAN(DAMPS, LOGL_INFO, "Call control disconnects on control channel, removing transaction.\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call control disconnects on control channel, removing transaction.\n");
call_up_release(callref, cause);
trans->callref = 0;
destroy_transaction(trans);
@ -1049,7 +999,7 @@ void call_down_release(int callref, int cause)
amps_t *amps;
transaction_t *trans;
LOGP(DAMPS, LOGL_INFO, "Call has been released by network, releasing call.\n");
PDEBUG(DAMPS, DEBUG_INFO, "Call has been released by network, releasing call.\n");
for (sender = sender_head; sender; sender = sender->next) {
amps = (amps_t *) sender;
@ -1059,7 +1009,7 @@ void call_down_release(int callref, int cause)
break;
}
if (!sender) {
LOGP(DAMPS, LOGL_NOTICE, "Outgoing release, but no callref!\n");
PDEBUG(DAMPS, DEBUG_NOTICE, "Outgoing release, but no callref!\n");
/* don't send release, because caller already released */
return;
}
@ -1067,69 +1017,76 @@ void call_down_release(int callref, int cause)
trans->callref = 0;
switch (amps->dsp_mode) {
case DSP_MODE_AUDIO_RX_SILENCE_TX:
case DSP_MODE_AUDIO_RX_AUDIO_TX:
case DSP_MODE_AUDIO_RX_FRAME_TX:
LOGP_CHAN(DAMPS, LOGL_INFO, "Call control releases on voice channel, releasing towards mobile station.\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call control releases on voice channel, releasing towards mobile station.\n");
amps_release(trans, cause);
break;
default:
LOGP_CHAN(DAMPS, LOGL_INFO, "Call control releases on control channel, removing transaction.\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call control releases on control channel, removing transaction.\n");
destroy_transaction(trans);
amps_go_idle(amps);
}
}
/* Timeout handling */
void transaction_timeout(void *data)
/* Receive audio from call instance. */
void call_down_audio(int callref, sample_t *samples, int count)
{
transaction_t *trans = data;
sender_t *sender;
amps_t *amps;
for (sender = sender_head; sender; sender = sender->next) {
amps = (amps_t *) sender;
if (amps->trans_list && amps->trans_list->callref == callref)
break;
}
if (!sender)
return;
if (amps->dsp_mode == DSP_MODE_AUDIO_RX_AUDIO_TX) {
sample_t up[(int)((double)count * amps->sender.srstate.factor + 0.5) + 10];
compress_audio(&amps->cstate, samples, count);
count = samplerate_upsample(&amps->sender.srstate, samples, count, up);
jitter_save(&amps->sender.dejitter, up, count);
}
}
void call_down_clock(void) {}
/* Timeout handling */
void transaction_timeout(struct timer *timer)
{
transaction_t *trans = (transaction_t *)timer->priv;
amps_t *amps = trans->amps;
switch (trans->state) {
case TRANS_CALL_MO_ASSIGN_CONFIRM:
case TRANS_CALL_MT_ASSIGN_CONFIRM:
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Timeout after %ld seconds not receiving initial SAT signal.\n", trans->timer.timeout.tv_sec);
LOGP_CHAN(DAMPS, LOGL_INFO, "Release call towards network.\n");
amps_release(amps->trans_list, CAUSE_TEMPFAIL);
break;
case TRANS_CALL:
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Timeout after %ld seconds loosing SAT signal.\n", trans->timer.timeout.tv_sec);
LOGP_CHAN(DAMPS, LOGL_INFO, "Release call towards network.\n");
amps_release(amps->trans_list, CAUSE_TEMPFAIL);
timeout_sat(amps, timer->duration);
break;
case TRANS_CALL_RELEASE:
case TRANS_CALL_RELEASE_SEND:
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Release timeout, destroying transaction\n");
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Release timeout, destroying transaction\n");
destroy_transaction(trans);
amps_go_idle(amps);
break;
case TRANS_CALL_MT_ALERT_SEND:
case TRANS_CALL_MT_ALERT_CONFIRM:
if (trans->alert_retry++ == ALERT_TRIES) {
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Phone does not respond to alert order, destroying transaction\n");
amps_release(trans, CAUSE_TEMPFAIL);
} else {
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Phone does not respond to alert order, retrying\n");
trans_new_state(trans, TRANS_CALL_MT_ALERT);
amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_FRAME_TX, 0);
}
case TRANS_CALL_MT_ALERT:
amps_release(trans, CAUSE_TEMPFAIL);
break;
case TRANS_CALL_MT_ANSWER_WAIT:
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Alerting timeout, destroying transaction\n");
case TRANS_CALL_MT_ALERT_SEND:
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Alerting timeout, destroying transaction\n");
amps_release(trans, CAUSE_NOANSWER);
break;
case TRANS_PAGE_REPLY:
if (trans->page_retry++ == PAGE_TRIES) {
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Paging timeout, destroying transaction\n");
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Paging timeout, destroying transaction\n");
amps_release(trans, CAUSE_OUTOFORDER);
} else {
LOGP_CHAN(DAMPS, LOGL_NOTICE, "Paging timeout, retrying\n");
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Paging timeout, retrying\n");
trans_new_state(trans, TRANS_PAGE);
}
break;
default:
LOGP_CHAN(DAMPS, LOGL_ERROR, "Timeout unhandled in state %d\n", trans->state);
PDEBUG_CHAN(DAMPS, DEBUG_ERROR, "Timeout unhandled in state %d\n", trans->state);
}
}
@ -1141,18 +1098,18 @@ static amps_t *assign_voice_channel(transaction_t *trans)
vc = search_channel(trans->chan);
if (!vc) {
LOGP(DAMPS, LOGL_NOTICE, "Channel %d is not free anymore, rejecting call\n", trans->chan);
PDEBUG(DAMPS, DEBUG_NOTICE, "Channel %d is not free anymore, rejecting call\n", trans->chan);
amps_release(trans, CAUSE_NOCHANNEL);
return NULL;
}
if (vc == amps)
LOGP(DAMPS, LOGL_INFO, "Staying on combined control + voice channel %s\n", vc->sender.kanal);
PDEBUG(DAMPS, DEBUG_INFO, "Staying on combined control + voice channel %s\n", vc->sender.kanal);
else
LOGP(DAMPS, LOGL_INFO, "Moving to voice channel %s\n", vc->sender.kanal);
PDEBUG(DAMPS, DEBUG_INFO, "Moving to voice channel %s\n", vc->sender.kanal);
/* switch channel... */
osmo_timer_schedule(&trans->timer, SAT_TO1);
timer_start(&trans->timer, SAT_TO1);
/* make channel busy */
amps_new_state(vc, STATE_BUSY);
/* relink */
@ -1165,7 +1122,7 @@ static amps_t *assign_voice_channel(transaction_t *trans)
char esn_text[16];
sprintf(esn_text, "%u", trans->esn);
/* setup call */
LOGP(DAMPS, LOGL_INFO, "Setup call to network.\n");
PDEBUG(DAMPS, DEBUG_INFO, "Setup call to network.\n");
trans->callref = call_up_setup(callerid, trans->dialing, OSMO_CC_NETWORK_AMPS_ESN, esn_text);
}
@ -1184,55 +1141,54 @@ again:
switch (trans->state) {
case TRANS_REGISTER_ACK:
LOGP_CHAN(DAMPS, LOGL_INFO, "Sending Register acknowledge\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Sending Register acknowledge\n");
trans_new_state(trans, TRANS_REGISTER_ACK_SEND);
return trans;
case TRANS_REGISTER_ACK_SEND:
destroy_transaction(trans);
goto again;
case TRANS_CALL_REJECT:
LOGP_CHAN(DAMPS, LOGL_INFO, "Rejecting call from mobile station\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Rejecting call from mobile station\n");
trans_new_state(trans, TRANS_CALL_REJECT_SEND);
return trans;
case TRANS_CALL_REJECT_SEND:
destroy_transaction(trans);
goto again;
case TRANS_CALL_MO_ASSIGN:
LOGP_CHAN(DAMPS, LOGL_INFO, "Assigning channel to call from mobile station\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Assigning channel to call from mobile station\n");
trans_new_state(trans, TRANS_CALL_MO_ASSIGN_SEND);
return trans;
case TRANS_CALL_MO_ASSIGN_SEND:
vc = assign_voice_channel(trans);
if (vc) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Assignment complete, voice connected\n");
/* timer and other things are processed at assign_voice_channel() */
trans_new_state(trans, TRANS_CALL_MO_ASSIGN_CONFIRM);
amps_set_dsp_mode(vc, DSP_MODE_AUDIO_RX_SILENCE_TX, 0);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Assignment complete, voice connected\n");
trans_new_state(trans, TRANS_CALL);
amps_set_dsp_mode(vc, DSP_MODE_AUDIO_RX_AUDIO_TX, 0);
}
return NULL;
case TRANS_CALL_MT_ASSIGN:
LOGP_CHAN(DAMPS, LOGL_INFO, "Assigning channel to call to mobile station\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Assigning channel to call to mobile station\n");
trans_new_state(trans, TRANS_CALL_MT_ASSIGN_SEND);
return trans;
case TRANS_CALL_MT_ASSIGN_SEND:
vc = assign_voice_channel(trans);
if (vc) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Assignment complete, waiting for SAT on VC\n");
/* timer and other things are processed at assign_voice_channel() */
trans_new_state(trans, TRANS_CALL_MT_ASSIGN_CONFIRM);
amps_set_dsp_mode(vc, DSP_MODE_AUDIO_RX_SILENCE_TX, 0);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Assignment complete, next: sending alerting on VC\n");
trans->chan = 0;
trans->msg_type = 0;
trans->ordq = 0;
trans->order = 1;
trans_new_state(trans, TRANS_CALL_MT_ALERT);
amps_set_dsp_mode(vc, DSP_MODE_AUDIO_RX_FRAME_TX, 0);
}
return NULL;
case TRANS_PAGE:
LOGP_CHAN(DAMPS, LOGL_INFO, "Paging the phone\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Paging the phone\n");
trans_new_state(trans, TRANS_PAGE_SEND);
return trans;
case TRANS_PAGE_SEND:
trans_new_state(trans, TRANS_PAGE_REPLY);
if (trans->page_retry == PAGE_TRIES)
osmo_timer_schedule(&trans->timer, PAGE_TO2);
else
osmo_timer_schedule(&trans->timer, PAGE_TO1);
timer_start(&trans->timer, (trans->page_retry == PAGE_TRIES) ? PAGE_TO2 : PAGE_TO1);
return NULL;
default:
return NULL;
@ -1249,32 +1205,15 @@ transaction_t *amps_tx_frame_fvc(amps_t *amps)
switch (trans->state) {
case TRANS_CALL_RELEASE:
LOGP_CHAN(DAMPS, LOGL_INFO, "Releasing call towards mobile station\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Releasing call towards mobile station\n");
trans_new_state(trans, TRANS_CALL_RELEASE_SEND);
return trans;
case TRANS_CALL_RELEASE_SEND:
LOGP_CHAN(DAMPS, LOGL_INFO, "Release call was sent, continue sending release\n");
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Release call was sent, continue sending release\n");
return trans;
case TRANS_CALL_MT_ALERT:
trans->chan = 0;
trans->msg_type = 0;
trans->ordq = 0;
// "Alert with caller ID" causes older phones to interrupt the connection for some reason, therefore we don't use order 17 when no caller ID is set
if (amps->send_callerid && trans->alert_retry == 1 && trans->caller_id[0]) {
LOGP_CHAN(DAMPS, LOGL_INFO, "Sending alerting with caller ID\n");
trans->order = 17;
} else {
LOGP_CHAN(DAMPS, LOGL_INFO, "Sending alerting\n");
trans->order = 1;
}
trans_new_state(trans, TRANS_CALL_MT_ALERT_SEND);
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Sending alerting\n");
return trans;
case TRANS_CALL_MT_ALERT_SEND:
LOGP_CHAN(DAMPS, LOGL_INFO, "Alerting was sent, continue waiting for ST or timeout\n");
osmo_timer_schedule(&trans->timer, ALERT_TO);
amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_SILENCE_TX, 0);
trans_new_state(trans, TRANS_CALL_MT_ALERT_CONFIRM);
return NULL;
default:
return NULL;
}

View File

@ -1,6 +1,6 @@
#include "../libgoertzel/goertzel.h"
#include "../libmobile/sender.h"
#include <osmocom/core/timer.h>
#include "../libtimer/timer.h"
#include "../libcompandor/compandor.h"
typedef struct amps amps_t;
#include "sysinfo.h"
@ -10,7 +10,6 @@ enum dsp_mode {
DSP_MODE_OFF, /* channel not active (VC) */
DSP_MODE_AUDIO_RX_AUDIO_TX, /* stream audio */
DSP_MODE_AUDIO_RX_FRAME_TX, /* stream audio, send frames */
DSP_MODE_AUDIO_RX_SILENCE_TX, /* stream audio, send silence */
DSP_MODE_FRAME_RX_FRAME_TX, /* send and decode frames */
};
@ -57,7 +56,6 @@ struct amps {
/* system info */
amps_si si;
int send_callerid; /* if set, caller ID is transmitted */
/* cell nr selection */
int cell_auto; /* if set, cell_nr is selected automatically */
@ -135,19 +133,12 @@ struct amps {
uint8_t tx_focc_order;
int tx_focc_word_count; /* counts transmitted words in a multi word message */
int tx_focc_word_repeat; /* counts repeats of multi word message */
int tx_focc_debugged; /* indicator to prevent debugging all SI/filler frames */
/* FVC frame states */
int tx_fvc_send; /* if set, send message words */
int tx_fvc_chan; /* channel to assign for voice call */
uint8_t tx_fvc_msg_type; /* message (3 values) */
uint8_t tx_fvc_ordq;
uint8_t tx_fvc_order;
char tx_fvc_callerid[34]; /* caller ID */
int tx_fvc_callerid_present;/* presentation of caller ID */
int tx_fvc_callerid_screen; /* screening of caller ID */
int tx_fvc_callerid_signal; /* signal to send in conjunction with caller ID */
int tx_fvc_word_count; /* counts transmitted words in a muli word message */
int tx_fvc_word_repeat; /* counts repeats of mulit word message */
/* SAT tone */
int sat; /* use SAT tone 0..2 */
int sat_samples; /* number of samples in buffer for supervisory detection */
@ -171,7 +162,6 @@ struct amps {
int when_count; /* counter of the filler frame */
};
void amps_display_status(void);
void amps_channel_list(void);
int amps_channel_by_short_name(const char *short_name);
const char *chan_type_short_name(enum amps_chan_type chan_type);
@ -183,10 +173,8 @@ const char *amps_min22number(uint16_t min2);
const char *amps_min12number(uint32_t min1);
void amps_number2min(const char *number, uint32_t *min1, uint16_t *min2);
const char *amps_min2number(uint32_t min1, uint16_t min2);
void amps_encode_esn(uint32_t *esn, uint8_t mfr, uint32_t serial);
void amps_decode_esn(uint32_t esn, uint8_t *mfr, uint32_t *serial);
const char *amps_scm(uint8_t scm);
int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int send_callerid, int tolerant, int loopback);
int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback);
void amps_destroy(sender_t *sender);
void amps_go_idle(amps_t *amps);
void amps_rx_signaling_tone(amps_t *amps, int tone, double quality);

View File

@ -24,7 +24,7 @@
#include <errno.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../liboptions/options.h"
#include "../libfm/fm.h"
@ -38,19 +38,9 @@
int num_chan_type = 0;
enum amps_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_PC_VC };
const char *flip_polarity = "";
int ms_power = 4;
int dtx = 0;
int send_callerid = 0;
int dcc = 0, scc = 0, sid = 0, regh = 1, regr = 1, pureg = 0, pdreg = 0, locaid = -1, regincr = 300, bis = 0;
int ms_power = 4, dtx = 0, dcc = 0, scc = 0, sid = 0, regh = 1, regr = 1, pureg = 0, pdreg = 0, locaid = -1, regincr = 300, bis = 0;
int tolerant = 0;
static void print_location_area_note(void)
{
/* - - */
printf(" Warning: Older phones may not like this and show 'No Service'!\n");
printf(" Note: This feature was added 1995 to the standard, it might not work.\n");
}
void print_help(const char *arg0)
{
if (!tacs)
@ -67,24 +57,12 @@ void print_help(const char *arg0)
printf(" If the phone shows 'NoSrv', try the other way.\n");
printf(" -P --ms-power <power level>\n");
printf(" Give power level of the mobile station 0..7. (default = '%d')\n", ms_power);
if (!tacs) {
printf(" 0 = 4 W; 1 = 1.6 W; 2 = 630 mW; 3 = 250 mW;\n");
printf(" 4 = 100 mW; 5 = 40 mW; 6 = 16 mW; 7 = 6.3 mW\n");
} else {
/* tacs, not jtacs: https://www.academia.edu/8265916/Total_Access_Communication_System?email_work_card=view-paper */
printf(" 0 = 2.28 W; 1 = 1.12 W; 2 = 447 mW; 3 = 178 mW;\n");
printf(" 4 = 70.8 mW; 5 = 28.2 mW; 6 = 11.2 mW; 7 = 4.5 mW\n");
}
printf(" 0 = %2d W; 1 = 1.6 W; 2 = 630 mW; 3 = 250 mW;\n", (tacs) ? 10 : 4);
printf(" 4 = 100 mW; 5 = 40 mW; 6 = 16 mW; 7 = 6.3 mW\n");
printf(" -D --dtx <parameter>\n");
printf(" Give DTX parameter for Discontinuous Transmission. (default = '%d')\n", dtx);
printf(" 0 = disable DTX; 1 = reserved;\n");
printf(" 2 = 8 dB attenuation in low state; 3 = transmitter off\n");
printf(" -I --caller-id 1 | 0\n");
printf(" If set, the caller ID is sent while ringing the phone. (default = '%d')\n", send_callerid);
printf(" Note that this does not work as documented in the specs. If the phone\n");
printf(" does not support caller ID, it will abort connection on receiving\n");
printf(" caller ID for some unknown reason. Therefore use caller ID only with\n");
printf(" phones that support it.\n");
if (!tacs) {
printf(" -S --sysinfo sid=<System ID> | sid=list\n");
printf(" Give system ID of cell broadcast\n");
@ -104,14 +82,14 @@ void print_help(const char *arg0)
printf(" many second the phone waits before it re-registers.\n");
printf(" -S --sysinfo pureg=0 | pureg=1\n");
printf(" If 1, phone registers on every power on (default = '%d')\n", pureg);
print_location_area_note();
printf(" Warning: Older phones may not like this and show 'No Service'!\n");
printf(" -S --sysinfo pdreg=0 | pdreg=1\n");
printf(" If 1, phone de-registers on every power down (default = '%d')\n", pureg);
print_location_area_note();
printf(" Warning: Older phones may not like this and show 'No Service'!\n");
printf(" -S --sysinfo locaid=<location area ID > | locaid=-1 to disable\n");
printf(" (default = '%d')\n", locaid);
printf(" If it changes, phone re-registers.\n");
print_location_area_note();
printf(" Warning: Older phones may not like this and show 'No Service'!\n");
printf(" -S --sysinfo regh=0 | regh=1\n");
printf(" If 1, phone registers only if System ID matches (default = '%d')\n", regh);
printf(" -S --sysinfo regr=0 | regr=1\n");
@ -132,7 +110,6 @@ static void add_options(void)
option_add('F', "flip-polarity", 1);
option_add('P', "ms-power", 1);
option_add('D', "dtx", 1);
option_add('I', "caller-id", 1);
option_add('S', "sysinfo", 1);
option_add('O', "tolerant", 0);
}
@ -179,9 +156,6 @@ static int handle_options(int short_option, int argi, char **argv)
if (dtx < 0)
dtx = 0;
break;
case 'I':
send_callerid = atoi(argv[argi]);
break;
case 'S':
p = strchr(argv[argi], '=');
if (!p) {
@ -252,7 +226,10 @@ static int handle_options(int short_option, int argi, char **argv)
return 1;
}
extern const struct number_lengths number_lengths[];
static const struct number_lengths number_lengths[] = {
{ 10, "AMPS number" },
{ 0, NULL }
};
int main_amps_tacs(const char *name, int argc, char *argv[])
{
@ -261,10 +238,6 @@ int main_amps_tacs(const char *name, int argc, char *argv[])
int polarity;
int i;
/* jtacs has only system A, so there are only odd AIDs */
if (jtacs)
sid = 1;
/* override default */
dsp_samplerate = 96000;
@ -294,7 +267,7 @@ int main_amps_tacs(const char *name, int argc, char *argv[])
}
if (!num_kanal) {
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", (!tacs) ? 333 : ((!jtacs) ? 323 : 418));
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", (!tacs) ? 333 : 323);
print_help(argv[0]);
return 0;
}
@ -411,7 +384,7 @@ int main_amps_tacs(const char *name, int argc, char *argv[])
amps_si si;
init_sysinfo(&si, ms_power, ms_power, dtx, dcc, sid >> 1, regh, regr, pureg, pdreg, locaid, regincr, bis);
rc = amps_create(kanal[i], chan_type[i], dsp_device[i], use_sdr, dsp_samplerate, rx_gain, tx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, &si, sid, scc, polarity, send_callerid, tolerant, loopback);
rc = amps_create(kanal[i], chan_type[i], dsp_device[i], use_sdr, dsp_samplerate, rx_gain, tx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, &si, sid, scc, polarity, tolerant, loopback);
if (rc < 0) {
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
goto fail;
@ -430,7 +403,6 @@ fail:
amps_destroy(sender_head);
/* exits */
main_mobile_exit();
fm_exit();
options_free();

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "congestion.h"
static int16_t pattern[] = {
0xfffd, 0x0004, 0xfffb, 0x0004, 0xfffe, 0x0001, 0x0001, 0xfffe,

View File

@ -82,9 +82,8 @@
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/get_time.h"
#include "amps.h"
#include "frame.h"
#include "dsp.h"
@ -126,7 +125,7 @@
#define SIG_LOST_COUNT 4 /* number of measures to loose Signaling Tone */
#define CUT_OFF_HIGHPASS 300.0 /* cut off frequency for high pass filter to remove dc level from sound card / sample */
#define BEST_QUALITY 0.68 /* Best possible RX quality */
#define COMFORT_NOISE 0.02 /* audio level of comfort noise (relative to speech level) */
#define COMFORT_NOISE 0.02 /* audio level of comfort noise (relative to ISDN level) */
static sample_t ramp_up[256], ramp_down[256];
@ -147,7 +146,7 @@ void dsp_init(void)
int i;
double s;
LOGP(DDSP, LOGL_DEBUG, "Generating sine table for SAT signal.\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for SAT signal.\n");
for (i = 0; i < 65536; i++) {
s = sin((double)i / 65536.0 * 2.0 * PI);
dsp_sine_sat[i] = s * ((!tacs) ? AMPS_SAT_DEVIATION : TACS_SAT_DEVIATION);
@ -163,8 +162,6 @@ void dsp_init(void)
}
dsp_sync_check[0x712] = 0x00; /* no bit error */
dsp_sync_check[0x0ed] = 0x80; /* no bit error */
compandor_init();
}
static void dsp_init_ramp(amps_t *amps)
@ -172,7 +169,7 @@ static void dsp_init_ramp(amps_t *amps)
double c;
int i;
LOGP(DDSP, LOGL_DEBUG, "Generating smooth ramp table.\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Generating smooth ramp table.\n");
for (i = 0; i < 256; i++) {
c = cos((double)i / 256.0 * PI);
#if 0
@ -197,9 +194,9 @@ int dsp_init_sender(amps_t *amps, int tolerant)
int half;
/* attack (3ms) and recovery time (13.5ms) according to amps specs */
setup_compandor(&amps->cstate, 8000, 3.0, 13.5);
init_compandor(&amps->cstate, 8000, 3.0, 13.5);
LOGP_CHAN(DDSP, LOGL_DEBUG, "Init DSP for transceiver.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for transceiver.\n");
/* set modulation parameters */
sender_set_fm(&amps->sender,
@ -209,18 +206,18 @@ int dsp_init_sender(amps_t *amps, int tolerant)
(!tacs) ? AMPS_MAX_DISPLAY : TACS_MAX_DISPLAY);
if (amps->sender.samplerate < 96000) {
LOGP(DDSP, LOGL_ERROR, "Sample rate must be at least 96000 Hz to process FSK and SAT signals.\n");
PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 96000 Hz to process FSK and SAT signals.\n");
return -EINVAL;
}
amps->fsk_bitduration = (double)amps->sender.samplerate / (double)((!tacs) ? AMPS_BITRATE : TACS_BITRATE);
amps->fsk_bitstep = 1.0 / amps->fsk_bitduration;
LOGP(DDSP, LOGL_DEBUG, "Use %.4f samples for full bit duration @ %d.\n", amps->fsk_bitduration, amps->sender.samplerate);
PDEBUG(DDSP, DEBUG_DEBUG, "Use %.4f samples for full bit duration @ %d.\n", amps->fsk_bitduration, amps->sender.samplerate);
amps->fsk_tx_buffer_size = amps->fsk_bitduration + 10; /* 10 extra to avoid overflow due to rounding */
spl = calloc(sizeof(*spl), amps->fsk_tx_buffer_size);
if (!spl) {
LOGP(DDSP, LOGL_ERROR, "No memory!\n");
PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n");
rc = -ENOMEM;
goto error;
}
@ -231,12 +228,12 @@ int dsp_init_sender(amps_t *amps, int tolerant)
amps->fsk_rx_window_begin = half >> 1;
amps->fsk_rx_window_half = half;
amps->fsk_rx_window_end = amps->fsk_rx_window_length - (half >> 1);
LOGP(DDSP, LOGL_DEBUG, "Bit window length: %d\n", amps->fsk_rx_window_length);
LOGP(DDSP, LOGL_DEBUG, " -> Samples in window to analyse level left of edge: %d..%d\n", amps->fsk_rx_window_begin, amps->fsk_rx_window_half - 1);
LOGP(DDSP, LOGL_DEBUG, " -> Samples in window to analyse level right of edge: %d..%d\n", amps->fsk_rx_window_half, amps->fsk_rx_window_end - 1);
PDEBUG(DDSP, DEBUG_DEBUG, "Bit window length: %d\n", amps->fsk_rx_window_length);
PDEBUG(DDSP, DEBUG_DEBUG, " -> Samples in window to analyse level left of edge: %d..%d\n", amps->fsk_rx_window_begin, amps->fsk_rx_window_half - 1);
PDEBUG(DDSP, DEBUG_DEBUG, " -> Samples in window to analyse level right of edge: %d..%d\n", amps->fsk_rx_window_half, amps->fsk_rx_window_end - 1);
spl = calloc(sizeof(*amps->fsk_rx_window), amps->fsk_rx_window_length);
if (!spl) {
LOGP(DDSP, LOGL_ERROR, "No memory!\n");
PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n");
rc = -ENOMEM;
goto error;
}
@ -253,10 +250,9 @@ int dsp_init_sender(amps_t *amps, int tolerant)
amps->sat_samples = (int)((double)amps->sender.samplerate * (1.0 / (SAT_BANDWIDTH / 2.0)) + 0.5);
spl = calloc(sizeof(*spl), amps->sat_samples);
if (!spl) {
LOGP(DDSP, LOGL_ERROR, "No memory!\n");
PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n");
return -ENOMEM;
}
LOGP(DDSP, LOGL_DEBUG, "Sat detection interval is %d ms.\n", amps->sat_samples * 1000 / amps->sender.samplerate);
amps->sat_filter_spl = spl;
/* count SAT tones */
@ -290,7 +286,7 @@ error:
/* Cleanup transceiver instance. */
void dsp_cleanup_sender(amps_t *amps)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "Cleanup DSP for treansceiver.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for treansceiver.\n");
if (amps->fsk_tx_buffer)
free(amps->fsk_tx_buffer);
@ -403,8 +399,8 @@ again:
rc = amps_encode_frame_fvc(amps, amps->fsk_tx_frame);
else
rc = amps_encode_frame_focc(amps, amps->fsk_tx_frame);
/* check if we have no bit string (change to tx audio / silence)
* we may not store fsk_tx_buffer_pos, because is was reset on a mode change */
/* check if we have not bit string (change to tx audio)
* we may not store fsk_tx_buffer_pos, because is was reset on a mode achange */
if (rc)
return count;
amps->fsk_tx_frame_pos = 0;
@ -477,7 +473,7 @@ static void sat_encode(amps_t *amps, sample_t *samples, int length)
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length)
{
amps_t *amps = (amps_t *) sender;
int count, input_num;
int count;
again:
switch (amps->dsp_mode) {
@ -487,24 +483,11 @@ again:
break;
case DSP_MODE_AUDIO_RX_AUDIO_TX:
memset(power, 1, length);
input_num = samplerate_upsample_input_num(&sender->srstate, length);
{
int16_t spl[input_num];
jitter_load_samples(&sender->dejitter, (uint8_t *)spl, input_num, sizeof(*spl), jitter_conceal_s16, NULL);
int16_to_samples_speech(samples, spl, input_num);
}
compress_audio(&amps->cstate, samples, input_num);
samplerate_upsample(&sender->srstate, samples, input_num, samples, length);
jitter_load(&amps->sender.dejitter, samples, length);
/* pre-emphasis */
if (amps->pre_emphasis)
pre_emphasis(&amps->estate, samples, length);
/* encode SAT during call */
sat_encode(amps, samples, length);
break;
case DSP_MODE_AUDIO_RX_SILENCE_TX:
memset(power, 1, length);
memset(samples, 0, sizeof(*samples) * length);
/* encode SAT while waiting for alert response or answer */
/* encode sat */
sat_encode(amps, samples, length);
break;
case DSP_MODE_AUDIO_RX_FRAME_TX:
@ -513,7 +496,6 @@ again:
* stopped, process again for rest of stream. */
count = fsk_frame(amps, samples, length);
memset(power, 1, count);
// no SAT during frame transmission, according to specs
samples += count;
power += count;
length -= count;
@ -776,7 +758,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
/* debug SAT */
if (++amps->sat_print == SAT_PRINT) {
LOGP_CHAN(DDSP, LOGL_NOTICE, "SAT level %.2f%% quality %.0f%%\n", sat_level * 100.0, sat_quality * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", sat_level * 100.0, sat_quality * 100.0);
amps->sat_print = 0;
}
@ -785,8 +767,8 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
display_measurements_update(amps->dmp_sat_quality, sat_quality * 100.0, 0.0);
/* debug signaling tone */
if (amps->sender.loopback || loglevel == LOGL_DEBUG) {
LOGP_CHAN(DDSP, loglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", sig_level * 100.0, sig_quality * 100.0);
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", sig_level * 100.0, sig_quality * 100.0);
}
/* mute if SAT quality or level is below threshold */
@ -802,7 +784,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
if (amps->sat_detect_count == SAT_DETECT_COUNT) {
amps->sat_detected = 1;
amps->sat_detect_count = 0;
LOGP_CHAN(DDSP, LOGL_DEBUG, "SAT signal detected with level=%.0f%%, quality=%.0f%%.\n", sat_level * 100.0, sat_quality * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT signal detected with level=%.0f%%, quality=%.0f%%.\n", sat_level * 100.0, sat_quality * 100.0);
amps_rx_sat(amps, 1, sat_quality);
}
} else
@ -813,7 +795,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
if (amps->sat_detect_count == SAT_LOST_COUNT) {
amps->sat_detected = 0;
amps->sat_detect_count = 0;
LOGP_CHAN(DDSP, LOGL_DEBUG, "SAT signal lost.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT signal lost.\n");
amps_rx_sat(amps, 0, 0.0);
}
} else
@ -827,7 +809,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
if (amps->sig_detect_count == SIG_DETECT_COUNT) {
amps->sig_detected = 1;
amps->sig_detect_count = 0;
LOGP_CHAN(DDSP, LOGL_DEBUG, "Signaling Tone detected with level=%.0f%%, quality=%.0f%%.\n", sig_level * 100.0, sig_quality * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signaling Tone detected with level=%.0f%%, quality=%.0f%%.\n", sig_level * 100.0, sig_quality * 100.0);
amps_rx_signaling_tone(amps, 1, sig_quality);
}
} else
@ -838,7 +820,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
if (amps->sig_detect_count == SIG_LOST_COUNT) {
amps->sig_detected = 0;
amps->sig_detect_count = 0;
LOGP_CHAN(DDSP, LOGL_DEBUG, "Signaling Tone lost.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signaling Tone lost.\n");
amps_rx_signaling_tone(amps, 0, 0.0);
}
} else
@ -849,7 +831,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
{
transaction_t *trans = amps->trans_list;
sample_t *spl, s;
sample_t *spl;
int max, pos;
int i;
@ -858,10 +840,7 @@ static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
spl = amps->sat_filter_spl;
pos = amps->sat_filter_pos;
for (i = 0; i < length; i++) {
/* unmute: use buffer, to delay audio, so we do not miss that chunk when SAT is detected */
s = spl[pos];
spl[pos++] = samples[i];
samples[i] = s;
if (pos == max) {
pos = 0;
sat_decode(amps, spl, max);
@ -915,7 +894,6 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double __at
break;
case DSP_MODE_AUDIO_RX_AUDIO_TX:
case DSP_MODE_AUDIO_RX_FRAME_TX:
case DSP_MODE_AUDIO_RX_SILENCE_TX:
sender_receive_audio(amps, samples, length);
break;
}
@ -924,7 +902,7 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double __at
/* Reset SAT detection states, so ongoing tone will be detected again. */
static void sat_reset(amps_t *amps, const char *reason)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "SAT detector reset: %s.\n", reason);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT detector reset: %s.\n", reason);
amps->sat_detected = 0;
amps->sat_detect_count = 0;
amps->sig_detected = 0;
@ -941,30 +919,25 @@ void amps_set_dsp_mode(amps_t *amps, enum dsp_mode mode, int frame_length)
if (mode == DSP_MODE_FRAME_RX_FRAME_TX) {
/* reset SAT detection */
sat_reset(amps, "Change to FOCC");
LOGP_CHAN(DDSP, LOGL_INFO, "Change mode to FOCC\n");
amps->tx_focc_debugged = 0;
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode to FOCC\n");
}
if (amps->dsp_mode == DSP_MODE_FRAME_RX_FRAME_TX
&& (mode == DSP_MODE_AUDIO_RX_AUDIO_TX || mode == DSP_MODE_AUDIO_RX_FRAME_TX || mode == DSP_MODE_AUDIO_RX_SILENCE_TX)) {
&& (mode == DSP_MODE_AUDIO_RX_AUDIO_TX || mode == DSP_MODE_AUDIO_RX_FRAME_TX)) {
/* reset SAT detection */
sat_reset(amps, "Change from FOCC to FVC");
LOGP_CHAN(DDSP, LOGL_INFO, "Change mode from FOCC to FVC\n");
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode from FOCC to FVC\n");
}
if (amps->dsp_mode == DSP_MODE_OFF
&& (mode == DSP_MODE_AUDIO_RX_AUDIO_TX || mode == DSP_MODE_AUDIO_RX_FRAME_TX || mode == DSP_MODE_AUDIO_RX_SILENCE_TX)) {
&& (mode == DSP_MODE_AUDIO_RX_AUDIO_TX || mode == DSP_MODE_AUDIO_RX_FRAME_TX)) {
/* reset SAT detection */
sat_reset(amps, "Enable FVC");
LOGP_CHAN(DDSP, LOGL_INFO, "Change mode from OFF to FVC\n");
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode from OFF to FVC\n");
}
if (mode == DSP_MODE_OFF) {
/* reset SAT detection */
sat_reset(amps, "Disable FVC");
LOGP_CHAN(DDSP, LOGL_INFO, "Change mode from FVC to OFF\n");
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode from FVC to OFF\n");
}
if (mode == DSP_MODE_AUDIO_RX_AUDIO_TX && amps->dsp_mode != mode)
jitter_reset(&amps->sender.dejitter);
LOGP_CHAN(DDSP, LOGL_DEBUG, "Reset FSK frame transmitter, due to setting dsp mode.\n");
amps->dsp_mode = mode;
if (frame_length)
@ -981,27 +954,3 @@ void amps_set_dsp_mode(amps_t *amps, enum dsp_mode mode, int frame_length)
amps->fsk_tx_frame_pos = 0;
}
/* Receive audio from call instance. */
void call_down_audio(void *decoder, void *decoder_priv, int callref, uint16_t sequence, uint8_t marker, uint32_t timestamp, uint32_t ssrc, uint8_t *payload, int payload_len)
{
sender_t *sender;
amps_t *amps;
for (sender = sender_head; sender; sender = sender->next) {
amps = (amps_t *) sender;
if (amps->trans_list && amps->trans_list->callref == callref)
break;
}
if (!sender)
return;
if (amps->dsp_mode == DSP_MODE_AUDIO_RX_AUDIO_TX) {
jitter_frame_t *jf;
jf = jitter_frame_alloc(decoder, decoder_priv, payload, payload_len, marker, sequence, timestamp, ssrc);
if (jf)
jitter_save(&amps->sender.dejitter, jf);
}
}
void call_down_clock(void) {}

View File

@ -1,153 +0,0 @@
/* AMPS ESN specification
*
* (C) 2023 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 <string.h>
#include <pthread.h>
#include <sys/time.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
#include <osmocom/cc/message.h>
#include "amps.h"
#include "esn.h"
const char *amps_manufacturer[256] = {
[129] = "Oki",
[130] = "Motorola, Inc.",
[131] = "E.F. Johnson",
[132] = "Hitachi",
[133] = "Fujitsu",
[134] = "Mitsubishi",
[135] = "NEC America, Inc.",
[136] = "Matsushita (Panasonic)",
[137] = "Harris",
[138] = "Toshiba",
[139] = "Kokusai",
[140] = "Clarion Company, Ltd.",
[141] = "GoldStar Products Co.,Ltd.",
[142] = "International Systcom (Novatel)",
[143] = "Ericsson, Inc.",
[144] = "Murata Machinery, Ltd.",
[145] = "DI-BAR Electronics, Inc.",
[146] = "Ericsson Inc. (formerly assigned to General Electric)",
[147] = "Gateway Telephone, Inc.",
[148] = "Robert Bosch Corporation (Blaupunkt)",
[149] = "Universal Cellular, Inc.",
[150] = "Alpine Electronics of America, Inc.",
[151] = "Verma Laboratories",
[152] = "Japan Radio Co.,Ltd.",
[153] = "CM Communications Incorporated",
[154] = "Sony Corporation (Japan)",
[155] = "Tama Denki Company, Ltd.",
[156] = "Mobira (Nokia-Kinex)",
[157] = "Ericsson GE Mobile Communications, Inc.",
[158] = "AT&T Technologies, Inc.",
[159] = "QUALCOMM, Incorporated",
[160] = "Hyundai",
[161] = "Satellite Technology Services, Inc.",
[162] = "Technophone Limited",
[163] = "Yupiteru Industries Company Ltd.",
[164] = "Hughes Network Systems",
[165] = "TMC Company Limited (Nokia)",
[166] = "Clarion Manufacturing Corporation of America",
[167] = "Mansoor Electronics Limited",
[168] = "Motorola International",
[169] = "Otron Corporation",
[170] = "Philips Telecom Equipment Corporation",
[171] = "Philips Circuit Assemblies",
[172] = "Uniden Corporation of America",
[173] = "Uniden Corporation - Japan",
[174] = "Shintom West Corporation of America",
[175] = "Tottori Sanyo Electric Co. Ltd.",
[176] = "Samsung Communications",
[177] = "INFA Telecom Canada, Inc.",
[178] = "Emptel Electronics Company Ltd.",
[179] = "**Unassigned**",
[180] = "ASCNet",
[181] = "Yaesu USA",
[182] = "Tecom Co. Ltd.",
[183] = "Omni Telecommunications, Inc. (formerly assigned to Valor Electronics, Inc.)",
[184] = "Royal Information Electronics Co. Ltd.",
[185] = "Tele Digital Development, Inc. (formerly assigned to Cumulus Corporation.)",
[186] = "DNC",
[187] = "**Unassigned**",
[188] = "Myday Technology, Ltd.",
[189] = "NEC America, Inc.",
[190] = "Kyocera Corporation",
[191] = "Digital Security Controls",
[192] = "CTCELL Digital, Inc.",
[193] = "Matsushita Communication Industrial Corporation of America",
[194] = "HS Electronics Corporation",
[195] = "Motorola, Inc.",
[196] = "Pacific Communication Sciences, Inc.",
[197] = "Maxon Systems, Inc., (London) Ltd.",
[198] = "Hongsheng Electronics Co., Ltd.",
[199] = "M/ACOM",
[200] = "CHANNLE LINK Incorporation",
[201] = "L.G. Information & Communications (formerly assigned to Goldstar Information & Communications, Ltd.)",
[202] = "Intel Corporation",
[203] = "Air Communications, Inc.",
[204] = "Ericsson GE Mobile Communications Inc.",
[205] = "Goldtron RF PTE Ltd.",
[206] = "Sierra Wireless Inc.",
[207] = "Mitsubishi International Corp.",
[208] = "JRC International, Inc.",
[209] = "Sapura Holdings SDN. BHD.",
[210] = "Inex Technologies, Inc.",
[211] = "Sony Electronics (U.S.A.)",
[212] = "Motorola, Inc.",
[213] = "Motorola, Inc.",
[214] = "Philips Semiconductors",
[215] = "Carillon Corp.",
[216] = "Nippondenso America, Inc.",
[217] = "International Business Machines Corporation",
[218] = "Nokia (Hong Kong)",
[219] = "Nokia (TMC Co. Ltd.)",
[220] = "TEMIC",
[221] = "Northern Telecom",
[222] = "Telrad Telecommunications Ltd.",
[223] = "Motorola, Inc.",
[224] = "Motorola, Inc.",
[225] = "Telital s.r.l.",
[226] = "Nokia (Manau, Brazil)",
[227] = "Stanilite Pacific",
[228] = "Philips Consumer Communications",
[229] = "NEC America, Inc.",
[230] = "TELLULAR Corporation",
[231] = "Ericsson Inc.",
};
const char *esn_to_string(uint32_t esn)
{
uint8_t mfr;
uint32_t serial;
static char esn_string[256];
amps_decode_esn(esn, &mfr, &serial);
if (amps_manufacturer[mfr])
snprintf(esn_string, sizeof(esn_string), "0x%08x or %d-%06d (%s)", esn, mfr, serial, amps_manufacturer[mfr]);
else
snprintf(esn_string, sizeof(esn_string), "0x%08x or %d-%06d", esn, mfr, serial);
return esn_string;
}

View File

@ -1,3 +0,0 @@
const char *esn_to_string(uint32_t esn);

View File

@ -27,8 +27,7 @@
#include <math.h>
#include <inttypes.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libmobile/get_time.h"
#include "../libdebug/debug.h"
#include "amps.h"
#include "dsp.h"
#include "frame.h"
@ -2708,7 +2707,7 @@ static uint64_t amps_encode_word(frame_t *frame, struct def_word *w, int debug)
int i, t4 = 0;
#ifdef DEBUG_ALL_MESSAGES
debug = 1;
debug=1;
#endif
memset(spaces, ' ', ie_desc_max_len);
@ -2719,8 +2718,7 @@ static uint64_t amps_encode_word(frame_t *frame, struct def_word *w, int debug)
for (i = 0; w->ie[i].name; i++)
sum_bits += w->ie[i].bits;
if (debug)
LOGP(DFRAME, LOGL_INFO, "Transmit: %s\n", w->name);
PDEBUG(DFRAME, (debug >= 0) ? DEBUG_INFO : DEBUG_DEBUG, "Transmit: %s\n", w->name);
word = 0;
for (i = 0; w->ie[i].name; i++) {
bits = w->ie[i].bits;
@ -2729,26 +2727,26 @@ static uint64_t amps_encode_word(frame_t *frame, struct def_word *w, int debug)
else
value = frame->ie[w->ie[i].ie];
word = (word << bits) | (value & cut_bits[bits]);
if (debug) {
if (debug >= 0) {
if (amps_ie_desc[w->ie[i].ie].decoder)
LOGP(DFRAME, LOGL_DEBUG, " %s%s: %" PRIu64 " = %s (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].decoder(value), amps_ie_desc[w->ie[i].ie].desc);
PDEBUG(DFRAME, DEBUG_DEBUG, " %s%s: %" PRIu64 " = %s (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].decoder(value), amps_ie_desc[w->ie[i].ie].desc);
else
LOGP(DFRAME, LOGL_DEBUG, " %s%s: %" PRIu64 " (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].desc);
PDEBUG(DFRAME, DEBUG_DEBUG, " %s%s: %" PRIu64 " (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].desc);
}
/* show result for 3 IEs of table 4 */
if (w->ie[i].ie == AMPS_IE_LOCAL_MSG_TYPE || w->ie[i].ie == AMPS_IE_ORDQ || w->ie[i].ie == AMPS_IE_ORDER)
t4++;
if (t4 == 3) {
t4 = 0;
if (debug)
LOGP(DFRAME, LOGL_DEBUG, " %s--> %s\n", spaces, amps_table4_name(frame->ie[AMPS_IE_LOCAL_MSG_TYPE], frame->ie[AMPS_IE_ORDQ], frame->ie[AMPS_IE_ORDER]));
if (debug >= 0)
PDEBUG(DFRAME, DEBUG_DEBUG, " %s--> %s\n", spaces, amps_table4_name(frame->ie[AMPS_IE_LOCAL_MSG_TYPE], frame->ie[AMPS_IE_ORDQ], frame->ie[AMPS_IE_ORDER]));
}
}
return word;
}
static uint64_t amps_encode_control_filler(amps_t *amps, uint8_t dcc, uint8_t cmac, uint8_t sdcc1, uint8_t sdcc2, uint8_t wfom, int debug)
static uint64_t amps_encode_control_filler(amps_t *amps, uint8_t dcc, uint8_t cmac, uint8_t sdcc1, uint8_t sdcc2, uint8_t wfom)
{
frame_t frame;
@ -2769,10 +2767,10 @@ static uint64_t amps_encode_control_filler(amps_t *amps, uint8_t dcc, uint8_t cm
} else
frame.ie[AMPS_IE_1111] = 15;
frame.ie[AMPS_IE_OHD] = 1;
return amps_encode_word(&frame, &control_filler, debug);
return amps_encode_word(&frame, &control_filler, -1);
}
uint64_t amps_encode_word1_system(uint8_t dcc, uint16_t sid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc, int debug)
uint64_t amps_encode_word1_system(uint8_t dcc, uint16_t sid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc)
{
frame_t frame;
@ -2785,10 +2783,10 @@ uint64_t amps_encode_word1_system(uint8_t dcc, uint16_t sid1, uint8_t ep, uint8_
frame.ie[AMPS_IE_PCI] = pci;
frame.ie[AMPS_IE_NAWC] = nawc;
frame.ie[AMPS_IE_OHD] = 6;
return amps_encode_word(&frame, &amps_word1_system_parameter_overhead, debug);
return amps_encode_word(&frame, &amps_word1_system_parameter_overhead, -1);
}
uint64_t tacs_encode_word1_system(uint8_t dcc, uint16_t aid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc, int debug)
uint64_t tacs_encode_word1_system(uint8_t dcc, uint16_t aid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc)
{
frame_t frame;
@ -2801,10 +2799,10 @@ uint64_t tacs_encode_word1_system(uint8_t dcc, uint16_t aid1, uint8_t ep, uint8_
frame.ie[AMPS_IE_PCI] = pci;
frame.ie[AMPS_IE_NAWC] = nawc;
frame.ie[AMPS_IE_OHD] = 6;
return amps_encode_word(&frame, &tacs_word1_system_parameter_overhead, debug);
return amps_encode_word(&frame, &tacs_word1_system_parameter_overhead, -1);
}
uint64_t amps_encode_word2_system(uint8_t dcc, uint8_t s, uint8_t e, uint8_t regh, uint8_t regr, uint8_t dtx, uint8_t n_1, uint8_t rcf, uint8_t cpa, uint8_t cmax_1, uint8_t end, int debug)
uint64_t amps_encode_word2_system(uint8_t dcc, uint8_t s, uint8_t e, uint8_t regh, uint8_t regr, uint8_t dtx, uint8_t n_1, uint8_t rcf, uint8_t cpa, uint8_t cmax_1, uint8_t end)
{
frame_t frame;
@ -2822,10 +2820,10 @@ uint64_t amps_encode_word2_system(uint8_t dcc, uint8_t s, uint8_t e, uint8_t reg
frame.ie[AMPS_IE_CMAX_1] = cmax_1;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 7;
return amps_encode_word(&frame, &word2_system_parameter_overhead, debug);
return amps_encode_word(&frame, &word2_system_parameter_overhead, -1);
}
uint64_t amps_encode_registration_id(uint8_t dcc, uint32_t regid, uint8_t end, int debug)
uint64_t amps_encode_registration_id(uint8_t dcc, uint32_t regid, uint8_t end)
{
frame_t frame;
@ -2835,10 +2833,10 @@ uint64_t amps_encode_registration_id(uint8_t dcc, uint32_t regid, uint8_t end, i
frame.ie[AMPS_IE_REGID] = regid;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 0;
return amps_encode_word(&frame, &registration_id, debug);
return amps_encode_word(&frame, &registration_id, -1);
}
uint64_t amps_encode_registration_increment(uint8_t dcc, uint16_t regincr, uint8_t end, int debug)
uint64_t amps_encode_registration_increment(uint8_t dcc, uint16_t regincr, uint8_t end)
{
frame_t frame;
@ -2849,10 +2847,10 @@ uint64_t amps_encode_registration_increment(uint8_t dcc, uint16_t regincr, uint8
frame.ie[AMPS_IE_REGINCR] = regincr;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 4;
return amps_encode_word(&frame, &registration_increment_global_action, debug);
return amps_encode_word(&frame, &registration_increment_global_action, -1);
}
uint64_t amps_encode_location_area(uint8_t dcc, uint8_t pureg, uint8_t pdreg, uint8_t lreg, uint16_t locaid, uint8_t end, int debug)
uint64_t amps_encode_location_area(uint8_t dcc, uint8_t pureg, uint8_t pdreg, uint8_t lreg, uint16_t locaid, uint8_t end)
{
frame_t frame;
@ -2866,10 +2864,10 @@ uint64_t amps_encode_location_area(uint8_t dcc, uint8_t pureg, uint8_t pdreg, ui
frame.ie[AMPS_IE_LOCAID] = locaid;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 4;
return amps_encode_word(&frame, &location_area_global_action, debug);
return amps_encode_word(&frame, &location_area_global_action, -1);
}
uint64_t amps_encode_new_access_channel_set(uint8_t dcc, uint16_t newacc, uint8_t end, int debug)
uint64_t amps_encode_new_access_channel_set(uint8_t dcc, uint16_t newacc, uint8_t end)
{
frame_t frame;
@ -2880,10 +2878,10 @@ uint64_t amps_encode_new_access_channel_set(uint8_t dcc, uint16_t newacc, uint8_
frame.ie[AMPS_IE_NEWACC] = newacc;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 4;
return amps_encode_word(&frame, &new_access_channel_set_global_action, debug);
return amps_encode_word(&frame, &new_access_channel_set_global_action, -1);
}
uint64_t amps_encode_overload_control(uint8_t dcc, uint8_t *olc, uint8_t end, int debug)
uint64_t amps_encode_overload_control(uint8_t dcc, uint8_t *olc, uint8_t end)
{
frame_t frame;
@ -2909,10 +2907,10 @@ uint64_t amps_encode_overload_control(uint8_t dcc, uint8_t *olc, uint8_t end, in
frame.ie[AMPS_IE_OLC_15] = olc[15];
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 4;
return amps_encode_word(&frame, &overload_control_global_action, debug);
return amps_encode_word(&frame, &overload_control_global_action, -1);
}
uint64_t amps_encode_access_type(uint8_t dcc, uint8_t bis, uint8_t pci_home, uint8_t pci_roam, uint8_t bspc, uint8_t bscap, uint8_t end, int debug)
uint64_t amps_encode_access_type(uint8_t dcc, uint8_t bis, uint8_t pci_home, uint8_t pci_roam, uint8_t bspc, uint8_t bscap, uint8_t end)
{
frame_t frame;
@ -2927,10 +2925,10 @@ uint64_t amps_encode_access_type(uint8_t dcc, uint8_t bis, uint8_t pci_home, uin
frame.ie[AMPS_IE_BSCAP] = bscap;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 4;
return amps_encode_word(&frame, &access_type_parameters_global_action, debug);
return amps_encode_word(&frame, &access_type_parameters_global_action, -1);
}
uint64_t amps_encode_access_attempt(uint8_t dcc, uint8_t maxbusy_pgr, uint8_t maxsztr_pgr, uint8_t maxbusy_other, uint8_t maxsztr_other, uint8_t end, int debug)
uint64_t amps_encode_access_attempt(uint8_t dcc, uint8_t maxbusy_pgr, uint8_t maxsztr_pgr, uint8_t maxbusy_other, uint8_t maxsztr_other, uint8_t end)
{
frame_t frame;
@ -2944,7 +2942,7 @@ uint64_t amps_encode_access_attempt(uint8_t dcc, uint8_t maxbusy_pgr, uint8_t ma
frame.ie[AMPS_IE_MAXSZTR_OTHER] = maxsztr_other;
frame.ie[AMPS_IE_END] = end;
frame.ie[AMPS_IE_OHD] = 4;
return amps_encode_word(&frame, &access_attempt_parameters_global_action, debug);
return amps_encode_word(&frame, &access_attempt_parameters_global_action, -1);
}
static uint64_t amps_encode_word1_abbreviated_address_word(uint8_t dcc, uint32_t min1, int multiple)
@ -2958,7 +2956,7 @@ static uint64_t amps_encode_word1_abbreviated_address_word(uint8_t dcc, uint32_t
frame.ie[AMPS_IE_T1T2] = 0;
frame.ie[AMPS_IE_DCC] = dcc;
frame.ie[AMPS_IE_MIN1] = min1;
return amps_encode_word(&frame, &word1_abbreviated_address_word, 1);
return amps_encode_word(&frame, &word1_abbreviated_address_word, DEBUG_INFO);
}
static uint64_t amps_encode_word2_extended_address_word_a(uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order)
@ -2973,7 +2971,7 @@ static uint64_t amps_encode_word2_extended_address_word_a(uint16_t min2, uint8_t
frame.ie[AMPS_IE_LOCAL_MSG_TYPE] = msg_type;
frame.ie[AMPS_IE_ORDQ] = ordq;
frame.ie[AMPS_IE_ORDER] = order;
return amps_encode_word(&frame, &word2_extended_address_word_a, 1);
return amps_encode_word(&frame, &word2_extended_address_word_a, DEBUG_INFO);
}
static uint64_t amps_encode_word2_extended_address_word_b(uint8_t scc, uint16_t min2, uint8_t vmac, uint16_t chan)
@ -2986,7 +2984,7 @@ static uint64_t amps_encode_word2_extended_address_word_b(uint8_t scc, uint16_t
frame.ie[AMPS_IE_MIN2] = min2;
frame.ie[AMPS_IE_VMAC] = vmac;
frame.ie[AMPS_IE_CHAN] = chan;
return amps_encode_word(&frame, &word2_extended_address_word_b, 1);
return amps_encode_word(&frame, &word2_extended_address_word_b, DEBUG_INFO);
}
static uint64_t amps_encode_mobile_station_control_message_word1_a(uint8_t pscc, uint8_t msg_type, uint8_t ordq, uint8_t order)
@ -3001,7 +2999,7 @@ static uint64_t amps_encode_mobile_station_control_message_word1_a(uint8_t pscc,
frame.ie[AMPS_IE_LOCAL_MSG_TYPE] = msg_type;
frame.ie[AMPS_IE_ORDQ] = ordq;
frame.ie[AMPS_IE_ORDER] = order;
return amps_encode_word(&frame, &mobile_station_control_message_word1_a, 1);
return amps_encode_word(&frame, &mobile_station_control_message_word1_a, DEBUG_INFO);
}
static uint64_t amps_encode_mobile_station_control_message_word1_b(uint8_t scc, uint8_t pscc, uint8_t dtx, uint8_t pvi, uint8_t mem, uint8_t vmac, uint16_t chan)
@ -3018,38 +3016,7 @@ static uint64_t amps_encode_mobile_station_control_message_word1_b(uint8_t scc,
frame.ie[AMPS_IE_MEM] = mem;
frame.ie[AMPS_IE_VMAC] = vmac;
frame.ie[AMPS_IE_CHAN] = chan;
return amps_encode_word(&frame, &mobile_station_control_message_word1_b, 1);
}
static uint64_t amps_encode_word2_first_alert_with_info_word(uint8_t rl_w, uint8_t signal, uint8_t cpn_rl, uint8_t pi, uint8_t si)
{
frame_t frame;
memset(&frame, 0, sizeof(frame));
frame.ie[AMPS_IE_T1T2] = 1;
frame.ie[AMPS_IE_RL_W] = rl_w;
frame.ie[AMPS_IE_SIGNAL] = signal;
frame.ie[AMPS_IE_CPN_RL] = cpn_rl;
frame.ie[AMPS_IE_PI] = pi;
frame.ie[AMPS_IE_SI] = si;
return amps_encode_word(&frame, &word2_first_alert_with_info_word, 1);
}
static uint64_t amps_encode_wordn_n_minus_1th_alert_with_info_word(const char *character)
{
frame_t frame;
memset(&frame, 0, sizeof(frame));
frame.ie[AMPS_IE_T1T2] = 1;
if (character[0]) {
frame.ie[AMPS_IE_CHARACTER_1] = character[0];
if (character[1]) {
frame.ie[AMPS_IE_CHARACTER_2] = character[1];
if (character[2])
frame.ie[AMPS_IE_CHARACTER_3] = character[2];
}
}
return amps_encode_word(&frame, &wordn_n_minus_1th_alert_with_info_word, 1);
return amps_encode_word(&frame, &mobile_station_control_message_word1_b, DEBUG_INFO);
}
/* decoder function of a word */
@ -3071,22 +3038,22 @@ static frame_t *amps_decode_word(uint64_t word, struct def_word *w)
for (i = 0; w->ie[i].name; i++)
bits_left += w->ie[i].bits;
LOGP(DFRAME, LOGL_INFO, "Received: %s\n", w->name);
PDEBUG(DFRAME, DEBUG_INFO, "Received: %s\n", w->name);
for (i = 0; w->ie[i].name; i++) {
bits = w->ie[i].bits;
bits_left -= bits;
value = (word >> bits_left) & cut_bits[bits];
frame.ie[w->ie[i].ie] = value;
if (amps_ie_desc[w->ie[i].ie].decoder)
LOGP(DFRAME, LOGL_DEBUG, " %s%s: %" PRIu64 " = %s (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].decoder(value), amps_ie_desc[w->ie[i].ie].desc);
PDEBUG(DFRAME, DEBUG_DEBUG, " %s%s: %" PRIu64 " = %s (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].decoder(value), amps_ie_desc[w->ie[i].ie].desc);
else
LOGP(DFRAME, LOGL_DEBUG, " %s%s: %" PRIu64 " (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].desc);
PDEBUG(DFRAME, DEBUG_DEBUG, " %s%s: %" PRIu64 " (%s)\n", spaces + strlen(w->ie[i].name), w->ie[i].name, value, amps_ie_desc[w->ie[i].ie].desc);
/* show result for 3 IEs of table 4 */
if (w->ie[i].ie == AMPS_IE_LOCAL_MSG_TYPE || w->ie[i].ie == AMPS_IE_ORDQ || w->ie[i].ie == AMPS_IE_ORDER)
t4++;
if (t4 == 3) {
t4 = 0;
LOGP(DFRAME, LOGL_DEBUG, " %s--> %s\n", spaces, amps_table4_name(frame.ie[AMPS_IE_LOCAL_MSG_TYPE], frame.ie[AMPS_IE_ORDQ], frame.ie[AMPS_IE_ORDER]));
PDEBUG(DFRAME, DEBUG_DEBUG, " %s--> %s\n", spaces, amps_table4_name(frame.ie[AMPS_IE_LOCAL_MSG_TYPE], frame.ie[AMPS_IE_ORDQ], frame.ie[AMPS_IE_ORDER]));
}
}
@ -3104,7 +3071,7 @@ static void amps_decode_word_focc(amps_t *amps, uint64_t word)
/* control message */
if (t1t2 != 3) {
LOGP_CHAN(DFRAME, LOGL_INFO, "Received Mobile Station Control Message (T1T2 = %d)\n", t1t2);
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "Received Mobile Station Control Message (T1T2 = %d)\n", t1t2);
if (t1t2 == 1)
amps->rx_focc_word_count = 1;
if (t1t2 == 0 || t1t2 == 1) {
@ -3121,7 +3088,7 @@ static void amps_decode_word_focc(amps_t *amps, uint64_t word)
w = &word2_extended_address_word_b;
goto decode;
}
LOGP_CHAN(DFRAME, LOGL_INFO, "Decoding of more than 2 Control messages not supported\n");
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "Decoding of more than 2 Control messages not supported\n");
}
return;
}
@ -3189,14 +3156,14 @@ static void amps_decode_word_focc(amps_t *amps, uint64_t word)
decode:
if (!w) {
LOGP_CHAN(DFRAME, LOGL_INFO, "Received Illegal Overhead Message\n");
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "Received Illegal Overhead Message\n");
return;
}
frame = amps_decode_word(word, w);
/* show control filler delay */
if (amps->sender.loopback && ohd == 1)
LOGP_CHAN(DDSP, LOGL_NOTICE, "Round trip delay is %.3f seconds\n", amps->when_received - amps->when_transmitted[frame->ie[AMPS_IE_1111]]);
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Round trip delay is %.3f seconds\n", amps->when_received - amps->when_transmitted[frame->ie[AMPS_IE_1111]]);
}
/* get word from data bits and call decoder function
@ -3215,24 +3182,24 @@ static int amps_decode_word_recc(amps_t *amps, uint64_t word, int first)
amps->rx_recc_word_count = 0;
amps->rx_recc_nawc = nawc;
if (f == 0) {
LOGP_CHAN(DFRAME, LOGL_NOTICE, "Received first word, but F bit is not set.\n");
PDEBUG_CHAN(DFRAME, DEBUG_NOTICE, "Received first word, but F bit is not set.\n");
return 0;
}
} else {
if (f == 1) {
LOGP_CHAN(DFRAME, LOGL_NOTICE, "Received additional word, but F bit is set.\n");
PDEBUG_CHAN(DFRAME, DEBUG_NOTICE, "Received additional word, but F bit is set.\n");
return 0;
}
amps->rx_recc_nawc--;
if (amps->rx_recc_nawc != nawc) {
LOGP_CHAN(DFRAME, LOGL_NOTICE, "Received additional word with NAWC mismatch!\n");
PDEBUG_CHAN(DFRAME, DEBUG_NOTICE, "Received additional word with NAWC mismatch!\n");
}
}
msg_count = amps->rx_recc_word_count;
if (msg_count == 8) {
LOGP_CHAN(DFRAME, LOGL_NOTICE, "Received too many words.\n");
PDEBUG_CHAN(DFRAME, DEBUG_NOTICE, "Received too many words.\n");
return 0;
}
@ -3269,7 +3236,7 @@ static int amps_decode_word_recc(amps_t *amps, uint64_t word, int first)
if (!w) {
LOGP_CHAN(DFRAME, LOGL_INFO, "Received Illegal RECC Message\n");
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "Received Illegal RECC Message\n");
goto done;
}
@ -3334,7 +3301,7 @@ static int amps_decode_word_recc(amps_t *amps, uint64_t word, int first)
amps->rx_recc_dialing[31] = digit2number[frame->ie[AMPS_IE_DIGIT_32]];
}
LOGP_CHAN(DFRAME, LOGL_INFO, "expecting %d more word(s) to come\n", amps->rx_recc_nawc);
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "expecting %d more word(s) to come\n", amps->rx_recc_nawc);
if (msg_count >= 3 && amps->rx_recc_nawc == 0) {
/* if no digit messages are present, send NULL as dial string (paging reply) */
@ -3378,7 +3345,7 @@ static void amps_encode_focc_bits(uint64_t word_a, uint64_t word_b, char *bits)
memcpy(bits + 0, dotting, 10);
bits[10] = 'i';
memcpy(bits + 11, sync_word, 11);
strcpy(bits + 11, sync_word);
bits[22] = 'i';
k = 23;
for (i = 0; i < 5; i++) {
@ -3398,22 +3365,22 @@ static void amps_encode_focc_bits(uint64_t word_a, uint64_t word_b, char *bits)
if (k != 463)
abort();
bits[k] = '\0';
bits[463] = '\0';
#ifdef BIT_DEBUGGING
if (loglevel == LOGL_DEBUG) {
if (debuglevel == DEBUG_DEBUG) {
char text[64];
strncpy(text, bits, 23);
text[23] = '\0';
LOGP(DFRAME, LOGL_INFO, "TX FOCC: %s\n", text);
#ifdef BIT_DEBUGGING
PDEBUG(DFRAME, DEBUG_INFO, "TX FOCC: %s\n", text);
for (i = 0; i < 10; i++) {
strncpy(text, bits + 23 + i * 44, 44);
text[44] = '\0';
LOGP(DFRAME, LOGL_DEBUG, " word %c - %s\n", (i & 1) ? 'b' : 'a', text);
PDEBUG(DFRAME, DEBUG_DEBUG, " word %c - %s\n", (i & 1) ? 'b' : 'a', text);
}
}
#endif
}
}
static void amps_encode_fvc_bits(uint64_t word_a, char *bits)
@ -3430,19 +3397,19 @@ static void amps_encode_fvc_bits(uint64_t word_a, char *bits)
memcpy(bits + k, dotting, 37);
k += 37;
}
memcpy(bits + k, sync_word, 11);
strcpy(bits + k, sync_word);
k += 11;
for (j = 39; j >= 0; j--)
bits[k++] = ((word_a >> j) & 1) + '0';
}
if (k != 1032)
abort();
bits[k] = '\0';
bits[1032] = '\0';
#ifdef BIT_DEBUGGING
if (loglevel == LOGL_DEBUG) {
LOGP(DFRAME, LOGL_INFO, "TX FVC: %s\n", bits);
if (debuglevel == DEBUG_DEBUG) {
PDEBUG(DFRAME, DEBUG_INFO, "TX FVC: %s\n", bits);
}
#endif
}
@ -3450,14 +3417,13 @@ static void amps_encode_fvc_bits(uint64_t word_a, char *bits)
int amps_encode_frame_focc(amps_t *amps, char *bits)
{
uint64_t word;
int debug = !amps->tx_focc_debugged;
/* init overhead train */
if (amps->tx_focc_frame_count == 0)
prepare_sysinfo(&amps->si);
/* send overhead train */
if (amps->si.num) {
word = get_sysinfo(&amps->si, debug);
word = get_sysinfo(&amps->si);
if (++amps->tx_focc_frame_count >= amps->si.overhead_repeat)
amps->tx_focc_frame_count = 0;
goto send;
@ -3508,12 +3474,9 @@ int amps_encode_frame_focc(amps_t *amps, char *bits)
}
/* send filler */
word = amps_encode_control_filler(amps, amps->si.dcc, amps->si.filler.cmac, amps->si.filler.sdcc1, amps->si.filler.sdcc2, amps->si.filler.wfom, debug);
word = amps_encode_control_filler(amps, amps->si.dcc, amps->si.filler.cmac, amps->si.filler.sdcc1, amps->si.filler.sdcc2, amps->si.filler.wfom);
if (++amps->tx_focc_frame_count >= amps->si.overhead_repeat)
amps->tx_focc_frame_count = 0;
if (debug)
LOGP_CHAN(DFRAME, LOGL_INFO, "Subsequent system/filler frames are not show, to prevent flooding the output.\n");
amps->tx_focc_debugged = 1;
send:
amps_encode_focc_bits(word, word, bits);
@ -3534,16 +3497,7 @@ int amps_encode_frame_fvc(amps_t *amps, char *bits)
amps->tx_fvc_ordq = trans->ordq;
amps->tx_fvc_order = trans->order;
amps->tx_fvc_chan = trans->chan;
strncpy(amps->tx_fvc_callerid, trans->caller_id, sizeof(amps->tx_fvc_callerid) - 1);
amps->tx_fvc_callerid_signal = 1;
amps->tx_fvc_callerid_screen = 3;
if (trans->caller_id[0])
amps->tx_fvc_callerid_present = 0;
else
amps->tx_fvc_callerid_signal = 1;
amps->tx_fvc_send = 1;
amps->tx_fvc_word_count = 0;
amps->tx_fvc_word_repeat = 0;
}
/* on change of dsp mode */
if (amps->dsp_mode != DSP_MODE_AUDIO_RX_FRAME_TX)
@ -3552,32 +3506,11 @@ int amps_encode_frame_fvc(amps_t *amps, char *bits)
/* send scheduled mobile control message */
if (amps->tx_fvc_send) {
if (amps->tx_fvc_word_count == 0) {
if (amps->tx_fvc_chan)
word = amps_encode_mobile_station_control_message_word1_b(amps->sat, amps->sat, (amps->si.word2.dtx) ? 1 : 0, 0, 0, amps->si.vmac, amps->tx_fvc_chan);
else
word = amps_encode_mobile_station_control_message_word1_a(amps->sat, amps->tx_fvc_msg_type, amps->tx_fvc_ordq, amps->tx_fvc_order);
/* done, if we don't have ALERTING with info */
if (amps->tx_fvc_order != 17)
amps->tx_fvc_send = 0;
} else if (amps->tx_fvc_word_count == 1) {
int cpn_rl, rl_w;
/* number of characters */
cpn_rl = strlen(amps->tx_fvc_callerid);
/* number of frames that are required to hold number of characters */
rl_w = (cpn_rl + 2) / 3;
word = amps_encode_word2_first_alert_with_info_word(rl_w, amps->tx_fvc_callerid_signal, cpn_rl, amps->tx_fvc_callerid_present, amps->tx_fvc_callerid_screen);
if (cpn_rl == 0)
amps->tx_fvc_send = 0;
} else {
const char *callerid;
/* chunk of caller ID */
callerid = amps->tx_fvc_callerid + (amps->tx_fvc_word_count - 2) * 3;
word = amps_encode_wordn_n_minus_1th_alert_with_info_word(callerid);
if (strlen(callerid) <= 3)
amps->tx_fvc_send = 0;
}
amps->tx_fvc_word_count++;
amps->tx_fvc_send = 0;
if (amps->tx_fvc_chan)
word = amps_encode_mobile_station_control_message_word1_b(amps->sat, amps->sat, (amps->si.word2.dtx) ? 1 : 0, 0, 0, amps->si.vmac, amps->tx_fvc_chan);
else
word = amps_encode_mobile_station_control_message_word1_a(amps->sat, amps->tx_fvc_msg_type, amps->tx_fvc_ordq, amps->tx_fvc_order);
} else
return 1;
@ -3627,17 +3560,17 @@ static void amps_decode_bits_focc(amps_t *amps, const char *bits)
else
idle = 0;
LOGP_CHAN(DFRAME, LOGL_INFO, "RX FOCC: B/I = %s\n", (idle) ? "idle" : "busy");
if (loglevel == LOGL_DEBUG) {
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "RX FOCC: B/I = %s\n", (idle) ? "idle" : "busy");
if (debuglevel == DEBUG_DEBUG) {
char text[64];
for (i = 0; i < 10; i++) {
strncpy(text, bits + i * 44, 44);
text[44] = '\0';
if ((i & 1) == 0)
LOGP_CHAN(DFRAME, LOGL_DEBUG, " word a - %s%s\n", text, (crc_a_ok[i >> 1]) ? " ok" : " BAD CRC!");
PDEBUG_CHAN(DFRAME, DEBUG_DEBUG, " word a - %s%s\n", text, (crc_a_ok[i >> 1]) ? " ok" : " BAD CRC!");
else
LOGP_CHAN(DFRAME, LOGL_DEBUG, " word b - %s%s\n", text, (crc_b_ok[i >> 1]) ? " ok" : " BAD CRC!");
PDEBUG_CHAN(DFRAME, DEBUG_DEBUG, " word b - %s%s\n", text, (crc_b_ok[i >> 1]) ? " ok" : " BAD CRC!");
}
}
@ -3713,7 +3646,7 @@ static int amps_decode_bits_recc(amps_t *amps, const char *bits, int first)
crc_ok++;
}
if (crc_ok) {
LOGP_CHAN(DFRAME, LOGL_NOTICE, "Seems we RX FOCC frame due to loopback, ignoring!\n");
PDEBUG_CHAN(DFRAME, DEBUG_NOTICE, "Seems we RX FOCC frame due to loopback, ignoring!\n");
return 0;
}
bits_ -= 221;
@ -3725,24 +3658,24 @@ static int amps_decode_bits_recc(amps_t *amps, const char *bits, int first)
}
if (first) {
if (loglevel == LOGL_DEBUG || crc_ok_count > 0) {
LOGP_CHAN(DFRAME, LOGL_INFO, "RX RECC: DCC=%d (%d of 5 CRCs are ok)\n", dcc, crc_ok_count);
if (debuglevel == DEBUG_DEBUG || crc_ok_count > 0) {
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "RX RECC: DCC=%d (%d of 5 CRCs are ok)\n", dcc, crc_ok_count);
if (dcc != amps->si.dcc) {
LOGP(DFRAME, LOGL_INFO, "received DCC=%d mismatches the base station's DCC=%d\n", dcc, amps->si.dcc);
PDEBUG(DFRAME, DEBUG_INFO, "received DCC=%d mismatches the base station's DCC=%d\n", dcc, amps->si.dcc);
return 0;
}
}
} else {
if (loglevel == LOGL_DEBUG || crc_ok_count > 0)
LOGP_CHAN(DFRAME, LOGL_INFO, "RX RECC: (%d of 5 CRCs are ok)\n", crc_ok_count);
if (debuglevel == DEBUG_DEBUG || crc_ok_count > 0)
PDEBUG_CHAN(DFRAME, DEBUG_INFO, "RX RECC: (%d of 5 CRCs are ok)\n", crc_ok_count);
}
if (loglevel == LOGL_DEBUG) {
if (debuglevel == DEBUG_DEBUG) {
char text[64];
for (i = 0; i < 5; i++) {
strncpy(text, bits + i * 48, 48);
text[48] = '\0';
LOGP_CHAN(DFRAME, LOGL_DEBUG, " word - %s%s\n", text, (crc_a_ok[i]) ? " ok" : " BAD CRC!");
PDEBUG_CHAN(DFRAME, DEBUG_DEBUG, " word - %s%s\n", text, (crc_a_ok[i]) ? " ok" : " BAD CRC!");
}
}
@ -3757,7 +3690,7 @@ int amps_decode_frame(amps_t *amps, const char *bits, int count, double level, d
/* not if additional words are received without sync */
if (count != 240) {
LOGP_CHAN(DDSP, LOGL_INFO, "RX Level: %.0f%% Quality: %.0f%% Polarity: %s\n", level * 100.0, quality * 100.0, (negative) ? "NEGATIVE" : "POSITIVE");
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Quality: %.0f%% Polarity: %s\n", level * 100.0, quality * 100.0, (negative) ? "NEGATIVE" : "POSITIVE");
}
if (count == 441) {
amps_decode_bits_focc(amps, bits);
@ -3766,7 +3699,7 @@ int amps_decode_frame(amps_t *amps, const char *bits, int count, double level, d
} else if (count == 240) {
more = amps_decode_bits_recc(amps, bits, 0);
} else {
LOGP_CHAN(DFRAME, LOGL_ERROR, "Frame with unknown length = %d, please fix!\n", count);
PDEBUG_CHAN(DFRAME, DEBUG_ERROR, "Frame with unknown length = %d, please fix!\n", count);
}
return more;

View File

@ -211,16 +211,16 @@ typedef struct amps_frame {
} frame_t;
void init_frame(void);
uint64_t amps_encode_word1_system(uint8_t dcc, uint16_t sid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc, int debug);
uint64_t tacs_encode_word1_system(uint8_t dcc, uint16_t aid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc, int debug);
uint64_t amps_encode_word2_system(uint8_t dcc, uint8_t s, uint8_t e, uint8_t regh, uint8_t regr, uint8_t dtx, uint8_t n_1, uint8_t rcf, uint8_t cpa, uint8_t cmax_1, uint8_t end, int debug);
uint64_t amps_encode_registration_id(uint8_t dcc, uint32_t regid, uint8_t end, int debug);
uint64_t amps_encode_registration_increment(uint8_t dcc, uint16_t regincr, uint8_t end, int debug);
uint64_t amps_encode_location_area(uint8_t dcc, uint8_t pureg, uint8_t pdreg, uint8_t lreg, uint16_t locaid, uint8_t end, int debug);
uint64_t amps_encode_new_access_channel_set(uint8_t dcc, uint16_t newacc, uint8_t end, int debug);
uint64_t amps_encode_overload_control(uint8_t dcc, uint8_t *olc, uint8_t end, int debug);
uint64_t amps_encode_access_type(uint8_t dcc, uint8_t bis, uint8_t pci_home, uint8_t pci_roam, uint8_t bspc, uint8_t bscap, uint8_t end, int debug);
uint64_t amps_encode_access_attempt(uint8_t dcc, uint8_t maxbusy_pgr, uint8_t maxsztr_pgr, uint8_t maxbusy_other, uint8_t maxsztr_other, uint8_t end, int debug);
uint64_t amps_encode_word1_system(uint8_t dcc, uint16_t sid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc);
uint64_t tacs_encode_word1_system(uint8_t dcc, uint16_t aid1, uint8_t ep, uint8_t auth, uint8_t pci, uint8_t nawc);
uint64_t amps_encode_word2_system(uint8_t dcc, uint8_t s, uint8_t e, uint8_t regh, uint8_t regr, uint8_t dtx, uint8_t n_1, uint8_t rcf, uint8_t cpa, uint8_t cmax_1, uint8_t end);
uint64_t amps_encode_registration_id(uint8_t dcc, uint32_t regid, uint8_t end);
uint64_t amps_encode_registration_increment(uint8_t dcc, uint16_t regincr, uint8_t end);
uint64_t amps_encode_location_area(uint8_t dcc, uint8_t pureg, uint8_t pdreg, uint8_t lreg, uint16_t locaid, uint8_t end);
uint64_t amps_encode_new_access_channel_set(uint8_t dcc, uint16_t newacc, uint8_t end);
uint64_t amps_encode_overload_control(uint8_t dcc, uint8_t *olc, uint8_t end);
uint64_t amps_encode_access_type(uint8_t dcc, uint8_t bis, uint8_t pci_home, uint8_t pci_roam, uint8_t bspc, uint8_t bscap, uint8_t end);
uint64_t amps_encode_access_attempt(uint8_t dcc, uint8_t maxbusy_pgr, uint8_t maxsztr_pgr, uint8_t maxbusy_other, uint8_t maxsztr_other, uint8_t end);
int amps_encode_frame_focc(amps_t *amps, char *bits);
int amps_encode_frame_fvc(amps_t *amps, char *bits);
int amps_decode_frame(amps_t *amps, const char *bits, int count, double level, double quality, int negative);

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "invalidnumber.h"
static int16_t pattern[] = {
0xfffe, 0x0001, 0xffff, 0x0001, 0xffff, 0x0002, 0xfffe, 0x0002,

View File

@ -5,16 +5,10 @@
#include "outoforder.h"
#include "invalidnumber.h"
#include "congestion.h"
#include "../libmobile/main_mobile.h"
const int tacs = 0;
const int jtacs = 0;
const struct number_lengths number_lengths[] = {
{ 10, "AMPS number (NPA-XXX-XXXX)" },
{ 0, NULL }
};
const char *number_prefixes[] = {
"1xxxxxxxxxx",
"+1xxxxxxxxxx",

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "noanswer.h"
static int16_t pattern[] = {
0xfe24, 0xfd20, 0xfd2c, 0xfdb5, 0xfeba, 0xfe20, 0xfd41, 0xfe32,

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "outoforder.h"
static int16_t pattern[] = {
0xfeae, 0xfde4, 0xfe26, 0xfea7, 0xfe94, 0xfe8a, 0xfeb4, 0xfe3b,

View File

@ -2,7 +2,6 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include "../libsample/sample.h"
#include "amps.h"
@ -151,7 +150,7 @@ void prepare_sysinfo(amps_si *si)
}
}
uint64_t get_sysinfo(amps_si *si, int debug)
uint64_t get_sysinfo(amps_si *si)
{
int count, nawc, end = 0;
time_t ti = time(NULL);
@ -167,27 +166,27 @@ uint64_t get_sysinfo(amps_si *si, int debug)
case SYSINFO_WORD1:
nawc = si->num - 1;
if (!tacs)
return amps_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc, debug);
return amps_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc);
else
return tacs_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc, debug);
return tacs_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc);
case SYSINFO_WORD2:
return amps_encode_word2_system(si->dcc, si->word2.s, si->word2.e, si->word2.regh, si->word2.regr, si->word2.dtx, si->word2.n_1, si->word2.rcf, si->word2.cpa, si->word2.cmax_1, end, debug);
return amps_encode_word2_system(si->dcc, si->word2.s, si->word2.e, si->word2.regh, si->word2.regr, si->word2.dtx, si->word2.n_1, si->word2.rcf, si->word2.cpa, si->word2.cmax_1, end);
case SYSINFO_REG_ID:
/* use time stamp to generate regid */
si->reg_id.regid = ti & 0xfffff;
return amps_encode_registration_id(si->dcc, si->reg_id.regid, end, debug);
return amps_encode_registration_id(si->dcc, si->reg_id.regid, end);
case SYSINFO_REG_INCR:
return amps_encode_registration_increment(si->dcc, si->reg_incr.regincr, end, debug);
return amps_encode_registration_increment(si->dcc, si->reg_incr.regincr, end);
case SYSINFO_LOC_AREA:
return amps_encode_location_area(si->dcc, si->loc_area.pureg, si->loc_area.pdreg, si->loc_area.lreg, si->loc_area.locaid, end, debug);
return amps_encode_location_area(si->dcc, si->loc_area.pureg, si->loc_area.pdreg, si->loc_area.lreg, si->loc_area.locaid, end);
case SYSINFO_NEW_ACC:
return amps_encode_new_access_channel_set(si->dcc, si->new_acc.newacc, end, debug);
return amps_encode_new_access_channel_set(si->dcc, si->new_acc.newacc, end);
case SYSINFO_OVERLOAD:
return amps_encode_overload_control(si->dcc, si->overload.olc, end, debug);
return amps_encode_overload_control(si->dcc, si->overload.olc, end);
case SYSINFO_ACC_TYPE:
return amps_encode_access_type(si->dcc, si->acc_type.bis, si->acc_type.pci_home, si->acc_type.pci_roam, si->acc_type.bspc, si->acc_type.bscap, end, debug);
return amps_encode_access_type(si->dcc, si->acc_type.bis, si->acc_type.pci_home, si->acc_type.pci_roam, si->acc_type.bspc, si->acc_type.bscap, end);
case SYSINFO_ACC_ATTEMPT:
return amps_encode_access_attempt(si->dcc, si->acc_attempt.maxbusy_pgr, si->acc_attempt.maxsztr_pgr, si->acc_attempt.maxbusy_other, si->acc_attempt.maxsztr_other, end, debug);
return amps_encode_access_attempt(si->dcc, si->acc_attempt.maxbusy_pgr, si->acc_attempt.maxsztr_pgr, si->acc_attempt.maxbusy_other, si->acc_attempt.maxsztr_other, end);
}
fprintf(stderr, "get_sysinfo unknown type, please fix!\n");

View File

@ -112,5 +112,5 @@ typedef struct system_information {
void init_sysinfo(amps_si *si, int cmac, int vmac, int dtx, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis);
void prepare_sysinfo(amps_si *si);
uint64_t get_sysinfo(amps_si *si, int debug);
uint64_t get_sysinfo(amps_si *si);

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "tones.h"
static int16_t pattern_ringback[] = {
0x0070, 0x00dd, 0x013b, 0x0192, 0x0191, 0x0153, 0x0099, 0xffb2,

View File

@ -21,7 +21,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
#include "amps.h"
@ -37,25 +37,17 @@ static const char *trans_state_name(int state)
case TRANS_REGISTER_ACK_SEND:
return "REGISTER ACK SEND";
case TRANS_CALL_MO_ASSIGN:
return "MO CALL ASSIGNMENT";
return "CALL ASSIGN MOBILE ORIGINATING";
case TRANS_CALL_MO_ASSIGN_SEND:
return "MO CALL ASSIGNMENT SENDING";
case TRANS_CALL_MO_ASSIGN_CONFIRM:
return "MO CALL ASSIGNMENT WAIT CONFIRM";
return "CALL ASSIGN MOBILE ORIGINATING SEND";
case TRANS_CALL_MT_ASSIGN:
return "MT CALL ASSIGNMENT";
return "CALL ASSIGN MOBILE TERMINATING";
case TRANS_CALL_MT_ASSIGN_SEND:
return "MT CALL ASSIGNMENT SENDING";
case TRANS_CALL_MT_ASSIGN_CONFIRM:
return "MT CALL ASSIGNMENT WAIT CONFIRM";
return "CALL ASSIGN MOBILE TERMINATING SEND";
case TRANS_CALL_MT_ALERT:
return "MT CALL ALERT";
return "CALL ALERT MOBILE TERMINATING";
case TRANS_CALL_MT_ALERT_SEND:
return "MT CALL ALERT SENDING";
case TRANS_CALL_MT_ALERT_CONFIRM:
return "MT CALL ALERT WAIT CONFIRM";
case TRANS_CALL_MT_ANSWER_WAIT:
return "MT CALL ANSWER WAIT";
return "CALL ALERT MOBILE TERMINATING SEND";
case TRANS_CALL_REJECT:
return "CALL REJECT";
case TRANS_CALL_REJECT_SEND:
@ -87,15 +79,11 @@ const char *trans_short_state_name(int state)
return "REGISTER";
case TRANS_CALL_MO_ASSIGN:
case TRANS_CALL_MO_ASSIGN_SEND:
case TRANS_CALL_MO_ASSIGN_CONFIRM:
case TRANS_CALL_MT_ASSIGN:
case TRANS_CALL_MT_ASSIGN_SEND:
case TRANS_CALL_MT_ASSIGN_CONFIRM:
return "ASSIGN";
case TRANS_CALL_MT_ALERT:
case TRANS_CALL_MT_ALERT_SEND:
case TRANS_CALL_MT_ALERT_CONFIRM:
case TRANS_CALL_MT_ANSWER_WAIT:
return "ALERT";
case TRANS_CALL_REJECT:
case TRANS_CALL_REJECT_SEND:
@ -133,7 +121,7 @@ transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uin
const char *number = amps_min2number(trans->min1, trans->min2);
int old_callref = trans->callref;
amps_t *old_amps = trans->amps;
LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", number);
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", number);
destroy_transaction(trans);
if (old_amps) /* should be... */
amps_go_idle(old_amps);
@ -143,11 +131,11 @@ transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uin
trans = calloc(1, sizeof(*trans));
if (!trans) {
LOGP(DTRANS, LOGL_ERROR, "No memory!\n");
PDEBUG(DTRANS, DEBUG_ERROR, "No memory!\n");
return NULL;
}
osmo_timer_setup(&trans->timer, transaction_timeout, trans);
timer_init(&trans->timer, transaction_timeout, trans);
trans_new_state(trans, state);
trans->min1 = min1;
@ -159,7 +147,7 @@ transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uin
trans->chan = chan;
const char *number = amps_min2number(trans->min1, trans->min2);
LOGP(DTRANS, LOGL_INFO, "Created transaction for subscriber '%s'\n", number);
PDEBUG(DTRANS, DEBUG_INFO, "Created transaction for subscriber '%s'\n", number);
link_transaction(trans, amps);
@ -172,9 +160,9 @@ void destroy_transaction(transaction_t *trans)
unlink_transaction(trans);
const char *number = amps_min2number(trans->min1, trans->min2);
LOGP(DTRANS, LOGL_INFO, "Destroying transaction for subscriber '%s'\n", number);
PDEBUG(DTRANS, DEBUG_INFO, "Destroying transaction for subscriber '%s'\n", number);
osmo_timer_del(&trans->timer);
timer_exit(&trans->timer);
trans_new_state(trans, 0);
@ -187,7 +175,7 @@ void link_transaction(transaction_t *trans, amps_t *amps)
transaction_t **transp;
/* attach to end of list, so first transaction is served first */
LOGP(DTRANS, LOGL_DEBUG, "Linking transaction %p to amps %p\n", trans, amps);
PDEBUG(DTRANS, DEBUG_DEBUG, "Linking transaction %p to amps %p\n", trans, amps);
trans->amps = amps;
trans->next = NULL;
transp = &amps->trans_list;
@ -203,12 +191,12 @@ void unlink_transaction(transaction_t *trans)
transaction_t **transp;
/* unlink */
LOGP(DTRANS, LOGL_DEBUG, "Unlinking transaction %p from amps %p\n", trans, trans->amps);
PDEBUG(DTRANS, DEBUG_DEBUG, "Unlinking transaction %p from amps %p\n", trans, trans->amps);
transp = &trans->amps->trans_list;
while (*transp && *transp != trans)
transp = &((*transp)->next);
if (!(*transp)) {
LOGP(DTRANS, LOGL_ERROR, "Transaction not in list, please fix!!\n");
PDEBUG(DTRANS, DEBUG_ERROR, "Transaction not in list, please fix!!\n");
abort();
}
*transp = trans->next;
@ -224,7 +212,7 @@ transaction_t *search_transaction_number(amps_t *amps, uint32_t min1, uint16_t m
if (trans->min1 == min1
&& trans->min2 == min2) {
const char *number = amps_min2number(trans->min1, trans->min2);
LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", number);
PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", number);
return trans;
}
trans = trans->next;
@ -243,7 +231,7 @@ transaction_t *search_transaction_callref(amps_t *amps, int callref)
while (trans) {
if (trans->callref == callref) {
const char *number = amps_min2number(trans->min1, trans->min2);
LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", number);
PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", number);
return trans;
}
trans = trans->next;
@ -254,7 +242,7 @@ transaction_t *search_transaction_callref(amps_t *amps, int callref)
void trans_new_state(transaction_t *trans, int state)
{
LOGP(DTRANS, LOGL_INFO, "Transaction state %s -> %s\n", trans_state_name(trans->state), trans_state_name(state));
PDEBUG(DTRANS, DEBUG_INFO, "Transaction state %s -> %s\n", trans_state_name(trans->state), trans_state_name(state));
trans->state = state;
amps_display_status();
}
@ -263,12 +251,12 @@ void amps_flush_other_transactions(amps_t *amps, transaction_t *trans)
{
/* flush after this very trans */
while (trans->next) {
LOGP(DTRANS, LOGL_NOTICE, "Kicking other pending transaction\n");
PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n");
destroy_transaction(trans->next);
}
/* flush before this very trans */
while (amps->trans_list != trans) {
LOGP(DTRANS, LOGL_NOTICE, "Kicking other pending transaction\n");
PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n");
destroy_transaction(amps->trans_list);
}
}

View File

@ -5,14 +5,10 @@ enum amps_trans_state {
TRANS_REGISTER_ACK_SEND, /* attach request received, sending ack */
TRANS_CALL_MO_ASSIGN, /* assigning channel, waiting to send */
TRANS_CALL_MO_ASSIGN_SEND, /* assigning channel, sending assignment */
TRANS_CALL_MO_ASSIGN_CONFIRM, /* assignment sent, waiting for confirm (SAT) */
TRANS_CALL_MT_ASSIGN, /* assigning channel, waiting to send */
TRANS_CALL_MT_ASSIGN_SEND, /* assigning channel, sending assignment */
TRANS_CALL_MT_ASSIGN_CONFIRM, /* assignment sent, waiting for confirm (SAT) */
TRANS_CALL_MT_ALERT, /* ringing the phone, waiting to send alert */
TRANS_CALL_MT_ALERT_SEND, /* ringing the phone, sending alert */
TRANS_CALL_MT_ALERT_CONFIRM, /* ringing the phone, signaling tone is received */
TRANS_CALL_MT_ANSWER_WAIT, /* ringing the phone, waiting for the phone to answer */
TRANS_CALL_MT_ALERT, /* ringing the phone, sending alert order until signaling tone is received */
TRANS_CALL_MT_ALERT_SEND, /* ringing the phone, signaling tone is received */
TRANS_CALL_REJECT, /* rejecting channel, waiting to send */
TRANS_CALL_REJECT_SEND, /* rejecting channel, sending reject */
TRANS_CALL, /* active call */
@ -35,11 +31,9 @@ typedef struct transaction {
uint8_t ordq;
uint8_t order;
uint16_t chan; /* channel to assign */
int alert_retry; /* current number of alter order (re)try */
char caller_id[33]; /* id of calling phone */
char dialing[33]; /* number dialed by the phone */
enum amps_trans_state state; /* state of transaction */
struct osmo_timer_list timer; /* for varous timeouts */
struct timer timer; /* for varous timeouts */
int sat_detected; /* state if we detected SAT */
int dtx; /* if set, DTX is used with this call */
} transaction_t;
@ -53,6 +47,6 @@ transaction_t *search_transaction_number(amps_t *amps, uint32_t min1, uint16_t m
transaction_t *search_transaction_callref(amps_t *amps, int callref);
void trans_new_state(transaction_t *trans, int state);
void amps_flush_other_transactions(amps_t *amps, transaction_t *trans);
void transaction_timeout(void *data);
void transaction_timeout(struct timer *timer);
const char *trans_short_state_name(int state);

View File

@ -1,4 +1,4 @@
AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes)
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
bin_PROGRAMS = \
anetz
@ -19,21 +19,22 @@ anetz_LDADD = \
$(COMMON_LA) \
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/libgoertzel/libgoertzel.a \
$(top_builddir)/src/libjitter/libjitter.a \
$(top_builddir)/src/libsquelch/libsquelch.a \
$(top_builddir)/src/libtimer/libtimer.a \
$(top_builddir)/src/libsamplerate/libsamplerate.a \
$(top_builddir)/src/libemphasis/libemphasis.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 \
$(top_builddir)/src/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
-lm
if HAVE_ALSA

View File

@ -25,19 +25,19 @@
#include <string.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include <osmocom/core/timer.h>
#include "../libdebug/debug.h"
#include "../libtimer/timer.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
#include <osmocom/cc/message.h>
#include "../libosmocc/message.h"
#include "anetz.h"
#include "dsp.h"
/* Timers */
#define PAGING_TO 30,0 /* Nach dieser Zeit ist der Operator genervt... */
#define RELEASE_TO 3,0 /* Release time, so station keeps blocked for a while */
#define PAGING_TO 30 /* Nach dieser Zeit ist der Operator genervt... */
#define RELEASE_TO 3 /* Release time, so station keeps blocked for a while */
static const char *anetz_state_name(enum anetz_state state)
const char *anetz_state_name(enum anetz_state state)
{
static char invalid[16];
@ -58,7 +58,7 @@ static const char *anetz_state_name(enum anetz_state state)
return invalid;
}
static void anetz_display_status(void)
void anetz_display_status(void)
{
sender_t *sender;
anetz_t *anetz;
@ -77,7 +77,7 @@ static void anetz_new_state(anetz_t *anetz, enum anetz_state new_state)
{
if (anetz->state == new_state)
return;
LOGP_CHAN(DANETZ, LOGL_DEBUG, "State change: %s -> %s\n", anetz_state_name(anetz->state), anetz_state_name(new_state));
PDEBUG_CHAN(DANETZ, DEBUG_DEBUG, "State change: %s -> %s\n", anetz_state_name(anetz->state), anetz_state_name(new_state));
anetz->state = new_state;
anetz_display_status();
}
@ -141,7 +141,7 @@ static double *anetz_nummer2freq(const char *nummer)
/* get decade */
dekade = anetz_gruppenkennziffer[*nummer - '0'].dekade;
LOGP(DANETZ, LOGL_DEBUG, "Dekaden: %d %d %d %d\n", dekade[0], dekade[1], dekade[2], dekade[3]);
PDEBUG(DANETZ, DEBUG_DEBUG, "Dekaden: %d %d %d %d\n", dekade[0], dekade[1], dekade[2], dekade[3]);
nummer++;
/* get 4 frequencies out of decades */
@ -161,7 +161,7 @@ static double *anetz_nummer2freq(const char *nummer)
}
}
LOGP(DANETZ, LOGL_DEBUG, "Frequencies: F%d=%.1f F%d=%.1f F%d=%.1f F%d=%.1f\n", f[0], freq[0], f[1], freq[1], f[2], freq[2], f[3], freq[3]);
PDEBUG(DANETZ, DEBUG_DEBUG, "Frequencies: F%d=%.1f F%d=%.1f F%d=%.1f F%d=%.1f\n", f[0], freq[0], f[1], freq[1], f[2], freq[2], f[3], freq[3]);
return freq;
}
@ -186,7 +186,7 @@ int anetz_init(void)
return 0;
}
static void anetz_timeout(void *data);
static void anetz_timeout(struct timer *timer);
static void anetz_go_idle(anetz_t *anetz);
/* Create transceiver instance and link to a list. */
@ -196,40 +196,40 @@ int anetz_create(const char *kanal, const char *device, int use_sdr, int sampler
int rc;
if (atoi(kanal) < 30 || atoi(kanal) > 63) {
LOGP(DANETZ, LOGL_ERROR, "Channel ('Kanal') number %s invalid.\n", kanal);
PDEBUG(DANETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid.\n", kanal);
return -EINVAL;
}
anetz = calloc(1, sizeof(anetz_t));
if (!anetz) {
LOGP(DANETZ, LOGL_ERROR, "No memory!\n");
PDEBUG(DANETZ, DEBUG_ERROR, "No memory!\n");
return -EIO;
}
anetz->operator = operator;
LOGP(DANETZ, LOGL_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %s (sample rate %d).\n", kanal, samplerate);
PDEBUG(DANETZ, DEBUG_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %s (sample rate %d).\n", kanal, samplerate);
/* init general part of transceiver */
rc = sender_create(&anetz->sender, kanal, anetz_kanal2freq(atoi(kanal), 0), anetz_kanal2freq(atoi(kanal), 1), device, use_sdr, samplerate, rx_gain, tx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
if (rc < 0) {
LOGP(DANETZ, LOGL_ERROR, "Failed to init 'Sender' processing!\n");
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init 'Sender' processing!\n");
goto error;
}
/* init audio processing */
rc = dsp_init_sender(anetz, page_gain, page_sequence, squelch_db);
if (rc < 0) {
LOGP(DANETZ, LOGL_ERROR, "Failed to init signal processing!\n");
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init signal processing!\n");
goto error;
}
osmo_timer_setup(&anetz->timer, anetz_timeout, anetz);
timer_init(&anetz->timer, anetz_timeout, anetz);
/* go into idle state */
anetz_go_idle(anetz);
LOGP(DANETZ, LOGL_NOTICE, "Created 'Kanal' #%s\n", kanal);
PDEBUG(DANETZ, DEBUG_NOTICE, "Created 'Kanal' #%s\n", kanal);
return 0;
@ -244,9 +244,9 @@ void anetz_destroy(sender_t *sender)
{
anetz_t *anetz = (anetz_t *) sender;
LOGP(DANETZ, LOGL_DEBUG, "Destroying 'A-Netz' instance for 'Kanal' = %s.\n", sender->kanal);
PDEBUG(DANETZ, DEBUG_DEBUG, "Destroying 'A-Netz' instance for 'Kanal' = %s.\n", sender->kanal);
osmo_timer_del(&anetz->timer);
timer_exit(&anetz->timer);
dsp_cleanup_sender(anetz);
sender_destroy(&anetz->sender);
free(sender);
@ -255,9 +255,9 @@ void anetz_destroy(sender_t *sender)
/* Abort connection towards mobile station by sending idle tone. */
static void anetz_go_idle(anetz_t *anetz)
{
osmo_timer_del(&anetz->timer);
timer_stop(&anetz->timer);
LOGP(DANETZ, LOGL_INFO, "Entering IDLE state on channel %s, sending 2280 Hz tone.\n", anetz->sender.kanal);
PDEBUG(DANETZ, DEBUG_INFO, "Entering IDLE state on channel %s, sending 2280 Hz tone.\n", anetz->sender.kanal);
anetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_FREI);
/* also reset detector, so if there is a new call it is answered */
@ -267,31 +267,31 @@ static void anetz_go_idle(anetz_t *anetz)
/* Release connection towards mobile station by sending idle tone for a while. */
static void anetz_release(anetz_t *anetz)
{
osmo_timer_del(&anetz->timer);
timer_stop(&anetz->timer);
LOGP_CHAN(DANETZ, LOGL_INFO, "Sending 2280 Hz release tone.\n");
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Sending 2280 Hz release tone.\n");
anetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_AUSLOESEN);
anetz_set_dsp_mode(anetz, DSP_MODE_TONE, 0);
osmo_timer_schedule(&anetz->timer, RELEASE_TO);
timer_start(&anetz->timer, RELEASE_TO);
}
/* Enter paging state and transmit 4 paging tones. */
static void anetz_page(anetz_t *anetz, const char *dial_string, double *freq)
{
LOGP_CHAN(DANETZ, LOGL_INFO, "Entering paging state, sending 'Selektivruf' to '%s'.\n", dial_string);
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Entering paging state, sending 'Selektivruf' to '%s'.\n", dial_string);
strcpy(anetz->station_id, dial_string); /* set station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_ANRUF);
anetz_set_dsp_mode(anetz, DSP_MODE_PAGING, 0);
dsp_set_paging(anetz, freq);
osmo_timer_schedule(&anetz->timer, PAGING_TO);
timer_start(&anetz->timer, PAGING_TO);
}
/* Loss of signal was detected, release active call. */
void anetz_loss_indication(anetz_t *anetz, double loss_time)
{
if (anetz->state == ANETZ_GESPRAECH) {
LOGP_CHAN(DANETZ, LOGL_NOTICE, "Detected loss of signal after %.1f seconds, releasing.\n", loss_time);
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Detected loss of signal after %.1f seconds, releasing.\n", loss_time);
anetz_release(anetz);
call_up_release(anetz->callref, CAUSE_TEMPFAIL);
anetz->callref = 0;
@ -302,9 +302,9 @@ void anetz_loss_indication(anetz_t *anetz, double loss_time)
void anetz_receive_tone(anetz_t *anetz, int tone)
{
if (tone >= 0)
LOGP_CHAN(DANETZ, LOGL_DEBUG, "Received contiuous %d Hz tone.\n", (tone) ? 1750 : 2280);
PDEBUG_CHAN(DANETZ, DEBUG_DEBUG, "Received contiuous %d Hz tone.\n", (tone) ? 1750 : 2280);
else
LOGP_CHAN(DANETZ, LOGL_DEBUG, "Continuous tone is gone.\n");
PDEBUG_CHAN(DANETZ, DEBUG_DEBUG, "Continuous tone is gone.\n");
/* skip any handling in loopback mode */
if (anetz->sender.loopback)
@ -318,7 +318,7 @@ void anetz_receive_tone(anetz_t *anetz, int tone)
case ANETZ_FREI:
/* initiate call on calling tone */
if (tone == 1) {
LOGP_CHAN(DANETZ, LOGL_INFO, "Received 1750 Hz calling signal from mobile station, removing idle signal.\n");
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Received 1750 Hz calling signal from mobile station, removing idle signal.\n");
strcpy(anetz->station_id, "unknown"); /* set station ID before state change, so status is shown correctly */
anetz_new_state(anetz, ANETZ_GESPRAECH);
@ -330,17 +330,17 @@ void anetz_receive_tone(anetz_t *anetz, int tone)
/* throughconnect speech when calling/answer tone is gone */
if (tone != 1) {
if (!anetz->callref) {
LOGP_CHAN(DANETZ, LOGL_INFO, "1750 Hz signal from mobile station is gone, setup call.\n");
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "1750 Hz signal from mobile station is gone, setup call.\n");
anetz->callref = call_up_setup(NULL, anetz->operator, OSMO_CC_NETWORK_ANETZ_NONE, "");
} else {
LOGP_CHAN(DANETZ, LOGL_INFO, "1750 Hz signal from mobile station is gone, answer call.\n");
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "1750 Hz signal from mobile station is gone, answer call.\n");
call_up_answer(anetz->callref, anetz->station_id);
}
anetz_set_dsp_mode(anetz, DSP_MODE_AUDIO, 0);
}
/* release call */
if (tone == 1) {
LOGP_CHAN(DANETZ, LOGL_INFO, "Received 1750 Hz release signal from mobile station, sending release tone.\n");
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Received 1750 Hz release signal from mobile station, sending release tone.\n");
anetz_release(anetz);
call_up_release(anetz->callref, CAUSE_NORMAL);
anetz->callref = 0;
@ -350,8 +350,8 @@ void anetz_receive_tone(anetz_t *anetz, int tone)
case ANETZ_ANRUF:
/* answer call on answer tone */
if (tone == 1) {
LOGP_CHAN(DANETZ, LOGL_INFO, "Received 1750 Hz answer signal from mobile station, removing paging tones.\n");
osmo_timer_del(&anetz->timer);
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Received 1750 Hz answer signal from mobile station, removing paging tones.\n");
timer_stop(&anetz->timer);
anetz_new_state(anetz, ANETZ_GESPRAECH);
anetz_set_dsp_mode(anetz, DSP_MODE_SILENCE, 0);
break;
@ -362,13 +362,13 @@ void anetz_receive_tone(anetz_t *anetz, int tone)
}
/* Timeout handling */
static void anetz_timeout(void *data)
static void anetz_timeout(struct timer *timer)
{
anetz_t *anetz = data;
anetz_t *anetz = (anetz_t *)timer->priv;
switch (anetz->state) {
case ANETZ_ANRUF:
LOGP_CHAN(DANETZ, LOGL_NOTICE, "Timeout while waiting for answer, releasing.\n");
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Timeout while waiting for answer, releasing.\n");
anetz_go_idle(anetz);
call_up_release(anetz->callref, CAUSE_NOANSWER);
anetz->callref = 0;
@ -391,8 +391,8 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
/* 1. determine paging frequencies */
freq = anetz_nummer2freq(dialing);
if (!freq) {
LOGP(DANETZ, LOGL_NOTICE, "Number invalid: %s\n", anetz_nummer2freq_error);
LOGP(DANETZ, LOGL_NOTICE, "Outgoing call to invalid number '%s', rejecting!\n", dialing);
PDEBUG(DANETZ, DEBUG_NOTICE, "Number invalid: %s\n", anetz_nummer2freq_error);
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing call to invalid number '%s', rejecting!\n", dialing);
return -CAUSE_INVALNUMBER;
}
@ -405,7 +405,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
break;
}
if (sender) {
LOGP(DANETZ, LOGL_NOTICE, "Outgoing call to busy number, rejecting!\n");
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
return -CAUSE_BUSY;
}
@ -416,13 +416,13 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
break;
}
if (!sender) {
LOGP(DANETZ, LOGL_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
return -CAUSE_NOCHANNEL;
}
LOGP_CHAN(DANETZ, LOGL_INFO, "Call to mobile station, paging with tones: %.1f %.1f %.1f %.1f\n", freq[0], freq[1], freq[2], freq[3]);
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "Call to mobile station, paging with tones: %.1f %.1f %.1f %.1f\n", freq[0], freq[1], freq[2], freq[3]);
if (anetz->page_sequence)
LOGP(DANETZ, LOGL_NOTICE, "Sending paging tones in sequence.\n");
PDEBUG(DANETZ, DEBUG_NOTICE, "Sending paging tones in sequence.\n");
/* 4. trying to page mobile station */
anetz->callref = callref;
@ -433,7 +433,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
return 0;
}
void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter)
void call_down_answer(int __attribute__((unused)) callref)
{
}
@ -446,7 +446,7 @@ void call_down_disconnect(int callref, int cause)
sender_t *sender;
anetz_t *anetz;
LOGP(DANETZ, LOGL_INFO, "Call has been disconnected by network.\n");
PDEBUG(DANETZ, DEBUG_INFO, "Call has been disconnected by network.\n");
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
@ -454,7 +454,7 @@ void call_down_disconnect(int callref, int cause)
break;
}
if (!sender) {
LOGP(DANETZ, LOGL_NOTICE, "Outgoing disconnect, but no callref!\n");
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n");
call_up_release(callref, CAUSE_INVALCALLREF);
return;
}
@ -464,7 +464,7 @@ void call_down_disconnect(int callref, int cause)
return;
switch (anetz->state) {
case ANETZ_ANRUF:
LOGP_CHAN(DANETZ, LOGL_NOTICE, "Outgoing disconnect, during alerting, going idle!\n");
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Outgoing disconnect, during alerting, going idle!\n");
anetz_go_idle(anetz);
break;
default:
@ -483,7 +483,7 @@ void call_down_release(int callref, __attribute__((unused)) int cause)
sender_t *sender;
anetz_t *anetz;
LOGP(DANETZ, LOGL_INFO, "Call has been released by network, releasing call.\n");
PDEBUG(DANETZ, DEBUG_INFO, "Call has been released by network, releasing call.\n");
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
@ -491,7 +491,7 @@ void call_down_release(int callref, __attribute__((unused)) int cause)
break;
}
if (!sender) {
LOGP(DANETZ, LOGL_NOTICE, "Outgoing release, but no callref!\n");
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing release, but no callref!\n");
/* don't send release, because caller already released */
return;
}
@ -500,11 +500,11 @@ void call_down_release(int callref, __attribute__((unused)) int cause)
switch (anetz->state) {
case ANETZ_GESPRAECH:
LOGP_CHAN(DANETZ, LOGL_NOTICE, "Outgoing release, during call, sending release tone!\n");
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Outgoing release, during call, sending release tone!\n");
anetz_release(anetz);
break;
case ANETZ_ANRUF:
LOGP_CHAN(DANETZ, LOGL_NOTICE, "Outgoing release, during alerting, going idle!\n");
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Outgoing release, during alerting, going idle!\n");
anetz_go_idle(anetz);
break;
default:
@ -512,5 +512,28 @@ void call_down_release(int callref, __attribute__((unused)) int cause)
}
}
/* Receive audio from call instance. */
void call_down_audio(int callref, sample_t *samples, int count)
{
sender_t *sender;
anetz_t *anetz;
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
if (anetz->callref == callref)
break;
}
if (!sender)
return;
if (anetz->dsp_mode == DSP_MODE_AUDIO) {
sample_t up[(int)((double)count * anetz->sender.srstate.factor + 0.5) + 10];
count = samplerate_upsample(&anetz->sender.srstate, samples, count, up);
jitter_save(&anetz->sender.dejitter, up, count);
}
}
void call_down_clock(void) {}
void dump_info(void) {}

View File

@ -24,7 +24,7 @@ typedef struct anetz {
enum anetz_state state; /* current sender's state */
int callref; /* call reference */
char station_id[8]; /* current station ID */
struct osmo_timer_list timer;
struct timer timer;
/* display measurements */
dispmeasparam_t *dmp_tone_level;

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "besetztton.h"
static int16_t pattern[] = {
0x0004, 0xffe9, 0xffc9, 0xffac, 0xff92, 0xff83, 0xff75, 0xff56,

View File

@ -26,8 +26,8 @@
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include <osmocom/core/timer.h>
#include "../libdebug/debug.h"
#include "../libtimer/timer.h"
#include "../libmobile/call.h"
#include "anetz.h"
#include "dsp.h"
@ -68,7 +68,7 @@ void dsp_init(void)
int i;
double s;
LOGP(DDSP, LOGL_DEBUG, "Generating sine tables.\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine tables.\n");
for (i = 0; i < 65536; i++) {
s = sin((double)i / 65536.0 * 2.0 * PI);
dsp_sine_tone[i] = s * TX_PEAK_TONE;
@ -83,7 +83,7 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence, double
int i;
double tone;
LOGP_CHAN(DDSP, LOGL_DEBUG, "Init DSP for 'Sender'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
/* init squelch */
squelch_init(&anetz->squelch, anetz->sender.kanal, squelch_db, MUTE_TIME, LOSS_TIME);
@ -95,10 +95,10 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence, double
anetz->page_sequence = page_sequence;
anetz->samples_per_chunk = anetz->sender.samplerate * CHUNK_DURATION;
LOGP(DDSP, LOGL_DEBUG, "Using %d samples per filter chunk duration.\n", anetz->samples_per_chunk);
PDEBUG(DDSP, DEBUG_DEBUG, "Using %d samples per filter chunk duration.\n", anetz->samples_per_chunk);
spl = calloc(anetz->samples_per_chunk, sizeof(sample_t));
if (!spl) {
LOGP(DDSP, LOGL_ERROR, "No memory!\n");
PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n");
return -ENOMEM;
}
anetz->fsk_filter_spl = spl;
@ -119,7 +119,7 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence, double
/* Cleanup transceiver instance. */
void dsp_cleanup_sender(anetz_t *anetz)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "Cleanup DSP for 'Sender'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for 'Sender'.\n");
if (anetz->fsk_filter_spl) {
free(anetz->fsk_filter_spl);
@ -133,7 +133,7 @@ static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double leve
/* lost tone because it is not good anymore or has changed */
if (!goodtone || tone != anetz->tone_detected) {
if (anetz->tone_count >= TONE_DETECT_TH) {
LOGP_CHAN(DDSP, LOGL_INFO, "Lost %.0f Hz tone after %.0f ms.\n", fsk_tones[anetz->tone_detected], 1000.0 * CHUNK_DURATION * anetz->tone_count);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Lost %.0f Hz tone after %.0f ms.\n", fsk_tones[anetz->tone_detected], 1000.0 * CHUNK_DURATION * anetz->tone_count);
anetz_receive_tone(anetz, -1);
}
if (goodtone)
@ -148,7 +148,7 @@ static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double leve
anetz->tone_count++;
if (anetz->tone_count == TONE_DETECT_TH) {
LOGP_CHAN(DDSP, LOGL_INFO, "Detecting continuous %.0f Hz tone. (level = %.0f%%, quality =%.0f%%)\n", fsk_tones[anetz->tone_detected], level * 100.0, quality * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Detecting continuous %.0f Hz tone. (level = %.0f%%, quality =%.0f%%)\n", fsk_tones[anetz->tone_detected], level * 100.0, quality * 100.0);
anetz_receive_tone(anetz, anetz->tone_detected);
}
}
@ -171,7 +171,7 @@ static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
display_measurements_update(anetz->dmp_tone_level, level * 100.0, 0.0);
display_measurements_update(anetz->dmp_tone_quality, quality[1] * 100.0, 0.0);
if ((level > TONE_THRESHOLD && quality[1] > QUAL_THRESHOLD) || anetz->sender.loopback)
LOGP_CHAN(DDSP, LOGL_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level * 100.0, quality[1] * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level * 100.0, quality[1] * 100.0);
/* adjust level, so we get peak of sine curve */
/* indicate detected tone */
@ -357,7 +357,6 @@ static void fsk_tone(anetz_t *anetz, sample_t *samples, int length)
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length)
{
anetz_t *anetz = (anetz_t *) sender;
int input_num;
memset(power, 1, length);
@ -366,13 +365,7 @@ void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length
memset(samples, 0, length * sizeof(*samples));
break;
case DSP_MODE_AUDIO:
input_num = samplerate_upsample_input_num(&sender->srstate, length);
{
int16_t spl[input_num];
jitter_load_samples(&sender->dejitter, (uint8_t *)spl, input_num, sizeof(*spl), jitter_conceal_s16, NULL);
int16_to_samples_speech(samples, spl, input_num);
}
samplerate_upsample(&sender->srstate, samples, input_num, samples, length);
jitter_load(&anetz->sender.dejitter, samples, length);
break;
case DSP_MODE_TONE:
fsk_tone(anetz, samples, length);
@ -386,7 +379,7 @@ void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length
}
}
static const char *anetz_dsp_mode_name(enum dsp_mode mode)
const char *anetz_dsp_mode_name(enum dsp_mode mode)
{
static char invalid[16];
@ -407,10 +400,7 @@ static const char *anetz_dsp_mode_name(enum dsp_mode mode)
void anetz_set_dsp_mode(anetz_t *anetz, enum dsp_mode mode, int detect_reset)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "DSP mode %s -> %s\n", anetz_dsp_mode_name(anetz->dsp_mode), anetz_dsp_mode_name(mode));
if (mode == DSP_MODE_AUDIO && anetz->dsp_mode != mode)
jitter_reset(&anetz->sender.dejitter);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", anetz_dsp_mode_name(anetz->dsp_mode), anetz_dsp_mode_name(mode));
anetz->dsp_mode = mode;
/* reset sequence paging */
anetz->paging_tone = 0;
@ -421,27 +411,3 @@ void anetz_set_dsp_mode(anetz_t *anetz, enum dsp_mode mode, int detect_reset)
anetz->tone_detected = -1;
}
/* Receive audio from call instance. */
void call_down_audio(void *decoder, void *decoder_priv, int callref, uint16_t sequence, uint8_t marker, uint32_t timestamp, uint32_t ssrc, uint8_t *payload, int payload_len)
{
sender_t *sender;
anetz_t *anetz;
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
if (anetz->callref == callref)
break;
}
if (!sender)
return;
if (anetz->dsp_mode == DSP_MODE_AUDIO) {
jitter_frame_t *jf;
jf = jitter_frame_alloc(decoder, decoder_priv, payload, payload_len, marker, sequence, timestamp, ssrc);
if (jf)
jitter_save(&anetz->sender.dejitter, jf);
}
}
void call_down_clock(void) {}

View File

@ -1,5 +1,4 @@
#include <stdint.h>
#include "freiton.h"
static int16_t pattern[] = {
0x0056, 0x0068, 0x0065, 0x005d, 0x0040, 0x0031, 0x001a, 0x000d,

View File

@ -25,8 +25,8 @@
#include <math.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../liblogging/logging.h"
#include <osmocom/core/timer.h>
#include "../libdebug/debug.h"
#include "../libtimer/timer.h"
#include "../libmobile/call.h"
#include "../liboptions/options.h"
#include "../libfm/fm.h"
@ -198,7 +198,6 @@ fail:
anetz_destroy(sender_head);
/* exits */
main_mobile_exit();
fm_exit();
options_free();

View File

@ -2,7 +2,6 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "stations.h"
static struct anetz_stations {
const char *standort;
@ -148,7 +147,7 @@ static struct anetz_stations {
{ NULL, 0, 0, 0, 0, 0, NULL }
};
static double lat_from_coordinates(const char *string)
double lat_from_coordinates(const char *string)
{
if (strlen(string) != 11)
abort();
@ -169,7 +168,7 @@ static double lat_from_coordinates(const char *string)
(double)(string[4] - '0') / 60.0;
}
static double lon_from_coordinates(const char *string)
double lon_from_coordinates(const char *string)
{
if (strlen(string) != 11)
abort();
@ -201,45 +200,7 @@ void station_list(void)
printf("List of all base stations:\n");
for (i = 0; anetz_stations[i].standort; i++) {
printf("%s (%.2f deg N %.2f deg E)\n", anetz_stations[i].standort, lat_from_coordinates(anetz_stations[i].coordinates), lon_from_coordinates(anetz_stations[i].coordinates));
if (anetz_stations[i].kanal21) {
if (anetz_stations[i].kanal22)
printf("\tPrefix 21: Channel %d\n", anetz_stations[i].kanal21);
else if (anetz_stations[i].kanal23)
printf("\tPrefix 21-22: Channel %d\n", anetz_stations[i].kanal21);
else if (anetz_stations[i].kanal24)
printf("\tPrefix 21-23: Channel %d\n", anetz_stations[i].kanal21);
else if (anetz_stations[i].kanal25)
printf("\tPrefix 21-24: Channel %d\n", anetz_stations[i].kanal21);
else
printf("\tPrefix 21-25: Channel %d\n", anetz_stations[i].kanal21);
}
if (anetz_stations[i].kanal22) {
if (anetz_stations[i].kanal23)
printf("\tPrefix 22: Channel %d\n", anetz_stations[i].kanal22);
else if (anetz_stations[i].kanal24)
printf("\tPrefix 22-23: Channel %d\n", anetz_stations[i].kanal22);
else if (anetz_stations[i].kanal25)
printf("\tPrefix 22-24: Channel %d\n", anetz_stations[i].kanal22);
else
printf("\tPrefix 22-25: Channel %d\n", anetz_stations[i].kanal22);
}
if (anetz_stations[i].kanal23) {
if (anetz_stations[i].kanal24)
printf("\tPrefix 23: Channel %d\n", anetz_stations[i].kanal23);
else if (anetz_stations[i].kanal25)
printf("\tPrefix 23-24: Channel %d\n", anetz_stations[i].kanal23);
else
printf("\tPrefix 23-25: Channel %d\n", anetz_stations[i].kanal23);
}
if (anetz_stations[i].kanal24) {
if (anetz_stations[i].kanal25)
printf("\tPrefix 24: Channel %d\n", anetz_stations[i].kanal24);
else
printf("\tPrefix 24-25: Channel %d\n", anetz_stations[i].kanal24);
}
if (anetz_stations[i].kanal25)
printf("\tPrefix 25: Channel %d\n", anetz_stations[i].kanal25);
printf("%s (%.2f° N %.2f° E)\n", anetz_stations[i].standort, lat_from_coordinates(anetz_stations[i].coordinates), lon_from_coordinates(anetz_stations[i].coordinates));
}
}

View File

@ -1,4 +1,4 @@
AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes)
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
bin_PROGRAMS = \
bnetz \
@ -16,10 +16,13 @@ bnetz_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/libtimer/libtimer.a \
$(top_builddir)/src/libsamplerate/libsamplerate.a \
$(top_builddir)/src/libemphasis/libemphasis.a \
$(top_builddir)/src/libfsk/libfsk.a \
@ -27,10 +30,8 @@ bnetz_LDADD = \
$(top_builddir)/src/libfilter/libfilter.a \
$(top_builddir)/src/libwave/libwave.a \
$(top_builddir)/src/libsample/libsample.a \
$(top_builddir)/src/libg711/libg711.a \
$(top_builddir)/src/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
-lm
bnetz_dialer_SOURCES = \
@ -39,14 +40,12 @@ bnetz_dialer_SOURCES = \
bnetz_dialer_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.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/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
$(ALSA_LIBS)
-lm

View File

@ -25,33 +25,32 @@
#include <string.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
#include "../libmobile/get_time.h"
#include <osmocom/cc/message.h>
#include "../libosmocc/message.h"
#include "bnetz.h"
#include "telegramm.h"
#include "dsp.h"
/* mobile originating call */
#define CARRIER_TO 0.080000 /* 80 ms search for carrier */
#define DIALING_TO 3,800000 /* timeout after channel allocation "Kanalbelegung" (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.8) */
#define DIALING_TO2 0,500000 /* timeout while receiving digits */
#define CARRIER_TO 0.08 /* 80 ms search for carrier */
#define DIALING_TO 3.8 /* timeout after channel allocation "Kanalbelegung" (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.8) */
#define DIALING_TO2 0.5 /* timeout while receiving digits */
/* mobile terminating call */
#define ALERTING_TO 60,0 /* timeout after 60 seconds alerting the MS (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.7) */
#define PAGING_TO 2,100000 /* 700..2100 ms timeout after paging "Selektivruf" (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.4.3) */
#define PAGE_TRIES 2 /* two tries (see Clause 3.2.2.2.4.3) */
#define SWITCH19_TIME 1,0 /* time to switch channel (radio should be tansmitting after that) */
#define SWITCHBACK_TIME 0,100000 /* time to wait until switching back (latency of sound device shall be lower) */
#define ALERTING_TO 60 /* timeout after 60 seconds alerting the MS (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.7) */
#define PAGING_TO 2.1 /* 700..2100 ms timeout after paging "Selektivruf" (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.4.3) */
#define PAGE_TRIES 2 /* two tries (see Clause 3.2.2.2.4.3) */
#define SWITCH19_TIME 1.0 /* time to switch channel (radio should be tansmitting after that) */
#define SWITCHBACK_TIME 0.1 /* time to wait until switching back (latency of sound device shall be lower) */
#define TRENN_COUNT 5 /* min. 720 ms release 'Trennsignal' (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.6) */
#define TRENN_COUNT 5 /* min. 720 ms release 'Trennsignal' (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.6) */
#define METERING_DURATION_US 140000 /* duration of metering pulse (according to FTZ 1727 Pfl 32 Clause 3.2.6.6.1) */
#define METERING_START 1,0 /* start metering 1 second after call start */
#define METERING_DURATION 0.140 /* duration of metering pulse (according to FTZ 1727 Pfl 32 Clause 3.2.6.6.1) */
#define METERING_START 1.0 /* start metering 1 second after call start */
static const char *bnetz_state_name(enum bnetz_state state)
const char *bnetz_state_name(enum bnetz_state state)
{
static char invalid[16];
@ -80,7 +79,7 @@ static const char *bnetz_state_name(enum bnetz_state state)
return invalid;
}
static void bnetz_display_status(void)
void bnetz_display_status(void)
{
sender_t *sender;
bnetz_t *bnetz;
@ -100,7 +99,7 @@ static void bnetz_new_state(bnetz_t *bnetz, enum bnetz_state new_state)
{
if (bnetz->state == new_state)
return;
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "State change: %s -> %s\n", bnetz_state_name(bnetz->state), bnetz_state_name(new_state));
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "State change: %s -> %s\n", bnetz_state_name(bnetz->state), bnetz_state_name(new_state));
bnetz->state = new_state;
bnetz_display_status();
}
@ -134,7 +133,7 @@ static void switch_channel_19(bnetz_t *bnetz, int on)
fp = fopen(bnetz->paging_file, "w");
if (!fp) {
LOGP(DBNETZ, LOGL_ERROR, "Failed to open file '%s' to switch channel 19!\n", bnetz->paging_file);
PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to open file '%s' to switch channel 19!\n", bnetz->paging_file);
return;
}
fprintf(fp, "%s\n", (on) ? bnetz->paging_on : bnetz->paging_off);
@ -151,7 +150,7 @@ int bnetz_init(void)
return 0;
}
static void bnetz_timeout(void *data);
static void bnetz_timeout(struct timer *timer);
static void bnetz_go_idle(bnetz_t *bnetz);
/* Create transceiver instance and link to a list. */
@ -163,22 +162,22 @@ int bnetz_create(const char *kanal, const char *device, int use_sdr, int sampler
int rc;
if (!(atoi(kanal) >= 1 && atoi(kanal) <= 39) && !(atoi(kanal) >= 50 && atoi(kanal) <= 86)) {
LOGP(DBNETZ, LOGL_ERROR, "Channel ('Kanal') number %s invalid.\n", kanal);
PDEBUG(DBNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid.\n", kanal);
return -EINVAL;
}
if (atoi(kanal) == 19) {
LOGP(DBNETZ, LOGL_ERROR, "Selected calling channel ('Rufkanal') number %s can't be used as traffic channel.\n", kanal);
PDEBUG(DBNETZ, DEBUG_ERROR, "Selected calling channel ('Rufkanal') number %s can't be used as traffic channel.\n", kanal);
return -EINVAL;
}
if (atoi(kanal) >= 38 && atoi(kanal) <= 39)
LOGP(DBNETZ, LOGL_NOTICE, "Selected channel ('Kanal') number %s may not be supported by older B1-Network phones.\n", kanal);
PDEBUG(DBNETZ, DEBUG_NOTICE, "Selected channel ('Kanal') number %s may not be supported by older B1-Network phones.\n", kanal);
if (atoi(kanal) >= 50)
LOGP(DBNETZ, LOGL_NOTICE, "Selected channel ('Kanal') number %s belongs to B2-Network and is not supported by B1 phones.\n", kanal);
PDEBUG(DBNETZ, DEBUG_NOTICE, "Selected channel ('Kanal') number %s belongs to B2-Network and is not supported by B1 phones.\n", kanal);
if ((gfs < 1 || gfs > 19)) {
LOGP(DBNETZ, LOGL_ERROR, "Given 'Gruppenfreisignal' %d invalid.\n", gfs);
PDEBUG(DBNETZ, DEBUG_ERROR, "Given 'Gruppenfreisignal' %d invalid.\n", gfs);
return -EINVAL;
}
@ -200,7 +199,7 @@ int bnetz_create(const char *kanal, const char *device, int use_sdr, int sampler
p = strchr(paging_file, '=');
if (!p) {
error_paging:
LOGP(DBNETZ, LOGL_ERROR, "Given paging file (to switch to channel 19) is missing parameters. Use <file>=<on>:<off> format!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "Given paging file (to switch to channel 19) is missing parameters. Use <file>=<on>:<off> format!\n");
return -EINVAL;
}
*p++ = '\0';
@ -214,16 +213,16 @@ error_paging:
bnetz = calloc(1, sizeof(bnetz_t));
if (!bnetz) {
LOGP(DBNETZ, LOGL_ERROR, "No memory!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "No memory!\n");
return -ENOMEM;
}
LOGP(DBNETZ, LOGL_DEBUG, "Creating 'B-Netz' instance for 'Kanal' = %s 'Gruppenfreisignal' = %d (sample rate %d).\n", kanal, gfs, samplerate);
PDEBUG(DBNETZ, DEBUG_DEBUG, "Creating 'B-Netz' instance for 'Kanal' = %s 'Gruppenfreisignal' = %d (sample rate %d).\n", kanal, gfs, samplerate);
/* init general part of transceiver */
rc = sender_create(&bnetz->sender, kanal, bnetz_kanal2freq(atoi(kanal), 0), bnetz_kanal2freq(atoi(kanal), 1), device, use_sdr, samplerate, rx_gain, tx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, paging_signal);
if (rc < 0) {
LOGP(DBNETZ, LOGL_ERROR, "Failed to init transceiver process!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
goto error;
}
bnetz->sender.ruffrequenz = bnetz_kanal2freq(19, 0);
@ -231,7 +230,7 @@ error_paging:
/* init audio processing */
rc = dsp_init_sender(bnetz, squelch_db);
if (rc < 0) {
LOGP(DBNETZ, LOGL_ERROR, "Failed to init audio processing!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to init audio processing!\n");
goto error;
}
@ -240,13 +239,13 @@ error_paging:
strncpy(bnetz->paging_file, paging_file, sizeof(bnetz->paging_file) - 1);
strncpy(bnetz->paging_on, paging_on, sizeof(bnetz->paging_on) - 1);
strncpy(bnetz->paging_off, paging_off, sizeof(bnetz->paging_off) - 1);
osmo_timer_setup(&bnetz->timer, bnetz_timeout, bnetz);
timer_init(&bnetz->timer, bnetz_timeout, bnetz);
/* go into idle state */
bnetz_go_idle(bnetz);
LOGP(DBNETZ, LOGL_NOTICE, "Created 'Kanal' #%s\n", kanal);
LOGP(DBNETZ, LOGL_NOTICE, " -> Using station ID (Gruppenfreisignal) %d\n", gfs);
PDEBUG(DBNETZ, DEBUG_NOTICE, "Created 'Kanal' #%s\n", kanal);
PDEBUG(DBNETZ, DEBUG_NOTICE, " -> Using station ID (Gruppenfreisignal) %d\n", gfs);
return 0;
@ -261,10 +260,10 @@ void bnetz_destroy(sender_t *sender)
{
bnetz_t *bnetz = (bnetz_t *) sender;
LOGP(DBNETZ, LOGL_DEBUG, "Destroying 'B-Netz' instance for 'Kanal' = %s.\n", sender->kanal);
PDEBUG(DBNETZ, DEBUG_DEBUG, "Destroying 'B-Netz' instance for 'Kanal' = %s.\n", sender->kanal);
switch_channel_19(bnetz, 0);
dsp_cleanup_sender(bnetz);
osmo_timer_del(&bnetz->timer);
timer_exit(&bnetz->timer);
sender_destroy(&bnetz->sender);
free(bnetz);
}
@ -272,9 +271,9 @@ void bnetz_destroy(sender_t *sender)
/* releaseing connection towards mobile station by sending idle digits. */
static void bnetz_go_idle(bnetz_t *bnetz)
{
osmo_timer_del(&bnetz->timer);
timer_stop(&bnetz->timer);
LOGP(DBNETZ, LOGL_INFO, "Entering IDLE state on channel %s, sending 'Gruppenfreisignal' %d.\n", bnetz->sender.kanal, bnetz->gfs);
PDEBUG(DBNETZ, DEBUG_INFO, "Entering IDLE state on channel %s, sending 'Gruppenfreisignal' %d.\n", bnetz->sender.kanal, bnetz->gfs);
bnetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
bnetz_new_state(bnetz, BNETZ_FREI);
bnetz_set_dsp_mode(bnetz, DSP_MODE_TELEGRAMM);
@ -284,9 +283,9 @@ static void bnetz_go_idle(bnetz_t *bnetz)
/* Release connection towards mobile station by sending release digits. */
static void bnetz_release(bnetz_t *bnetz, int trenn_count)
{
osmo_timer_del(&bnetz->timer);
timer_stop(&bnetz->timer);
LOGP_CHAN(DBNETZ, LOGL_INFO, "Entering release state, sending 'Trennsignal' (%d times).\n", trenn_count);
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Entering release state, sending 'Trennsignal' (%d times).\n", trenn_count);
bnetz->station_id[0] = '\0'; /* remove station ID before state change, so status is shown correctly */
bnetz_new_state(bnetz, BNETZ_TRENNEN);
bnetz_set_dsp_mode(bnetz, DSP_MODE_TELEGRAMM);
@ -297,14 +296,14 @@ static void bnetz_release(bnetz_t *bnetz, int trenn_count)
/* Enter paging state and transmit station ID. */
static void bnetz_page(bnetz_t *bnetz, const char *dial_string, int try)
{
LOGP_CHAN(DBNETZ, LOGL_INFO, "Entering paging state (try %d), sending 'Selektivruf' to '%s'.\n", try, dial_string);
memmove(bnetz->station_id, dial_string, strlen(dial_string) + 1); /* set station ID before state change, so status is shown correctly */
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Entering paging state (try %d), sending 'Selektivruf' to '%s'.\n", try, dial_string);
strcpy(bnetz->station_id, dial_string); /* set station ID before state change, so status is shown correctly */
bnetz->station_id_pos = 0;
bnetz_new_state(bnetz, BNETZ_SELEKTIVRUF_EIN);
bnetz_set_dsp_mode(bnetz, DSP_MODE_0);
bnetz->page_mode = PAGE_MODE_NUMBER;
bnetz->page_try = try;
osmo_timer_schedule(&bnetz->timer, SWITCH19_TIME);
timer_start(&bnetz->timer, SWITCH19_TIME);
switch_channel_19(bnetz, 1);
}
@ -333,10 +332,10 @@ const char *bnetz_get_telegramm(bnetz_t *bnetz)
break;
case BNETZ_SELEKTIVRUF_EIN:
if (bnetz->page_mode == PAGE_MODE_KANALBEFEHL) {
LOGP_CHAN(DBNETZ, LOGL_INFO, "Paging mobile station %s complete, waiting for answer.\n", bnetz->station_id);
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Paging mobile station %s complete, waiting for answer.\n", bnetz->station_id);
bnetz_new_state(bnetz, BNETZ_SELEKTIVRUF_AUS);
bnetz_set_dsp_mode(bnetz, DSP_MODE_SILENCE);
osmo_timer_schedule(&bnetz->timer, SWITCHBACK_TIME);
timer_start(&bnetz->timer, SWITCHBACK_TIME);
return NULL;
}
if (bnetz->station_id_pos == 5) {
@ -348,7 +347,7 @@ const char *bnetz_get_telegramm(bnetz_t *bnetz)
break;
case BNETZ_TRENNEN:
if (bnetz->trenn_count-- == 0) {
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "Maximum number of release digits sent, going idle.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "Maximum number of release digits sent, going idle.\n");
bnetz_go_idle(bnetz);
return NULL;
}
@ -361,7 +360,7 @@ const char *bnetz_get_telegramm(bnetz_t *bnetz)
if (!it)
abort();
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "Sending telegramm '%s'.\n", it->description);
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "Sending telegramm '%s'.\n", it->description);
return it->sequence;
}
@ -370,7 +369,7 @@ void bnetz_loss_indication(bnetz_t *bnetz, double loss_time)
{
if (bnetz->state == BNETZ_GESPRAECH
|| bnetz->state == BNETZ_RUFHALTUNG) {
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Detected loss of signal after %.1f seconds, releasing.\n", loss_time);
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Detected loss of signal after %.1f seconds, releasing.\n", loss_time);
bnetz_release(bnetz, TRENN_COUNT);
call_up_release(bnetz->callref, CAUSE_TEMPFAIL);
bnetz->callref = 0;
@ -381,9 +380,9 @@ void bnetz_loss_indication(bnetz_t *bnetz, double loss_time)
void bnetz_receive_tone(bnetz_t *bnetz, int bit)
{
if (bit >= 0)
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "Received continuous %d Hz tone.\n", (bit)?1950:2070);
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "Received continuous %d Hz tone.\n", (bit)?1950:2070);
else
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "Continuous tone is gone.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "Continuous tone is gone.\n");
if (bnetz->sender.loopback) {
return;
@ -392,11 +391,11 @@ void bnetz_receive_tone(bnetz_t *bnetz, int bit)
switch (bnetz->state) {
case BNETZ_FREI:
if (bit == 0) {
LOGP_CHAN(DBNETZ, LOGL_INFO, "Received signal 'Kanalbelegung' from mobile station, sending signal 'Wahlabruf'.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Received signal 'Kanalbelegung' from mobile station, sending signal 'Wahlabruf'.\n");
bnetz_new_state(bnetz, BNETZ_WAHLABRUF);
bnetz->dial_mode = DIAL_MODE_START;
bnetz_set_dsp_mode(bnetz, DSP_MODE_1);
osmo_timer_schedule(&bnetz->timer, DIALING_TO);
timer_start(&bnetz->timer, DIALING_TO);
/* must reset, so we will not get corrupt first digit */
bnetz->rx_telegramm = bnetz->tone_detected * 0xffff;
break;
@ -404,27 +403,24 @@ void bnetz_receive_tone(bnetz_t *bnetz, int bit)
break;
case BNETZ_RUFBESTAETIGUNG:
if (bit == 1) {
LOGP_CHAN(DBNETZ, LOGL_INFO, "Received signal 'Rufbestaetigung' from mobile station, sending signal 'Rufhaltung'. (call is ringing)\n");
osmo_timer_del(&bnetz->timer);
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Received signal 'Rufbestaetigung' from mobile station, sending signal 'Rufhaltung'. (call is ringing)\n");
timer_stop(&bnetz->timer);
bnetz_new_state(bnetz, BNETZ_RUFHALTUNG);
bnetz_set_dsp_mode(bnetz, DSP_MODE_1);
call_up_alerting(bnetz->callref);
osmo_timer_schedule(&bnetz->timer, ALERTING_TO);
timer_start(&bnetz->timer, ALERTING_TO);
break;
}
break;
case BNETZ_RUFHALTUNG:
if (bit == 0) {
LOGP_CHAN(DBNETZ, LOGL_INFO, "Received signal 'Beginnsignal' from mobile station, call establised.\n");
osmo_timer_del(&bnetz->timer);
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Received signal 'Beginnsignal' from mobile station, call establised.\n");
timer_stop(&bnetz->timer);
bnetz_new_state(bnetz, BNETZ_GESPRAECH);
bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO);
/* start metering pulses, if forced (mobile terminating call) */
if (bnetz->metering < 0) {
bnetz->metering_tv.tv_sec = abs(bnetz->metering);
bnetz->metering_tv.tv_usec = 0;
osmo_timer_schedule(&bnetz->timer, METERING_START);
}
/* start metering pulses if forced */
if (bnetz->metering < 0)
timer_start(&bnetz->timer, METERING_START);
call_up_answer(bnetz->callref, bnetz->station_id);
break;
}
@ -442,22 +438,22 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
it = bnetz_telegramm2digit(telegramm);
if (it) {
digit = it->digit;
LOGP(DBNETZ, (bnetz->sender.loopback) ? LOGL_NOTICE : LOGL_INFO, "Received telegramm '%s'\n", it->description);
PDEBUG(DBNETZ, (bnetz->sender.loopback) ? DEBUG_NOTICE : DEBUG_INFO, "Received telegramm '%s'\n", it->description);
} else {
LOGP(DBNETZ, LOGL_DEBUG, "Received unknown telegramm digit '0x%04x' (might be radio noise)\n", telegramm);
PDEBUG(DBNETZ, DEBUG_DEBUG, "Received unknown telegramm digit '0x%04x' (might be radio noise)\n", telegramm);
return;
}
if (bnetz->sender.loopback) {
if (digit >= '0' && digit <= '9') {
LOGP(DBNETZ, LOGL_NOTICE, "Round trip delay is %.3f seconds\n", get_time() - bnetz->loopback_time[digit - '0'] - 0.160);
PDEBUG(DBNETZ, DEBUG_NOTICE, "Round trip delay is %.3f seconds\n", get_time() - bnetz->loopback_time[digit - '0'] - 0.160);
}
return;
}
switch (bnetz->state) {
case BNETZ_WAHLABRUF:
osmo_timer_schedule(&bnetz->timer, DIALING_TO2);
timer_start(&bnetz->timer, DIALING_TO2);
switch (bnetz->dial_mode) {
case DIAL_MODE_START:
switch (digit) {
@ -471,7 +467,7 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
bnetz->dial_type = DIAL_TYPE_METER_MUENZ;
break;
default:
LOGP(DBNETZ, LOGL_NOTICE, "Received digit that is not a start digit ('Funkwahl'), releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received digit that is not a start digit ('Funkwahl'), releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
@ -481,7 +477,7 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
break;
case DIAL_MODE_STATIONID:
if (digit < '0' || digit > '9') {
LOGP(DBNETZ, LOGL_NOTICE, "Received message that is not a valid station id digit, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received message that is not a valid station id digit, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
@ -489,29 +485,29 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
/* update status while receiving station ID */
bnetz_display_status();
if (bnetz->dial_pos == 5) {
LOGP(DBNETZ, LOGL_INFO, "Received station id from mobile phone: %s\n", bnetz->station_id);
PDEBUG(DBNETZ, DEBUG_INFO, "Received station id from mobile phone: %s\n", bnetz->station_id);
bnetz->dial_mode = DIAL_MODE_NUMBER;
memset(bnetz->dial_number, 0, sizeof(bnetz->dial_number));
bnetz->dial_pos = 0;
/* reply station ID */
LOGP(DBNETZ, LOGL_INFO, "Sending station id back to phone: %s.\n", bnetz->station_id);
PDEBUG(DBNETZ, DEBUG_INFO, "Sending station id back to phone: %s.\n", bnetz->station_id);
bnetz_set_dsp_mode(bnetz, DSP_MODE_TELEGRAMM);
bnetz->station_id_pos = 0;
}
break;
case DIAL_MODE_NUMBER:
if (digit == 'e') {
LOGP(DBNETZ, LOGL_INFO, "Received number from mobile phone: %s\n", bnetz->dial_number);
PDEBUG(DBNETZ, DEBUG_INFO, "Received number from mobile phone: %s\n", bnetz->dial_number);
bnetz->dial_mode = DIAL_MODE_START2;
break;
}
if (digit < '0' || digit > '9') {
LOGP(DBNETZ, LOGL_NOTICE, "Received message that is not a valid number digit, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received message that is not a valid number digit, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
if (bnetz->dial_pos == sizeof(bnetz->dial_number) - 1) {
LOGP(DBNETZ, LOGL_NOTICE, "Received too many number digits, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received too many number digits, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
@ -521,27 +517,27 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
switch (digit) {
case 's':
if (bnetz->dial_type != DIAL_TYPE_NOMETER) {
LOGP(DBNETZ, LOGL_NOTICE, "Repeated start message ('Funkwahl') does not match first one (no metering support), releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Repeated start message ('Funkwahl') does not match first one (no metering support), releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
break;
case 'S':
if (bnetz->dial_type != DIAL_TYPE_METER) {
LOGP(DBNETZ, LOGL_NOTICE, "Repeated start message ('Funkwahl') does not match first one (metering support), releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Repeated start message ('Funkwahl') does not match first one (metering support), releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
break;
case 'M':
if (bnetz->dial_type != DIAL_TYPE_METER_MUENZ) {
LOGP(DBNETZ, LOGL_NOTICE, "Repeated start message ('Funkwahl') does not match first one (metering support, payphone), releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Repeated start message ('Funkwahl') does not match first one (metering support, payphone), releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
break;
default:
LOGP(DBNETZ, LOGL_NOTICE, "Repeated digit is not a start digit ('Funkwahl'), releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Repeated digit is not a start digit ('Funkwahl'), releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
@ -550,12 +546,12 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
break;
case DIAL_MODE_STATIONID2:
if (digit < '0' || digit > '9') {
LOGP(DBNETZ, LOGL_NOTICE, "Received message that is not a valid station id digit, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received message that is not a valid station id digit, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
if (bnetz->station_id[bnetz->dial_pos++] != digit) {
LOGP(DBNETZ, LOGL_NOTICE, "Repeated station id does not match the first one, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Repeated station id does not match the first one, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
@ -571,40 +567,43 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
strcpy(dialing + 1, bnetz->dial_number);
if (bnetz->dial_pos != (int)strlen(bnetz->dial_number)) {
LOGP(DBNETZ, LOGL_NOTICE, "Received too few repeated number digits, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received too few repeated number digits, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
if (!strncmp(dialing, "0110", 4)) {
LOGP(DBNETZ, LOGL_INFO, "Translating emergency number to '110'.\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Translating emergency number to '110'.\n");
strcpy(dialing, "110");
}
if (!strncmp(dialing, "0112", 4)) {
LOGP(DBNETZ, LOGL_INFO, "Translating emergency number to '112'.\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Translating emergency number to '112'.\n");
strcpy(dialing, "112");
}
LOGP(DBNETZ, LOGL_INFO, "Dialing complete %s->%s, call established.\n", bnetz->station_id, dialing);
osmo_timer_del(&bnetz->timer);
PDEBUG(DBNETZ, DEBUG_INFO, "Dialing complete %s->%s, call established.\n", bnetz->station_id, dialing);
timer_stop(&bnetz->timer);
bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO);
bnetz_new_state(bnetz, BNETZ_GESPRAECH);
/* start metering pulses if enabled and supported by phone or if forced */
if (bnetz->metering < 0 || (bnetz->metering > 0 && (bnetz->dial_type == DIAL_TYPE_METER || bnetz->dial_type == DIAL_TYPE_METER_MUENZ)))
timer_start(&bnetz->timer, METERING_START);
/* setup call */
LOGP(DBNETZ, LOGL_INFO, "Setup call to network.\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Setup call to network.\n");
bnetz->callref = call_up_setup(bnetz->station_id, dialing, OSMO_CC_NETWORK_BNETZ_MUENZ, (bnetz->dial_type == DIAL_TYPE_METER_MUENZ) ? "MUENZ" : "");
break;
}
if (digit < '0' || digit > '9') {
LOGP(DBNETZ, LOGL_NOTICE, "Received message that is not a valid number digit, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received message that is not a valid number digit, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
if (bnetz->dial_pos == (int)strlen(bnetz->dial_number)) {
LOGP(DBNETZ, LOGL_NOTICE, "Received too many number digits, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received too many number digits, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
if (bnetz->dial_number[bnetz->dial_pos++] != digit) {
LOGP(DBNETZ, LOGL_NOTICE, "Repeated number does not match the first one, releaseing.\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Repeated number does not match the first one, releaseing.\n");
bnetz_release(bnetz, TRENN_COUNT);
return;
}
@ -619,7 +618,7 @@ lets see, if noise will not generate a release signal....
return;
#endif
if (digit == 't') {
LOGP(DBNETZ, LOGL_NOTICE, "Received 'Schlusssignal' from mobile station\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Received 'Schlusssignal' from mobile station\n");
bnetz_release(bnetz, TRENN_COUNT);
call_up_release(bnetz->callref, CAUSE_NORMAL);
bnetz->callref = 0;
@ -632,39 +631,38 @@ lets see, if noise will not generate a release signal....
}
/* Timeout handling */
static void bnetz_timeout(void *data)
static void bnetz_timeout(struct timer *timer)
{
bnetz_t *bnetz = data;
int to_sec, to_usec;
bnetz_t *bnetz = (bnetz_t *)timer->priv;
switch (bnetz->state) {
case BNETZ_WAHLABRUF:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Timeout while receiving call setup from mobile station, releasing.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Timeout while receiving call setup from mobile station, releasing.\n");
bnetz_release(bnetz, TRENN_COUNT);
break;
case BNETZ_SELEKTIVRUF_EIN:
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "Transmitter switched to channel 19, starting paging telegramms.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "Transmitter switched to channel 19, starting paging telegramms.\n");
bnetz_set_dsp_mode(bnetz, DSP_MODE_TELEGRAMM);
break;
case BNETZ_SELEKTIVRUF_AUS:
LOGP_CHAN(DBNETZ, LOGL_DEBUG, "Transmitter switched back to channel %s, waiting for paging response.\n", bnetz->sender.kanal);
PDEBUG_CHAN(DBNETZ, DEBUG_DEBUG, "Transmitter switched back to channel %s, waiting for paging response.\n", bnetz->sender.kanal);
bnetz_new_state(bnetz, BNETZ_RUFBESTAETIGUNG);
switch_channel_19(bnetz, 0);
osmo_timer_schedule(&bnetz->timer, PAGING_TO);
timer_start(&bnetz->timer, PAGING_TO);
break;
case BNETZ_RUFBESTAETIGUNG:
if (bnetz->page_try == PAGE_TRIES) {
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Timeout while waiting for call acknowledge from mobile station, releasing.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Timeout while waiting for call acknowledge from mobile station, releasing.\n");
bnetz_release(bnetz, TRENN_COUNT);
call_up_release(bnetz->callref, CAUSE_OUTOFORDER);
bnetz->callref = 0;
break;
}
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Timeout while waiting for call acknowledge from mobile station, trying again.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Timeout while waiting for call acknowledge from mobile station, trying again.\n");
bnetz_page(bnetz, bnetz->station_id, bnetz->page_try + 1);
break;
case BNETZ_RUFHALTUNG:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Timeout while waiting for answer of mobile station, releasing.\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Timeout while waiting for answer of mobile station, releasing.\n");
bnetz_release(bnetz, TRENN_COUNT);
call_up_release(bnetz->callref, CAUSE_NOANSWER);
bnetz->callref = 0;
@ -674,21 +672,12 @@ static void bnetz_timeout(void *data)
case DSP_MODE_AUDIO:
/* turn on merting pulse */
bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO_METER);
osmo_timer_schedule(&bnetz->timer, 0, METERING_DURATION_US);
timer_start(&bnetz->timer, METERING_DURATION);
break;
case DSP_MODE_AUDIO_METER:
/* turn off and wait given seconds for next metering cycle */
bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO);
/* if metering has been disabled due to disconnect (must be at least 1s) */
if (!bnetz->metering_tv.tv_sec)
break;
to_sec = bnetz->metering_tv.tv_sec;
to_usec = bnetz->metering_tv.tv_usec - METERING_DURATION_US;
if (to_usec < 0) {
to_usec += 1000000;
to_sec--;
}
osmo_timer_schedule(&bnetz->timer, to_sec, to_usec);
timer_start(&bnetz->timer, (double)abs(bnetz->metering) - METERING_DURATION);
break;
default:
break;
@ -712,7 +701,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
break;
}
if (sender) {
LOGP(DBNETZ, LOGL_NOTICE, "Outgoing call to busy number, rejecting!\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
return -CAUSE_BUSY;
}
@ -723,11 +712,11 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
break;
}
if (!sender) {
LOGP(DBNETZ, LOGL_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
return -CAUSE_NOCHANNEL;
}
LOGP_CHAN(DBNETZ, LOGL_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
PDEBUG_CHAN(DBNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
/* 3. trying to page mobile station */
bnetz->callref = callref;
@ -736,35 +725,8 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
return 0;
}
void call_down_answer(int callref, struct timeval *tv_meter)
void call_down_answer(int __attribute__((unused)) callref)
{
sender_t *sender;
bnetz_t *bnetz;
LOGP(DBNETZ, LOGL_INFO, "Call has been answered by network.\n");
for (sender = sender_head; sender; sender = sender->next) {
bnetz = (bnetz_t *) sender;
if (bnetz->callref == callref)
break;
}
if (!sender) {
LOGP(DBNETZ, LOGL_NOTICE, "Incoming answer, but no callref!\n");
return;
}
/* At least tone second! */
if (tv_meter->tv_sec) {
LOGP(DBNETZ, LOGL_INFO, "Network starts metering pulses every %lu.%03lu seconds.\n", tv_meter->tv_sec, tv_meter->tv_usec / 1000);
memcpy(&bnetz->metering_tv, tv_meter, sizeof(bnetz->metering_tv));
osmo_timer_schedule(&bnetz->timer, METERING_START);
} else if (bnetz->metering < 0 || (bnetz->metering > 0 && (bnetz->dial_type == DIAL_TYPE_METER || bnetz->dial_type == DIAL_TYPE_METER_MUENZ))) {
/* start metering pulses if enabled and supported by phone or if forced (mobile origninating call) */
LOGP(DBNETZ, LOGL_INFO, "Command line options starts metering pulses every %d seconds.\n", abs(bnetz->metering));
bnetz->metering_tv.tv_sec = abs(bnetz->metering);
bnetz->metering_tv.tv_usec = 0;
osmo_timer_schedule(&bnetz->timer, METERING_START);
}
}
/* Call control sends disconnect (with tones).
@ -776,7 +738,7 @@ void call_down_disconnect(int callref, int cause)
sender_t *sender;
bnetz_t *bnetz;
LOGP(DBNETZ, LOGL_INFO, "Call has been disconnected by network.\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Call has been disconnected by network.\n");
for (sender = sender_head; sender; sender = sender->next) {
bnetz = (bnetz_t *) sender;
@ -784,27 +746,23 @@ void call_down_disconnect(int callref, int cause)
break;
}
if (!sender) {
LOGP(DBNETZ, LOGL_NOTICE, "Outgoing disconnect, but no callref!\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n");
call_up_release(callref, CAUSE_INVALCALLREF);
return;
}
/* Release when not active */
if (bnetz->state == BNETZ_GESPRAECH) {
/* stop metering */
bnetz->metering_tv.tv_sec = 0;
bnetz->metering_tv.tv_usec = 0;
if (bnetz->state == BNETZ_GESPRAECH)
return;
}
switch (bnetz->state) {
case BNETZ_SELEKTIVRUF_EIN:
case BNETZ_SELEKTIVRUF_AUS:
case BNETZ_RUFBESTAETIGUNG:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Outgoing disconnect, during paging, releasing!\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Outgoing disconnect, during paging, releasing!\n");
bnetz_release(bnetz, TRENN_COUNT);
break;
case BNETZ_RUFHALTUNG:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Outgoing disconnect, during alerting, releasing!\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Outgoing disconnect, during alerting, releasing!\n");
bnetz_release(bnetz, TRENN_COUNT);
break;
default:
@ -822,7 +780,7 @@ void call_down_release(int callref, int __attribute__((unused)) cause)
sender_t *sender;
bnetz_t *bnetz;
LOGP(DBNETZ, LOGL_INFO, "Call has been released by network, releasing call.\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Call has been released by network, releasing call.\n");
for (sender = sender_head; sender; sender = sender->next) {
bnetz = (bnetz_t *) sender;
@ -830,7 +788,7 @@ void call_down_release(int callref, int __attribute__((unused)) cause)
break;
}
if (!sender) {
LOGP(DBNETZ, LOGL_NOTICE, "Outgoing release, but no callref!\n");
PDEBUG(DBNETZ, DEBUG_NOTICE, "Outgoing release, but no callref!\n");
/* don't send release, because caller already released */
return;
}
@ -839,17 +797,17 @@ void call_down_release(int callref, int __attribute__((unused)) cause)
switch (bnetz->state) {
case BNETZ_GESPRAECH:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Outgoing release, during call, releasing!\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Outgoing release, during call, releasing!\n");
bnetz_release(bnetz, TRENN_COUNT);
break;
case BNETZ_SELEKTIVRUF_EIN:
case BNETZ_SELEKTIVRUF_AUS:
case BNETZ_RUFBESTAETIGUNG:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Outgoing release, during paging, releasing!\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Outgoing release, during paging, releasing!\n");
bnetz_release(bnetz, TRENN_COUNT);
break;
case BNETZ_RUFHALTUNG:
LOGP_CHAN(DBNETZ, LOGL_NOTICE, "Outgoing release, during alerting, releasing!\n");
PDEBUG_CHAN(DBNETZ, DEBUG_NOTICE, "Outgoing release, during alerting, releasing!\n");
bnetz_release(bnetz, TRENN_COUNT);
break;
default:
@ -857,5 +815,29 @@ void call_down_release(int callref, int __attribute__((unused)) cause)
}
}
/* Receive audio from call instance. */
void call_down_audio(int callref, sample_t *samples, int count)
{
sender_t *sender;
bnetz_t *bnetz;
for (sender = sender_head; sender; sender = sender->next) {
bnetz = (bnetz_t *) sender;
if (bnetz->callref == callref)
break;
}
if (!sender)
return;
if (bnetz->dsp_mode == DSP_MODE_AUDIO
|| bnetz->dsp_mode == DSP_MODE_AUDIO_METER) {
sample_t up[(int)((double)count * bnetz->sender.srstate.factor + 0.5) + 10];
count = samplerate_upsample(&bnetz->sender.srstate, samples, count, up);
jitter_save(&bnetz->sender.dejitter, up, count);
}
}
void call_down_clock(void) {}
void dump_info(void) {}

View File

@ -1,7 +1,7 @@
#include "../libsquelch/squelch.h"
#include "../libfsk/fsk.h"
#include "../libmobile/sender.h"
#include <osmocom/core/timer.h>
#include "../libtimer/timer.h"
/* fsk modes of transmission */
enum dsp_mode {
@ -56,7 +56,6 @@ typedef struct bnetz {
/* system info */
int gfs; /* 'Gruppenfreisignal' */
int metering; /* use metering pulses in seconds 0 = off, < 0 = force */
struct timeval metering_tv; /* time to repeat metering pulse (current call) */
/* switch sender to channel 19 */
char paging_file[256]; /* if set, write to given file to switch to channel 19 or back */
@ -75,7 +74,7 @@ typedef struct bnetz {
int station_id_pos; /* position while transmitting */
enum page_mode page_mode; /* sub state while paging */
int page_try; /* try number (1 or 2) */
struct osmo_timer_list timer;
struct timer timer;
int trenn_count; /* count number of release messages */
/* display measurements */

View File

@ -26,7 +26,7 @@
#include "../libsample/sample.h"
#include "../libfsk/fsk.h"
#include "../libwave/wave.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#ifdef HAVE_ALSA
#include "../libsound/sound.h"
#endif
@ -68,11 +68,8 @@ wave_rec_t wave_tx_rec;
/* dummy functions */
int num_kanal = 1; /* only one channel used for debugging */
void *get_sender_by_empfangsfrequenz(void);
void *get_sender_by_empfangsfrequenz() { return NULL; }
void display_measurements_add(void);
void display_measurements_add() {}
void display_measurements_update(void);
void display_measurements_update() {}
#define OPT_METERING 1000
@ -164,13 +161,13 @@ static int fsk_send_bit(void __attribute__((unused)) *inst)
if (!tx_telegramm || tx_telegramm_pos == 16) {
switch (funkwahl[digit_pos]) {
case '\0':
LOGP(DBNETZ, LOGL_INFO, "Done sending dialing sequence\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Done sending dialing sequence\n");
tx_mode = TX_MODE_SILENCE;
tx_silence_count = 0;
return -1;
case 'w':
if (!tx_telegramm)
LOGP(DBNETZ, LOGL_INFO, "Sending channel allocation tone ('Kanalbelegung')\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Sending channel allocation tone ('Kanalbelegung')\n");
tx_telegramm = "0000000000000000";
tx_telegramm_pos = 0;
digit_pos++;
@ -178,23 +175,23 @@ static int fsk_send_bit(void __attribute__((unused)) *inst)
default:
switch (funkwahl[digit_pos]) {
case 's':
LOGP(DBNETZ, LOGL_INFO, "Sending start digit (no charging meater on board)\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Sending start digit (no charging meater on board)\n");
break;
case 'S':
LOGP(DBNETZ, LOGL_INFO, "Sending start digit (with charging meater on board)\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Sending start digit (with charging meater on board)\n");
break;
case 'M':
LOGP(DBNETZ, LOGL_INFO, "Sending start digit (Phone is a coin box.)\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Sending start digit (Phone is a coin box.)\n");
break;
case 'e':
LOGP(DBNETZ, LOGL_INFO, "Sending stop digit\n");
PDEBUG(DBNETZ, DEBUG_INFO, "Sending stop digit\n");
break;
default:
LOGP(DBNETZ, LOGL_INFO, "Sending digit '%c'\n", funkwahl[digit_pos]);
PDEBUG(DBNETZ, DEBUG_INFO, "Sending digit '%c'\n", funkwahl[digit_pos]);
}
impulstelegramm = bnetz_digit2telegramm(funkwahl[digit_pos]);
if (!impulstelegramm) {
LOGP(DBNETZ, LOGL_ERROR, "Illegal digit '%c', please fix!\n", funkwahl[digit_pos]);
PDEBUG(DBNETZ, DEBUG_ERROR, "Illegal digit '%c', please fix!\n", funkwahl[digit_pos]);
abort();
}
tx_telegramm = impulstelegramm->sequence;
@ -255,7 +252,7 @@ static void process_signal(int buffer_size)
count = dsp_samplerate / 1000;
#endif
if (count < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to get number of samples in buffer (rc = %d)!\n", count);
PDEBUG(DDSP, DEBUG_ERROR, "Failed to get number of samples in buffer (rc = %d)!\n", count);
break;
}
@ -270,7 +267,7 @@ static void process_signal(int buffer_size)
/* write audio */
rc = sound_write(audio, samples, power, count, NULL, NULL, 1);
if (rc < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
PDEBUG(DDSP, DEBUG_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
break;
}
#endif
@ -343,15 +340,15 @@ int main(int argc, char *argv[])
/* init fsk */
if (fsk_mod_init(&fsk_mod, NULL, fsk_send_bit, dsp_samplerate, BIT_RATE, F0, F1, 1.0, 0, 0) < 0) {
LOGP(DDSP, LOGL_ERROR, "FSK init failed!\n");
PDEBUG(DDSP, DEBUG_ERROR, "FSK init failed!\n");
goto exit;
}
#ifdef HAVE_ALSA
/* init sound */
audio = sound_open(SOUND_DIR_PLAY, dsp_audiodev, NULL, NULL, NULL, 1, 0.0, dsp_samplerate, buffer_size, 1.0, 1.0, 4000.0, 2.0);
audio = sound_open(dsp_audiodev, NULL, NULL, NULL, 1, 0.0, dsp_samplerate, buffer_size, 1.0, 1.0, 4000.0, 2.0);
if (!audio) {
LOGP(DBNETZ, LOGL_ERROR, "No sound device!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "No sound device!\n");
goto exit;
}
#endif
@ -360,13 +357,13 @@ int main(int argc, char *argv[])
if (write_tx_wave) {
rc = wave_create_record(&wave_tx_rec, write_tx_wave, dsp_samplerate, 1, 1.0);
if (rc < 0) {
LOGP(DBNETZ, LOGL_ERROR, "Failed to create WAVE recoding instance!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
goto exit;
}
}
#ifndef HAVE_ALSA
else {
LOGP(DBNETZ, LOGL_ERROR, "No sound support compiled in, so you need to write to a wave file. See help!\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "No sound support compiled in, so you need to write to a wave file. See help!\n");
goto exit;
}
#endif
@ -376,7 +373,7 @@ int main(int argc, char *argv[])
sound_start(audio);
#endif
LOGP(DBNETZ, LOGL_ERROR, "Start audio after pause...\n");
PDEBUG(DBNETZ, DEBUG_ERROR, "Start audio after pause...\n");
process_signal(buffer_size);

View File

@ -26,7 +26,7 @@
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "bnetz.h"
#include "dsp.h"
@ -70,7 +70,7 @@ void dsp_init(void)
{
int i;
LOGP(DDSP, LOGL_DEBUG, "Generating sine table for metering tone.\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for metering tone.\n");
for (i = 0; i < 65536; i++)
dsp_metering[i] = sin((double)i / 65536.0 * 2.0 * PI) * TX_PEAK_METER;
}
@ -81,10 +81,10 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level);
/* Init transceiver instance. */
int dsp_init_sender(bnetz_t *bnetz, double squelch_db)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "Init DSP for 'Sender'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
if (TONE_DETECT_CNT > sizeof(bnetz->rx_tone_quality) / sizeof(bnetz->rx_tone_quality[0])) {
LOGP_CHAN(DDSP, LOGL_ERROR, "buffer for tone quality is too small, please fix!\n");
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "buffer for tone quality is too small, please fix!\n");
return -EINVAL;
}
@ -94,15 +94,15 @@ int dsp_init_sender(bnetz_t *bnetz, double squelch_db)
/* set modulation parameters */
sender_set_fm(&bnetz->sender, MAX_DEVIATION, MAX_MODULATION, SPEECH_DEVIATION, MAX_DISPLAY);
LOGP(DDSP, LOGL_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation @ 2000 Hz)\n", TX_PEAK_FSK, 4.0);
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation @ 2000 Hz)\n", TX_PEAK_FSK, 4.0);
/* init fsk */
if (fsk_mod_init(&bnetz->fsk_mod, bnetz, fsk_send_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 0, 0) < 0) {
LOGP_CHAN(DDSP, LOGL_ERROR, "FSK init failed!\n");
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
return -EINVAL;
}
if (fsk_demod_init(&bnetz->fsk_demod, bnetz, fsk_receive_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, BIT_ADJUST) < 0) {
LOGP_CHAN(DDSP, LOGL_ERROR, "FSK init failed!\n");
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
return -EINVAL;
}
@ -124,7 +124,7 @@ int dsp_init_sender(bnetz_t *bnetz, double squelch_db)
/* Cleanup transceiver instance. */
void dsp_cleanup_sender(bnetz_t *bnetz)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "Cleanup DSP for 'Sender'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for 'Sender'.\n");
fsk_mod_cleanup(&bnetz->fsk_mod);
fsk_demod_cleanup(&bnetz->fsk_demod);
@ -148,7 +148,7 @@ static void fsk_receive_tone(bnetz_t *bnetz, int tone, int goodtone, double leve
/* set duration to TONE_DETECT_CNT, because it took that long to detect the tone */
bnetz->tone_duration = TONE_DETECT_CNT;
bnetz->tone_detected = tone;
LOGP_CHAN(DDSP, LOGL_INFO, "Detecting continuous tone: F%d Level=%3.0f%% (threshold %3.0f%%) standard deviation=%.0f%% (threshold=%.0f%%) Quality=%3.0f%%\n", bnetz->tone_detected, level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0, quality_avg * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Detecting continuous tone: F%d Level=%3.0f%% (threshold %3.0f%%) standard deviation=%.0f%% (threshold=%.0f%%) Quality=%3.0f%%\n", bnetz->tone_detected, level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0, quality_avg * 100.0);
bnetz_receive_tone(bnetz, bnetz->tone_detected);
}
}
@ -158,7 +158,7 @@ static void fsk_receive_tone(bnetz_t *bnetz, int tone, int goodtone, double leve
bnetz->tone_count++;
if (bnetz->tone_count == TONE_LOST_CNT) {
/* subtract TONE_LOST_CNT from duration, because it took that long to detect loss of tone */
LOGP_CHAN(DDSP, LOGL_INFO, "Lost F%d tone after %.2f seconds.\n", bnetz->tone_detected, (double)(bnetz->tone_duration - TONE_LOST_CNT) / 100.0);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Lost F%d tone after %.2f seconds.\n", bnetz->tone_detected, (double)(bnetz->tone_duration - TONE_LOST_CNT) / 100.0);
bnetz->tone_detected = -1;
bnetz_receive_tone(bnetz, -1);
}
@ -250,7 +250,7 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
j++;
}
LOGP_CHAN(DDSP, LOGL_DEBUG, "FSK Valid bits: %d/%d Level: %.0f%% (threshold %.0f%%) Stddev: %.0f%% (threshold %.0f%%)\n", j, 16, level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "FSK Valid bits: %d/%d Level: %.0f%% (threshold %.0f%%) Stddev: %.0f%% (threshold %.0f%%)\n", j, 16, level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0);
/* drop any telegramm that is too bad */
if (level_stddev / level_avg > TONE_STDDEV_TH || j < 16)
@ -261,7 +261,7 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
display_measurements_update(bnetz->dmp_frame_stddev, level_stddev / level_avg * 100.0, 0.0);
display_measurements_update(bnetz->dmp_frame_quality, quality_avg * 100.0, 0.0);
LOGP_CHAN(DDSP, LOGL_INFO, "Telegramm RX Level: average=%.0f%% (threshold %.0f%%) standard deviation=%.0f%% (threshold %.0f%%) Quality: %.0f%%\n", level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0, quality_avg * 100.0);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Telegramm RX Level: average=%.0f%% (threshold %.0f%%) standard deviation=%.0f%% (threshold %.0f%%) Quality: %.0f%%\n", level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0, quality_avg * 100.0);
/* receive telegramm */
bnetz_receive_telegramm(bnetz, bnetz->rx_telegramm);
@ -320,7 +320,7 @@ static int fsk_send_bit(void *inst)
/* request frame */
bnetz->tx_telegramm = bnetz_get_telegramm(bnetz);
if (!bnetz->tx_telegramm) {
LOGP_CHAN(DDSP, LOGL_DEBUG, "Stop sending 'Telegramm'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Stop sending 'Telegramm'.\n");
return -1;
}
bnetz->tx_telegramm_pos = 0;
@ -361,7 +361,7 @@ static void metering_tone(bnetz_t *bnetz, sample_t *samples, int length)
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length)
{
bnetz_t *bnetz = (bnetz_t *) sender;
int count, input_num;
int count;
memset(power, 1, length);
@ -372,13 +372,7 @@ again:
break;
case DSP_MODE_AUDIO:
case DSP_MODE_AUDIO_METER:
input_num = samplerate_upsample_input_num(&sender->srstate, length);
{
int16_t spl[input_num];
jitter_load_samples(&sender->dejitter, (uint8_t *)spl, input_num, sizeof(*spl), jitter_conceal_s16, NULL);
int16_to_samples_speech(samples, spl, input_num);
}
samplerate_upsample(&sender->srstate, samples, input_num, samples, length);
jitter_load(&bnetz->sender.dejitter, samples, length);
if (bnetz->dsp_mode == DSP_MODE_AUDIO_METER)
metering_tone(bnetz, samples, length);
break;
@ -396,7 +390,7 @@ again:
}
}
static const char *bnetz_dsp_mode_name(enum dsp_mode mode)
const char *bnetz_dsp_mode_name(enum dsp_mode mode)
{
static char invalid[16];
@ -424,37 +418,10 @@ void bnetz_set_dsp_mode(bnetz_t *bnetz, enum dsp_mode mode)
/* reset telegramm */
if (mode == DSP_MODE_TELEGRAMM && bnetz->dsp_mode != mode) {
bnetz->tx_telegramm = 0;
fsk_mod_reset(&bnetz->fsk_mod);
fsk_mod_tx_reset(&bnetz->fsk_mod);
}
if ((mode == DSP_MODE_AUDIO || mode == DSP_MODE_AUDIO_METER) && (bnetz->dsp_mode != DSP_MODE_AUDIO && bnetz->dsp_mode != DSP_MODE_AUDIO_METER))
jitter_reset(&bnetz->sender.dejitter);
LOGP_CHAN(DDSP, LOGL_DEBUG, "DSP mode %s -> %s\n", bnetz_dsp_mode_name(bnetz->dsp_mode), bnetz_dsp_mode_name(mode));
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", bnetz_dsp_mode_name(bnetz->dsp_mode), bnetz_dsp_mode_name(mode));
bnetz->dsp_mode = mode;
}
/* Receive audio from call instance. */
void call_down_audio(void *decoder, void *decoder_priv, int callref, uint16_t sequence, uint8_t marker, uint32_t timestamp, uint32_t ssrc, uint8_t *payload, int payload_len)
{
sender_t *sender;
bnetz_t *bnetz;
for (sender = sender_head; sender; sender = sender->next) {
bnetz = (bnetz_t *) sender;
if (bnetz->callref == callref)
break;
}
if (!sender)
return;
if (bnetz->dsp_mode == DSP_MODE_AUDIO
|| bnetz->dsp_mode == DSP_MODE_AUDIO_METER) {
jitter_frame_t *jf;
jf = jitter_frame_alloc(decoder, decoder_priv, payload, payload_len, marker, sequence, timestamp, ssrc);
if (jf)
jitter_save(&bnetz->sender.dejitter, jf);
}
}
void call_down_clock(void) {}

View File

@ -24,7 +24,7 @@
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/main_mobile.h"
#include "../anetz/freiton.h"
@ -58,8 +58,6 @@ void print_help(const char *arg0)
printf(" Pulses will be sent on outgoing calls only and only if mobile station\n");
printf(" requests it. Use negative value to force metering pulses for all calls.\n");
printf(" (default = %d)\n", metering);
printf(" If metering pulses are sent via Osmo-CC interface, pulses are always\n");
printf(" sent, if mobile station requests it. This overrides this option.\n");
printf(" -P --paging tone | notone | positive | negative | <file>=<on>:<off>\n");
printf(" Send a tone, give a signal or write to a file when switching to\n");
printf(" channel 19. (paging the phone).\n");
@ -220,7 +218,6 @@ fail:
bnetz_destroy(sender_head);
/* exits */
main_mobile_exit();
fm_exit();
options_free();

View File

@ -2,7 +2,6 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "stations.h"
static struct bnetz_stations {
const char *standort;
@ -222,7 +221,7 @@ static struct bnetz_stations {
{ NULL, 0, NULL }
};
static double lat_from_coordinates(const char *string)
double lat_from_coordinates(const char *string)
{
if (strlen(string) != 11)
abort();
@ -243,7 +242,7 @@ static double lat_from_coordinates(const char *string)
(double)(string[4] - '0') / 60.0;
}
static double lon_from_coordinates(const char *string)
double lon_from_coordinates(const char *string)
{
if (strlen(string) != 11)
abort();

View File

@ -1,4 +1,4 @@
AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes)
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
bin_PROGRAMS = \
cnetz
@ -24,10 +24,13 @@ cnetz_LDADD = \
../anetz/libgermanton.a \
libcnetztones.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/libcompandor/libcompandor.a \
$(top_builddir)/src/libjitter/libjitter.a \
$(top_builddir)/src/libtimer/libtimer.a \
$(top_builddir)/src/libsamplerate/libsamplerate.a \
$(top_builddir)/src/libscrambler/libscrambler.a \
$(top_builddir)/src/libemphasis/libemphasis.a \
@ -35,10 +38,8 @@ cnetz_LDADD = \
$(top_builddir)/src/libfilter/libfilter.a \
$(top_builddir)/src/libwave/libwave.a \
$(top_builddir)/src/libsample/libsample.a \
$(top_builddir)/src/libg711/libg711.a \
$(top_builddir)/src/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCC_LIBS) \
-lm
if HAVE_ALSA

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,12 @@
#include "../libcompandor/compandor.h"
#include <osmocom/core/timer.h>
#include "../libtimer/timer.h"
#include "../libmobile/sender.h"
#include "../libscrambler/scrambler.h"
typedef struct cnetz cnetz_t;
#include "fsk_demod.h"
#include "transaction.h"
#define CNETZ_STD_OGK_KANAL 131
#define CNETZ_OGK_KANAL 131
/* dsp modes of transmission */
enum dsp_mode {
@ -40,9 +40,9 @@ enum cnetz_state {
#define N_AFKT 6 /* number of release frames to send during concentrated signaling */
#define N_AFV 4 /* number of release frames to send during distributed signaling */
#define N 3 /* now many times we repeat a message on OgK */
#define T_VAG2 180,0 /* time on outgoing queue */
#define T_VAK 60,0 /* time on incoming queue */
#define T_AP 0,750000 /* Time to wait for SIM card's authentication reply */
#define T_VAG2 180 /* time on outgoing queue */
#define T_VAK 60 /* time on incoming queue */
#define T_AP 750 /* Time to wait for SIM card's authentication reply */
/* clear causes */
#define CNETZ_CAUSE_GASSENBESETZT 0 /* network congested */
@ -66,7 +66,6 @@ struct clock_speed {
/* instance of cnetz sender */
struct cnetz {
sender_t sender;
int kanal; /* channel number */
enum cnetz_chan_type chan_type; /* channel type */
scrambler_t scrambler_tx; /* mirror what we transmit to MS */
scrambler_t scrambler_rx; /* mirror what we receive from MS */
@ -82,7 +81,7 @@ struct cnetz {
int response_valid; /* expect authorizaton response */
uint64_t response; /* authorization response */
int warteschlange; /* use queue */
int metering; /* send metering units in seconds 0 = off */
int metering; /* use metering pulses in seconds 0 = off */
/* all cnetz states */
enum cnetz_state state; /* main state of sender */
@ -97,12 +96,9 @@ struct cnetz {
int sched_r_m; /* Rufblock (0) / Meldeblock (1) */
enum dsp_mode sched_dsp_mode; /* what mode shall be switched to */
int sched_dsp_mode_ts; /* time slot when to switch mode (-1 = don't switch) */
int sched_lr_debugged; /* indicator to prevent debugging all idle frames */
int sched_mlr_debugged; /* indicator to prevent debugging all idle frames */
/* dsp states */
enum dsp_mode dsp_mode; /* current mode: audio, "Telegramm", .... */
double rf_level_db; /* current RF level or nan, if not applicable */
iir_filter_t lp; /* low pass filter to eliminate noise above 5280 Hz */
fsk_fm_demod_t fsk_demod; /* demod process */
double fsk_deviation; /* deviation of FSK signal on sound card */
@ -127,8 +123,8 @@ struct cnetz {
double frame_last_phase; /* master's bit phase of last frame sync */
/* audio offset removal */
double offset_last; /* last sample value of last frame */
int offset_range; /* range of samples to ramp the offset */
double offset_factor; /* filer alpha of high-pass filter */
double offset_y_last; /* last stored sample */
/* measurements */
int measure_speed; /* measure clock speed */
@ -148,7 +144,7 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
void cnetz_destroy(sender_t *sender);
void cnetz_go_idle(cnetz_t *cnetz);
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal);
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
const struct telegramm *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz);
const struct telegramm *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz);
void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, struct telegramm *telegramm, int block);

View File

@ -22,22 +22,21 @@
#include <stdlib.h>
#include <string.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libmobile/get_time.h"
#include "../libdebug/debug.h"
#include "cnetz.h"
#include "database.h"
#include "sysinfo.h"
/* the network specs say: check every 1 - 6.5 minutes for availability
* remove from database after 3 subsequent failures
* the phone will register 20 minutes after no call / no paging from network.
*/
#define MELDE_WIEDERHOLUNG 60.0 /* when busy */
#define MELDE_INTERVAL 120.0
#define MELDE_WIEDERHOLUNG 60.0
#define MELDE_MAXIMAL 3
typedef struct cnetz_database {
struct cnetz_database *next;
int ogk_kanal; /* available on which channel */
uint8_t futln_nat; /* who ... */
uint8_t futln_fuvst;
uint16_t futln_rest;
@ -46,23 +45,12 @@ typedef struct cnetz_database {
int eingebucht; /* set if still available */
double last_seen;
int busy; /* set if currently in a call */
struct osmo_timer_list timer; /* timer for next availability check */
struct timer timer; /* timer for next availability check */
int retry; /* counts number of retries */
} cnetz_db_t;
cnetz_db_t *cnetz_db_head;
static const char *print_meldeaufrufe(int versuche)
{
static char text[32];
if (versuche <= 0)
return "infinite";
sprintf(text, "%d", versuche);
return text;
}
/* destroy transaction */
static void remove_db(cnetz_db_t *db)
{
@ -73,39 +61,39 @@ static void remove_db(cnetz_db_t *db)
while (*dbp && *dbp != db)
dbp = &((*dbp)->next);
if (!(*dbp)) {
LOGP(DDB, LOGL_ERROR, "Subscriber not in list, please fix!!\n");
PDEBUG(DDB, DEBUG_ERROR, "Subscriber not in list, please fix!!\n");
abort();
}
*dbp = db->next;
LOGP(DDB, LOGL_INFO, "Removing subscriber '%d,%d,%05d' from database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
PDEBUG(DDB, DEBUG_INFO, "Removing subscriber '%d,%d,%05d' from database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
osmo_timer_del(&db->timer);
timer_exit(&db->timer);
free(db);
}
/* Timeout handling */
static void db_timeout(void *data)
static void db_timeout(struct timer *timer)
{
cnetz_db_t *db = data;
cnetz_db_t *db = (cnetz_db_t *)timer->priv;
int rc;
LOGP(DDB, LOGL_INFO, "Check, if subscriber '%d,%d,%05d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
PDEBUG(DDB, DEBUG_INFO, "Check, if subscriber '%d,%d,%05d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal);
rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest);
if (rc < 0) {
/* OgK is used for speech, but this never happens in a real
* network. We just assume that the phone has responded and
* assume we had a response. */
LOGP(DDB, LOGL_INFO, "OgK busy, so we assume a positive response.\n");
osmo_timer_schedule(&db->timer, si.meldeinterval,0); /* when to check avaiability again */
PDEBUG(DDB, DEBUG_INFO, "OgK busy, so we assume a positive response.\n");
timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability again */
db->retry = 0;
}
}
/* create/update db entry */
int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal, int *futelg_bit, int *extended, int busy, int failed)
int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed)
{
cnetz_db_t *db, **dbp;
@ -121,10 +109,10 @@ int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int o
if (!db) {
db = calloc(1, sizeof(*db));
if (!db) {
LOGP(DDB, LOGL_ERROR, "No memory!\n");
PDEBUG(DDB, DEBUG_ERROR, "No memory!\n");
return 0;
}
osmo_timer_setup(&db->timer, db_timeout, db);
timer_init(&db->timer, db_timeout, db);
db->eingebucht = 1;
db->futln_nat = futln_nat;
@ -137,12 +125,9 @@ int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int o
dbp = &((*dbp)->next);
*dbp = db;
LOGP(DDB, LOGL_INFO, "Adding subscriber '%d,%d,%05d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
PDEBUG(DDB, DEBUG_INFO, "Adding subscriber '%d,%d,%05d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
}
if (ogk_kanal)
db->ogk_kanal = ogk_kanal;
if (futelg_bit && *futelg_bit >= 0)
db->futelg_bit = *futelg_bit;
@ -151,23 +136,23 @@ int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int o
db->busy = busy;
if (busy) {
LOGP(DDB, LOGL_INFO, "Subscriber '%d,%d,%05d' on OGK channel #%d is busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal);
osmo_timer_del(&db->timer);
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%05d' busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
timer_stop(&db->timer);
} else if (!failed) {
LOGP(DDB, LOGL_INFO, "Subscriber '%d,%d,%05d' on OGK channel #%d is idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal);
osmo_timer_schedule(&db->timer, si.meldeinterval,0); /* when to check avaiability (again) */
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%05d' idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability (again) */
db->retry = 0;
db->eingebucht = 1;
db->last_seen = get_time();
} else {
db->retry++;
LOGP(DDB, LOGL_NOTICE, "Paging subscriber '%d,%d,%05d' on OGK channel #%d failed (try %d of %s).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal, db->retry, print_meldeaufrufe(si.meldeaufrufe));
if (si.meldeaufrufe && db->retry == si.meldeaufrufe) {
LOGP(DDB, LOGL_INFO, "Marking subscriber as gone.\n");
PDEBUG(DDB, DEBUG_NOTICE, "Paging subscriber '%d,%d,%05d' failed (try %d of %d).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->retry, MELDE_MAXIMAL);
if (db->retry == MELDE_MAXIMAL) {
PDEBUG(DDB, DEBUG_INFO, "Marking subscriber as gone.\n");
db->eingebucht = 0;
return db->extended;
}
osmo_timer_schedule(&db->timer, (si.meldeinterval < MELDE_WIEDERHOLUNG) ? si.meldeinterval : MELDE_WIEDERHOLUNG,0); /* when to do retry */
timer_start(&db->timer, MELDE_WIEDERHOLUNG); /* when to do retry */
}
if (futelg_bit)
@ -177,7 +162,7 @@ int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int o
return 0;
}
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *ogk_kanal, int *futelg_bit, int *extended)
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended)
{
cnetz_db_t *db = cnetz_db_head;
@ -186,8 +171,6 @@ int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *og
&& db->futln_nat == futln_nat
&& db->futln_fuvst == futln_fuvst
&& db->futln_rest == futln_rest) {
if (ogk_kanal)
*ogk_kanal = db->ogk_kanal;
if (futelg_bit)
*futelg_bit = db->futelg_bit;
if (extended)
@ -210,20 +193,18 @@ void dump_db(void)
cnetz_db_t *db = cnetz_db_head;
double now = get_time();
int last;
char attached[16];
LOGP(DDB, LOGL_NOTICE, "Dump of subscriber database:\n");
PDEBUG(DDB, DEBUG_NOTICE, "Dump of subscriber database:\n");
if (!db) {
LOGP(DDB, LOGL_NOTICE, " - No subscribers attached!\n");
PDEBUG(DDB, DEBUG_NOTICE, " - No subscribers attached!\n");
return;
}
LOGP(DDB, LOGL_NOTICE, "Subscriber\tAttached\tBusy\t\tLast seen\tMeldeaufrufe\n");
LOGP(DDB, LOGL_NOTICE, "-------------------------------------------------------------------------------\n");
PDEBUG(DDB, DEBUG_NOTICE, "Subscriber\tAttached\tBusy\t\tLast seen\tMeldeaufrufe\n");
PDEBUG(DDB, DEBUG_NOTICE, "-------------------------------------------------------------------------------\n");
while (db) {
last = (db->busy) ? 0 : (uint32_t)(now - db->last_seen);
sprintf(attached, "YES (OGK %d)", db->ogk_kanal);
LOGP(DDB, LOGL_NOTICE, "%d,%d,%05d\t%s\t%s\t\t%02d:%02d:%02d \t%d/%s\n", db->futln_nat, db->futln_fuvst, db->futln_rest, (db->eingebucht) ? attached : "-no-\t", (db->busy) ? "YES" : "-no-", last / 3600, (last / 60) % 60, last % 60, db->retry, print_meldeaufrufe(si.meldeaufrufe));
PDEBUG(DDB, DEBUG_NOTICE, "%d,%d,%05d\t%s\t\t%s\t\t%02d:%02d:%02d \t%d/%d\n", db->futln_nat, db->futln_fuvst, db->futln_rest, (db->eingebucht) ? "YES" : "-no-", (db->busy) ? "YES" : "-no-", last / 3600, (last / 60) % 60, last % 60, db->retry, MELDE_MAXIMAL);
db = db->next;
}
}

View File

@ -1,6 +1,6 @@
int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal, int *futelg_bit, int *extended, int busy, int failed);
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *ogk_kanal, int *futelg_bit, int *extended);
int update_db(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed);
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended);
void flush_db(void);
void dump_db(void);

View File

@ -26,9 +26,8 @@
#include <math.h>
#include <errno.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/get_time.h"
#include "cnetz.h"
#include "sysinfo.h"
#include "telegramm.h"
@ -47,14 +46,15 @@
#define MAX_DISPLAY 1.4 /* something above speech level, no emphasis */
#define BITRATE 5280.0 /* bits per second */
#define BLOCK_BITS 198 /* duration of one time slot including pause at beginning and end */
#define CUT_OFF_OFFSET 300.0 /* cut off frequency for offset filter (level correction between subsequent audio chunks) */
#ifdef TEST_SCRAMBLE
test_echo_t scrambler_test_echo = {};
jitter_t scrambler_test_jb;
scrambler_t scrambler_test_scrambler1;
scrambler_t scrambler_test_scrambler2;
#endif
static const char *cnetz_dsp_mode_name(enum dsp_mode mode)
const char *cnetz_dsp_mode_name(enum dsp_mode mode)
{
static char invalid[16];
@ -77,7 +77,6 @@ static const char *cnetz_dsp_mode_name(enum dsp_mode mode)
void dsp_init(void)
{
compandor_init();
}
static void dsp_init_ramp(cnetz_t *cnetz)
@ -85,7 +84,7 @@ static void dsp_init_ramp(cnetz_t *cnetz)
double c;
int i;
LOGP(DDSP, LOGL_DEBUG, "Generating smooth ramp table.\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Generating smooth ramp table.\n");
for (i = 0; i < 256; i++) {
/* use square-root of cosine ramp. tests showed that phones are more
* happy with that. (This is not correct pulse shaping!) */
@ -104,8 +103,9 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
{
int rc = 0;
double size;
double RC, dt;
LOGP_CHAN(DDSP, LOGL_DEBUG, "Init FSK for 'Sender'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n");
/* set modulation parameters */
sender_set_fm(&cnetz->sender, MAX_DEVIATION, MAX_MODULATION, speech_deviation, MAX_DISPLAY);
@ -116,20 +116,20 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
}
if (clock_speed[0] > 1000 || clock_speed[0] < -1000 || clock_speed[1] > 1000 || clock_speed[1] < -1000) {
LOGP_CHAN(DDSP, LOGL_ERROR, "Clock speed %.1f,%.1f ppm out of range! Please use range between +-1000 ppm!\n", clock_speed[0], clock_speed[1]);
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "Clock speed %.1f,%.1f ppm out of range! Please use range between +-1000 ppm!\n", clock_speed[0], clock_speed[1]);
return -EINVAL;
}
LOGP_CHAN(DDSP, LOGL_INFO, "Using clock speed of %.1f ppm (RX) and %.1f ppm (TX) to correct sound card's clock.\n", clock_speed[0], clock_speed[1]);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Using clock speed of %.1f ppm (RX) and %.1f ppm (TX) to correct sound card's clock.\n", clock_speed[0], clock_speed[1]);
cnetz->fsk_bitduration = (double)cnetz->sender.samplerate / ((double)BITRATE / (1.0 + clock_speed[1] / 1000000.0));
cnetz->fsk_tx_bitstep = 1.0 / cnetz->fsk_bitduration;
LOGP_CHAN(DDSP, LOGL_DEBUG, "Use %.4f samples for one bit duration @ %d.\n", cnetz->fsk_bitduration, cnetz->sender.samplerate);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Use %.4f samples for one bit duration @ %d.\n", cnetz->fsk_bitduration, cnetz->sender.samplerate);
size = cnetz->fsk_bitduration * (double)BLOCK_BITS * 16.0; /* 16 blocks for distributed frames */
cnetz->fsk_tx_buffer_size = size * 1.1; /* more to compensate clock speed */
cnetz->fsk_tx_buffer = calloc(sizeof(sample_t), cnetz->fsk_tx_buffer_size);
if (!cnetz->fsk_tx_buffer) {
LOGP_CHAN(DDSP, LOGL_ERROR, "No memory!\n");
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "No memory!\n");
rc = -ENOMEM;
goto error;
}
@ -144,13 +144,13 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
/* create speech buffer */
cnetz->dsp_speech_buffer = calloc(sizeof(sample_t), (int)(cnetz->fsk_bitduration * 70.0)); /* more to compensate clock speed. we just need it to fill 62 bits (60 bits, including pause bits). */
if (!cnetz->dsp_speech_buffer) {
LOGP_CHAN(DDSP, LOGL_ERROR, "No memory!\n");
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "No memory!\n");
rc = -ENOMEM;
goto error;
}
/* reinit the sample rate to shrink/expand audio */
init_samplerate(&cnetz->sender.srstate, 8000.0, (double)cnetz->sender.samplerate / (1.1 / (1.0 + clock_speed[0] / 1000000.0)), 3300.0); /* 66 <-> 60 */
init_samplerate(&cnetz->sender.srstate, 8000.0, (double)cnetz->sender.samplerate / 1.1, 3300.0); /* 66 <-> 60 */
rc = fsk_fm_init(&cnetz->fsk_demod, cnetz, cnetz->sender.samplerate, (double)BITRATE / (1.0 + clock_speed[0] / 1000000.0), demod);
if (rc < 0)
@ -160,17 +160,25 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
scrambler_setup(&cnetz->scrambler_tx, (double)cnetz->sender.samplerate / 1.1);
scrambler_setup(&cnetz->scrambler_rx, (double)cnetz->sender.samplerate / 1.1);
/* reinit jitter buffer for 8000 kHz */
jitter_destroy(&cnetz->sender.dejitter);
rc = jitter_create(&cnetz->sender.dejitter, 8000 / 5);
if (rc < 0)
goto error;
/* init compandor, according to C-Netz specs, attack and recovery time
* shall not exceed according to ITU G.162 */
setup_compandor(&cnetz->cstate, 8000, 5.0, 22.5);
init_compandor(&cnetz->cstate, 8000, 5.0, 22.5);
/* use duration of one bit to ramp level of last frame to current frame */
cnetz->offset_range = ceil(cnetz->fsk_bitduration);
/* use this filter to compensate level changes between two subsequent audio chunks */
RC = 1.0 / (CUT_OFF_OFFSET * 2.0 *3.14);
dt = 1.0 / cnetz->sender.samplerate;
cnetz->offset_factor = RC / (RC + dt);
#ifdef TEST_SCRAMBLE
rc = test_echo_alloc(&scrambler_test_echo, cnetz->sender.samplerate / 20);
rc = jitter_create(&scrambler_test_jb, cnetz->sender.samplerate / 5);
if (rc < 0) {
LOGP_CHAN(DDSP, LOGL_ERROR, "Failed to init echo buffer for scrambler test!\n");
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "Failed to init jitter buffer for scrambler test!\n");
exit(0);
}
scrambler_setup(&scrambler_test_scrambler1, cnetz->sender.samplerate);
@ -189,7 +197,7 @@ error:
void dsp_cleanup_sender(cnetz_t *cnetz)
{
LOGP_CHAN(DDSP, LOGL_DEBUG, "Cleanup FSK for 'Sender'.\n");
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup FSK for 'Sender'.\n");
if (cnetz->fsk_tx_buffer) {
free(cnetz->fsk_tx_buffer);
@ -257,7 +265,7 @@ void calc_clock_speed(cnetz_t *cnetz, double samples, int tx, int result)
speed_ppm_avg[index] += cs->speed_ppm[index][(cs->idx[index] - i - 1) & 0xff];
speed_ppm_avg[index] /= (double)cs->num[index];
}
LOGP_CHAN(DDSP, LOGL_NOTICE, "Clock: RX=%.3f TX=%.3f; Signal: RX=%.3f TX=%.3f ppm\n", speed_ppm_avg[0], speed_ppm_avg[1], speed_ppm_avg[2], speed_ppm_avg[3]);
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Clock: RX=%.3f TX=%.3f; Signal: RX=%.3f TX=%.3f ppm\n", speed_ppm_avg[0], speed_ppm_avg[1], speed_ppm_avg[2], speed_ppm_avg[3]);
}
static int fsk_nothing_encode(cnetz_t *cnetz)
@ -560,12 +568,10 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits)
/* decode samples and hut for bit changes
* use deviation to find greatest slope of the signal (bit change)
*/
void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_level_db)
void sender_receive(sender_t *sender, sample_t *samples, int length, double __attribute__((unused)) rf_level_db)
{
cnetz_t *cnetz = (cnetz_t *) sender;
cnetz->rf_level_db = rf_level_db;
/* measure rx sample speed */
calc_clock_speed(cnetz, length, 0, 0);
@ -573,7 +579,7 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_l
#ifdef TEST_UNSCRAMBLE
scrambler(&scrambler_test_scrambler1, samples, length);
#endif
test_echo_store(&scrambler_test_echo, samples, length);
jitter_save(&scrambler_test_jb, samples, length);
return;
#endif
@ -589,15 +595,12 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_l
static int shrink_speech(cnetz_t *cnetz, sample_t *speech_buffer)
{
int speech_length;
int16_t spl[100];
jitter_load_samples(&cnetz->sender.dejitter, (uint8_t *)spl, 100, sizeof(*spl), jitter_conceal_s16, NULL);
int16_to_samples_speech(speech_buffer, spl, 100);
jitter_load(&cnetz->sender.dejitter, speech_buffer, 100);
/* 1. compress dynamics */
compress_audio(&cnetz->cstate, speech_buffer, 100);
/* 2. upsample */
speech_length = samplerate_upsample_output_num(&cnetz->sender.srstate, 100);
samplerate_upsample(&cnetz->sender.srstate, speech_buffer, 100, speech_buffer, speech_length);
speech_length = samplerate_upsample(&cnetz->sender.srstate, speech_buffer, 100, speech_buffer);
/* 3. scramble */
if (cnetz->scrambler)
scrambler(&cnetz->scrambler_tx, speech_buffer, speech_length);
@ -645,10 +648,10 @@ again:
* because one has a phase wrap before and the other after a sample.
* then we do it next super frame cycle */
if (master->frame_last_scount == cnetz->fsk_tx_scount) {
LOGP(DDSP, LOGL_DEBUG, "Sync phase of slave to master: master=%.15f, slave=%.15f, diff=%.15f\n", master->frame_last_phase, cnetz->fsk_tx_phase, master->frame_last_phase - cnetz->fsk_tx_phase);
PDEBUG(DDSP, DEBUG_DEBUG, "Sync phase of slave to master: master=%.15f, slave=%.15f, diff=%.15f\n", master->frame_last_phase, cnetz->fsk_tx_phase, master->frame_last_phase - cnetz->fsk_tx_phase);
cnetz->fsk_tx_phase = master->frame_last_phase;
} else {
LOGP(DDSP, LOGL_DEBUG, "Not sync phase of slave to master: Sample counts during frame change are different, ignoring this time!\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Not sync phase of slave to master: Sample counts during frame change are different, ignoring this time!\n");
}
}
}
@ -657,7 +660,7 @@ again:
if (cnetz->sched_dsp_mode_ts >= 0 && cnetz->sched_r_m == 0) {
if (cnetz->sched_dsp_mode_ts == cnetz->sched_ts) {
/* OgK / SpK(K) / SpK(V) */
LOGP_CHAN(DDSP, LOGL_INFO, "Now switching channel mode to %s at timeslot %d\n", cnetz_dsp_mode_name(cnetz->sched_dsp_mode), cnetz->sched_dsp_mode_ts);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Now switching channel mode to %s at timeslot %d\n", cnetz_dsp_mode_name(cnetz->sched_dsp_mode), cnetz->sched_dsp_mode_ts);
cnetz->sched_dsp_mode_ts = -1;
cnetz_set_dsp_mode(cnetz, cnetz->sched_dsp_mode);
}
@ -665,23 +668,31 @@ again:
switch (cnetz->dsp_mode) {
case DSP_MODE_OGK:
if (((si.timeslots >> cnetz->sched_ts) & 1)) {
/* if automatic polarity selection is used, toggle between
* two polarities (every 4 slots) until a response is received
* then continue to use the time slots of that polarity
*/
if (cnetz->auto_polarity)
cnetz->negative_polarity = (cnetz->sched_ts & 7) >> 2;
/* send on timeslots depending on the polarity:
* positive polarity: ts, ts+8, ts+16, ts+24
* negative polarity: ts+4, ts+12, ts+20, ts+28
*/
if (((cnetz->sched_ts & 7) == (si.timeslot & 7) && cnetz->negative_polarity == 0)
|| ((cnetz->sched_ts & 7) == ((si.timeslot + 4) & 7) && cnetz->negative_polarity == 1)) {
if (cnetz->sched_r_m == 0) {
/* if automatic polarity selection is used, toggle between two polarities (every transmitted slot) until a response is received then continue to use the time slots of that polarity */
if (cnetz->auto_polarity)
cnetz->negative_polarity = (cnetz->sched_ts & 7) >> 2;
/* set last time slot, so we know to which time slot the message from mobile station belongs to */
cnetz->sched_last_ts = cnetz->sched_ts;
bits = cnetz_encode_telegramm(cnetz);
if (bits) {
LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Rufblock' at timeslot %d\n", cnetz->sched_ts);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Rufblock' at timeslot %d\n", cnetz->sched_ts);
fsk_block_encode(cnetz, bits, 1);
} else
fsk_nothing_encode(cnetz);
} else {
bits = cnetz_encode_telegramm(cnetz);
if (bits) {
LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Meldeblock' at timeslot %d\n", cnetz->sched_ts);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Meldeblock' at timeslot %d\n", cnetz->sched_ts);
fsk_block_encode(cnetz, bits, 1);
} else
fsk_nothing_encode(cnetz);
@ -693,7 +704,7 @@ again:
case DSP_MODE_SPK_K:
bits = cnetz_encode_telegramm(cnetz);
if (bits) {
LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Konzentrierte Signalisierung' at timeslot %d.%d\n", cnetz->sched_ts, cnetz->sched_r_m * 5);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Konzentrierte Signalisierung' at timeslot %d.%d\n", cnetz->sched_ts, cnetz->sched_r_m * 5);
fsk_block_encode(cnetz, bits, 0);
} else
fsk_nothing_encode(cnetz);
@ -701,7 +712,7 @@ again:
case DSP_MODE_SPK_V:
bits = cnetz_encode_telegramm(cnetz);
if (bits) {
LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Verteilte Signalisierung' starting at timeslot %d\n", cnetz->sched_ts);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Verteilte Signalisierung' starting at timeslot %d\n", cnetz->sched_ts);
fsk_distributed_encode(cnetz, bits);
} else
fsk_nothing_encode(cnetz);
@ -797,7 +808,7 @@ void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length
calc_clock_speed(cnetz, length, 1, 0);
#ifdef TEST_SCRAMBLE
test_echo_load(&scrambler_test_echo, samples, length);
jitter_load(&scrambler_test_jb, samples, length);
scrambler(&scrambler_test_scrambler2, samples, length);
return;
#endif
@ -816,8 +827,7 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
{
sample_t *spl;
int pos, i;
int range;
double offset;
double x, y, x_last, y_last, factor;
/* check if we still have a transaction
* this might not be true, if we just released transaction, but still
@ -826,13 +836,21 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
if (!cnetz->trans_list)
return;
/* ramp from level of last frame to level of current frame */
range = cnetz->offset_range;
offset = speech_buffer[0] - cnetz->offset_last;
for (i = 0; i < range; i++) {
speech_buffer[i] -= offset * (1.0 - (double)i / (double)range);
/* fix offset between speech blocks by using high pass filter */
/* use first sample as previous sample, so we don't have a level jump between two subsequent audio chunks */
x_last = speech_buffer[0];
y_last = cnetz->offset_y_last;
factor = cnetz->offset_factor;
for (i = 0; i < count; i++) {
/* change level */
x = speech_buffer[i];
/* high-pass to remove low level frequencies, caused by level jump between audio chunks */
y = factor * (y_last + x - x_last);
x_last = x;
y_last = y;
speech_buffer[i] = y;
}
cnetz->offset_last = speech_buffer[count - 1];
cnetz->offset_y_last = y_last;
/* 4. de-emphasis is done by cnetz code, not by common code */
/* de-emphasis is only used when scrambler is off, see FTZ 171 TR 60 Clause 4 */
@ -863,12 +881,9 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
void cnetz_set_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode)
{
if (mode != cnetz->dsp_mode) {
LOGP_CHAN(DDSP, LOGL_INFO, "DSP mode %s -> %s\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode));
PDEBUG_CHAN(DDSP, DEBUG_INFO, "DSP mode %s -> %s\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode));
cnetz->dsp_mode = mode;
}
if (mode == DSP_MODE_SPK_V && cnetz->dsp_mode != mode)
jitter_reset(&cnetz->sender.dejitter);
/* we must get rid of partly received frame */
fsk_demod_reset(&cnetz->fsk_demod);
}
@ -876,35 +891,11 @@ void cnetz_set_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode)
void cnetz_set_sched_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode, int timeslot)
{
if (cnetz->sched_dsp_mode_ts < 0 && mode == cnetz->dsp_mode) {
LOGP_CHAN(DDSP, LOGL_INFO, "Schedule DSP mode %s not required, we are already in that mode\n", cnetz_dsp_mode_name(mode));
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Schedule DSP mode %s not required, we are already in that mode\n", cnetz_dsp_mode_name(mode));
return;
}
LOGP_CHAN(DDSP, LOGL_INFO, "Schedule DSP mode %s -> %s at timeslot %d\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode), timeslot);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Schedule DSP mode %s -> %s at timeslot %d\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode), timeslot);
cnetz->sched_dsp_mode = mode;
cnetz->sched_dsp_mode_ts = timeslot;
}
/* Receive audio from call instance. */
void call_down_audio(void *decoder, void *decoder_priv, int callref, uint16_t sequence, uint8_t marker, uint32_t timestamp, uint32_t ssrc, uint8_t *payload, int payload_len)
{
sender_t *sender;
cnetz_t *cnetz;
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
if (cnetz->trans_list && cnetz->trans_list->callref == callref)
break;
}
if (!sender)
return;
if (cnetz->dsp_mode == DSP_MODE_SPK_V) {
jitter_frame_t *jf;
jf = jitter_frame_alloc(decoder, decoder_priv, payload, payload_len, marker, sequence, timestamp, ssrc);
if (jf)
jitter_save(&cnetz->sender.dejitter, jf);
}
}
void call_down_clock(void) {}

View File

@ -121,10 +121,7 @@
* if debug is set to 1, debugging will start at program start
*/
//#define DEBUG_DECODER
#ifdef DEBUG_DECODER
static int debug = 0;
#endif
//static int debug = 0;
#include <stdio.h>
#include <stdint.h>
@ -132,7 +129,7 @@ static int debug = 0;
#include <string.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "cnetz.h"
#include "dsp.h"
#include "telegramm.h"
@ -143,7 +140,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
memset(fsk, 0, sizeof(*fsk));
if (samplerate < 48000) {
LOGP(DDSP, LOGL_ERROR, "Sample rate must be at least 48000 Hz!\n");
PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 48000 Hz!\n");
return -1;
}
@ -152,13 +149,13 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
switch (demod) {
case FSK_DEMOD_SLOPE:
LOGP(DDSP, LOGL_INFO, "Detecting level change by looking at slope (good for sound cards)\n");
PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking at slope (good for sound cards)\n");
break;
case FSK_DEMOD_LEVEL:
LOGP(DDSP, LOGL_INFO, "Detecting level change by looking zero crosssing (good for SDR)\n");
PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking zero crosssing (good for SDR)\n");
break;
default:
LOGP(DDSP, LOGL_ERROR, "Wrong demod type, please fix!\n");
PDEBUG(DDSP, DEBUG_ERROR, "Wrong demod type, please fix!\n");
abort();
}
@ -166,7 +163,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
half = (int)((double)samplerate / bitrate / 2.0 + 0.5);
fsk->bit_buffer_spl = calloc(sizeof(fsk->bit_buffer_spl[0]), len);
if (!fsk->bit_buffer_spl) {
LOGP(DDSP, LOGL_ERROR, "No mem!\n");
PDEBUG(DDSP, DEBUG_ERROR, "No mem!\n");
goto error;
}
@ -177,7 +174,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
fsk->speech_size = samplerate * 60 / bitrate + 10; /* 60 bits duration, add 10 to be safe */
fsk->speech_buffer = calloc(sizeof(fsk->speech_buffer[0]), fsk->speech_size);
if (!fsk->speech_buffer) {
LOGP(DDSP, LOGL_ERROR, "No mem!\n");
PDEBUG(DDSP, DEBUG_ERROR, "No mem!\n");
goto error;
}
@ -185,7 +182,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
#ifdef DEBUG_DECODER
char debug_filename[256];
sprintf(debug_filename, "/tmp/debug_decoder_channel_%s.txt", cnetz->sender.kanal);
sprintf(debug_filename, "/tmp/debug_decoder_channel_%d.txt", cnetz->sender.kanal);
fsk->debug_fp = fopen(debug_filename, "w");
if (!fsk->debug_fp) {
fprintf(stderr, "Failed to open decoder debug file '%s'!\n", debug_filename);
@ -417,6 +414,17 @@ static inline void find_change_slope(fsk_fm_demod_t *fsk)
sample_t threshold;
int i;
#ifdef DEBUG_DECODER
/* show deviation of middle sample in windows (in a range of bandwidth) */
if (debug) {
fprintf(fsk->debug_fp, "%s",
debug_amplitude(
fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]
)
);
}
#endif
/* get level range (level_min and level_max) and also
* get maximum slope (change_max) and where it was
* (change_at) and what direction it went (change_positive)
@ -484,6 +492,10 @@ static inline void find_change_slope(fsk_fm_demod_t *fsk)
}
fsk->next_bit -= fsk->bits_per_sample;
#ifdef DEBUG_DECODER
if (debug)
fprintf(fsk->debug_fp, "\n");
#endif
}
/* find bit change by looking at zero crossing */
@ -495,6 +507,12 @@ static inline void find_change_level(fsk_fm_demod_t *fsk)
/* get bit in the middle of the buffer */
s = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len];
#ifdef DEBUG_DECODER
/* show deviation */
if (debug)
fprintf(fsk->debug_fp, "%s", debug_amplitude(s));
#endif
/* just sample first bit in distributed mode */
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0) {
if (fmod(fsk->bit_time, BITS_PER_SPK_BLOCK) < 1.5)
@ -551,6 +569,10 @@ static inline void find_change_level(fsk_fm_demod_t *fsk)
fsk->next_bit -= fsk->bits_per_sample;
done:
#ifdef DEBUG_DECODER
if (debug)
fprintf(fsk->debug_fp, "\n");
#endif
return;
}
@ -558,7 +580,7 @@ done:
void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
{
int i;
double t = 0.0;
double t;
/* process signaling block, sample by sample */
for (i = 0; i < length; i++) {
@ -568,14 +590,6 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
if (fsk->bit_buffer_pos == fsk->bit_buffer_len)
fsk->bit_buffer_pos = 0;
#ifdef DEBUG_DECODER
/* show deviation of center sample in window */
if (debug)
fprintf(fsk->debug_fp, "%s", debug_amplitude(fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]));
if (debug && fmod(fsk->bit_time - fsk->bits_per_sample, 1.0) > fmod(fsk->bit_time, 1.0))
fprintf(fsk->debug_fp, " -bitchange-");
#endif
/* for each sample process buffer */
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
if (fsk->demod_type == FSK_DEMOD_SLOPE)
@ -597,7 +611,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
fsk->next_bit = 1.0 - fsk->bits_per_sample;
#ifdef DEBUG_DECODER
if (debug && fsk->bit_count)
fprintf(fsk->debug_fp, "\n---- SPK(V) BLOCK START ----");
fprintf(fsk->debug_fp, "---- SPK(V) BLOCK START ----\n");
#endif
fsk->bit_count = 0;
} else
@ -608,21 +622,13 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
find_change_level(fsk);
} else
if (t >= 5.5 && t < 65.5) {
#ifdef DEBUG_DECODER
if (debug && !fsk->speech_count)
fprintf(fsk->debug_fp, " (start recording speech)");
#endif
/* get audio for the duration of 60 bits */
/* prevent overflow, if speech_size != 0 and SPK_V
* has been restarted. */
if (fsk->speech_count < fsk->speech_size)
fsk->speech_buffer[fsk->speech_count++] = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len];
fsk->speech_buffer[fsk->speech_count++] = samples[i];
} else
if (t >= 65.5) {
#ifdef DEBUG_DECODER
if (debug && fsk->speech_count)
fprintf(fsk->debug_fp, " (stop recording speech)");
#endif
if (fsk->speech_count) {
unshrink_speech(fsk->cnetz, fsk->speech_buffer, fsk->speech_count);
fsk->speech_count = 0;
@ -635,10 +641,6 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
if (fsk->bit_time >= BITS_PER_SUPERFRAME) {
fsk->bit_time -= BITS_PER_SUPERFRAME;
}
#ifdef DEBUG_DECODER
if (debug && samples)
fprintf(fsk->debug_fp, "\n");
#endif
/* another clock is used to measure actual super frame time */
fsk->bit_time_uncorrected += fsk->bits_per_sample;
if (fsk->bit_time_uncorrected >= BITS_PER_SUPERFRAME) {

View File

@ -24,7 +24,7 @@
#include <errno.h>
#include "../libsample/sample.h"
#include "../libmobile/main_mobile.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../anetz/freiton.h"
#include "../anetz/besetztton.h"
@ -44,20 +44,19 @@ enum cnetz_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_OGK_SPK };
int measure_speed = 0;
double clock_speed[2] = { 0.0, 0.0 };
int set_clock_speed = 0;
const char *flip_polarity = "";
const char *flip_polarity = "auto";
int ms_power = 6; /* 1..8 */
int warteschlange = 1;
int challenge_valid;
uint64_t challenge;
int response_valid;
uint64_t response;
uint32_t timeslots = 4; /* 1 up to 8 */
uint8_t timeslot = 0;
uint8_t fuz_nat = 1;
uint8_t fuz_fuvst = 4;
uint8_t fuz_rest = 66;
const char *fuz_name = NULL;
uint8_t kennung_fufst = 1; /* normal prio */
uint8_t bahn_bs = 0; /* normal */
uint8_t authentifikationsbit = 0;
uint8_t ws_kennung = 0; /* no queue */
uint8_t fuvst_sperren = 0; /* no blocking registration/calls */
@ -73,11 +72,9 @@ uint8_t reduzierung = 0; /* factor 4 */
uint8_t nachbar_prio = 0;
int8_t futln_sperre_start = -1; /* no blocking */
int8_t futln_sperre_end = -1; /* no range */
int meldeinterval = 120; /* when to ask the phone about beeing alive */
int meldeaufrufe = 3; /* how many times to ask phone about beeing alive */
enum demod_type demod = FSK_DEMOD_AUTO;
int metering = 20;
double speech_deviation = 2400.0; /* best results with older equipment (not C5) */
double speech_deviation = 4000.0; /* best results with all my equipment */
void print_help(const char *arg0)
{
@ -85,10 +82,6 @@ void print_help(const char *arg0)
/* - - */
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(" You must define at least one OgK at channel 131. This channel may be a\n");
printf(" a combined OgK+SpK channel, but this works with older phones only.\n");
printf(" You must define additionally one or more SpK, in order to make calls.\n");
printf(" You may define alternative OgK, the phones will attach to it then.\n");
printf(" -M --measure-speed\n");
printf(" Measures clock speed. THIS IS REQUIRED! See documentation!\n");
printf(" -C --clock-speed <rx ppm>,<tx ppm>\n");
@ -102,8 +95,8 @@ void print_help(const char *arg0)
printf(" generates a negative signal rather than a positive one. If auto, the\n");
printf(" base station uses double time slots with alternating polarity.\n");
printf(" Once a mobile registers, the correct polarity is selected and used.\n");
printf(" (default = %s)\n", (flip_polarity[0]) ? flip_polarity : "auto");
printf(" Note: Correct polarity is selected for SDR by default.\n");
printf(" (default = %s)\n", flip_polarity);
printf(" Note: This has no effect with SDR.\n");
printf(" -P --ms-power <power level>\n");
printf(" Give power level of the mobile station: 1, 2, 4, 6, 8 (default = '%d')\n", ms_power);
printf(" 1 = 7.5-20 W; 2 = 4-8 W; 4 = 0.5-1 W; 6 = 50-125 mW; 8 = 2-10 mW\n");
@ -122,18 +115,17 @@ void print_help(const char *arg0)
printf(" Enable queue support. If no channel is available, calls will be kept\n");
printf(" in a queue for maximum of 60 seconds. (default = %d)\n", warteschlange);
printf(" -G --gebuehren <seconds> | 0\n");
printf(" Increment metering counter every given number of seconds.\n");
printf(" Increment metering counter every given number of seconds.\n");
printf(" To turn off, use 0. (default = %d)\n", metering);
printf(" If metering pulses are sent via Osmo-CC interface, pulses are always\n");
printf(" increment metering counter. This overrides this option.\n");
printf(" -V --voice-deviation <2400..4000 Hz>\n");
printf(" It is unclear what the actual voice deviation is. Please increase, if\n");
printf(" mobile's earpiece is too quiet and the microphone is too loud.\n");
printf(" It is unclear what the actual voice deviation is. Please decrease, if\n");
printf(" mobile's microphone is too loud and speaker is too quiet.\n");
printf(" (default = %.0f)\n", speech_deviation);
printf(" -S --sysinfo timeslots=1|2|4|8\n");
printf(" Set number of timeslots of OgK broadcast. There are 32 time slots per\n");
printf(" frame, but only up to 8 slots can be used, because of processing\n");
printf(" delay. (default = %d)\n", timeslots);
printf(" -S --sysinfo timeslot=<0..31>\n");
printf(" Set time slot of OgK broadcast. There are 32 time slots, but every 8th\n");
printf(" slot is used. This means if you select time slot 0, also slots 8, 16\n");
printf(" and 24 will be used. If you select slot 14, also slots 6, 22 and 30\n");
printf(" will be used. (default = %d)\n", timeslot);
printf(" -S --sysinfo fuz-nat=<nat>\n");
printf(" Set country ID of base station. All IDs were used inside Germany only.\n");
printf(" (default = %d)\n", fuz_nat);
@ -153,12 +145,6 @@ void print_help(const char *arg0)
printf(" 2 = Higher priority base station.\n");
printf(" 3 = Highest priority base station.\n");
printf(" Note: Priority has no effect, because there is only one base station.\n");
printf(" -S --sysinfo bahn-bs=<value>\n");
printf(" Set special tunnel base station mode for train mobile phones only.\n");
printf(" (default = %d)\n", kennung_fufst);
printf(" 0 = Disable (every phone is allowed)\n");
printf(" 1 = Enable (only train phones are allowed)\n");
printf(" Note: Enableing this will force priority to 0 (Test base station).\n");
printf(" -S --sysinfo auth=<auth>\n");
printf(" Enable authentication flag on the base station. Since we cannot\n");
printf(" authenticate, because we don't know the secret key and the algorithm,\n");
@ -231,12 +217,6 @@ void print_help(const char *arg0)
} else {
printf(" (default = %d-%d)\n", futln_sperre_start, futln_sperre_end);
}
printf(" -S --sysinfo meldeinterval=<seconds>\n");
printf(" Time to wait until pinging the phone wether it is still available.\n");
printf(" (default = %d)\n", meldeinterval);
printf(" -S --sysinfo meldeaufrufe=<count>\n");
printf(" Number of times we try to ping mobile until we assume it is gone.\n");
printf(" Use '0' for infinite tries. (default = %d)\n", meldeaufrufe);
printf(" -D --demod auto | slope | level\n");
printf(" Adjust demodulation algorithm. Use 'slope' to detect a level change\n");
printf(" by finding the highest slope of a bit transition. It is useful, if\n");
@ -366,8 +346,8 @@ static int handle_options(int short_option, int argi, char **argv)
return -EINVAL;
}
p++;
if (!strncasecmp(argv[argi], "timeslots=", p - argv[argi])) {
timeslots = atoi_limit(p, 1, 8);
if (!strncasecmp(argv[argi], "timeslot=", p - argv[argi])) {
timeslot = atoi_limit(p, 0, 31);
} else
if (!strncasecmp(argv[argi], "fuz-nat=", p - argv[argi])) {
fuz_nat = atoi_limit(p, 0, 7);
@ -400,9 +380,6 @@ error_fuz:
if (!strncasecmp(argv[argi], "kennung-fufst=", p - argv[argi])) {
kennung_fufst = atoi_limit(p, 0, 3);
} else
if (!strncasecmp(argv[argi], "bahn-bs=", p - argv[argi])) {
bahn_bs = atoi_limit(p, 0, 1);
} else
if (!strncasecmp(argv[argi], "auth=", p - argv[argi])) {
authentifikationsbit = atoi_limit(p, 0, 1);
} else
@ -456,12 +433,6 @@ error_fuz:
futln_sperre_end = atoi(q) & 0xf;
}
} else
if (!strncasecmp(argv[argi], "meldeinterval=", p - argv[argi])) {
meldeinterval = atoi_limit(p, 1, 20 * 60);
} else
if (!strncasecmp(argv[argi], "meldeaufrufe=", p - argv[argi])) {
meldeaufrufe = atoi_limit(p, 0, 1000000);
} else
{
fprintf(stderr, "Given sysinfo parameter '%s' unknown, use '-h' for help!\n", argv[argi]);
return -EINVAL;
@ -553,7 +524,7 @@ int main(int argc, char *argv[])
}
if (!num_kanal) {
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_STD_OGK_KANAL);
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_OGK_KANAL);
mandatory = 1;
}
if (use_sdr) {
@ -604,13 +575,7 @@ int main(int argc, char *argv[])
}
if (anzahl_gesperrter_teilnehmergruppen)
printf("Blocked subscriber with number's last 4 bits from 0x%x to 0x%x\n", teilnehmergruppensperre, (teilnehmergruppensperre + anzahl_gesperrter_teilnehmergruppen - 1) & 0xf);
switch(timeslots) {
case 1: timeslots=0x00000001; break;
case 2: timeslots=0x00010001; break;
case 4: timeslots=0x01010101; break;
default: timeslots=0x11111111;
}
init_sysinfo(timeslots, fuz_nat, fuz_fuvst, fuz_rest, kennung_fufst, bahn_bs, authentifikationsbit, ws_kennung, fuvst_sperren, grenz_einbuchen, grenz_umschalten, grenz_ausloesen, mittel_umschalten, mittel_ausloesen, genauigkeit, bewertung, entfernung, reduzierung, nachbar_prio, teilnehmergruppensperre, anzahl_gesperrter_teilnehmergruppen, meldeinterval, meldeaufrufe);
init_sysinfo(timeslot, fuz_nat, fuz_fuvst, fuz_rest, kennung_fufst, authentifikationsbit, ws_kennung, fuvst_sperren, grenz_einbuchen, grenz_umschalten, grenz_ausloesen, mittel_umschalten, mittel_ausloesen, genauigkeit, bewertung, entfernung, reduzierung, nachbar_prio, teilnehmergruppensperre, anzahl_gesperrter_teilnehmergruppen);
dsp_init();
rc = init_telegramm();
if (rc < 0) {
@ -620,7 +585,7 @@ int main(int argc, char *argv[])
init_coding();
cnetz_init();
/* check for mandatory standard OgK */
/* check for mandatory OgK */
for (i = 0; i < num_kanal; i++) {
if (chan_type[i] == CHAN_TYPE_OGK || chan_type[i] == CHAN_TYPE_OGK_SPK)
break;
@ -664,7 +629,7 @@ int main(int argc, char *argv[])
polarity = 1; /* positive */
if (!strcmp(flip_polarity, "yes"))
polarity = -1; /* negative */
if (use_sdr && !flip_polarity[0])
if (use_sdr && polarity == 0)
polarity = 1; /* SDR is always positive */
/* demodulation algorithm */
@ -702,7 +667,6 @@ fail:
cnetz_destroy(sender_head);
/* exits */
main_mobile_exit();
fm_exit();
options_free();

View File

@ -7,10 +7,10 @@
/* The list of cell towers is ripped from BSA61 phone's firmware */
static struct cnetz_stations {
char long_name[32], name[8];
char standort[32], name[8];
uint8_t nat, fuvst, rest;
} cnetz_stations[] = {
/* Langer-Name Kurzer Name, Nat FuVST Rest */
/* Standort-Name Kurzer Name, Nat FuVST Rest */
{ "Oberhausen 32", "OB32", 1, 2, 1, },
{ "Oberhausen 0 <prov.>", "OB0", 1, 2, 5, },
{ "Wuppertal 18", "WUP18", 1, 2, 6, },
@ -2143,37 +2143,37 @@ void station_list(void)
char name[33];
printf("List of all base stations:\n\n");
printf("Kurz Name Nat FuVst Rest\n");
printf("Name Standort Nat FuVst Rest\n");
printf("------------------------------------------------------------\n");
for (i = 0; cnetz_stations[i].long_name[0]; i++) {
for (i = 0; cnetz_stations[i].standort[0]; i++) {
memset(name, ' ', sizeof(name));
memcpy(name, cnetz_stations[i].name, strlen(cnetz_stations[i].name));
name[8] = '\0';
printf("%s", name);
memset(name, ' ', sizeof(name));
memcpy(name, cnetz_stations[i].long_name, strlen(cnetz_stations[i].long_name));
memcpy(name, cnetz_stations[i].standort, strlen(cnetz_stations[i].standort));
name[sizeof(name) - 1] = '\0';
printf("%s%d\t%d\t%d\n", name, cnetz_stations[i].nat, cnetz_stations[i].fuvst, cnetz_stations[i].rest);
}
}
const char *get_station_name(uint8_t nat, uint8_t fuvst, uint8_t rest, const char **long_name)
const char *get_station_name(uint8_t nat, uint8_t fuvst, uint8_t rest, const char **standort)
{
int i;
for (i = 0; cnetz_stations[i].long_name[0]; i++) {
for (i = 0; cnetz_stations[i].standort[0]; i++) {
if (cnetz_stations[i].nat == nat
&& cnetz_stations[i].fuvst == fuvst
&& cnetz_stations[i].rest == rest) {
if (long_name)
*long_name = cnetz_stations[i].long_name;
if (standort)
*standort = cnetz_stations[i].standort;
return cnetz_stations[i].name;
}
}
if (long_name)
*long_name = "unknown";
return *long_name;
if (standort)
*standort = "unknown";
return *standort;
}
const char *get_station_id(const char *name, uint8_t *nat, uint8_t *fuvst, uint8_t *rest)
@ -2182,8 +2182,7 @@ const char *get_station_id(const char *name, uint8_t *nat, uint8_t *fuvst, uint8
for (i = 0; cnetz_stations[i].name[0]; i++) {
/* check for given prefix */
if (!strncasecmp(cnetz_stations[i].name, name, strlen(name))
|| !strncasecmp(cnetz_stations[i].long_name, name, strlen(name)) ) {
if (!strncasecmp(cnetz_stations[i].name, name, strlen(name))) {
/* found twice */
if (found >= 0)
return "Given station name is ambiguous, use more letters! Use '-S fuz-name=list' to get a list of all stations.";

View File

@ -4,12 +4,12 @@
cnetz_si si;
void init_sysinfo(uint32_t timeslots, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t bahn_bs, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen, int meldeinterval, int meldeaufrufe)
void init_sysinfo(uint8_t timeslot, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen)
{
memset(&si, 0, sizeof(si));
/* timeslot to use */
si.timeslots = timeslots;
si.timeslot = timeslot;
/* ID of base station */
si.fuz_nat = fuz_nat;
@ -37,10 +37,7 @@ void init_sysinfo(uint32_t timeslots, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_
/* a low value is tollerant to bad quality */
si.grenz_einbuchen = grenz_einbuchen; /* 1..7 */
if (bahn_bs)
kennung_fufst = 0;
si.kennung_fufst = kennung_fufst;
si.bahn_bs = bahn_bs;
si.authentifikationsbit = authentifikationsbit;
@ -55,8 +52,5 @@ void init_sysinfo(uint32_t timeslots, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_
/* deny group of subscribers. (used to balance subscribers between base stations) */
si.teilnehmergruppensperre = teilnehmergruppensperre;
si.anzahl_gesperrter_teilnehmergruppen = anzahl_gesperrter_teilnehmergruppen;
si.meldeinterval = meldeinterval;
si.meldeaufrufe = meldeaufrufe;
}

View File

@ -1,6 +1,6 @@
typedef struct system_information {
uint32_t timeslots; /* timeslot map to use */
uint8_t timeslot; /* timeslot to use */
uint8_t fuz_nat; /* national network ID */
uint8_t fuz_fuvst; /* id of switching center */
uint8_t fuz_rest; /* rest of base station id */
@ -13,7 +13,6 @@ typedef struct system_information {
uint8_t entfernung;
uint8_t grenz_einbuchen;
uint8_t kennung_fufst; /* prio of base station */
uint8_t bahn_bs; /* special train base station */
uint8_t authentifikationsbit; /* base station suppoerts authentication */
uint8_t ws_kennung; /* queue setting sof base station */
uint8_t nachbar_prio;
@ -21,11 +20,9 @@ typedef struct system_information {
uint8_t reduzierung;
int8_t teilnehmergruppensperre;
int8_t anzahl_gesperrter_teilnehmergruppen;
int meldeinterval; /* when to retry availability check */
int meldeaufrufe; /* 0 for infinite */
} cnetz_si;
extern cnetz_si si;
void init_sysinfo(uint32_t timeslots, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t bahn_bs, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen, int meldeinterval, int meldeaufrufe);
void init_sysinfo(uint8_t timeslot, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen);

View File

@ -27,7 +27,7 @@
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "cnetz.h"
#include "dsp.h"
#include "sysinfo.h"
@ -510,13 +510,13 @@ static int encode_dialstring(uint64_t *value, const char *number)
max = strlen(number);
if (max > 16) {
LOGP(DFRAME, LOGL_NOTICE, "Given number '%s' has more than 16 digits\n", number);
PDEBUG(DFRAME, DEBUG_NOTICE, "Given number '%s' has more than 16 digits\n", number);
return -EINVAL;
}
if (max == 16) {
if (number[0] != '0') {
LOGP(DFRAME, LOGL_NOTICE, "Given 16 digit number '%s' does not start with '0'\n", number);
PDEBUG(DFRAME, DEBUG_NOTICE, "Given 16 digit number '%s' does not start with '0'\n", number);
return -EINVAL;
}
*value = 0;
@ -575,7 +575,7 @@ int match_fuz(telegramm_t *telegramm)
if (telegramm->fuz_nationalitaet != si.fuz_nat
|| telegramm->fuz_fuvst_nr != si.fuz_fuvst
|| telegramm->fuz_rest_nr != si.fuz_rest) {
LOGP(DFRAME, LOGL_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Cell 'Funkzelle' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
PDEBUG(DFRAME, DEBUG_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Cell 'Funkzelle' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
return 0;
}
@ -587,7 +587,7 @@ int match_futln(telegramm_t *telegramm, uint8_t futln_nat, uint8_t futln_fuvst,
if (telegramm->futln_nationalitaet != futln_nat
|| telegramm->futln_heimat_fuvst_nr != futln_fuvst
|| telegramm->futln_rest_nr != futln_rest) {
LOGP(DFRAME, LOGL_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Mobile station 'Funktelefongeraet' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
PDEBUG(DFRAME, DEBUG_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Mobile station 'Funktelefongeraet' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
return 0;
}
@ -600,19 +600,19 @@ static void debug_parameter(char digit, uint64_t value)
parameter = get_parameter(digit);
if (!parameter) {
LOGP(DFRAME, LOGL_ERROR, "Digit '%c' not found in definition_parameter list, please fix!\n", digit);
PDEBUG(DFRAME, DEBUG_ERROR, "Digit '%c' not found in definition_parameter list, please fix!\n", digit);
abort();
}
if (parameter->value_names)
LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : %s\n", digit, parameter->param_name, parameter->value_names[value]);
PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : %s\n", digit, parameter->param_name, parameter->value_names[value]);
else if (parameter->bits == 64)
LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : 0x%016" PRIx64 "\n", digit, parameter->param_name, value);
PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : 0x%016" PRIx64 "\n", digit, parameter->param_name, value);
else if (digit == 'X') {
char wahlziffern[17];
decode_dialstring(wahlziffern, value);
LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : '%s'\n", digit, parameter->param_name, wahlziffern);
PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : '%s'\n", digit, parameter->param_name, wahlziffern);
} else
LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : %" PRIu64 "\n", digit, parameter->param_name, value);
PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : %" PRIu64 "\n", digit, parameter->param_name, value);
}
/* encode telegram to 70 bits
@ -628,12 +628,11 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug)
int rc;
if (telegramm->opcode >= 64) {
LOGP(DFRAME, LOGL_ERROR, "Opcode '0x%x' exceeds bit range, please fix!\n", telegramm->opcode);
PDEBUG(DFRAME, DEBUG_ERROR, "Opcode '0x%x' exceeds bit range, please fix!\n", telegramm->opcode);
abort();
}
if (debug)
LOGP(DFRAME, LOGL_INFO, "Coding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text);
PDEBUG(DFRAME, DEBUG_DEBUG, "Coding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text);
/* copy opcode */
for (i = 0; i < 6; i++)
@ -717,7 +716,7 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug)
case 'X':
rc = encode_dialstring(&value, telegramm->wahlziffern);
if (rc < 0) {
LOGP(DFRAME, LOGL_ERROR, "Illegal dial string '%s', please fix!\n", telegramm->wahlziffern);
PDEBUG(DFRAME, DEBUG_ERROR, "Illegal dial string '%s', please fix!\n", telegramm->wahlziffern);
abort();
}
break;
@ -806,10 +805,10 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug)
value = telegramm->illegaler_opcode;
break;
default:
LOGP(DFRAME, LOGL_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter);
PDEBUG(DFRAME, DEBUG_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter);
abort();
}
if (debug && loglevel <= LOGL_DEBUG)
if (debug && debuglevel <= DEBUG_DEBUG)
debug_parameter(parameter, value);
val = value;
for (j = 0; string[63 - i - j] == parameter; j++) {
@ -817,14 +816,14 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug)
val >>= 1;
}
if (val)
LOGP(DFRAME, LOGL_ERROR, "Parameter '%c' value '0x%" PRIx64 "' exceeds bit range!\n", parameter, value);
PDEBUG(DFRAME, DEBUG_ERROR, "Parameter '%c' value '0x%" PRIx64 "' exceeds bit range!\n", parameter, value);
i += j - 1;
}
bits[70] = '\0';
if (debug) {
LOGP(DFRAME, LOGL_DEBUG, "OOOOOO%s\n", string);
LOGP(DFRAME, LOGL_DEBUG, "%s\n", bits);
PDEBUG(DFRAME, DEBUG_DEBUG, "OOOOOO%s\n", string);
PDEBUG(DFRAME, DEBUG_DEBUG, "%s\n", bits);
}
return bits;
@ -848,7 +847,7 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int
value = (value << 1) | (bits[i] == '1');
telegramm->opcode = value;
LOGP(DFRAME, LOGL_INFO, "Decoding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text);
PDEBUG(DFRAME, DEBUG_DEBUG, "Decoding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text);
/* copy parameters */
if (auth && bits[1]) /* auth flag and chip card flag */
@ -864,7 +863,7 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int
value = (value >> 1) | ((uint64_t)(bits[69 - i - j] == '1') << 63);
value >>= 64 - j;
i += j - 1;
if (loglevel <= LOGL_DEBUG)
if (debuglevel <= DEBUG_DEBUG)
debug_parameter(parameter, value);
switch (parameter) {
case 'A':
@ -1021,18 +1020,18 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int
telegramm->illegaler_opcode = value;
break;
default:
LOGP(DFRAME, LOGL_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter);
PDEBUG(DFRAME, DEBUG_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter);
abort();
}
}
if (loglevel <= LOGL_DEBUG) {
if (debuglevel <= DEBUG_DEBUG) {
char debug_bits[71];
memcpy(debug_bits, bits, 70);
debug_bits[70] = '\0';
LOGP(DFRAME, LOGL_DEBUG, "OOOOOO%s\n", string);
LOGP(DFRAME, LOGL_DEBUG, "%s\n", debug_bits);
PDEBUG(DFRAME, DEBUG_DEBUG, "OOOOOO%s\n", string);
PDEBUG(DFRAME, DEBUG_DEBUG, "%s\n", debug_bits);
}
}
@ -1392,11 +1391,11 @@ static const char *decode(const char *input, int *_bit_errors)
fail_str[10] = '\0';
if (failed)
LOGP(DFRAME, LOGL_DEBUG, "Received Telegram with these block errors: '%s' (X = uncorrectable)\n", fail_str);
PDEBUG(DFRAME, DEBUG_DEBUG, "Received Telegram with these block errors: '%s' (X = uncorrectable)\n", fail_str);
else if (warn)
LOGP(DFRAME, LOGL_DEBUG, "Received Telegram with these block errors: '%s' (1 / 2 = correctable)\n", fail_str);
PDEBUG(DFRAME, DEBUG_DEBUG, "Received Telegram with these block errors: '%s' (1 / 2 = correctable)\n", fail_str);
else
LOGP(DFRAME, LOGL_DEBUG, "Received Telegram with no block errors.\n");
PDEBUG(DFRAME, DEBUG_DEBUG, "Received Telegram with no block errors.\n");
if (failed)
return NULL;
@ -1496,13 +1495,14 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub
break;
}
if (i == 70) {
LOGP(DFRAME, LOGL_INFO, "Ignoring mysterious unmodulated telegramm (noise from phone's transmitter)\n");
PDEBUG(DFRAME, DEBUG_INFO, "Ignoring mysterious unmodulated telegramm (noise from phone's transmitter)\n");
return;
}
LOGP_CHAN(DDSP, LOGL_INFO, "RF level: %.1f dB RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) %s\n", cnetz->rf_level_db, fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
if (bit_errors)
LOGP_CHAN(DDSP, LOGL_INFO, " -> Frame has %d bit errors.\n", bit_errors);
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
else
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
disassemble_telegramm(&telegramm, bits, si.authentifikationsbit);
opcode = telegramm.opcode;
@ -1510,18 +1510,18 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub
telegramm.sync_time = sync_time;
if (cnetz->sender.loopback) {
LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
cnetz_sync_frame(cnetz, sync_time, -1);
return;
}
if (opcode >= 32) {
LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used by mobile station, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used by mobile station, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
return;
}
if (definition_opcode[opcode].block == BLOCK_I) {
LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is an illegal opcode, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is an illegal opcode, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
return;
}
@ -1544,7 +1544,7 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub
switch (cnetz->dsp_mode) {
case DSP_MODE_OGK:
if (definition_opcode[opcode].block != BLOCK_R && definition_opcode[opcode].block != BLOCK_M) {
LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used OgK channel signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used OgK channel signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
return;
}
/* determine block by last timeslot sent and by message type
@ -1557,14 +1557,14 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub
break;
case DSP_MODE_SPK_K:
if (definition_opcode[opcode].block != BLOCK_K) {
LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used for concentrated signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used for concentrated signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
return;
}
cnetz_receive_telegramm_spk_k(cnetz, &telegramm);
break;
case DSP_MODE_SPK_V:
if (definition_opcode[opcode].block != BLOCK_V) {
LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used for distributed signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used for distributed signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
return;
}
cnetz_receive_telegramm_spk_v(cnetz, &telegramm);
@ -1579,7 +1579,6 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz)
const telegramm_t *telegramm = NULL;
uint8_t opcode;
char *bits;
int debug = 1;
switch (cnetz->dsp_mode) {
case DSP_MODE_OGK:
@ -1602,11 +1601,7 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz)
return NULL;
opcode = telegramm->opcode;
if (opcode == OPCODE_LR_R && cnetz->sched_lr_debugged)
debug = 0;
if (opcode == OPCODE_MLR_M && cnetz->sched_mlr_debugged)
debug = 0;
bits = assemble_telegramm(telegramm, debug);
bits = assemble_telegramm(telegramm, (opcode != OPCODE_LR_R) && (opcode != OPCODE_MLR_M));
bits = encode(bits);
bits = interleave(bits);
@ -1618,13 +1613,6 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz)
bits[i] ^= 1;
}
if (opcode == OPCODE_LR_R && !cnetz->sched_lr_debugged)
cnetz->sched_lr_debugged = 1;
if (opcode == OPCODE_MLR_M && !cnetz->sched_mlr_debugged) {
cnetz->sched_mlr_debugged = 1;
LOGP(DFRAME, LOGL_INFO, "Subsequent IDLE frames are not show, to prevent flooding the output.\n");
}
return bits;
}

View File

@ -20,17 +20,14 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include "../libsample/sample.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libmobile/call.h"
#include "../libmobile/cause.h"
#include "cnetz.h"
#include "telegramm.h"
#include "database.h"
static int new_cueue_position = 0;
const char *transaction2rufnummer(transaction_t *trans)
{
static char rufnummer[32]; /* make GCC happy (overflow check) */
@ -41,35 +38,25 @@ const char *transaction2rufnummer(transaction_t *trans)
}
/* create transaction */
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended, double rf_level_db)
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended)
{
transaction_t *trans;
sender_t *sender;
transaction_t *trans = NULL;
cnetz_t *search_cnetz;
trans = search_transaction_number_global(futln_nat, futln_fuvst, futln_rest);
/* search transaction for this subscriber */
for (sender = sender_head; sender; sender = sender->next) {
search_cnetz = (cnetz_t *) sender;
/* search transaction for this callref */
trans = search_transaction_number(search_cnetz, futln_nat, futln_fuvst, futln_rest);
if (trans)
break;
}
if (trans) {
const char *rufnummer = transaction2rufnummer(trans);
int old_callref = trans->callref;
cnetz_t *old_cnetz = trans->cnetz;
/* both states must be the same and one of the give selection */
if ((trans->state & state & (TRANS_EM | TRANS_UM | TRANS_VWG | TRANS_ATQ_IDLE))) {
if (!isnan(trans->rf_level_db) && !isnan(rf_level_db) && trans->cnetz->kanal != cnetz->kanal) {
if (rf_level_db > trans->rf_level_db) {
LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is stronger, so we move to that channel!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal);
trans->rf_level_db = rf_level_db;
unlink_transaction(trans);
link_transaction(trans, cnetz);
update_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, cnetz->kanal, NULL, NULL, 1, 0);
return trans;
}
if (rf_level_db < trans->rf_level_db) {
LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is weaker, so we ignore that channel!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal);
return trans;
}
}
LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is also received. Try to avoid multiple OgK channels!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal);
return trans;
}
LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", rufnummer);
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", rufnummer);
destroy_transaction(trans);
if (old_cnetz) /* should be... */
cnetz_go_idle(old_cnetz);
@ -79,11 +66,11 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_
trans = calloc(1, sizeof(*trans));
if (!trans) {
LOGP(DTRANS, LOGL_ERROR, "No memory!\n");
PDEBUG(DTRANS, DEBUG_ERROR, "No memory!\n");
return NULL;
}
osmo_timer_setup(&trans->timer, transaction_timeout, trans);
timer_init(&trans->timer, transaction_timeout, trans);
trans_new_state(trans, state);
trans->futln_nat = futln_nat;
@ -96,17 +83,15 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_
trans->mt_call = 1;
const char *rufnummer = transaction2rufnummer(trans);
LOGP(DTRANS, LOGL_INFO, "Created transaction for subscriber '%s'\n", rufnummer);
PDEBUG(DTRANS, DEBUG_INFO, "Created transaction for subscriber '%s'\n", rufnummer);
link_transaction(trans, cnetz);
/* update database: now busy */
update_db(futln_nat, futln_fuvst, futln_rest, cnetz->kanal, &futelg_bit, &extended, 1, 0);
update_db(cnetz, futln_nat, futln_fuvst, futln_rest, &futelg_bit, &extended, 1, 0);
trans->futelg_bit = futelg_bit;
trans->extended = extended;
trans->rf_level_db = rf_level_db;
return trans;
}
@ -114,14 +99,14 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_
void destroy_transaction(transaction_t *trans)
{
/* update database: now idle */
update_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, 0, NULL, NULL, 0, trans->page_failed);
update_db(trans->cnetz, trans->futln_nat, trans->futln_fuvst, trans->futln_rest, NULL, NULL, 0, trans->page_failed);
unlink_transaction(trans);
const char *rufnummer = transaction2rufnummer(trans);
LOGP(DTRANS, LOGL_INFO, "Destroying transaction for subscriber '%s'\n", rufnummer);
PDEBUG(DTRANS, DEBUG_INFO, "Destroying transaction for subscriber '%s'\n", rufnummer);
osmo_timer_del(&trans->timer);
timer_exit(&trans->timer);
trans_new_state(trans, 0);
@ -134,7 +119,7 @@ void link_transaction(transaction_t *trans, cnetz_t *cnetz)
transaction_t **transp;
/* attach to end of list, so first transaction is served first */
LOGP(DTRANS, LOGL_DEBUG, "Linking transaction %p to cnetz %p\n", trans, cnetz);
PDEBUG(DTRANS, DEBUG_DEBUG, "Linking transaction %p to cnetz %p\n", trans, cnetz);
trans->cnetz = cnetz;
trans->next = NULL;
transp = &cnetz->trans_list;
@ -150,12 +135,12 @@ void unlink_transaction(transaction_t *trans)
transaction_t **transp;
/* unlink */
LOGP(DTRANS, LOGL_DEBUG, "Unlinking transaction %p from cnetz %p\n", trans, trans->cnetz);
PDEBUG(DTRANS, DEBUG_DEBUG, "Unlinking transaction %p from cnetz %p\n", trans, trans->cnetz);
transp = &trans->cnetz->trans_list;
while (*transp && *transp != trans)
transp = &((*transp)->next);
if (!(*transp)) {
LOGP(DTRANS, LOGL_ERROR, "Transaction not in list, please fix!!\n");
PDEBUG(DTRANS, DEBUG_ERROR, "Transaction not in list, please fix!!\n");
abort();
}
*transp = trans->next;
@ -170,7 +155,7 @@ transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask)
while (trans) {
if ((trans->state & state_mask)) {
const char *rufnummer = transaction2rufnummer(trans);
LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer);
PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer);
return trans;
}
trans = trans->next;
@ -188,7 +173,7 @@ transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint
&& trans->futln_fuvst == futln_fuvst
&& trans->futln_rest == futln_rest) {
const char *rufnummer = transaction2rufnummer(trans);
LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer);
PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer);
return trans;
}
trans = trans->next;
@ -197,23 +182,6 @@ transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint
return NULL;
}
transaction_t *search_transaction_number_global(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
{
sender_t *sender;
cnetz_t *cnetz;
transaction_t *trans = NULL;
/* search transaction for this subscriber */
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
/* search transaction for this callref */
trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest);
if (trans)
break;
}
return trans;
}
transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
{
transaction_t *trans = cnetz->trans_list;
@ -224,7 +192,7 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
while (trans) {
if (trans->callref == callref) {
const char *rufnummer = transaction2rufnummer(trans);
LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer);
PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer);
return trans;
}
trans = trans->next;
@ -233,42 +201,6 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
return NULL;
}
/* get oldest transaction in queue:
*
* oldest means that the queue number is the smallest.
* all candidates (transactions) must be in queue state.
*/
transaction_t *search_transaction_queue(void)
{
sender_t *sender;
transaction_t *trans, *found = NULL;
cnetz_t *cnetz;
int queue_max = 0;
for (sender = sender_head; sender; sender = sender->next) {
cnetz = (cnetz_t *) sender;
trans = cnetz->trans_list;
while (trans) {
if ((trans->state & (TRANS_MO_QUEUE | TRANS_MT_QUEUE))) {
/* select if first or lower number */
if (!found || trans->queue_position < queue_max) {
queue_max = trans->queue_position;
found = trans;
}
}
trans = trans->next;
}
}
if (found) {
const char *rufnummer = transaction2rufnummer(found);
LOGP(DTRANS, LOGL_DEBUG, "Found oldest transaction in queue for subscriber '%s'\n", rufnummer);
return found;
}
return NULL;
}
static const char *trans_state_name(uint64_t state)
{
switch (state) {
@ -320,8 +252,6 @@ static const char *trans_state_name(uint64_t state)
return "AT";
case TRANS_ATQ:
return "ATQ";
case TRANS_ATQ_IDLE:
return "ATQ_IDLE";
case TRANS_MO_QUEUE:
return "MO_QUEUE";
case TRANS_MT_QUEUE:
@ -371,7 +301,6 @@ const char *trans_short_state_name(uint64_t state)
case TRANS_AF:
case TRANS_AT:
case TRANS_ATQ:
case TRANS_ATQ_IDLE:
return "RELEASE";
case TRANS_MO_QUEUE:
case TRANS_MO_DELAY:
@ -386,11 +315,8 @@ const char *trans_short_state_name(uint64_t state)
void trans_new_state(transaction_t *trans, uint64_t state)
{
LOGP(DTRANS, LOGL_INFO, "Transaction (%s) state %s -> %s\n", transaction2rufnummer(trans), trans_state_name(trans->state), trans_state_name(state));
PDEBUG(DTRANS, DEBUG_INFO, "Transaction (%s) state %s -> %s\n", transaction2rufnummer(trans), trans_state_name(trans->state), trans_state_name(state));
trans->state = state;
/* in case of a queue, set new positon */
if (!trans->queue_position && (state == TRANS_MO_QUEUE || state == TRANS_MT_QUEUE))
trans->queue_position = ++new_cueue_position;
cnetz_display_status();
}
@ -398,12 +324,12 @@ void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans)
{
/* flush after this very trans */
while (trans->next) {
LOGP(DTRANS, LOGL_NOTICE, "Kicking other pending transaction\n");
PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n");
destroy_transaction(trans->next);
}
/* flush before this very trans */
while (cnetz->trans_list != trans) {
LOGP(DTRANS, LOGL_NOTICE, "Kicking other pending transaction\n");
PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n");
destroy_transaction(cnetz->trans_list);
}
}

View File

@ -29,12 +29,11 @@
#define TRANS_AF (1 << 20) /* release connection by base station (SpK) */
#define TRANS_AT (1 << 21) /* release connection by mobile station */
#define TRANS_ATQ (1 << 22) /* acknowledge release of MO call in queue */
#define TRANS_ATQ_IDLE (1 << 23) /* repeat, if call has been released already (mobile sends again) */
/* queue */
#define TRANS_MO_QUEUE (1 << 24) /* MO queue */
#define TRANS_MT_QUEUE (1 << 25) /* MT queue */
#define TRANS_MO_DELAY (1 << 26) /* delay to be sure the channel is free again */
#define TRANS_MT_DELAY (1 << 27)
#define TRANS_MO_QUEUE (1 << 23) /* MO queue */
#define TRANS_MT_QUEUE (1 << 24) /* MT queue */
#define TRANS_MO_DELAY (1 << 25) /* delay to be sure the channel is free again */
#define TRANS_MT_DELAY (1 << 26)
typedef struct transaction {
struct transaction *next; /* pointer to next node in list */
@ -50,29 +49,23 @@ typedef struct transaction {
int8_t release_cause; /* reason for release, (c-netz coding) */
int try; /* counts resending messages */
int repeat; /* counts repeating messages */
struct osmo_timer_list timer; /* for varous timeouts */
struct timer timer; /* for varous timeouts */
int mo_call; /* flags a moile originating call */
int mt_call; /* flags a moile terminating call */
int page_failed; /* failed to get a response from MS */
double metering_time; /* time between units (0.0 if no metering set) */
double meter_start; /* when did the metering start? (0.0 if not yet started) */
double meter_end; /* when did the metering end? (0.0 if not yet ended) */
int queue_position; /* to find next transaction in queue */
double rf_level_db; /* level of first contact, so we can detect correct channel at multiple receptions */
double call_start; /* when did the call start? (used for metering) */
} transaction_t;
const char *transaction2rufnummer(transaction_t *trans);
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended, double rf_level_db);
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended);
void destroy_transaction(transaction_t *trans);
void link_transaction(transaction_t *trans, cnetz_t *cnetz);
void unlink_transaction(transaction_t *trans);
transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask);
transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
transaction_t *search_transaction_number_global(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref);
transaction_t *search_transaction_queue(void);
void trans_new_state(transaction_t *trans, uint64_t state);
void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans);
void transaction_timeout(void *data);
void transaction_timeout(struct timer *timer);
const char *trans_short_state_name(uint64_t state);

View File

@ -1,5 +1,4 @@
AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes) \
$(FUSE_CFLAGS)
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) $(FUSE_CFLAGS)
bin_PROGRAMS = \
datenklo
@ -13,15 +12,15 @@ datenklo_SOURCES = \
datenklo_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdebug/libdebug.a \
$(top_builddir)/src/libfsk/libfsk.a \
$(top_builddir)/src/libtimer/libtimer.a \
$(top_builddir)/src/libfm/libfm.a \
$(top_builddir)/src/libfilter/libfilter.a \
$(top_builddir)/src/libsound/libsound.a \
$(top_builddir)/src/libwave/libwave.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
$(top_builddir)/src/libsample/libsample.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(ALSA_LIBS) \
$(FUSE_LIBS) \
-lm

View File

@ -75,14 +75,12 @@
#include <string.h>
#include <errno.h>
#include <math.h>
#include "../liblogging/logging.h"
#include <osmocom/core/timer.h>
#include "../libdebug/debug.h"
#include "../libtimer/timer.h"
#include "../libsample/sample.h"
#include "../libfsk/fsk.h"
#include "am791x.h"
#define FLOAT_TO_TIMEOUT(f) floor(f), ((f) - floor(f)) * 1000000
#define db2level(db) pow(10, (double)(db) / 20.0)
#define level2db(level) (20 * log10(level))
@ -300,13 +298,13 @@ void am791x_list_mc(enum am791x_type type)
}
/* init STO signal */
static void init_sto(am791x_t *am791x)
void init_sto(am791x_t *am791x)
{
am791x->sto_phaseshift65536 = 900 / (double)am791x->samplerate * 65536.0;
}
/* transmit STO signal, use phase from FSK modulator, to avoid phase jumps */
static int send_sto(am791x_t *am791x, sample_t *sample, int length)
int send_sto(am791x_t *am791x, sample_t *sample, int length)
{
fsk_mod_t *fsk = &am791x->fsk_tx;
int count = 0;
@ -316,7 +314,7 @@ static int send_sto(am791x_t *am791x, sample_t *sample, int length)
/* modulate STO */
phaseshift = am791x->sto_phaseshift65536;
while (count < length) {
while (count < length && fsk->tx_bitpos < 1.0) {
sample[count++] = fsk->sin_tab[(uint16_t)phase];
phase += phaseshift;
if (phase >= 65536.0)
@ -375,19 +373,19 @@ static int fsk_send_bit(void *inst)
/* main channel returns TD */
if (!am791x->block_td) {
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, "Modulating bit '%d' for MAIN channel\n", bit);
PDEBUG(DDSP, DEBUG_DEBUG, "Modulating bit '%d' for MAIN channel\n", bit);
#endif
return bit;
}
/* back channel returns BTD */
if (!am791x->block_btd) {
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, "Modulating bit '%d' for BACK channel\n", bbit);
PDEBUG(DDSP, DEBUG_DEBUG, "Modulating bit '%d' for BACK channel\n", bbit);
#endif
return bbit;
}
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, "Modulating bit '1', because TD & BTD is ignored\n");
PDEBUG(DDSP, DEBUG_DEBUG, "Modulating bit '1', because TD & BTD is ignored\n");
#endif
return 1;
}
@ -401,7 +399,7 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
int *block, *cd;
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, "Demodulated bit '%d' (level = %.0f dBm, quality = %%%.0f)\n", bit, level2db(level), quality * 100.0);
PDEBUG(DDSP, DEBUG_DEBUG, "Demodulated bit '%d' (level = %.0f dBm, quality = %%%.0f)\n", bit, level2db(level), quality * 100.0);
#endif
if (!am791x->rx_back_channel) {
@ -418,12 +416,12 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
handle_rx_state(am791x);
} else
if (!(*block) && !(*cd) && level > am791x->cd_on && quality >= RX_QUALITY) {
LOGP(DDSP, LOGL_DEBUG, "Good quality (level = %.0f dBm, quality = %%%.0f)\n", level2db(level), quality * 100.0);
PDEBUG(DDSP, DEBUG_DEBUG, "Good quality (level = %.0f dBm, quality = %%%.0f)\n", level2db(level), quality * 100.0);
*cd = 1;
handle_rx_state(am791x);
} else
if (*cd && (level < am791x->cd_off || quality < RX_QUALITY)) {
LOGP(DDSP, LOGL_DEBUG, "Bad quality (level = %.0f dBm, quality = %%%.0f)\n", level2db(level), quality * 100.0);
PDEBUG(DDSP, DEBUG_DEBUG, "Bad quality (level = %.0f dBm, quality = %%%.0f)\n", level2db(level), quality * 100.0);
*cd = 0;
handle_rx_state(am791x);
}
@ -439,24 +437,24 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
/* main channel forwards bit to RD */
if (!am791x->block_rd) {
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, " -> Forwarding bit '%d' to MAIN channel\n", bit);
PDEBUG(DDSP, DEBUG_DEBUG, " -> Forwarding bit '%d' to MAIN channel\n", bit);
#endif
am791x->rd_cb(am791x->inst, bit, quality * 100.0, level2db(level));
} else {
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, " -> Forwarding bit '1' to MAIN channel, because RD is set to MARK\n");
PDEBUG(DDSP, DEBUG_DEBUG, " -> Forwarding bit '1' to MAIN channel, because RD is set to MARK\n");
#endif
am791x->rd_cb(am791x->inst, 1, NAN, NAN);
}
/* main channel forwards bit to RD */
if (!am791x->block_brd) {
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, " -> Forwarding bit '%d' to BACK channel\n", bit);
PDEBUG(DDSP, DEBUG_DEBUG, " -> Forwarding bit '%d' to BACK channel\n", bit);
#endif
am791x->brd_cb(am791x->inst, bit, quality * 100.0, level2db(level));
} else {
#ifdef HEAVY_DEBUG
LOGP(DDSP, LOGL_DEBUG, " -> Forwarding bit '1' to BACK channel, because BRD is set to MARK\n");
PDEBUG(DDSP, DEBUG_DEBUG, " -> Forwarding bit '1' to BACK channel, because BRD is set to MARK\n");
#endif
am791x->brd_cb(am791x->inst, 1, NAN, NAN);
}
@ -531,9 +529,9 @@ static void set_filters(am791x_t *am791x)
/* transmitter used */
if (f0_tx > 0 && am791x->f0_tx == 0) {
LOGP(DDSP, LOGL_DEBUG, "Setting modulator to %s channel's frequencies (F0 = %d, F1 = %d), baudrate %.0f\n", name_tx, f0_tx, f1_tx, am791x->tx_baud);
PDEBUG(DDSP, DEBUG_DEBUG, "Setting modulator to %s channel's frequencies (F0 = %d, F1 = %d), baudrate %.0f\n", name_tx, f0_tx, f1_tx, am791x->tx_baud);
if (fsk_mod_init(&am791x->fsk_tx, am791x, fsk_send_bit, am791x->samplerate, am791x->tx_baud, (double)f0_tx, (double)f1_tx, am791x->tx_level, 0, 1) < 0)
LOGP(DDSP, LOGL_ERROR, "FSK RX init failed!\n");
PDEBUG(DDSP, DEBUG_ERROR, "FSK RX init failed!\n");
else {
am791x->f0_tx = f0_tx;
am791x->f1_tx = f1_tx;
@ -550,9 +548,9 @@ static void set_filters(am791x_t *am791x)
/* receiver used */
if (f0_rx > 0 && am791x->f0_rx == 0) {
LOGP(DDSP, LOGL_DEBUG, "Setting demodulator to %s channel's frequencies (F0 = %d, F1 = %d), baudrate %.0f\n", name_rx, f0_rx, f1_rx, am791x->rx_baud);
PDEBUG(DDSP, DEBUG_DEBUG, "Setting demodulator to %s channel's frequencies (F0 = %d, F1 = %d), baudrate %.0f\n", name_rx, f0_rx, f1_rx, am791x->rx_baud);
if (fsk_demod_init(&am791x->fsk_rx, am791x, fsk_receive_bit, am791x->samplerate, am791x->rx_baud, (double)f0_rx, (double)f1_rx, BIT_ADJUST) < 0)
LOGP(DDSP, LOGL_ERROR, "FSK RX init failed!\n");
PDEBUG(DDSP, DEBUG_ERROR, "FSK RX init failed!\n");
else {
am791x->f0_rx = f0_rx;
am791x->f1_rx = f1_rx;
@ -564,14 +562,14 @@ static void set_filters(am791x_t *am791x)
static void new_tx_state(am791x_t *am791x, enum am791x_st state)
{
if (am791x->tx_state != state)
LOGP(DAM791X, LOGL_DEBUG, "Change TX state %s -> %s\n", am791x_state_names[am791x->tx_state], am791x_state_names[state]);
PDEBUG(DAM791X, DEBUG_DEBUG, "Change TX state %s -> %s\n", am791x_state_names[am791x->tx_state], am791x_state_names[state]);
am791x->tx_state = state;
}
static void new_rx_state(am791x_t *am791x, enum am791x_st state)
{
if (am791x->rx_state != state)
LOGP(DAM791X, LOGL_DEBUG, "Change RX state %s -> %s\n", am791x_state_names[am791x->rx_state], am791x_state_names[state]);
PDEBUG(DAM791X, DEBUG_DEBUG, "Change RX state %s -> %s\n", am791x_state_names[am791x->rx_state], am791x_state_names[state]);
am791x->rx_state = state;
}
@ -579,7 +577,7 @@ static void new_rx_state(am791x_t *am791x, enum am791x_st state)
static void set_flag(int *flag_p, int value, const char *name)
{
if (*flag_p != value) {
LOGP(DAM791X, LOGL_DEBUG, " -> %s\n", name);
PDEBUG(DAM791X, DEBUG_DEBUG, " -> %s\n", name);
*flag_p = value;
}
}
@ -587,9 +585,10 @@ static void set_flag(int *flag_p, int value, const char *name)
/*
* state machine according to datasheet
*/
static void go_main_channel_tx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable transmitter on main channel\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Enable transmitter on main channel\n");
/* only block RD, if not full duplex and not 4-wire (loopback mode) */
if (!am791x->fullduplex && !am791x->loopback_main) {
@ -600,8 +599,7 @@ static void go_main_channel_tx(am791x_t *am791x)
/* activate TD now and set CTS timer (RCON) */
set_flag(&am791x->block_td, 0, "TD RELEASED");
set_flag(&am791x->tx_silence, 0, "RESET SILENCE");
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_rcon;
timer_start(&am791x->tx_timer, am791x->t_rcon);
new_tx_state(am791x, AM791X_STATE_RCON);
set_filters(am791x);
/* check CD to be blocked */
@ -615,7 +613,7 @@ static void go_main_channel_tx(am791x_t *am791x)
static void rcon_release_rts(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "RTS was released\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "RTS was released\n");
set_flag(&am791x->block_td, 1, "TD IGNORED");
set_flag(&am791x->tx_silence, 1, "SET SILENCE");
@ -631,7 +629,7 @@ static void rcon_release_rts(am791x_t *am791x)
static void rcon_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Transmission started\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Transmission started\n");
new_tx_state(am791x, AM791X_STATE_DATA);
/* CTS on */
@ -640,7 +638,7 @@ static void rcon_done(am791x_t *am791x)
static void tx_data_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "RTS was released\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "RTS was released\n");
new_tx_state(am791x, AM791X_STATE_RCOFF);
set_flag(&am791x->block_td, 1, "TD IGNORED");
@ -652,13 +650,12 @@ static void tx_data_done(am791x_t *am791x)
if (!am791x->fullduplex) {
set_flag(&am791x->squelch, 1, "SET SQUELCH (ON)");
}
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_rcoff;
timer_start(&am791x->tx_timer, am791x->t_rcoff);
}
static void rcoff_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Transmission over\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Transmission over\n");
/* CTS off */
am791x->cts_cb(am791x->inst, 0);
@ -668,19 +665,17 @@ static void rcoff_done(am791x_t *am791x)
return;
}
if (!am791x->sto) {
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_sq - am791x->t_rcoff;
timer_start(&am791x->tx_timer, am791x->t_sq - am791x->t_rcoff);
new_tx_state(am791x, AM791X_STATE_SQ_OFF);
return;
}
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_sto - am791x->t_rcoff;
timer_start(&am791x->tx_timer, am791x->t_sto - am791x->t_rcoff);
new_tx_state(am791x, AM791X_STATE_STO_OFF);
}
static void sq_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Squelch over\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Squelch over\n");
set_flag(&am791x->block_cd, 0, "CD RELEASED");
new_tx_state(am791x, AM791X_STATE_INIT);
@ -695,17 +690,16 @@ static void sq_done(am791x_t *am791x)
static void sto_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "STO over\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "STO over\n");
set_flag(&am791x->tx_sto, 0, "stop STO");
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_sq - am791x->t_sto;
timer_start(&am791x->tx_timer, am791x->t_sq - am791x->t_sto);
new_tx_state(am791x, AM791X_STATE_SQ_OFF);
}
static void go_back_channel_tx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable transmitter on back channel\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Enable transmitter on back channel\n");
if (!am791x->loopback_back) {
set_flag(&am791x->block_brd, 1, "BRD = MARK");
@ -715,8 +709,7 @@ static void go_back_channel_tx(am791x_t *am791x)
/* activate BTD now and set BCTS timer (BRCON) */
set_flag(&am791x->block_btd, 0, "BTD RELEASED");
set_flag(&am791x->tx_silence, 0, "RESET SILENCE");
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_brcon;
timer_start(&am791x->tx_timer, am791x->t_brcon);
new_tx_state(am791x, AM791X_STATE_BRCON);
set_filters(am791x);
/* check BCD to be blocked */
@ -730,7 +723,7 @@ static void go_back_channel_tx(am791x_t *am791x)
static void brcon_release_brts(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "BRTS was released\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "BRTS was released\n");
set_flag(&am791x->tx_silence, 1, "SET SILENCE");
new_tx_state(am791x, AM791X_STATE_INIT);
@ -739,7 +732,7 @@ static void brcon_release_brts(am791x_t *am791x)
static void brcon_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Transmission started\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Transmission started\n");
new_tx_state(am791x, AM791X_STATE_BDATA);
/* BCTS on */
@ -748,17 +741,16 @@ static void brcon_done(am791x_t *am791x)
static void tx_bdata_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "BRTS was released\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "BRTS was released\n");
set_flag(&am791x->block_btd, 1, "BTD IGNORED");
set_flag(&am791x->tx_silence, 1, "SET SILENCE");
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_brcoff;
timer_start(&am791x->tx_timer, am791x->t_brcoff);
}
static void brcoff_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Transmission over\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Transmission over\n");
/* BCTS off */
am791x->bcts_cb(am791x->inst, 0);
@ -799,8 +791,7 @@ static void handle_tx_state(am791x_t *am791x)
rcon_release_rts(am791x);
break;
}
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
if (!timer_running(&am791x->tx_timer)) {
rcon_done(am791x);
break;
}
@ -812,22 +803,19 @@ static void handle_tx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_RCOFF:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
if (!timer_running(&am791x->tx_timer)) {
rcoff_done(am791x);
break;
}
break;
case AM791X_STATE_STO_OFF:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
if (!timer_running(&am791x->tx_timer)) {
sto_done(am791x);
break;
}
break;
case AM791X_STATE_SQ_OFF:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
if (!timer_running(&am791x->tx_timer)) {
sq_done(am791x);
break;
}
@ -838,8 +826,7 @@ static void handle_tx_state(am791x_t *am791x)
brcon_release_brts(am791x);
break;
}
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
if (!timer_running(&am791x->tx_timer)) {
brcon_done(am791x);
break;
}
@ -851,29 +838,27 @@ static void handle_tx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_BRCOFF:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
if (!timer_running(&am791x->tx_timer)) {
brcoff_done(am791x);
break;
}
break;
default:
LOGP(DAM791X, LOGL_ERROR, "State %s not handled!\n", am791x_state_names[am791x->rx_state]);
PDEBUG(DAM791X, DEBUG_ERROR, "State %s not handled!\n", am791x_state_names[am791x->rx_state]);
}
}
static void go_main_channel_rx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable receiver on main channel\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Enable receiver on main channel\n");
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_cdon;
timer_start(&am791x->rx_timer, am791x->t_cdon);
new_rx_state(am791x, AM791X_STATE_CDON);
}
static void cdon_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Reception started\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Reception started\n");
set_flag(&am791x->block_rd, 0, "RD RELEASED");
new_rx_state(am791x, AM791X_STATE_DATA);
@ -887,25 +872,23 @@ static void cdon_done(am791x_t *am791x)
static void cdon_no_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier is gone\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier is gone\n");
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
timer_stop(&am791x->rx_timer);
new_rx_state(am791x, AM791X_STATE_INIT);
}
static void rx_data_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier lost\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier lost\n");
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_cdoff;
timer_start(&am791x->rx_timer, am791x->t_cdoff);
new_rx_state(am791x, AM791X_STATE_CDOFF);
}
static void cdoff_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Reception finished\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Reception finished\n");
set_flag(&am791x->block_rd, 1, "RD = MARK");
new_rx_state(am791x, AM791X_STATE_INIT);
@ -919,25 +902,23 @@ static void cdoff_done(am791x_t *am791x)
static void cdoff_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier recovered\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier recovered\n");
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
timer_stop(&am791x->rx_timer);
new_rx_state(am791x, AM791X_STATE_DATA);
}
static void go_back_channel_rx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable receiver on back channel\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Enable receiver on back channel\n");
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_bcdon;
timer_start(&am791x->rx_timer, am791x->t_bcdon);
new_rx_state(am791x, AM791X_STATE_BCDON);
}
static void bcdon_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier was detected\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier was detected\n");
set_flag(&am791x->block_brd, 0, "BRD RELEASED");
new_rx_state(am791x, AM791X_STATE_BDATA);
@ -951,25 +932,23 @@ static void bcdon_done(am791x_t *am791x)
static void bcdon_no_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier is gone\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier is gone\n");
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
timer_stop(&am791x->rx_timer);
new_rx_state(am791x, AM791X_STATE_INIT);
}
static void rx_bdata_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier lost\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier lost\n");
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_bcdoff;
timer_start(&am791x->rx_timer, am791x->t_bcdoff);
new_rx_state(am791x, AM791X_STATE_BCDOFF);
}
static void bcdoff_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Reception finished\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Reception finished\n");
if (!am791x->bell_202)
set_flag(&am791x->block_brd, 1, "BRD = MARK");
@ -984,10 +963,9 @@ static void bcdoff_done(am791x_t *am791x)
static void bcdoff_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier recovered\n");
PDEBUG(DAM791X, DEBUG_DEBUG, "Carrier recovered\n");
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
timer_stop(&am791x->rx_timer);
new_rx_state(am791x, AM791X_STATE_BDATA);
}
@ -1014,8 +992,7 @@ static void handle_rx_state(am791x_t *am791x)
break;
/* all main channel states ... */
case AM791X_STATE_CDON:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
if (!timer_running(&am791x->rx_timer)) {
cdon_done(am791x);
break;
}
@ -1031,8 +1008,7 @@ static void handle_rx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_CDOFF:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
if (!timer_running(&am791x->rx_timer)) {
cdoff_done(am791x);
break;
}
@ -1043,8 +1019,7 @@ static void handle_rx_state(am791x_t *am791x)
break;
/* all back channel states ... */
case AM791X_STATE_BCDON:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
if (!timer_running(&am791x->rx_timer)) {
bcdon_done(am791x);
break;
}
@ -1060,8 +1035,7 @@ static void handle_rx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_BCDOFF:
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
if (!timer_running(&am791x->rx_timer)) {
bcdoff_done(am791x);
break;
}
@ -1071,7 +1045,7 @@ static void handle_rx_state(am791x_t *am791x)
}
break;
default:
LOGP(DAM791X, LOGL_ERROR, "State %s not handled!\n", am791x_state_names[am791x->rx_state]);
PDEBUG(DAM791X, DEBUG_ERROR, "State %s not handled!\n", am791x_state_names[am791x->rx_state]);
}
}
@ -1092,16 +1066,16 @@ static void handle_state(am791x_t *am791x)
}
/* timeout events */
static void tx_timeout(void *data)
static void tx_timeout(struct timer *timer)
{
am791x_t *am791x = data;
am791x_t *am791x = (am791x_t *)timer->priv;
handle_tx_state(am791x);
}
static void rx_timeout(void *data)
static void rx_timeout(struct timer *timer)
{
am791x_t *am791x = data;
am791x_t *am791x = (am791x_t *)timer->priv;
handle_rx_state(am791x);
}
@ -1112,10 +1086,10 @@ int am791x_init(am791x_t *am791x, void *inst, enum am791x_type type, uint8_t mc,
memset(am791x, 0, sizeof(*am791x));
/* init timers */
osmo_timer_setup(&am791x->tx_timer, tx_timeout, am791x);
osmo_timer_setup(&am791x->rx_timer, rx_timeout, am791x);
timer_init(&am791x->tx_timer, tx_timeout, am791x);
timer_init(&am791x->rx_timer, rx_timeout, am791x);
LOGP(DAM791X, LOGL_DEBUG, "Initializing instance of AM791%d:\n", type);
PDEBUG(DAM791X, DEBUG_DEBUG, "Initializing instance of AM791%d:\n", type);
am791x->inst = inst;
am791x->type = type;
@ -1145,13 +1119,13 @@ int am791x_init(am791x_t *am791x, void *inst, enum am791x_type type, uint8_t mc,
/* exit routine, must be called when exit */
void am791x_exit(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Exit instance of AM791%d:\n", am791x->type);
PDEBUG(DAM791X, DEBUG_DEBUG, "Exit instance of AM791%d:\n", am791x->type);
/* bring to reset state, be sure to clean FSK processes */
am791x_reset(am791x);
osmo_timer_del(&am791x->tx_timer);
osmo_timer_del(&am791x->rx_timer);
timer_exit(&am791x->tx_timer);
timer_exit(&am791x->rx_timer);
}
/* get some default baud rate for each mode, before IOCTL sets it (if it sets it) */
@ -1175,8 +1149,8 @@ int am791x_mc(am791x_t *am791x, uint8_t mc, int samplerate, double tx_baud, doub
if (!((am791x->type) ? am791x_modes[mc].sup_7911 : am791x_modes[mc].sup_7910))
rc = -EINVAL;
LOGP(DAM791X, LOGL_INFO, "Setting mode %d: %s\n", mc, am791x_modes[mc].description);
LOGP(DAM791X, LOGL_DEBUG, " -> Baud rate: %.1f/%.1f\n", rx_baud, tx_baud);
PDEBUG(DAM791X, DEBUG_INFO, "Setting mode %d: %s\n", mc, am791x_modes[mc].description);
PDEBUG(DAM791X, DEBUG_DEBUG, " -> Baud rate: %.1f/%.1f\n", rx_baud, tx_baud);
am791x->mc = mc;
am791x->samplerate = samplerate;
@ -1213,12 +1187,10 @@ int am791x_mc(am791x_t *am791x, uint8_t mc, int samplerate, double tx_baud, doub
/* reset at any time, may be called any time by upper layer */
void am791x_reset(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_INFO, "Reset!\n");
PDEBUG(DAM791X, DEBUG_INFO, "Reset!\n");
/* Flag timer, because it must be deleted in main thread. */
am791x->tx_timer_f = -1.0;
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1.0;
timer_stop(&am791x->tx_timer);
timer_stop(&am791x->rx_timer);
if (am791x->f0_tx) {
fsk_mod_cleanup(&am791x->fsk_tx);
@ -1256,7 +1228,7 @@ void am791x_reset(am791x_t *am791x)
/* change input lines */
void am791x_dtr(am791x_t *am791x, int dtr)
{
LOGP(DAM791X, LOGL_DEBUG, "Terminal is%s ready!\n", (dtr) ? "" : " not");
PDEBUG(DAM791X, DEBUG_DEBUG, "Terminal is%s ready!\n", (dtr) ? "" : " not");
/* set filters, if DTR becomes on */
if (!am791x->line_dtr && dtr) {
@ -1270,7 +1242,7 @@ void am791x_dtr(am791x_t *am791x, int dtr)
void am791x_rts(am791x_t *am791x, int rts)
{
LOGP(DAM791X, LOGL_DEBUG, "Terminal %s RTS.\n", (rts) ? "sets" : "clears");
PDEBUG(DAM791X, DEBUG_DEBUG, "Terminal %s RTS.\n", (rts) ? "sets" : "clears");
am791x->line_rts = rts;
handle_state(am791x);
@ -1278,7 +1250,7 @@ void am791x_rts(am791x_t *am791x, int rts)
void am791x_brts(am791x_t *am791x, int rts)
{
LOGP(DAM791X, LOGL_DEBUG, "Terminal %s BRTS.\n", (rts) ? "sets" : "clears");
PDEBUG(DAM791X, DEBUG_DEBUG, "Terminal %s BRTS.\n", (rts) ? "sets" : "clears");
am791x->line_brts = rts;
handle_state(am791x);
@ -1286,25 +1258,9 @@ void am791x_brts(am791x_t *am791x, int rts)
void am791x_ring(am791x_t *am791x, int ring)
{
LOGP(DAM791X, LOGL_DEBUG, "Terminal %s RING.\n", (ring) ? "sets" : "clears");
PDEBUG(DAM791X, DEBUG_DEBUG, "Terminal %s RING.\n", (ring) ? "sets" : "clears");
am791x->line_ring = ring;
handle_state(am791x);
}
void am791x_add_del_timers(am791x_t *am791x)
{
/* Timers may only be processed in main thread, because libosmocore has timer lists for individual threads. */
if (am791x->tx_timer_f < 0.0)
osmo_timer_del(&am791x->tx_timer);
if (am791x->tx_timer_f > 0.0)
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->tx_timer_f));
am791x->tx_timer_f = 0.0;
if (am791x->rx_timer_f < 0.0)
osmo_timer_del(&am791x->rx_timer);
if (am791x->rx_timer_f > 0.0)
osmo_timer_schedule(&am791x->rx_timer, FLOAT_TO_TIMEOUT(am791x->rx_timer_f));
am791x->rx_timer_f = 0.0;
}

View File

@ -67,8 +67,7 @@ typedef struct am791x {
int f0_rx, f1_rx;
/* timers */
struct osmo_timer_list tx_timer, rx_timer;
double tx_timer_f, rx_timer_f; /* time to stat / flag to stop */
struct timer tx_timer, rx_timer;
double t_rcon;
double t_rcoff;
double t_brcon;
@ -105,5 +104,4 @@ void am791x_dtr(am791x_t *am791x, int dtr);
void am791x_rts(am791x_t *am791x, int rts);
void am791x_brts(am791x_t *am791x, int brts);
void am791x_ring(am791x_t *am791x, int ring);
void am791x_add_del_timers(am791x_t *am791x);

View File

@ -32,14 +32,12 @@
#include <fcntl.h>
#include <math.h>
#include "../libsample/sample.h"
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include "../libtimer/timer.h"
#include "../libfsk/fsk.h"
#include "../libsound/sound.h"
#include "../libwave/wave.h"
#include "../libdisplay/display.h"
#include "../liblogging/logging.h"
#include "../libmobile/get_time.c"
#include "../libdebug/debug.h"
#include "device.h"
#include "am791x.h"
#include "uart.h"
@ -219,7 +217,7 @@ static void cts(void *inst, int cts)
return;
if (datenklo->auto_rts) {
LOGP(DDATENKLO, LOGL_INFO, "Received CTS=%d in Automatic RTS Mode.\n", cts);
PDEBUG(DDATENKLO, DEBUG_INFO, "Received CTS=%d in Automatic RTS Mode.\n", cts);
datenklo->auto_rts_cts = cts;
return;
}
@ -228,7 +226,7 @@ static void cts(void *inst, int cts)
datenklo->lines |= TIOCM_CTS;
else
datenklo->lines &= ~TIOCM_CTS;
LOGP(DDATENKLO, LOGL_INFO, "Indicating to terminal that CTS is %s\n", (cts) ? "on" : "off");
PDEBUG(DDATENKLO, DEBUG_INFO, "Indicating to terminal that CTS is %s\n", (cts) ? "on" : "off");
}
/* modem changes CTS state (back channel) */
@ -240,7 +238,7 @@ static void bcts(void *inst, int cts)
return;
if (datenklo->auto_rts) {
LOGP(DDATENKLO, LOGL_INFO, "Received BCTS=%d in Automatic RTS Mode.\n", cts);
PDEBUG(DDATENKLO, DEBUG_INFO, "Received BCTS=%d in Automatic RTS Mode.\n", cts);
datenklo->auto_rts_cts = cts;
return;
}
@ -249,7 +247,7 @@ static void bcts(void *inst, int cts)
datenklo->lines |= TIOCM_CTS;
else
datenklo->lines &= ~TIOCM_CTS;
LOGP(DDATENKLO, LOGL_INFO, "Indicating to terminal that BCTS is %s\n", (cts) ? "on" : "off");
PDEBUG(DDATENKLO, DEBUG_INFO, "Indicating to terminal that BCTS is %s\n", (cts) ? "on" : "off");
}
/* modem changes CD state */
@ -261,7 +259,7 @@ static void cd(void *inst, int cd)
return;
if (datenklo->auto_rts) {
LOGP(DDATENKLO, LOGL_INFO, "Received CD=%d in Automatic RTS Mode.\n", cd);
PDEBUG(DDATENKLO, DEBUG_INFO, "Received CD=%d in Automatic RTS Mode.\n", cd);
datenklo->auto_rts_cd = cd;
return;
}
@ -270,7 +268,7 @@ static void cd(void *inst, int cd)
datenklo->lines |= TIOCM_CD;
else
datenklo->lines &= ~TIOCM_CD;
LOGP(DDATENKLO, LOGL_INFO, "Indicating to terminal that CD is %s\n", (cd) ? "on" : "off");
PDEBUG(DDATENKLO, DEBUG_INFO, "Indicating to terminal that CD is %s\n", (cd) ? "on" : "off");
}
/* modem changes CD state (back channel) */
@ -282,7 +280,7 @@ static void bcd(void *inst, int cd)
return;
if (datenklo->auto_rts) {
LOGP(DDATENKLO, LOGL_INFO, "Received BCD=%d in Automatic RTS Mode.\n", cd);
PDEBUG(DDATENKLO, DEBUG_INFO, "Received BCD=%d in Automatic RTS Mode.\n", cd);
datenklo->auto_rts_cd = cd;
return;
}
@ -291,7 +289,7 @@ static void bcd(void *inst, int cd)
datenklo->lines |= TIOCM_CD;
else
datenklo->lines &= ~TIOCM_CD;
LOGP(DDATENKLO, LOGL_INFO, "Indicating to terminal that BCD is %s\n", (cd) ? "on" : "off");
PDEBUG(DDATENKLO, DEBUG_INFO, "Indicating to terminal that BCD is %s\n", (cd) ? "on" : "off");
}
/* modem request bit */
@ -407,7 +405,7 @@ static int tx(void *inst)
if (datenklo->onlcr_char) {
datenklo->onlcr_char = 0;
data = '\n';
LOGP(DDATENKLO, LOGL_DEBUG, "ONLCR: sending NL\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "ONLCR: sending NL\n");
goto out;
}
@ -416,7 +414,7 @@ again:
if (fill == (size_t)datenklo->tx_fifo_full) {
/* tell cuse to write again */
LOGP(DDATENKLO, LOGL_DEBUG, "Set POLLOUT!\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Set POLLOUT!\n");
datenklo->revents |= POLLOUT;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -426,12 +424,12 @@ again:
datenklo->auto_rts_on = 0;
if (datenklo->tcsetsw) {
LOGP(DDATENKLO, LOGL_DEBUG, "Transmission finished, applying termios now.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Transmission finished, applying termios now.\n");
memcpy(&datenklo->termios, &datenklo->tcsetsw_termios, sizeof(datenklo->termios));
if (datenklo->tcsetsw == 2) {
flush_rx(datenklo);
if ((datenklo->revents & POLLIN)) {
LOGP(DDATENKLO, LOGL_DEBUG, "Reset POLLIN (flushed)\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Reset POLLIN (flushed)\n");
datenklo->revents &= ~POLLIN;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -452,26 +450,26 @@ again:
/* process output features */
if (datenklo->opost) {
if (datenklo->olcuc) {
LOGP(DDATENKLO, LOGL_DEBUG, "OLCUC: 0x%02x -> 0x%02x\n", data, toupper(data));
PDEBUG(DDATENKLO, DEBUG_DEBUG, "OLCUC: 0x%02x -> 0x%02x\n", data, toupper(data));
data = toupper(data);
}
if (datenklo->onlret && data == '\r') {
LOGP(DDATENKLO, LOGL_DEBUG, "ONLRET: ignore CR\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "ONLRET: ignore CR\n");
goto again;
}
if (datenklo->ocrnl && data == '\r') {
LOGP(DDATENKLO, LOGL_DEBUG, "OCRNL: CR -> NL\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "OCRNL: CR -> NL\n");
data = '\n';
}
if (datenklo->onlcr && data == '\n') {
datenklo->onlcr_char = 1;
data = '\r';
LOGP(DDATENKLO, LOGL_DEBUG, "ONLCR: sending CR\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "ONLCR: sending CR\n");
}
}
out:
LOGP(DDATENKLO, LOGL_DEBUG, "Transmitting byte 0x%02x to UART.\n", data);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Transmitting byte 0x%02x to UART.\n", data);
return data;
}
@ -482,35 +480,35 @@ static void rx(void *inst, int data, uint32_t __attribute__((unused)) flags)
datenklo_t *datenklo = (datenklo_t *)inst;
size_t space;
LOGP(DDATENKLO, LOGL_DEBUG, "Received byte 0x%02x ('%c') from UART.\n", data, (data >= 32 && data <= 126) ? data : '.');
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Received byte 0x%02x ('%c') from UART.\n", data, (data >= 32 && data <= 126) ? data : '.');
/* process input features */
if (datenklo->ignbrk && (flags & UART_BREAK)) {
LOGP(DDATENKLO, LOGL_DEBUG, "IGNBRK: ignore BREAK\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "IGNBRK: ignore BREAK\n");
return;
}
if (datenklo->istrip && (data & 0x80)) {
LOGP(DDATENKLO, LOGL_DEBUG, "ISTRIP: 0x%02x -> 0x%02x\n", data, data & 0x7f);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "ISTRIP: 0x%02x -> 0x%02x\n", data, data & 0x7f);
data &= 0x7f;
}
if (datenklo->inlcr && data == '\n') {
LOGP(DDATENKLO, LOGL_DEBUG, "INLCR: NL -> CR\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "INLCR: NL -> CR\n");
data = '\r';
}
if (datenklo->igncr && data == '\r') {
LOGP(DDATENKLO, LOGL_DEBUG, "IGNCR: ignore CR\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "IGNCR: ignore CR\n");
return;
}
if (datenklo->icrnl && data == '\r') {
LOGP(DDATENKLO, LOGL_DEBUG, "ICRNL: CR -> NL\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "ICRNL: CR -> NL\n");
data = '\n';
}
if (datenklo->iuclc) {
LOGP(DDATENKLO, LOGL_DEBUG, "IUCLC: 0x%02x -> 0x%02x\n", data, tolower(data));
PDEBUG(DDATENKLO, DEBUG_DEBUG, "IUCLC: 0x%02x -> 0x%02x\n", data, tolower(data));
data = tolower(data);
}
if (datenklo->echo) {
LOGP(DDATENKLO, LOGL_DEBUG, "ECHO: write to output\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "ECHO: write to output\n");
space = (datenklo->tx_fifo_out - datenklo->tx_fifo_in - 1 + datenklo->tx_fifo_size) % datenklo->tx_fifo_size;
if (space) {
datenklo->tx_fifo[datenklo->tx_fifo_in++] = data;
@ -521,7 +519,7 @@ static void rx(void *inst, int data, uint32_t __attribute__((unused)) flags)
/* empty buffer gets data */
if (datenklo->rx_fifo_out == datenklo->rx_fifo_in) {
/* tell cuse to read again */
LOGP(DDATENKLO, LOGL_DEBUG, "Set POLLIN!\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Set POLLIN!\n");
datenklo->revents |= POLLIN;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -530,13 +528,13 @@ static void rx(void *inst, int data, uint32_t __attribute__((unused)) flags)
if (!space) {
err_overflow:
LOGP(DDATENKLO, LOGL_NOTICE, "RX buffer overflow, dropping!\n");
PDEBUG(DDATENKLO, DEBUG_NOTICE, "RX buffer overflow, dropping!\n");
return;
}
if (datenklo->parmrk) {
if ((flags & (UART_BREAK | UART_PARITY_ERROR))) {
LOGP(DDATENKLO, LOGL_DEBUG, "PARMRK: 0x%02x -> 0xff,0x00,0x%02x\n", data, data);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "PARMRK: 0x%02x -> 0xff,0x00,0x%02x\n", data, data);
if (space < 3)
goto err_overflow;
datenklo->rx_fifo[datenklo->rx_fifo_in++] = 0xff;
@ -546,7 +544,7 @@ static void rx(void *inst, int data, uint32_t __attribute__((unused)) flags)
datenklo->rx_fifo_in %= datenklo->rx_fifo_size;
space--;
} else if (data == 0xff) {
LOGP(DDATENKLO, LOGL_DEBUG, "PARMRK: 0xff -> 0xff,0xff\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "PARMRK: 0xff -> 0xff,0xff\n");
if (space < 2)
goto err_overflow;
datenklo->rx_fifo[datenklo->rx_fifo_in++] = 0xff;
@ -569,18 +567,18 @@ static void set_lines(datenklo_t *datenklo, int new)
int old = datenklo->lines;
if (!(old & TIOCM_DTR) && (new & TIOCM_DTR)) {
LOGP(DDATENKLO, LOGL_INFO, "Terminal turns DTR on\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal turns DTR on\n");
flush_tx(datenklo);
flush_rx(datenklo);
am791x_dtr(&datenklo->am791x, 1);
}
if ((old & TIOCM_DTR) && !(new & TIOCM_DTR)) {
LOGP(DDATENKLO, LOGL_INFO, "Terminal turns DTR off\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal turns DTR off\n");
am791x_dtr(&datenklo->am791x, 0);
}
if (!(old & TIOCM_RTS) && (new & TIOCM_RTS)) {
LOGP(DDATENKLO, LOGL_INFO, "Terminal turns RTS on\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal turns RTS on\n");
if (datenklo->auto_rts)
new |= TIOCM_CTS | TIOCM_CD;
else {
@ -591,7 +589,7 @@ static void set_lines(datenklo_t *datenklo, int new)
}
}
if ((old & TIOCM_RTS) && !(new & TIOCM_RTS)) {
LOGP(DDATENKLO, LOGL_INFO, "Terminal turns RTS off\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal turns RTS off\n");
if (datenklo->auto_rts)
new &= ~(TIOCM_CTS | TIOCM_CD);
else {
@ -611,7 +609,7 @@ static void process_auto_rts(datenklo_t *datenklo)
if (!datenklo->auto_rts)
return;
if (datenklo->auto_rts_on && !datenklo->auto_rts_rts && !datenklo->auto_rts_cd) {
LOGP(DDATENKLO, LOGL_INFO, "Automatically raising RTS.\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Automatically raising RTS.\n");
datenklo->auto_rts_rts = 1;
if (!datenklo->tx_back)
am791x_rts(&datenklo->am791x, 1);
@ -619,7 +617,7 @@ static void process_auto_rts(datenklo_t *datenklo)
am791x_brts(&datenklo->am791x, 1);
}
if (!datenklo->auto_rts_on && datenklo->auto_rts_rts) {
LOGP(DDATENKLO, LOGL_INFO, "Automatically dropping RTS.\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Automatically dropping RTS.\n");
datenklo->auto_rts_rts = 0;
if (!datenklo->tx_back)
am791x_rts(&datenklo->am791x, 0);
@ -636,7 +634,7 @@ static ssize_t dk_ioctl_get(void *inst, int cmd, void *buf, size_t out_bufsz)
ssize_t rc = 0;
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Device has been read for ioctl (cmd = %d, size = %zu).\n", cmd, out_bufsz);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Device has been read for ioctl (cmd = %d, size = %zu).\n", cmd, out_bufsz);
#endif
switch (cmd) {
@ -645,7 +643,7 @@ static ssize_t dk_ioctl_get(void *inst, int cmd, void *buf, size_t out_bufsz)
if (!out_bufsz)
break;
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal requests termios.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal requests termios.\n");
#endif
memcpy(buf, &datenklo->termios, rc);
break;
@ -654,7 +652,7 @@ static ssize_t dk_ioctl_get(void *inst, int cmd, void *buf, size_t out_bufsz)
if (!out_bufsz)
break;
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal requests line states.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal requests line states.\n");
#endif
status = datenklo->lines | TIOCM_LE | TIOCM_DSR;
memcpy(buf, &status, rc);
@ -664,7 +662,7 @@ static ssize_t dk_ioctl_get(void *inst, int cmd, void *buf, size_t out_bufsz)
if (!out_bufsz)
break;
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal requests window size.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal requests window size.\n");
#endif
struct winsize *winsize = (struct winsize *)buf;
winsize->ws_row = 25;
@ -679,7 +677,7 @@ static ssize_t dk_ioctl_get(void *inst, int cmd, void *buf, size_t out_bufsz)
status = (datenklo->rx_fifo_in - datenklo->rx_fifo_out + datenklo->rx_fifo_size) % datenklo->rx_fifo_size;
memcpy(buf, &status, rc);
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal requests RX buffer fill states.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal requests RX buffer fill states.\n");
#endif
break;
case TIOCOUTQ:
@ -687,7 +685,7 @@ static ssize_t dk_ioctl_get(void *inst, int cmd, void *buf, size_t out_bufsz)
if (!out_bufsz)
break;
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal requests TX buffer fill states.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal requests TX buffer fill states.\n");
#endif
status = (datenklo->tx_fifo_in - datenklo->tx_fifo_out + datenklo->tx_fifo_size) % datenklo->tx_fifo_size;
memcpy(buf, &status, rc);
@ -788,15 +786,15 @@ static void set_termios(datenklo_t *datenklo, const void *buf)
new_echo = !!(datenklo->termios.c_lflag & ECHO);
if (old_baud != new_baud && (!datenklo->force_tx_baud || !datenklo->force_rx_baud)) {
LOGP(DDATENKLO, LOGL_INFO, "Terminal changes baud rate to %.1f Baud.\n", new_baud);
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal changes baud rate to %.1f Baud.\n", new_baud);
if ((datenklo->lines & TIOCM_DTR) && !new_baud) {
LOGP(DDATENKLO, LOGL_INFO, "Baudrate is set to 0, we drop DTR\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Baudrate is set to 0, we drop DTR\n");
am791x_dtr(&datenklo->am791x, 0);
}
datenklo->baudrate = new_baud;
am791x_mc(&datenklo->am791x, datenklo->mc, datenklo->samplerate, tx_baud_rate(datenklo), rx_baud_rate(datenklo));
if ((datenklo->lines & TIOCM_DTR) && !old_baud) {
LOGP(DDATENKLO, LOGL_INFO, "Baudrate is set from 0, we raise DTR\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Baudrate is set from 0, we raise DTR\n");
am791x_dtr(&datenklo->am791x, 1);
}
}
@ -804,10 +802,10 @@ static void set_termios(datenklo_t *datenklo, const void *buf)
if (old_databits != new_databits
|| old_parity != new_parity
|| old_stopbits != new_stopbits) {
LOGP(DDATENKLO, LOGL_INFO, "Terminal changes serial mode to %d%c%d.\n", cflag2databits(datenklo->termios.c_cflag), parity2char(cflag2parity(datenklo->termios.c_cflag)), cflag2stopbits(datenklo->termios.c_cflag));
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal changes serial mode to %d%c%d.\n", cflag2databits(datenklo->termios.c_cflag), parity2char(cflag2parity(datenklo->termios.c_cflag)), cflag2stopbits(datenklo->termios.c_cflag));
rc = uart_init(&datenklo->uart, datenklo, cflag2databits(datenklo->termios.c_cflag), cflag2parity(datenklo->termios.c_cflag), cflag2stopbits(datenklo->termios.c_cflag), tx, rx);
if (rc < 0)
LOGP(DDATENKLO, LOGL_ERROR, "Failed to initialize UART.\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to initialize UART.\n");
}
if (old_stopbits != new_stopbits
@ -837,8 +835,8 @@ static void set_termios(datenklo_t *datenklo, const void *buf)
datenklo->onlret = new_onlret;
datenklo->olcuc = new_olcuc;
datenklo->echo = new_echo;
LOGP(DDATENKLO, LOGL_INFO, "Terminal sets serial flags:\n");
LOGP(DDATENKLO, LOGL_INFO, "%cignbrk %cparmrk %cistrip %cinlcr %cigncr %cicrnl %ciuclc %copost %conlcr %cocrnl %conlret %colcuc %cecho\n",
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal sets serial flags:\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "%cignbrk %cparmrk %cistrip %cinlcr %cigncr %cicrnl %ciuclc %copost %conlcr %cocrnl %conlret %colcuc %cecho\n",
(datenklo->ignbrk) ? '+' : '-',
(datenklo->parmrk) ? '+' : '-',
(datenklo->istrip) ? '+' : '-',
@ -864,7 +862,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
size_t space;
#ifdef HEAVY_DEBUG
LOGP(DDATENKLO, LOGL_DEBUG, "Device has been written for ioctl (cmd = %d, size = %zu).\n", cmd, in_bufsz);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Device has been written for ioctl (cmd = %d, size = %zu).\n", cmd, in_bufsz);
#endif
switch (cmd) {
@ -872,7 +870,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
rc = sizeof(datenklo->termios);
if (!in_bufsz)
break;
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal sets termios now.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal sets termios now.\n");
set_termios(datenklo, buf);
break;
case TCSETSW:
@ -880,9 +878,9 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
rc = sizeof(datenklo->termios);
if (!in_bufsz)
break;
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal sets termios after draining output buffer.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal sets termios after draining output buffer.\n");
if (1 || datenklo->tx_fifo_out == datenklo->tx_fifo_in) {
LOGP(DDATENKLO, LOGL_DEBUG, "Output buffer empty, applying termios now.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Output buffer empty, applying termios now.\n");
set_termios(datenklo, buf);
break;
}
@ -897,12 +895,12 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
if (!in_bufsz)
break;
memcpy(&status, buf, rc);
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal flushes buffer (status = %d).\n", status);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal flushes buffer (status = %d).\n", status);
if (status == TCIOFLUSH || status == TCOFLUSH) {
flush_tx(datenklo);
if (!(datenklo->revents & POLLOUT)) {
/* tell cuse to write again */
LOGP(DDATENKLO, LOGL_DEBUG, "Set POLLOUT (flushed)\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Set POLLOUT (flushed)\n");
datenklo->revents |= POLLOUT;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -910,7 +908,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
if (status == TCIOFLUSH || status == TCIFLUSH) {
flush_rx(datenklo);
if ((datenklo->revents & POLLIN)) {
LOGP(DDATENKLO, LOGL_DEBUG, "Reset POLLIN (flushed)\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Reset POLLIN (flushed)\n");
datenklo->revents &= ~POLLIN;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -918,7 +916,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
break;
case TCSBRK:
rc = 0;
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal sends break\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal sends break\n");
datenklo->break_bits = tx_baud_rate(datenklo) * 3 / 10;
break;
case TCSBRKP:
@ -926,7 +924,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
if (!in_bufsz)
break;
memcpy(&status, buf, rc);
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal sends break (duration = %d).\n", status);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal sends break (duration = %d).\n", status);
if (status == 0)
status = 3;
if (status > 30)
@ -935,12 +933,12 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
break;
case TIOCSBRK:
rc = 0;
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal turns break on\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal turns break on\n");
datenklo->break_on = 1;
break;
case TIOCCBRK:
rc = 0;
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal turns break off\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal turns break off\n");
datenklo->break_on = 0;
break;
case TIOCMBIS:
@ -948,7 +946,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
if (!in_bufsz)
break;
memcpy(&status, buf, rc);
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal sets line status (0x%x).\n", status);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal sets line status (0x%x).\n", status);
status = datenklo->lines | status;
set_lines(datenklo, status);
break;
@ -957,7 +955,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
if (!in_bufsz)
break;
memcpy(&status, buf, rc);
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal clears line status (0x%x).\n", status);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal clears line status (0x%x).\n", status);
status = datenklo->lines & ~status;
set_lines(datenklo, status);
break;
@ -966,30 +964,30 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
if (!in_bufsz)
break;
memcpy(&status, buf, rc);
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal specifies line status (0x%x).\n", status);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal specifies line status (0x%x).\n", status);
set_lines(datenklo, status);
break;
case TIOCGSID:
LOGP(DDATENKLO, LOGL_DEBUG, "TIOGSID -> ENOTTY\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "TIOGSID -> ENOTTY\n");
rc = -ENOTTY;
break;
case TIOCGPGRP:
LOGP(DDATENKLO, LOGL_DEBUG, "TIOCGPGRP -> ENOTTY\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "TIOCGPGRP -> ENOTTY\n");
rc = -ENOTTY;
break;
case TIOCSCTTY:
LOGP(DDATENKLO, LOGL_DEBUG, "TIOCSCTTY -> ENOTTY\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "TIOCSCTTY -> ENOTTY\n");
rc = -ENOTTY;
break;
case TIOCSPGRP:
LOGP(DDATENKLO, LOGL_DEBUG, "TIOCSPGRP -> ENOTTY\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "TIOCSPGRP -> ENOTTY\n");
rc = -ENOTTY;
break;
case TIOCSWINSZ:
rc = sizeof(struct winsize);
if (!in_bufsz)
break;
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal sets window size.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal sets window size.\n");
break;
case TCXONC:
rc = sizeof(status);
@ -998,15 +996,15 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
memcpy(&status, buf, rc);
switch (status) {
case TCOOFF:
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal turns off output.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal turns off output.\n");
datenklo->output_off = 1;
break;
case TCOON:
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal turns on output.\n");
datenklo->output_off = 0;
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal turns on output.\n");
datenklo->output_off = 1;
break;
case TCIOFF:
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal turns off input.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal turns off input.\n");
space = (datenklo->rx_fifo_out - datenklo->rx_fifo_in - 1 + datenklo->rx_fifo_size) % datenklo->rx_fifo_size;
if (space < 1)
break;
@ -1014,7 +1012,7 @@ static ssize_t dk_ioctl_set(void *inst, int cmd, const void *buf, size_t in_bufs
datenklo->rx_fifo_in %= datenklo->rx_fifo_size;
break;
case TCION:
LOGP(DDATENKLO, LOGL_DEBUG, "Terminal turns on input.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Terminal turns on input.\n");
space = (datenklo->rx_fifo_out - datenklo->rx_fifo_in - 1 + datenklo->rx_fifo_size) % datenklo->rx_fifo_size;
if (space < 1)
break;
@ -1036,12 +1034,12 @@ static int dk_open(void *inst, int flags)
datenklo_t *datenklo = (datenklo_t *)inst;
if (datenklo->open_count) {
LOGP(DDATENKLO, LOGL_NOTICE, "Device is busy.\n");
PDEBUG(DDATENKLO, DEBUG_NOTICE, "Device is busy.\n");
return -EBUSY;
}
datenklo->open_count++;
datenklo->flags = flags;
LOGP(DDATENKLO, LOGL_INFO, "Device has been opened.\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Device has been opened.\n");
int status = datenklo->lines | TIOCM_DTR | TIOCM_RTS;
set_lines(datenklo, status);
@ -1053,7 +1051,7 @@ static void dk_close(void *inst)
{
datenklo_t *datenklo = (datenklo_t *)inst;
LOGP(DDATENKLO, LOGL_INFO, "Device has been closed.\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Device has been closed.\n");
datenklo->open_count--;
int status = datenklo->lines & ~(TIOCM_DTR | TIOCM_RTS);
set_lines(datenklo, status);
@ -1073,7 +1071,7 @@ static void debug_data(const char *buf, int count)
count--;
}
text[i] = '\0';
LOGP(DDATENKLO, LOGL_DEBUG, " \"%s\"\n", text);
PDEBUG(DDATENKLO, DEBUG_DEBUG, " \"%s\"\n", text);
}
}
@ -1093,7 +1091,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
if (vmin && vtime) {
/* first: start timer */
if (!datenklo->vtimeout)
datenklo->vtimer_us = vtime * 100000; /* start timer in main loop */
timer_start(&datenklo->vtimer, (double)vtime * 0.1);
/* no data: block (in blocking IO) */
if (fill == 0) {
/* special value to tell device there is no data right now, we have to block */
@ -1106,7 +1104,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
}
/* enough data or timeout or nonblocking IO: stop timer and return what we have */
datenklo->vtimeout = 0;
datenklo->vtimer_us = -1; /* stop timer in main loop */
timer_stop(&datenklo->vtimer);
}
/* both MIN and TIME are zero */
if (!vmin && !vtime) {
@ -1119,7 +1117,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
if (!vmin && vtime) {
/* first: start timer */
if (!datenklo->vtimeout)
datenklo->vtimer_us = vtime * 100000; /* start timer in main loop */
timer_start(&datenklo->vtimer, (double)vtime * 0.1);
if (fill == 0) {
/* no data and no timeout: block (in blocking IO) */
if (!datenklo->vtimeout) {
@ -1132,7 +1130,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
}
/* data: stop timer and return what we have */
datenklo->vtimeout = 0;
datenklo->vtimer_us = -1; /* stop timer in main loop */
timer_stop(&datenklo->vtimer);
}
/* MIN is nonzero, TIME is zero */
if (vmin && !vtime) {
@ -1144,7 +1142,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
/* enough data in buffer: return what we have */
}
LOGP(DDATENKLO, LOGL_DEBUG, "Device has been read from. (fill = %zu)\n", fill);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Device has been read from. (fill = %zu)\n", fill);
/* get data from fifo */
count = 0;
@ -1162,7 +1160,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
if (!fill) {
/* tell cuse not to read anymore */
if ((datenklo->revents & POLLIN)) {
LOGP(DDATENKLO, LOGL_DEBUG, "Reset POLLIN (now empty)!\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Reset POLLIN (now empty)!\n");
datenklo->revents &= ~POLLIN;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -1179,17 +1177,17 @@ static ssize_t dk_write(void *inst, const char *buf, size_t size, int __attribut
size_t i;
if (!(datenklo->lines & TIOCM_DTR)) {
LOGP(DDATENKLO, LOGL_INFO, "Dropping data, DTR is off!\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Dropping data, DTR is off!\n");
return -EIO;
}
if (!(datenklo->lines & TIOCM_RTS)) {
LOGP(DDATENKLO, LOGL_INFO, "Dropping data, RTS is off!\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Dropping data, RTS is off!\n");
return -EIO;
}
if (size > (size_t)datenklo->tx_fifo_size - 1) {
LOGP(DDATENKLO, LOGL_NOTICE, "Device sends us too many data. (size = %zu)\n", size);
PDEBUG(DDATENKLO, DEBUG_NOTICE, "Device sends us too many data. (size = %zu)\n", size);
return -EIO;
}
@ -1201,7 +1199,7 @@ static ssize_t dk_write(void *inst, const char *buf, size_t size, int __attribut
return -EAGAIN;
}
LOGP(DDATENKLO, LOGL_DEBUG, "Device has been written to. (space = %zu)\n", space);
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Device has been written to. (space = %zu)\n", space);
debug_data(buf, size);
if (datenklo->auto_rts)
@ -1217,7 +1215,7 @@ static ssize_t dk_write(void *inst, const char *buf, size_t size, int __attribut
if ((datenklo->revents & POLLOUT) && fill >= (size_t)datenklo->tx_fifo_full) {
/* tell cuse not to write */
LOGP(DDATENKLO, LOGL_DEBUG, "Reset POLLOUT (buffer full)\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Reset POLLOUT (buffer full)\n");
datenklo->revents &= ~POLLOUT;
device_set_poll_events(datenklo->device, datenklo->revents);
}
@ -1229,7 +1227,7 @@ static void dk_flush_tx(void *inst)
{
datenklo_t *datenklo = (datenklo_t *)inst;
LOGP(DDATENKLO, LOGL_INFO, "Terminal sends interrupt while writing, flushing TX buffer\n");
PDEBUG(DDATENKLO, DEBUG_INFO, "Terminal sends interrupt while writing, flushing TX buffer\n");
flush_tx(datenklo);
}
@ -1246,7 +1244,7 @@ static void dk_unlock(void)
}
/* signal handler to exit */
static void sighandler(int sigset)
void sighandler(int sigset)
{
if (sigset == SIGHUP)
return;
@ -1259,9 +1257,9 @@ static void sighandler(int sigset)
}
/* vtimer */
static void vtime_timeout(void *data)
static void vtime_timeout(struct timer *timer)
{
datenklo_t *datenklo = data;
datenklo_t *datenklo = (datenklo_t *)timer->priv;
/* check if there is enough data to read */
datenklo->vtimeout = 1;
@ -1272,7 +1270,7 @@ static void vtime_timeout(void *data)
void datenklo_init_global(void)
{
if (pthread_mutex_init(&mutex, NULL)) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to init mutex.\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to init mutex.\n");
exit(0);
}
}
@ -1284,7 +1282,7 @@ int datenklo_init(datenklo_t *datenklo, const char *dev_name, enum am791x_type a
tcflag_t flag;
cc_t *cc;
LOGP(DDATENKLO, LOGL_DEBUG, "Creating Datenklo instance.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Creating Datenklo instance.\n");
memset(datenklo, 0, sizeof(*datenklo));
@ -1334,7 +1332,7 @@ int datenklo_init(datenklo_t *datenklo, const char *dev_name, enum am791x_type a
datenklo->device = device_init(datenklo, dev_name, dk_open, dk_close, dk_read, dk_write, dk_ioctl_get, dk_ioctl_set, dk_flush_tx, dk_lock, dk_unlock);
if (!datenklo->device) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to attach virtual device '%s' using cuse.\n", dev_name);
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to attach virtual device '%s' using cuse.\n", dev_name);
rc = -errno;
goto error;
}
@ -1344,7 +1342,7 @@ int datenklo_init(datenklo_t *datenklo, const char *dev_name, enum am791x_type a
datenklo->baudrate = cflag2baud(datenklo->termios.c_cflag);
rc = am791x_init(&datenklo->am791x, datenklo, am791x_type, datenklo->mc, datenklo->samplerate, tx_baud_rate(datenklo), rx_baud_rate(datenklo), cts, bcts, cd, bcd, td, btd, rd, brd);
if (rc < 0) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to initialize AM791X modem chip.\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to initialize AM791X modem chip.\n");
goto error;
}
@ -1354,16 +1352,16 @@ int datenklo_init(datenklo_t *datenklo, const char *dev_name, enum am791x_type a
datenklo->tx_fifo = calloc(datenklo->tx_fifo_size, 1);
datenklo->rx_fifo = calloc(datenklo->rx_fifo_size, 1);
if (!datenklo->tx_fifo || !datenklo->rx_fifo) {
LOGP(DDATENKLO, LOGL_ERROR, "No mem!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "No mem!\n");
rc = -ENOMEM;
goto error;
}
osmo_timer_setup(&datenklo->vtimer, vtime_timeout, datenklo);
timer_init(&datenklo->vtimer, vtime_timeout, datenklo);
rc = uart_init(&datenklo->uart, datenklo, cflag2databits(datenklo->termios.c_cflag), cflag2parity(datenklo->termios.c_cflag), cflag2stopbits(datenklo->termios.c_cflag), tx, rx);
if (rc < 0) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to initialize UART.\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to initialize UART.\n");
goto error;
}
@ -1397,9 +1395,9 @@ int datenklo_open_audio(datenklo_t *datenklo, const char *audiodev, int buffer,
#ifdef HAVE_ALSA
/* init sound */
datenklo->audio = sound_open(SOUND_DIR_DUPLEX, audiodev, NULL, NULL, NULL, channels, 0.0, datenklo->samplerate, datenklo->buffer_size, 1.0, 1.0, 4000.0, 2.0);
datenklo->audio = sound_open(audiodev, NULL, NULL, NULL, channels, 0.0, datenklo->samplerate, datenklo->buffer_size, 1.0, 1.0, 4000.0, 2.0);
if (!datenklo->audio) {
LOGP(DDATENKLO, LOGL_ERROR, "No sound device!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "No sound device!\n");
return -EIO;
}
#endif
@ -1407,28 +1405,28 @@ int datenklo_open_audio(datenklo_t *datenklo, const char *audiodev, int buffer,
if (write_rx_wave) {
rc = wave_create_record(&datenklo->wave_rx_rec, write_rx_wave, datenklo->samplerate, channels, 1.0);
if (rc < 0) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to create WAVE recoding instance!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
return rc;
}
}
if (write_tx_wave) {
rc = wave_create_record(&datenklo->wave_tx_rec, write_tx_wave, datenklo->samplerate, channels, 1.0);
if (rc < 0) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to create WAVE recoding instance!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
return rc;
}
}
if (read_rx_wave) {
rc = wave_create_playback(&datenklo->wave_rx_play, read_rx_wave, &datenklo->samplerate, &channels, 1.0);
if (rc < 0) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to create WAVE playback instance!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
return rc;
}
}
if (read_tx_wave) {
rc = wave_create_playback(&datenklo->wave_tx_play, read_tx_wave, &datenklo->samplerate, &channels, 1.0);
if (rc < 0) {
LOGP(DDATENKLO, LOGL_ERROR, "Failed to create WAVE playback instance!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
return rc;
}
}
@ -1522,23 +1520,15 @@ void datenklo_main(datenklo_t *datenklo, int loopback)
if (num_chan > 1)
process_auto_rts(datenklo->slave);
/* Timers may only be processed in main thread, because libosmocore has timer lists for individual threads. */
if (datenklo->vtimer_us < 0)
osmo_timer_del(&datenklo->vtimer);
if (datenklo->vtimer_us > 0)
osmo_timer_schedule(&datenklo->vtimer, datenklo->vtimer_us / 1000000,datenklo->vtimer_us % 1000000);
datenklo->vtimer_us = 0;
am791x_add_del_timers(&datenklo->am791x);
osmo_select_main(1);
/* process timers */
process_timer();
#ifdef HAVE_ALSA
count = sound_read(datenklo->audio, samples, datenklo->buffer_size, num_chan, rf_level_db);
if (count < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to read RX data from audio device (rc = %d)\n", count);
PDEBUG(DDSP, DEBUG_ERROR, "Failed to read RX data from audio device (rc = %d)\n", count);
if (count == -EPIPE) {
LOGP(DDATENKLO, LOGL_ERROR, "Trying to recover!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Trying to recover!\n");
continue;
}
break;
@ -1571,9 +1561,9 @@ void datenklo_main(datenklo_t *datenklo, int loopback)
count = samplerate / 1000;
#endif
if (count < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to get number of samples in buffer (rc = %d)!\n", count);
PDEBUG(DDSP, DEBUG_ERROR, "Failed to get number of samples in buffer (rc = %d)!\n", count);
if (count == -EPIPE) {
LOGP(DDATENKLO, LOGL_ERROR, "Trying to recover!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Trying to recover!\n");
continue;
}
break;
@ -1621,9 +1611,9 @@ void datenklo_main(datenklo_t *datenklo, int loopback)
/* write audio */
rc = sound_write(datenklo->audio, samples, power, count, NULL, NULL, num_chan);
if (rc < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
PDEBUG(DDSP, DEBUG_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
if (rc == -EPIPE) {
LOGP(DDATENKLO, LOGL_ERROR, "Trying to recover!\n");
PDEBUG(DDATENKLO, DEBUG_ERROR, "Trying to recover!\n");
continue;
}
break;
@ -1635,6 +1625,8 @@ next_char:
switch (c) {
case 3:
/* quit */
if (clear_console_text)
clear_console_text();
printf("CTRL+c received, quitting!\n");
quit = 1;
goto next_char;
@ -1663,6 +1655,10 @@ next_char:
pthread_mutex_lock(&mutex);
}
/* get rid of last entry */
if (clear_console_text)
clear_console_text();
/* reset terminal */
tcsetattr(0, TCSANOW, &term_orig);
@ -1672,18 +1668,15 @@ next_char:
signal(SIGTERM, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
display_measurements_on(0);
display_wave_on(0);
pthread_mutex_unlock(&mutex);
}
/* cleanup function */
void datenklo_exit(datenklo_t *datenklo)
{
LOGP(DDATENKLO, LOGL_DEBUG, "Destroying Datenklo instance.\n");
PDEBUG(DDATENKLO, DEBUG_DEBUG, "Destroying Datenklo instance.\n");
osmo_timer_del(&datenklo->vtimer);
timer_exit(&datenklo->vtimer);
/* exit device */
if (datenklo->device)

View File

@ -52,8 +52,7 @@ typedef struct datenklo {
int auto_rts_cts; /* CTS was indicated */
int auto_rts_cd; /* CD was indicated */
int output_off; /* output stopped by flow control */
struct osmo_timer_list vtimer; /* VTIME timer */
int vtimer_us; /* time to stat / flag to stop */
struct timer vtimer; /* VTIME timer */
int vtimeout; /* when timeout has fired */
/* data fifos */

View File

@ -27,7 +27,7 @@
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#define __USE_GNU
#include <pthread.h>
#include <signal.h>
@ -122,7 +122,7 @@ static void cuse_read_interrupt(fuse_req_t req, void *data)
if (!device->read_locked)
device->lock_cb();
LOGP(DDEVICE, LOGL_DEBUG, "%s received interrupt from client!\n", device->name);
PDEBUG(DDEVICE, DEBUG_DEBUG, "%s received interrupt from client!\n", device->name);
if (device->read_req) {
device->read_req = NULL;
@ -167,7 +167,7 @@ static void cuse_device_read(fuse_req_t req, size_t size, off_t off, struct fuse
if (device->read_req) {
device->unlock_cb();
LOGP(DDEVICE, LOGL_ERROR, "%s: Got another read(), while first read() has not been replied, please fix.\n", device->name);
PDEBUG(DDEVICE, DEBUG_ERROR, "%s: Got another read(), while first read() has not been replied, please fix.\n", device->name);
fuse_reply_err(req, EBUSY);
return;
}
@ -182,7 +182,7 @@ static void cuse_device_read(fuse_req_t req, size_t size, off_t off, struct fuse
/* this means that we block until modem's read() returns 0 or positive value (in nonblocking io, we return -EAGAIN) */
if (!(fi->flags & O_NONBLOCK) && count == -EAGAIN) {
LOGP(DDEVICE, LOGL_DEBUG, "%s has no data available, waiting for data, timer or interrupt.\n", device->name);
PDEBUG(DDEVICE, DEBUG_DEBUG, "%s has no data available, waiting for data, timer or interrupt.\n", device->name);
device->read_req = req;
device->read_size = size;
@ -216,7 +216,7 @@ static void cuse_write_interrupt(fuse_req_t req, void *data)
if (!device->write_locked)
device->lock_cb();
LOGP(DDEVICE, LOGL_DEBUG, "%s received interrupt from client!\n", device->name);
PDEBUG(DDEVICE, DEBUG_DEBUG, "%s received interrupt from client!\n", device->name);
if (device->write_req) {
device->write_req = NULL;
@ -262,7 +262,7 @@ static void cuse_device_write(fuse_req_t req, const char *buf, size_t size, off_
if (device->write_req) {
device->unlock_cb();
LOGP(DDEVICE, LOGL_ERROR, "%s: Got another write(), while first write() has not been replied, please fix.\n", device->name);
PDEBUG(DDEVICE, DEBUG_ERROR, "%s: Got another write(), while first write() has not been replied, please fix.\n", device->name);
fuse_reply_err(req, EBUSY);
return;
}
@ -271,13 +271,13 @@ static void cuse_device_write(fuse_req_t req, const char *buf, size_t size, off_
/* this means that we block until modem's write() returns 0 or positive value (in nonblocking io, we return -EAGAIN) */
if (!(fi->flags & O_NONBLOCK) && count == -EAGAIN) {
LOGP(DDEVICE, LOGL_DEBUG, "%s has no buffer space available, waiting for space or interrupt.\n", device->name);
PDEBUG(DDEVICE, DEBUG_DEBUG, "%s has no buffer space available, waiting for space or interrupt.\n", device->name);
device->write_req = req;
device->write_size = size;
device->write_buf = malloc(size);
if (!buf) {
LOGP(DDEVICE, LOGL_ERROR, "No memory!\n");
PDEBUG(DDEVICE, DEBUG_ERROR, "No memory!\n");
exit(0);
}
memcpy(device->write_buf, buf, size);
@ -376,7 +376,7 @@ static void cuse_device_ioctl(fuse_req_t req, int cmd, void *arg, struct fuse_fi
}
break;
default:
LOGP(DDEVICE, LOGL_NOTICE, "%s: receives unknown ioctl: 0x%x\n", device->name, cmd);
PDEBUG(DDEVICE, DEBUG_NOTICE, "%s: receives unknown ioctl: 0x%x\n", device->name, cmd);
fuse_reply_err(req, EINVAL);
}
}
@ -432,7 +432,7 @@ static void cuse_device_flush(fuse_req_t req, struct fuse_file_info *fi)
(void)req;
(void)fi;
device_t *device = get_device_by_thread();
LOGP(DDEVICE, LOGL_NOTICE, "%s: unhandled flush\n", device->name);
PDEBUG(DDEVICE, DEBUG_NOTICE, "%s: unhandled flush\n", device->name);
}
static void cuse_device_fsync(fuse_req_t req, int datasync, struct fuse_file_info *fi)
@ -441,7 +441,7 @@ static void cuse_device_fsync(fuse_req_t req, int datasync, struct fuse_file_inf
(void)datasync;
(void)fi;
device_t *device = get_device_by_thread();
LOGP(DDEVICE, LOGL_NOTICE, "%s: unhandled fsync\n", device->name);
PDEBUG(DDEVICE, DEBUG_NOTICE, "%s: unhandled fsync\n", device->name);
}
@ -467,7 +467,7 @@ static void *device_child(void *arg)
const char *dev_info_argv[] = { dev_name };
struct cuse_info ci;
strncat(dev_name, device->name, sizeof(dev_name) - strlen(dev_name) - 1);
strncat(dev_name, device->name, sizeof(dev_name) - strlen(device->name) - 1);
memset(&ci, 0, sizeof(ci));
ci.dev_major = device->major;
@ -478,9 +478,9 @@ static void *device_child(void *arg)
device->thread_started = 1;
LOGP(DDEVICE, LOGL_INFO, "Device '%s' started.\n", device->name);
PDEBUG(DDEVICE, DEBUG_INFO, "Device '%s' started.\n", device->name);
cuse_lowlevel_main(argc, argv, &ci, &cuse_device_clop, NULL);
LOGP(DDEVICE, LOGL_INFO, "Device '%s' terminated.\n", device->name);
PDEBUG(DDEVICE, DEBUG_INFO, "Device '%s' terminated.\n", device->name);
device->thread_stopped = 1;
@ -496,7 +496,7 @@ void *device_init(void *inst, const char *name, int (*open)(void *inst, int flag
device = calloc(1, sizeof(*device));
if (!device) {
LOGP(DDEVICE, LOGL_ERROR, "No memory!\n");
PDEBUG(DDEVICE, DEBUG_ERROR, "No memory!\n");
errno = ENOMEM;
goto error;
}
@ -514,13 +514,13 @@ void *device_init(void *inst, const char *name, int (*open)(void *inst, int flag
rc = pthread_create(&device->thread, NULL, device_child, device);
if (rc < 0) {
LOGP(DDEVICE, LOGL_ERROR, "Failed to create device thread!\n");
PDEBUG(DDEVICE, DEBUG_ERROR, "Failed to create device thread!\n");
errno = -rc;
goto error;
}
pthread_getname_np(device->thread, tname, sizeof(tname));
strncat(tname, "-device", sizeof(tname) - strlen(tname) - 1);
strncat(tname, "-device", sizeof(tname) - 7 - 1);
tname[sizeof(tname) - 1] = '\0';
pthread_setname_np(device->thread, tname);

View File

@ -26,10 +26,9 @@
#include <errno.h>
#include <math.h>
#include "../libsample/sample.h"
#include <osmocom/core/timer.h>
#include <osmocom/cc/misc.h>
#include "../libtimer/timer.h"
#include "../liboptions/options.h"
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "../libfsk/fsk.h"
#include "../libwave/wave.h"
#include "../libdisplay/display.h"
@ -50,7 +49,6 @@
/* dummy functions */
int num_kanal = 1; /* only one channel used for debugging */
void *get_sender_by_empfangsfrequenz(void);
void *get_sender_by_empfangsfrequenz() { return "void"; }
static datenklo_t datenklo[MAX_DEVICES];
@ -73,7 +71,7 @@ const char *write_rx_wave = NULL;
const char *read_tx_wave = NULL;
const char *read_rx_wave = NULL;
static void print_help(const char *arg0)
void print_help(const char *arg0)
{
printf("Usage: %s [options] -M <mode>\n\n", arg0);
/* - - */
@ -82,7 +80,6 @@ static void print_help(const char *arg0)
printf(" --config [~/]<path to config file>\n");
printf(" Give a config file to use. If it starts with '~/', path is at home dir.\n");
printf(" Each line in config file is one option, '-' or '--' must not be given!\n");
logging_print_help();
printf(" -T --am791x-type 7910 | 7911\n");
printf(" Give modem chip type. (Default = 791%d)\n", am791x_type);
printf(" -M --mc <mode>\n");
@ -161,11 +158,13 @@ static int handle_options(int short_option, int argi, char **argv)
print_help(argv[0]);
return 0;
case 'v':
rc = parse_logging_opt(argv[argi]);
if (rc > 0)
if (!strcasecmp(argv[argi], "list")) {
debug_list_cat();
return 0;
}
rc = parse_debug_opt(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Failed to parse logging option, please use -h for help.\n");
fprintf(stderr, "Failed to parse debug option, please use -h for help.\n");
return rc;
}
break;
@ -237,7 +236,7 @@ static int handle_options(int short_option, int argi, char **argv)
return 1;
}
static const char *inc_dev_name(const char *dev_name)
const char *inc_dev_name(const char *dev_name)
{
char *new_name, *number;
int integer;
@ -266,8 +265,6 @@ int main(int argc, char *argv[])
int rc, argi;
int i;
logging_init();
/* handle options / config file */
add_options();
rc = options_config_file(argc, argv, "~/.osmocom/analog/datenklo.conf", handle_options);
@ -328,5 +325,3 @@ fail:
return 0;
}
void osmo_cc_set_log_cat(int __attribute__((unused)) cc_log_cat) {}

View File

@ -21,7 +21,7 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "../liblogging/logging.h"
#include "../libdebug/debug.h"
#include "uart.h"
static uint32_t calc_parity(uint32_t data, uint8_t data_bits, enum uart_parity parity)
@ -56,13 +56,13 @@ int uart_init(uart_t *uart, void *inst, uint8_t data_bits, enum uart_parity pari
uart->rx_cb = rx_cb;
uart->data_bits = data_bits;
if (uart->data_bits > 9) {
LOGP(DUART, LOGL_ERROR, "Illegal number of data bits, please fix!\n");
PDEBUG(DUART, DEBUG_ERROR, "Illegal number of data bits, please fix!\n");
abort();
}
uart->parity = parity;
uart->stop_bits = stop_bits;
if (uart->stop_bits < 1 || uart->stop_bits > 2) {
LOGP(DUART, LOGL_ERROR, "Illegal number of stop bits, please fix!\n");
PDEBUG(DUART, DEBUG_ERROR, "Illegal number of stop bits, please fix!\n");
abort();
}
uart->tx_pos = -1;

View File

@ -1,27 +0,0 @@
AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes)
if HAVE_ALSA
bin_PROGRAMS = \
dcf77
dcf77_SOURCES = \
dcf77.c \
weather.c \
cities.c \
image.c \
main.c
dcf77_LDADD = \
$(COMMON_LA) \
$(top_builddir)/src/liboptions/liboptions.a \
$(top_builddir)/src/libdisplay/libdisplay.a \
$(top_builddir)/src/libfilter/libfilter.a \
$(top_builddir)/src/libwave/libwave.a \
$(top_builddir)/src/libsample/libsample.a \
$(top_builddir)/src/libsound/libsound.a \
$(top_builddir)/src/libaaimage/libaaimage.a \
$(top_builddir)/src/liblogging/liblogging.a \
$(LIBOSMOCORE_LIBS) \
$(ALSA_LIBS) \
-lm
endif

View File

@ -1,633 +0,0 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include "cities.h"
static struct city_list {
int region;
const char *name;
} city_list[] = {
{ 0, "AGEN" },
{ 0, "AUCH" },
{ 0, "BORDEAUX" },
{ 0, "BRIVE LA GAILLARDE" },
{ 0, "CAHORS" },
{ 0, "MONTAUBAN" },
{ 0, "MONT MARSAN" },
{ 0, "PAU" },
{ 0, "PERIGUEUX" },
{ 0, "TARBES" },
{ 0, "TOULOUSE" },
{ 1, "ANGOULEME" },
{ 1, "LA ROCHELL" },
{ 1, "LA ROCHE S" },
{ 1, "LIMOGES" },
{ 1, "NIORT" },
{ 1, "POITIERS" },
{ 2, "ALENCON" },
{ 2, "AUXERRE" },
{ 2, "BAR LE DUC" },
{ 2, "BLOIS" },
{ 2, "BOBIGNY" },
{ 2, "BOURGES" },
{ 2, "CERGY PONT" },
{ 2, "CHARTRES" },
{ 2, "CRETEIL" },
{ 2, "EVRY" },
{ 2, "LE MANS" },
{ 2, "MELUN" },
{ 2, "NANTERRE" },
{ 2, "NEVERS" },
{ 2, "ORLEANS" },
{ 2, "PARIS" },
{ 2, "REIMS" },
{ 2, "TOURS" },
{ 2, "TROYES" },
{ 2, "VERSAILLES" },
{ 3, "ANGERS" },
{ 3, "BREST" },
{ 3, "CHERBOURG" },
{ 3, "JERSEY" },
{ 3, "LAVAL" },
{ 3, "LORIENT" },
{ 3, "NANTES" },
{ 3, "RENNES" },
{ 3, "ST BRIEUC" },
{ 4, "AURILLAC" },
{ 4, "CLERMON FERRAND" },
{ 4, "FLORAC" },
{ 4, "GUERET" },
{ 4, "MENDE" },
{ 4, "MILLAU" },
{ 4, "MONTLUCON" },
{ 4, "PUY VELAY" },
{ 4, "RODEZ" },
{ 4, "ST-ETIENNE" },
{ 4, "ST FLOUR" },
{ 5, "ALBI" },
{ 5, "BEZIERS" },
{ 5, "CARCASSONN" },
{ 5, "FOIX" },
{ 5, "MONTPELLIER" },
{ 5, "PERPIGNAN" },
{ 6, "AALST" },
{ 6, "ANTWERPEN" },
{ 6, "BOULOGNE" },
{ 6, "BRUGGE" },
{ 6, "BRUSSEL" },
{ 6, "CHARLEROI" },
{ 6, "GENK" },
{ 6, "GENT" },
{ 6, "HALLE" },
{ 6, "HASSELT" },
{ 6, "IXELLES" },
{ 6, "KNOKKE-HEIST" },
{ 6, "KORTRIJK" },
{ 6, "LEUVEN" },
{ 6, "LIEGE" },
{ 6, "LILLE" },
{ 6, "LOKEREN" },
{ 6, "MAASTRICHT" },
{ 6, "MECHELEN" },
{ 6, "MIDDELBURG" },
{ 6, "MONS" },
{ 6, "MOUSCRON" },
{ 6, "NAMUR" },
{ 6, "OOSTENDE" },
{ 6, "ROESELARE" },
{ 6, "SCHAERBEEK" },
{ 6, "TERNEUZEN" },
{ 6, "TOURNAI" },
{ 7, "CHAUMONT" },
{ 7, "DIJON" },
{ 7, "EPINAL" },
{ 7, "LONS LE S" },
{ 7, "METZ" },
{ 7, "NANCY" },
{ 7, "VESOUL" },
{ 8, "ALES" },
{ 8, "AVIGNON" },
{ 8, "MARSEILLE" },
{ 8, "MONTELIMAR" },
{ 8, "NIMES" },
{ 8, "PRIVAS" },
{ 8, "ST TROPEZ" },
{ 8, "TOULON" },
{ 9, "BOURG EN B" },
{ 9, "LYON" },
{ 9, "MACON" },
{ 9, "VALENCE" },
{ 10, "BRIANCON" },
{ 10, "CHAMBERY" },
{ 10, "DIGNE" },
{ 10, "GAP" },
{ 10, "GRENOBLE" },
{ 11, "ANNECY" },
{ 11, "BESANCON" },
{ 11, "DELEMONT" },
{ 11, "LA CHAUX-DE-FONDS" },
{ 12, "ASCHAFFENBURG" },
{ 12, "BAD HOMBURG" },
{ 12, "BAD KREUZNACH" },
{ 12, "DARMSTADT" },
{ 12, "FRANKFURT AM MAIN" },
{ 12, "HEIDELBERG" },
{ 12, "KAISERSLAUTERN" },
{ 12, "KARLSRUHE" },
{ 12, "LANDAU IN DER PFALZ" },
{ 12, "LUDWIGSHAFEN" },
{ 12, "MAINZ" },
{ 12, "MANNHEIM" },
{ 12, "PIRMASENS" },
{ 12, "WORMS" },
{ 13, "BITBURG" },
{ 13, "HAGEN" },
{ 13, "ISERLOHN" },
{ 13, "KOBLENZ" },
{ 13, "LUEDENSCHEID" },
{ 13, "LUXEMBOURG" },
{ 13, "NEUWIED" },
{ 13, "SAARBRUECKEN" },
{ 13, "SEDAN" },
{ 13, "SIEGEN" },
{ 13, "TRIER" },
{ 13, "VERVIERS" },
{ 13, "WIESBADEN" },
{ 14, "AACHEN" },
{ 14, "BIELEFELD" },
{ 14, "BOCHUM" },
{ 14, "BONN" },
{ 14, "DORTMUND" },
{ 14, "DUEREN" },
{ 14, "DUESSELDORF" },
{ 14, "DUISBURG" },
{ 14, "ESSEN" },
{ 14, "GELSENKIRCHEN" },
{ 14, "GUETERSLOH" },
{ 14, "KOELN" },
{ 14, "LINGEN" },
{ 14, "LIPPSTADT" },
{ 14, "MOENCHENGLADBACH" },
{ 14, "MUELHEIM AN DER RUHR" },
{ 14, "MUENSTER" },
{ 14, "NORDHORN" },
{ 14, "OBERHAUSEN" },
{ 14, "OSNABRUECK" },
{ 14, "RECKLINGHAUSEN" },
{ 14, "RHEINE" },
{ 14, "SOLINGEN" },
{ 14, "WESEL" },
{ 14, "WUPPERTAL" },
{ 15, "BRISTOL" },
{ 15, "CARDIFF" },
{ 15, "EXETER" },
{ 15, "HOLYHEAD" },
{ 15, "PLYMOUTH" },
{ 15, "ST DAVIDS" },
{ 15, "SWANSEA" },
{ 16, "BIRMINGHAM" },
{ 16, "BLACKPOOL" },
{ 16, "LEEDS" },
{ 16, "LEICESTER" },
{ 16, "LIVERPOOL" },
{ 16, "MANCHESTER" },
{ 16, "MIDDLESBROUGH" },
{ 16, "NEWCASTLE" },
{ 16, "NOTTINGHAM" },
{ 16, "SHEFFIELD" },
{ 17, "AMIENS" },
{ 17, "BEAUVAIS" },
{ 17, "CAEN" },
{ 17, "EVREUX" },
{ 17, "LAON" },
{ 17, "LE HAVRE" },
{ 17, "ROUEN" },
{ 18, "BOURNEMOUT" },
{ 18, "BRIGHTON" },
{ 18, "CAMBRIDGE" },
{ 18, "DOVER" },
{ 18, "IPSWICH" },
{ 18, "KINGSTON" },
{ 18, "LONDON" },
{ 18, "NORTHAMPTON" },
{ 18, "NORWICH" },
{ 18, "OXFORD" },
{ 18, "PORTSMOUTH" },
{ 18, "READING" },
{ 18, "SOUTHAMPTON" },
{ 19, "BORKUM" },
{ 19, "BREMERHAVEN" },
{ 19, "CUXHAVEN" },
{ 19, "DEN HELDER" },
{ 19, "ELMSHORN" },
{ 19, "EMDEN" },
{ 19, "GRONINGEN" },
{ 19, "HAMBURG" },
{ 19, "LEEUWARDEN" },
{ 19, "NORDERTSTEDT" },
{ 19, "SPIEKEROOG" },
{ 19, "ST PETER ORDING" },
{ 19, "SYLT" },
{ 19, "TEXEL" },
{ 19, "WILHELMSHAVEN" },
{ 20, "ALBORG" },
{ 20, "ESBJERG" },
{ 20, "FREDERIKSHAVN" },
{ 20, "HERNING" },
{ 20, "HOLSTERBRO" },
{ 20, "SKAGEN" },
{ 20, "THISTED" },
{ 20, "THYBOROEN" },
{ 20, "VIBORG" },
{ 21, "ARHUS" },
{ 21, "FREDERICIA" },
{ 21, "HORSENS" },
{ 21, "KOLDING" },
{ 21, "ODENSE" },
{ 21, "RANDERS" },
{ 21, "SILKEBORG" },
{ 21, "VEJLE" },
{ 22, "BRAUNSCHWEIG" },
{ 22, "BREMEN" },
{ 22, "CELLE" },
{ 22, "GOSLAR" },
{ 22, "HAMELN" },
{ 22, "HANNOVER" },
{ 22, "HERFORD" },
{ 22, "HILDESHEIM" },
{ 22, "LUENEBURG" },
{ 22, "MAGDEBURG" },
{ 22, "MINDEN" },
{ 22, "OLDENBURG" },
{ 22, "WOLFSBURG" },
{ 23, "HELSINGOER" },
{ 23, "KALUNDBORG" },
{ 23, "KOEBENHAVN" },
{ 23, "MALMOE" },
{ 23, "NAESTVED" },
{ 23, "ROSKILDE" },
{ 23, "SLAGELSE" },
{ 24, "FEHMARN" },
{ 24, "FLENSBURG" },
{ 24, "GREIFSWALD" },
{ 24, "KIEL" },
{ 24, "LUEBECK" },
{ 24, "ROSTOCK" },
{ 24, "RUEGEN" },
{ 24, "SCHWERIN" },
{ 24, "STRALSUND" },
{ 24, "SZCZECIN" },
{ 24, "WISMAR" },
{ 25, "AUGSBURG" },
{ 25, "DEGGENDORF" },
{ 25, "INGOLSTADT" },
{ 25, "LANDSHUT" },
{ 25, "PASSAU" },
{ 25, "REGENSBURG" },
{ 25, "ULM" },
{ 26, "BURGHAUSEN" },
{ 26, "FRIEDRICHSHAFEN" },
{ 26, "KEMPTEN" },
{ 26, "LINZ" },
{ 26, "MUENCHEN" },
{ 26, "ROSENHEIM" },
{ 26, "SIGMARINGEN" },
{ 26, "WELS" },
{ 27, "BOLZANO" },
{ 27, "MERANO" },
{ 27, "TRENTO" },
{ 28, "ANSBACH" },
{ 28, "BAMBERG" },
{ 28, "BAYREUTH" },
{ 28, "ERLANGEN" },
{ 28, "FUERTH" },
{ 28, "NUERNBERG" },
{ 28, "SCHWEINFURT" },
{ 28, "WEIDEN" },
{ 28, "WERTHEIM" },
{ 28, "WUERZBURG" },
{ 29, "ALTENBURG" },
{ 29, "BAUTZEN" },
{ 29, "CHEMNITZ" },
{ 29, "COTTBUS" },
{ 29, "DESSAU" },
{ 29, "DRESDEN" },
{ 29, "EISENHUETTENSTADT" },
{ 29, "GOERLITZ" },
{ 29, "HALLE" },
{ 29, "HOYERSWERDA" },
{ 29, "LEIPZIG" },
{ 29, "WITTENBERG" },
{ 29, "WROCLAW" },
{ 30, "EISENACH" },
{ 30, "ERFURT" },
{ 30, "GOTHA" },
{ 30, "HOF" },
{ 30, "JENA" },
{ 30, "NORDHAUSEN" },
{ 30, "PLAUEN" },
{ 30, "SUHL" },
{ 30, "WEIMAR" },
{ 30, "ZWICKAU" },
{ 31, "EVIAN" },
{ 31, "FRIBOURG" },
{ 31, "GENEVE" },
{ 31, "LAUSANNE" },
{ 31, "MONTREUX" },
{ 31, "NEUCHATEL" },
{ 32, "AARAU" },
{ 32, "BERN" },
{ 32, "BIENNE" },
{ 32, "FRAUENFELD" },
{ 32, "KONSTANZ" },
{ 32, "LUZERN" },
{ 32, "SCHAFFHAUSEN" },
{ 32, "SOLOTHURN" },
{ 32, "ZUERICH" },
{ 32, "ZUG" },
{ 33, "ADELBODEN" },
{ 33, "GRINDELWALD" },
{ 33, "INTERLAKEN" },
{ 34, "BRIG" },
{ 34, "MARTIGNY" },
{ 34, "SION" },
{ 35, "ALTDORF" },
{ 35, "GLARUS" },
{ 35, "SARNEN" },
{ 35, "SCHWYZ" },
{ 35, "STANS" },
{ 35, "ST.GALLEN" },
{ 36, "CHUR" },
{ 36, "DAVOS" },
{ 37, "FULDA" },
{ 37, "GIESSEN" },
{ 37, "GOETTINGEN" },
{ 37, "KASSEL" },
{ 37, "MARBURG" },
{ 38, "BELLINZONA" },
{ 38, "EDOLO" },
{ 38, "LOCARNO" },
{ 38, "LUGANO" },
{ 39, "AOSTA" },
{ 39, "SESTRIERE" },
{ 40, "ALESSANDRIA" },
{ 40, "BERGAMO" },
{ 40, "BRESCIA" },
{ 40, "MILANO" },
{ 40, "PARMA" },
{ 40, "PIACENZA" },
{ 40, "TORINO" },
{ 40, "VERONA" },
{ 41, "FIRENZE" },
{ 41, "PERUGIA" },
{ 41, "PISA" },
{ 41, "ROMA" },
{ 41, "SIENA" },
{ 41, "VATICANO" },
{ 42, "AMSTERDAM" },
{ 42, "ARNHEM" },
{ 42, "ASSEN" },
{ 42, "DEN HAAG" },
{ 42, "EINDHOVEN" },
{ 42, "HAARLEM" },
{ 42, "LELYSTAD" },
{ 42, "ROTTERDAM" },
{ 42, "S.HERTOGENBOSCH" },
{ 42, "UTRECHT" },
{ 42, "ZWOLLE" },
{ 43, "CANNES" },
{ 43, "GENOVA" },
{ 43, "LA SPEZIA" },
{ 43, "MONACO" },
{ 43, "NICE" },
{ 43, "SAN REMO" },
{ 44, "BOLOGNA" },
{ 44, "NOVA GORIC" },
{ 44, "RIJEKA" },
{ 44, "RIMINI" },
{ 44, "TRIESTE" },
{ 44, "UDINE" },
{ 44, "VENEZIA" },
{ 45, "BASEL" },
{ 45, "BELFORT" },
{ 45, "COLMAR" },
{ 45, "FREIBURG" },
{ 45, "LIESTAL" },
{ 45, "LOERRACH" },
{ 45, "MULHOUSE" },
{ 45, "OFFENBURG" },
{ 45, "STRASBOURG" },
{ 46, "GRAZ" },
{ 46, "KLAGENFURT" },
{ 46, "LIENZ" },
{ 46, "LJUBLJANA" },
{ 46, "MARIBOR" },
{ 46, "SEMMERING" },
{ 46, "VILLACH" },
{ 46, "ZELTWEG" },
{ 47, "BAD GASTEIN" },
{ 47, "INNSBRUCK" },
{ 47, "ISCHGL" },
{ 47, "LANDECK" },
{ 47, "SOELDEN" },
{ 47, "TUXERTAL" },
{ 48, "BAD TOELZ" },
{ 48, "BERCHTESGADEN" },
{ 48, "BISCHOFSHOFEN" },
{ 48, "BREGENZ" },
{ 48, "GARMISCH PARTENKIRCHEN" },
{ 48, "KITZBUEHEL" },
{ 48, "LINDAU" },
{ 48, "SALZBURG" },
{ 48, "SCHLADMING" },
{ 48, "STEYR" },
{ 48, "VADUZ" },
{ 49, "BRATISLAVA" },
{ 49, "EISENSTADT" },
{ 49, "GYOER" },
{ 49, "KLOSTERNEUBURG" },
{ 49, "SOPRON" },
{ 49, "SZOMBATHELY" },
{ 49, "TRENCIN" },
{ 49, "WIEN" },
{ 49, "WIENER NEUSTADT" },
{ 49, "ZALAEGERSZEG" },
{ 50, "BRNO" },
{ 50, "BUDEJOVICE" },
{ 50, "CHEB" },
{ 50, "HAVLICKAV BROD" },
{ 50, "HRADEC/KRA" },
{ 50, "JIHLAVA" },
{ 50, "KARLOVY VARY" },
{ 50, "KLADNO" },
{ 50, "MOST" },
{ 50, "OLOMOUC" },
{ 50, "OSTRAVA" },
{ 50, "PARDUBICE" },
{ 50, "PLZEN" },
{ 50, "PRAHA" },
{ 50, "PREROV" },
{ 50, "PROSTEJOV" },
{ 50, "ST POELTEN" },
{ 50, "ZWETTL" },
{ 51, "CHOMUTOV" },
{ 51, "DECIN" },
{ 51, "LIBEREC" },
{ 51, "OPAVA" },
{ 51, "PIRNA" },
{ 51, "SNIEZKA" },
{ 51, "TEPLICE" },
{ 51, "USTI NAD LABEM" },
{ 51, "WALBRZYCH" },
{ 52, "BERLIN" },
{ 52, "BRANDENBURG" },
{ 52, "FINOW" },
{ 52, "FRANKFURT AN DER ODER" },
{ 52, "GORZOW" },
{ 52, "NEUBRANDENBURG" },
{ 52, "POTSDAM" },
{ 52, "POZNAN" },
{ 52, "STENDAL" },
{ 53, "GOETEBORG" },
{ 53, "HALMSTAD" },
{ 54, "GAEVLE" },
{ 54, "NYKOPING" },
{ 54, "STOCKHOLM" },
{ 54, "UPPSALA" },
{ 54, "VAESTERAS" },
{ 55, "BORGHOLM" },
{ 55, "BORNHOLM" },
{ 55, "KALMAR" },
{ 55, "LINKOEPING" },
{ 55, "RONNE" },
{ 55, "VISBY" },
{ 56, "BORAS" },
{ 56, "JOENKOEPING" },
{ 56, "KARLSTAD" },
{ 56, "OEREBRO" },
{ 57, "BADEN-BADEN" },
{ 57, "DONAUESCHINGEN" },
{ 57, "FREUDENSTADT" },
{ 57, "VILLINGEN-SCHWENNINGEN" },
{ 58, "DRAMMEN" },
{ 58, "FREDRIKSTADEN" },
{ 58, "OSLO" },
{ 58, "TOENSBERG" },
{ 59, "AALEN" },
{ 59, "GOEPPINGEN" },
{ 59, "HEILBRONN" },
{ 59, "PFORZHEIM" },
{ 59, "REUTLINGEN" },
{ 59, "SCHWAEBISCH GMUEND" },
{ 59, "STUTTGART" },
{ 59, "TUEBINGEN" },
{ 60, "NAPOLI" },
{ 61, "ANCONA" },
{ 61, "PESCARA" },
{ 61, "SAN MARINO" },
{ 62, "BARI" },
{ 62, "FOGGIA" },
{ 62, "LECCE" },
{ 63, "BEKESCSABA" },
{ 63, "BRANSKA" },
{ 63, "BUDAPEST" },
{ 63, "DEBRECEN" },
{ 63, "DUNAIJVAROS" },
{ 63, "EGER" },
{ 63, "ERD" },
{ 63, "HODMEZOVASARHELY" },
{ 63, "KAPOSVAR" },
{ 63, "KECSKEMET" },
{ 63, "KOSICE" },
{ 63, "MISKOLC" },
{ 63, "NAGYKANIZSA" },
{ 63, "NYIREGYHAZA" },
{ 63, "OZD" },
{ 63, "PECS" },
{ 63, "SALGOTARJAN" },
{ 63, "SIOFOK" },
{ 63, "SZEGED" },
{ 63, "SZEKESFEEVAR" },
{ 63, "SZOLNOK" },
{ 63, "TATABANYA" },
{ 63, "VESZPREM" },
{ 64, "MADRID" },
{ 65, "BILBAO" },
{ 66, "CATANIA" },
{ 66, "COSENZA" },
{ 66, "MESSINA" },
{ 66, "PALERMO" },
{ 66, "REGGIO CALABRIA" },
{ 67, "IBIZA" },
{ 67, "MAHON" },
{ 67, "PALMA DE MALLORCA" },
{ 68, "VALENCIA" },
{ 69, "BARCELONA" },
{ 69, "FIGUERES" },
{ 69, "GIRONA" },
{ 69, "LLORET DE MAR" },
{ 70, "ANDORRA LA VELLA" },
{ 71, "SEVILLA" },
{ 72, "LISBOA" },
{ 73, "AJACCIO" },
{ 73, "BASTIA" },
{ 73, "CAGLIARI" },
{ 73, "SASSARI" },
{ 74, "GIJON" },
{ 75, "CORK" },
{ 75, "GALWAY" },
{ 75, "LIMERICK" },
{ 76, "BELFAST" },
{ 76, "DUBLIN" },
{ 77, "ABERDEEN" },
{ 77, "EDINBURGH" },
{ 77, "GLASGOW" },
{ 77, "ISLE OF MAN" },
{ 78, "BERGEN" },
{ 78, "STAVANGER" },
{ 79, "TRONDHEIM" },
{ 80, "SUNDSVALL" },
{ 81, "GDANSK" },
{ 81, "OLSZTYN" },
{ 81, "SLUPSK" },
{ 82, "BIALYSTOK" },
{ 82, "BYDGOSZCZ" },
{ 82, "LODZ" },
{ 82, "LUBLIN" },
{ 82, "TORUN" },
{ 82, "WARSZAWA" },
{ 83, "BIELSKO" },
{ 83, "KATOWICE" },
{ 83, "KIELCE" },
{ 83, "KRAKOW" },
{ 83, "OPOLE" },
{ 83, "RZESZOW" },
{ 83, "ZAKOPANE" },
{ 84, "UMEA" },
{ 85, "FALUN" },
{ 85, "OESTERSUND" },
{ 86, "SAMEDAN" },
{ 87, "OSIJEK" },
{ 87, "ZAGREB" },
{ 88, "ZERMATT" },
{ 89, "SPLIT" },
{ 24, "Doerphof" },
{ -1, NULL }
};
void display_city(const char *search)
{
int i;
int found = 0;
for (i = 0; city_list[i].name; i++) {
if (strcasestr(city_list[i].name, search)) {
found++;
printf("City %s is located in region %d.\n", city_list[i].name, city_list[i].region);
}
}
if (!found) {
printf("No city found for '%s', try larger city.\n", search);
}
}

View File

@ -1,3 +0,0 @@
void display_city(const char *search);

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
#include "../libsample/sample.h"
#include "../libfilter/iir_filter.h"
#include "../libdisplay/display.h"
#include <time.h>
typedef struct dcf77_tx {
int enable;
double phase_360;
double carrier_phase, carrier_phase_step; /* uncorrected phase */
double test_phase, test_phase_step;
double level;
int wave, waves_0, waves_1, waves_sec;
time_t timestamp;
int second;
char symbol;
uint64_t data_frame;
char data_string[100]; /* 60 digits + spaces + '\0' */
int test_tone;
int weather;
int weather_day;
int weather_night;
int extreme;
int rain;
int wind_dir;
int wind_bft;
int temperature_day;
int temperature_night;
uint64_t weather_cipher;
} dcf77_tx_t;
typedef struct dcf77_rx {
int enable;
double phase_360;
double carrier_phase, carrier_phase_step; /* uncorrected phase */
iir_filter_t carrier_lp[2]; /* filters received carrier signal */
double sample_counter, sample_step; /* when to sample */
double *delay_buffer;
int delay_size, delay_index;
int clock_count;
double value_level, value_short, value_long; /* measured values */
int data_receive, data_index;
char data_string[100]; /* 60 digits + spaces + '\0' */
int string_index;
uint64_t data_frame;
int weather_index;
uint64_t weather_cipher;
uint64_t weather_key;
} dcf77_rx_t;
typedef struct dcf77 {
dcf77_tx_t tx;
dcf77_rx_t rx;
/* measurements */
dispmeas_t dispmeas; /* display measurements */
dispmeasparam_t *dmp_input_level;
dispmeasparam_t *dmp_signal_level;
dispmeasparam_t *dmp_signal_quality;
dispmeasparam_t *dmp_current_second;
/* wave */
dispwav_t dispwav; /* display wave form */
} dcf77_t;
int dcf77_init(int _fast_math);
void dcf77_exit(void);
dcf77_t *dcf77_create(int samplerate, int use_tx, int use_rx, int test_tone);
void dcf77_destroy(dcf77_t *dcf77);
void dcf77_tx_start(dcf77_t *dcf77, time_t timestamp, double sub_sec);
void dcf77_encode(dcf77_t *dcf77, sample_t *samples, int length);
void dcf77_decode(dcf77_t *dcf77, sample_t *samples, int length);
void list_weather(void);
time_t dcf77_start_weather(time_t timestamp, int region, int offset);
void dcf77_set_weather(dcf77_t *dcf77, int weather_day, int weather_night, int extreme, int rain, int wind_dir, int wind_bft, int temperature_day, int temperature_night);

View File

@ -1,16 +0,0 @@
#include <stdio.h>
const char *aaimage[] = {
"",
"@W * DCF77 with weather info *",
"",
" @Y\\__/",
" @w_______@Y/ \\__",
" @w/ ____\\_@Y/@w_",
" \\___/@r10:08:33@w\\",
" @B/ @w\\________/",
" @B/ @W*@B/ @W*@B/ @W*@B/ @W*@B/",
" @W*@B/ @W*@B/ @W*@B/ @W*@B/",
"",
NULL
};

View File

@ -1,660 +0,0 @@
/* DCF77 main
*
* (C) 2022 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 <unistd.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <termios.h>
#include <sched.h>
#include <time.h>
#include <math.h>
#include "../liblogging/logging.h"
#include "../liboptions/options.h"
#include "../libsample/sample.h"
#include "../libsound/sound.h"
#include "../libaaimage/aaimage.h"
#include <osmocom/cc/misc.h>
#include "dcf77.h"
#include "cities.h"
int num_kanal = 1;
dcf77_t *dcf77 = NULL;
static void *soundif = NULL;
static const char *dsp_device = "";
static int dsp_samplerate = 192000;
static int dsp_buffer = 50;
static int rx = 0, tx = 0;
static double timestamp = -1;
static int weather = 0;
static int weather_day;
static int weather_night;
static int extreme;
static int rain;
static int wind_dir;
static int wind_bft;
static int temperature_day;
static int temperature_night;
static int region = -1, region_advance;
static int double_amplitude = 0;
static int test_tone = 0;
static int dsp_interval = 1; /* ms */
static int rt_prio = 0;
static int fast_math = 0;
/* not static, in case we add libtimer some day, then compiler hits an error */
double get_time(void);
double get_time(void)
{
static struct timespec tv;
clock_gettime(CLOCK_REALTIME, &tv);
return (double)tv.tv_sec + (double)tv.tv_nsec / 1000000000.0;
}
static time_t parse_time(char **argv)
{
time_t t;
struct tm *tm;
int val;
t = get_time();
tm = localtime(&t);
if (!tm)
return -1;
val = atoi(argv[0]);
if (val < 1900)
return -1;
tm->tm_year = val - 1900;
val = atoi(argv[1]);
if (val < 1 || val > 12)
return -1;
tm->tm_mon = val - 1;
val = atoi(argv[2]);
if (val < 1 || val > 31)
return -1;
tm->tm_mday = val;
val = atoi(argv[3]);
if (val < 0 || val > 23)
return -1;
tm->tm_hour = val;
val = atoi(argv[4]);
if (val < 0 || val > 59)
return -1;
tm->tm_min = val;
val = atoi(argv[5]);
if (val < 0 || val > 59)
return -1;
tm->tm_sec = val;
tm->tm_isdst = -1;
return mktime(tm);
}
static time_t feierabend_time()
{
time_t t;
struct tm *tm;
t = get_time();
tm = localtime(&t);
tm->tm_hour = 17;
tm->tm_min = 0;
tm->tm_sec = 0;
tm->tm_isdst = -1;
return mktime(tm);
}
static void print_usage(const char *app)
{
printf("Usage: %s [-a hw:0,0] [<options>]\n", app);
}
static void print_help(void)
{
/* - - */
printf(" -h --help\n");
printf(" This help\n");
printf(" --config [~/]<path to config file>\n");
printf(" Give a config file to use. If it starts with '~/', path is at home dir.\n");
printf(" Each line in config file is one option, '-' or '--' must not be given!\n");
logging_print_help();
printf(" -a --audio-device hw:<card>,<device>\n");
printf(" Sound card and device number (default = '%s')\n", dsp_device);
printf(" -s --samplerate <rate>\n");
printf(" Sample rate of sound device (default = '%d')\n", dsp_samplerate);
printf(" -b --buffer <ms>\n");
printf(" How many milliseconds are processed in advance (default = '%d')\n", dsp_buffer);
printf(" A buffer below 10 ms requires low interval like 0.1 ms.\n");
printf(" -T --tx\n");
printf(" Transmit time signal (default)\n");
printf(" -R --rx\n");
printf(" Receive time signal\n");
printf(" -F --fake\n");
printf(" Use given time stamp: <year> <month> <day> <hour> <min> <sec>.\n");
printf(" All values have to be numerical. The year must have 4 digits.\n");
printf(" --feierabend\n");
printf(" --end-of-working-day\n");
printf(" Use fake time stamp that equals 5 O'Clock PM.\n");
printf(" --geburtstag\n");
printf(" --birthday\n");
printf(" Use fake time stamp that equals birth of the author.\n");
printf(" -W --weather <weather> <extreme> <rain> <wind dir> <wind bft> <temperature>\n");
printf(" Send these weather info for all regions / all days.\n");
printf(" See -L for infos on values.\n");
printf(" weather = 1..15 for common day and night weather.\n");
printf(" weather = 1..15,1..15 for specific day and night weather.\n");
printf(" extreme = 0..15 for extreme weather conditions.\n");
printf(" rain = 0..100 for rain/show probability. (closest is used)\n");
printf(" wind dir = N | NE | E | SE | S | SW | W | NW | 0 for wind direction.\n");
printf(" wind bft = <bft> for wind speed in bft. (closest is used)\n");
printf(" temerature = <celsius> for common min and max temperature.\n");
printf(" temerature = <celsius>,<celsius> for specific min and max temperature.\n");
printf(" --beach-party\n");
printf(" Beach weather, equivalent to -W 1 0 0 0 2 35,20\n");
printf(" --santa-claus\n");
printf(" --muenster-2005\n");
printf(" Deep snow, equivalent to -W 7 1 100 E 3 1,-1\n");
printf(" -A --at-region <region> <advance minutes>\n");
printf(" Alter time, so that the weather of the given region is transmitted.\n");
printf(" To allow the receiver to sync, give time to advance in minutes.\n");
printf(" -L --list\n");
printf(" List all regions / weather values.\n");
printf(" -C --city <name fragment>\n");
printf(" Search for city (case insensitive) and display its region code.\n");
printf(" -D --double-amplitude\n");
printf(" Transmit with double amplitude by using differential stereo output.\n");
printf(" --test-tone\n");
printf(" Transmit a test tone (10%% level, 1000 Hz) with the carrier.\n");
printf(" -r --realtime <prio>\n");
printf(" Set prio: 0 to disable, 99 for maximum (default = %d)\n", rt_prio);
printf(" --fast-math\n");
printf(" Use fast math approximation for slow CPU / ARM based systems.\n");
printf("\n");
printf("Press 'w' key to toggle display of RX wave form.\n");
printf("Press 'm' key to toggle display of measurement values.\n");
}
#define OPT_F1 1001
#define OPT_F2 1002
#define OPT_G1 1003
#define OPT_G2 1004
#define OPT_BEACH 1005
#define OPT_SANTA 1006
#define OPT_MUENSTER 1007
#define OPT_TEST_TONE 1008
#define OPT_FAST_MATH 1009
static void add_options(void)
{
option_add('h', "help", 0);
option_add('v', "verbose", 1);
option_add('a', "audio-device", 1);
option_add('s', "samplerate", 1);
option_add('b', "buffer", 1);
option_add('T', "tx", 0);
option_add('R', "rx", 0);
option_add('F', "fake", 6);
option_add(OPT_F1, "feierabend", 0);
option_add(OPT_F2, "end-of-working-day", 0);
option_add(OPT_G1, "geburtstag", 0);
option_add(OPT_G2, "birthday", 0);
option_add('W', "weather", 6);
option_add(OPT_BEACH, "beach-party", 0);
option_add(OPT_SANTA, "santa-claus", 0);
option_add(OPT_MUENSTER, "muenster-2005", 0);
option_add('A', "at-region", 2);
option_add('L', "list", 0);
option_add('C', "city", 1);
option_add('D', "double-amplitude", 0);
option_add(OPT_TEST_TONE, "test-tone", 0);
option_add('r', "realtime", 1);
option_add(OPT_FAST_MATH, "fast-math", 0);
}
static const char *wind_dirs[8] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW" };
static int handle_options(int short_option, int argi, char **argv)
{
char *string, *string1;
int rc, i;
switch (short_option) {
case 'h':
print_usage(argv[0]);
print_help();
return 0;
case 'v':
rc = parse_logging_opt(argv[argi]);
if (rc > 0)
return 0;
if (rc < 0) {
fprintf(stderr, "Failed to parse logging option, please use -h for help.\n");
return rc;
}
break;
case 'a':
dsp_device = options_strdup(argv[argi]);
break;
case 's':
dsp_samplerate = atoi(argv[argi]);
break;
case 'b':
dsp_buffer = atoi(argv[argi]);
break;
case 'T':
tx = 1;
break;
case 'R':
rx = 1;
break;
case 'F':
timestamp = parse_time(argv + argi);
if (timestamp < 0) {
fprintf(stderr, "Given time stamp is invalid, please use -h for help.\n");
return -EINVAL;
}
break;
case OPT_F1:
case OPT_F2:
timestamp = feierabend_time() - 70;
break;
case OPT_G1:
case OPT_G2:
timestamp = 115099200 - 70;
break;
case 'W':
if (weather) {
no_multiple_weathers:
fprintf(stderr, "You cannot define more than one weather situation.\n");
return -EINVAL;
}
weather = 1;
string = options_strdup(argv[argi++]);
string1 = strsep(&string, ",");
weather_day = atoi(string1);
if (string)
weather_night = atoi(string);
else
weather_night = weather_day;
extreme = atoi(argv[argi++]);
rain = atoi(argv[argi++]);
/* if wind is not found, wind 8 (changable) is selected */
string = options_strdup(argv[argi++]);
for (i = 0; i < 8; i++) {
if (!strcasecmp(string, wind_dirs[i]))
break;
}
wind_dir = i;
wind_bft = atoi(argv[argi++]);
string = options_strdup(argv[argi++]);
string1 = strsep(&string, ",");
temperature_day = atoi(string1);
if (string)
temperature_night = atoi(string);
else
temperature_night = temperature_day;
break;
case OPT_BEACH:
if (weather)
goto no_multiple_weathers;
weather = 1;
weather_day = 1;
weather_night = 1;
extreme = 0;
rain = 0;
wind_dir = 8;
wind_bft = 2;
temperature_day = 35;
temperature_night = 20; /* tropical night >= 20 */
break;
case OPT_SANTA:
case OPT_MUENSTER:
if (weather)
goto no_multiple_weathers;
weather = 1;
weather_day = 7;
weather_night = 7;
extreme = 0;
rain = 100;
wind_dir = 6;
wind_bft = 3;
temperature_day = 1;
temperature_night = -1; /* freezing a little */
break;
case 'A':
region = atoi(argv[argi++]);
if (region < 0 || region > 89) {
fprintf(stderr, "Given region number is is invalid, please use -L for list of valid regions.\n");
return -EINVAL;
}
region_advance = atoi(argv[argi++]);
break;
case 'L':
list_weather();
return 0;
case 'C':
display_city(argv[argi++]);
return 0;
case OPT_TEST_TONE:
test_tone = 1;
break;
case 'D':
double_amplitude = 1;
break;
case 'r':
rt_prio = atoi(argv[argi]);
break;
case OPT_FAST_MATH:
fast_math = 1;
break;
default:
return -EINVAL;
}
return 1;
}
static int quit = 0;
static void sighandler(int sigset)
{
if (sigset == SIGHUP || sigset == SIGPIPE)
return;
fprintf(stderr, "\nSignal %d received.\n", sigset);
quit = 1;
}
static int get_char()
{
struct timeval tv = {0, 0};
fd_set fds;
char c = 0;
int __attribute__((__unused__)) rc;
FD_ZERO(&fds);
FD_SET(0, &fds);
select(0+1, &fds, NULL, NULL, &tv);
if (FD_ISSET(0, &fds)) {
rc = read(0, &c, 1);
return c;
} else
return -1;
}
static int soundif_open(const char *audiodev, int samplerate, int buffer_size)
{
enum sound_direction direction = SOUND_DIR_DUPLEX;
if (!audiodev || !audiodev[0]) {
LOGP(DDSP, LOGL_ERROR, "No audio device given!\n");
return -EINVAL;
}
/* open audiodev */
if (tx && !rx)
direction = SOUND_DIR_PLAY;
if (rx && !tx)
direction = SOUND_DIR_REC;
soundif = sound_open(direction, audiodev, NULL, NULL, NULL, (double_amplitude) ? 2 : 1, 0.0, samplerate, buffer_size, 1.0, 1.0, 0.0, 2.0);
if (!soundif) {
LOGP(DDSP, LOGL_ERROR, "Failed to open sound device!\n");
return -EIO;
}
return 0;
}
static void soundif_start(void)
{
sound_start(soundif);
LOGP(DDSP, LOGL_DEBUG, "Starting audio stream!\n");
}
static void soundif_close(void)
{
/* close audiodev */
if (soundif) {
sound_close(soundif);
soundif = NULL;
}
}
static void soundif_work(int buffer_size)
{
int count;
sample_t buff1[buffer_size], buff2[buffer_size], *samples[2] = { buff1, buff2 };
double rf_level_db[2];
int rc;
int i;
if (tx) {
/* encode and write */
count = sound_get_tosend(soundif, buffer_size);
if (count < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to get number of samples in buffer (rc = %d)!\n", count);
return;
}
if (count) {
dcf77_encode(dcf77, samples[0], count);
if (double_amplitude) {
for (i = 0; i < count; i++)
samples[1][i] = -samples[0][i];
}
rc = sound_write(soundif, samples, NULL, count, NULL, NULL, (double_amplitude) ? 2 : 1);
if (rc < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
return;
}
}
}
if (rx) {
/* read */
count = sound_read(soundif, samples, buffer_size, 1, rf_level_db);
if (count < 0) {
LOGP(DDSP, LOGL_ERROR, "Failed to read from audio device (rc = %d)!\n", count);
return;
}
/* decode */
dcf77_decode(dcf77, samples[0], count);
}
}
int main(int argc, char *argv[])
{
int rc, argi;
int buffer_size;
struct termios term, term_orig;
double begin_time, now, sleep;
char c;
logging_init();
/* handle options / config file */
add_options();
rc = options_config_file(argc, argv, "~/.osmocom/dcf77/dcf77.conf", handle_options);
if (rc < 0)
return 0;
argi = options_command_line(argc, argv, handle_options);
if (argi <= 0)
return argi;
if (dsp_samplerate < 192000) {
fprintf(stderr, "The sample rate must be at least 192000 to TX or RX 77.5 kHz. Quitting!\n");
goto error;
}
/* default to TX, if --tx and --rx was not set */
if (!tx && !rx)
tx = 1;
/* inits */
dcf77_init(fast_math);
/* size of dsp buffer in samples */
buffer_size = dsp_samplerate * dsp_buffer / 1000;
rc = soundif_open(dsp_device, dsp_samplerate, buffer_size);
if (rc < 0) {
printf("Failed to open sound for DCF77, use '-h' for help.\n");
goto error;
}
dcf77 = dcf77_create(dsp_samplerate, tx, rx, test_tone);
if (!dcf77) {
fprintf(stderr, "Failed to create \"DCF77\" instance. Quitting!\n");
goto error;
}
if (weather)
dcf77_set_weather(dcf77, weather_day, weather_night, extreme, rain, wind_dir, wind_bft, temperature_day, temperature_night);
/* no time stamp given, so we use our clock */
if (tx) {
if (timestamp < 0 && region < 0)
printf("No alternative time given, so you might not notice the difference between our transmission and the real DCF77 transmission.\n");
if (timestamp < 0)
timestamp = get_time();
if (region >= 0 && weather)
timestamp = dcf77_start_weather((time_t)timestamp, region, region_advance);
}
/* set real time prio */
if (rt_prio) {
struct sched_param schedp;
memset(&schedp, 0, sizeof(schedp));
schedp.sched_priority = rt_prio;
rc = sched_setscheduler(0, SCHED_RR, &schedp);
if (rc) {
fprintf(stderr, "Error setting SCHED_RR with prio %d\n", rt_prio);
goto error;
}
}
print_aaimage();
printf("DCF77 ready.\n");
/* prepare terminal */
tcgetattr(0, &term_orig);
term = term_orig;
term.c_lflag &= ~(ISIG|ICANON|ECHO);
term.c_cc[VMIN]=1;
term.c_cc[VTIME]=2;
tcsetattr(0, TCSANOW, &term);
signal(SIGINT, sighandler);
signal(SIGHUP, sighandler);
signal(SIGTERM, sighandler);
signal(SIGPIPE, sighandler);
soundif_start();
if (tx)
dcf77_tx_start(dcf77, (time_t)timestamp, fmod(timestamp, 1.0));
while (!quit) {
int w;
begin_time = get_time();
soundif_work(buffer_size);
do {
w = 0;
} while (w);
c = get_char();
switch (c) {
case 3:
printf("CTRL+c received, quitting!\n");
quit = 1;
break;
case 'w':
/* toggle wave display */
display_measurements_on(0);
display_wave_on(-1);
break;
case 'm':
/* toggle measurements display */
display_wave_on(0);
display_measurements_on(-1);
break;
default:
break;
}
display_measurements(dsp_interval / 1000.0);
now = get_time();
/* sleep interval */
sleep = ((double)dsp_interval / 1000.0) - (now - begin_time);
if (sleep > 0)
usleep(sleep * 1000000.0);
}
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
/* reset real time prio */
if (rt_prio > 0) {
struct sched_param schedp;
memset(&schedp, 0, sizeof(schedp));
schedp.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &schedp);
}
/* reset terminal */
tcsetattr(0, TCSANOW, &term_orig);
error:
/* destroy UK0 instances */
if (dcf77)
dcf77_destroy(dcf77);
soundif_close();
dcf77_exit();
options_free();
return 0;
}
void osmo_cc_set_log_cat(int __attribute__((unused)) cc_log_cat) {}

Some files were not shown because too many files have changed in this diff Show More