Skip to content

Commit 210192e

Browse files
committed
Added a reset command to interrupt long running operations.
1 parent 4c8325a commit 210192e

File tree

3 files changed

+162
-66
lines changed

3 files changed

+162
-66
lines changed

arduino/arduino.ino

Lines changed: 102 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
* 8 | EEPROM IO6
1717
* 9 | EEPROM IO7
1818
* ----+--------------
19-
* 10 | 74HC595 SER
20-
* 11 | 74HC595 RCLK
21-
* 12 | 74HC595 SCLK
19+
* A3 | 74HC595 OE
20+
* A4 | 74HC595 SER
21+
* 11 | 74HC595 SCLK
22+
* 12 | 74HC595 RCLK
23+
* 13 | 74HC595 CLR
2224
* ----+--------------
23-
* A0 | EEPROM CE
25+
* A0 | EEPROM WE
2426
* A1 | EEPROM OE
25-
* A2 | EEPROM WE
27+
* A2 | EEPROM CE
2628
* ----+--------------
2729
* 13 | Activity LED
2830
* ----+--------------
@@ -42,6 +44,14 @@
4244
* limitations under the License.
4345
*/
4446
enum MODE {STANDBY, READ, WRITE};
47+
typedef enum {
48+
OK,
49+
E_RESET, // reset command received
50+
E_CORRUPT, // inbound packet corrupt
51+
E_UNEXPECTED, // unexpected packet received
52+
E_UNKNOWN // unknown error
53+
} error;
54+
4555
const unsigned int MAX_PAYLOAD = 63;
4656
const unsigned int DELAY_US = 10;
4757

@@ -64,6 +74,7 @@ const unsigned int ACT_LED = 10;
6474
const unsigned int dataPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
6575

6676
MODE mode = NULL;
77+
error errno = OK;
6778

6879

