rp2040js 0.17.17 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/dist/cjs/clock/clock.d.ts +11 -11
  2. package/dist/cjs/clock/clock.js +2 -2
  3. package/dist/cjs/clock/mock-clock.d.ts +17 -17
  4. package/dist/cjs/clock/mock-clock.js +52 -52
  5. package/dist/cjs/clock/realtime-clock.d.ts +23 -23
  6. package/dist/cjs/clock/realtime-clock.js +73 -73
  7. package/dist/cjs/cortex-m0-core.d.ts +87 -87
  8. package/dist/cjs/cortex-m0-core.js +1251 -1251
  9. package/dist/cjs/gdb/gdb-connection.d.ts +11 -11
  10. package/dist/cjs/gdb/gdb-connection.js +57 -57
  11. package/dist/cjs/gdb/gdb-server.d.ts +23 -23
  12. package/dist/cjs/gdb/gdb-server.js +232 -232
  13. package/dist/cjs/gdb/gdb-tcp-server.d.ts +10 -10
  14. package/dist/cjs/gdb/gdb-tcp-server.js +34 -34
  15. package/dist/cjs/gdb/gdb-utils.d.ts +9 -9
  16. package/dist/cjs/gdb/gdb-utils.js +48 -48
  17. package/dist/cjs/gpio-pin.d.ts +56 -56
  18. package/dist/cjs/gpio-pin.js +216 -216
  19. package/dist/cjs/index.d.ts +11 -11
  20. package/dist/cjs/index.js +36 -36
  21. package/dist/cjs/interpolator.d.ts +36 -36
  22. package/dist/cjs/interpolator.js +150 -150
  23. package/dist/cjs/irq.d.ts +29 -29
  24. package/dist/cjs/irq.js +33 -33
  25. package/dist/cjs/peripherals/adc.d.ts +52 -52
  26. package/dist/cjs/peripherals/adc.js +261 -261
  27. package/dist/cjs/peripherals/busctrl.d.ts +10 -10
  28. package/dist/cjs/peripherals/busctrl.js +84 -84
  29. package/dist/cjs/peripherals/clocks.d.ts +9 -9
  30. package/dist/cjs/peripherals/clocks.js +42 -42
  31. package/dist/cjs/peripherals/dma.d.ts +109 -109
  32. package/dist/cjs/peripherals/dma.js +520 -520
  33. package/dist/cjs/peripherals/i2c.d.ts +54 -54
  34. package/dist/cjs/peripherals/i2c.js +458 -458
  35. package/dist/cjs/peripherals/io.d.ts +11 -11
  36. package/dist/cjs/peripherals/io.js +100 -100
  37. package/dist/cjs/peripherals/pads.d.ts +13 -13
  38. package/dist/cjs/peripherals/pads.js +58 -58
  39. package/dist/cjs/peripherals/peripheral.d.ts +22 -22
  40. package/dist/cjs/peripherals/peripheral.js +61 -61
  41. package/dist/cjs/peripherals/pio.d.ts +120 -120
  42. package/dist/cjs/peripherals/pio.js +1086 -1086
  43. package/dist/cjs/peripherals/ppb.d.ts +25 -25
  44. package/dist/cjs/peripherals/ppb.js +229 -229
  45. package/dist/cjs/peripherals/pwm.d.ts +65 -65
  46. package/dist/cjs/peripherals/pwm.js +372 -372
  47. package/dist/cjs/peripherals/reset.d.ts +8 -8
  48. package/dist/cjs/peripherals/reset.js +40 -40
  49. package/dist/cjs/peripherals/rtc.d.ts +10 -10
  50. package/dist/cjs/peripherals/rtc.js +74 -74
  51. package/dist/cjs/peripherals/spi.d.ts +38 -38
  52. package/dist/cjs/peripherals/spi.js +240 -240
  53. package/dist/cjs/peripherals/ssi.d.ts +6 -6
  54. package/dist/cjs/peripherals/ssi.js +43 -43
  55. package/dist/cjs/peripherals/syscfg.d.ts +5 -5
  56. package/dist/cjs/peripherals/syscfg.js +26 -26
  57. package/dist/cjs/peripherals/sysinfo.d.ts +4 -4
  58. package/dist/cjs/peripherals/sysinfo.js +22 -22
  59. package/dist/cjs/peripherals/tbman.d.ts +4 -4
  60. package/dist/cjs/peripherals/tbman.js +17 -17
  61. package/dist/cjs/peripherals/timer.d.ts +18 -18
  62. package/dist/cjs/peripherals/timer.js +156 -156
  63. package/dist/cjs/peripherals/uart.d.ts +31 -31
  64. package/dist/cjs/peripherals/uart.js +132 -132
  65. package/dist/cjs/peripherals/usb.d.ts +29 -29
  66. package/dist/cjs/peripherals/usb.js +309 -309
  67. package/dist/cjs/rp2040.d.ts +71 -71
  68. package/dist/cjs/rp2040.js +361 -361
  69. package/dist/cjs/sio.d.ts +21 -21
  70. package/dist/cjs/sio.js +425 -425
  71. package/dist/cjs/usb/cdc.d.ts +20 -20
  72. package/dist/cjs/usb/cdc.js +126 -126
  73. package/dist/cjs/usb/interfaces.d.ts +47 -47
  74. package/dist/cjs/usb/interfaces.js +46 -46
  75. package/dist/cjs/usb/setup.d.ts +5 -5
  76. package/dist/cjs/usb/setup.js +53 -53
  77. package/dist/cjs/utils/assembler.d.ts +79 -79
  78. package/dist/cjs/utils/assembler.js +328 -328
  79. package/dist/cjs/utils/bit.d.ts +3 -3
  80. package/dist/cjs/utils/bit.js +15 -15
  81. package/dist/cjs/utils/fifo.d.ts +15 -15
  82. package/dist/cjs/utils/fifo.js +56 -56
  83. package/dist/cjs/utils/logging.d.ts +23 -23
  84. package/dist/cjs/utils/logging.js +48 -48
  85. package/dist/cjs/utils/pio-assembler.d.ts +45 -45
  86. package/dist/cjs/utils/pio-assembler.js +87 -87
  87. package/dist/cjs/utils/time.d.ts +2 -2
  88. package/dist/cjs/utils/time.js +32 -32
  89. package/dist/cjs/utils/timer32.d.ts +57 -57
  90. package/dist/cjs/utils/timer32.js +208 -208
  91. package/dist/esm/clock/clock.d.ts +11 -11
  92. package/dist/esm/clock/clock.js +1 -1
  93. package/dist/esm/clock/mock-clock.d.ts +17 -17
  94. package/dist/esm/clock/mock-clock.js +47 -47
  95. package/dist/esm/clock/realtime-clock.d.ts +23 -23
  96. package/dist/esm/clock/realtime-clock.js +68 -68
  97. package/dist/esm/cortex-m0-core.d.ts +87 -87
  98. package/dist/esm/cortex-m0-core.js +1247 -1247
  99. package/dist/esm/gdb/gdb-connection.d.ts +11 -11
  100. package/dist/esm/gdb/gdb-connection.js +53 -53
  101. package/dist/esm/gdb/gdb-server.d.ts +23 -23
  102. package/dist/esm/gdb/gdb-server.js +228 -228
  103. package/dist/esm/gdb/gdb-tcp-server.d.ts +10 -10
  104. package/dist/esm/gdb/gdb-tcp-server.js +30 -30
  105. package/dist/esm/gdb/gdb-utils.d.ts +9 -9
  106. package/dist/esm/gdb/gdb-utils.js +36 -36
  107. package/dist/esm/gpio-pin.d.ts +56 -56
  108. package/dist/esm/gpio-pin.js +212 -212
  109. package/dist/esm/index.d.ts +11 -11
  110. package/dist/esm/index.js +11 -11
  111. package/dist/esm/interpolator.d.ts +36 -36
  112. package/dist/esm/interpolator.js +145 -145
  113. package/dist/esm/irq.d.ts +29 -29
  114. package/dist/esm/irq.js +30 -30
  115. package/dist/esm/peripherals/adc.d.ts +52 -52
  116. package/dist/esm/peripherals/adc.js +257 -257
  117. package/dist/esm/peripherals/busctrl.d.ts +10 -10
  118. package/dist/esm/peripherals/busctrl.js +80 -80
  119. package/dist/esm/peripherals/clocks.d.ts +9 -9
  120. package/dist/esm/peripherals/clocks.js +38 -38
  121. package/dist/esm/peripherals/dma.d.ts +109 -109
  122. package/dist/esm/peripherals/dma.js +515 -515
  123. package/dist/esm/peripherals/i2c.d.ts +54 -54
  124. package/dist/esm/peripherals/i2c.js +454 -454
  125. package/dist/esm/peripherals/io.d.ts +11 -11
  126. package/dist/esm/peripherals/io.js +96 -96
  127. package/dist/esm/peripherals/pads.d.ts +13 -13
  128. package/dist/esm/peripherals/pads.js +54 -54
  129. package/dist/esm/peripherals/peripheral.d.ts +22 -22
  130. package/dist/esm/peripherals/peripheral.js +55 -55
  131. package/dist/esm/peripherals/pio.d.ts +120 -120
  132. package/dist/esm/peripherals/pio.js +1081 -1081
  133. package/dist/esm/peripherals/ppb.d.ts +25 -25
  134. package/dist/esm/peripherals/ppb.js +225 -225
  135. package/dist/esm/peripherals/pwm.d.ts +65 -65
  136. package/dist/esm/peripherals/pwm.js +368 -368
  137. package/dist/esm/peripherals/reset.d.ts +8 -8
  138. package/dist/esm/peripherals/reset.js +36 -36
  139. package/dist/esm/peripherals/rtc.d.ts +10 -10
  140. package/dist/esm/peripherals/rtc.js +70 -70
  141. package/dist/esm/peripherals/spi.d.ts +38 -38
  142. package/dist/esm/peripherals/spi.js +236 -236
  143. package/dist/esm/peripherals/ssi.d.ts +6 -6
  144. package/dist/esm/peripherals/ssi.js +39 -39
  145. package/dist/esm/peripherals/syscfg.d.ts +5 -5
  146. package/dist/esm/peripherals/syscfg.js +22 -22
  147. package/dist/esm/peripherals/sysinfo.d.ts +4 -4
  148. package/dist/esm/peripherals/sysinfo.js +18 -18
  149. package/dist/esm/peripherals/tbman.d.ts +4 -4
  150. package/dist/esm/peripherals/tbman.js +13 -13
  151. package/dist/esm/peripherals/timer.d.ts +18 -18
  152. package/dist/esm/peripherals/timer.js +152 -152
  153. package/dist/esm/peripherals/uart.d.ts +31 -31
  154. package/dist/esm/peripherals/uart.js +128 -128
  155. package/dist/esm/peripherals/usb.d.ts +29 -29
  156. package/dist/esm/peripherals/usb.js +305 -305
  157. package/dist/esm/rp2040.d.ts +71 -71
  158. package/dist/esm/rp2040.js +357 -357
  159. package/dist/esm/sio.d.ts +21 -21
  160. package/dist/esm/sio.js +421 -421
  161. package/dist/esm/usb/cdc.d.ts +20 -20
  162. package/dist/esm/usb/cdc.js +121 -121
  163. package/dist/esm/usb/interfaces.d.ts +47 -47
  164. package/dist/esm/usb/interfaces.js +43 -43
  165. package/dist/esm/usb/setup.d.ts +5 -5
  166. package/dist/esm/usb/setup.js +46 -46
  167. package/dist/esm/utils/assembler.d.ts +79 -79
  168. package/dist/esm/utils/assembler.js +245 -245
  169. package/dist/esm/utils/bit.d.ts +3 -3
  170. package/dist/esm/utils/bit.js +9 -9
  171. package/dist/esm/utils/fifo.d.ts +15 -15
  172. package/dist/esm/utils/fifo.js +52 -52
  173. package/dist/esm/utils/logging.d.ts +23 -23
  174. package/dist/esm/utils/logging.js +44 -44
  175. package/dist/esm/utils/pio-assembler.d.ts +45 -45
  176. package/dist/esm/utils/pio-assembler.js +75 -75
  177. package/dist/esm/utils/time.d.ts +2 -2
  178. package/dist/esm/utils/time.js +27 -27
  179. package/dist/esm/utils/timer32.d.ts +57 -57
  180. package/dist/esm/utils/timer32.js +203 -203
  181. package/package.json +33 -22
  182. package/dist/esm/package.json +0 -1
