Shop OBEX P1 Docs P2 Docs Learn Events
Reading DEX files with propeller. Need some help with code. — Parallax Forums

Reading DEX files with propeller. Need some help with code.

Don MDon M Posts: 1,654
edited 2011-09-12 15:50 in Propeller 1
I am working on a project to read a DEX file from a Vending Machine Controller (VMC). DEX files contain audit data for transactions in a vending machine. It utilizes a 9600 baud 8 bit data link. Nothing fancy. The data is standard ASCII characters and contains line feeds and carriage returns for formatting.

I have tried to condense as much as possible my code to read in the data. Maybe too much :)

The data stream has a max limit of 245 characters. The messages start with a $10 (DLE) $02 (STX) ... ASCII DATA... $10 (DLE) $17 (ETB) then a 2 byte CRC-16 checksum The data block is then ACK'd by the VMC with a DLE 1 ($10 $31) the first time then a DLE 0 then next time then back to a DLE 1. The ACK alternates between DLE 1 and DLE 0 starting with a DLE 1.

My problem lies beginning in this section. See below:
    inx := 1                                            ' initialize index counter to 1
                                                        
    i := dex.rxtime(20)                                 ' receive in dex data and assign it to variable i
      if i == $10                                       ' check to see if byte is DLE
        i := dex.rx                                     ' receive in next byte
         if i == $02                                    ' check to see if next byte is STX. if so start repeat loop
            repeat until i == $10                       ' do repeat until byte received is DLE then quit
              i := dex.rx                               ' receive in nexy byte and assign to variable i
              dexdata[inx] := i                         ' assign received byte i to dexdata variable indexed by index counter inx
              term.tx(dexdata[inx])                     ' send data byte to terminal for printing
              inx += 1                                  ' increment index counter
              
    dex.tx($10)                                         ' send ACK - DLE 1
    dex.tx($31)                                         ' ACK's alternate between DLE 0 and DLE 1

    inx := 1                                            ' repeat process again for next batch of data
    
    i := dex.rxtime(20)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1
              
    dex.tx($10)                                         ' send ACK - DLE 0
    dex.tx($30)

    inx := 1                                            ' repeat process again for next batch of data
    
    i := dex.rxtime(250)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1

    dex.tx($10)
    dex.tx($31)

It sends the ACK's all in a row without waiting for the data block to be received in. I think it has somethng to do with my logic of looking for a DLE ($10) since it is in the beginning and end of a block.

Also I don't know what happens to the end DLE ETB and 2 byte checksum.

Here's the full code I worite. Don't laugh as I am vey much a novice at this yet.
'' =================================================================================================
''
''   File....... DEX_Prop.spin
''   Purpose.... DEX Reader
''   Author..... Don Merchant
''               -- see below for terms of use
''   E-mail..... 
''   Started.... 06 SEP 2011
''   Updated.... 08 SEP 2011  This version excluded PST control and prints data in ASCII format
''
'' =================================================================================================


con

  _clkmode        = xtal1 + pll16x                      ' Feedback and PLL multiplier
  _xinfreq        = 5_000_000                           ' External oscillator = 5 MHz


  MS_001   = 80_000_000 / 1_000                         ' ticks in 1ms 

  DEX_TX = 0                                            ' DEX -> VMC
  DEX_RX = 1                                            ' VMC -> DEX

  

obj

  dex   : "fullduplexserialplus"                                       
  term  : "fullduplexserialplus"


var

  byte  dexstrng[24], dexdata[245]

  
