Browse Source

initial git import

master
Andreas Eversberg 6 years ago
commit
946c9ce10a
  1. 24
      .gitignore
  2. 3
      Makefile.am
  3. 11
      README
  4. 36
      configure.ac
  5. BIN
      docs/a-netz-display.jpg
  6. 80
      docs/a-netz.html
  7. BIN
      docs/a-netz.jpg
  8. BIN
      docs/a-netz_small.jpg
  9. BIN
      docs/alsa-mic.png
  10. BIN
      docs/alsa-mute.png
  11. BIN
      docs/alsa-select.png
  12. BIN
      docs/alsa.png
  13. BIN
      docs/b-netz-display.jpg
  14. 109
      docs/b-netz.html
  15. BIN
      docs/b-netz.jpg
  16. BIN
      docs/b-netz_small.jpg
  17. BIN
      docs/coil.jpg
  18. BIN
      docs/dummyload.jpg
  19. BIN
      docs/headphone.jpg
  20. 92
      docs/headset.html
  21. BIN
      docs/headset.jpg
  22. 31
      docs/index.html
  23. 59
      docs/install.html
  24. BIN
      docs/microphone.jpg
  25. BIN
      docs/pc+sound.jpg
  26. BIN
      docs/power.jpg
  27. BIN
      docs/receiver.jpg
  28. 144
      docs/setup.html
  29. BIN
      docs/transmitter.jpg
  30. BIN
      docs/trigger-1.jpg
  31. BIN
      docs/trigger-2.jpg
  32. BIN
      docs/trigger-3.jpg
  33. 151
      git-version-gen
  34. 3
      src/Makefile.am
  35. 16
      src/anetz/Makefile.am
  36. 458
      src/anetz/anetz.c
  37. 47
      src/anetz/anetz.h
  38. 329
      src/anetz/dsp.c
  39. 6
      src/anetz/dsp.h
  40. 59
      src/anetz/image.c
  41. 3
      src/anetz/image.h
  42. 177
      src/anetz/main.c
  43. 17
      src/bnetz/Makefile.am
  44. 5003
      src/bnetz/ansage-27.c
  45. 3
      src/bnetz/ansage-27.h
  46. 870
      src/bnetz/bnetz.c
  47. 99
      src/bnetz/bnetz.h
  48. 416
      src/bnetz/dsp.c
  49. 5
      src/bnetz/dsp.h
  50. 65
      src/bnetz/image.c
  51. 3
      src/bnetz/image.h
  52. 190
      src/bnetz/main.c
  53. 21
      src/common/Makefile.am
  54. 185
      src/common/besetztton.c
  55. 3
      src/common/besetztton.h
  56. 920
      src/common/call.c
  57. 26
      src/common/call.h
  58. 48
      src/common/cause.c
  59. 12
      src/common/cause.h
  60. 69
      src/common/debug.c
  61. 20
      src/common/debug.h
  62. 81
      src/common/filter.c
  63. 9
      src/common/filter.h
  64. 1073
      src/common/freiton.c
  65. 3
      src/common/freiton.h
  66. 100
      src/common/goertzel.c
  67. 5
      src/common/goertzel.h
  68. 114
      src/common/jitter.c
  69. 13
      src/common/jitter.h
  70. 93
      src/common/loss.c
  71. 15
      src/common/loss.h
  72. 22
      src/common/main.h
  73. 183
      src/common/main_common.c
  74. 347
      src/common/mncc.h
  75. 236
      src/common/mncc_sock.c
  76. 8
      src/common/mncc_sock.h
  77. 159
      src/common/samplerate.c
  78. 18
      src/common/samplerate.h
  79. 228
      src/common/sender.c
  80. 50
      src/common/sender.h
  81. 6
      src/common/sound.h
  82. 260
      src/common/sound_alsa.c
  83. 107
      src/common/timer.c
  84. 16
      src/common/timer.h

24
.gitignore vendored

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
config.guess
config.log
config.status
config.sub
configure
depcomp
install-sh
libcolorize.pc
libtool
ltmain.sh
missing
*.o
*.lo
*.la
.deps
.libs
m4
src/common/libcommon.a
src/anetz/anetz
src/bnetz/bnetz

3
Makefile.am

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src

11
README

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
This software implements base station protocol of classic mobile phones. With
radio transmitter and receiver connected to one sound card and a headset
connected to another sound card, it is possible to make and receive calls to
and from mobile phone. Currently supported networks:
* A-Netz base station
* B-Netz (ATF-1) base station
USE AT YOUR OWN RISK!

36
configure.ac

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT([abcnetz],
m4_esyscmd([./git-version-gen .tarball-version]),
[authors@their.domains])
AM_INIT_AUTOMAKE([dist-bzip2])
AC_CONFIG_MACRO_DIR([m4])
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl checks for programs
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
LT_INIT
dnl checks for header files
AC_HEADER_STDC
dnl Checks for typedefs, structures and compiler characteristics
AC_CANONICAL_HOST
PKG_CHECK_MODULES(ALSA, alsa >= 1.0)
AC_OUTPUT(
src/common/Makefile
src/anetz/Makefile
src/bnetz/Makefile
src/Makefile
Makefile)

BIN
docs/a-netz-display.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

