Home AMX User Forum NetLinx Studio

convert WIDECHAR to a 2 byte CHAR string

OK... I've read through as much as I could on here, and have read through the whole UnicodeLib.axi, and I cannot figure out how to do this... I have a checksum that adds up to a 16 bit number, so when you convert to hex, it's wide. For example, I add up all of the hex bytes in a string, and an integer total would be 2356. Converted to hex (which it's a wide since it's more than 255) it's 0x0934. I need to convert this to two hex bytes of "0x09" and "0x34" in order for the checksum to be correct. I was originally taking my integer total of 2356, dividing by 255, and TYPE_CAST() that into a CHAR value called BYTE_1. I then TYPE_CAST the full total of the Integer to a CHAR value called BYTE_2 (which just truncated the first byte). This mostly works, but for whatever reason there is some math error that's happening in some cases, so that my BYTE_1 become incorrect.

ANY help would be GREATLY appreciated. Here's a snippit of what I was doing that mostly worked. lvSTRING_TO_SEND is built between the variable declarations & the checksum part I'm showing below. The string assembly works perfect, so I didn't see a reason to put it all here:

LOCAL_VAR CHAR lvSTRING_TO_SEND[20]
LOCAL_VAR INTEGER lvCOMMAND_LENGTH
LOCAL_VAR INTEGER lvCOMMAND_SUM
LOCAL_VAR CHAR lvFIRST_BYTE
LOCAL_VAR CHAR lvSECOND_BYTE
LOCAL_VAR INTEGER lvINDEX
.
.
.
lvINDEX=0
lvCOMMAND_SUM=0
lvCOMMAND_LENGTH=0
lvCOMMAND_LENGTH=LENGTH_STRING(lvSTRING_TO_SEND)
FOR(lvINDEX=1;lvINDEX<=lvCOMMAND_LENGTH;lvINDEX++)
{lvCOMMAND_SUM=(lvCOMMAND_SUM+lvSTRING_TO_SEND[lvINDEX])}
lvTEMP=(lvCOMMAND_SUM/255)
lvFIRST_BYTE=TYPE_CAST(lvTEMP)
lvSECOND_BYTE=TYPE_CAST(lvCOMMAND_SUM)
lvSTRING_TO_SEND="lvSTRING_TO_SEND,lvFIRST_BYTE"
lvSTRING_TO_SEND="lvSTRING_TO_SEND,lvSECOND_BYTE"
SEND_STRING dvSHADES,lvSTRING_TO_SEND

This is for Somfy ILT shades.

Thanks!!!

Comments

  • IC-STL-JB wrote: »
    lvINDEX=0
    lvCOMMAND_SUM=0
    lvCOMMAND_LENGTH=0
    lvCOMMAND_LENGTH=LENGTH_STRING(lvSTRING_TO_SEND)
    FOR(lvINDEX=1;lvINDEX<=lvCOMMAND_LENGTH;lvINDEX++)
    {lvCOMMAND_SUM=(lvCOMMAND_SUM+lvSTRING_TO_SEND[lvINDEX])}
    lvTEMP=(lvCOMMAND_SUM % 256)
    lvFIRST_BYTE=TYPE_CAST(lvTEMP)
    lvTEMP = (lvCOMMAND_SUM/256)
    lvSECOND_BYTE=TYPE_CAST(lvTEMP)
    lvSTRING_TO_SEND="lvSTRING_TO_SEND,lvFIRST_BYTE"
    lvSTRING_TO_SEND="lvSTRING_TO_SEND,lvSECOND_BYTE"
    SEND_STRING dvSHADES,lvSTRING_TO_SEND

    I've marked the changes I made by bolding them in the quote above. What you have to do is take the modulo of the integer with 256 (0x100) to get the low byte. Then if you do a straight division by 256 of the same integer, you'll get the high byte. Hope that helps.

    ETA: If you want to check some of this kind of thing and you have Windows 7, the programmer mode on the calculator is very handy for checking this sort of math.
  • BigsquatchBigsquatch Posts: 216
    I've marked the changes I made by bolding them in the quote above. What you have to do is take the modulo of the integer with 256 (0x100) to get the low byte. Then if you do a straight division by 256 of the same integer, you'll get the high byte. Hope that helps.

    ETA: If you want to check some of this kind of thing and you have Windows 7, the programmer mode on the calculator is very handy for checking this sort of math.

    There's no need to do the calculations in your code. Calculate your checksums manualy and put them in char (byte) arrays that you define as constants. Then you can send the contants as strings to the somfy.

    Hopefully this psuedocode will make it clear:
    DEFINE_CONSTANT
    
    // Const name      byte 1, byte2..., cksumHighByte, cksumLowByte  
    CHAR COMMAND1[] = "$02   , $00     , $09          , $34         "  // (Leave out the spaces)
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dv,1]
    {
        PUSH: { SEND_STRING dvSomfy, COMMAND1 }
    }
    

    When posting code type [*code] before your code and [*/code] after without the *'s.
  • DHawthorneDHawthorne Posts: 4,584
    Bigsquatch wrote: »
    There's no need to do the calculations in your code. Calculate your checksums manualy and put them in char (byte) arrays that you define as constants. Then you can send the contants as strings to the somfy.

    That's what I do when the data is static. No point having extra overhead in the code. It's only when the string might change (like a calculated zone number, etc.) that you have to do the checksum in code.
  • nicholasjamesnicholasjames Posts: 154
    If you need to grab bytes on the fly, I prefer bit masking and shifting:
    lvFIRST_BYTE=TYPE_CAST(lvCOMMAND_SUM & $FF) // Bitwise And
    lvSECOND_BYTE=TYPE_CAST(lvCOMMAND_SUM >> 8) // Bitwise Right Shift
    

    In this instance it doesn't really gain you anything speed wise, but I like the "cleanliness" of moving and grabbing the bits you want instead of returning the results of division.
  • PhreaKPhreaK Posts: 966
    +1 for bitwise operations. Far neater way to target the data you want.
Sign In or Register to comment.