-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.ts
307 lines (286 loc) · 7.84 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
import { openPromisified } from 'i2c-bus';
/**
* I2C Port Map Max サイズ
*/
const I2CPortMapSizeMax = 32;
/**
* Uint16 Max サイズ
*/
const Uint16Max = 65535;
/**
*
* Uint16型変換処理
* @param parseString 変換文字列
* @return Uint16型変換値
*/
function parseUint16(parseString: string) {
const n = Number.parseInt(parseString, 10);
if (0 <= n && n <= Uint16Max) return n;
else throw new RangeError(`Must be between 0 and ${Uint16Max}.`);
}
/** ポート番号 */
type PortNumber = number;
/** ポート名 */
type PortName = string;
/** I2C Slave アドレス */
type I2CSlaveAddress = number;
/**
* I2CAccess クラス
*/
export class I2CAccess {
private readonly _ports: I2CPortMap;
/**
* Creates an instance of GPIOAccess.
* @param ports ポート番号
*/
constructor(ports?: I2CPortMap) {
this._ports = ports == null ? new I2CPortMap() : ports;
}
/**
* ポート情報取得処理
* @return 現在のポート情報
*/
get ports(): I2CPortMap {
return this._ports;
}
}
/** Different from Web I2C API specification. */
export class I2CPortMap extends Map<PortNumber, I2CPort> {
getByName(portName: PortName): I2CPort | undefined {
const matches = /^i2c-(\d+)$/.exec(portName);
return matches == null ? undefined : this.get(parseUint16(matches[1]));
}
}
/**
* I2CPort クラス
*/
export class I2CPort {
private readonly _portNumber: PortNumber;
/**
* Creates an instance of GPIOPort.
* @param portNumber ポート番号
*/
constructor(portNumber: PortNumber) {
this._portNumber = parseUint16(portNumber.toString());
}
/**
* ポート番号取得処理
* @return 現在のポート番号
*/
get portNumber(): PortNumber {
return this._portNumber;
}
/**
* ポート名取得処理
* @return 現在のポート名
*/
get portName(): string {
return `i2c-${this.portNumber}`;
}
/**
* I2CSlave 接続デバイスオープン処理
* @param slaveAddress 接続デバイス情報のアドレス
* @return I2CSlaveDevice インスタンスの生成の完了
*/
async open(slaveAddress: I2CSlaveAddress): Promise<I2CSlaveDevice> {
const bus = await openPromisified(this.portNumber).catch((error) => {
throw new OperationError(error);
});
return {
slaveAddress,
/**
* @function
* I2C 読み取り処理
* @param registerNumber 読み取りアドレス
*/
read8: (registerNumber) =>
bus.readByte(slaveAddress, registerNumber).catch((error) => {
throw new OperationError(error);
}),
/**
* @function
* I2C 読み取り処理
* @param registerNumber 読み取りアドレス
*/
read16: (registerNumber) =>
bus.readWord(slaveAddress, registerNumber).catch((error) => {
throw new OperationError(error);
}),
/**
* @function
* I2c s/I2c/I2C 書き込み処理
* @param registerNumber 書き込みアドレス
* @param byte 書き込みの値(バイト)
*/
write8: async (registerNumber, byte) => {
try {
await bus.writeByte(slaveAddress, registerNumber, byte);
return byte;
} catch (error: any) {
throw new OperationError(error);
}
},
/**
* @function
* I2c bytes 書き込み処理
* @param registerNumber 書き込みアドレス
* @param word 書き込みの値(ワード)
*/
write16: async (registerNumber, word) => {
try {
await bus.writeWord(slaveAddress, registerNumber, word);
return word;
} catch (error: any) {
throw new OperationError(error);
}
},
/**
* @function
* I2c bytes 読み取りバイト処理
* Different from Web I2C API specification.
*/
readByte: async () => {
try {
const byte = await bus.receiveByte(slaveAddress);
return byte;
} catch (error: any) {
throw new OperationError(error);
}
},
/**
* @function
* I2c bytes 読み取りバイト処理
* Different from Web I2C API specification.
* @param length 読み取る配列の長さ
*/
readBytes: async (length) => {
try {
const { bytesRead, buffer } = await bus.i2cRead(
slaveAddress,
length,
Buffer.allocUnsafe(length)
);
return new Uint8Array(buffer.slice(0, bytesRead));
} catch (error: any) {
throw new OperationError(error);
}
},
/**
* @function
* I2c bytes 書き込みバイト処理
* Different from Web I2C API specification.
* @param byte 書き込みの値
*/
writeByte: async (byte) => {
try {
await bus.sendByte(slaveAddress, byte);
return byte;
} catch (error: any) {
throw new OperationError(error);
}
},
/**
* @function
* I2c bytes 書き込み処理
* Different from Web I2C API specification.
* @param bytes 書き込みの値の配列
*/
writeBytes: async (bytes) => {
try {
const { bytesWritten, buffer } = await bus.i2cWrite(
slaveAddress,
bytes.length,
Buffer.from(bytes)
);
return new Uint8Array(buffer.slice(0, bytesWritten));
} catch (error: any) {
throw new OperationError(error);
}
},
};
}
}
/**
* I2CSlaveDevice クラス
*/
export interface I2CSlaveDevice {
/** I2C Slave アドレス */
readonly slaveAddress: I2CSlaveAddress;
/**
* @function
* I2C 読み取り処理
* @param registerNumber 読み取りアドレス
*/
read8(registerNumber: number): Promise<number>;
/**
* @function
* I2C 読み取り処理
* @param registerNumber 読み取りアドレス
*/
read16(registerNumber: number): Promise<number>;
/**
* @function
* I2c s/I2c/I2C 書き込み処理
* @param registerNumber 書き込みアドレス
* @param value 書き込みの値(バイト)
*/
write8(registerNumber: number, value: number): Promise<number>;
/**
* @function
* I2c bytes 書き込み処理
* @param registerNumber 書き込みアドレス
* @param value 書き込みの値(ワード)
*/
write16(registerNumber: number, value: number): Promise<number>;
/**
* @function
* I2c bytes 読み取りバイト処理
* Different from Web I2C API specification.
*/
readByte(): Promise<number>;
/**
* @function
* I2c bytes 読み取りバイト処理
* Different from Web I2C API specification.
* @param length 読み取る配列の長さ
*/
readBytes(length: number): Promise<Uint8Array>;
/**
* @function
* I2c bytes 書き込みバイト処理
* Different from Web I2C API specification.
* @param byte 書き込みの値
*/
writeByte(byte: number): Promise<number>;
/**
* @function
* I2c bytes 書き込みバイト配列処理
* Different from Web I2C API specification.
* @param bytes 書き込みの値の配列
*/
writeBytes(bytes: Array<number>): Promise<Uint8Array>;
}
/**
* 操作エラー
*/
export class OperationError extends Error {
/**
* Creates an instance of OperationError.
* @param message エラーメッセージ
*/
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}
// Web I2Cの仕様に基づく意図的なasync関数の使用なので、ルールを無効化
// eslint-disable-next-line
export async function requestI2CAccess(): Promise<I2CAccess> {
const ports = new I2CPortMap(
[...Array(I2CPortMapSizeMax).keys()].map((portNumber) => [
portNumber,
new I2CPort(portNumber),
])
);
return new I2CAccess(ports);
}