80
docs/a-netz.html

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
<html>
<head>
<title>osmocom-analog</title>
</head>
<body>
<center><table border='0' cellspacing='0' cellpadding='0' width='816'><tr><td><font face="ARIAL" size='5'>
<h2><center>A-Netz</center></h2>
<center><img src="a-netz.jpg"/></center>
<p align='justify'>
Now run your base station on channel 30.
Tune the transmitter to 162.050 MHz and the receiver to 157.550.
You should tune the receiver to 164.050 first, to check if you hear the idle signal from the base station.
Then tune to actually uplink frequency 157.550 MHz.
</p>
<font size='4'><pre>
# src/anetz/anetz -k 30
...
anetz.c:170 info : Entering IDLE state, sending 2280 Hz tone.
Base station ready, please tune transmitter to 162.050 MHz and receiver to 157.550 MHz.
on-hook: ..... (enter 0..9 or d=dial)
</pre></font>
<center><img src="a-netz-display.jpg"/></center>
<p align='justify'>
Turn on you phone and wait for it to warm up (requires about half a minute).
Tune the phone to channel 30 and switch on your transmitter for the base station.
The phone should indicate a (green) light, to show idle channel.
If there is no green light, increase the level of your FM signal on the transmitter.
Or if you can't increase the audio level on the transmitter, do it with 'alsamixer'.
</p>
<font size='4'><pre>
anetz.c:244 info : Received 1750 Hz calling signal from mobile station, sending 1750 Hz acknowledge signal.
anetz.c:256 info : 1750 Hz signal from mobile station is gone, stopping acknowledge signal.
call.c:574 info : Incomming call from '' to 'operator'
anetz.c:272 info : Received 1750 Hz release signal from mobile station, sending idle signal.
anetz.c:201 info : Entering IDLE state, sending 2280 Hz tone.
call.c:695 info : Call has been released with cause=16
call disconnected: hangup (enter h=hangup)
</pre></font>
<p align='justify'>
When you pick up the phone, the phone transmits a 1750 Hz calling tone.
On reception, the base station then transmits a 1750 Hz acknowledge ton.
After that the call is establised.
After establishment, you can use the headset, if present, for speech communication with the phone.
On hangup, the phone transmit a 1750 Hz hangup tone.
Then the base station returns to idle again.
Be sure that the phone turns off the transmitter and indicates the (green) light.
</p>
<p align='justify'>
To call to the phone, be sure that your transmitter transmits loud enough to send 4 sine waves at once.
Enter the last 5 digits of the phone's number and press 'd' to dial.
If you listen to the transmit signal, you should hear 4 low pitched tones at once.
The phone should now stop the idle light and indicate an incomming call.
There is no acknowledgement from the phone until you pick up the call.
If the phone does not indicate an incomming call, increase the volume of the transmit signal, but be sure not to overdrive it.
Also be sure that you are actually dialing the right number, so the base station generates the correct paging tones.
</p>
<p align='justify'>
Instead of transmitting all 4 tones at once, they can be transmitted after each other.
Each tone is playes for a short time.
After the last tone has been played, base station starts again with the first tone.
My phone also responds to a call, even if the tones cycle rather than sent simultaniously.
In this case the level of each tone is four times highter (+6 dB).
Add command line option "-P 50" to send each tone for 50 milliseconds.
Try something between 20-100 milliseconds, if the phone still doesn't ring.
</p>
[<a href="index.html">Back to main page</a>]
</font></td></tr></table></center>
</body>
</html>

BIN
docs/a-netz.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

BIN
docs/a-netz_small.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

BIN
docs/alsa-mic.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/alsa-mute.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/alsa-select.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/alsa.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/b-netz-display.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

