rp2040js 0.17.15 → 0.17.17

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.
package/README.md CHANGED
@@ -30,7 +30,7 @@ npm start
30
30
 
31
31
  ### MicroPython code
32
32
 
33
- To run the MicroPython demo, first download [rp2-pico-20210902-v1.17.uf2](https://micropython.org/resources/firmware/rp2-pico-20210902-v1.17.uf2), place it in the rp2040js root directory, then run:
33
+ To run the MicroPython demo, first download [RPI_PICO-20230426-v1.20.0.uf2](https://micropython.org/resources/firmware/RPI_PICO-20230426-v1.20.0.uf2), place it in the rp2040js root directory, then run:
34
34
 
35
35
  ```
36
36
  npm install
@@ -1,8 +1,14 @@
1
1
  import { RP2040 } from '../rp2040';
2
2
  import { FIFO } from '../utils/fifo';
3
+ import { DREQChannel } from './dma';
3
4
  import { BasePeripheral, Peripheral } from './peripheral';
5
+ export interface ISPIDMAChannels {
6
+ rx: DREQChannel;
7
+ tx: DREQChannel;
8
+ }
4
9
  export declare class RPSPI extends BasePeripheral implements Peripheral {
5
10
  readonly irq: number;
11
+ readonly dreq: ISPIDMAChannels;
6
12
  readonly rxFIFO: FIFO;
7
13
  readonly txFIFO: FIFO;
8
14
  onTransmit: (value: number) => void;
@@ -20,7 +26,9 @@ export declare class RPSPI extends BasePeripheral implements Peripheral {
20
26
  get masterMode(): boolean;
21
27
  get spiMode(): 2 | 3 | 0 | 1;
22
28
  get clockFrequency(): number;
23
- constructor(rp2040: RP2040, name: string, irq: number);
29
+ private updateDMATx;
30
+ private updateDMARx;
31
+ constructor(rp2040: RP2040, name: string, irq: number, dreq: ISPIDMAChannels);
24
32
  private doTX;
25
33
  completeTransmit(rxValue: number): void;
26
34
  checkInterrupts(): void;
@@ -53,9 +53,10 @@ const SSPRXINTR = 1 << 2;
53
53
  const SSPRTINTR = 1 << 1;
54
54
  const SSPRORINTR = 1 << 0;
55
55
  class RPSPI extends peripheral_1.BasePeripheral {
56
- constructor(rp2040, name, irq) {
56
+ constructor(rp2040, name, irq, dreq) {
57
57
  super(rp2040, name);
58
58
  this.irq = irq;
59
+ this.dreq = dreq;
59
60
  this.rxFIFO = new fifo_1.FIFO(8);
60
61
  this.txFIFO = new fifo_1.FIFO(8);
61
62
  // User provided callbacks
@@ -67,6 +68,8 @@ class RPSPI extends peripheral_1.BasePeripheral {
67
68
  this.clockDivisor = 0;
68
69
  this.intRaw = 0;
69
70
  this.intEnable = 0;
71
+ this.updateDMATx();
72
+ this.updateDMARx();
70
73
  }
71
74
  get intStatus() {
72
75
  return this.intRaw & this.intEnable;
@@ -93,6 +96,22 @@ class RPSPI extends peripheral_1.BasePeripheral {
93
96
  const scr = (this.control0 >> SCR_SHIFT) & SCR_MASK;
94
97
  return this.rp2040.clkPeri / (this.clockDivisor * (1 + scr));
95
98
  }
99
+ updateDMATx() {
100
+ if (this.txFIFO.full) {
101
+ this.rp2040.dma.clearDREQ(this.dreq.tx);
102
+ }
103
+ else {
104
+ this.rp2040.dma.setDREQ(this.dreq.tx);
105
+ }
106
+ }
107
+ updateDMARx() {
108
+ if (this.rxFIFO.empty) {
109
+ this.rp2040.dma.clearDREQ(this.dreq.rx);
110
+ }
111
+ else {
112
+ this.rp2040.dma.setDREQ(this.dreq.rx);
113
+ }
114
+ }
96
115
  doTX() {
97
116
  if (!this.busy && !this.txFIFO.empty) {
98
117
  const value = this.txFIFO.pull();
@@ -132,6 +151,8 @@ class RPSPI extends peripheral_1.BasePeripheral {
132
151
  if (this.intStatus !== prevStatus) {
133
152
  this.checkInterrupts();
134
153
  }
154
+ this.updateDMATx();
155
+ this.updateDMARx();
135
156
  }
136
157
  readUint32(offset) {
137
158
  switch (offset) {
@@ -191,7 +212,8 @@ class RPSPI extends peripheral_1.BasePeripheral {
191
212
  return;
192
213
  case SSPDR:
193
214
  if (!this.txFIFO.full) {
194
- this.txFIFO.push(value);
215
+ // decoded with respect to SSPCR0.DSS
216
+ this.txFIFO.push(value & ((1 << this.dataBits) - 1));
195
217
  this.doTX();
196
218
  this.fifosUpdated();
197
219
  }
@@ -1,14 +1,20 @@
1
1
  import { RP2040 } from '../rp2040';
2
+ import { DREQChannel } from './dma';
2
3
  import { BasePeripheral, Peripheral } from './peripheral';
4
+ export interface IUARTDMAChannels {
5
+ rx: DREQChannel;
6
+ tx: DREQChannel;
7
+ }
3
8
  export declare class RPUART extends BasePeripheral implements Peripheral {
4
9
  readonly irq: number;
10
+ readonly dreq: IUARTDMAChannels;
5
11
  private ctrlRegister;
6
12
  private lineCtrlRegister;
7
13
  private rxFIFO;
8
14
  private interruptMask;
9
15
  private interruptStatus;
10
16
  onByte?: (value: number) => void;
11
- constructor(rp2040: RP2040, name: string, irq: number);
17
+ constructor(rp2040: RP2040, name: string, irq: number, dreq: IUARTDMAChannels);
12
18
  get enabled(): boolean;
13
19
  get txEnabled(): boolean;
14
20
  get rxEnabled(): boolean;
@@ -24,9 +24,10 @@ const UARTEN = 1 << 0;
24
24
  // Interrupt bits
25
25
  const UARTRXINTR = 1 << 4;
26
26
  class RPUART extends peripheral_1.BasePeripheral {
27
- constructor(rp2040, name, irq) {
27
+ constructor(rp2040, name, irq, dreq) {
28
28
  super(rp2040, name);
29
29
  this.irq = irq;
30
+ this.dreq = dreq;
30
31
  this.ctrlRegister = RXE | TXE;
31
32
  this.lineCtrlRegister = 0;
32
33
  this.rxFIFO = new fifo_1.FIFO(32);
@@ -108,6 +109,12 @@ class RPUART extends peripheral_1.BasePeripheral {
108
109
  break;
109
110
  case UARTCR:
110
111
  this.ctrlRegister = value;
112
+ if (this.enabled) {
113
+ this.rp2040.dma.setDREQ(this.dreq.tx);
114
+ }
115
+ else {
116
+ this.rp2040.dma.clearDREQ(this.dreq.tx);
117
+ }
111
118
  break;
112
119
  case UARTIMSC:
113
120
  this.interruptMask = value & 0x7ff;
@@ -35,7 +35,6 @@ export declare class RP2040 {
35
35
  readonly sio: RPSIO;
36
36
  readonly uart: RPUART[];
37
37
  readonly i2c: RPI2C[];
38
- readonly spi: RPSPI[];
39
38
  readonly pwm: RPPWM;
40
39
  readonly adc: RPADC;
41
40
  readonly gpio: GPIOPin[];
@@ -43,6 +42,7 @@ export declare class RP2040 {
43
42
  readonly dma: RPDMA;
44
43
  readonly pio: RPPIO[];
45
44
  readonly usbCtrl: RPUSBController;
45
+ readonly spi: RPSPI[];
46
46
  private stopped;
47
47
  logger: Logger;
48
48
  private executeTimer;
@@ -54,9 +54,17 @@ class RP2040 {
54
54
  this.clkPeri = 125 * MHz;
55
55
  this.ppb = new ppb_1.RPPPB(this, 'PPB');
56
56
  this.sio = new sio_1.RPSIO(this);
57
- this.uart = [new uart_1.RPUART(this, 'UART0', irq_1.IRQ.UART0), new uart_1.RPUART(this, 'UART1', irq_1.IRQ.UART1)];
57
+ this.uart = [
58
+ new uart_1.RPUART(this, 'UART0', irq_1.IRQ.UART0, {
59
+ rx: dma_1.DREQChannel.DREQ_UART0_RX,
60
+ tx: dma_1.DREQChannel.DREQ_UART0_TX,
61
+ }),
62
+ new uart_1.RPUART(this, 'UART1', irq_1.IRQ.UART1, {
63
+ rx: dma_1.DREQChannel.DREQ_UART1_RX,
64
+ tx: dma_1.DREQChannel.DREQ_UART1_TX,
65
+ }),
66
+ ];
58
67
  this.i2c = [new i2c_1.RPI2C(this, 'I2C0', irq_1.IRQ.I2C0), new i2c_1.RPI2C(this, 'I2C1', irq_1.IRQ.I2C1)];
59
- this.spi = [new spi_1.RPSPI(this, 'SPI0', irq_1.IRQ.SPI0), new spi_1.RPSPI(this, 'SPI1', irq_1.IRQ.SPI1)];
60
68
  this.pwm = new pwm_1.RPPWM(this, 'PWM_BASE');
61
69
  this.adc = new adc_1.RPADC(this, 'ADC');
62
70
  this.gpio = [
@@ -105,6 +113,16 @@ class RP2040 {
105
113
  new pio_1.RPPIO(this, 'PIO1', irq_1.IRQ.PIO1_IRQ0, 1),
106
114
  ];
107
115
  this.usbCtrl = new usb_1.RPUSBController(this, 'USB');
116
+ this.spi = [
117
+ new spi_1.RPSPI(this, 'SPI0', irq_1.IRQ.SPI0, {
118
+ rx: dma_1.DREQChannel.DREQ_SPI0_RX,
119
+ tx: dma_1.DREQChannel.DREQ_SPI0_TX,
120
+ }),
121
+ new spi_1.RPSPI(this, 'SPI1', irq_1.IRQ.SPI1, {
122
+ rx: dma_1.DREQChannel.DREQ_SPI1_RX,
123
+ tx: dma_1.DREQChannel.DREQ_SPI1_TX,
124
+ }),
125
+ ];
108
126
  this.stopped = true;
109
127
  this.logger = new logging_1.ConsoleLogger(logging_1.LogLevel.Debug, true);
110
128
  this.executeTimer = null;
@@ -1,8 +1,14 @@
1
1
  import { RP2040 } from '../rp2040';
2
2
  import { FIFO } from '../utils/fifo';
3
+ import { DREQChannel } from './dma';
3
4
  import { BasePeripheral, Peripheral } from './peripheral';
5
+ export interface ISPIDMAChannels {
6
+ rx: DREQChannel;
7
+ tx: DREQChannel;
8
+ }
4
9
  export declare class RPSPI extends BasePeripheral implements Peripheral {
5
10
  readonly irq: number;
11
+ readonly dreq: ISPIDMAChannels;
6
12
  readonly rxFIFO: FIFO;
7
13
  readonly txFIFO: FIFO;
8
14
  onTransmit: (value: number) => void;
@@ -20,7 +26,9 @@ export declare class RPSPI extends BasePeripheral implements Peripheral {
20
26
  get masterMode(): boolean;
21
27
  get spiMode(): 2 | 3 | 0 | 1;
22
28
  get clockFrequency(): number;
23
- constructor(rp2040: RP2040, name: string, irq: number);
29
+ private updateDMATx;
30
+ private updateDMARx;
31
+ constructor(rp2040: RP2040, name: string, irq: number, dreq: ISPIDMAChannels);
24
32
  private doTX;
25
33
  completeTransmit(rxValue: number): void;
26
34
  checkInterrupts(): void;
@@ -50,9 +50,10 @@ const SSPRXINTR = 1 << 2;
50
50
  const SSPRTINTR = 1 << 1;
51
51
  const SSPRORINTR = 1 << 0;
52
52
  export class RPSPI extends BasePeripheral {
53
- constructor(rp2040, name, irq) {
53
+ constructor(rp2040, name, irq, dreq) {
54
54
  super(rp2040, name);
55
55
  this.irq = irq;
56
+ this.dreq = dreq;
56
57
  this.rxFIFO = new FIFO(8);
57
58
  this.txFIFO = new FIFO(8);
58
59
  // User provided callbacks
@@ -64,6 +65,8 @@ export class RPSPI extends BasePeripheral {
64
65
  this.clockDivisor = 0;
65
66
  this.intRaw = 0;
66
67
  this.intEnable = 0;
68
+ this.updateDMATx();
69
+ this.updateDMARx();
67
70
  }
68
71
  get intStatus() {
69
72
  return this.intRaw & this.intEnable;
@@ -90,6 +93,22 @@ export class RPSPI extends BasePeripheral {
90
93
  const scr = (this.control0 >> SCR_SHIFT) & SCR_MASK;
91
94
  return this.rp2040.clkPeri / (this.clockDivisor * (1 + scr));
92
95
  }
96
+ updateDMATx() {
97
+ if (this.txFIFO.full) {
98
+ this.rp2040.dma.clearDREQ(this.dreq.tx);
99
+ }
100
+ else {
101
+ this.rp2040.dma.setDREQ(this.dreq.tx);
102
+ }
103
+ }
104
+ updateDMARx() {
105
+ if (this.rxFIFO.empty) {
106
+ this.rp2040.dma.clearDREQ(this.dreq.rx);
107
+ }
108
+ else {
109
+ this.rp2040.dma.setDREQ(this.dreq.rx);
110
+ }
111
+ }
93
112
  doTX() {
94
113
  if (!this.busy && !this.txFIFO.empty) {
95
114
  const value = this.txFIFO.pull();
@@ -129,6 +148,8 @@ export class RPSPI extends BasePeripheral {
129
148
  if (this.intStatus !== prevStatus) {
130
149
  this.checkInterrupts();
131
150
  }
151
+ this.updateDMATx();
152
+ this.updateDMARx();
132
153
  }
133
154
  readUint32(offset) {
134
155
  switch (offset) {
@@ -188,7 +209,8 @@ export class RPSPI extends BasePeripheral {
188
209
  return;
189
210
  case SSPDR:
190
211
  if (!this.txFIFO.full) {
191
- this.txFIFO.push(value);
212
+ // decoded with respect to SSPCR0.DSS
213
+ this.txFIFO.push(value & ((1 << this.dataBits) - 1));
192
214
  this.doTX();
193
215
  this.fifosUpdated();
194
216
  }
@@ -1,14 +1,20 @@
1
1
  import { RP2040 } from '../rp2040';
2
+ import { DREQChannel } from './dma';
2
3
  import { BasePeripheral, Peripheral } from './peripheral';
4
+ export interface IUARTDMAChannels {
5
+ rx: DREQChannel;
6
+ tx: DREQChannel;
7
+ }
3
8
  export declare class RPUART extends BasePeripheral implements Peripheral {
4
9
  readonly irq: number;
10
+ readonly dreq: IUARTDMAChannels;
5
11
  private ctrlRegister;
6
12
  private lineCtrlRegister;
7
13
  private rxFIFO;
8
14
  private interruptMask;
9
15
  private interruptStatus;
10
16
  onByte?: (value: number) => void;
11
- constructor(rp2040: RP2040, name: string, irq: number);
17
+ constructor(rp2040: RP2040, name: string, irq: number, dreq: IUARTDMAChannels);
12
18
  get enabled(): boolean;
13
19
  get txEnabled(): boolean;
14
20
  get rxEnabled(): boolean;
@@ -21,9 +21,10 @@ const UARTEN = 1 << 0;
21
21
  // Interrupt bits
22
22
  const UARTRXINTR = 1 << 4;
23
23
  export class RPUART extends BasePeripheral {
24
- constructor(rp2040, name, irq) {
24
+ constructor(rp2040, name, irq, dreq) {
25
25
  super(rp2040, name);
26
26
  this.irq = irq;
27
+ this.dreq = dreq;
27
28
  this.ctrlRegister = RXE | TXE;
28
29
  this.lineCtrlRegister = 0;
29
30
  this.rxFIFO = new FIFO(32);
@@ -105,6 +106,12 @@ export class RPUART extends BasePeripheral {
105
106
  break;
106
107
  case UARTCR:
107
108
  this.ctrlRegister = value;
109
+ if (this.enabled) {
110
+ this.rp2040.dma.setDREQ(this.dreq.tx);
111
+ }
112
+ else {
113
+ this.rp2040.dma.clearDREQ(this.dreq.tx);
114
+ }
108
115
  break;
109
116
  case UARTIMSC:
110
117
  this.interruptMask = value & 0x7ff;
@@ -35,7 +35,6 @@ export declare class RP2040 {
35
35
  readonly sio: RPSIO;
36
36
  readonly uart: RPUART[];
37
37
  readonly i2c: RPI2C[];
38
- readonly spi: RPSPI[];
39
38
  readonly pwm: RPPWM;
40
39
  readonly adc: RPADC;
41
40
  readonly gpio: GPIOPin[];
@@ -43,6 +42,7 @@ export declare class RP2040 {
43
42
  readonly dma: RPDMA;
44
43
  readonly pio: RPPIO[];
45
44
  readonly usbCtrl: RPUSBController;
45
+ readonly spi: RPSPI[];
46
46
  private stopped;
47
47
  logger: Logger;
48
48
  private executeTimer;
@@ -5,7 +5,7 @@ import { IRQ } from './irq';
5
5
  import { RPADC } from './peripherals/adc';
6
6
  import { RPBUSCTRL } from './peripherals/busctrl';
7
7
  import { RPClocks } from './peripherals/clocks';
8
- import { RPDMA } from './peripherals/dma';
8
+ import { DREQChannel, RPDMA } from './peripherals/dma';
9
9
  import { RPI2C } from './peripherals/i2c';
10
10
  import { RPIO } from './peripherals/io';
11
11
  import { RPPADS } from './peripherals/pads';
@@ -51,9 +51,17 @@ export class RP2040 {
51
51
  this.clkPeri = 125 * MHz;
52
52
  this.ppb = new RPPPB(this, 'PPB');
53
53
  this.sio = new RPSIO(this);
54
- this.uart = [new RPUART(this, 'UART0', IRQ.UART0), new RPUART(this, 'UART1', IRQ.UART1)];
54
+ this.uart = [
55
+ new RPUART(this, 'UART0', IRQ.UART0, {
56
+ rx: DREQChannel.DREQ_UART0_RX,
57
+ tx: DREQChannel.DREQ_UART0_TX,
58
+ }),
59
+ new RPUART(this, 'UART1', IRQ.UART1, {
60
+ rx: DREQChannel.DREQ_UART1_RX,
61
+ tx: DREQChannel.DREQ_UART1_TX,
62
+ }),
63
+ ];
55
64
  this.i2c = [new RPI2C(this, 'I2C0', IRQ.I2C0), new RPI2C(this, 'I2C1', IRQ.I2C1)];
56
- this.spi = [new RPSPI(this, 'SPI0', IRQ.SPI0), new RPSPI(this, 'SPI1', IRQ.SPI1)];
57
65
  this.pwm = new RPPWM(this, 'PWM_BASE');
58
66
  this.adc = new RPADC(this, 'ADC');
59
67
  this.gpio = [
@@ -102,6 +110,16 @@ export class RP2040 {
102
110
  new RPPIO(this, 'PIO1', IRQ.PIO1_IRQ0, 1),
103
111
  ];
104
112
  this.usbCtrl = new RPUSBController(this, 'USB');
113
+ this.spi = [
114
+ new RPSPI(this, 'SPI0', IRQ.SPI0, {
115
+ rx: DREQChannel.DREQ_SPI0_RX,
116
+ tx: DREQChannel.DREQ_SPI0_TX,
117
+ }),
118
+ new RPSPI(this, 'SPI1', IRQ.SPI1, {
119
+ rx: DREQChannel.DREQ_SPI1_RX,
120
+ tx: DREQChannel.DREQ_SPI1_TX,
121
+ }),
122
+ ];
105
123
  this.stopped = true;
106
124
  this.logger = new ConsoleLogger(LogLevel.Debug, true);
107
125
  this.executeTimer = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rp2040js",
3
- "version": "0.17.15",
3
+ "version": "0.17.17",
4
4
  "description": "Raspberry Pi Pico (RP2040) Emulator",
5
5
  "repository": "https://github.com/wokwi/rp2040js",
6
6
  "keywords": [
@@ -16,6 +16,9 @@
16
16
  "main": "./dist/cjs/index.js",
17
17
  "module": "./dist/esm/index.js",
18
18
  "typings": "./dist/cjs/index.d.ts",
19
+ "engines": {
20
+ "node": ">=16.0.0"
21
+ },
19
22
  "exports": {
20
23
  ".": {
21
24
  "import": "./dist/esm/index.js",
@@ -36,7 +39,8 @@
36
39
  "start:micropython": "ts-node demo/micropython-run.ts",
37
40
  "start:circuitpython": "ts-node demo/micropython-run.ts --circuitpython",
38
41
  "start:gdbdiff": "ts-node debug/gdbdiff.ts",
39
- "test": "jest"
42
+ "test": "jest",
43
+ "test:micropython-spi": "ts-node test/micropython-spi-test.ts"
40
44
  },
41
45
  "devDependencies": {
42
46
  "@types/jest": "^27.4.1",