Skip to content

Commit 9f24bbe

Browse files
committed
USB: Added an OUT EP handler with double buffering.
1 parent b2ddb22 commit 9f24bbe

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

cores/arduino/USB/USBCore.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,138 @@ class EPHandler {
5353
virtual uint32_t available() const = 0;
5454
};
5555

56+
class DoubleBufferedEPOutHandler : public EPHandler {
57+
public:
58+
DoubleBufferedEPOutHandler(uint32_t endPoint, uint32_t bufferSize) :
59+
ep(endPoint), size(bufferSize),
60+
current(0), incoming(0),
61+
first0(0), last0(0), ready0(false),
62+
first1(0), last1(0), ready1(false),
63+
notify(false)
64+
{
65+
data0 = reinterpret_cast<uint8_t *>(malloc(size));
66+
data1 = reinterpret_cast<uint8_t *>(malloc(size));
67+
68+
usbd.epBank0SetSize(ep, 64);
69+
usbd.epBank0SetType(ep, 3); // BULK OUT
70+
71+
release();
72+
}
73+
74+
// Read one byte from the buffer, if the buffer is empty -1 is returned
75+
int read() {
76+
if (current == 0) {
77+
if (!ready0) {
78+
return -1;
79+
}
80+
if (first0 == last0) {
81+
first0 = 0;
82+
last0 = 0;
83+
ready0 = false;
84+
if (notify) {
85+
release();
86+
}
87+
current = 1;
88+
return -1;
89+
}
90+
return data0[first0++];
91+
} else {
92+
if (!ready1) {
93+
return -1;
94+
}
95+
if (first1 == last1) {
96+
first1 = 0;
97+
last1 = 0;
98+
ready1 = false;
99+
if (notify) {
100+
release();
101+
}
102+
current = 0;
103+
return -1;
104+
}
105+
return data1[first1++];
106+
}
107+
}
108+
109+
virtual void handleEndpoint()
110+
{
111+
if (usbd.epBank0IsTransferComplete(ep))
112+
{
113+
// Ack Transfer complete
114+
usbd.epBank0AckTransferComplete(ep);
115+
116+
// Update counters and swap banks
117+
if (incoming == 0) {
118+
last0 = usbd.epBank0ByteCount(ep);
119+
ready0 = true;
120+
incoming = 1;
121+
} else {
122+
last1 = usbd.epBank0ByteCount(ep);
123+
ready1 = true;
124+
incoming = 0;
125+
}
126+
release();
127+
}
128+
}
129+
130+
virtual uint32_t recv(void *_data, uint32_t len)
131+
{
132+
uint8_t *data = reinterpret_cast<uint8_t *>(_data);
133+
uint32_t i;
134+
for (i=0; i<len; i++) {
135+
int c = read();
136+
if (c == -1) break;
137+
data[i] = c;
138+
}
139+
return i;
140+
}
141+
142+
// Returns how many bytes are stored in the buffers
143+
virtual uint32_t available() const {
144+
return (last0 - first0) + (last1 - first1);
145+
}
146+
147+
void release() {
148+
if (incoming == 0) {
149+
if (ready0) {
150+
notify = true;
151+
return;
152+
}
153+
usbd.epBank0SetAddress(ep, data0);
154+
} else {
155+
if (ready1) {
156+
notify = true;
157+
return;
158+
}
159+
usbd.epBank0SetAddress(ep, data1);
160+
}
161+
usbd.epBank0AckTransferComplete(ep);
162+
//usbd.epBank0AckTransferFailed(ep);
163+
usbd.epBank0EnableTransferComplete(ep);
164+
165+
// Release OUT EP
166+
usbd.epBank0SetMultiPacketSize(ep, size);
167+
usbd.epBank0SetByteCount(ep, 0);
168+
usbd.epBank0ResetReady(ep);
169+
notify = false;
170+
}
171+
172+
private:
173+
const uint32_t ep;
174+
const uint32_t size;
175+
uint32_t current, incoming;
176+
177+
uint8_t *data0;
178+
uint32_t first0, last0;
179+
bool ready0;
180+
181+
uint8_t *data1;
182+
uint32_t first1, last1;
183+
bool ready1;
184+
185+
bool notify;
186+
};
187+
56188

57189
const uint16_t STRING_LANGUAGE[2] = {
58190
(3<<8) | (2+2),

0 commit comments

Comments
 (0)