109
docs/b-netz.html

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
<html>
<head>
<title>osmocom-analog</title>
</head>
<body>
<center><table border='0' cellspacing='0' cellpadding='0' width='816'><tr><td><font face="ARIAL" size='5'>
<h2><center>B-Netz</center></h2>
<center><img src="b-netz.jpg"/></center>
<p align='justify'>
Before testing this software, power on your B-Netz.
Refer to the manual how to dial a number.
Start dialing and after some seconds you should hear a busy signal.
This means that the phone sweeps over all channels to find a base startion.
If no free base station is found, you will get a busy signal.
</p>
<center><img src="b-netz-display.jpg"/></center>
<p align='justify'>
Now run your base station on channel 1.
Tune the transmitter to 153.010 MHz and the receiver to 148.410.
You should tune the receiver to 153.010 first, to check if you hear the idle signal from the base station.
Then tune to actually uplink frequency 148.410 MHz.
</p>
<font size='4'><pre>
# src/bnetz/bnetz -k 1
...
bnetz.c:316 info : Entering IDLE state, sending 'Gruppenfreisignal' 2 on channel 1.
Base station ready, please tune transmitter to 153.010 MHz and receiver to 148.410 MHz.
To call phone, switch transmitter (using pilot signal) to 153.370 MHz.
on-hook: ..... (enter 0..9 or d=dial)
</pre></font>
<p align='justify'>
Now dial again on the phone and watch the base station receiving the call:
</p>
<font size='4'><pre>
bnetz.c:471 info : Received signal 'Kanalbelegung' from mobile station, sending signal 'Wahlabruf'.
bnetz.c:561 info : Received station id from mobile phone: 50993
bnetz.c:569 info : Received number from mobile phone: 800330100
bnetz.c:571 info : Sending station id back to phone: 50993.
bnetz.c:631 info : Dialing complete 50993-&gt;0800330100, call established.
bnetz.c:637 info : Setup call to network.
call.c:574 info : Incomming call from '50993' to '0800330100'
bnetz.c:669 notice : Received 'Schlusssignal' from mobile station
bnetz.c:352 info : Entering IDLE state, sending 'Gruppenfreisignal' 2.
call.c:695 info : Call has been released with cause=16
</pre></font>
<p align='justify'>
The first thing the phone does is to find the channel 1.
Then it transmits a signal tone, called 'Kanalbelegung'.
The base station responds and sends a signal tone, called 'Wahlabruf'.
Then the phone sends caller ID + number.
The base station replies the caller ID to prevent false transmissions.
After establishment, you can use the headset, if present, for speech communication with the phone.
If you hangup the phone, the call gets released by a message, called 'Schlusssignal'.
The base station returns to idle.
</p>
<p align='justify'>
In order to call the phone from the base station, you need to transmit channel 19.
Your transmitter must tune to 153.370 MHz in order to page the phone.
The phones listens to incomming signals from the base station.
In order to transmit on channel 19, you may use a second transmitter or re-tune your single transmitter.
There are many ways todo that, but it is actually up to your own how to couple it and how to control your transmitter.
I use an optocoupler to tell my transmitter to switch to channel 19.
</p>
<center><img src="trigger-1.jpg"/></center>
<br>
<center><img src="trigger-2.jpg"/><img src="trigger-3.jpg"/></center>
<p align='justify'>
I measure about 3 Volts peak on the ouput of the USB chip I use.
Since my optocoupler triggers at arround 1 Volts, I have two Volts on the Resistor, which results in 10 mA current.
In order to check and change the voltage, use '-P positive' or '-P negative' option to select trigger level on one audio channel.
Run the base station and enter a 5 digit number.
Measure the voltage on both audio output channels.
Once you press 'd' for dialing, the base station triggers the channel using positive or negative level.
See if and where the voltage changes.
The trigger is just about two seconds long, so check your meter quickly after pressing 'd'.
Once the base station timed out, press 'h' for hangup and try again.
</p>
<font size='4'><pre>
./bnetz/bnetz -k 1 -P positive
...
on-hook: 55555 (enter 0..9 or d=dial)
call.c:437 info : Outgoing call to 55555
bnetz.c:757 info : Call to mobile station, paging station id '55555'
bnetz.c:375 info : Entering paging state (try 1), sending 'Selektivruf' to '55555'.
bnetz.c:411 info : Paging mobile station 55555 complete, waiting for answer.
</pre></font>
<p align='justify'>
Now again it is up to your own to make the transmitter switch to channel 19 on trigger level.
If you use a second transmitter, use the tigger to press the PTT button.
</p>
[<a href="index.html">Back to main page</a>]
</font></td></tr></table></center>
</body>
</html>

BIN
docs/b-netz.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

BIN
docs/b-netz_small.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
docs/coil.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

BIN
docs/dummyload.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
docs/headphone.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

92
docs/headset.html

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
<html>
<head>
<title>osmocom-analog</title>
</head>
<body>
<center><table border='0' cellspacing='0' cellpadding='0' width='816'><tr><td><font face="ARIAL" size='5'>
<h2><center>Connecting headset</center></h2>
<p align='justify'>
You need a headset and a second audio device.
I use a cheap 'LogiLink' USB sound adapter and a Headset with microphone.
</p>
<center><img src="headset.jpg"/></center>
<p align='justify'>
You may use an USB sound adapter and a headset or a USB headset with built-in sound card.
Check 'alsamixer' if the sound adapter has been detected.
Press 'F6' to select the headset or the sound adapter connected to the headset.
</p>
<center><img src="alsa-select.png"/></center>
<p align='justify'>
Mute the microphone, so you wount hear yourself if you speak into the microphone.
Be sure to press 'F3' to change into Playback view.
Mute playback and not recording from microphone.
To mute, select he microphone with the cursor keys and press 'm'.
</p>
<center><img src="alsa-mute.png"/></center>
<p align='justify'>
To get the device, run 'arecord -l' and you get the following list, if you have two sound cards:
</p>
<font size='4'><pre>
# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Intel [HDA Intel], device 0: ALC269VB Analog [ALC269VB Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: Set [C-Media USB Headphone Set], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
</pre></font>
<p align='justify'>
You see your card 0 and device 0: This should be the sound card you connect to your radio equipment.
There is also the second sound device: In my case it is card 2 and device 0.
Connect the second sound device to your headset and use '-c hw:2,0" (card 2, device 0) to tell the base station to select this sound device for your headset.
</p>
<p align='justify'>
To calibrate audio level, run some music player and adjust output volume, so you hear the music at regular speech volume.
Use 'alsamixer' to change the output volume of your second sound card.
This calibartion must be done before calibrating the microphone.
To calibarte input level (mircrophone), run the B-Netz base station with loopback test 3.
</p>
<font size='4'><pre>
# src/bnetz/bnetz -L 3 -c hw:2,0
bnetz.c:268 info : Entering IDLE state, sending 'Gruppenfreisignal' 2 on channel 1.
Base station ready, please tune transmitter to 153.010 MHz and receiver to 148.410 MHz.
To call phone, switch transmitter using pilot tone to 153.370 MHz
</pre></font>
<p align='justify'>
Now you should hear yourself when you speak into the microphone.
You should also notice a short delay, but this is normal.
Now it is time to calibrate the microphone:
Use 'alsamixer' to adjust input level, so that you hear your voice at regular speech volume.
Be sure to select Capture view by pressing 'F4'.
</p>
<center><img src="alsa-mic.png"/></center>
<p align='justify'>
I also had to mute the "Auto Gain Control", as found in the Playback View by pressing 'F4'.
I muted it using 'm' key.
</p>
<p align='justify'>
Finally store the settings using "alsactl store" command.
Do this whenever you want to keep your adjustments.
</p>
[<a href="index.html">Back to main page</a>]
</font></td></tr></table></center>
</body>
</html>

