Shop OBEX P1 Docs P2 Docs Learn Events
RFID tag as _one_ variable — Parallax Forums

RFID tag as _one_ variable

ErlendErlend Posts: 612
edited 2013-03-19 00:41 in Propeller 1
I want to handle the RFID tag as one variable instead of 10 byte values. The byte codes seem to be in the range 0 - 99, but I am not sure it is always so. If it is, and I just string all the numbers together ino one integer (i,e, 44 52 87 ... becomes 445287...) the value could be as high as 10EE10 (-1), obviously blowing the LONG capacity. I may be forced to split into two LONGs and I suppose I could live with that too, if there is no, more elegant solution out there. But, that would mean I need to add some PUB to take care of comparison and lookup, etc. Same goes for a solution based on storing the tag code as a 20 char string. Ideas to a more elegant solution is appreciated.

Erlend
I am using the RFID reader object by Brandon Nimon, and the RFID hardware from Parallax.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-03-10 08:44
    The information content of the tags is 40 bits (10 x 4 bits) which requires 2 longs to store. Each character in the tag is a hexadecimal value ("0"-"9" and "A"-"F") and can be reduced to 4 bits from a single character. Some of the bits in the tag values are relatively fixed. I believe some of them reflect the tag manufacturer, so you may be able to leave them out of any table and just check them for a fixed value.
  • AribaAriba Posts: 2,690
    edited 2013-03-10 10:20
    Why not handle the tags as strings with a fixed length of 10 bytes. A string needs an ending zero, so every tag needs 11 bytes.
    Spin has enough string support for simple moves and compares, and a fixed stringsize makes this really easy:
    VAR
      byte tag[11]
      byte table[11*50]  'for 50 tags
    
    PUB ..
    
     if strcomp(@tag, @table+index*11)    'compare with table[index]
       'equal
     else
       'not equal
    
     bytemove(@table+index*11, @tag, 10)  'write tag into table[index]
    
     bytemove(@tag, @table+index*11, 10)  'read tag from table[index]
    

    Andy
  • ErlendErlend Posts: 612
    edited 2013-03-10 11:20
    Mike,
    How can this be? One of my cards reads: 48 49 48 48 65 54 52 56 66 68. Can't see how this could fit into 10x 4 bit?

    Ariba,
    I had forgotten the 'native' strcomp. This looks good, and based on the above code, all the bytes are printable characters. But it would be better to think of the tag not as a string as such, but an array of bytes, and then it does not matter if they are printable or not, right? No reason to behave and only use strcomp for real strings.
    I will define thus: DAT refTag1 BYTE 48, 49, 48, 48, 65, 54, 52, 56, 66, 68 -, and next, same way for refTag2, ...etc. After that I can deal with refTag as a string, right?
    And I will modify the RFID reader object to write the 10 codes into the (global) tag[] by means of passing @tag to it, right?
    My Main code will have a CASE block where the action depends on which of the refTag matches the value of tag. Am I on the right track?
  • kuronekokuroneko Posts: 3,623
    edited 2013-03-10 16:39
    Erlend wrote: »
    one of my cards reads: 48 49 48 48 65 54 52 56 66 68. Can't see how this could fit into 10x 4 bit?
    ASCII      48   49   48   48   65   54   52   56   66   68
      hex       0    1    0    0    A    6    4    8    B    D
      bin   %0000_0001_0000_0000_1010_0110_0100_1000_1011_1101
    
  • AribaAriba Posts: 2,690
    edited 2013-03-10 22:34
    Erlend wrote: »
    Mike,
    How can this be? One of my cards reads: 48 49 48 48 65 54 52 56 66 68. Can't see how this could fit into 10x 4 bit?

    Ariba,
    I had forgotten the 'native' strcomp. This looks good, and based on the above code, all the bytes are printable characters. But it would be better to think of the tag not as a string as such, but an array of bytes, and then it does not matter if they are printable or not, right? No reason to behave and only use strcomp for real strings.
    I will define thus: DAT refTag1 BYTE 48, 49, 48, 48, 65, 54, 52, 56, 66, 68 -, and next, same way for refTag2, ...etc. After that I can deal with refTag as a string, right?
    And I will modify the RFID reader object to write the 10 codes into the (global) tag[] by means of passing @tag to it, right?
    My Main code will have a CASE block where the action depends on which of the refTag matches the value of tag. Am I on the right track?

    You can define the tag numbers in a DAT section with the ASCII charcters in quotes:
    DAT
    refTags
    refTag1  byte "0100A648BD",0
    refTag2  byte "0100CA0056",0
    refTag3  byte "480459F433",0
    
    But you can also write 10 decimal values as in your example, but you need to add a zero as 11th byte.

    I don't know how you get the number from the RFID reader. If you read it serially byte per byte then this may work:
    repeat i from 0 to 9
       tag[i] := rfid.rx  'serin from RFID
     tag[10] := 0
    
    If you have the tag characters in the @tag string then you can serach it in the refTags like that:
    repeat i from 0 to MAX_REF_TAGS - 1
       if strcomp(@tag, @refTags+i*11)
         quit
     if i < MAX_REF_TAGS
       'found refTag number in i
     else
       'not there
    
    Andy
  • ErlendErlend Posts: 612
    edited 2013-03-11 00:40
    @Mike Green
    @kuroneko

    I didn't realise the 48 49 48 ... were ASCII codes for the character form of the hex code, I thought they were numerals. Sorry. that's why I could not understand how 4 bits could do 48 49 48 etc. I guess I should have recognized it from the familiar number range. I'm learning : ).

    @Ariba

    Thanks for the guideline. Knowing they are all ASCII codes makes it so much easier. I'm on my wings now.

    Erlend
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-11 09:26
    I'm the author of that object. When the object outputs the value (for example in the demo) it outputs it as a 10-byte string into the rec_tag address you supply. Also, there is built in a way for you to either hard code a list of "valid" RFID tags into the bottom of the object, or "soft code" them in at runtime through the tagloc variable. The string comparing is built into the PASM code so it would be faster than anything you can do outside of the object in SPIN. Though, both the hard coded and run time RFID tag tables expect each tag not to be zero terminated.
    Is there a problem with using the built in functionality?

    You could build a list in RAM or as part of a DAT that is formatted list this:
    '' Key#         Key Byte values   Key ID
            tags       {1}  byte    "1234567890"    ' 0098765432
                       {2}  byte    "2345678901"    ' 0087654321
                       {3}  byte    "3456789012"    ' 0076543210
                       {4}  byte    "4567890123"    ' 0065432109
                       {5}  byte    $23, $89, $6F, $58, $69, $11, $12, $A2, $7C, $41 ' 0023569832   <--- notice here, these are the ASCII values you are referring to
                       {6}  byte    "5678901234"    ' 0054321098
    

    I could alter the software to allow tags to be zero-terminated strings and just add a parameter in the start method to reflect the option.
  • ErlendErlend Posts: 612
    edited 2013-03-11 13:29
    I never stop being amazed about how friendly and helpful people are in this forum!

    Bobb,
    I was debugging my setup with a RFID reader written in spin, but now it is up and running, and I understand what is going on, and it is time to move over to a permanent solution. I want to use your object for that. I've seen it has lots of functionality, and I have only a few thoughts; I think it is 'cleaner' when the object is not specific to one application, so I would like to avoid putting DAT data in there. Better to pass a pointer to DAT stuff instead. And, my application is not only looking to check if the card has a valid code, but must also find which card it is. I thought I would try to implement this as an additional functionality in the object, but PASM is hard and slow for me to work on.
    What I would ideally want is:
    Define the ok tags in DAT in the Main code, pass a pointer to the RFID object
    Have the RFID reader continously running in a separate cog, where it reads tag id, checks which of the ok tags is matching, and then writes this to a global valueID variable (an index only, i.e. 1, 2, 3,..) in Main. After 10 sec (or a parameter time) it resets the valueID by writing a -1 to it. This way it will only contain the id of a recent card swipe, and not hold on to old ones.
    This would allow me - in the Main code - to anywhere in my algorithms check "who is here", by looking at valueID. No more fuzz.

    I would very much appreciate help to do this!

    Erlend
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-11 14:12
    I tried to make the object have as broad an application as possible, I think it already does what you are looking for. A tag index is already passed to the main object through the tag_ret address. The only functionality that would need to be added (though I don't think it should be part of the object) is the clearing of the value every 10 seconds.

    Using the tagloc parameter, you supply the object with an address (a "table") that has the valid tags run end-to-end as 10-byte arrays (no zero termination/delimitation).
    With the tagcount parameter, you tell the object how many tags are in that table.

    When a tag is read, the supplied output address contains (1) if the tag is in the supplied table, and (2) if the tag is not (or (3) if there has been a wrong tag and a correct tag scanned since the last time the value was cleared). These values are not cleared by the object, you'll have to do it in the parent object.
    At the same time, the rec_tag address is populated with the 10-byte string of the tag's value, and the tag_ret address gets the tag's index (that's why -- in my tags table example above -- I have the tags numbered).
    None of the return values are cleared by the object, they do get overwritten when a new tag is read though. That's all up to the parent object to detect and control that.
  • ErlendErlend Posts: 612
    edited 2013-03-11 14:47
    Bobb,
    Thanks. I suspected tag_ret could be what I was looking for. Now all I have to sort out is the automatic clearing of an old card tag value. I don't like to have this kind of housekeeping in my Main, though. If you don't mind too much I will tweak the code to take one more parameter - auto_clear - and if >0 it will clear tag_ret to -1 after auto_clear seconds.
    I am doing it this way for all the inputs in my project. Inputs are read, converted, and digital ones timetagged - outside the Main cog. Results are written back to global variables that the Main code can use without worrying about houskeeping.

    Erlend
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-11 15:01
    Go for it, it's MIT licensed, you can do whatever you want to it, as long as you cite and share alike.

    Just FYI, when you dig into it, the PASM COG just sits at a WAITPEQ Dat_p, Dat_p until a tag is read, so you would have to replace that with a loop that jumps out if the Dat_p goes high, then have a timer for when the last tag was read, and clears the values based on that. It shouldn't be too difficult.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-11 16:21
    This is untested, but I think something close to this will work, replace the WAITPEQ line with this:
    waitrfid
                            TEST    Dat_p, INA      WC      ' test Dat_p
                  IF_C      JMP     #moveon                 ' if it is high, go to rest of program
    
                            MOV     waitlen, cnt            ' get now
                            ADDS    waitlen, strt           ' difference of start and now
                            CMP     waitlen, waitprd WZ, WC ' if a waitperiod hasn't passed, do another loop
                  IF_B      JMP     #waitrfid               ' do it again!             
    
                            WRWORD  negone, tagnoAddr       ' put -1 (actually 32767 into the tag number (maybe you should use 0?)
                            WRBYTE  zero, doutAddr          ' put 0 into the output value
                            '' write a loop here to clear the tag string if you need it. 
    
                            WAITPEQ Dat_p, Dat_p            ' if there's no need to wait for time to pass, just wait high
    moveon
    


    And add this right after BigLoop:
    MOV     strt, cnt               ' start timer
                            NEG     strt, strt              ' get negative (used in place of SUB later on)
    
  • ErlendErlend Posts: 612
    edited 2013-03-13 12:40
    Bobb,
    Just to make sure I've got it (I never did get a grip on assembly, nor on Forth), here's the stiched together code:
    DAT
    
                            ORG
    entry                                       
                            MOV     p1, PAR
                            SHR     p1, #1
                            
                            RDWORD  DoutAddr, p1            ' get address
    
                            ADD     p1, #2
                            RDWORD  tagnoAddr, p1           ' get address
                            
                            ADD     p1, #2
                            RDWORD  TagAddr, p1             ' get address
                            MOV     TagAddr2, TagAddr       ' save copy
    
                            ADD     p1, #2
                            RDWORD  tagsAddr, p1            ' get address
                            MOV     tagsAddr2, tagsAddr     ' save copy    
    
                            MOV     DeltaT2, DeltaT  
                            SHR     DeltaT2, #1      
                            ADD     DeltaT2, DeltaT  
                            SUB     DeltaT2, #4             ' DeltaT2 := DeltaT / 2 + DeltaT - 4
    
                            MOV     OUTA, En_p       
                            MOV     DIRA, En_p       
    
    BigLoop                 MOV     strt, cnt               ' start timer
                            NEG     strt, strt              ' get negative (used in place of SUB later on)
                            MOV     time, cnt     
                            ADD     time, pauselen
                            WAITCNT time, #0                ' kind of debounce for RFID
                            
                            MOVD    set_tag, #tag
                            MOV     TagAddr, TagAddr2       ' restore backup
    
    ReadRFID                MOV     idx1, #12               ' recieve 12 bytes (only middle 10 are used)
                            MOV     OUTA, #0                ' /enable RFID         
    
    waitrfid               waitrfid
                            TEST    Dat_p, INA      WC      ' test Dat_p
                  IF_C      JMP     #moveon                 ' if it is high, go to rest of program
    
                            MOV     waitlen, cnt            ' get now
                            ADDS    waitlen, strt           ' difference of start and now
                            CMP     waitlen, waitprd WZ, WC ' if a waitperiod hasn't passed, do another loop
                  IF_B      JMP     #waitrfid               ' do it again!             
    
                            WRWORD  zero, tagnoAddr         ' put 0 into the tag number
                            WRBYTE  zero, doutAddr          ' put 0 into the output value
                            '' write a loop here to clear the tag string if you need it. 
    
                            WAITPEQ Dat_p, Dat_p            ' if there's no need to wait for time to pass, just wait high
    
    moveon                  WAITPNE Dat_p, Dat_p            ' wait low
                            MOV     time, cnt               ' mark time
                            MOV     OUTA, En_p              ' shutdown RFID as soon as possible
    
                            MOV     idx2, #8                ' get eight bits    
                            MOV     val_out, #0             ' clear last value
    
                            ADD     time, DeltaT2           ' wait for middle of first bit (and all subsequent bits)
    getbit                        
                            WAITCNT time, DeltaT            ' wait for center of next bit
                            TEST    Dat_p, INA      WC  
                            RCL     val_out, #1             ' shift value in (LSB first)
                            DJNZ    idx2, #getbit
                                                   
                            REV     val_out, #24            ' reverse byte
    set_tag                 MOV     tag, val_out            
                            WRBYTE  val_out, TagAddr        ' write to hub so parent object can see which RFID
                            ADD     TagAddr, #1
                            ADD     set_tag, add1dest
                            DJNZ    idx1, #waitrfid
    
                            MOV     TagAddr, TagAddr2       ' restore backup
                            TJZ     tagc2, #nocheck         ' if no tags to check
                            MOV     tagsAddr, tagsAddr2     ' restore backup
    
    
    mainloop                MOV     tagc, tagc2             ' restore backup
    
    bloop                   MOVD    cmp_bytes, #tag+1
                            MOV     idx, #10                ' check 10 bytes
                            
    check_byte              RDBYTE  tagsbyte, tagsAddr      ' byte from DAT section below
                            ADD     tagsAddr, #1
                                         
    cmp_bytes               CMP     tag, tagsbyte     WZ, NR
                            ADD     cmp_bytes, add1dest
    
                  IF_NZ     JMP     #skip_tag               ' if one byte is wrong, skip the rest of tag
                  
                            DJNZ    idx, #check_byte
                                                    
                            MOV     p1, tagc2
                            ADD     p1, #1         
                            SUB     p1, tagc                ' calculate RFID tag number
                            WRWORD  p1, tagnoAddr
                            MOV     p1, #|< 0               ' RFID match
                            WRBYTE  p1, DoutAddr
                            JMP     #BigLoop                ' on success, back to beginning
    
    skip_tag_ret            DJNZ    tagc, #bloop            ' check next tag
    
                            WRBYTE  zero, tagnoAddr
    nocheck                 MOV     p1, #|< 1               ' no matching RFID
                            WRBYTE  p1, DoutAddr
                            JMP     #BigLoop                ' after failure, back to beginning
    
                            
    skip_tag                ADD     tagsAddr, idx           ' move to next tag address
                            SUB     tagsAddr, #1 
                            JMP     #skip_tag_ret
    
    
                                          
    deltaT                  LONG    0  
    pauselen                LONG    0
    add1dest                LONG    1 << 9 
    zero                    LONG    0
    tagc2                   LONG    0
    Dat_p                   LONG    0
    En_p                    LONG    0
    
    DeltaT2                 RES
    tag                     RES     12
    tagc                    RES
    tagsbyte                RES 
    
    DoutAddr                RES
    tagnoAddr               RES
    tagsAddr                RES
    tagsAddr2               RES
    TagAddr                 RES
    TagAddr2                RES  
    
    p1                      RES
    idx                     RES
    idx1                    RES
    idx2                    RES
    time                    RES
    val_out                 RES
    
                            FIT
    
    DAT                        
                    '' Key#         Key Byte values   Key ID
            tags       {1}  byte    "1234567890"    ' 0098765432
                       {2}  byte    "2345678901"    ' 0087654321
                       {3}  byte    "3456789012"    ' 0076543210
                       {4}  byte    "4567890123"    ' 0065432109
                       {5}  byte    $23, $89, $6F, $58, $69, $11, $12, $A2, $7C, $41 ' 0023569832
                       {6}  byte    "5678901234"    ' 0054321098
    

    Must admit I cannot follow it more than I can understand German, i.e. some. Where is tagno (:= tag_retAddr) given a value? And where&how is waitprd defined? And I cannot find tags (DAT) anywhere in the code.
    Sorry for being PAStupidM.

    Erlend
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-13 13:09
    No problem, assembly languages are notoriously difficult to learn because they are so unlike any other programming language (except other ASM languages).
    Though they help you appreciate what the high-level languages you are used to working with actually do behind the scenes (almost all high-level languages break down to languages like PASM -- SPIN is no exception).

    It looks like you have the program how I described, but I am unsure it will work. I may be able to test it later today or tomorrow, and get it to work if it isn't (let me know).

    Just to answer your questions:

    tagnoAddr is assigned an address in SPIN, and the COG gets that address during initialization on line RDWORD tagnoAddr, p1. Then the value is populated on this line: WRWORD p1, tagnoAddr where p1 is the assigned value, and is calculated by the few lines before it. For WRWORD, the first value (the source) is the value written, and the second value (the destination) is the HUB address to write it to.

    WAITPEQ, or more importantly the Dat_p (a 32-bit mask where specific bits are assigned to instruct it to wait for specific pins -- i.e. if you wait for pin 3 to go high, Dat_p has a value of %...000_0000_1000) register is assigned all the way back up in the SPIN code that starts the COG. You can store values to the DAT section in SPIN (which is a HUB address), then when the cog is started, those values are loaded into the COG as a local variable (changing the value in the PASM cog won't affect the HUB value). The mask is assigned using the |< operator.

    The tags address is passed by assigning the tagcheckAddr variable. And as with tagnoAddr, the address is gathered when the COG starts on this line: RDWORD TagAddr, p1. Though, just the address is passed, the values are read from the HUB memory each time a tag is read using this line: RDBYTE tagsbyte, tagsAddr. This means the tags could actually be changed after the COG has started and the new tags would then be compared.
  • ErlendErlend Posts: 612
    edited 2013-03-18 00:40
    Learning about PASM, but I still have some way to go. I've put this on the background learning process. I need to read about PASM. In the mean time I am writing code to do the same thing using spin, and adding other functions too.

    Erlend
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-18 15:51
    Here you go, it resets the output and tag number to 0 (do you need the tag value to be errased?) the amount of time is set using parameters,
    PUB start_rfid (Ser_p, Ena_p, outputAddr, rec_tagAddr, tag_retAddr, tagcount, tagloc, debounce, resettime)
    '' Start RFID Cog.
    ''******************************************
    ''* Ser_p is RFID serial data line
    ''* Ena_P is RFID /ENABLE line
    ''* outputAddr is address of byte or longer, returns %01 on RFID match, %10 on read, but no RFID match
    ''* rec_tagAddr is address of 12 bytes (array) where to place recieved RFID tag (regaurdless of valid or not)
    ''* tag_retAddr is address of word or longer, where matching tag number is returned (1 through NO_OF_TAGS -- 0 on no match)
    ''* tagcount is the number of tags to recognize, needs to match the table supplied
    ''* tagloc is 0 for when using tags table at bottom of this program, else it is an address of a tag table (same format as below)
    ''* debounce is the number of seconds after a card is read before the program continues
    ''* resettime is the number of seconds (correct timing only if same or longer than debounce) before the output and rec_tag get reset. 0 will disable this feature. 
    ''******************************************
            
      stop
                                    
      pauselen := (clkfreq * debounce) #> 9                 ' time to "debounce" RFID reads so a card doesn't get read twice in quick succession (minimum 9 clocks)
      waitprd := clkfreq * resettime 
    
      enable_p := Ena_p 
      Dat_p := |< Ser_p
      En_P := |< Ena_p    
      tagc2 := tagcount
      
      Dout := outputAddr
      tagno := tag_retAddr      
      outtagAddr := rec_tagAddr 
      
      IF (tagloc == 0)
        tagcheckAddr := @tags
      ELSE
        tagcheckAddr := tagloc
    
      deltaT := clkfreq / 2400             
                                   
    
      cogon := (cog := cognew(@entry, @Dout << 1)) > 0 
      
      RETURN cogon
    
    PUB stop
    '' Stop cogs if already in use.
    
      if cogon~      
        cogstop(cog)   
    
    PUB disable
    '' Disable RFID reader by setting the /ENABLE pin high
    
      IF (cogon)
        OUTA[enable_p]~~
        DIRA[enable_p]~~ 
    
    PUB enable
    '' Enable RFID reader by setting IO as input (allowing PASM cog to control the /ENABLE pin)
    
      IF (cogon)        
        DIRA[enable_p]~
      
    
    DAT
    
                            ORG
    entry                                       
                            MOV     p1, PAR
                            SHR     p1, #1
                            
                            RDWORD  DoutAddr, p1            ' get address
    
                            ADD     p1, #2
                            RDWORD  tagnoAddr, p1           ' get address
                            
                            ADD     p1, #2
                            RDWORD  TagAddr, p1             ' get address
                            MOV     TagAddr2, TagAddr       ' save copy
    
                            ADD     p1, #2
                            RDWORD  tagsAddr, p1            ' get address
                            MOV     tagsAddr2, tagsAddr     ' save copy    
    
                            MOV     DeltaT2, DeltaT  
                            SHR     DeltaT2, #1      
                            ADD     DeltaT2, DeltaT  
                            SUB     DeltaT2, #4             ' DeltaT2 := DeltaT / 2 + DeltaT - 4
    
                            MOV     OUTA, En_p       
                            MOV     DIRA, En_p       
    
    BigLoop
                            MOV     strt, cnt               ' start timer
                            NEG     strt, strt              ' get negative (used in place of SUB later on)                             
    
                            MOV     time, cnt     
                            ADD     time, pauselen
                            WAITCNT time, #0                ' kind of debounce for RFID
                            
                            MOVD    set_tag, #tag
                            MOV     TagAddr, TagAddr2       ' restore backup
    
    ReadRFID                MOV     idx1, #12               ' recieve 12 bytes (only middle 10 are used)
                            MOV     OUTA, #0                ' /enable RFID         
    
    nextbyte
                            WAITPEQ Dat_p, Dat_p            ' high is initiated when RFIT starts
    
    waitrfid
                            TJZ     waitprd, #wait          ' if not setup to reset, just wait
                            TEST    Dat_p, INA      WC      ' test Dat_p
                  IF_NC     JMP     #moveon                 ' if it is low, go to rest of program
    
                            MOV     waitlen, cnt            ' get now
                            ADDS    waitlen, strt           ' difference of start and now
                            CMP     waitlen, waitprd WZ, WC ' if below one waitperiod, do another loop
                  IF_B      JMP     #waitrfid               ' do it again!             
    
                            WRBYTE  zero, DoutAddr          ' put 0 into the output value
                            WRWORD  zero, tagnoAddr         ' put -1 (actually 65535 into the tag number (maybe you should use 0?)
                            '' write a loop here to clear the tag string if you need it. 
    wait
                            WAITPNE Dat_p, Dat_p            ' wait low
    moveon
                            MOV     time, cnt               ' mark time
                            MOV     OUTA, En_p              ' shutdown RFID as soon as possible
    
                            MOV     idx2, #8                ' get eight bits    
                            MOV     val_out, #0             ' clear last value
    
                            ADD     time, DeltaT2           ' wait for middle of first bit (and all subsequent bits)
    getbit                        
                            WAITCNT time, DeltaT            ' wait for center of next bit
                            TEST    Dat_p, INA      WC      ' test pin
                            RCL     val_out, #1             ' shift value in (LSB first)
                            DJNZ    idx2, #getbit           ' get next bit
                                                   
                            TJZ     val_out, #BigLoop       ' if false read (recieves 0 value), send back to beginning
                            REV     val_out, #24            ' reverse byte
    set_tag                 MOV     tag, val_out            
                            WRBYTE  val_out, TagAddr        ' write to hub so parent object can see which RFID
                            ADD     TagAddr, #1
                            ADD     set_tag, add1dest
                            DJNZ    idx1, #nextbyte         ' go to next byte
    
                            MOV     TagAddr, TagAddr2       ' restore backup
                            TJZ     tagc2, #nocheck         ' if no tags to check
                            MOV     tagsAddr, tagsAddr2     ' restore backup
    
    
    mainloop                MOV     tagc, tagc2             ' restore backup
    
    bloop                   MOVD    cmp_bytes, #tag+1
                            MOV     idx, #10                ' check 10 bytes
                            
    check_byte              RDBYTE  tagsbyte, tagsAddr      ' byte from DAT section below
                            ADD     tagsAddr, #1
                                         
    cmp_bytes               CMP     tag, tagsbyte     WZ, NR
                            ADD     cmp_bytes, add1dest
    
                  IF_NZ     JMP     #skip_tag               ' if one byte is wrong, skip the rest of tag
                  
                            DJNZ    idx, #check_byte
                                                    
                            MOV     p1, tagc2
                            ADD     p1, #1         
                            SUB     p1, tagc                ' calculate RFID tag number
                            WRWORD  p1, tagnoAddr
                            RDBYTE  p1, DoutAddr
                            OR      p1, #|< 0               ' RFID match
                            WRBYTE  p1, DoutAddr
                            JMP     #BigLoop                ' on success, back to beginning
    
    skip_tag_ret            DJNZ    tagc, #bloop            ' check next tag
    
                            WRBYTE  zero, tagnoAddr
    nocheck                 RDBYTE  p1, DoutAddr
                            OR      p1, #|< 1               ' no matching RFID
                            WRBYTE  p1, DoutAddr
                            JMP     #BigLoop                ' after failure, back to beginning
    
                            
    skip_tag                ADD     tagsAddr, idx           ' move to next tag address
                            SUB     tagsAddr, #1 
                            JMP     #skip_tag_ret
    
    
                                          
    deltaT                  LONG    0  
    pauselen                LONG    0
    add1dest                LONG    1 << 9 
    zero                    LONG    0
    tagc2                   LONG    0
    Dat_p                   LONG    0
    En_p                    LONG    0
    waitprd                 LONG    0
    
    waitlen                 RES
    strt                    RES
    
    DeltaT2                 RES
    tag                     RES     12
    tagc                    RES
    tagsbyte                RES 
    
    DoutAddr                RES
    tagnoAddr               RES
    tagsAddr                RES
    tagsAddr2               RES
    TagAddr                 RES
    TagAddr2                RES  
    
    p1                      RES
    idx                     RES
    idx1                    RES
    idx2                    RES
    time                    RES
    val_out                 RES
    
                            FIT
    
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-03-18 16:55
    And if you add:
    CMP     tag, lead_byte  WZ      ' make sure tag value has a valid first byte
                  IF_Z      CMP     tag+11, end_byte WZ, NR ' make sure tag value has a valid last byte
                  IF_NZ     JMP     #BigLoop                ' if not valid, go back to beginning
    
    ...before bloop, and:
    lead_byte               LONG    $0A ' (10 / LF)
    end_byte                LONG    $0D ' (13 / CR)
    
    ...after waitprd, you get a valid RFID card test.

    I have had some errant RFID reads from due to interference or the card being on the edge of reception, so this will help (I'll be adding this and the debounce parameter to a soon to be released update on the OBEX).
  • ErlendErlend Posts: 612
    edited 2013-03-19 00:41
    Bobb,

    Thanks a thousand. I'll sit down with this code and the textbook PASMchapter until I understand it all. But, I need to learn to walk before I fly, and I am still in the learning process wrt the COG mechanism and how it relates to the Main code. My background is from Pascal, some C, and digital Control System programming - all quite high level abstract languages - and a looong time ago. With ideas, logical flow, and program control I am fine, but the stuff specific to prop must be learned - which is part of the fun for sure. For me the prop's cog functionality is perfect because it allows me to put all the hard labor housekeeping code into 'independent lives', and concentrate on implementing my ideas in the Main code, keeping it uncluttered.
    A bit off-topic, I guess.

    Erlend
Sign In or Register to comment.