mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			101 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "lib/core/globals.h"
 | |
| #include "lib/config/config.h"
 | |
| #include "lib/data/fluxmap.h"
 | |
| #include "lib/data/fluxpattern.h"
 | |
| #include "lib/config/proto.h"
 | |
| #include "protocol.h"
 | |
| #include <numeric>
 | |
| #include <math.h>
 | |
| #include <strings.h>
 | |
| 
 | |
| FluxPattern::FluxPattern(unsigned bits, uint64_t pattern): _bits(bits)
 | |
| {
 | |
|     const uint64_t TOPBIT = 1ULL << 63;
 | |
| 
 | |
|     assert(pattern != 0);
 | |
| 
 | |
|     unsigned lowbit = findLowestSetBit(pattern) - 1;
 | |
| 
 | |
|     pattern <<= 64 - bits;
 | |
|     _highzeroes = 0;
 | |
|     while (!(pattern & TOPBIT))
 | |
|     {
 | |
|         pattern <<= 1;
 | |
|         _highzeroes++;
 | |
|     }
 | |
| 
 | |
|     _length = 0;
 | |
|     while (pattern != TOPBIT)
 | |
|     {
 | |
|         unsigned interval = 0;
 | |
|         do
 | |
|         {
 | |
|             pattern <<= 1;
 | |
|             interval++;
 | |
|         } while (!(pattern & TOPBIT));
 | |
|         _intervals.push_back(interval);
 | |
|         _length += interval;
 | |
|     }
 | |
| 
 | |
|     if (lowbit)
 | |
|     {
 | |
|         _lowzero = true;
 | |
|         /* Note that length does *not* include this interval. */
 | |
|         _intervals.push_back(lowbit + 1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool FluxPattern::matches(const unsigned* end, FluxMatch& match) const
 | |
| {
 | |
|     const double clockDecodeThreshold =
 | |
|         globalConfig()->decoder().bit_error_threshold();
 | |
|     const unsigned* start = end - _intervals.size();
 | |
|     unsigned candidatelength = std::accumulate(start, end - _lowzero, 0);
 | |
|     if (!candidatelength)
 | |
|         return false;
 | |
|     match.clock = (double)candidatelength / (double)_length;
 | |
| 
 | |
|     unsigned exactIntervals = _intervals.size() - _lowzero;
 | |
|     for (unsigned i = 0; i < exactIntervals; i++)
 | |
|     {
 | |
|         double ii = match.clock * (double)_intervals[i];
 | |
|         double ci = (double)start[i];
 | |
|         double error = fabs((ii - ci) / match.clock);
 | |
|         if (error > clockDecodeThreshold)
 | |
|             return false;
 | |
|     }
 | |
| 
 | |
|     if (_lowzero)
 | |
|     {
 | |
|         double ii = match.clock * (double)_intervals[exactIntervals];
 | |
|         double ci = (double)start[exactIntervals];
 | |
|         double error = (ii - ci) / match.clock;
 | |
|         if (error > clockDecodeThreshold)
 | |
|             return false;
 | |
|     }
 | |
| 
 | |
|     match.matcher = this;
 | |
|     match.intervals = _intervals.size();
 | |
|     match.zeroes = _highzeroes;
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| FluxMatchers::FluxMatchers(
 | |
|     const std::initializer_list<const FluxMatcher*> matchers):
 | |
|     _matchers(matchers)
 | |
| {
 | |
|     _intervals = 0;
 | |
|     for (const auto* matcher : matchers)
 | |
|         _intervals = std::max(_intervals, matcher->intervals());
 | |
| }
 | |
| 
 | |
| bool FluxMatchers::matches(const unsigned* intervals, FluxMatch& match) const
 | |
| {
 | |
|     for (const auto* matcher : _matchers)
 | |
|     {
 | |
|         if (matcher->matches(intervals, match))
 | |
|             return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 |