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 ) .
*
* 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 :
*
2017-10-27 12:54:50 -04:00
* _______________ | ______ / ' \ ______
* - C A B C
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
*
* Taps should be computed to shift the whole spectrum by - 9600 Hz ( " left " ) so that it looks like this :
*
* ______________ / ' \ ______________
* - C D C
*
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
*
* Then the clock_recovery function should be happy : )
*
* 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 .
*
* Can SciPy ' s remez function be used for this ? See tools / firtest . py
* GnuRadio ' s firdes only outputs an odd number of taps
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Looking at the AIS baseband processor :
*
* 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.
*
* 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 ?
*
* See ais_baseband . hpp
*
* */
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>
2021-06-13 18:35:33 -04:00
2021-06-16 18:23:47 -04:00
# define BEEP_MIN_DURATION 60
# define BEEP_DURATION_RANGE 100
# define BEEP_BASE_FREQ 200
2021-06-13 18:35:33 -04:00
# define RSSI_CEILING 1000
# define PROPORTIONAL_BEEP_THRES 0.8
2021-06-16 18:23:47 -04:00
# 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 {
public :
SondeProcessor ( ) ;
void execute ( const buffer_c8_t & buffer ) override ;
2021-06-08 18:07:37 -04:00
void on_message ( const Message * const msg ) ;
2017-10-05 00:38:45 -04:00
private :
2021-06-08 18:07:37 -04:00
2017-10-05 00:38:45 -04:00
static constexpr size_t baseband_fs = 2457600 ;
2021-06-08 18:07:37 -04:00
2021-06-10 07:10:24 -04:00
std : : array < int16_t , 32 > audio { } ;
2021-06-08 18:07:37 -04:00
const buffer_s16_t audio_buffer {
( int16_t * ) audio . data ( ) ,
sizeof ( audio ) / sizeof ( int16_t )
} ;
AudioOutput audio_output { } ;
2021-06-10 19:13:56 -04:00
bool beep_play { false } ;
bool silence_play { false } ;
2021-06-08 18:07:37 -04:00
bool pitch_rssi_enabled { false } ;
2021-06-13 18:35:33 -04:00
uint32_t last_rssi { 0 } ;
2021-06-10 19:13:56 -04:00
ToneGen tone_gen { } ;
2021-06-08 18:07:37 -04:00
2017-10-05 00:38:45 -04:00
BasebandThread baseband_thread { baseband_fs , this , NORMALPRIO + 20 , baseband : : Direction : : Receive } ;
RSSIThread rssi_thread { NORMALPRIO + 10 } ;
std : : array < complex16_t , 512 > dst { } ;
const buffer_c16_t dst_buffer {
dst . data ( ) ,
dst . size ( )
} ;
2017-10-06 00:35:25 -04:00
dsp : : decimate : : FIRC8xR16x24FS4Decim8 decim_0 { } ;
dsp : : decimate : : FIRC16xR16x32Decim8 decim_1 { } ;
dsp : : matched_filter : : MatchedFilter mf { baseband : : ais : : square_taps_38k4_1t_p , 2 } ;
2017-10-05 00:38:45 -04:00
2017-11-09 21:20:44 -05:00
// Actually 4800bits/s but the Manchester coding doubles the symbol rate
clock_recovery : : ClockRecovery < clock_recovery : : FixedErrorFilter > clock_recovery_fsk_9600 {
2017-10-27 12:54:50 -04:00
19200 , 9600 , { 0.0555f } ,
2017-10-05 00:38:45 -04:00
[ this ] ( const float raw_symbol ) {
const uint_fast8_t sliced_symbol = ( raw_symbol > = 0.0f ) ? 1 : 0 ;
2017-11-09 21:20:44 -05:00
this - > packet_builder_fsk_9600_Meteomodem . execute ( sliced_symbol ) ;
2017-10-05 00:38:45 -04:00
}
} ;
2017-11-09 21:20:44 -05:00
PacketBuilder < BitPattern , NeverMatch , FixedLength > packet_builder_fsk_9600_Meteomodem {
2017-10-27 12:54:50 -04:00
{ 0b00110011001100110101100110110011 , 32 , 1 } ,
2017-10-05 00:38:45 -04:00
{ } ,
2017-10-28 13:16:06 -04:00
{ 88 * 2 * 8 } ,
2017-10-05 00:38:45 -04:00
[ this ] ( const baseband : : Packet & packet ) {
2017-11-09 21:20:44 -05:00
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 {
2020-08-14 14:51:12 -04:00
{ 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.
2017-11-09 21:20:44 -05:00
{ } ,
{ 320 * 8 } ,
[ this ] ( const baseband : : Packet & packet ) {
const SondePacketMessage message { sonde : : Packet : : Type : : Vaisala_RS41_SG , packet } ;
2017-10-05 00:38:45 -04:00
shared_memory . application_queue . push ( message ) ;
}
} ;
2021-06-08 18:07:37 -04:00
void play_beep ( ) ;
void stop_beep ( ) ;
2021-06-10 19:13:56 -04:00
/**
* Used for filling the audio buffer with the waveform
* generated by the ToneGen class :
*
*/
2021-06-10 07:10:24 -04:00
void generate_beep ( ) ;
2021-06-10 19:13:56 -04:00
/**
* Used for filling the audio buffer with silence :
*/
2021-06-10 07:10:24 -04:00
void generate_silence ( ) ;
2021-06-08 18:07:37 -04:00
void pitch_rssi_config ( const PitchRSSIConfigureMessage & message ) ;
2017-10-05 00:38:45 -04:00
} ;
# endif /*__PROC_ERT_H__*/