SparkFun GPS mini-mod string help
grasshopper
Posts: 438
I made a very crude object for the SparkFun GPS mini-mod www.sparkfun.com/commerce/product_info.php?products_id=8416
My question is how can I pack more than 4 byes into a long variable? I receive data from the module in a byte array and typically I can pack them into a long (4 bytes make a long) as long as the string is => 4 bytes.
Take a look at the code
My troubled area is that the first 5bytes are letters and I need to pack them into a long so that I can look up commands in a table. Otherwise this whole program works.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Those who criticize our generation forget who raised it.
My question is how can I pack more than 4 byes into a long variable? I receive data from the module in a byte array and typically I can pack them into a long (4 bytes make a long) as long as the string is => 4 bytes.
Take a look at the code
obj Ser : "FullDuplexSerial" Math : "FloatMath" Var byte SerialData[noparse][[/noparse] 70 ] byte Float_String[noparse][[/noparse] 20 ] Long Array[noparse][[/noparse] 30 ] Pub loadcogs | Scrap ser.start(0,30,0,baud) waitcnt (500_000 + cnt ) Repeat If (ser.rxcheck == $24) GetCom GetTime(@SerialData[noparse][[/noparse] 5 ]) [b]' This is my troubled area cause the first 5 bytes are letters[/b] Pub getcom | stringCount StringCount~ Repeat until (SerialData[noparse][[/noparse] StringCount ] := Ser.rx ) == "*" StringCount ++ Pub GetTime(In) | Int, Dec, Sign, X, Letter Int~ Dec~ Sign~ Letter~ X := 0 Repeat Until(byte[noparse][[/noparse] In ] == $2A) Case byte[noparse][[/noparse] In ] $2D: Sign := 1 $2E: Dec := 1 $30..$39: Int := Int * 10 + byte[noparse][[/noparse] In ] - $30 IF Dec Dec++ $41..$5A: Letter := 1 Array[noparse][[/noparse] X ] := byte[noparse][[/noparse] In ] $2C: IF Letter Int~ Dec~ Sign~ Letter~ X++ IF Sign Int := -Int Array[noparse][[/noparse] X ] := math.FFloat(Int) Int~ Dec~ Sign~ Letter~ X++ IF Dec Array[noparse][[/noparse] X ] := math.FFloat(Int) Repeat Dec - 1 Array[noparse][[/noparse] X ] := Math.FDiv(Array[noparse][[/noparse] X ],10.0) Int~ Dec~ Sign~ Letter~ X++ In++
My troubled area is that the first 5bytes are letters and I need to pack them into a long so that I can look up commands in a table. Otherwise this whole program works.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Those who criticize our generation forget who raised it.
Comments
If you encode characters differently, you can pack more than 4 characters into a 32 bit word.
For example, you can represent 26 letters, 10 digits and quite a few punctuation characters in 6 bits with appropriate conversion.
5 of these will fit in a 32 bit long. The easiest way to do this would be to check that the character is between $20 and $5F, convert
all the lower case letters to upper case, and discard all the rest. You'd then subtract $20 to get a value between $00 and $3F and
pack them into a 32 bit long. You'd have to write some kind of utility program to allow you to type in a command and it would do
the translation into a 32 bit hex value which you could copy down or cut and paste into your program.
It's not hard to write a subroutine to look up one string in a table of strings and return the table entry number for use in a CASE
statement. FemtoBasic uses a table like this. Have a look at the "tokenize" routine.
Post Edited (Mike Green) : 2/22/2009 9:15:34 PM GMT
Steps
1. Allow data to be received from $20 to $5A this translates as Space - Z (I wont need lowercase letters)
2. Take data and subtract $20 from it thus making Space = $0, 1 = $10 and A = $21 etc...
3. Pack into a long
This seems right? Ill start some type of code to do this.
*Edited - How do I squeeze this all into 6bits? Should I use Decimal instead of hex ?
Mike you are always a great help and...
...Thanks!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Those who criticize our generation forget who raised it.
I mean a hex value is still A Byte right?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Those who criticize our generation forget who raised it.
ASCII doesn't use the top bit. It only uses the lower 7. You scheme of subtracting ASCII value of space should work to get that down to even less (6?).
What you need to do after that transformation is to fit them into the long by shifting and ORing.
A Hex value is representation of bits. A two digit hex number will fit inside a byte.
**Scratches head // Must do this differently
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Those who criticize our generation forget who raised it.
What you need to do for each character is:
1 - Make sure it is not less than 20 hex and not greater than 5A hex
2 - Subtract 20 hex from the character. Now you have a number between 0 and 3A hex, 3A hex being 0011 1010 in binary or 58 decimal
3 - Add this to your long and shift it left 6
4 - Repeat for the next four characters
You will end up with 5 characters squeezed into 30 bits of a long. I think the code you have will work (not a spin expert yet) provided you adjust it to shift 6 bits instead of 8
Data := ((SerialData [noparse][[/noparse] 0 ] << 24) | (SerialData [noparse][[/noparse] 1 ] << 18) | (SerialData [noparse][[/noparse] 2 ] << 12) | SerialData[noparse][[/noparse] 3] << 6 | SerialData[noparse][[/noparse] 4] )
For each new character C, call "Data := packItIn(Data,C)". You can fit 5 characters into a long this way.