-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrunner.js
67 lines (59 loc) · 2.06 KB
/
runner.js
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
const { avrInstruction, AVRTimer, CPU, timer0Config, AVRUSART, usart0Config, AVRIOPort, portBConfig, portCConfig, portDConfig } = require("avr8js");
const FLASH = 0x8000;
function loadHex(source, target) {
for (const line of source.split('\n')) {
if (line[0] === ':' && line.substr(7, 2) === '00') {
const bytes = parseInt(line.substr(1, 2), 16);
const addr = parseInt(line.substr(3, 4), 16);
for (let i = 0; i < bytes; i++) {
target[addr + i] = parseInt(line.substr(9 + i * 2, 2), 16);
}
}
}
}
class AVRRunner {
constructor(hex) {
this.program = new Uint16Array(FLASH);
loadHex(hex, new Uint8Array(this.program.buffer));
this.cpu = new CPU(this.program);
this.timer = new AVRTimer(this.cpu, timer0Config);
this.portB = new AVRIOPort(this.cpu, portBConfig);
this.portC = new AVRIOPort(this.cpu, portCConfig);
this.portD = new AVRIOPort(this.cpu, portDConfig);
this.usart = new AVRUSART(this.cpu, usart0Config, this.MHZ);
this.usart.onRxComplete = () => this.flushTXQueue();
this.MHZ = 16e6;
this.stopped = false;
this.serialQueue = [];
}
async execute(callback) {
this.stopped = false;
while (true) {
avrInstruction(this.cpu);
this.cpu.tick();
if (this.cpu.cycles % 500000 === 0) {
callback(this.cpu);
await new Promise(resolve => setTimeout(resolve, 0));
if (this.stopped) {
break;
}
}
}
}
flushTXQueue() {
if (!this.usart.rxBusy && this.serialQueue.length) {
this.usart.writeByte(this.serialQueue.shift());
}
}
transmit(...values) {
this.serialQueue.push(...values);
this.flushTXQueue();
}
transmitString(value) {
this.transmit(...Array.from(new TextEncoder().encode(value)));
}
stop() {
this.stopped = true;
}
}
module.exports = { AVRRunner, loadHex }