BIN
docs/headset.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

31
docs/index.html

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
<html>
<head>
<link href="style.css" rel="stylesheet" type="text/css" />
<title>osmocom-analog</title>
</head>
<body>
<center><table border='0' cellspacing='0' cellpadding='0' width='816'><tr><td><font face="ARIAL" size='5'>
<h2><center>osmocom-analog</center></h2>
<center><img src="a-netz_small.jpg"/><img src="b-netz_small.jpg"/></center>
<br><br>
<center>
A base station emulator for classic mobile networks. All these networks use analog voice transmission. The signalling is done by tones (A-Netz) or FSK modulated digital messages.
</center>
<center>
<ul>
<li><a href="install.html">Software installation</a></li>
<li><a href="setup.html">Radio setup</a></li>
<li><a href="headset.html">Connecting headset</a></li>
<li><a href="a-netz.html">Using A-Netz phone</a></li>
<li><a href="b-netz.html">Using B-Netz phone</a></li>
</ul>
</center>
</font></td></tr></table></center>
</body>
</html>

59
docs/install.html

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
<html>
<head>
<title>osmocom-analog</title>
</head>
<body>
<center><table border='0' cellspacing='0' cellpadding='0' width='816'><tr><td><font face="ARIAL" size='5'>
<h2><center>Software installation</center></h2>
<p align='justify'>
To run this software, you need a linux PC with development environment (gcc compiler).
At least one Alsa sound interfaces is required.
Two sound interfaces are required to talk and listen trough the base station using a headset with microphone.
</p>
<p align='justify'>
If you want to install from GIT repository, run 'autoreconf -if' inside GIT repository first:
</p>
<font size='4'><pre>
# autoreconf -if
</pre></font>
<p align='justify'>
Unpack the archive and change to its directory. Then compile:
</p>
<font size='4'><pre>
# ./configure
# make
</pre></font>
<p align='justify'>
At your option:
</p>
<font size='4'><pre>
# make install
</pre></font>
<p align='justify'>
Now you are ready for a quick test:
</p>
<font size='4'><pre>
# src/bnetz/bnetz -k 1 -L 2
bnetz.c:268 info : Entering IDLE state, sending 'Gruppenfreisignal' 2 on channel 1.
Base station ready, please tune transmitter to 153.010 MHz and receiver to 148.410 MHz.
To call phone, switch transmitter using pilot tone to 153.370 MHz
</pre></font>
<p align='justify'>
Do you hear the whisteling sound on your speaker/headset? Now you can continue with the radio setup.
</p>
[<a href="index.html">Back to main page</a>]
</font></td></tr></table></center>
</body>
</html>

BIN
docs/microphone.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
docs/pc+sound.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

BIN
docs/power.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
docs/receiver.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

