PDA

View Full Version : Data processing in array



Ioannis
- 2nd June 2022, 23:26
There is an array of n elements. Each element stored the pulse width from a PulsIn. Then according to pulse width, the bit_array bit will be 0 or 1. But if it is out of range then a new data set will be collected.

If the byte_array(x) is between a and b then bit_array.0(x)=0

If the byte_array(x) is between c and d then bit_array.0(x)=1

if complete n elements then continue, else goto parse new byte_array data.

Seems easy but could not find a way to exit the loop!

Any help please?



parse byte_array

find_bit:
if byte_array[index]>145 then '>725ìs
if byte_array[index]<180 then
bit_array.0[index]=0
index=index+1
if index<n then find_bit
endif
endif

if byte_array[index]<100 then '>725ìs
if byte_array[index]>75 then
bit_array.0[index]=1
index=index+1
if index<n then find_bit
endif
endif


Ioannis

richard
- 3rd June 2022, 01:27
i would do it this way




sample_data var byte[32]
fail var bit
sample var byte
a_one var byte
a_zero var byte
result var byte[4]
tolerance var byte

tolerance = 20
a_one = 160 ; mean value of a one bit
a_zero = 90 ; mean value of a zero bit


clear_result:
result[0] = 0
result[1] = 0
result[2] = 0
result[3] = 0
get_result:
sample = 32
fail = 0
while sample && ! fail
sample = sample-1
if (abs(sample_data[sample] - a_one)< tolerance ) then
result.0[sample] = 1
else
if (abs(sample_data[sample] - a_zero)> tolerance ) then fail = 1
endif
wend
if fail then
result bad
else
break out the champagne
endif

Ioannis
- 3rd June 2022, 16:25
Thanks Richard.

Makes sense though kinda heavy in respect of calculations.

Ioannis

richard
- 4th June 2022, 02:05
kinda heavy in respect of calculations.

maybe but it has positive indication of failure , it ceases testing on failure and it actually detects failures.
i would not be quibbling over a few words of code space when the entire process of encoding the bit stream into an unnecessary byte array
of times instead of directly into a bit array on detection would be heaps more efficient.


if the correct conditions can be met the pbp abs command can substituted for byte results like below


failure detection comparison





'parse byte_array define OSC 8
bit_array var byte[4]
byte_array var byte[32]
arraywrite byte_array,[80,80,160,80,80,160,80,160,_
80,160,80,80,160,80,80,160,_
160,80,80,80,80,160,160,80,_
80,80,80,160,80,110,160,160]
n var byte
index var byte
trisa.1 =0
porta=2
pause 1000
serout2 porta.1 ,84 ,["ready",13]

n = 32
index = 0


find_bit:
if byte_array[index]>145 then '>725ìs
if byte_array[index]<180 then
bit_array.0[index]=0
index=index+1
if index<n then find_bit
endif
endif


if byte_array[index]<100 then '>725ìs
if byte_array[index]>75 then
bit_array.0[index]=1
index=index+1
if index<n then find_bit
endif
endif
serout2 porta.1 ,84 ,[bin8 bit_array[3], bin8 bit_array[2], _
bin8 bit_array[1], bin8 bit_array[0],13]

;my way
tolerance con 20
a_one con 90 ; mean value of a one bit
a_zero con 160 ; mean value of a zero bit
fail var bit


clear_result:
bit_array[0] = 0
bit_array[1] = 0
bit_array[2] = 0
bit_array[3] = 0
get_result:
n = 32
fail = 0
while n && (!fail)
n = n-1
index = byte_array[n] - a_one; bytewise abs shortcut
if index.7 then index = ~index+1; bytewise abs shortcut
if index <tolerance then ; (abs(byte_array[n] - a_one)) < tolerance
bit_array.0[n] = 1
else
index = byte_array[n] - a_zero ; bytewise abs shortcut
if index.7 then index = ~index+1 ; bytewise abs shortcut
if index then fail = 1 ;(abs(byte_array[n] - a_zero))>tolerance
endif
serout2 porta.1 ,84 ,["."]
wend
if fail then
serout2 porta.1 ,84 ,[13,"fail",13]
else
serout2 porta.1 ,84 ,[13,bin8 bit_array[3], bin8 bit_array[2], _
bin8 bit_array[1], bin8 bit_array[0],13]
endif

richard
- 4th June 2022, 02:09
result of sim
9225

Ioannis
- 4th June 2022, 14:48
...when the entire process of encoding the bit stream into an unnecessary byte array
of times instead of directly into a bit array on detection would be heaps more efficient...


Sure I agree but could not find a fast way to encode directly the PWM bit stream into bits. The bits are coming from an RF radio receiver and have the typical 66-bit format of a keeloq transmission: 16ms guard time (low), 12 bits of 400us/400us as preamble, a 3-4ms low header and then the 66 bits of the data.

My routine to receive all these bits is based on the PulsIn command in a while-wend loop:



code VAR byte[9] BANK0 ' PWM read in
code1 var byte[66] ' Keeloq bits to be decrypted

KEY_0 var byte BANK0
KEY_1 var byte BANK0
KEY_2 VAR BYTE BANK0
KEY_3 VAR BYTE BANK0
KEY_4 VAR BYTE BANK0
KEY_5 VAR BYTE BANK0
KEY_6 VAR BYTE BANK0
KEY_7 VAR BYTE BANK0
mask VAR BYTE BANK0
CSR_0 VAR BYTE BANK0
CSR_1 VAR BYTE BANK0
CSR_2 VAR BYTE BANK0
CSR_3 VAR BYTE BANK0
pass VAR BYTE BANK0
CNT1 VAR BYTE BANK0
CNT2 VAR BYTE BANK0

temp var word

