5

Background

I have a device connected to my machine on a serial port that is message oriented, where each incoming command message is exactly eight 16-bit words. The most significant byte of each word is received first and the least significant byte received second. Each header word is a command identifier (ranging from 0 - 255). The format is defined like so:

XXXX    Header Word (Placeholder for 16-bit Hexadecimal value)
XXXX    Data Word
XXXX    Data Word
XXXX    Data Word
XXXX    Data Word
XXXX    Data Word
XXXX    Data Word
XXXX    Checksum Word (Result of Exclusive OR on header word and all six data words)

The format for the command I need to send, header 0x5D, is defined like so:

Word 1: Header = 005Dh
Word 2: Mode (values can be 2, 3, 6, 8, 9)
Words 3-7: Not significant
Word 8: 16 bit checksum 

Questions (all related)

I have this example from other source code that apparently sends this message correctly, but I'm not sure what is going on, even after reading perldoc on pack.

pack("v"x8, 0x00, 0x5D, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x5D);
  1. "v" means little endian, but I cannot find any reference on the x8 following it.
  2. And according to the format of the message, shouldn't the 0x5D value be right after the "v"x8, not after the 0x00?
  3. The message is supposed to have eight 16-bit words, so why are there 16 and not 8? Some are 0x00, and not 0x0? Does that make a difference?
ikegami
  • 367,544
  • 15
  • 269
  • 518
rem45acp
  • 469
  • 5
  • 16
  • 1
    doesn't `"v"x8` means `vvvvvvvv`? – Fabricator Jun 08 '14 at 01:22
  • Ah, right. The string repeating multiplier magic. Not related to pack but strings in general. So it was just tersely written instead of pack("vvvvvvvv", ....). Still lost on questions 2&3 though. – rem45acp Jun 08 '14 at 01:26
  • What "0x68 value" are you referring to in question 2? There's no 0x68 value in your given specification or the code. – jwodder Jun 08 '14 at 01:50
  • No, there's no difference between 0x00, 0x0, 0, 0+0, 4-4, etc. They all produce the zero. – ikegami Jun 08 '14 at 01:58
  • @jwodder I meant the 0x5D, the third argument in pack(). Typo on my part. – rem45acp Jun 08 '14 at 01:59
  • @John C: Please don't delete your comments through embarrassment. It is highly likely that others will have the same thoughts as you, but ikegami's responses make little sense in a vacuum and are robbed of meaning by your deletions – Borodin Jun 08 '14 at 03:24

1 Answers1

5

pack "v"x8 (which results in pack "vvvvvvvv", which can be written as pack "v8" for short) packs eight 16-bit numbers, yet you passed sixteen.

If you have sixteen bytes already, you want

pack 'C16', 0x00, 0x5D, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x5D

But I would expect you to have eight 16-bit words instead, so you'd use

pack 'n8', 0x005D, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x005D

Note the use of n instead of v to get the desired byte order.

pack 'v', 0x1234      => "\x34\x12"   Most significant byte last
pack 'n', 0x1234      => "\x12\x34"   Most significant byte first

Proof that both methods are equivalent:

my $method1 =  pack 'C16',
    0x00, 0x5D, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x5D;

my $method2 = pack 'n8',
    0x005D, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x005D;

print($method1 eq $method2 ? "yes" : "no", "\n");  # yes
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    This answer makes a lot of sense. The "v8" I've seen similar in the perl doc but not the "v"x8, didn't realize they were the same. However, passing sixteen values or 8 values is basically the same input, right? As long as each is 16-bits. I do find 8 clearer, as the message was defined to have the eight 16-bit words, and it shows that the first word does indeed have the message header. I'm going to have to experiment with the byte order. – rem45acp Jun 08 '14 at 15:17
  • Re "However, passing sixteen values or 8 values is basically the same input, right?" As I showed, You can construct the same packed data from 16 numbers or 8 numbers, but those numbers are going to have to be different, and so will the instructions on how to pack them. I've added proof that both methods are equivalent. – ikegami Jun 08 '14 at 15:46