mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-30 04:20:21 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			85 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2020 Mobilinkd LLC.
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "IirFilter.h"
 | |
| 
 | |
| #include <array>
 | |
| #include <algorithm>
 | |
| #include <numeric>
 | |
| #include <tuple>
 | |
| 
 | |
| namespace modemm17
 | |
| {
 | |
| 
 | |
| template <size_t N>
 | |
| struct SymbolEvm
 | |
| {
 | |
|     using filter_type = BaseIirFilter<N>;
 | |
|     using symbol_t = int;
 | |
|     using result_type = std::tuple<symbol_t, float>;
 | |
| 
 | |
|     filter_type filter_;
 | |
|     float erasure_limit_;
 | |
|     float evm_ = 0.0;
 | |
| 
 | |
|     SymbolEvm(filter_type&& filter, float erasure_limit = 0.0) :
 | |
|         filter_(std::forward<filter_type>(filter)),
 | |
|         erasure_limit_(erasure_limit)
 | |
|     {}
 | |
| 
 | |
|     float evm() const { return evm_; }
 | |
| 
 | |
|     /**
 | |
|      * Decode a normalized sample into a symbol.  Symbols
 | |
|      * are decoded into +3, +1, -1, -3.  If an erasure limit
 | |
|      * is set, symbols outside this limit are 'erased' and
 | |
|      * returned as 0.
 | |
|      */
 | |
|     result_type operator()(float sample)
 | |
|     {
 | |
|         symbol_t symbol;
 | |
|         float evm;
 | |
| 
 | |
|         sample = std::min(3.0f, std::max(-3.0f, sample));
 | |
| 
 | |
|         if (sample > 2)
 | |
|         {
 | |
|             symbol = 3;
 | |
|             evm = (sample - 3) * 0.333333;
 | |
|         }
 | |
|         else if (sample > 0)
 | |
|         {
 | |
|             symbol = 1;
 | |
|             evm = sample - 1;
 | |
|         }
 | |
|         else if (sample >= -2)
 | |
|         {
 | |
|             symbol = -1;
 | |
|             evm = sample + 1;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             symbol = -3;
 | |
|             evm = (sample + 3) * 0.333333;
 | |
|         }
 | |
| 
 | |
|         if (erasure_limit_ and (std::abs(evm) > erasure_limit_)) symbol = 0;
 | |
| 
 | |
|         evm_ = filter_(evm);
 | |
| 
 | |
|         return std::make_tuple(symbol, evm);
 | |
|     }
 | |
| };
 | |
| 
 | |
| template <size_t N>
 | |
| SymbolEvm<N> makeSymbolEvm(
 | |
|     BaseIirFilter<N>&& filter,
 | |
|     float erasure_limit = 0.0f
 | |
| )
 | |
| {
 | |
|     return std::move(SymbolEvm<N>(std::move(filter), erasure_limit));
 | |
| }
 | |
| 
 | |
| } // modemm17
 |