@@ -1,1086 +1,1086 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RPPIO = exports.StateMachine = exports.WaitType = void 0;
4
- const fifo_1 = require("../utils/fifo");
5
- const dma_1 = require("./dma");
6
- const peripheral_1 = require("./peripheral");
7
- // Generic registers
8
- const CTRL = 0x000;
9
- const FSTAT = 0x004;
10
- const FDEBUG = 0x008;
11
- const FLEVEL = 0x00c;
12
- const IRQ = 0x030;
13
- const IRQ_FORCE = 0x034;
14
- const INPUT_SYNC_BYPASS = 0x038;
15
- const DBG_PADOUT = 0x03c;
16
- const DBG_PADOE = 0x040;
17
- const DBG_CFGINFO = 0x044;
18
- const INSTR_MEM0 = 0x48;
19
- const INSTR_MEM31 = 0x0c4;
20
- const INTR = 0x128; // Raw Interrupts
21
- const IRQ0_INTE = 0x12c; // Interrupt Enable for irq0
22
- const IRQ0_INTF = 0x130; // Interrupt Force for irq0
23
- const IRQ0_INTS = 0x134; // Interrupt status after masking & forcing for irq0
24
- const IRQ1_INTE = 0x138; // Interrupt Enable for irq1
25
- const IRQ1_INTF = 0x13c; // Interrupt Force for irq1
26
- const IRQ1_INTS = 0x140; // Interrupt status after masking & forcing for irq1
27
- // State-machine specific registers
28
- const TXF0 = 0x010;
29
- const TXF1 = 0x014;
30
- const TXF2 = 0x018;
31
- const TXF3 = 0x01c;
32
- const RXF0 = 0x020;
33
- const RXF1 = 0x024;
34
- const RXF2 = 0x028;
35
- const RXF3 = 0x02c;
36
- const SM0_CLKDIV = 0x0c8; // Clock divisor register for state machine 0
37
- const SM0_EXECCTRL = 0x0cc; // Execution/behavioural settings for state machine 0
38
- const SM0_SHIFTCTRL = 0x0d0; // Control behaviour of the input/output shift registers for state machine 0
39
- const SM0_ADDR = 0x0d4; // Current instruction address of state machine 0
40
- const SM0_INSTR = 0x0d8; // Write to execute an instruction immediately (including jumps) and then resume execution.
41
- const SM0_PINCTRL = 0x0dc; //State machine pin control
42
- const SM1_CLKDIV = 0x0e0;
43
- const SM1_PINCTRL = 0x0f4;
44
- const SM2_CLKDIV = 0x0f8;
45
- const SM2_PINCTRL = 0x10c;
46
- const SM3_CLKDIV = 0x110;
47
- const SM3_PINCTRL = 0x124;
48
- // FSTAT bits
49
- const FSTAT_TXEMPTY = 1 << 24;
50
- const FSTAT_TXFULL = 1 << 16;
51
- const FSTAT_RXEMPTY = 1 << 8;
52
- const FSTAT_RXFULL = 1 << 0;
53
- // FDEBUG bits
54
- const FDEBUG_TXSTALL = 1 << 24;
55
- const FDEBUG_TXOVER = 1 << 16;
56
- const FDEBUG_RXUNDER = 1 << 8;
57
- const FDEBUG_RXSTALL = 1 << 0;
58
- // SHIFTCTRL bits
59
- const SHIFTCTRL_AUTOPUSH = 1 << 16;
60
- const SHIFTCTRL_AUTOPULL = 1 << 17;
61
- const SHIFTCTRL_IN_SHIFTDIR = 1 << 18; // 1 = shift input shift register to right (data enters from left). 0 = to left
62
- const SHIFTCTRL_OUT_SHIFTDIR = 1 << 19; // 1 = shift out of output shift register to right. 0 = to left
63
- // EXECCTRL bits
64
- const EXECCTRL_STATUS_SEL = 1 << 4;
65
- const EXECCTRL_SIDE_PINDIR = 1 << 29;
66
- const EXECCTRL_SIDE_EN = 1 << 30;
67
- const EXECCTRL_EXEC_STALLED = 1 << 31;
68
- var WaitType;
69
- (function (WaitType) {
70
- WaitType[WaitType["None"] = 0] = "None";
71
- WaitType[WaitType["Pin"] = 1] = "Pin";
72
- WaitType[WaitType["rxFIFO"] = 2] = "rxFIFO";
73
- WaitType[WaitType["txFIFO"] = 3] = "txFIFO";
74
- WaitType[WaitType["IRQ"] = 4] = "IRQ";
75
- WaitType[WaitType["Out"] = 5] = "Out";
76
- })(WaitType = exports.WaitType || (exports.WaitType = {}));
77
- function bitReverse(x) {
78
- x = ((x & 0x55555555) << 1) | ((x & 0xaaaaaaaa) >>> 1);
79
- x = ((x & 0x33333333) << 2) | ((x & 0xcccccccc) >>> 2);
80
- x = ((x & 0x0f0f0f0f) << 4) | ((x & 0xf0f0f0f0) >>> 4);
81
- x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >>> 8);
82
- x = ((x & 0x0000ffff) << 16) | ((x & 0xffff0000) >>> 16);
83
- return x >>> 0;
84
- }
85
- function irqIndex(irq, machineIndex) {
86
- const rel = !!(irq & 0x10);
87
- return rel ? (irq & 0x4) | (((irq & 0x3) + machineIndex) & 0x3) : irq & 0x7;
88
- }
89
- const dreqRx0 = [
90
- dma_1.DREQChannel.DREQ_PIO0_RX0,
91
- dma_1.DREQChannel.DREQ_PIO0_RX1,
92
- dma_1.DREQChannel.DREQ_PIO0_RX2,
93
- dma_1.DREQChannel.DREQ_PIO0_RX3,
94
- ];
95
- const dreqTx0 = [
96
- dma_1.DREQChannel.DREQ_PIO0_TX0,
97
- dma_1.DREQChannel.DREQ_PIO0_TX1,
98
- dma_1.DREQChannel.DREQ_PIO0_TX2,
99
- dma_1.DREQChannel.DREQ_PIO0_TX3,
100
- ];
101
- const dreqRx1 = [
102
- dma_1.DREQChannel.DREQ_PIO1_RX0,
103
- dma_1.DREQChannel.DREQ_PIO1_RX1,
104
- dma_1.DREQChannel.DREQ_PIO1_RX2,
105
- dma_1.DREQChannel.DREQ_PIO1_RX3,
106
- ];
107
- const dreqTx1 = [
108
- dma_1.DREQChannel.DREQ_PIO1_TX0,
109
- dma_1.DREQChannel.DREQ_PIO1_TX1,
110
- dma_1.DREQChannel.DREQ_PIO1_TX2,
111
- dma_1.DREQChannel.DREQ_PIO1_TX3,
112
- ];
113
- class StateMachine {
114
- constructor(rp2040, pio, index) {
115
- this.rp2040 = rp2040;
116
- this.pio = pio;
117
- this.index = index;
118
- this.enabled = false;
119
- // State machine registers
120
- this.x = 0;
121
- this.y = 0;
122
- this.pc = 0;
123
- this.inputShiftReg = 0;
124
- this.inputShiftCount = 0;
125
- this.outputShiftReg = 0;
126
- this.outputShiftCount = 0;
127
- this.cycles = 0;
128
- this.execOpcode = 0;
129
- this.execValid = false;
130
- this.updatePC = true;
131
- this.clockDivInt = 1;
132
- this.clockDivFrac = 0;
133
- this.execCtrl = 0x1f << 12;
134
- this.shiftCtrl = 0b11 << 18;
135
- this.pinCtrl = 0x5 << 26;
136
- this.rxFIFO = new fifo_1.FIFO(4);
137
- this.txFIFO = new fifo_1.FIFO(4);
138
- this.outPinValues = 0;
139
- this.outPinDirection = 0;
140
- this.waiting = false;
141
- this.waitType = WaitType.None;
142
- this.waitIndex = 0;
143
- this.waitPolarity = false;
144
- this.waitDelay = -1;
145
- this.dreqRx = this.pio.dreqRx[this.index];
146
- this.dreqTx = this.pio.dreqTx[this.index];
147
- this.updateDMARx();
148
- this.updateDMATx();
149
- }
150
- updateDMATx() {
151
- if (this.txFIFO.full) {
152
- this.rp2040.dma.clearDREQ(this.dreqTx);
153
- }
154
- else {
155
- this.rp2040.dma.setDREQ(this.dreqTx);
156
- }
157
- }
158
- updateDMARx() {
159
- if (this.rxFIFO.empty) {
160
- this.rp2040.dma.clearDREQ(this.dreqRx);
161
- }
162
- else {
163
- this.rp2040.dma.setDREQ(this.dreqRx);
164
- }
165
- }
166
- writeFIFO(value) {
167
- if (this.txFIFO.full) {
168
- this.pio.fdebug |= FDEBUG_TXOVER << this.index;
169
- return;
170
- }
171
- this.txFIFO.push(value);
172
- this.updateDMATx();
173
- this.checkWait();
174
- if (this.txFIFO.full) {
175
- this.pio.checkInterrupts();
176
- }
177
- }
178
- readFIFO() {
179
- if (this.rxFIFO.empty) {
180
- this.pio.fdebug |= FDEBUG_RXUNDER << this.index;
181
- return 0;
182
- }
183
- const result = this.rxFIFO.pull();
184
- this.updateDMARx();
185
- this.checkWait();
186
- if (this.rxFIFO.empty) {
187
- this.pio.checkInterrupts();
188
- }
189
- return result;
190
- }
191
- get status() {
192
- const statusN = this.execCtrl & 0xf;
193
- if (this.execCtrl & EXECCTRL_STATUS_SEL) {
194
- return this.rxFIFO.itemCount < statusN ? 0xffffffff : 0;
195
- }
196
- else {
197
- return this.txFIFO.itemCount < statusN ? 0xffffffff : 0;
198
- }
199
- }
200
- jmpCondition(condition) {
201
- switch (condition) {
202
- // (no condition): Always
203
- case 0b000:
204
- return true;
205
- // !X: scratch X zero
206
- case 0b001:
207
- return this.x === 0;
208
- // X--: scratch X non-zero, post-decrement
209
- case 0b010: {
210
- const oldX = this.x;
211
- this.x = (this.x - 1) >>> 0;
212
- return oldX !== 0;
213
- }
214
- // !Y: scratch Y zero
215
- case 0b011:
216
- return this.y === 0;
217
- // Y--: scratch Y non-zero, post-decrement
218
- case 0b100: {
219
- const oldY = this.y;
220
- this.y = (this.y - 1) >>> 0;
221
- return oldY !== 0;
222
- }
223
- // X!=Y: scratch X not equal scratch Y
224
- case 0b101:
225
- return this.x >>> 0 !== this.y >>> 0;
226
- // PIN: branch on input pin
227
- case 0b110: {
228
- const { gpio } = this.rp2040;
229
- const { jmpPin } = this;
230
- return jmpPin < gpio.length ? gpio[jmpPin].inputValue : false;
231
- }
232
- // !OSRE: output shift register not empty
233
- case 0b111:
234
- return this.outputShiftCount < this.pullThreshold;
235
- }
236
- this.pio.error(`jmpCondition with unsupported condition: ${condition}`);
237
- return false;
238
- }
239
- get inPins() {
240
- const { gpioValues } = this.rp2040;
241
- const { inBase } = this;
242
- return inBase ? (gpioValues << (32 - inBase)) | (gpioValues >>> inBase) : gpioValues;
243
- }
244
- inSourceValue(source) {
245
- switch (source) {
246
- // PINS
247
- case 0b000:
248
- return this.inPins;
249
- // X (scratch register X)
250
- case 0b001:
251
- return this.x;
252
- // Y (scratch register Y)
253
- case 0b010:
254
- return this.y;
255
- // NULL (all zeroes)
256
- case 0b011:
257
- return 0;
258
- // Reserved
259
- case 0b100:
260
- return 0;
261
- // Reserved for IN, STATUS for MOV
262
- case 0b101:
263
- return this.status;
264
- // ISR
265
- case 0b110:
266
- return this.inputShiftReg;
267
- // OSR
268
- case 0b111:
269
- return this.outputShiftReg;
270
- }
271
- this.pio.error(`inSourceValue with unsupported source: ${source}`);
272
- return 0;
273
- }
274
- writeOutValue(destination, value, bitCount) {
275
- switch (destination) {
276
- // PINS
277
- case 0b000:
278
- this.setOutPins(value);
279
- break;
280
- // X (scratch register X)
281
- case 0b001:
282
- this.x = value;
283
- break;
284
- // Y (scratch register Y)
285
- case 0b010:
286
- this.y = value;
287
- break;
288
- // NULL (discard data)
289
- case 0b011:
290
- break;
291
- // PINDIRS
292
- case 0b100:
293
- this.setOutPinDirs(value);
294
- break;
295
- // PC
296
- case 0b101:
297
- this.pc = value & 0x1f;
298
- this.updatePC = false;
299
- break;
300
- // ISR (also sets ISR shift counter to Bit count)
301
- case 0b110:
302
- this.inputShiftReg = value;
303
- this.inputShiftCount = bitCount;
304
- break;
305
- // EXEC (Execute OSR shift data as instruction)
306
- case 0b111:
307
- this.execOpcode = value;
308
- this.execValid = true;
309
- break;
310
- }
311
- }
312
- get pushThreshold() {
313
- const value = (this.shiftCtrl >> 20) & 0x1f;
314
- return value ? value : 32;
315
- }
316
- get pullThreshold() {
317
- const value = (this.shiftCtrl >> 25) & 0x1f;
318
- return value ? value : 32;
319
- }
320
- get sidesetCount() {
321
- return (this.pinCtrl >> 29) & 0x7;
322
- }
323
- get setCount() {
324
- return (this.pinCtrl >> 26) & 0x7;
325
- }
326
- get outCount() {
327
- return (this.pinCtrl >> 20) & 0x3f;
328
- }
329
- get inBase() {
330
- return (this.pinCtrl >> 15) & 0x1f;
331
- }
332
- get sidesetBase() {
333
- return (this.pinCtrl >> 10) & 0x1f;
334
- }
335
- get setBase() {
336
- return (this.pinCtrl >> 5) & 0x1f;
337
- }
338
- get outBase() {
339
- return (this.pinCtrl >> 0) & 0x1f;
340
- }
341
- get jmpPin() {
342
- return (this.execCtrl >> 24) & 0x1f;
343
- }
344
- get wrapTop() {
345
- return (this.execCtrl >> 12) & 0x1f;
346
- }
347
- get wrapBottom() {
348
- return (this.execCtrl >> 7) & 0x1f;
349
- }
350
- setOutPinDirs(value) {
351
- this.outPinDirection = value;
352
- this.pio.pinDirectionsChanged(value, this.outBase, this.outCount);
353
- }
354
- setOutPins(value) {
355
- this.outPinValues = value;
356
- this.pio.pinValuesChanged(value, this.outBase, this.outCount);
357
- }
358
- outInstruction(arg) {
359
- const bitCount = arg & 0x1f;
360
- const destination = arg >> 5;
361
- if (bitCount === 0) {
362
- this.writeOutValue(destination, this.outputShiftReg, 32);
363
- this.outputShiftCount = 32;
364
- }
365
- else {
366
- if (this.shiftCtrl & SHIFTCTRL_OUT_SHIFTDIR) {
367
- const value = this.outputShiftReg & ((1 << bitCount) - 1);
368
- this.outputShiftReg >>>= bitCount;
369
- this.writeOutValue(destination, value, bitCount);
370
- }
371
- else {
372
- const value = this.outputShiftReg >>> (32 - bitCount);
373
- this.outputShiftReg <<= bitCount;
374
- this.writeOutValue(destination, value, bitCount);
375
- }
376
- this.outputShiftCount += bitCount;
377
- if (this.outputShiftCount > 32) {
378
- this.outputShiftCount = 32;
379
- }
380
- }
381
- }
382
- executeInstruction(opcode) {
383
- const arg = opcode & 0xff;
384
- switch (opcode >>> 13) {
385
- /* JMP */
386
- case 0b000:
387
- if (this.jmpCondition(arg >> 5)) {
388
- this.pc = arg & 0x1f;
389
- this.updatePC = false;
390
- }
391
- break;
392
- /* WAIT */
393
- case 0b001: {
394
- const polarity = !!(arg & 0x80);
395
- const source = (arg >> 5) & 0x3;
396
- const index = arg & 0x1f;
397
- switch (source) {
398
- // GPIO:
399
- case 0b00:
400
- this.wait(WaitType.Pin, polarity, index);
401
- break;
402
- // PIN:
403
- case 0b01:
404
- this.wait(WaitType.Pin, polarity, (index + this.inBase) % 32);
405
- break;
406
- // IRQ:
407
- case 0b10:
408
- this.wait(WaitType.IRQ, polarity, irqIndex(index, this.index));
409
- break;
410
- }
411
- break;
412
- }
413
- /* IN */
414
- case 0b010: {
415
- const bitCount = arg & 0x1f;
416
- let sourceValue = this.inSourceValue(arg >> 5);
417
- if (bitCount == 0) {
418
- this.inputShiftReg = sourceValue;
419
- this.inputShiftCount = 32;
420
- }
421
- else {
422
- sourceValue &= (1 << bitCount) - 1;
423
- if (this.shiftCtrl & SHIFTCTRL_IN_SHIFTDIR) {
424
- this.inputShiftReg >>>= bitCount;
425
- this.inputShiftReg |= sourceValue << (32 - bitCount);
426
- }
427
- else {
428
- this.inputShiftReg <<= bitCount;
429
- this.inputShiftReg |= sourceValue;
430
- }
431
- this.inputShiftCount += bitCount;
432
- if (this.inputShiftCount > 32) {
433
- this.inputShiftCount = 32;
434
- }
435
- }
436
- if (this.shiftCtrl & SHIFTCTRL_AUTOPUSH && this.inputShiftCount >= this.pushThreshold) {
437
- if (!this.rxFIFO.full) {
438
- this.rxFIFO.push(this.inputShiftReg);
439
- this.updateDMARx();
440
- this.pio.checkInterrupts();
441
- }
442
- else {
443
- this.pio.fdebug |= FDEBUG_RXSTALL << this.index;
444
- this.wait(WaitType.rxFIFO, false, this.inputShiftReg);
445
- }
446
- this.inputShiftCount = 0;
447
- this.inputShiftReg = 0;
448
- }
449
- break;
450
- }
451
- /* OUT */
452
- case 0b011: {
453
- if (this.shiftCtrl & SHIFTCTRL_AUTOPULL && this.outputShiftCount >= this.pullThreshold) {
454
- this.outputShiftCount = 0;
455
- if (!this.txFIFO.empty) {
456
- this.outputShiftReg = this.txFIFO.pull();
457
- this.updateDMATx();
458
- this.pio.checkInterrupts();
459
- }
460
- else {
461
- this.pio.fdebug |= FDEBUG_TXSTALL << this.index;
462
- this.wait(WaitType.Out, false, arg);
463
- }
464
- }
465
- if (!this.waiting) {
466
- this.outInstruction(arg);
467
- }
468
- break;
469
- }
470
- /* PUSH/PULL */
471
- case 0b100: {
472
- const block = !!(arg & (1 << 5));
473
- const ifFullOrEmpty = !!(arg & (1 << 6));
474
- if (arg & 0x1f) {
475
- // Unknown instruction
476
- break;
477
- }
478
- if (arg & 0x80) {
479
- // PULL
480
- if (ifFullOrEmpty &&
481
- this.shiftCtrl & SHIFTCTRL_AUTOPULL &&
482
- this.outputShiftCount < this.pullThreshold) {
483
- break;
484
- }
485
- if (!this.txFIFO.empty) {
486
- this.outputShiftReg = this.txFIFO.pull();
487
- this.updateDMATx();
488
- this.pio.checkInterrupts();
489
- }
490
- else {
491
- this.pio.fdebug |= FDEBUG_TXSTALL << this.index;
492
- if (block) {
493
- this.wait(WaitType.txFIFO, false, 0);
494
- }
495
- else {
496
- this.outputShiftReg = this.x;
497
- }
498
- }
499
- this.outputShiftCount = 0;
500
- }
501
- else {
502
- // PUSH
503
- if (ifFullOrEmpty &&
504
- this.shiftCtrl & SHIFTCTRL_AUTOPUSH &&
505
- this.inputShiftCount < this.pushThreshold) {
506
- break;
507
- }
508
- if (!this.rxFIFO.full) {
509
- this.rxFIFO.push(this.inputShiftReg);
510
- this.updateDMARx();
511
- this.pio.checkInterrupts();
512
- }
513
- else {
514
- this.pio.fdebug |= FDEBUG_RXSTALL << this.index;
515
- if (block) {
516
- this.wait(WaitType.rxFIFO, false, this.inputShiftReg);
517
- }
518
- }
519
- this.inputShiftReg = 0;
520
- this.inputShiftCount = 0;
521
- }
522
- break;
523
- }
524
- /* MOV */
525
- case 0b101: {
526
- const source = arg & 0x7;
527
- const op = (arg >> 3) & 0x3;
528
- const destination = (arg >> 5) & 0x7;
529
- const value = this.inSourceValue(source);
530
- const transformedValue = this.transformMovValue(value, op) >>> 0;
531
- this.setMovDestination(destination, transformedValue);
532
- break;
533
- }
534
- /* IRQ */
535
- case 0b110: {
536
- if (arg & 0x80) {
537
- // Unknown instruction
538
- break;
539
- }
540
- const clear = !!(arg & 0x40);
541
- const wait = !!(arg & 0x20);
542
- const irq = irqIndex(arg & 0x1f, this.index);
543
- if (clear) {
544
- this.pio.irq &= ~(1 << irq);
545
- this.pio.irqUpdated();
546
- }
547
- else {
548
- this.pio.irq |= 1 << irq;
549
- this.pio.irqUpdated();
550
- if (wait) {
551
- this.wait(WaitType.IRQ, false, irq);
552
- }
553
- }
554
- break;
555
- }
556
- /* SET */
557
- case 0b111: {
558
- const data = arg & 0x1f;
559
- const destination = arg >> 5;
560
- switch (destination) {
561
- case 0b000:
562
- this.setSetPins(data);
563
- break;
564
- case 0b001:
565
- this.x = data;
566
- break;
567
- case 0b010:
568
- this.y = data;
569
- break;
570
- case 0b100:
571
- this.setSetPinDirs(data);
572
- break;
573
- }
574
- break;
575
- }
576
- }
577
- this.cycles++;
578
- const { sidesetCount, execCtrl } = this;
579
- const delaySideset = (opcode >> 8) & 0x1f;
580
- const sideEn = !!(execCtrl & EXECCTRL_SIDE_EN);
581
- const delay = delaySideset & ((1 << (5 - sidesetCount)) - 1);
582
- if (sidesetCount && (!sideEn || delaySideset & 0x10)) {
583
- const sideset = delaySideset >> (5 - sidesetCount);
584
- this.setSideset(sideset, sideEn ? sidesetCount - 1 : sidesetCount);
585
- }
586
- if (this.execValid) {
587
- this.execValid = false;
588
- this.executeInstruction(this.execOpcode);
589
- }
590
- else if (this.waiting) {
591
- if (this.waitDelay < 0) {
592
- this.waitDelay = delay;
593
- }
594
- this.checkWait();
595
- }
596
- else {
597
- this.cycles += delay;
598
- }
599
- }
600
- wait(type, polarity, index) {
601
- this.waiting = true;
602
- this.waitType = type;
603
- this.waitPolarity = polarity;
604
- this.waitIndex = index;
605
- this.waitDelay = -1;
606
- this.updatePC = false;
607
- }
608
- nextPC() {
609
- if (this.pc === this.wrapTop) {
610
- this.pc = this.wrapBottom;
611
- }
612
- else {
613
- this.pc = (this.pc + 1) & 0x1f;
614
- }
615
- }
616
- step() {
617
- if (this.waiting) {
618
- this.checkWait();
619
- if (this.waiting) {
620
- return;
621
- }
622
- }
623
- this.updatePC = true;
624
- this.executeInstruction(this.pio.instructions[this.pc]);
625
- if (this.updatePC) {
626
- this.nextPC();
627
- }
628
- }
629
- setSetPinDirs(value) {
630
- this.pio.pinDirectionsChanged(value, this.setBase, this.setCount);
631
- }
632
- setSetPins(value) {
633
- this.pio.pinValuesChanged(value, this.setBase, this.setCount);
634
- }
635
- setSideset(value, count) {
636
- if (this.execCtrl & EXECCTRL_SIDE_PINDIR) {
637
- this.pio.pinDirectionsChanged(value, this.sidesetBase, count);
638
- }
639
- else {
640
- this.pio.pinValuesChanged(value, this.sidesetBase, count);
641
- }
642
- }
643
- transformMovValue(value, op) {
644
- switch (op) {
645
- case 0b00:
646
- return value;
647
- case 0b01:
648
- return ~value;
649
- case 0b10:
650
- return bitReverse(value);
651
- case 0b11:
652
- default:
653
- return value; // reserved
654
- }
655
- }
656
- setMovDestination(destination, value) {
657
- switch (destination) {
658
- // PINS
659
- case 0b000:
660
- this.setOutPins(value);
661
- break;
662
- // X (scratch register X)
663
- case 0b001:
664
- this.x = value;
665
- break;
666
- // Y (scratch register Y)
667
- case 0b010:
668
- this.y = value;
669
- break;
670
- // reserved (discard data)
671
- case 0b011:
672
- break;
673
- // EXEC
674
- case 0b100:
675
- this.execOpcode = value;
676
- this.execValid = true;
677
- break;
678
- // PC
679
- case 0b101:
680
- this.pc = value & 0x1f;
681
- this.updatePC = false;
682
- break;
683
- // ISR (Input shift counter is reset to 0 by this operation, i.e. empty)
684
- case 0b110:
685
- this.inputShiftReg = value;
686
- this.inputShiftCount = 0;
687
- break;
688
- // OSR (Output shift counter is reset to 0 by this operation, i.e. full)
689
- case 0b111:
690
- this.outputShiftReg = value;
691
- this.outputShiftCount = 0;
692
- break;
693
- }
694
- }
695
- readUint32(offset) {
696
- switch (offset + SM0_CLKDIV) {
697
- case SM0_CLKDIV:
698
- return (this.clockDivInt << 16) | (this.clockDivFrac << 8);
699
- case SM0_EXECCTRL:
700
- return this.execCtrl;
701
- case SM0_SHIFTCTRL:
702
- return this.shiftCtrl;
703
- case SM0_ADDR:
704
- return this.pc;
705
- case SM0_INSTR:
706
- return this.pio.instructions[this.pc];
707
- case SM0_PINCTRL:
708
- return this.pinCtrl;
709
- }
710
- this.pio.error(`Read from invalid state machine register: ${offset}`);
711
- return 0;
712
- }
713
- writeUint32(offset, value) {
714
- switch (offset + SM0_CLKDIV) {
715
- case SM0_CLKDIV:
716
- this.clockDivFrac = (value >>> 8) & 0xff;
717
- this.clockDivInt = value >>> 16;
718
- break;
719
- case SM0_EXECCTRL:
720
- this.execCtrl = ((value & 0x7fffffff) | (this.execCtrl & 0x80000000)) >>> 0;
721
- break;
722
- case SM0_SHIFTCTRL:
723
- this.shiftCtrl = value;
724
- break;
725
- case SM0_ADDR:
726
- /* read-only */
727
- break;
728
- case SM0_INSTR:
729
- this.executeInstruction(value & 0xffff);
730
- if (this.waiting) {
731
- this.execCtrl |= EXECCTRL_EXEC_STALLED;
732
- }
733
- break;
734
- case SM0_PINCTRL:
735
- this.pinCtrl = value;
736
- break;
737
- default:
738
- this.pio.error(`Write to invalid state machine register: ${offset}`);
739
- }
740
- }
741
- get fifoStat() {
742
- const result = (this.txFIFO.empty ? FSTAT_TXEMPTY : 0) |
743
- (this.txFIFO.full ? FSTAT_TXFULL : 0) |
744
- (this.rxFIFO.empty ? FSTAT_RXEMPTY : 0) |
745
- (this.rxFIFO.full ? FSTAT_RXFULL : 0);
746
- return result << this.index;
747
- }
748
- restart() {
749
- this.cycles = 0;
750
- this.inputShiftCount = 0;
751
- this.outputShiftCount = 32;
752
- this.inputShiftReg = 0;
753
- this.waiting = false;
754
- // TODO any pin write left asserted due to OUT_STICKY.
755
- }
756
- clkDivRestart() {
757
- this.pio.warn('clkDivRestart not implemented');
758
- }
759
- checkWait() {
760
- if (!this.waiting) {
761
- return;
762
- }
763
- switch (this.waitType) {
764
- case WaitType.IRQ: {
765
- const irqValue = !!(this.pio.irq & (1 << this.waitIndex));
766
- if (irqValue === this.waitPolarity) {
767
- this.waiting = false;
768
- if (irqValue) {
769
- this.pio.irq &= ~(1 << this.waitIndex);
770
- }
771
- }
772
- break;
773
- }
774
- case WaitType.Pin: {
775
- if (this.waitIndex < this.rp2040.gpio.length &&
776
- this.rp2040.gpio[this.waitIndex].inputValue === this.waitPolarity) {
777
- this.waiting = false;
778
- }
779
- break;
780
- }
781
- case WaitType.rxFIFO: {
782
- if (!this.rxFIFO.full) {
783
- this.rxFIFO.push(this.waitIndex);
784
- this.waiting = false;
785
- this.updateDMARx();
786
- this.pio.checkInterrupts();
787
- }
788
- break;
789
- }
790
- case WaitType.txFIFO: {
791
- if (!this.txFIFO.empty) {
792
- this.outputShiftReg = this.txFIFO.pull();
793
- this.waiting = false;
794
- this.updateDMATx();
795
- this.pio.checkInterrupts();
796
- }
797
- break;
798
- }
799
- case WaitType.Out: {
800
- if (!this.txFIFO.empty) {
801
- this.outputShiftReg = this.txFIFO.pull();
802
- this.outInstruction(this.waitIndex);
803
- this.waiting = false;
804
- this.updateDMATx();
805
- this.pio.checkInterrupts();
806
- }
807
- break;
808
- }
809
- }
810
- if (!this.waiting) {
811
- this.nextPC();
812
- this.cycles += this.waitDelay;
813
- this.execCtrl &= ~EXECCTRL_EXEC_STALLED;
814
- }
815
- }
816
- }
817
- exports.StateMachine = StateMachine;
818
- class RPPIO extends peripheral_1.BasePeripheral {
819
- constructor(rp2040, name, firstIrq, index) {
820
- super(rp2040, name);
821
- this.firstIrq = firstIrq;
822
- this.index = index;
823
- this.instructions = new Uint32Array(32);
824
- this.dreqRx = this.index ? dreqRx1 : dreqRx0;
825
- this.dreqTx = this.index ? dreqTx1 : dreqTx0;
826
- this.machines = [
827
- new StateMachine(this.rp2040, this, 0),
828
- new StateMachine(this.rp2040, this, 1),
829
- new StateMachine(this.rp2040, this, 2),
830
- new StateMachine(this.rp2040, this, 3),
831
- ];
832
- this.stopped = true;
833
- this.fdebug = 0;
834
- this.inputSyncBypass = 0;
835
- this.irq = 0;
836
- this.pinValues = 0;
837
- this.pinDirections = 0;
838
- this.oldPinValues = 0;
839
- this.oldPinDirections = 0;
840
- this.runTimer = null;
841
- this.irq0IntEnable = 0;
842
- this.irq0IntForce = 0;
843
- this.irq1IntEnable = 0;
844
- this.irq1IntForce = 0;
845
- }
846
- get intRaw() {
847
- return (((this.irq & 0xf) << 8) |
848
- (!this.machines[3].txFIFO.full ? 0x80 : 0) |
849
- (!this.machines[2].txFIFO.full ? 0x40 : 0) |
850
- (!this.machines[1].txFIFO.full ? 0x20 : 0) |
851
- (!this.machines[0].txFIFO.full ? 0x10 : 0) |
852
- (!this.machines[3].rxFIFO.empty ? 0x08 : 0) |
853
- (!this.machines[2].rxFIFO.empty ? 0x04 : 0) |
854
- (!this.machines[1].rxFIFO.empty ? 0x02 : 0) |
855
- (!this.machines[0].rxFIFO.empty ? 0x01 : 0));
856
- }
857
- get irq0IntStatus() {
858
- return (this.intRaw & this.irq0IntEnable) | this.irq0IntForce;
859
- }
860
- get irq1IntStatus() {
861
- return (this.intRaw & this.irq1IntEnable) | this.irq1IntForce;
862
- }
863
- readUint32(offset) {
864
- if (offset >= SM0_CLKDIV && offset <= SM0_PINCTRL) {
865
- return this.machines[0].readUint32(offset - SM0_CLKDIV);
866
- }
867
- if (offset >= SM1_CLKDIV && offset <= SM1_PINCTRL) {
868
- return this.machines[1].readUint32(offset - SM1_CLKDIV);
869
- }
870
- if (offset >= SM2_CLKDIV && offset <= SM2_PINCTRL) {
871
- return this.machines[2].readUint32(offset - SM2_CLKDIV);
872
- }
873
- if (offset >= SM3_CLKDIV && offset <= SM3_PINCTRL) {
874
- return this.machines[3].readUint32(offset - SM3_CLKDIV);
875
- }
876
- switch (offset) {
877
- case CTRL:
878
- return ((this.machines[0].enabled ? 1 << 0 : 0) |
879
- (this.machines[1].enabled ? 1 << 1 : 0) |
880
- (this.machines[2].enabled ? 1 << 2 : 0) |
881
- (this.machines[3].enabled ? 1 << 3 : 0));
882
- case FSTAT:
883
- return (this.machines[0].fifoStat |
884
- this.machines[1].fifoStat |
885
- this.machines[2].fifoStat |
886
- this.machines[3].fifoStat);
887
- case FDEBUG:
888
- return this.fdebug;
889
- case FLEVEL:
890
- return ((this.machines[0].txFIFO.itemCount & 0xf) |
891
- ((this.machines[0].rxFIFO.itemCount & 0xf) << 4) |
892
- ((this.machines[1].txFIFO.itemCount & 0xf) << 8) |
893
- ((this.machines[1].rxFIFO.itemCount & 0xf) << 12) |
894
- ((this.machines[2].txFIFO.itemCount & 0xf) << 16) |
895
- ((this.machines[2].rxFIFO.itemCount & 0xf) << 20) |
896
- ((this.machines[3].txFIFO.itemCount & 0xf) << 24) |
897
- ((this.machines[3].rxFIFO.itemCount & 0xf) << 28));
898
- case RXF0:
899
- return this.machines[0].readFIFO();
900
- case RXF1:
901
- return this.machines[1].readFIFO();
902
- case RXF2:
903
- return this.machines[2].readFIFO();
904
- case RXF3:
905
- return this.machines[3].readFIFO();
906
- case IRQ:
907
- return this.irq;
908
- case IRQ_FORCE:
909
- return 0;
910
- case INPUT_SYNC_BYPASS:
911
- return this.inputSyncBypass;
912
- case DBG_PADOUT:
913
- return this.pinValues;
914
- case DBG_PADOE:
915
- return this.pinDirections;
916
- case DBG_CFGINFO:
917
- return 0x200404;
918
- case INTR:
919
- return this.intRaw;
920
- case IRQ0_INTE:
921
- return this.irq0IntEnable;
922
- case IRQ0_INTF:
923
- return this.irq0IntForce;
924
- case IRQ0_INTS:
925
- return this.irq0IntStatus;
926
- case IRQ1_INTE:
927
- return this.irq1IntEnable;
928
- case IRQ1_INTF:
929
- return this.irq1IntForce;
930
- case IRQ1_INTS:
931
- return this.irq1IntStatus;
932
- }
933
- return super.readUint32(offset);
934
- }
935
- writeUint32(offset, value) {
936
- if (offset >= INSTR_MEM0 && offset <= INSTR_MEM31) {
937
- const index = (offset - INSTR_MEM0) >> 2;
938
- this.instructions[index] = value & 0xffff;
939
- return;
940
- }
941
- if (offset >= SM0_CLKDIV && offset <= SM0_PINCTRL) {
942
- this.machines[0].writeUint32(offset - SM0_CLKDIV, value);
943
- return;
944
- }
945
- if (offset >= SM1_CLKDIV && offset <= SM1_PINCTRL) {
946
- this.machines[1].writeUint32(offset - SM1_CLKDIV, value);
947
- return;
948
- }
949
- if (offset >= SM2_CLKDIV && offset <= SM2_PINCTRL) {
950
- this.machines[2].writeUint32(offset - SM2_CLKDIV, value);
951
- return;
952
- }
953
- if (offset >= SM3_CLKDIV && offset <= SM3_PINCTRL) {
954
- this.machines[3].writeUint32(offset - SM3_CLKDIV, value);
955
- return;
956
- }
957
- switch (offset) {
958
- case CTRL: {
959
- for (let index = 0; index < 4; index++) {
960
- this.machines[index].enabled = value & (1 << index) ? true : false;
961
- if (value & (1 << (4 + index))) {
962
- this.machines[index].restart();
963
- }
964
- if (value & (1 << (8 + index))) {
965
- this.machines[index].clkDivRestart();
966
- }
967
- }
968
- const shouldRun = value & 0xf;
969
- if (this.stopped && shouldRun) {
970
- this.stopped = false;
971
- this.run();
972
- }
973
- if (!shouldRun) {
974
- this.stopped = true;
975
- }
976
- break;
977
- }
978
- case FDEBUG:
979
- this.fdebug &= ~this.rawWriteValue;
980
- break;
981
- case TXF0:
982
- this.machines[0].writeFIFO(value);
983
- break;
984
- case TXF1:
985
- this.machines[1].writeFIFO(value);
986
- break;
987
- case TXF2:
988
- this.machines[2].writeFIFO(value);
989
- break;
990
- case TXF3:
991
- this.machines[3].writeFIFO(value);
992
- break;
993
- case IRQ:
994
- this.irq &= ~this.rawWriteValue;
995
- this.irqUpdated();
996
- break;
997
- case INPUT_SYNC_BYPASS:
998
- this.inputSyncBypass = value;
999
- break;
1000
- case IRQ_FORCE:
1001
- this.irq |= value;
1002
- this.irqUpdated();
1003
- break;
1004
- case IRQ0_INTE:
1005
- this.irq0IntEnable = value & 0xfff;
1006
- this.checkInterrupts();
1007
- break;
1008
- case IRQ0_INTF:
1009
- this.irq0IntForce = value & 0xfff;
1010
- this.checkInterrupts();
1011
- break;
1012
- case IRQ1_INTE:
1013
- this.irq1IntEnable = value & 0xfff;
1014
- this.checkInterrupts();
1015
- break;
1016
- case IRQ1_INTF:
1017
- this.irq1IntForce = value & 0xfff;
1018
- this.checkInterrupts();
1019
- break;
1020
- default:
1021
- super.writeUint32(offset, value);
1022
- }
1023
- }
1024
- pinValuesChanged(value, firstPin, count) {
1025
- // TODO: wrapping after pin 31
1026
- const mask = count > 31 ? 0xffffffff : ((1 << count) - 1) << firstPin;
1027
- const newValue = ((this.pinValues & ~mask) | ((value << firstPin) & mask)) & 0x3fffffff;
1028
- this.pinValues = newValue;
1029
- }
1030
- pinDirectionsChanged(value, firstPin, count) {
1031
- // TODO: wrapping after pin 31
1032
- const mask = count > 31 ? 0xffffffff : ((1 << count) - 1) << firstPin;
1033
- const newValue = ((this.pinDirections & ~mask) | ((value << firstPin) & mask)) & 0x3fffffff;
1034
- this.pinDirections = newValue;
1035
- }
1036
- checkInterrupts() {
1037
- const { firstIrq } = this;
1038
- this.rp2040.setInterrupt(firstIrq, !!this.irq0IntStatus);
1039
- this.rp2040.setInterrupt(firstIrq + 1, !!this.irq1IntStatus);
1040
- }
1041
- irqUpdated() {
1042
- for (const machine of this.machines) {
1043
- machine.checkWait();
1044
- }
1045
- this.checkInterrupts();
1046
- }
1047
- checkChangedPins() {
1048
- const changedPins = (this.oldPinDirections ^ this.pinDirections) | (this.oldPinValues ^ this.pinValues);
1049
- if (changedPins) {
1050
- this.oldPinDirections = this.pinDirections;
1051
- this.oldPinValues = this.pinValues;
1052
- // Notify GPIO about the changed pins
1053
- const { gpio } = this.rp2040;
1054
- for (let gpioIndex = 0; gpioIndex < gpio.length; gpioIndex++) {
1055
- if (changedPins & (1 << gpioIndex)) {
1056
- gpio[gpioIndex].checkForUpdates();
1057
- }
1058
- }
1059
- }
1060
- }
1061
- step() {
1062
- for (const machine of this.machines) {
1063
- machine.step();
1064
- }
1065
- this.checkChangedPins();
1066
- }
1067
- run() {
1068
- for (let i = 0; i < 1000 && !this.stopped; i++) {
1069
- this.step();
1070
- }
1071
- if (!this.stopped) {
1072
- this.runTimer = setTimeout(() => this.run(), 0);
1073
- }
1074
- }
1075
- stop() {
1076
- for (const machine of this.machines) {
1077
- machine.enabled = false;
1078
- }
1079
- this.stopped = true;
1080
- if (this.runTimer) {
1081
- clearTimeout(this.runTimer);
1082
- this.runTimer = null;
1083
- }
1084
- }
1085
- }
1086
- exports.RPPIO = RPPIO;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RPPIO = exports.StateMachine = exports.WaitType = void 0;
4
+ const fifo_js_1 = require("../utils/fifo.js");
5
+ const dma_js_1 = require("./dma.js");
6
+ const peripheral_js_1 = require("./peripheral.js");
7
+ // Generic registers
8
+ const CTRL = 0x000;
9
+ const FSTAT = 0x004;
10
+ const FDEBUG = 0x008;
11
+ const FLEVEL = 0x00c;
12
+ const IRQ = 0x030;
13
+ const IRQ_FORCE = 0x034;
14
+ const INPUT_SYNC_BYPASS = 0x038;
15
+ const DBG_PADOUT = 0x03c;
16
+ const DBG_PADOE = 0x040;
17
+ const DBG_CFGINFO = 0x044;
18
+ const INSTR_MEM0 = 0x48;
19
+ const INSTR_MEM31 = 0x0c4;
20
+ const INTR = 0x128; // Raw Interrupts
21
+ const IRQ0_INTE = 0x12c; // Interrupt Enable for irq0
22
+ const IRQ0_INTF = 0x130; // Interrupt Force for irq0
23
+ const IRQ0_INTS = 0x134; // Interrupt status after masking & forcing for irq0
24
+ const IRQ1_INTE = 0x138; // Interrupt Enable for irq1
25
+ const IRQ1_INTF = 0x13c; // Interrupt Force for irq1
26
+ const IRQ1_INTS = 0x140; // Interrupt status after masking & forcing for irq1
27
+ // State-machine specific registers
28
+ const TXF0 = 0x010;
29
+ const TXF1 = 0x014;
30
+ const TXF2 = 0x018;
31
+ const TXF3 = 0x01c;
32
+ const RXF0 = 0x020;
33
+ const RXF1 = 0x024;
34
+ const RXF2 = 0x028;
35
+ const RXF3 = 0x02c;
36
+ const SM0_CLKDIV = 0x0c8; // Clock divisor register for state machine 0
37
+ const SM0_EXECCTRL = 0x0cc; // Execution/behavioural settings for state machine 0
38
+ const SM0_SHIFTCTRL = 0x0d0; // Control behaviour of the input/output shift registers for state machine 0
39
+ const SM0_ADDR = 0x0d4; // Current instruction address of state machine 0
40
+ const SM0_INSTR = 0x0d8; // Write to execute an instruction immediately (including jumps) and then resume execution.
41
+ const SM0_PINCTRL = 0x0dc; //State machine pin control
42
+ const SM1_CLKDIV = 0x0e0;
43
+ const SM1_PINCTRL = 0x0f4;
44
+ const SM2_CLKDIV = 0x0f8;
45
+ const SM2_PINCTRL = 0x10c;
46
+ const SM3_CLKDIV = 0x110;
47
+ const SM3_PINCTRL = 0x124;
48
+ // FSTAT bits
49
+ const FSTAT_TXEMPTY = 1 << 24;
50
+ const FSTAT_TXFULL = 1 << 16;
51
+ const FSTAT_RXEMPTY = 1 << 8;
52
+ const FSTAT_RXFULL = 1 << 0;
53
+ // FDEBUG bits
54
+ const FDEBUG_TXSTALL = 1 << 24;
55
+ const FDEBUG_TXOVER = 1 << 16;
56
+ const FDEBUG_RXUNDER = 1 << 8;
57
+ const FDEBUG_RXSTALL = 1 << 0;
58
+ // SHIFTCTRL bits
59
+ const SHIFTCTRL_AUTOPUSH = 1 << 16;
60
+ const SHIFTCTRL_AUTOPULL = 1 << 17;
61
+ const SHIFTCTRL_IN_SHIFTDIR = 1 << 18; // 1 = shift input shift register to right (data enters from left). 0 = to left
62
+ const SHIFTCTRL_OUT_SHIFTDIR = 1 << 19; // 1 = shift out of output shift register to right. 0 = to left
63
+ // EXECCTRL bits
64
+ const EXECCTRL_STATUS_SEL = 1 << 4;
65
+ const EXECCTRL_SIDE_PINDIR = 1 << 29;
66
+ const EXECCTRL_SIDE_EN = 1 << 30;
67
+ const EXECCTRL_EXEC_STALLED = 1 << 31;
68
+ var WaitType;
69
+ (function (WaitType) {
70
+ WaitType[WaitType["None"] = 0] = "None";
71
+ WaitType[WaitType["Pin"] = 1] = "Pin";
72
+ WaitType[WaitType["rxFIFO"] = 2] = "rxFIFO";
73
+ WaitType[WaitType["txFIFO"] = 3] = "txFIFO";
74
+ WaitType[WaitType["IRQ"] = 4] = "IRQ";
75
+ WaitType[WaitType["Out"] = 5] = "Out";
76
+ })(WaitType || (exports.WaitType = WaitType = {}));
77
+ function bitReverse(x) {
78
+ x = ((x & 0x55555555) << 1) | ((x & 0xaaaaaaaa) >>> 1);
79
+ x = ((x & 0x33333333) << 2) | ((x & 0xcccccccc) >>> 2);
80
+ x = ((x & 0x0f0f0f0f) << 4) | ((x & 0xf0f0f0f0) >>> 4);
81
+ x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >>> 8);
82
+ x = ((x & 0x0000ffff) << 16) | ((x & 0xffff0000) >>> 16);
83
+ return x >>> 0;
84
+ }
85
+ function irqIndex(irq, machineIndex) {
86
+ const rel = !!(irq & 0x10);
87
+ return rel ? (irq & 0x4) | (((irq & 0x3) + machineIndex) & 0x3) : irq & 0x7;
88
+ }
89
+ const dreqRx0 = [
90
+ dma_js_1.DREQChannel.DREQ_PIO0_RX0,
91
+ dma_js_1.DREQChannel.DREQ_PIO0_RX1,
92
+ dma_js_1.DREQChannel.DREQ_PIO0_RX2,
93
+ dma_js_1.DREQChannel.DREQ_PIO0_RX3,
94
+ ];
95
+ const dreqTx0 = [
96
+ dma_js_1.DREQChannel.DREQ_PIO0_TX0,
97
+ dma_js_1.DREQChannel.DREQ_PIO0_TX1,
98
+ dma_js_1.DREQChannel.DREQ_PIO0_TX2,
99
+ dma_js_1.DREQChannel.DREQ_PIO0_TX3,
100
+ ];
101
+ const dreqRx1 = [
102
+ dma_js_1.DREQChannel.DREQ_PIO1_RX0,
103
+ dma_js_1.DREQChannel.DREQ_PIO1_RX1,
104
+ dma_js_1.DREQChannel.DREQ_PIO1_RX2,
105
+ dma_js_1.DREQChannel.DREQ_PIO1_RX3,
106
+ ];
107
+ const dreqTx1 = [
108
+ dma_js_1.DREQChannel.DREQ_PIO1_TX0,
109
+ dma_js_1.DREQChannel.DREQ_PIO1_TX1,
110
+ dma_js_1.DREQChannel.DREQ_PIO1_TX2,
111
+ dma_js_1.DREQChannel.DREQ_PIO1_TX3,
112
+ ];
113
+ class StateMachine {
114
+ constructor(rp2040, pio, index) {
115
+ this.rp2040 = rp2040;
116
+ this.pio = pio;
117
+ this.index = index;
118
+ this.enabled = false;
119
+ // State machine registers
120
+ this.x = 0;
121
+ this.y = 0;
122
+ this.pc = 0;
123
+ this.inputShiftReg = 0;
124
+ this.inputShiftCount = 0;
125
+ this.outputShiftReg = 0;
126
+ this.outputShiftCount = 0;
127
+ this.cycles = 0;
128
+ this.execOpcode = 0;
129
+ this.execValid = false;
130
+ this.updatePC = true;
131
+ this.clockDivInt = 1;
132
+ this.clockDivFrac = 0;
133
+ this.execCtrl = 0x1f << 12;
134
+ this.shiftCtrl = 0b11 << 18;
135
+ this.pinCtrl = 0x5 << 26;
136
+ this.rxFIFO = new fifo_js_1.FIFO(4);
137
+ this.txFIFO = new fifo_js_1.FIFO(4);
138
+ this.outPinValues = 0;
139
+ this.outPinDirection = 0;
140
+ this.waiting = false;
141
+ this.waitType = WaitType.None;
142
+ this.waitIndex = 0;
143
+ this.waitPolarity = false;
144
+ this.waitDelay = -1;
145
+ this.dreqRx = this.pio.dreqRx[this.index];
146
+ this.dreqTx = this.pio.dreqTx[this.index];
147
+ this.updateDMARx();
148
+ this.updateDMATx();
149
+ }
150
+ updateDMATx() {
151
+ if (this.txFIFO.full) {
152
+ this.rp2040.dma.clearDREQ(this.dreqTx);
153
+ }
154
+ else {
155
+ this.rp2040.dma.setDREQ(this.dreqTx);
156
+ }
157
+ }
158
+ updateDMARx() {
159
+ if (this.rxFIFO.empty) {
160
+ this.rp2040.dma.clearDREQ(this.dreqRx);
161
+ }
162
+ else {
163
+ this.rp2040.dma.setDREQ(this.dreqRx);
164
+ }
165
+ }
166
+ writeFIFO(value) {
167
+ if (this.txFIFO.full) {
168
+ this.pio.fdebug |= FDEBUG_TXOVER << this.index;
169
+ return;
170
+ }
171
+ this.txFIFO.push(value);
172
+ this.updateDMATx();
173
+ this.checkWait();
174
+ if (this.txFIFO.full) {
175
+ this.pio.checkInterrupts();
176
+ }
177
+ }
178
+ readFIFO() {
179
+ if (this.rxFIFO.empty) {
180
+ this.pio.fdebug |= FDEBUG_RXUNDER << this.index;
181
+ return 0;
182
+ }
183
+ const result = this.rxFIFO.pull();
184
+ this.updateDMARx();
185
+ this.checkWait();
186
+ if (this.rxFIFO.empty) {
187
+ this.pio.checkInterrupts();
188
+ }
189
+ return result;
190
+ }
191
+ get status() {
192
+ const statusN = this.execCtrl & 0xf;
193
+ if (this.execCtrl & EXECCTRL_STATUS_SEL) {
194
+ return this.rxFIFO.itemCount < statusN ? 0xffffffff : 0;
195
+ }
196
+ else {
197
+ return this.txFIFO.itemCount < statusN ? 0xffffffff : 0;
198
+ }
199
+ }
200
+ jmpCondition(condition) {
201
+ switch (condition) {
202
+ // (no condition): Always
203
+ case 0b000:
204
+ return true;
205
+ // !X: scratch X zero
206
+ case 0b001:
207
+ return this.x === 0;
208
+ // X--: scratch X non-zero, post-decrement
209
+ case 0b010: {
210
+ const oldX = this.x;
211
+ this.x = (this.x - 1) >>> 0;
212
+ return oldX !== 0;
213
+ }
214
+ // !Y: scratch Y zero
215
+ case 0b011:
216
+ return this.y === 0;
217
+ // Y--: scratch Y non-zero, post-decrement
218
+ case 0b100: {
219
+ const oldY = this.y;
220
+ this.y = (this.y - 1) >>> 0;
221
+ return oldY !== 0;
222
+ }
223
+ // X!=Y: scratch X not equal scratch Y
224
+ case 0b101:
225
+ return this.x >>> 0 !== this.y >>> 0;
226
+ // PIN: branch on input pin
227
+ case 0b110: {
228
+ const { gpio } = this.rp2040;
229
+ const { jmpPin } = this;
230
+ return jmpPin < gpio.length ? gpio[jmpPin].inputValue : false;
231
+ }
232
+ // !OSRE: output shift register not empty
233
+ case 0b111:
234
+ return this.outputShiftCount < this.pullThreshold;
235
+ }
236
+ this.pio.error(`jmpCondition with unsupported condition: ${condition}`);
237
+ return false;
238
+ }
239
+ get inPins() {
240
+ const { gpioValues } = this.rp2040;
241
+ const { inBase } = this;
242
+ return inBase ? (gpioValues << (32 - inBase)) | (gpioValues >>> inBase) : gpioValues;
243
+ }
244
+ inSourceValue(source) {
245
+ switch (source) {
246
+ // PINS
247
+ case 0b000:
248
+ return this.inPins;
249
+ // X (scratch register X)
250
+ case 0b001:
251
+ return this.x;
252
+ // Y (scratch register Y)
253
+ case 0b010:
254
+ return this.y;
255
+ // NULL (all zeroes)
256
+ case 0b011:
257
+ return 0;
258
+ // Reserved
259
+ case 0b100:
260
+ return 0;
261
+ // Reserved for IN, STATUS for MOV
262
+ case 0b101:
263
+ return this.status;
264
+ // ISR
265
+ case 0b110:
266
+ return this.inputShiftReg;
267
+ // OSR
268
+ case 0b111:
269
+ return this.outputShiftReg;
270
+ }
271
+ this.pio.error(`inSourceValue with unsupported source: ${source}`);
272
+ return 0;
273
+ }
274
+ writeOutValue(destination, value, bitCount) {
275
+ switch (destination) {
276
+ // PINS
277
+ case 0b000:
278
+ this.setOutPins(value);
279
+ break;
280
+ // X (scratch register X)
281
+ case 0b001:
282
+ this.x = value;
283
+ break;
284
+ // Y (scratch register Y)
285
+ case 0b010:
286
+ this.y = value;
287
+ break;
288
+ // NULL (discard data)
289
+ case 0b011:
290
+ break;
291
+ // PINDIRS
292
+ case 0b100:
293
+ this.setOutPinDirs(value);
294
+ break;
295
+ // PC
296
+ case 0b101:
297
+ this.pc = value & 0x1f;
298
+ this.updatePC = false;
299
+ break;
300
+ // ISR (also sets ISR shift counter to Bit count)
301
+ case 0b110:
302
+ this.inputShiftReg = value;
303
+ this.inputShiftCount = bitCount;
304
+ break;
305
+ // EXEC (Execute OSR shift data as instruction)
306
+ case 0b111:
307
+ this.execOpcode = value;
308
+ this.execValid = true;
309
+ break;
310
+ }
311
+ }
312
+ get pushThreshold() {
313
+ const value = (this.shiftCtrl >> 20) & 0x1f;
314
+ return value ? value : 32;
315
+ }
316
+ get pullThreshold() {
317
+ const value = (this.shiftCtrl >> 25) & 0x1f;
318
+ return value ? value : 32;
319
+ }
320
+ get sidesetCount() {
321
+ return (this.pinCtrl >> 29) & 0x7;
322
+ }
323
+ get setCount() {
324
+ return (this.pinCtrl >> 26) & 0x7;
325
+ }
326
+ get outCount() {
327
+ return (this.pinCtrl >> 20) & 0x3f;
328
+ }
329
+ get inBase() {
330
+ return (this.pinCtrl >> 15) & 0x1f;
331
+ }
332
+ get sidesetBase() {
333
+ return (this.pinCtrl >> 10) & 0x1f;
334
+ }
335
+ get setBase() {
336
+ return (this.pinCtrl >> 5) & 0x1f;
337
+ }
338
+ get outBase() {
339
+ return (this.pinCtrl >> 0) & 0x1f;
340
+ }
341
+ get jmpPin() {
342
+ return (this.execCtrl >> 24) & 0x1f;
343
+ }
344
+ get wrapTop() {
345
+ return (this.execCtrl >> 12) & 0x1f;
346
+ }
347
+ get wrapBottom() {
348
+ return (this.execCtrl >> 7) & 0x1f;
349
+ }
350
+ setOutPinDirs(value) {
351
+ this.outPinDirection = value;
352
+ this.pio.pinDirectionsChanged(value, this.outBase, this.outCount);
353
+ }
354
+ setOutPins(value) {
355
+ this.outPinValues = value;
356
+ this.pio.pinValuesChanged(value, this.outBase, this.outCount);
357
+ }
358
+ outInstruction(arg) {
359
+ const bitCount = arg & 0x1f;
360
+ const destination = arg >> 5;
361
+ if (bitCount === 0) {
362
+ this.writeOutValue(destination, this.outputShiftReg, 32);
363
+ this.outputShiftCount = 32;
364
+ }
365
+ else {
366
+ if (this.shiftCtrl & SHIFTCTRL_OUT_SHIFTDIR) {
367
+ const value = this.outputShiftReg & ((1 << bitCount) - 1);
368
+ this.outputShiftReg >>>= bitCount;
369
+ this.writeOutValue(destination, value, bitCount);
370
+ }
371
+ else {
372
+ const value = this.outputShiftReg >>> (32 - bitCount);
373
+ this.outputShiftReg <<= bitCount;
374
+ this.writeOutValue(destination, value, bitCount);
375
+ }
376
+ this.outputShiftCount += bitCount;
377
+ if (this.outputShiftCount > 32) {
378
+ this.outputShiftCount = 32;
379
+ }
380
+ }
381
+ }
382
+ executeInstruction(opcode) {
383
+ const arg = opcode & 0xff;
384
+ switch (opcode >>> 13) {
385
+ /* JMP */
386
+ case 0b000:
387
+ if (this.jmpCondition(arg >> 5)) {
388
+ this.pc = arg & 0x1f;
389
+ this.updatePC = false;
390
+ }
391
+ break;
392
+ /* WAIT */
393
+ case 0b001: {
394
+ const polarity = !!(arg & 0x80);
395
+ const source = (arg >> 5) & 0x3;
396
+ const index = arg & 0x1f;
397
+ switch (source) {
398
+ // GPIO:
399
+ case 0b00:
400
+ this.wait(WaitType.Pin, polarity, index);
401
+ break;
402
+ // PIN:
403
+ case 0b01:
404
+ this.wait(WaitType.Pin, polarity, (index + this.inBase) % 32);
405
+ break;
406
+ // IRQ:
407
+ case 0b10:
408
+ this.wait(WaitType.IRQ, polarity, irqIndex(index, this.index));
409
+ break;
410
+ }
411
+ break;
412
+ }
413
+ /* IN */
414
+ case 0b010: {
415
+ const bitCount = arg & 0x1f;
416
+ let sourceValue = this.inSourceValue(arg >> 5);
417
+ if (bitCount == 0) {
418
+ this.inputShiftReg = sourceValue;
419
+ this.inputShiftCount = 32;
420
+ }
421
+ else {
422
+ sourceValue &= (1 << bitCount) - 1;
423
+ if (this.shiftCtrl & SHIFTCTRL_IN_SHIFTDIR) {
424
+ this.inputShiftReg >>>= bitCount;
425
+ this.inputShiftReg |= sourceValue << (32 - bitCount);
426
+ }
427
+ else {
428
+ this.inputShiftReg <<= bitCount;
429
+ this.inputShiftReg |= sourceValue;
430
+ }
431
+ this.inputShiftCount += bitCount;
432
+ if (this.inputShiftCount > 32) {
433
+ this.inputShiftCount = 32;
434
+ }
435
+ }
436
+ if (this.shiftCtrl & SHIFTCTRL_AUTOPUSH && this.inputShiftCount >= this.pushThreshold) {
437
+ if (!this.rxFIFO.full) {
438
+ this.rxFIFO.push(this.inputShiftReg);
439
+ this.updateDMARx();
440
+ this.pio.checkInterrupts();
441
+ }
442
+ else {
443
+ this.pio.fdebug |= FDEBUG_RXSTALL << this.index;
444
+ this.wait(WaitType.rxFIFO, false, this.inputShiftReg);
445
+ }
446
+ this.inputShiftCount = 0;
447
+ this.inputShiftReg = 0;
448
+ }
449
+ break;
450
+ }
451
+ /* OUT */
452
+ case 0b011: {
453
+ if (this.shiftCtrl & SHIFTCTRL_AUTOPULL && this.outputShiftCount >= this.pullThreshold) {
454
+ this.outputShiftCount = 0;
455
+ if (!this.txFIFO.empty) {
456
+ this.outputShiftReg = this.txFIFO.pull();
457
+ this.updateDMATx();
458
+ this.pio.checkInterrupts();
459
+ }
460
+ else {
461
+ this.pio.fdebug |= FDEBUG_TXSTALL << this.index;
462
+ this.wait(WaitType.Out, false, arg);
463
+ }
464
+ }
465
+ if (!this.waiting) {
466
+ this.outInstruction(arg);
467
+ }
468
+ break;
469
+ }
470
+ /* PUSH/PULL */
471
+ case 0b100: {
472
+ const block = !!(arg & (1 << 5));
473
+ const ifFullOrEmpty = !!(arg & (1 << 6));
474
+ if (arg & 0x1f) {
475
+ // Unknown instruction
476
+ break;
477
+ }
478
+ if (arg & 0x80) {
479
+ // PULL
480
+ if (ifFullOrEmpty &&
481
+ this.shiftCtrl & SHIFTCTRL_AUTOPULL &&
482
+ this.outputShiftCount < this.pullThreshold) {
483
+ break;
484
+ }
485
+ if (!this.txFIFO.empty) {
486
+ this.outputShiftReg = this.txFIFO.pull();
487
+ this.updateDMATx();
488
+ this.pio.checkInterrupts();
489
+ }
490
+ else {
491
+ this.pio.fdebug |= FDEBUG_TXSTALL << this.index;
492
+ if (block) {
493
+ this.wait(WaitType.txFIFO, false, 0);
494
+ }
495
+ else {
496
+ this.outputShiftReg = this.x;
497
+ }
498
+ }
499
+ this.outputShiftCount = 0;
500
+ }
501
+ else {
502
+ // PUSH
503
+ if (ifFullOrEmpty &&
504
+ this.shiftCtrl & SHIFTCTRL_AUTOPUSH &&
505
+ this.inputShiftCount < this.pushThreshold) {
506
+ break;
507
+ }
508
+ if (!this.rxFIFO.full) {
509
+ this.rxFIFO.push(this.inputShiftReg);
510
+ this.updateDMARx();
511
+ this.pio.checkInterrupts();
512
+ }
513
+ else {
514
+ this.pio.fdebug |= FDEBUG_RXSTALL << this.index;
515
+ if (block) {
516
+ this.wait(WaitType.rxFIFO, false, this.inputShiftReg);
517
+ }
518
+ }
519
+ this.inputShiftReg = 0;
520
+ this.inputShiftCount = 0;
521
+ }
522
+ break;
523
+ }
524
+ /* MOV */
525
+ case 0b101: {
526
+ const source = arg & 0x7;
527
+ const op = (arg >> 3) & 0x3;
528
+ const destination = (arg >> 5) & 0x7;
529
+ const value = this.inSourceValue(source);
530
+ const transformedValue = this.transformMovValue(value, op) >>> 0;
531
+ this.setMovDestination(destination, transformedValue);
532
+ break;
533
+ }
534
+ /* IRQ */
535
+ case 0b110: {
536
+ if (arg & 0x80) {
537
+ // Unknown instruction
538
+ break;
539
+ }
540
+ const clear = !!(arg & 0x40);
541
+ const wait = !!(arg & 0x20);
542
+ const irq = irqIndex(arg & 0x1f, this.index);
543
+ if (clear) {
544
+ this.pio.irq &= ~(1 << irq);
545
+ this.pio.irqUpdated();
546
+ }
547
+ else {
548
+ this.pio.irq |= 1 << irq;
549
+ this.pio.irqUpdated();
550
+ if (wait) {
551
+ this.wait(WaitType.IRQ, false, irq);
552
+ }
553
+ }
554
+ break;
555
+ }
556
+ /* SET */
557
+ case 0b111: {
558
+ const data = arg & 0x1f;
559
+ const destination = arg >> 5;
560
+ switch (destination) {
561
+ case 0b000:
562
+ this.setSetPins(data);
563
+ break;
564
+ case 0b001:
565
+ this.x = data;
566
+ break;
567
+ case 0b010:
568
+ this.y = data;
569
+ break;
570
+ case 0b100:
571
+ this.setSetPinDirs(data);
572
+ break;
573
+ }
574
+ break;
575
+ }
576
+ }
577
+ this.cycles++;
578
+ const { sidesetCount, execCtrl } = this;
579
+ const delaySideset = (opcode >> 8) & 0x1f;
580
+ const sideEn = !!(execCtrl & EXECCTRL_SIDE_EN);
581
+ const delay = delaySideset & ((1 << (5 - sidesetCount)) - 1);
582
+ if (sidesetCount && (!sideEn || delaySideset & 0x10)) {
583
+ const sideset = delaySideset >> (5 - sidesetCount);
584
+ this.setSideset(sideset, sideEn ? sidesetCount - 1 : sidesetCount);
585
+ }
586
+ if (this.execValid) {
587
+ this.execValid = false;
588
+ this.executeInstruction(this.execOpcode);
589
+ }
590
+ else if (this.waiting) {
591
+ if (this.waitDelay < 0) {
592
+ this.waitDelay = delay;
593
+ }
594
+ this.checkWait();
595
+ }
596
+ else {
597
+ this.cycles += delay;
598
+ }
599
+ }
600
+ wait(type, polarity, index) {
601
+ this.waiting = true;
602
+ this.waitType = type;
603
+ this.waitPolarity = polarity;
604
+ this.waitIndex = index;
605
+ this.waitDelay = -1;
606
+ this.updatePC = false;
607
+ }
608
+ nextPC() {
609
+ if (this.pc === this.wrapTop) {
610
+ this.pc = this.wrapBottom;
611
+ }
612
+ else {
613
+ this.pc = (this.pc + 1) & 0x1f;
614
+ }
615
+ }
616
+ step() {
617
+ if (this.waiting) {
618
+ this.checkWait();
619
+ if (this.waiting) {
620
+ return;
621
+ }
622
+ }
623
+ this.updatePC = true;
624
+ this.executeInstruction(this.pio.instructions[this.pc]);
625
+ if (this.updatePC) {
626
+ this.nextPC();
627
+ }
628
+ }
629
+ setSetPinDirs(value) {
630
+ this.pio.pinDirectionsChanged(value, this.setBase, this.setCount);
631
+ }
632
+ setSetPins(value) {
633
+ this.pio.pinValuesChanged(value, this.setBase, this.setCount);
634
+ }
635
+ setSideset(value, count) {
636
+ if (this.execCtrl & EXECCTRL_SIDE_PINDIR) {
637
+ this.pio.pinDirectionsChanged(value, this.sidesetBase, count);
638
+ }
639
+ else {
640
+ this.pio.pinValuesChanged(value, this.sidesetBase, count);
641
+ }
642
+ }
643
+ transformMovValue(value, op) {
644
+ switch (op) {
645
+ case 0b00:
646
+ return value;
647
+ case 0b01:
648
+ return ~value;
649
+ case 0b10:
650
+ return bitReverse(value);
651
+ case 0b11:
652
+ default:
653
+ return value; // reserved
654
+ }
655
+ }
656
+ setMovDestination(destination, value) {
657
+ switch (destination) {
658
+ // PINS
659
+ case 0b000:
660
+ this.setOutPins(value);
661
+ break;
662
+ // X (scratch register X)
663
+ case 0b001:
664
+ this.x = value;
665
+ break;
666
+ // Y (scratch register Y)
667
+ case 0b010:
668
+ this.y = value;
669
+ break;
670
+ // reserved (discard data)
671
+ case 0b011:
672
+ break;
673
+ // EXEC
674
+ case 0b100:
675
+ this.execOpcode = value;
676
+ this.execValid = true;
677
+ break;
678
+ // PC
679
+ case 0b101:
680
+ this.pc = value & 0x1f;
681
+ this.updatePC = false;
682
+ break;
683
+ // ISR (Input shift counter is reset to 0 by this operation, i.e. empty)
684
+ case 0b110:
685
+ this.inputShiftReg = value;
686
+ this.inputShiftCount = 0;
687
+ break;
688
+ // OSR (Output shift counter is reset to 0 by this operation, i.e. full)
689
+ case 0b111:
690
+ this.outputShiftReg = value;
691
+ this.outputShiftCount = 0;
692
+ break;
693
+ }
694
+ }
695
+ readUint32(offset) {
696
+ switch (offset + SM0_CLKDIV) {
697
+ case SM0_CLKDIV:
698
+ return (this.clockDivInt << 16) | (this.clockDivFrac << 8);
699
+ case SM0_EXECCTRL:
700
+ return this.execCtrl;
701
+ case SM0_SHIFTCTRL:
702
+ return this.shiftCtrl;
703
+ case SM0_ADDR:
704
+ return this.pc;
705
+ case SM0_INSTR:
706
+ return this.pio.instructions[this.pc];
707
+ case SM0_PINCTRL:
708
+ return this.pinCtrl;
709
+ }
710
+ this.pio.error(`Read from invalid state machine register: ${offset}`);
711
+ return 0;
712
+ }
713
+ writeUint32(offset, value) {
714
+ switch (offset + SM0_CLKDIV) {
715
+ case SM0_CLKDIV:
716
+ this.clockDivFrac = (value >>> 8) & 0xff;
717
+ this.clockDivInt = value >>> 16;
718
+ break;
719
+ case SM0_EXECCTRL:
720
+ this.execCtrl = ((value & 0x7fffffff) | (this.execCtrl & 0x80000000)) >>> 0;
721
+ break;
722
+ case SM0_SHIFTCTRL:
723
+ this.shiftCtrl = value;
724
+ break;
725
+ case SM0_ADDR:
726
+ /* read-only */
727
+ break;
728
+ case SM0_INSTR:
729
+ this.executeInstruction(value & 0xffff);
730
+ if (this.waiting) {
731
+ this.execCtrl |= EXECCTRL_EXEC_STALLED;
732
+ }
733
+ break;
734
+ case SM0_PINCTRL:
735
+ this.pinCtrl = value;
736
+ break;
737
+ default:
738
+ this.pio.error(`Write to invalid state machine register: ${offset}`);
739
+ }
740
+ }
741
+ get fifoStat() {
742
+ const result = (this.txFIFO.empty ? FSTAT_TXEMPTY : 0) |
743
+ (this.txFIFO.full ? FSTAT_TXFULL : 0) |
744
+ (this.rxFIFO.empty ? FSTAT_RXEMPTY : 0) |
745
+ (this.rxFIFO.full ? FSTAT_RXFULL : 0);
746
+ return result << this.index;
747
+ }
748
+ restart() {
749
+ this.cycles = 0;
750
+ this.inputShiftCount = 0;
751
+ this.outputShiftCount = 32;
752
+ this.inputShiftReg = 0;
753
+ this.waiting = false;
754
+ // TODO any pin write left asserted due to OUT_STICKY.
755
+ }
756
+ clkDivRestart() {
757
+ this.pio.warn('clkDivRestart not implemented');
758
+ }
759
+ checkWait() {
760
+ if (!this.waiting) {
761
+ return;
762
+ }
763
+ switch (this.waitType) {
764
+ case WaitType.IRQ: {
765
+ const irqValue = !!(this.pio.irq & (1 << this.waitIndex));
766
+ if (irqValue === this.waitPolarity) {
767
+ this.waiting = false;
768
+ if (irqValue) {
769
+ this.pio.irq &= ~(1 << this.waitIndex);
770
+ }
771
+ }
772
+ break;
773
+ }
774
+ case WaitType.Pin: {
775
+ if (this.waitIndex < this.rp2040.gpio.length &&
776
+ this.rp2040.gpio[this.waitIndex].inputValue === this.waitPolarity) {
777
+ this.waiting = false;
778
+ }
779
+ break;
780
+ }
781
+ case WaitType.rxFIFO: {
782
+ if (!this.rxFIFO.full) {
783
+ this.rxFIFO.push(this.waitIndex);
784
+ this.waiting = false;
785
+ this.updateDMARx();
786
+ this.pio.checkInterrupts();
787
+ }
788
+ break;
789
+ }
790
+ case WaitType.txFIFO: {
791
+ if (!this.txFIFO.empty) {
792
+ this.outputShiftReg = this.txFIFO.pull();
793
+ this.waiting = false;
794
+ this.updateDMATx();
795
+ this.pio.checkInterrupts();
796
+ }
797
+ break;
798
+ }
799
+ case WaitType.Out: {
800
+ if (!this.txFIFO.empty) {
801
+ this.outputShiftReg = this.txFIFO.pull();
802
+ this.outInstruction(this.waitIndex);
803
+ this.waiting = false;
804
+ this.updateDMATx();
805
+ this.pio.checkInterrupts();
806
+ }
807
+ break;
808
+ }
809
+ }
810
+ if (!this.waiting) {
811
+ this.nextPC();
812
+ this.cycles += this.waitDelay;
813
+ this.execCtrl &= ~EXECCTRL_EXEC_STALLED;
814
+ }
815
+ }
816
+ }
817
+ exports.StateMachine = StateMachine;
818
+ class RPPIO extends peripheral_js_1.BasePeripheral {
819
+ constructor(rp2040, name, firstIrq, index) {
820
+ super(rp2040, name);
821
+ this.firstIrq = firstIrq;
822
+ this.index = index;
823
+ this.instructions = new Uint32Array(32);
824
+ this.dreqRx = this.index ? dreqRx1 : dreqRx0;
825
+ this.dreqTx = this.index ? dreqTx1 : dreqTx0;
826
+ this.machines = [
827
+ new StateMachine(this.rp2040, this, 0),
828
+ new StateMachine(this.rp2040, this, 1),
829
+ new StateMachine(this.rp2040, this, 2),
830
+ new StateMachine(this.rp2040, this, 3),
831
+ ];
832
+ this.stopped = true;
833
+ this.fdebug = 0;
834
+ this.inputSyncBypass = 0;
835
+ this.irq = 0;
836
+ this.pinValues = 0;
837
+ this.pinDirections = 0;
838
+ this.oldPinValues = 0;
839
+ this.oldPinDirections = 0;
840
+ this.runTimer = null;
841
+ this.irq0IntEnable = 0;
842
+ this.irq0IntForce = 0;
843
+ this.irq1IntEnable = 0;
844
+ this.irq1IntForce = 0;
845
+ }
846
+ get intRaw() {
847
+ return (((this.irq & 0xf) << 8) |
848
+ (!this.machines[3].txFIFO.full ? 0x80 : 0) |
849
+ (!this.machines[2].txFIFO.full ? 0x40 : 0) |
850
+ (!this.machines[1].txFIFO.full ? 0x20 : 0) |
851
+ (!this.machines[0].txFIFO.full ? 0x10 : 0) |
852
+ (!this.machines[3].rxFIFO.empty ? 0x08 : 0) |
853
+ (!this.machines[2].rxFIFO.empty ? 0x04 : 0) |
854
+ (!this.machines[1].rxFIFO.empty ? 0x02 : 0) |
855
+ (!this.machines[0].rxFIFO.empty ? 0x01 : 0));
856
+ }
857
+ get irq0IntStatus() {
858
+ return (this.intRaw & this.irq0IntEnable) | this.irq0IntForce;
859
+ }
860
+ get irq1IntStatus() {
861
+ return (this.intRaw & this.irq1IntEnable) | this.irq1IntForce;
862
+ }
863
+ readUint32(offset) {
864
+ if (offset >= SM0_CLKDIV && offset <= SM0_PINCTRL) {
865
+ return this.machines[0].readUint32(offset - SM0_CLKDIV);
866
+ }
867
+ if (offset >= SM1_CLKDIV && offset <= SM1_PINCTRL) {
868
+ return this.machines[1].readUint32(offset - SM1_CLKDIV);
869
+ }
870
+ if (offset >= SM2_CLKDIV && offset <= SM2_PINCTRL) {
871
+ return this.machines[2].readUint32(offset - SM2_CLKDIV);
872
+ }
873
+ if (offset >= SM3_CLKDIV && offset <= SM3_PINCTRL) {
874
+ return this.machines[3].readUint32(offset - SM3_CLKDIV);
875
+ }
876
+ switch (offset) {
877
+ case CTRL:
878
+ return ((this.machines[0].enabled ? 1 << 0 : 0) |
879
+ (this.machines[1].enabled ? 1 << 1 : 0) |
880
+ (this.machines[2].enabled ? 1 << 2 : 0) |
881
+ (this.machines[3].enabled ? 1 << 3 : 0));
882
+ case FSTAT:
883
+ return (this.machines[0].fifoStat |
884
+ this.machines[1].fifoStat |
885
+ this.machines[2].fifoStat |
886
+ this.machines[3].fifoStat);
887
+ case FDEBUG:
888
+ return this.fdebug;
889
+ case FLEVEL:
890
+ return ((this.machines[0].txFIFO.itemCount & 0xf) |
891
+ ((this.machines[0].rxFIFO.itemCount & 0xf) << 4) |
892
+ ((this.machines[1].txFIFO.itemCount & 0xf) << 8) |
893
+ ((this.machines[1].rxFIFO.itemCount & 0xf) << 12) |
894
+ ((this.machines[2].txFIFO.itemCount & 0xf) << 16) |
895
+ ((this.machines[2].rxFIFO.itemCount & 0xf) << 20) |
896
+ ((this.machines[3].txFIFO.itemCount & 0xf) << 24) |
897
+ ((this.machines[3].rxFIFO.itemCount & 0xf) << 28));
898
+ case RXF0:
899
+ return this.machines[0].readFIFO();
900
+ case RXF1:
901
+ return this.machines[1].readFIFO();
902
+ case RXF2:
903
+ return this.machines[2].readFIFO();
904
+ case RXF3:
905
+ return this.machines[3].readFIFO();
906
+ case IRQ:
907
+ return this.irq;
908
+ case IRQ_FORCE:
909
+ return 0;
910
+ case INPUT_SYNC_BYPASS:
911
+ return this.inputSyncBypass;
912
+ case DBG_PADOUT:
913
+ return this.pinValues;
914
+ case DBG_PADOE:
915
+ return this.pinDirections;
916
+ case DBG_CFGINFO:
917
+ return 0x200404;
918
+ case INTR:
919
+ return this.intRaw;
920
+ case IRQ0_INTE:
921
+ return this.irq0IntEnable;
922
+ case IRQ0_INTF:
923
+ return this.irq0IntForce;
924
+ case IRQ0_INTS:
925
+ return this.irq0IntStatus;
926
+ case IRQ1_INTE:
927
+ return this.irq1IntEnable;
928
+ case IRQ1_INTF:
929
+ return this.irq1IntForce;
930
+ case IRQ1_INTS:
931
+ return this.irq1IntStatus;
932
+ }
933
+ return super.readUint32(offset);
934
+ }
935
+ writeUint32(offset, value) {
936
+ if (offset >= INSTR_MEM0 && offset <= INSTR_MEM31) {
937
+ const index = (offset - INSTR_MEM0) >> 2;
938
+ this.instructions[index] = value & 0xffff;
939
+ return;
940
+ }
941
+ if (offset >= SM0_CLKDIV && offset <= SM0_PINCTRL) {
942
+ this.machines[0].writeUint32(offset - SM0_CLKDIV, value);
943
+ return;
944
+ }
945
+ if (offset >= SM1_CLKDIV && offset <= SM1_PINCTRL) {
946
+ this.machines[1].writeUint32(offset - SM1_CLKDIV, value);
947
+ return;
948
+ }
949
+ if (offset >= SM2_CLKDIV && offset <= SM2_PINCTRL) {
950
+ this.machines[2].writeUint32(offset - SM2_CLKDIV, value);
951
+ return;
952
+ }
953
+ if (offset >= SM3_CLKDIV && offset <= SM3_PINCTRL) {
954
+ this.machines[3].writeUint32(offset - SM3_CLKDIV, value);
955
+ return;
956
+ }
957
+ switch (offset) {
958
+ case CTRL: {
959
+ for (let index = 0; index < 4; index++) {
960
+ this.machines[index].enabled = value & (1 << index) ? true : false;
961
+ if (value & (1 << (4 + index))) {
962
+ this.machines[index].restart();
963
+ }
964
+ if (value & (1 << (8 + index))) {
965
+ this.machines[index].clkDivRestart();
966
+ }
967
+ }
968
+ const shouldRun = value & 0xf;
969
+ if (this.stopped && shouldRun) {
970
+ this.stopped = false;
971
+ this.run();
972
+ }
973
+ if (!shouldRun) {
974
+ this.stopped = true;
975
+ }
976
+ break;
977
+ }
978
+ case FDEBUG:
979
+ this.fdebug &= ~this.rawWriteValue;
980
+ break;
981
+ case TXF0:
982
+ this.machines[0].writeFIFO(value);
983
+ break;
984
+ case TXF1:
985
+ this.machines[1].writeFIFO(value);
986
+ break;
987
+ case TXF2:
988
+ this.machines[2].writeFIFO(value);
989
+ break;
990
+ case TXF3:
991
+ this.machines[3].writeFIFO(value);
992
+ break;
993
+ case IRQ:
994
+ this.irq &= ~this.rawWriteValue;
995
+ this.irqUpdated();
996
+ break;
997
+ case INPUT_SYNC_BYPASS:
998
+ this.inputSyncBypass = value;
999
+ break;
1000
+ case IRQ_FORCE:
1001
+ this.irq |= value;
1002
+ this.irqUpdated();
1003
+ break;
1004
+ case IRQ0_INTE:
1005
+ this.irq0IntEnable = value & 0xfff;
1006
+ this.checkInterrupts();
1007
+ break;
1008
+ case IRQ0_INTF:
1009
+ this.irq0IntForce = value & 0xfff;
1010
+ this.checkInterrupts();
1011
+ break;
1012
+ case IRQ1_INTE:
1013
+ this.irq1IntEnable = value & 0xfff;
1014
+ this.checkInterrupts();
1015
+ break;
1016
+ case IRQ1_INTF:
1017
+ this.irq1IntForce = value & 0xfff;
1018
+ this.checkInterrupts();
1019
+ break;
1020
+ default:
1021
+ super.writeUint32(offset, value);
1022
+ }
1023
+ }
1024
+ pinValuesChanged(value, firstPin, count) {
1025
+ // TODO: wrapping after pin 31
1026
+ const mask = count > 31 ? 0xffffffff : ((1 << count) - 1) << firstPin;
1027
+ const newValue = ((this.pinValues & ~mask) | ((value << firstPin) & mask)) & 0x3fffffff;
1028
+ this.pinValues = newValue;
1029
+ }
1030
+ pinDirectionsChanged(value, firstPin, count) {
1031
+ // TODO: wrapping after pin 31
1032
+ const mask = count > 31 ? 0xffffffff : ((1 << count) - 1) << firstPin;
1033
+ const newValue = ((this.pinDirections & ~mask) | ((value << firstPin) & mask)) & 0x3fffffff;
1034
+ this.pinDirections = newValue;
1035
+ }
1036
+ checkInterrupts() {
1037
+ const { firstIrq } = this;
1038
+ this.rp2040.setInterrupt(firstIrq, !!this.irq0IntStatus);
1039
+ this.rp2040.setInterrupt(firstIrq + 1, !!this.irq1IntStatus);
1040
+ }
1041
+ irqUpdated() {
1042
+ for (const machine of this.machines) {
1043
+ machine.checkWait();
1044
+ }
1045
+ this.checkInterrupts();
1046
+ }
1047
+ checkChangedPins() {
1048
+ const changedPins = (this.oldPinDirections ^ this.pinDirections) | (this.oldPinValues ^ this.pinValues);
1049
+ if (changedPins) {
1050
+ this.oldPinDirections = this.pinDirections;
1051
+ this.oldPinValues = this.pinValues;
1052
+ // Notify GPIO about the changed pins
1053
+ const { gpio } = this.rp2040;
1054
+ for (let gpioIndex = 0; gpioIndex < gpio.length; gpioIndex++) {
1055
+ if (changedPins & (1 << gpioIndex)) {
1056
+ gpio[gpioIndex].checkForUpdates();
1057
+ }
1058
+ }
1059
+ }
1060
+ }
1061
+ step() {
1062
+ for (const machine of this.machines) {
1063
+ machine.step();
1064
+ }
1065
+ this.checkChangedPins();
1066
+ }
1067
+ run() {
1068
+ for (let i = 0; i < 1000 && !this.stopped; i++) {
1069
+ this.step();
1070
+ }
1071
+ if (!this.stopped) {
1072
+ this.runTimer = setTimeout(() => this.run(), 0);
1073
+ }
1074
+ }
1075
+ stop() {
1076
+ for (const machine of this.machines) {
1077
+ machine.enabled = false;
1078
+ }
1079
+ this.stopped = true;
1080
+ if (this.runTimer) {
1081
+ clearTimeout(this.runTimer);
1082
+ this.runTimer = null;
1083
+ }
1084
+ }
1085
+ }
1086
+ exports.RPPIO = RPPIO;