i2c-ftdi-d2xx
Version:
i2c protocol implementation with ftdi-d2xx on standard boards that features no level translators on SDA and SCL
700 lines (594 loc) • 31.9 kB
JavaScript
const path = require("path");
const fs = require("fs");
const {
getDefaultFilter,
list,
open,
close,
i2cScan,
i2cListRegisters,
i2cWrite,
i2cRead,
setRegisterMap,
getRegisterMap,
i2cReadRegister,
i2cReadField,
i2cReadFields,
i2cReadRegistersFields,
i2cReadRegistersWithDetails,
i2cReadAllFields,
i2cWriteRegister,
i2cWriteField,
i2cWriteFields,
i2cResetAllRegisters,
setEmulatedDevicePath,
read,
write
} = require("../index");
const { createFileIfItDoesNotExist } = require("../src/file-manager");
const REGMAP = require("../hidden_resources/regmap.json");
const emulatedDevicePath = path.resolve("hidden_resources/emulated_device.json");
const chai = require('chai');
const expect = chai.expect;
const RGX_DEFAULT_DESCRIPTION = /FT2232H.*[^B]$/;
const REGMAP_PATH = path.join("hidden_resources", "regmap.json");
const buildRandomWriteTarget = ({strict = false}) => {
const regmap = getRegisterMap()
const addressPool = strict ? Object.values(regmap).map(r => r.address) : [...Array(256)].map((_, i) => i);
const registersPool = Object.keys(regmap);
const fieldsPool = Object.entries(regmap).flatMap(r => Object.keys(r[1].fields));
let writeTarget = {};
let i = 0
const numberOftargets = strict ? Object.keys(regmap).length / 2 : 130
while (i <= numberOftargets) {
const choice = Math.floor(Math.random() * 10);
const randomData = Math.floor(Math.random() * 256);
if (choice < 5) {
const randomIndex = Math.floor(Math.random() * addressPool.length);
const register = Object.entries(regmap).find(r => r[1].address === addressPool[randomIndex]);
writeTarget[addressPool.splice(randomIndex, 1)[0]] = randomData;
if(register) {
const registerIndex = registersPool.findIndex(r => r === register[0]);
registersPool.splice(registerIndex, 1);
if (strict) {
Object.keys(register[1].fields).forEach(f => {
const brotherFieldIndex = fieldsPool.findIndex(fpn => fpn === f);
fieldsPool.splice(brotherFieldIndex, 1);
});
}
}
i++;
} else if (choice >=5 && choice < 9) {
const randomIndex = Math.floor(Math.random() * registersPool.length);
const registerName = registersPool.splice(randomIndex, 1)[0];
writeTarget[registerName] = randomData;
const address = regmap[registerName].address;
const addressIndex = addressPool.findIndex(a => a === address);
addressPool.splice(addressIndex, 1);
if (strict) {
Object.keys(regmap[registerName].fields).forEach(f => {
const brotherFieldIndex = fieldsPool.findIndex(fpn => fpn === f);
fieldsPool.splice(brotherFieldIndex, 1);
});
}
i++;
} else {
const randomIndex = Math.floor(Math.random() * fieldsPool.length);
const fieldName = fieldsPool.splice(randomIndex, 1)[0];
writeTarget[fieldName] = randomData;
if (strict) {
const register = Object.entries(regmap).find(r => Object.keys(r[1].fields).includes(fieldName));
const addressIndex = addressPool.findIndex(a => a === register[1].address);
addressPool.splice(addressIndex, 1);
const registerIndex = registersPool.findIndex(r => r === register[0]);
registersPool.splice(registerIndex, 1);
Object.keys(register[1].fields).forEach(f => {
const brotherFieldIndex = fieldsPool.findIndex(fpn => fpn === f);
fieldsPool.splice(brotherFieldIndex, 1);
});
i++;
}
}
}
return writeTarget;
}
describe('check for default device I2C generic communications', () => {
it('it should test positive to the DEAFULT orcasemi custom description regex', function() {
const rgxTest = RGX_DEFAULT_DESCRIPTION.test(getDefaultFilter());
expect(rgxTest).to.be.true;
});
it('should return a list of device if anything valid is connected to the USB port', async function() {
const devices = await list();
const asserts = [];
asserts.push(devices.length > 0);
asserts.push(typeof devices[0].is_open === "boolean");
asserts.push(typeof devices[0].description === "string");
asserts.push(typeof devices[0].serial_number === "string");
asserts.push(typeof devices[0].type === "string");
asserts.push(typeof devices[0].usb_loc_id === "number");
asserts.push(typeof devices[0].usb_pid === "number");
asserts.push(typeof devices[0].usb_vid === "number");
asserts.push(typeof devices[0].usb_speed === "string");
let result = asserts.every(a => a);
expect(result).to.be.true;
});
it('should open a the first avalable valid device (FTDI-D2XX) with DEAFULT orcasemi custom description', async function() {
const res = await open();
expect(res.success && res.errors.length === 0).to.be.true;
});
let slaves;
it('should scan I2C bus and return all respondi slave ID connected', async function() {
this.timeout(15000);
slaves = await i2cScan();
const asserts = [];
asserts.push(slaves.length > 0);
asserts.push(slaves.every(s => typeof s === "number"));
const result = asserts.every(a => a);
expect(result).to.be.true;
});
let registers;
it('should scan the first acking I2C slaves of previous test to check all available registers', async function() {
this.timeout(15000);
registers = await i2cListRegisters({slave: slaves[0]});
const asserts = [];
asserts.push(registers.length > 0);
asserts.push(registers.every(s => typeof s === "number"));
const result = asserts.every(a => a);
expect(result).to.be.true;
});
it('write 0xFF in the first available registers of the register list retrieved in the previous test and should receive a valid ACK on the operation', async function() {
const {ack} = await i2cWrite({slave: slaves[0], address: registers[0], data: 0xFF});
expect(ack).to.be.true;
});
it('burst write 10 bytes [0xF0 ..0xF9] starting in the first available registers of the register list retrieved in the previous tests and should receive a valid ACK on the operation', async function() {
const {ack} = await i2cWrite({slave: slaves[0], address: registers[0], data: [0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9]});
expect(ack).to.be.true;
});
it('should receive valid ack and data on register read operation on the first register available retrieved from previous test', async function() {
const {ack, data} = await i2cRead({slave: slaves[0], address: registers[0]});
const asserts = [];
asserts.push(ack);
asserts.push(typeof data === "number");
result = asserts.every(a => a);
expect(result).to.be.true;
});
it('should receive valid ack and data on a 10 byte burst read operation starting on the first register available retrieved from previous test', async function() {
const {ack, data} = await i2cRead({slave: slaves[0], address: registers[0], nByte: 10});
const asserts = [];
asserts.push(ack);
asserts.push(data.length === 10);
asserts.push(data.every(d => typeof d === "number"));
result = asserts.every(a => a);
expect(result).to.be.true;
});
it('should close the opened device of previous tests', async function() {
const res = await close();
expect(res.success && res.errors.length === 0).to.be.true;
});
})
describe('check for default device regmap I2C communication', () => {
let res;
let slaves;
let slave;
const registers = [Object.keys(REGMAP)[0], Object.keys(REGMAP)[1], Object.keys(REGMAP)[2]]
const register = registers[0];
const fields = Object.keys(REGMAP[register].fields)
const field = fields[0];
it("should load the regmap located in the hidden_resources folder", async function() {
res = await open();
const regmap = await setRegisterMap({registerMap: REGMAP_PATH});
expect(JSON.stringify(regmap)).to.be.equal(JSON.stringify(REGMAP));
});
it('should return the regmap loaded in the previous test', async function() {
await setRegisterMap({registerMap: REGMAP_PATH});
const regmapLoaded = JSON.stringify(getRegisterMap());
const regmapObject = JSON.stringify(REGMAP)
expect(regmapLoaded).to.be.equal(regmapObject);
});
it('should compare the regmap loaded as an object to the one loaded as a filepath and find no differences', async function() {
await setRegisterMap({registerMap: REGMAP_PATH});
const regmapFromFile = JSON.stringify(getRegisterMap());
await setRegisterMap({registerMap: REGMAP});
const regmapFromObject = JSON.stringify(getRegisterMap());
expect(regmapFromFile).to.be.equal(regmapFromObject);
})
it('should return data of REGMAP[0] register', async function() {
this.timeout(15000);
slaves = await i2cScan();
slave = slaves[0];
res = await i2cReadRegister({slave: slave, register: register});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'number');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of fields[0] of REGMAP[0] register', async function() {
res = await i2cReadField({slave: slave, field: field});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'number');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of fields of REGMAP[0] register', async function() {
res = await i2cReadFields({slave: slave, fields: fields});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === fields.length);
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of all fields of registers defined by the variable registers', async function() {
res = await i2cReadRegistersFields({slave: slave, registers: registers})
const multiRegisterFields = registers.flatMap(r => Object.keys(REGMAP[r].fields))
let asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === multiRegisterFields.length);
const validData = Object.keys(res.data).map(f => typeof res.data[f] === 'number');
asserts = [...asserts, ...validData];
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the hierarchical structure of all registers defined by the variable registers with proper value for all fields', async function() {
res = await i2cReadRegistersWithDetails({slave: slave, registers: registers})
let asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === registers.length);
const validData = Object.keys(res.data).flatMap(r => Object.keys(res.data[r]).flatMap(f => typeof res.data[r][f] === 'number'));
asserts = [...asserts, ...validData];
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of all fields of REGMAP', async function() {
this.timeout(15000);
res = await i2cReadAllFields({slave: slave})
const allFields = Object.keys(REGMAP).flatMap(r => Object.keys(REGMAP[r].fields))
let asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === allFields.length);
const validData = Object.keys(res.data).map(f => typeof res.data[f] === 'number');
asserts = [...asserts, ...validData];
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should write 0x55 on REGMAP[0] and receive "pass" as result of the operation', async function() {
res = await i2cWriteRegister({slave: slave, register: register, data: 0x55});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should write 0x55 on fields[0] of REGMAP[0] (capped to the right number of bits) and receive "pass" as result of the operation', async function() {
res = await i2cWriteField({slave: slave, field: field, data: 0x55});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should write 0x55 on all REGMAP[0] fields (capped to the right number of bits) and receive "pass" as result of the operation', async function() {
const fieldsDictionary = {};
fields.forEach(f => {
fieldsDictionary[f] = 0x55
})
res = await i2cWriteFields({slave: slave, fields: fieldsDictionary});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should reset all registers to the REGMAP reset value', async function() {
this.timeout(15000);
res = await i2cResetAllRegisters({slave: slave});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
})
describe('check for simulated I2C communication', () => {
let res;
const regmapKeys = Object.keys(REGMAP);
const slave = Math.round(Math.random() * regmapKeys.length);
const register = regmapKeys[Math.round(Math.random() * regmapKeys.length)];
const registers = [regmapKeys[Math.round(Math.random() * regmapKeys.length)], regmapKeys[Math.round(Math.random() * regmapKeys.length)], regmapKeys[Math.round(Math.random() * regmapKeys.length)]]
const fields = Object.keys(REGMAP[register].fields)
const field = fields[0];
it('should return 255 and fail if trying to read without setting any file to emulate device memory', async () => {
res = await i2cReadRegister({slave: 0, register: 0, simulated: true});
expect(res.data).to.be.equal(255);
expect(res.result).to.be.equal('fail');
});
it('should try to access the given filepath, create if not existing or confirm existence', async () => {
const filepath = emulatedDevicePath;
res = await createFileIfItDoesNotExist(filepath);
const possibleResponse = [
`File ${filepath} exists`,
`File ${filepath} was not existing and has been created`
]
expect(possibleResponse).to.contain(res);
});
it('should return true after having setup the emulated device', async () => {
res = await setEmulatedDevicePath({filepath: emulatedDevicePath});
expect(res).to.be.true;
});
it('should compare the regmap loaded as an object to the one loaded as a filepath and find no differences', async function() {
await setRegisterMap({registerMap: REGMAP_PATH});
const regmapFromFile = JSON.stringify(getRegisterMap());
await setRegisterMap({registerMap: REGMAP});
const regmapFromObject = JSON.stringify(getRegisterMap());
expect(regmapFromFile).to.be.equal(regmapFromObject);
});
it('should ack true for a 256 registers burst write', async function() {
const data = [...Array(256)].map((_, i) => Math.round(Math.random() * 255));
res = await i2cWrite({slave: slave, address: 0, data: data, simulated: true});
expect(res.ack).to.be.true;
});
it('should return data of REGMAP[0] register', async function() {
res = await i2cReadRegister({slave: slave, register: register, simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'number');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of fields[0] of REGMAP[0] register', async function() {
res = await i2cReadField({slave: slave, field: field, simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'number');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of fields of REGMAP[0] register', async function() {
res = await i2cReadFields({slave: slave, fields: fields, simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === fields.length);
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of all fields of registers defined by the variable registers', async function() {
res = await i2cReadRegistersFields({slave: slave, registers: registers, simulated: true})
const multiRegisterFields = registers.flatMap(r => Object.keys(REGMAP[r].fields))
let asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === multiRegisterFields.length);
const validData = Object.keys(res.data).map(f => typeof res.data[f] === 'number');
asserts = [...asserts, ...validData];
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the hierarchical structure of all registers defined by the variable registers with proper value for all fields', async function() {
res = await i2cReadRegistersWithDetails({slave: slave, registers: registers, simulated: true})
let asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === registers.length);
const validData = Object.keys(res.data).flatMap(r => Object.keys(res.data[r]).flatMap(f => typeof res.data[r][f] === 'number'));
asserts = [...asserts, ...validData];
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('should return the value of all fields of REGMAP', async function() {
res = await i2cReadAllFields({slave: slave, cap: 255, simulated: true})
const allFields = Object.keys(REGMAP).flatMap(r => Object.keys(REGMAP[r].fields))
let asserts = [];
asserts.push(res.result === 'pass');
asserts.push(typeof res.data === 'object');
asserts.push(Object.keys(res.data).length === allFields.length);
const validData = Object.keys(res.data).map(f => typeof res.data[f] === 'number');
asserts = [...asserts, ...validData];
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should write 0x55 on REGMAP[0] and receive "pass" as result of the operation', async function() {
res = await i2cWriteRegister({slave: slave, register: register, data: 0x55, simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should write 0x55 on fields[0] of REGMAP[0] (capped to the right number of bits) and receive "pass" as result of the operation', async function() {
res = await i2cWriteField({slave: slave, field: field, data: 0x55, simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should write 0x55 on all REGMAP[0] fields (capped to the right number of bits) and receive "pass" as result of the operation', async function() {
const fieldsDictionary = {};
fields.forEach(f => {
fieldsDictionary[f] = 0x55
})
res = await i2cWriteFields({slave: slave, fields: fieldsDictionary, simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
it('it should confirm read and write coherence by filling out all regmap with random numbers and reading back the same values', async function() {
const regmap = getRegisterMap();
const registersPool = Object.keys(regmap);
const fieldsPool = Object.entries(regmap).flatMap(r => Object.keys(r[1].fields));
const writeTarget = buildRandomWriteTarget({strict: true});
// const writeTarget = {unused_ADCConfig_b4: 55}
const expectedResult = {};
Object.entries(writeTarget).forEach(t => {
if (registersPool.includes(t[0])) {
expectedResult[t[0]] = t[1];
} else if (fieldsPool.includes(t[0])) {
const register = Object.entries(regmap).find(r => Object.keys(r[1].fields).includes(t[0]))[1];
const field = register.fields[t[0]];
const lsbFirstValue = t[1].toString(2).padStart(8, '0').split("").reverse().join("");
const cappedValue = lsbFirstValue.slice(0, field.size).split("").reverse().join("");
expectedResult[t[0]] = Number(`0b${cappedValue}`);
} else {
expectedResult[t[0]] = t[1];
}
});
let res;
let acks;
res = await write({slave: slave, target: writeTarget, simulated:true});
acks = Object.values(res.acks);
expect(acks.every(a => a)).to.be.true;
const readTarget = Object.keys(writeTarget);
res = await read({slave: slave, target: readTarget, simulated:true});
acks = Object.values(res.acks)
expect(acks.every(a => a)).to.be.true;
let equivalenceCheck = Object.entries(res.data).every(d => d[1] === expectedResult[d[0]]);
expect(equivalenceCheck).to.be.true;
equivalenceCheck = Object.entries(expectedResult).every(e => e[1] === res.data[e[0]]);
expect(equivalenceCheck).to.be.true;
const file = fs.readFileSync(emulatedDevicePath)
const dummyMemory = JSON.parse(file)
const memoryCheck = {}
readTarget.forEach(t => {
if (registersPool.includes(t)) {
memoryCheck[t] = dummyMemory[regmap[t].address]
} else if (fieldsPool.includes(t)) {
const register = Object.values(regmap).find(r => Object.keys(r.fields).includes(t));
const field = register.fields[t];
const lsbFirstValue = dummyMemory[register.address].toString(2).padStart(8, '0').split("").reverse().join("");
const cappedValue = lsbFirstValue.slice(field.offset, field.offset + field.size).split("").reverse().join("");
memoryCheck[t] = Number(`0b${cappedValue}`);
} else {
memoryCheck[t] = dummyMemory[t];
}
});
equivalenceCheck = Object.entries(res.data).every(d => d[1] === Number(memoryCheck[d[0]]));
expect(equivalenceCheck).to.be.true;
equivalenceCheck = Object.entries(memoryCheck).every(m => m[1] === res.data[m[0]]);
expect(equivalenceCheck).to.be.true;
});
it('it should reset all registers to the REGMAP reset value', async function() {
res = await i2cResetAllRegisters({slave: slave, bannedRegister: [], simulated: true});
const asserts = [];
asserts.push(res.result === 'pass');
asserts.push(!!!res.error);
expect(asserts.every(a => a)).to.be.true;
});
})
describe('test compact integrated methods read and write (flatten, all inclusive versions)', () => {
let slave = 0x02;
it('should open a the first avalable valid device (FTDI-D2XX) with DEAFULT orcasemi custom description', async function() {
const res = await open();
expect(res.success && res.errors.length === 0).to.be.true;
});
it("should load the regmap located in the hidden_resources folder", async function() {
res = await open();
const regmap = await setRegisterMap({registerMap: REGMAP_PATH});
expect(JSON.stringify(regmap)).to.be.equal(JSON.stringify(REGMAP));
});
it('should read a field value consistent with field size for 10 consecutives times', async function () {
const regmap = getRegisterMap()
const fieldsPool = Object.entries(regmap).flatMap(r => Object.keys(r[1].fields));
const testFields = [...Array(10)].flatMap(_ => fieldsPool.splice(Math.floor(Math.random() * fieldsPool.length), 1));
for(const f of testFields) {
const res = await read({slave: slave, target: f});
const field = Object.entries(regmap).find(r => Object.keys(r[1].fields).includes(f))[1].fields[f]
expect(res.acks[f]).to.be.true;
expect(res.data[f]).to.be.greaterThanOrEqual(0);
expect(res.data[f]).to.be.lessThan(Math.pow(2, field.size))
}
});
it('should receive valid ack and data on a 130+ burst read operation made on a random hybrid list of addresses, registers or fields', async function() {
const addressPool = [...Array(256)].map((_, i) => i);
const regmap = getRegisterMap()
const registersPool = Object.keys(regmap);
const fieldsPool = Object.entries(regmap).flatMap(r => Object.keys(r[1].fields));
let readTarget = [];
let i = 0
while (i <= 130) {
const choice = Math.floor(Math.random() * 10);
if (choice < 5) {
const randomIndex = Math.floor(Math.random() * addressPool.length);
const register = Object.entries(regmap).find(r => r[1].address === addressPool[randomIndex]);
readTarget.push(...addressPool.splice(randomIndex, 1));
if(register) {
const registerIndex = registersPool.findIndex(r => r === register[0]);
registersPool.splice(registerIndex, 1);
}
i++;
} else if (choice >=5 && choice < 9) {
const randomIndex = Math.floor(Math.random() * registersPool.length);
const registerName = registersPool.splice(randomIndex, 1);
readTarget.push(...registerName);
const address = regmap[registerName].address;
const addressIndex = addressPool.findIndex(a => a === address);
addressPool.splice(addressIndex, 1);
i++;
} else {
const randomIndex = Math.floor(Math.random() * fieldsPool.length);
const fieldName = fieldsPool.splice(randomIndex, 1);
readTarget.push(...fieldName);
}
}
const res = await read({slave: slave, target: readTarget});
const asserts = [];
asserts.push(Object.values(res.acks));
asserts.push(Object.keys(res.data).length === readTarget.length);
asserts.push(Object.values(res.data).every(d => typeof d === "number"));
result = asserts.every(a => a);
expect(result).to.be.true;
});
it('should write a field 10 times and always and receive ack', async function () {
const regmap = getRegisterMap()
const fieldsPool = Object.entries(regmap).flatMap(r => Object.keys(r[1].fields));
const testFields = [...Array(10)].flatMap(_ => fieldsPool.splice(Math.floor(Math.random() * fieldsPool.length), 1));
for(const f of testFields) {
const randomData = Math.floor(Math.random() * 256);
const res = await write({slave: slave, target: f, data: randomData});
expect(res.acks[f]).to.be.true;
}
});
it('should receive valid ack on 130+ burst write made on a random hybrid list of addresses, registers or fields', async function() {
const addressPool = [...Array(256)].map((_, i) => i);
const regmap = getRegisterMap()
const registersPool = Object.keys(regmap);
const fieldsPool = Object.entries(regmap).flatMap(r => Object.keys(r[1].fields));
let writeTarget = {};
let i = 0
while (i <= 130) {
const choice = Math.floor(Math.random() * 10);
const randomData = Math.floor(Math.random() * 256);
if (choice < 5) {
const randomIndex = Math.floor(Math.random() * addressPool.length);
const register = Object.entries(regmap).find(r => r[1].address === addressPool[randomIndex]);
writeTarget[addressPool.splice(randomIndex, 1)[0]] = randomData;
if(register) {
const registerIndex = registersPool.findIndex(r => r === register[0]);
registersPool.splice(registerIndex, 1);
}
i++;
} else if (choice >=5 && choice < 9) {
const randomIndex = Math.floor(Math.random() * registersPool.length);
const registerName = registersPool.splice(randomIndex, 1);
writeTarget[registerName[0]] = randomData;
const address = regmap[registerName].address;
const addressIndex = addressPool.findIndex(a => a === address);
addressPool.splice(addressIndex, 1);
i++;
} else {
const randomIndex = Math.floor(Math.random() * fieldsPool.length);
const fieldName = fieldsPool.splice(randomIndex, 1);
writeTarget[fieldName[0]] = randomData;
}
}
const res = await write({slave: slave, target: writeTarget});
const asserts = [];
asserts.push(Object.values(res.acks));
result = asserts.every(a => a);
expect(result).to.be.true;
});
it('should close the opened device of previous tests', async function() {
const res = await close();
expect(res.success && res.errors.length === 0).to.be.true;
});
})