rp2040js 1.1.1 → 1.2.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.
- package/README.md +3 -1
- package/dist/cjs/peripherals/xosc.d.ts +13 -0
- package/dist/cjs/peripherals/xosc.js +123 -0
- package/dist/cjs/rp2040.js +2 -1
- package/dist/esm/peripherals/xosc.d.ts +13 -0
- package/dist/esm/peripherals/xosc.js +119 -0
- package/dist/esm/rp2040.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
  
|
|
2
|
+
|
|
1
3
|
# rp2040js
|
|
2
4
|
|
|
3
5
|
Raspberry Pi Pico Emulator for the [Wokwi Simulation Platform](https://wokwi.com). It blinks, runs Arduino code, and even the MicroPython REPL!
|
|
@@ -58,7 +60,7 @@ A GDB server on port 3333 can be enabled by specifying the `--gdb` flag:
|
|
|
58
60
|
npm run start:micropython -- --gdb
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
For using the MicroPython demo code in tests, the `--expect-text` can come handy: it will look for the given text in the serial output and exit with code 0 if found, or 1 if not found. You can find an example in [the MicroPython CI test](
|
|
63
|
+
For using the MicroPython demo code in tests, the `--expect-text` can come handy: it will look for the given text in the serial output and exit with code 0 if found, or 1 if not found. You can find an example in [the MicroPython CI test](./.github/workflows/ci-micropython.yml).
|
|
62
64
|
|
|
63
65
|
#### Filesystem support
|
|
64
66
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BasePeripheral, Peripheral } from './peripheral.js';
|
|
2
|
+
export declare class RPXOSC extends BasePeripheral implements Peripheral {
|
|
3
|
+
private ctrl;
|
|
4
|
+
private status;
|
|
5
|
+
private dormant;
|
|
6
|
+
private startup;
|
|
7
|
+
private count;
|
|
8
|
+
private enabled;
|
|
9
|
+
private stable;
|
|
10
|
+
private isDormant;
|
|
11
|
+
readUint32(offset: number): number;
|
|
12
|
+
writeUint32(offset: number, value: number): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RPXOSC = void 0;
|
|
4
|
+
const peripheral_js_1 = require("./peripheral.js");
|
|
5
|
+
// XOSC register offsets
|
|
6
|
+
const XOSC_CTRL = 0x00;
|
|
7
|
+
const XOSC_STATUS = 0x04;
|
|
8
|
+
const XOSC_DORMANT = 0x08;
|
|
9
|
+
const XOSC_STARTUP = 0x0c;
|
|
10
|
+
const XOSC_COUNT = 0x1c;
|
|
11
|
+
// CTRL register bits
|
|
12
|
+
const CTRL_ENABLE_LSB = 12;
|
|
13
|
+
const CTRL_ENABLE_BITS = 0x00fff000;
|
|
14
|
+
const CTRL_FREQ_RANGE_BITS = 0x00000fff;
|
|
15
|
+
// CTRL ENABLE values
|
|
16
|
+
const CTRL_ENABLE_DISABLE = 0xd1e;
|
|
17
|
+
const CTRL_ENABLE_ENABLE = 0xfab;
|
|
18
|
+
// STATUS register bits
|
|
19
|
+
const STATUS_STABLE = 0x80000000; // bit 31
|
|
20
|
+
const STATUS_BADWRITE = 0x01000000; // bit 24
|
|
21
|
+
const STATUS_ENABLED = 0x00001000; // bit 12
|
|
22
|
+
const STATUS_FREQ_RANGE_BITS = 0x00000003;
|
|
23
|
+
// DORMANT register values
|
|
24
|
+
const DORMANT_VALUE = 0x636f6d61; // "coma" in ASCII
|
|
25
|
+
const WAKE_VALUE = 0x77616b65; // "wake" in ASCII
|
|
26
|
+
// STARTUP register bits
|
|
27
|
+
const STARTUP_X4 = 0x00100000; // bit 20
|
|
28
|
+
const STARTUP_DELAY_BITS = 0x00003fff;
|
|
29
|
+
class RPXOSC extends peripheral_js_1.BasePeripheral {
|
|
30
|
+
constructor() {
|
|
31
|
+
super(...arguments);
|
|
32
|
+
this.ctrl = 0;
|
|
33
|
+
this.status = 0;
|
|
34
|
+
this.dormant = 0;
|
|
35
|
+
this.startup = 0;
|
|
36
|
+
this.count = 0;
|
|
37
|
+
this.enabled = false;
|
|
38
|
+
this.stable = false;
|
|
39
|
+
this.isDormant = false;
|
|
40
|
+
}
|
|
41
|
+
readUint32(offset) {
|
|
42
|
+
switch (offset) {
|
|
43
|
+
case XOSC_CTRL:
|
|
44
|
+
return this.ctrl;
|
|
45
|
+
case XOSC_STATUS: {
|
|
46
|
+
let status = this.status;
|
|
47
|
+
if (this.stable) {
|
|
48
|
+
status |= STATUS_STABLE;
|
|
49
|
+
}
|
|
50
|
+
if (this.enabled) {
|
|
51
|
+
status |= STATUS_ENABLED;
|
|
52
|
+
}
|
|
53
|
+
return status;
|
|
54
|
+
}
|
|
55
|
+
case XOSC_DORMANT:
|
|
56
|
+
return this.dormant;
|
|
57
|
+
case XOSC_STARTUP:
|
|
58
|
+
return this.startup;
|
|
59
|
+
case XOSC_COUNT:
|
|
60
|
+
return this.count;
|
|
61
|
+
}
|
|
62
|
+
return super.readUint32(offset);
|
|
63
|
+
}
|
|
64
|
+
writeUint32(offset, value) {
|
|
65
|
+
switch (offset) {
|
|
66
|
+
case XOSC_CTRL: {
|
|
67
|
+
this.ctrl = value;
|
|
68
|
+
const enableValue = (value & CTRL_ENABLE_BITS) >>> CTRL_ENABLE_LSB;
|
|
69
|
+
const freqRange = value & CTRL_FREQ_RANGE_BITS;
|
|
70
|
+
void freqRange; // Currently unused, but could be logged or validated
|
|
71
|
+
if (enableValue === CTRL_ENABLE_ENABLE) {
|
|
72
|
+
if (!this.isDormant) {
|
|
73
|
+
this.enabled = true;
|
|
74
|
+
// For simplicity, become stable immediately
|
|
75
|
+
// In real hardware, this would take time based on STARTUP register
|
|
76
|
+
this.stable = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (enableValue === CTRL_ENABLE_DISABLE) {
|
|
80
|
+
this.enabled = false;
|
|
81
|
+
this.stable = false;
|
|
82
|
+
}
|
|
83
|
+
else if (enableValue !== 0) {
|
|
84
|
+
// Invalid write to ENABLE field
|
|
85
|
+
this.status |= STATUS_BADWRITE;
|
|
86
|
+
this.warn(`Invalid ENABLE value written: 0x${enableValue.toString(16)}`);
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case XOSC_STATUS:
|
|
91
|
+
// Clear BADWRITE bit if written as 1 (write-1-to-clear)
|
|
92
|
+
if (value & STATUS_BADWRITE) {
|
|
93
|
+
this.status &= ~STATUS_BADWRITE;
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case XOSC_DORMANT:
|
|
97
|
+
if (value === DORMANT_VALUE) {
|
|
98
|
+
this.isDormant = true;
|
|
99
|
+
this.stable = false;
|
|
100
|
+
}
|
|
101
|
+
else if (value === WAKE_VALUE) {
|
|
102
|
+
this.isDormant = false;
|
|
103
|
+
if (this.enabled) {
|
|
104
|
+
this.stable = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.dormant = value;
|
|
108
|
+
break;
|
|
109
|
+
case XOSC_STARTUP:
|
|
110
|
+
this.startup = value & (STARTUP_X4 | STARTUP_DELAY_BITS);
|
|
111
|
+
break;
|
|
112
|
+
case XOSC_COUNT:
|
|
113
|
+
// Writing to COUNT starts the countdown
|
|
114
|
+
this.count = value & 0xff;
|
|
115
|
+
// For simplicity, we don't actually implement the countdown
|
|
116
|
+
// In real hardware, this would decrement at the XOSC frequency
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
super.writeUint32(offset, value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.RPXOSC = RPXOSC;
|
package/dist/cjs/rp2040.js
CHANGED
|
@@ -27,6 +27,7 @@ const timer_js_1 = require("./peripherals/timer.js");
|
|
|
27
27
|
const uart_js_1 = require("./peripherals/uart.js");
|
|
28
28
|
const usb_js_1 = require("./peripherals/usb.js");
|
|
29
29
|
const watchdog_js_1 = require("./peripherals/watchdog.js");
|
|
30
|
+
const xosc_js_1 = require("./peripherals/xosc.js");
|
|
30
31
|
const sio_js_1 = require("./sio.js");
|
|
31
32
|
const logging_js_1 = require("./utils/logging.js");
|
|
32
33
|
exports.FLASH_START_ADDRESS = 0x10000000;
|
|
@@ -137,7 +138,7 @@ class RP2040 {
|
|
|
137
138
|
0x40018: new peripheral_js_1.UnimplementedPeripheral(this, 'IO_QSPI_BASE'),
|
|
138
139
|
0x4001c: new pads_js_1.RPPADS(this, 'PADS_BANK0_BASE', 'bank0'),
|
|
139
140
|
0x40020: new pads_js_1.RPPADS(this, 'PADS_QSPI_BASE', 'qspi'),
|
|
140
|
-
0x40024: new
|
|
141
|
+
0x40024: new xosc_js_1.RPXOSC(this, 'XOSC_BASE'),
|
|
141
142
|
0x40028: new peripheral_js_1.UnimplementedPeripheral(this, 'PLL_SYS_BASE'),
|
|
142
143
|
0x4002c: new peripheral_js_1.UnimplementedPeripheral(this, 'PLL_USB_BASE'),
|
|
143
144
|
0x40030: new busctrl_js_1.RPBUSCTRL(this, 'BUSCTRL_BASE'),
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BasePeripheral, Peripheral } from './peripheral.js';
|
|
2
|
+
export declare class RPXOSC extends BasePeripheral implements Peripheral {
|
|
3
|
+
private ctrl;
|
|
4
|
+
private status;
|
|
5
|
+
private dormant;
|
|
6
|
+
private startup;
|
|
7
|
+
private count;
|
|
8
|
+
private enabled;
|
|
9
|
+
private stable;
|
|
10
|
+
private isDormant;
|
|
11
|
+
readUint32(offset: number): number;
|
|
12
|
+
writeUint32(offset: number, value: number): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { BasePeripheral } from './peripheral.js';
|
|
2
|
+
// XOSC register offsets
|
|
3
|
+
const XOSC_CTRL = 0x00;
|
|
4
|
+
const XOSC_STATUS = 0x04;
|
|
5
|
+
const XOSC_DORMANT = 0x08;
|
|
6
|
+
const XOSC_STARTUP = 0x0c;
|
|
7
|
+
const XOSC_COUNT = 0x1c;
|
|
8
|
+
// CTRL register bits
|
|
9
|
+
const CTRL_ENABLE_LSB = 12;
|
|
10
|
+
const CTRL_ENABLE_BITS = 0x00fff000;
|
|
11
|
+
const CTRL_FREQ_RANGE_BITS = 0x00000fff;
|
|
12
|
+
// CTRL ENABLE values
|
|
13
|
+
const CTRL_ENABLE_DISABLE = 0xd1e;
|
|
14
|
+
const CTRL_ENABLE_ENABLE = 0xfab;
|
|
15
|
+
// STATUS register bits
|
|
16
|
+
const STATUS_STABLE = 0x80000000; // bit 31
|
|
17
|
+
const STATUS_BADWRITE = 0x01000000; // bit 24
|
|
18
|
+
const STATUS_ENABLED = 0x00001000; // bit 12
|
|
19
|
+
const STATUS_FREQ_RANGE_BITS = 0x00000003;
|
|
20
|
+
// DORMANT register values
|
|
21
|
+
const DORMANT_VALUE = 0x636f6d61; // "coma" in ASCII
|
|
22
|
+
const WAKE_VALUE = 0x77616b65; // "wake" in ASCII
|
|
23
|
+
// STARTUP register bits
|
|
24
|
+
const STARTUP_X4 = 0x00100000; // bit 20
|
|
25
|
+
const STARTUP_DELAY_BITS = 0x00003fff;
|
|
26
|
+
export class RPXOSC extends BasePeripheral {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
this.ctrl = 0;
|
|
30
|
+
this.status = 0;
|
|
31
|
+
this.dormant = 0;
|
|
32
|
+
this.startup = 0;
|
|
33
|
+
this.count = 0;
|
|
34
|
+
this.enabled = false;
|
|
35
|
+
this.stable = false;
|
|
36
|
+
this.isDormant = false;
|
|
37
|
+
}
|
|
38
|
+
readUint32(offset) {
|
|
39
|
+
switch (offset) {
|
|
40
|
+
case XOSC_CTRL:
|
|
41
|
+
return this.ctrl;
|
|
42
|
+
case XOSC_STATUS: {
|
|
43
|
+
let status = this.status;
|
|
44
|
+
if (this.stable) {
|
|
45
|
+
status |= STATUS_STABLE;
|
|
46
|
+
}
|
|
47
|
+
if (this.enabled) {
|
|
48
|
+
status |= STATUS_ENABLED;
|
|
49
|
+
}
|
|
50
|
+
return status;
|
|
51
|
+
}
|
|
52
|
+
case XOSC_DORMANT:
|
|
53
|
+
return this.dormant;
|
|
54
|
+
case XOSC_STARTUP:
|
|
55
|
+
return this.startup;
|
|
56
|
+
case XOSC_COUNT:
|
|
57
|
+
return this.count;
|
|
58
|
+
}
|
|
59
|
+
return super.readUint32(offset);
|
|
60
|
+
}
|
|
61
|
+
writeUint32(offset, value) {
|
|
62
|
+
switch (offset) {
|
|
63
|
+
case XOSC_CTRL: {
|
|
64
|
+
this.ctrl = value;
|
|
65
|
+
const enableValue = (value & CTRL_ENABLE_BITS) >>> CTRL_ENABLE_LSB;
|
|
66
|
+
const freqRange = value & CTRL_FREQ_RANGE_BITS;
|
|
67
|
+
void freqRange; // Currently unused, but could be logged or validated
|
|
68
|
+
if (enableValue === CTRL_ENABLE_ENABLE) {
|
|
69
|
+
if (!this.isDormant) {
|
|
70
|
+
this.enabled = true;
|
|
71
|
+
// For simplicity, become stable immediately
|
|
72
|
+
// In real hardware, this would take time based on STARTUP register
|
|
73
|
+
this.stable = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (enableValue === CTRL_ENABLE_DISABLE) {
|
|
77
|
+
this.enabled = false;
|
|
78
|
+
this.stable = false;
|
|
79
|
+
}
|
|
80
|
+
else if (enableValue !== 0) {
|
|
81
|
+
// Invalid write to ENABLE field
|
|
82
|
+
this.status |= STATUS_BADWRITE;
|
|
83
|
+
this.warn(`Invalid ENABLE value written: 0x${enableValue.toString(16)}`);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case XOSC_STATUS:
|
|
88
|
+
// Clear BADWRITE bit if written as 1 (write-1-to-clear)
|
|
89
|
+
if (value & STATUS_BADWRITE) {
|
|
90
|
+
this.status &= ~STATUS_BADWRITE;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case XOSC_DORMANT:
|
|
94
|
+
if (value === DORMANT_VALUE) {
|
|
95
|
+
this.isDormant = true;
|
|
96
|
+
this.stable = false;
|
|
97
|
+
}
|
|
98
|
+
else if (value === WAKE_VALUE) {
|
|
99
|
+
this.isDormant = false;
|
|
100
|
+
if (this.enabled) {
|
|
101
|
+
this.stable = true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
this.dormant = value;
|
|
105
|
+
break;
|
|
106
|
+
case XOSC_STARTUP:
|
|
107
|
+
this.startup = value & (STARTUP_X4 | STARTUP_DELAY_BITS);
|
|
108
|
+
break;
|
|
109
|
+
case XOSC_COUNT:
|
|
110
|
+
// Writing to COUNT starts the countdown
|
|
111
|
+
this.count = value & 0xff;
|
|
112
|
+
// For simplicity, we don't actually implement the countdown
|
|
113
|
+
// In real hardware, this would decrement at the XOSC frequency
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
super.writeUint32(offset, value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
package/dist/esm/rp2040.js
CHANGED
|
@@ -24,6 +24,7 @@ import { RPTimer } from './peripherals/timer.js';
|
|
|
24
24
|
import { RPUART } from './peripherals/uart.js';
|
|
25
25
|
import { RPUSBController } from './peripherals/usb.js';
|
|
26
26
|
import { RPWatchdog } from './peripherals/watchdog.js';
|
|
27
|
+
import { RPXOSC } from './peripherals/xosc.js';
|
|
27
28
|
import { RPSIO } from './sio.js';
|
|
28
29
|
import { ConsoleLogger, LogLevel } from './utils/logging.js';
|
|
29
30
|
export const FLASH_START_ADDRESS = 0x10000000;
|
|
@@ -134,7 +135,7 @@ export class RP2040 {
|
|
|
134
135
|
0x40018: new UnimplementedPeripheral(this, 'IO_QSPI_BASE'),
|
|
135
136
|
0x4001c: new RPPADS(this, 'PADS_BANK0_BASE', 'bank0'),
|
|
136
137
|
0x40020: new RPPADS(this, 'PADS_QSPI_BASE', 'qspi'),
|
|
137
|
-
0x40024: new
|
|
138
|
+
0x40024: new RPXOSC(this, 'XOSC_BASE'),
|
|
138
139
|
0x40028: new UnimplementedPeripheral(this, 'PLL_SYS_BASE'),
|
|
139
140
|
0x4002c: new UnimplementedPeripheral(this, 'PLL_USB_BASE'),
|
|
140
141
|
0x40030: new RPBUSCTRL(this, 'BUSCTRL_BASE'),
|