Skip to content

Commit

Permalink
refactor after capture testing and bus rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
johntalton committed Jun 2, 2024
1 parent c592198 commit dbd6bf9
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 113 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@johntalton/excamera-i2cdriver",
"version": "1.0.0",
"version": "2.0.0",
"type": "module",
"exports": {
".": "./src/i2c-driver.js",
Expand Down
15 changes: 10 additions & 5 deletions src/capture-generator/i2c-state-machine.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export const i2cStateMachine = {
[STATES.WARM_IDLE]: {
'idle': { target: STATES.WARM_IDLE },
'data': { target: STATES.ADDRESSED, setAddress: true },
'stop': { target: STATES.STOPPED, closeTransaction: true }
'stop': { target: STATES.STOPPED, closeTransaction: true },
'start': { target: STATES.ADDRESSING, openTransaction: true },
},
[STATES.STOPPED]: {
'idle': { target: STATES.WARM_IDLE },
Expand All @@ -39,24 +40,28 @@ export const i2cStateMachine = {
'stop': { target: STATES.STOPPED, closeTransaction: true }
},
[STATES.ADDRESSED]: {
'ack': { target: STATES.ADDRESSED_ACKED },
'nack': { target: STATES.WARM_IDLE } // no response
'ack': { target: STATES.ADDRESSED_ACKED, online: true },
'nack': { target: STATES.WARM_IDLE, online: false } // no response
},
[STATES.ADDRESSED_ACKED]: {
'data': { target: STATES.TRANSMITION, bufferBytes: true },
'stop': { target: STATES.STOPPED, closeTransaction: true },

'stop': { target: STATES.STOPPED, closeTransaction: true }
'idle': { target: STATES.IDLE, closeTransaction: true } // ?? error
},
[STATES.TRANSMITION]: {
'ack': { target: STATES.TRANSMITION_ACKED, flushBytes: true },
'nack': { target: STATES.TRANSMITION_NACK_END, flushBytes: true }
},
[STATES.TRANSMITION_ACKED]: {
'stop': { target: STATES.STOPPED, closeTransaction: true },
'data': { target: STATES.TRANSMITION, bufferBytes: true }
'data': { target: STATES.TRANSMITION, bufferBytes: true },
'start': { target: STATES.ADDRESSING, openTransaction: true },
'idle': { target: STATES.IDLE, closeTransaction: true } //
},
[STATES.TRANSMITION_NACK_END]: {
'stop': { target: STATES.STOPPED, clearAddress: true, closeTransaction: true }
// start
},


Expand Down
2 changes: 1 addition & 1 deletion src/capture-generator/state-machine-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async function takeActions(event, info, options) {

if(setAddress) {
options.address = event.value >> 1
options.mode = event.value & 0b1 === 1 ? 'read' : 'write'
options.mode = (event.value & 0b1) === 1 ? 'read' : 'write'
}

const source = options.bytesAccumulator ?? []
Expand Down
144 changes: 75 additions & 69 deletions src/i2c-driver.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ResponseBufferPasrser } from './parse-buffers.js'
import { ResponseBufferParser } from './parse-buffers.js'

export const EXCAMERA_LABS_VENDOR_ID = 0x0403
export const EXCAMERA_LABS_PRODUCT_ID = 0x6015
Expand Down Expand Up @@ -54,55 +54,59 @@ const COMMAND_REPLY_LENGTH_SCAN = 112
const COMMAND_REPLY_LENGTH_TRANSMIT_STATUS_INFO = 80
const COMMAND_REPLY_LENGTH_INTERNAL_STATE = 80

export class ExcameraLabsI2CDriverI2C {
#port

export class ExcameraLabsI2CDriver {
static from({ port }) {
return {
//
start: async (dev, readMode) => ExcameraLabsI2CDriver.start(port, dev, readMode),
stop: async () => ExcameraLabsI2CDriver.stop(port),
readACKAll: async (count) => ExcameraLabsI2CDriver.readACKAll(port, count),
readNACKFinal: async (count) => ExcameraLabsI2CDriver.readNACKFinal(port, count),
write: async (count, bufferSource) => ExcameraLabsI2CDriver.write(port, count, bufferSource),

readRegister: async (dev, addr, count) => ExcameraLabsI2CDriver.readRegister(port, dev, addr, count),

resetBus: async () => ExcameraLabsI2CDriver.resetBus(port),

_transmitStatusInfo: async () => ExcameraLabsI2CDriver.transmitStatusInfo(port),
}
}

static controlFrom({ port }) {
return {
//
reboot: async () => ExcameraLabsI2CDriver.reboot(port),
static from(options) { return new ExcameraLabsI2CDriverI2C(options) }

//
transmitStatusInfo: async () => ExcameraLabsI2CDriver.transmitStatusInfo(port),
internalState: async () => ExcameraLabsI2CDriver.internalState(port),
echoByte: async b => ExcameraLabsI2CDriver.echoByte(port, b),
/**
* @param {SerialPort} port
*/
constructor({ port }) { this.#port = port }

//
setPullupControls: async (sda, scl) => ExcameraLabsI2CDriver.setPullupControls(port, sda, scl),
setSpeed: async speed => ExcameraLabsI2CDriver.setSpeed(port, speed),
resetBus: async () => ExcameraLabsI2CDriver.resetBus(port),
scan: async () => ExcameraLabsI2CDriver.scan(port),
async start(dev, readMode) { return ExcameraLabsI2CDriver.start(this.#port, dev, readMode) }
async stop() { return ExcameraLabsI2CDriver.stop(this.#port) }
async readACKAll(count) { return ExcameraLabsI2CDriver.readACKAll(this.#port, count) }
async readNACKFinal(count) { return ExcameraLabsI2CDriver.readNACKFinal(this.#port, count) }
async write(count, bufferSource) { return ExcameraLabsI2CDriver.write(this.#port, count, bufferSource) }

//
enterMonitorMode: async () => ExcameraLabsI2CDriver.enterMonitorMode(port),
exitMonitorMode: async () => ExcameraLabsI2CDriver.exitMonitorMode(port),
async readRegister(dev, addr, count) { return ExcameraLabsI2CDriver.readRegister(this.#port, dev, addr, count) }
async resetBus() { return ExcameraLabsI2CDriver.resetBus(this.#port) }
async transmitStatusInfo() { return ExcameraLabsI2CDriver.transmitStatusInfo(this.#port) }
}

//
enterCaptureMode: async () => ExcameraLabsI2CDriver.enterCaptureMode(port),

//
enterBitbangMode: async () => ExcameraLabsI2CDriver.enterBitbangMode(port),
exitBitbangMode: async () => ExcameraLabsI2CDriver.exitBitbangModeo(port),
sendBitbangCommand: async command => ExcameraLabsI2CDriver.sendBitbangCommand(port, command),
endBitbangCommand: async () => ExcameraLabsI2CDriver.endBitbangCommand(port),
}
}
export class ExcameraLabsI2CDriver {
// static controlFrom({ port }) {
// return {
// //
// reboot: async () => ExcameraLabsI2CDriver.reboot(port),

// //
// transmitStatusInfo: async () => ExcameraLabsI2CDriver.transmitStatusInfo(port),
// internalState: async () => ExcameraLabsI2CDriver.internalState(port),
// echoByte: async b => ExcameraLabsI2CDriver.echoByte(port, b),

// //
// setPullupControls: async (sda, scl) => ExcameraLabsI2CDriver.setPullupControls(port, sda, scl),
// setSpeed: async speed => ExcameraLabsI2CDriver.setSpeed(port, speed),
// resetBus: async () => ExcameraLabsI2CDriver.resetBus(port),
// scan: async () => ExcameraLabsI2CDriver.scan(port),

// //
// enterMonitorMode: async () => ExcameraLabsI2CDriver.enterMonitorMode(port),
// exitMonitorMode: async () => ExcameraLabsI2CDriver.exitMonitorMode(port),

// //
// enterCaptureMode: async () => ExcameraLabsI2CDriver.enterCaptureMode(port),

// //
// enterBitbangMode: async () => ExcameraLabsI2CDriver.enterBitbangMode(port),
// exitBitbangMode: async () => ExcameraLabsI2CDriver.exitBitbangMode(port),
// sendBitbangCommand: async command => ExcameraLabsI2CDriver.sendBitbangCommand(port, command),
// endBitbangCommand: async () => ExcameraLabsI2CDriver.endBitbangCommand(port),
// }
// }


static async #streamChunkRead(defaultReader, recvLength) {
Expand All @@ -111,24 +115,19 @@ export class ExcameraLabsI2CDriver {
defaultReader.cancel()
}, 2000)

const acc = []
const accSize = () => {
return acc.map(a => a.length).reduce((sum, length) => sum += length, 0)
const scratch = {
accumulator: [],
length: 0
}

while(true) {
// console.log('await read')
const { value, done } = await defaultReader.read()
if(done) { break }

if(done) {
// console.log('DONE', value)
break
}

//console.log('accumulate value', value, accSize(), recvLength)
acc.push([...value])
scratch.accumulator.push(value)
scratch.length += value.length

if(accSize() >= recvLength) {
if(scratch.length >= recvLength) {
// console.log('OVERSIZE')
break
}
Expand All @@ -137,9 +136,10 @@ export class ExcameraLabsI2CDriver {
clearTimeout(timer)

//console.log({ acc })
return Uint8Array.from(acc.reduce((flat, a) => {
return [ ...flat, ...a ]
}, []))
// return Uint8Array.from(acc.reduce((flat, a) => {
// return [ ...flat, ...a ]
// }, []))
return (new Blob(scratch.accumulator)).arrayBuffer()
}

static async #streamChunkRead_Alt(defaultReader, recvLength) {
Expand Down Expand Up @@ -178,13 +178,17 @@ export class ExcameraLabsI2CDriver {
return this.sendRecvCommand(port, command, sendBuffer, recvLength)
}

/** @param {SerialPort} port */
/**
* @param {SerialPort} port
* @param {ArrayBufferLike|ArrayBufferView} sendBuffer
*/
static async sendRecvCommand(port, command, sendBuffer, recvLength) {
// console.log('reader state', port.readable.locked, command, sendBuffer, recvLength)
if(port.readable.locked) {
console.warn('locked reader ...')

throw new Error('locked reader')
return new ArrayBuffer(0)
//throw new Error('locked reader')
}

const defaultWriter = port.writable.getWriter()
Expand Down Expand Up @@ -227,21 +231,23 @@ export class ExcameraLabsI2CDriver {
}
finally {
// console.log('finally')
await defaultWriter.ready

await defaultReader.releaseLock()
await defaultWriter.releaseLock()
}
}

static async transmitStatusInfo(port) {
return ResponseBufferPasrser.parseTransmitStatusInfo(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_TRANSMIT_STATUS_INFO, undefined, COMMAND_REPLY_LENGTH_TRANSMIT_STATUS_INFO))
return ResponseBufferParser.parseTransmitStatusInfo(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_TRANSMIT_STATUS_INFO, undefined, COMMAND_REPLY_LENGTH_TRANSMIT_STATUS_INFO))
}

static async internalState(port) {
return ResponseBufferPasrser.parseInternalStatus(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_TRANSMIT_INTERNAL_STATE, undefined, COMMAND_REPLY_LENGTH_INTERNAL_STATE))
return ResponseBufferParser.parseInternalStatus(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_TRANSMIT_INTERNAL_STATE, undefined, COMMAND_REPLY_LENGTH_INTERNAL_STATE))
}

static async echoByte(port, b) {
return ResponseBufferPasrser.parseEchoByte(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_ECHO_BYTE, Uint8Array.from([ b ]), COMMAND_REPLY_LENGTH_SINGLE_BYTE))
return ResponseBufferParser.parseEchoByte(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_ECHO_BYTE, Uint8Array.from([ b ]), COMMAND_REPLY_LENGTH_SINGLE_BYTE))
}

static async setSpeed(port, speed) {
Expand All @@ -252,7 +258,7 @@ export class ExcameraLabsI2CDriver {

static async start(port, dev, readMode) {
const b = (dev << 1) | (readMode ? 1 : 0)
return ResponseBufferPasrser.parseStart(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_START, Uint8Array.from([ b ]), COMMAND_REPLY_LENGTH_SINGLE_BYTE))
return ResponseBufferParser.parseStart(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_START, Uint8Array.from([ b ]), COMMAND_REPLY_LENGTH_SINGLE_BYTE))
}

static async readNACKFinal(port, count) {
Expand Down Expand Up @@ -280,7 +286,7 @@ export class ExcameraLabsI2CDriver {

const command = COMMAND_MASK_WRITE | countMinusOne

return ResponseBufferPasrser.parseStart(await ExcameraLabsI2CDriver.sendRecvCommand(port, command, bufferSource, COMMAND_REPLY_LENGTH_SINGLE_BYTE))
return ResponseBufferParser.parseStart(await ExcameraLabsI2CDriver.sendRecvCommand(port, command, bufferSource, COMMAND_REPLY_LENGTH_SINGLE_BYTE))
}

static async readACKAll(port, count) {
Expand All @@ -292,16 +298,16 @@ export class ExcameraLabsI2CDriver {
}

static async resetBus(port) {
return ResponseBufferPasrser.parseResetBus(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_RESET_BUS, undefined, COMMAND_REPLY_LENGTH_SINGLE_BYTE))
return ResponseBufferParser.parseResetBus(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_RESET_BUS, undefined, COMMAND_REPLY_LENGTH_SINGLE_BYTE))
}

static async readRegister(port, dev, addr, count) {
const data = Uint8Array.from([ dev, addr, count ])
return ResponseBufferPasrser.parseRegister(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_READ_REGISTER, data, count))
return ResponseBufferParser.parseRegister(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_READ_REGISTER, data, count))
}

static async scan(port) {
return ResponseBufferPasrser.parseScan(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_SCAN, undefined, COMMAND_REPLY_LENGTH_SCAN))
return ResponseBufferParser.parseScan(await ExcameraLabsI2CDriver.sendRecvCommand(port, COMMAND_SCAN, undefined, COMMAND_REPLY_LENGTH_SCAN))
}

static async enterMonitorMode(port) {
Expand Down
Loading

0 comments on commit dbd6bf9

Please sign in to comment.