i2c-ftdi-d2xx
Version:
i2c protocol implementation with ftdi-d2xx on standard boards that features no level translators on SDA and SCL
114 lines (102 loc) • 4.65 kB
JavaScript
const _ = require('lodash');
const TARGET_KIND = {
ADDRESS: 'address',
REGISTER: 'register',
FIELD: 'field'
}
const sleep = (ms) => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
const generateMask8Bit = (offset, size) => {
const mask = parseInt([...Array(8)].map((_, i) =>
i < 8 - offset && i >= 8 - offset - size ?
1 : 0).join(''), 2);
return mask;
}
const extractData = (data, offset, size) => {
const mask = generateMask8Bit(offset, size);
const result = (mask & data) >> offset
return result;
}
const insertData = (data, offset, size, read) => {
const binaryData = data.toString(2).padStart(8, '0');
const slicedData = binaryData.slice(binaryData.length - size);
const shiftedData = parseInt(slicedData, 2) << offset;
const mask = generateMask8Bit(offset, size);
const fieldData = (mask & shiftedData);
const sideData = (~mask & read);
return fieldData + sideData;
}
const addAdressProgressionIndex = (oderedTargets) => {
let index = 0;
oderedTargets.forEach((r, i) => {
if(i === 0) {
oderedTargets[i] = {...r, index: index}
} else if ((r.address === oderedTargets[i-1].address) || (r.address === oderedTargets[i-1].address + 1)) {
oderedTargets[i] = {...r, index: index}
} else {
index++;
oderedTargets[i] = {...r, index: index}
}
});
}
const getNon8BitFieldsFromHybridTarget = (req, regmap) => {
const fields = Object.values(regmap).flatMap(r => Object.entries(r.fields)).filter(f => f[1].size < 8).map(f => f[0]);
const nonFullFields = Object.keys(req).filter(f => fields.includes(f))
return nonFullFields;
}
const buildWriteInfo = (req, data, regmap) => {
const addresses = Object.entries(req).filter(r => !isNaN(Number(r[0]))).map((r) => {return {target:r[0], address:Number(r[0]), kind: TARGET_KIND.ADDRESS, data: r[1]}});
let registerAddresses = [];
let fieldsAddresses = [];
if (regmap) {
registerKeys = Object.keys(regmap);
fieldKeys = Object.entries(regmap).flatMap(g => Object.keys(g[1].fields));
registerNames = Object.entries(req).filter(r => registerKeys.includes(r[0]));
fieldNames = Object.entries(req).filter(r => fieldKeys.includes(r[0]));
registerAddresses = registerNames.map(r => {return {target: r[0], address: regmap[r[0]].address, kind: TARGET_KIND.REGISTER, data: r[1]}});
fieldsAddresses = fieldNames.map(f => {
const fieldRegister = Object.values(regmap).find(r => Object.keys(r.fields).includes(f[0]));
const field = fieldRegister.fields[f[0]];
let modifiedData;
if(field.size < 8) {
modifiedData = insertData(f[1], field.offset, field.size, data[f[0]]);
}
return {target: f[0], address: fieldRegister.address, kind: TARGET_KIND.FIELD, data: modifiedData ? modifiedData : f[1]};
})
}
const orderedRequest = [...addresses, ...registerAddresses, ...fieldsAddresses].sort((a, b) => a.address - b.address);
addAdressProgressionIndex(orderedRequest);
info = _.groupBy(orderedRequest, (r) => r.index);
return info;
}
const buildReadInfo = (req, regmap) => {
const addresses = req.filter(r => !isNaN(Number(r))).map((r) => {return {target:r, address:Number(r), kind: TARGET_KIND.ADDRESS}});
let registerAddresses = [];
let fieldsAddresses = [];
if (regmap) {
registerKeys = Object.keys(regmap);
fieldKeys = Object.entries(regmap).flatMap(g => Object.keys(g[1].fields));
registerNames = req.filter(r => registerKeys.includes(r));
fieldNames = req.filter(r => fieldKeys.includes(r));
registerAddresses = registerNames.map(r => {return {target:r, address:regmap[r].address, kind: TARGET_KIND.REGISTER}});
fieldsAddresses = fieldNames.map(f => {
const fieldRegister = Object.values(regmap).find(r => Object.keys(r.fields).includes(f));
return {target:f, address:fieldRegister.address, kind: TARGET_KIND.FIELD};
})
}
const orderedRequest = [...addresses, ...registerAddresses, ...fieldsAddresses].sort((a, b) => a.address - b.address);
addAdressProgressionIndex(orderedRequest);
info = _.groupBy(orderedRequest, (r) => r.index);
return info;
}
module.exports.sleep = sleep;
module.exports.TARGET_KIND = TARGET_KIND
module.exports.generateMask8Bit = generateMask8Bit;
module.exports.extractData = extractData;
module.exports.insertData = insertData;
module.exports.buildWriteInfo = buildWriteInfo;
module.exports.buildReadInfo = buildReadInfo;
module.exports.getNon8BitFieldsFromHybridTarget = getNon8BitFieldsFromHybridTarget;