UNPKG

i2c-ftdi-d2xx

Version:

i2c protocol implementation with ftdi-d2xx on standard boards that features no level translators on SDA and SCL

196 lines (172 loc) 7.8 kB
const fs = require("fs"); const i2c = require("./i2c"); const { generateMask8Bit, extractData, insertData } = require("./utils") let regmap; const readFile = (filepath) => { return new Promise((resolve, reject) => { fs.readFile(filepath, 'utf8', (err, data) => { if (err) { reject(err); } else { resolve(data); } }); }); }; const setRegisterMapByFilePath = async ({filepath}) => { const regmapFile = await readFile(filepath); regmap = JSON.parse(regmapFile); return regmap; }; const setRegisterMap = ({registerMap}) => { regmap = registerMap; return regmap; }; const getRegisterMap = () => regmap; const findRegisterFromField = (field) => { let register; if(regmap) { register = Object.entries(regmap).find(r => Object.keys(regmap[r[0]].fields).includes(field)); } else { throw('ERROR: no register map loaded .. before any communication you MUST load a valid register map with setRegisterMap') } return register ? {...register[1], name: register[0]} : null; } const i2cReadRegister = async ({slaveId, register, simulated = false}) => { const result = await i2c.i2cReadAddress({slaveId: slaveId, regAddress: isNaN(register) ? regmap[register].address : register, simulated: simulated}); return {data: result.data, result: result.ack ? 'pass' : 'fail'} }; const i2cReadRegistersWithDetails = async ({slaveId, registers = [], simulated = false}) => { let data = {}; let acks = []; if(regmap) { for (let r of registers) { const register = regmap[r]; const res = await i2c.i2cReadAddress({slaveId: slaveId, regAddress: register.address, simulated: simulated}); let registerData = {}; Object.keys(register.fields).forEach(f => { const field = register.fields[f]; const fieldData = extractData(res.data, field.offset, field.size) registerData[f] = res.ack ? fieldData : NaN; }); data[r] = registerData; acks.push(res.ack); }; } else { throw('ERROR: no register map loaded .. before any communication you MUST load a valid register map with setRegisterMap') } return {data: data, result: acks.every(a => a) ? 'pass' : 'fail'}; } const i2cReadField = async ({slaveId, field, simulated = false}) => { const register = findRegisterFromField(field); const info = register.fields[field] const {data, ack} = await i2c.i2cReadAddress({slaveId: slaveId, regAddress: register.address, simulated: simulated}); const fieldData = extractData(data, info.offset, info.size) return {data: fieldData, result: ack ? 'pass' : 'fail'}; }; const i2cReadFields = async ({slaveId, fields = [], simulated = false}) => { let data = {}; let results = []; for(let f of fields){ const singleRes = await i2cReadField({slaveId: slaveId, field: f, simulated: simulated}) results.push(singleRes.result); data[f] = singleRes.data } const result = results.every(r => r); return {data: data, result: result ? 'pass' : 'fail'}; }; const i2cReadRegistersFields = async ({slaveId, registers = [], simulated = false}) => { const read = {}; const acks = []; for(r of registers) { const {data, ack} = await i2c.i2cReadAddress({slaveId: slaveId, regAddress: isNaN(r) ? regmap[r].address : r, simulated: simulated}); acks.push(ack); const fields = Object.keys(regmap[r].fields); for (f of fields) { const field = regmap[r].fields[f]; const mask = generateMask8Bit(field.offset, field.size) read[f] = (data & mask) >> field.offset; }; }; const result = acks.every(a => a) ? 'pass' : 'fail'; return {data: read, result: result}; }; const i2cReadAllFields = async ({slaveId, capAddress=256, bannedRegisters = [], simulated = false}) => { const registers = Object.keys(regmap) .filter(r => regmap[r].address < capAddress) .filter(r => !bannedRegisters.includes(r)); const res = await i2cReadRegistersFields({slaveId: slaveId, registers: registers, simulated: simulated}) return res; }; const i2cWriteRegister = async ({slaveId, register, data, simulated = false}) => { const {ack} = await i2c.i2cWriteAddress({slaveId: slaveId, regAddress: isNaN(register) ? regmap[register].address : register, data: data, simulated: simulated}) const result = ack ? {result: "pass"} : {result: "fail"}; return result; }; const i2cWriteField = async ({slaveId, field, data, simulated = false}) => { const register = findRegisterFromField(field); let res = {}; if (register.fields[field].size < 8) { res = await i2c.i2cReadAddress({slaveId: slaveId, regAddress: register.address, simulated: simulated}); } else { res.data = 0; res.ack = true } let result; if(res.ack) { const newData = insertData(data, register.fields[field].offset, register.fields[field].size, res.data) const {ack} = await i2c.i2cWriteAddress({slaveId: slaveId, regAddress: register.address, data: newData, simulated: simulated}); result = ack ? {result: "pass"} : {result: "fail"}; } else { result = "fail"; } return result; }; const i2cWriteFields = async ({slaveId, fieldsDictionary, simulated = false}) => { const results = {}; for(f of Object.keys(fieldsDictionary)) { const res = await i2cWriteField({slaveId: slaveId, field: f, data: fieldsDictionary[f], simulated: simulated}); results[f] = res.result; } let result; if (Object.values(results).every(r => r === "pass")) { result = {result: "pass"} } else if (Object.values(results).some(r => r === "pass")){ result = {result: "fail", error: `write failed for the following fields: ${Object.keys(results).filter(f => results[f] === 'fail').join(', ')}`} } else { result = {result: "fail", error: `write failed for all requested fields`} } return result }; const i2cResetAllRegisters = async ({slaveId, bannedRegisters = [], simulated = false}) => { const registers = Object.keys(regmap).filter(r => !bannedRegisters.includes(r)); const results = []; for (r of registers) { results.push(await i2c.i2cWriteAddress({slaveId: slaveId, regAddress: regmap[r].address, data: regmap[r].reset, simulated: simulated})); }; if (results.every(r => r.ack)) { return {result: "pass"}; } else if (results.some(r => r.ack)) { return {result: "fail", error: "some registers failed to reset"}; } else { return {result: "fail", error: "it was not possible to reset any register"}; } }; module.exports.setRegisterMap = setRegisterMap; module.exports.setRegisterMapByFilePath = setRegisterMapByFilePath; module.exports.getRegisterMap = getRegisterMap; module.exports.getFieldRegister = findRegisterFromField; module.exports.i2cReadRegister = i2cReadRegister; module.exports.i2cReadField = i2cReadField; module.exports.i2cReadFields = i2cReadFields; module.exports.i2cReadRegistersFields = i2cReadRegistersFields; module.exports.i2cReadRegistersWithDetails = i2cReadRegistersWithDetails; module.exports.i2cReadAllFields = i2cReadAllFields; module.exports.i2cWriteRegister = i2cWriteRegister; module.exports.i2cWriteField = i2cWriteField; module.exports.i2cWriteFields = i2cWriteFields; module.exports.i2cResetAllRegisters = i2cResetAllRegisters;