@johntalton/ftdi 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +89 -0
- package/lib/consts.d.ts +33 -0
- package/lib/consts.d.ts.map +1 -0
- package/lib/consts.js +42 -0
- package/lib/consts.js.map +1 -0
- package/lib/eeprom.d.ts +129 -0
- package/lib/eeprom.d.ts.map +1 -0
- package/lib/eeprom.js +495 -0
- package/lib/eeprom.js.map +1 -0
- package/lib/ft232h.d.ts +37 -0
- package/lib/ft232h.d.ts.map +1 -0
- package/lib/ft232h.js +204 -0
- package/lib/ft232h.js.map +1 -0
- package/lib/ftdi.d.ts +37 -0
- package/lib/ftdi.d.ts.map +1 -0
- package/lib/ftdi.js +204 -0
- package/lib/ftdi.js.map +1 -0
- package/lib/i2c/i2c-template.d.ts +10 -0
- package/lib/i2c/i2c-template.d.ts.map +1 -0
- package/lib/i2c/i2c-template.js +122 -0
- package/lib/i2c/i2c-template.js.map +1 -0
- package/lib/i2c/i2c.d.ts +29 -0
- package/lib/i2c/i2c.d.ts.map +1 -0
- package/lib/i2c/i2c.js +169 -0
- package/lib/i2c/i2c.js.map +1 -0
- package/lib/i2c/index.d.ts +5 -0
- package/lib/i2c/index.d.ts.map +1 -0
- package/lib/i2c/index.js +5 -0
- package/lib/i2c/index.js.map +1 -0
- package/lib/i2c/range.d.ts +2 -0
- package/lib/i2c/range.d.ts.map +1 -0
- package/lib/i2c/range.js +6 -0
- package/lib/i2c/range.js.map +1 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +9 -0
- package/lib/index.js.map +1 -0
- package/lib/mpsse/clock.d.ts +16 -0
- package/lib/mpsse/clock.d.ts.map +1 -0
- package/lib/mpsse/clock.js +34 -0
- package/lib/mpsse/clock.js.map +1 -0
- package/lib/mpsse/command.d.ts +66 -0
- package/lib/mpsse/command.d.ts.map +1 -0
- package/lib/mpsse/command.js +89 -0
- package/lib/mpsse/command.js.map +1 -0
- package/lib/mpsse/index.d.ts +7 -0
- package/lib/mpsse/index.d.ts.map +1 -0
- package/lib/mpsse/index.js +7 -0
- package/lib/mpsse/index.js.map +1 -0
- package/lib/mpsse/mpsse-template.d.ts +19 -0
- package/lib/mpsse/mpsse-template.d.ts.map +1 -0
- package/lib/mpsse/mpsse-template.js +81 -0
- package/lib/mpsse/mpsse-template.js.map +1 -0
- package/lib/mpsse/mpsse.d.ts +18 -0
- package/lib/mpsse/mpsse.d.ts.map +1 -0
- package/lib/mpsse/mpsse.js +77 -0
- package/lib/mpsse/mpsse.js.map +1 -0
- package/lib/status.d.ts +39 -0
- package/lib/status.d.ts.map +1 -0
- package/lib/status.js +62 -0
- package/lib/status.js.map +1 -0
- package/lib/util.d.ts +26 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +57 -0
- package/lib/util.js.map +1 -0
- package/package.json +38 -0
- package/src/consts.ts +57 -0
- package/src/eeprom.ts +663 -0
- package/src/ftdi.ts +215 -0
- package/src/i2c/i2c-template.ts +156 -0
- package/src/i2c/i2c.ts +210 -0
- package/src/i2c/index.ts +4 -0
- package/src/i2c/range.ts +6 -0
- package/src/index.ts +8 -0
- package/src/mpsse/clock.ts +36 -0
- package/src/mpsse/command.ts +113 -0
- package/src/mpsse/index.ts +6 -0
- package/src/mpsse/mpsse-template.ts +96 -0
- package/src/mpsse/mpsse.ts +95 -0
- package/src/status.ts +94 -0
- package/src/util.ts +72 -0
package/src/eeprom.ts
ADDED
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
/** biome-ignore-all lint/performance/noAwaitInLoops: <explanation> */
|
|
2
|
+
/** biome-ignore-all lint/nursery/noMisleadingReturnType: <explanation> */
|
|
3
|
+
/** biome-ignore-all lint/style/useConsistentArrayType: <explanation> */
|
|
4
|
+
/** biome-ignore-all lint/style/noExcessiveLinesPerFile: <explanation> */
|
|
5
|
+
/** biome-ignore-all lint/style/useDestructuring: <explanation> */
|
|
6
|
+
import type { FTDIDevice } from './ftdi.ts'
|
|
7
|
+
import {
|
|
8
|
+
type ChipInfo,
|
|
9
|
+
USB_MAJOR_TYPE_232H,
|
|
10
|
+
USB_MAJOR_TYPE_2232H,
|
|
11
|
+
USB_MAJOR_TYPE_R,
|
|
12
|
+
} from './util.ts'
|
|
13
|
+
|
|
14
|
+
export const MASK_16 = 0xFF_FF
|
|
15
|
+
export const MASK_8 = 0xFF
|
|
16
|
+
export const MASK_4 = 0x0F
|
|
17
|
+
export const MASK_3 = 0b0111
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export const MAX_POWER_MILLIAMP_PER_UNIT = 2
|
|
21
|
+
export const USB_DESCRIPTOR_TYPE_STRING = 0x03
|
|
22
|
+
|
|
23
|
+
export const CONFIG_RESERVED_MASK = 0b1000_0000
|
|
24
|
+
export const CONFIG_SELF_POWERED_MASK = 0b0100_0000
|
|
25
|
+
export const CONFIG_REMOTE_WAKE_MASK = 0b0010_0000
|
|
26
|
+
|
|
27
|
+
export const CONFIG_IN_ISOCHRONOUS_MASK = 0b0000_0001
|
|
28
|
+
export const CONFIG_OUT_ISOCHRONOUS_MASK = 0b0000_0010
|
|
29
|
+
export const CONFIG_SUSPEND_PULL_DOWN = 0b0000_0100
|
|
30
|
+
export const CONFIG_USE_SERIAL = 0b0000_1000
|
|
31
|
+
export const CONFIG_USE_USB_VERSION = 0b0001_0000
|
|
32
|
+
|
|
33
|
+
export const CHANNEL_TYPE: Record<number, string> = {
|
|
34
|
+
0: 'UART',
|
|
35
|
+
1: 'FIFO',
|
|
36
|
+
2: 'OPTO',
|
|
37
|
+
4: 'CPU',
|
|
38
|
+
8: 'FT1284'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const GROUP_DRIVE: Record<number, GroupDriveInfo> = {
|
|
42
|
+
0: { name: '4mA', mA: 4 },
|
|
43
|
+
1: { name: '8mA', mA: 8 },
|
|
44
|
+
2: { name: '12mA', mA: 12 },
|
|
45
|
+
3: { name: '16mA', mA: 16 }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const CBUS_FUNC_NAME_H: Record<number, string> = {
|
|
49
|
+
0: 'TRISTATE',
|
|
50
|
+
1: 'TXLED',
|
|
51
|
+
2: 'RXLED',
|
|
52
|
+
3: 'TXRXLED',
|
|
53
|
+
4: 'PWREN',
|
|
54
|
+
5: 'SLEEP',
|
|
55
|
+
6: 'DRIVE0',
|
|
56
|
+
7: 'DRIVE1',
|
|
57
|
+
8: 'GPIO',
|
|
58
|
+
9: 'TXDEN',
|
|
59
|
+
10: 'CLK30',
|
|
60
|
+
11: 'CLK15',
|
|
61
|
+
12: 'CLK7_5'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const CBUS_FUNC_NAME_R: Record<number, string> = {
|
|
65
|
+
0: 'TXDEN',
|
|
66
|
+
1: 'PWREN',
|
|
67
|
+
2: 'RXLED',
|
|
68
|
+
3: 'TXLED',
|
|
69
|
+
4: 'TX+RXLED',
|
|
70
|
+
5: 'SLEEP',
|
|
71
|
+
6: 'CLK48',
|
|
72
|
+
7: 'CLK24',
|
|
73
|
+
8: 'CLK12',
|
|
74
|
+
9: 'CLK6',
|
|
75
|
+
10: 'IOMODE',
|
|
76
|
+
11: 'BB_WR',
|
|
77
|
+
12: 'BB_RD"'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const GROUP_DRIVE_MASK = 0b0000_0011
|
|
81
|
+
export const SLOW_SLEW_MASK = 0b0000_0100
|
|
82
|
+
export const IS_SCHMITT_MASK = 0b0000_1000
|
|
83
|
+
|
|
84
|
+
export const EEPROM_CHIP_TYPE_ID = {
|
|
85
|
+
LC_46: 0x46, // 64 x 16-bit
|
|
86
|
+
LC_56: 0x56, // 128 x 16-bit
|
|
87
|
+
LC_66: 0x66 // 256 x 16-bit
|
|
88
|
+
} as const
|
|
89
|
+
|
|
90
|
+
export type EEPROMChipType = typeof EEPROM_CHIP_TYPE_ID[keyof typeof EEPROM_CHIP_TYPE_ID]
|
|
91
|
+
|
|
92
|
+
export interface EEPROMChipInfo {
|
|
93
|
+
id: EEPROMChipType | 0
|
|
94
|
+
name: string
|
|
95
|
+
byteLength: number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const EEPROM_CHIP_TYPE_INFO: Record<string, EEPROMChipInfo> = {
|
|
99
|
+
[EEPROM_CHIP_TYPE_ID.LC_46]: { id: EEPROM_CHIP_TYPE_ID.LC_46, name: '93LC46 64 x 16-bit', byteLength: 128 },
|
|
100
|
+
[EEPROM_CHIP_TYPE_ID.LC_56]: { id: EEPROM_CHIP_TYPE_ID.LC_56, name: '93LC56 128 x 16-bit', byteLength: 256 },
|
|
101
|
+
[EEPROM_CHIP_TYPE_ID.LC_66]: { id: EEPROM_CHIP_TYPE_ID.LC_66, name: '93LC66 256 x 16-bit', byteLength: 512 }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function eepromTypeFromValue(chipInfo: ChipInfo, value: number|undefined): EEPROMChipInfo|undefined {
|
|
105
|
+
if(chipInfo.major === USB_MAJOR_TYPE_R) { return { id: 0, name: 'Built-in 64 x 16-bit', byteLength: 128 } }
|
|
106
|
+
|
|
107
|
+
if(value === undefined) { return undefined }
|
|
108
|
+
return EEPROM_CHIP_TYPE_INFO[value]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
export interface EEPROMInfo {
|
|
113
|
+
vendorId: number
|
|
114
|
+
productId: number
|
|
115
|
+
chipVersion: {
|
|
116
|
+
chipMajor: number
|
|
117
|
+
chipMinor: number
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
chipInfo: ChipInfo
|
|
121
|
+
|
|
122
|
+
eepromType: EEPROMChipInfo|undefined
|
|
123
|
+
|
|
124
|
+
config: {
|
|
125
|
+
_reservedHigh: boolean
|
|
126
|
+
selfPowered: boolean
|
|
127
|
+
remoteWake: boolean
|
|
128
|
+
maxPower: number
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
chipConfig: {
|
|
132
|
+
isInIsochronous: boolean
|
|
133
|
+
isOutIsochronous: boolean
|
|
134
|
+
suspendPullDowns: boolean
|
|
135
|
+
useSerial: boolean
|
|
136
|
+
useUSBVersion: boolean
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
manufacture: string|undefined
|
|
140
|
+
product: string|undefined
|
|
141
|
+
serial: string|undefined
|
|
142
|
+
|
|
143
|
+
checksumCalculated: number
|
|
144
|
+
checksum: number|undefined
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface GroupDriveInfo {
|
|
148
|
+
name: string
|
|
149
|
+
mA: number
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface GroupItem {
|
|
153
|
+
name: string
|
|
154
|
+
drive: GroupDriveInfo | undefined
|
|
155
|
+
isSchmitt: boolean
|
|
156
|
+
slowSlew: boolean
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const CHANNEL_DRIVE_D2XX = 'D2xx'
|
|
160
|
+
export const CHANNEL_DRIVE_VCP = 'VCP'
|
|
161
|
+
|
|
162
|
+
export type ChannelDrive = typeof CHANNEL_DRIVE_D2XX | typeof CHANNEL_DRIVE_VCP
|
|
163
|
+
|
|
164
|
+
export interface EEPROMInfo2232H {
|
|
165
|
+
channelADrive: ChannelDrive
|
|
166
|
+
channelAType: string | undefined
|
|
167
|
+
|
|
168
|
+
channelBDrive: ChannelDrive
|
|
169
|
+
channelBType: string | undefined
|
|
170
|
+
|
|
171
|
+
suspendDBUS7: boolean
|
|
172
|
+
|
|
173
|
+
group: [ GroupItem, GroupItem, GroupItem, GroupItem ],
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface EEPROMInfo232H {
|
|
177
|
+
channelADrive: ChannelDrive
|
|
178
|
+
channelAType: string | undefined
|
|
179
|
+
clockPolarityHigh: boolean
|
|
180
|
+
lsbData: boolean
|
|
181
|
+
flowcontrol: boolean
|
|
182
|
+
powersave: boolean
|
|
183
|
+
|
|
184
|
+
group: [ GroupItem, GroupItem ],
|
|
185
|
+
|
|
186
|
+
cbusFunction: Array<string|undefined>
|
|
187
|
+
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface EEPROMInfo232R {
|
|
191
|
+
channelADrive: ChannelDrive
|
|
192
|
+
highCurrent: boolean
|
|
193
|
+
externalOscillator: boolean
|
|
194
|
+
|
|
195
|
+
invert: {
|
|
196
|
+
TXD: boolean
|
|
197
|
+
RXD: boolean
|
|
198
|
+
RTS: boolean
|
|
199
|
+
CTS: boolean
|
|
200
|
+
DTR: boolean
|
|
201
|
+
DSR: boolean
|
|
202
|
+
DCD: boolean
|
|
203
|
+
RI: boolean
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
cbusFunction: Array<string|undefined>
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export type ChipSpecificInfo = EEPROMInfo2232H | EEPROMInfo232H | EEPROMInfo232R | undefined
|
|
210
|
+
|
|
211
|
+
export function eepromTypeOffset(chipInfo: ChipInfo): number|undefined {
|
|
212
|
+
// if(chipInfo.major === USB_MAJOR_TYPE_2232C) { return 10 }// 2232C 0x14 -> 10
|
|
213
|
+
// this is wrong? if(major === USB_MAJOR_TYPE_R) { return 11 } // R 0x16 -> 11
|
|
214
|
+
if(chipInfo.major === USB_MAJOR_TYPE_2232H) { return 12 } // 2232H / 4232H 0x18 -> 12
|
|
215
|
+
// if(chipInfo.major === USB_MAJOR_TYPE_4232H) { return 12 } // 2232H / 4232H 0x18 -> 12
|
|
216
|
+
if(chipInfo.major === USB_MAJOR_TYPE_232H) { return 15 } // 232H 0x1e -> 15
|
|
217
|
+
|
|
218
|
+
return undefined
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export class FTDIEEPROM {
|
|
222
|
+
|
|
223
|
+
static async readEEPROMBulk(device: FTDIDevice, eepromSize16: number): Promise<ArrayBufferView<ArrayBuffer>> {
|
|
224
|
+
const result16 = new Uint16Array(eepromSize16)
|
|
225
|
+
for(let i = 0; i < eepromSize16; i += 1) {
|
|
226
|
+
const result = await device.readEEPROM(i, 2)
|
|
227
|
+
result16.set([result.getUint16(0, true)], i)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// const buf = Uint16Array.from([
|
|
231
|
+
// 0x03_12,
|
|
232
|
+
// ...('🧟 ❤️ 🧠'.split('').map(c => c.charCodeAt(0)))
|
|
233
|
+
// ])
|
|
234
|
+
// result16.set(buf, 80)
|
|
235
|
+
|
|
236
|
+
// checksum
|
|
237
|
+
// const csbuf = Uint16Array.from([ 42791 ])
|
|
238
|
+
// result16.set(csbuf, eepromSize16 - 1)
|
|
239
|
+
|
|
240
|
+
// console.log('read eeprom result', result16)
|
|
241
|
+
|
|
242
|
+
return result16
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
static calculateChecksum(buffer16: Uint16Array, size16: number): number {
|
|
246
|
+
const CHECKSUM_INITIAL_VALUE = 0xAA_AA
|
|
247
|
+
let checksum = CHECKSUM_INITIAL_VALUE
|
|
248
|
+
|
|
249
|
+
for(let i = 0; i < (size16 - 1); i += 1) {
|
|
250
|
+
const value = buffer16[i]
|
|
251
|
+
checksum ^= value ?? 0
|
|
252
|
+
checksum = ((checksum << 1) | (checksum >>> (16 - 1))) & MASK_16 // rotate16
|
|
253
|
+
}
|
|
254
|
+
return checksum
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static parseEEPROMDescriptorString(info: number, buffer16: Uint16Array, eepromSize16: number, decoder = new TextDecoder('utf-16LE')): string|undefined {
|
|
258
|
+
// info offset suffer from wrap-around indexing
|
|
259
|
+
// mask off the bits of the size to make sure index
|
|
260
|
+
// is withing the size.
|
|
261
|
+
const DESCRIPTOR_OFFSET_MASK = (eepromSize16 * 2) - 1
|
|
262
|
+
|
|
263
|
+
// info contains offset/length to the descriptor
|
|
264
|
+
const offset16 = (info & DESCRIPTOR_OFFSET_MASK) / 2
|
|
265
|
+
const length = (info >> 8) / 2
|
|
266
|
+
|
|
267
|
+
//
|
|
268
|
+
const prefix = buffer16[offset16]
|
|
269
|
+
if(prefix === undefined) {
|
|
270
|
+
console.warn('undefined prefix value', offset16)
|
|
271
|
+
return undefined
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// descriptors have length and USB descriptor type (length includes prefix)
|
|
275
|
+
const prefixLength = (prefix & MASK_8) / 2
|
|
276
|
+
const prefixDescriptorType = prefix >> 8
|
|
277
|
+
|
|
278
|
+
if(length !== prefixLength) {
|
|
279
|
+
console.warn('prefix length disagrees with info length', prefixLength, length)
|
|
280
|
+
return undefined
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if(prefixDescriptorType !== USB_DESCRIPTOR_TYPE_STRING) {
|
|
284
|
+
console.warn('USB Descriptor type is not String', prefixDescriptorType)
|
|
285
|
+
return undefined
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// skip the string prefix (reduce size by one)
|
|
289
|
+
const begin = offset16 + 1
|
|
290
|
+
const end = begin + length - 1
|
|
291
|
+
const buffer = buffer16.subarray(begin, end)
|
|
292
|
+
|
|
293
|
+
// decode utf-16le
|
|
294
|
+
return decoder.decode(buffer)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
static parseEEPROM_FT2232H(buffer: ArrayBufferView<ArrayBuffer>|ArrayBuffer, _chipInfo: ChipInfo): EEPROMInfo2232H | undefined {
|
|
298
|
+
const u16 = ArrayBuffer.isView(buffer) ?
|
|
299
|
+
new Uint16Array(buffer.buffer, buffer.byteOffset) :
|
|
300
|
+
new Uint16Array(buffer)
|
|
301
|
+
|
|
302
|
+
const DRIVE_MASK = 0b0000_1000
|
|
303
|
+
const SUSPEND_DBUS_7_MASK = 0b1000_0000
|
|
304
|
+
|
|
305
|
+
const control = u16[0]
|
|
306
|
+
const groupConfig = u16[6]
|
|
307
|
+
|
|
308
|
+
if(control === undefined) { return undefined }
|
|
309
|
+
if(groupConfig === undefined) { return undefined }
|
|
310
|
+
|
|
311
|
+
const controlH = (control >> 8) & MASK_8 // 1
|
|
312
|
+
const controlL = control & MASK_8 // 0
|
|
313
|
+
|
|
314
|
+
const channelAType = CHANNEL_TYPE[controlL & MASK_3]
|
|
315
|
+
const channelBType = CHANNEL_TYPE[controlH & MASK_3]
|
|
316
|
+
|
|
317
|
+
const channelADrive = ((controlL & DRIVE_MASK) === DRIVE_MASK) ? CHANNEL_DRIVE_VCP : CHANNEL_DRIVE_D2XX
|
|
318
|
+
const channelBDrive = ((controlH & DRIVE_MASK) === DRIVE_MASK) ? CHANNEL_DRIVE_VCP : CHANNEL_DRIVE_D2XX
|
|
319
|
+
|
|
320
|
+
const suspendDBUS7 = (controlH & SUSPEND_DBUS_7_MASK) === SUSPEND_DBUS_7_MASK
|
|
321
|
+
|
|
322
|
+
const groupConfigH = (groupConfig >> 8) & MASK_8 // d
|
|
323
|
+
const groupConfigL = groupConfig & MASK_8 // c
|
|
324
|
+
|
|
325
|
+
const groupConfigHH = (groupConfigH >> 4) & MASK_4 // 3
|
|
326
|
+
const groupConfigHL = groupConfigH & MASK_4 // 2
|
|
327
|
+
const groupConfigLH = (groupConfigL >> 4) & MASK_4 // 1
|
|
328
|
+
const groupConfigLL = groupConfigL & MASK_4 // 0
|
|
329
|
+
|
|
330
|
+
const group: [ GroupItem, GroupItem, GroupItem, GroupItem ] = [
|
|
331
|
+
{
|
|
332
|
+
name: 'AL',
|
|
333
|
+
drive: GROUP_DRIVE[(groupConfigLL & GROUP_DRIVE_MASK)],
|
|
334
|
+
isSchmitt: (groupConfigLL & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
|
|
335
|
+
slowSlew: (groupConfigLL & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
name: 'AH',
|
|
339
|
+
drive: GROUP_DRIVE[(groupConfigLH & GROUP_DRIVE_MASK)],
|
|
340
|
+
isSchmitt: (groupConfigLH & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
|
|
341
|
+
slowSlew: (groupConfigLH & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
name: 'BL',
|
|
345
|
+
drive: GROUP_DRIVE[(groupConfigHL & GROUP_DRIVE_MASK)],
|
|
346
|
+
isSchmitt: (groupConfigHL & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
|
|
347
|
+
slowSlew: (groupConfigHL & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
name: 'BH',
|
|
351
|
+
drive: GROUP_DRIVE[(groupConfigHH & GROUP_DRIVE_MASK)],
|
|
352
|
+
isSchmitt: (groupConfigHH & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
|
|
353
|
+
slowSlew: (groupConfigHH & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
channelAType,
|
|
359
|
+
channelBType,
|
|
360
|
+
channelADrive,
|
|
361
|
+
channelBDrive,
|
|
362
|
+
|
|
363
|
+
suspendDBUS7,
|
|
364
|
+
|
|
365
|
+
group
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
static parseEEPROM_232H(buffer: ArrayBufferView<ArrayBuffer>|ArrayBuffer, _chipInfo: ChipInfo): EEPROMInfo232H | undefined {
|
|
370
|
+
const u16 = ArrayBuffer.isView(buffer) ?
|
|
371
|
+
new Uint16Array(buffer.buffer, buffer.byteOffset) :
|
|
372
|
+
new Uint16Array(buffer)
|
|
373
|
+
|
|
374
|
+
const DRIVE_H_MASK = 0b0001_0000
|
|
375
|
+
const FT1284_CLOCK_STATE_MASK = 0b0000_0001
|
|
376
|
+
const FT1284_DATA_LSB_MASK = 0b0000_0010
|
|
377
|
+
const FT1284_FLOW_CONTROL_MASK = 0b0000_0100
|
|
378
|
+
const POWER_SAVE_DISABLE_H_MASK = 0b0000_1000
|
|
379
|
+
|
|
380
|
+
const control = u16[0]
|
|
381
|
+
const groupConfig = u16[6]
|
|
382
|
+
|
|
383
|
+
const cbusFunction0123 = u16[12] // 3 2 1 0
|
|
384
|
+
const cbusFunction4567 = u16[13] // 7 6 5 4
|
|
385
|
+
const cbusFunction89 = u16[14] // x x 9 8
|
|
386
|
+
|
|
387
|
+
if(control === undefined) { return undefined }
|
|
388
|
+
if(groupConfig === undefined) { return undefined }
|
|
389
|
+
if(cbusFunction0123 === undefined) { return undefined }
|
|
390
|
+
if(cbusFunction4567 === undefined) { return undefined }
|
|
391
|
+
if(cbusFunction89 === undefined) { return undefined }
|
|
392
|
+
|
|
393
|
+
const controlH = (control >> 8) & MASK_8 // 1
|
|
394
|
+
const controlL = control & MASK_8 // 0
|
|
395
|
+
|
|
396
|
+
const channelADrive = ((controlL & DRIVE_H_MASK) === DRIVE_H_MASK) ? CHANNEL_DRIVE_VCP : CHANNEL_DRIVE_D2XX
|
|
397
|
+
const channelAType = CHANNEL_TYPE[controlL & MASK_4]
|
|
398
|
+
|
|
399
|
+
const clockPolarityHigh = (controlH & FT1284_CLOCK_STATE_MASK) === FT1284_CLOCK_STATE_MASK
|
|
400
|
+
const lsbData = (controlH & FT1284_DATA_LSB_MASK) === FT1284_DATA_LSB_MASK
|
|
401
|
+
const flowcontrol = (controlH & FT1284_FLOW_CONTROL_MASK) === FT1284_FLOW_CONTROL_MASK
|
|
402
|
+
const powersave = (controlH & POWER_SAVE_DISABLE_H_MASK) === POWER_SAVE_DISABLE_H_MASK
|
|
403
|
+
|
|
404
|
+
const groupConfigH = (groupConfig >> 8) & MASK_8 // d
|
|
405
|
+
const groupConfigL = groupConfig & MASK_8 // c
|
|
406
|
+
|
|
407
|
+
const group: [ GroupItem, GroupItem ] = [
|
|
408
|
+
{
|
|
409
|
+
name: 'ACBUS',
|
|
410
|
+
drive: GROUP_DRIVE[(groupConfigL & GROUP_DRIVE_MASK)],
|
|
411
|
+
isSchmitt: (groupConfigL & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
|
|
412
|
+
slowSlew: (groupConfigL & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
name: 'ADBUS',
|
|
416
|
+
drive: GROUP_DRIVE[(groupConfigH & GROUP_DRIVE_MASK)],
|
|
417
|
+
isSchmitt: (groupConfigH & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
|
|
418
|
+
slowSlew: (groupConfigH & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
|
|
419
|
+
}
|
|
420
|
+
]
|
|
421
|
+
|
|
422
|
+
const cbusFunc0 = (cbusFunction0123 >> 0) & MASK_4
|
|
423
|
+
const cbusFunc1 = (cbusFunction0123 >> 4) & MASK_4
|
|
424
|
+
const cbusFunc2 = (cbusFunction0123 >> 8) & MASK_4
|
|
425
|
+
const cbusFunc3 = (cbusFunction0123 >> 12) & MASK_4
|
|
426
|
+
|
|
427
|
+
const cbusFunc4 = (cbusFunction4567 >> 0) & MASK_4
|
|
428
|
+
const cbusFunc5 = (cbusFunction4567 >> 4) & MASK_4
|
|
429
|
+
const cbusFunc6 = (cbusFunction4567 >> 8) & MASK_4
|
|
430
|
+
const cbusFunc7 = (cbusFunction4567 >> 12) & MASK_4
|
|
431
|
+
|
|
432
|
+
const cbusFunc8 = (cbusFunction89 >> 0) & MASK_4
|
|
433
|
+
const cbusFunc9 = (cbusFunction89 >> 4) & MASK_4
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
channelADrive,
|
|
437
|
+
channelAType,
|
|
438
|
+
clockPolarityHigh,
|
|
439
|
+
lsbData,
|
|
440
|
+
flowcontrol,
|
|
441
|
+
powersave,
|
|
442
|
+
|
|
443
|
+
group,
|
|
444
|
+
|
|
445
|
+
cbusFunction: [
|
|
446
|
+
CBUS_FUNC_NAME_H[cbusFunc0],
|
|
447
|
+
CBUS_FUNC_NAME_H[cbusFunc1],
|
|
448
|
+
CBUS_FUNC_NAME_H[cbusFunc2],
|
|
449
|
+
CBUS_FUNC_NAME_H[cbusFunc3],
|
|
450
|
+
CBUS_FUNC_NAME_H[cbusFunc4],
|
|
451
|
+
CBUS_FUNC_NAME_H[cbusFunc5],
|
|
452
|
+
CBUS_FUNC_NAME_H[cbusFunc6],
|
|
453
|
+
CBUS_FUNC_NAME_H[cbusFunc7],
|
|
454
|
+
CBUS_FUNC_NAME_H[cbusFunc8],
|
|
455
|
+
CBUS_FUNC_NAME_H[cbusFunc9]
|
|
456
|
+
]
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
static parseEEPROM_232R(buffer: ArrayBufferView<ArrayBuffer>|ArrayBuffer, _chipInfo: ChipInfo): EEPROMInfo232R | undefined {
|
|
461
|
+
const u16 = ArrayBuffer.isView(buffer) ?
|
|
462
|
+
new Uint16Array(buffer.buffer, buffer.byteOffset) :
|
|
463
|
+
new Uint16Array(buffer)
|
|
464
|
+
|
|
465
|
+
const DRIVE_MASK = 0b0000_1000
|
|
466
|
+
const HIGH_CURRENT_MASK = 0b0000_0100
|
|
467
|
+
const EXTERNAL_OSCILLATOR_MASK = 0b0000_0010
|
|
468
|
+
|
|
469
|
+
// const ENDPOINT_SIZE_MASK = 0b0100_0000
|
|
470
|
+
|
|
471
|
+
const INVERT_TXD_MASK = 0b0000_0001
|
|
472
|
+
const INVERT_RXD_MASK = 0b0000_0010
|
|
473
|
+
const INVERT_RTS_MASK = 0b0000_0100
|
|
474
|
+
const INVERT_CTS_MASK = 0b0000_1000
|
|
475
|
+
const INVERT_DTR_MASK = 0b0001_0000
|
|
476
|
+
const INVERT_DSR_MASK = 0b0010_0000
|
|
477
|
+
const INVERT_DCD_MASK = 0b0100_0000
|
|
478
|
+
const INVERT_RI_MASK = 0b1000_0000
|
|
479
|
+
|
|
480
|
+
const control = u16[0]
|
|
481
|
+
const config = u16[5]
|
|
482
|
+
|
|
483
|
+
const cbusFunction0123 = u16[10] // 3 2 1 0
|
|
484
|
+
const cbusFunction4 = u16[11] // x x x 4
|
|
485
|
+
|
|
486
|
+
if(control === undefined) { return undefined }
|
|
487
|
+
if(config === undefined) { return undefined }
|
|
488
|
+
if(cbusFunction0123 === undefined) { return undefined }
|
|
489
|
+
if(cbusFunction4 === undefined) { return undefined }
|
|
490
|
+
|
|
491
|
+
const controlH = (control >> 8) & MASK_8 // 1
|
|
492
|
+
const controlL = control & MASK_8 // 0
|
|
493
|
+
|
|
494
|
+
const invertH = (config >> 8) & MASK_8 // 11
|
|
495
|
+
|
|
496
|
+
const channelADrive = ((controlL & DRIVE_MASK) === DRIVE_MASK) ? CHANNEL_DRIVE_D2XX : CHANNEL_DRIVE_VCP
|
|
497
|
+
const highCurrent = (controlH & HIGH_CURRENT_MASK) === HIGH_CURRENT_MASK
|
|
498
|
+
const externalOscillator = (controlH & EXTERNAL_OSCILLATOR_MASK) === EXTERNAL_OSCILLATOR_MASK
|
|
499
|
+
|
|
500
|
+
// const endpointSize = (controlL & ENDPOINT_SIZE_MASK) === ENDPOINT_SIZE_MASK
|
|
501
|
+
|
|
502
|
+
const invert = {
|
|
503
|
+
TXD: (invertH & INVERT_TXD_MASK) === INVERT_TXD_MASK,
|
|
504
|
+
RXD: (invertH & INVERT_RXD_MASK) === INVERT_RXD_MASK,
|
|
505
|
+
RTS: (invertH & INVERT_RTS_MASK) === INVERT_RTS_MASK,
|
|
506
|
+
CTS: (invertH & INVERT_CTS_MASK) === INVERT_CTS_MASK,
|
|
507
|
+
DTR: (invertH & INVERT_DTR_MASK) === INVERT_DTR_MASK,
|
|
508
|
+
DSR: (invertH & INVERT_DSR_MASK) === INVERT_DSR_MASK,
|
|
509
|
+
DCD: (invertH & INVERT_DCD_MASK) === INVERT_DCD_MASK,
|
|
510
|
+
RI: (invertH & INVERT_RI_MASK) === INVERT_RI_MASK
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const cbusFunc0 = (cbusFunction0123 >> 0) & MASK_4
|
|
514
|
+
const cbusFunc1 = (cbusFunction0123 >> 4) & MASK_4
|
|
515
|
+
const cbusFunc2 = (cbusFunction0123 >> 8) & MASK_4
|
|
516
|
+
const cbusFunc3 = (cbusFunction0123 >> 12) & MASK_4
|
|
517
|
+
|
|
518
|
+
const cbusFunc4 = (cbusFunction4 >> 0) & MASK_4
|
|
519
|
+
|
|
520
|
+
return {
|
|
521
|
+
channelADrive,
|
|
522
|
+
highCurrent,
|
|
523
|
+
externalOscillator,
|
|
524
|
+
|
|
525
|
+
invert,
|
|
526
|
+
|
|
527
|
+
cbusFunction: [
|
|
528
|
+
CBUS_FUNC_NAME_R[cbusFunc0],
|
|
529
|
+
CBUS_FUNC_NAME_R[cbusFunc1],
|
|
530
|
+
CBUS_FUNC_NAME_R[cbusFunc2],
|
|
531
|
+
CBUS_FUNC_NAME_R[cbusFunc3],
|
|
532
|
+
CBUS_FUNC_NAME_R[cbusFunc4]
|
|
533
|
+
]
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
static parseEEPROM_ChipSpecific(buffer: ArrayBufferView<ArrayBuffer|ArrayBuffer>, chipInfo: ChipInfo): ChipSpecificInfo {
|
|
538
|
+
// if(chipInfo.major === USB_MAJOR_TYPE_BM) { return FTDIEEPROM.parseEEPROM_FT2232BM(buffer, chipInfo) }
|
|
539
|
+
if(chipInfo.major === USB_MAJOR_TYPE_R) { return FTDIEEPROM.parseEEPROM_232R(buffer, chipInfo) }
|
|
540
|
+
if(chipInfo.major === USB_MAJOR_TYPE_2232H) { return FTDIEEPROM.parseEEPROM_FT2232H(buffer, chipInfo) }
|
|
541
|
+
if(chipInfo.major === USB_MAJOR_TYPE_232H) { return FTDIEEPROM.parseEEPROM_232H(buffer, chipInfo) }
|
|
542
|
+
|
|
543
|
+
return undefined
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
static parseEEPROM(buffer: ArrayBufferView<ArrayBuffer|ArrayBuffer>, chipInfo: ChipInfo): EEPROMInfo|undefined {
|
|
547
|
+
const u16 = ArrayBuffer.isView(buffer) ?
|
|
548
|
+
new Uint16Array(buffer.buffer, buffer.byteOffset) :
|
|
549
|
+
new Uint16Array(buffer)
|
|
550
|
+
|
|
551
|
+
// cache the chip info as it will be updated
|
|
552
|
+
// to reflect the values used when parsing
|
|
553
|
+
const usedChipInfo = { ...chipInfo }
|
|
554
|
+
|
|
555
|
+
usedChipInfo.eepromSize = chipInfo.eepromSize ?? u16.length
|
|
556
|
+
console.log('using eepromSize16', usedChipInfo.eepromSize)
|
|
557
|
+
console.log('with u16 array length', u16.length)
|
|
558
|
+
|
|
559
|
+
const checksumCalculated = FTDIEEPROM.calculateChecksum(u16, usedChipInfo.eepromSize)
|
|
560
|
+
const checksum = u16[usedChipInfo.eepromSize - 1]
|
|
561
|
+
|
|
562
|
+
// const header = u16[0]
|
|
563
|
+
const vendorId = u16[1]
|
|
564
|
+
const productId = u16[2]
|
|
565
|
+
const type = u16[3]
|
|
566
|
+
const config = u16[4]
|
|
567
|
+
const chipConfig = u16[5]
|
|
568
|
+
// const _groupConfig = u16[6]
|
|
569
|
+
const manufactureInfo = u16[7]
|
|
570
|
+
const productInfo = u16[8]
|
|
571
|
+
const serialInfo = u16[9]
|
|
572
|
+
|
|
573
|
+
//
|
|
574
|
+
if(type === undefined) { return undefined }
|
|
575
|
+
const chipMajor = type >> 8 // 7
|
|
576
|
+
const chipMinor = type & MASK_8 // 6
|
|
577
|
+
|
|
578
|
+
//
|
|
579
|
+
usedChipInfo.major = usedChipInfo.major ?? chipMajor
|
|
580
|
+
usedChipInfo.minor = usedChipInfo.minor ?? chipMinor
|
|
581
|
+
|
|
582
|
+
//
|
|
583
|
+
const chipOffset = eepromTypeOffset(usedChipInfo)
|
|
584
|
+
const eepromType = eepromTypeFromValue(usedChipInfo, chipOffset ? u16[chipOffset]: undefined)
|
|
585
|
+
|
|
586
|
+
if(eepromType !== undefined && ((eepromType.byteLength/2) !== usedChipInfo.eepromSize)) {
|
|
587
|
+
console.log('Used ChipInfo byteLength does not match Detected EEPROM byteLength', eepromType.byteLength/2, usedChipInfo.eepromSize)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
//
|
|
591
|
+
if(vendorId === undefined) { return undefined }
|
|
592
|
+
if(productId === undefined) { return undefined }
|
|
593
|
+
if(config === undefined) { return undefined }
|
|
594
|
+
if(chipConfig === undefined) { return undefined }
|
|
595
|
+
if(manufactureInfo === undefined) { return undefined }
|
|
596
|
+
if(productInfo === undefined) { return undefined }
|
|
597
|
+
if(serialInfo === undefined) { return undefined }
|
|
598
|
+
|
|
599
|
+
//
|
|
600
|
+
const configH = config >> 8 // 9
|
|
601
|
+
const configL = config & MASK_8 // 8
|
|
602
|
+
const _reservedHigh = (configL & CONFIG_RESERVED_MASK) === CONFIG_RESERVED_MASK
|
|
603
|
+
const selfPowered = (configL & CONFIG_SELF_POWERED_MASK) === CONFIG_SELF_POWERED_MASK
|
|
604
|
+
const remoteWake = (configL & CONFIG_REMOTE_WAKE_MASK) === CONFIG_REMOTE_WAKE_MASK
|
|
605
|
+
|
|
606
|
+
const maxPower = configH * MAX_POWER_MILLIAMP_PER_UNIT
|
|
607
|
+
|
|
608
|
+
//
|
|
609
|
+
// const chipConfigH = chipConfig >> 8 // 11
|
|
610
|
+
const chipConfigL = chipConfig & MASK_8 // 10
|
|
611
|
+
const isInIsochronous = (chipConfigL & CONFIG_IN_ISOCHRONOUS_MASK) === CONFIG_IN_ISOCHRONOUS_MASK
|
|
612
|
+
const isOutIsochronous = (chipConfigL & CONFIG_OUT_ISOCHRONOUS_MASK) === CONFIG_OUT_ISOCHRONOUS_MASK
|
|
613
|
+
const suspendPullDowns = (chipConfigL & CONFIG_SUSPEND_PULL_DOWN) === CONFIG_SUSPEND_PULL_DOWN
|
|
614
|
+
const useSerial = (chipConfigL & CONFIG_USE_SERIAL) === CONFIG_USE_SERIAL
|
|
615
|
+
const useUSBVersion = (chipConfigL & CONFIG_USE_USB_VERSION) === CONFIG_USE_USB_VERSION
|
|
616
|
+
|
|
617
|
+
//
|
|
618
|
+
const decoder = new TextDecoder('utf-16le') // per-USB descriptor spec
|
|
619
|
+
const manufactureStr = FTDIEEPROM.parseEEPROMDescriptorString(manufactureInfo, u16, usedChipInfo.eepromSize, decoder)
|
|
620
|
+
const productStr = FTDIEEPROM.parseEEPROMDescriptorString(productInfo, u16, usedChipInfo.eepromSize, decoder)
|
|
621
|
+
const serialStr = FTDIEEPROM.parseEEPROMDescriptorString(serialInfo, u16, usedChipInfo.eepromSize, decoder)
|
|
622
|
+
|
|
623
|
+
//
|
|
624
|
+
const chipSpecificInfo = FTDIEEPROM.parseEEPROM_ChipSpecific(buffer, usedChipInfo) ?? {}
|
|
625
|
+
|
|
626
|
+
return {
|
|
627
|
+
vendorId,
|
|
628
|
+
productId,
|
|
629
|
+
|
|
630
|
+
chipVersion: {
|
|
631
|
+
chipMajor,
|
|
632
|
+
chipMinor,
|
|
633
|
+
},
|
|
634
|
+
chipInfo: usedChipInfo,
|
|
635
|
+
|
|
636
|
+
eepromType,
|
|
637
|
+
|
|
638
|
+
config: {
|
|
639
|
+
_reservedHigh,
|
|
640
|
+
selfPowered,
|
|
641
|
+
remoteWake,
|
|
642
|
+
maxPower
|
|
643
|
+
},
|
|
644
|
+
|
|
645
|
+
chipConfig: {
|
|
646
|
+
isInIsochronous,
|
|
647
|
+
isOutIsochronous,
|
|
648
|
+
suspendPullDowns,
|
|
649
|
+
useSerial,
|
|
650
|
+
useUSBVersion
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
manufacture: manufactureStr,
|
|
654
|
+
product: productStr,
|
|
655
|
+
serial: serialStr,
|
|
656
|
+
|
|
657
|
+
...chipSpecificInfo,
|
|
658
|
+
|
|
659
|
+
checksumCalculated,
|
|
660
|
+
checksum
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|