pub main   | i, d, inx 

  term.start(31, 30, %0000, 115_200)                    ' start terminal (use PST)
  dex.start(1, 0, %0000, 9_600)                         ' start DEX read

  pause (1000)                                          ' pause for PST to start
  
  
    dex.tx($05)                                         ' send ENQ to start
    term.str(string("Start DEX_Prop Ver 0.2", 13))
    i := dex.rxtime(100)                                ' look for response from VMC
    if i == $10                                         ' if DLE received from VMC start handshake
       i := dex.rx
       if i == $30
          term.str(string("Start 1st Handshake", 13))
          dex.tx($10)                                   ' send DLE
          pause(15)
          dex.tx($01)                                   ' send SOH
          pause(15)
          dex.str(string("1234567890RR01L01"))          ' send string
          pause(15)
          dex.tx($10)                                   ' send DLE
          pause(15)
          dex.tx($03)                                   ' send ETX
          pause(15)
          dex.tx($DE)                                   ' send upper byte of CRC checksum
          pause(15)
          dex.tx($4D)                                   ' send lower byte of CRC checksum
          pause(15)
       else
          term.str(string(2, 1, 3, "No response"))      ' If no DLE received from VMC then indicate no communication
          
    i := dex.rx                                         ' In this section we look for a DLE response from the VMC to end first handshake
     
    if i == $15
       term.str(string(2, 1, 5, "NAK"))                 ' if checksum isn't right let us know
    else
      if i == $10
         i := dex.rx
         if i == $31
            term.str(string("First Handshake Successful", 13))
            dex.tx($04)                                  ' send EOT
      else
          term.str(string(2, 1, 5, "Didn't recognize DLE..."))

    i := dex.rx

    if i == $05                                         ' look for ENQ
       term.str(string("Start 2nd Handshake"))
       dex.tx($10)                                      ' acknowledge the ENQ by sending DLE 0
       dex.tx($30)     
    else
       term.str(string(2, 1, 7, "Didn't recognize ENQ..."))

    pause(15)
  
    inx := 1                                            ' receive id data from VMC but do nothing with it
    repeat 24
      i := dex.rxtime(40)
      dexstrng[inx] := i
      'term.tx(dexstrng[inx])   
      inx += 1

    term.tx(13)
    dex.tx($10)
    dex.tx($31)
    
    i := dex.rxtime(100)                                ' look for response from VMC
    if i == $04                                         ' if DLE received from VMC start handshake
       term.str(string("Second Handshake Successful", 13))
       i := dex.rx
       if i == $05
          term.str(string("Begin DEX dump from VMC...", 13))
          dex.tx($10)
          dex.tx($30)

    inx := 1                                            ' initialize index counter to 1
                                                        
    i := dex.rxtime(20)                                 ' receive in dex data and assign it to variable i
      if i == $10                                       ' check to see if byte is DLE
        i := dex.rx                                     ' receive in next byte
         if i == $02                                    ' check to see if next byte is STX. if so start repeat loop
            repeat until i == $10                       ' do repeat until byte received is DLE then quit
              i := dex.rx                               ' receive in nexy byte and assign to variable i
              dexdata[inx] := i                         ' assign received byte i to dexdata variable indexed by index counter inx
              term.tx(dexdata[inx])                     ' send data byte to terminal for printing
              inx += 1                                  ' increment index counter
              
    dex.tx($10)                                         ' send ACK - DLE 1
    dex.tx($31)                                         ' ACK's alternate between DLE 0 and DLE 1

    inx := 1                                            ' repeat process again for next batch of data
    
    i := dex.rxtime(20)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1
              
    dex.tx($10)                                         ' send ACK - DLE 0
    dex.tx($30)

    inx := 1                                            ' repeat process again for next batch of data
    
    i := dex.rxtime(250)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1

    dex.tx($10)
    dex.tx($31)

    inx := 1
    
    i := dex.rxtime(250)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1

    dex.tx($10)
    dex.tx($30)

    inx := 1
    
    i := dex.rxtime(250)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1

    dex.tx($10)
    dex.tx($31)

    inx := 1
    
    i := dex.rxtime(250)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1

    dex.tx($10)
    dex.tx($30)

    inx := 1
    
    i := dex.rxtime(250)
      if i == $10
         i := dex.rx
         if i == $02
            repeat until i == $10
              i := dex.rx
              dexdata[inx] := i
              term.tx(dexdata[inx])
              inx += 1

    term.tx(13)
    dex.tx($10)
    dex.tx($31)

    i := dex.rx                                         ' look for EOT to end routine                               
    if i == $04
       term.str(string(" DEX finished"))
           

                         
pub pause(ms) | t

