@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
JavaScript
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