Shop OBEX P1 Docs P2 Docs Learn Events
Variable Question — Parallax Forums

Variable Question

JomsJoms Posts: 279
edited 2008-09-29 08:52 in BASIC Stamp
I have been messing around with this problem for over two hours and can't seem to figure it out.· What I am trying to do is I have a variable that I store a hex number in.· I am then trying to use the serial out to send it as two seperate hex numbers.



checksum·· VAR·· Byte


checksum = $33·· <
there is actually an expression here, but I have tested it and it outputs $33


SEROUT 15, 16572, [noparse][[/noparse]HEX checksum.LOWNIB, HEX checksum.HIGHNIB]


What I want to come out of the serial port is "33 33" in hex.· Please let me know if you see where I am going wrong.· I have tried multiple variables, I have tried playing with different word/byte/nib/bit combinations.· I have also been trying to go through the Variable section of the help file because I think the answer is there, I just dont see it.· Please let me know if you have any ideas.· Thanks in advance...

Comments

  • FranklinFranklin Posts: 4,747
    edited 2008-06-27 02:19
    All numbers are stored as binary so your sending the nibbles will just send the high 4 bits as an eight bit number then the low 4 bits. What is it you ARE getting out?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Stephen
  • JomsJoms Posts: 279
    edited 2008-06-27 02:28
    I get two binary numbers out = 03 00, but I want to get 33 33

    Character 3 is hex 33
  • JomsJoms Posts: 279
    edited 2008-06-27 02:47
    After re-reading the post I think a better way to explain it would be to either save the first digit and second digit to different variables. I think that would be a work around for this problem. Unless I can send just one digit at a time...
  • FranklinFranklin Posts: 4,747
    edited 2008-06-27 02:47
    Why not SEROUT 15, 16572, [noparse][[/noparse]HEX checksum, HEX checksum]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Stephen
  • JomsJoms Posts: 279
    edited 2008-06-27 02:50
    The number actually changes... it was probably a bad example to use 33, but sometimes the checksum can be 'D3' or '0C', which I need to split up and send in two seperate hex numbers...

    Just examples would be...
    D3 = 44 33
    0C = 30 43
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-27 02:51
    If you just use "SEROUT 15,16572,[noparse][[/noparse] HEX2 checksum ]" then you will get "33" for a byte value of $33. The HEX formatter does this conversion. The reason you got "03 00" was that you asked for two two character hex strings, one from the lower 4 bits of "checksum" and the other one from the upper 4 bits of checksum.
  • JomsJoms Posts: 279
    edited 2008-06-27 03:06
    THAT FIXXED IT! Mike where did you find that command. I looked again in the help but didn't see it in there under the variable section.

    One second question:

    I am trying to get the two variables 'dest' and 'src' to be a hex. When I put a HEX in front of the variables I get an error that says Unexpected Constant. I have tried putting them in () and it still gives me an error. Does anyone know how to actually get them to calculate as a HEX? They are inputed to the program earlier as a decimal.

    CheckSum = $FF + (-($4E + $30 + $54 + $49 + $9 + $30 + $30 + Dest + $9 + $30 + $30 + Src)//$100) + 1
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-27 03:19
    There really isn't a distinction between binary and decimal or binary and hexadecimal except in the I/O statements like SERIN or SEROUT. Internally all computation is done with 16 bit binary values. If you write $54 or %01010100 or 84 or "T" it's all the same internally.
  • JomsJoms Posts: 279
    edited 2008-06-27 03:27
    Actually I think I found the beginning of the problems. I need to do the same thing with the Dest and Src variables like I did with the HEX2 command in the serial out. I am calculating a checksum and need to calculate the digits seperatly that are in the dest and src variables (add them together). But I would need to change them into two seperate HEX numbers in order for it to come out correctly. Basically I think the Dest number needs to be calculated as two seperate hex number instead of one two digit decimal number, and the same with the src variable. Can I do that with one line or do I need to do those calculations seperatly first?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-27 03:57
    I think you're making this unnecessarily complicated. Most checksums are simple arithmetic sums. You don't need to split up the bytes into 4bit pieces and add the "nibbles" separately. There are some exceptions in legacy 4-bit systems, but it doesn't sound like that's what you have.
  • JomsJoms Posts: 279
    edited 2008-06-27 04:07
    I am trying to calculate it automatically no matter what the value of the two variables are. Overcomplicated sounds like something I would do but I haven't found a way to simplify this. This is what the book says about the checksum - "Negative sum mod 256 of all previous byte values (not including SOH). The one byte checksum is broken into two hex digits, converted to ASCII representation, and sent as two ASCII characters. The most significant hex digit is sent first."

    The two variables 'dest' and 'src' is actually the only two things that will be changing in the program. The program comes up with a decimal number and stores it, but when I output it it will output as a HEX. The number can be anywhere from a single digit number to a four digit number. When calculating the checksum the program needs to add all four of the digits together even if they are zero's because a zero charactor is actually a hex 30.

    When I calculate it out on paper it seems to work and if I get rid of the variables and put '$30 + $30 + $30 + $31' in place of a '1' stored in the variable it will work. So basically I just need to find a way to make the program always see four places and use hex instead of the actually charactor.

    Thanks for all your help so far too!, I really appreciate it!
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-27 04:33
    Yep. This is a standard 8-bit arithmetic sum. Define the variable "checksum" as a byte (not a word) and simply add all the characters to "checksum" that follow the SOH. When it's time to send the checksum, just use "HEX2 -checksum". That's all. The "HEX2" will take the least significant 8 bits of the 2's complement of "checksum" and format and send the hexadecimal equivalent as two ASCII characters.

    I suspect that your block format doesn't really need the "HEX2". Commonly the checksum information is sent as an 8 bit character value. For example, a block might be: SEROUT 15,...,[noparse][[/noparse]$01, $65, $75, $66, $76] with the first byte being the SOH. The check sum would be calculated as "checksum = $65 + $75 + $66 + $76". You'd send the checksum as: SEROUT 15,...,[noparse][[/noparse]-checksum]. I don't know how the receiving end knows the block size. I assume it's either fixed and known or included in the data somehow.

    Post Edited (Mike Green) : 6/27/2008 4:42:40 AM GMT
  • JomsJoms Posts: 279
    edited 2008-06-27 19:15
    So if I understand you correctly I don't need to do the other calculations as far as the '//100 + $FF + $01'? Do you mean all I need to do is add my data together and then that is my checksum? I tried that and it doesn't give me the right answer. The problem is I need to actually send four digits for each variable which I am doing by using 'HEX4 dest' and 'HEX4 src' in my SEROUT command but I can't make the checksum actually calculate using 4 digits as the variable instead of just he variable number... Sorry if it is hard to understand, I am having problems explaining it the way I am thinking of it. Do you know how I can make the variable show up as 4 seperate hex numbers in the checksum?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-27 19:37
    Do you have a simple example of what has to be transmitted as byte values?
  • JomsJoms Posts: 279
    edited 2008-06-27 19:56
    In decimal form this is what I need to send out the serial port:

    SEROUT 15, 16572, [noparse][[/noparse]6,1,78,48,84,73,9,48,48,49,56,9,48,48,52,67,51,51,4]

    Basically this is what it all means:

    6 - Acknowledge from last command
    1 - Start of Heading
    78,48 - Protocol ID
    84,73 - Command
    9 - Horizontal Tab
    48,48,49,56 - Dest Variable
    9 - Horizontal Tab
    48,48,52,67 - Src Variable
    51,51 - Checksum
    4 - End of Transmission

    Basically the only two things that change are the Dest variable and the Src variable in which I need to calculate the checksum and send the command. The checksum is calculated by doing the arithmatic that I talked about earlier. What I am having problems with is that '0' as a charactor is actually '$30' as a hex or '48' as a decimal. When I input the number into the variable I need it to output after it calculates using all four digits in the variable, even if it has leading zero's....
  • allanlane5allanlane5 Posts: 3,815
    edited 2008-06-27 19:59
    Then output the number using "SEROUT 15, ...., [noparse][[/noparse]HEX4 OutValue, ... ]
    or
    "SEROUT 15, ..., [noparse][[/noparse]DEC4 OutValue, ...]

    The "HEX4" or "DEC4" modifiers say to the BS2 to "convert" the value in memory into a STRING version of itself, and send that. HEX4 means as a 4 character string with leading zeros -- which SOUNDS like what you're trying to do.
  • JomsJoms Posts: 279
    edited 2008-06-27 20:03
    The problem is getting the checksum to calculate right. I can get the serout command to work properly by putting HEX4 in front of the variable but I need to be able to put HEX4 in front of the variable when I am calculating the checksum but I get and error that it doesn't like the HEX4 located there.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-27 20:21
    OK, now I get what you're trying to do. Here's a routine to take a 16 bit value "Val" and convert it into a 4 character byte array "Bytes":
    Convert:
       for i = 0 to 3
          temp = Val & $F
          Val = Val >> 4
          if temp < 10 then
             temp = temp + "0"
          else
             temp = temp - 10 + "A"
          Bytes[noparse][[/noparse] i ] = temp
       next
       return
    


    I don't know whether you want to send the most significant bits first or last, so they're just in "Bytes" with the least significant 4 bits in Bytes[noparse][[/noparse] 0 ] and the most significant 4 bits in Bytes[noparse][[/noparse] 3 ]. temp and i are just temporary byte variables that you have to declare.
  • JomsJoms Posts: 279
    edited 2008-06-27 20:44
    I changed the 'temp' to my variable named 'dest' and defined and var called 'bytes' and one called 'i'. The bytes is a 4 byte array. I am having problems with the line 'Bytes[noparse][[/noparse] i ] = temp. The program doesn't like the [noparse][[/noparse] i ] and says it would expect to see a = there.
  • JomsJoms Posts: 279
    edited 2008-06-27 20:56
    OK, I got that part fixxed by changeing it to (i). Also, I had to add an EndIf in there, but no biggie... However, I still can't get the program to calculate the checksum properly. When I do the calculation by hand I come up with 33 33, which is what it should be. I have attached the program. Can you take a quick look at it and see if you can give me a clue where I am going wrong?

    '{$STAMP BS2}
    '{$PBASIC 2.5}




    Dest VAR Byte
    Src VAR Byte
    CheckSum VAR Byte
    i VAR Nib
    temp VAR Byte
    Bytes1 VAR Byte(4)
    Bytes2 VAR Byte(4)


    Dest = 24
    Src = 76

    FOR i = 0 TO 3
    temp = Dest & $F
    Dest = Dest >> 4
    IF temp < 10 THEN
    temp = temp + "0"
    ELSE
    temp = temp - 10 + "A"
    Bytes1(i) = temp
    ENDIF
    NEXT

    FOR i = 0 TO 3
    temp = Src & $F
    Src = Src >> 4
    IF temp < 10 THEN
    temp = temp + "0"
    ELSE
    temp = temp - 10 + "A"
    Bytes2(i) = temp
    ENDIF
    NEXT

    CheckSum = $FF + (-($4E + $30 + $54 + $49 + $9 + $30 + $30 + Bytes1 + $9 + $30 + $30 + Bytes2)//$100) + 1

    DEBUG HEX2 CheckSum, CR

    END
  • JomsJoms Posts: 279
    edited 2008-06-28 00:35
    I dont think I am one the right path here.· I have been working on this over the past few hours and actually loosing ground the gaining ground.· All I need to do is make a charactor type number calculate as a four position hex number....

    Example:

    Variable = '0024'

    Calculations need to use the number '$30 $30 $32 $34'

    Are we trying to over complicate this with all the calculations or are they actually nessisary?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-28 00:56
    Sorry about the [noparse][[/noparse] i ] vs ( i ).

    The "+ Bytes1" and "+ Bytes2" won't work as you might expect. The best way to do this is to put the checksum calculation in the loops, so after "Bytes1 ( i ) = temp" put "checksum = checksum·- temp". Similarly, after "Bytes2( i ) = temp" put "checksum = checksum·- temp".· Initialize checksum (like to $FF) somewhere before the loops.· You don't need the "// $100" because the "HEX2" will ignore bits beyond the least significant 8 bits.



    Post Edited (Mike Green) : 6/28/2008 1:02:21 AM GMT
  • JomsJoms Posts: 279
    edited 2008-06-28 01:27
    I can't get that to work either. I have tried many different changes also, such as subratacting instead of adding. What does the 'Bytes1(i) = temp' line do anymore because I don't use that variable anywhere else in the program. I have pasted the current program. With the two numbers I have saved in the Dest and Src variables I still should be getting '33 33' as a checksum. I assume I still have to add all the other constants to the checksum value that I was doing before in the long addition calculation.

    '{$STAMP BS2}
    '{$PBASIC 2.5}


    Dest VAR Byte
    Src VAR Byte
    CheckSum VAR Byte
    i VAR Nib
    temp VAR Byte(4)
    Bytes1 VAR Byte(4)
    Bytes2 VAR Byte(4)


    Main:


    Dest = 24
    Src = 76

    CheckSum = $FF

    FOR i = 0 TO 3
    temp = Dest & $F
    Dest = Dest >> 4
    IF temp < 10 THEN
    temp = temp + "0"
    ELSE
    temp = temp - 10 + "A"
    Bytes1(i) = temp
    CheckSum = CheckSum - temp
    ENDIF
    NEXT

    FOR i = 0 TO 3
    temp = Src & $F
    Src = Src >> 4
    IF temp < 10 THEN
    temp = temp + "0"
    ELSE
    temp = temp - 10 + "A"
    Bytes2(i) = temp
    CheckSum = CheckSum - temp
    ENDIF
    NEXT

    CheckSum = CheckSum + $12D

    DEBUG HEX2 CheckSum, CR

    END
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-28 01:37
    In the suggested code I posted, I copied the logic you had in your posting where you initialized the checksum to $FF and effectively subtracted each output character from that. Now you are adding the "extra" characters ($12D). You need to be consistent with this. Either change the "-" to "+" in the routines I posted or change the "+" to "-" in the checksum adjustment you added.

    The "Bytes1" and "Bytes2" arrays are for use in your output statements instead of using "HEX4". If you'd prefer to use "HEX4", then you don't need the arrays or the statements that set them. The two loops just do the HEX4 conversion storing the 4 characters in "Bytes1" or "Bytes2" and including those characters in "checksum".

    I'm a little confused about "dest" and "src".· You allow 4 hexadecimal digits for these (16 bits), yet declare them as byte variables which only hold 8 bits.· Two of the hexadecimal digits will always be "0"s.


    Post Edited (Mike Green) : 6/28/2008 1:42:55 AM GMT
  • JomsJoms Posts: 279
    edited 2008-06-28 01:56
    OK, I understand what you mean now... I think I have it figured out so I changed the ' + $12D' to ' - 89' and it gave me the answer I needed! So I picked a different number for the variable 'src' and set it equal to 69 which should have givin me a answer of '34 31' but instead it have me '37 36'.... I did do away with the 'Bytes1' and 'Bytes2' variables because they were not needed at this point. Do you see an error in the coding?

    Mike, Also, I would like to thank you for all your help with this so far and in the future. You are highly valued by the Parallax Community!
  • Mike GreenMike Green Posts: 23,101
    edited 2008-06-28 03:20
    How about posting your current source code?

    When you say "answer" do you mean the DEBUG output?
  • JomsJoms Posts: 279
    edited 2008-06-30 19:46
    Yes, I mean on the Debug output.· Currently I have simplified the code down to only what I need to do the checksum and then display it.· I figure once I get that part of the code working properly I will just start putting my other code that sends the data out the serial port little by little, so if there is a problem I can figure it out in steps.· I have attached my code if you would like to give it a try.

    When I hand calculate it with the following values I end up with the following answers.· I know the hand calculations are correct because they actually work when I calculate it outside of the program and input just the answer....

    Dest Variable = 24 (decimal)
    Src Variable = 76 (decimal)
    Answer = 33 33 (hex) (51 51 in decimal)

    Dest Variable = 24 (decimal)
    Src Variable = 69 (decimal)
    Answer = 34 31 (hex) (52 49 in decimal)
  • SolarBlitzSolarBlitz Posts: 2
    edited 2008-09-29 08:52
    I had a similar challenge... only in reverse. I was trying to receive (SERIN) a formatted serial string that included a HEX string to represent values. CHR(0) is difficult to store in a database! So, I used the LOOKUP command to convert a formatted string of HEX values (captured with the SERIN command into an array : serstr().

    I looked through the forums for a snippet... and when I didn't find one, I decided I could tackle it myself... I hope this helps someone.

    Mike, would the checksum method have been easier?


    this converts HEX to a byte:
    i = serstr(4) ' process requested value
    GOSUB BCD_TO_HEX '
    value = x * 16
    i = serstr(5)
    GOSUB BCD_TO_HEX
    value = value + x 'value is now converted


    this converts a 4 character HEX value to a word (eeprom_add):
    i = serstr(7)
    GOSUB BCD_TO_HEX
    eeprom_add.HIGHBYTE = x *16
    i = serstr(8)
    GOSUB BCD_TO_HEX
    eeprom_add.HIGHBYTE = eeprom_add.HIGHBYTE + x

    i= serstr(9)
    GOSUB BCD_TO_HEX
    eeprom_add.LOWBYTE = x * 16
    i = serstr(10)
    GOSUB BCD_TO_HEX
    eeprom_add.LOWBYTE = eeprom_add.LOWBYTE + x

    WRITE eeprom_add, value



    the subroutine that makes the conversion from HEX to decimal (I should've named this HEX_TO_BCD)

    BCD_TO_HEX:
    'this converts one serial byte (i)to an integer (x)
    LOOKDOWN i ,[noparse][[/noparse]48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70], x
    RETURN



    SolarBlitz
Sign In or Register to comment.