├── .github ├── dependabot.yml └── workflows │ ├── cmake.yml │ └── qmake.yml ├── .gitignore ├── BCHCode.c ├── BCHCode.h ├── BCHCode_stub.c ├── CMakeLists.txt ├── COPYING ├── README.md ├── cJSON.c ├── cJSON.h ├── clip.c ├── costabf.c ├── costabi.c ├── demod_afsk12.c ├── demod_afsk24.c ├── demod_afsk24_2.c ├── demod_afsk24_3.c ├── demod_ccir.c ├── demod_clipfsk.c ├── demod_display.c ├── demod_dtmf.c ├── demod_dumpcsv.c ├── demod_dzvei.c ├── demod_eas.c ├── demod_eea.c ├── demod_eia.c ├── demod_flex.c ├── demod_flex_next.c ├── demod_fmsfsk.c ├── demod_fsk96.c ├── demod_hapn48.c ├── demod_morse.c ├── demod_poc12.c ├── demod_poc24.c ├── demod_poc5.c ├── demod_pzvei.c ├── demod_ufsk12.c ├── demod_x10.c ├── demod_zvei1.c ├── demod_zvei2.c ├── demod_zvei3.c ├── example ├── README-dumpcsv.txt ├── dumpcsv_png.txt ├── multipager.py ├── ufsk1200.raw └── x10rf.wav ├── filter-i386.h ├── filter.h ├── fms.c ├── gen-ng.pro ├── gen.c ├── gen.h ├── gen_clipfsk.c ├── gen_dtmf.c ├── gen_hdlc.c ├── gen_sin.c ├── gen_uart.c ├── gen_zvei.c ├── hdlc.c ├── mkcostab.c ├── msvc_support.h ├── multimon-ng.1 ├── multimon-ng.pro ├── multimon.h ├── pocsag.c ├── selcall.c ├── uart.c ├── unixinput.c ├── unsupported ├── Makefile.legacy ├── multimonNG.sln └── multimonNG.vcxproj ├── win32_getopt.c ├── win32_getopt.h ├── win32_soundin.c └── xdisplay.c /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | open-pull-requests-limit: 1000 13 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI cmake 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: cmake 13 | run: mkdir build && cd build && cmake .. 14 | - name: make 15 | run: cd build && make 16 | -------------------------------------------------------------------------------- /.github/workflows/qmake.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI qmake 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: jurplel/install-qt-action@v4 13 | - name: qmake 14 | run: mkdir build && cd build && qmake ../multimon-ng.pro 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | bin-* 10 | build 11 | 12 | # Packages # 13 | ############ 14 | # it's better to unpack these files and commit the raw source 15 | # git has its own built in compression methods 16 | *.7z 17 | *.dmg 18 | *.gz 19 | *.iso 20 | *.jar 21 | *.rar 22 | *.tar 23 | *.zip 24 | 25 | # Logs and databases # 26 | ###################### 27 | *.log 28 | *.sql 29 | *.sqlite 30 | 31 | # OS generated files # 32 | ###################### 33 | .DS_Store 34 | .DS_Store? 35 | ._* 36 | .Spotlight-V100 37 | .Trashes 38 | Icon? 39 | ehthumbs.db 40 | Thumbs.db 41 | *.bak 42 | 43 | # Tool cache # 44 | ############## 45 | *.sw[op] 46 | -------------------------------------------------------------------------------- /BCHCode.h: -------------------------------------------------------------------------------- 1 | struct BCHCode; 2 | 3 | struct BCHCode * BCHCode_New(int p[], int m, int n, int k, int t); 4 | void BCHCode_Delete(struct BCHCode * BCHCode_data); 5 | void BCHCode_Encode(struct BCHCode * BCHCode_data, int data[]); 6 | int BCHCode_Decode(struct BCHCode * BCHCode_data, int recd[]); 7 | -------------------------------------------------------------------------------- /BCHCode_stub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BCHCode_stub.c 3 | * 4 | * Copyright (C) 2018 Göran Weinholt 5 | * 6 | * Stub replacement for BCHCode.c, whose license is GPL incompatible 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along 19 | * with this program; if not, write to the Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 | */ 22 | 23 | #include 24 | #include "BCHCode.h" 25 | 26 | struct BCHCode { 27 | }; 28 | 29 | struct BCHCode *BCHCode_New(int p[], int m, int n, int k, int t) 30 | { 31 | /* Ignore unused variables */ 32 | (void) p; 33 | (void) m; 34 | (void) n; 35 | (void) k; 36 | (void) t; 37 | return malloc(sizeof(struct BCHCode)); 38 | } 39 | 40 | void BCHCode_Delete(struct BCHCode *BCHCode_data) 41 | { 42 | free(BCHCode_data); 43 | } 44 | 45 | int BCHCode_Decode(struct BCHCode *BCHCode_data, int recd[]) 46 | { 47 | (void) BCHCode_data; 48 | (void) recd; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 2.8.8 ) 2 | 3 | # The "MSVC" flag isn't set until the "project" command 4 | # is called. Let's just check the operating system. 5 | if( NOT WIN32 ) 6 | project( multimon-ng C ) 7 | else( NOT WIN32 ) 8 | # Visual Studio C compiler doesn't support C99 (i.e. stdbool.h); 9 | # so use the Visual Studio C++ compiler instead 10 | project( multimon-ng CXX ) 11 | endif( NOT WIN32 ) 12 | 13 | set( TARGET "${PROJECT_NAME}" ) 14 | set( VERSION "1.4.1" ) 15 | set( MAJOR "1" ) 16 | set( MINOR "4" ) 17 | set( PATCH "1" ) 18 | set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra" ) 19 | 20 | if( WIN32 ) 21 | add_definitions( "-DWIN32_AUDIO" "-DONLY_RAW" "-DWINDOWS" ) 22 | link_libraries( ${TARGET} "-lwinmm" ) 23 | set( SOURCES ${SOURCES} 24 | "win32_soundin.c" 25 | ) 26 | elseif( UNIX ) 27 | find_package( X11 ) 28 | if ( X11_FOUND ) 29 | option( X11_SUPPORT "Enable X11 display support" ${X11_FOUND} ) 30 | mark_as_advanced( X11_SUPPORT ) 31 | endif( X11_FOUND ) 32 | find_package( PulseAudio ) 33 | if ( PULSEAUDIO_FOUND ) 34 | option( PULSE_AUDIO_SUPPORT "Enable pulse audio support" ${PULSEAUDIO_FOUND} ) 35 | mark_as_advanced( PULSE_AUDIO_SUPPORT ) 36 | endif( PULSEAUDIO_FOUND ) 37 | 38 | # Check if we can use the GCC/llvm __builtin_popcount 39 | include( CheckCSourceCompiles ) 40 | check_c_source_compiles( 41 | "int main() { __builtin_popcount(42); return 0; }" USE_BUILTIN_POPCOUNT ) 42 | 43 | set( INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" ) 44 | install( FILES multimon-ng.1 DESTINATION "${INSTALL_MAN_DIR}/man1" ) 45 | endif( WIN32 ) 46 | 47 | if( X11_SUPPORT ) 48 | include_directories( ${X11_INCLUDE_DIR} ) 49 | link_libraries( ${X11_LIBRARIES} ) 50 | set( SOURCES ${SOURCES} 51 | xdisplay.c 52 | demod_display.c 53 | ) 54 | else( X11_SUPPORT ) 55 | add_definitions( "-DNO_X11" ) 56 | endif( X11_SUPPORT ) 57 | 58 | if( PULSE_AUDIO_SUPPORT ) 59 | include_directories( ${PULSEAUDIO_INCLUDE_DIR} ) 60 | find_library( PULSE_SIMPLE NAMES pulse-simple REQUIRED ) 61 | link_libraries( ${PULSEAUDIO_LIBRARY} ${PULSE_SIMPLE} ) 62 | add_definitions( "-DPULSE_AUDIO" ) 63 | else( PULSE_AUDIO_SUPPORT ) 64 | add_definitions( "-DDUMMY_AUDIO" ) 65 | endif( PULSE_AUDIO_SUPPORT ) 66 | 67 | if( NOT MSVC ) 68 | add_definitions( "-std=gnu11" ) 69 | endif( NOT MSVC ) 70 | add_definitions( "-DMAX_VERBOSE_LEVEL=3" "-DCHARSET_UTF8" ) 71 | 72 | if ( EXISTS "${multimon-ng_SOURCE_DIR}/BCHCode.c" ) 73 | set( SOURCES ${SOURCES} 74 | BCHCode.c ) 75 | else() 76 | message(STATUS "Using the BCH decoder stub") 77 | set( SOURCES ${SOURCES} 78 | BCHCode_stub.c ) 79 | endif() 80 | 81 | set( HEADERS ${HEADERS} 82 | multimon.h 83 | gen.h 84 | filter.h 85 | filter-i386.h 86 | cJSON.h 87 | ) 88 | 89 | set( SOURCES ${SOURCES} 90 | unixinput.c 91 | uart.c 92 | pocsag.c 93 | selcall.c 94 | hdlc.c 95 | demod_zvei1.c 96 | demod_zvei2.c 97 | demod_zvei3.c 98 | demod_pzvei.c 99 | demod_dzvei.c 100 | demod_ccir.c 101 | demod_eia.c 102 | demod_eea.c 103 | demod_ufsk12.c 104 | demod_poc24.c 105 | demod_poc12.c 106 | demod_poc5.c 107 | demod_hapn48.c 108 | demod_fsk96.c 109 | demod_dtmf.c 110 | demod_clipfsk.c 111 | demod_fmsfsk.c 112 | demod_afsk24.c 113 | demod_afsk24_3.c 114 | demod_afsk24_2.c 115 | demod_afsk12.c 116 | demod_flex.c 117 | demod_flex_next.c 118 | costabi.c 119 | costabf.c 120 | clip.c 121 | fms.c 122 | demod_eas.c 123 | demod_morse.c 124 | demod_dumpcsv.c 125 | demod_x10.c 126 | cJSON.c 127 | ) 128 | 129 | 130 | add_executable( "${TARGET}" ${SOURCES} ${HEADERS} ) 131 | set_property(TARGET "${TARGET}" PROPERTY LINKER_LANGUAGE C) 132 | target_link_libraries( "${TARGET}" m ) 133 | install(TARGETS multimon-ng DESTINATION bin) 134 | 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # multimon-ng 2 | 3 | multimon-ng is the successor of multimon. It decodes the following digital transmission modes: 4 | 5 | - POCSAG512 POCSAG1200 POCSAG2400 6 | - FLEX 7 | - EAS 8 | - UFSK1200 CLIPFSK AFSK1200 AFSK2400 AFSK2400_2 AFSK2400_3 9 | - HAPN4800 10 | - FSK9600 11 | - DTMF 12 | - ZVEI1 ZVEI2 ZVEI3 DZVEI PZVEI 13 | - EEA EIA CCIR 14 | - MORSE CW 15 | - X10 16 | 17 | ## Building 18 | 19 | multimon-ng can be built using either qmake or CMake: 20 | 21 | #### qmake 22 | ``` 23 | mkdir build 24 | cd build 25 | qmake ../multimon-ng.pro 26 | make 27 | sudo make install 28 | ``` 29 | 30 | #### CMake 31 | ``` 32 | mkdir build 33 | cd build 34 | cmake .. 35 | make 36 | sudo make install 37 | ``` 38 | 39 | The installation prefix can be set by passing a 'PREFIX' parameter to qmake. e.g: 40 | ```qmake multimon-ng.pro PREFIX=/usr/local``` 41 | 42 | ### Environments 43 | 44 | So far multimon-ng has been successfully built on: 45 | 46 | - Arch Linux 47 | - Debian 48 | - Gentoo 49 | - Kali Linux 50 | - Ubuntu 51 | - OS X 52 | - Windows (Qt-MinGW build environment, Cygwin, and VisualStudio/MSVC) 53 | - FreeBSD 54 | 55 | ## Examples 56 | 57 | ### Wav to raw 58 | 59 | Files can be easily converted into multimon-ng's native raw format using *sox*. e.g: 60 | 61 | sox -t wav pocsag_short.wav -esigned-integer -b16 -r 22050 -t raw pocsag_short.raw 62 | 63 | GNURadio can also generate the format using the file sink in input mode *short*. 64 | 65 | ### Pipe sox to multimon-ng 66 | 67 | You can also "pipe" raw samples into multimon-ng using something like: 68 | 69 | sox -t wav pocsag_short.wav -esigned-integer -b16 -r 22050 -t raw - | ./multimon-ng - 70 | 71 | > [!NOTE] 72 | > Note the trailing dash, means write/read to/from stdin 73 | 74 | ### Pipe rtl_fm to multimon-ng 75 | 76 | As a last example, here is how you can use it in combination with RTL-SDR: 77 | 78 | rtl_fm -f 403600000 -s 22050 | multimon-ng -t raw -a FMSFSK -a AFSK1200 /dev/stdin 79 | 80 | ### Flac record and parse live data 81 | 82 | A more advanced sample that combines `rtl_fm`, `flac`, and `tee` to split the output from `rtl_rm` into separate streams. One stream to be passed to `flac` to record the audio and another stream to for example an application that does text parsing of `mulimon-ng` output 83 | 84 | 85 | 86 | ```sh 87 | rtl_fm -s 22050 -f 123.456M -g -9.9 | tee >(flac -8 --endian=little --channels=1 --bps=16 --sample-rate=22050 --sign=signed - -o ~/recordings/rtlfm.$EPOCHSECONDS.flac -f) | multimon-ng -v 0 -a FLEX -a FLEX_NEXT -t raw /dev/stdin 88 | ``` 89 | 90 | 1. You can pass `-l` to `rtl_fm` for the squelch level, this will cut the noise floor so less data gets encoded by flac and will significantly reduce the file size but could result in loss of signal data. **This value must be tuned!** 91 | 2. Flac uses `-8` here, if you run an a resource constraint device you may want to lower this value 92 | 3. The Flac `-o` argument value contains `$EPOCHSECONDS` to make unique files when this gets restarted 93 | 94 | To replay the recorded flac file to multimon-ng (requires sox): 95 | 96 | ```sg 97 | flac -d --stdout ~/recordings/rtlf/rtlfm.1725033204.flac | multimon-ng -v 0 -a FLEX_NEXT -t flac - 98 | ``` 99 | 100 | ## Packaging 101 | 102 | ``` 103 | qmake multimon-ng.pro PREFIX=/usr/local 104 | make 105 | make install INSTALL_ROOT=/ 106 | ``` 107 | -------------------------------------------------------------------------------- /costabi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is machine generated, DO NOT EDIT! 3 | */ 4 | 5 | const int costabi[0x400] = { 6 | 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736, 7 | 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628, 8 | 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441, 9 | 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176, 10 | 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, 11 | 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413, 12 | 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918, 13 | 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349, 14 | 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706, 15 | 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992, 16 | 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208, 17 | 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355, 18 | 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437, 19 | 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, 20 | 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413, 21 | 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311, 22 | 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153, 23 | 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942, 24 | 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680, 25 | 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371, 26 | 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017, 27 | 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623, 28 | 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, 29 | 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724, 30 | 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227, 31 | 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703, 32 | 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156, 33 | 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589, 34 | 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006, 35 | 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411, 36 | 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808, 37 | 1607, 1406, 1206, 1005, 804, 603, 402, 201, 38 | 0, -201, -402, -603, -804, -1005, -1206, -1406, 39 | -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011, 40 | -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608, 41 | -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195, 42 | -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766, 43 | -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319, 44 | -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849, 45 | -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353, 46 | -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827, 47 | -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268, 48 | -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672, 49 | -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036, 50 | -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357, 51 | -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631, 52 | -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855, 53 | -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027, 54 | -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143, 55 | -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201, 56 | -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198, 57 | -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132, 58 | -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001, 59 | -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802, 60 | -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534, 61 | -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195, 62 | -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783, 63 | -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297, 64 | -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735, 65 | -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097, 66 | -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382, 67 | -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588, 68 | -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717, 69 | -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766, 70 | -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736, 71 | -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628, 72 | -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441, 73 | -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176, 74 | -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833, 75 | -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413, 76 | -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918, 77 | -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349, 78 | -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706, 79 | -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992, 80 | -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208, 81 | -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355, 82 | -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437, 83 | -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456, 84 | -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413, 85 | -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311, 86 | -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153, 87 | -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942, 88 | -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680, 89 | -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371, 90 | -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017, 91 | -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623, 92 | -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191, 93 | -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724, 94 | -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227, 95 | -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703, 96 | -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156, 97 | -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589, 98 | -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006, 99 | -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411, 100 | -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, 101 | -1607, -1406, -1206, -1005, -804, -603, -402, -201, 102 | 0, 201, 402, 603, 804, 1005, 1206, 1406, 103 | 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, 104 | 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, 105 | 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195, 106 | 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766, 107 | 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319, 108 | 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849, 109 | 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353, 110 | 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827, 111 | 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, 112 | 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672, 113 | 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036, 114 | 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357, 115 | 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631, 116 | 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855, 117 | 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027, 118 | 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143, 119 | 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201, 120 | 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, 121 | 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132, 122 | 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001, 123 | 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802, 124 | 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534, 125 | 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195, 126 | 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783, 127 | 30851, 30918, 30984, 31049, 31113, 31175, 31236, 31297, 128 | 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735, 129 | 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, 130 | 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382, 131 | 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588, 132 | 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717, 133 | 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766 134 | }; 135 | -------------------------------------------------------------------------------- /demod_afsk12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_afsk12.c -- 1200 baud AFSK demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * Copyright (C) 2024 7 | * Marat Fayzullin (luarvique@gmail.com) 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 | */ 23 | 24 | /* ---------------------------------------------------------------------- */ 25 | 26 | #include "multimon.h" 27 | #include "filter.h" 28 | #include 29 | #include 30 | 31 | /* ---------------------------------------------------------------------- */ 32 | 33 | /* 34 | * Standard TCM3105 clock frequency: 4.4336MHz 35 | * Mark frequency: 2200 Hz 36 | * Space frequency: 1200 Hz 37 | */ 38 | 39 | #define FREQ_MARK 1200 40 | #define FREQ_SPACE 2200 41 | #define FREQ_SAMP 22050 42 | #define BAUD 1200 43 | #define SUBSAMP 2 44 | 45 | /* ---------------------------------------------------------------------- */ 46 | 47 | #define CORRLEN ((int)(FREQ_SAMP/BAUD)) 48 | #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) 49 | 50 | static float corr_mark_i[CORRLEN]; 51 | static float corr_mark_q[CORRLEN]; 52 | static float corr_space_i[CORRLEN]; 53 | static float corr_space_q[CORRLEN]; 54 | 55 | /* ---------------------------------------------------------------------- */ 56 | 57 | static void afsk12_init(struct demod_state *s) 58 | { 59 | float f; 60 | int i; 61 | 62 | hdlc_init(s); 63 | memset(&s->l1.afsk12, 0, sizeof(s->l1.afsk12)); 64 | for (f = 0, i = 0; i < CORRLEN; i++) { 65 | corr_mark_i[i] = cos(f); 66 | corr_mark_q[i] = sin(f); 67 | f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; 68 | } 69 | for (f = 0, i = 0; i < CORRLEN; i++) { 70 | corr_space_i[i] = cos(f); 71 | corr_space_q[i] = sin(f); 72 | f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; 73 | } 74 | } 75 | 76 | /* ---------------------------------------------------------------------- */ 77 | 78 | static void afsk12_demod(struct demod_state *s, buffer_t buffer, int length) 79 | { 80 | float f; 81 | unsigned char curbit; 82 | 83 | if (s->l1.afsk12.subsamp) { 84 | if (length <= (int)s->l1.afsk12.subsamp) { 85 | s->l1.afsk12.subsamp -= length; 86 | return; 87 | } 88 | buffer.fbuffer += s->l1.afsk12.subsamp; 89 | length -= s->l1.afsk12.subsamp; 90 | s->l1.afsk12.subsamp = 0; 91 | } 92 | for (; length > 0; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) { 93 | f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) + 94 | fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) - 95 | fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) - 96 | fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN)); 97 | s->l1.afsk12.dcd_shreg <<= 1; 98 | s->l1.afsk12.dcd_shreg |= (f > 0); 99 | verbprintf(10, "%c", '0'+(s->l1.afsk12.dcd_shreg & 1)); 100 | /* 101 | * check if transition 102 | */ 103 | if ((s->l1.afsk12.dcd_shreg ^ (s->l1.afsk12.dcd_shreg >> 1)) & 1) { 104 | if (s->l1.afsk12.sphase < (0x8000u-(SPHASEINC/2))) 105 | s->l1.afsk12.sphase += SPHASEINC/8; 106 | else 107 | s->l1.afsk12.sphase -= SPHASEINC/8; 108 | } 109 | s->l1.afsk12.sphase += SPHASEINC; 110 | if (s->l1.afsk12.sphase >= 0x10000u) { 111 | s->l1.afsk12.sphase &= 0xffffu; 112 | s->l1.afsk12.lasts <<= 1; 113 | s->l1.afsk12.lasts |= s->l1.afsk12.dcd_shreg & 1; 114 | curbit = (s->l1.afsk12.lasts ^ 115 | (s->l1.afsk12.lasts >> 1) ^ 1) & 1; 116 | verbprintf(9, " %c ", '0'+curbit); 117 | hdlc_rxbit(s, curbit); 118 | } 119 | } 120 | s->l1.afsk12.subsamp = -length; 121 | } 122 | 123 | /* ---------------------------------------------------------------------- */ 124 | 125 | const struct demod_param demod_afsk1200 = { 126 | "AFSK1200", true, FREQ_SAMP, CORRLEN, afsk12_init, afsk12_demod, NULL 127 | }; 128 | 129 | /* ---------------------------------------------------------------------- */ 130 | -------------------------------------------------------------------------------- /demod_afsk24.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_afsk24.c -- 2400 baud AFSK demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "multimon.h" 25 | #include "filter.h" 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | /* 32 | * Standard TCM3105 clock frequency: 4.4336MHz 33 | * Xtal used: 8 MHz 34 | * Ratio: 1.8044 35 | * Mark frequency: 3970 Hz 36 | * Space frequency: 2165 Hz 37 | */ 38 | 39 | #define FREQ_MARK 3970 40 | #define FREQ_SPACE 2165 41 | #define FREQ_SAMP 22050 42 | #define BAUD 2400 43 | 44 | /* ---------------------------------------------------------------------- */ 45 | 46 | #define CORRLEN (2*(int)(FREQ_SAMP/BAUD)) 47 | #define SPHASEINC (0x10000u*BAUD/FREQ_SAMP) 48 | 49 | static float corr_mark_i[CORRLEN]; 50 | static float corr_mark_q[CORRLEN]; 51 | static float corr_space_i[CORRLEN]; 52 | static float corr_space_q[CORRLEN]; 53 | 54 | /* ---------------------------------------------------------------------- */ 55 | 56 | static void afsk24_init(struct demod_state *s) 57 | { 58 | float f; 59 | int i; 60 | 61 | hdlc_init(s); 62 | memset(&s->l1.afsk24, 0, sizeof(s->l1.afsk24)); 63 | for (f = 0, i = 0; i < CORRLEN; i++) { 64 | corr_mark_i[i] = cos(f); 65 | corr_mark_q[i] = sin(f); 66 | f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; 67 | } 68 | for (f = 0, i = 0; i < CORRLEN; i++) { 69 | corr_space_i[i] = cos(f); 70 | corr_space_q[i] = sin(f); 71 | f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; 72 | } 73 | for (i = 0; i < CORRLEN; i++) { 74 | f = 0.54 - 0.46*cos(2*M_PI*i/(float)(CORRLEN-1)); 75 | corr_mark_i[i] *= f; 76 | corr_mark_q[i] *= f; 77 | corr_space_i[i] *= f; 78 | corr_space_q[i] *= f; 79 | } 80 | } 81 | 82 | /* ---------------------------------------------------------------------- */ 83 | 84 | static void afsk24_demod(struct demod_state *s, buffer_t buffer, int length) 85 | { 86 | float f; 87 | unsigned char curbit; 88 | 89 | for (; length > 0; length--, buffer.fbuffer++) { 90 | f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) + 91 | fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) - 92 | fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) - 93 | fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN)); 94 | s->l1.afsk24.dcd_shreg <<= 1; 95 | s->l1.afsk24.dcd_shreg |= (f > 0); 96 | verbprintf(10, "%c", '0'+(s->l1.afsk24.dcd_shreg & 1)); 97 | /* 98 | * check if transition 99 | */ 100 | if ((s->l1.afsk24.dcd_shreg ^ (s->l1.afsk24.dcd_shreg >> 1)) & 1) { 101 | if (s->l1.afsk24.sphase < (0x8000u-(SPHASEINC/2))) 102 | s->l1.afsk24.sphase += SPHASEINC/8; 103 | else 104 | s->l1.afsk24.sphase -= SPHASEINC/8; 105 | } 106 | s->l1.afsk24.sphase += SPHASEINC; 107 | if (s->l1.afsk24.sphase >= 0x10000u) { 108 | s->l1.afsk24.sphase &= 0xffffu; 109 | s->l1.afsk24.lasts <<= 1; 110 | s->l1.afsk24.lasts |= s->l1.afsk24.dcd_shreg & 1; 111 | curbit = (s->l1.afsk24.lasts ^ 112 | (s->l1.afsk24.lasts >> 1) ^ 1) & 1; 113 | verbprintf(9, " %c ", '0'+curbit); 114 | hdlc_rxbit(s, curbit); 115 | } 116 | } 117 | } 118 | 119 | /* ---------------------------------------------------------------------- */ 120 | 121 | const struct demod_param demod_afsk2400 = { 122 | "AFSK2400", true, FREQ_SAMP, CORRLEN, afsk24_init, afsk24_demod, NULL 123 | }; 124 | 125 | /* ---------------------------------------------------------------------- */ 126 | -------------------------------------------------------------------------------- /demod_afsk24_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_afsk24.c -- 2400 baud AFSK demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "multimon.h" 25 | #include "filter.h" 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | /* 32 | * Standard TCM3105 clock frequency: 4.4336MHz 33 | * Xtal used: 7.3728 MHz 34 | * Ratio: 1.6629 35 | * Mark frequency: 3658 Hz 36 | * Space frequency: 1996 Hz 37 | */ 38 | 39 | #define FREQ_MARK 3658 40 | #define FREQ_SPACE 1996 41 | #define FREQ_SAMP 22050 42 | #define BAUD 2400 43 | 44 | /* ---------------------------------------------------------------------- */ 45 | 46 | #define CORRLEN ((int)(2*FREQ_SAMP/BAUD)) 47 | #define SPHASEINC (0x10000u*BAUD/FREQ_SAMP) 48 | 49 | static float corr_mark_i[CORRLEN]; 50 | static float corr_mark_q[CORRLEN]; 51 | static float corr_space_i[CORRLEN]; 52 | static float corr_space_q[CORRLEN]; 53 | 54 | /* ---------------------------------------------------------------------- */ 55 | 56 | static void afsk24_2_init(struct demod_state *s) 57 | { 58 | float f; 59 | int i; 60 | 61 | hdlc_init(s); 62 | memset(&s->l1.afsk24, 0, sizeof(s->l1.afsk24)); 63 | for (f = 0, i = 0; i < CORRLEN; i++) { 64 | corr_mark_i[i] = cos(f); 65 | corr_mark_q[i] = sin(f); 66 | f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; 67 | } 68 | for (f = 0, i = 0; i < CORRLEN; i++) { 69 | corr_space_i[i] = cos(f); 70 | corr_space_q[i] = sin(f); 71 | f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; 72 | } 73 | for (i = 0; i < CORRLEN; i++) { 74 | f = 0.54 - 0.46*cos(2*M_PI*i/(float)(CORRLEN-1)); 75 | corr_mark_i[i] *= f; 76 | corr_mark_q[i] *= f; 77 | corr_space_i[i] *= f; 78 | corr_space_q[i] *= f; 79 | } 80 | } 81 | 82 | /* ---------------------------------------------------------------------- */ 83 | 84 | static void afsk24_2_demod(struct demod_state *s, buffer_t buffer, int length) 85 | { 86 | float f; 87 | unsigned char curbit; 88 | 89 | for (; length > 0; length--, buffer.fbuffer++) { 90 | f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) + 91 | fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) - 92 | fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) - 93 | fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN)); 94 | s->l1.afsk24.dcd_shreg <<= 1; 95 | s->l1.afsk24.dcd_shreg |= (f > 0); 96 | verbprintf(10, "%c", '0'+(s->l1.afsk24.dcd_shreg & 1)); 97 | /* 98 | * check if transition 99 | */ 100 | if ((s->l1.afsk24.dcd_shreg ^ (s->l1.afsk24.dcd_shreg >> 1)) & 1) { 101 | if (s->l1.afsk24.sphase < (0x8000u-(SPHASEINC/2))) 102 | s->l1.afsk24.sphase += SPHASEINC/8; 103 | else 104 | s->l1.afsk24.sphase -= SPHASEINC/8; 105 | } 106 | s->l1.afsk24.sphase += SPHASEINC; 107 | if (s->l1.afsk24.sphase >= 0x10000u) { 108 | s->l1.afsk24.sphase &= 0xffffu; 109 | s->l1.afsk24.lasts <<= 1; 110 | s->l1.afsk24.lasts |= s->l1.afsk24.dcd_shreg & 1; 111 | curbit = (s->l1.afsk24.lasts ^ 112 | (s->l1.afsk24.lasts >> 1) ^ 1) & 1; 113 | verbprintf(9, " %c ", '0'+curbit); 114 | hdlc_rxbit(s, curbit); 115 | } 116 | } 117 | } 118 | 119 | /* ---------------------------------------------------------------------- */ 120 | 121 | const struct demod_param demod_afsk2400_2 = { 122 | "AFSK2400_2", true, FREQ_SAMP, CORRLEN, afsk24_2_init, afsk24_2_demod, NULL 123 | }; 124 | 125 | /* ---------------------------------------------------------------------- */ 126 | -------------------------------------------------------------------------------- /demod_afsk24_3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_afsk24.c -- 2400 baud AFSK demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "multimon.h" 25 | #include "filter.h" 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | /* 32 | * Standard TCM3105 clock frequency: 4.4336MHz 33 | * Xtal used: 6.5536 MHz 34 | * Ratio: 1.47816 35 | * Mark frequency: 3252 Hz 36 | * Space frequency: 1774 Hz 37 | */ 38 | 39 | #define FREQ_MARK 3252 40 | #define FREQ_SPACE 1774 41 | #define FREQ_SAMP 22050 42 | #define BAUD 2400 43 | 44 | /* ---------------------------------------------------------------------- */ 45 | 46 | #define CORRLEN ((int)(2*FREQ_SAMP/BAUD)) 47 | #define SPHASEINC (0x10000u*BAUD/FREQ_SAMP) 48 | 49 | static float corr_mark_i[CORRLEN]; 50 | static float corr_mark_q[CORRLEN]; 51 | static float corr_space_i[CORRLEN]; 52 | static float corr_space_q[CORRLEN]; 53 | 54 | /* ---------------------------------------------------------------------- */ 55 | 56 | static void afsk24_3_init(struct demod_state *s) 57 | { 58 | float f; 59 | int i; 60 | 61 | hdlc_init(s); 62 | memset(&s->l1.afsk24, 0, sizeof(s->l1.afsk24)); 63 | for (f = 0, i = 0; i < CORRLEN; i++) { 64 | corr_mark_i[i] = cos(f); 65 | corr_mark_q[i] = sin(f); 66 | f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; 67 | } 68 | for (f = 0, i = 0; i < CORRLEN; i++) { 69 | corr_space_i[i] = cos(f); 70 | corr_space_q[i] = sin(f); 71 | f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; 72 | } 73 | for (i = 0; i < CORRLEN; i++) { 74 | f = 0.54 - 0.46*cos(2*M_PI*i/(float)(CORRLEN-1)); 75 | corr_mark_i[i] *= f; 76 | corr_mark_q[i] *= f; 77 | corr_space_i[i] *= f; 78 | corr_space_q[i] *= f; 79 | } 80 | } 81 | 82 | /* ---------------------------------------------------------------------- */ 83 | 84 | static void afsk24_3_demod(struct demod_state *s, buffer_t buffer, int length) 85 | { 86 | float f; 87 | unsigned char curbit; 88 | 89 | for (; length > 0; length--, buffer.fbuffer++) { 90 | f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) + 91 | fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) - 92 | fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) - 93 | fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN)); 94 | s->l1.afsk24.dcd_shreg <<= 1; 95 | s->l1.afsk24.dcd_shreg |= (f > 0); 96 | verbprintf(10, "%c", '0'+(s->l1.afsk24.dcd_shreg & 1)); 97 | /* 98 | * check if transition 99 | */ 100 | if ((s->l1.afsk24.dcd_shreg ^ (s->l1.afsk24.dcd_shreg >> 1)) & 1) { 101 | if (s->l1.afsk24.sphase < (0x8000u-(SPHASEINC/2))) 102 | s->l1.afsk24.sphase += SPHASEINC/8; 103 | else 104 | s->l1.afsk24.sphase -= SPHASEINC/8; 105 | } 106 | s->l1.afsk24.sphase += SPHASEINC; 107 | if (s->l1.afsk24.sphase >= 0x10000u) { 108 | s->l1.afsk24.sphase &= 0xffffu; 109 | s->l1.afsk24.lasts <<= 1; 110 | s->l1.afsk24.lasts |= s->l1.afsk24.dcd_shreg & 1; 111 | curbit = (s->l1.afsk24.lasts ^ 112 | (s->l1.afsk24.lasts >> 1) ^ 1) & 1; 113 | verbprintf(9, " %c ", '0'+curbit); 114 | hdlc_rxbit(s, curbit); 115 | } 116 | } 117 | } 118 | 119 | /* ---------------------------------------------------------------------- */ 120 | 121 | const struct demod_param demod_afsk2400_3 = { 122 | "AFSK2400_3", true, FREQ_SAMP, CORRLEN, afsk24_3_init, afsk24_3_demod, NULL 123 | }; 124 | 125 | /* ---------------------------------------------------------------------- */ 126 | -------------------------------------------------------------------------------- /demod_ccir.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_ccir.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int ccir_freq[16] = { 28 | PHINC(1981), PHINC(1124), PHINC(1197), PHINC(1275), 29 | PHINC(1358), PHINC(1446), PHINC(1540), PHINC(1640), 30 | PHINC(1747), PHINC(1860), PHINC(2400), PHINC(930), 31 | PHINC(2247), PHINC(991), PHINC(2110), PHINC(1055) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void ccir_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void ccir_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void ccir_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, ccir_freq, demod_ccir.name); 49 | } 50 | 51 | const struct demod_param demod_ccir = { 52 | "CCIR", true, SAMPLE_RATE, 0, ccir_init, ccir_demod, ccir_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_clipfsk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_clipfsk.c -- 1200 baud FSK demodulator 3 | * 4 | * Copyright (C) 2007, 2024 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | */ 20 | 21 | /* ---------------------------------------------------------------------- */ 22 | 23 | #include "multimon.h" 24 | #include "filter.h" 25 | #include 26 | #include 27 | 28 | /* ---------------------------------------------------------------------- */ 29 | 30 | /* 31 | * V.23 signaling 1200 baud +/- 1% 32 | * Mark frequency: 2300 Hz +/- 1.5% 33 | * Space frequency: 1100 Hz +/- 1.5% 34 | */ 35 | 36 | #define FREQ_MARK 1200 37 | #define FREQ_SPACE 2200 38 | #define FREQ_SAMP 22050 39 | #define BAUD 1200 40 | #define SUBSAMP 2 41 | 42 | /* ---------------------------------------------------------------------- */ 43 | 44 | #define CORRLEN ((int)(FREQ_SAMP/BAUD)) 45 | #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) 46 | 47 | static float corr_mark_i[CORRLEN]; 48 | static float corr_mark_q[CORRLEN]; 49 | static float corr_space_i[CORRLEN]; 50 | static float corr_space_q[CORRLEN]; 51 | 52 | /* ---------------------------------------------------------------------- */ 53 | 54 | static void clipfsk_init(struct demod_state *s) 55 | { 56 | float f; 57 | int i; 58 | 59 | clip_init(s); 60 | memset(&s->l1.clipfsk, 0, sizeof(s->l1.clipfsk)); 61 | for (f = 0, i = 0; i < CORRLEN; i++) { 62 | corr_mark_i[i] = cos(f); 63 | corr_mark_q[i] = sin(f); 64 | f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; 65 | } 66 | for (f = 0, i = 0; i < CORRLEN; i++) { 67 | corr_space_i[i] = cos(f); 68 | corr_space_q[i] = sin(f); 69 | f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; 70 | } 71 | } 72 | 73 | /* ---------------------------------------------------------------------- */ 74 | 75 | static void clipfsk_demod(struct demod_state *s, buffer_t buffer, int length) 76 | { 77 | float f; 78 | unsigned char curbit; 79 | 80 | if (s->l1.clipfsk.subsamp) { 81 | if (length <= (int)s->l1.clipfsk.subsamp) { 82 | s->l1.clipfsk.subsamp -= length; 83 | return; 84 | } 85 | buffer.fbuffer += s->l1.clipfsk.subsamp; 86 | length -= s->l1.clipfsk.subsamp; 87 | s->l1.clipfsk.subsamp = 0; 88 | } 89 | for (; length > 0; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) { 90 | f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) + 91 | fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) - 92 | fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) - 93 | fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN)); 94 | s->l1.clipfsk.dcd_shreg <<= 1; 95 | s->l1.clipfsk.dcd_shreg |= (f > 0); 96 | verbprintf(10, "%c", '0'+(s->l1.clipfsk.dcd_shreg & 1)); 97 | /* 98 | * check if transition 99 | */ 100 | if ((s->l1.clipfsk.dcd_shreg ^ (s->l1.clipfsk.dcd_shreg >> 1)) & 1) { 101 | if (s->l1.clipfsk.sphase < (0x8000u-(SPHASEINC/2))) 102 | s->l1.clipfsk.sphase += SPHASEINC/8; 103 | else 104 | s->l1.clipfsk.sphase -= SPHASEINC/8; 105 | } 106 | s->l1.clipfsk.sphase += SPHASEINC; 107 | if (s->l1.clipfsk.sphase >= 0x10000u) { 108 | s->l1.clipfsk.sphase &= 0xffffu; 109 | curbit = s->l1.clipfsk.dcd_shreg & 1; 110 | verbprintf(9, " %c ", '0'+curbit); 111 | clip_rxbit(s, curbit); 112 | } 113 | } 114 | s->l1.clipfsk.subsamp = -length; 115 | } 116 | 117 | /* ---------------------------------------------------------------------- */ 118 | 119 | const struct demod_param demod_clipfsk = { 120 | "CLIPFSK", true, FREQ_SAMP, CORRLEN, clipfsk_init, clipfsk_demod, NULL 121 | }; 122 | 123 | /* ---------------------------------------------------------------------- */ 124 | -------------------------------------------------------------------------------- /demod_display.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_display.c -- signal display 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #ifndef NO_X11 23 | /* ---------------------------------------------------------------------- */ 24 | 25 | #include "multimon.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | /* ---------------------------------------------------------------------- */ 37 | 38 | #define SAMPLING_RATE 22050 39 | 40 | /* ---------------------------------------------------------------------- */ 41 | 42 | static void scope_init(struct demod_state *s) 43 | { 44 | memset(&s->l1.scope, 0, sizeof(s->l1.scope)); 45 | s->l1.scope.dispnum = xdisp_start(); 46 | if (s->l1.scope.dispnum == -1) 47 | return; 48 | } 49 | 50 | /* ---------------------------------------------------------------------- */ 51 | 52 | #define MEMSIZE sizeof(s->l1.scope.data)/sizeof(s->l1.scope.data[0]) 53 | 54 | static void scope_demod(struct demod_state *s, buffer_t buffer, int length) 55 | { 56 | const float *src; 57 | float *dst; 58 | int i; 59 | 60 | if (s->l1.scope.dispnum == -1) 61 | return; 62 | if ( (unsigned int) length >= MEMSIZE) { 63 | src = buffer.fbuffer+length-MEMSIZE; 64 | dst = s->l1.scope.data; 65 | i = MEMSIZE; 66 | } else { 67 | i = MEMSIZE-length; 68 | memmove(s->l1.scope.data, s->l1.scope.data+i, 69 | i*sizeof(s->l1.scope.data[0])); 70 | src = buffer.fbuffer; 71 | dst = s->l1.scope.data+i; 72 | i = length; 73 | } 74 | s->l1.scope.datalen += i; 75 | memcpy(dst, src, i*sizeof(s->l1.scope.data[0])); 76 | if ( (unsigned int) s->l1.scope.datalen < MEMSIZE) 77 | return; 78 | if (xdisp_update(s->l1.scope.dispnum, s->l1.scope.data)) 79 | s->l1.scope.datalen = 0; 80 | } 81 | 82 | /* ---------------------------------------------------------------------- */ 83 | 84 | const struct demod_param demod_scope = { 85 | "SCOPE", true, SAMPLING_RATE, 0, scope_init, scope_demod, NULL 86 | }; 87 | 88 | 89 | /* ---------------------------------------------------------------------- */ 90 | #endif //NO_X11 91 | -------------------------------------------------------------------------------- /demod_dtmf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_dtmf.c -- DTMF signalling demodulator/decoder 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * Copyright (C) 2024 8 | * Jason Lingohr (jason@lucid.net.au) 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 | */ 24 | 25 | /* ---------------------------------------------------------------------- */ 26 | 27 | #include "multimon.h" 28 | #include "filter.h" 29 | #include 30 | #include 31 | #include 32 | 33 | #include "cJSON.h" 34 | 35 | /* ---------------------------------------------------------------------- */ 36 | 37 | /* 38 | * 39 | * DTMF frequencies 40 | * 41 | * 1209 1336 1477 1633 42 | * 697 1 2 3 A 43 | * 770 4 5 6 B 44 | * 852 7 8 9 C 45 | * 941 * 0 # D 46 | * 47 | */ 48 | 49 | #define SAMPLE_RATE 22050 50 | #define BLOCKLEN (SAMPLE_RATE/100) /* 10ms blocks */ 51 | #define BLOCKNUM 4 /* must match numbers in multimon.h */ 52 | 53 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 54 | 55 | static const char *dtmf_transl = "123A456B789C*0#D"; 56 | 57 | static const unsigned int dtmf_phinc[8] = { 58 | PHINC(1209), PHINC(1336), PHINC(1477), PHINC(1633), 59 | PHINC(697), PHINC(770), PHINC(852), PHINC(941) 60 | }; 61 | 62 | extern int json_mode; 63 | 64 | /* ---------------------------------------------------------------------- */ 65 | 66 | static void dtmf_init(struct demod_state *s) 67 | { 68 | memset(&s->l1.dtmf, 0, sizeof(s->l1.dtmf)); 69 | } 70 | 71 | /* ---------------------------------------------------------------------- */ 72 | 73 | static int find_max_idx(const float *f) 74 | { 75 | float en = 0; 76 | int idx = -1, i; 77 | 78 | for (i = 0; i < 4; i++) 79 | if (f[i] > en) { 80 | en = f[i]; 81 | idx = i; 82 | } 83 | if (idx < 0) 84 | return -1; 85 | en *= 0.1; 86 | for (i = 0; i < 4; i++) 87 | if (idx != i && f[i] > en) 88 | return -1; 89 | return idx; 90 | } 91 | 92 | /* ---------------------------------------------------------------------- */ 93 | 94 | static inline int process_block(struct demod_state *s) 95 | { 96 | float tote; 97 | float totte[16]; 98 | int i, j; 99 | 100 | tote = 0; 101 | for (i = 0; i < BLOCKNUM; i++) 102 | tote += s->l1.dtmf.energy[i]; 103 | for (i = 0; i < 16; i++) { 104 | totte[i] = 0; 105 | for (j = 0; j < BLOCKNUM; j++) 106 | totte[i] += s->l1.dtmf.tenergy[j][i]; 107 | } 108 | for (i = 0; i < 8; i++) 109 | totte[i] = fsqr(totte[i]) + fsqr(totte[i+8]); 110 | memmove(s->l1.dtmf.energy+1, s->l1.dtmf.energy, 111 | sizeof(s->l1.dtmf.energy) - sizeof(s->l1.dtmf.energy[0])); 112 | s->l1.dtmf.energy[0] = 0; 113 | memmove(s->l1.dtmf.tenergy+1, s->l1.dtmf.tenergy, 114 | sizeof(s->l1.dtmf.tenergy) - sizeof(s->l1.dtmf.tenergy[0])); 115 | memset(s->l1.dtmf.tenergy, 0, sizeof(s->l1.dtmf.tenergy[0])); 116 | tote *= (BLOCKNUM*BLOCKLEN*0.5); /* adjust for block lengths */ 117 | verbprintf(10, "DTMF: Energies: %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f\n", 118 | tote, totte[0], totte[1], totte[2], totte[3], totte[4], totte[5], totte[6], totte[7]); 119 | if ((i = find_max_idx(totte)) < 0) 120 | return -1; 121 | if ((j = find_max_idx(totte+4)) < 0) 122 | return -1; 123 | if ((tote * 0.4) > (totte[i] + totte[j+4])) 124 | return -1; 125 | if (totte[i]*3.0 0; length--, buffer.fbuffer++) { 140 | s_in = *buffer.fbuffer; 141 | s->l1.dtmf.energy[0] += fsqr(s_in); 142 | for (i = 0; i < 8; i++) { 143 | s->l1.dtmf.tenergy[0][i] += COS(s->l1.dtmf.ph[i]) * s_in; 144 | s->l1.dtmf.tenergy[0][i+8] += SIN(s->l1.dtmf.ph[i]) * s_in; 145 | s->l1.dtmf.ph[i] += dtmf_phinc[i]; 146 | } 147 | if ((s->l1.dtmf.blkcount--) <= 0) { 148 | s->l1.dtmf.blkcount = BLOCKLEN; 149 | i = process_block(s); 150 | if (i != s->l1.dtmf.lastch && i >= 0) { 151 | if (!json_mode) { 152 | verbprintf(0, "DTMF: %c\n", dtmf_transl[i]); 153 | } 154 | else { 155 | cJSON *json_output = cJSON_CreateObject(); 156 | cJSON_AddStringToObject(json_output, "demod_name", "DTMF"); 157 | char digit[2] = {dtmf_transl[i], '\0'}; 158 | cJSON_AddStringToObject(json_output, "digit", digit); 159 | fprintf(stdout, "%s\n", cJSON_PrintUnformatted(json_output)); 160 | cJSON_Delete(json_output); 161 | } 162 | } 163 | s->l1.dtmf.lastch = i; 164 | } 165 | } 166 | } 167 | 168 | /* ---------------------------------------------------------------------- */ 169 | 170 | const struct demod_param demod_dtmf = { 171 | "DTMF", true, SAMPLE_RATE, 0, dtmf_init, dtmf_demod, NULL 172 | }; 173 | 174 | /* ---------------------------------------------------------------------- */ 175 | -------------------------------------------------------------------------------- /demod_dumpcsv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_dumpcsv.c -- dump data in CSV format 3 | * 4 | * Written and placed into the public domain by 5 | * Peter Shipley < peter.shipley@gmail.com > 6 | */ 7 | 8 | 9 | /* 10 | * Useful for piping to gnuplot 11 | * format is in time,value 12 | * where : 13 | * time is a float in ms 14 | * value is a float from the current data stream 15 | * 16 | */ 17 | 18 | /* ---------------------------------------------------------------------- */ 19 | 20 | #include "multimon.h" 21 | #include 22 | #include 23 | 24 | /* ---------------------------------------------------------------------- */ 25 | 26 | #define SAMPLING_RATE 22050 27 | #define SAMPLE_MS 22.050f 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | static void dumpcsv_init(struct demod_state *s) 32 | { 33 | memset(&s->l1.dumpcsv, 0, sizeof(s->l1.dumpcsv)); 34 | } 35 | 36 | /* ---------------------------------------------------------------------- */ 37 | 38 | 39 | static void dumpcsv_demod(struct demod_state *s, buffer_t buffer, int length) 40 | { 41 | const short *src; 42 | float f; 43 | int i; 44 | 45 | verbprintf(2, "dump_demod length=%d, current_sequence=%d\n", length, s->l1.dumpcsv.current_sequence); 46 | 47 | 48 | src = buffer.sbuffer; 49 | for ( i=0 ; i < length ; i++, src++) { 50 | f = (float) ( (i + s->l1.dumpcsv.current_sequence) / SAMPLE_MS ); 51 | 52 | /* cut back on superfluous plot points 53 | if (i > 0 && abs(src[-1] - *src ) < 40 ) 54 | continue; 55 | */ 56 | 57 | fprintf(stdout, "%.6f,%hd\n", f, *src); 58 | } 59 | 60 | // Save current count 61 | s->l1.dumpcsv.current_sequence = s->l1.dumpcsv.current_sequence + i; 62 | 63 | } 64 | 65 | /* ---------------------------------------------------------------------- */ 66 | 67 | const struct demod_param demod_dumpcsv = { 68 | "DUMPCSV", false, SAMPLING_RATE, 0, dumpcsv_init, dumpcsv_demod, NULL 69 | }; 70 | 71 | 72 | /* ---------------------------------------------------------------------- */ 73 | -------------------------------------------------------------------------------- /demod_dzvei.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_dzvei.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int dzvei_freq[16] = { 28 | PHINC(2200), PHINC(970), PHINC(1060), PHINC(1160), 29 | PHINC(1270), PHINC(1400), PHINC(1530), PHINC(1670), 30 | PHINC(1830), PHINC(2000), PHINC(825), PHINC(740), 31 | PHINC(2600), PHINC(885), PHINC(2400), PHINC(680) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void dzvei_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void dzvei_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void dzvei_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, dzvei_freq, demod_dzvei.name); 49 | } 50 | 51 | const struct demod_param demod_dzvei = { 52 | "DZVEI", true, SAMPLE_RATE, 0, dzvei_init, dzvei_demod, dzvei_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_eea.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_eea.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int eea_freq[16] = { 28 | PHINC(1981), PHINC(1124), PHINC(1197), PHINC(1275), 29 | PHINC(1358), PHINC(1446), PHINC(1540), PHINC(1640), 30 | PHINC(1747), PHINC(1860), PHINC(1055), PHINC(930), 31 | PHINC(2400), PHINC(991), PHINC(2110), PHINC(2247) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void eea_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void eea_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void eea_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, eea_freq, demod_eea.name); 49 | } 50 | 51 | const struct demod_param demod_eea = { 52 | "EEA", true, SAMPLE_RATE, 0, eea_init, eea_demod, eea_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_eia.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_eia.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int eia_freq[16] = { 28 | PHINC(600), PHINC(741), PHINC(882), PHINC(1023), 29 | PHINC(1164), PHINC(1305), PHINC(1446), PHINC(1587), 30 | PHINC(1728), PHINC(1869), PHINC(2151), PHINC(2433), 31 | PHINC(2010), PHINC(2292), PHINC(459), PHINC(1091) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void eia_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void eia_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void eia_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, eia_freq, demod_eia.name); 49 | } 50 | 51 | const struct demod_param demod_eia = { 52 | "EIA", true, SAMPLE_RATE, 0, eia_init, eia_demod, eia_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_fmsfsk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_fmsfsk.c -- 1200 baud FMS FSK demodulator 3 | * 4 | * Copyright (C) 2014, 2024 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | */ 20 | 21 | /* ---------------------------------------------------------------------- */ 22 | 23 | #include "multimon.h" 24 | #include "filter.h" 25 | #include 26 | #include 27 | 28 | /* ---------------------------------------------------------------------- */ 29 | 30 | /* 31 | * FSM signaling 1200 baud +/- 0.01% 32 | * "1" frequency: 1200 Hz 33 | * "0" frequency: 1800 Hz 34 | */ 35 | 36 | #define FREQ_1 1200 37 | #define FREQ_0 1800 38 | #define FREQ_SAMP 22050 39 | #define BAUD 1200 40 | #define SUBSAMP 2 41 | 42 | /* ---------------------------------------------------------------------- */ 43 | 44 | #define CORRLEN ((int)(FREQ_SAMP/BAUD)) 45 | #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) 46 | 47 | static float corr_1_i[CORRLEN]; 48 | static float corr_1_q[CORRLEN]; 49 | static float corr_0_i[CORRLEN]; 50 | static float corr_0_q[CORRLEN]; 51 | 52 | /* ---------------------------------------------------------------------- */ 53 | 54 | static void fmsfsk_init(struct demod_state *s) 55 | { 56 | float f; 57 | int i; 58 | 59 | fms_init(s); 60 | memset(&s->l1.fmsfsk, 0, sizeof(s->l1.fmsfsk)); 61 | for (f = 0, i = 0; i < CORRLEN; i++) { 62 | corr_1_i[i] = cos(f); 63 | corr_1_q[i] = sin(f); 64 | f += 2.0*M_PI*FREQ_1/FREQ_SAMP; 65 | } 66 | for (f = 0, i = 0; i < CORRLEN; i++) { 67 | corr_0_i[i] = cos(f); 68 | corr_0_q[i] = sin(f); 69 | f += 2.0*M_PI*FREQ_0/FREQ_SAMP; 70 | } 71 | } 72 | 73 | /* ---------------------------------------------------------------------- */ 74 | 75 | static void fmsfsk_demod(struct demod_state *s, buffer_t buffer, int length) 76 | { 77 | float f; 78 | unsigned char curbit; 79 | 80 | if (s->l1.fmsfsk.subsamp) { 81 | if (length <= (int)s->l1.fmsfsk.subsamp) { 82 | s->l1.fmsfsk.subsamp -= length; 83 | return; 84 | } 85 | buffer.fbuffer += s->l1.fmsfsk.subsamp; 86 | length -= s->l1.fmsfsk.subsamp; 87 | s->l1.fmsfsk.subsamp = 0; 88 | } 89 | for (; length > 0; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) { 90 | f = fsqr(mac(buffer.fbuffer, corr_1_i, CORRLEN)) + 91 | fsqr(mac(buffer.fbuffer, corr_1_q, CORRLEN)) - 92 | fsqr(mac(buffer.fbuffer, corr_0_i, CORRLEN)) - 93 | fsqr(mac(buffer.fbuffer, corr_0_q, CORRLEN)); 94 | s->l1.fmsfsk.dcd_shreg <<= 1; 95 | s->l1.fmsfsk.dcd_shreg |= (f > 0); 96 | verbprintf(10, "%c", '0'+(s->l1.fmsfsk.dcd_shreg & 1)); 97 | /* 98 | * check if transition 99 | */ 100 | if ((s->l1.fmsfsk.dcd_shreg ^ (s->l1.fmsfsk.dcd_shreg >> 1)) & 1) { 101 | if (s->l1.fmsfsk.sphase < (0x8000u-(SPHASEINC/2))) 102 | s->l1.fmsfsk.sphase += SPHASEINC/8; 103 | else 104 | s->l1.fmsfsk.sphase -= SPHASEINC/8; 105 | } 106 | s->l1.fmsfsk.sphase += SPHASEINC; 107 | if (s->l1.fmsfsk.sphase >= 0x10000u) { 108 | s->l1.fmsfsk.sphase &= 0xffffu; 109 | curbit = s->l1.fmsfsk.dcd_shreg & 1; 110 | verbprintf(9, "FMS %c ", '0'+curbit); 111 | fms_rxbit(s, curbit); 112 | } 113 | } 114 | s->l1.fmsfsk.subsamp = -length; 115 | } 116 | 117 | /* ---------------------------------------------------------------------- */ 118 | 119 | const struct demod_param demod_fmsfsk = { 120 | "FMSFSK", true, FREQ_SAMP, CORRLEN, fmsfsk_init, fmsfsk_demod, NULL 121 | }; 122 | 123 | /* ---------------------------------------------------------------------- */ 124 | -------------------------------------------------------------------------------- /demod_fsk96.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_fsk96.c -- FSK 9600 baud demodulator (G3RUH) 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "multimon.h" 25 | #include "filter.h" 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | #define FREQ_SAMP 22050 32 | #define BAUD 9600 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | #define DESCRAM_TAP1 0x20000 37 | #define DESCRAM_TAP2 0x01000 38 | #define DESCRAM_TAP3 0x00001 39 | 40 | #define DESCRAM_TAPSH1 17 41 | #define DESCRAM_TAPSH2 12 42 | #define DESCRAM_TAPSH3 0 43 | 44 | #define SCRAM_TAP1 0x20000 /* X^17 */ 45 | #define SCRAM_TAPN 0x00021 /* X^0+X^5 */ 46 | 47 | /* --------------------------------------------------------------------- */ 48 | 49 | #define FILTLEN 24 50 | #define UPSAMP 3 51 | 52 | static const float inp_filt[3][24] = { 53 | { 0.000440, -0.001198, -0.000493, 0.003648, 54 | -0.000630, -0.008433, 0.005567, 0.015557, 55 | -0.019931, -0.026514, 0.079822, 0.181779, 56 | 0.124956, -0.002471, -0.032062, 0.008024, 57 | 0.012568, -0.006559, -0.004235, 0.003711, 58 | 0.000909, -0.001520, -0.000018, 0.000709}, 59 | { 0.000686, -0.000618, -0.001332, 0.002494, 60 | 0.002258, -0.007308, -0.001538, 0.016708, 61 | -0.004897, -0.035748, 0.034724, 0.161417, 62 | 0.161417, 0.034724, -0.035748, -0.004897, 63 | 0.016708, -0.001538, -0.007308, 0.002258, 64 | 0.002494, -0.001332, -0.000618, 0.000686}, 65 | { 0.000709, -0.000018, -0.001520, 0.000909, 66 | 0.003711, -0.004235, -0.006559, 0.012568, 67 | 0.008024, -0.032062, -0.002471, 0.124956, 68 | 0.181779, 0.079822, -0.026514, -0.019931, 69 | 0.015557, 0.005567, -0.008433, -0.000630, 70 | 0.003648, -0.000493, -0.001198, 0.000440} 71 | }; 72 | 73 | #define SPHASEINC (0x10000u*BAUD/FREQ_SAMP/UPSAMP) 74 | 75 | /* ---------------------------------------------------------------------- */ 76 | 77 | static void fsk96_init(struct demod_state *s) 78 | { 79 | hdlc_init(s); 80 | memset(&s->l1.fsk96, 0, sizeof(s->l1.fsk96)); 81 | } 82 | 83 | /* ---------------------------------------------------------------------- */ 84 | 85 | static void fsk96_demod(struct demod_state *s, buffer_t buffer, int length) 86 | { 87 | float f; 88 | unsigned char curbit; 89 | int i; 90 | unsigned int descx; 91 | 92 | for (; length > 0; length--, buffer.fbuffer++) { 93 | for (i = 0; i < UPSAMP; i++) { 94 | f = mac(buffer.fbuffer, inp_filt[i], FILTLEN); 95 | s->l1.fsk96.dcd_shreg <<= 1; 96 | s->l1.fsk96.dcd_shreg |= (f > 0); 97 | verbprintf(10, "%c", '0'+(s->l1.fsk96.dcd_shreg & 1)); 98 | /* 99 | * check if transition 100 | */ 101 | if ((s->l1.fsk96.dcd_shreg ^ (s->l1.fsk96.dcd_shreg >> 1)) & 1) { 102 | if (s->l1.fsk96.sphase < (0x8000u-(SPHASEINC/2))) 103 | s->l1.fsk96.sphase += SPHASEINC/8; 104 | else 105 | s->l1.fsk96.sphase -= SPHASEINC/8; 106 | } 107 | s->l1.fsk96.sphase += SPHASEINC; 108 | if (s->l1.fsk96.sphase >= 0x10000u) { 109 | s->l1.fsk96.sphase &= 0xffffu; 110 | s->l1.fsk96.descram <<= 1; 111 | s->l1.fsk96.descram |= s->l1.fsk96.dcd_shreg & 1; 112 | descx = s->l1.fsk96.descram ^ (s->l1.fsk96.descram >> 1); 113 | curbit = ((descx >> DESCRAM_TAPSH1) ^ (descx >> DESCRAM_TAPSH2) ^ 114 | (descx >> DESCRAM_TAPSH3) ^ 1) & 1; 115 | verbprintf(9, " %c ", '0'+curbit); 116 | hdlc_rxbit(s, curbit); 117 | } 118 | } 119 | } 120 | } 121 | 122 | /* ---------------------------------------------------------------------- */ 123 | 124 | const struct demod_param demod_fsk9600 = { 125 | "FSK9600", true, FREQ_SAMP, FILTLEN, fsk96_init, fsk96_demod, NULL 126 | }; 127 | 128 | /* ---------------------------------------------------------------------- */ 129 | -------------------------------------------------------------------------------- /demod_hapn48.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_hapn48.c -- HAPN 4800 baud demodulator (G3RUH) 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "multimon.h" 25 | #include "filter.h" 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | #define FREQ_SAMP 22050 32 | #define BAUD 4800 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | #define SPHASEINC (0x10000u*BAUD/FREQ_SAMP) 37 | 38 | /* ---------------------------------------------------------------------- */ 39 | 40 | static void hapn48_init(struct demod_state *s) 41 | { 42 | hdlc_init(s); 43 | memset(&s->l1.hapn48, 0, sizeof(s->l1.hapn48)); 44 | } 45 | 46 | /* ---------------------------------------------------------------------- */ 47 | 48 | static void hapn48_demod(struct demod_state *s, buffer_t buffer, int length) 49 | { 50 | unsigned int curbit; 51 | 52 | for (; length > 0; length--, buffer.fbuffer++) { 53 | s->l1.hapn48.lvlhi *= 0.999; 54 | s->l1.hapn48.lvllo *= 0.999; 55 | if (buffer.fbuffer[1] > s->l1.hapn48.lvlhi) 56 | s->l1.hapn48.lvlhi = buffer.fbuffer[1]; 57 | if (buffer.fbuffer[1] < s->l1.hapn48.lvllo) 58 | s->l1.hapn48.lvllo = buffer.fbuffer[1]; 59 | s->l1.hapn48.shreg = (s->l1.hapn48.shreg << 1) | 60 | (s->l1.hapn48.shreg & 1); 61 | if (buffer.fbuffer[1] > s->l1.hapn48.lvlhi * 0.5) { 62 | s->l1.hapn48.shreg |= 1; 63 | } else if (buffer.fbuffer[1] < s->l1.hapn48.lvllo * 0.5) { 64 | s->l1.hapn48.shreg &= ~1; 65 | } 66 | verbprintf(10, "%c", '0' + (s->l1.hapn48.shreg & 1)); 67 | s->l1.hapn48.sphase += SPHASEINC; 68 | if (((s->l1.hapn48.shreg >> 1) ^ s->l1.hapn48.shreg) & 1) { 69 | if (s->l1.hapn48.sphase >= 0x8000+SPHASEINC/2) 70 | s->l1.hapn48.sphase -= 0x800; 71 | else 72 | s->l1.hapn48.sphase += 0x800; 73 | } 74 | #ifdef HAPN48_CURSYNC 75 | int cursync = 0; 76 | if (buffer.fbuffer[1] > s->l1.hapn48.lvlhi * 0.5) { 77 | cursync = (buffer.fbuffer[1] > buffer.fbuffer[0] && buffer.fbuffer[1] > buffer.fbuffer[2]); 78 | } else if (buffer.fbuffer[1] < s->l1.hapn48.lvllo * 0.5) { 79 | cursync = (buffer.fbuffer[1] < buffer.fbuffer[0] && buffer.fbuffer[1] < buffer.fbuffer[2]); 80 | } 81 | if (cursync) { 82 | if (((s->l1.hapn48.sphase-0x8000)&0xffffu) >= 0x8000+SPHASEINC/2) 83 | s->l1.hapn48.sphase -= 0x800; 84 | else 85 | s->l1.hapn48.sphase += 0x800; 86 | } 87 | #endif 88 | if (s->l1.hapn48.sphase >= 0x10000) { 89 | s->l1.hapn48.sphase &= 0xffff; 90 | curbit = ((s->l1.hapn48.shreg >> 4) ^ s->l1.hapn48.shreg ^ 1) & 1; 91 | verbprintf(9, " %c ", '0'+curbit); 92 | hdlc_rxbit(s, curbit); 93 | } 94 | } 95 | } 96 | 97 | /* ---------------------------------------------------------------------- */ 98 | 99 | const struct demod_param demod_hapn4800 = { 100 | "HAPN4800", true, FREQ_SAMP, 3, hapn48_init, hapn48_demod, NULL 101 | }; 102 | 103 | /* ---------------------------------------------------------------------- */ 104 | -------------------------------------------------------------------------------- /demod_poc12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_poc12.c -- 1200 baud POCSAG demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * Copyright (C) 2024 7 | * Marat Fayzullin (luarvique@gmail.com) 8 | * 9 | * POCSAG (Post Office Code Standard Advisory Group) 10 | * Radio Paging Decoder 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation; either version 2 of the License, or 15 | * (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 | */ 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | 29 | #include "multimon.h" 30 | #include "filter.h" 31 | #include 32 | #include 33 | #include 34 | 35 | /* ---------------------------------------------------------------------- */ 36 | 37 | #define FREQ_SAMP 22050 38 | #define BAUD 1200 39 | #define SUBSAMP 2 40 | #define FILTLEN 1 41 | 42 | /* ---------------------------------------------------------------------- */ 43 | 44 | #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) 45 | 46 | /* ---------------------------------------------------------------------- */ 47 | 48 | static void poc12_init(struct demod_state *s) 49 | { 50 | pocsag_init(s); 51 | memset(&s->l1.poc12, 0, sizeof(s->l1.poc12)); 52 | } 53 | 54 | /* ---------------------------------------------------------------------- */ 55 | 56 | static void poc12_demod(struct demod_state *s, buffer_t buffer, int length) 57 | { 58 | if (s->l1.poc12.subsamp) { 59 | if (length <= (int)s->l1.poc12.subsamp) { 60 | s->l1.poc12.subsamp -= length; 61 | return; 62 | } 63 | buffer.fbuffer += s->l1.poc12.subsamp; 64 | length -= s->l1.poc12.subsamp; 65 | s->l1.poc12.subsamp = 0; 66 | } 67 | for (; length > 0; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) { 68 | s->l1.poc12.dcd_shreg <<= 1; 69 | s->l1.poc12.dcd_shreg |= ((*buffer.fbuffer) > 0); 70 | verbprintf(10, "%c", '0'+(s->l1.poc12.dcd_shreg & 1)); 71 | /* 72 | * check if transition 73 | */ 74 | if ((s->l1.poc12.dcd_shreg ^ (s->l1.poc12.dcd_shreg >> 1)) & 1) { 75 | if (s->l1.poc12.sphase < (0x8000u-(SPHASEINC/2))) 76 | s->l1.poc12.sphase += SPHASEINC/8; 77 | else 78 | s->l1.poc12.sphase -= SPHASEINC/8; 79 | } 80 | s->l1.poc12.sphase += SPHASEINC; 81 | if (s->l1.poc12.sphase >= 0x10000u) { 82 | s->l1.poc12.sphase &= 0xffffu; 83 | pocsag_rxbit(s, s->l1.poc12.dcd_shreg & 1); 84 | } 85 | } 86 | s->l1.poc12.subsamp = -length; 87 | } 88 | 89 | static void poc12_deinit(struct demod_state *s) 90 | { 91 | pocsag_deinit(s); 92 | } 93 | 94 | /* ---------------------------------------------------------------------- */ 95 | 96 | const struct demod_param demod_poc12 = { 97 | "POCSAG1200", true, FREQ_SAMP, FILTLEN, poc12_init, poc12_demod, poc12_deinit 98 | }; 99 | 100 | /* ---------------------------------------------------------------------- */ 101 | -------------------------------------------------------------------------------- /demod_poc24.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_poc24.c -- 2400 baud POCSAG demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * POCSAG (Post Office Code Standard Advisory Group) 8 | * Radio Paging Decoder 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 | */ 24 | 25 | /* ---------------------------------------------------------------------- */ 26 | 27 | #include "multimon.h" 28 | #include "filter.h" 29 | #include 30 | #include 31 | /* ---------------------------------------------------------------------- */ 32 | 33 | #define FREQ_SAMP 22050 34 | #define BAUD 2400 35 | #define FILTLEN 1 36 | 37 | /* ---------------------------------------------------------------------- */ 38 | 39 | #define SPHASEINC (0x10000u*BAUD/FREQ_SAMP) 40 | 41 | /* ---------------------------------------------------------------------- */ 42 | 43 | static void poc24_init(struct demod_state *s) 44 | { 45 | pocsag_init(s); 46 | memset(&s->l1.poc24, 0, sizeof(s->l1.poc24)); 47 | } 48 | 49 | /* ---------------------------------------------------------------------- */ 50 | 51 | static void poc24_demod(struct demod_state *s, buffer_t buffer, int length) 52 | { 53 | for (; length > 0; length--, buffer.fbuffer++) { 54 | s->l1.poc24.dcd_shreg <<= 1; 55 | s->l1.poc24.dcd_shreg |= ((*buffer.fbuffer) > 0); 56 | verbprintf(10, "%c", '0'+(s->l1.poc24.dcd_shreg & 1)); 57 | /* 58 | * check if transition 59 | */ 60 | if ((s->l1.poc24.dcd_shreg ^ (s->l1.poc24.dcd_shreg >> 1)) & 1) { 61 | if (s->l1.poc24.sphase < (0x8000u-(SPHASEINC/2))) 62 | s->l1.poc24.sphase += SPHASEINC/8; 63 | else 64 | s->l1.poc24.sphase -= SPHASEINC/8; 65 | } 66 | s->l1.poc24.sphase += SPHASEINC; 67 | if (s->l1.poc24.sphase >= 0x10000u) { 68 | s->l1.poc24.sphase &= 0xffffu; 69 | pocsag_rxbit(s, s->l1.poc24.dcd_shreg & 1); 70 | } 71 | } 72 | } 73 | 74 | static void poc24_deinit(struct demod_state *s) 75 | { 76 | pocsag_deinit(s); 77 | } 78 | 79 | /* ---------------------------------------------------------------------- */ 80 | 81 | const struct demod_param demod_poc24 = { 82 | "POCSAG2400", true, FREQ_SAMP, FILTLEN, poc24_init, poc24_demod, poc24_deinit 83 | }; 84 | 85 | /* ---------------------------------------------------------------------- */ 86 | -------------------------------------------------------------------------------- /demod_poc5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_poc5.c -- 512 baud POCSAG demodulator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * Copyright (C) 2024 7 | * Marat Fayzullin (luarvique@gmail.com) 8 | * 9 | * POCSAG (Post Office Code Standard Advisory Group) 10 | * Radio Paging Decoder 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation; either version 2 of the License, or 15 | * (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 | */ 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | 29 | #include "multimon.h" 30 | #include "filter.h" 31 | #include 32 | #include 33 | /* ---------------------------------------------------------------------- */ 34 | 35 | #define FREQ_SAMP 22050 36 | #define BAUD 512 37 | #define SUBSAMP 5 38 | #define FILTLEN 1 39 | 40 | /* ---------------------------------------------------------------------- */ 41 | 42 | #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) 43 | 44 | /* ---------------------------------------------------------------------- */ 45 | 46 | static void poc5_init(struct demod_state *s) 47 | { 48 | pocsag_init(s); 49 | memset(&s->l1.poc5, 0, sizeof(s->l1.poc5)); 50 | } 51 | 52 | /* ---------------------------------------------------------------------- */ 53 | 54 | static void poc5_demod(struct demod_state *s, buffer_t buffer, int length) 55 | { 56 | if (s->l1.poc5.subsamp) { 57 | if (length <= (int)s->l1.poc5.subsamp) { 58 | s->l1.poc5.subsamp -= length; 59 | return; 60 | } 61 | buffer.fbuffer += s->l1.poc5.subsamp; 62 | length -= s->l1.poc5.subsamp; 63 | s->l1.poc5.subsamp = 0; 64 | } 65 | for (; length > 0; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) { 66 | s->l1.poc5.dcd_shreg <<= 1; 67 | s->l1.poc5.dcd_shreg |= ((*buffer.fbuffer) > 0); 68 | verbprintf(10, "%c", '0'+(s->l1.poc5.dcd_shreg & 1)); 69 | /* 70 | * check if transition 71 | */ 72 | if ((s->l1.poc5.dcd_shreg ^ (s->l1.poc5.dcd_shreg >> 1)) & 1) { 73 | if (s->l1.poc5.sphase < (0x8000u-(SPHASEINC/2))) 74 | s->l1.poc5.sphase += SPHASEINC/8; 75 | else 76 | s->l1.poc5.sphase -= SPHASEINC/8; 77 | } 78 | s->l1.poc5.sphase += SPHASEINC; 79 | if (s->l1.poc5.sphase >= 0x10000u) { 80 | s->l1.poc5.sphase &= 0xffffu; 81 | pocsag_rxbit(s, s->l1.poc5.dcd_shreg & 1); 82 | } 83 | } 84 | s->l1.poc5.subsamp = -length; 85 | } 86 | 87 | static void poc5_deinit(struct demod_state *s) 88 | { 89 | pocsag_deinit(s); 90 | } 91 | 92 | /* ---------------------------------------------------------------------- */ 93 | 94 | const struct demod_param demod_poc5 = { 95 | "POCSAG512", true, FREQ_SAMP, FILTLEN, poc5_init, poc5_demod, poc5_deinit 96 | }; 97 | 98 | /* ---------------------------------------------------------------------- */ 99 | -------------------------------------------------------------------------------- /demod_pzvei.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_pzvei.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int pzvei_freq[16] = { 28 | PHINC(2400), PHINC(1060), PHINC(1160), PHINC(1270), 29 | PHINC(1400), PHINC(1530), PHINC(1670), PHINC(1830), 30 | PHINC(2000), PHINC(2200), PHINC(970), PHINC(810), 31 | PHINC(2800), PHINC(885), PHINC(2400), PHINC(680) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void pzvei_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void pzvei_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void pzvei_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, pzvei_freq, demod_pzvei.name); 49 | } 50 | 51 | const struct demod_param demod_pzvei = { 52 | "PZVEI", true, SAMPLE_RATE, 0, pzvei_init, pzvei_demod, pzvei_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_ufsk12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_ufsk12.c -- 1200 baud FSK demodulator 3 | * 4 | * Copyright (C) 2007, 2024 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | */ 20 | 21 | /* ---------------------------------------------------------------------- */ 22 | 23 | #include "multimon.h" 24 | #include "filter.h" 25 | #include 26 | #include 27 | 28 | /* ---------------------------------------------------------------------- */ 29 | 30 | /* 31 | * Standard TCM3105 clock frequency: 4.4336MHz 32 | * Mark frequency: 2200 Hz 33 | * Space frequency: 1200 Hz 34 | */ 35 | 36 | #define FREQ_MARK 1200 37 | #define FREQ_SPACE 2200 38 | #define FREQ_SAMP 22050 39 | #define BAUD 1200 40 | #define SUBSAMP 2 41 | 42 | /* ---------------------------------------------------------------------- */ 43 | 44 | #define CORRLEN ((int)(FREQ_SAMP/BAUD)) 45 | #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) 46 | 47 | static float corr_mark_i[CORRLEN]; 48 | static float corr_mark_q[CORRLEN]; 49 | static float corr_space_i[CORRLEN]; 50 | static float corr_space_q[CORRLEN]; 51 | 52 | /* ---------------------------------------------------------------------- */ 53 | 54 | static void ufsk12_init(struct demod_state *s) 55 | { 56 | float f; 57 | int i; 58 | 59 | uart_init(s); 60 | memset(&s->l1.ufsk12, 0, sizeof(s->l1.ufsk12)); 61 | for (f = 0, i = 0; i < CORRLEN; i++) { 62 | corr_mark_i[i] = cos(f); 63 | corr_mark_q[i] = sin(f); 64 | f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; 65 | } 66 | for (f = 0, i = 0; i < CORRLEN; i++) { 67 | corr_space_i[i] = cos(f); 68 | corr_space_q[i] = sin(f); 69 | f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; 70 | } 71 | } 72 | 73 | /* ---------------------------------------------------------------------- */ 74 | 75 | static void ufsk12_demod(struct demod_state *s, buffer_t buffer, int length) 76 | { 77 | float f; 78 | unsigned char curbit; 79 | 80 | if (s->l1.ufsk12.subsamp) { 81 | if (length <= (int)s->l1.ufsk12.subsamp) { 82 | s->l1.ufsk12.subsamp -= length; 83 | return; 84 | } 85 | buffer.fbuffer += s->l1.ufsk12.subsamp; 86 | length -= s->l1.ufsk12.subsamp; 87 | s->l1.ufsk12.subsamp = 0; 88 | } 89 | for (; length > 0; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) { 90 | f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) + 91 | fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) - 92 | fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) - 93 | fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN)); 94 | s->l1.ufsk12.dcd_shreg <<= 1; 95 | s->l1.ufsk12.dcd_shreg |= (f > 0); 96 | verbprintf(10, "%c", '0'+(s->l1.ufsk12.dcd_shreg & 1)); 97 | /* 98 | * check if transition 99 | */ 100 | if ((s->l1.ufsk12.dcd_shreg ^ (s->l1.ufsk12.dcd_shreg >> 1)) & 1) { 101 | if (s->l1.ufsk12.sphase < (0x8000u-(SPHASEINC/2))) 102 | s->l1.ufsk12.sphase += SPHASEINC/8; 103 | else 104 | s->l1.ufsk12.sphase -= SPHASEINC/8; 105 | } 106 | s->l1.ufsk12.sphase += SPHASEINC; 107 | if (s->l1.ufsk12.sphase >= 0x10000u) { 108 | s->l1.ufsk12.sphase &= 0xffffu; 109 | curbit = s->l1.ufsk12.dcd_shreg & 1; 110 | verbprintf(9, " %c ", '0'+curbit); 111 | uart_rxbit(s, curbit); 112 | } 113 | } 114 | s->l1.ufsk12.subsamp = -length; 115 | } 116 | 117 | /* ---------------------------------------------------------------------- */ 118 | 119 | const struct demod_param demod_ufsk1200 = { 120 | "UFSK1200", true, FREQ_SAMP, CORRLEN, ufsk12_init, ufsk12_demod, NULL 121 | }; 122 | 123 | /* ---------------------------------------------------------------------- */ 124 | -------------------------------------------------------------------------------- /demod_x10.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_x10.c -- dump data in CSV format 3 | * 4 | * Written and placed into the public domain by 5 | * Peter Shipley < peter.shipley@gmail.com > 6 | */ 7 | 8 | 9 | /* 10 | * Useful for piping to gnuplot 11 | * format is in time,value 12 | * where : 13 | * time is a float in ms 14 | * value is a float from the current data stream 15 | * 16 | */ 17 | 18 | /* ---------------------------------------------------------------------- */ 19 | #include "multimon.h" 20 | #include 21 | #include 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | static const char housecode[] = "MECKOGAINFDLPHBJ"; 25 | 26 | /* ---------------------------------------------------------------------- */ 27 | 28 | #define SAMPLING_RATE 22050 29 | 30 | /* Samples in a MS */ 31 | #define SAMPLE_MS 22.050f 32 | 33 | #define SAMPLING_THRESHOLD_HIGH 13000 34 | #define SAMPLING_THRESHOLD_LOW 9000 35 | #define SAMPLING_THRESHOLD_PULSE_WIDTH 40 36 | 37 | #define SAMPLING_TIMEOUT 220 38 | 39 | /* ---------------------------------------------------------------------- */ 40 | 41 | static void x10_init(struct demod_state *s) 42 | { 43 | memset(&s->l1.x10, 0, sizeof(s->l1.x10)); 44 | } 45 | 46 | /* ---------------------------------------------------------------------- */ 47 | 48 | 49 | /* 50 | struct l1_state_x10 { 51 | uint32_t current_sequence; 52 | uint32_t last_rise; 53 | short current_state; 54 | short current_stage; 55 | } x10; 56 | 57 | current_state indicates if the last sample was "high" or "low" 58 | current_stage stage indicator : 59 | 0 = waiting for sync header 60 | 1 = sync part 1 61 | 2 = sync part 2 62 | 3 = reading data 63 | 64 | */ 65 | 66 | 67 | void printbits(unsigned char v) { 68 | int i; // for C89 compatability 69 | for(i = 7; i >= 0; i--) fputc( ('0' + ((v >> i) & 1)), stderr); 70 | } 71 | 72 | static void x10_report(struct demod_state *s, int clr) { 73 | char h, u; 74 | 75 | if (s->l1.x10.bi == 0) 76 | return; 77 | 78 | fprintf(stderr, "bstring = %s\n", s->l1.x10.bstring); 79 | 80 | fprintf(stderr, "bytes = "); 81 | 82 | printbits(s->l1.x10.b[0]); 83 | fputs(" ", stderr); 84 | 85 | printbits(s->l1.x10.b[1]); 86 | fputs(" ", stderr); 87 | 88 | printbits(s->l1.x10.b[2]); 89 | fputs(" ", stderr); 90 | 91 | printbits(s->l1.x10.b[3]); 92 | fputs("\n", stderr); 93 | 94 | fprintf(stderr, "\t %.2hhX %.2hhX %.2hhX %.2hhX\n", s->l1.x10.b[0], s->l1.x10.b[1], s->l1.x10.b[2], s->l1.x10.b[3]); 95 | 96 | if ( s->l1.x10.bi == 32 ) { 97 | u = 0; 98 | h = housecode[(s->l1.x10.b[0] & 0x0f)]; 99 | if ( s->l1.x10.b[2] & 0x08 ) 100 | u |= 0x01; 101 | if ( s->l1.x10.b[2] & 0x10 ) 102 | u |= 0x02; 103 | if ( s->l1.x10.b[2] & 0x02 ) 104 | u |= 0x04; 105 | if ( s->l1.x10.b[0] & 0x20 ) 106 | u |= 0x08; 107 | 108 | u++; 109 | fprintf(stderr, "housecode = %c %d\n", h, u); 110 | } 111 | 112 | 113 | if ( clr || s->l1.x10.bi == 32 ) { 114 | s->l1.x10.bi = 0; 115 | memset(s->l1.x10.bstring, 0, sizeof(s->l1.x10.bstring)); 116 | memset(s->l1.x10.b, 0, sizeof(s->l1.x10.b)); 117 | } 118 | 119 | 120 | } 121 | 122 | static void x10_demod(struct demod_state *s, buffer_t buffer, int length) 123 | { 124 | const short *src; 125 | int i; 126 | int bits = 0; 127 | 128 | verbprintf(2, "x10_demod length=%d, current_sequence=%d\n", length, s->l1.x10.current_sequence); 129 | 130 | src = buffer.sbuffer; 131 | for ( i=0 ; i < length ; i++, src++) { 132 | 133 | // Start of 9ms high preable (part 1) 134 | if ( s->l1.x10.current_stage == 0 ) { 135 | if ( *src >= SAMPLING_THRESHOLD_HIGH ) { 136 | s->l1.x10.last_rise = i + s->l1.x10.current_sequence; 137 | s->l1.x10.current_state = 1; 138 | s->l1.x10.current_stage = 1; 139 | } 140 | continue; 141 | 142 | // Start of 4.5ms low preable (part 2) 143 | } else if ( s->l1.x10.current_stage == 1 ) { 144 | 145 | if ( *src <= SAMPLING_THRESHOLD_LOW ) { 146 | int j; 147 | 148 | s->l1.x10.current_state = 0; 149 | 150 | j = i + s->l1.x10.current_sequence - s->l1.x10.last_rise; 151 | /* 152 | fprintf(stderr, "stage 1->2 drop (%d) %0.4f ms\n", 153 | j, (float) (j / SAMPLE_MS) ); 154 | */ 155 | 156 | if ( j >= 176 && j <= 210 ) { 157 | s->l1.x10.current_stage = 2; 158 | s->l1.x10.last_rise = i + s->l1.x10.current_sequence; 159 | } else { 160 | verbprintf(9, "stage 1 fail1\n"); 161 | s->l1.x10.current_stage = 0; 162 | } 163 | continue; 164 | 165 | } else { 166 | continue; 167 | } 168 | 169 | 170 | // End of preable? start of data 171 | } else if ( s->l1.x10.current_stage == 2 ) { 172 | if ( *src >= SAMPLING_THRESHOLD_HIGH ) { 173 | int j; 174 | 175 | s->l1.x10.current_state = 1; 176 | 177 | j = i + s->l1.x10.current_sequence - s->l1.x10.last_rise; 178 | /* 179 | fprintf(stderr, "stage 2->3 drop (%d) %0.4f ms\n", 180 | j, (float) (j / SAMPLE_MS) ); 181 | */ 182 | 183 | // End of 4.5ms low preable 184 | if ( j >= 90 && j <= 104 ) { 185 | // fprintf(stderr, "stage 3 drop\n"); 186 | s->l1.x10.current_stage = 3; 187 | s->l1.x10.last_rise = i + s->l1.x10.current_sequence; 188 | } else { 189 | verbprintf(2, "preamble 2nd stage fail\n"); 190 | s->l1.x10.current_stage = 0; 191 | } 192 | 193 | } 194 | continue; 195 | 196 | // Data stage 197 | } else if ( s->l1.x10.current_stage == 3 ) { 198 | 199 | if ( s->l1.x10.current_state == 0 ) { 200 | int j; 201 | 202 | j = (i + s->l1.x10.current_sequence) - s->l1.x10.last_rise; 203 | 204 | if ( *src >= SAMPLING_THRESHOLD_HIGH ) { 205 | 206 | s->l1.x10.current_state = 1; 207 | bits++; 208 | verbprintf(3, "stage 3 rise (%d) %0.4f ms\n", j, (float) (j / SAMPLE_MS) ); 209 | 210 | // fprintf(stderr, "stage 3 b %d %d %x\n", ( s->l1.x10.bi / 8 ), ( s->l1.x10.bi % 8 ), ( 1<< ( s->l1.x10.bi % 8 ) ) ); 211 | 212 | 213 | s->l1.x10.last_rise = i + s->l1.x10.current_sequence; 214 | 215 | if ( j > SAMPLING_THRESHOLD_PULSE_WIDTH ) { 216 | s->l1.x10.bstring[(int)s->l1.x10.bi] = '1'; 217 | s->l1.x10.b[ ( s->l1.x10.bi / 8 ) ] |= ( 1<< ( s->l1.x10.bi % 8 ) ); 218 | } else { 219 | s->l1.x10.bstring[(int)s->l1.x10.bi] = '0'; 220 | } 221 | s->l1.x10.bi++; 222 | 223 | 224 | } else { 225 | if ( j > SAMPLING_TIMEOUT ) { // if low for more then 10ms (appox) 226 | verbprintf(2, "Data stage end ( timeout )\n"); 227 | s->l1.x10.current_stage = 0; 228 | // fprintf(stderr, "bits = %d\n", bits); 229 | x10_report(s, 1); 230 | } 231 | } 232 | 233 | } else if ( s->l1.x10.current_state == 1 ) { 234 | if ( *src < SAMPLING_THRESHOLD_LOW ) { 235 | s->l1.x10.current_state = 0; 236 | } 237 | continue; 238 | 239 | } else { 240 | fprintf(stderr, "bad state = %d\n", s->l1.x10.current_state ); 241 | s->l1.x10.current_stage = 0; 242 | continue; 243 | } 244 | 245 | } 246 | } 247 | 248 | // Save current count 249 | s->l1.x10.current_sequence = s->l1.x10.current_sequence + i; 250 | if ( bits ) { 251 | fprintf(stderr, "Bits = %d\n", bits); 252 | x10_report(s, 0); 253 | } 254 | 255 | } 256 | 257 | 258 | /* ---------------------------------------------------------------------- */ 259 | 260 | const struct demod_param demod_x10 = { 261 | "X10", false, SAMPLING_RATE, 0, x10_init, x10_demod, NULL 262 | }; 263 | 264 | 265 | /* ---------------------------------------------------------------------- */ 266 | -------------------------------------------------------------------------------- /demod_zvei1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_zvei1.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int zvei1_freq[16] = { 28 | PHINC(2400), PHINC(1060), PHINC(1160), PHINC(1270), 29 | PHINC(1400), PHINC(1530), PHINC(1670), PHINC(1830), 30 | PHINC(2000), PHINC(2200), PHINC(2800), PHINC(810), 31 | PHINC(970), PHINC(885), PHINC(2600), PHINC(680) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void zvei1_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void zvei1_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void zvei1_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, zvei1_freq, demod_zvei1.name); 49 | } 50 | 51 | const struct demod_param demod_zvei1 = { 52 | "ZVEI1", true, SAMPLE_RATE, 0, zvei1_init, zvei1_demod, zvei1_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_zvei2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_zvei2.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int zvei2_freq[16] = { 28 | PHINC(2400), PHINC(1060), PHINC(1160), PHINC(1270), 29 | PHINC(1400), PHINC(1530), PHINC(1670), PHINC(1830), 30 | PHINC(2000), PHINC(2200), PHINC(885), PHINC(825), 31 | PHINC(740), PHINC(680), PHINC(970), PHINC(2600) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void zvei2_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void zvei2_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void zvei2_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, zvei2_freq, demod_zvei2.name); 49 | } 50 | 51 | const struct demod_param demod_zvei2 = { 52 | "ZVEI2", true, SAMPLE_RATE, 0, zvei2_init, zvei2_demod, zvei2_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demod_zvei3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * demod_zvei3.c 3 | * 4 | * Copyright (C) 2013 5 | * Elias Oenal (EliasOenal@gmail.com) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #define SAMPLE_RATE 22050 23 | #define PHINC(x) ((x)*0x10000/SAMPLE_RATE) 24 | 25 | #include "multimon.h" 26 | 27 | static const unsigned int zvei3_freq[16] = { 28 | PHINC(2400), PHINC(1060), PHINC(1160), PHINC(1270), 29 | PHINC(1400), PHINC(1530), PHINC(1670), PHINC(1830), 30 | PHINC(2000), PHINC(2200), PHINC(885), PHINC(810), 31 | PHINC(2800), PHINC(680), PHINC(970), PHINC(2600) 32 | }; 33 | 34 | /* ---------------------------------------------------------------------- */ 35 | 36 | static void zvei3_init(struct demod_state *s) 37 | { 38 | selcall_init(s); 39 | } 40 | 41 | static void zvei3_deinit(struct demod_state *s) 42 | { 43 | selcall_deinit(s); 44 | } 45 | 46 | static void zvei3_demod(struct demod_state *s, buffer_t buffer, int length) 47 | { 48 | selcall_demod(s, buffer.fbuffer, length, zvei3_freq, demod_zvei3.name); 49 | } 50 | 51 | const struct demod_param demod_zvei3 = { 52 | "ZVEI3", true, SAMPLE_RATE, 0, zvei3_init, zvei3_demod, zvei3_deinit 53 | }; 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /example/README-dumpcsv.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | To generate a png from a wav file 5 | 6 | generate a .csv file from the data : 7 | 8 | multimon-ng -q -t wav -a DUMPCSV x10rf.wav > x10rf.csv 9 | 10 | use gnuplot to generate a PNG of the data 11 | 12 | gnuplot -e "plot_data_file='x10rf'" dumpcsv_png.txt 13 | 14 | there should be a file named x10rf.png 15 | 16 | -------------------------------------------------------------------------------- /example/dumpcsv_png.txt: -------------------------------------------------------------------------------- 1 | set terminal png size 2600,500 2 | #set terminal png size 1920,500 3 | #set terminal png size 800,150 4 | set datafile separator "," 5 | set xlabel "Time (ms)" 6 | set ylabel "Arbitrary Power (dB?)" 7 | set grid 8 | #show mxtics 9 | set xtics 0.5 rotate 10 | set mxtics 10 11 | set key off 12 | set pointsize 0.5 13 | 14 | name=plot_data_file 15 | 16 | set title name." multimon-ng dump" 17 | # name=system("echo $plot_data_file") 18 | 19 | set output name.".png" 20 | 21 | plot name.".csv" using 1:2 with linespoints pt 6 lc 3 22 | 23 | -------------------------------------------------------------------------------- /example/multipager.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | ################################################## 4 | # GNU Radio Python Flow Graph 5 | # Title: Multipager 6 | # Generated: Thu Aug 3 14:04:34 2017 7 | ################################################## 8 | 9 | from gnuradio import analog 10 | from gnuradio import audio 11 | from gnuradio import blocks 12 | from gnuradio import eng_notation 13 | from gnuradio import filter 14 | from gnuradio import gr 15 | from gnuradio.eng_option import eng_option 16 | from gnuradio.filter import firdes 17 | from gnuradio.filter import pfb 18 | from optparse import OptionParser 19 | import osmosdr 20 | import subprocess 21 | import sip 22 | import sys 23 | import trollius as asyncio 24 | 25 | samplefile = 'sampler.raw' 26 | cmdpat = "sox -t raw -esigned-integer -b16 -r 22050 - -esigned-integer -b16 -r 22050 -t raw - | multimon-ng -t raw -q -a POCSAG512 -a POCSAG1200 -a POCSAG2400 -e -u -f alpha --timestamp --label \"%.3f MHz:\" -" 27 | 28 | class multipager(gr.top_block): 29 | 30 | def __init__(self): 31 | gr.top_block.__init__(self, "Multipager") 32 | ################################################## 33 | # Variables 34 | ################################################## 35 | self.volume = volume = 0.5 36 | self.squelch = squelch = -20 37 | self.sample_rate = sample_rate = 1e6 38 | self.out_scale = out_scale = 10000 39 | self.num_chan = num_chan = 20 40 | self.freq = freq = 148.664e6 41 | self.decim = decim = 2 42 | self.channel = channel = 19 43 | self.audio_rate = audio_rate = 50e3 44 | 45 | ################################################## 46 | # Blocks 47 | ################################################## 48 | if True: 49 | self.source = blocks.file_source(gr.sizeof_gr_complex*1, samplefile, True) 50 | else: 51 | self.source = osmosdr.source(args="hackrf") 52 | self.source.set_sample_rate(sample_rate) 53 | self.source.set_center_freq(freq, 0) 54 | self.source.set_freq_corr(0, 0) 55 | self.source.set_dc_offset_mode(0, 0) 56 | self.source.set_iq_balance_mode(0, 0) 57 | self.source.set_gain_mode(False, 0) 58 | self.source.set_gain(0, 0) 59 | self.source.set_if_gain(36, 0) 60 | self.source.set_bb_gain(44, 0) 61 | self.source.set_antenna("", 0) 62 | self.source.set_bandwidth(0, 0) 63 | 64 | self.pfb_channelizer_ccf_0 = pfb.channelizer_ccf( 65 | num_chan, 66 | (firdes.low_pass(1.0, sample_rate/decim, 7.25e3, 1.5e3, firdes.WIN_HAMMING, 6.76)), 67 | 1, 68 | 60) 69 | self.pfb_channelizer_ccf_0.set_channel_map(([])) 70 | self.pfb_channelizer_ccf_0.declare_sample_delay(0) 71 | 72 | self.low_pass_filter_0 = filter.fir_filter_ccf(decim, firdes.low_pass( 73 | 1, sample_rate, 400e3, 500e3, firdes.WIN_HAMMING, 6.76)) 74 | 75 | chwidth = sample_rate / decim / num_chan 76 | 77 | ################################################## 78 | # Connections 79 | ################################################## 80 | self.connect((self.source, 0), (self.low_pass_filter_0, 0)) 81 | self.connect((self.low_pass_filter_0, 0), (self.pfb_channelizer_ccf_0, 0)) 82 | 83 | # All channels 84 | sel = map(None, range(num_chan)) 85 | 86 | loop = asyncio.get_event_loop() 87 | self.fms = {} 88 | for i in range(num_chan): 89 | #fifopath = fifopat % (i) 90 | fifopath = None 91 | if i > num_chan / 2: 92 | chfreq = freq + chwidth * (i - num_chan) 93 | else: 94 | chfreq = freq + chwidth * i 95 | 96 | if i in sel: 97 | print("Channel %d %.3f MHz" % (i, chfreq / 1e6)) 98 | command = cmdpat % (chfreq / 1e6) 99 | fm = FMtoCommand(squelch, int(sample_rate / num_chan / decim), int(sample_rate / num_chan / decim), 5e3, 100 | out_scale, chfreq, command) 101 | 102 | self.connect((self.pfb_channelizer_ccf_0, i), (fm, 0)) 103 | self.fms[chfreq] = fm 104 | else: 105 | n = blocks.null_sink(gr.sizeof_gr_complex*1) 106 | self.connect((self.pfb_channelizer_ccf_0, i), (n, 0)) 107 | 108 | class FMtoCommand(gr.hier_block2): 109 | def __init__(self, squelch, quad_rate, audio_rate, max_dev, out_scale, freq, command): 110 | gr.hier_block2.__init__(self, "FMtoCommand", 111 | gr.io_signature(1, 1, gr.sizeof_gr_complex), 112 | gr.io_signature(0, 0, gr.sizeof_gr_complex)) 113 | 114 | analog_pwr_squelch = analog.pwr_squelch_cc(squelch, 1e-4, 0, True) 115 | analog_nbfm_rx = analog.nbfm_rx( 116 | audio_rate = audio_rate, 117 | quad_rate = quad_rate, 118 | tau = 75e-6, 119 | max_dev = max_dev, 120 | ) 121 | rational_resampler = filter.rational_resampler_fff( 122 | interpolation = 441, 123 | decimation = 500, 124 | taps = None, 125 | fractional_bw = None, 126 | ) 127 | blocks_float_to_short = blocks.float_to_short(1, out_scale) 128 | 129 | self.p = subprocess.Popen(command, shell = True, stdin = subprocess.PIPE) 130 | sink = blocks.file_descriptor_sink(gr.sizeof_short*1, self.p.stdin.fileno()) 131 | self.connect(self, (analog_pwr_squelch, 0)) 132 | self.connect((analog_pwr_squelch, 0), (analog_nbfm_rx, 0)) 133 | self.connect((analog_nbfm_rx, 0), (rational_resampler, 0)) 134 | self.connect((rational_resampler, 0), (blocks_float_to_short, 0)) 135 | self.connect((blocks_float_to_short, 0), (sink, 0)) 136 | 137 | def main(top_block_cls=multipager, options=None): 138 | 139 | tb = top_block_cls() 140 | tb.start() 141 | try: 142 | raw_input('Press Enter to quit: ') 143 | except EOFError: 144 | pass 145 | 146 | tb.stop() 147 | tb.wait() 148 | 149 | if __name__ == '__main__': 150 | main() 151 | -------------------------------------------------------------------------------- /example/ufsk1200.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliasOenal/multimon-ng/5c33a208d692b4f3fc351a123d82a8f2208054d4/example/ufsk1200.raw -------------------------------------------------------------------------------- /example/x10rf.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliasOenal/multimon-ng/5c33a208d692b4f3fc351a123d82a8f2208054d4/example/x10rf.wav -------------------------------------------------------------------------------- /filter-i386.h: -------------------------------------------------------------------------------- 1 | /* 2 | * filter-i386.h -- optimized filter routines 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #ifndef _FILTER_I386_H 25 | #define _FILTER_I386_H 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | 29 | #define __HAVE_ARCH_MAC 30 | #define mac(a,b,size) \ 31 | (__builtin_constant_p(size) ? __mac_c((a),(b),(size)) : __mac_g((a),(b),(size))) 32 | 33 | #include 34 | 35 | static inline float __mac_g(const float *a, const float *b, unsigned int size) 36 | { 37 | float sum = 0; 38 | unsigned int i; 39 | 40 | for (i = 0; i < size; i++) 41 | sum += (*a++) * (*b++); 42 | return sum; 43 | } 44 | 45 | static inline float __mac_c(const float *a, const float *b, unsigned int size) 46 | { 47 | float f; 48 | 49 | /* 50 | * inspired from Phil Karn, KA9Q's home page 51 | */ 52 | switch (size) { 53 | case 9: 54 | asm volatile ("flds (%1);\n\t" 55 | "fmuls (%2);\n\t" 56 | "flds 4(%1);\n\t" 57 | "fmuls 4(%2);\n\t" 58 | "flds 8(%1);\n\t" 59 | "fmuls 8(%2);\n\t" 60 | "fxch %%st(2);\n\t" 61 | "faddp;\n\t" 62 | "flds 12(%1);\n\t" 63 | "fmuls 12(%2);\n\t" 64 | "fxch %%st(2);\n\t" 65 | "faddp;\n\t" 66 | "flds 16(%1);\n\t" 67 | "fmuls 16(%2);\n\t" 68 | "fxch %%st(2);\n\t" 69 | "faddp;\n\t" 70 | "flds 20(%1);\n\t" 71 | "fmuls 20(%2);\n\t" 72 | "fxch %%st(2);\n\t" 73 | "faddp;\n\t" 74 | "flds 24(%1);\n\t" 75 | "fmuls 24(%2);\n\t" 76 | "fxch %%st(2);\n\t" 77 | "faddp;\n\t" 78 | "flds 28(%1);\n\t" 79 | "fmuls 28(%2);\n\t" 80 | "fxch %%st(2);\n\t" 81 | "faddp;\n\t" 82 | "flds 32(%1);\n\t" 83 | "fmuls 32(%2);\n\t" 84 | "fxch %%st(2);\n\t" 85 | "faddp;\n\t" 86 | "faddp;\n\t" : 87 | "=t" (f) : 88 | "r" (a), 89 | "r" (b) : "memory"); 90 | return f; 91 | 92 | case 18: 93 | asm volatile ("flds (%1);\n\t" 94 | "fmuls (%2);\n\t" 95 | "flds 4(%1);\n\t" 96 | "fmuls 4(%2);\n\t" 97 | "flds 8(%1);\n\t" 98 | "fmuls 8(%2);\n\t" 99 | "fxch %%st(2);\n\t" 100 | "faddp;\n\t" 101 | "flds 12(%1);\n\t" 102 | "fmuls 12(%2);\n\t" 103 | "fxch %%st(2);\n\t" 104 | "faddp;\n\t" 105 | "flds 16(%1);\n\t" 106 | "fmuls 16(%2);\n\t" 107 | "fxch %%st(2);\n\t" 108 | "faddp;\n\t" 109 | "flds 20(%1);\n\t" 110 | "fmuls 20(%2);\n\t" 111 | "fxch %%st(2);\n\t" 112 | "faddp;\n\t" 113 | "flds 24(%1);\n\t" 114 | "fmuls 24(%2);\n\t" 115 | "fxch %%st(2);\n\t" 116 | "faddp;\n\t" 117 | "flds 28(%1);\n\t" 118 | "fmuls 28(%2);\n\t" 119 | "fxch %%st(2);\n\t" 120 | "faddp;\n\t" 121 | "flds 32(%1);\n\t" 122 | "fmuls 32(%2);\n\t" 123 | "fxch %%st(2);\n\t" 124 | "faddp;\n\t" 125 | "flds 36(%1);\n\t" 126 | "fmuls 36(%2);\n\t" 127 | "fxch %%st(2);\n\t" 128 | "faddp;\n\t" 129 | "flds 40(%1);\n\t" 130 | "fmuls 40(%2);\n\t" 131 | "fxch %%st(2);\n\t" 132 | "faddp;\n\t" 133 | "flds 44(%1);\n\t" 134 | "fmuls 44(%2);\n\t" 135 | "fxch %%st(2);\n\t" 136 | "faddp;\n\t" 137 | "flds 48(%1);\n\t" 138 | "fmuls 48(%2);\n\t" 139 | "fxch %%st(2);\n\t" 140 | "faddp;\n\t" 141 | "flds 52(%1);\n\t" 142 | "fmuls 52(%2);\n\t" 143 | "fxch %%st(2);\n\t" 144 | "faddp;\n\t" 145 | "flds 56(%1);\n\t" 146 | "fmuls 56(%2);\n\t" 147 | "fxch %%st(2);\n\t" 148 | "faddp;\n\t" 149 | "flds 60(%1);\n\t" 150 | "fmuls 60(%2);\n\t" 151 | "fxch %%st(2);\n\t" 152 | "faddp;\n\t" 153 | "flds 64(%1);\n\t" 154 | "fmuls 64(%2);\n\t" 155 | "fxch %%st(2);\n\t" 156 | "faddp;\n\t" 157 | "flds 68(%1);\n\t" 158 | "fmuls 68(%2);\n\t" 159 | "fxch %%st(2);\n\t" 160 | "faddp;\n\t" 161 | "faddp;\n\t" : 162 | "=t" (f) : 163 | "r" (a), 164 | "r" (b) : "memory"); 165 | return f; 166 | 167 | case 24: 168 | asm volatile ("flds (%1);\n\t" 169 | "fmuls (%2);\n\t" 170 | "flds 4(%1);\n\t" 171 | "fmuls 4(%2);\n\t" 172 | "flds 8(%1);\n\t" 173 | "fmuls 8(%2);\n\t" 174 | "fxch %%st(2);\n\t" 175 | "faddp;\n\t" 176 | "flds 12(%1);\n\t" 177 | "fmuls 12(%2);\n\t" 178 | "fxch %%st(2);\n\t" 179 | "faddp;\n\t" 180 | "flds 16(%1);\n\t" 181 | "fmuls 16(%2);\n\t" 182 | "fxch %%st(2);\n\t" 183 | "faddp;\n\t" 184 | "flds 20(%1);\n\t" 185 | "fmuls 20(%2);\n\t" 186 | "fxch %%st(2);\n\t" 187 | "faddp;\n\t" 188 | "flds 24(%1);\n\t" 189 | "fmuls 24(%2);\n\t" 190 | "fxch %%st(2);\n\t" 191 | "faddp;\n\t" 192 | "flds 28(%1);\n\t" 193 | "fmuls 28(%2);\n\t" 194 | "fxch %%st(2);\n\t" 195 | "faddp;\n\t" 196 | "flds 32(%1);\n\t" 197 | "fmuls 32(%2);\n\t" 198 | "fxch %%st(2);\n\t" 199 | "faddp;\n\t" 200 | "flds 36(%1);\n\t" 201 | "fmuls 36(%2);\n\t" 202 | "fxch %%st(2);\n\t" 203 | "faddp;\n\t" 204 | "flds 40(%1);\n\t" 205 | "fmuls 40(%2);\n\t" 206 | "fxch %%st(2);\n\t" 207 | "faddp;\n\t" 208 | "flds 44(%1);\n\t" 209 | "fmuls 44(%2);\n\t" 210 | "fxch %%st(2);\n\t" 211 | "faddp;\n\t" 212 | "flds 48(%1);\n\t" 213 | "fmuls 48(%2);\n\t" 214 | "fxch %%st(2);\n\t" 215 | "faddp;\n\t" 216 | "flds 52(%1);\n\t" 217 | "fmuls 52(%2);\n\t" 218 | "fxch %%st(2);\n\t" 219 | "faddp;\n\t" 220 | "flds 56(%1);\n\t" 221 | "fmuls 56(%2);\n\t" 222 | "fxch %%st(2);\n\t" 223 | "faddp;\n\t" 224 | "flds 60(%1);\n\t" 225 | "fmuls 60(%2);\n\t" 226 | "fxch %%st(2);\n\t" 227 | "faddp;\n\t" 228 | "flds 64(%1);\n\t" 229 | "fmuls 64(%2);\n\t" 230 | "fxch %%st(2);\n\t" 231 | "faddp;\n\t" 232 | "flds 68(%1);\n\t" 233 | "fmuls 68(%2);\n\t" 234 | "fxch %%st(2);\n\t" 235 | "faddp;\n\t" 236 | "flds 72(%1);\n\t" 237 | "fmuls 72(%2);\n\t" 238 | "fxch %%st(2);\n\t" 239 | "faddp;\n\t" 240 | "flds 76(%1);\n\t" 241 | "fmuls 76(%2);\n\t" 242 | "fxch %%st(2);\n\t" 243 | "faddp;\n\t" 244 | "flds 80(%1);\n\t" 245 | "fmuls 80(%2);\n\t" 246 | "fxch %%st(2);\n\t" 247 | "faddp;\n\t" 248 | "flds 84(%1);\n\t" 249 | "fmuls 84(%2);\n\t" 250 | "fxch %%st(2);\n\t" 251 | "faddp;\n\t" 252 | "flds 88(%1);\n\t" 253 | "fmuls 88(%2);\n\t" 254 | "fxch %%st(2);\n\t" 255 | "faddp;\n\t" 256 | "flds 92(%1);\n\t" 257 | "fmuls 92(%2);\n\t" 258 | "fxch %%st(2);\n\t" 259 | "faddp;\n\t" 260 | "faddp;\n\t" : 261 | "=t" (f) : 262 | "r" (a), 263 | "r" (b) : "memory"); 264 | return f; 265 | 266 | default: 267 | printf("Warning: optimize __mac_c(..., ..., %d)\n", size); 268 | return __mac_g(a, b, size); 269 | } 270 | } 271 | 272 | /* ---------------------------------------------------------------------- */ 273 | #endif /* _FILTER_I386_H */ 274 | 275 | 276 | 277 | 278 | -------------------------------------------------------------------------------- /filter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * filter.h -- optimized filter routines 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #ifndef _FILTER_H 25 | #define _FILTER_H 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | 29 | #ifdef ARCH_I386 30 | #include "filter-i386.h" 31 | #endif /* ARCH_I386 */ 32 | 33 | /* ---------------------------------------------------------------------- */ 34 | 35 | static inline unsigned int hweight32(unsigned int w) 36 | #ifndef _MSC_VER 37 | __attribute__ ((unused)) 38 | #endif 39 | ; 40 | static inline unsigned int hweight16(unsigned short w) 41 | #ifndef _MSC_VER 42 | __attribute__ ((unused)) 43 | #endif 44 | ; 45 | 46 | static inline unsigned int hweight8(unsigned char w) 47 | #ifndef _MSC_VER 48 | __attribute__ ((unused)) 49 | #endif 50 | ; 51 | 52 | static inline unsigned int hweight32(unsigned int w) 53 | { 54 | unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); 55 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); 56 | res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); 57 | res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); 58 | return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); 59 | } 60 | 61 | static inline unsigned int hweight16(unsigned short w) 62 | { 63 | unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555); 64 | res = (res & 0x3333) + ((res >> 2) & 0x3333); 65 | res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); 66 | return (res & 0x00FF) + ((res >> 8) & 0x00FF); 67 | } 68 | 69 | static inline unsigned int hweight8(unsigned char w) 70 | { 71 | unsigned short res = (w & 0x55) + ((w >> 1) & 0x55); 72 | res = (res & 0x33) + ((res >> 2) & 0x33); 73 | return (res & 0x0F) + ((res >> 4) & 0x0F); 74 | } 75 | 76 | static inline unsigned int gcd(unsigned int x, unsigned int y) 77 | #ifndef _MSC_VER 78 | __attribute__ ((unused)) 79 | #endif 80 | ; 81 | static inline unsigned int lcm(unsigned int x, unsigned int y) 82 | #ifndef _MSC_VER 83 | __attribute__ ((unused)) 84 | #endif 85 | ; 86 | 87 | static inline unsigned int gcd(unsigned int x, unsigned int y) 88 | { 89 | for (;;) { 90 | if (!x) 91 | return y; 92 | if (!y) 93 | return x; 94 | if (x > y) 95 | x %= y; 96 | else 97 | y %= x; 98 | } 99 | } 100 | 101 | static inline unsigned int lcm(unsigned int x, unsigned int y) 102 | { 103 | return x * y / gcd(x, y); 104 | } 105 | 106 | /* ---------------------------------------------------------------------- */ 107 | 108 | #ifndef __HAVE_ARCH_MAC 109 | static inline float mac(const float *a, const float *b, unsigned int size) 110 | { 111 | float sum = 0; 112 | unsigned int i; 113 | 114 | for (i = 0; i < size; i++) 115 | sum += (*a++) * (*b++); 116 | return sum; 117 | } 118 | #endif /* __HAVE_ARCH_MAC */ 119 | 120 | static inline float fsqr(float f) 121 | { 122 | return f*f; 123 | } 124 | 125 | /* ---------------------------------------------------------------------- */ 126 | #endif /* _FILTER_H */ 127 | -------------------------------------------------------------------------------- /gen-ng.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | CONFIG -= qt 4 | CONFIG -= app_bundle 5 | DEFINES += MAX_VERBOSE_LEVEL=1 6 | 7 | isEmpty(PREFIX) { 8 | PREFIX = /usr/local/ 9 | } 10 | TARGET = gen-ng 11 | target.path = $$PREFIX/bin 12 | INSTALLS += target 13 | 14 | HEADERS += \ 15 | gen.h 16 | 17 | 18 | SOURCES += \ 19 | gen.c \ 20 | gen_dtmf.c \ 21 | gen_sin.c \ 22 | gen_zvei.c \ 23 | gen_hdlc.c \ 24 | gen_uart.c \ 25 | gen_clipfsk.c \ 26 | costabi.c 27 | 28 | macx{ 29 | DEFINES += DUMMY_AUDIO 30 | DEFINES += ONLY_RAW 31 | DEFINES += CHARSET_UTF8 32 | } 33 | 34 | win32{ 35 | DEFINES += DUMMY_AUDIO 36 | DEFINES += ONLY_RAW 37 | DEFINES += WINDOWS 38 | LIBS += -lwinmm 39 | } 40 | 41 | 42 | unix:linux-g++-32:!symbian:!macx{ 43 | DEFINES += CHARSET_UTF8 44 | } 45 | 46 | unix:linux-g++-64:!symbian:!macx{ 47 | DEFINES += CHARSET_UTF8 48 | } 49 | 50 | unix:linux-g++:!symbian:!macx{ 51 | DEFINES += CHARSET_UTF8 52 | } 53 | -------------------------------------------------------------------------------- /gen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * gen.h -- generate different test signals 3 | * 4 | * Copyright (C) 1997 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #define SAMPLE_RATE 22050 25 | #define MS(x) ((float)(x)*SAMPLE_RATE/1000) 26 | 27 | extern const int costabi[0x400]; 28 | 29 | #define COS(x) costabi[(((x)>>6)&0x3ffu)] 30 | 31 | enum gen_type { gentype_dtmf, gentype_sine, gentype_zvei, gentype_hdlc, gentype_uart, gentype_clipfsk }; 32 | 33 | struct gen_params { 34 | enum gen_type type; 35 | int ampl; 36 | union { 37 | struct { 38 | int duration; 39 | int pause; 40 | char str[256]; 41 | } dtmf; 42 | struct { 43 | int duration; 44 | int freq; 45 | } sine; 46 | struct { 47 | int duration; 48 | int pause; 49 | char str[256]; 50 | } zvei; 51 | struct { 52 | int modulation; 53 | int txdelay; 54 | int pktlen; 55 | unsigned char pkt[256]; 56 | } uart; 57 | struct { 58 | int modulation; 59 | int txdelay; 60 | int pktlen; 61 | unsigned char pkt[256]; 62 | } clipfsk; 63 | struct { 64 | int modulation; 65 | int txdelay; 66 | int pktlen; 67 | unsigned char pkt[256]; 68 | } hdlc; 69 | } p; 70 | }; 71 | 72 | struct gen_state { 73 | union { 74 | struct { 75 | int ch_idx; 76 | int ph_row, ph_col, phinc_row, phinc_col; 77 | int time, time2; 78 | } dtmf; 79 | struct { 80 | int ph, phinc; 81 | int time; 82 | } sine; 83 | struct { 84 | int ch_idx; 85 | int ph, phinc; 86 | int time, time2; 87 | } zvei; 88 | struct { 89 | int ch_idx, bitmask; 90 | unsigned int ph, phinc, bitph; 91 | unsigned int datalen; 92 | unsigned char data[512]; 93 | } uart; 94 | struct { 95 | int ch_idx, bitmask; 96 | unsigned int ph, phinc, bitph; 97 | unsigned int datalen; 98 | unsigned char data[512]; 99 | } clipfsk; 100 | struct { 101 | int lastb; 102 | int ch_idx, bitmask; 103 | unsigned int ph, phinc, bitph; 104 | unsigned int datalen; 105 | unsigned char data[512]; 106 | } hdlc; 107 | } s; 108 | }; 109 | 110 | extern void gen_init_dtmf(struct gen_params *p, struct gen_state *s); 111 | extern int gen_dtmf(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); 112 | 113 | extern void gen_init_sine(struct gen_params *p, struct gen_state *s); 114 | extern int gen_sine(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); 115 | 116 | extern void gen_init_zvei(struct gen_params *p, struct gen_state *s); 117 | extern int gen_zvei(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); 118 | 119 | extern void gen_init_uart(struct gen_params *p, struct gen_state *s); 120 | extern int gen_uart(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); 121 | 122 | extern void gen_init_clipfsk(struct gen_params *p, struct gen_state *s); 123 | extern int gen_clipfsk(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); 124 | 125 | extern void gen_init_hdlc(struct gen_params *p, struct gen_state *s); 126 | extern int gen_hdlc(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); 127 | 128 | -------------------------------------------------------------------------------- /gen_clipfsk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gen_clipfsk.c -- generate CLIP FSK 1200 bps sequences 3 | * 4 | * Copyright (C) 2007 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | */ 20 | 21 | /* ---------------------------------------------------------------------- */ 22 | 23 | #include "gen.h" 24 | #include 25 | 26 | /*---------------------------------------------------------------------------*/ 27 | 28 | struct clipfsktx { 29 | unsigned int bitstream; 30 | unsigned int bitbuf; 31 | int numbits; 32 | }; 33 | 34 | static void txb_addbyte(struct gen_state *s, struct clipfsktx *clipfsktx, 35 | unsigned char bits, unsigned char nostart) 36 | { 37 | int i,j; 38 | if (clipfsktx->numbits >= 8) { 39 | if (s->s.clipfsk.datalen >= sizeof(s->s.clipfsk.data)) 40 | return; 41 | s->s.clipfsk.data[s->s.clipfsk.datalen++] = clipfsktx->bitbuf; 42 | clipfsktx->bitbuf >>= 8; 43 | clipfsktx->numbits -= 8; 44 | } 45 | 46 | if (!nostart) { 47 | clipfsktx->bitbuf &= ~(1 << clipfsktx->numbits); 48 | clipfsktx->numbits++; 49 | } 50 | clipfsktx->bitbuf |= bits << clipfsktx->numbits; 51 | clipfsktx->numbits += 8; 52 | clipfsktx->bitbuf |= 1 << clipfsktx->numbits; 53 | clipfsktx->numbits++; 54 | 55 | if (clipfsktx->numbits >= 8) { 56 | if (s->s.clipfsk.datalen >= sizeof(s->s.clipfsk.data)) 57 | return; 58 | s->s.clipfsk.data[s->s.clipfsk.datalen++] = clipfsktx->bitbuf; 59 | clipfsktx->bitbuf >>= 8; 60 | clipfsktx->numbits -= 8; 61 | } 62 | /* 63 | printf("bits:%02x\n", bits); 64 | for (i = 0; i < s->s.clipfsk.datalen; i++) { 65 | // printf("%08X", s->s.clipfsk.data[i]); 66 | for ( j = 0; j < 8; j++) { 67 | printf("%c", ((s->s.clipfsk.data[i]) & (1<s.clipfsk.bitmask = 1; 83 | // for (i = 0; i < (p->p.clipfsk.txdelay * (1200/100) / 8); i++) 84 | // txb_addbyte(s, &clipfsktx, 0xff, 1); 85 | for (i = 0; i < 30; i++) 86 | txb_addbyte(s, &clipfsktx, 0x55, 0); 87 | for (i = 0; i < 18; i++) 88 | txb_addbyte(s, &clipfsktx, 0xff, 1); 89 | for (i = 0; i < p->p.clipfsk.pktlen; i++) 90 | txb_addbyte(s, &clipfsktx, p->p.clipfsk.pkt[i], 0); 91 | /* The specifications are to stop carrier inmediatly with last stop bit, but an extra one 92 | is needed with this demodulator, so a full 10 bit stop must be generated */ 93 | txb_addbyte(s, &clipfsktx, 0xff, 1); 94 | } 95 | 96 | int gen_clipfsk(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) 97 | { 98 | int num = 0; 99 | 100 | if (!s || s->s.clipfsk.ch_idx < 0 || s->s.clipfsk.ch_idx >= s->s.clipfsk.datalen) 101 | return 0; 102 | for (; buflen > 0; buflen--, buf++, num++) { 103 | s->s.clipfsk.bitph += 0x10000*1200 / SAMPLE_RATE; 104 | if (s->s.clipfsk.bitph >= 0x10000u) { 105 | s->s.clipfsk.bitph &= 0xffffu; 106 | s->s.clipfsk.bitmask <<= 1; 107 | if (s->s.clipfsk.bitmask >= 0x100) { 108 | s->s.clipfsk.bitmask = 1; 109 | s->s.clipfsk.ch_idx++; 110 | if (s->s.clipfsk.ch_idx >= s->s.clipfsk.datalen) 111 | return num; 112 | } 113 | s->s.clipfsk.phinc = (s->s.clipfsk.data[s->s.clipfsk.ch_idx] & s->s.clipfsk.bitmask) ? 114 | // 0x10000*120/SAMPLE_RATE : 0x10000*2200/SAMPLE_RATE; 115 | 0x10000*1200/SAMPLE_RATE : 0x10000*2200/SAMPLE_RATE; 116 | } 117 | *buf += (p->ampl * COS(s->s.clipfsk.ph)) >> 15; 118 | s->s.clipfsk.ph += s->s.clipfsk.phinc; 119 | } 120 | return num; 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /gen_dtmf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gen_dtmf.c -- generate DTMF sequences 3 | * 4 | * Copyright (C) 1997 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "gen.h" 25 | #include 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | /* 32 | * 33 | * DTMF frequencies 34 | * 35 | * 1209 1336 1477 1633 36 | * 697 1 2 3 A 37 | * 770 4 5 6 B 38 | * 852 7 8 9 C 39 | * 941 * 0 # D 40 | * 41 | */ 42 | 43 | 44 | static const char *dtmf_transl = "123A456B789C*0#D"; 45 | 46 | #define PHINC(x) ((float)(x)*0x10000/SAMPLE_RATE) 47 | 48 | static const unsigned int row_freq[4] = { 49 | PHINC(697), PHINC(770), PHINC(852), PHINC(941) 50 | }; 51 | 52 | static const unsigned int col_freq[4] = { 53 | PHINC(1209), PHINC(1336), PHINC(1477), PHINC(1633) 54 | }; 55 | 56 | void gen_init_dtmf(struct gen_params *p, struct gen_state *s) 57 | { 58 | memset(s, 0, sizeof(struct gen_state)); 59 | } 60 | 61 | int gen_dtmf(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) 62 | { 63 | char c; 64 | char *cp; 65 | int num = 0, i; 66 | 67 | for (; buflen > 0; buflen--, buf++, num++) { 68 | if (s->s.dtmf.time <= 0) { 69 | c = p->p.dtmf.str[s->s.dtmf.ch_idx]; 70 | if (!c) 71 | return num; 72 | s->s.dtmf.ch_idx++; 73 | cp = (char*)memchr(dtmf_transl, toupper(c), 16); 74 | if (!cp) { 75 | s->s.dtmf.time = s->s.dtmf.time2 = 1; 76 | fprintf(stderr, "gen: dtmf; invalid char '%c'\n", c); 77 | } else { 78 | s->s.dtmf.time = p->p.dtmf.duration + p->p.dtmf.pause; 79 | s->s.dtmf.time2 = p->p.dtmf.duration; 80 | i = cp - dtmf_transl; 81 | s->s.dtmf.phinc_row = row_freq[(i >> 2) & 3]; 82 | s->s.dtmf.phinc_col = col_freq[i & 3]; 83 | } 84 | } else if (!s->s.dtmf.time2) { 85 | s->s.dtmf.phinc_row = s->s.dtmf.phinc_col = 0; 86 | s->s.dtmf.ph_row = s->s.dtmf.ph_col = 0xc000; 87 | } 88 | s->s.dtmf.time--; 89 | s->s.dtmf.time2--; 90 | *buf += ((p->ampl >> 1) * (COS(s->s.dtmf.ph_row) + COS(s->s.dtmf.ph_col))) >> 15; 91 | s->s.dtmf.ph_row += s->s.dtmf.phinc_row; 92 | s->s.dtmf.ph_col += s->s.dtmf.phinc_col; 93 | } 94 | return num; 95 | } 96 | -------------------------------------------------------------------------------- /gen_hdlc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gen_hdlc.c -- generate DTMF sequences 3 | * 4 | * Copyright (C) 1997 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "gen.h" 25 | #include 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | /* 29 | * the CRC routines are stolen from WAMPES 30 | * by Dieter Deyke 31 | */ 32 | 33 | static const unsigned short crc_ccitt_table[] = { 34 | 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 35 | 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 36 | 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 37 | 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 38 | 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 39 | 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 40 | 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 41 | 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 42 | 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 43 | 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 44 | 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 45 | 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 46 | 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 47 | 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 48 | 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 49 | 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 50 | 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 51 | 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 52 | 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 53 | 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 54 | 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 55 | 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 56 | 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 57 | 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 58 | 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 59 | 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 60 | 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 61 | 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 62 | 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 63 | 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 64 | 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 65 | 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 66 | }; 67 | 68 | /*---------------------------------------------------------------------------*/ 69 | 70 | #if 0 71 | static inline void append_crc_ccitt(unsigned char *buffer, int len) 72 | { 73 | unsigned int crc = 0xffff; 74 | 75 | for (;len>0;len--) 76 | crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff]; 77 | crc ^= 0xffff; 78 | *buffer++ = crc; 79 | *buffer++ = crc >> 8; 80 | } 81 | 82 | /*---------------------------------------------------------------------------*/ 83 | 84 | static inline int check_crc_ccitt(const unsigned char *buf, int cnt) 85 | { 86 | unsigned int crc = 0xffff; 87 | 88 | for (; cnt > 0; cnt--) 89 | crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff]; 90 | return (crc & 0xffff) == 0xf0b8; 91 | } 92 | #endif 93 | 94 | /*---------------------------------------------------------------------------*/ 95 | 96 | static inline int calc_crc_ccitt(const unsigned char *buf, int cnt) 97 | { 98 | unsigned int crc = 0xffff; 99 | 100 | for (; cnt > 0; cnt--) 101 | crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff]; 102 | crc ^= 0xffff; 103 | return (crc & 0xffff); 104 | } 105 | 106 | /* ---------------------------------------------------------------------- */ 107 | 108 | struct hdlctx { 109 | unsigned int bitstream; 110 | unsigned int bitbuf; 111 | int numbits; 112 | }; 113 | 114 | static void txb_addbyte(struct gen_state *s, struct hdlctx *hdlctx, 115 | unsigned char bits, unsigned char stuff) 116 | { 117 | unsigned int mask1, mask2; 118 | unsigned int mask3; 119 | int i; 120 | 121 | if (hdlctx->numbits >= 8) { 122 | if (s->s.hdlc.datalen >= sizeof(s->s.hdlc.data)) 123 | return; 124 | s->s.hdlc.data[s->s.hdlc.datalen++] = hdlctx->bitbuf; 125 | hdlctx->bitbuf >>= 8; 126 | hdlctx->numbits -= 8; 127 | } 128 | hdlctx->bitbuf |= bits << hdlctx->numbits; 129 | hdlctx->bitstream >>= 8; 130 | hdlctx->bitstream |= bits << 8; 131 | mask1 = 0x1f0; 132 | mask2 = 0x100; 133 | mask3 = 0xffffffff >> (31 - hdlctx->numbits); 134 | hdlctx->numbits += 8; 135 | if (!stuff) 136 | goto nostuff; 137 | for(i = 0; i < 8; i++, mask1 <<= 1, mask2 <<= 1, mask3 = (mask3 << 1) | 1) { 138 | if ((hdlctx->bitstream & mask1) != mask1) 139 | continue; 140 | hdlctx->bitstream &= ~mask2; 141 | hdlctx->bitbuf = (hdlctx->bitbuf & mask3) | ((hdlctx->bitbuf & (~mask3)) << 1); 142 | hdlctx->numbits++; 143 | mask3 = (mask3 << 1) | 1; 144 | } 145 | nostuff: 146 | if (hdlctx->numbits >= 8) { 147 | if (s->s.hdlc.datalen >= sizeof(s->s.hdlc.data)) 148 | return; 149 | s->s.hdlc.data[s->s.hdlc.datalen++] = hdlctx->bitbuf; 150 | hdlctx->bitbuf >>= 8; 151 | hdlctx->numbits -= 8; 152 | } 153 | } 154 | 155 | /* ---------------------------------------------------------------------- */ 156 | 157 | void gen_init_hdlc(struct gen_params *p, struct gen_state *s) 158 | { 159 | struct hdlctx hdlctx = { 0, 0, 0 }; 160 | int i; 161 | 162 | memset(s, 0, sizeof(struct gen_state)); 163 | s->s.hdlc.bitmask = 1; 164 | for (i = 0; i < (p->p.hdlc.txdelay * (1200/100) / 8); i++) 165 | txb_addbyte(s, &hdlctx, 0x7e, 0); 166 | txb_addbyte(s, &hdlctx, 0x7e, 0); 167 | for (i = 0; i < p->p.hdlc.pktlen; i++) 168 | txb_addbyte(s, &hdlctx, p->p.hdlc.pkt[i], 1); 169 | i = calc_crc_ccitt(p->p.hdlc.pkt, p->p.hdlc.pktlen); 170 | txb_addbyte(s, &hdlctx, i, 1); 171 | txb_addbyte(s, &hdlctx, i >> 8, 1); 172 | txb_addbyte(s, &hdlctx, 0x7e, 0); 173 | txb_addbyte(s, &hdlctx, 0x7e, 0); 174 | txb_addbyte(s, &hdlctx, 0x7e, 0); 175 | txb_addbyte(s, &hdlctx, 0x7e, 0); 176 | txb_addbyte(s, &hdlctx, 0x7e, 0); 177 | txb_addbyte(s, &hdlctx, 0x7e, 0); 178 | } 179 | 180 | int gen_hdlc(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) 181 | { 182 | int num = 0; 183 | 184 | if (!s || s->s.hdlc.ch_idx < 0 || s->s.hdlc.ch_idx >= s->s.hdlc.datalen) 185 | return 0; 186 | for (; buflen > 0; buflen--, buf++, num++) { 187 | s->s.hdlc.bitph += 0x10000*1200 / SAMPLE_RATE; 188 | if (s->s.hdlc.bitph >= 0x10000u) { 189 | s->s.hdlc.bitph &= 0xffffu; 190 | s->s.hdlc.bitmask <<= 1; 191 | if (s->s.hdlc.bitmask >= 0x100) { 192 | s->s.hdlc.bitmask = 1; 193 | s->s.hdlc.ch_idx++; 194 | if (s->s.hdlc.ch_idx >= s->s.hdlc.datalen) 195 | return num; 196 | } 197 | if (!(s->s.hdlc.data[s->s.hdlc.ch_idx] & s->s.hdlc.bitmask)) 198 | s->s.hdlc.lastb = !s->s.hdlc.lastb; 199 | s->s.hdlc.phinc = (s->s.hdlc.lastb) ? 200 | 0x10000*2200/SAMPLE_RATE : 0x10000*1200/SAMPLE_RATE; 201 | } 202 | *buf += (p->ampl * COS(s->s.hdlc.ph)) >> 15; 203 | s->s.hdlc.ph += s->s.hdlc.phinc; 204 | } 205 | return num; 206 | } 207 | 208 | 209 | -------------------------------------------------------------------------------- /gen_sin.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gen_sine.c -- generate DTMF sequences 3 | * 4 | * Copyright (C) 1997 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "gen.h" 25 | #include 26 | 27 | /* ---------------------------------------------------------------------- */ 28 | 29 | void gen_init_sine(struct gen_params *p, struct gen_state *s) 30 | { 31 | memset(s, 0, sizeof(struct gen_state)); 32 | s->s.sine.ph = 0; 33 | s->s.sine.phinc = (float)0x10000 * p->p.sine.freq / SAMPLE_RATE; 34 | s->s.sine.time = p->p.sine.duration; 35 | } 36 | 37 | int gen_sine(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) 38 | { 39 | int num = 0; 40 | 41 | for (; (buflen > 0) && (s->s.sine.time > 0); buflen--, buf++, num++, s->s.sine.time--) { 42 | *buf += (p->ampl * COS(s->s.sine.ph)) >> 15; 43 | s->s.sine.ph += s->s.sine.phinc; 44 | } 45 | return num; 46 | } 47 | -------------------------------------------------------------------------------- /gen_uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gen_uart.c -- generate DTMF sequences 3 | * 4 | * Copyright (C) 2007 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | */ 20 | 21 | /* ---------------------------------------------------------------------- */ 22 | 23 | #include "gen.h" 24 | #include 25 | #include 26 | 27 | /*---------------------------------------------------------------------------*/ 28 | 29 | struct uarttx { 30 | unsigned int bitstream; 31 | unsigned int bitbuf; 32 | int numbits; 33 | }; 34 | 35 | static void txb_addbyte(struct gen_state *s, struct uarttx *uarttx, 36 | unsigned char bits, unsigned char nostart) 37 | { 38 | int i,j; 39 | if (uarttx->numbits >= 8) { 40 | if (s->s.uart.datalen >= sizeof(s->s.uart.data)) 41 | return; 42 | s->s.uart.data[s->s.uart.datalen++] = uarttx->bitbuf; 43 | uarttx->bitbuf >>= 8; 44 | uarttx->numbits -= 8; 45 | } 46 | 47 | if (!nostart) { 48 | uarttx->bitbuf &= ~(1 << uarttx->numbits); 49 | uarttx->numbits++; 50 | } 51 | uarttx->bitbuf |= bits << uarttx->numbits; 52 | uarttx->numbits += 8; 53 | uarttx->bitbuf |= 1 << uarttx->numbits; 54 | uarttx->numbits++; 55 | 56 | if (uarttx->numbits >= 8) { 57 | if (s->s.uart.datalen >= sizeof(s->s.uart.data)) 58 | return; 59 | s->s.uart.data[s->s.uart.datalen++] = uarttx->bitbuf; 60 | uarttx->bitbuf >>= 8; 61 | uarttx->numbits -= 8; 62 | } 63 | /* 64 | printf("bits:%02x\n", bits); 65 | for (i = 0; i < s->s.uart.datalen; i++) { 66 | // printf("%08X", s->s.uart.data[i]); 67 | for ( j = 0; j < 8; j++) { 68 | printf("%c", ((s->s.uart.data[i]) & (1<s.uart.bitmask = 1; 84 | for (i = 0; i < (p->p.uart.txdelay * (1200/100) / 8); i++) 85 | txb_addbyte(s, &uarttx, 0xff, 1); 86 | for (i = 0; i < 30; i++) 87 | txb_addbyte(s, &uarttx, 0x55, 0); 88 | for (i = 0; i < 18; i++) 89 | txb_addbyte(s, &uarttx, 0xff, 1); 90 | /* txb_addbyte(s, &uarttx, 0xff, 0); 91 | txb_addbyte(s, &uarttx, 0x00, 0); 92 | txb_addbyte(s, &uarttx, 0x01, 0); 93 | txb_addbyte(s, &uarttx, 0x02, 0); 94 | txb_addbyte(s, &uarttx, 0x03, 0); 95 | txb_addbyte(s, &uarttx, 0x00, 0); 96 | txb_addbyte(s, &uarttx, 0x55, 0); 97 | */ for (i = 0; i < p->p.uart.pktlen; i++) 98 | txb_addbyte(s, &uarttx, p->p.uart.pkt[i], 0); 99 | txb_addbyte(s, &uarttx, 0xff, 1); 100 | txb_addbyte(s, &uarttx, 0xff, 1); 101 | } 102 | 103 | int gen_uart(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) 104 | { 105 | int num = 0; 106 | 107 | if (!s || s->s.uart.ch_idx < 0 || s->s.uart.ch_idx >= s->s.uart.datalen) 108 | return 0; 109 | for (; buflen > 0; buflen--, buf++, num++) { 110 | s->s.uart.bitph += 0x10000*1200 / SAMPLE_RATE; 111 | if (s->s.uart.bitph >= 0x10000u) { 112 | s->s.uart.bitph &= 0xffffu; 113 | s->s.uart.bitmask <<= 1; 114 | if (s->s.uart.bitmask >= 0x100) { 115 | s->s.uart.bitmask = 1; 116 | s->s.uart.ch_idx++; 117 | if (s->s.uart.ch_idx >= s->s.uart.datalen) 118 | return num; 119 | } 120 | s->s.uart.phinc = (s->s.uart.data[s->s.uart.ch_idx] & s->s.uart.bitmask) ? 121 | // 0x10000*120/SAMPLE_RATE : 0x10000*2200/SAMPLE_RATE; 122 | 0x10000*1200/SAMPLE_RATE : 0x10000*2200/SAMPLE_RATE; 123 | } 124 | *buf += (p->ampl * COS(s->s.uart.ph)) >> 15; 125 | s->s.uart.ph += s->s.uart.phinc; 126 | } 127 | return num; 128 | } 129 | 130 | 131 | -------------------------------------------------------------------------------- /gen_zvei.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gen_zvei.c -- generate DTMF sequences 3 | * 4 | * Copyright (C) 1997 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include "gen.h" 25 | #include 26 | #include 27 | #include 28 | 29 | /* ---------------------------------------------------------------------- */ 30 | 31 | #define PHINC(x) ((float)(x)*0x10000/SAMPLE_RATE) 32 | 33 | static const unsigned int zvei_freq[16] = { 34 | PHINC(2400), PHINC(1060), PHINC(1160), PHINC(1270), 35 | PHINC(1400), PHINC(1530), PHINC(1670), PHINC(1830), 36 | PHINC(2000), PHINC(2200), PHINC(2800), PHINC(810), 37 | PHINC(970), PHINC(886), PHINC(2600), PHINC(0) 38 | }; 39 | 40 | static const unsigned int zveis_freq[16] = { 41 | PHINC(2400), PHINC(1060), PHINC(1160), PHINC(1270), 42 | PHINC(1400), PHINC(1530), PHINC(1670), PHINC(1830), 43 | PHINC(2000), PHINC(2200), PHINC(886), PHINC(810), 44 | PHINC(740), PHINC(680), PHINC(970), PHINC(0) 45 | }; 46 | 47 | void gen_init_zvei(struct gen_params *p, struct gen_state *s) 48 | { 49 | memset(s, 0, sizeof(struct gen_state)); 50 | } 51 | 52 | int gen_zvei(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) 53 | { 54 | char c; 55 | int num = 0, i; 56 | 57 | for (; buflen > 0; buflen--, buf++, num++) { 58 | if (s->s.zvei.time <= 0) { 59 | c = p->p.zvei.str[s->s.zvei.ch_idx]; 60 | if (!c) 61 | return num; 62 | s->s.zvei.ch_idx++; 63 | if (!isxdigit(c)) { 64 | s->s.zvei.time = s->s.zvei.time2 = 1; 65 | fprintf(stderr, "gen: zvei; invalid char '%c'\n", c); 66 | } else { 67 | s->s.zvei.time = p->p.zvei.duration + p->p.zvei.pause; 68 | s->s.zvei.time2 = p->p.zvei.duration; 69 | if (c >= '0' && c <= '9') 70 | i = c - '0'; 71 | else if (c >= 'A' && c <= 'F') 72 | i = c - 'A' + 10; 73 | else 74 | i = c - 'a' + 10; 75 | s->s.zvei.phinc = zvei_freq[i & 0xf]; 76 | } 77 | } else if (!s->s.zvei.time2) { 78 | s->s.zvei.phinc = 0; 79 | s->s.zvei.ph = 0xc000; 80 | } 81 | s->s.zvei.time--; 82 | s->s.zvei.time2--; 83 | *buf += (p->ampl * COS(s->s.zvei.ph)) >> 15; 84 | s->s.zvei.ph += s->s.zvei.phinc; 85 | } 86 | return num; 87 | } 88 | -------------------------------------------------------------------------------- /mkcostab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mkcostab.c -- cosine table generator 3 | * 4 | * Copyright (C) 1996 5 | * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | /* ---------------------------------------------------------------------- */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | /* ---------------------------------------------------------------------- */ 29 | 30 | #define COSTABSIZE 0x400 31 | 32 | /* ---------------------------------------------------------------------- */ 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | int i; 37 | FILE *fi, *ff; 38 | float f; 39 | 40 | if (!(fi = fopen("costabi.c", "w"))) 41 | exit(1); 42 | if (!(ff = fopen("costabf.c", "w"))) 43 | exit(1); 44 | fprintf(fi, "/*\n * This file is machine generated, DO NOT EDIT!\n */\n\n" 45 | "const int costabi[0x%x] = {", COSTABSIZE); 46 | fprintf(ff, "/*\n * This file is machine generated, DO NOT EDIT!\n */\n\n" 47 | "const float costabf[0x%x] = {", COSTABSIZE); 48 | for (i = 0; i < COSTABSIZE; i++) { 49 | if ((i & 3) == 0) 50 | fprintf(ff, "\n\t"); 51 | if ((i & 7) == 0) 52 | fprintf(fi, "\n\t"); 53 | f = cos(M_PI*2.0*i/COSTABSIZE); 54 | fprintf(ff, "%12.9f", f); 55 | fprintf(fi, "%6i", (int)(32767.0*f)); 56 | if (i < COSTABSIZE-1) { 57 | fprintf(ff, ", "); 58 | fprintf(fi, ", "); 59 | } 60 | } 61 | fprintf(ff, "\n};\n"); 62 | fprintf(fi, "\n};\n"); 63 | exit(0); 64 | } 65 | -------------------------------------------------------------------------------- /msvc_support.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define inline __inline 4 | 5 | #include "win32_getopt.h" 6 | 7 | #define strcasecmp(s1, s2) _stricmp(s1, s2) -------------------------------------------------------------------------------- /multimon-ng.1: -------------------------------------------------------------------------------- 1 | .\" -*- nroff -*- 2 | .TH MULTIMON-NG 1 "February 22, 2025" 3 | .\" Please adjust this date whenever revising the manpage. 4 | .\" 5 | .\" Some roff macros, for reference: 6 | .\" .nh disable hyphenation 7 | .\" .hy enable hyphenation 8 | .\" .ad l left justify 9 | .\" .ad b justify to both left and right margins 10 | .\" .nf disable filling 11 | .\" .fi enable filling 12 | .\" .br insert line break 13 | .\" .sp insert n+1 empty lines 14 | .\" for manpage-specific macros, see man(7) 15 | .SH NAME 16 | multimon-ng \- program to decode radio transmissions 17 | .SH SYNOPSIS 18 | .B multimon-ng 19 | .RI [ options ]\ [input_file] 20 | .SH DESCRIPTION 21 | This manual page documents briefly the 22 | .B multimon-ng 23 | command. This manual page was written for Debian because the original 24 | program does not have a manual page. 25 | .PP 26 | .\" TeX users may be more comfortable with the \fB\fP and 27 | .\" \fI\fP escape sequences to invode bold face and italics, 28 | .\" respectively. 29 | The \fBmultimon-ng\fP software can decode a variety of digital transmission modes commonly found on VHF/UHF radio. A standard PC soundcard is used to acquire the signal from a transceiver. The decoding is done completely in software. Currently, the following modes are supported: 30 | .PP 31 | .RS 32 | .IP \(bu 4 33 | AX.25 34 | .RS 35 | .IP \(bu 4 36 | 1200 Baud AFSK 37 | .IP \(bu 4 38 | 2400 Baud AFSK (2 variants) 39 | .IP \(bu 4 40 | 4800 Baud HAPN 41 | .IP \(bu 4 42 | 9600 Baud FSK (G3RUH) 43 | .RE 44 | . 45 | .IP \(bu 4 46 | POCSAG 47 | .RS 48 | .IP \(bu 4 49 | 512 Baud 50 | .IP \(bu 4 51 | 1200 Baud 52 | .IP \(bu 4 53 | 2400 Baud 54 | .RE 55 | . 56 | .IP \(bu 4 57 | Selective call 58 | .RS 59 | .IP \(bu 4 60 | CCIR 61 | .IP \(bu 4 62 | EEA 63 | .IP \(bu 4 64 | EIA 65 | .RE 66 | . 67 | .IP \(bu 4 68 | Frequency Shift Keying 69 | .RS 70 | .IP \(bu 4 71 | 1200 Baud FSK (2200/1200 Hz) 72 | .IP \(bu 4 73 | 1200 Baud FSK (2300/1100 Hz) 74 | .IP \(bu 4 75 | 1200 baud FMS FSK 76 | .RE 77 | . 78 | .IP \(bu 4 79 | Miscellaneous 80 | .RS 81 | .IP \(bu 4 82 | DTMF 83 | .IP \(bu 4 84 | CW/Morse 85 | .IP \(bu 4 86 | EAS 87 | .IP \(bu 4 88 | FLEX 89 | .IP \(bu 4 90 | SCOPE 91 | .IP \(bu 4 92 | X10 93 | .IP \(bu 4 94 | ZVEI 95 | .RE 96 | .RE 97 | .PP 98 | An arbitrary set of the above modes may run concurrently on the same input signal (provided the CPU power is sufficient), so you do not have to know in advance which mode is used. Note however that some modes might require modifications to the radio (especially the 9600 baud FSK and the POCSAG modes) to work properly. 99 | .PP 100 | AX.25 - Amateur Packet Radio protocol datagram format. 101 | .br 102 | DTMF - Dual Tone Multi Frequency. Commonly used in in-band telephone dialing. 103 | .br 104 | EAS - Emergency Alert System. 105 | .br 106 | FLEX - a paging format. 107 | .br 108 | POCSAG (Post Office Code Standards Advisory Group) is a common paging transmission format. 109 | .br 110 | SCOPE - show samples in a rudimentary oscilloscope display on an X server. 111 | .br 112 | X10 - a home automation protocol. 113 | .br 114 | ZVEI - The German Electrical and Electronic Manufacturers' Association - paging tone format. 115 | .SH OPTIONS 116 | .TP 117 | .B \-t 118 | Input file type (any other type than raw requires sox). 119 | Allowed types: raw aiff au hcom sf voc cdr dat smp wav maud vwe. 120 | .TP 121 | .B \-a 122 | Add demodulator (see below). 123 | .TP 124 | .B \-s 125 | Subtract demodulator. 126 | .TP 127 | .B \-c 128 | Remove all demodulators (must be added with -a ). 129 | .TP 130 | .B \-q 131 | Quiet output messages. 132 | .TP 133 | .B \-v 134 | Verbosity level (0-10). 135 | For POCSAG and MORSE_CW '-v1' prints decoding statistics. 136 | .TP 137 | .B \-h 138 | Print the help. 139 | .TP 140 | .B \-A 141 | APRS mode (TNC2 text output). 142 | .TP 143 | .B \-m 144 | Mute SoX warnings. 145 | .TP 146 | .B \-m 147 | Call SoX in repeatable mode (e.g. fixed random seed for dithering). 148 | .TP 149 | .B \-n 150 | Don't flush stdout, increases performance. 151 | .TP 152 | .B \-j 153 | FMS: Just output hex data and CRC, no parsing. 154 | .TP 155 | .B \-e 156 | POCSAG: Hide empty messages. 157 | .TP 158 | .B \-u 159 | POCSAG: Heuristically prune unlikely decodes. 160 | .TP 161 | .B \-i 162 | POCSAG: Inverts the input samples. Try this if decoding fails. 163 | .TP 164 | .B \-p 165 | POCSAG: Show partially received messages. 166 | .TP 167 | .B \-f 168 | POCSAG: Disables auto-detection and forces decoding of data as 169 | ( can be 'numeric', 'alpha', 'skyper' and 'auto') 170 | .TP 171 | .B \-b 172 | POCSAG: BCH bit error correction level. Set 0 to disable, default is 2. 173 | Lower levels increase performance and lower false positives. 174 | .TP 175 | .B \-C 176 | POCSAG: Set charset (default: US), where is one of: 177 | US, FR, DE, SE, SI 178 | .TP 179 | .B \-o