-
Notifications
You must be signed in to change notification settings - Fork 101
/
reset.ts
192 lines (176 loc) · 5.36 KB
/
reset.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
import { Transport } from "./webserial.js";
const DEFAULT_RESET_DELAY = 50;
/**
* Sleep for ms milliseconds
* @param {number} ms Milliseconds to wait
* @returns {Promise<void>}
*/
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Execute a classic set of commands that will reset the chip.
*
* Commands (e.g. R0) are defined by a code (R) and an argument (0).
*
* The commands are:
*
* D: setDTR - 1=True / 0=False
*
* R: setRTS - 1=True / 0=False
*
* W: Wait (time delay) - positive integer number (miliseconds)
*
* "D0|R1|W100|D1|R0|W50|D0" represents the classic reset strategy
* @param {Transport} transport Transport class to perform serial communication.
* @param {number} resetDelay Delay in milliseconds for reset.
*/
export async function classicReset(transport: Transport, resetDelay = DEFAULT_RESET_DELAY) {
await transport.setDTR(false);
await transport.setRTS(true);
await sleep(100);
await transport.setDTR(true);
await transport.setRTS(false);
await sleep(resetDelay);
await transport.setDTR(false);
}
/**
* Execute a set of commands for USB JTAG serial reset.
*
* Commands (e.g. R0) are defined by a code (R) and an argument (0).
*
* The commands are:
*
* D: setDTR - 1=True / 0=False
*
* R: setRTS - 1=True / 0=False
*
* W: Wait (time delay) - positive integer number (miliseconds)
* @param {Transport} transport Transport class to perform serial communication.
*/
export async function usbJTAGSerialReset(transport: Transport) {
await transport.setRTS(false);
await transport.setDTR(false);
await sleep(100);
await transport.setDTR(true);
await transport.setRTS(false);
await sleep(100);
await transport.setRTS(true);
await transport.setDTR(false);
await transport.setRTS(true);
await sleep(100);
await transport.setRTS(false);
await transport.setDTR(false);
}
/**
* Execute a set of commands that will hard reset the chip.
*
* Commands (e.g. R0) are defined by a code (R) and an argument (0).
*
* The commands are:
*
* D: setDTR - 1=True / 0=False
*
* R: setRTS - 1=True / 0=False
*
* W: Wait (time delay) - positive integer number (miliseconds)
* @param {Transport} transport Transport class to perform serial communication.
* @param {boolean} usingUsbOtg is it using USB-OTG ?
*/
export async function hardReset(transport: Transport, usingUsbOtg = false) {
if (usingUsbOtg) {
await sleep(200);
await transport.setRTS(false);
await sleep(200);
} else {
await sleep(100);
await transport.setRTS(false);
}
}
type CmdsArgsTypes = {
D: boolean;
R: boolean;
W: number;
};
/**
* Validate a sequence string based on the following format:
*
* Commands (e.g. R0) are defined by a code (R) and an argument (0).
*
* The commands are:
*
* D: setDTR - 1=True / 0=False
*
* R: setRTS - 1=True / 0=False
*
* W: Wait (time delay) - positive integer number (miliseconds)
* @param {string} seqStr Sequence string to validate
* @returns {boolean} Is the sequence string valid ?
*/
export function validateCustomResetStringSequence(seqStr: string): boolean {
const commands: (keyof CmdsArgsTypes)[] = ["D", "R", "W"];
const commandsList = seqStr.split("|");
for (const cmd of commandsList) {
const code = cmd[0];
const arg = cmd.slice(1);
if (!commands.includes(code as keyof CmdsArgsTypes)) {
return false; // Invalid command code
}
if (code === "D" || code === "R") {
if (arg !== "0" && arg !== "1") {
return false; // Invalid argument for D and R commands
}
} else if (code === "W") {
const delay = parseInt(arg);
if (isNaN(delay) || delay <= 0) {
return false; // Invalid argument for W command
}
}
}
return true; // All commands are valid
}
/**
* Custom reset strategy defined with a string.
*
* The sequenceString input string consists of individual commands divided by "|".
*
* Commands (e.g. R0) are defined by a code (R) and an argument (0).
*
* The commands are:
*
* D: setDTR - 1=True / 0=False
*
* R: setRTS - 1=True / 0=False
*
* W: Wait (time delay) - positive integer number (miliseconds)
*
* "D0|R1|W100|D1|R0|W50|D0" represents the classic reset strategy
* @param {Transport} transport Transport class to perform serial communication.
* @param {string} sequenceString Custom string sequence for reset strategy
*/
export async function customReset(transport: Transport, sequenceString: string) {
const resetDictionary: { [K in keyof CmdsArgsTypes]: (arg: CmdsArgsTypes[K]) => Promise<void> } = {
D: async (arg: boolean) => await transport.setDTR(arg),
R: async (arg: boolean) => await transport.setRTS(arg),
W: async (delay: number) => await sleep(delay),
};
try {
const isValidSequence = validateCustomResetStringSequence(sequenceString);
if (!isValidSequence) {
return;
}
const cmds = sequenceString.split("|");
for (const cmd of cmds) {
const cmdKey = cmd[0];
const cmdVal = cmd.slice(1);
if (cmdKey === "W") {
await resetDictionary["W"](Number(cmdVal));
} else if (cmdKey === "D" || cmdKey === "R") {
await resetDictionary[cmdKey as "D" | "R"](cmdVal === "1");
}
}
} catch (error) {
throw new Error("Invalid custom reset sequence");
}
}
export default { classicReset, customReset, hardReset, usbJTAGSerialReset, validateCustomResetStringSequence };