2017-10-05 00:38:45 -04:00
/*
* Copyright ( C ) 2015 Jared Boone , ShareBrained Technology , Inc .
* Copyright ( C ) 2017 Furrtek
2017-11-09 21:20:44 -05:00
* Copyright ( C ) 2014 zilog80
2017-10-05 00:38:45 -04:00
*
* This file is part of PortaPack .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; see the file COPYING . If not , write to
* the Free Software Foundation , Inc . , 51 Franklin Street ,
* Boston , MA 02110 - 1301 , USA .
*/
2017-10-06 00:35:25 -04:00
/* Notes to self (or others, welcome !):
* Sharebrained wrote in matched_filter . hpp that taps should be those of a complex low - pass filter combined with a complex sinusoid , so
* that the filter shifts the spectrum where we want ( signal of interest around 0 Hz ) .
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* In this baseband processor , after decim_0 and decim_1 , the signal ends up being sampled at 38400 Hz ( 2457600 / 8 / 8 )
* Since the applied shift in ui_sonde . cpp is - fs / 4 = - 2457600 / 4 = - 614400 Hz to avoid the DC spike , the FSK signal ends up being
* shifted by 614400 / 8 / 8 = 9600 Hz . So decim_1_out should look like this :
2023-05-18 16:16:05 -04:00
*
2017-10-27 12:54:50 -04:00
* _______________ | ______ / ' \ ______
* - C A B C
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* A is the DC spike at 0 Hz
* B is the FSK signal shifted right at 9600 Hz
* C is the bandwidth edge at 19200 Hz
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* Taps should be computed to shift the whole spectrum by - 9600 Hz ( " left " ) so that it looks like this :
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* ______________ / ' \ ______________
* - C D C
2023-05-18 16:16:05 -04:00
*
2017-10-27 12:54:50 -04:00
* Anything unwanted ( like A ) should have been filtered off
2017-10-06 00:35:25 -04:00
* D is B around 0 Hz now
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* Then the clock_recovery function should be happy : )
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* Mathworks . com says :
* In the case of a single - rate FIR design , we simply multiply each set of coefficients by ( aka ' heterodyne with ' ) a complex exponential .
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* Can SciPy ' s remez function be used for this ? See tools / firtest . py
* GnuRadio ' s firdes only outputs an odd number of taps
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* Looking at the AIS baseband processor :
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* Copied everything necessary to get decim_1_out ( so same 8 * 8 = 64 decimation factor )
* The samplerate is also the same ( 2457600 )
* After the matching filter , the data is decimated by 2 so the final samplerate for clock_recovery is 38400 / 2 = 19200 Hz .
* Like here , the shift used is fs / 4 , so decim_1_out should be looking similar .
* The AIS signal deviates by 2400 ( 4800 Hz signal width ) , the symbol rate is 9600.
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* The matched filter ' s input samplerate is 38400 Hz , to get a 9600 Hz shift it must use 4 taps ?
* To obtain unity gain , the sinusoid length must be / by the number of taps ?
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* See ais_baseband . hpp
2023-05-18 16:16:05 -04:00
*
2017-10-06 00:35:25 -04:00
* */
2017-10-05 00:38:45 -04:00
# ifndef __PROC_SONDE_H__
# define __PROC_SONDE_H__
# include "baseband_processor.hpp"
# include "baseband_thread.hpp"
# include "rssi_thread.hpp"
2017-10-06 00:35:25 -04:00
# include "proc_ais.hpp"
2017-10-05 00:38:45 -04:00
# include "channel_decimator.hpp"
# include "matched_filter.hpp"
# include "clock_recovery.hpp"
# include "symbol_coding.hpp"
# include "packet_builder.hpp"
# include "baseband_packet.hpp"
# include "message.hpp"
# include "portapack_shared_memory.hpp"
2021-06-08 18:07:37 -04:00
# include "audio_output.hpp"
# include "tone_gen.hpp"
# include "buffer.hpp"
2017-10-05 00:38:45 -04:00
# include <cstdint>
# include <cstddef>
# include <bitset>
2023-05-18 16:16:05 -04:00
# define BEEP_MIN_DURATION 60
# define BEEP_DURATION_RANGE 100
# define BEEP_BASE_FREQ 200
# define RSSI_CEILING 1000
# define PROPORTIONAL_BEEP_THRES 0.8
# define RSSI_PITCH_WEIGHT 0.5
# define AUDIO_SAMPLE_RATE 24000
2021-06-13 18:35:33 -04:00
2017-10-05 00:38:45 -04:00
class SondeProcessor : public BasebandProcessor {
2023-05-18 16:16:05 -04:00
public :
SondeProcessor ( ) ;
void execute ( const buffer_c8_t & buffer ) override ;
void on_message ( const Message * const msg ) ;
private :
static constexpr size_t baseband_fs = 2457600 ;
std : : array < int16_t , 32 > audio { } ;
const buffer_s16_t audio_buffer {
( int16_t * ) audio . data ( ) ,
sizeof ( audio ) / sizeof ( int16_t ) } ;
AudioOutput audio_output { } ;
bool beep_play { false } ;
bool silence_play { false } ;
bool pitch_rssi_enabled { false } ;
uint32_t last_rssi { 0 } ;
ToneGen tone_gen { } ;
std : : array < complex16_t , 512 > dst { } ;
const buffer_c16_t dst_buffer {
dst . data ( ) ,
dst . size ( ) } ;
dsp : : decimate : : FIRC8xR16x24FS4Decim8 decim_0 { } ;
dsp : : decimate : : FIRC16xR16x32Decim8 decim_1 { } ;
dsp : : matched_filter : : MatchedFilter mf { baseband : : ais : : square_taps_38k4_1t_p , 2 } ;
// Actually 4800bits/s but the Manchester coding doubles the symbol rate
clock_recovery : : ClockRecovery < clock_recovery : : FixedErrorFilter > clock_recovery_fsk_9600 {
19200 ,
9600 ,
{ 0.0555f } ,
[ this ] ( const float raw_symbol ) {
const uint_fast8_t sliced_symbol = ( raw_symbol > = 0.0f ) ? 1 : 0 ;
this - > packet_builder_fsk_9600_Meteomodem . execute ( sliced_symbol ) ;
} } ;
PacketBuilder < BitPattern , NeverMatch , FixedLength > packet_builder_fsk_9600_Meteomodem {
{ 0b00110011001100110101100110110011 , 32 , 1 } ,
{ } ,
{ 88 * 2 * 8 } ,
[ this ] ( const baseband : : Packet & packet ) {
const SondePacketMessage message { sonde : : Packet : : Type : : Meteomodem_unknown , packet } ;
shared_memory . application_queue . push ( message ) ;
} } ;
clock_recovery : : ClockRecovery < clock_recovery : : FixedErrorFilter > clock_recovery_fsk_4800 {
19200 ,
4800 ,
{ 0.0555f } ,
[ this ] ( const float raw_symbol ) {
const uint_fast8_t sliced_symbol = ( raw_symbol > = 0.0f ) ? 1 : 0 ;
this - > packet_builder_fsk_4800_Vaisala . execute ( sliced_symbol ) ;
} } ;
PacketBuilder < BitPattern , NeverMatch , FixedLength > packet_builder_fsk_4800_Vaisala {
{ 0b00001000011011010101001110001000 , 32 , 1 } , // euquiq Header detects 4 of 8 bytes 0x10B6CA11 /this is in raw format) (these bits are not passed at the beginning of packet)
//{ 0b0000100001101101010100111000100001000100011010010100100000011111, 64, 1 }, //euquiq whole header detection would be 8 bytes.
{ } ,
{ 320 * 8 } ,
[ this ] ( const baseband : : Packet & packet ) {
const SondePacketMessage message { sonde : : Packet : : Type : : Vaisala_RS41_SG , packet } ;
shared_memory . application_queue . push ( message ) ;
} } ;
2023-07-23 02:54:17 -04:00
/* NB: Threads should be the last members in the class definition. */
BasebandThread baseband_thread {
baseband_fs , this , baseband : : Direction : : Receive , /*auto_start*/ false } ;
RSSIThread rssi_thread { } ;
2023-05-18 16:16:05 -04:00
void play_beep ( ) ;
void stop_beep ( ) ;
/**
* Used for filling the audio buffer with the waveform
* generated by the ToneGen class :
*
*/
void generate_beep ( ) ;
/**
* Used for filling the audio buffer with silence :
*/
void generate_silence ( ) ;
void pitch_rssi_config ( const PitchRSSIConfigureMessage & message ) ;
2017-10-05 00:38:45 -04:00
} ;
2023-05-18 16:16:05 -04:00
# endif /*__PROC_ERT_H__*/