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-03-13 10:57:01 +08:00
// Low frequency demod/decode commands - by marshmellow, holiman, iceman and
// many others who came before
2017-03-13 10:47:50 +08:00
//
// NOTES:
// LF Demod functions are placed here to allow the flexability to use client or
// device side. Most BUT NOT ALL of these functions are currenlty safe for
// device side use currently. (DetectST for example...)
//
// There are likely many improvements to the code that could be made, please
// make suggestions...
//
2017-03-13 10:57:01 +08:00
// we tried to include author comments so any questions could be directed to
// the source.
//
2017-03-13 10:47:50 +08:00
// There are 4 main sections of code below:
// Utilities Section:
// for general utilities used by multiple other functions
// Clock / Bitrate Detection Section:
// for clock detection functions for each modulation
2017-03-13 11:11:52 +08:00
// Modulation Demods &/or Decoding Section:
// for main general modulation demodulating and encoding decoding code.
2017-03-13 10:47:50 +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-03-13 11:11:52 +08:00
# include <string.h> // for memset, memcmp and size_t
2017-04-04 23:52:10 +08:00
# include "lfdemod.h"
2017-03-13 11:11:52 +08:00
# include <stdint.h> // for uint_32+
# include <stdbool.h> // for bool
2017-03-29 22:02:29 +08:00
# include "parity.h" // for parity test
2015-11-18 13:10:11 +08:00
2017-03-13 11:11:52 +08:00
//**********************************************************************************************
//---------------------------------Utilities Section--------------------------------------------
//**********************************************************************************************
2017-03-15 05:08:58 +08:00
# define LOWEST_DEFAULT_CLOCK 32
2017-03-15 22:53:32 +08:00
# define FSK_PSK_THRESHOLD 123
2017-03-15 23:07:52 +08:00
2016-02-17 01:49:30 +08:00
//to allow debug print calls when used not on device
2015-11-18 13:10:11 +08:00
void dummy ( char * fmt , . . . ) { }
# ifndef ON_DEVICE
# include "ui.h"
2015-11-22 13:00:32 +08:00
# include "cmdparser.h"
# include "cmddata.h"
2015-11-18 13:10:11 +08:00
# define prnt PrintAndLog
# else
2015-11-22 13:00:32 +08:00
uint8_t g_debugMode = 0 ;
2015-11-18 13:10:11 +08:00
# define prnt dummy
# endif
2017-03-13 10:57:01 +08:00
uint8_t justNoise ( uint8_t * BitStream , size_t size ) {
2015-01-28 03:51:12 +08:00
//test samples are not just noise
uint8_t justNoise1 = 1 ;
for ( size_t idx = 0 ; idx < size & & justNoise1 ; idx + + ) {
2017-03-15 22:53:32 +08:00
justNoise1 = BitStream [ idx ] < FSK_PSK_THRESHOLD ;
2015-01-28 03:51:12 +08:00
}
return justNoise1 ;
}
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
2017-03-13 10:57:01 +08:00
int getHiLo ( uint8_t * BitStream , size_t size , int * high , int * low , uint8_t fuzzHi , uint8_t fuzzLo ) {
2015-01-19 07:13:32 +08:00
* high = 0 ;
* low = 255 ;
// get high and low thresholds
2015-03-27 12:02:30 +08:00
for ( size_t i = 0 ; i < size ; i + + ) {
2015-01-19 07:13:32 +08:00
if ( BitStream [ i ] > * high ) * high = BitStream [ i ] ;
if ( BitStream [ i ] < * low ) * low = BitStream [ i ] ;
}
2017-03-15 22:53:32 +08:00
if ( * high < FSK_PSK_THRESHOLD ) return - 1 ; // just noise
2015-03-31 22:49:06 +08:00
* high = ( ( * high - 128 ) * fuzzHi + 12800 ) / 100 ;
* low = ( ( * low - 128 ) * fuzzLo + 12800 ) / 100 ;
2015-01-19 07:13:32 +08:00
return 1 ;
}
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
2017-03-29 22:02:29 +08:00
bool parityTest ( uint32_t bits , uint8_t bitLen , uint8_t pType ) {
return oddparity32 ( bits ) ^ pType ;
2015-01-28 03:51:12 +08:00
}
2015-11-22 13:00:32 +08:00
// by marshmellow
2017-03-29 22:02:29 +08:00
// takes a array of binary values, start position, length of bits per parity (includes parity bit - MAX 32),
// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
2017-03-13 10:57:01 +08:00
size_t removeParity ( uint8_t * BitStream , size_t startIdx , uint8_t pLen , uint8_t pType , size_t bLen ) {
2015-11-22 13:00:32 +08:00
uint32_t parityWd = 0 ;
2017-03-29 22:02:29 +08:00
size_t bitCnt = 0 ;
2017-02-17 14:33:27 +08:00
for ( int word = 0 ; word < ( bLen ) ; word + = pLen ) {
for ( int bit = 0 ; bit < pLen ; bit + + ) {
2017-03-29 22:02:29 +08:00
if ( word + bit > = bLen ) break ;
2015-11-22 13:00:32 +08:00
parityWd = ( parityWd < < 1 ) | BitStream [ startIdx + word + bit ] ;
2017-03-29 22:02:29 +08:00
BitStream [ bitCnt + + ] = ( BitStream [ startIdx + word + bit ] ) ;
2015-11-22 13:00:32 +08:00
}
2017-02-24 02:53:40 +08:00
if ( word + pLen > bLen ) break ;
2017-02-17 14:33:27 +08:00
2017-03-29 22:02:29 +08:00
bitCnt - - ; // overwrite parity with next data
2015-11-22 13:00:32 +08:00
// if parity fails then return 0
2016-03-01 06:05:02 +08:00
switch ( pType ) {
2017-03-29 22:02:29 +08:00
case 3 : if ( BitStream [ bitCnt ] = = 1 ) { return 0 ; } break ; //should be 0 spacer bit
case 2 : if ( BitStream [ bitCnt ] = = 0 ) { return 0 ; } break ; //should be 1 spacer bit
2016-09-27 03:15:49 +08:00
default : if ( parityTest ( parityWd , pLen , pType ) = = 0 ) { return 0 ; } break ; //test parity
2015-11-22 13:00:32 +08:00
}
parityWd = 0 ;
}
// if we got here then all the parities passed
2017-03-29 22:02:29 +08:00
//return size
2015-11-22 13:00:32 +08:00
return bitCnt ;
}
// by marshmellow
// takes a array of binary values, length of bits per parity (includes parity bit),
2016-03-01 06:05:02 +08:00
// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
// Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
2017-03-13 10:57:01 +08:00
size_t addParity ( uint8_t * BitSource , uint8_t * dest , uint8_t sourceLen , uint8_t pLen , uint8_t pType ) {
2015-11-22 13:00:32 +08:00
uint32_t parityWd = 0 ;
size_t j = 0 , bitCnt = 0 ;
for ( int word = 0 ; word < sourceLen ; word + = pLen - 1 ) {
for ( int bit = 0 ; bit < pLen - 1 ; bit + + ) {
parityWd = ( parityWd < < 1 ) | BitSource [ word + bit ] ;
dest [ j + + ] = ( BitSource [ word + bit ] ) ;
}
// if parity fails then return 0
2016-03-01 06:05:02 +08:00
switch ( pType ) {
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
default :
dest [ j + + ] = parityTest ( parityWd , pLen - 1 , pType ) ^ 1 ;
break ;
2015-11-22 13:00:32 +08:00
}
bitCnt + = pLen ;
parityWd = 0 ;
}
// if we got here then all the parities passed
//return ID start index and size
return bitCnt ;
}
2017-03-13 10:57:01 +08:00
uint32_t bytebits_to_byte ( uint8_t * src , size_t numbits ) {
2015-11-22 13:00:32 +08:00
uint32_t num = 0 ;
for ( int i = 0 ; i < numbits ; i + + )
{
num = ( num < < 1 ) | ( * src ) ;
src + + ;
}
return num ;
}
//least significant bit first
2017-03-13 10:57:01 +08:00
uint32_t bytebits_to_byteLSBF ( uint8_t * src , size_t numbits ) {
2015-11-22 13:00:32 +08:00
uint32_t num = 0 ;
for ( int i = 0 ; i < numbits ; i + + )
{
num = ( num < < 1 ) | * ( src + ( numbits - ( i + 1 ) ) ) ;
}
return num ;
}
2017-02-24 02:53:40 +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
// fineone does not look for a repeating preamble for em4x05/4x69 sends preamble once, so look for it once in the first pLen bits
bool preambleSearchEx ( uint8_t * BitStream , uint8_t * preamble , size_t pLen , size_t * size , size_t * startIdx , bool findone ) {
2017-02-16 12:27:15 +08:00
// Sanity check. If preamble length is bigger than bitstream length.
2017-02-24 02:53:40 +08:00
if ( * size < = pLen ) return false ;
2017-02-16 12:27:15 +08:00
2017-02-24 02:53:40 +08:00
uint8_t foundCnt = 0 ;
for ( size_t idx = 0 ; idx < * size - pLen ; idx + + ) {
if ( memcmp ( BitStream + idx , preamble , pLen ) = = 0 ) {
2015-03-26 02:24:36 +08:00
//first index found
foundCnt + + ;
2017-02-24 02:53:40 +08:00
if ( foundCnt = = 1 ) {
if ( g_debugMode ) prnt ( " DEBUG: preamble found at %u " , idx ) ;
2015-03-26 02:24:36 +08:00
* startIdx = idx ;
2017-02-24 02:53:40 +08:00
if ( findone ) return true ;
} else if ( foundCnt = = 2 ) {
2015-03-26 02:24:36 +08:00
* size = idx - * startIdx ;
2017-02-24 02:53:40 +08:00
return true ;
2015-03-26 02:24:36 +08:00
}
}
}
2017-02-20 09:47:45 +08:00
return false ;
}
2017-03-13 10:57:01 +08:00
//by marshmellow
//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
uint8_t preambleSearch ( uint8_t * BitStream , uint8_t * preamble , size_t pLen , size_t * size , size_t * startIdx ) {
return ( preambleSearchEx ( BitStream , preamble , pLen , size , startIdx , false ) ) ? 1 : 0 ;
}
2017-02-22 12:00:43 +08:00
// find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup.
2017-03-15 22:53:32 +08:00
size_t findModStart ( uint8_t dest [ ] , size_t size , uint8_t expWaveSize ) {
2017-02-22 12:00:43 +08:00
size_t i = 0 ;
size_t waveSizeCnt = 0 ;
uint8_t thresholdCnt = 0 ;
2017-03-15 22:53:32 +08:00
bool isAboveThreshold = dest [ i + + ] > = FSK_PSK_THRESHOLD ;
2017-02-22 12:00:43 +08:00
for ( ; i < size - 20 ; i + + ) {
2017-03-15 22:53:32 +08:00
if ( dest [ i ] < FSK_PSK_THRESHOLD & & isAboveThreshold ) {
2017-02-22 12:00:43 +08:00
thresholdCnt + + ;
if ( thresholdCnt > 2 & & waveSizeCnt < expWaveSize + 1 ) break ;
isAboveThreshold = false ;
waveSizeCnt = 0 ;
2017-03-15 22:53:32 +08:00
} else if ( dest [ i ] > = FSK_PSK_THRESHOLD & & ! isAboveThreshold ) {
2017-02-22 12:00:43 +08:00
thresholdCnt + + ;
if ( thresholdCnt > 2 & & waveSizeCnt < expWaveSize + 1 ) break ;
isAboveThreshold = true ;
waveSizeCnt = 0 ;
} else {
waveSizeCnt + + ;
}
if ( thresholdCnt > 10 ) break ;
}
if ( g_debugMode = = 2 ) prnt ( " DEBUG: threshold Count reached at %u, count: %u " , i , thresholdCnt ) ;
return i ;
}
2017-03-15 05:08:58 +08:00
int getClosestClock ( int testclk ) {
uint8_t fndClk [ ] = { 8 , 16 , 32 , 40 , 50 , 64 , 128 } ;
for ( uint8_t clkCnt = 0 ; clkCnt < 7 ; clkCnt + + )
if ( testclk > = fndClk [ clkCnt ] - ( fndClk [ clkCnt ] / 8 ) & & testclk < = fndClk [ clkCnt ] + 1 )
return fndClk [ clkCnt ] ;
return 0 ;
}
void getNextLow ( uint8_t samples [ ] , size_t size , int low , size_t * i ) {
2017-03-15 04:24:14 +08:00
while ( ( samples [ * i ] > low ) & & ( * i < size ) )
* i + = 1 ;
}
2017-03-15 05:08:58 +08:00
void getNextHigh ( uint8_t samples [ ] , size_t size , int high , size_t * i ) {
2017-03-15 04:24:14 +08:00
while ( ( samples [ * i ] < high ) & & ( * i < size ) )
* i + = 1 ;
}
// load wave counters
bool loadWaveCounters ( uint8_t samples [ ] , size_t size , int lowToLowWaveLen [ ] , int highToLowWaveLen [ ] , int * waveCnt , int * skip , int * minClk , int * high , int * low ) {
2017-03-15 05:08:58 +08:00
size_t i = 0 , firstLow , firstHigh ;
2017-03-15 04:24:14 +08:00
size_t testsize = ( size < 512 ) ? size : 512 ;
if ( getHiLo ( samples , testsize , high , low , 80 , 80 ) = = - 1 ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: just noise detected - quitting " ) ;
return false ; //just noise
}
// 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
2017-03-15 05:08:58 +08:00
firstLow = i ;
2017-03-15 04:24:14 +08:00
//find first high point for this wave
getNextHigh ( samples , size , * high , & i ) ;
2017-03-15 05:08:58 +08:00
firstHigh = i ;
2017-03-15 04:24:14 +08:00
getNextLow ( samples , size , * low , & i ) ;
2017-03-15 05:08:58 +08:00
if ( * waveCnt > = ( size / LOWEST_DEFAULT_CLOCK ) )
2017-03-15 04:24:14 +08:00
break ;
2017-03-15 05:08:58 +08:00
highToLowWaveLen [ * waveCnt ] = i - firstHigh ; //first high to first low
lowToLowWaveLen [ * waveCnt ] = i - firstLow ;
2017-03-15 04:24:14 +08:00
* waveCnt + = 1 ;
2017-03-15 05:08:58 +08:00
if ( i - firstLow < * minClk & & i < size ) {
* minClk = i - firstLow ;
2017-03-15 04:24:14 +08:00
}
}
return true ;
}
2017-04-04 23:52:10 +08:00
size_t pskFindFirstPhaseShift ( uint8_t samples [ ] , size_t size , uint8_t * curPhase , size_t waveStart , uint16_t fc , uint16_t * fullWaveLen ) {
uint16_t loopCnt = ( size + 3 < 4096 ) ? size : 4096 ; //don't need to loop through entire array...
uint16_t avgWaveVal = 0 , lastAvgWaveVal = 0 ;
size_t i = waveStart , waveEnd , waveLenCnt , firstFullWave ;
for ( ; i < loopCnt ; i + + ) {
// find peak // was "samples[i] + fc" but why? must have been used to weed out some wave error... removed..
if ( samples [ i ] < samples [ i + 1 ] & & samples [ i + 1 ] > = samples [ i + 2 ] ) {
waveEnd = i + 1 ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: waveEnd: %u, waveStart: %u " , waveEnd , waveStart ) ;
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 ) ;
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 ;
}
waveStart = i + 1 ;
avgWaveVal = 0 ;
}
avgWaveVal + = samples [ i + 2 ] ;
}
return 0 ;
}
2015-03-16 20:39:18 +08:00
//by marshmellow
2017-03-13 10:47:50 +08:00
//amplify based on ask edge detection - not accurate enough to use all the time
void askAmp ( uint8_t * BitStream , size_t size ) {
2016-06-20 12:42:03 +08:00
uint8_t Last = 128 ;
2015-04-08 13:07:39 +08:00
for ( size_t i = 1 ; i < size ; i + + ) {
if ( BitStream [ i ] - BitStream [ i - 1 ] > = 30 ) //large jump up
2016-06-20 12:42:03 +08:00
Last = 255 ;
else if ( BitStream [ i - 1 ] - BitStream [ i ] > = 20 ) //large jump down
Last = 0 ;
BitStream [ i - 1 ] = Last ;
2015-04-08 13:07:39 +08:00
}
return ;
}
2014-12-31 15:27:30 +08:00
2015-10-24 21:54:04 +08:00
uint32_t manchesterEncode2Bytes ( uint16_t datain ) {
uint32_t output = 0 ;
uint8_t curBit = 0 ;
for ( uint8_t i = 0 ; i < 16 ; i + + ) {
curBit = ( datain > > ( 15 - i ) & 1 ) ;
output | = ( 1 < < ( ( ( 15 - i ) * 2 ) + curBit ) ) ;
}
return output ;
}
2015-04-08 13:07:39 +08:00
//by marshmellow
//encode binary data into binary manchester
2017-03-21 21:53:14 +08:00
//NOTE: BitStream must have triple the size of "size" available in memory to do the swap
2017-03-13 10:47:50 +08:00
int ManchesterEncode ( uint8_t * BitStream , size_t size ) {
2017-03-21 21:53:14 +08:00
//allow up to 4K out (means BitStream must be at least 2048+4096 to handle the swap)
size = ( size > 2048 ) ? 2048 : size ;
size_t modIdx = size ;
size_t i ;
2015-04-08 13:07:39 +08:00
for ( size_t idx = 0 ; idx < size ; idx + + ) {
BitStream [ idx + modIdx + + ] = BitStream [ idx ] ;
BitStream [ idx + modIdx + + ] = BitStream [ idx ] ^ 1 ;
}
2017-03-21 21:53:14 +08:00
for ( i = 0 ; i < ( size * 2 ) ; i + + ) {
2017-03-13 10:47:50 +08:00
BitStream [ i ] = BitStream [ i + size ] ;
2015-04-08 13:07:39 +08:00
}
return i ;
}
2017-03-13 11:11:52 +08:00
// by marshmellow
// to detect a wave that has heavily clipped (clean) samples
uint8_t DetectCleanAskWave ( uint8_t dest [ ] , size_t size , uint8_t high , uint8_t low ) {
bool allArePeaks = true ;
uint16_t cntPeaks = 0 ;
size_t loopEnd = 512 + 160 ;
if ( loopEnd > size ) loopEnd = size ;
for ( size_t i = 160 ; i < loopEnd ; i + + ) {
if ( dest [ i ] > low & & dest [ i ] < high )
allArePeaks = false ;
else
cntPeaks + + ;
2017-03-13 10:57:01 +08:00
}
2017-03-13 11:11:52 +08:00
if ( ! allArePeaks ) {
if ( cntPeaks > 300 ) return true ;
}
return allArePeaks ;
2017-03-13 10:57:01 +08:00
}
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
//**********************************************************************************************
//-------------------Clock / Bitrate Detection Section------------------------------------------
//**********************************************************************************************
// by marshmellow
// to help detect clocks on heavily clipped samples
// based on count of low to low
2017-03-15 05:08:58 +08:00
int DetectStrongAskClock ( uint8_t dest [ ] , size_t size , int high , int low , int * clock ) {
2017-03-13 11:11:52 +08:00
size_t startwave ;
size_t i = 100 ;
size_t minClk = 255 ;
int shortestWaveIdx = 0 ;
// get to first full low to prime loop and skip incomplete first pulse
2017-03-15 05:08:58 +08:00
getNextHigh ( dest , size , high , & i ) ;
getNextLow ( dest , size , low , & i ) ;
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
// loop through all samples
while ( i < size ) {
2017-03-13 10:47:50 +08:00
// measure from low to low
2017-03-13 11:11:52 +08:00
startwave = i ;
2017-03-15 05:08:58 +08:00
getNextHigh ( dest , size , high , & i ) ;
getNextLow ( dest , size , low , & i ) ;
2017-03-13 11:11:52 +08:00
//get minimum measured distance
if ( i - startwave < minClk & & i < size ) {
minClk = i - startwave ;
shortestWaveIdx = startwave ;
2017-03-13 10:47:50 +08:00
}
}
2017-03-13 11:11:52 +08:00
// set clock
2017-03-15 05:08:58 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: DetectStrongAskClock smallest wave: %d " , minClk ) ;
* clock = getClosestClock ( minClk ) ;
if ( * clock = = 0 )
return 0 ;
return shortestWaveIdx ;
2017-03-13 11:11:52 +08:00
}
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +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)
int DetectASKClock ( uint8_t dest [ ] , size_t size , int * clock , int maxErr ) {
size_t i = 1 ;
uint8_t clk [ ] = { 255 , 8 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 255 } ;
uint8_t clkEnd = 9 ;
uint8_t loopCnt = 255 ; //don't need to loop through entire array...
if ( size < = loopCnt + 60 ) return - 1 ; //not enough samples
size - = 60 ; //sometimes there is a strange end wave - filter out this....
//if we already have a valid clock
uint8_t clockFnd = 0 ;
for ( ; i < clkEnd ; + + i )
if ( clk [ i ] = = * clock ) clockFnd = i ;
//clock found but continue to find best startpos
//get high and low peak
int peak , low ;
if ( getHiLo ( dest , loopCnt , & peak , & low , 75 , 75 ) < 1 ) return - 1 ;
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
//test for large clean peaks
if ( ! clockFnd ) {
if ( DetectCleanAskWave ( dest , size , peak , low ) = = 1 ) {
int ans = DetectStrongAskClock ( dest , size , peak , low , clock ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i " , clock , ans ) ;
if ( ans > 0 ) {
return ans ; //return shortest wave start position
2017-03-13 10:47:50 +08:00
}
}
2017-03-13 11:11:52 +08:00
}
uint8_t ii ;
uint8_t clkCnt , tol = 0 ;
uint16_t bestErr [ ] = { 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 , 1000 } ;
uint8_t bestStart [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
size_t errCnt = 0 ;
size_t arrLoc , loopEnd ;
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
if ( clockFnd > 0 ) {
clkCnt = clockFnd ;
clkEnd = clockFnd + 1 ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
else clkCnt = 1 ;
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
//test each valid clock from smallest to greatest to see which lines up
for ( ; clkCnt < clkEnd ; clkCnt + + ) {
if ( clk [ clkCnt ] < = 32 ) {
tol = 1 ;
} else {
tol = 0 ;
2015-01-07 12:29:45 +08:00
}
2017-03-13 11:11:52 +08:00
//if no errors allowed - keep start within the first clock
if ( ! maxErr & & size > clk [ clkCnt ] * 2 + tol & & clk [ clkCnt ] < 128 ) loopCnt = clk [ clkCnt ] * 2 ;
bestErr [ clkCnt ] = 1000 ;
//try lining up the peaks by moving starting point (try first few clocks)
for ( ii = 0 ; ii < loopCnt ; ii + + ) {
if ( dest [ ii ] < peak & & dest [ ii ] > low ) continue ;
2015-03-04 05:20:18 +08:00
2017-03-13 11:11:52 +08:00
errCnt = 0 ;
// now that we have the first one lined up test rest of wave array
loopEnd = ( ( size - ii - tol ) / clk [ clkCnt ] ) - 1 ;
for ( i = 0 ; i < loopEnd ; + + i ) {
arrLoc = ii + ( i * clk [ clkCnt ] ) ;
if ( dest [ arrLoc ] > = peak | | dest [ arrLoc ] < = low ) {
} else if ( dest [ arrLoc - tol ] > = peak | | dest [ arrLoc - tol ] < = low ) {
} else if ( dest [ arrLoc + tol ] > = peak | | dest [ arrLoc + tol ] < = low ) {
} 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 , ii , i ) ;
if ( errCnt = = 0 & & clkCnt < 7 ) {
if ( ! clockFnd ) * clock = clk [ clkCnt ] ;
return ii ;
}
//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 ] = ii ;
}
2017-03-13 10:47:50 +08:00
}
2015-03-04 05:20:18 +08:00
}
2017-03-13 11:11:52 +08:00
uint8_t iii ;
uint8_t best = 0 ;
for ( iii = 1 ; iii < clkEnd ; + + iii ) {
if ( bestErr [ iii ] < bestErr [ best ] ) {
if ( bestErr [ iii ] = = 0 ) bestErr [ iii ] = 1 ;
// current best bit to error ratio vs new bit to error ratio
if ( ( size / clk [ best ] ) / bestErr [ best ] < ( size / clk [ iii ] ) / bestErr [ iii ] ) {
best = iii ;
}
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d " , clk [ iii ] , bestErr [ iii ] , clk [ best ] , bestStart [ best ] ) ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
if ( ! clockFnd ) * clock = clk [ best ] ;
return bestStart [ best ] ;
2015-03-04 05:20:18 +08:00
}
2017-07-12 13:31:42 +08:00
int DetectStrongNRZClk ( uint8_t * dest , size_t size , int peak , int low , bool * strong ) {
2017-03-13 11:11:52 +08:00
//find shortest transition from high to low
2017-07-12 13:31:42 +08:00
* strong = false ;
2017-03-13 11:11:52 +08:00
size_t i = 0 ;
size_t transition1 = 0 ;
int lowestTransition = 255 ;
bool lastWasHigh = false ;
2017-07-12 13:31:42 +08:00
size_t transitionSampleCount = 0 ;
2017-03-13 11:11:52 +08:00
//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 ;
for ( ; i < size ; i + + ) {
if ( ( dest [ i ] > = peak & & ! lastWasHigh ) | | ( dest [ i ] < = low & & lastWasHigh ) ) {
lastWasHigh = ( dest [ i ] > = peak ) ;
if ( i - transition1 < lowestTransition ) lowestTransition = i - transition1 ;
transition1 = i ;
2017-07-12 13:31:42 +08:00
} else if ( dest [ i ] < peak & & dest [ i ] > low ) {
transitionSampleCount + + ;
2017-03-13 11:11:52 +08:00
}
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
if ( lowestTransition = = 255 ) lowestTransition = 0 ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: detectstrongNRZclk smallest wave: %d " , lowestTransition ) ;
2017-07-12 13:31:42 +08:00
// 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 ) ;
}
2017-03-13 11:11:52 +08:00
return lowestTransition ;
2017-03-13 10:47:50 +08:00
}
//by marshmellow
2017-03-13 11:11:52 +08:00
//detect nrz clock by reading #peaks vs no peaks(or errors)
2017-03-15 22:53:32 +08:00
int DetectNRZClock ( uint8_t dest [ ] , size_t size , int clock , size_t * clockStartIdx ) {
2017-03-13 11:11:52 +08:00
size_t i = 0 ;
uint8_t clk [ ] = { 8 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 255 } ;
size_t loopCnt = 4096 ; //don't need to loop through entire array...
if ( size = = 0 ) return 0 ;
if ( size < loopCnt ) loopCnt = size - 20 ;
//if we already have a valid clock quit
for ( ; i < 8 ; + + i )
if ( clk [ i ] = = clock ) return clock ;
//get high and low peak
int peak , low ;
2017-04-05 05:22:21 +08:00
if ( getHiLo ( dest , loopCnt , & peak , & low , 90 , 90 ) < 1 ) return 0 ;
2017-03-13 11:11:52 +08:00
2017-07-12 13:31:42 +08:00
bool strong = false ;
int lowestTransition = DetectStrongNRZClk ( dest , size - 20 , peak , low , & strong ) ;
if ( strong ) return lowestTransition ;
2017-03-13 11:11:52 +08:00
size_t ii ;
uint8_t clkCnt ;
uint8_t tol = 0 ;
uint16_t smplCnt = 0 ;
int16_t peakcnt = 0 ;
int16_t peaksdet [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2017-04-04 23:52:10 +08:00
uint16_t minPeak = 255 ;
bool firstpeak = true ;
//test for large clipped waves - ignore first peak
for ( i = 0 ; i < loopCnt ; i + + ) {
if ( dest [ i ] > = peak | | dest [ i ] < = low ) {
if ( firstpeak ) continue ;
2017-03-13 10:47:50 +08:00
smplCnt + + ;
2017-03-13 11:11:52 +08:00
} else {
2017-04-04 23:52:10 +08:00
firstpeak = false ;
if ( smplCnt > 0 ) {
if ( minPeak > smplCnt & & smplCnt > 7 ) minPeak = smplCnt ;
2017-03-13 11:11:52 +08:00
peakcnt + + ;
2017-04-04 23:52:10 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: minPeak: %d, smplCnt: %d, peakcnt: %d " , minPeak , smplCnt , peakcnt ) ;
smplCnt = 0 ;
2017-03-13 10:47:50 +08:00
}
}
}
2017-04-04 23:52:10 +08:00
if ( minPeak < 8 ) return 0 ;
2017-03-13 11:11:52 +08:00
bool errBitHigh = 0 ;
bool bitHigh = 0 ;
uint8_t ignoreCnt = 0 ;
uint8_t ignoreWindow = 4 ;
bool lastPeakHigh = 0 ;
int lastBit = 0 ;
size_t bestStart [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
peakcnt = 0 ;
//test each valid clock from smallest to greatest to see which lines up
2017-04-04 23:52:10 +08:00
for ( clkCnt = 0 ; clkCnt < 8 ; + + clkCnt ) {
2017-03-13 11:11:52 +08:00
//ignore clocks smaller than smallest peak
2017-04-04 23:52:10 +08:00
if ( clk [ clkCnt ] < minPeak - ( clk [ clkCnt ] / 4 ) ) continue ;
2017-03-13 11:11:52 +08:00
//try lining up the peaks by moving starting point (try first 256)
2017-04-04 23:52:10 +08:00
for ( ii = 20 ; ii < loopCnt ; + + ii ) {
if ( ( dest [ ii ] > = peak ) | | ( dest [ ii ] < = low ) ) {
2017-03-13 11:11:52 +08:00
peakcnt = 0 ;
bitHigh = false ;
ignoreCnt = 0 ;
lastBit = ii - clk [ clkCnt ] ;
//loop through to see if this start location works
for ( i = ii ; i < size - 20 ; + + i ) {
//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 ] ;
}
//else if not a clock bit and no peaks
2017-04-04 23:52:10 +08:00
} else if ( dest [ i ] < peak & & dest [ i ] > low ) {
if ( ignoreCnt = = 0 ) {
2017-03-13 11:11:52 +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 ;
}
2017-03-13 10:47:50 +08:00
}
}
}
2017-03-13 11:11:52 +08:00
int iii = 7 ;
uint8_t best = 0 ;
2017-04-04 23:52:10 +08:00
for ( iii = 7 ; iii > 0 ; iii - - ) {
2017-03-13 11:11:52 +08:00
if ( ( peaksdet [ iii ] > = ( peaksdet [ best ] - 1 ) ) & & ( peaksdet [ iii ] < = peaksdet [ best ] + 1 ) & & lowestTransition ) {
if ( clk [ iii ] > ( lowestTransition - ( clk [ iii ] / 8 ) ) & & clk [ iii ] < ( lowestTransition + ( clk [ iii ] / 8 ) ) ) {
best = iii ;
2017-03-13 10:47:50 +08:00
}
2017-04-04 23:52:10 +08:00
} else if ( peaksdet [ iii ] > peaksdet [ best ] ) {
2017-03-13 11:11:52 +08:00
best = iii ;
2017-03-13 10:47:50 +08:00
}
2017-04-04 23:52:10 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d " , clk [ iii ] , peaksdet [ iii ] , minPeak , clk [ best ] , lowestTransition ) ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
* clockStartIdx = bestStart [ best ] ;
return clk [ best ] ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +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
uint16_t countFC ( uint8_t * BitStream , size_t size , uint8_t fskAdj ) {
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 } ;
uint8_t fcLensFnd = 0 ;
uint8_t lastFCcnt = 0 ;
uint8_t fcCounter = 0 ;
size_t i ;
if ( size < 180 ) return 0 ;
2017-02-18 01:59:35 +08:00
2017-03-13 11:11:52 +08:00
// prime i to first up transition
for ( i = 160 ; i < size - 20 ; i + + )
if ( BitStream [ i ] > BitStream [ i - 1 ] & & BitStream [ i ] > = BitStream [ i + 1 ] )
break ;
2015-01-07 12:29:45 +08:00
2017-03-13 11:11:52 +08:00
for ( ; i < size - 20 ; i + + ) {
if ( BitStream [ i ] > BitStream [ i - 1 ] & & BitStream [ i ] > = BitStream [ i + 1 ] ) {
// new up transition
fcCounter + + ;
if ( fskAdj ) {
//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:
for ( int ii = 0 ; ii < 15 ; ii + + ) {
if ( fcLens [ ii ] = = fcCounter ) {
fcCnts [ ii ] + + ;
fcCounter = 0 ;
break ;
2015-10-15 13:09:49 +08:00
}
2015-01-07 12:29:45 +08:00
}
2017-03-13 11:11:52 +08:00
if ( fcCounter > 0 & & fcLensFnd < 15 ) {
//add new fc length
fcCnts [ fcLensFnd ] + + ;
fcLens [ fcLensFnd + + ] = fcCounter ;
}
fcCounter = 0 ;
} else {
// count sample
fcCounter + + ;
2015-01-07 12:29:45 +08:00
}
}
2017-03-13 11:11:52 +08:00
uint8_t best1 = 14 , best2 = 14 , best3 = 14 ;
uint16_t maxCnt1 = 0 ;
// go through fclens and find which ones are bigest 2
for ( i = 0 ; i < 15 ; i + + ) {
// get the 3 best FC values
if ( fcCnts [ i ] > maxCnt1 ) {
best3 = best2 ;
best2 = best1 ;
maxCnt1 = fcCnts [ i ] ;
best1 = i ;
} else if ( fcCnts [ i ] > fcCnts [ best2 ] ) {
best3 = best2 ;
best2 = i ;
} else if ( fcCnts [ i ] > fcCnts [ best3 ] ) {
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 ] ) ;
2017-04-04 23:52:10 +08:00
if ( fcLens [ i ] = = 0 ) break ;
2017-03-13 11:11:52 +08:00
}
if ( fcLens [ best1 ] = = 0 ) return 0 ;
uint8_t fcH = 0 , fcL = 0 ;
if ( fcLens [ best1 ] > fcLens [ best2 ] ) {
fcH = fcLens [ best1 ] ;
fcL = fcLens [ best2 ] ;
} else {
fcH = fcLens [ best2 ] ;
fcL = fcLens [ best1 ] ;
}
if ( ( size - 180 ) / fcH / 3 > fcCnts [ best1 ] + fcCnts [ best2 ] ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG countfc: fc is too large: %u > %u. Not psk or fsk " , ( size - 180 ) / fcH / 3 , fcCnts [ best1 ] + fcCnts [ best2 ] ) ;
return 0 ; //lots of waves not psk or fsk
}
// TODO: take top 3 answers and compare to known Field clocks to get top 2
uint16_t fcs = ( ( ( uint16_t ) fcH ) < < 8 ) | fcL ;
2017-04-04 23:52:10 +08:00
if ( fskAdj ) return fcs ;
return ( uint16_t ) fcLens [ best2 ] < < 8 | fcLens [ best1 ] ;
2014-12-29 09:33:32 +08:00
}
2017-03-13 11:11:52 +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
2017-04-04 23:52:10 +08:00
int DetectPSKClock ( uint8_t dest [ ] , size_t size , int clock , size_t * firstPhaseShift , uint8_t * curPhase , uint8_t * fc ) {
2017-03-13 11:11:52 +08:00
uint8_t clk [ ] = { 255 , 16 , 32 , 40 , 50 , 64 , 100 , 128 , 255 } ; //255 is not a valid clock
uint16_t loopCnt = 4096 ; //don't need to loop through entire array...
if ( size = = 0 ) return 0 ;
2017-04-04 23:52:10 +08:00
if ( size + 3 < loopCnt ) loopCnt = size - 20 ;
uint16_t fcs = countFC ( dest , size , 0 ) ;
* fc = fcs & 0xFF ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: FC: %d, FC2: %d " , * fc , fcs > > 8 ) ;
2017-04-08 05:41:22 +08:00
if ( ( fcs > > 8 ) = = 10 & & * fc = = 8 ) return 0 ;
if ( * fc ! = 2 & & * fc ! = 4 & & * fc ! = 8 ) return 0 ;
2017-03-13 11:11:52 +08:00
//if we already have a valid clock quit
size_t i = 1 ;
for ( ; i < 8 ; + + i )
if ( clk [ i ] = = clock ) return clock ;
size_t waveStart = 0 , waveEnd = 0 , firstFullWave = 0 , lastClkBit = 0 ;
2017-04-04 23:52:10 +08:00
uint8_t clkCnt , tol = 1 ;
uint16_t peakcnt = 0 , errCnt = 0 , waveLenCnt = 0 , fullWaveLen = 0 ;
2017-03-13 11:11:52 +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 } ;
2017-04-04 23:52:10 +08:00
//find start of modulating data in trace
i = findModStart ( dest , size , * fc ) ;
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 ;
2017-03-13 11:11:52 +08:00
}
2017-04-04 23:52:10 +08:00
2017-03-13 11:11:52 +08:00
* firstPhaseShift = firstFullWave ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: firstFullWave: %d, waveLen: %d " , firstFullWave , fullWaveLen ) ;
//test each valid clock from greatest to smallest to see which lines up
2017-04-04 23:52:10 +08:00
for ( clkCnt = 7 ; clkCnt > = 1 ; clkCnt - - ) {
tol = * fc / 2 ;
2017-03-13 11:11:52 +08:00
lastClkBit = firstFullWave ; //set end of wave as clock align
waveStart = 0 ;
errCnt = 0 ;
peakcnt = 0 ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: clk: %d, lastClkBit: %d " , clk [ clkCnt ] , lastClkBit ) ;
2015-01-07 12:29:45 +08:00
2017-03-13 11:11:52 +08:00
for ( i = firstFullWave + fullWaveLen - 1 ; i < loopCnt - 2 ; i + + ) {
//top edge of wave = start of new wave
if ( dest [ i ] < dest [ i + 1 ] & & dest [ i + 1 ] > = dest [ i + 2 ] ) {
if ( waveStart = = 0 ) {
waveStart = i + 1 ;
waveLenCnt = 0 ;
} else { //waveEnd
waveEnd = i + 1 ;
waveLenCnt = waveEnd - waveStart ;
2017-04-04 23:52:10 +08:00
if ( waveLenCnt > * fc ) {
2017-03-13 11:11:52 +08:00
//if this wave is a phase shift
2017-04-04 23:52:10 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d " , waveStart , waveLenCnt , lastClkBit + clk [ clkCnt ] - tol , i + 1 , * fc ) ;
2017-03-13 11:11:52 +08:00
if ( i + 1 > = lastClkBit + clk [ clkCnt ] - tol ) { //should be a clock bit
peakcnt + + ;
lastClkBit + = clk [ clkCnt ] ;
} else if ( i < lastClkBit + 8 ) {
//noise after a phase shift - ignore
} else { //phase shift before supposed to based on clock
errCnt + + ;
}
2017-04-04 23:52:10 +08:00
} else if ( i + 1 > lastClkBit + clk [ clkCnt ] + tol + * fc ) {
2017-03-13 11:11:52 +08:00
lastClkBit + = clk [ clkCnt ] ; //no phase shift but clock bit
}
waveStart = i + 1 ;
}
}
2015-03-23 03:28:48 +08:00
}
2017-03-13 11:11:52 +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 ;
for ( i = 7 ; i > = 1 ; i - - ) {
if ( peaksdet [ i ] > peaksdet [ best ] ) {
best = i ;
}
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d " , clk [ i ] , peaksdet [ i ] , bestErr [ i ] , clk [ best ] ) ;
2015-03-23 03:28:48 +08:00
}
2017-03-13 11:11:52 +08:00
return clk [ best ] ;
2014-12-29 09:33:32 +08:00
}
2015-11-18 13:10:11 +08:00
2017-03-13 11:11:52 +08:00
//by marshmellow
//detects the bit clock for FSK given the high and low Field Clocks
2017-04-11 22:34:43 +08:00
uint8_t detectFSKClk ( uint8_t * BitStream , size_t size , uint8_t fcHigh , uint8_t fcLow , int * firstClockEdge ) {
2017-03-13 11:11:52 +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 } ;
uint8_t rfLensFnd = 0 ;
uint8_t lastFCcnt = 0 ;
uint16_t fcCounter = 0 ;
uint16_t rfCounter = 0 ;
uint8_t firstBitFnd = 0 ;
size_t i ;
if ( size = = 0 ) return 0 ;
2017-03-12 08:21:53 +08:00
2017-03-13 11:11:52 +08:00
uint8_t fcTol = ( ( fcHigh * 100 - fcLow * 100 ) / 2 + 50 ) / 100 ; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2);
rfLensFnd = 0 ;
fcCounter = 0 ;
rfCounter = 0 ;
firstBitFnd = 0 ;
//PrintAndLog("DEBUG: fcTol: %d",fcTol);
// prime i to first peak / up transition
for ( i = 160 ; i < size - 20 ; i + + )
if ( BitStream [ i ] > BitStream [ i - 1 ] & & BitStream [ i ] > = BitStream [ i + 1 ] )
break ;
for ( ; i < size - 20 ; i + + ) {
fcCounter + + ;
rfCounter + + ;
if ( BitStream [ i ] < = BitStream [ i - 1 ] | | BitStream [ i ] < BitStream [ i + 1 ] )
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 ;
else if ( fcCounter < fcLow + fcTol )
fcCounter = fcLow ;
else //set it to the large fc
fcCounter = fcHigh ;
//look for bit clock (rf/xx)
if ( ( fcCounter < lastFCcnt | | fcCounter > lastFCcnt ) ) {
//not the same size as the last wave - start of new bit sequence
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 ) ) {
rfCnts [ ii ] + + ;
rfCounter = 0 ;
break ;
}
}
if ( rfCounter > 0 & & rfLensFnd < 15 ) {
//PrintAndLog("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter);
rfCnts [ rfLensFnd ] + + ;
rfLens [ rfLensFnd + + ] = rfCounter ;
}
} else {
* firstClockEdge = i ;
firstBitFnd + + ;
}
rfCounter = 0 ;
lastFCcnt = fcCounter ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
fcCounter = 0 ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
uint8_t rfHighest = 15 , rfHighest2 = 15 , rfHighest3 = 15 ;
for ( i = 0 ; i < 15 ; i + + ) {
//get highest 2 RF values (might need to get more values to compare or compare all?)
if ( rfCnts [ i ] > rfCnts [ rfHighest ] ) {
rfHighest3 = rfHighest2 ;
rfHighest2 = rfHighest ;
rfHighest = i ;
} else if ( rfCnts [ i ] > rfCnts [ rfHighest2 ] ) {
rfHighest3 = rfHighest2 ;
rfHighest2 = i ;
} else if ( rfCnts [ i ] > rfCnts [ rfHighest3 ] ) {
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
uint8_t tol1 = fcHigh + 1 ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d " , rfLens [ rfHighest ] , rfLens [ rfHighest2 ] , rfLens [ rfHighest3 ] ) ;
2014-12-29 09:33:32 +08:00
2017-03-13 11:11:52 +08:00
// 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 ii = 7 ;
for ( ; ii > = 2 ; ii - - ) {
if ( rfLens [ rfHighest ] % clk [ ii ] < tol1 | | rfLens [ rfHighest ] % clk [ ii ] > clk [ ii ] - tol1 ) {
if ( rfLens [ rfHighest2 ] % clk [ ii ] < tol1 | | rfLens [ rfHighest2 ] % clk [ ii ] > clk [ ii ] - tol1 ) {
if ( rfLens [ rfHighest3 ] % clk [ ii ] < tol1 | | rfLens [ rfHighest3 ] % clk [ ii ] > clk [ ii ] - tol1 ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG FSK: clk %d divides into the 3 most rf values within tolerance " , clk [ ii ] ) ;
break ;
}
}
2017-03-13 10:47:50 +08:00
}
2015-01-21 06:28:51 +08:00
}
2017-03-13 11:11:52 +08:00
if ( ii < 2 ) return 0 ; // oops we went too far
2014-12-29 09:33:32 +08:00
2017-03-13 11:11:52 +08:00
return clk [ ii ] ;
}
2015-11-10 12:09:26 +08:00
2017-03-13 11:11:52 +08:00
//**********************************************************************************************
//--------------------Modulation Demods &/or Decoding Section-----------------------------------
//**********************************************************************************************
2015-01-19 07:13:32 +08:00
2017-03-13 11:11:52 +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...
2017-03-15 05:08:58 +08:00
bool findST ( int * stStopLoc , int * stStartIdx , int lowToLowWaveLen [ ] , int highToLowWaveLen [ ] , int clk , int tol , int buffSize , size_t * i ) {
2017-04-05 05:22:21 +08:00
if ( buffSize < * i + 4 ) return false ;
2017-03-14 01:27:38 +08:00
for ( ; * i < buffSize - 4 ; * i + = 1 ) {
* 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...
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
* stStopLoc = * i + 3 ;
2017-03-13 11:11:52 +08:00
return true ;
2017-03-13 10:47:50 +08:00
}
}
}
}
}
2017-03-13 11:11:52 +08:00
return false ;
2016-03-06 12:45:28 +08:00
}
2017-03-13 11:11:52 +08:00
//by marshmellow
//attempt to identify a Sequence Terminator in ASK modulated raw wave
2017-04-11 22:34:43 +08:00
bool DetectST ( uint8_t buffer [ ] , size_t * size , int * foundclock , size_t * ststart , size_t * stend ) {
2017-03-13 11:11:52 +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 ;
2017-04-04 23:52:10 +08:00
int j = 0 , high , low , skip = 0 , start = 0 , end = 0 , minClk = 255 ;
2017-03-15 05:08:58 +08:00
size_t i = 0 ;
2017-03-13 11:11:52 +08:00
//probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow]
2017-03-15 05:08:58 +08:00
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...
2017-03-15 04:20:15 +08:00
//size_t testsize = (bufsize < 512) ? bufsize : 512;
2017-03-13 11:11:52 +08:00
int phaseoff = 0 ;
high = low = 128 ;
memset ( tmpbuff , 0 , sizeof ( tmpbuff ) ) ;
2017-03-14 01:27:38 +08:00
memset ( waveLen , 0 , sizeof ( waveLen ) ) ;
2017-03-13 11:11:52 +08:00
2017-03-15 04:20:15 +08:00
if ( ! loadWaveCounters ( buffer , bufsize , tmpbuff , waveLen , & j , & skip , & minClk , & high , & low ) ) return false ;
2017-03-13 11:11:52 +08:00
// set clock - might be able to get this externally and remove this work...
2017-03-15 05:08:58 +08:00
clk = getClosestClock ( minClk ) ;
// clock not found - ERROR
if ( clk = = 0 ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: clock not found - quitting " ) ;
return false ;
}
2017-03-13 11:11:52 +08:00
* foundclock = clk ;
2017-03-15 05:08:58 +08:00
tol = clk / 8 ;
2017-03-14 01:27:38 +08:00
if ( ! findST ( & start , & skip , tmpbuff , waveLen , clk , tol , j , & i ) ) {
2017-03-13 11:11:52 +08:00
// first ST not found - ERROR
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: first STT not found - quitting " ) ;
return false ;
} else {
2017-03-14 01:27:38 +08:00
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: first STT found at wave: %i, skip: %i, j=%i " , start , skip , j ) ;
2015-04-07 11:17:30 +08:00
}
2017-03-13 11:11:52 +08:00
if ( waveLen [ i + 2 ] > clk * 1 + tol )
phaseoff = 0 ;
else
phaseoff = clk / 2 ;
// skip over the remainder of ST
skip + = clk * 7 / 2 ; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point
2015-03-27 12:02:30 +08:00
2017-03-13 11:11:52 +08:00
// now do it again to find the end
int dummy1 = 0 ;
end = skip ;
2017-03-14 01:27:38 +08:00
i + = 3 ;
if ( ! findST ( & dummy1 , & end , tmpbuff , waveLen , clk , tol , j , & i ) ) {
2017-03-13 11:11:52 +08:00
//didn't find second ST - ERROR
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: second STT not found - quitting " ) ;
return false ;
}
end - = phaseoff ;
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 ) ;
//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
if ( clk - ( datalen % clk ) < = clk / 8 ) {
// padd the amount off - could be problematic... but shouldn't happen often
datalen + = clk - ( datalen % clk ) ;
} else if ( ( datalen % clk ) < = clk / 8 ) {
// padd the amount off - could be problematic... but shouldn't happen often
datalen - = datalen % clk ;
} else {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting " , datalen , clk , datalen % clk ) ;
return false ;
}
// if datalen is less than one t55xx block - ERROR
if ( datalen / clk < 8 * 4 ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: datalen is less than 1 full t55xx block - quitting " ) ;
return false ;
}
size_t dataloc = start ;
2017-04-04 23:52:10 +08:00
if ( buffer [ dataloc - ( clk * 4 ) - ( clk / 4 ) ] < = low & & buffer [ dataloc ] < = low & & buffer [ dataloc - ( clk * 4 ) ] > = high ) {
2017-03-13 11:11:52 +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
2017-04-04 23:52:10 +08:00
for ( i = 0 ; i < = ( clk / 4 ) ; + + i ) {
2017-03-13 11:11:52 +08:00
if ( buffer [ dataloc - ( clk * 4 ) - i ] < = low ) {
dataloc - = i ;
break ;
2015-03-27 12:02:30 +08:00
}
2015-03-26 02:24:36 +08:00
}
}
2017-03-13 11:11:52 +08:00
size_t newloc = 0 ;
i = 0 ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: Starting STT trim - start: %d, datalen: %d " , dataloc , datalen ) ;
bool firstrun = true ;
// warning - overwriting buffer given with raw wave data with ST removed...
while ( dataloc < bufsize - ( clk / 2 ) ) {
//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)
2017-04-04 23:52:10 +08:00
if ( buffer [ dataloc ] < high & & buffer [ dataloc ] > low & & buffer [ dataloc + clk / 4 ] < high & & buffer [ dataloc + clk / 4 ] > low ) {
2017-03-13 11:11:52 +08:00
for ( i = 0 ; i < clk / 2 - tol ; + + i ) {
buffer [ dataloc + i ] = high + 5 ;
}
2017-04-04 23:52:10 +08:00
} //test for small spike outlier (high between two lows) in the case of very strong waves
if ( buffer [ dataloc ] > low & & buffer [ dataloc + clk / 4 ] < = low ) {
for ( i = 0 ; i < clk / 4 ; + + i ) {
buffer [ dataloc + i ] = buffer [ dataloc + clk / 4 ] ;
}
2017-03-13 11:11:52 +08:00
}
if ( firstrun ) {
* stend = dataloc ;
* ststart = dataloc - ( clk * 4 ) ;
firstrun = false ;
}
for ( i = 0 ; i < datalen ; + + i ) {
if ( i + newloc < bufsize ) {
if ( i + newloc < dataloc )
buffer [ i + newloc ] = buffer [ dataloc ] ;
dataloc + + ;
2015-03-26 02:24:36 +08:00
}
}
2017-03-13 11:11:52 +08:00
newloc + = i ;
//skip next ST - we just assume it will be there from now on...
if ( g_debugMode = = 2 ) prnt ( " DEBUG STT: skipping STT at %d to %d " , dataloc , dataloc + ( clk * 4 ) ) ;
dataloc + = clk * 4 ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
* size = newloc ;
return true ;
}
2015-01-07 12:29:45 +08:00
2017-03-14 01:27:38 +08:00
//by marshmellow
2017-03-15 01:16:30 +08:00
//take 11 10 01 11 00 and make 01100 ... miller decoding
2017-03-14 01:27:38 +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!
2017-03-15 01:16:30 +08:00
int millerRawDecode ( uint8_t * BitStream , size_t * size , int invert ) {
2017-03-14 01:27:38 +08:00
if ( * size < 16 ) return - 1 ;
2017-03-15 01:16:30 +08:00
uint16_t MaxBits = 512 , errCnt = 0 ;
size_t i , bitCnt = 0 ;
uint8_t alignCnt = 0 , curBit = BitStream [ 0 ] , alignedIdx = 0 ;
uint8_t halfClkErr = 0 ;
2017-03-14 01:27:38 +08:00
//find alignment, needs 4 1s or 0s to properly align
2017-03-15 01:16:30 +08:00
for ( i = 1 ; i < * size - 1 ; i + + ) {
2017-03-14 01:27:38 +08:00
alignCnt = ( BitStream [ i ] = = curBit ) ? alignCnt + 1 : 0 ;
curBit = BitStream [ 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 bitstream is not miller or your data does not have a 101 in it " ) ;
return - 1 ;
}
2017-03-15 01:16:30 +08:00
alignedIdx = ( i - 1 ) % 2 ;
for ( i = alignedIdx ; i < * size - 3 ; i + = 2 ) {
halfClkErr = ( uint8_t ) ( ( halfClkErr < < 1 | BitStream [ i ] ) & 0xFF ) ;
if ( ( halfClkErr & 0x7 ) = = 5 | | ( halfClkErr & 0x7 ) = = 2 | | ( i > 2 & & ( halfClkErr & 0x7 ) = = 0 ) | | ( halfClkErr & 0x1F ) = = 0x1F ) {
errCnt + + ;
BitStream [ bitCnt + + ] = 7 ;
continue ;
}
BitStream [ bitCnt + + ] = BitStream [ i ] ^ BitStream [ i + 1 ] ^ invert ;
2017-03-14 01:27:38 +08:00
2017-03-15 01:16:30 +08:00
if ( bitCnt > MaxBits ) break ;
}
* size = bitCnt ;
return errCnt ;
}
2017-03-14 01:27:38 +08:00
2017-03-13 11:11:52 +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
2017-04-13 05:55:31 +08:00
int BiphaseRawDecode ( uint8_t * BitStream , size_t * size , int * offset , int invert ) {
2017-03-13 11:11:52 +08:00
uint16_t bitnum = 0 ;
uint16_t errCnt = 0 ;
2017-04-13 05:55:31 +08:00
size_t i = * offset ;
2017-03-13 11:11:52 +08:00
uint16_t MaxBits = 512 ;
//if not enough samples - error
if ( * size < 51 ) return - 1 ;
//check for phase change faults - skip one sample if faulty
uint8_t offsetA = 1 , offsetB = 1 ;
for ( ; i < 48 ; i + = 2 ) {
if ( BitStream [ i + 1 ] = = BitStream [ i + 2 ] ) offsetA = 0 ;
if ( BitStream [ i + 2 ] = = BitStream [ i + 3 ] ) offsetB = 0 ;
}
2017-04-13 05:55:31 +08:00
if ( ! offsetA & & offsetB ) * offset + = 1 ;
for ( i = * offset ; i < * size - 3 ; i + = 2 ) {
2017-03-13 11:11:52 +08:00
//check for phase error
if ( BitStream [ i + 1 ] = = BitStream [ i + 2 ] ) {
BitStream [ bitnum + + ] = 7 ;
errCnt + + ;
}
if ( ( BitStream [ i ] = = 1 & & BitStream [ i + 1 ] = = 0 ) | | ( BitStream [ i ] = = 0 & & BitStream [ i + 1 ] = = 1 ) ) {
BitStream [ bitnum + + ] = 1 ^ invert ;
} else if ( ( BitStream [ i ] = = 0 & & BitStream [ i + 1 ] = = 0 ) | | ( BitStream [ i ] = = 1 & & BitStream [ i + 1 ] = = 1 ) ) {
BitStream [ bitnum + + ] = invert ;
} else {
BitStream [ bitnum + + ] = 7 ;
errCnt + + ;
2015-11-17 07:49:20 +08:00
}
2017-03-13 11:11:52 +08:00
if ( bitnum > MaxBits ) break ;
2015-11-17 07:49:20 +08:00
}
2017-03-13 11:11:52 +08:00
* size = bitnum ;
return errCnt ;
2015-11-17 07:49:20 +08:00
}
2015-02-07 03:36:25 +08:00
//by marshmellow
2017-03-13 11:11:52 +08:00
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
int manrawdecode ( uint8_t * BitStream , size_t * size , uint8_t invert , uint8_t * alignPos ) {
uint16_t bitnum = 0 , MaxBits = 512 , errCnt = 0 ;
size_t i , ii ;
uint16_t bestErr = 1000 , bestRun = 0 ;
if ( * size < 16 ) return - 1 ;
//find correct start position [alignment]
for ( ii = 0 ; ii < 2 ; + + ii ) {
for ( i = ii ; i < * size - 3 ; i + = 2 )
if ( BitStream [ i ] = = BitStream [ i + 1 ] )
errCnt + + ;
if ( bestErr > errCnt ) {
bestErr = errCnt ;
bestRun = ii ;
}
errCnt = 0 ;
}
* alignPos = bestRun ;
//decode
for ( i = bestRun ; i < * size - 3 ; i + = 2 ) {
if ( BitStream [ i ] = = 1 & & ( BitStream [ i + 1 ] = = 0 ) ) {
BitStream [ bitnum + + ] = invert ;
} else if ( ( BitStream [ i ] = = 0 ) & & BitStream [ i + 1 ] = = 1 ) {
BitStream [ bitnum + + ] = invert ^ 1 ;
2015-03-26 02:24:36 +08:00
} else {
2017-03-13 11:11:52 +08:00
BitStream [ bitnum + + ] = 7 ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
if ( bitnum > MaxBits ) break ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
* size = bitnum ;
return bestErr ;
}
//by marshmellow
//demodulates strong heavily clipped samples
int cleanAskRawDemod ( uint8_t * BinStream , size_t * size , int clk , int invert , int high , int low , int * startIdx )
{
* startIdx = 0 ;
size_t bitCnt = 0 , smplCnt = 1 , errCnt = 0 ;
bool waveHigh = ( BinStream [ 0 ] > = high ) ;
for ( size_t i = 1 ; i < * size ; i + + ) {
if ( BinStream [ i ] > = high & & waveHigh ) {
smplCnt + + ;
} else if ( BinStream [ i ] < = low & & ! waveHigh ) {
smplCnt + + ;
} else { //transition
if ( ( BinStream [ i ] > = high & & ! waveHigh ) | | ( BinStream [ i ] < = low & & waveHigh ) ) {
if ( smplCnt > clk - ( clk / 4 ) - 1 ) { //full clock
if ( smplCnt > clk + ( clk / 4 ) + 1 ) { //too many samples
errCnt + + ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: Modulation Error at: %u " , i ) ;
BinStream [ bitCnt + + ] = 7 ;
} else if ( waveHigh ) {
BinStream [ bitCnt + + ] = invert ;
BinStream [ bitCnt + + ] = invert ;
} else if ( ! waveHigh ) {
BinStream [ bitCnt + + ] = invert ^ 1 ;
BinStream [ bitCnt + + ] = invert ^ 1 ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
if ( * startIdx = = 0 ) * startIdx = i - clk ;
waveHigh = ! waveHigh ;
smplCnt = 0 ;
} else if ( smplCnt > ( clk / 2 ) - ( clk / 4 ) - 1 ) { //half clock
if ( waveHigh ) {
BinStream [ bitCnt + + ] = invert ;
} else if ( ! waveHigh ) {
BinStream [ bitCnt + + ] = invert ^ 1 ;
}
if ( * startIdx = = 0 ) * startIdx = i - ( clk / 2 ) ;
waveHigh = ! waveHigh ;
smplCnt = 0 ;
} else {
smplCnt + + ;
//transition bit oops
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
} else { //haven't hit new high or new low yet
smplCnt + + ;
2015-11-17 07:49:20 +08:00
}
2015-03-26 02:24:36 +08:00
}
}
2017-03-13 11:11:52 +08:00
* size = bitCnt ;
return errCnt ;
2017-03-12 08:21:53 +08:00
}
2017-03-13 10:47:50 +08:00
//by marshmellow
2017-03-13 11:11:52 +08:00
//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester
int askdemod_ext ( uint8_t * BinStream , size_t * size , int * clk , int * invert , int maxErr , uint8_t amp , uint8_t askType , int * startIdx ) {
if ( * size = = 0 ) return - 1 ;
int start = DetectASKClock ( BinStream , * size , clk , maxErr ) ; //clock default
if ( * clk = = 0 | | start < 0 ) return - 3 ;
if ( * invert ! = 1 ) * invert = 0 ;
if ( amp = = 1 ) askAmp ( BinStream , * size ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: clk %d, beststart %d, amp %d " , * clk , start , amp ) ;
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +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 ) ;
uint8_t initLoopMax = 255 ;
if ( initLoopMax > * size ) initLoopMax = * size ;
// Detect high and lows
//25% clip in case highs and lows aren't clipped [marshmellow]
int high , low ;
if ( getHiLo ( BinStream , initLoopMax , & high , & low , 75 , 75 ) < 1 )
return - 2 ; //just noise
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
size_t errCnt = 0 ;
// if clean clipped waves detected run alternate demod
if ( DetectCleanAskWave ( BinStream , * size , high , low ) ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: Clean Wave Detected - using clean wave demod " ) ;
errCnt = cleanAskRawDemod ( BinStream , size , * clk , * invert , high , low , startIdx ) ;
if ( askType ) { //askman
uint8_t alignPos = 0 ;
errCnt = manrawdecode ( BinStream , size , 0 , & alignPos ) ;
* startIdx + = * clk / 2 * alignPos ;
if ( g_debugMode ) prnt ( " DEBUG ASK CLEAN: startIdx %i, alignPos %u " , * startIdx , alignPos ) ;
return errCnt ;
} else { //askraw
return errCnt ;
}
}
if ( g_debugMode ) prnt ( " DEBUG ASK WEAK: startIdx %i " , * startIdx ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: Weak Wave Detected - using weak wave demod " ) ;
int lastBit ; //set first clock check - can go negative
size_t i , bitnum = 0 ; //output counter
uint8_t midBit = 0 ;
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
lastBit = start - * clk ;
for ( i = start ; i < * size ; + + i ) {
if ( i - lastBit > = * clk - tol ) {
if ( BinStream [ i ] > = high ) {
BinStream [ bitnum + + ] = * invert ;
} else if ( BinStream [ i ] < = low ) {
BinStream [ bitnum + + ] = * invert ^ 1 ;
} else if ( i - lastBit > = * clk + tol ) {
if ( bitnum > 0 ) {
if ( g_debugMode = = 2 ) prnt ( " DEBUG ASK: Modulation Error at: %u " , i ) ;
BinStream [ bitnum + + ] = 7 ;
errCnt + + ;
}
} else { //in tolerance - looking for peak
continue ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
midBit = 0 ;
lastBit + = * clk ;
} else if ( i - lastBit > = ( * clk / 2 - tol ) & & ! midBit & & ! askType ) {
if ( BinStream [ i ] > = high ) {
BinStream [ bitnum + + ] = * invert ;
} else if ( BinStream [ i ] < = low ) {
BinStream [ bitnum + + ] = * invert ^ 1 ;
} else if ( i - lastBit > = * clk / 2 + tol ) {
BinStream [ bitnum ] = BinStream [ bitnum - 1 ] ;
bitnum + + ;
} else { //in tolerance - looking for peak
continue ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
midBit = 1 ;
2015-01-27 06:23:19 +08:00
}
2017-03-13 11:11:52 +08:00
if ( bitnum > = MaxBits ) break ;
2015-01-27 06:23:19 +08:00
}
2017-03-13 11:11:52 +08:00
* size = bitnum ;
return errCnt ;
}
int askdemod ( uint8_t * BinStream , size_t * size , int * clk , int * invert , int maxErr , uint8_t amp , uint8_t askType ) {
int start = 0 ;
return askdemod_ext ( BinStream , size , clk , invert , maxErr , amp , askType , & start ) ;
}
// 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
2017-03-15 22:53:32 +08:00
int nrzRawDemod ( uint8_t * dest , size_t * size , int * clk , int * invert , int * startIdx ) {
2017-03-13 11:11:52 +08:00
if ( justNoise ( dest , * size ) ) return - 1 ;
2017-03-15 22:53:32 +08:00
size_t clkStartIdx = 0 ;
* clk = DetectNRZClock ( dest , * size , * clk , & clkStartIdx ) ;
2017-03-13 11:11:52 +08:00
if ( * clk = = 0 ) return - 2 ;
size_t i , gLen = 4096 ;
if ( gLen > * size ) gLen = * size - 20 ;
int high , low ;
if ( getHiLo ( dest , gLen , & high , & low , 75 , 75 ) < 1 ) return - 3 ; //25% fuzz on high 25% fuzz on low
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
uint8_t bit = 0 ;
//convert wave samples to 1's and 0's
for ( i = 20 ; i < * size - 20 ; i + + ) {
if ( dest [ i ] > = high ) bit = 1 ;
if ( dest [ i ] < = low ) bit = 0 ;
dest [ i ] = bit ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
//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 ;
for ( i = 21 ; i < * size - 20 ; i + + ) {
//if transition detected or large number of same bits - store the passed bits
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 ;
if ( lastBit = = 0 ) {
* startIdx = i - ( numBits * * clk ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG NRZ: startIdx %i " , * startIdx ) ;
}
lastBit = i - 1 ;
}
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
* size = numBits ;
return 0 ;
}
2015-02-22 11:54:52 +08:00
2017-03-13 11:11:52 +08:00
//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
size_t fsk_wave_demod ( uint8_t * dest , size_t size , uint8_t fchigh , uint8_t fclow , int * startIdx ) {
size_t last_transition = 0 ;
size_t idx = 1 ;
if ( fchigh = = 0 ) fchigh = 10 ;
if ( fclow = = 0 ) fclow = 8 ;
//set the threshold close to 0 (graph) or 128 std to avoid static
size_t preLastSample = 0 ;
size_t LastSample = 0 ;
size_t currSample = 0 ;
if ( size < 1024 ) return 0 ; // not enough samples
2015-01-07 12:29:45 +08:00
2017-03-13 11:11:52 +08:00
//find start of modulating data in trace
2017-03-15 22:53:32 +08:00
idx = findModStart ( dest , size , fchigh ) ;
2017-03-13 11:11:52 +08:00
// Need to threshold first sample
2017-03-15 22:53:32 +08:00
if ( dest [ idx ] < FSK_PSK_THRESHOLD ) dest [ 0 ] = 0 ;
2017-03-13 11:11:52 +08:00
else dest [ 0 ] = 1 ;
last_transition = idx ;
idx + + ;
size_t numBits = 0 ;
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
// (could also be fc/5 && fc/7 for fsk1 = 4-9)
for ( ; idx < size ; idx + + ) {
// threshold current value
2017-03-15 22:53:32 +08:00
if ( dest [ idx ] < FSK_PSK_THRESHOLD ) dest [ idx ] = 0 ;
2017-03-13 11:11:52 +08:00
else dest [ idx ] = 1 ;
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
// Check for 0->1 transition
if ( dest [ idx - 1 ] < dest [ idx ] ) {
preLastSample = LastSample ;
LastSample = currSample ;
currSample = idx - last_transition ;
if ( currSample < ( fclow - 2 ) ) { //0-5 = garbage noise (or 0-3)
//do nothing with extra garbage
} else if ( currSample < ( fchigh - 1 ) ) { //6-8 = 8 sample waves (or 3-6 = 5)
//correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
if ( numBits > 1 & & LastSample > ( fchigh - 2 ) & & ( preLastSample < ( fchigh - 1 ) ) ) {
dest [ numBits - 1 ] = 1 ;
}
dest [ numBits + + ] = 1 ;
if ( numBits > 0 & & * startIdx = = 0 ) * startIdx = idx - fclow ;
} else if ( currSample > ( fchigh + 1 ) & & numBits < 3 ) { //12 + and first two bit = unusable garbage
//do nothing with beginning garbage and reset.. should be rare..
numBits = 0 ;
} 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 ;
if ( numBits > 0 & & * startIdx = = 0 ) * startIdx = idx - fclow ;
} else { //9+ = 10 sample waves (or 6+ = 7)
dest [ numBits + + ] = 0 ;
if ( numBits > 0 & & * startIdx = = 0 ) * startIdx = idx - fchigh ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
last_transition = idx ;
2017-03-13 10:47:50 +08:00
}
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
return numBits ; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
}
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
//translate 11111100000 to 10
//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
size_t aggregate_bits ( uint8_t * dest , size_t size , uint8_t rfLen , uint8_t invert , uint8_t fchigh , uint8_t fclow , int * startIdx ) {
uint8_t lastval = dest [ 0 ] ;
size_t idx = 0 ;
size_t numBits = 0 ;
uint32_t n = 1 ;
for ( idx = 1 ; idx < size ; idx + + ) {
n + + ;
if ( dest [ idx ] = = lastval ) continue ; //skip until we hit a transition
//find out how many bits (n) we collected (use 1/2 clk tolerance)
//if lastval was 1, we have a 1->0 crossing
if ( dest [ idx - 1 ] = = 1 ) {
n = ( n * fclow + rfLen / 2 ) / rfLen ;
} else { // 0->1 crossing
n = ( n * fchigh + rfLen / 2 ) / rfLen ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
if ( n = = 0 ) n = 1 ;
//first transition - save startidx
if ( numBits = = 0 ) {
if ( lastval = = 1 ) { //high to low
* startIdx + = ( fclow * idx ) - ( n * rfLen ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG FSK: startIdx %i, fclow*idx %i, n*rflen %u " , * startIdx , fclow * ( idx ) , n * rfLen ) ;
} else {
* startIdx + = ( fchigh * idx ) - ( n * rfLen ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG FSK: startIdx %i, fchigh*idx %i, n*rflen %u " , * startIdx , fchigh * ( idx ) , n * rfLen ) ;
}
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
//add to our destination the bits we collected
memset ( dest + numBits , dest [ idx - 1 ] ^ invert , n ) ;
numBits + = n ;
n = 0 ;
lastval = dest [ idx ] ;
} //end for
// if valid extra bits at the end were all the same frequency - add them in
if ( n > rfLen / fchigh ) {
if ( dest [ idx - 2 ] = = 1 ) {
n = ( n * fclow + rfLen / 2 ) / rfLen ;
} else {
n = ( n * fchigh + rfLen / 2 ) / rfLen ;
2017-03-13 10:47:50 +08:00
}
2017-03-13 11:11:52 +08:00
memset ( dest + numBits , dest [ idx - 1 ] ^ invert , n ) ;
numBits + = n ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
return numBits ;
2015-01-07 12:29:45 +08:00
}
2017-03-13 10:47:50 +08:00
2017-03-13 11:11:52 +08:00
//by marshmellow (from holiman's base)
// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
2017-04-16 04:18:54 +08:00
int fskdemod ( uint8_t * dest , size_t size , uint8_t rfLen , uint8_t invert , uint8_t fchigh , uint8_t fclow , int * startIdx ) {
2017-04-13 22:33:18 +08:00
if ( justNoise ( dest , size ) ) return 0 ;
2017-03-13 11:11:52 +08:00
// FSK demodulator
size = fsk_wave_demod ( dest , size , fchigh , fclow , startIdx ) ;
size = aggregate_bits ( dest , size , rfLen , invert , fchigh , fclow , startIdx ) ;
return size ;
2017-03-07 21:48:16 +08:00
}
2017-03-13 11:11:52 +08:00
// by marshmellow
// convert psk1 demod to psk2 demod
// only transition waves are 1s
void psk1TOpsk2 ( uint8_t * BitStream , size_t size ) {
size_t i = 1 ;
uint8_t lastBit = BitStream [ 0 ] ;
for ( ; i < size ; i + + ) {
if ( BitStream [ i ] = = 7 ) {
//ignore errors
} else if ( lastBit ! = BitStream [ i ] ) {
lastBit = BitStream [ i ] ;
BitStream [ i ] = 1 ;
} else {
BitStream [ i ] = 0 ;
}
}
return ;
}
2015-03-26 02:24:36 +08:00
2017-03-13 11:11:52 +08:00
// by marshmellow
// convert psk2 demod to psk1 demod
// from only transition waves are 1s to phase shifts change bit
void psk2TOpsk1 ( uint8_t * BitStream , size_t size ) {
uint8_t phase = 0 ;
for ( size_t i = 0 ; i < size ; i + + ) {
if ( BitStream [ i ] = = 1 ) {
phase ^ = 1 ;
}
BitStream [ i ] = phase ;
}
return ;
}
2015-03-27 12:02:30 +08:00
2017-03-13 11:11:52 +08:00
//by marshmellow - demodulate PSK1 wave
//uses wave lengths (# Samples)
int pskRawDemod_ext ( uint8_t dest [ ] , size_t * size , int * clock , int * invert , int * startIdx ) {
2017-03-15 22:53:32 +08:00
if ( * size < 170 ) return - 1 ;
2015-03-27 12:02:30 +08:00
2017-03-13 11:11:52 +08:00
uint8_t curPhase = * invert ;
2017-04-04 23:52:10 +08:00
uint8_t fc = 0 ;
2017-03-15 22:53:32 +08:00
size_t i = 0 , numBits = 0 , waveStart = 1 , waveEnd = 0 , firstFullWave = 0 , lastClkBit = 0 ;
2017-04-04 23:52:10 +08:00
uint16_t fullWaveLen = 0 , waveLenCnt = 0 , avgWaveVal ;
2017-03-15 22:53:32 +08:00
uint16_t errCnt = 0 , errCnt2 = 0 ;
2017-04-04 23:52:10 +08:00
* clock = DetectPSKClock ( dest , * size , * clock , & firstFullWave , & curPhase , & fc ) ;
2017-04-08 05:41:22 +08:00
if ( * clock < = 0 ) return - 1 ;
2017-04-04 23:52:10 +08:00
//if clock detect found firstfullwave...
uint16_t tol = fc / 2 ;
2017-03-13 11:11:52 +08:00
if ( firstFullWave = = 0 ) {
2017-04-04 23:52:10 +08:00
//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 {
memset ( dest , curPhase ^ 1 , firstFullWave / * clock ) ;
}
2017-03-13 11:11:52 +08:00
} else {
memset ( dest , curPhase ^ 1 , firstFullWave / * clock ) ;
}
//advance bits
numBits + = ( firstFullWave / * clock ) ;
* startIdx = firstFullWave - ( * clock * numBits ) + 2 ;
//set start of wave as clock align
lastClkBit = firstFullWave ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i " , firstFullWave , fullWaveLen , * startIdx ) ;
if ( g_debugMode = = 2 ) prnt ( " DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u " , * clock , lastClkBit , ( unsigned int ) fc ) ;
waveStart = 0 ;
dest [ numBits + + ] = curPhase ; //set first read bit
2017-04-04 23:52:10 +08:00
for ( i = firstFullWave + fullWaveLen - 1 ; i < * size - 3 ; i + + ) {
2017-03-13 11:11:52 +08:00
//top edge of wave = start of new wave
2017-04-04 23:52:10 +08:00
if ( dest [ i ] + fc < dest [ i + 1 ] & & dest [ i + 1 ] > = dest [ i + 2 ] ) {
2017-03-13 11:11:52 +08:00
if ( waveStart = = 0 ) {
waveStart = i + 1 ;
waveLenCnt = 0 ;
avgWaveVal = dest [ i + 1 ] ;
} else { //waveEnd
waveEnd = i + 1 ;
waveLenCnt = waveEnd - waveStart ;
2017-04-04 23:52:10 +08:00
if ( waveLenCnt > fc ) {
2017-03-13 11:11:52 +08:00
//this wave is a phase shift
//PrintAndLog("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc);
2017-04-04 23:52:10 +08:00
if ( i + 1 > = lastClkBit + * clock - tol ) { //should be a clock bit
2017-03-13 11:11:52 +08:00
curPhase ^ = 1 ;
dest [ numBits + + ] = curPhase ;
lastClkBit + = * clock ;
2017-04-04 23:52:10 +08:00
} else if ( i < lastClkBit + 10 + fc ) {
2017-03-13 11:11:52 +08:00
//noise after a phase shift - ignore
} else { //phase shift before supposed to based on clock
errCnt + + ;
dest [ numBits + + ] = 7 ;
}
2017-04-04 23:52:10 +08:00
} else if ( i + 1 > lastClkBit + * clock + tol + fc ) {
2017-03-13 11:11:52 +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 ;
2017-04-04 23:52:10 +08:00
avgWaveVal + = dest [ i + 1 ] ;
continue ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
avgWaveVal = 0 ;
waveStart = i + 1 ;
2015-03-26 02:24:36 +08:00
}
}
2017-03-13 11:11:52 +08:00
avgWaveVal + = dest [ i + 1 ] ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 11:11:52 +08:00
* size = numBits ;
return errCnt ;
2015-01-23 03:24:03 +08:00
}
2015-01-19 07:13:32 +08:00
2017-03-13 11:11:52 +08:00
int pskRawDemod ( uint8_t dest [ ] , size_t * size , int * clock , int * invert ) {
int startIdx = 0 ;
return pskRawDemod_ext ( dest , size , clock , invert , & startIdx ) ;
2017-03-12 08:21:53 +08:00
}
2017-03-13 11:11:52 +08:00
//**********************************************************************************************
//-----------------Tag format detection section-------------------------------------------------
//**********************************************************************************************
2017-03-13 10:47:50 +08:00
// by marshmellow
// FSK Demod then try to locate an AWID ID
2017-04-16 04:18:54 +08:00
int AWIDdemodFSK ( uint8_t * dest , size_t * size , int * waveStartIdx ) {
2017-03-13 10:47:50 +08:00
//make sure buffer has enough data
if ( * size < 96 * 50 ) return - 1 ;
// FSK demodulator
2017-04-16 04:18:54 +08:00
* size = fskdemod ( dest , * size , 50 , 1 , 10 , 8 , waveStartIdx ) ; // fsk2a RF/50
2017-03-13 10:47:50 +08:00
if ( * size < 96 ) return - 3 ; //did we get a good demod?
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
size_t startIdx = 0 ;
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 4 ; //preamble not found
if ( * size ! = 96 ) return - 5 ;
return ( int ) startIdx ;
}
2015-01-23 03:24:03 +08:00
//by marshmellow
2017-03-13 10:47:50 +08:00
//takes 1s and 0s and searches for EM410x format - output EM ID
uint8_t Em410xDecode ( uint8_t * BitStream , size_t * size , size_t * startIdx , uint32_t * hi , uint64_t * lo )
2015-01-23 03:24:03 +08:00
{
2017-03-13 10:47:50 +08:00
//sanity checks
if ( * size < 64 ) return 0 ;
if ( BitStream [ 1 ] > 1 ) return 0 ; //allow only 1s and 0s
2015-03-26 02:24:36 +08:00
2017-03-13 10:47:50 +08:00
// 111111111 bit pattern represent start of frame
// include 0 in front to help get start pos
uint8_t preamble [ ] = { 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 } ;
uint8_t errChk = 0 ;
uint8_t FmtLen = 10 ; // sets of 4 bits = end data
* startIdx = 0 ;
errChk = preambleSearch ( BitStream , preamble , sizeof ( preamble ) , size , startIdx ) ;
if ( errChk = = 0 | | ( * size ! = 64 & & * size ! = 128 ) ) return 0 ;
if ( * size = = 128 ) FmtLen = 22 ; // 22 sets of 4 bits
2015-03-26 02:24:36 +08:00
2017-03-13 10:47:50 +08:00
//skip last 4bit parity row for simplicity
* size = removeParity ( BitStream , * startIdx + sizeof ( preamble ) , 5 , 0 , FmtLen * 5 ) ;
if ( * size = = 40 ) { // std em410x format
* hi = 0 ;
* lo = ( ( uint64_t ) ( bytebits_to_byte ( BitStream , 8 ) ) < < 32 ) | ( bytebits_to_byte ( BitStream + 8 , 32 ) ) ;
} else if ( * size = = 88 ) { // long em format
* hi = ( bytebits_to_byte ( BitStream , 24 ) ) ;
* lo = ( ( uint64_t ) ( bytebits_to_byte ( BitStream + 24 , 32 ) ) < < 32 ) | ( bytebits_to_byte ( BitStream + 24 + 32 , 32 ) ) ;
} else {
2017-03-29 22:02:29 +08:00
if ( g_debugMode ) prnt ( " Error removing parity: %u " , * size ) ;
2017-03-13 10:47:50 +08:00
return 0 ;
2015-11-22 13:00:32 +08:00
}
2017-03-13 10:47:50 +08:00
return 1 ;
2015-02-07 03:36:25 +08:00
}
2017-03-13 10:47:50 +08:00
// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
// BitStream must contain previously askrawdemod and biphasedemoded data
int FDXBdemodBI ( uint8_t * dest , size_t * size ) {
//make sure buffer has enough data
if ( * size < 128 ) return - 1 ;
2015-03-26 02:24:36 +08:00
2017-03-13 10:47:50 +08:00
size_t startIdx = 0 ;
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
2017-02-18 03:40:40 +08:00
2017-03-13 10:47:50 +08:00
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 2 ; //preamble not found
2017-03-26 20:09:40 +08:00
if ( * size ! = 128 ) return - 3 ; //wrong size for fdxb
//return start position
2017-03-13 10:47:50 +08:00
return ( int ) startIdx ;
}
2017-02-18 03:40:40 +08:00
2017-03-13 10:47:50 +08:00
// by marshmellow
// demod gProxIIDemod
// error returns as -x
// success returns start position in BitStream
// BitStream must contain previously askrawdemod and biphasedemoded data
int gProxII_Demod ( uint8_t BitStream [ ] , size_t * size ) {
size_t startIdx = 0 ;
uint8_t preamble [ ] = { 1 , 1 , 1 , 1 , 1 , 0 } ;
2017-03-12 08:21:53 +08:00
2017-03-13 10:47:50 +08:00
uint8_t errChk = preambleSearch ( BitStream , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 3 ; //preamble not found
if ( * size ! = 96 ) return - 2 ; //should have found 96 bits
//check first 6 spacer bits to verify format
if ( ! BitStream [ startIdx + 5 ] & & ! BitStream [ startIdx + 10 ] & & ! BitStream [ startIdx + 15 ] & & ! BitStream [ startIdx + 20 ] & & ! BitStream [ startIdx + 25 ] & & ! BitStream [ startIdx + 30 ] ) {
//confirmed proper separator bits found
//return start position
return ( int ) startIdx ;
2015-03-26 02:24:36 +08:00
}
2017-03-13 10:47:50 +08:00
return - 5 ; //spacer bits not found - not a valid gproxII
2017-03-01 05:35:01 +08:00
}
2017-03-13 10:47:50 +08:00
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
2017-04-16 04:18:54 +08:00
int HIDdemodFSK ( uint8_t * dest , size_t * size , uint32_t * hi2 , uint32_t * hi , uint32_t * lo , int * waveStartIdx ) {
2017-03-13 10:47:50 +08:00
size_t numStart = 0 , size2 = * size , startIdx = 0 ;
2017-04-16 04:18:54 +08:00
// FSK demodulator fsk2a so invert and fc/10/8
* size = fskdemod ( dest , size2 , 50 , 1 , 10 , 8 , waveStartIdx ) ;
2017-03-13 10:47:50 +08:00
if ( * size < 96 * 2 ) return - 2 ;
// 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
uint8_t preamble [ ] = { 0 , 0 , 0 , 1 , 1 , 1 , 0 , 1 } ;
// find bitstring in array
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 3 ; //preamble not found
2016-02-17 01:49:30 +08:00
2017-03-13 10:47:50 +08:00
numStart = startIdx + sizeof ( preamble ) ;
// final loop, go over previously decoded FSK data and manchester decode into usable tag ID
for ( size_t idx = numStart ; ( idx - numStart ) < * size - sizeof ( preamble ) ; idx + = 2 ) {
if ( dest [ idx ] = = dest [ idx + 1 ] ) {
return - 4 ; //not manchester data
2016-02-17 01:49:30 +08:00
}
2017-03-13 10:47:50 +08:00
* hi2 = ( * hi2 < < 1 ) | ( * hi > > 31 ) ;
* hi = ( * hi < < 1 ) | ( * lo > > 31 ) ;
//Then, shift in a 0 or one into low
if ( dest [ idx ] & & ! dest [ idx + 1 ] ) // 1 0
* lo = ( * lo < < 1 ) | 1 ;
else // 0 1
* lo = ( * lo < < 1 ) | 0 ;
2016-02-17 01:49:30 +08:00
}
2017-03-13 10:47:50 +08:00
return ( int ) startIdx ;
}
2016-02-17 01:49:30 +08:00
2017-04-16 04:18:54 +08:00
int IOdemodFSK ( uint8_t * dest , size_t size , int * waveStartIdx ) {
2017-03-13 10:47:50 +08:00
//make sure buffer has data
if ( size < 66 * 64 ) return - 2 ;
2017-04-16 04:18:54 +08:00
// FSK demodulator RF/64, fsk2a so invert, and fc/10/8
size = fskdemod ( dest , size , 64 , 1 , 10 , 8 , waveStartIdx ) ;
2017-03-13 10:47:50 +08:00
if ( size < 65 ) return - 3 ; //did we get a good demod?
//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
//Handle the data
size_t startIdx = 0 ;
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , & size , & startIdx ) ;
if ( errChk = = 0 ) return - 4 ; //preamble not found
2016-02-17 01:49:30 +08:00
2017-03-13 10:47:50 +08:00
if ( ! dest [ startIdx + 8 ] & & dest [ startIdx + 17 ] = = 1 & & dest [ startIdx + 26 ] = = 1 & & dest [ startIdx + 35 ] = = 1 & & dest [ startIdx + 44 ] = = 1 & & dest [ startIdx + 53 ] = = 1 ) {
//confirmed proper separator bits found
//return start position
return ( int ) startIdx ;
2016-02-17 01:49:30 +08:00
}
2017-03-13 10:47:50 +08:00
return - 5 ;
}
2016-02-17 01:49:30 +08:00
2017-03-13 10:47:50 +08:00
// redesigned by marshmellow adjusted from existing decode functions
// indala id decoding - only tested on 26 bit tags, but attempted to make it work for more
int indala26decode ( uint8_t * bitStream , size_t * size , uint8_t * invert ) {
//26 bit 40134 format (don't know other formats)
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
uint8_t preamble_i [ ] = { 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 } ;
size_t startidx = 0 ;
if ( ! preambleSearch ( bitStream , preamble , sizeof ( preamble ) , size , & startidx ) ) {
// if didn't find preamble try again inverting
if ( ! preambleSearch ( bitStream , preamble_i , sizeof ( preamble_i ) , size , & startidx ) ) return - 1 ;
* invert ^ = 1 ;
}
if ( * size ! = 64 & & * size ! = 224 ) return - 2 ;
if ( * invert = = 1 )
2017-04-04 23:52:10 +08:00
for ( size_t i = startidx ; i < * size + startidx ; i + + )
2017-03-13 10:47:50 +08:00
bitStream [ i ] ^ = 1 ;
return ( int ) startidx ;
}
// loop to get raw paradox waveform then FSK demodulate the TAG ID from it
2017-04-16 04:18:54 +08:00
int ParadoxdemodFSK ( uint8_t * dest , size_t * size , uint32_t * hi2 , uint32_t * hi , uint32_t * lo , int * waveStartIdx ) {
2017-03-13 10:47:50 +08:00
size_t numStart = 0 , size2 = * size , startIdx = 0 ;
// FSK demodulator
2017-04-16 04:18:54 +08:00
* size = fskdemod ( dest , size2 , 50 , 1 , 10 , 8 , waveStartIdx ) ; //fsk2a
2017-03-13 10:47:50 +08:00
if ( * size < 96 ) return - 2 ;
2016-02-17 01:49:30 +08:00
2017-03-13 10:47:50 +08:00
// 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 } ;
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 3 ; //preamble not found
numStart = startIdx + sizeof ( preamble ) ;
// final loop, go over previously decoded FSK data and manchester decode into usable tag ID
for ( size_t idx = numStart ; ( idx - numStart ) < * size - sizeof ( preamble ) ; idx + = 2 ) {
if ( dest [ idx ] = = dest [ idx + 1 ] )
return - 4 ; //not manchester data
* hi2 = ( * hi2 < < 1 ) | ( * hi > > 31 ) ;
* hi = ( * hi < < 1 ) | ( * lo > > 31 ) ;
//Then, shift in a 0 or one into low
if ( dest [ idx ] & & ! dest [ idx + 1 ] ) // 1 0
* lo = ( * lo < < 1 ) | 1 ;
else // 0 1
* lo = ( * lo < < 1 ) | 0 ;
2016-02-17 01:49:30 +08:00
}
2017-03-13 10:47:50 +08:00
return ( int ) startIdx ;
2016-02-17 01:49:30 +08:00
}
2017-03-07 21:48:16 +08:00
2017-03-13 10:47:50 +08:00
// find presco preamble 0x10D in already demoded data
int PrescoDemod ( uint8_t * dest , size_t * size ) {
//make sure buffer has data
if ( * size < 64 * 2 ) return - 2 ;
size_t startIdx = 0 ;
uint8_t preamble [ ] = { 1 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 4 ; //preamble not found
//return start position
return ( int ) startIdx ;
2017-03-12 08:21:53 +08:00
}
2017-03-13 10:47:50 +08:00
// by marshmellow
// FSK Demod then try to locate a Farpointe Data (pyramid) ID
2017-04-16 04:18:54 +08:00
int PyramiddemodFSK ( uint8_t * dest , size_t * size , int * waveStartIdx ) {
2017-03-13 10:47:50 +08:00
//make sure buffer has data
if ( * size < 128 * 50 ) return - 5 ;
// FSK demodulator
2017-04-16 04:18:54 +08:00
* size = fskdemod ( dest , * size , 50 , 1 , 10 , 8 , waveStartIdx ) ; // fsk2a RF/50
2017-03-13 10:47:50 +08:00
if ( * size < 128 ) return - 2 ; //did we get a good demod?
uint8_t preamble [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
size_t startIdx = 0 ;
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 4 ; //preamble not found
if ( * size ! = 128 ) return - 3 ;
return ( int ) startIdx ;
}
// by marshmellow
// find viking preamble 0xF200 in already demoded data
int VikingDemod_AM ( uint8_t * dest , size_t * size ) {
//make sure buffer has data
if ( * size < 64 * 2 ) return - 2 ;
size_t startIdx = 0 ;
uint8_t preamble [ ] = { 1 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t errChk = preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) ;
if ( errChk = = 0 ) return - 4 ; //preamble not found
uint32_t checkCalc = bytebits_to_byte ( dest + startIdx , 8 ) ^ bytebits_to_byte ( dest + startIdx + 8 , 8 ) ^ bytebits_to_byte ( dest + startIdx + 16 , 8 )
^ bytebits_to_byte ( dest + startIdx + 24 , 8 ) ^ bytebits_to_byte ( dest + startIdx + 32 , 8 ) ^ bytebits_to_byte ( dest + startIdx + 40 , 8 )
^ bytebits_to_byte ( dest + startIdx + 48 , 8 ) ^ bytebits_to_byte ( dest + startIdx + 56 , 8 ) ;
if ( checkCalc ! = 0xA8 ) return - 5 ;
if ( * size ! = 64 ) return - 6 ;
//return start position
return ( int ) startIdx ;
}
2017-03-07 21:48:16 +08:00
// by iceman
// find Visa2000 preamble in already demoded data
int Visa2kDemod_AM ( uint8_t * dest , size_t * size ) {
if ( * size < 96 ) return - 1 ; //make sure buffer has data
size_t startIdx = 0 ;
uint8_t preamble [ ] = { 0 , 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 0 } ;
if ( preambleSearch ( dest , preamble , sizeof ( preamble ) , size , & startIdx ) = = 0 )
return - 2 ; //preamble not found
if ( * size ! = 96 ) return - 3 ; //wrong demoded size
//return start position
return ( int ) startIdx ;
}