'' Delays program for ms milliseconds

  t := cnt
  repeat ms
    waitcnt(t += MS_001)

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-09-08 13:26
    Don,

    I don't have time to look over your code but I do wonder if FullDuplexSerial could be causing you trouble because of its small buffer.

    I posted a modified version of Tim Moore's four port driver with a 512 byte rx buffer. You should be able to safely receive the whole message and then manipulate it after it has all arrived.

    Post #9 of the thread is a modification I frequently use. The driver monitors for an end of message flag so the parent object knows when a complete message has arrived.

    Duane
  • Don MDon M Posts: 1,654
    edited 2011-09-08 14:08
    Duane- I had a previous version of my code that does receive all the data in with no problem. Here is a copy of that. FullDuplexSerial seemed to work fine. But then hey- I'm not the expert here...
    '' =================================================================================================
    ''
    ''   File....... DEX_Prop.spin
    ''   Purpose.... DEX Reader
    ''   Author..... Don Merchant
    ''               -- see below for terms of use
    ''   E-mail..... 
    ''   Started.... 06 SEP 2011
    ''   Updated.... 08 SEP 2011  This version excluded PST control and prints data in ASCII format
    ''
    '' =================================================================================================
    
    
    con
    
      _clkmode        = xtal1 + pll16x                      ' Feedback and PLL multiplier
      _xinfreq        = 5_000_000                           ' External oscillator = 5 MHz
    
    
      MS_001   = 80_000_000 / 1_000                         ' ticks in 1ms 
    
      DEX_TX = 0                                            ' DEX -> VMC
      DEX_RX = 1                                            ' VMC -> DEX
    
      
    
    ''     Parallax Serial Terminal
    ''    Control Character Constants
    ''-------------------------------------
    ''  CS = 16  ''CS: Clear Screen      
    ''  CE = 11  ''CE: Clear to End of line     
    ''  CB = 12  ''CB: Clear lines Below 
    
    ''  HM =  1  ''HM: HoMe cursor       
    ''  PC =  2  ''PC: Position Cursor in x,y          
    ''  PX = 14  ''PX: Position cursor in X         
    ''  PY = 15  ''PY: Position cursor in Y         
    
    ''  NL = 13  ''NL: New Line        
    ''  LF = 10  ''LF: Line Feed       
    ''  ML =  3  ''ML: Move cursor Left          
    ''  MR =  4  ''MR: Move cursor Right         
    ''  MU =  5  ''MU: Move cursor Up          
    ''  MD =  6  ''MD: Move cursor Down
    ''  TB =  9  ''TB: TaB          
    ''  BS =  8  ''BS: BackSpace          
               
    ''  BP =  7  ''BP: BeeP speaker
    obj
    
      dex   : "fullduplexserialplus"                                       
      term  : "fullduplexserialplus"
    
    
    var
    
      byte  dexstrng[24], dexdata[245]
    
      
    pub main   | i, inx 
    
      term.start(31, 30, %0000, 115_200)                   ' start terminal (use PST)
      dex.start(1, 0, %0000, 9_600)                        ' start DEX read
    
      pause (1000)
      'term.tx(16)
      
         
    '  repeat
      
        dex.tx($05)                                         ' send ENQ to start
        term.str(string("Start DEX_Prop Ver 0.2", 13))
        i := dex.rxtime(100)                                ' look for response from VMC
        if i == $10                                         ' if DLE received from VMC start handshake
           i := dex.rx
           if i == $30
              term.str(string("Start 1st Handshake", 13))
              dex.tx($10)                                   ' send DLE
              pause(15)
              dex.tx($01)                                   ' send SOH
              pause(15)
              dex.str(string("1234567890RR01L01"))          ' send string
              pause(15)
              dex.tx($10)                                   ' send DLE
              pause(15)
              dex.tx($03)                                   ' send ETX
              pause(15)
              dex.tx($DE)                                   ' send upper byte of CRC checksum
              pause(15)
              dex.tx($4D)                                   ' send lower byte of CRC checksum
              pause(15)
           else
              term.str(string(2, 1, 3, "No response"))      ' If no DLE received from VMC then indicate no communication
              
        i := dex.rx                                         ' In this section we look for a DLE response from the VMC to end first handshake
         
        if i == $15
           term.str(string(2, 1, 5, "NAK"))                 ' if checksum isn't right let us know
        else
          if i == $10
             i := dex.rx
             if i == $31
                term.str(string("First Handshake Successful", 13))
                dex.tx($04)                                  ' send EOT
          else
              term.str(string(2, 1, 5, "Didn't recognize DLE..."))
    
        i := dex.rx
    
        if i == $05                                         ' look for ENQ
           term.str(string("Start 2nd Handshake"))
           dex.tx($10)                                      ' acknowledge the ENQ by sending DLE 0
           dex.tx($30)     
        else
           term.str(string(2, 1, 7, "Didn't recognize ENQ..."))
    
        pause(15)
      
        inx := 1
        repeat 24
          i := dex.rxtime(40)
          dexstrng[inx] := i
          'term.tx(dexstrng[inx])   
          inx += 1
    
        term.tx(13)
        dex.tx($10)
        dex.tx($31)
        
        i := dex.rxtime(100)                                ' look for response from VMC
        if i == $04                                         ' if DLE received from VMC start handshake
           term.str(string("Second Handshake Successful", 13))
           i := dex.rx
           if i == $05
              term.str(string("Begin DEX dump from VMC...", 13))
              dex.tx($10)
              dex.tx($30)
    
        inx := 1                                            ' Routine needs to look for DLE ETB ($10, $17) before checksum
        repeat 239                                          ' and then determine whether to send a $10 $30 or $10 $31 to 
          i := dex.rxtime(250)                              ' start next block of data and to set how long the repeat goes
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)                         ' If it finds a DLE ETX ($10, $03) then it should signal end of DEX transmission
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1
    
        'term.tx($0D)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($31)
    
        inx := 1
        repeat 236
          i := dex.rxtime(250)
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1
                
        'term.tx($0D)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($30)
    
        inx := 1
        repeat 236
          i := dex.rxtime(250)
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1
    
        'term.tx($0D)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($31)
    
        inx := 1
        repeat 236
          i := dex.rxtime(250)
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1      
    
        'term.tx($0D)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($30)
    
        inx := 1
        repeat 236
          i := dex.rxtime(250)
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1
    
        'term.tx($0D)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($31)
    
        inx := 1
        repeat 236
          i := dex.rxtime(250)
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1
    
        'term.tx($0D)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($30)
    
        inx := 1
        repeat 46
          i := dex.rxtime(250)
          dexdata[inx] := i
          'term.hex(dexdata[inx], 2)
          term.tx(dexdata[inx])
          'term.tx($20)
          inx += 1
    
        term.tx(13)
        'term.tx($0D)
        dex.tx($10)
        dex.tx($31)
    
        i := dex.rx                                
        if i == $04
           term.str(string(" DEX finished"))
               
    
                             
    pub pause(ms) | t
    
    '' Delays program for ms milliseconds
    
      t := cnt
      repeat ms
        waitcnt(t += MS_001)
      
    
  • rosco_pcrosco_pc Posts: 468
    edited 2011-09-08 19:24
    I think that your first problem is that you send back an ACK even if you have not received any usefull data.
    I personally would do something like this (completely untested):
      ...
      repeat
        if receive(@dexstr, ACK_token)  ' ALternate ACK-token s needed
          ' Do something with the data received
        else
          ' Error recovery actions
      ...
          
    PUB receive(inx, token) | checksum, dle_rec, start
      '' Receive data from DEX source, Keep looping until data received
      ''
      '' Returns TRUE when valid data received
      '' Returns FALSE when checksum failure or too much data received
      start := inx
      repeat                              ' keep looping until we receive data
        repeat until dex.rx == $10        ' Wait for DLE 
        if dex.rx == $02                  ' Check that next data is STX
          repeat 245                      ' Check for max size
            i := dex.rx
            case i
              $10:                        ' DLE
                dle_rec := i              ' Save received byte
              $17:                        ' ETB
                if dle_rec                ' Did we receive DLE before?
                  checksum := dex.rx << 8 ' Get CRC-16 checksum
                  checksum += dex.rx
                  if crc-16(start, inx-start, checksum)  ' Check if received data is OK 
                    term.str(string("Data OK",13))
                    ' Send ACK
                    dex.tx($10)           ' Send DLE
                    dex.tx(token)         ' Send ACK token
                    return true
                  else
                    term.str(string("Wrong checksum",13))
                    return false          ' Something went wrong no ACK sent
                else
                  BYTE[inx++] := i        ' Store received data
              other:
                if prev
                  BYTE[inx++] := dle_rec  ' Store DLE as no ETB was received
                  dle_rec~                ' Clear dle_rec
                BYTE[inx++] := i          ' Store data received
          term.str(string("Too much data received",13))
          return false                        ' Too much data received, no ACK send
    
      
    PUB CRC-16(inx, size, checksum)
      ' Check CRC-16 chechsum
      ...
    
  • Don MDon M Posts: 1,654
    edited 2011-09-09 08:01
    To give a better visual understanding of what I'm having trouble with-

    Here's the code portion that works and a logic trace of the result-
        inx := 1                                            
        repeat 239                                          
          i := dex.rxtime(250)                              
          dexdata[inx] := i
          term.tx(dexdata[inx])
          inx += 1
    
        dex.tx($10)
        dex.tx($31)
    

    Ver 0_2 trace.jpg


    Here's the code that gives me trouble and a logic trace of its result. You can see all the ACK's it sends in a row unlike the code above-
        inx := 1                                            ' initialize index counter to 1
                                                            
        i := dex.rxtime(20)                                 ' receive in dex data and assign it to variable i
          if i == $10                                       ' check to see if byte is DLE
            i := dex.rx                                     ' receive in next byte
             if i == $02                                    ' check to see if next byte is STX. if so start repeat loop
                repeat until i == $10                       ' do repeat until byte received is DLE then quit
                  i := dex.rx                               ' receive in nexy byte and assign to variable i
                  dexdata[inx] := i                         ' dexdata variable indexed by index counter inx
                  term.tx(dexdata[inx])                     ' send data byte to terminal for printing
                  inx += 1                                  ' increment index counter
                  
        dex.tx($10)                                         ' send ACK - DLE 1
        dex.tx($31)                                         ' ACK's alternate between DLE 0 and DLE 1
    

    Ver 0_3 trace.jpg


    I want to make the second code work as the message length may vary. In the first code I hand coded the message length.

    @rosco_pc- yes I know I am not doing anything with the checksums at this point and just assuming they are correct to get started. I was going to implement them in the next go around after I get this portion to work better. Thanks for your code help. I'll look it over and see what I can learn from it.
    1024 x 171 - 26K
    1024 x 164 - 30K
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-09-09 09:05
    It looks like you're sending acks if several conditions aren't met. Are these acks causing the transmitting line to change?

    I'd think you'd want your "dex.tx($10)" to line up with "repeat until" so you only acknowledged after receiving a full message.

    Duane
  • Don MDon M Posts: 1,654
    edited 2011-09-09 11:18
    I have made a few changes and fixed the multiple ACK's from occuring.
        inx := 1                                            ' initialize index counter to 1
                                                            
        i := dex.rxtime(20)                                 ' receive in dex data and assign it to variable i
          if i == $10                                       ' check to see if byte is DLE
            i := dex.rx                                     ' receive in next byte
             if i == $02                                    ' check to see if next byte is STX. if so start repeat loop
                repeat until i == $10                       ' do repeat until byte received is DLE then quit
                  i := dex.rx                               ' receive in nexy byte and assign to variable i
                  dexdata[inx] := i                         ' assign received byte i to dexdata variable indexed by index counter inx
                  term.tx(dexdata[inx])                     ' send data byte to terminal for printing
                  inx += 1                                  ' increment index counter
                i := dex.rx
                if i == $17
                   pause(2)
                   dex.tx($10)                                         ' send ACK - DLE 1
                   dex.tx($31)                                         ' ACK's alternate between DLE 0 and DLE 1
    

    Now on to more refinement....

    I messed with the code that rosco_pc suggested but I didn't get anywhere with it due to some code needed for CRC-16 calculation which I don't have.... yet.
  • rosco_pcrosco_pc Posts: 468
    edited 2011-09-09 17:53
    There are several implementation floating around here in this forum :) Here is one from Mike Green as found in this old thread http://forums.parallax.com/showthread.php?92895-CRC16-routine-problem
    PUB crc16(buffer,count)
       result := $FFFF
       repeat count
          result ^= byte[buffer++]
          repeat 8
             result := result >> 1 ^ ($A001 & (result & 1 <> 0))
    

    You'll need to change the calling of the crc routine to
    if crc16(start, inx-start) == checksum 
    
    I had never heard of DEX, so I after some quick googling l found some interesting links:
    http://saturn.ece.ndsu.nodak.edu/ecewiki/images/0/06/SD0802Technical_Report.pdf
    http://bonusdata.ch/Download/DEX-UCS/dexucs_english.htm

    First link contains some flow charts on how DEX is supposed to work (there is no source code)
    The second link contains some source code (it's C++ though) and you'll have a reference implementation for DEX.
  • Don MDon M Posts: 1,654
    edited 2011-09-10 15:34
    How do I tell if my rx buffer is getting full? Is there a way to clear it? Let's say that the variable i was assigned to receive data- does i~ clear that variable but not the buffer?

    Is there a command to clear the buffer?
  • Don MDon M Posts: 1,654
    edited 2011-09-10 15:38
    I see there is a method called "rxflush" in fullduplexserial. I tried adding that into my routine but it didn't change anything. The data comes in for just so long then quits.
  • rosco_pcrosco_pc Posts: 468
    edited 2011-09-10 16:47
    Don M wrote: »
    Let's say that the variable i was assigned to receive data- does i~ clear that variable but not the buffer?

    This only clears the variable i (reading from the buffer removes the data)
    I see there is a method called "rxflush" in fullduplexserial. I tried adding that into my routine but it didn't change anything. The data comes in for just so long then quits.
    FDS buffer is 64 byte, do you only get 64 characters? If you get more or less then you most likely have a problem with handshaking.
  • Don MDon M Posts: 1,654
    edited 2011-09-11 06:14
    Here's my latest code loop for receiving in the data:
        inx := 1                                            ' initialize index counter to 1
        ack := 1                                            ' initialize ack counter to 1        
        repeat
           repeat until i == $10                            ' watch for DLE 
              i := dex.rx                                   ' receive data and assign to variable i
               if i == $10                                  ' check to see if byte is DLE
                 i := dex.rx                                ' receive in next byte
                 if i == $02                                ' check to see if next byte is STX to start
                    repeat until i == $10                   ' receive data until second DLE 
                      i := dex.rx                           ' receive next byte to variable i
                      dexdata[inx] := i                     ' received byte i to dexdata indexed by inx
                      term.tx(dexdata[inx])                 ' send data byte to PST
                      inx += 1                              ' increment index counter
                    i := dex.rx                             ' receive next byte to variable i                    
                    if i == $17                             ' watch for ETB
                       inx := 1                             ' reset index counter
                       i~                                   ' clear variable i
                       pause(2)                             ' pause for ACK 
                       dex.tx($10)                          ' send DLE
                       if ack == 1                          ' this routine toggles ACK between
                          dex.tx($31)                       ' $30 and $31 depending on ACK index
                          ack--
                       else
                          dex.tx($30)                                        
                          ack++
                    else
                       if i == $03                          ' else look for ETX
                          pause(2)                          ' pause for ACK 
                          dex.tx($10)                       ' send DLE                   
                          if ack == 1                       ' this routine toggles ACK between
                          dex.tx($31)                       ' $30 and $31 depending on ACK index
                          ack--
                       else
                          dex.tx($30)                                        
                          ack++                                        
                       repeat until i == $04                ' watch for EOT                                                                   
                          i := dex.rx
                          term.str(string("DEX Finished !"))' indicate DEX finished 
                          quit
                       quit
    

    Different manufacturers report different amounts of DEX data. It just so happens that one board I have this whole routine works fine on. It takes approx 5 seconds to go through the whole process. The board I'm having trouble with reports quite a bit more data and runs along fine for about 12 seconds then just hangs. There is a DLE ETB sent from the board but my program then decides not to ACK it for some reason after that time even though it was ACKing fine in the seconds preceeding.
  • Don MDon M Posts: 1,654
    edited 2011-09-11 06:27
    Here's some screen shots from the logic analyzer.

    This one is from the board that the code works fine on. You can see the long data stream on the bottom line and the ACK's on the top line. It then shows the final EOT on the bottom line from the board. Life is good.

    DEX works.jpg


    This is the one from the board that hangs after a while. You can see where the data is ACK'd then it decides not to ACK at the end.

    DEX hangs.jpg


    You'll also notice that the packets of data are shorter on the second board than the first. Maybe that has something to do with it I don't know.
    1024 x 147 - 22K
    1024 x 144 - 22K
  • rosco_pcrosco_pc Posts: 468
    edited 2011-09-11 16:27
    You have some issue with indentation (rght spelling), at least at the end of the routine where you check for ETX, the IF .. ELSE ... for the ACK is wrongly indented. Not sure about the REPEAT loop for EOT.
    ...
                    else
                       if i == $03                          ' else look for ETX
                          pause(2)                          ' pause for ACK 
                          dex.tx($10)                       ' send DLE                   
    		      if ack == 1                       ' this routine toggles ACK between
                             dex.tx($31)                       ' $30 and $31 depending on ACK index
                             ack--
                          else
                             dex.tx($30)                                        
                             ack++                                        
                       repeat until i == $04                ' watch for EOT                                                                   
    ...
    
  • Don MDon M Posts: 1,654
    edited 2011-09-11 19:39
    Rosco-Thanks you are correct. However that still doesn't solve the problem.
  • rosco_pcrosco_pc Posts: 468
    edited 2011-09-12 15:01
    I suspect you get a control character you are not expecting, try printing all data youreceive including all control characters (you can use term.hex(i,2) for that)
  • Don MDon M Posts: 1,654
    edited 2011-09-12 15:50
    I finally got it to work. What I was trying to do initially was to "ignore" the 2 checksum bytes until I get (find) a method working to receive them in and calculate a checksum. I thought I was ignoring them by inserting a i~ and a rxflush in the loop to clean them out but that was not the case. For now I am just accepting them as is.

    What I did to find this problem was to insert some string statements in different strategic points in my code to print on PST. The problem then showed up where it was quitting. Should have thought of this sooner....

    Anyway here is the updated portion that works. I'll work on finding a checksum method that I can add to this.
        ack := 1                                            ' initialize ack counter to 1        
    
           repeat                                           ' watch for DLE 
              i := dex.rxtime(250)                          ' receive data and assign to variable i
               if i == $10                                  ' check to see if byte is DLE
                 term.str(string("DLE1", 13))
                  i := dex.rx                                ' receive in next byte
                 if i == $02                                ' check to see if next byte is STX to start
                    term.str(string("STX", 13))
                    repeat 'until i == $10                   ' receive data until second DLE 
                      i := dex.rx                           ' receive next byte to variable i
                      term.tx(i)                            ' send data byte to PST
                       if i == $10                             ' watch for ETB
                         term.str(string(13, "DLE2", 13))
                         i := dex.rx
                         if i == $17
                            term.str(string("ETB", 13, "Checksum "))
                            i := dex.rx
                            term.hex(i, 2)
                            i := dex.rx
                            term.hex(i,2)
                            term.tx(13)
                            dex.tx($10)                          ' send DLE
                            if ack == 1                          ' this routine toggles ACK between
                               dex.tx($31)                       ' $30 and $31 depending on ACK index
                               ack--
                               quit
                            else
                               dex.tx($30)                                        
                               ack++
                               quit
                         else
                           if i == $03                          ' else look for ETX
                              term.str(string("ETX", 13))
                              pause(2)                          ' pause for ACK 
                              dex.tx($10)                       ' send DLE                   
                              if ack == 1                       ' this routine toggles ACK between
                                 dex.tx($31)                    ' $30 and $31 depending on ACK index
                                 ack--
                                 quit
                              else
                                 dex.tx($30)                                        
                                 ack++
                                 quit                                        
               else
                 if i == $04                ' watch for EOT
                    term.str(string("EOT", 13))
                    term.str(string("DEX Finished !"))' indicate DEX finished 
                    quit
    

    Don't pay much attention to the comments in the code as they are somewhat messed up from editing code.
Sign In or Register to comment.