Skip to content

Commit 9d69bc0

Browse files
committed
fix(usb): add read delay, improved CDC latency
New CDC behavior: when the code reads data from CDC and the Tx FIFO is empty, we just return an empty buffer instead of waiting until there's some data to send. Otherwise, this causes output latency in CircuitPython. Also, tested it against the hardware and it seem to be sending empty buffers when there's nothing to send over CDC, matching the new behavior.
1 parent 3c7c5c7 commit 9d69bc0

File tree

2 files changed

+16
-21
lines changed

2 files changed

+16
-21
lines changed

src/peripherals/usb.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export class RPUSBController extends BasePeripheral {
8787
onEndpointWrite?: (endpoint: number, buffer: Uint8Array) => void;
8888
onEndpointRead?: (endpoint: number, byteCount: number) => void;
8989

90+
readDelayMicroseconds = 1;
9091
writeDelayMicroseconds = 1;
9192

9293
get intStatus() {
@@ -197,7 +198,17 @@ export class RPUSBController extends BasePeripheral {
197198
}
198199
}
199200

200-
endpointReadDone(endpoint: number, buffer: Uint8Array) {
201+
endpointReadDone(endpoint: number, buffer: Uint8Array, delay = this.readDelayMicroseconds) {
202+
if (delay) {
203+
this.rp2040.clock.createTimer(delay, () => {
204+
this.finishRead(endpoint, buffer);
205+
});
206+
} else {
207+
this.finishRead(endpoint, buffer);
208+
}
209+
}
210+
211+
private finishRead(endpoint: number, buffer: Uint8Array) {
201212
const bufferOffset = this.getEndpointBufferOffset(endpoint, true);
202213
const bufControlReg = EP0_OUT_BUFFER_CONTROL + endpoint * 8;
203214
let bufControl = this.rp2040.usbDPRAMView.getUint32(bufControlReg, true);

src/usb/cdc.ts

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ export class USBCDC {
6767
private descriptors: number[] = [];
6868
private outEndpoint = -1;
6969
private inEndpoint = -1;
70-
private deviceWaitingForData = false;
71-
private outBufferSize = 0;
7270

7371
constructor(readonly usb: RPUSBController) {
7472
this.usb.onUSBEnabled = () => {
@@ -118,28 +116,15 @@ export class USBCDC {
118116
};
119117
this.usb.onEndpointRead = (endpoint, size) => {
120118
if (endpoint === this.outEndpoint) {
121-
this.deviceWaitingForData = true;
122-
this.outBufferSize = size;
123-
if (!this.txFIFO.empty) {
124-
this.sendDataToDevice();
119+
const buffer = new Uint8Array(Math.min(size, this.txFIFO.itemCount));
120+
for (let i = 0; i < buffer.length; i++) {
121+
buffer[i] = this.txFIFO.pull();
125122
}
123+
this.usb.endpointReadDone(this.outEndpoint, buffer);
126124
}
127125
};
128126
}
129127

130-
protected sendDataToDevice() {
131-
if (!this.deviceWaitingForData) {
132-
return;
133-
}
134-
135-
const buffer = new Uint8Array(Math.min(this.outBufferSize, this.txFIFO.itemCount));
136-
for (let i = 0; i < buffer.length; i++) {
137-
buffer[i] = this.txFIFO.pull();
138-
}
139-
this.usb.endpointReadDone(this.outEndpoint, buffer);
140-
this.deviceWaitingForData = false;
141-
}
142-
143128
private cdcSetControlLineState(value = CDC_DTR | CDC_RTS, interfaceNumber = 0) {
144129
this.usb.sendSetupPacket(
145130
createSetupPacket({
@@ -157,6 +142,5 @@ export class USBCDC {
157142

158143
sendSerialByte(data: number) {
159144
this.txFIFO.push(data);
160-
this.sendDataToDevice();
161145
}
162146
}

0 commit comments

Comments
 (0)