UNPKG

i2c-ftdi-d2xx

Version:

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

139 lines (129 loc) 4.93 kB
const ftdi = require('./ftdi'); const {readFile, writeFile, createFileIfItDoesNotExist} = require('./file-manager'); let emulatedDevicePath; const i2cReadAddress = async ({slaveId, regAddress, simulated}) => { let data; let ack = false; if (simulated) { try { const read = JSON.parse(await readFile(emulatedDevicePath)); data = read[regAddress]; ack = true; } catch (error) { data = 255; ack = false; } } else { if (ftdi.isConnected() && slaveId) { const i2cRead = await ftdi.read(Number(slaveId), Number(regAddress), 1) data = i2cRead.data[0]; ack = (i2cRead.slaveAck === 0) && (i2cRead.readAck === 0) && (i2cRead.addressAck === 0) } } return {data: data, ack: ack} } const i2cReadBurst = async ({slaveId, regAddress, nBytes, simulated = false}) => { let data; let ack = false; if (simulated) { try { const read = JSON.parse(await readFile(emulatedDevicePath)); data = [...Array(nBytes)].map((_, i) => read[regAddress + i]); ack = true; } catch (error) { data = [...Array(nBytes)].map((_) => 255); ack = false; } } else { if (ftdi.isConnected() && slaveId) { const i2cRead = await ftdi.read(Number(slaveId), Number(regAddress), Number(nBytes)); data = i2cRead.data; ack = (i2cRead.slaveAck === 0) && (i2cRead.readAck === 0) && (i2cRead.addressAck === 0); } } return {data: data, ack: ack} } const i2cWriteAddress = async ({slaveId, regAddress, data, simulated}) => { let ack = false; if (simulated) { await createFileIfItDoesNotExist(emulatedDevicePath); const emulatedDevice = JSON.parse(await readFile(emulatedDevicePath)); emulatedDevice[regAddress] = data; await writeFile(JSON.stringify(emulatedDevice, null, 2), emulatedDevicePath); ack = true; } else { if (ftdi.isConnected() && slaveId) { const res = await ftdi.write(Number(slaveId), Number(regAddress), Number(data)); ack = (res.slaveAck === 0) && (res.addressAck === 0) && (res.dataAck === 0); } } return {ack: ack}; } const i2cWriteBurst = async ({slaveId, regAddress, data, simulated = false}) => { let ack = false; if (simulated) { await createFileIfItDoesNotExist(emulatedDevicePath); let emulatedDevice try { emulatedDevice = JSON.parse(await readFile(emulatedDevicePath)); } catch (error) { if (error instanceof SyntaxError && error.message.includes('Unexpected end of JSON input')) { emulatedDevice = {}; } else { throw new error.constructor(error.message) } } data.forEach((d, i) => { emulatedDevice[Number(regAddress) + i] = d; }); await writeFile(JSON.stringify(emulatedDevice, null, 2), emulatedDevicePath); ack = true; } else { if ((regAddress || regAddress === 0) && data.every(d => !isNaN(d))) { const burstData = data.map(d => Number(d)); if (ftdi.isConnected() && slaveId) { const res = await ftdi.burstWrite(Number(slaveId), Number(regAddress), burstData); ack = (res.slaveAck === 0) && (res.addressAck === 0) && (res.dataAcks.every(a => a === 0)) } } } return {ack: ack}; } const scanI2cBus = async () => { const slaves = []; for(let i = 0; i < 256; i += 2) { if (ftdi.isConnected()) { const res = await ftdi.ping(i); if (res.slaveAck === 0) { slaves.push(i); } } } return slaves; } const scanDeviceRegisters = async ({slaveId}) => { const registers = []; if(slaveId) { for(let i = 0; i < 256; i++) { if (ftdi.isConnected()) { const res = await ftdi.sendCommand(Number(slaveId), i); if (res.slaveAck === 0 && res.commandAck === 0) { registers.push(i); } } } } return registers; } const setEmulatedDevicePath = async ({filepath}) => { await createFileIfItDoesNotExist(filepath); emulatedDevicePath = filepath; return true; } module.exports.i2cReadAddress = i2cReadAddress; module.exports.i2cReadBurst = i2cReadBurst; module.exports.i2cWriteAddress = i2cWriteAddress; module.exports.i2cWriteBurst = i2cWriteBurst; module.exports.scanI2cBus = scanI2cBus; module.exports.scanDeviceRegisters = scanDeviceRegisters; module.exports.setEmulatedDevicePath = setEmulatedDevicePath;