Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 14:26 25 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : How can I capture this data-stream?(non-standard)

     Page 2 of 2    
Author Message
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2285
Posted: 02:47am 01 Jul 2020
Copy link to clipboard 
Print this post

revised version. moved getcode into main body, handle pulse lengths as pairs (short,long or long,short) so no need to calculate a threshold value, other bits tidied up, outputs the code as a 6-digit hex value. is now more tolerant of CPU speed and seems to work ok with CPU 40.

i also see we have a PULSIN function in micromite basic, which could possibly simplify things even further. will experiment with this next.


cheers,
rob   :-)


CPU 48
Option break 0
SetPin 22, DIN
Dim times(150)
Dim keylist%(20)




' main program begins here

For I=149 To 150: times(I)=9999: Next I
For I=1 To 20: keylist%(I)=&hDEADC0DE: Next I

keylist%(15)=&h0B1864
keylist%(16)=&h0B1868
keylist%(17)=&h0B186C
keylist%(18)=&h089964
keylist%(19)=&h089968
keylist%(20)=&h08996C

Print "press 'esc' to exit, space bar to add fob code, '?' to list saved codes"

Do
' retrieve pulse timings from SYN470R receiver

 state=0
 For I=0 To 148
   count=0
   Do :count=count+1:Loop Until (Pin(22)=state)
   times(I)=count
   state=Not state
 Next I

' find maximum time value, use 1/4 of this as threshold for start/end pulse

 tv=0
 For I=1 To 148:tv=Max(tv,times(I)): Next I
 tv=tv/4

' find beginning and end of a (possibly) valid code segment

 I=1
 Do While times(I)<(tv): I=I+1:Loop
 I1=I: I=I+1
 Do While times(I)<(tv): I=I+1:Loop
 I2=I

 If (I2-I1-1)<>49 Then Print ".";: GoTo skip
 Print

 code%=0
 For I=I1+1 To I2-2 Step 2
   Print Str$(times(I),0) "|" Str$(times(I+1),0) "  ";
   If Pos>40) Then Print
   code%=code%<<1
   If times(I)>times(I+1) Then code%=code%+1
 Next I
 Print times(I2-1)

 Print I1, I2,, "(" Str$(I2-I1-1,0) ")",, times(I1), times(I2),, Str$(tv,0,1)
 Print Hex$(code%, 6)
 Print Bin$(code%, 24)
 Print

' check for a match to a saved code, beep if found

 For I=1 To 20
   If code%=keylist%(I) Then Print Chr$(7);
 Next I

 Pause (900)
 skip:

' press space bar to add fob code to list (max 20)

 key$=Inkey$
 If key$=" " Then
   keylist%(index+1)=code%
   index=(index+1) Mod 20
 EndIf

' press '?' to print out the list of saved fob codes

 If key$="?" Then
   Print
   For I=1 To 20
     If keylist%(I)<>&hDEADC0DE Then Print Hex$(keylist%(I), 6)
   Next I
   Print
 EndIf

 If key$=Chr$(27) Then Exit Do
 key$=""

Loop
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9060
Posted: 03:18am 01 Jul 2020
Copy link to clipboard 
Print this post

Have to go to a job now, but I just HAD to try out your 1st code - and then I see you have already added another one!  

Anyway, here is the result of my pressing a button using your 1st code:





I pressed the same button twice, and I note I get exactly the same code back, so that is confirming that the 1st code you posted IS giving consistent results.

I have to go to work now, but I will be back to try your latest code later!!!!  
Smoke makes things work. When the smoke gets out, it stops!
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2285
Posted: 03:29am 01 Jul 2020
Copy link to clipboard 
Print this post

here's an even 'better' version, using PULSIN to measure just the negative pulses. the down side is that it isn't self-calibrating. cutoff points are hard-wired at 5000us and 600us. so it may not work right with non-1527 key fobs.


cheers,
rob   :-)


CPU 48
Option break 0
SetPin 22, DIN
Dim times(60)
Dim keylist%(20)




' main program begins here

For I=59 To 60: times(I)=9999: Next I
For I=1 To 20: keylist%(I)=&hDEADC0DE: Next I

