Shop OBEX P1 Docs P2 Docs Learn Events
Please Review; Need Help moving bytes from byte array to longs; — Parallax Forums

Please Review; Need Help moving bytes from byte array to longs;

mre_robmre_rob Posts: 31
edited 2007-05-18 16:00 in Propeller 1
Please review the attached code that is not working.... I am not sure why· but I think it has to do with my mis-understanding of how to move bytes from an array to longs... TIA

The code below is supposed to parse the GPRMC sentence of the Parrallax GPS into a memory map ala Matteo. Thanks to him for all of his support thus far.....

I figured I throw this out for a little help.

Pri ParseGPRMC(PtrSentence)|i, j, idxField, delimiter, delimiter2, tmp
{{
     NMEA 0183 version 3.00 active the Mode indicator field is added
     $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a,m*hh
Field #
1    = UTC time of fix
2    = Data status (A=Valid position, V=navigation receiver warning)
3    = Latitude of fix
4    = N or S of longitude
5    = Longitude of fix
6    = E or W of longitude
7    = Speed over ground in knots
8    = Track made good in degrees True
9    = UTC date of fix
10   = Magnetic variation degrees (Easterly var. subtracts from true course)
11   = E or W of magnetic variation
12   = Mode indicator, (A=Autonomous, D=Differential, E=Estimated, N=Data not valid)
13   = Checksum
 }}
   delimiter:=","
   delimiter2:="*"
   i:=6  'move off of the head to the first ","  
   idxField:=1
   
   objVGA.str(PtrSentence)
    objVGA.out(_crlf)
    
   repeat while i< _sentenceSize and idxField< 13
    j:=0
    longfill(@tmp,0,1)
    repeat while byte[noparse][[/noparse]PtrSentence+i] <> delimiter and i< _sentenceSize and byte[noparse][[/noparse]PtrSentence+i] <> delimiter2
      tmp.byte[noparse][[/noparse]j] := byte[noparse][[/noparse]PtrSentence+i]
      j++
      i++
      
    case (idxField)
       1: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcUtcTime)]:=tmp
       2: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcValid)] :=tmp 
       3: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcLat)]  :=tmp 
       4: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcNs)]  :=tmp 
       5: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcLon)] :=tmp 
       6: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcEw)]  :=tmp 
       7: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcSpeed)] :=tmp 
       8: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcCourse)]  :=tmp 
       9: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcUtcDate)]  :=tmp 
       10: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcVariation)] :=tmp 
       11: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcVarEw)] :=tmp 
       12: long[noparse][[/noparse]constant(objMem#SensorDataAddress + objMem#GprmcMode)] :=tmp    
    idxField++
    'bump i
    i++
  longfill(@tmp,0,1)
  tmp.byte[noparse][[/noparse]0]:= byte[noparse][[/noparse]PtrSentence+i]
  i++
  tmp.byte[noparse][[/noparse]1]:=byte[noparse][[/noparse]PtrSentence+i]
  tmp.byte[noparse][[/noparse]2]:=0
  longMove(long[noparse][[/noparse]objMem#SensorDataAddress + objMem#GprmcCheckSum],@tmp,1)

Comments

  • M. K. BorriM. K. Borri Posts: 279
    edited 2007-05-16 16:41
    You need some way to go from ASCII numbers to actual numeric values, recommend you look at numbers.spin in the object exchange, or my ParseNextInt/ParseNextFloat in the ftof.spin in the NAVCOM AI archive.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://forums.parallax.com/showthread.php?p=650217

    meow, i have my own topic now? (sorta)
  • KaioKaio Posts: 253
    edited 2007-05-16 19:40
    mre_rob,

    I don't know how the other part of your code looks like, but the code in the case statement looks complicated for me.
    I would use the data in buffer to separate each field as strings. The format of GPS data permits this solution. The separated fields are not copied to another location of memory. Then you can convert the fields to numeric values you are interested as M. K. Borri has mentioned.

    Ok, here is my preferred solution.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      DELIM_COMMA    = ","
      DELIM_ASTERISK = "*"
      GPSFIELDS      = 14
      _crlf          = $0D
      _vgaPin        = 16
      _sentenceSize  = 256
    
    
    VAR
    
      long gpsData[noparse][[/noparse]GPSFIELDS]
    
        
    OBJ
    
      objVGA : "VGA_Text"
    
      
    PUB testIt | i
    
      objVGA.start(_vgaPin)
    
      objVGA.str(@TestData)
      objVGA.out(_crlf)
    
      ParseGPRMC(@TestData)
    '  ParseValues  'convert fields from string to numeric value which you are interested
      
      i := 0
      objVGA.out(0)
      repeat while i < GPSFIELDS
        objVGA.dec(i)
        objVGA.out($20)
        objVGA.str(gpsData[noparse][[/noparse]i++])
        objVGA.out(_crlf)
    
      repeat
    
        
    Pri ParseGPRMC(PtrSentence)| i, idxField, tmp
    {{
         NMEA 0183 version 3.00 active the Mode indicator field is added
         $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a,m*hh
    Field #
    1    = UTC time of fix
    2    = Data status (A=Valid position, V=navigation receiver warning)
    3    = Latitude of fix
    4    = N or S of longitude
    5    = Longitude of fix
    6    = E or W of longitude
    7    = Speed over ground in knots
    8    = Track made good in degrees True
    9    = UTC date of fix
    10   = Magnetic variation degrees (Easterly var. subtracts from true course)
    11   = E or W of magnetic variation
    12   = Mode indicator, (A=Autonomous, D=Differential, E=Estimated, N=Data not valid)
    13   = Checksum
     }}
       idxField := i := 0
      
       repeat while i < _sentenceSize and idxField < GPSFIELDS - 1
         gpsData[noparse][[/noparse]idxField++] := PtrSentence + i
         
         repeat while i < _sentenceSize
           if byte[noparse][[/noparse]PtrSentence][noparse][[/noparse] i] == 0 or byte[noparse][[/noparse]PtrSentence][noparse][[/noparse] i] == DELIM_COMMA or byte[noparse][[/noparse]PtrSentence][noparse][[/noparse] i] == DELIM_ASTERISK
             byte[noparse][[/noparse]PtrSentence][noparse][[/noparse] i] := 0 'terminate the field
             i++
             quit
             
           i++
    
       gpsData[noparse][[/noparse]idxField] := PtrSentence + i
       i += 2 'point after checksum 
    
       byte[noparse][[/noparse]PtrSentence][noparse][[/noparse] i] := 0 'terminate the field
    
    
    DAT
    
    TestData      byte      "$GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a,m*hh",$0D
                  byte      "Test",0
    
    



    Thomas

    Post Edited (Kaio) : 5/17/2007 7:34:09 PM GMT
  • M. K. BorriM. K. Borri Posts: 279
    edited 2007-05-16 20:24
    Good point, but you also may want to either skip decimal points (use fixed-point arithmetic), or use floats. I found myself obligated to use floating point after a while, for precision reasons.

    This said, Thomas' code is a lot neater than mine [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://forums.parallax.com/showthread.php?p=650217

    meow, i have my own topic now? (sorta)
  • mre_robmre_rob Posts: 31
    edited 2007-05-17 10:33
    Kaio said...
    mre_rob,

    I don't know how the other part of your code looks like, but the code in the case statement looks complicated for me.
    I would use the data in buffer to separate each field as strings. The format of GPS data permits this solution. The separated fields are not copied to another location of memory. Then you can convert the fields to numeric values you are interested as M. K. Borri has mentioned.

    Ok, here is my preferred solution.
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      DELIM_COMMA    = ","
      DELIM_ASTERISK = "*"
      GPSFIELDS      = 14
      _crlf          = $0D
      _vgaPin        = 16
      _sentenceSize  = 256
    
    
    VAR
    
      long gpsData[noparse][[/noparse]GPSFIELDS]
    
        
    OBJ
    
      objVGA : "VGA_Text"
    
      
    PUB testIt | i
    
      objVGA.start(_vgaPin)
    
      objVGA.str(@TestData)
      objVGA.out(_crlf)
    
      ParseGPRMC(@TestData)
    '  ParseValues  'convert fields from string to numeric value which you are interested
      
      i := 0
      objVGA.out(0)
      repeat while i < GPSFIELDS
        objVGA.dec(i)
        objVGA.out($20)
        objVGA.str(gpsData[noparse][[/noparse]i++])
        objVGA.out(_crlf)
    
      repeat
    
        
    Pri ParseGPRMC(PtrSentence)| i, idxField, tmp
    {{
         NMEA 0183 version 3.00 active the Mode indicator field is added
         $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a,m*hh
    Field #
    1    = UTC time of fix
    2    = Data status (A=Valid position, V=navigation receiver warning)
    3    = Latitude of fix
    4    = N or S of longitude
    5    = Longitude of fix
    6    = E or W of longitude
    7    = Speed over ground in knots
    8    = Track made good in degrees True
    9    = UTC date of fix
    10   = Magnetic variation degrees (Easterly var. subtracts from true course)
    11   = E or W of magnetic variation
    12   = Mode indicator, (A=Autonomous, D=Differential, E=Estimated, N=Data not valid)
    13   = Checksum
     }}
       idxField := i := 0
      
       repeat while i < _sentenceSize and idxField < GPSFIELDS - 1
         gpsData[noparse][[/noparse]idxField++] := PtrSentence + i
         
         repeat while i < _sentenceSize
           if byte[noparse][[/noparse]PtrSentence][i] == 0 or byte[noparse][[/noparse]PtrSentence][i] == DELIM_COMMA or byte[noparse][[/noparse]PtrSentence][i] == DELIM_ASTERISK
             byte[noparse][[/noparse]PtrSentence][i] := 0 'terminate the field
             i++
             quit
             
           i++
    
       gpsData[noparse][[/noparse]idxField] := PtrSentence + i
       i += 2 'point after checksum 
    
       byte[noparse][[/noparse]PtrSentence][i] := 0 'terminate the field
    
    
    DAT
    
    TestData      byte      "$GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a,m*hh",$0D
                  byte      "Test",0
    [/i][/i][/i][/i][/i]
    



    Thomas
    · Wow... Thanks... I will get this into testing... Thank you very much for the time you put into this for me.

    · I know my initial code was a little complex, but being new to Spin and coming from another OO language, I was trying to apply the other languages constructs... maybe they don't translate and that might be my learning cureve with SPin...

    Post Edited (mre_rob) : 5/17/2007 10:42:27 AM GMT

  • KaioKaio Posts: 253
    edited 2007-05-17 19:49
    I have edit my post above, because I had overlook that the forum software was hiding the correct array access.

    My code should be to inspire you for a possible variant to parse the GPS data. I don't know if this code is what you need, but it can be useful to find the right way.

    Thomas
  • mre_robmre_rob Posts: 31
    edited 2007-05-18 16:00
    Thanks... I'll change the code and retest it.... It was bombing out the demo board yesterday...
Sign In or Register to comment.