| 
									
										
										
										
											2022-07-20 07:07:00 +00:00
										 |  |  | // Copyright 2020-2021 Rob Riggs <rob@mobilinkd.com>
 | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | // All rights reserved.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ClockRecovery.h"
 | 
					
						
							|  |  |  | #include "Correlator.h"
 | 
					
						
							|  |  |  | #include "DataCarrierDetect.h"
 | 
					
						
							|  |  |  | #include "FirFilter.h"
 | 
					
						
							|  |  |  | #include "FreqDevEstimator.h"
 | 
					
						
							|  |  |  | #include "M17FrameDecoder.h"
 | 
					
						
							|  |  |  | #include "M17Framer.h"
 | 
					
						
							|  |  |  | #include "Util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <array>
 | 
					
						
							|  |  |  | #include <functional>
 | 
					
						
							|  |  |  | #include <tuple>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-10 17:17:56 +00:00
										 |  |  | #include "export.h"
 | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-04 21:03:07 +00:00
										 |  |  | namespace modemm17 { | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 03:47:48 +00:00
										 |  |  | struct MODEMM17_API M17Demodulator | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	static const uint16_t SAMPLE_RATE = 48000; | 
					
						
							|  |  |  | 	static const uint16_t SYMBOL_RATE = 4800; | 
					
						
							|  |  |  | 	static const uint16_t SAMPLES_PER_SYMBOL = SAMPLE_RATE / SYMBOL_RATE; | 
					
						
							|  |  |  | 	static const uint16_t BLOCK_SIZE = 192; | 
					
						
							|  |  |  | 	static const uint8_t MAX_MISSING_SYNC = 8; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	using callback_t = M17FrameDecoder::callback_t; | 
					
						
							| 
									
										
										
										
											2022-07-06 05:01:42 +00:00
										 |  |  | 	using diagnostic_callback_t = std::function<void(bool, float, float, float, int, int, float, int, int, int, int)>; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	enum class DemodState { | 
					
						
							|  |  |  |         UNLOCKED, | 
					
						
							|  |  |  |         LSF_SYNC, | 
					
						
							|  |  |  |         STREAM_SYNC, | 
					
						
							|  |  |  |         PACKET_SYNC, | 
					
						
							|  |  |  |         BERT_SYNC, | 
					
						
							|  |  |  |         FRAME | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 18:12:35 +00:00
										 |  |  | 	DataCarrierDetect<SAMPLE_RATE, 500> dcd{2500, 4000, 1.0, 4.0}; | 
					
						
							| 
									
										
										
										
											2022-07-27 12:58:33 +00:00
										 |  |  | 	ClockRecovery clock_recovery; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 21:38:35 +00:00
										 |  |  | 	SyncWord preamble_sync{{+3, -3, +3, -3, +3, -3, +3, -3}, 29.f}; | 
					
						
							|  |  |  | 	SyncWord lsf_sync{     {+3, +3, +3, +3, -3, -3, +3, -3}, 32.f, -31.f};	// LSF or STREAM (inverted)
 | 
					
						
							|  |  |  | 	SyncWord packet_sync{  {+3, -3, +3, +3, -3, -3, -3, -3}, 31.f, -31.f};	// PACKET or BERT (inverted)
 | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 18:12:35 +00:00
										 |  |  | 	FreqDevEstimator dev; | 
					
						
							|  |  |  | 	float idev; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 	size_t count_ = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int8_t polarity = 1; | 
					
						
							|  |  |  | 	M17Framer<368> framer; | 
					
						
							|  |  |  | 	M17FrameDecoder decoder; | 
					
						
							|  |  |  | 	DemodState demodState = DemodState::UNLOCKED; | 
					
						
							|  |  |  | 	M17FrameDecoder::SyncWordType sync_word_type = M17FrameDecoder::SyncWordType::LSF; | 
					
						
							|  |  |  | 	uint8_t sample_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool dcd_ = false; | 
					
						
							|  |  |  | 	bool need_clock_reset_ = false; | 
					
						
							|  |  |  | 	bool need_clock_update_ = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool passall_ = false; | 
					
						
							|  |  |  | 	int viterbi_cost = 0; | 
					
						
							|  |  |  | 	int sync_count = 0; | 
					
						
							|  |  |  | 	int missing_sync_count = 0; | 
					
						
							|  |  |  | 	uint8_t sync_sample_index = 0; | 
					
						
							|  |  |  | 	diagnostic_callback_t diagnostic_callback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	M17Demodulator(callback_t callback)	: | 
					
						
							| 
									
										
										
										
											2022-07-27 12:58:33 +00:00
										 |  |  |         clock_recovery(SAMPLE_RATE, SYMBOL_RATE), | 
					
						
							| 
									
										
										
										
											2022-06-17 00:25:34 +00:00
										 |  |  |         decoder(callback), | 
					
						
							|  |  |  |         initializing_count_(1920) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  |         demodState = DemodState::UNLOCKED; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	virtual ~M17Demodulator() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void dcd_on(); | 
					
						
							|  |  |  | 	void dcd_off(); | 
					
						
							| 
									
										
										
										
											2022-06-09 18:12:35 +00:00
										 |  |  | 	void initialize(const float input); | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 	void update_dcd(); | 
					
						
							|  |  |  | 	void do_unlocked(); | 
					
						
							|  |  |  | 	void do_lsf_sync(); | 
					
						
							|  |  |  | 	void do_packet_sync(); | 
					
						
							|  |  |  | 	void do_stream_sync(); | 
					
						
							|  |  |  | 	void do_bert_sync(); | 
					
						
							| 
									
										
										
										
											2022-06-09 18:12:35 +00:00
										 |  |  | 	void do_frame(float filtered_sample); | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-17 00:25:34 +00:00
										 |  |  | 	bool locked() const { | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 		return dcd_; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-17 00:25:34 +00:00
										 |  |  | 	void passall(bool enabled) { | 
					
						
							|  |  |  | 	    passall_ = enabled; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 		// decoder.passall(enabled);
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void diagnostics(diagnostic_callback_t callback) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		diagnostic_callback = callback; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void update_values(uint8_t index); | 
					
						
							| 
									
										
										
										
											2022-06-09 18:12:35 +00:00
										 |  |  | 	void operator()(const float input); | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2022-06-09 18:12:35 +00:00
										 |  |  |     static const std::array<float, 150> rrc_taps; | 
					
						
							|  |  |  |     BaseFirFilter<rrc_taps.size()> demod_filter{rrc_taps}; | 
					
						
							| 
									
										
										
										
											2022-07-27 21:38:35 +00:00
										 |  |  |   	Correlator correlator; | 
					
						
							| 
									
										
										
										
											2022-06-17 00:25:34 +00:00
										 |  |  |     int16_t initializing_count_; | 
					
						
							| 
									
										
										
										
											2022-06-07 01:22:18 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-04 21:03:07 +00:00
										 |  |  | } // modemm17
 |