keylist%(15)=&h0B1864
keylist%(16)=&h0B1868
keylist%(17)=&h0B186C
keylist%(18)=&h089964
keylist%(19)=&h089968
keylist%(20)=&h08996C

Print "press 'esc' to exit, space bar to add fob code, '?' to list saved codes"

Do
' retrieve pulse timings from SYN470R receiver

 For I=0 To 58: times(I)=Pulsin(22, 0): Next I

' find beginning and end of a (possibly) valid code segment

 I=1
 Do While times(I)<(5000): I=I+1:Loop
 I1=I: I=I+1
 Do While times(I)<(5000): I=I+1:Loop
 I2=I

 If (I2-I1-1)<>24 Then Print ".";: GoTo skip
 Print

 code%=0
 For I=I1+1 To I2-1
   Print Str$(Int(times(I)),5);
   If Pos>40 Then Print
   code%=code%<<1
   If times(I)<600 Then code%=code%+1
 Next I
 Print

 Print I1, I2,, "(" Str$(I2-I1-1,0) ")",, times(I1), times(I2)
 Print Hex$(code%, 6)
 Print Bin$(code%, 24)
 Print

' check for a match to a saved code, beep if found

 For I=1 To 20
   If code%=keylist%(I) Then Print Chr$(7);
 Next I

 Pause (900)
 skip:

' press space bar to add fob code to list (max 20)

 key$=Inkey$
 If key$=" " Then
   keylist%(index+1)=code%
   index=(index+1) Mod 20
 EndIf

' press '?' to print out the list of saved fob codes

 If key$="?" Then
   Print
   For I=1 To 20
     If keylist%(I)<>&hDEADC0DE Then Print Hex$(keylist%(I), 6)
   Next I
   Print
 EndIf

 If key$=Chr$(27) Then Exit Do
 key$=""

Loop
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9060
Posted: 04:01am 01 Jul 2020
Copy link to clipboard 
Print this post

Wonderful!    

Here is a screenshot from your 2nd code:





This one is MUCH faster then the 1st code.
I tried three different buttons on this one.
Came here to post photo, and you have ANOTHER one for me to try!  

I have yet another job to go to now, but I will be back later tonight to post the results of your latest(3rd) code.
Smoke makes things work. When the smoke gets out, it stops!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9060
Posted: 07:14am 01 Jul 2020
Copy link to clipboard 
Print this post

OK, here is the image of Rob's 3rd code:





The first button is a 1527 encoder, the 2nd and 3rd buttons are 2264 encoders with solder-blob addressing.(same address, different D0-D3 bit blob settings)

This is really excellent.  Can you explain what the columns of debug information are, and the line that is 2,27,(24),15918,15938.7 in my image are?

The HEX code for the button follow that, and then the last line is the binary code for the same button, so I follow that no problems, but would like to understand what the other debug information represents.
Smoke makes things work. When the smoke gets out, it stops!
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5898
Posted: 07:52am 01 Jul 2020
Copy link to clipboard 
Print this post

The first 24 numbers are the times of each bit decoded.
Above 1000 indicates a 0 and below 1000 indicates a 1

On the next row are the starting and ending array slots for the two long pulses indication start and end.
the (24) is the count of bits decoded between the start and stop which should equal the number of readings in the above array.
It does.

the last two numbers are the length of the start and stop long pulses in microseconds.


I think I have it right.

Jim
VK7JH
MMedit   MMBasic Help
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9060
Posted: 10:24am 01 Jul 2020
Copy link to clipboard 
Print this post

Excellent, thank you for that.  It helps me understand what is going on.
Smoke makes things work. When the smoke gets out, it stops!
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2285
Posted: 02:48pm 02 Jul 2020
Copy link to clipboard 
Print this post

TassyJim's explanation is pretty much spot on.

following is a quick guide to how both versions (2 and 3) work. terminology is:
BREAK = 8-10ms negative pulse,
SHORT = 300us pulse (typically < 600us)
LONG = 900us pulse ( typically > 600us)

