smie
smie

Reputation: 612

Create 4 bytes from 16 bits

I have 16 bits. In each bit I can set some property and send to COM port(fiscal printer). For example: if 0 bit checked, then show logo on check.

This 16 bits I need convert to 4 bytes and send to COM port. For example: if 0 bit checked, 4 bytes will be 0x30, 0x31, 0x30, 0x30. Bytes result I get with COM port monitoring API.

What I must to do, to get 4 bytes from 16 bits?

Other examples:

Upvotes: 3

Views: 2907

Answers (4)

Rup
Rup

Reputation: 34408

Note that 0x30 = '0' in ASCII. It looks to me like you're transmitting the sixteen bits as two bytes of hex, with bits 0-7 first and the 8-15 second, i.e. you want to transmit

  • hex digit for bits 4-7
  • hex digit for bits 0-3
  • hex digit for bits 12-15
  • hex digit for bits 8-11

We'd need more data points to be sure, but this fits your examples above:

bit 0 set encodes to string "0100" = 0x30 0x31 0x30 0x30
bit 1 set                   "0200" = 0x30 0x32 0x30 0x30
bit 2 set                   "0400" = 0x30 0x34 0x30 0x30
0+2                         "0500" = 0x30 0x30 0x30 0x30
0+9                         "0102" = 0x30 0x31 0x30 0x32
0,1,2,3,4,5,9               "3F02" = 0x33 0x46 0x30 0x32

i.e. in Java if you have your bits in a single integer n you probably want

String output = Integer.toHexString((n >> 4) & 0xf)
              + Integer.toHexString(n & 0xf)
              + Integer.toHexString((n >> 12) & 0xf)
              + Integer.toHexString((n >> 8) & 0xf);
byte[] data = output.toUpperCase().getBytes("ASCII");

via a string, or

byte[] data = new byte[4];
data[0] = (byte)((n >> 4) & 0xf);
data[1] = (byte)(n & 0xf);
data[2] = (byte)((n >> 12) & 0xf);
data[3] = (byte)((n >> 8) & 0xf);
for(int i = 0; i < 4; ++i) {
    data[i] += (data[i] < 10) ? '0' : ('A' - 10);
}

avoiding the string.

To parse the four bytes back into a single int you could use

int bits = (((data[0] & 0xf) + ((data[0] >= 'A') ? 9 : 0)) << 4)
           | ((data[1] & 0xf) + ((data[1] >= 'A') ? 9 : 0))
           | (((data[2] & 0xf) + ((data[2] >= 'A') ? 9 : 0)) << 12)
           | (((data[3] & 0xf) + ((data[3] >= 'A') ? 9 : 0)) << 8);

Obviously there's no input checking here - I'm assuming we get the input in the expected format. The main bit in brackets should just parses a single hex digit out of the string - you could refactor that or implement something more robust if you wanted.

Upvotes: 2

nd.
nd.

Reputation: 8932

This question is a bit open to interpretation, I assume that you mean the following:

I must check each bit of a 16 bit datatype if it is set. In case it is set, then I must send data to the COM port. What data I need to send depends on the bit that was set. Bye the way, the data I need to send is always 4 bytes long.

Let's assume the bits that need to be checked come in as a Java int, i.e. a 32 bit integer where the upper 16 bits are always 0. I would like to suggest using a BitSet for checking the bits and an array for defining what to send if the bit is set:

private static final byte[][] BYTES_TO_SEND = new byte[][] { { 0x30, 0x31, 0x30, 0x30 }, // data to send if bit #0 is checked { 0x42 }, // data to send if bit #1 is checked // ... data to send if bit #2, #3, ... is checked };

private OutputStream com;

private static final byte[][] BYTES_TO_SEND = new byte[][] {
    { 0x30, 0x31, 0x30, 0x30 }, // data to send if bit #0 is checked
    { 0x42 }, // data to send if bit #1 is checked
// ... data to send if bit #2, #3, ... is checked
};

private OutputStream com;

public void initializeCOMFromBits(int bits) throws IOException {
  for (byte[] toSendIfSet : BYTES_TO_SEND) {
    if ((bits & 0x1) == 0x1) { // check if the lowest bit is set
      com.write(toSendIfSet);
    }
    bits >>>= 1; // shift all bits by one to the left
    // now the lowest bit if the bit that was second-to-lowest previously
  }
  assert bits == 0 : "There should be at most " + BYTES_TO_SEND.length + " bits set in the incoming bit set";
}

If your bits are in a BitSet, then change the loop into a for-loop with index and check the i-th bit with .get(i) - if it was set, then send BYTES_TO_SEND[i] to the COM port.

Upvotes: 0

Thomas
Thomas

Reputation: 88707

Well, 16 bits are 2 bytes. Thus if you split those 2 bytes in half you get 4 bytes.

Basically it's

byte b = ...;

byte firstHalf = (byte)((b & 0x0F) >> 4);
byte secondHalf = (byte)(b & 0xF0);

Note, however, that this is basically just the splitting and won't provide the result you describe in your question. As has already been pointed out, it's not clear what the "0"-bit is that should be checked and how you'd get those 0x30 0x31 0x30 0x30 values (which you could not get from just splitting 16 bits into packets of 4 and putting them into a byte each).

Upvotes: 0

Ferdau
Ferdau

Reputation: 1558

Not sure what you mean:

You have 16bits, which is only 2 bytes, so you could just leave the first 2 bytes 0 and use you're 16 bit in the last 2 bytes...

Byte1: 0000 0000
Byte2: 0000 0000
Byte3: first 8 bits of your 16 bits
Byte4: second 8 bits of your 16 bits

EDIT: I don't understand how you get 0x30, 0x30, 0x31, 0x30

0x stands for hexadecimal

0x30 hexadecimal = 0011 0000 binairy So I don't get why you would use 0x30 instead of just 0x00...

Upvotes: 0

Related Questions