OVER:
while 1
main:
index=0
guard:
pulsin portb.0,0,temp 'find header of 16ms
if temp<2500 then main ' PIC is clocked at 8MHz, so a PulsIn step is 5usec.
if temp>4400 then main ' 5usec x 2500= 12.5ms up to 5usec x 4400=22ms
preamp:
pulsin portb.0,1,temp 'then skip 12 pulses of 50% Duty, 400usec
if temp<50 then main
if temp>90 then main
index=index+1
if index<11 then preamp

index=0
pulsetrain: 'now collect 66 pulses ~800/400 usec
pulsin portb.0,1,code1[index]
index=index+1
if index<66 then pulsetrain

index=0
find_code: 'convert pulse width to binary 66 bit stream
if code1[index]>130 then
if code1[index]<170 then
code.0[index]=0
endif
endif

if code1[index]<80 then
if code1[index]>55 then
code.0[index]=1
endif
endif

index=index+1
if index<66 then find_code

'Display the encrypted and decrypted array
hserout ["Rec: ",bin2 code[8]," ",bin8 code[7]," ",bin8 code[6]," ",bin8 code[5]," ",bin8 code[4],":",bin8 code[3]," ",bin8 code[2]," ",hex2 code[1]," ",hex2 code[0],13,10] 'display pulse train
CSR_0=CODE[0]:CSR_1=CODE[1]:CSR_2=CODE[2]:CSR_3=CODE[3]
GOSUB DECRYPT_K
hserout ["Dec: ",bin2 code[8]," ",bin8 code[7]," ",bin8 code[6]," ",bin8 code[5]," ",bin8 code[4],":",bin8 CSR_3," ",bin8 CSR_2," ",hex2 CSR_1," ",hex2 CSR_0,13,10,13,10]

wend



Obviously, cannot show the DECRYPT_K routine... Sorry.

The above code is not near your fail safe program and will try to fit in the code space after a clean up of the rest code.

Ioannis

Ioannis
- 4th June 2022, 18:41
The more I observe your code and way of thinking, the more I see its briliance.

Thank you again Richard,
Ioannis

richard
- 5th June 2022, 01:21
a couple of ways


pulsetrain:
index=67
while index
while !portb.0 :wend ;wait for hi
index=index-1
pauseus 600 ;bit period=3*te ie 3*400=1200uS
code.0[index]= ~ portb.0 ;sample @midpoint of bit period
while portb.0 :wend ;wait for lo
wend




;or with some simple time supervision



fail var bit
timer var word ext
@timer = TMR1L
PRELOAD CON 65535-820 ;@8MHz timer prediv 2 each tick=1uS




pulsetrain:
index=67
t1con=0
fail=0


while index
timer=preload
while !portb.0 :wend ;wait for hi
t1con=$21
index=index-1
pauseus 600 ;bit period=3*te ie 3*400=1200uS
code.0[index]= ~ portb.0 ;sample @midpoint of bit period
while portb.0 && !pir1.0 :wend ;wait for lo
t1con=0
fail=fail | pir1.0
wend



or sample @50,250,450,650,850 uS past transition to hi
where valid result is
11000 for a 1
11110 for a 0

there are endless methods

Ioannis
- 5th June 2022, 11:29
My simple thinking lead me to this version ditching the big array:



index=0
pulsetrain: 'now collect 66 pulses ~800/400 ìsec
pulsin portb.0,1,temp1
if temp1<55 then main
if temp1>170 then main
if temp1<130 then
code.0[index]=1
else
code.0[index]=0
endif
index=index+1
if index<66 then pulsetrain


And then came your masterpiece of coding with TMR1...! Amazing!

It just needs to be reversed (the code array) I guess. No big deal.

Thanks,
Ioannis

richard
- 5th June 2022, 12:22
In a noisy environment you can over sample a bit to be sure of data validity, i expect the serial data from a keeloq
chip to be quite clean so a single sample point would suffice

sample @50,250,450,650,850 uS past transition to hi
where valid result is
11000 for a 1
11110 for a 0




sample var bitfail var bit


fail=0
pulsetrain:
index=67
while index && !fail
while !portb.0 :wend
pauseus 50 ;50
if !portb.0 then fail = fail | 1
pauseus 200 ;250
if !portb.0 then fail = fail | 1
pauseus 200 ;450
sample=portb.0
pauseus 200 ;650
if portb.0^sample then fail = fail | 1
pauseus 200 ;850
if portb.0 then fail = fail | 1
index=index-1

code.0[index]= !sample

wend

Ioannis
- 5th June 2022, 21:09
In general the data stream on a good signal level is very clean. But when there is no RF signal, the radio module will produce a lot of noise that is converted to random pulses through the data slicer. This creates a lot of bad data and false triggers on a non rolling code systems if digital filtering is not applied. With the keeloq encryption it is safe to assume that such triggers will not happen. The probability to have 66 bits in a correct timing and also in the correct sequence, not mentioning the other safety measures of keeloq like counter etc, is really low if not zero.

When you referred to 5 sampling points I was thinking of timers etc to maintain a fixed sampling point in time...

Your code showed the application of KISS in a fine way!

Thank you for your great ideas,
Ioannis

richard
- 6th June 2022, 02:43
The probability to have 66 bits in a correct timing and also in the correct sequence, not mentioning the other safety measures of keeloq like counter etc, is really low if not zero.
i would not expect to ever receive a malformed bit from a keeloq serial stream , the data may be useless however.
single point sampling should be ok imho

Ioannis
- 6th June 2022, 09:04
Agree.

Though I have checked various implementations of RF remote controls and many have wide tolerances from the specified timings.

I am very much sure that those chips are bad copies of the original Microchip one. But are out there... If interested, I have many test of original and copy chips with the timings in excel file.

Ioannis