version 2
we time the length of 149 positive and negative pulses, using a simple counter loop. we do not need to bother keeping track of which ones are positive and which ones are negative, as we know that there are really long BREAK pulses between code blocks. these BREAKJ pulses are negative, so we can later on work out the polarity of the rest of the pulses from there. this is the code that collects the 149 pulse lengths:

state=0
For I=0 To 148
 count=0
 Do :count=count+1:Loop Until (Pin(22)=state)
 times(I)=count
 state=Not state
Next I


the value of state switches us back and forth between looking for positive and looking for negative pulses after each pulse has been timed.

we also place a couple of 'dummy' counts at the end of the times array (of 9999), so that when we search through the data further down in the code, the search always terminates. there are neater ways that this could have been done. also note that if there is NO data coming from the receiver, then this code will loop forever - it relies upon the random data that the receiver produces when no signal is present to work correctly.

the sorts of numbers we see with an MX170 are:
SHORT -> 1 or 2 passes through the counter loop,
LONG -> 4 or 5 passes through the counter loop,
BREAK -> 70 or so passes through the counter loop.

numbers when run on an MX470 would appear to be 2-3, 9-10, and 110.

we next process the collected data:
(1) search through the captured timing data to find the longest pulse captured, which corresponds to the one of the 8-10ms BREAKs between code blocks. we divide this found value by 4 (dividing by 2 would have been safer) and use it to pick out the start and end of one single code block. because we have collected 148 samples, we know that there should be at least ONE valid code block in there if a fob transmitting:

' find maximum time value, use 1/4 of this as threshold for start/end pulse
tv=0
For I=1 To 148:tv=Max(tv,times(I)): Next I
tv=tv/4

' find beginning and end of a (possibly) valid code segment
I=1
Do While times(I)<(tv): I=I+1:Loop
I1=I: I=I+1
Do While times(I)<(tv): I=I+1:Loop
I2=I


(2) check that the code block is the right length - 49 timed periods (the number of pulses will always be odd, there being an extra 'dummy' positive pulse at the end). if the number of periods  is not right, we print a "." and go back to collecting data.

(3) looking at pairs of time values, LONG followed by SHORT = 1, SHORT followed by LONG = 0. the first time value in a pair always corresponds to a positive pulse, while the second corresponds to a negative pulse. we display these in the diagnostics output as pairs of numbers with a "|" between them. one number should always be about 4x the other, ie "1|5" or "9|2", with higher numbers better from the perspective of the code being more reliable. outside of the for...next loop we print the value for the last (dummy) pulse just for completeness.

the next line of diagnostics output consists of:
index of first BREAK, index of second BREAK, "(" number of pulses including the 'dummy' one ")" loop counter for first BREAK, loop counter for second BREAK, calculated threshold value used to locating BREAKS.


version 3
we time the length of 59 negative pulses using the PULSIN function. we know from the 1527 specifications that with a valid transmission the lengths of pulses should be around about 300us, 900us, and 9ms. PULSIN returns the length in microseconds, and times out after 100ms - so the code does not lock up if there is no activity on pin 22:

For I=0 To 58: times(I)=Pulsin(22, 0): Next I


as in version 2, we search for the BREAK pulses, but just use the criterion of > 5000us. we check for 24 negative pulses captured between the BREAK pulses, and if the number of periods  is not right, we print a "." and go back to collecting data.

next, we loop through the 24 measured negative pulses (these are the second pulse in each of the pairs talked about for version 2 of the code) - if a pulse is <600us this corresponds to a code bit of "1", otherwise the code bit is a "0". for diagnostics, we print out the length of each pulse, which is a value in microseconds.

is version 3, on the diagnostics line the last two numbers are the lengths of the two BREAKs in microseconds.


i'll work on cleaning up the code a bit more, removing the diagnostics, removing the save fob code option (which was useful for testing), and add a check that the receiver module is working.


cheers,
rob   :-)
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2285
Posted: 03:22pm 02 Jul 2020
Copy link to clipboard 
Print this post

here we go, a final version:

CPU 48
Option break 0
SetPin 22, DIN
Dim times(60)


