rp2040js 0.15.1 → 0.17.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.
@@ -0,0 +1,36 @@
1
+ export declare class InterpolatorConfig {
2
+ shift: number;
3
+ maskLSB: number;
4
+ maskMSB: number;
5
+ signed: boolean;
6
+ crossInput: boolean;
7
+ crossResult: boolean;
8
+ addRaw: boolean;
9
+ forceMSB: number;
10
+ blend: boolean;
11
+ clamp: boolean;
12
+ overf0: boolean;
13
+ overf1: boolean;
14
+ overf: boolean;
15
+ constructor(value: number);
16
+ toUint32(): number;
17
+ }
18
+ export declare class Interpolator {
19
+ private readonly index;
20
+ accum0: number;
21
+ accum1: number;
22
+ base0: number;
23
+ base1: number;
24
+ base2: number;
25
+ ctrl0: number;
26
+ ctrl1: number;
27
+ result0: number;
28
+ result1: number;
29
+ result2: number;
30
+ smresult0: number;
31
+ smresult1: number;
32
+ constructor(index: number);
33
+ update(): void;
34
+ writeback(): void;
35
+ setBase01(value: number): void;
36
+ }
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Interpolator = exports.InterpolatorConfig = void 0;
4
+ const bit_1 = require("./utils/bit");
5
+ class InterpolatorConfig {
6
+ constructor(value) {
7
+ this.shift = 0;
8
+ this.maskLSB = 0;
9
+ this.maskMSB = 0;
10
+ this.signed = false;
11
+ this.crossInput = false;
12
+ this.crossResult = false;
13
+ this.addRaw = false;
14
+ this.forceMSB = 0;
15
+ this.blend = false;
16
+ this.clamp = false;
17
+ this.overf0 = false;
18
+ this.overf1 = false;
19
+ this.overf = false;
20
+ this.shift = (value >>> 0) & 0b11111;
21
+ this.maskLSB = (value >>> 5) & 0b11111;
22
+ this.maskMSB = (value >>> 10) & 0b11111;
23
+ this.signed = Boolean((value >>> 15) & 1);
24
+ this.crossInput = Boolean((value >>> 16) & 1);
25
+ this.crossResult = Boolean((value >>> 17) & 1);
26
+ this.addRaw = Boolean((value >>> 18) & 1);
27
+ this.forceMSB = (value >>> 19) & 0b11;
28
+ this.blend = Boolean((value >>> 21) & 1);
29
+ this.clamp = Boolean((value >>> 22) & 1);
30
+ this.overf0 = Boolean((value >>> 23) & 1);
31
+ this.overf1 = Boolean((value >>> 24) & 1);
32
+ this.overf = Boolean((value >>> 25) & 1);
33
+ }
34
+ toUint32() {
35
+ return (((this.shift & 0b11111) << 0) |
36
+ ((this.maskLSB & 0b11111) << 5) |
37
+ ((this.maskMSB & 0b11111) << 10) |
38
+ ((Number(this.signed) & 1) << 15) |
39
+ ((Number(this.crossInput) & 1) << 16) |
40
+ ((Number(this.crossResult) & 1) << 17) |
41
+ ((Number(this.addRaw) & 1) << 18) |
42
+ ((this.forceMSB & 0b11) << 19) |
43
+ ((Number(this.blend) & 1) << 21) |
44
+ ((Number(this.clamp) & 1) << 22) |
45
+ ((Number(this.overf0) & 1) << 23) |
46
+ ((Number(this.overf1) & 1) << 24) |
47
+ ((Number(this.overf) & 1) << 25));
48
+ }
49
+ }
50
+ exports.InterpolatorConfig = InterpolatorConfig;
51
+ class Interpolator {
52
+ constructor(index) {
53
+ this.index = index;
54
+ this.accum0 = 0;
55
+ this.accum1 = 0;
56
+ this.base0 = 0;
57
+ this.base1 = 0;
58
+ this.base2 = 0;
59
+ this.ctrl0 = 0;
60
+ this.ctrl1 = 0;
61
+ this.result0 = 0;
62
+ this.result1 = 0;
63
+ this.result2 = 0;
64
+ this.smresult0 = 0;
65
+ this.smresult1 = 0;
66
+ this.update();
67
+ }
68
+ update() {
69
+ const N = this.index;
70
+ const ctrl0 = new InterpolatorConfig(this.ctrl0);
71
+ const ctrl1 = new InterpolatorConfig(this.ctrl1);
72
+ const do_clamp = ctrl0.clamp && N == 1;
73
+ const do_blend = ctrl0.blend && N == 0;
74
+ ctrl0.clamp = do_clamp;
75
+ ctrl0.blend = do_blend;
76
+ ctrl1.clamp = false;
77
+ ctrl1.blend = false;
78
+ ctrl1.overf0 = false;
79
+ ctrl1.overf1 = false;
80
+ ctrl1.overf = false;
81
+ const input0 = bit_1.s32(ctrl0.crossInput ? this.accum1 : this.accum0);
82
+ const input1 = bit_1.s32(ctrl1.crossInput ? this.accum0 : this.accum1);
83
+ const msbmask0 = ctrl0.maskMSB == 31 ? 0xffffffff : (1 << (ctrl0.maskMSB + 1)) - 1;
84
+ const msbmask1 = ctrl1.maskMSB == 31 ? 0xffffffff : (1 << (ctrl1.maskMSB + 1)) - 1;
85
+ const mask0 = msbmask0 & ~((1 << ctrl0.maskLSB) - 1);
86
+ const mask1 = msbmask1 & ~((1 << ctrl1.maskLSB) - 1);
87
+ const uresult0 = (input0 >>> ctrl0.shift) & mask0;
88
+ const uresult1 = (input1 >>> ctrl1.shift) & mask1;
89
+ const overf0 = Boolean((input0 >>> ctrl0.shift) & ~msbmask0);
90
+ const overf1 = Boolean((input1 >>> ctrl1.shift) & ~msbmask1);
91
+ const overf = overf0 || overf1;
92
+ const sextmask0 = (uresult0 & (1 << ctrl0.maskMSB)) ? (-1 << ctrl0.maskMSB) : 0;
93
+ const sextmask1 = (uresult1 & (1 << ctrl1.maskMSB)) ? (-1 << ctrl1.maskMSB) : 0;
94
+ const sresult0 = uresult0 | sextmask0;
95
+ const sresult1 = uresult1 | sextmask1;
96
+ const result0 = ctrl0.signed ? sresult0 : uresult0;
97
+ const result1 = ctrl1.signed ? sresult1 : uresult1;
98
+ const addresult0 = this.base0 + (ctrl0.addRaw ? input0 : result0);
99
+ const addresult1 = this.base1 + (ctrl1.addRaw ? input1 : result1);
100
+ const addresult2 = this.base2 + result0 + (do_blend ? 0 : result1);
101
+ const uclamp0 = bit_1.u32(result0) < bit_1.u32(this.base0) ? this.base0 : (bit_1.u32(result0) > bit_1.u32(this.base1) ? this.base1 : result0);
102
+ const sclamp0 = bit_1.s32(result0) < bit_1.s32(this.base0) ? this.base0 : (bit_1.s32(result0) > bit_1.s32(this.base1) ? this.base1 : result0);
103
+ const clamp0 = ctrl0.signed ? sclamp0 : uclamp0;
104
+ const alpha1 = result1 & 0xff;
105
+ const ublend1 = bit_1.u32(this.base0) + (Math.floor((alpha1 * (bit_1.u32(this.base1) - bit_1.u32(this.base0))) / 256) | 0);
106
+ const sblend1 = bit_1.s32(this.base0) + (Math.floor((alpha1 * (bit_1.s32(this.base1) - bit_1.s32(this.base0))) / 256) | 0);
107
+ const blend1 = ctrl1.signed ? sblend1 : ublend1;
108
+ this.smresult0 = bit_1.u32(result0);
109
+ this.smresult1 = bit_1.u32(result1);
110
+ this.result0 = bit_1.u32(do_blend ? alpha1 : (do_clamp ? clamp0 : addresult0) | (ctrl0.forceMSB << 28));
111
+ this.result1 = bit_1.u32((do_blend ? blend1 : addresult1) | (ctrl0.forceMSB << 28));
112
+ this.result2 = bit_1.u32(addresult2);
113
+ ctrl0.overf0 = overf0;
114
+ ctrl0.overf1 = overf1;
115
+ ctrl0.overf = overf;
116
+ this.ctrl0 = ctrl0.toUint32();
117
+ this.ctrl1 = ctrl1.toUint32();
118
+ }
119
+ writeback() {
120
+ const ctrl0 = new InterpolatorConfig(this.ctrl0);
121
+ const ctrl1 = new InterpolatorConfig(this.ctrl1);
122
+ this.accum0 = bit_1.u32(ctrl0.crossResult ? this.result1 : this.result0);
123
+ this.accum1 = bit_1.u32(ctrl1.crossResult ? this.result0 : this.result1);
124
+ this.update();
125
+ }
126
+ setBase01(value) {
127
+ const N = this.index;
128
+ const ctrl0 = new InterpolatorConfig(this.ctrl0);
129
+ const ctrl1 = new InterpolatorConfig(this.ctrl1);
130
+ const do_blend = ctrl0.blend && N == 0;
131
+ const input0 = value & 0xffff;
132
+ const input1 = (value >>> 16) & 0xffff;
133
+ const sextmask0 = input0 & (1 << 15) ? -1 << 15 : 0;
134
+ const sextmask1 = input1 & (1 << 15) ? -1 << 15 : 0;
135
+ const base0 = (do_blend ? ctrl1.signed : ctrl0.signed) ? input0 | sextmask0 : input0;
136
+ const base1 = ctrl1.signed ? input1 | sextmask1 : input1;
137
+ this.base0 = bit_1.u32(base0);
138
+ this.base1 = bit_1.u32(base1);
139
+ this.update();
140
+ }
141
+ }
142
+ exports.Interpolator = Interpolator;
@@ -0,0 +1,4 @@
1
+ import { BasePeripheral, Peripheral } from './peripheral';
2
+ export declare class RP2040SysInfo extends BasePeripheral implements Peripheral {
3
+ readUint32(offset: number): number;
4
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RP2040SysInfo = void 0;
4
+ const peripheral_1 = require("./peripheral");
5
+ const CHIP_ID = 0;
6
+ const PLATFORM = 0x4;
7
+ const GITREF_RP2040 = 0x40;
8
+ class RP2040SysInfo extends peripheral_1.BasePeripheral {
9
+ readUint32(offset) {
10
+ // All the values here were verified against the silicon
11
+ switch (offset) {
12
+ case CHIP_ID:
13
+ return 0x10002927;
14
+ case PLATFORM:
15
+ return 0x00000002;
16
+ case GITREF_RP2040:
17
+ return 0xe0c912e8;
18
+ }
19
+ return super.readUint32(offset);
20
+ }
21
+ }
22
+ exports.RP2040SysInfo = RP2040SysInfo;
@@ -20,6 +20,7 @@ const rtc_1 = require("./peripherals/rtc");
20
20
  const spi_1 = require("./peripherals/spi");
21
21
  const ssi_1 = require("./peripherals/ssi");
22
22
  const syscfg_1 = require("./peripherals/syscfg");
23
+ const sysinfo_1 = require("./peripherals/sysinfo");
23
24
  const timer_1 = require("./peripherals/timer");
24
25
  const uart_1 = require("./peripherals/uart");
25
26
  const usb_1 = require("./peripherals/usb");
@@ -107,7 +108,7 @@ class RP2040 {
107
108
  this.executeTimer = null;
108
109
  this.peripherals = {
109
110
  0x18000: new ssi_1.RPSSI(this, 'SSI'),
110
- 0x40000: new peripheral_1.UnimplementedPeripheral(this, 'SYSINFO_BASE'),
111
+ 0x40000: new sysinfo_1.RP2040SysInfo(this, 'SYSINFO_BASE'),
111
112
  0x40004: new syscfg_1.RP2040SysCfg(this, 'SYSCFG'),
112
113
  0x40008: new clocks_1.RPClocks(this, 'CLOCKS_BASE'),
113
114
  0x4000c: new reset_1.RPReset(this, 'RESETS_BASE'),
package/dist/cjs/sio.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RP2040 } from './rp2040';
2
+ import { Interpolator } from './interpolator';
2
3
  export declare class RPSIO {
3
4
  private readonly rp2040;
4
5
  gpioValue: number;
@@ -11,6 +12,8 @@ export declare class RPSIO {
11
12
  divRemainder: number;
12
13
  divCSR: number;
13
14
  spinLock: number;
15
+ interp0: Interpolator;
16
+ interp1: Interpolator;
14
17
  constructor(rp2040: RP2040);
15
18
  updateHardwareDivider(signed: boolean): void;
16
19
  readUint32(offset: number): number;
package/dist/cjs/sio.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RPSIO = void 0;
4
+ const interpolator_1 = require("./interpolator");
4
5
  const CPUID = 0x000;
5
6
  // GPIO
6
7
  const GPIO_IN = 0x004; // Input value for GPIO pins
@@ -30,6 +31,39 @@ const DIV_SDIVISOR = 0x06c; // Divider signed divisor
30
31
  const DIV_QUOTIENT = 0x070; // Divider result quotient
31
32
  const DIV_REMAINDER = 0x074; //Divider result remainder
32
33
  const DIV_CSR = 0x078;
34
+ //INTERPOLATOR
35
+ const INTERP0_ACCUM0 = 0x080; // Read/write access to accumulator 0
36
+ const INTERP0_ACCUM1 = 0x084; // Read/write access to accumulator 1
37
+ const INTERP0_BASE0 = 0x088; // Read/write access to BASE0 register
38
+ const INTERP0_BASE1 = 0x08c; // Read/write access to BASE1 register
39
+ const INTERP0_BASE2 = 0x090; // Read/write access to BASE2 register
40
+ const INTERP0_POP_LANE0 = 0x094; // Read LANE0 result, and simultaneously write lane results to both accumulators (POP)
41
+ const INTERP0_POP_LANE1 = 0x098; // Read LANE1 result, and simultaneously write lane results to both accumulators (POP)
42
+ const INTERP0_POP_FULL = 0x09c; // Read FULL result, and simultaneously write lane results to both accumulators (POP)
43
+ const INTERP0_PEEK_LANE0 = 0x0a0; // Read LANE0 result, without altering any internal state (PEEK)
44
+ const INTERP0_PEEK_LANE1 = 0x0a4; // Read LANE1 result, without altering any internal state (PEEK)
45
+ const INTERP0_PEEK_FULL = 0x0a8; // Read FULL result, without altering any internal state (PEEK)
46
+ const INTERP0_CTRL_LANE0 = 0x0ac; // Control register for lane 0
47
+ const INTERP0_CTRL_LANE1 = 0x0b0; // Control register for lane 1
48
+ const INTERP0_ACCUM0_ADD = 0x0b4; // Values written here are atomically added to ACCUM0
49
+ const INTERP0_ACCUM1_ADD = 0x0b8; // Values written here are atomically added to ACCUM1
50
+ const INTERP0_BASE_1AND0 = 0x0bc; // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously
51
+ const INTERP1_ACCUM0 = 0x0c0; // Read/write access to accumulator 0
52
+ const INTERP1_ACCUM1 = 0x0c4; // Read/write access to accumulator 1
53
+ const INTERP1_BASE0 = 0x0c8; // Read/write access to BASE0 register
54
+ const INTERP1_BASE1 = 0x0cc; // Read/write access to BASE1 register
55
+ const INTERP1_BASE2 = 0x0d0; // Read/write access to BASE2 register
56
+ const INTERP1_POP_LANE0 = 0x0d4; // Read LANE0 result, and simultaneously write lane results to both accumulators (POP)
57
+ const INTERP1_POP_LANE1 = 0x0d8; // Read LANE1 result, and simultaneously write lane results to both accumulators (POP)
58
+ const INTERP1_POP_FULL = 0x0dc; // Read FULL result, and simultaneously write lane results to both accumulators (POP)
59
+ const INTERP1_PEEK_LANE0 = 0x0e0; // Read LANE0 result, without altering any internal state (PEEK)
60
+ const INTERP1_PEEK_LANE1 = 0x0e4; // Read LANE1 result, without altering any internal state (PEEK)
61
+ const INTERP1_PEEK_FULL = 0x0e8; // Read FULL result, without altering any internal state (PEEK)
62
+ const INTERP1_CTRL_LANE0 = 0x0ec; // Control register for lane 0
63
+ const INTERP1_CTRL_LANE1 = 0x0f0; // Control register for lane 1
64
+ const INTERP1_ACCUM0_ADD = 0x0f4; // Values written here are atomically added to ACCUM0
65
+ const INTERP1_ACCUM1_ADD = 0x0f8; // Values written here are atomically added to ACCUM1
66
+ const INTERP1_BASE_1AND0 = 0x0fc; // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously
33
67
  //SPINLOCK
34
68
  const SPINLOCK_ST = 0x5c;
35
69
  const SPINLOCK0 = 0x100;
@@ -47,6 +81,8 @@ class RPSIO {
47
81
  this.divRemainder = 0;
48
82
  this.divCSR = 0;
49
83
  this.spinLock = 0;
84
+ this.interp0 = new interpolator_1.Interpolator(0);
85
+ this.interp1 = new interpolator_1.Interpolator(1);
50
86
  }
51
87
  updateHardwareDivider(signed) {
52
88
  if (this.divDivisor == 0) {
@@ -131,6 +167,84 @@ class RPSIO {
131
167
  return this.divRemainder;
132
168
  case DIV_CSR:
133
169
  return this.divCSR;
170
+ case INTERP0_ACCUM0:
171
+ return this.interp0.accum0;
172
+ case INTERP0_ACCUM1:
173
+ return this.interp0.accum1;
174
+ case INTERP0_BASE0:
175
+ return this.interp0.base0;
176
+ case INTERP0_BASE1:
177
+ return this.interp0.base1;
178
+ case INTERP0_BASE2:
179
+ return this.interp0.base2;
180
+ case INTERP0_CTRL_LANE0:
181
+ return this.interp0.ctrl0;
182
+ case INTERP0_CTRL_LANE1:
183
+ return this.interp0.ctrl1;
184
+ case INTERP0_PEEK_LANE0:
185
+ return this.interp0.result0;
186
+ case INTERP0_PEEK_LANE1:
187
+ return this.interp0.result1;
188
+ case INTERP0_PEEK_FULL:
189
+ return this.interp0.result2;
190
+ case INTERP0_POP_LANE0: {
191
+ const value = this.interp0.result0;
192
+ this.interp0.writeback();
193
+ return value;
194
+ }
195
+ case INTERP0_POP_LANE1: {
196
+ const value = this.interp0.result1;
197
+ this.interp0.writeback();
198
+ return value;
199
+ }
200
+ case INTERP0_POP_FULL: {
201
+ const value = this.interp0.result2;
202
+ this.interp0.writeback();
203
+ return value;
204
+ }
205
+ case INTERP0_ACCUM0_ADD:
206
+ return this.interp0.smresult0;
207
+ case INTERP0_ACCUM1_ADD:
208
+ return this.interp0.smresult1;
209
+ case INTERP1_ACCUM0:
210
+ return this.interp1.accum0;
211
+ case INTERP1_ACCUM1:
212
+ return this.interp1.accum1;
213
+ case INTERP1_BASE0:
214
+ return this.interp1.base0;
215
+ case INTERP1_BASE1:
216
+ return this.interp1.base1;
217
+ case INTERP1_BASE2:
218
+ return this.interp1.base2;
219
+ case INTERP1_CTRL_LANE0:
220
+ return this.interp1.ctrl0;
221
+ case INTERP1_CTRL_LANE1:
222
+ return this.interp1.ctrl1;
223
+ case INTERP1_PEEK_LANE0:
224
+ return this.interp1.result0;
225
+ case INTERP1_PEEK_LANE1:
226
+ return this.interp1.result1;
227
+ case INTERP1_PEEK_FULL:
228
+ return this.interp1.result2;
229
+ case INTERP1_POP_LANE0: {
230
+ const value = this.interp1.result0;
231
+ this.interp1.writeback();
232
+ return value;
233
+ }
234
+ case INTERP1_POP_LANE1: {
235
+ const value = this.interp1.result1;
236
+ this.interp1.writeback();
237
+ return value;
238
+ }
239
+ case INTERP1_POP_FULL: {
240
+ const value = this.interp1.result2;
241
+ this.interp1.writeback();
242
+ return value;
243
+ }
244
+ case INTERP1_ACCUM0_ADD:
245
+ return this.interp1.smresult0;
246
+ case INTERP1_ACCUM1_ADD:
247
+ return this.interp1.smresult1;
134
248
  }
135
249
  console.warn(`Read from invalid SIO address: ${offset.toString(16)}`);
136
250
  return 0xffffffff;
@@ -216,6 +330,84 @@ class RPSIO {
216
330
  this.divRemainder = value;
217
331
  this.divCSR = 0b11;
218
332
  break;
333
+ case INTERP0_ACCUM0:
334
+ this.interp0.accum0 = value;
335
+ this.interp0.update();
336
+ break;
337
+ case INTERP0_ACCUM1:
338
+ this.interp0.accum1 = value;
339
+ this.interp0.update();
340
+ break;
341
+ case INTERP0_BASE0:
342
+ this.interp0.base0 = value;
343
+ this.interp0.update();
344
+ break;
345
+ case INTERP0_BASE1:
346
+ this.interp0.base1 = value;
347
+ this.interp0.update();
348
+ break;
349
+ case INTERP0_BASE2:
350
+ this.interp0.base2 = value;
351
+ this.interp0.update();
352
+ break;
353
+ case INTERP0_CTRL_LANE0:
354
+ this.interp0.ctrl0 = value;
355
+ this.interp0.update();
356
+ break;
357
+ case INTERP0_CTRL_LANE1:
358
+ this.interp0.ctrl1 = value;
359
+ this.interp0.update();
360
+ break;
361
+ case INTERP0_ACCUM0_ADD:
362
+ this.interp0.accum0 += value;
363
+ this.interp0.update();
364
+ break;
365
+ case INTERP0_ACCUM1_ADD:
366
+ this.interp0.accum1 += value;
367
+ this.interp0.update();
368
+ break;
369
+ case INTERP0_BASE_1AND0:
370
+ this.interp0.setBase01(value);
371
+ break;
372
+ case INTERP1_ACCUM0:
373
+ this.interp1.accum0 = value;
374
+ this.interp1.update();
375
+ break;
376
+ case INTERP1_ACCUM1:
377
+ this.interp1.accum1 = value;
378
+ this.interp1.update();
379
+ break;
380
+ case INTERP1_BASE0:
381
+ this.interp1.base0 = value;
382
+ this.interp1.update();
383
+ break;
384
+ case INTERP1_BASE1:
385
+ this.interp1.base1 = value;
386
+ this.interp1.update();
387
+ break;
388
+ case INTERP1_BASE2:
389
+ this.interp1.base2 = value;
390
+ this.interp1.update();
391
+ break;
392
+ case INTERP1_CTRL_LANE0:
393
+ this.interp1.ctrl0 = value;
394
+ this.interp1.update();
395
+ break;
396
+ case INTERP1_CTRL_LANE1:
397
+ this.interp1.ctrl1 = value;
398
+ this.interp1.update();
399
+ break;
400
+ case INTERP1_ACCUM0_ADD:
401
+ this.interp1.accum0 += value;
402
+ this.interp1.update();
403
+ break;
404
+ case INTERP1_ACCUM1_ADD:
405
+ this.interp1.accum1 += value;
406
+ this.interp1.update();
407
+ break;
408
+ case INTERP1_BASE_1AND0:
409
+ this.interp1.setBase01(value);
410
+ break;
219
411
  default:
220
412
  console.warn(`Write to invalid SIO address: ${offset.toString(16)}, value=${value.toString(16)}`);
221
413
  }
@@ -1 +1,3 @@
1
1
  export declare function bit(n: number): number;
2
+ export declare function s32(n: number): number;
3
+ export declare function u32(n: number): number;
@@ -1,7 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bit = void 0;
3
+ exports.u32 = exports.s32 = exports.bit = void 0;
4
4
  function bit(n) {
5
5
  return 1 << n;
6
6
  }
7
7
  exports.bit = bit;
8
+ function s32(n) {
9
+ return n | 0;
10
+ }
11
+ exports.s32 = s32;
12
+ function u32(n) {
13
+ return n >>> 0;
14
+ }
15
+ exports.u32 = u32;
@@ -0,0 +1,36 @@
1
+ export declare class InterpolatorConfig {
2
+ shift: number;
3
+ maskLSB: number;
4
+ maskMSB: number;
5
+ signed: boolean;
6
+ crossInput: boolean;
7
+ crossResult: boolean;
8
+ addRaw: boolean;
9
+ forceMSB: number;
10
+ blend: boolean;
11
+ clamp: boolean;
12
+ overf0: boolean;
13
+ overf1: boolean;
14
+ overf: boolean;
15
+ constructor(value: number);
16
+ toUint32(): number;
17
+ }
18
+ export declare class Interpolator {
19
+ private readonly index;
20
+ accum0: number;
21
+ accum1: number;
22
+ base0: number;
23
+ base1: number;
24
+ base2: number;
25
+ ctrl0: number;
26
+ ctrl1: number;
27
+ result0: number;
28
+ result1: number;
29
+ result2: number;
30
+ smresult0: number;
31
+ smresult1: number;
32
+ constructor(index: number);
33
+ update(): void;
34
+ writeback(): void;
35
+ setBase01(value: number): void;
36
+ }
@@ -0,0 +1,137 @@
1
+ import { s32, u32 } from './utils/bit';
2
+ export class InterpolatorConfig {
3
+ constructor(value) {
4
+ this.shift = 0;
5
+ this.maskLSB = 0;
6
+ this.maskMSB = 0;
7
+ this.signed = false;
8
+ this.crossInput = false;
9
+ this.crossResult = false;
10
+ this.addRaw = false;
11
+ this.forceMSB = 0;
12
+ this.blend = false;
13
+ this.clamp = false;
14
+ this.overf0 = false;
15
+ this.overf1 = false;
16
+ this.overf = false;
17
+ this.shift = (value >>> 0) & 0b11111;
18
+ this.maskLSB = (value >>> 5) & 0b11111;
19
+ this.maskMSB = (value >>> 10) & 0b11111;
20
+ this.signed = Boolean((value >>> 15) & 1);
21
+ this.crossInput = Boolean((value >>> 16) & 1);
22
+ this.crossResult = Boolean((value >>> 17) & 1);
23
+ this.addRaw = Boolean((value >>> 18) & 1);
24
+ this.forceMSB = (value >>> 19) & 0b11;
25
+ this.blend = Boolean((value >>> 21) & 1);
26
+ this.clamp = Boolean((value >>> 22) & 1);
27
+ this.overf0 = Boolean((value >>> 23) & 1);
28
+ this.overf1 = Boolean((value >>> 24) & 1);
29
+ this.overf = Boolean((value >>> 25) & 1);
30
+ }
31
+ toUint32() {
32
+ return (((this.shift & 0b11111) << 0) |
33
+ ((this.maskLSB & 0b11111) << 5) |
34
+ ((this.maskMSB & 0b11111) << 10) |
35
+ ((Number(this.signed) & 1) << 15) |
36
+ ((Number(this.crossInput) & 1) << 16) |
37
+ ((Number(this.crossResult) & 1) << 17) |
38
+ ((Number(this.addRaw) & 1) << 18) |
39
+ ((this.forceMSB & 0b11) << 19) |
40
+ ((Number(this.blend) & 1) << 21) |
41
+ ((Number(this.clamp) & 1) << 22) |
42
+ ((Number(this.overf0) & 1) << 23) |
43
+ ((Number(this.overf1) & 1) << 24) |
44
+ ((Number(this.overf) & 1) << 25));
45
+ }
46
+ }
47
+ export class Interpolator {
48
+ constructor(index) {
49
+ this.index = index;
50
+ this.accum0 = 0;
51
+ this.accum1 = 0;
52
+ this.base0 = 0;
53
+ this.base1 = 0;
54
+ this.base2 = 0;
55
+ this.ctrl0 = 0;
56
+ this.ctrl1 = 0;
57
+ this.result0 = 0;
58
+ this.result1 = 0;
59
+ this.result2 = 0;
60
+ this.smresult0 = 0;
61
+ this.smresult1 = 0;
62
+ this.update();
63
+ }
64
+ update() {
65
+ const N = this.index;
66
+ const ctrl0 = new InterpolatorConfig(this.ctrl0);
67
+ const ctrl1 = new InterpolatorConfig(this.ctrl1);
68
+ const do_clamp = ctrl0.clamp && N == 1;
69
+ const do_blend = ctrl0.blend && N == 0;
70
+ ctrl0.clamp = do_clamp;
71
+ ctrl0.blend = do_blend;
72
+ ctrl1.clamp = false;
73
+ ctrl1.blend = false;
74
+ ctrl1.overf0 = false;
75
+ ctrl1.overf1 = false;
76
+ ctrl1.overf = false;
77
+ const input0 = s32(ctrl0.crossInput ? this.accum1 : this.accum0);
78
+ const input1 = s32(ctrl1.crossInput ? this.accum0 : this.accum1);
79
+ const msbmask0 = ctrl0.maskMSB == 31 ? 0xffffffff : (1 << (ctrl0.maskMSB + 1)) - 1;
80
+ const msbmask1 = ctrl1.maskMSB == 31 ? 0xffffffff : (1 << (ctrl1.maskMSB + 1)) - 1;
81
+ const mask0 = msbmask0 & ~((1 << ctrl0.maskLSB) - 1);
82
+ const mask1 = msbmask1 & ~((1 << ctrl1.maskLSB) - 1);
83
+ const uresult0 = (input0 >>> ctrl0.shift) & mask0;
84
+ const uresult1 = (input1 >>> ctrl1.shift) & mask1;
85
+ const overf0 = Boolean((input0 >>> ctrl0.shift) & ~msbmask0);
86
+ const overf1 = Boolean((input1 >>> ctrl1.shift) & ~msbmask1);
87
+ const overf = overf0 || overf1;
88
+ const sextmask0 = (uresult0 & (1 << ctrl0.maskMSB)) ? (-1 << ctrl0.maskMSB) : 0;
89
+ const sextmask1 = (uresult1 & (1 << ctrl1.maskMSB)) ? (-1 << ctrl1.maskMSB) : 0;
90
+ const sresult0 = uresult0 | sextmask0;
91
+ const sresult1 = uresult1 | sextmask1;
92
+ const result0 = ctrl0.signed ? sresult0 : uresult0;
93
+ const result1 = ctrl1.signed ? sresult1 : uresult1;
94
+ const addresult0 = this.base0 + (ctrl0.addRaw ? input0 : result0);
95
+ const addresult1 = this.base1 + (ctrl1.addRaw ? input1 : result1);
96
+ const addresult2 = this.base2 + result0 + (do_blend ? 0 : result1);
97
+ const uclamp0 = u32(result0) < u32(this.base0) ? this.base0 : (u32(result0) > u32(this.base1) ? this.base1 : result0);
98
+ const sclamp0 = s32(result0) < s32(this.base0) ? this.base0 : (s32(result0) > s32(this.base1) ? this.base1 : result0);
99
+ const clamp0 = ctrl0.signed ? sclamp0 : uclamp0;
100
+ const alpha1 = result1 & 0xff;
101
+ const ublend1 = u32(this.base0) + (Math.floor((alpha1 * (u32(this.base1) - u32(this.base0))) / 256) | 0);
102
+ const sblend1 = s32(this.base0) + (Math.floor((alpha1 * (s32(this.base1) - s32(this.base0))) / 256) | 0);
103
+ const blend1 = ctrl1.signed ? sblend1 : ublend1;
104
+ this.smresult0 = u32(result0);
105
+ this.smresult1 = u32(result1);
106
+ this.result0 = u32(do_blend ? alpha1 : (do_clamp ? clamp0 : addresult0) | (ctrl0.forceMSB << 28));
107
+ this.result1 = u32((do_blend ? blend1 : addresult1) | (ctrl0.forceMSB << 28));
108
+ this.result2 = u32(addresult2);
109
+ ctrl0.overf0 = overf0;
110
+ ctrl0.overf1 = overf1;
111
+ ctrl0.overf = overf;
112
+ this.ctrl0 = ctrl0.toUint32();
113
+ this.ctrl1 = ctrl1.toUint32();
114
+ }
115
+ writeback() {
116
+ const ctrl0 = new InterpolatorConfig(this.ctrl0);
117
+ const ctrl1 = new InterpolatorConfig(this.ctrl1);
118
+ this.accum0 = u32(ctrl0.crossResult ? this.result1 : this.result0);
119
+ this.accum1 = u32(ctrl1.crossResult ? this.result0 : this.result1);
120
+ this.update();
121
+ }
122
+ setBase01(value) {
123
+ const N = this.index;
124
+ const ctrl0 = new InterpolatorConfig(this.ctrl0);
125
+ const ctrl1 = new InterpolatorConfig(this.ctrl1);
126
+ const do_blend = ctrl0.blend && N == 0;
127
+ const input0 = value & 0xffff;
128
+ const input1 = (value >>> 16) & 0xffff;
129
+ const sextmask0 = input0 & (1 << 15) ? -1 << 15 : 0;
130
+ const sextmask1 = input1 & (1 << 15) ? -1 << 15 : 0;
131
+ const base0 = (do_blend ? ctrl1.signed : ctrl0.signed) ? input0 | sextmask0 : input0;
132
+ const base1 = ctrl1.signed ? input1 | sextmask1 : input1;
133
+ this.base0 = u32(base0);
134
+ this.base1 = u32(base1);
135
+ this.update();
136
+ }
137
+ }
@@ -0,0 +1,4 @@
1
+ import { BasePeripheral, Peripheral } from './peripheral';
2
+ export declare class RP2040SysInfo extends BasePeripheral implements Peripheral {
3
+ readUint32(offset: number): number;
4
+ }
@@ -0,0 +1,18 @@
1
+ import { BasePeripheral } from './peripheral';
2
+ const CHIP_ID = 0;
3
+ const PLATFORM = 0x4;
4
+ const GITREF_RP2040 = 0x40;
5
+ export class RP2040SysInfo extends BasePeripheral {
6
+ readUint32(offset) {
7
+ // All the values here were verified against the silicon
8
+ switch (offset) {
9
+ case CHIP_ID:
10
+ return 0x10002927;
11
+ case PLATFORM:
12
+ return 0x00000002;
13
+ case GITREF_RP2040:
14
+ return 0xe0c912e8;
15
+ }
16
+ return super.readUint32(offset);
17
+ }
18
+ }
@@ -17,6 +17,7 @@ import { RP2040RTC } from './peripherals/rtc';
17
17
  import { RPSPI } from './peripherals/spi';
18
18
  import { RPSSI } from './peripherals/ssi';
19
19
  import { RP2040SysCfg } from './peripherals/syscfg';
20
+ import { RP2040SysInfo } from './peripherals/sysinfo';
20
21
  import { RPTimer } from './peripherals/timer';
21
22
  import { RPUART } from './peripherals/uart';
22
23
  import { RPUSBController } from './peripherals/usb';
@@ -104,7 +105,7 @@ export class RP2040 {
104
105
  this.executeTimer = null;
105
106
  this.peripherals = {
106
107
  0x18000: new RPSSI(this, 'SSI'),
107
- 0x40000: new UnimplementedPeripheral(this, 'SYSINFO_BASE'),
108
+ 0x40000: new RP2040SysInfo(this, 'SYSINFO_BASE'),
108
109
  0x40004: new RP2040SysCfg(this, 'SYSCFG'),
109
110
  0x40008: new RPClocks(this, 'CLOCKS_BASE'),
110
111
  0x4000c: new RPReset(this, 'RESETS_BASE'),
package/dist/esm/sio.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RP2040 } from './rp2040';
2
+ import { Interpolator } from './interpolator';
2
3
  export declare class RPSIO {
3
4
  private readonly rp2040;
4
5
  gpioValue: number;
@@ -11,6 +12,8 @@ export declare class RPSIO {
11
12
  divRemainder: number;
12
13
  divCSR: number;
13
14
  spinLock: number;
15
+ interp0: Interpolator;
16
+ interp1: Interpolator;
14
17
  constructor(rp2040: RP2040);
15
18
  updateHardwareDivider(signed: boolean): void;
16
19
  readUint32(offset: number): number;
package/dist/esm/sio.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { Interpolator } from './interpolator';
1
2
  const CPUID = 0x000;
2
3
  // GPIO
3
4
  const GPIO_IN = 0x004; // Input value for GPIO pins
@@ -27,6 +28,39 @@ const DIV_SDIVISOR = 0x06c; // Divider signed divisor
27
28
  const DIV_QUOTIENT = 0x070; // Divider result quotient
28
29
  const DIV_REMAINDER = 0x074; //Divider result remainder
29
30
  const DIV_CSR = 0x078;
31
+ //INTERPOLATOR
32
+ const INTERP0_ACCUM0 = 0x080; // Read/write access to accumulator 0
33
+ const INTERP0_ACCUM1 = 0x084; // Read/write access to accumulator 1
34
+ const INTERP0_BASE0 = 0x088; // Read/write access to BASE0 register
35
+ const INTERP0_BASE1 = 0x08c; // Read/write access to BASE1 register
36
+ const INTERP0_BASE2 = 0x090; // Read/write access to BASE2 register
37
+ const INTERP0_POP_LANE0 = 0x094; // Read LANE0 result, and simultaneously write lane results to both accumulators (POP)
38
+ const INTERP0_POP_LANE1 = 0x098; // Read LANE1 result, and simultaneously write lane results to both accumulators (POP)
39
+ const INTERP0_POP_FULL = 0x09c; // Read FULL result, and simultaneously write lane results to both accumulators (POP)
40
+ const INTERP0_PEEK_LANE0 = 0x0a0; // Read LANE0 result, without altering any internal state (PEEK)
41
+ const INTERP0_PEEK_LANE1 = 0x0a4; // Read LANE1 result, without altering any internal state (PEEK)
42
+ const INTERP0_PEEK_FULL = 0x0a8; // Read FULL result, without altering any internal state (PEEK)
43
+ const INTERP0_CTRL_LANE0 = 0x0ac; // Control register for lane 0
44
+ const INTERP0_CTRL_LANE1 = 0x0b0; // Control register for lane 1
45
+ const INTERP0_ACCUM0_ADD = 0x0b4; // Values written here are atomically added to ACCUM0
46
+ const INTERP0_ACCUM1_ADD = 0x0b8; // Values written here are atomically added to ACCUM1
47
+ const INTERP0_BASE_1AND0 = 0x0bc; // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously
48
+ const INTERP1_ACCUM0 = 0x0c0; // Read/write access to accumulator 0
49
+ const INTERP1_ACCUM1 = 0x0c4; // Read/write access to accumulator 1
50
+ const INTERP1_BASE0 = 0x0c8; // Read/write access to BASE0 register
51
+ const INTERP1_BASE1 = 0x0cc; // Read/write access to BASE1 register
52
+ const INTERP1_BASE2 = 0x0d0; // Read/write access to BASE2 register
53
+ const INTERP1_POP_LANE0 = 0x0d4; // Read LANE0 result, and simultaneously write lane results to both accumulators (POP)
54
+ const INTERP1_POP_LANE1 = 0x0d8; // Read LANE1 result, and simultaneously write lane results to both accumulators (POP)
55
+ const INTERP1_POP_FULL = 0x0dc; // Read FULL result, and simultaneously write lane results to both accumulators (POP)
56
+ const INTERP1_PEEK_LANE0 = 0x0e0; // Read LANE0 result, without altering any internal state (PEEK)
57
+ const INTERP1_PEEK_LANE1 = 0x0e4; // Read LANE1 result, without altering any internal state (PEEK)
58
+ const INTERP1_PEEK_FULL = 0x0e8; // Read FULL result, without altering any internal state (PEEK)
59
+ const INTERP1_CTRL_LANE0 = 0x0ec; // Control register for lane 0
60
+ const INTERP1_CTRL_LANE1 = 0x0f0; // Control register for lane 1
61
+ const INTERP1_ACCUM0_ADD = 0x0f4; // Values written here are atomically added to ACCUM0
62
+ const INTERP1_ACCUM1_ADD = 0x0f8; // Values written here are atomically added to ACCUM1
63
+ const INTERP1_BASE_1AND0 = 0x0fc; // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously
30
64
  //SPINLOCK
31
65
  const SPINLOCK_ST = 0x5c;
32
66
  const SPINLOCK0 = 0x100;
@@ -44,6 +78,8 @@ export class RPSIO {
44
78
  this.divRemainder = 0;
45
79
  this.divCSR = 0;
46
80
  this.spinLock = 0;
81
+ this.interp0 = new Interpolator(0);
82
+ this.interp1 = new Interpolator(1);
47
83
  }
48
84
  updateHardwareDivider(signed) {
49
85
  if (this.divDivisor == 0) {
@@ -128,6 +164,84 @@ export class RPSIO {
128
164
  return this.divRemainder;
129
165
  case DIV_CSR:
130
166
  return this.divCSR;
167
+ case INTERP0_ACCUM0:
168
+ return this.interp0.accum0;
169
+ case INTERP0_ACCUM1:
170
+ return this.interp0.accum1;
171
+ case INTERP0_BASE0:
172
+ return this.interp0.base0;
173
+ case INTERP0_BASE1:
174
+ return this.interp0.base1;
175
+ case INTERP0_BASE2:
176
+ return this.interp0.base2;
177
+ case INTERP0_CTRL_LANE0:
178
+ return this.interp0.ctrl0;
179
+ case INTERP0_CTRL_LANE1:
180
+ return this.interp0.ctrl1;
181
+ case INTERP0_PEEK_LANE0:
182
+ return this.interp0.result0;
183
+ case INTERP0_PEEK_LANE1:
184
+ return this.interp0.result1;
185
+ case INTERP0_PEEK_FULL:
186
+ return this.interp0.result2;
187
+ case INTERP0_POP_LANE0: {
188
+ const value = this.interp0.result0;
189
+ this.interp0.writeback();
190
+ return value;
191
+ }
192
+ case INTERP0_POP_LANE1: {
193
+ const value = this.interp0.result1;
194
+ this.interp0.writeback();
195
+ return value;
196
+ }
197
+ case INTERP0_POP_FULL: {
198
+ const value = this.interp0.result2;
199
+ this.interp0.writeback();
200
+ return value;
201
+ }
202
+ case INTERP0_ACCUM0_ADD:
203
+ return this.interp0.smresult0;
204
+ case INTERP0_ACCUM1_ADD:
205
+ return this.interp0.smresult1;
206
+ case INTERP1_ACCUM0:
207
+ return this.interp1.accum0;
208
+ case INTERP1_ACCUM1:
209
+ return this.interp1.accum1;
210
+ case INTERP1_BASE0:
211
+ return this.interp1.base0;
212
+ case INTERP1_BASE1:
213
+ return this.interp1.base1;
214
+ case INTERP1_BASE2:
215
+ return this.interp1.base2;
216
+ case INTERP1_CTRL_LANE0:
217
+ return this.interp1.ctrl0;
218
+ case INTERP1_CTRL_LANE1:
219
+ return this.interp1.ctrl1;
220
+ case INTERP1_PEEK_LANE0:
221
+ return this.interp1.result0;
222
+ case INTERP1_PEEK_LANE1:
223
+ return this.interp1.result1;
224
+ case INTERP1_PEEK_FULL:
225
+ return this.interp1.result2;
226
+ case INTERP1_POP_LANE0: {
227
+ const value = this.interp1.result0;
228
+ this.interp1.writeback();
229
+ return value;
230
+ }
231
+ case INTERP1_POP_LANE1: {
232
+ const value = this.interp1.result1;
233
+ this.interp1.writeback();
234
+ return value;
235
+ }
236
+ case INTERP1_POP_FULL: {
237
+ const value = this.interp1.result2;
238
+ this.interp1.writeback();
239
+ return value;
240
+ }
241
+ case INTERP1_ACCUM0_ADD:
242
+ return this.interp1.smresult0;
243
+ case INTERP1_ACCUM1_ADD:
244
+ return this.interp1.smresult1;
131
245
  }
132
246
  console.warn(`Read from invalid SIO address: ${offset.toString(16)}`);
133
247
  return 0xffffffff;
@@ -213,6 +327,84 @@ export class RPSIO {
213
327
  this.divRemainder = value;
214
328
  this.divCSR = 0b11;
215
329
  break;
330
+ case INTERP0_ACCUM0:
331
+ this.interp0.accum0 = value;
332
+ this.interp0.update();
333
+ break;
334
+ case INTERP0_ACCUM1:
335
+ this.interp0.accum1 = value;
336
+ this.interp0.update();
337
+ break;
338
+ case INTERP0_BASE0:
339
+ this.interp0.base0 = value;
340
+ this.interp0.update();
341
+ break;
342
+ case INTERP0_BASE1:
343
+ this.interp0.base1 = value;
344
+ this.interp0.update();
345
+ break;
346
+ case INTERP0_BASE2:
347
+ this.interp0.base2 = value;
348
+ this.interp0.update();
349
+ break;
350
+ case INTERP0_CTRL_LANE0:
351
+ this.interp0.ctrl0 = value;
352
+ this.interp0.update();
353
+ break;
354
+ case INTERP0_CTRL_LANE1:
355
+ this.interp0.ctrl1 = value;
356
+ this.interp0.update();
357
+ break;
358
+ case INTERP0_ACCUM0_ADD:
359
+ this.interp0.accum0 += value;
360
+ this.interp0.update();
361
+ break;
362
+ case INTERP0_ACCUM1_ADD:
363
+ this.interp0.accum1 += value;
364
+ this.interp0.update();
365
+ break;
366
+ case INTERP0_BASE_1AND0:
367
+ this.interp0.setBase01(value);
368
+ break;
369
+ case INTERP1_ACCUM0:
370
+ this.interp1.accum0 = value;
371
+ this.interp1.update();
372
+ break;
373
+ case INTERP1_ACCUM1:
374
+ this.interp1.accum1 = value;
375
+ this.interp1.update();
376
+ break;
377
+ case INTERP1_BASE0:
378
+ this.interp1.base0 = value;
379
+ this.interp1.update();
380
+ break;
381
+ case INTERP1_BASE1:
382
+ this.interp1.base1 = value;
383
+ this.interp1.update();
384
+ break;
385
+ case INTERP1_BASE2:
386
+ this.interp1.base2 = value;
387
+ this.interp1.update();
388
+ break;
389
+ case INTERP1_CTRL_LANE0:
390
+ this.interp1.ctrl0 = value;
391
+ this.interp1.update();
392
+ break;
393
+ case INTERP1_CTRL_LANE1:
394
+ this.interp1.ctrl1 = value;
395
+ this.interp1.update();
396
+ break;
397
+ case INTERP1_ACCUM0_ADD:
398
+ this.interp1.accum0 += value;
399
+ this.interp1.update();
400
+ break;
401
+ case INTERP1_ACCUM1_ADD:
402
+ this.interp1.accum1 += value;
403
+ this.interp1.update();
404
+ break;
405
+ case INTERP1_BASE_1AND0:
406
+ this.interp1.setBase01(value);
407
+ break;
216
408
  default:
217
409
  console.warn(`Write to invalid SIO address: ${offset.toString(16)}, value=${value.toString(16)}`);
218
410
  }
@@ -1 +1,3 @@
1
1
  export declare function bit(n: number): number;
2
+ export declare function s32(n: number): number;
3
+ export declare function u32(n: number): number;
@@ -1,3 +1,9 @@
1
1
  export function bit(n) {
2
2
  return 1 << n;
3
3
  }
4
+ export function s32(n) {
5
+ return n | 0;
6
+ }
7
+ export function u32(n) {
8
+ return n >>> 0;
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rp2040js",
3
- "version": "0.15.1",
3
+ "version": "0.17.0",
4
4
  "description": "Raspberry Pi Pico (RP2040) Emulator",
5
5
  "repository": "https://github.com/wokwi/rp2040js",
6
6
  "keywords": [