Skip to content

Commit 37019e4

Browse files
authored
Merge pull request #145 from rivimey/feature/peripheral-registers
Feature: additional peripheral registers
2 parents 543b93a + 730dd17 commit 37019e4

File tree

6 files changed

+276
-10
lines changed

6 files changed

+276
-10
lines changed

src/gpio-pin.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export enum GPIOPinState {
77
Input,
88
InputPullUp,
99
InputPullDown,
10+
InputBusKeeper,
1011
}
1112

1213
export const FUNCTION_PWM = 4;
@@ -186,10 +187,13 @@ export class GPIOPin {
186187
return this.outputValue ? GPIOPinState.High : GPIOPinState.Low;
187188
} else {
188189
// TODO: check what happens when we enable both pullup/pulldown
189-
if (this.pulldownEnabled) {
190+
// ANSWER: It is valid, see: 2.19.4.1. Bus Keeper Mode, datasheet p240
191+
if (this.pulldownEnabled && this.pullupEnabled) {
192+
// Pull high when high, pull low when low:
193+
return GPIOPinState.InputBusKeeper;
194+
} else if (this.pulldownEnabled) {
190195
return GPIOPinState.InputPullDown;
191-
}
192-
if (this.pullupEnabled) {
196+
} else if (this.pullupEnabled) {
193197
return GPIOPinState.InputPullUp;
194198
}
195199
return GPIOPinState.Input;

src/peripherals/clocks.ts

Lines changed: 160 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,198 @@
11
import { RP2040 } from '../rp2040.js';
22
import { BasePeripheral, Peripheral } from './peripheral.js';
33

4+
const CLK_GPOUT0_CTRL = 0x00;
5+
const CLK_GPOUT0_DIV = 0x04;
6+
const CLK_GPOUT0_SELECTED = 0x8;
7+
const CLK_GPOUT1_CTRL = 0x0c;
8+
const CLK_GPOUT1_DIV = 0x10;
9+
const CLK_GPOUT1_SELECTED = 0x14;
10+
const CLK_GPOUT2_CTRL = 0x18;
11+
const CLK_GPOUT2_DIV = 0x01c;
12+
const CLK_GPOUT2_SELECTED = 0x20;
13+
const CLK_GPOUT3_CTRL = 0x24;
14+
const CLK_GPOUT3_DIV = 0x28;
15+
const CLK_GPOUT3_SELECTED = 0x2c;
416
const CLK_REF_CTRL = 0x30;
17+
const CLK_REF_DIV = 0x34;
518
const CLK_REF_SELECTED = 0x38;
619
const CLK_SYS_CTRL = 0x3c;
20+
const CLK_SYS_DIV = 0x40;
721
const CLK_SYS_SELECTED = 0x44;
22+
const CLK_PERI_CTRL = 0x48;
23+
const CLK_PERI_DIV = 0x4c;
24+
const CLK_PERI_SELECTED = 0x50;
25+
const CLK_USB_CTRL = 0x54;
26+
const CLK_USB_DIV = 0x58;
27+
const CLK_USB_SELECTED = 0x5c;
28+
const CLK_ADC_CTRL = 0x60;
29+
const CLK_ADC_DIV = 0x64;
30+
const CLK_ADC_SELECTED = 0x68;
31+
const CLK_RTC_CTRL = 0x6c;
32+
const CLK_RTC_DIV = 0x70;
33+
const CLK_RTC_SELECTED = 0x74;
34+
const CLK_SYS_RESUS_CTRL = 0x78;
35+
const CLK_SYS_RESUS_STATUS = 0x7c;
836

937
export class RPClocks extends BasePeripheral implements Peripheral {
38+
gpout0Ctrl = 0;
39+
gpout0Div = 0x100;
40+
gpout1Ctrl = 0;
41+
gpout1Div = 0x100;
42+
gpout2Ctrl = 0;
43+
gpout2Div = 0x100;
44+
gpout3Ctrl = 0;
45+
gpout3Div = 0x100;
1046
refCtrl = 0;
47+
refDiv = 0x100;
48+
periCtrl = 0;
49+
periDiv = 0x100;
50+
usbCtrl = 0;
51+
usbDiv = 0x100;
1152
sysCtrl = 0;
53+
sysDiv = 0x100;
54+
adcCtrl = 0;
55+
adcDiv = 0x100;
56+
rtcCtrl = 0;
57+
rtcDiv = 0x100;
1258
constructor(rp2040: RP2040, name: string) {
1359
super(rp2040, name);
1460
}
1561

1662
readUint32(offset: number) {
1763
switch (offset) {
64+
case CLK_GPOUT0_CTRL:
65+
return this.gpout0Ctrl & 0b100110001110111100000;
66+
case CLK_GPOUT0_DIV:
67+
return this.gpout0Div;
68+
case CLK_GPOUT0_SELECTED:
69+
return 1;
70+
case CLK_GPOUT1_CTRL:
71+
return this.gpout1Ctrl & 0b100110001110111100000;
72+
case CLK_GPOUT1_DIV:
73+
return this.gpout1Div;
74+
case CLK_GPOUT1_SELECTED:
75+
return 1;
76+
case CLK_GPOUT2_CTRL:
77+
return this.gpout2Ctrl & 0b100110001110111100000;
78+
case CLK_GPOUT2_DIV:
79+
return this.gpout2Div;
80+
case CLK_GPOUT2_SELECTED:
81+
return 1;
82+
case CLK_GPOUT3_CTRL:
83+
return this.gpout3Ctrl & 0b100110001110111100000;
84+
case CLK_GPOUT3_DIV:
85+
return this.gpout3Div;
86+
case CLK_GPOUT3_SELECTED:
87+
return 1;
1888
case CLK_REF_CTRL:
19-
return this.refCtrl;
89+
return this.refCtrl & 0b000001100011;
90+
case CLK_REF_DIV:
91+
return this.refDiv & 0x30; // b8..9 = int divisor. no frac divisor present
2092
case CLK_REF_SELECTED:
2193
return 1 << (this.refCtrl & 0x03);
2294
case CLK_SYS_CTRL:
23-
return this.sysCtrl;
95+
return this.sysCtrl & 0b000011100001;
96+
case CLK_SYS_DIV:
97+
return this.sysDiv;
2498
case CLK_SYS_SELECTED:
2599
return 1 << (this.sysCtrl & 0x01);
100+
case CLK_PERI_CTRL:
101+
return this.periCtrl & 0b110011100000;
102+
case CLK_PERI_DIV:
103+
return this.periDiv;
104+
case CLK_PERI_SELECTED:
105+
return 1;
106+
case CLK_USB_CTRL:
107+
return this.usbCtrl & 0b100110000110011100000;
108+
case CLK_USB_DIV:
109+
return this.usbDiv;
110+
case CLK_USB_SELECTED:
111+
return 1;
112+
case CLK_ADC_CTRL:
113+
return this.adcCtrl & 0b100110000110011100000;
114+
case CLK_ADC_DIV:
115+
return this.adcDiv & 0x30;
116+
case CLK_ADC_SELECTED:
117+
return 1;
118+
case CLK_RTC_CTRL:
119+
return this.rtcCtrl & 0b100110000110011100000;
120+
case CLK_RTC_DIV:
121+
return this.rtcDiv & 0x30;
122+
case CLK_RTC_SELECTED:
123+
return 1;
124+
case CLK_SYS_RESUS_CTRL:
125+
return 0xff;
126+
case CLK_SYS_RESUS_STATUS:
127+
return 0; /* clock resus not implemented */
26128
}
27129
return super.readUint32(offset);
28130
}
29131

30132
writeUint32(offset: number, value: number): void {
31133
switch (offset) {
134+
case CLK_GPOUT0_CTRL:
135+
this.gpout0Ctrl = value;
136+
break;
137+
case CLK_GPOUT0_DIV:
138+
this.gpout0Div = value;
139+
break;
140+
case CLK_GPOUT1_CTRL:
141+
this.gpout1Ctrl = value;
142+
break;
143+
case CLK_GPOUT1_DIV:
144+
this.gpout1Div = value;
145+
break;
146+
case CLK_GPOUT2_CTRL:
147+
this.gpout2Ctrl = value;
148+
break;
149+
case CLK_GPOUT2_DIV:
150+
this.gpout2Div = value;
151+
break;
152+
case CLK_GPOUT3_CTRL:
153+
this.gpout3Ctrl = value;
154+
break;
155+
case CLK_GPOUT3_DIV:
156+
this.gpout3Div = value;
157+
break;
32158
case CLK_REF_CTRL:
33159
this.refCtrl = value;
34160
break;
161+
case CLK_REF_DIV:
162+
this.refDiv = value;
163+
break;
35164
case CLK_SYS_CTRL:
36165
this.sysCtrl = value;
37166
break;
167+
case CLK_SYS_DIV:
168+
this.sysDiv = value;
169+
break;
170+
case CLK_PERI_CTRL:
171+
this.periCtrl = value;
172+
break;
173+
case CLK_PERI_DIV:
174+
this.periDiv = value;
175+
break;
176+
case CLK_USB_CTRL:
177+
this.usbCtrl = value;
178+
break;
179+
case CLK_USB_DIV:
180+
this.usbDiv = value;
181+
break;
182+
case CLK_ADC_CTRL:
183+
this.adcCtrl = value;
184+
break;
185+
case CLK_ADC_DIV:
186+
this.adcDiv = value;
187+
break;
188+
case CLK_RTC_CTRL:
189+
this.rtcCtrl = value;
190+
break;
191+
case CLK_RTC_DIV:
192+
this.rtcDiv = value;
193+
break;
194+
case CLK_SYS_RESUS_CTRL:
195+
return; /* clock resus not implemented */
38196
default:
39197
super.writeUint32(offset, value);
40198
break;

src/peripherals/i2c.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export class RPI2C extends BasePeripheral implements Peripheral {
171171
abortSource = 0;
172172
intRaw = 0;
173173
intEnable = 0;
174+
private spikelen = 0x07;
174175

175176
get intStatus() {
176177
return this.intRaw & this.intEnable;
@@ -428,11 +429,18 @@ export class RPI2C extends BasePeripheral implements Peripheral {
428429
return this.txFIFO.itemCount;
429430
case IC_RXFLR:
430431
return this.rxFIFO.itemCount;
432+
case IC_SDA_HOLD:
433+
return 0x01;
431434
case IC_TX_ABRT_SOURCE: {
432435
const value = this.abortSource;
433436
this.abortSource &= ABRT_SBYTE_NORSTRT; // Clear IC_TX_ABRT_SOURCE, expect for bit 9
434437
return value;
435438
}
439+
case IC_ENABLE_STATUS:
440+
// I2C status - read only. bit 0 reflects IC_ENABLE, bit 1,2 relate to i2c slave mode.
441+
return this.enable & 0x1;
442+
case IC_FS_SPKLEN:
443+
return this.spikelen & 0xff;
436444
case IC_COMP_PARAM_1:
437445
// From the datasheet:
438446
// Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only
@@ -489,6 +497,14 @@ export class RPI2C extends BasePeripheral implements Peripheral {
489497
this.fsClockLowPeriod = value & 0xffff;
490498
return;
491499

500+
case IC_SDA_HOLD:
501+
if (!(value & ENABLE)) {
502+
if (value != 0x1) {
503+
this.warn('Unimplemented write to IC_SDA_HOLD');
504+
}
505+
}
506+
return;
507+
492508
case IC_RX_TL:
493509
this.rxThreshold = value & 0xff;
494510
if (this.rxThreshold > this.rxFIFO.size) {
@@ -522,6 +538,12 @@ export class RPI2C extends BasePeripheral implements Peripheral {
522538
this.nextCommand(); // TX_CMD_BLOCK may have changed
523539
return;
524540

541+
case IC_FS_SPKLEN:
542+
if (!(value & ENABLE) && value > 0) {
543+
this.spikelen = value;
544+
}
545+
return;
546+
525547
default:
526548
super.writeUint32(offset, value);
527549
}

src/peripherals/peripheral.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@ export class BasePeripheral implements Peripheral {
3434
) {}
3535

3636
readUint32(offset: number) {
37-
this.warn(`Unimplemented peripheral read from ${offset.toString(16)}`);
37+
this.warn(`Unimplemented peripheral read from 0x${offset.toString(16)}`);
3838
if (offset > 0x1000) {
3939
this.warn('Unimplemented read from peripheral in the atomic operation region');
4040
}
4141
return 0xffffffff;
4242
}
4343

4444
writeUint32(offset: number, value: number) {
45-
this.warn(`Unimplemented peripheral write to ${offset.toString(16)}: ${value}`);
45+
this.warn(
46+
`Unimplemented peripheral write to 0x${offset.toString(16)}: 0x${value.toString(16)}`,
47+
);
4648
}
4749

4850
writeUint32Atomic(offset: number, value: number, atomicType: number) {

0 commit comments

Comments
 (0)