rp2040js 0.17.17 → 0.18.1

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 +38 -27
  182. package/dist/esm/package.json +0 -1
@@ -1,368 +1,368 @@
1
- import { IRQ } from '../irq';
2
- import { Timer32, Timer32PeriodicAlarm, TimerMode } from '../utils/timer32';
3
- import { DREQChannel } from './dma';
4
- import { BasePeripheral } from './peripheral';
5
- /** Control and status register */
6
- const CHn_CSR = 0x00;
7
- /**
8
- * INT and FRAC form a fixed-point fractional number.
9
- * Counting rate is system clock frequency divided by this number.
10
- * Fractional division uses simple 1st-order sigma-delta.
11
- */
12
- const CHn_DIV = 0x04;
13
- /** Direct access to the PWM counter */
14
- const CHn_CTR = 0x08;
15
- /** Counter compare values */
16
- const CHn_CC = 0x0c;
17
- /** Counter wrap value */
18
- const CHn_TOP = 0x10;
19
- /**
20
- * This register aliases the CSR_EN bits for all channels.
21
- * Writing to this register allows multiple channels to be enabled
22
- * or disabled simultaneously, so they can run in perfect sync.
23
- * For each channel, there is only one physical EN register bit,
24
- * which can be accessed through here or CHx_CSR.
25
- */
26
- const EN = 0xa0;
27
- /** Raw Interrupts */
28
- const INTR = 0xa4;
29
- /** Interrupt Enable */
30
- const INTE = 0xa8;
31
- /** Interrupt Force */
32
- const INTF = 0xac;
33
- /** Interrupt status after masking & forcing */
34
- const INTS = 0xb0;
35
- const INT_MASK = 0xff;
36
- /* CHn_CSR bits */
37
- const CSR_PH_ADV = 1 << 7;
38
- const CSR_PH_RET = 1 << 6;
39
- const CSR_DIVMODE_SHIFT = 4;
40
- const CSR_DIVMODE_MASK = 0x3;
41
- const CSR_B_INV = 1 << 3;
42
- const CSR_A_INV = 1 << 2;
43
- const CSR_PH_CORRECT = 1 << 1;
44
- const CSR_EN = 1 << 0;
45
- var PWMDivMode;
46
- (function (PWMDivMode) {
47
- PWMDivMode[PWMDivMode["FreeRunning"] = 0] = "FreeRunning";
48
- PWMDivMode[PWMDivMode["BGated"] = 1] = "BGated";
49
- PWMDivMode[PWMDivMode["BRisingEdge"] = 2] = "BRisingEdge";
50
- PWMDivMode[PWMDivMode["BFallingEdge"] = 3] = "BFallingEdge";
51
- })(PWMDivMode || (PWMDivMode = {}));
52
- class PWMChannel {
53
- constructor(pwm, clock, index) {
54
- this.pwm = pwm;
55
- this.clock = clock;
56
- this.index = index;
57
- this.timer = new Timer32(this.clock, this.pwm.clockFreq);
58
- this.alarmA = new Timer32PeriodicAlarm(this.timer, () => {
59
- this.setA(false);
60
- });
61
- this.alarmB = new Timer32PeriodicAlarm(this.timer, () => {
62
- this.setB(false);
63
- });
64
- this.alarmBottom = new Timer32PeriodicAlarm(this.timer, () => this.wrap());
65
- this.csr = 0;
66
- this.div = 0;
67
- this.cc = 0;
68
- this.top = 0;
69
- this.lastBValue = false;
70
- this.countingUp = true;
71
- this.ccUpdated = false;
72
- this.topUpdated = false;
73
- this.tickCounter = 0;
74
- this.divMode = PWMDivMode.FreeRunning;
75
- // GPIO pin indices: Table 525. Mapping of PWM channels to GPIO pins on RP2040
76
- this.pinA1 = this.index * 2;
77
- this.pinB1 = this.index * 2 + 1;
78
- this.pinA2 = this.index < 7 ? 16 + this.index * 2 : -1;
79
- this.pinB2 = this.index < 7 ? 16 + this.index * 2 + 1 : -1;
80
- this.alarmA.enable = true;
81
- this.alarmB.enable = true;
82
- this.alarmBottom.enable = true;
83
- }
84
- readRegister(offset) {
85
- switch (offset) {
86
- case CHn_CSR:
87
- return this.csr;
88
- case CHn_DIV:
89
- return this.div;
90
- case CHn_CTR:
91
- return this.timer.counter;
92
- case CHn_CC:
93
- return this.cc;
94
- case CHn_TOP:
95
- return this.top;
96
- }
97
- /* Shouldn't get here */
98
- return 0;
99
- }
100
- writeRegister(offset, value) {
101
- switch (offset) {
102
- case CHn_CSR:
103
- if (value & CSR_EN && !(this.csr & CSR_EN)) {
104
- this.updateDoubleBuffered();
105
- }
106
- this.csr = value & ~(CSR_PH_ADV | CSR_PH_RET);
107
- if (this.csr & CSR_PH_ADV) {
108
- this.timer.advance(1);
109
- }
110
- if (this.csr & CSR_PH_RET) {
111
- this.timer.advance(-1);
112
- }
113
- this.divMode = (this.csr >> CSR_DIVMODE_SHIFT) & CSR_DIVMODE_MASK;
114
- this.setBDirection(this.divMode === PWMDivMode.FreeRunning);
115
- this.updateEnable();
116
- this.lastBValue = this.gpioBValue;
117
- this.timer.mode = value & CSR_PH_CORRECT ? TimerMode.ZigZag : TimerMode.Increment;
118
- break;
119
- case CHn_DIV: {
120
- this.div = value & 1048575;
121
- const intValue = (value >> 4) & 0xff;
122
- const fracValue = value & 0xf;
123
- this.timer.prescaler = (intValue ? intValue : 256) + fracValue / 16;
124
- break;
125
- }
126
- case CHn_CTR:
127
- this.timer.set(value & 0xffff);
128
- break;
129
- case CHn_CC:
130
- this.cc = value;
131
- this.ccUpdated = true;
132
- break;
133
- case CHn_TOP:
134
- this.top = value & 0xffff;
135
- this.topUpdated = true;
136
- break;
137
- }
138
- }
139
- reset() {
140
- this.writeRegister(CHn_CSR, 0);
141
- this.writeRegister(CHn_DIV, 0x01 << 4);
142
- this.writeRegister(CHn_CTR, 0);
143
- this.writeRegister(CHn_CC, 0);
144
- this.writeRegister(CHn_TOP, 0xffff);
145
- this.countingUp = true;
146
- this.timer.enable = false;
147
- this.timer.reset();
148
- }
149
- updateDoubleBuffered() {
150
- if (this.ccUpdated) {
151
- this.alarmB.target = this.cc >>> 16;
152
- this.alarmA.target = this.cc & 0xffff;
153
- this.ccUpdated = false;
154
- }
155
- if (this.topUpdated) {
156
- this.timer.top = this.top;
157
- this.topUpdated = false;
158
- }
159
- }
160
- wrap() {
161
- this.pwm.channelInterrupt(this.index);
162
- this.updateDoubleBuffered();
163
- if (!(this.csr & CSR_PH_CORRECT)) {
164
- this.setA(this.alarmA.target > 0);
165
- this.setB(this.alarmB.target > 0);
166
- }
167
- }
168
- setA(value) {
169
- if (this.csr & CSR_A_INV) {
170
- value = !value;
171
- }
172
- this.pwm.gpioSet(this.pinA1, value);
173
- if (this.pinA2 >= 0) {
174
- this.pwm.gpioSet(this.pinA2, value);
175
- }
176
- }
177
- setB(value) {
178
- if (this.csr & CSR_B_INV) {
179
- value = !value;
180
- }
181
- this.pwm.gpioSet(this.pinB1, value);
182
- if (this.pinB2 >= 0) {
183
- this.pwm.gpioSet(this.pinB2, value);
184
- }
185
- }
186
- get gpioBValue() {
187
- return (this.pwm.gpioRead(this.pinB1) || (this.pinB2 > 0 ? this.pwm.gpioRead(this.pinB2) : false));
188
- }
189
- setBDirection(value) {
190
- this.pwm.gpioSetDir(this.pinB1, value);
191
- if (this.pinB2 >= 0) {
192
- this.pwm.gpioSetDir(this.pinB2, value);
193
- }
194
- }
195
- gpioBChanged() {
196
- const value = this.gpioBValue;
197
- if (value === this.lastBValue) {
198
- return;
199
- }
200
- this.lastBValue = value;
201
- switch (this.divMode) {
202
- case PWMDivMode.BGated:
203
- this.updateEnable();
204
- break;
205
- case PWMDivMode.BRisingEdge:
206
- if (value) {
207
- this.tickCounter++;
208
- }
209
- break;
210
- case PWMDivMode.BFallingEdge:
211
- if (!value) {
212
- this.tickCounter++;
213
- }
214
- break;
215
- }
216
- if (this.tickCounter >= this.timer.prescaler) {
217
- this.timer.advance(1);
218
- this.tickCounter -= this.timer.prescaler;
219
- }
220
- }
221
- updateEnable() {
222
- const { csr, divMode } = this;
223
- const enable = !!(csr & CSR_EN);
224
- this.timer.enable =
225
- enable &&
226
- (divMode === PWMDivMode.FreeRunning || (divMode === PWMDivMode.BGated && this.gpioBValue));
227
- }
228
- set en(value) {
229
- if (value && !(this.csr & CSR_EN)) {
230
- this.updateDoubleBuffered();
231
- }
232
- if (value) {
233
- this.csr |= CSR_EN;
234
- }
235
- else {
236
- this.csr &= ~CSR_EN;
237
- }
238
- this.updateEnable();
239
- }
240
- }
241
- export class RPPWM extends BasePeripheral {
242
- constructor() {
243
- super(...arguments);
244
- this.channels = [
245
- new PWMChannel(this, this.rp2040.clock, 0),
246
- new PWMChannel(this, this.rp2040.clock, 1),
247
- new PWMChannel(this, this.rp2040.clock, 2),
248
- new PWMChannel(this, this.rp2040.clock, 3),
249
- new PWMChannel(this, this.rp2040.clock, 4),
250
- new PWMChannel(this, this.rp2040.clock, 5),
251
- new PWMChannel(this, this.rp2040.clock, 6),
252
- new PWMChannel(this, this.rp2040.clock, 7),
253
- ];
254
- this.intRaw = 0;
255
- this.intEnable = 0;
256
- this.intForce = 0;
257
- this.gpioValue = 0;
258
- this.gpioDirection = 0;
259
- }
260
- get intStatus() {
261
- return (this.intRaw & this.intEnable) | this.intForce;
262
- }
263
- readUint32(offset) {
264
- if (offset < EN) {
265
- const channel = Math.floor(offset / 0x14);
266
- return this.channels[channel].readRegister(offset % 0x14);
267
- }
268
- switch (offset) {
269
- case EN:
270
- return ((this.channels[7].en << 7) |
271
- (this.channels[6].en << 6) |
272
- (this.channels[5].en << 5) |
273
- (this.channels[4].en << 4) |
274
- (this.channels[3].en << 3) |
275
- (this.channels[2].en << 2) |
276
- (this.channels[1].en << 1) |
277
- (this.channels[0].en << 0));
278
- case INTR:
279
- return this.intRaw;
280
- case INTE:
281
- return this.intEnable;
282
- case INTF:
283
- return this.intForce;
284
- case INTS:
285
- return this.intStatus;
286
- }
287
- return super.readUint32(offset);
288
- }
289
- writeUint32(offset, value) {
290
- if (offset < EN) {
291
- const channel = Math.floor(offset / 0x14);
292
- return this.channels[channel].writeRegister(offset % 0x14, value);
293
- }
294
- switch (offset) {
295
- case EN:
296
- this.channels[7].en = value & (1 << 7);
297
- this.channels[6].en = value & (1 << 6);
298
- this.channels[5].en = value & (1 << 5);
299
- this.channels[4].en = value & (1 << 4);
300
- this.channels[3].en = value & (1 << 3);
301
- this.channels[2].en = value & (1 << 2);
302
- this.channels[1].en = value & (1 << 1);
303
- this.channels[0].en = value & (1 << 0);
304
- break;
305
- case INTR:
306
- this.intRaw &= ~(value & INT_MASK);
307
- this.checkInterrupts();
308
- break;
309
- case INTE:
310
- this.intEnable = value & INT_MASK;
311
- this.checkInterrupts();
312
- break;
313
- case INTF:
314
- this.intForce = value & INT_MASK;
315
- this.checkInterrupts();
316
- break;
317
- default:
318
- super.writeUint32(offset, value);
319
- }
320
- }
321
- get clockFreq() {
322
- return this.rp2040.clkSys;
323
- }
324
- channelInterrupt(index) {
325
- this.intRaw |= 1 << index;
326
- this.checkInterrupts();
327
- // We also set the DMA Request (DREQ) for the channel
328
- this.rp2040.dma.setDREQ(DREQChannel.DREQ_PWM_WRAP0 + index);
329
- }
330
- checkInterrupts() {
331
- this.rp2040.setInterrupt(IRQ.PWM_WRAP, !!this.intStatus);
332
- }
333
- gpioSet(index, value) {
334
- const bit = 1 << index;
335
- const newGpioValue = value ? this.gpioValue | bit : this.gpioValue & ~bit;
336
- if (this.gpioValue != newGpioValue) {
337
- this.gpioValue = newGpioValue;
338
- this.rp2040.gpio[index].checkForUpdates();
339
- }
340
- }
341
- gpioSetDir(index, output) {
342
- const bit = 1 << index;
343
- const newGpioDirection = output ? this.gpioDirection | bit : this.gpioDirection & ~bit;
344
- if (this.gpioDirection != newGpioDirection) {
345
- this.gpioDirection = newGpioDirection;
346
- this.rp2040.gpio[index].checkForUpdates();
347
- }
348
- }
349
- gpioRead(index) {
350
- return this.rp2040.gpio[index].inputValue;
351
- }
352
- gpioOnInput(index) {
353
- if (this.gpioDirection && 1 << index) {
354
- return;
355
- }
356
- for (const channel of this.channels) {
357
- if (channel.pinB1 === index || channel.pinB2 === index) {
358
- channel.gpioBChanged();
359
- }
360
- }
361
- }
362
- reset() {
363
- this.gpioDirection = 0xffffffff;
364
- for (const channel of this.channels) {
365
- channel.reset();
366
- }
367
- }
368
- }
1
+ import { IRQ } from '../irq.js';
2
+ import { Timer32, Timer32PeriodicAlarm, TimerMode } from '../utils/timer32.js';
3
+ import { DREQChannel } from './dma.js';
4
+ import { BasePeripheral } from './peripheral.js';
5
+ /** Control and status register */
6
+ const CHn_CSR = 0x00;
7
+ /**
8
+ * INT and FRAC form a fixed-point fractional number.
9
+ * Counting rate is system clock frequency divided by this number.
10
+ * Fractional division uses simple 1st-order sigma-delta.
11
+ */
12
+ const CHn_DIV = 0x04;
13
+ /** Direct access to the PWM counter */
14
+ const CHn_CTR = 0x08;
15
+ /** Counter compare values */
16
+ const CHn_CC = 0x0c;
17
+ /** Counter wrap value */
18
+ const CHn_TOP = 0x10;
19
+ /**
20
+ * This register aliases the CSR_EN bits for all channels.
21
+ * Writing to this register allows multiple channels to be enabled
22
+ * or disabled simultaneously, so they can run in perfect sync.
23
+ * For each channel, there is only one physical EN register bit,
24
+ * which can be accessed through here or CHx_CSR.
25
+ */
26
+ const EN = 0xa0;
27
+ /** Raw Interrupts */
28
+ const INTR = 0xa4;
29
+ /** Interrupt Enable */
30
+ const INTE = 0xa8;
31
+ /** Interrupt Force */
32
+ const INTF = 0xac;
33
+ /** Interrupt status after masking & forcing */
34
+ const INTS = 0xb0;
35
+ const INT_MASK = 0xff;
36
+ /* CHn_CSR bits */
37
+ const CSR_PH_ADV = 1 << 7;
38
+ const CSR_PH_RET = 1 << 6;
39
+ const CSR_DIVMODE_SHIFT = 4;
40
+ const CSR_DIVMODE_MASK = 0x3;
41
+ const CSR_B_INV = 1 << 3;
42
+ const CSR_A_INV = 1 << 2;
43
+ const CSR_PH_CORRECT = 1 << 1;
44
+ const CSR_EN = 1 << 0;
45
+ var PWMDivMode;
46
+ (function (PWMDivMode) {
47
+ PWMDivMode[PWMDivMode["FreeRunning"] = 0] = "FreeRunning";
48
+ PWMDivMode[PWMDivMode["BGated"] = 1] = "BGated";
49
+ PWMDivMode[PWMDivMode["BRisingEdge"] = 2] = "BRisingEdge";
50
+ PWMDivMode[PWMDivMode["BFallingEdge"] = 3] = "BFallingEdge";
51
+ })(PWMDivMode || (PWMDivMode = {}));
52
+ class PWMChannel {
53
+ constructor(pwm, clock, index) {
54
+ this.pwm = pwm;
55
+ this.clock = clock;
56
+ this.index = index;
57
+ this.timer = new Timer32(this.clock, this.pwm.clockFreq);
58
+ this.alarmA = new Timer32PeriodicAlarm(this.timer, () => {
59
+ this.setA(false);
60
+ });
61
+ this.alarmB = new Timer32PeriodicAlarm(this.timer, () => {
62
+ this.setB(false);
63
+ });
64
+ this.alarmBottom = new Timer32PeriodicAlarm(this.timer, () => this.wrap());
65
+ this.csr = 0;
66
+ this.div = 0;
67
+ this.cc = 0;
68
+ this.top = 0;
69
+ this.lastBValue = false;
70
+ this.countingUp = true;
71
+ this.ccUpdated = false;
72
+ this.topUpdated = false;
73
+ this.tickCounter = 0;
74
+ this.divMode = PWMDivMode.FreeRunning;
75
+ // GPIO pin indices: Table 525. Mapping of PWM channels to GPIO pins on RP2040
76
+ this.pinA1 = this.index * 2;
77
+ this.pinB1 = this.index * 2 + 1;
78
+ this.pinA2 = this.index < 7 ? 16 + this.index * 2 : -1;
79
+ this.pinB2 = this.index < 7 ? 16 + this.index * 2 + 1 : -1;
80
+ this.alarmA.enable = true;
81
+ this.alarmB.enable = true;
82
+ this.alarmBottom.enable = true;
83
+ }
84
+ readRegister(offset) {
85
+ switch (offset) {
86
+ case CHn_CSR:
87
+ return this.csr;
88
+ case CHn_DIV:
89
+ return this.div;
90
+ case CHn_CTR:
91
+ return this.timer.counter;
92
+ case CHn_CC:
93
+ return this.cc;
94
+ case CHn_TOP:
95
+ return this.top;
96
+ }
97
+ /* Shouldn't get here */
98
+ return 0;
99
+ }
100
+ writeRegister(offset, value) {
101
+ switch (offset) {
102
+ case CHn_CSR:
103
+ if (value & CSR_EN && !(this.csr & CSR_EN)) {
104
+ this.updateDoubleBuffered();
105
+ }
106
+ this.csr = value & ~(CSR_PH_ADV | CSR_PH_RET);
107
+ if (this.csr & CSR_PH_ADV) {
108
+ this.timer.advance(1);
109
+ }
110
+ if (this.csr & CSR_PH_RET) {
111
+ this.timer.advance(-1);
112
+ }
113
+ this.divMode = (this.csr >> CSR_DIVMODE_SHIFT) & CSR_DIVMODE_MASK;
114
+ this.setBDirection(this.divMode === PWMDivMode.FreeRunning);
115
+ this.updateEnable();
116
+ this.lastBValue = this.gpioBValue;
117
+ this.timer.mode = value & CSR_PH_CORRECT ? TimerMode.ZigZag : TimerMode.Increment;
118
+ break;
119
+ case CHn_DIV: {
120
+ this.div = value & 1048575;
121
+ const intValue = (value >> 4) & 0xff;
122
+ const fracValue = value & 0xf;
123
+ this.timer.prescaler = (intValue ? intValue : 256) + fracValue / 16;
124
+ break;
125
+ }
126
+ case CHn_CTR:
127
+ this.timer.set(value & 0xffff);
128
+ break;
129
+ case CHn_CC:
130
+ this.cc = value;
131
+ this.ccUpdated = true;
132
+ break;
133
+ case CHn_TOP:
134
+ this.top = value & 0xffff;
135
+ this.topUpdated = true;
136
+ break;
137
+ }
138
+ }
139
+ reset() {
140
+ this.writeRegister(CHn_CSR, 0);
141
+ this.writeRegister(CHn_DIV, 0x01 << 4);
142
+ this.writeRegister(CHn_CTR, 0);
143
+ this.writeRegister(CHn_CC, 0);
144
+ this.writeRegister(CHn_TOP, 0xffff);
145
+ this.countingUp = true;
146
+ this.timer.enable = false;
147
+ this.timer.reset();
148
+ }
149
+ updateDoubleBuffered() {
150
+ if (this.ccUpdated) {
151
+ this.alarmB.target = this.cc >>> 16;
152
+ this.alarmA.target = this.cc & 0xffff;
153
+ this.ccUpdated = false;
154
+ }
155
+ if (this.topUpdated) {
156
+ this.timer.top = this.top;
157
+ this.topUpdated = false;
158
+ }
159
+ }
160
+ wrap() {
161
+ this.pwm.channelInterrupt(this.index);
162
+ this.updateDoubleBuffered();
163
+ if (!(this.csr & CSR_PH_CORRECT)) {
164
+ this.setA(this.alarmA.target > 0);
165
+ this.setB(this.alarmB.target > 0);
166
+ }
167
+ }
168
+ setA(value) {
169
+ if (this.csr & CSR_A_INV) {
170
+ value = !value;
171
+ }
172
+ this.pwm.gpioSet(this.pinA1, value);
173
+ if (this.pinA2 >= 0) {
174
+ this.pwm.gpioSet(this.pinA2, value);
175
+ }
176
+ }
177
+ setB(value) {
178
+ if (this.csr & CSR_B_INV) {
179
+ value = !value;
180
+ }
181
+ this.pwm.gpioSet(this.pinB1, value);
182
+ if (this.pinB2 >= 0) {
183
+ this.pwm.gpioSet(this.pinB2, value);
184
+ }
185
+ }
186
+ get gpioBValue() {
187
+ return (this.pwm.gpioRead(this.pinB1) || (this.pinB2 > 0 ? this.pwm.gpioRead(this.pinB2) : false));
188
+ }
189
+ setBDirection(value) {
190
+ this.pwm.gpioSetDir(this.pinB1, value);
191
+ if (this.pinB2 >= 0) {
192
+ this.pwm.gpioSetDir(this.pinB2, value);
193
+ }
194
+ }
195
+ gpioBChanged() {
196
+ const value = this.gpioBValue;
197
+ if (value === this.lastBValue) {
198
+ return;
199
+ }
200
+ this.lastBValue = value;
201
+ switch (this.divMode) {
202
+ case PWMDivMode.BGated:
203
+ this.updateEnable();
204
+ break;
205
+ case PWMDivMode.BRisingEdge:
206
+ if (value) {
207
+ this.tickCounter++;
208
+ }
209
+ break;
210
+ case PWMDivMode.BFallingEdge:
211
+ if (!value) {
212
+ this.tickCounter++;
213
+ }
214
+ break;
215
+ }
216
+ if (this.tickCounter >= this.timer.prescaler) {
217
+ this.timer.advance(1);
218
+ this.tickCounter -= this.timer.prescaler;
219
+ }
220
+ }
221
+ updateEnable() {
222
+ const { csr, divMode } = this;
223
+ const enable = !!(csr & CSR_EN);
224
+ this.timer.enable =
225
+ enable &&
226
+ (divMode === PWMDivMode.FreeRunning || (divMode === PWMDivMode.BGated && this.gpioBValue));
227
+ }
228
+ set en(value) {
229
+ if (value && !(this.csr & CSR_EN)) {
230
+ this.updateDoubleBuffered();
231
+ }
232
+ if (value) {
233
+ this.csr |= CSR_EN;
234
+ }
235
+ else {
236
+ this.csr &= ~CSR_EN;
237
+ }
238
+ this.updateEnable();
239
+ }
240
+ }
241
+ export class RPPWM extends BasePeripheral {
242
+ constructor() {
243
+ super(...arguments);
244
+ this.channels = [
245
+ new PWMChannel(this, this.rp2040.clock, 0),
246
+ new PWMChannel(this, this.rp2040.clock, 1),
247
+ new PWMChannel(this, this.rp2040.clock, 2),
248
+ new PWMChannel(this, this.rp2040.clock, 3),
249
+ new PWMChannel(this, this.rp2040.clock, 4),
250
+ new PWMChannel(this, this.rp2040.clock, 5),
251
+ new PWMChannel(this, this.rp2040.clock, 6),
252
+ new PWMChannel(this, this.rp2040.clock, 7),
253
+ ];
254
+ this.intRaw = 0;
255
+ this.intEnable = 0;
256
+ this.intForce = 0;
257
+ this.gpioValue = 0;
258
+ this.gpioDirection = 0;
259
+ }
260
+ get intStatus() {
261
+ return (this.intRaw & this.intEnable) | this.intForce;
262
+ }
263
+ readUint32(offset) {
264
+ if (offset < EN) {
265
+ const channel = Math.floor(offset / 0x14);
266
+ return this.channels[channel].readRegister(offset % 0x14);
267
+ }
268
+ switch (offset) {
269
+ case EN:
270
+ return ((this.channels[7].en << 7) |
271
+ (this.channels[6].en << 6) |
272
+ (this.channels[5].en << 5) |
273
+ (this.channels[4].en << 4) |
274
+ (this.channels[3].en << 3) |
275
+ (this.channels[2].en << 2) |
276
+ (this.channels[1].en << 1) |
277
+ (this.channels[0].en << 0));
278
+ case INTR:
279
+ return this.intRaw;
280
+ case INTE:
281
+ return this.intEnable;
282
+ case INTF:
283
+ return this.intForce;
284
+ case INTS:
285
+ return this.intStatus;
286
+ }
287
+ return super.readUint32(offset);
288
+ }
289
+ writeUint32(offset, value) {
290
+ if (offset < EN) {
291
+ const channel = Math.floor(offset / 0x14);
292
+ return this.channels[channel].writeRegister(offset % 0x14, value);
293
+ }
294
+ switch (offset) {
295
+ case EN:
296
+ this.channels[7].en = value & (1 << 7);
297
+ this.channels[6].en = value & (1 << 6);
298
+ this.channels[5].en = value & (1 << 5);
299
+ this.channels[4].en = value & (1 << 4);
300
+ this.channels[3].en = value & (1 << 3);
301
+ this.channels[2].en = value & (1 << 2);
302
+ this.channels[1].en = value & (1 << 1);
303
+ this.channels[0].en = value & (1 << 0);
304
+ break;
305
+ case INTR:
306
+ this.intRaw &= ~(value & INT_MASK);
307
+ this.checkInterrupts();
308
+ break;
309
+ case INTE:
310
+ this.intEnable = value & INT_MASK;
311
+ this.checkInterrupts();
312
+ break;
313
+ case INTF:
314
+ this.intForce = value & INT_MASK;
315
+ this.checkInterrupts();
316
+ break;
317
+ default:
318
+ super.writeUint32(offset, value);
319
+ }
320
+ }
321
+ get clockFreq() {
322
+ return this.rp2040.clkSys;
323
+ }
324
+ channelInterrupt(index) {
325
+ this.intRaw |= 1 << index;
326
+ this.checkInterrupts();
327
+ // We also set the DMA Request (DREQ) for the channel
328
+ this.rp2040.dma.setDREQ(DREQChannel.DREQ_PWM_WRAP0 + index);
329
+ }
330
+ checkInterrupts() {
331
+ this.rp2040.setInterrupt(IRQ.PWM_WRAP, !!this.intStatus);
332
+ }
333
+ gpioSet(index, value) {
334
+ const bit = 1 << index;
335
+ const newGpioValue = value ? this.gpioValue | bit : this.gpioValue & ~bit;
336
+ if (this.gpioValue != newGpioValue) {
337
+ this.gpioValue = newGpioValue;
338
+ this.rp2040.gpio[index].checkForUpdates();
339
+ }
340
+ }
341
+ gpioSetDir(index, output) {
342
+ const bit = 1 << index;
343
+ const newGpioDirection = output ? this.gpioDirection | bit : this.gpioDirection & ~bit;
344
+ if (this.gpioDirection != newGpioDirection) {
345
+ this.gpioDirection = newGpioDirection;
346
+ this.rp2040.gpio[index].checkForUpdates();
347
+ }
348
+ }
349
+ gpioRead(index) {
350
+ return this.rp2040.gpio[index].inputValue;
351
+ }
352
+ gpioOnInput(index) {
353
+ if (this.gpioDirection && 1 << index) {
354
+ return;
355
+ }
356
+ for (const channel of this.channels) {
357
+ if (channel.pinB1 === index || channel.pinB2 === index) {
358
+ channel.gpioBChanged();
359
+ }
360
+ }
361
+ }
362
+ reset() {
363
+ this.gpioDirection = 0xffffffff;
364
+ for (const channel of this.channels) {
365
+ channel.reset();
366
+ }
367
+ }
368
+ }