144
docs/setup.html

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
<html>
<head>
<title>osmocom-analog</title>
</head>
<body>
<center><table border='0' cellspacing='0' cellpadding='0' width='816'><tr><td><font face="ARIAL" size='5'>
<h2><center>Radio setup</center></h2>
<p align='justify'>
To emulate a base station, you need a linux machine with sound interface. The interface must be supported by <a href="http://www.alsa-project.org">Alsa</a> kernel driver.
</p>
<center><img src="pc+sound.jpg"/></center>
<p align='justify'>
Use a radio transmitter for 2-meter band to transmit to the phone (downlink).
An amateur radio can be used, but be sure it is not limited to amateur radio frequencies.
For A-Netz the transmitter must be able to transmit arround 162 MHz.
For B-Netz the transmitter must be able to transmit arround 153 MHz.
</p>
<center><img src="transmitter.jpg"/></center>
<p align='justify'>
Use radio receiver for 2-methers band to receive from the phone. (uplink)
You cannot use the transmitter as well, since you need to transmit and receive simultaniously.
For A-Netz the receiver must be able to receive arround 162 MHz and 157 MHz.
For B-Netz the receiver must be able to receive arround 153 MHz and 148 MHz.
The reason why the receiver must also receive on the transmitter frequency (downlink) is because you need to make a test loop for calibration process.
This is explained below.
</p>
<center><img src="receiver.jpg"/></center>
<p align='justify'>
In order to keep RF emission low, use a dummy load for lab test.
Use two seperated antennas for outside use of the mobile phone.
Connect one dummy load to the transmitter and another one to the mobile phone's antenna connector.
</p>
<center><img src="dummyload.jpg"/></center>
<p align='justify'>
For the radios and the phone, I use a sufficient power supply.
Especially for old A-Netz phones, be sure to have something close to 13.8 Volts and 5 Ampere or even more, depending on your phone.
My phone did not work correctly with a standard 12 Volts regulated power supply.
Amateur radio power supplies are made for 13.8 Volts.
Also you can use a fully charged car battery with a sufficient fuse.
In my case I use a modified ATX-2 power supply with 13.8 Volts and a built-in overcurrent protection.
</p>
<center><img src="power.jpg"/></center>
<p align='justify'>
And finally you need a classic working phone.
Be sure to connect the phone to a dummy load and the transmitter to another one.
</p>
<center><img src="b-netz-display.jpg"/></center>
<p align='justify'>
There are two ways to couple the receiver and transmitter with your sound card. You can use a headset and a microphone. The pro is that you can monitor what you actually transmitting and receiving. The problem is that you might get audio from RX side mixed with TX side. You get echo and the base station may detect self-generated tones. This might cause malfuntion to the base station software. Better you put the microphone inside a headset and keep TX and RX side away from each other.
</p>
<center><img src="microphone.jpg"/></center>
<p align='justify'>
The better way is to use inductive coil and resistors.
How to couple your sound card with radios is beyond the scope of this document.
Because you have radios and all the electronics that is required, I assume you have the knowledge to do it right.
</p>
<center><img src="coil.jpg"/></center>
<p align='justify'>
To adjust input and output levels of your sound card, run 'alsamixer'.
</p>
<center><img src="alsa.png"/></center>
<p align='justify'>
To avoid echo of audio input (mic), mute the input (select item and press 'm').
We want to capture microphone, but not echo it back to the audio output.
Also we want audio on line/headset output and capture from microphone imput.
</p>
<p align='justify'>
Now we want to calibrate transmitter and receiver audio level.
Run the B-Netz base station in loopback test mode (-L 2).
Even if you plan to setup A-Netz base station, use B-Netz base station for calibration.
</p>
<font size='4'><pre>
# src/bnetz/bnetz -k 1 -L 2
bnetz.c:268 info : Entering IDLE state, sending 'Gruppenfreisignal' 2 on channel 1.
Base station ready, please tune transmitter to 153.010 MHz and receiver to 148.410 MHz.
To call phone, switch transmitter using pilot tone to 153.370 MHz
</pre></font>
<p align='justify'>
Tune your transmitter AND reciever to 153.010 MHz.
Press the PTT button on you transmitter and check if you hear your voice at a normal level from the receiver.
Then connect the audio output (line out) to your transmitter or couple it with a headphone.
You should hear now the whistle sound clearly on the receiver.
Adjust the audio output, so that the tone is not overdriven but loud enough to match any regular received voice.
</p>
<p align='justify'>
Now connect the audio input (microphone) to your receiver or couple it with a microphone to the speaker of your receiver.
Enable the transmitter. (PTT button)
You should now see the signal beeing decoded by the base station:
</p>
<font size='4'><pre>
bnetz.c:474 notice : Received telegramm 'Ziffer 2'. (quality=99% level=33%)
bnetz.c:478 notice : Round trip delay is 0.053 seconds
bnetz.c:474 notice : Received telegramm 'Ziffer 3'. (quality=98% level=33%)
bnetz.c:478 notice : Round trip delay is 0.054 seconds
bnetz.c:474 notice : Received telegramm 'Ziffer 4'. (quality=99% level=31%)
bnetz.c:478 notice : Round trip delay is 0.053 seconds
bnetz.c:474 notice : Received telegramm 'Ziffer 5'. (quality=97% level=30%)
bnetz.c:478 notice : Round trip delay is 0.054 seconds
</pre></font>
<p align='justify'>
Adjust the input level. (using 'alsamixer')
Try to maintain an input level arround 30%.
The quality should be 90% or better.
</p>
<p align='justify'>
Now you have connected the base station to your radio eqipment and roughly adjusted the levels.
</p>
<p align='justify'>
Finally store the settings using "alsactl store" command.
Do this whenever you want to keep your adjustments.
</p>
[<a href="index.html">Back to main page</a>]
</font></td></tr></table></center>
</body>
</html>

BIN
docs/transmitter.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

BIN
docs/trigger-1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
docs/trigger-2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
docs/trigger-3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

151
git-version-gen