Do
 T=Timer
 For I=0 To 60:times(I)=Pulsin(22, 0):Next I
 If Timer-T>2000 Then Print "receiver fault"

 I1=0: I2=0
 For I=1 To 60
   If (times(I)>4000) And (I1=0) Then I1=I
 Next I
 For I=I1+1 To 60
   If (times(I)>4000) And (I2=0) Then I2=I
 Next I

 If (I2<>0) And (I2-I1-1)=24 Then
   threshold=64*times(I1)/992
   code%=0
   For I=I1+1 To I2-1
     code%=code%<<1
     If times(I)<threshold Then code%=code%+1
   Next I

'   For I=I1 To I2: Print times(I),: Next I:Print
'   Print I1, I2,, "(" Str$(I2-I1-1,0) ")",, times(I1), times(I2), threshold

   Print Hex$(code%, 6)
'   Print Bin$(code%, 24)
 End If
Loop


note the line:
threshold=64*times(I1)/992

this adjusts the threshold according to the width of the BLANK pulse preceding the code block, following the timing specifications of the RT1527 and PT2262; BLANK pulse is 1024-32=992 units wide, SHORT pulses are 32 units wide, LONG pulses are 32*3=96 units wide. ADDENDUM: we don't use the trailing BLANK pulse, as the button on the key fob may have been released during this pulse, considerably extending the pulse (as seen by the receiver) and resulting in an excessively high threshold value causing the fob code appearing to be 0xFFFFFF


cheers,
rob   :-)
Edited 2020-07-03 22:38 by robert.rozee
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 522
Posted: 03:57am 04 Jul 2020
Copy link to clipboard 
Print this post

I was going through some old saved youtube videos and found this
Hacking Radio
some of the tools and methodology may be of use for any one playing
with radio and digital decoding/coding of signals.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9060
Posted: 09:01am 05 Jul 2020
Copy link to clipboard 
Print this post

@ robert_rozee: Thanks for that extra excellent description of what is going on.  I owe you a big jug of the beer of your choice!    

I have customised your latest code, so it now does everything I need:

  Quote  '==============================================
'SYN470R 433MHz/315MHz SDU (Smart Decoder Unit)
'Version 1A, [05/07/2020]: Inital code
'==============================================

'The heart of this code was written by Robert Rozee' on The BackShed Forums.
'Robert Rozee' is a clever man!  Thanks Rob! :)

'I have edited his testing code so that the MM2 simply decodes the data packet from the FOB, and forwards
'this to another system for processing.  This means that this MM2 chip is dedicated to only decoding the
'data packet from the FOB transmitter, and nothing else - apart from a couple of LED's and an IRQ line.
'This is primarily because decoding the data from the white-noise is reasonably CPU intensive under MMBASIC,
'so it is best to dedicate a MM2 chip solely to processing the transmissions from the FOB transmitters, and
'not to bother concentrating on anything else that might be happening at the same time - this, the main system
'can do. ;)

'The code can decode transmissions from most FOB transmitters, including the common 1527 and 2262/2264 encoders
'often found in wireless FOB buttons or other wireless transmitters these days.
'The code automatically deals with the white-noise on the receiver data output when there is no valid data.
'The IRQ line is pulsed for 100mS when a valid data packet is received and decoded, to signal to the host
'system that data has been received, although, most modern MCU's UART buffers can deal with this without needing
'an IRQ line, but as there are plenty of spare pins on the MM2 in this application......why not! ;)
'To receive 315MHz FOB transmitters, you only need to use a 315MHz version of the receiver module.

'The 315MHz and 433MHz versions of the SYN470 receiver module only differ in that the crystal used for 433MHz
'oprtation is 6.7458MHz, and the crystal used for 315MHz modules is 4.8970MHz.  The input matching LC SMD parts are
'also slightly different values, so you should not simply swap crystals, but obtain the correct module for the
'frequency of choice.
'Other then that, the MM2 decoder will function in exactly the same way for both frequency bands.

'---------------
'SETUP THE CHIP:
'---------------

