Shop OBEX P1 Docs P2 Docs Learn Events
Reading a series bytes — Parallax Forums

Reading a series bytes

JCeeJCee Posts: 36
edited 2010-01-21 20:38 in Propeller 1
Is it possible to read data of different sizes (ie byte, long) within an array that is not aligned to with prop memory locations. I am trying to read a long of byte aligned data but the results are backwards.
·
For example I have a GPS string of data that is 16 bytes long.· Some of the data needs to be read as bytes and some as long.· When I read a long, the data is reversed from what I expect.

Long[noparse][[/noparse]@GPS_Data[noparse][[/noparse]0]] 


Dat 
GPS_Data Byte $7E, $71, $D6, $04, $03, $DD, $00, $00, $C4, $05, $00, $00, $A6, $A1, $02, $00

·· Gives $04D6717E
·
· but what I was expecting is $7E71D604

·
Is there a better way to read the data?
What is the fastest way to reverse the order?··

Comments

  • BocephusBocephus Posts: 58
    edited 2010-01-20 19:51
    I haven't worked with GPS but I can show you a way to reverse a long.

    CON
      _clkmode      = xtal1 + pll16x                     
      _xinfreq      = 5_000_000
      
    OBJ
      tv : "tv_text"                                                                        
    
    PUB main | rev_long
      rev_long := $04D6717E
      
      tv.start(13)
      tv.hex(rev_long,8)
      
      cognew(@entry,@rev_long)    
      
      tv.str(string(" Reversed "))  
      tv.hex(rev_long,8) 
    
    DAT    
            org
    entry   rdlong  source,par    
            ror     source,#8     
            and     dest,source   
            ror     source,#16    
            and     source,mask   
            or      dest,source   
             
            wrlong  dest, par    
            
            CogId   mask        
            CogStop mask        
    
    source  long    $00000000
    dest    long    $FF00FF00
    mask    long    $00FF00FF
    
    
  • SamMishalSamMishal Posts: 468
    edited 2010-01-20 20:59
    JCee,

    You are experiencing this because of something called Little-Endian format.

    In the Propeller as in Intel Chips and other microcontrollers a Long (or word) is stored in the Least Significant Byte First order (LSBF)
    or what is called Little-Endian format.

    So if you store 4 bytes A4 65 4B 32 then the number that these 4 bytes represent is actually 324B65A4 = 843802020 (in decimal)

    So when you read bytes through a serial port and they come in the order A4.... then you will need to reverse them as shown by Bocefus
    OR
    you need to store them in the reverse order in the buffer as they come in.





    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Samuel

    www.RobotBASIC.com
    ·
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-20 21:17
    Well ... using PASM to reverse a long might be a waste of a COG when you need them. And maybe it's not necessary because the spee requirements are not to big.

    bytes[noparse][[/noparse] 0 ]:=gps_data[noparse][[/noparse] 3 ]
    bytes[noparse][[/noparse] 1 ]:=gps_data[noparse][[/noparse] 2 ]
    bytes[noparse][[/noparse] 2 ]:=gps_data[noparse][[/noparse] 1 ]
    bytes[noparse][[/noparse] 3 ]:=gps_data[noparse][[/noparse] 0 ]

    ' now long_val contains the reversed long
    .....

    dat
    long_val long
    bytes byte 0[noparse][[/noparse] 4 ]

    gps_data byte .....

    Instead of fixed index for gps_data you can of course use an offset and revert not alligned longs in the middle of the gps_data.
    Only the long_val needs to be alligned.

    This PASM code does not work for unalligned longs.



    PS: sorry ... forgot about the [noparse][[/noparse] ] problem ;o)

    Post Edited (MagIO2) : 1/20/2010 9:22:45 PM GMT

  • Mike GreenMike Green Posts: 23,101
    edited 2010-01-20 23:47
    Neither Spin nor PAsm will work with unaligned values. That means that all longs have to reside on an address that's a multiple of 4 and all words have to reside on an address that's a multiple of 2. That said, you can store longs, words, and bytes all in a byte array and the long values and word values don't have to be aligned, but they have to be treated as bytes. You can assemble two successive bytes into a word and 4 successive bytes into a long using shifts and logical ors like:

    wordValue := byte[noparse][[/noparse] address ][noparse][[/noparse] 0 ] + byte[noparse][[/noparse] address ][noparse][[/noparse] 1 ]<<8

    or

    longValue := byte[noparse][[/noparse] address ][noparse][[/noparse] 0 ] + byte[noparse][[/noparse] address ][noparse][[/noparse] 1 ] << 8 + byte[noparse][[/noparse] address ][noparse][[/noparse] 2 ]<<16 + byte[noparse][[/noparse] address ][noparse][[/noparse] 3 ]<<24
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-01-21 05:49
    @mike:
    I don't see a big difference to my version above except that I don't need the shift operation. The shift is simply omitted by accessing the single bytes inside the long.

    But ... another thing to mention : you did not revert which was a requirement and is needed when you read a big-endian stream and want to use it in the propeller, which stores longs little-endian.
  • JCeeJCee Posts: 36
    edited 2010-01-21 20:38
    Thanks all for the feedback, this spin code looks to be the most straight forward.

    bytes[noparse][[/noparse] 0 ]:=gps_data[noparse][[/noparse] 3 ]
    bytes[noparse][[/noparse] 1 ]:=gps_data[noparse][[/noparse] 2 ]
    bytes[noparse][[/noparse] 2 ]:=gps_data[noparse][[/noparse] 1 ]
    bytes[noparse][[/noparse] 3 ]:=gps_data[noparse][[/noparse] 0 ]
Sign In or Register to comment.