@ -0,0 +1,151 @@ @@ -0,0 +1,151 @@
#!/bin/sh
# Print a version string.
scriptversion=2010-01-28.01
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
#
# 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/>.
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
# It may be run two ways:
# - from a git repository in which the "git describe" command below
# produces useful output (thus requiring at least one signed tag)
# - from a non-git-repo directory containing a .tarball-version file, which
# presumes this script is invoked like "./git-version-gen .tarball-version".
# In order to use intra-version strings in your project, you will need two
# separate generated version string files:
#
# .tarball-version - present only in a distribution tarball, and not in
# a checked-out repository. Created with contents that were learned at
# the last time autoconf was run, and used by git-version-gen. Must not
# be present in either $(srcdir) or $(builddir) for git-version-gen to
# give accurate answers during normal development with a checked out tree,
# but must be present in a tarball when there is no version control system.
# Therefore, it cannot be used in any dependencies. GNUmakefile has
# hooks to force a reconfigure at distribution time to get the value
# correct, without penalizing normal development with extra reconfigures.
#
# .version - present in a checked-out repository and in a distribution
# tarball. Usable in dependencies, particularly for files that don't
# want to depend on config.h but do want to track version changes.
# Delete this file prior to any autoconf run where you want to rebuild
# files to pick up a version string change; and leave it stale to
# minimize rebuild time after unrelated changes to configure sources.
#
# It is probably wise to add these two files to .gitignore, so that you
# don't accidentally commit either generated file.
#
# Use the following line in your configure.ac, so that $(VERSION) will
# automatically be up-to-date each time configure is run (and note that
# since configure.ac no longer includes a version string, Makefile rules
# should not depend on configure.ac for version updates).
#
# AC_INIT([GNU project],
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
# [bug-project@example])
#
# Then use the following lines in your Makefile.am, so that .version
# will be present for dependencies, and so that .tarball-version will
# exist in distribution tarballs.
#
# BUILT_SOURCES = $(top_srcdir)/.version
# $(top_srcdir)/.version:
# echo $(VERSION) > $@-t && mv $@-t $@
# dist-hook:
# echo $(VERSION) > $(distdir)/.tarball-version
case $# in
1) ;;
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
esac
tarball_version_file=$1
nl='
'
# First see if there is a tarball-only version file.
# then try "git describe", then default.
if test -f $tarball_version_file
then
v=`cat $tarball_version_file` || exit 1
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test -z "$v" \
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
fi
if test -n "$v"
then
: # use $v
elif
v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|| git describe --abbrev=4 HEAD 2>/dev/null` \
&& case $v in
[0-9]*) ;;
v[0-9]*) ;;
*) (exit 1) ;;
esac
then
# Is this a new git that lists number of commits since the last
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
case $v in
*-*-*) : git describe is okay three part flavor ;;
*-*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
# of git describe.
vtag=`echo "$v" | sed 's/-.*//'`
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
;;
esac
# Change the first '-' to a '.', so version-comparing tools work properly.
# Remove the "g" in git describe's output string, to save a byte.
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
else
v=UNKNOWN
fi
v=`echo "$v" |sed 's/^v//'`
# Don't declare a version "dirty" merely because a time stamp has changed.
git status > /dev/null 2>&1
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
case "$dirty" in
'') ;;
*) # Append the suffix only if there isn't one already.
case $v in
*-dirty) ;;
*) v="$v-dirty" ;;
esac ;;
esac
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
echo "$v" | tr -d '\012'
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

3
src/Makefile.am

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = common anetz bnetz

16
src/anetz/Makefile.am

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
AM_CPPFLAGS = -Wall -g $(all_includes)
bin_PROGRAMS = \
anetz
anetz_SOURCES = \
anetz.c \
dsp.c \
image.c \
main.c
anetz_LDADD = \
$(COMMON_LA) \
$(ALSA_LIBS) \
$(top_builddir)/src/common/libcommon.a \
-lm

458
src/anetz/anetz.c

@ -0,0 +1,458 @@ @@ -0,0 +1,458 @@
/* A-Netz protocol handling
*
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
* All Rights Reserved
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "../common/debug.h"
#include "../common/timer.h"
#include "../common/call.h"
#include "../common/cause.h"
#include "anetz.h"
#include "dsp.h"
/* Call reference for calls from mobile station to network
This offset of 0x400000000 is required for MNCC interface. */
static int new_callref = 0x40000000;
/* Timers */
#define PAGING_TO 30 /* Nach dieser Zeit ist der Operator genervt... */
/* Convert channel number to frequency number of base station.
Set 'unterband' to 1 to get frequency of mobile station. */
double anetz_kanal2freq(int kanal, int unterband)
{
double freq = 162.050;
freq += (kanal - 30) * 0.050;
if (kanal >= 45)
freq += 6.800;
if (unterband)
freq -= 4.500;
return freq;
}
/* Convert paging frequency number to to frequency. */
static double anetz_dauerruf_frq(int n)
{
if (n < 1 || n > 30)
abort();
return 337.5 + (double)n * 15.0;
}
/* Table with frequency sets to use for paging. */
static struct anetz_dekaden {
int dekade[4];
} anetz_gruppenkennziffer[10] = {
{ { 2, 2, 3, 3 } }, /* 0 */
{ { 1, 1, 2, 2 } }, /* 1 */
{ { 1, 1, 3, 3 } }, /* 2 */
{ { 1, 1, 2, 3 } }, /* 3 */
{ { 1, 2, 2, 3 } }, /* 4 */
{ { 1, 2, 3, 3 } }, /* 5 */
{ { 1, 1, 1, 2 } }, /* 6 */
{ { 1, 1, 1, 3 } }, /* 7 */
{ { 2, 2, 2, 3 } }, /* 8 */
{ { 1, 2, 2, 2 } }, /* 9 */
};
/* Takes the last 5 digits of a number and returns 4 paging tones.
If number is invalid, NULL is returned. */
static double *anetz_nummer2freq(const char *nummer)
{
int f[4];
static double freq[4];
int *dekade;
int i, j, digit;
/* get last 5 digits */
if (strlen(nummer) < 5) {
PDEBUG(DANETZ, DEBUG_ERROR, "Number must have at least 5 digits!\n");
return NULL;
}
nummer = nummer + strlen(nummer) - 5;
/* check for digits */
for (i = 0; i < 4; i++) {
if (nummer[i] < '0' || nummer[i] > '9') {
PDEBUG(DANETZ, DEBUG_ERROR, "Number must have digits 0..9!\n");
return NULL;
}
}
/* get decade */
dekade = anetz_gruppenkennziffer[*nummer - '0'].dekade;
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 */
for (i = 0; i < 4; i++) {
digit = nummer[i] - '0';
if (digit == 0)
digit = 10;
f[i] = (dekade[i] - 1) * 10 + digit;
freq[i] = anetz_dauerruf_frq(f[i]);
for (j = 0; j < i; j++) {
if (dekade[i] == dekade[j] && nummer[i] == nummer[j]) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Number invalid, digit #%d and #%d of '%s' use same frequency F%d=%.1f of same decade %d!\n", i+1, j+1, nummer, f[i], freq[i], dekade[i]);
return NULL;
}
}
}
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;
}
/* global init */
int anetz_init(void)
{
return 0;
}
static void anetz_timeout(struct timer *timer);
/* Create transceiver instance and link to a list. */
int anetz_create(const char *sounddev, int samplerate, int kanal, int loopback, double loss_volume)
{
anetz_t *anetz;
int rc;
if (kanal < 30 || kanal > 63) {
PDEBUG(DANETZ, DEBUG_ERROR, "Channel ('Kanal') number %d invalid.\n", kanal);
return -EINVAL;
}
anetz = calloc(1, sizeof(anetz_t));
if (!anetz) {
PDEBUG(DANETZ, DEBUG_ERROR, "No memory!\n");
return -EIO;
}
PDEBUG(DANETZ, DEBUG_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate);
/* init general part of transceiver */
rc = sender_create(&anetz->sender, sounddev, samplerate, kanal, loopback, loss_volume, -1);
if (rc < 0) {
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init 'Sender' processing!\n");
goto error;
}
/* init audio processing */
rc = dsp_init_sender(anetz);
if (rc < 0) {
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init signal processing!\n");
goto error;
}
/* go into idle state */
PDEBUG(DANETZ, DEBUG_INFO, "Entering IDLE state, sending 2280 Hz tone.\n");
anetz->state = ANETZ_FREI;
anetz->dsp_mode = DSP_MODE_TONE;
timer_init(&anetz->timer, anetz_timeout, anetz);
return 0;
error:
anetz_destroy(&anetz->sender);
return rc;
}
/* Destroy transceiver instance and unlink from list. */
void anetz_destroy(sender_t *sender)
{
anetz_t *anetz = (anetz_t *) sender;
PDEBUG(DANETZ, DEBUG_DEBUG, "Destroying 'A-Netz' instance for 'Kanal' = %d.\n", sender->kanal);
timer_exit(&anetz->timer);
dsp_cleanup_sender(anetz);
sender_destroy(&anetz->sender);
free(sender);
}
/* Abort connection towards mobile station by sending idle tone. */
static void anetz_go_idle(anetz_t *anetz)
{
timer_stop(&anetz->timer);
PDEBUG(DANETZ, DEBUG_INFO, "Entering IDLE state, sending 2280 Hz tone.\n");
anetz->state = ANETZ_FREI;
anetz->dsp_mode = DSP_MODE_TONE;
anetz->station_id[0] = '\0';
}
/* Enter paging state and transmit 4 paging tones. */
static void anetz_page(anetz_t *anetz, const char *dial_string, double *freq)
{
PDEBUG(DANETZ, DEBUG_INFO, "Entering paging state, sending 'Selektivruf' to '%s'.\n", dial_string);
anetz->state = ANETZ_ANRUF;
anetz->dsp_mode = DSP_MODE_PAGING;
dsp_set_paging(anetz, freq);
strcpy(anetz->station_id, dial_string);
timer_start(&anetz->timer, PAGING_TO);
}
/* Loss of signal was detected, release active call. */
void anetz_loss_indication(anetz_t *anetz)
{
if (anetz->state == ANETZ_GESPRAECH) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Detected loss of signal, releasing.\n");
anetz_go_idle(anetz);
call_in_release(anetz->sender.callref, CAUSE_TEMPFAIL);
anetz->sender.callref = 0;
}
}
/* A continuous tone was detected or is gone. */
void anetz_receive_tone(anetz_t *anetz, int tone)
{
if (tone >= 0)
PDEBUG(DANETZ, DEBUG_DEBUG, "Received contiuous %d Hz tone.\n", (tone) ? 1750 : 2280);
else
PDEBUG(DANETZ, DEBUG_DEBUG, "Continuous tone is gone.\n");
if (anetz->sender.loopback) {
return;
}
switch (anetz->state) {
case ANETZ_FREI:
/* initiate call on calling tone */
if (tone == 1) {
PDEBUG(DANETZ, DEBUG_INFO, "Received 1750 Hz calling signal from mobile station, removing idle signal.\n");
anetz->state = ANETZ_GESPRAECH;
anetz->dsp_mode = DSP_MODE_SILENCE;
break;
}
break;
case ANETZ_GESPRAECH:
/* throughconnect speech when calling/answer tone is gone */
if (tone != 1) {
if (!anetz->sender.callref) {
int callref = ++new_callref;
int rc;
PDEBUG(DANETZ, DEBUG_INFO, "1750 Hz signal from mobile station is gone, setup call.\n");
rc = call_in_setup(callref, anetz->station_id, "0");
if (rc < 0) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc);
anetz_go_idle(anetz);
break;
}
anetz->sender.callref = callref;
} else {
PDEBUG(DANETZ, DEBUG_INFO, "1750 Hz signal from mobile station is gone, answer call.\n");
call_in_answer(anetz->sender.callref, anetz->station_id);
}
anetz->dsp_mode = DSP_MODE_AUDIO;
}
/* release call */
if (tone == 1) {
PDEBUG(DANETZ, DEBUG_INFO, "Received 1750 Hz release signal from mobile station, sending idle signal.\n");
anetz_go_idle(anetz);
call_in_release(anetz->sender.callref, CAUSE_NORMAL);
anetz->sender.callref = 0;
break;
}
break;
case ANETZ_ANRUF:
/* answer call on answer tone */
if (tone == 1) {
PDEBUG(DANETZ, DEBUG_INFO, "Received 1750 Hz answer signal from mobile station, removing paging tones.\n");
timer_stop(&anetz->timer);
anetz->state = ANETZ_GESPRAECH;
anetz->dsp_mode = DSP_MODE_SILENCE;
break;
}
default:
break;
}
}
/* Timeout handling */
static void anetz_timeout(struct timer *timer)
{
anetz_t *anetz = (anetz_t *)timer->priv;
switch (anetz->state) {
case ANETZ_ANRUF:
PDEBUG(DANETZ, DEBUG_NOTICE, "Timeout while waiting for answer, releasing.\n");
anetz_go_idle(anetz);
call_in_release(anetz->sender.callref, CAUSE_NOANSWER);
anetz->sender.callref = 0;
break;
default:
break;
}
}
/* Call control starts call towards mobile station. */
int call_out_setup(int callref, char *dialing)
{
sender_t *sender;
anetz_t *anetz;
double *freq;
/* 1. check if number is invalid, return INVALNUMBER */
if (strlen(dialing) > 7) {
inval:
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing call to invalid number '%s', rejecting!\n", dialing);
return -CAUSE_INVALNUMBER;
}
freq = anetz_nummer2freq(dialing);
if (!freq)
goto inval;
/* 2. check if given number is already in a call, return BUSY */
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
if (strlen(anetz->station_id) < 5)
continue;
if (!strcmp(anetz->station_id + strlen(anetz->station_id) - 5, dialing + strlen(dialing) - 5))
break;
}
if (sender) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
return -CAUSE_BUSY;
}
/* 3. check if all senders are busy, return NOCHANNEL */
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
if (anetz->state == ANETZ_FREI)
break;
}
if (!sender) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
return -CAUSE_NOCHANNEL;
}
PDEBUG(DANETZ, DEBUG_INFO, "Call to mobile station, paging with tones: %.1f %.1f %.1f %.1f\n", freq[0], freq[1], freq[2], freq[3]);
/* 4. trying to page mobile station */
sender->callref = callref;
anetz_page(anetz, dialing, freq);
call_in_alerting(callref);
return 0;
}
/* Call control sends disconnect (with tones).
* An active call stays active, so tones and annoucements can be received
* by mobile station.
*/
void call_out_disconnect(int callref, int cause)
{
sender_t *sender;
anetz_t *anetz;
PDEBUG(DANETZ, DEBUG_INFO, "Call has been disconnected by network.\n");
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
if (sender->callref == callref)
break;
}
if (!sender) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n");
call_in_release(callref, CAUSE_INVALCALLREF);
return;
}
/* Release when not active */
if (anetz->state == ANETZ_GESPRAECH)
return;
switch (anetz->state) {
case ANETZ_ANRUF:
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing disconnect, during alerting, going idle!\n");
anetz_go_idle(anetz);
break;
default:
break;
}
call_in_release(callref, cause);
sender->callref = 0;
}
/* Call control releases call toward mobile station. */
void call_out_release(int callref, int cause)
{
sender_t *sender;
anetz_t *anetz;
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;
if (sender->callref == callref)
break;
}
if (!sender) {
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing release, but no callref!\n");
/* don't send release, because caller already released */
return;
}
sender->callref = 0;
switch (anetz->state) {
case ANETZ_GESPRAECH:
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing release, during call, going idle!\n");
anetz_go_idle(anetz);
break;
case ANETZ_ANRUF:
PDEBUG(DANETZ, DEBUG_NOTICE, "Outgoing release, during alerting, going idle!\n");
anetz_go_idle(anetz);
break;
default:
break;
}
}
/* Receive audio from call instance. */
void call_rx_audio(int callref, int16_t *samples, int count)
{
sender_t *sender;
anetz_t *anetz;
for (sender = sender_head; sender; sender = sender->next) {
anetz = (anetz_t *) sender;
if (sender->callref == callref)
break;
}
if (!sender)
return;
if (anetz->dsp_mode == DSP_MODE_AUDIO) {
int16_t up[count * anetz->sender.srstate.factor];
count = samplerate_upsample(&anetz->sender.srstate, samples, count, up);
jitter_save(&anetz->sender.audio, up, count);
}
}

47
src/anetz/anetz.h

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
#include "../common/sender.h"
enum dsp_mode {
DSP_MODE_SILENCE, /* send silence to transmitter, block audio from receiver */
DSP_MODE_AUDIO, /* stream audio */
DSP_MODE_TONE, /* send 2280 Hz tone 0 */
DSP_MODE_PAGING, /* send four paging tones */
};
enum anetz_state {
ANETZ_FREI, /* sending 2280 Hz tone */
ANETZ_GESPRAECH, /* during conversation */
ANETZ_ANRUF, /* phone is paged */
};
typedef struct anetz {
sender_t sender;
/* sender's states */
enum anetz_state state; /* current sender's state */
char station_id[8]; /* current station ID */
struct timer timer;
/* dsp states */
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
int fsk_tone_coeff; /* coefficient k = 2*cos(2*PI*f/samplerate), k << 15 */
int samples_per_chunk; /* how many samples lasts one chunk */
int16_t *fsk_filter_spl; /* array with samples_per_chunk */
int fsk_filter_pos; /* current sample position in filter_spl */
int tone_detected; /* what tone has been detected */
int tone_count; /* how long has that tone been detected */
double tone_phaseshift256; /* how much the phase of sine wave changes per sample */
double tone_phase256; /* current phase */
double paging_phaseshift256[4];/* how much the phase of sine wave changes per sample */
double paging_phase256[4]; /* current phase */
int paging_tone; /* current tone (0..3) in sequenced mode */
int paging_count; /* current sample count of tone in seq. mode */
} anetz_t;
double anetz_kanal2freq(int kanal, int unterband);
int anetz_init(void);
int anetz_create(const char *sounddev, int samplerate, int kanal, int loopback, double loss_volume);
void anetz_destroy(sender_t *sender);
void anetz_loss_indication(anetz_t *anetz);
void anetz_receive_tone(anetz_t *anetz, int bit);

329
src/anetz/dsp.c

@ -0,0 +1,329 @@ @@ -0,0 +1,329 @@
/* A-Netz signal processing
*
* (C) 2016 by