Skip to content

Commit df95e5a

Browse files
committed
pio: run in sync with CPU core, honor ClockDiv
1 parent 4b038d5 commit df95e5a

File tree

2 files changed

+46
-25
lines changed

2 files changed

+46
-25
lines changed

src/peripherals/pio.ts

+36-25
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ export class StateMachine {
138138

139139
clockDivInt: number = 1;
140140
clockDivFrac: number = 0;
141+
curClockInt: number = 0;
142+
curClockFrac: number = 0;
143+
remainingDelay: number = 0;
141144
execCtrl = 0x1f << 12;
142145
shiftCtrl = 0b11 << 18;
143146
pinCtrl = 0x5 << 26;
@@ -436,7 +439,7 @@ export class StateMachine {
436439
}
437440
}
438441

439-
executeInstruction(opcode: number) {
442+
executeInstruction(opcode: number): number {
440443
const arg = opcode & 0xff;
441444
switch (opcode >>> 13) {
442445
/* JMP */
@@ -654,14 +657,16 @@ export class StateMachine {
654657

655658
if (this.execValid) {
656659
this.execValid = false;
657-
this.executeInstruction(this.execOpcode);
660+
return this.executeInstruction(this.execOpcode);
658661
} else if (this.waiting) {
659662
if (this.waitDelay < 0) {
660663
this.waitDelay = delay;
661664
}
662665
this.checkWait();
666+
return delay;
663667
} else {
664668
this.cycles += delay;
669+
return delay;
665670
}
666671
}
667672

@@ -683,6 +688,27 @@ export class StateMachine {
683688
}
684689

685690
step() {
691+
if (!this.enabled) {
692+
return;
693+
}
694+
695+
this.curClockFrac += this.clockDivFrac;
696+
if (this.curClockFrac > 0xff) {
697+
this.curClockInt++;
698+
this.curClockFrac -= 0x100;
699+
}
700+
this.curClockInt++;
701+
if (this.curClockInt < this.clockDivInt) {
702+
return;
703+
} else {
704+
this.curClockInt -= this.clockDivInt;
705+
}
706+
707+
if (this.remainingDelay > 0) {
708+
this.remainingDelay--;
709+
return;
710+
}
711+
686712
if (this.waiting) {
687713
this.checkWait();
688714
if (this.waiting) {
@@ -691,7 +717,7 @@ export class StateMachine {
691717
}
692718

693719
this.updatePC = true;
694-
this.executeInstruction(this.pio.instructions[this.pc]);
720+
this.remainingDelay += this.executeInstruction(this.pio.instructions[this.pc]);
695721
if (this.updatePC) {
696722
this.nextPC();
697723
}
@@ -833,6 +859,9 @@ export class StateMachine {
833859

834860
restart() {
835861
this.cycles = 0;
862+
this.curClockInt = 0;
863+
this.curClockFrac = 0;
864+
this.remainingDelay = 0;
836865
this.inputShiftCount = 0;
837866
this.outputShiftCount = 32;
838867
this.inputShiftReg = 0;
@@ -930,7 +959,6 @@ export class RPPIO extends BasePeripheral implements Peripheral {
930959
pinDirections = 0;
931960
oldPinValues = 0;
932961
oldPinDirections = 0;
933-
private runTimer: NodeJS.Timeout | null = null;
934962

935963
irq0IntEnable = 0;
936964
irq0IntForce = 0;
@@ -1077,14 +1105,7 @@ export class RPPIO extends BasePeripheral implements Peripheral {
10771105
this.machines[index].clkDivRestart();
10781106
}
10791107
}
1080-
const shouldRun = value & 0xf;
1081-
if (this.stopped && shouldRun) {
1082-
this.stopped = false;
1083-
this.run();
1084-
}
1085-
if (!shouldRun) {
1086-
this.stopped = true;
1087-
}
1108+
this.stopped = !(value & 0xf);
10881109
break;
10891110
}
10901111
case FDEBUG:
@@ -1179,29 +1200,19 @@ export class RPPIO extends BasePeripheral implements Peripheral {
11791200
}
11801201

11811202
step() {
1203+
if (this.stopped) {
1204+
return;
1205+
}
11821206
for (const machine of this.machines) {
11831207
machine.step();
11841208
}
11851209
this.checkChangedPins();
11861210
}
11871211

1188-
run() {
1189-
for (let i = 0; i < 1000 && !this.stopped; i++) {
1190-
this.step();
1191-
}
1192-
if (!this.stopped) {
1193-
this.runTimer = setTimeout(() => this.run(), 0);
1194-
}
1195-
}
1196-
11971212
stop() {
11981213
for (const machine of this.machines) {
11991214
machine.enabled = false;
12001215
}
12011216
this.stopped = true;
1202-
if (this.runTimer) {
1203-
clearTimeout(this.runTimer);
1204-
this.runTimer = null;
1205-
}
12061217
}
12071218
}

src/rp2040.ts

+10
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,25 @@ export class RP2040 {
350350
}
351351

352352
step() {
353+
const coreStartCycles = this.core.cycles;
353354
this.core.executeInstruction();
355+
for (let cycle = coreStartCycles; cycle < this.core.cycles; cycle++) {
356+
this.pio[0].step();
357+
this.pio[1].step();
358+
}
354359
}
355360

356361
execute() {
357362
this.clock.resume();
358363
this.executeTimer = null;
359364
this.stopped = false;
360365
for (let i = 0; i < 100000 && !this.stopped && !this.core.waiting; i++) {
366+
const coreStartCycles = this.core.cycles;
361367
this.core.executeInstruction();
368+
for (let cycle = coreStartCycles; cycle < this.core.cycles; cycle++) {
369+
this.pio[0].step();
370+
this.pio[1].step();
371+
}
362372
}
363373
if (!this.stopped) {
364374
this.executeTimer = setTimeout(() => this.execute(), 0);

0 commit comments

Comments
 (0)