2014-12-29 09:33:32 +08:00
//-----------------------------------------------------------------------------
2015-01-07 12:29:45 +08:00
// Copyright (C) 2014
2014-12-29 09:33:32 +08:00
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
2017-07-28 04:05:54 +08:00
// Low frequency demod/decode commands - by marshmellow, holiman, iceman and
// many others who came before
//
2019-03-09 15:59:13 +08:00
// NOTES:
2017-07-28 04:05:54 +08:00
// LF Demod functions are placed here to allow the flexability to use client or
2019-03-09 15:59:13 +08:00
// device side. Most BUT NOT ALL of these functions are currenlty safe for
2017-07-28 04:05:54 +08:00
// device side use currently. (DetectST for example...)
//
// There are likely many improvements to the code that could be made, please
// make suggestions...
//
2019-03-09 15:59:13 +08:00
// we tried to include author comments so any questions could be directed to
2017-07-28 04:05:54 +08:00
// the source.
//
// There are 4 main sections of code below:
2017-07-30 15:17:48 +08:00
//
2019-03-09 15:59:13 +08:00
// Utilities Section:
2017-07-28 04:05:54 +08:00
// for general utilities used by multiple other functions
2017-07-30 15:17:48 +08:00
//
2017-07-28 04:05:54 +08:00
// Clock / Bitrate Detection Section:
// for clock detection functions for each modulation
2017-07-30 15:17:48 +08:00
//
2017-07-28 04:05:54 +08:00
// Modulation Demods &/or Decoding Section:
// for main general modulation demodulating and encoding decoding code.
2017-07-30 15:17:48 +08:00
//
2017-07-28 04:05:54 +08:00
// Tag format detection section:
// for detection of specific tag formats within demodulated data
//
// marshmellow
2014-12-29 09:33:32 +08:00
//-----------------------------------------------------------------------------
2017-07-28 04:05:54 +08:00
2014-12-29 09:33:32 +08:00
# include "lfdemod.h"
2019-08-08 22:57:33 +08:00
# include <string.h> // for memset, memcmp and size_t
2019-09-23 01:00:11 +08:00
# include <stdlib.h> // qsort
2017-07-28 04:05:54 +08:00
# include "parity.h" // for parity test
2019-08-05 01:26:53 +08:00
# include "pm3_cmd.h" // error codes
2021-01-28 07:35:14 +08:00
# include "commonutil.h" // Arraylen
2019-09-23 01:00:11 +08:00
// **********************************************************************************************
// ---------------------------------Utilities Section--------------------------------------------
// **********************************************************************************************
2017-07-28 04:05:54 +08:00
# define LOWEST_DEFAULT_CLOCK 32
# define FSK_PSK_THRESHOLD 123
2019-03-09 02:06:55 +08:00
2017-11-06 22:06:42 +08:00
//to allow debug print calls when used not on dev
2017-02-13 22:33:26 +08:00
2015-11-20 23:56:43 +08:00
# ifndef ON_DEVICE
2017-07-30 15:17:48 +08:00
# include "ui.h"
2020-05-03 18:23:55 +08:00
# include "util.h"
2017-02-13 22:33:26 +08:00
# include "cmddata.h"
2019-03-25 21:40:29 +08:00
# define prnt(args...) PrintAndLogEx(DEBUG, ## args );
2019-03-09 15:59:13 +08:00
# else
2019-08-08 22:57:33 +08:00
# include "dbprint.h"
2019-03-10 07:00:59 +08:00
uint8_t g_debugMode = 0 ;
2018-09-06 01:13:39 +08:00
# define prnt Dbprintf
2017-03-03 19:27:35 +08:00
# endif
2017-03-03 18:36:07 +08:00
2017-11-06 22:06:42 +08:00
signal_t signalprop = { 255 , - 255 , 0 , 0 , true } ;
2019-03-10 18:20:22 +08:00
signal_t * getSignalProperties ( void ) {
2019-03-10 02:19:50 +08:00
return & signalprop ;
2017-11-06 22:06:42 +08:00
}
2019-03-10 18:20:22 +08:00
static void resetSignal ( void ) {
2019-03-10 02:19:50 +08:00
signalprop . low = 255 ;
signalprop . high = - 255 ;
signalprop . mean = 0 ;
signalprop . amplitude = 0 ;
signalprop . isnoise = true ;
2017-11-06 22:06:42 +08:00
}
2019-03-09 02:06:55 +08:00
2019-03-10 18:20:22 +08:00
static void printSignal ( void ) {
2019-03-10 02:19:50 +08:00
prnt ( " LF signal properties: " ) ;
prnt ( " high..........%d " , signalprop . high ) ;
prnt ( " low...........%d " , signalprop . low ) ;
prnt ( " mean..........%d " , signalprop . mean ) ;
prnt ( " amplitude.....%d " , signalprop . amplitude ) ;
2019-05-28 17:15:12 +08:00
prnt ( " is Noise......%s " , ( signalprop . isnoise ) ? _RED_ ( " Yes " ) : _GREEN_ ( " No " ) ) ;
2019-03-10 07:00:59 +08:00
prnt ( " THRESHOLD noise amplitude......%d " , NOISE_AMPLITUDE_THRESHOLD ) ;
2018-09-08 05:47:42 +08:00
}
2019-09-23 01:00:11 +08:00
# ifndef ON_DEVICE
static int cmp_uint8 ( const void * a , const void * b ) {
2019-10-13 06:48:26 +08:00
if ( * ( const uint8_t * ) a < * ( const uint8_t * ) b )
return - 1 ;
else
return * ( const uint8_t * ) a > * ( const uint8_t * ) b ;
2019-09-23 01:00:11 +08:00
}
# endif
2019-03-10 18:20:22 +08:00
void computeSignalProperties ( uint8_t * samples , uint32_t size ) {
2019-03-10 02:19:50 +08:00
resetSignal ( ) ;
2019-09-23 01:00:11 +08:00
if ( samples = = NULL | | size < SIGNAL_MIN_SAMPLES ) return ;
2019-03-10 02:19:50 +08:00
uint32_t sum = 0 ;
2019-09-23 01:00:11 +08:00
uint32_t offset_size = size - SIGNAL_IGNORE_FIRST_SAMPLES ;
# ifndef ON_DEVICE
uint8_t tmp [ offset_size ] ;
memcpy ( tmp , samples + SIGNAL_IGNORE_FIRST_SAMPLES , sizeof ( tmp ) ) ;
qsort ( tmp , sizeof ( tmp ) , sizeof ( uint8_t ) , cmp_uint8 ) ;
uint8_t low10 = 0.5 * ( tmp [ ( int ) ( offset_size * 0.1 ) ] + tmp [ ( int ) ( ( offset_size - 1 ) * 0.1 ) ] ) ;
uint8_t hi90 = 0.5 * ( tmp [ ( int ) ( offset_size * 0.9 ) ] + tmp [ ( int ) ( ( offset_size - 1 ) * 0.9 ) ] ) ;
uint32_t cnt = 0 ;
for ( uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES ; i < size ; i + + ) {
if ( samples [ i ] < signalprop . low ) signalprop . low = samples [ i ] ;
if ( samples [ i ] > signalprop . high ) signalprop . high = samples [ i ] ;
if ( samples [ i ] < low10 | | samples [ i ] > hi90 )
continue ;
sum + = samples [ i ] ;
cnt + + ;
2019-10-10 05:01:07 +08:00
}
if ( cnt > 0 )
signalprop . mean = sum / cnt ;
else
signalprop . mean = 0 ;
2019-09-23 01:00:11 +08:00
# else
2019-10-13 06:48:26 +08:00
for ( uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES ; i < size ; i + + ) {
2019-03-10 07:00:59 +08:00
if ( samples [ i ] < signalprop . low ) signalprop . low = samples [ i ] ;
if ( samples [ i ] > signalprop . high ) signalprop . high = samples [ i ] ;
2019-03-10 02:19:50 +08:00
sum + = samples [ i ] ;
}
2019-09-23 01:00:11 +08:00
signalprop . mean = sum / offset_size ;
# endif
2019-03-10 02:19:50 +08:00
// measure amplitude of signal
signalprop . amplitude = signalprop . high - signalprop . mean ;
// By measuring mean and look at amplitude of signal from HIGH / LOW,
// we can detect noise
signalprop . isnoise = signalprop . amplitude < NOISE_AMPLITUDE_THRESHOLD ;
2019-07-13 06:38:30 +08:00
if ( g_debugMode )
2019-06-08 22:16:15 +08:00
printSignal ( ) ;
2019-03-09 02:06:55 +08:00
}
2019-03-10 18:20:22 +08:00
void removeSignalOffset ( uint8_t * samples , uint32_t size ) {
2019-03-10 07:00:59 +08:00
if ( samples = = NULL | | size < SIGNAL_MIN_SAMPLES ) return ;
2019-03-10 02:19:50 +08:00
int acc_off = 0 ;
2019-09-23 01:00:11 +08:00
uint32_t offset_size = size - SIGNAL_IGNORE_FIRST_SAMPLES ;
# ifndef ON_DEVICE
uint8_t tmp [ offset_size ] ;
memcpy ( tmp , samples + SIGNAL_IGNORE_FIRST_SAMPLES , sizeof ( tmp ) ) ;
qsort ( tmp , sizeof ( tmp ) , sizeof ( uint8_t ) , cmp_uint8 ) ;
uint8_t low10 = 0.5 * ( tmp [ ( int ) ( offset_size * 0.05 ) ] + tmp [ ( int ) ( ( offset_size - 1 ) * 0.05 ) ] ) ;
uint8_t hi90 = 0.5 * ( tmp [ ( int ) ( offset_size * 0.95 ) ] + tmp [ ( int ) ( ( offset_size - 1 ) * 0.95 ) ] ) ;
int32_t cnt = 0 ;
for ( uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES ; i < size ; i + + ) {
if ( samples [ i ] < low10 | | samples [ i ] > hi90 )
continue ;
acc_off + = samples [ i ] - 128 ;
cnt + + ;
2019-10-10 05:01:07 +08:00
}
if ( cnt > 0 )
acc_off / = cnt ;
else
acc_off = 0 ;
2019-09-23 01:00:11 +08:00
# else
2019-03-10 02:19:50 +08:00
for ( uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES ; i < size ; i + + )
acc_off + = samples [ i ] - 128 ;
2019-09-23 01:00:11 +08:00
acc_off / = ( int ) offset_size ;
# endif
2019-03-10 02:19:50 +08:00
// shift and saturate samples to center the mean
2019-03-10 07:00:59 +08:00
for ( uint32_t i = 0 ; i < size ; i + + ) {
2019-03-10 02:19:50 +08:00
if ( acc_off > 0 ) {
2019-03-10 07:00:59 +08:00
samples [ i ] = ( samples [ i ] > = acc_off ) ? samples [ i ] - acc_off : 0 ;
2019-03-10 02:19:50 +08:00
}
if ( acc_off < 0 ) {
2019-03-10 07:00:59 +08:00
samples [ i ] = ( 255 - samples [ i ] > = - acc_off ) ? samples [ i ] - acc_off : 255 ;
2019-03-10 02:19:50 +08:00
}
}
2015-01-28 03:51:12 +08:00
}
2015-01-19 07:13:32 +08:00
//by marshmellow
2015-02-22 10:36:02 +08:00
//get high and low values of a wave with passed in fuzz factor. also return noise test = 1 for passed or 0 for only noise
2018-09-09 18:34:43 +08:00
//void getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) {
2019-03-10 18:20:22 +08:00
void getHiLo ( int * high , int * low , uint8_t fuzzHi , uint8_t fuzzLo ) {
2019-03-10 02:19:50 +08:00
// add fuzz.
* high = ( signalprop . high * fuzzHi ) / 100 ;
2019-03-10 07:00:59 +08:00
if ( signalprop . low < 0 ) {
2019-03-10 02:19:50 +08:00
* low = ( signalprop . low * fuzzLo ) / 100 ;
} else {
uint8_t range = signalprop . high - signalprop . low ;
2019-03-10 07:00:59 +08:00
* low = signalprop . low + ( ( range * ( 100 - fuzzLo ) ) / 100 ) ;
2019-03-10 02:19:50 +08:00
}
// if fuzzing to great and overlap
2019-10-15 03:17:41 +08:00
if ( * high < = * low ) {
2019-03-10 02:19:50 +08:00
* high = signalprop . high ;
* low = signalprop . low ;
}
2020-03-10 00:09:07 +08:00
// prnt("getHiLo fuzzed: High %d | Low %d", *high, *low);
2015-01-19 07:13:32 +08:00
}
2015-01-28 03:51:12 +08:00
// by marshmellow
// pass bits to be tested in bits, length bits passed in bitLen, and parity type (even=0 | odd=1) in pType
// returns 1 if passed
2019-03-10 18:20:22 +08:00
bool parityTest ( uint32_t bits , uint8_t bitLen , uint8_t pType ) {
2019-03-10 02:19:50 +08:00
return oddparity32 ( bits ) ^ pType ;
2015-01-28 03:51:12 +08:00
}
2015-11-23 00:33:41 +08:00
//by marshmellow
2017-07-28 04:05:54 +08:00
// takes a array of binary values, start position, length of bits per parity (includes parity bit - MAX 32),
2019-03-09 15:59:13 +08:00
// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
2019-03-10 18:20:22 +08:00
size_t removeParity ( uint8_t * bits , size_t startIdx , uint8_t pLen , uint8_t pType , size_t bLen ) {
2019-03-10 02:19:50 +08:00
uint32_t parityWd = 0 ;
size_t bitCnt = 0 ;
2019-03-10 07:00:59 +08:00
for ( int word = 0 ; word < ( bLen ) ; word + = pLen ) {
for ( int bit = 0 ; bit < pLen ; bit + + ) {
if ( word + bit > = bLen ) break ;
parityWd = ( parityWd < < 1 ) | bits [ startIdx + word + bit ] ;
bits [ bitCnt + + ] = ( bits [ startIdx + word + bit ] ) ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
if ( word + pLen > bLen ) break ;
2019-03-10 02:19:50 +08:00
bitCnt - - ; // overwrite parity with next data
// if parity fails then return 0
switch ( pType ) {
2019-03-10 07:00:59 +08:00
case 3 :
if ( bits [ bitCnt ] = = 1 ) { return 0 ; }
break ; //should be 0 spacer bit
case 2 :
if ( bits [ bitCnt ] = = 0 ) { return 0 ; }
break ; //should be 1 spacer bit
default :
if ( parityTest ( parityWd , pLen , pType ) = = 0 ) { return 0 ; }
break ; //test parity
2019-03-10 02:19:50 +08:00
}
parityWd = 0 ;
}
// if we got here then all the parities passed
//return size
return bitCnt ;
2015-11-23 00:33:41 +08:00
}
// by marshmellow
// takes a array of binary values, length of bits per parity (includes parity bit),
2016-02-29 05:43:21 +08:00
// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
2016-03-01 13:57:02 +08:00
// Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
2019-03-10 18:20:22 +08:00
size_t addParity ( uint8_t * src , uint8_t * dest , uint8_t sourceLen , uint8_t pLen , uint8_t pType ) {
2019-03-10 02:19:50 +08:00
uint32_t parityWd = 0 ;
size_t j = 0 , bitCnt = 0 ;
2019-03-10 07:00:59 +08:00
for ( int word = 0 ; word < sourceLen ; word + = pLen - 1 ) {
for ( int bit = 0 ; bit < pLen - 1 ; bit + + ) {
parityWd = ( parityWd < < 1 ) | src [ word + bit ] ;
dest [ j + + ] = ( src [ word + bit ] ) ;
2019-03-10 02:19:50 +08:00
}
// if parity fails then return 0
switch ( pType ) {
2019-03-10 07:00:59 +08:00
case 3 :
dest [ j + + ] = 0 ;
break ; // marker bit which should be a 0
case 2 :
dest [ j + + ] = 1 ;
break ; // marker bit which should be a 1
2019-03-10 02:19:50 +08:00
default :
2019-03-10 07:00:59 +08:00
dest [ j + + ] = parityTest ( parityWd , pLen - 1 , pType ) ^ 1 ;
2019-03-10 02:19:50 +08:00
break ;
}
bitCnt + = pLen ;
parityWd = 0 ;
}
// if we got here then all the parities passed
//return ID start index and size
return bitCnt ;
2015-11-23 00:33:41 +08:00
}
2017-12-23 18:23:14 +08:00
// array must be size dividable with 8
2019-08-05 01:26:53 +08:00
int bits_to_array ( const uint8_t * bits , size_t size , uint8_t * dest ) {
if ( ( size = = 0 ) | | ( size % 8 ) ! = 0 ) return PM3_EINVARG ;
2019-03-09 15:59:13 +08:00
2019-03-10 07:00:59 +08:00
for ( uint32_t i = 0 ; i < ( size / 8 ) ; i + + )
2019-03-10 02:19:50 +08:00
dest [ i ] = bytebits_to_byte ( ( uint8_t * ) bits + ( i * 8 ) , 8 ) ;
2017-12-23 18:23:14 +08:00
2019-08-05 01:26:53 +08:00
return PM3_SUCCESS ;
2017-12-23 18:23:14 +08:00
}
2019-03-10 18:20:22 +08:00
uint32_t bytebits_to_byte ( uint8_t * src , size_t numbits ) {
2019-03-10 02:19:50 +08:00
uint32_t num = 0 ;
2019-03-10 07:00:59 +08:00
for ( int i = 0 ; i < numbits ; i + + ) {
2019-03-10 02:19:50 +08:00
num = ( num < < 1 ) | ( * src ) ;
src + + ;
}
return num ;
2015-11-23 00:33:41 +08:00
}
//least significant bit first
2019-03-10 18:20:22 +08:00
uint32_t bytebits_to_byteLSBF ( uint8_t * src , size_t numbits ) {
2019-03-10 02:19:50 +08:00
uint32_t num = 0 ;
2019-03-10 07:00:59 +08:00
for ( int i = 0 ; i < numbits ; i + + ) {
num = ( num < < 1 ) | * ( src + ( numbits - ( i + 1 ) ) ) ;
2019-03-10 02:19:50 +08:00
}
return num ;
2015-11-23 00:33:41 +08:00
}
2017-02-23 07:52:40 +08:00
//by marshmellow
2017-07-30 15:17:48 +08:00
//search for given preamble in given BitStream and return success = TRUE or fail = FALSE and startIndex and length
2019-03-10 18:20:22 +08:00
bool preambleSearch ( uint8_t * bits , uint8_t * preamble , size_t pLen , size_t * size , size_t * startIdx ) {
2019-03-10 02:19:50 +08:00
return preambleSearchEx ( bits , preamble , pLen , size , startIdx , false ) ;
2017-02-23 07:52:40 +08:00
}
2015-01-28 03:51:12 +08:00
//by marshmellow
2019-03-09 15:59:13 +08:00
// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) and length if not fineone
2017-07-30 15:17:48 +08:00
// fineone does not look for a repeating preamble for em4x05/4x69 sends preamble once, so look for it once in the first pLen bits
2017-07-31 03:21:02 +08:00
//(iceman) FINDONE, only finds start index. NOT SIZE!. I see Em410xDecode (lfdemod.c) uses SIZE to determine success
2019-03-10 18:20:22 +08:00
bool preambleSearchEx ( uint8_t * bits , uint8_t * preamble , size_t pLen , size_t * size , size_t * startIdx , bool findone ) {
2019-03-10 02:19:50 +08:00
// Sanity check. If preamble length is bigger than bits length.
2019-03-25 21:03:36 +08:00
if ( * size < = pLen )
return false ;
2019-03-10 02:19:50 +08:00
uint8_t foundCnt = 0 ;
for ( size_t idx = 0 ; idx < * size - pLen ; idx + + ) {
2019-03-10 07:00:59 +08:00
if ( memcmp ( bits + idx , preamble , pLen ) = = 0 ) {
2019-03-10 02:19:50 +08:00
//first index found
foundCnt + + ;
2019-03-10 07:00:59 +08:00
if ( foundCnt = = 1 ) {
2019-10-09 22:40:01 +08:00
if ( g_debugMode > = 1 ) prnt ( " DEBUG: (preambleSearchEx) preamble found at %zu " , idx ) ;
2019-03-10 02:19:50 +08:00
* startIdx = idx ;
2019-06-08 03:40:33 +08:00
if ( findone )
2019-05-28 17:24:36 +08:00
return true ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
if ( foundCnt = = 2 ) {
2019-10-09 22:40:01 +08:00
if ( g_debugMode > = 1 ) prnt ( " DEBUG: (preambleSearchEx) preamble 2 found at %zu " , idx ) ;
2019-03-10 02:19:50 +08:00
* size = idx - * startIdx ;
return true ;
}
}
}
return ( foundCnt > 0 ) ;
2017-02-23 07:52:40 +08:00
}
// find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup.
2019-04-13 06:25:43 +08:00
static size_t findModStart ( uint8_t * src , size_t size , uint8_t expWaveSize ) {
2019-03-10 02:19:50 +08:00
size_t i = 0 ;
size_t waveSizeCnt = 0 ;
uint8_t thresholdCnt = 0 ;
bool isAboveThreshold = src [ i + + ] > = signalprop . mean ; //FSK_PSK_THRESHOLD;
2019-03-10 07:00:59 +08:00
for ( ; i < size - 20 ; i + + ) {
2019-03-10 02:19:50 +08:00
if ( src [ i ] < signalprop . mean & & isAboveThreshold ) {
thresholdCnt + + ;
2019-03-10 07:00:59 +08:00
if ( thresholdCnt > 2 & & waveSizeCnt < expWaveSize + 1 ) break ;
2019-03-10 02:19:50 +08:00
isAboveThreshold = false ;
waveSizeCnt = 0 ;
} else if ( src [ i ] > = signalprop . mean & & ! isAboveThreshold ) {
thresholdCnt + + ;
2019-03-10 07:00:59 +08:00
if ( thresholdCnt > 2 & & waveSizeCnt < expWaveSize + 1 ) break ;
2019-03-10 02:19:50 +08:00
isAboveThreshold = true ;
waveSizeCnt = 0 ;
} else {
waveSizeCnt + + ;
}
if ( thresholdCnt > 10 ) break ;
}
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG: threshold Count reached at index %zu, count: %u " , i , thresholdCnt ) ;
2019-03-10 02:19:50 +08:00
return i ;
2015-01-28 03:51:12 +08:00
}
2019-04-13 06:25:43 +08:00
static int getClosestClock ( int testclk ) {
2019-03-20 00:53:58 +08:00
uint16_t clocks [ ] = { 8 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 256 , 384 } ;
uint8_t limit [ ] = { 1 , 2 , 4 , 4 , 5 , 8 , 8 , 8 , 8 , 8 } ;
2017-03-02 03:14:46 +08:00
2019-05-26 01:27:43 +08:00
for ( uint8_t i = 0 ; i < 10 ; i + + ) {
2019-03-10 07:00:59 +08:00
if ( testclk > = clocks [ i ] - limit [ i ] & & testclk < = clocks [ i ] + limit [ i ] )
2019-03-10 02:19:50 +08:00
return clocks [ i ] ;
2019-05-26 01:27:43 +08:00
}
2019-03-10 02:19:50 +08:00
return 0 ;
2015-03-16 20:39:18 +08:00
}
2019-03-10 18:20:22 +08:00
void getNextLow ( uint8_t * samples , size_t size , int low , size_t * i ) {
2019-03-10 02:19:50 +08:00
while ( ( samples [ * i ] > low ) & & ( * i < size ) )
* i + = 1 ;
2015-04-03 00:48:52 +08:00
}
2019-03-10 18:20:22 +08:00
void getNextHigh ( uint8_t * samples , size_t size , int high , size_t * i ) {
2019-03-10 02:19:50 +08:00
while ( ( samples [ * i ] < high ) & & ( * i < size ) )
* i + = 1 ;
2015-04-08 13:07:39 +08:00
}
2017-07-30 15:17:48 +08:00
// load wave counters
2019-03-10 18:20:22 +08:00
bool loadWaveCounters ( uint8_t * samples , size_t size , int lowToLowWaveLen [ ] , int highToLowWaveLen [ ] , int * waveCnt , int * skip , int * minClk , int * high , int * low ) {
2019-06-08 00:41:39 +08:00
size_t i = 0 ;
2019-03-10 02:19:50 +08:00
//size_t testsize = (size < 512) ? size : 512;
// just noise - no super good detection. good enough
if ( signalprop . isnoise ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: just noise detected - quitting " ) ;
return false ;
}
getHiLo ( high , low , 80 , 80 ) ;
// get to first full low to prime loop and skip incomplete first pulse
getNextHigh ( samples , size , * high , & i ) ;
getNextLow ( samples , size , * low , & i ) ;
* skip = i ;
// populate tmpbuff buffer with pulse lengths
while ( i < size ) {
// measure from low to low
2019-06-08 00:41:39 +08:00
size_t firstLow = i ;
2019-03-10 02:19:50 +08:00
//find first high point for this wave
getNextHigh ( samples , size , * high , & i ) ;
2019-06-08 00:41:39 +08:00
size_t firstHigh = i ;
2019-03-10 02:19:50 +08:00
getNextLow ( samples , size , * low , & i ) ;
2019-03-10 07:00:59 +08:00
if ( * waveCnt > = ( size / LOWEST_DEFAULT_CLOCK ) )
2019-03-10 02:19:50 +08:00
break ;
highToLowWaveLen [ * waveCnt ] = i - firstHigh ; //first high to first low
lowToLowWaveLen [ * waveCnt ] = i - firstLow ;
* waveCnt + = 1 ;
2019-03-10 07:00:59 +08:00
if ( i - firstLow < * minClk & & i < size ) {
2019-03-10 02:19:50 +08:00
* minClk = i - firstLow ;
}
}
return true ;
2014-12-29 09:33:32 +08:00
}
2017-02-28 23:55:16 +08:00
2019-03-10 18:20:22 +08:00
size_t pskFindFirstPhaseShift ( uint8_t * samples , size_t size , uint8_t * curPhase , size_t waveStart , uint16_t fc , uint16_t * fullWaveLen ) {
2019-03-10 07:00:59 +08:00
uint16_t loopCnt = ( size + 3 < 4096 ) ? size : 4096 ; //don't need to loop through entire array...
2019-03-10 02:19:50 +08:00
2019-04-13 14:50:05 +08:00
uint16_t avgWaveVal = 0 , lastAvgWaveVal ;
2019-03-10 02:19:50 +08:00
size_t i = waveStart , waveEnd , waveLenCnt , firstFullWave ;
2019-03-10 07:00:59 +08:00
for ( ; i < loopCnt ; i + + ) {
2019-03-10 02:19:50 +08:00
// find peak // was "samples[i] + fc" but why? must have been used to weed out some wave error... removed..
2019-03-10 07:00:59 +08:00
if ( samples [ i ] < samples [ i + 1 ] & & samples [ i + 1 ] > = samples [ i + 2 ] ) {
waveEnd = i + 1 ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: waveEnd: %zu, waveStart: %zu " , waveEnd , waveStart ) ;
2019-03-10 07:00:59 +08:00
waveLenCnt = waveEnd - waveStart ;
if ( waveLenCnt > fc & & waveStart > fc & & ! ( waveLenCnt > fc + 8 ) ) { //not first peak and is a large wave but not out of whack
lastAvgWaveVal = avgWaveVal / ( waveLenCnt ) ;
2019-03-10 02:19:50 +08:00
firstFullWave = waveStart ;
* fullWaveLen = waveLenCnt ;
//if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting)
if ( lastAvgWaveVal > FSK_PSK_THRESHOLD ) * curPhase ^ = 1 ;
return firstFullWave ;
}
2019-03-10 07:00:59 +08:00
waveStart = i + 1 ;
2019-03-10 02:19:50 +08:00
avgWaveVal = 0 ;
}
2019-03-10 07:00:59 +08:00
avgWaveVal + = samples [ i + 2 ] ;
2019-03-10 02:19:50 +08:00
}
return 0 ;
2017-07-30 15:17:48 +08:00
}
//by marshmellow
//amplify based on ask edge detection - not accurate enough to use all the time
2019-03-10 18:20:22 +08:00
void askAmp ( uint8_t * bits , size_t size ) {
2019-03-10 02:19:50 +08:00
uint8_t last = 128 ;
2019-03-10 07:00:59 +08:00
for ( size_t i = 1 ; i < size ; + + i ) {
if ( bits [ i ] - bits [ i - 1 ] > = 30 ) //large jump up
2019-03-10 02:19:50 +08:00
last = 255 ;
2019-03-10 07:00:59 +08:00
else if ( bits [ i - 1 ] - bits [ i ] > = 20 ) //large jump down
2019-03-10 02:19:50 +08:00
last = 0 ;
bits [ i ] = last ;
}
2014-12-31 15:27:30 +08:00
}
2017-07-30 15:17:48 +08:00
// iceman, simplify this
2019-03-10 18:20:22 +08:00
uint32_t manchesterEncode2Bytes ( uint16_t datain ) {
2019-03-10 02:19:50 +08:00
uint32_t output = 0 ;
for ( uint8_t i = 0 ; i < 16 ; i + + ) {
2021-04-28 01:16:21 +08:00
uint8_t b = ( datain > > ( 15 - i ) & 1 ) ;
output | = ( 1 < < ( ( ( 15 - i ) * 2 ) + b ) ) ;
2019-03-10 02:19:50 +08:00
}
return output ;
2015-10-28 04:47:21 +08:00
}
2019-09-15 08:09:40 +08:00
void manchesterEncodeUint32 ( uint32_t data_in , uint8_t bitlen_in , uint8_t * bits_out , uint16_t * index ) {
for ( int i = bitlen_in - 1 ; i > = 0 ; i - - ) {
if ( ( data_in > > i ) & 1 ) {
bits_out [ ( * index ) + + ] = 1 ;
bits_out [ ( * index ) + + ] = 0 ;
} else {
bits_out [ ( * index ) + + ] = 0 ;
bits_out [ ( * index ) + + ] = 1 ;
}
}
}
2015-04-08 13:07:39 +08:00
//by marshmellow
2019-03-09 15:59:13 +08:00
//encode binary data into binary manchester
2017-07-30 15:17:48 +08:00
//NOTE: bitstream must have triple the size of "size" available in memory to do the swap
2019-03-10 18:20:22 +08:00
int ManchesterEncode ( uint8_t * bits , size_t size ) {
2019-03-10 02:19:50 +08:00
//allow up to 4096b out (means bits must be at least 2048+4096 to handle the swap)
size = ( size > 2048 ) ? 2048 : size ;
size_t modIdx = size ;
size_t i ;
2019-03-10 07:00:59 +08:00
for ( size_t idx = 0 ; idx < size ; idx + + ) {
bits [ idx + modIdx + + ] = bits [ idx ] ;
bits [ idx + modIdx + + ] = bits [ idx ] ^ 1 ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < ( size * 2 ) ; i + + ) {
bits [ i ] = bits [ i + size ] ;
2019-03-10 02:19:50 +08:00
}
return i ;
2015-04-08 13:07:39 +08:00
}
2017-07-30 15:17:48 +08:00
// by marshmellow
// to detect a wave that has heavily clipped (clean) samples
2019-04-06 02:28:58 +08:00
// loop 1024 samples, if 250 of them is deemed maxed out, we assume the wave is clipped.
2019-03-10 18:20:22 +08:00
bool DetectCleanAskWave ( uint8_t * dest , size_t size , uint8_t high , uint8_t low ) {
2019-03-10 02:19:50 +08:00
bool allArePeaks = true ;
uint16_t cntPeaks = 0 ;
2019-04-06 02:28:58 +08:00
size_t loopEnd = 1024 + 160 ;
2019-03-09 15:59:13 +08:00
2019-03-10 02:19:50 +08:00
// sanity check
if ( loopEnd > size ) loopEnd = size ;
2019-03-09 15:59:13 +08:00
2019-03-10 07:00:59 +08:00
for ( size_t i = 160 ; i < loopEnd ; i + + ) {
2019-03-09 15:59:13 +08:00
2019-03-10 02:19:50 +08:00
if ( dest [ i ] > low & & dest [ i ] < high )
allArePeaks = false ;
2019-04-09 22:23:55 +08:00
else {
2019-03-10 02:19:50 +08:00
cntPeaks + + ;
2019-04-09 22:23:55 +08:00
//if (g_debugMode == 2) prnt("DEBUG DetectCleanAskWave: peaks (200) %u", cntPeaks);
if ( cntPeaks > 200 ) return true ;
}
2019-03-10 02:19:50 +08:00
}
2019-03-09 15:59:13 +08:00
2019-04-09 22:23:55 +08:00
if ( allArePeaks = = false ) {
2019-04-06 02:28:58 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG DetectCleanAskWave: peaks (200) %u " , cntPeaks ) ;
if ( cntPeaks > 200 ) return true ;
2019-03-10 02:19:50 +08:00
}
return allArePeaks ;
2014-12-29 09:33:32 +08:00
}
2015-03-04 05:20:18 +08:00
2019-09-23 01:00:11 +08:00
// **********************************************************************************************
// -------------------Clock / Bitrate Detection Section------------------------------------------
// **********************************************************************************************
2017-02-23 07:52:40 +08:00
2017-02-19 07:12:35 +08:00
2017-07-30 15:17:48 +08:00
// by marshmellow
// to help detect clocks on heavily clipped samples
// based on count of low to low
2019-06-08 03:26:03 +08:00
int DetectStrongAskClock ( uint8_t * dest , size_t size , int high , int low , int * clock ) {
2019-03-10 02:19:50 +08:00
size_t i = 100 ;
size_t minClk = 512 ;
2019-03-19 21:41:57 +08:00
uint16_t shortestWaveIdx = 0 ;
2019-03-10 02:19:50 +08:00
// get to first full low to prime loop and skip incomplete first pulse
2019-06-08 03:26:03 +08:00
getNextHigh ( dest , size , high , & i ) ;
getNextLow ( dest , size , low , & i ) ;
2019-03-10 02:19:50 +08:00
2019-03-21 05:10:34 +08:00
if ( i = = size )
return - 1 ;
2019-05-26 01:27:43 +08:00
if ( size < 512 )
return - 2 ;
2019-03-28 21:19:41 +08:00
2019-03-19 21:41:57 +08:00
// clock, numoftimes, first idx
2019-03-20 00:53:58 +08:00
uint16_t tmpclk [ 10 ] [ 3 ] = {
2019-03-28 21:19:41 +08:00
{ 8 , 0 , 0 } ,
{ 16 , 0 , 0 } ,
{ 32 , 0 , 0 } ,
{ 40 , 0 , 0 } ,
{ 50 , 0 , 0 } ,
{ 64 , 0 , 0 } ,
{ 100 , 0 , 0 } ,
2019-03-19 21:41:57 +08:00
{ 128 , 0 , 0 } ,
2019-03-28 21:19:41 +08:00
{ 256 , 0 , 0 } ,
2019-03-19 21:41:57 +08:00
{ 384 , 0 , 0 } ,
2019-03-28 21:19:41 +08:00
} ;
2019-03-10 02:19:50 +08:00
// loop through all samples (well, we don't want to go out-of-bounds)
2019-05-26 01:27:43 +08:00
while ( i < ( size - 512 ) ) {
2019-03-10 02:19:50 +08:00
// measure from low to low
2019-04-13 14:50:05 +08:00
size_t startwave = i ;
2019-03-10 02:19:50 +08:00
2019-06-08 03:26:03 +08:00
getNextHigh ( dest , size , high , & i ) ;
getNextLow ( dest , size , low , & i ) ;
2019-03-10 02:19:50 +08:00
//get minimum measured distance
2019-03-10 07:00:59 +08:00
if ( i - startwave < minClk & & i < size ) {
2019-03-10 02:19:50 +08:00
minClk = i - startwave ;
shortestWaveIdx = startwave ;
}
2019-03-28 21:19:41 +08:00
2019-03-19 21:41:57 +08:00
int foo = getClosestClock ( minClk ) ;
2019-03-28 21:19:41 +08:00
if ( foo > 0 ) {
2019-04-06 06:23:01 +08:00
for ( uint8_t j = 0 ; j < 10 ; j + + ) {
if ( tmpclk [ j ] [ 0 ] = = foo ) {
tmpclk [ j ] [ 1 ] + + ;
2019-03-28 21:19:41 +08:00
2019-04-06 06:23:01 +08:00
if ( tmpclk [ j ] [ 2 ] = = 0 ) {
tmpclk [ j ] [ 2 ] = shortestWaveIdx ;
2019-03-19 21:41:57 +08:00
}
break ;
}
}
}
2019-03-10 02:19:50 +08:00
}
2019-03-19 21:41:57 +08:00
// find the clock with most hits and it the first index it was encountered.
int max = 0 ;
2019-04-06 06:23:01 +08:00
for ( uint8_t j = 0 ; j < 10 ; j + + ) {
2019-03-19 21:41:57 +08:00
if ( g_debugMode = = 2 ) {
prnt ( " DEBUG, ASK, clocks %u | hits %u | idx %u "
2019-04-06 06:23:01 +08:00
, tmpclk [ j ] [ 0 ]
, tmpclk [ j ] [ 1 ]
, tmpclk [ j ] [ 2 ]
2019-03-28 21:19:41 +08:00
) ;
2019-03-19 21:41:57 +08:00
}
2019-04-06 06:23:01 +08:00
if ( max < tmpclk [ j ] [ 1 ] ) {
* clock = tmpclk [ j ] [ 0 ] ;
shortestWaveIdx = tmpclk [ j ] [ 2 ] ;
max = tmpclk [ j ] [ 1 ] ;
2019-03-19 21:41:57 +08:00
}
2019-03-28 21:19:41 +08:00
}
2019-03-10 02:19:50 +08:00
if ( * clock = = 0 )
return - 1 ;
return shortestWaveIdx ;
2017-07-30 15:17:48 +08:00
}
2015-01-07 12:29:45 +08:00
2017-07-30 15:17:48 +08:00
// by marshmellow
// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
// maybe somehow adjust peak trimming value based on samples to fix?
// return start index of best starting position for that clock and return clock (by reference)
2019-03-10 18:20:22 +08:00
int DetectASKClock ( uint8_t * dest , size_t size , int * clock , int maxErr ) {
2015-10-15 16:23:15 +08:00
2019-03-10 02:19:50 +08:00
//don't need to loop through entire array. (cotag has clock of 384)
2019-05-28 17:15:12 +08:00
uint16_t loopCnt = 2000 ;
2019-03-10 02:19:50 +08:00
// not enough samples
2019-03-10 07:00:59 +08:00
if ( size < = loopCnt + 60 ) {
2019-03-10 02:19:50 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG DetectASKClock: not enough samples - aborting " ) ;
return - 1 ;
}
// just noise - no super good detection. good enough
if ( signalprop . isnoise ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG DetectASKClock: just noise detected - aborting " ) ;
return - 2 ;
}
size_t i = 1 ;
uint16_t num_clks = 9 ;
// first 255 value pos0 is placeholder for user inputed clock.
uint16_t clk [ ] = { 255 , 8 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 255 } ;
// sometimes there is a strange end wave - filter out this
size - = 60 ;
// What is purpose?
// already have a valid clock?
uint8_t found_clk = 0 ;
for ( ; i < num_clks ; + + i ) {
if ( clk [ i ] = = * clock ) {
found_clk = i ;
}
}
// threshold 75% of high, low peak
int peak_hi , peak_low ;
getHiLo ( & peak_hi , & peak_low , 75 , 75 ) ;
// test for large clean, STRONG, CLIPPED peaks
if ( ! found_clk ) {
2019-03-10 07:00:59 +08:00
if ( DetectCleanAskWave ( dest , size , peak_hi , peak_low ) ) {
2019-03-10 02:19:50 +08:00
int idx = DetectStrongAskClock ( dest , size , peak_hi , peak_low , clock ) ;
if ( g_debugMode = = 2 )
prnt ( " DEBUG ASK: DetectASKClock Clean ASK Wave detected: clk %i, Best Starting Position: %i " , * clock , idx ) ;
// return shortest wave start position
if ( idx > - 1 )
return idx ;
}
}
// test for weak peaks
// test clock if given as cmd parameter
2019-03-10 07:00:59 +08:00
if ( * clock > 0 )
2019-03-10 02:19:50 +08:00
clk [ 0 ] = * clock ;
2019-04-13 14:50:05 +08:00
uint8_t clkCnt , tol ;
2019-03-10 02:19:50 +08:00
size_t j = 0 ;
2019-03-10 07:00:59 +08:00
uint16_t bestErr [ ] = { 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 } ;
uint8_t bestStart [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-04-13 14:50:05 +08:00
size_t errCnt , arrLoc , loopEnd ;
2019-03-10 02:19:50 +08:00
if ( found_clk ) {
clkCnt = found_clk ;
num_clks = found_clk + 1 ;
} else {
clkCnt = 1 ;
}
//test each valid clock from smallest to greatest to see which lines up
for ( ; clkCnt < num_clks ; clkCnt + + ) {
if ( clk [ clkCnt ] < = 32 ) {
tol = 1 ;
} else {
tol = 0 ;
}
//if no errors allowed - keep start within the first clock
2019-03-10 07:00:59 +08:00
if ( ! maxErr & & size > clk [ clkCnt ] * 2 + tol & & clk [ clkCnt ] < 128 )
2019-03-10 02:19:50 +08:00
loopCnt = clk [ clkCnt ] * 2 ;
bestErr [ clkCnt ] = 1000 ;
//try lining up the peaks by moving starting point (try first few clocks)
// get to first full low to prime loop and skip incomplete first pulse
getNextHigh ( dest , size , peak_hi , & j ) ;
getNextLow ( dest , size , peak_low , & j ) ;
2019-03-10 07:00:59 +08:00
for ( ; j < loopCnt ; j + + ) {
2019-03-10 02:19:50 +08:00
errCnt = 0 ;
// now that we have the first one lined up test rest of wave array
2019-03-10 07:00:59 +08:00
loopEnd = ( ( size - j - tol ) / clk [ clkCnt ] ) - 1 ;
for ( i = 0 ; i < loopEnd ; + + i ) {
2019-03-10 02:19:50 +08:00
arrLoc = j + ( i * clk [ clkCnt ] ) ;
2019-03-10 07:00:59 +08:00
if ( dest [ arrLoc ] > = peak_hi | | dest [ arrLoc ] < = peak_low ) {
} else if ( dest [ arrLoc - tol ] > = peak_hi | | dest [ arrLoc - tol ] < = peak_low ) {
} else if ( dest [ arrLoc + tol ] > = peak_hi | | dest [ arrLoc + tol ] < = peak_low ) {
2019-03-10 02:19:50 +08:00
} else { //error no peak detected
errCnt + + ;
}
}
// if we found no errors then we can stop here and a low clock (common clocks)
// this is correct one - return this clock
// if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i);
if ( errCnt = = 0 & & clkCnt < 7 ) {
if ( ! found_clk )
* clock = clk [ clkCnt ] ;
return j ;
}
// if we found errors see if it is lowest so far and save it as best run
if ( errCnt < bestErr [ clkCnt ] ) {
bestErr [ clkCnt ] = errCnt ;
bestStart [ clkCnt ] = j ;
}
}
}
uint8_t k , best = 0 ;
2019-03-10 07:00:59 +08:00
for ( k = 1 ; k < num_clks ; + + k ) {
if ( bestErr [ k ] < bestErr [ best ] ) {
2019-03-10 02:19:50 +08:00
if ( bestErr [ k ] = = 0 ) bestErr [ k ] = 1 ;
// current best bit to error ratio vs new bit to error ratio
2019-03-10 07:00:59 +08:00
if ( ( size / clk [ best ] ) / bestErr [ best ] < ( size / clk [ k ] ) / bestErr [ k ] ) {
2019-03-10 02:19:50 +08:00
best = k ;
}
}
//if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]);
}
2021-01-28 07:35:14 +08:00
bool chg = false ;
for ( i = 0 ; i < ARRAYLEN ( bestErr ) ; i + + ) {
chg = ( bestErr [ i ] ! = 1000 ) ;
if ( chg )
break ;
chg = ( bestStart [ i ] ! = 0 ) ;
if ( chg )
break ;
}
// just noise - no super good detection. good enough
if ( chg = = false ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG DetectASKClock: no good values detected - aborting " ) ;
return - 2 ;
}
2019-03-10 02:19:50 +08:00
if ( ! found_clk )
* clock = clk [ best ] ;
return bestStart [ best ] ;
2014-12-29 09:33:32 +08:00
}
2019-03-10 18:20:22 +08:00
int DetectStrongNRZClk ( uint8_t * dest , size_t size , int peak , int low , bool * strong ) {
2019-03-10 02:19:50 +08:00
//find shortest transition from high to low
* strong = false ;
size_t i = 0 ;
size_t transition1 = 0 ;
int lowestTransition = 255 ;
bool lastWasHigh = false ;
size_t transitionSampleCount = 0 ;
//find first valid beginning of a high or low wave
while ( ( dest [ i ] > = peak | | dest [ i ] < = low ) & & ( i < size ) )
+ + i ;
while ( ( dest [ i ] < peak & & dest [ i ] > low ) & & ( i < size ) )
+ + i ;
lastWasHigh = ( dest [ i ] > = peak ) ;
if ( i = = size )
return 0 ;
transition1 = i ;
2019-03-10 07:00:59 +08:00
for ( ; i < size ; i + + ) {
2019-03-10 02:19:50 +08:00
if ( ( dest [ i ] > = peak & & ! lastWasHigh ) | | ( dest [ i ] < = low & & lastWasHigh ) ) {
lastWasHigh = ( dest [ i ] > = peak ) ;
2019-03-10 07:00:59 +08:00
if ( i - transition1 < lowestTransition )
lowestTransition = i - transition1 ;
2019-03-10 02:19:50 +08:00
transition1 = i ;
} else if ( dest [ i ] < peak & & dest [ i ] > low ) {
transitionSampleCount + + ;
}
}
if ( lowestTransition = = 255 )
lowestTransition = 0 ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: detectstrongNRZclk smallest wave: %d " , lowestTransition ) ;
// if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave
if ( transitionSampleCount / size < 10 ) {
* strong = true ;
lowestTransition = getClosestClock ( lowestTransition ) ;
}
return lowestTransition ;
2017-07-30 15:17:48 +08:00
}
2015-01-21 06:28:51 +08:00
2017-07-30 15:17:48 +08:00
//by marshmellow
//detect nrz clock by reading #peaks vs no peaks(or errors)
2019-03-10 18:20:22 +08:00
int DetectNRZClock ( uint8_t * dest , size_t size , int clock , size_t * clockStartIdx ) {
2019-03-10 02:19:50 +08:00
size_t i = 0 ;
2019-03-10 07:00:59 +08:00
uint8_t clk [ ] = { 8 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 255 } ;
2019-03-10 02:19:50 +08:00
size_t loopCnt = 4096 ; //don't need to loop through entire array...
//if we already have a valid clock quit
for ( ; i < 8 ; + + i )
if ( clk [ i ] = = clock ) return clock ;
if ( size < 20 ) return 0 ;
// size must be larger than 20 here
2019-03-10 07:00:59 +08:00
if ( size < loopCnt ) loopCnt = size - 20 ;
2019-03-10 02:19:50 +08:00
// just noise - no super good detection. good enough
if ( signalprop . isnoise ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG DetectNZRClock: just noise detected - quitting " ) ;
return 0 ;
}
//get high and low peak
int peak , low ;
//getHiLo(dest, loopCnt, &peak, &low, 90, 90);
getHiLo ( & peak , & low , 90 , 90 ) ;
bool strong = false ;
2019-03-10 07:00:59 +08:00
int lowestTransition = DetectStrongNRZClk ( dest , size - 20 , peak , low , & strong ) ;
2019-03-10 02:19:50 +08:00
if ( strong ) return lowestTransition ;
size_t ii ;
uint8_t clkCnt ;
uint8_t tol = 0 ;
uint16_t smplCnt = 0 ;
int16_t peakcnt = 0 ;
2019-03-10 07:00:59 +08:00
int16_t peaksdet [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-03-10 02:19:50 +08:00
uint16_t minPeak = 255 ;
bool firstpeak = true ;
//test for large clipped waves - ignore first peak
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < loopCnt ; i + + ) {
if ( dest [ i ] > = peak | | dest [ i ] < = low ) {
2019-03-10 02:19:50 +08:00
if ( firstpeak ) continue ;
smplCnt + + ;
} else {
firstpeak = false ;
if ( smplCnt > 0 ) {
if ( minPeak > smplCnt & & smplCnt > 7 ) minPeak = smplCnt ;
peakcnt + + ;
2019-03-10 07:00:59 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: minPeak: %d, smplCnt: %d, peakcnt: %d " , minPeak , smplCnt , peakcnt ) ;
2019-03-10 02:19:50 +08:00
smplCnt = 0 ;
}
}
}
if ( minPeak < 8 ) return 0 ;
bool errBitHigh = 0 , bitHigh = 0 , lastPeakHigh = 0 ;
uint8_t ignoreCnt = 0 , ignoreWindow = 4 ;
int lastBit = 0 ;
2019-03-10 07:00:59 +08:00
size_t bestStart [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-03-10 02:19:50 +08:00
peakcnt = 0 ;
//test each valid clock from smallest to greatest to see which lines up
2019-03-10 07:00:59 +08:00
for ( clkCnt = 0 ; clkCnt < 8 ; + + clkCnt ) {
2019-03-10 02:19:50 +08:00
//ignore clocks smaller than smallest peak
2019-03-10 07:00:59 +08:00
if ( clk [ clkCnt ] < minPeak - ( clk [ clkCnt ] / 4 ) ) continue ;
2019-03-10 02:19:50 +08:00
//try lining up the peaks by moving starting point (try first 256)
2019-03-10 07:00:59 +08:00
for ( ii = 20 ; ii < loopCnt ; + + ii ) {
if ( ( dest [ ii ] > = peak ) | | ( dest [ ii ] < = low ) ) {
peakcnt = 0 ;
2019-03-10 02:19:50 +08:00
bitHigh = false ;
ignoreCnt = 0 ;
2019-03-10 07:00:59 +08:00
lastBit = ii - clk [ clkCnt ] ;
2019-03-10 02:19:50 +08:00
//loop through to see if this start location works
2019-03-10 07:00:59 +08:00
for ( i = ii ; i < size - 20 ; + + i ) {
2019-03-10 02:19:50 +08:00
//if we are at a clock bit
if ( ( i > = lastBit + clk [ clkCnt ] - tol ) & & ( i < = lastBit + clk [ clkCnt ] + tol ) ) {
//test high/low
if ( dest [ i ] > = peak | | dest [ i ] < = low ) {
//if same peak don't count it
if ( ( dest [ i ] > = peak & & ! lastPeakHigh ) | | ( dest [ i ] < = low & & lastPeakHigh ) ) {
peakcnt + + ;
}
lastPeakHigh = ( dest [ i ] > = peak ) ;
bitHigh = true ;
errBitHigh = false ;
ignoreCnt = ignoreWindow ;
lastBit + = clk [ clkCnt ] ;
} else if ( i = = lastBit + clk [ clkCnt ] + tol ) {
lastBit + = clk [ clkCnt ] ;
}
2019-03-10 07:00:59 +08:00
//else if not a clock bit and no peaks
} else if ( dest [ i ] < peak & & dest [ i ] > low ) {
if ( ignoreCnt = = 0 ) {
2019-03-10 02:19:50 +08:00
bitHigh = false ;
if ( errBitHigh = = true )
peakcnt - - ;
errBitHigh = false ;
} else {
ignoreCnt - - ;
}
// else if not a clock bit but we have a peak
} else if ( ( dest [ i ] > = peak | | dest [ i ] < = low ) & & ( ! bitHigh ) ) {
//error bar found no clock...
errBitHigh = true ;
}
}
if ( peakcnt > peaksdet [ clkCnt ] ) {
bestStart [ clkCnt ] = ii ;
peaksdet [ clkCnt ] = peakcnt ;
}
}
}
}
uint8_t best = 0 ;
2019-03-10 07:00:59 +08:00
for ( int m = 7 ; m > 0 ; m - - ) {
if ( ( peaksdet [ m ] > = ( peaksdet [ best ] - 1 ) ) & & ( peaksdet [ m ] < = peaksdet [ best ] + 1 ) & & lowestTransition ) {
if ( clk [ m ] > ( lowestTransition - ( clk [ m ] / 8 ) ) & & clk [ m ] < ( lowestTransition + ( clk [ m ] / 8 ) ) ) {
2019-03-10 02:19:50 +08:00
best = m ;
}
2019-03-10 07:00:59 +08:00
} else if ( peaksdet [ m ] > peaksdet [ best ] ) {
2019-03-10 02:19:50 +08:00
best = m ;
}
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d " , clk [ m ] , peaksdet [ m ] , minPeak , clk [ best ] , lowestTransition ) ;
}
* clockStartIdx = bestStart [ best ] ;
return clk [ best ] ;
2015-01-19 07:13:32 +08:00
}
2017-07-30 15:17:48 +08:00
//by marshmellow
//countFC is to detect the field clock lengths.
//counts and returns the 2 most common wave lengths
//mainly used for FSK field clock detection
2019-03-10 18:20:22 +08:00
uint16_t countFC ( uint8_t * bits , size_t size , bool fskAdj ) {
2019-03-10 07:00:59 +08:00
uint8_t fcLens [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
uint16_t fcCnts [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-03-10 02:19:50 +08:00
uint8_t fcLensFnd = 0 ;
uint8_t lastFCcnt = 0 ;
uint8_t fcCounter = 0 ;
size_t i ;
if ( size < 180 ) return 0 ;
// prime i to first up transition
2019-03-10 07:00:59 +08:00
for ( i = 160 ; i < size - 20 ; i + + )
if ( bits [ i ] > bits [ i - 1 ] & & bits [ i ] > = bits [ i + 1 ] )
2019-03-10 02:19:50 +08:00
break ;
2019-03-10 07:00:59 +08:00
for ( ; i < size - 20 ; i + + ) {
if ( bits [ i ] > bits [ i - 1 ] & & bits [ i ] > = bits [ i + 1 ] ) {
2019-03-10 02:19:50 +08:00
// new up transition
fcCounter + + ;
2019-03-10 07:00:59 +08:00
if ( fskAdj ) {
2019-03-10 02:19:50 +08:00
//if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8)
if ( lastFCcnt = = 5 & & fcCounter = = 9 ) fcCounter - - ;
//if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5)
if ( ( fcCounter = = 9 ) | | fcCounter = = 4 ) fcCounter + + ;
// save last field clock count (fc/xx)
lastFCcnt = fcCounter ;
}
// find which fcLens to save it to:
2019-03-10 07:00:59 +08:00
for ( int m = 0 ; m < 15 ; m + + ) {
if ( fcLens [ m ] = = fcCounter ) {
2019-03-10 02:19:50 +08:00
fcCnts [ m ] + + ;
fcCounter = 0 ;
break ;
}
}
2019-03-10 07:00:59 +08:00
if ( fcCounter > 0 & & fcLensFnd < 15 ) {
2019-03-10 02:19:50 +08:00
//add new fc length
fcCnts [ fcLensFnd ] + + ;
fcLens [ fcLensFnd + + ] = fcCounter ;
}
2019-03-10 07:00:59 +08:00
fcCounter = 0 ;
2019-03-10 02:19:50 +08:00
} else {
// count sample
fcCounter + + ;
}
}
uint8_t best1 = 14 , best2 = 14 , best3 = 14 ;
uint16_t maxCnt1 = 0 ;
// go through fclens and find which ones are bigest 2
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < 15 ; i + + ) {
2019-03-10 02:19:50 +08:00
// get the 3 best FC values
if ( fcCnts [ i ] > maxCnt1 ) {
best3 = best2 ;
best2 = best1 ;
maxCnt1 = fcCnts [ i ] ;
best1 = i ;
2019-03-10 07:00:59 +08:00
} else if ( fcCnts [ i ] > fcCnts [ best2 ] ) {
2019-03-10 02:19:50 +08:00
best3 = best2 ;
best2 = i ;
2019-03-10 07:00:59 +08:00
} else if ( fcCnts [ i ] > fcCnts [ best3 ] ) {
2019-03-10 02:19:50 +08:00
best3 = i ;
}
if ( g_debugMode = = 2 ) prnt ( " DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u " , fcLens [ i ] , fcCnts [ i ] , fcLens [ best1 ] , fcLens [ best2 ] ) ;
if ( fcLens [ i ] = = 0 ) break ;
}
if ( fcLens [ best1 ] = = 0 ) return 0 ;
uint8_t fcH = 0 , fcL = 0 ;
2019-03-10 07:00:59 +08:00
if ( fcLens [ best1 ] > fcLens [ best2 ] ) {
2019-03-10 02:19:50 +08:00
fcH = fcLens [ best1 ] ;
fcL = fcLens [ best2 ] ;
2019-03-10 07:00:59 +08:00
} else {
2019-03-10 02:19:50 +08:00
fcH = fcLens [ best2 ] ;
fcL = fcLens [ best1 ] ;
}
2019-03-10 07:00:59 +08:00
if ( ( size - 180 ) / fcH / 3 > fcCnts [ best1 ] + fcCnts [ best2 ] ) {
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG countfc: fc is too large: %zu > %u. Not psk or fsk " , ( size - 180 ) / fcH / 3 , fcCnts [ best1 ] + fcCnts [ best2 ] ) ;
2019-03-10 02:19:50 +08:00
return 0 ; //lots of waves not psk or fsk
}
// TODO: take top 3 answers and compare to known Field clocks to get top 2
2019-03-10 07:00:59 +08:00
uint16_t fcs = ( ( ( uint16_t ) fcH ) < < 8 ) | fcL ;
2019-03-10 02:19:50 +08:00
if ( fskAdj ) return fcs ;
return ( uint16_t ) fcLens [ best2 ] < < 8 | fcLens [ best1 ] ;
2016-02-14 18:58:25 +08:00
}
2017-07-30 15:17:48 +08:00
//by marshmellow
//detect psk clock by reading each phase shift
// a phase shift is determined by measuring the sample length of each wave
2019-03-10 18:20:22 +08:00
int DetectPSKClock ( uint8_t * dest , size_t size , int clock , size_t * firstPhaseShift , uint8_t * curPhase , uint8_t * fc ) {
2019-03-10 07:00:59 +08:00
uint8_t clk [ ] = { 255 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 255 } ; //255 is not a valid clock
2019-03-10 02:19:50 +08:00
uint16_t loopCnt = 4096 ; //don't need to loop through entire array...
2019-03-10 07:00:59 +08:00
if ( size < 160 + 20 ) return 0 ;
2019-03-10 02:19:50 +08:00
// size must be larger than 20 here, and 160 later on.
2019-03-10 07:00:59 +08:00
if ( size < loopCnt ) loopCnt = size - 20 ;
2019-03-10 02:19:50 +08:00
uint16_t fcs = countFC ( dest , size , 0 ) ;
* fc = fcs & 0xFF ;
2019-03-10 07:00:59 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: FC: %d, FC2: %d " , * fc , fcs > > 8 ) ;
2019-03-10 02:19:50 +08:00
if ( ( fcs > > 8 ) = = 10 & & * fc = = 8 ) return 0 ;
if ( * fc ! = 2 & & * fc ! = 4 & & * fc ! = 8 ) return 0 ;
2019-04-13 14:50:05 +08:00
size_t waveEnd , firstFullWave = 0 ;
2019-03-10 02:19:50 +08:00
2019-04-13 14:50:05 +08:00
uint8_t clkCnt ;
uint16_t waveLenCnt , fullWaveLen = 0 ;
2019-03-10 07:00:59 +08:00
uint16_t bestErr [ ] = { 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 } ;
uint16_t peaksdet [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-03-10 02:19:50 +08:00
//find start of modulating data in trace
2019-03-25 21:03:36 +08:00
size_t i = findModStart ( dest , size , * fc ) ;
2019-03-10 02:19:50 +08:00
firstFullWave = pskFindFirstPhaseShift ( dest , size , curPhase , i , * fc , & fullWaveLen ) ;
if ( firstFullWave = = 0 ) {
// no phase shift detected - could be all 1's or 0's - doesn't matter where we start
// so skip a little to ensure we are past any Start Signal
firstFullWave = 160 ;
fullWaveLen = 0 ;
}
* firstPhaseShift = firstFullWave ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: firstFullWave: %zu, waveLen: %d " , firstFullWave , fullWaveLen ) ;
2019-03-10 02:19:50 +08:00
2020-12-11 08:17:51 +08:00
// Avoid autodetect if user selected a clock
2020-12-12 21:46:40 +08:00
for ( uint8_t validClk = 1 ; validClk < 8 ; validClk + + ) {
if ( clock = = clk [ validClk ] ) return ( clock ) ;
2020-12-11 08:17:51 +08:00
}
2019-03-10 02:19:50 +08:00
//test each valid clock from greatest to smallest to see which lines up
2019-03-10 07:00:59 +08:00
for ( clkCnt = 7 ; clkCnt > = 1 ; clkCnt - - ) {
2019-04-13 14:50:05 +08:00
uint8_t tol = * fc / 2 ;
size_t lastClkBit = firstFullWave ; //set end of wave as clock align
size_t waveStart = 0 ;
uint16_t errCnt = 0 ;
uint16_t peakcnt = 0 ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: clk: %d, lastClkBit: %zu " , clk [ clkCnt ] , lastClkBit ) ;
2019-03-10 02:19:50 +08:00
2019-03-10 07:00:59 +08:00
for ( i = firstFullWave + fullWaveLen - 1 ; i < loopCnt - 2 ; i + + ) {
2019-03-10 02:19:50 +08:00
//top edge of wave = start of new wave
2019-03-10 07:00:59 +08:00
if ( dest [ i ] < dest [ i + 1 ] & & dest [ i + 1 ] > = dest [ i + 2 ] ) {
2019-03-10 02:19:50 +08:00
if ( waveStart = = 0 ) {
2019-03-10 07:00:59 +08:00
waveStart = i + 1 ;
2019-03-10 02:19:50 +08:00
} else { //waveEnd
2019-03-10 07:00:59 +08:00
waveEnd = i + 1 ;
waveLenCnt = waveEnd - waveStart ;
if ( waveLenCnt > * fc ) {
2019-03-10 02:19:50 +08:00
//if this wave is a phase shift
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: phase shift at: %zu, len: %d, nextClk: %zu, i: %zu, fc: %d " , waveStart , waveLenCnt , lastClkBit + clk [ clkCnt ] - tol , i + 1 , * fc ) ;
2019-03-10 07:00:59 +08:00
if ( i + 1 > = lastClkBit + clk [ clkCnt ] - tol ) { //should be a clock bit
2019-03-10 02:19:50 +08:00
peakcnt + + ;
lastClkBit + = clk [ clkCnt ] ;
2019-03-10 07:00:59 +08:00
} else if ( i < lastClkBit + 8 ) {
2019-03-10 02:19:50 +08:00
//noise after a phase shift - ignore
} else { //phase shift before supposed to based on clock
errCnt + + ;
}
2019-03-10 07:00:59 +08:00
} else if ( i + 1 > lastClkBit + clk [ clkCnt ] + tol + * fc ) {
lastClkBit + = clk [ clkCnt ] ; //no phase shift but clock bit
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
waveStart = i + 1 ;
2019-03-10 02:19:50 +08:00
}
}
}
if ( errCnt = = 0 ) return clk [ clkCnt ] ;
if ( errCnt < = bestErr [ clkCnt ] ) bestErr [ clkCnt ] = errCnt ;
if ( peakcnt > peaksdet [ clkCnt ] ) peaksdet [ clkCnt ] = peakcnt ;
}
//all tested with errors
//return the highest clk with the most peaks found
uint8_t best = 7 ;
2019-03-10 07:00:59 +08:00
for ( i = 7 ; i > = 1 ; i - - ) {
2019-03-10 02:19:50 +08:00
if ( peaksdet [ i ] > peaksdet [ best ] )
best = i ;
2019-03-10 07:00:59 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d " , clk [ i ] , peaksdet [ i ] , bestErr [ i ] , clk [ best ] ) ;
2019-03-10 02:19:50 +08:00
}
return clk [ best ] ;
2015-06-04 03:12:24 +08:00
}
2015-01-19 07:13:32 +08:00
2017-07-30 15:17:48 +08:00
//by marshmellow
//detects the bit clock for FSK given the high and low Field Clocks
2019-03-10 18:20:22 +08:00
uint8_t detectFSKClk ( uint8_t * bits , size_t size , uint8_t fcHigh , uint8_t fcLow , int * firstClockEdge ) {
2017-11-06 22:06:42 +08:00
2019-03-10 02:19:50 +08:00
if ( size = = 0 )
return 0 ;
2019-03-10 07:00:59 +08:00
uint8_t clk [ ] = { 8 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 0 } ;
uint16_t rfLens [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t rfCnts [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-03-10 02:19:50 +08:00
uint8_t rfLensFnd = 0 ;
uint8_t lastFCcnt = 0 ;
uint16_t fcCounter = 0 ;
uint16_t rfCounter = 0 ;
uint8_t firstBitFnd = 0 ;
size_t i ;
2019-03-10 07:00:59 +08:00
uint8_t fcTol = ( ( fcHigh * 100 - fcLow * 100 ) / 2 + 50 ) / 100 ; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2);
2019-03-10 02:19:50 +08:00
// prime i to first peak / up transition
2019-03-10 07:00:59 +08:00
for ( i = 160 ; i < size - 20 ; i + + )
if ( bits [ i ] > bits [ i - 1 ] & & bits [ i ] > = bits [ i + 1 ] )
2019-03-10 02:19:50 +08:00
break ;
2019-03-10 07:00:59 +08:00
for ( ; i < size - 20 ; i + + ) {
2019-03-10 02:19:50 +08:00
fcCounter + + ;
rfCounter + + ;
2019-03-10 07:00:59 +08:00
if ( bits [ i ] < = bits [ i - 1 ] | | bits [ i ] < bits [ i + 1 ] )
2019-03-10 02:19:50 +08:00
continue ;
// else new peak
// if we got less than the small fc + tolerance then set it to the small fc
// if it is inbetween set it to the last counter
if ( fcCounter < fcHigh & & fcCounter > fcLow )
fcCounter = lastFCcnt ;
2019-03-10 07:00:59 +08:00
else if ( fcCounter < fcLow + fcTol )
2019-03-10 02:19:50 +08:00
fcCounter = fcLow ;
else //set it to the large fc
fcCounter = fcHigh ;
//look for bit clock (rf/xx)
2019-03-10 07:00:59 +08:00
if ( ( fcCounter < lastFCcnt | | fcCounter > lastFCcnt ) ) {
2019-03-10 02:19:50 +08:00
//not the same size as the last wave - start of new bit sequence
2019-03-10 07:00:59 +08:00
if ( firstBitFnd > 1 ) { //skip first wave change - probably not a complete bit
for ( int ii = 0 ; ii < 15 ; ii + + ) {
if ( rfLens [ ii ] > = ( rfCounter - 4 ) & & rfLens [ ii ] < = ( rfCounter + 4 ) ) {
2019-03-10 02:19:50 +08:00
rfCnts [ ii ] + + ;
rfCounter = 0 ;
break ;
}
}
2019-03-10 07:00:59 +08:00
if ( rfCounter > 0 & & rfLensFnd < 15 ) {
2019-03-10 02:19:50 +08:00
//prnt("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
rfCnts [ rfLensFnd ] + + ;
rfLens [ rfLensFnd + + ] = rfCounter ;
}
} else {
* firstClockEdge = i ;
firstBitFnd + + ;
}
rfCounter = 0 ;
lastFCcnt = fcCounter ;
}
fcCounter = 0 ;
}
uint8_t rfHighest = 15 , rfHighest2 = 15 , rfHighest3 = 15 ;
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < 15 ; i + + ) {
2019-03-10 02:19:50 +08:00
//get highest 2 RF values (might need to get more values to compare or compare all?)
2019-03-10 07:00:59 +08:00
if ( rfCnts [ i ] > rfCnts [ rfHighest ] ) {
2019-03-10 02:19:50 +08:00
rfHighest3 = rfHighest2 ;
rfHighest2 = rfHighest ;
rfHighest = i ;
2019-03-10 07:00:59 +08:00
} else if ( rfCnts [ i ] > rfCnts [ rfHighest2 ] ) {
2019-03-10 02:19:50 +08:00
rfHighest3 = rfHighest2 ;
rfHighest2 = i ;
2019-03-10 07:00:59 +08:00
} else if ( rfCnts [ i ] > rfCnts [ rfHighest3 ] ) {
2019-03-10 02:19:50 +08:00
rfHighest3 = i ;
}
if ( g_debugMode = = 2 )
prnt ( " DEBUG FSK: RF %d, cnts %d " , rfLens [ i ] , rfCnts [ i ] ) ;
}
// set allowed clock remainder tolerance to be 1 large field clock length+1
// we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off
2019-03-10 07:00:59 +08:00
uint8_t tol1 = fcHigh + 1 ;
2019-03-10 02:19:50 +08:00
if ( g_debugMode = = 2 )
prnt ( " DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d " , rfLens [ rfHighest ] , rfLens [ rfHighest2 ] , rfLens [ rfHighest3 ] ) ;
// loop to find the highest clock that has a remainder less than the tolerance
// compare samples counted divided by
// test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less)
int m = 7 ;
2019-03-10 07:00:59 +08:00
for ( ; m > = 2 ; m - - ) {
if ( rfLens [ rfHighest ] % clk [ m ] < tol1 | | rfLens [ rfHighest ] % clk [ m ] > clk [ m ] - tol1 ) {
if ( rfLens [ rfHighest2 ] % clk [ m ] < tol1 | | rfLens [ rfHighest2 ] % clk [ m ] > clk [ m ] - tol1 ) {
if ( rfLens [ rfHighest3 ] % clk [ m ] < tol1 | | rfLens [ rfHighest3 ] % clk [ m ] > clk [ m ] - tol1 ) {
2019-03-10 02:19:50 +08:00
if ( g_debugMode = = 2 )
prnt ( " DEBUG FSK: clk %d divides into the 3 most rf values within tolerance " , clk [ m ] ) ;
break ;
}
}
}
}
if ( m < 2 ) return 0 ; // oops we went too far
return clk [ m ] ;
2017-07-30 15:17:48 +08:00
}
2015-01-19 07:13:32 +08:00
2015-01-28 03:51:12 +08:00
2019-09-23 01:00:11 +08:00
// **********************************************************************************************
// --------------------Modulation Demods &/or Decoding Section-----------------------------------
// **********************************************************************************************
2015-01-19 07:13:32 +08:00
2015-01-28 03:51:12 +08:00
2017-07-30 15:17:48 +08:00
// look for Sequence Terminator - should be pulses of clk*(1 or 2), clk*2, clk*(1.5 or 2), by idx we mean graph position index...
2019-04-13 06:25:43 +08:00
static bool findST ( int * stStopLoc , int * stStartIdx , int lowToLowWaveLen [ ] , int highToLowWaveLen [ ] , int clk , int tol , int buffSize , size_t * i ) {
2019-03-10 07:00:59 +08:00
if ( buffSize < * i + 4 ) return false ;
2019-03-10 02:19:50 +08:00
2019-03-10 07:00:59 +08:00
for ( ; * i < buffSize - 4 ; * i + = 1 ) {
2019-03-10 02:19:50 +08:00
* stStartIdx + = lowToLowWaveLen [ * i ] ; //caution part of this wave may be data and part may be ST.... to be accounted for in main function for now...
2019-03-10 07:00:59 +08:00
if ( lowToLowWaveLen [ * i ] > = clk * 1 - tol & & lowToLowWaveLen [ * i ] < = ( clk * 2 ) + tol & & highToLowWaveLen [ * i ] < clk + tol ) { //1 to 2 clocks depending on 2 bits prior
if ( lowToLowWaveLen [ * i + 1 ] > = clk * 2 - tol & & lowToLowWaveLen [ * i + 1 ] < = clk * 2 + tol & & highToLowWaveLen [ * i + 1 ] > clk * 3 / 2 - tol ) { //2 clocks and wave size is 1 1/2
if ( lowToLowWaveLen [ * i + 2 ] > = ( clk * 3 ) / 2 - tol & & lowToLowWaveLen [ * i + 2 ] < = clk * 2 + tol & & highToLowWaveLen [ * i + 2 ] > clk - tol ) { //1 1/2 to 2 clocks and at least one full clock wave
if ( lowToLowWaveLen [ * i + 3 ] > = clk * 1 - tol & & lowToLowWaveLen [ * i + 3 ] < = clk * 2 + tol ) { //1 to 2 clocks for end of ST + first bit
2019-03-10 02:19:50 +08:00
* stStopLoc = * i + 3 ;
return true ;
}
}
}
}
}
return false ;
2015-01-19 07:13:32 +08:00
}
2017-07-30 15:17:48 +08:00
//by marshmellow
//attempt to identify a Sequence Terminator in ASK modulated raw wave
2019-03-10 18:20:22 +08:00
bool DetectST ( uint8_t * buffer , size_t * size , int * foundclock , size_t * ststart , size_t * stend ) {
2019-03-10 02:19:50 +08:00
size_t bufsize = * size ;
//need to loop through all samples and identify our clock, look for the ST pattern
int clk = 0 ;
int tol = 0 ;
2019-03-10 07:00:59 +08:00
int j = 0 , high , low , skip = 0 , start = 0 , end = 0 , minClk = 255 ;
2019-03-10 02:19:50 +08:00
size_t i = 0 ;
//probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow]
int tmpbuff [ bufsize / LOWEST_DEFAULT_CLOCK ] ; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured
int waveLen [ bufsize / LOWEST_DEFAULT_CLOCK ] ; // high to low wave count //if clock is larger then we waste memory in array size that is not needed...
//size_t testsize = (bufsize < 512) ? bufsize : 512;
int phaseoff = 0 ;
high = low = 128 ;
memset ( tmpbuff , 0 , sizeof ( tmpbuff ) ) ;
memset ( waveLen , 0 , sizeof ( waveLen ) ) ;
if ( ! loadWaveCounters ( buffer , bufsize , tmpbuff , waveLen , & j , & skip , & minClk , & high , & low ) ) return false ;
// set clock - might be able to get this externally and remove this work...
clk = getClosestClock ( minClk ) ;
2019-03-10 07:00:59 +08:00
// clock not found - ERROR
if ( ! clk ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: clock not found - quitting " ) ;
return false ;
}
2019-03-10 02:19:50 +08:00
* foundclock = clk ;
2019-03-10 07:00:59 +08:00
tol = clk / 8 ;
2019-03-10 02:19:50 +08:00
if ( ! findST ( & start , & skip , tmpbuff , waveLen , clk , tol , j , & i ) ) {
2019-03-10 07:00:59 +08:00
// first ST not found - ERROR
2019-03-10 02:19:50 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: first STT not found - quitting " ) ;
return false ;
} else {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: first STT found at wave: %i, skip: %i, j=%i " , start , skip , j ) ;
}
2019-03-10 07:00:59 +08:00
if ( waveLen [ i + 2 ] > clk * 1 + tol )
2019-03-10 02:19:50 +08:00
phaseoff = 0 ;
else
2019-03-10 07:00:59 +08:00
phaseoff = clk / 2 ;
2019-03-10 02:19:50 +08:00
// skip over the remainder of ST
2019-03-10 07:00:59 +08:00
skip + = clk * 7 / 2 ; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point
2019-03-10 02:19:50 +08:00
// now do it again to find the end
int dummy1 = 0 ;
end = skip ;
i + = 3 ;
if ( ! findST ( & dummy1 , & end , tmpbuff , waveLen , clk , tol , j , & i ) ) {
2019-03-10 07:00:59 +08:00
//didn't find second ST - ERROR
2019-03-10 02:19:50 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: second STT not found - quitting " ) ;
return false ;
}
end - = phaseoff ;
2019-03-10 07:00:59 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d " , skip , end , end - skip , clk , ( end - skip ) / clk , phaseoff ) ;
2019-03-10 02:19:50 +08:00
//now begin to trim out ST so we can use normal demod cmds
start = skip ;
size_t datalen = end - start ;
// check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock
2019-03-10 07:00:59 +08:00
if ( clk - ( datalen % clk ) < = clk / 8 ) {
2019-03-10 02:19:50 +08:00
// padd the amount off - could be problematic... but shouldn't happen often
datalen + = clk - ( datalen % clk ) ;
2019-03-10 07:00:59 +08:00
} else if ( ( datalen % clk ) < = clk / 8 ) {
2019-03-10 02:19:50 +08:00
// padd the amount off - could be problematic... but shouldn't happen often
datalen - = datalen % clk ;
} else {
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: datalen not divisible by clk: %zu %% %d = %zu - quitting " , datalen , clk , datalen % clk ) ;
2019-03-10 02:19:50 +08:00
return false ;
}
// if datalen is less than one t55xx block - ERROR
2019-03-10 07:00:59 +08:00
if ( datalen / clk < 8 * 4 ) {
2019-03-10 02:19:50 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: datalen is less than 1 full t55xx block - quitting " ) ;
return false ;
}
size_t dataloc = start ;
2019-03-10 07:00:59 +08:00
if ( buffer [ dataloc - ( clk * 4 ) - ( clk / 4 ) ] < = low & & buffer [ dataloc ] < = low & & buffer [ dataloc - ( clk * 4 ) ] > = high ) {
2019-03-10 02:19:50 +08:00
//we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < = ( clk / 4 ) ; + + i ) {
if ( buffer [ dataloc - ( clk * 4 ) - i ] < = low ) {
2019-03-10 02:19:50 +08:00
dataloc - = i ;
break ;
}
}
}
size_t newloc = 0 ;
2019-03-10 07:00:59 +08:00
i = 0 ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: Starting STT trim - start: %zu, datalen: %zu " , dataloc , datalen ) ;
2019-03-10 02:19:50 +08:00
bool firstrun = true ;
// warning - overwriting buffer given with raw wave data with ST removed...
2019-03-10 07:00:59 +08:00
while ( dataloc < bufsize - ( clk / 2 ) ) {
2019-03-10 02:19:50 +08:00
//compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
2019-03-10 07:00:59 +08:00
if ( buffer [ dataloc ] < high & & buffer [ dataloc ] > low & & buffer [ dataloc + clk / 4 ] < high & & buffer [ dataloc + clk / 4 ] > low ) {
for ( i = 0 ; i < clk / 2 - tol ; + + i ) {
buffer [ dataloc + i ] = high + 5 ;
2019-03-10 02:19:50 +08:00
}
} //test for small spike outlier (high between two lows) in the case of very strong waves
2019-03-10 07:00:59 +08:00
if ( buffer [ dataloc ] > low & & buffer [ dataloc + clk / 4 ] < = low ) {
for ( i = 0 ; i < clk / 4 ; + + i ) {
buffer [ dataloc + i ] = buffer [ dataloc + clk / 4 ] ;
2019-03-10 02:19:50 +08:00
}
}
if ( firstrun ) {
* stend = dataloc ;
2019-03-10 07:00:59 +08:00
* ststart = dataloc - ( clk * 4 ) ;
firstrun = false ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
for ( i = 0 ; i < datalen ; + + i ) {
if ( i + newloc < bufsize ) {
if ( i + newloc < dataloc )
buffer [ i + newloc ] = buffer [ dataloc ] ;
2019-03-10 02:19:50 +08:00
dataloc + + ;
}
}
newloc + = i ;
//skip next ST - we just assume it will be there from now on...
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: skipping STT at %zu to %zu " , dataloc , dataloc + ( clk * 4 ) ) ;
2019-03-10 07:00:59 +08:00
dataloc + = clk * 4 ;
2019-03-10 02:19:50 +08:00
}
* size = newloc ;
return true ;
2017-01-12 07:04:36 +08:00
}
2017-07-30 15:17:48 +08:00
//by marshmellow
2019-03-09 15:59:13 +08:00
//take 11 10 01 11 00 and make 01100 ... miller decoding
2017-07-30 15:17:48 +08:00
//check for phase errors - should never have half a 1 or 0 by itself and should never exceed 1111 or 0000 in a row
//decodes miller encoded binary
//NOTE askrawdemod will NOT demod miller encoded ask unless the clock is manually set to 1/2 what it is detected as!
2019-04-13 06:25:43 +08:00
/*
static int millerRawDecode ( uint8_t * bits , size_t * size , int invert ) {
2019-03-10 02:19:50 +08:00
if ( * size < 16 ) return - 1 ;
uint16_t MaxBits = 512 , errCnt = 0 ;
size_t i , bitCnt = 0 ;
uint8_t alignCnt = 0 , curBit = bits [ 0 ] , alignedIdx = 0 , halfClkErr = 0 ;
//find alignment, needs 4 1s or 0s to properly align
2019-03-10 07:00:59 +08:00
for ( i = 1 ; i < * size - 1 ; i + + ) {
alignCnt = ( bits [ i ] = = curBit ) ? alignCnt + 1 : 0 ;
2019-03-10 02:19:50 +08:00
curBit = bits [ i ] ;
if ( alignCnt = = 4 ) break ;
}
// for now error if alignment not found. later add option to run it with multiple offsets...
if ( alignCnt ! = 4 ) {
if ( g_debugMode ) prnt ( " ERROR MillerDecode: alignment not found so either your bits is not miller or your data does not have a 101 in it " ) ;
return - 1 ;
}
2019-03-10 07:00:59 +08:00
alignedIdx = ( i - 1 ) % 2 ;
for ( i = alignedIdx ; i < * size - 3 ; i + = 2 ) {
2019-03-10 02:19:50 +08:00
halfClkErr = ( uint8_t ) ( ( halfClkErr < < 1 | bits [ i ] ) & 0xFF ) ;
2019-03-10 07:00:59 +08:00
if ( ( halfClkErr & 0x7 ) = = 5 | | ( halfClkErr & 0x7 ) = = 2 | | ( i > 2 & & ( halfClkErr & 0x7 ) = = 0 ) | | ( halfClkErr & 0x1F ) = = 0x1F ) {
2019-03-10 02:19:50 +08:00
errCnt + + ;
bits [ bitCnt + + ] = 7 ;
continue ;
}
2019-03-10 07:00:59 +08:00
bits [ bitCnt + + ] = bits [ i ] ^ bits [ i + 1 ] ^ invert ;
2019-03-10 02:19:50 +08:00
if ( bitCnt > MaxBits ) break ;
}
* size = bitCnt ;
return errCnt ;
2017-07-30 15:17:48 +08:00
}
2019-04-13 06:25:43 +08:00
*/
2017-07-28 04:05:54 +08:00
2017-07-30 15:17:48 +08:00
//by marshmellow
//take 01 or 10 = 1 and 11 or 00 = 0
//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
2019-03-10 18:20:22 +08:00
int BiphaseRawDecode ( uint8_t * bits , size_t * size , int * offset , int invert ) {
2019-03-10 02:19:50 +08:00
//sanity check
if ( * size < 51 ) return - 1 ;
2019-07-13 06:38:30 +08:00
if ( * offset < 0 ) * offset = 0 ;
2019-03-10 02:19:50 +08:00
uint16_t bitnum = 0 ;
uint16_t errCnt = 0 ;
size_t i = * offset ;
uint16_t maxbits = 512 ;
//check for phase change faults - skip one sample if faulty
bool offsetA = true , offsetB = true ;
2019-03-10 07:00:59 +08:00
for ( ; i < * offset + 48 ; i + = 2 ) {
if ( bits [ i + 1 ] = = bits [ i + 2 ] ) offsetA = false ;
if ( bits [ i + 2 ] = = bits [ i + 3 ] ) offsetB = false ;
2019-03-10 02:19:50 +08:00
}
if ( ! offsetA & & offsetB ) + + * offset ;
2019-06-08 22:16:15 +08:00
// main loop
for ( i = * offset ; i < * size - 1 ; i + = 2 ) {
2019-03-10 02:19:50 +08:00
//check for phase error
2019-03-10 07:00:59 +08:00
if ( bits [ i + 1 ] = = bits [ i + 2 ] ) {
2019-03-10 02:19:50 +08:00
bits [ bitnum + + ] = 7 ;
errCnt + + ;
}
2019-03-10 07:00:59 +08:00
if ( ( bits [ i ] = = 1 & & bits [ i + 1 ] = = 0 ) | | ( bits [ i ] = = 0 & & bits [ i + 1 ] = = 1 ) ) {
2019-03-10 02:19:50 +08:00
bits [ bitnum + + ] = 1 ^ invert ;
2019-03-10 07:00:59 +08:00
} else if ( ( bits [ i ] = = 0 & & bits [ i + 1 ] = = 0 ) | | ( bits [ i ] = = 1 & & bits [ i + 1 ] = = 1 ) ) {
2019-03-10 02:19:50 +08:00
bits [ bitnum + + ] = invert ;
} else {
bits [ bitnum + + ] = 7 ;
errCnt + + ;
}
if ( bitnum > maxbits ) break ;
}
* size = bitnum ;
return errCnt ;
2015-03-23 03:28:48 +08:00
}
2017-07-30 15:17:48 +08:00
//by marshmellow
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
2019-03-21 05:10:34 +08:00
// "," indicates 00 or 11 wrong bit
2019-05-26 01:27:43 +08:00
uint16_t manrawdecode ( uint8_t * bits , size_t * size , uint8_t invert , uint8_t * alignPos ) {
2015-03-26 02:24:36 +08:00
2019-03-10 02:19:50 +08:00
// sanity check
2019-05-26 01:27:43 +08:00
if ( * size < 16 ) return 0xFFFF ;
2019-03-10 02:19:50 +08:00
int errCnt = 0 , bestErr = 1000 ;
uint16_t bitnum = 0 , maxBits = 512 , bestRun = 0 ;
2019-10-09 04:04:15 +08:00
size_t i ;
2019-03-10 02:19:50 +08:00
//find correct start position [alignment]
2019-10-09 04:04:15 +08:00
for ( uint8_t k = 0 ; k < 2 ; k + + ) {
2019-05-26 01:27:43 +08:00
2019-03-14 20:19:16 +08:00
for ( i = k ; i < * size - 1 ; i + = 2 ) {
2019-04-10 15:36:23 +08:00
2019-03-10 07:00:59 +08:00
if ( bits [ i ] = = bits [ i + 1 ] )
2019-03-10 02:19:50 +08:00
errCnt + + ;
2019-04-10 15:36:23 +08:00
if ( errCnt > 50 )
2019-04-09 22:23:55 +08:00
break ;
2019-03-10 02:19:50 +08:00
}
2019-04-10 15:36:23 +08:00
2019-03-10 07:00:59 +08:00
if ( bestErr > errCnt ) {
2019-03-10 02:19:50 +08:00
bestErr = errCnt ;
bestRun = k ;
2019-04-09 22:23:55 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG manrawdecode: bestErr %d | bestRun %u " , bestErr , bestRun ) ;
2019-03-10 02:19:50 +08:00
}
errCnt = 0 ;
}
2019-04-10 15:36:23 +08:00
2019-03-10 02:19:50 +08:00
* alignPos = bestRun ;
//decode
2019-05-26 01:27:43 +08:00
for ( i = bestRun ; i < * size ; i + = 2 ) {
2019-03-10 07:00:59 +08:00
if ( bits [ i ] = = 1 & & ( bits [ i + 1 ] = = 0 ) ) {
2019-03-10 02:19:50 +08:00
bits [ bitnum + + ] = invert ;
2019-03-10 07:00:59 +08:00
} else if ( ( bits [ i ] = = 0 ) & & bits [ i + 1 ] = = 1 ) {
bits [ bitnum + + ] = invert ^ 1 ;
2019-03-10 02:19:50 +08:00
} else {
bits [ bitnum + + ] = 7 ;
}
if ( bitnum > maxBits ) break ;
}
* size = bitnum ;
return bestErr ;
2017-07-30 15:17:48 +08:00
}
2017-01-19 05:56:55 +08:00
2017-07-30 15:17:48 +08:00
//by marshmellow
//demodulates strong heavily clipped samples
//RETURN: num of errors. if 0, is ok.
2019-05-26 01:27:43 +08:00
static uint16_t cleanAskRawDemod ( uint8_t * bits , size_t * size , int clk , int invert , int high , int low , int * startIdx ) {
2019-03-10 02:19:50 +08:00
* startIdx = 0 ;
size_t bitCnt = 0 , smplCnt = 1 , errCnt = 0 , pos = 0 ;
uint8_t cl_4 = clk / 4 ;
uint8_t cl_2 = clk / 2 ;
bool waveHigh = true ;
getNextHigh ( bits , * size , high , & pos ) ;
2019-05-28 17:15:12 +08:00
// getNextLow(bits, *size, low, &pos);
2019-03-10 02:19:50 +08:00
2020-06-14 20:51:48 +08:00
// do not skip first transition
if ( ( pos > cl_2 - cl_4 - 1 ) & & ( pos < = clk + cl_4 + 1 ) ) {
bits [ bitCnt + + ] = invert ^ 1 ;
}
2020-06-20 00:34:47 +08:00
2019-03-10 02:19:50 +08:00
// sample counts, like clock = 32.. it tries to find 32/4 = 8, 32/2 = 16
2019-03-10 07:00:59 +08:00
for ( size_t i = pos ; i < * size ; i + + ) {
if ( bits [ i ] > = high & & waveHigh ) {
2019-03-10 02:19:50 +08:00
smplCnt + + ;
2019-03-10 07:00:59 +08:00
} else if ( bits [ i ] < = low & & ! waveHigh ) {
2019-03-10 02:19:50 +08:00
smplCnt + + ;
2019-05-26 01:27:43 +08:00
} else {
2019-06-08 03:40:33 +08:00
//transition
2019-03-10 07:00:59 +08:00
if ( ( bits [ i ] > = high & & ! waveHigh ) | | ( bits [ i ] < = low & & waveHigh ) ) {
2019-03-10 02:19:50 +08:00
2019-05-22 18:01:27 +08:00
// 8 :: 8-2-1 = 5 8+2+1 = 11
// 16 :: 16-4-1 = 11 16+4+1 = 21
// 32 :: 32-8-1 = 23 32+8+1 = 41
// 64 :: 64-16-1 = 47 64+16+1 = 81
2019-03-10 02:19:50 +08:00
if ( smplCnt > clk - cl_4 - 1 ) { //full clock
2019-06-08 03:40:33 +08:00
if ( smplCnt > clk + cl_4 + 1 ) {
2019-05-26 01:27:43 +08:00
//too many samples
2019-03-10 02:19:50 +08:00
errCnt + + ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: cleanAskRawDemod ASK Modulation Error FULL at: %zu [%zu > %u] " , i , smplCnt , clk + cl_4 + 1 ) ;
2019-03-10 02:19:50 +08:00
bits [ bitCnt + + ] = 7 ;
} else if ( waveHigh ) {
bits [ bitCnt + + ] = invert ;
bits [ bitCnt + + ] = invert ;
2020-04-29 04:29:22 +08:00
} else {
2019-03-10 02:19:50 +08:00
bits [ bitCnt + + ] = invert ^ 1 ;
bits [ bitCnt + + ] = invert ^ 1 ;
}
2019-05-28 17:15:12 +08:00
if ( * startIdx = = 0 ) {
2019-03-10 02:19:50 +08:00
* startIdx = i - clk ;
2020-02-04 04:38:42 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: cleanAskRawDemod minus clock [%d] " , * startIdx ) ;
2019-05-28 17:15:12 +08:00
}
2019-03-10 02:19:50 +08:00
waveHigh = ! waveHigh ;
smplCnt = 0 ;
2019-03-10 07:00:59 +08:00
// 16-8-1 = 7
2019-03-10 02:19:50 +08:00
} else if ( smplCnt > cl_2 - cl_4 - 1 ) { //half clock
if ( smplCnt > cl_2 + cl_4 + 1 ) { //too many samples
errCnt + + ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: cleanAskRawDemod ASK Modulation Error HALF at: %zu [%zu] " , i , smplCnt ) ;
2019-03-10 02:19:50 +08:00
bits [ bitCnt + + ] = 7 ;
}
if ( waveHigh ) {
bits [ bitCnt + + ] = invert ;
2020-04-29 04:27:50 +08:00
} else {
2019-03-10 02:19:50 +08:00
bits [ bitCnt + + ] = invert ^ 1 ;
}
2020-04-29 04:27:50 +08:00
2019-05-28 17:15:12 +08:00
if ( * startIdx = = 0 ) {
2019-03-10 02:19:50 +08:00
* startIdx = i - cl_2 ;
2020-02-04 04:38:42 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: cleanAskRawDemod minus half clock [%d] " , * startIdx ) ;
2019-05-28 17:15:12 +08:00
}
2019-03-10 02:19:50 +08:00
waveHigh = ! waveHigh ;
smplCnt = 0 ;
} else {
smplCnt + + ;
//transition bit oops
}
} else { //haven't hit new high or new low yet
smplCnt + + ;
}
}
}
2019-05-26 01:27:43 +08:00
2019-03-10 02:19:50 +08:00
* size = bitCnt ;
2019-04-09 22:23:55 +08:00
2019-05-28 17:15:12 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: cleanAskRawDemod Startidx %d " , * startIdx ) ;
2019-04-10 15:36:23 +08:00
2019-03-10 02:19:50 +08:00
return errCnt ;
2017-03-03 18:36:07 +08:00
}
2015-01-07 12:29:45 +08:00
//by marshmellow
2017-07-30 15:17:48 +08:00
//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
2019-03-10 18:20:22 +08:00
int askdemod_ext ( uint8_t * bits , size_t * size , int * clk , int * invert , int maxErr , uint8_t amp , uint8_t askType , int * startIdx ) {
2019-03-09 15:59:13 +08:00
2019-03-10 02:19:50 +08:00
if ( * size = = 0 ) return - 1 ;
2019-03-18 20:40:51 +08:00
if ( signalprop . isnoise ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG (askdemod_ext) just noise detected - aborting " ) ;
return - 2 ;
}
2019-03-28 21:19:41 +08:00
2019-03-10 02:19:50 +08:00
int start = DetectASKClock ( bits , * size , clk , maxErr ) ;
if ( * clk = = 0 | | start < 0 ) return - 3 ;
2019-03-28 21:19:41 +08:00
2019-03-10 02:19:50 +08:00
if ( * invert ! = 1 ) * invert = 0 ;
// amplify signal data.
// ICEMAN todo,
if ( amp = = 1 ) askAmp ( bits , * size ) ;
2019-03-18 20:40:51 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG (askdemod_ext) clk %d, beststart %d, amp %d " , * clk , start , amp ) ;
2019-03-10 02:19:50 +08:00
// Detect high and lows
//25% clip in case highs and lows aren't clipped [marshmellow]
int high , low ;
getHiLo ( & high , & low , 75 , 75 ) ;
size_t errCnt = 0 ;
// if clean clipped waves detected run alternate demod
if ( DetectCleanAskWave ( bits , * size , high , low ) ) {
2019-05-28 17:15:12 +08:00
//start pos from detect ask clock is 1/2 clock offset
// NOTE: can be negative (demod assumes rest of wave was there)
* startIdx = start - ( * clk / 2 ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG: (askdemod_ext) Clean wave detected --- startindex %d " , * startIdx ) ;
2019-03-10 02:19:50 +08:00
errCnt = cleanAskRawDemod ( bits , size , * clk , * invert , high , low , startIdx ) ;
if ( askType ) { //ask/manchester
uint8_t alignPos = 0 ;
errCnt = manrawdecode ( bits , size , 0 , & alignPos ) ;
2019-05-28 17:15:12 +08:00
* startIdx + = ( ( * clk / 2 ) * alignPos ) ;
2019-03-10 02:19:50 +08:00
2020-02-04 04:38:42 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u , bestError %zu " , * startIdx , alignPos , errCnt ) ;
2019-03-10 02:19:50 +08:00
}
return errCnt ;
}
2020-10-08 04:50:22 +08:00
* startIdx = start - ( * clk / 2 ) ;
2020-02-05 00:38:02 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG: (askdemod_ext) Weak wave detected: startIdx %i " , * startIdx ) ;
2019-03-10 02:19:50 +08:00
2021-01-28 07:35:14 +08:00
int lastBit ; // set first clock check - can go negative
size_t i , bitnum = 0 ; // output counter
2019-03-10 02:19:50 +08:00
uint8_t midBit = 0 ;
2021-01-28 07:35:14 +08:00
uint8_t tol = 0 ; // clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
if ( * clk < = 32 ) tol = 1 ; // clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
size_t MaxBits = 3072 ; // max bits to collect
2019-03-10 02:19:50 +08:00
lastBit = start - * clk ;
for ( i = start ; i < * size ; + + i ) {
2019-03-10 07:00:59 +08:00
if ( i - lastBit > = * clk - tol ) {
2019-03-10 02:19:50 +08:00
if ( bits [ i ] > = high ) {
bits [ bitnum + + ] = * invert ;
} else if ( bits [ i ] < = low ) {
bits [ bitnum + + ] = * invert ^ 1 ;
2019-03-10 07:00:59 +08:00
} else if ( i - lastBit > = * clk + tol ) {
2019-03-10 02:19:50 +08:00
if ( bitnum > 0 ) {
2019-03-18 20:40:51 +08:00
// if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i);
2019-03-10 02:19:50 +08:00
bits [ bitnum + + ] = 7 ;
errCnt + + ;
}
} else { //in tolerance - looking for peak
continue ;
}
midBit = 0 ;
lastBit + = * clk ;
2019-03-10 07:00:59 +08:00
} else if ( i - lastBit > = ( * clk / 2 - tol ) & & ! midBit & & ! askType ) {
2019-03-10 02:19:50 +08:00
if ( bits [ i ] > = high ) {
bits [ bitnum + + ] = * invert ;
} else if ( bits [ i ] < = low ) {
bits [ bitnum + + ] = * invert ^ 1 ;
2019-03-10 07:00:59 +08:00
} else if ( i - lastBit > = * clk / 2 + tol ) {
2021-04-04 13:48:53 +08:00
if ( bitnum > 0 ) {
bits [ bitnum ] = bits [ bitnum - 1 ] ;
bitnum + + ;
} else {
bits [ bitnum ] = 0 ;
bitnum + + ;
}
2019-03-10 02:19:50 +08:00
} else { //in tolerance - looking for peak
continue ;
}
midBit = 1 ;
}
if ( bitnum > = MaxBits ) break ;
}
* size = bitnum ;
return errCnt ;
2015-01-07 12:29:45 +08:00
}
2019-03-10 18:20:22 +08:00
int askdemod ( uint8_t * bits , size_t * size , int * clk , int * invert , int maxErr , uint8_t amp , uint8_t askType ) {
2019-03-10 02:19:50 +08:00
int start = 0 ;
return askdemod_ext ( bits , size , clk , invert , maxErr , amp , askType , & start ) ;
2017-07-30 15:17:48 +08:00
}
2015-11-20 23:56:43 +08:00
2017-07-30 15:17:48 +08:00
// by marshmellow - demodulate NRZ wave - requires a read with strong signal
// peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak
2019-03-10 18:20:22 +08:00
int nrzRawDemod ( uint8_t * dest , size_t * size , int * clk , int * invert , int * startIdx ) {
2019-04-05 05:32:47 +08:00
2019-04-05 05:42:02 +08:00
if ( signalprop . isnoise ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG nrzRawDemod: just noise detected - quitting " ) ;
return - 1 ;
}
2019-04-07 01:09:01 +08:00
2019-03-10 02:19:50 +08:00
size_t clkStartIdx = 0 ;
* clk = DetectNRZClock ( dest , * size , * clk , & clkStartIdx ) ;
if ( * clk = = 0 ) return - 2 ;
2019-04-05 05:32:47 +08:00
size_t i ;
2019-03-10 02:19:50 +08:00
int high , low ;
2019-04-05 05:32:47 +08:00
2019-03-10 02:19:50 +08:00
getHiLo ( & high , & low , 75 , 75 ) ;
2019-03-10 07:00:59 +08:00
uint8_t bit = 0 ;
2019-03-10 02:19:50 +08:00
//convert wave samples to 1's and 0's
2019-03-10 07:00:59 +08:00
for ( i = 20 ; i < * size - 20 ; i + + ) {
2019-03-10 02:19:50 +08:00
if ( dest [ i ] > = high ) bit = 1 ;
if ( dest [ i ] < = low ) bit = 0 ;
dest [ i ] = bit ;
}
//now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit)
size_t lastBit = 0 ;
size_t numBits = 0 ;
2019-03-10 07:00:59 +08:00
for ( i = 21 ; i < * size - 20 ; i + + ) {
2019-03-10 02:19:50 +08:00
//if transition detected or large number of same bits - store the passed bits
2019-03-10 07:00:59 +08:00
if ( dest [ i ] ! = dest [ i - 1 ] | | ( i - lastBit ) = = ( 10 * * clk ) ) {
memset ( dest + numBits , dest [ i - 1 ] ^ * invert , ( i - lastBit + ( * clk / 4 ) ) / * clk ) ;
numBits + = ( i - lastBit + ( * clk / 4 ) ) / * clk ;
2019-03-10 02:19:50 +08:00
if ( lastBit = = 0 ) {
* startIdx = i - ( numBits * * clk ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: startIdx %i " , * startIdx ) ;
}
2019-03-10 07:00:59 +08:00
lastBit = i - 1 ;
2019-03-10 02:19:50 +08:00
}
}
* size = numBits ;
return 0 ;
2017-03-03 18:36:07 +08:00
}
2017-07-30 15:17:48 +08:00
//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
2019-04-13 06:25:43 +08:00
static size_t fsk_wave_demod ( uint8_t * dest , size_t size , uint8_t fchigh , uint8_t fclow , int * startIdx ) {
2019-03-09 15:59:13 +08:00
2019-03-10 07:00:59 +08:00
if ( size < 1024 ) return 0 ; // not enough samples
2019-03-10 02:19:50 +08:00
if ( fchigh = = 0 ) fchigh = 10 ;
if ( fclow = = 0 ) fclow = 8 ;
//set the threshold close to 0 (graph) or 128 std to avoid static
2019-04-07 21:18:02 +08:00
size_t preLastSample , LastSample = 0 ;
size_t currSample = 0 , last_transition = 0 ;
size_t idx , numBits = 0 ;
2019-03-10 02:19:50 +08:00
//find start of modulating data in trace
idx = findModStart ( dest , size , fchigh ) ;
// Need to threshold first sample
dest [ idx ] = ( dest [ idx ] < signalprop . mean ) ? 0 : 1 ;
last_transition = idx ;
idx + + ;
// Definition: cycles between consecutive lo-hi transitions
// Lets define some expected lengths. FSK1 is easier since it has bigger differences between.
// FSK1 8/5
// 50/8 = 6 | 40/8 = 5 | 64/8 = 8
// 50/5 = 10 | 40/5 = 8 | 64/5 = 12
// FSK2 10/8
// 50/10 = 5 | 40/10 = 4 | 64/10 = 6
// 50/8 = 6 | 40/8 = 5 | 64/8 = 8
// count cycles between consecutive lo-hi transitions,
// in practice due to noise etc we may end up with anywhere
// To allow fuzz would mean +-1 on expected cycle width.
// FSK1 8/5
// 50/8 = 6 (5-7) | 40/8 = 5 (4-6) | 64/8 = 8 (7-9)
// 50/5 = 10 (9-11) | 40/5 = 8 (7-9) | 64/5 = 12 (11-13)
// FSK2 10/8
// 50/10 = 5 (4-6) | 40/10 = 4 (3-5) | 64/10 = 6 (5-7)
// 50/8 = 6 (5-7) | 40/8 = 5 (4-6) | 64/8 = 8 (7-9)
//
// It easy to see to the overgaping, but luckily we the group value also, like 1111000001111
// to separate between which bit to demodulate to.
// process:
// count width from 0-1 transition to 1-0.
// determine the width is withing FUZZ_min and FUZZ_max tolerances
// width should be divided with exp_one. i:e 6+7+6+2=21, 21/5 = 4,
// the 1-0 to 0-1 width should be divided with exp_zero. Ie: 3+5+6+7 = 21/6 = 3
2019-03-10 07:00:59 +08:00
for ( ; idx < size - 20 ; idx + + ) {
2019-03-10 02:19:50 +08:00
// threshold current value
dest [ idx ] = ( dest [ idx ] < signalprop . mean ) ? 0 : 1 ;
// Check for 0->1 transition
2019-03-10 07:00:59 +08:00
if ( dest [ idx - 1 ] < dest [ idx ] ) {
2019-03-10 02:19:50 +08:00
preLastSample = LastSample ;
LastSample = currSample ;
2019-03-10 07:00:59 +08:00
currSample = idx - last_transition ;
if ( currSample < ( fclow - 2 ) ) { //0-5 = garbage noise (or 0-3)
2019-03-10 02:19:50 +08:00
//do nothing with extra garbage
2019-03-10 07:00:59 +08:00
} else if ( currSample < ( fchigh - 1 ) ) { //6-8 = 8 sample waves (or 3-6 = 5)
2019-03-10 02:19:50 +08:00
//correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
2019-03-10 07:00:59 +08:00
if ( numBits > 1 & & LastSample > ( fchigh - 2 ) & & ( preLastSample < ( fchigh - 1 ) ) ) {
dest [ numBits - 1 ] = 1 ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
dest [ numBits + + ] = 1 ;
2019-03-10 02:19:50 +08:00
if ( numBits > 0 & & * startIdx = = 0 )
* startIdx = idx - fclow ;
2019-03-10 07:00:59 +08:00
} else if ( currSample > ( fchigh + 1 ) & & numBits < 3 ) { //12 + and first two bit = unusable garbage
2019-03-10 02:19:50 +08:00
//do nothing with beginning garbage and reset.. should be rare..
numBits = 0 ;
2019-03-10 07:00:59 +08:00
} else if ( currSample = = ( fclow + 1 ) & & LastSample = = ( fclow - 1 ) ) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
dest [ numBits + + ] = 1 ;
2019-03-10 02:19:50 +08:00
if ( numBits > 0 & & * startIdx = = 0 ) {
* startIdx = idx - fclow ;
}
} else { //9+ = 10 sample waves (or 6+ = 7)
2019-03-10 07:00:59 +08:00
dest [ numBits + + ] = 0 ;
if ( numBits > 0 & & * startIdx = = 0 ) {
* startIdx = idx - fchigh ;
}
2019-03-10 02:19:50 +08:00
}
last_transition = idx ;
}
}
return numBits ; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
2017-07-30 15:17:48 +08:00
}
//translate 11111100000 to 10
//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
2019-04-13 06:25:43 +08:00
static size_t aggregate_bits ( uint8_t * dest , size_t size , uint8_t clk , uint8_t invert , uint8_t fchigh , uint8_t fclow , int * startIdx ) {
2018-09-06 01:13:39 +08:00
2019-03-10 02:19:50 +08:00
uint8_t lastval = dest [ 0 ] ;
size_t i = 0 ;
size_t numBits = 0 ;
uint32_t n = 1 ;
2019-03-10 07:00:59 +08:00
uint8_t hclk = clk / 2 ;
2019-03-10 02:19:50 +08:00
2019-03-10 07:00:59 +08:00
for ( i = 1 ; i < size ; i + + ) {
2019-03-10 02:19:50 +08:00
n + + ;
if ( dest [ i ] = = lastval ) continue ; //skip until we hit a transition
//find out how many bits (n) we collected (use 1/2 clk tolerance)
2019-03-10 07:00:59 +08:00
if ( dest [ i - 1 ] = = 1 )
//if lastval was 1, we have a 1->0 crossing
2019-03-10 02:19:50 +08:00
n = ( n * fclow + hclk ) / clk ;
else
// 0->1 crossing
n = ( n * fchigh + hclk ) / clk ;
if ( n = = 0 )
n = 1 ;
//first transition - save startidx
if ( numBits = = 0 ) {
if ( lastval = = 1 ) { //high to low
2019-03-10 07:00:59 +08:00
* startIdx + = ( fclow * i ) - ( n * clk ) ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG (aggregate_bits) FSK startIdx %i, fclow*idx %zu, n*clk %u " , * startIdx , fclow * i , n * clk ) ;
2019-03-10 02:19:50 +08:00
} else {
2019-03-10 07:00:59 +08:00
* startIdx + = ( fchigh * i ) - ( n * clk ) ;
2019-10-09 22:40:01 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG (aggregate_bits) FSK startIdx %i, fchigh*idx %zu, n*clk %u " , * startIdx , fchigh * i , n * clk ) ;
2019-03-10 02:19:50 +08:00
}
}
//add to our destination the bits we collected
2019-03-10 07:00:59 +08:00
memset ( dest + numBits , dest [ i - 1 ] ^ invert , n ) ;
2019-03-10 02:19:50 +08:00
numBits + = n ;
n = 0 ;
lastval = dest [ i ] ;
} //end for
// if valid extra bits at the end were all the same frequency - add them in
2019-03-10 07:00:59 +08:00
if ( n > clk / fchigh ) {
if ( dest [ i - 2 ] = = 1 ) {
n = ( n * fclow + clk / 2 ) / clk ;
2019-03-10 02:19:50 +08:00
} else {
2019-03-10 07:00:59 +08:00
n = ( n * fchigh + clk / 2 ) / clk ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
memset ( dest + numBits , dest [ i - 1 ] ^ invert , n ) ;
2019-03-10 02:19:50 +08:00
numBits + = n ;
2019-05-26 01:27:43 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG (aggregate_bits) extra bits in the end " ) ;
2019-03-10 02:19:50 +08:00
}
return numBits ;
2017-07-30 15:17:48 +08:00
}
//by marshmellow (from holiman's base)
// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
2019-03-10 18:20:22 +08:00
size_t fskdemod ( uint8_t * dest , size_t size , uint8_t rfLen , uint8_t invert , uint8_t fchigh , uint8_t fclow , int * start_idx ) {
2019-03-10 02:19:50 +08:00
if ( signalprop . isnoise ) return 0 ;
// FSK demodulator
size = fsk_wave_demod ( dest , size , fchigh , fclow , start_idx ) ;
2019-05-26 01:27:43 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG (fskdemod) got %zu bits " , size ) ;
2019-03-10 02:19:50 +08:00
size = aggregate_bits ( dest , size , rfLen , invert , fchigh , fclow , start_idx ) ;
2019-05-26 01:27:43 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG (fskdemod) got %zu bits " , size ) ;
2019-03-10 02:19:50 +08:00
return size ;
2015-01-07 12:29:45 +08:00
}
2015-01-27 06:23:19 +08:00
// by marshmellow
// convert psk1 demod to psk2 demod
// only transition waves are 1s
2018-09-06 01:13:39 +08:00
//TODO: Iceman - hard coded value 7, should be #define
2019-03-10 18:20:22 +08:00
void psk1TOpsk2 ( uint8_t * bits , size_t size ) {
2019-03-10 02:19:50 +08:00
uint8_t lastbit = bits [ 0 ] ;
2019-03-10 07:00:59 +08:00
for ( size_t i = 1 ; i < size ; i + + ) {
2019-03-10 02:19:50 +08:00
//ignore errors
if ( bits [ i ] = = 7 ) continue ;
2019-03-10 07:00:59 +08:00
if ( lastbit ! = bits [ i ] ) {
2019-03-10 02:19:50 +08:00
lastbit = bits [ i ] ;
bits [ i ] = 1 ;
} else {
bits [ i ] = 0 ;
}
}
2015-01-27 06:23:19 +08:00
}
2015-01-07 12:29:45 +08:00
2015-02-22 11:54:52 +08:00
// by marshmellow
// convert psk2 demod to psk1 demod
// from only transition waves are 1s to phase shifts change bit
2019-03-10 18:20:22 +08:00
void psk2TOpsk1 ( uint8_t * bits , size_t size ) {
2019-03-10 02:19:50 +08:00
uint8_t phase = 0 ;
2019-03-10 07:00:59 +08:00
for ( size_t i = 0 ; i < size ; i + + ) {
if ( bits [ i ] = = 1 ) {
2019-03-10 02:19:50 +08:00
phase ^ = 1 ;
}
bits [ i ] = phase ;
}
2015-02-22 11:54:52 +08:00
}
2019-03-09 15:59:13 +08:00
//by marshmellow - demodulate PSK1 wave
//uses wave lengths (# Samples)
2018-09-06 01:13:39 +08:00
//TODO: Iceman - hard coded value 7, should be #define
2019-03-10 18:20:22 +08:00
int pskRawDemod_ext ( uint8_t * dest , size_t * size , int * clock , int * invert , int * startIdx ) {
2019-03-09 15:59:13 +08:00
2019-03-10 02:19:50 +08:00
// sanity check
if ( * size < 170 ) return - 1 ;
uint8_t curPhase = * invert ;
2019-03-10 07:00:59 +08:00
uint8_t fc = 0 ;
2019-04-07 21:18:02 +08:00
size_t i = 0 , numBits = 0 , waveStart = 1 , waveEnd , firstFullWave = 0 , lastClkBit = 0 ;
uint16_t fullWaveLen = 0 , waveLenCnt , avgWaveVal = 0 ;
2019-03-10 07:00:59 +08:00
uint16_t errCnt = 0 , errCnt2 = 0 ;
2019-03-10 02:19:50 +08:00
* clock = DetectPSKClock ( dest , * size , * clock , & firstFullWave , & curPhase , & fc ) ;
if ( * clock < = 0 ) return - 1 ;
//if clock detect found firstfullwave...
2019-03-10 07:00:59 +08:00
uint16_t tol = fc / 2 ;
2019-03-10 02:19:50 +08:00
if ( firstFullWave = = 0 ) {
//find start of modulating data in trace
i = findModStart ( dest , * size , fc ) ;
//find first phase shift
firstFullWave = pskFindFirstPhaseShift ( dest , * size , & curPhase , i , fc , & fullWaveLen ) ;
if ( firstFullWave = = 0 ) {
// no phase shift detected - could be all 1's or 0's - doesn't matter where we start
// so skip a little to ensure we are past any Start Signal
firstFullWave = 160 ;
memset ( dest , curPhase , firstFullWave / * clock ) ;
} else {
2019-03-10 07:00:59 +08:00
memset ( dest , curPhase ^ 1 , firstFullWave / * clock ) ;
2019-03-10 02:19:50 +08:00
}
} else {
2019-03-10 07:00:59 +08:00
memset ( dest , curPhase ^ 1 , firstFullWave / * clock ) ;
2019-03-10 02:19:50 +08:00
}
//advance bits
numBits + = ( firstFullWave / * clock ) ;
2019-03-10 07:00:59 +08:00
* startIdx = firstFullWave - ( * clock * numBits ) + 2 ;
2019-03-10 02:19:50 +08:00
//set start of wave as clock align
lastClkBit = firstFullWave ;
2019-04-07 21:18:02 +08:00
if ( g_debugMode = = 2 ) {
2019-10-09 22:40:01 +08:00
prnt ( " DEBUG PSK: firstFullWave: %zu, waveLen: %u, startIdx %i " , firstFullWave , fullWaveLen , * startIdx ) ;
prnt ( " DEBUG PSK: clk: %d, lastClkBit: %zu, fc: %u " , * clock , lastClkBit , fc ) ;
2019-04-07 21:18:02 +08:00
}
2019-04-10 15:36:23 +08:00
2019-03-10 02:19:50 +08:00
waveStart = 0 ;
dest [ numBits + + ] = curPhase ; //set first read bit
2019-03-10 07:00:59 +08:00
for ( i = firstFullWave + fullWaveLen - 1 ; i < * size - 3 ; i + + ) {
2019-03-10 02:19:50 +08:00
//top edge of wave = start of new wave
2019-03-10 07:00:59 +08:00
if ( dest [ i ] + fc < dest [ i + 1 ] & & dest [ i + 1 ] > = dest [ i + 2 ] ) {
2019-03-10 02:19:50 +08:00
if ( waveStart = = 0 ) {
2019-03-10 07:00:59 +08:00
waveStart = i + 1 ;
avgWaveVal = dest [ i + 1 ] ;
2019-03-10 02:19:50 +08:00
} else { //waveEnd
2019-03-10 07:00:59 +08:00
waveEnd = i + 1 ;
waveLenCnt = waveEnd - waveStart ;
if ( waveLenCnt > fc ) {
2019-03-10 02:19:50 +08:00
//this wave is a phase shift
2019-04-04 13:23:18 +08:00
/*
2019-04-07 01:09:01 +08:00
prnt ( " DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d "
2019-04-04 13:23:18 +08:00
, waveStart
, waveLenCnt
, lastClkBit + * clock - tol
, i + 1
, fc ) ;
2019-04-07 01:09:01 +08:00
*/
2019-03-10 07:00:59 +08:00
if ( i + 1 > = lastClkBit + * clock - tol ) { //should be a clock bit
2019-03-10 02:19:50 +08:00
curPhase ^ = 1 ;
dest [ numBits + + ] = curPhase ;
lastClkBit + = * clock ;
2019-03-10 07:00:59 +08:00
} else if ( i < lastClkBit + 10 + fc ) {
2019-03-10 02:19:50 +08:00
//noise after a phase shift - ignore
} else { //phase shift before supposed to based on clock
errCnt + + ;
dest [ numBits + + ] = 7 ;
}
2019-03-10 07:00:59 +08:00
} else if ( i + 1 > lastClkBit + * clock + tol + fc ) {
2019-03-10 02:19:50 +08:00
lastClkBit + = * clock ; //no phase shift but clock bit
dest [ numBits + + ] = curPhase ;
} else if ( waveLenCnt < fc - 1 ) { //wave is smaller than field clock (shouldn't happen often)
errCnt2 + + ;
if ( errCnt2 > 101 ) return errCnt2 ;
2019-03-10 07:00:59 +08:00
avgWaveVal + = dest [ i + 1 ] ;
2019-03-10 02:19:50 +08:00
continue ;
}
avgWaveVal = 0 ;
2019-03-10 07:00:59 +08:00
waveStart = i + 1 ;
2019-03-10 02:19:50 +08:00
}
}
2019-03-10 07:00:59 +08:00
avgWaveVal + = dest [ i + 1 ] ;
2019-03-10 02:19:50 +08:00
}
* size = numBits ;
return errCnt ;
2015-02-07 03:36:25 +08:00
}
2016-02-20 05:30:19 +08:00
2019-03-10 18:20:22 +08:00
int pskRawDemod ( uint8_t * dest , size_t * size , int * clock , int * invert ) {
2019-03-10 02:19:50 +08:00
int start_idx = 0 ;
return pskRawDemod_ext ( dest , size , clock , invert , & start_idx ) ;
2017-07-30 15:17:48 +08:00
}
2019-09-23 01:00:11 +08:00
// **********************************************************************************************
// -----------------Tag format detection section-------------------------------------------------
// **********************************************************************************************
2017-07-30 15:17:48 +08:00
// by marshmellow
// FSK Demod then try to locate an AWID ID
2019-03-10 18:20:22 +08:00
int detectAWID ( uint8_t * dest , size_t * size , int * waveStartIdx ) {
2019-03-10 02:19:50 +08:00
//make sure buffer has enough data (96bits * 50clock samples)
2019-03-10 07:00:59 +08:00
if ( * size < 96 * 50 ) return - 1 ;
2017-07-30 15:17:48 +08:00
2019-03-10 02:19:50 +08:00
if ( signalprop . isnoise ) return - 2 ;
2017-07-30 15:17:48 +08:00
2019-03-10 02:19:50 +08:00
// FSK2a demodulator clock 50, invert 1, fcHigh 10, fcLow 8
* size = fskdemod ( dest , * size , 50 , 1 , 10 , 8 , waveStartIdx ) ; //awid fsk2a
2017-08-10 20:19:57 +08:00
2019-03-10 02:19:50 +08:00
//did we get a good demod?
if ( * size < 96 ) return - 3 ;
2017-07-30 15:17:48 +08:00
2019-03-10 02:19:50 +08:00
size_t start_idx = 0 ;
2019-03-10 07:00:59 +08:00
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
2019-03-10 02:19:50 +08:00
if ( ! preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & start_idx ) )
return - 4 ; //preamble not found
2019-03-09 15:59:13 +08:00
2019-03-10 02:19:50 +08:00
// wrong size? (between to preambles)
if ( * size ! = 96 ) return - 5 ;
2019-03-09 15:59:13 +08:00
2019-03-10 02:19:50 +08:00
return ( int ) start_idx ;
2017-03-02 03:14:46 +08:00
}
2016-02-20 05:30:19 +08:00
//by marshmellow
2017-07-30 15:17:48 +08:00
//takes 1s and 0s and searches for EM410x format - output EM ID
2019-03-10 18:20:22 +08:00
int Em410xDecode ( uint8_t * bits , size_t * size , size_t * start_idx , uint32_t * hi , uint64_t * lo ) {
2019-03-10 02:19:50 +08:00
// sanity check
if ( bits [ 1 ] > 1 ) return - 1 ;
if ( * size < 64 ) return - 2 ;
uint8_t fmtlen ;
* start_idx = 0 ;
// preamble 0111111111
// include 0 in front to help get start pos
2019-03-10 07:00:59 +08:00
uint8_t preamble [ ] = { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 } ;
2019-03-10 02:19:50 +08:00
if ( ! preambleSearch ( bits , preamble , sizeof ( preamble ) , size , start_idx ) )
return - 4 ;
// (iceman) if the preamble doesn't find two occuriences, this identification fails.
fmtlen = ( * size = = 128 ) ? 22 : 10 ;
//skip last 4bit parity row for simplicity
* size = removeParity ( bits , * start_idx + sizeof ( preamble ) , 5 , 0 , fmtlen * 5 ) ;
switch ( * size ) {
2019-03-10 07:00:59 +08:00
case 40 : {
// std em410x format
* hi = 0 ;
* lo = ( ( uint64_t ) ( bytebits_to_byte ( bits , 8 ) ) < < 32 ) | ( bytebits_to_byte ( bits + 8 , 32 ) ) ;
break ;
2019-03-10 02:19:50 +08:00
}
case 88 : {
2019-03-10 07:00:59 +08:00
// long em format
* hi = ( bytebits_to_byte ( bits , 24 ) ) ;
* lo = ( ( uint64_t ) ( bytebits_to_byte ( bits + 24 , 32 ) ) < < 32 ) | ( bytebits_to_byte ( bits + 24 + 32 , 32 ) ) ;
break ;
2019-03-10 02:19:50 +08:00
}
2019-03-10 07:00:59 +08:00
default :
return - 6 ;
2019-03-10 02:19:50 +08:00
}
return 1 ;
2017-07-30 15:17:48 +08:00
}
2016-02-20 05:30:19 +08:00
2018-09-08 05:47:42 +08:00
2017-07-30 15:17:48 +08:00
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
2019-03-10 18:20:22 +08:00
int HIDdemodFSK ( uint8_t * dest , size_t * size , uint32_t * hi2 , uint32_t * hi , uint32_t * lo , int * waveStartIdx ) {
2019-03-10 02:19:50 +08:00
//make sure buffer has data
2019-03-10 07:00:59 +08:00
if ( * size < 96 * 50 ) return - 1 ;
2019-03-10 02:19:50 +08:00
if ( signalprop . isnoise ) return - 2 ;
// FSK demodulator fsk2a so invert and fc/10/8
* size = fskdemod ( dest , * size , 50 , 1 , 10 , 8 , waveStartIdx ) ; //hid fsk2a
//did we get a good demod?
2019-03-10 07:00:59 +08:00
if ( * size < 96 * 2 ) return - 3 ;
2019-03-10 02:19:50 +08:00
// 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
size_t start_idx = 0 ;
2019-03-10 07:00:59 +08:00
uint8_t preamble [ ] = { 0 , 0 , 0 , 1 , 1 , 1 , 0 , 1 } ;
2019-03-10 02:19:50 +08:00
if ( ! preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & start_idx ) )
return - 4 ; //preamble not found
// wrong size? (between to preambles)
//if (*size != 96) return -5;
size_t num_start = start_idx + sizeof ( preamble ) ;
// final loop, go over previously decoded FSK data and manchester decode into usable tag ID
for ( size_t idx = num_start ; ( idx - num_start ) < * size - sizeof ( preamble ) ; idx + = 2 ) {
2019-03-10 07:00:59 +08:00
if ( dest [ idx ] = = dest [ idx + 1 ] ) {
2019-03-10 02:19:50 +08:00
return - 5 ; //not manchester data
}
* hi2 = ( * hi2 < < 1 ) | ( * hi > > 31 ) ;
* hi = ( * hi < < 1 ) | ( * lo > > 31 ) ;
//Then, shift in a 0 or one into low
* lo < < = 1 ;
2019-03-10 07:00:59 +08:00
if ( dest [ idx ] & & ! dest [ idx + 1 ] ) // 1 0
2019-03-10 02:19:50 +08:00
* lo | = 1 ;
else // 0 1
* lo | = 0 ;
}
return ( int ) start_idx ;
2017-07-30 15:17:48 +08:00
}
2016-02-20 05:30:19 +08:00
2019-03-10 18:20:22 +08:00
int detectIOProx ( uint8_t * dest , size_t * size , int * waveStartIdx ) {
2019-03-10 02:19:50 +08:00
//make sure buffer has data
2019-03-10 07:00:59 +08:00
if ( * size < 66 * 64 ) return - 1 ;
2019-03-10 02:19:50 +08:00
if ( signalprop . isnoise ) return - 2 ;
// FSK demodulator RF/64, fsk2a so invert, and fc/10/8
* size = fskdemod ( dest , * size , 64 , 1 , 10 , 8 , waveStartIdx ) ; //io fsk2a
//did we get enough demod data?
if ( * size < 64 ) return - 3 ;
//Index map
//0 10 20 30 40 50 60
//| | | | | | |
//01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
//-----------------------------------------------------------------------------
//00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
//
//XSF(version)facility:codeone+codetwo
size_t start_idx = 0 ;
2019-03-10 07:00:59 +08:00
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
2019-03-10 02:19:50 +08:00
if ( ! preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & start_idx ) )
return - 4 ; //preamble not found
// wrong size? (between to preambles)
if ( * size ! = 64 ) return - 5 ;
2019-03-10 07:00:59 +08:00
if ( ! dest [ start_idx + 8 ]
2019-03-10 18:20:22 +08:00
& & dest [ start_idx + 17 ] = = 1
& & dest [ start_idx + 26 ] = = 1
& & dest [ start_idx + 35 ] = = 1
& & dest [ start_idx + 44 ] = = 1
& & dest [ start_idx + 53 ] = = 1 ) {
2019-03-10 02:19:50 +08:00
//confirmed proper separator bits found
//return start position
return ( int ) start_idx ;
}
return - 6 ;
2019-03-08 04:13:58 +08:00
}