Search code examples
javascriptpackingtyped-arrays

Pack object values into a 4 bytes unsigned integer in Javascript


Bitwise operators are my weak side. I would like to pack / encode a certain object values in javascript into a 4 byte unsigned integer (32 bit). I cant find any samples on setting a value given into bytes.

const obj = {
  line1: 1, // 1 bit
  line2: 1, // 1 bit
  volt: 15, // 4 bits
  temp_cur: 35, // 8 bits
  temp_min: 32, // 8 bits
  temp_max: 32, // 8 bits
  reserve: 0 // 2 bits
};

const buffArr = new ArrayBuffer(4);
const dataView = new DataView(buffArr);

// Not sure how to initialize an unsigned 32bit int
let packed = dataView.setUint32(0, 0, true);

// Set the values
packed = packed << 1 | obj.line1;
packed = packed << 1 | obj.line2;
packed = packed << 4 | obj.volt;
packed = packed << 8 | obj.temp_cur;
packed = packed << 8 | obj.temp_min;
packed = packed << 8 | obj.temp_max;
packed = packed << 2 | obj.reserve;

console.log(packed);

It looks like i also need to mask this one? Since i set it to a unsigned 32 bit integer, and the endianess.


Solution

  • Your packing routine is really off, use & to mask of values and >>> for unsigned shift left. See below

    const obj = {
      line1: 1, // 1 bit
      line2: 1, // 1 bit
      volt: 15, // 4 bits
      temp_cur: 35, // 8 bits
      temp_min: 32, // 8 bits
      temp_max: 32, // 8 bits
      reserve: 0 // 2 bits
    };
    
    const buffArr = new ArrayBuffer(4);
    const dataView = new DataView(buffArr);
    
    // Not sure how to initialize an unsigned 32bit int
    let packed = dataView.setUint32(0, 0, true);
    
    packed =  0x1 & (obj.line1 << 0); // No shift
    packed += 0x2 & (obj.line2 << 1); // shift 0 + 1 bits
    packed += 0x3c & (obj.volt << 2); // shift 0 + 1 + 1 bits
    packed += 0x3FC0 & (obj.temp_cur << 6); // shift 0 + 1 + 1 + 4 bits
    packed += 0x3FC000 & (obj.temp_min << 14); // shift 0 + 1 + 1 + 4 + 8 bits
    packed += 0x3FC00000 & (obj.temp_max << 22); // shift 0 + 1 + 1 + 4 + 8 + 8 bits
    packed += 0xc0000000 & (obj.reserve << 30); // shift 0 + 1 + 1 + 4 + 8 + 8 bits
    
    let unpack = {
      line1: (packed & 0x1) >>> 0,  // mask out the specific bits and shift back into place
      line2: (packed & 0x2) >>> 1, 
      volt: (packed & 0x3c) >>> 2,
      temp_cur: (packed & 0x3FC0) >>> 6,
      temp_min: (packed & 0x3FC000) >>> 14,
      temp_max: (packed & 0x3FC00000) >>> 22,
      reserve: (packed & 0xc0000000) >>> 30
    };
    console.log(packed);
    console.log(unpack);