Option Explicit
Const DIL1=06,DIL2=07,DIL3=09,DIL4=10 'DIL switch pins
Const RXD=15 'Pin for LED
Const IRQ=16 'IRQ line to host(if required)
Const HB=17 'Heartbeat LED
Const FOB=26 'DATA output from SYN470R receiver unit
Dim TIMES(60),FORMAT,Y,CR,I,I1,I2,CODE%,T,DILSW,THRESHOLD
SetPin FOB,DIN 'FOB receiver module data line
SetPin RXD,DOUT 'RXD LED
SetPin IRQ,DOUT 'IRQ line (if needed)
SetPin HB,DOUT 'Heartbeat LED
SetPin DIL1,DIN,PULLDOWN 'DIL switch, pole 1
SetPin DIL2,DIN,PULLDOWN 'DIL switch, pole 2
SetPin DIL3,DIN,PULLDOWN 'DIL switch, pole 3
SetPin DIL4,DIN,PULLDOWN 'DIL switch, pole 4
OPEN "COM1:9600" as #1 'COM port to send decoded data out of
SetTick 1000,HEARTBEAT 'Start heartbeat flasher

'----------
'MAIN LOOP:
'----------
Do
 T=
Timer
 
For I=0 To 60:TIMES(I)=Pulsin(FOB,0):Next I 'Sample data from the RX module
 If Timer-T>2000 Then Print "RX Fault!"
 I1=
0: I2=0
 
For I=1 To 60
   
If (TIMES(I)>4000) And (I1=0) Then I1=I
 
Next I
 
For I=I1+1 To 60
   
If (TIMES(I)>4000) And (I2=0) Then I2=I
 
Next I
 
If (I2<>0) And (I2-I1-1)=24 Then
   THRESHOLD=
64*TIMES(I1)/992
   CODE%=
0
   
For I=I1+1 To I2-1
    CODE%=CODE%<<
1
   
If TIMES(I)<THRESHOLD Then CODE%=CODE%+1
   
Next I
   
Pin(RXD)=1
   
Print STR$(CODE%) 'Decimal version of code
   Print Hex$(CODE%, 6) 'Hexidecimal version of code (6-byte word)
   Print Bin$(CODE%, 24) 'Binary version of code (24-bit ASCII)
   Pulse IRQ,100 'Interrupt request pulse
   DILSW=PORT(6,2,9,2) 'Read the DIL switch settings
   Select Case DILSW
     
CASE 1 'Output only the decimal version of the FOB code
       Print #1,STR$(CODE%)
     
Case 2 'Output only the hexidecimal version of the FOB code
       Print #1,Hex$(CODE%,6)
     
Case 3 'Output only the ASCII-Binary version of the FOB code
       Print #1,Bin$(CODE%,24)
     
Case 4 'Output all three types of the FOB code
       Print #1,STR$(CODE%)
       
Print #1,Hex$(CODE%,6)
       
Print #1,Bin$(CODE%,24)
     
CASE ELSE
       
Print "No options set."
       
Print #1,"NOS"
   
End Select
   
Pause (300)
   
Pin(RXD)=0
 
EndIf
Loop


'-------------
'SUB-ROUTINES:
'-------------

SUB HEARTBEAT
 
Pulse HB,100
End Sub




...and I have a PCB being made for it now:









Smoke makes things work. When the smoke gets out, it stops!
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 1985
Posted: 10:08am 05 Jul 2020
Copy link to clipboard 
Print this post

  Quazee137 said  I was going through some old saved youtube videos and found this
Hacking Radio
some of the tools and methodology may be of use for any one playing
with radio and digital decoding/coding of signals.


Cheers for that link Q quite scary and a sombre lesson in why we should use encryption for even the most basic comms between units.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9060
Posted: 08:44am 13 Jul 2020
Copy link to clipboard 
Print this post

PCB's have arrived, so I have built one.







Worked on the very first attempt.
Thanks to all who have help with this, but extra special thanks to robert.rozee for all his code that I was then able to customise to my purposes.

If this is something that anyone else would like to have, I can put it up on my website as either a finished programmed unit, or as a construction pack with gerbers, rob's code and BOM etc.

Reply here if you want either of those options.
Smoke makes things work. When the smoke gets out, it stops!
 
     Page 2 of 2    
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024