rp2040js 0.17.16 → 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,17 +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
- readonly index: number;
5
9
  readonly irq: number;
10
+ readonly dreq: IUARTDMAChannels;
6
11
  private ctrlRegister;
7
12
  private lineCtrlRegister;
8
13
  private rxFIFO;
9
14
  private interruptMask;
10
15
  private interruptStatus;
11
- private readonly rxDREQ;
12
- private readonly txDREQ;
13
16
  onByte?: (value: number) => void;
14
- constructor(rp2040: RP2040, name: string, index: number, irq: number);
17
+ constructor(rp2040: RP2040, name: string, irq: number, dreq: IUARTDMAChannels);
15
18
  get enabled(): boolean;
16
19
  get txEnabled(): boolean;
17
20
  get rxEnabled(): boolean;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RPUART = void 0;
4
4
  const fifo_1 = require("../utils/fifo");
5
- const dma_1 = require("./dma");
6
5
  const peripheral_1 = require("./peripheral");
7
6
  const UARTDR = 0x0;
8
7
  const UARTFR = 0x18;
@@ -25,17 +24,15 @@ const UARTEN = 1 << 0;
25
24
  // Interrupt bits
26
25
  const UARTRXINTR = 1 << 4;
27
26
  class RPUART extends peripheral_1.BasePeripheral {
28
- constructor(rp2040, name, index, irq) {
27
+ constructor(rp2040, name, irq, dreq) {
29
28
  super(rp2040, name);
30
- this.index = index;
31
29
  this.irq = irq;
30
+ this.dreq = dreq;
32
31
  this.ctrlRegister = RXE | TXE;
33
32
  this.lineCtrlRegister = 0;
34
33
  this.rxFIFO = new fifo_1.FIFO(32);
35
34
  this.interruptMask = 0;
36
35
  this.interruptStatus = 0;
37
- this.rxDREQ = this.index == 0 ? dma_1.DREQChannel.DREQ_UART0_RX : dma_1.DREQChannel.DREQ_UART1_RX;
38
- this.txDREQ = this.index == 0 ? dma_1.DREQChannel.DREQ_UART0_TX : dma_1.DREQChannel.DREQ_UART1_TX;
39
36
  }
40
37
  get enabled() {
41
38
  return !!(this.ctrlRegister & UARTEN);
@@ -113,10 +110,10 @@ class RPUART extends peripheral_1.BasePeripheral {
113
110
  case UARTCR:
114
111
  this.ctrlRegister = value;
115
112
  if (this.enabled) {
116
- this.rp2040.dma.setDREQ(this.txDREQ);
113
+ this.rp2040.dma.setDREQ(this.dreq.tx);
117
114
  }
118
115
  else {
119
- this.rp2040.dma.clearDREQ(this.txDREQ);
116
+ this.rp2040.dma.clearDREQ(this.dreq.tx);
120
117
  }
121
118
  break;
122
119
  case UARTIMSC:
@@ -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;
@@ -55,11 +55,16 @@ class RP2040 {
55
55
  this.ppb = new ppb_1.RPPPB(this, 'PPB');
56
56
  this.sio = new sio_1.RPSIO(this);
57
57
  this.uart = [
58
- new uart_1.RPUART(this, 'UART0', 0, irq_1.IRQ.UART0),
59
- new uart_1.RPUART(this, 'UART1', 1, irq_1.IRQ.UART1),
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
+ }),
60
66
  ];
61
67
  this.i2c = [new i2c_1.RPI2C(this, 'I2C0', irq_1.IRQ.I2C0), new i2c_1.RPI2C(this, 'I2C1', irq_1.IRQ.I2C1)];
62
- this.spi = [new spi_1.RPSPI(this, 'SPI0', irq_1.IRQ.SPI0), new spi_1.RPSPI(this, 'SPI1', irq_1.IRQ.SPI1)];
63
68
  this.pwm = new pwm_1.RPPWM(this, 'PWM_BASE');
64
69
  this.adc = new adc_1.RPADC(this, 'ADC');
65
70
  this.gpio = [
@@ -108,6 +113,16 @@ class RP2040 {
108
113
  new pio_1.RPPIO(this, 'PIO1', irq_1.IRQ.PIO1_IRQ0, 1),
109
114
  ];
110
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
+ ];
111
126
  this.stopped = true;
112
127
  this.logger = new logging_1.ConsoleLogger(logging_1.LogLevel.Debug, true);
113
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,17 +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
- readonly index: number;
5
9
  readonly irq: number;
10
+ readonly dreq: IUARTDMAChannels;
6
11
  private ctrlRegister;
7
12
  private lineCtrlRegister;
8
13
  private rxFIFO;
9
14
  private interruptMask;
10
15
  private interruptStatus;
11
- private readonly rxDREQ;
12
- private readonly txDREQ;
13
16
  onByte?: (value: number) => void;
14
- constructor(rp2040: RP2040, name: string, index: number, irq: number);
17
+ constructor(rp2040: RP2040, name: string, irq: number, dreq: IUARTDMAChannels);
15
18
  get enabled(): boolean;
16
19
  get txEnabled(): boolean;
17
20
  get rxEnabled(): boolean;
@@ -1,5 +1,4 @@
1
1
  import { FIFO } from '../utils/fifo';
2
- import { DREQChannel } from './dma';
3
2
  import { BasePeripheral } from './peripheral';
4
3
  const UARTDR = 0x0;
5
4
  const UARTFR = 0x18;
@@ -22,17 +21,15 @@ const UARTEN = 1 << 0;
22
21
  // Interrupt bits
23
22
  const UARTRXINTR = 1 << 4;
24
23
  export class RPUART extends BasePeripheral {
25
- constructor(rp2040, name, index, irq) {
24
+ constructor(rp2040, name, irq, dreq) {
26
25
  super(rp2040, name);
27
- this.index = index;
28
26
  this.irq = irq;
27
+ this.dreq = dreq;
29
28
  this.ctrlRegister = RXE | TXE;
30
29
  this.lineCtrlRegister = 0;
31
30
  this.rxFIFO = new FIFO(32);
32
31
  this.interruptMask = 0;
33
32
  this.interruptStatus = 0;
34
- this.rxDREQ = this.index == 0 ? DREQChannel.DREQ_UART0_RX : DREQChannel.DREQ_UART1_RX;
35
- this.txDREQ = this.index == 0 ? DREQChannel.DREQ_UART0_TX : DREQChannel.DREQ_UART1_TX;
36
33
  }
37
34
  get enabled() {
38
35
  return !!(this.ctrlRegister & UARTEN);
@@ -110,10 +107,10 @@ export class RPUART extends BasePeripheral {
110
107
  case UARTCR:
111
108
  this.ctrlRegister = value;
112
109
  if (this.enabled) {
113
- this.rp2040.dma.setDREQ(this.txDREQ);
110
+ this.rp2040.dma.setDREQ(this.dreq.tx);
114
111
  }
115
112
  else {
116
- this.rp2040.dma.clearDREQ(this.txDREQ);
113
+ this.rp2040.dma.clearDREQ(this.dreq.tx);
117
114
  }
118
115
  break;
119
116
  case UARTIMSC:
@@ -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';
@@ -52,11 +52,16 @@ export class RP2040 {
52
52
  this.ppb = new RPPPB(this, 'PPB');
53
53
  this.sio = new RPSIO(this);
54
54
  this.uart = [
55
- new RPUART(this, 'UART0', 0, IRQ.UART0),
56
- new RPUART(this, 'UART1', 1, IRQ.UART1),
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
+ }),
57
63
  ];
58
64
  this.i2c = [new RPI2C(this, 'I2C0', IRQ.I2C0), new RPI2C(this, 'I2C1', IRQ.I2C1)];
59
- this.spi = [new RPSPI(this, 'SPI0', IRQ.SPI0), new RPSPI(this, 'SPI1', IRQ.SPI1)];
60
65
  this.pwm = new RPPWM(this, 'PWM_BASE');
61
66
  this.adc = new RPADC(this, 'ADC');
62
67
  this.gpio = [
@@ -105,6 +110,16 @@ export class RP2040 {
105
110
  new RPPIO(this, 'PIO1', IRQ.PIO1_IRQ0, 1),
106
111
  ];
107
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
+ ];
108
123
  this.stopped = true;
109
124
  this.logger = new ConsoleLogger(LogLevel.Debug, true);
110
125
  this.executeTimer = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rp2040js",
3
- "version": "0.17.16",
3
+ "version": "0.17.17",
4
4
  "description": "Raspberry Pi Pico (RP2040) Emulator",
5
5
  "repository": "https://github.com/wokwi/rp2040js",
6
6
  "keywords": [
@@ -39,7 +39,8 @@
39
39
  "start:micropython": "ts-node demo/micropython-run.ts",
40
40
  "start:circuitpython": "ts-node demo/micropython-run.ts --circuitpython",
41
41
  "start:gdbdiff": "ts-node debug/gdbdiff.ts",
42
- "test": "jest"
42
+ "test": "jest",
43
+ "test:micropython-spi": "ts-node test/micropython-spi-test.ts"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/jest": "^27.4.1",