6980
void setup() {
@@ -91,12 +102,13 @@ void setup() {
91102

92103
/*
93104
* Reads the next message from the serial port and copies its payload into
94-
* the global `buf` byte array.
105+
* the specified `buf` byte array.
95106
*
96107
* This function can participate in explicit flow control by sending an
97108
* explicit acknowledgement message if `sendAck` is `true`.
98109
*
99-
* Returns the number of bytes that were copied into `buf` (0 for acks).
110+
* Returns the number of bytes that were copied into `buf` (0 for acks), or -1
111+
* if there was an error (check global `errno`).
100112
*/
101113
int receive(byte *buf, size_t len, bool sendAck) {
102114
int l;
@@ -106,11 +118,12 @@ int receive(byte *buf, size_t len, bool sendAck) {
106118

107119
if (l > 0) {
108120
if (Serial.readBytes(buf, min(l, len)) != l) {
109-
error();
121+
errno = E_CORRUPT;
122+
return -1;
110123
}
111124
}
112-
if (sendAck) {
113-
send(NULL, 0, false);
125+
if (sendAck && send(NULL, 0, false) == -1) {
126+
return -1;
114127
}
115128
return l;
116129
}
@@ -121,18 +134,29 @@ int receive(byte *buf, size_t len, bool sendAck) {
121134
*
122135
* This function enforces flow control, blocking until the client has
123136
* acknowledged receipt with a 0-byte ack.
137+
*
138+
* Returns 0 on success, or -1 if an error occurred, in which case the global
139+
* `errno` variable gets set.
124140
*/
125-
void send(byte *buf, size_t len, bool waitForAck) {
141+
int send(byte *buf, size_t len, bool waitForAck) {
126142
Serial.write(len);
127143
if (len > 0) {
128144
Serial.write(buf, len);
129145
}
130146
if (waitForAck) {
131147
byte buf[1 + MAX_PAYLOAD];
132-
if (receive(buf, MAX_PAYLOAD, false) != 0) {
133-
error();
148+
int len = receive(buf, MAX_PAYLOAD, false);
149+
if (len != 0) {
150+
if (len == 1 && buf[0] == 'r') {
151+
// reset
152+
errno = E_RESET;
153+
} else if (len != -1) {
154+
errno = E_UNEXPECTED;
155+
}
156+
return -1;
134157
}
135158
}
159+
return 0;
136160
}
137161

138162
void pulse(int pin) {
@@ -198,8 +222,11 @@ void writeAddr(unsigned int addr, byte val) {
198222
/*
199223
* Writes the full contents of the EEPROM to the serial port in sequential
200224
* messages of up to 63 bytes, waiting for explicit acknowledgement of each.
225+
*
226+
* Returns 0 on success, -1 on error, in which case the global `errno` variable
227+
* will be set.
201228
*/
202-
void dump() {
229+
int dump() {
203230
byte payload[MAX_PAYLOAD];
204231
unsigned int i = 0;
205232

@@ -208,42 +235,55 @@ void dump() {
208235

209236
if (addr > 0 && i == 0) {
210237
// payload at capacity, send out:
211-
send(payload, sizeof(payload), true);
238+
if (send(payload, sizeof(payload), true) == -1) {
239+
return -1; // abort immediately
240+
}
212241
}
213242
payload[i++] = readAddr(addr);
214243
}
215244

216245
if (i) {
217246
// send remainder
218-
send(payload, i, true);
247+
return send(payload, i, true);
219248
}
249+
return 0;
220250
}
221251

222252
/*
223253
* Reads the specified number of bytes from the serial port and writes them
224254
* to the EEPROM.
225255
*
226256
* This requires the Arduino to be in WRITE mode.
257+
*
258+
* Returns 0 on success, -1 on error, in which case the global `errno` variable
259+
* gets set.
227260
*/
228-
void load(unsigned int len) {
261+
int load(unsigned int len) {
229262
unsigned int addr = 0;
230263
byte buf[1 + MAX_PAYLOAD];
231264

232265
while (addr < len) {
233-
unsigned int cnt = receive(buf, sizeof(buf), true);
266+
int cnt = receive(buf, sizeof(buf), true);
267+
if (cnt == -1) {
268+
// unexpected error; abort immediately
269+
return -1;
270+
}
234271

235-
for (unsigned int i = 0; i < cnt; i++) {
272+
for (int i = 0; i < cnt; i++) {
236273
writeAddr(addr++, buf[i]);
237274
delay(5);
238275
}
239276
}
277+
return 0;
240278
}
241279

242280
/*
243281
* Switches the pin mode for the I/O pins to OUTPUT, pulls EEPROM_CE LOW and
244282
* EEPROM_OE HIGH.
283+
*
284+
* Returns 0 on success, or -1 on error.
245285
*/
246-
void writeMode() {
286+
int writeMode() {
247287
digitalWrite(EEPROM_CE, LOW);
248288
digitalWrite(EEPROM_OE, HIGH);
249289
digitalWrite(EEPROM_WE, HIGH);
@@ -254,13 +294,16 @@ void writeMode() {
254294

255295
delayMicroseconds(DELAY_US);
256296
mode = WRITE;
297+
return 0;
257298
}
258299

259300
/**
260301
* Switches the pin mode for the I/O pins to INPUT, pulls EEPROM_CE LOW,
261302
* EEPROM_OE LOW and EEPROM_WE HIGH.
303+
*
304+
* Returns 0 on success, or -1 on error.
262305
*/
263-
void readMode() {
306+
int readMode() {
264307
if (mode != READ) {
265308
for (unsigned int i = 0; i < 8; i++) {
266309
pinMode(dataPins[i], INPUT);
@@ -273,9 +316,10 @@ void readMode() {
273316
delayMicroseconds(DELAY_US);
274317
mode = READ;
275318
}
319+
return 0;
276320
}
277321

278-
void standbyMode() {
322+
int standbyMode() {
279323
for (unsigned int i = 0; i < 8; i++) {
280324
pinMode(dataPins[i], INPUT);
281325
}
@@ -286,43 +330,57 @@ void standbyMode() {
286330

287331
delayMicroseconds(DELAY_US);
288332
mode = STANDBY;
333+
return 0;
289334
}
290335

291-
void error() {
292-
for (int i = 0; i < 5; i++) {
293-
digitalWrite(ACT_LED, LOW);
294-
delay(100);
295-
digitalWrite(ACT_LED, HIGH);
296-
delay(100);
336+
/**
337+
* Flashes out the errno value and resets the errno variable.
338+
*/
339+
void processError() {
340+
// TODO: different patterns for different errors
341+
if (errno != OK) {
342+
for (int i = 0; i < 5; i++) {
343+
digitalWrite(ACT_LED, HIGH);
344+
delay(100);
345+
digitalWrite(ACT_LED, LOW);
346+
delay(100);
347+
}
297348
}
349+
// clear global error state
350+
errno = OK;
298351
}
299352

300353
void loop() {
301354
if (Serial.available() > 0) {
302355
byte buf[1 + MAX_PAYLOAD];
303356
digitalWrite(ACT_LED, HIGH);
304357

305-
unsigned int len = receive(buf, sizeof(buf), false);
358+
const int len = receive(buf, sizeof(buf), false);
359+
if (len > 0) {
360+
if (buf[0] == 0x72 && len == 3) {
361+
byte val = readAddr((buf[1] << 8) + buf[2]);
362+
send(&val, 1, false);
363+
364+
} else if (buf[0] == 0x77 && len == 4) {
365+
writeAddr((buf[1] << 8) + buf[2], buf[3]);
366+
// signal operation completion
367+
send(NULL, 0, false);
306368

307-
if (buf[0] == 0x72 && len == 3) {
308-
byte val = readAddr((buf[1] << 8) + buf[2]);
309-
send(&val, 1, false);
369+
} else if (buf[0] == 0x64 && len == 1) {
370+
dump();
310371

311-
} else if (buf[0] == 0x77 && len == 4) {
312-
writeAddr((buf[1] << 8) + buf[2], buf[3]);
313-
// signal operation completion
314-
send(NULL, 0, false);
372+
} else if (buf[0] == 0x6c && len == 3) {
373+
send(NULL, 0, false); // acknowledge cmd message
374+
load((buf[1] << 8) + buf[2]);
315375

316-
} else if (buf[0] == 0x64 && len == 1) {
317-
dump();
318-
319-
} else if (buf[0] == 0x6c && len == 3) {
320-
send(NULL, 0, false); // acknowledge cmd message
321-
load((buf[1] << 8) + buf[2]);
376+
} else if (buf[0] == 0x72 && len == 1) {
377+
// ignore reset command
322378

323-
} else {
324-
error();
379+
} else {
380+
errno = E_UNKNOWN;
381+
}
325382
}
326383
digitalWrite(ACT_LED, LOW);
327384
}
385+
processError();
328386
}

0 commit comments

Comments
 (0)