3

My python script gets and sends words over a serial line. Each word is a signed 24-bit value, received as hex string. The script should now take these strings and convert them to integers, do some calculations on it, and send them back in the same format. My problem is, how to do this conversion

Examples

Rx string -> calc int
 012345   ->  74565
 fedcba   -> -74566

calc int -> Tx string
  74565  -> 012345
 -74566  -> fedcba

How can this be done?

4
  • Please confirm: the serial data is six bytes of '0'-padded text in the range 0-9a-fA-F. It is not 3-bytes of binary data. Is that correct? Commented Oct 9, 2014 at 16:19
  • Can your Task Definition also explicitly confirm any form of a lower-level serial line-code protocol present ( data-bits, stop-bits, parity, CRC, framing, HDB3-transmission-line-code-protection et al)? Commented Oct 9, 2014 at 16:26
  • 2
    @user3666197: there is another part of the software which treats the low level stuff, my part only gets/sets the 6 char string Commented Oct 10, 2014 at 6:19
  • "there is another part of the software which treats the low level stuff" - that makes much more sense. It seemed unlikely that hardware guys would design a serial line protocol like you described. Commented Oct 10, 2014 at 12:55

3 Answers 3

5
def str_to_int(s):
    i = int(s, 16)
    if i >= 2**23:
        i -= 2**24
    return i

def int_to_str(i):
    return '%06x'%((i+2**24)%2**24)

Test results:

In [36]: str_to_int('012345')
Out[36]: 74565

In [37]: str_to_int('fedcba')
Out[37]: -74566

In [38]: int_to_str(74565)
Out[38]: '012345'

In [39]: int_to_str(-74566)
Out[39]: 'fedcba'

Reference: Hex string to signed int in Python 3.2?

Sign up to request clarification or add additional context in comments.

1 Comment

Could you explain why you perform the subtractions? Is that simply to make use of the negative ints as well?
2

(Edit: An oversight on my part. See Rob's answer for correctly covering the negative sign numbers)

If you just want to convert a hex string into an int, do e.g.:

>>> int('0xff', 16)
255
>>> int('0xdaad', 16)
55981

The reverse can be done with the hex() function. From the help page:

Help on built-in function hex in module builtins:

>>> help(hex)
hex(...)
    hex(number) -> string

    Return the hexadecimal representation of an integer.

       >>> hex(3735928559)
       '0xdeadbeef'

It should be trivial to remove or add the '0x' if it's missing in your data stream. Here's an example to ensure padding to 6 chars (representing 3 bytes = 24 bits):

>>> '0x' + hex(255)[2:].rjust(6, '0')
'0x0000ff'

If you get the data in 3 byte form (24 bits), you can use int.to_bytes() and int.from_bytes() as described in the Python docs. This is new in Python 3.2.

Comments

1
$ pip install bitstring

Then:

from bitstring import BitStream
s1 = BitStream('0x012345')
s1.int # 74565
s2 = BitStream(int=-74565, length=24)
s2.hex # fedcbb

1 Comment

I marked the answer of @Robᵩ, because his solution does not need installing a module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.