UNPKG

@yinyinfurong_zmr/dbc-can

Version:

A general purpose CAN (Controller Area Network) toolbox with support for .dbc file parsing, CAN message decoding, and more

150 lines 5.04 kB
import { CAN_EFF_FLAG, CAN_EFF_MASK } from './Const'; class BitUtils { /** * Returns a boolean value indicating whether the provided CAN id is extended or standard * @param id Number * @protected */ isIdExtended(id) { return (id & CAN_EFF_FLAG) >>> 0 === CAN_EFF_FLAG; } /** * Sets the extended flag in the provided ID and returns the new CAN ID * @param id */ setExtendedFlag(id) { return (id | CAN_EFF_FLAG) >>> 0; } /** * Unsets the extended ID flag and returns the normal 29-bit CAN ID * @param id */ unsetExtendedFlag(id) { return (id & CAN_EFF_MASK) >>> 0; } bitGet(num, idx) { const bitField = this.uint8ToBinary(num).split(''); // Assumes least significant bit starts at the end of the array return bitField[idx]; } bitSet(num, idx, val) { num[num.length - idx - 1] = val; return num; } bin2decSigned(bits) { const negative = bits[0] === '1'; if (negative) { let inverse = ''; for (let i = 0; i < bits.length; i++) { inverse += bits[i] === '0' ? '1' : '0'; } return (parseInt(inverse, 2) + 1) * -1; } else { return parseInt(bits, 2); } } bin2dec(bin) { return parseInt(bin, 2); } // Utility function to convert decimal to binary string dec2bin(dec, length) { return (dec >>> 0).toString(2).padStart(length, '0'); } /** * Converts a signed decimal number to a binary string. * * @param dec number * @param length number * @returns string */ dec2binSigned(dec, length) { if (dec < 0) { dec = (1 << length) + dec; // Convert negative number to two's complement } return dec.toString(2).padStart(length, '0'); } uint8ToBinary(dec) { const paddedBin = '000000000' + (dec >>> 0).toString(2); return paddedBin.substring(paddedBin.length - 8); } /** * Converts an uint8[] payload to a binary string * @param payload number[] CAN payload in decimal. * @param endian The type of encoding, Intel vs Motorola for the payload */ payload2Binary(payload, endian) { let byteArray; if (endian === 'Intel') { // The splice method is here because reverse modifies // the original array. This could cause errors to // subsequent calls to this function when the top level reference is the // same byteArray = payload.slice().reverse(); } else { byteArray = payload; } // Convert payload into binary string const bitField = byteArray .reduce((previous, current) => { return previous + this.uint8ToBinary(current); }, '') .split(''); return bitField; } /** * Convert a binary string array into a byte array * * @param binaryArray string[] * @returns number[] */ binary2Payload(binaryArray, endian) { const byteArray = []; for (let i = 0; i < binaryArray.length; i += 8) { byteArray.push(parseInt(binaryArray.slice(i, i + 8).join(''), 2)); } if (endian === 'Intel') { return byteArray.reverse(); } return byteArray; } getStartOfBit(length, startBit, bitRange, endian) { let startOfBit; if (endian === 'Intel') { startOfBit = length - startBit - bitRange; } else { const endOfBitField = 8 * Math.floor(startBit / 8) + (7 - (startBit % 8)); // Need to account for sawtooth bit numbering in CAN messages startOfBit = endOfBitField - bitRange + 1; // startOfBit = length - (length - startBit + bitRange); } return startOfBit; } extractBitRange(binary, startBit, bitRange, endian) { let startOfBit; startOfBit = this.getStartOfBit(binary.length, startBit, bitRange, endian); return binary.slice(startOfBit, startOfBit + bitRange); } /** * Inserts a bitField into a specific range within the binary string array. * * @param binary string[] * @param bitField string * @param startBit number * @param bitRange number * @param endian EndianType ('Motorola' or 'Intel') * @returns string[] */ insertBitRange(binary, bitField, startBit, bitRange, endian) { let startOfBit; startOfBit = this.getStartOfBit(binary.length, startBit, bitRange, endian); for (let i = 0; i < bitRange; i++) { binary[startOfBit + i] = bitField[i] || '0'; } return binary; } } export default BitUtils; //# sourceMappingURL=BitUtils.js.map