Skip to content

Commit 73ff37e

Browse files
committed
Merge branch 'ep0utils'
2 parents 3590a1d + c665d75 commit 73ff37e

3 files changed

Lines changed: 99 additions & 14 deletions

File tree

include/eputils.h

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
#ifndef EPUTILS_H
2222
#define EPUTILS_H
2323

24+
#include <assert.h>
25+
2426
#include "fx2types.h"
27+
#include "fx2macros.h"
2528

2629
/**
2730
* NOTE you can't use these unless you define SYNCDELAY
@@ -80,13 +83,61 @@
8083
**/
8184
void readep0( BYTE* dst, WORD len );
8285

83-
8486
/**
8587
* Write bytes from src to ep0, allowing host to transfer data
8688
* between 64 byte blocks.
8789
**/
88-
void writeep0 ( BYTE* src, WORD len );
90+
void writeep0( BYTE* src, WORD len );
91+
92+
// The Setup Data Pointer can access data in either of two RAM spaces:
93+
// - On-chip Main RAM (8 KB at 0x0000-0x1FFF)
94+
// - On-chip Scratch RAM (512 bytes at 0xE000-0xE1FF)
95+
// The base address of SUDPTRH:L must be word-aligned.
96+
#define ep0_load_sudptr(src) \
97+
assert( \
98+
(((WORD)src) <= 0x3FFF) || \
99+
(((WORD)src) >= 0xE000 && ((WORD)src) <= 0xE1FF)); \
100+
assert(!(LSB(src) & bmBIT0)); \
101+
LOADWORD(SUDPTR, src);
102+
103+
// For manual mode, SUDPTRCTL must be in "auto read length mode".
104+
//
105+
// | Data Read | Data Length | SUDPTRCTL |
106+
// |-------------|-------------|-----------|
107+
// | Auto (0) | Manual (0) | 0|0 = 0 | SUDPTR->EP0BC
108+
// | Manual (1) | Manual (0) | 1|0 = 1 | EP0BUF->EP0BC
109+
// | Auto (0) | Auto (1) | 0|1 = 1 | SUDPTR
110+
// | Manual (1) | Auto (1) | Invalid | NA
111+
enum ep0_mode_data {
112+
EP0_DATA_AUTO = 0,
113+
EP0_DATA_MANUAL = 1,
114+
};
115+
enum ep0_mode_length {
116+
EP0_LENGTH_AUTO = 1,
117+
EP0_LENGTH_MANUAL = 0,
118+
};
119+
120+
#define ep0_mode(mode_data, mode_length) \
121+
assert(!(mode_data & mode_length)); \
122+
SUDPTRCTL = mode_data | mode_length;
123+
124+
#define ep0_busywait() \
125+
while (EP0CS & bmEPBUSY) printf("w\n");
126+
127+
#define ep0_load_length(len) \
128+
LOADWORD(EP0BC, len);
129+
130+
#define ep0_arm() \
131+
ep0_load_length(0);
132+
133+
// ep0 can only receive 64 bytes
134+
#define ep0_get_length() \
135+
EP0BCL
89136

137+
void ep0_send_auto(__xdata BYTE* src, WORD len);
138+
void ep0_send_byte(BYTE data);
139+
void ep0_send_word(WORD data);
90140

141+
BYTE ep0_recv();
91142

92143
#endif

include/fx2macros.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@
3232
#define LSW(dword) (WORD)(dword & 0xffff)
3333
#define MAKEDWORD(msw,lsw) (((DWORD)msw << 16) | lsw)
3434

35+
/**
36+
* Load a word register (such as the data pointers), high byte then low byte.
37+
*/
38+
#define LOADWORD(reg, value) \
39+
reg ## H = MSB(value); \
40+
reg ## L = LSB(value);
41+
3542
// clock stuff
3643

3744
/**

lib/eputils.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717
**/
1818

19-
20-
21-
2219
#include <eputils.h>
2320

2421
#include <fx2regs.h>
@@ -33,11 +30,7 @@ void readep0( BYTE* dst, WORD len) {
3330
WORD read = 0; // n bytes read
3431
BYTE c,avail;
3532
while (read < len) {
36-
EP0BCH = 0;
37-
// NOTE need syncdelay?
38-
EP0BCL = 0; // re-arm ep so host can send more
39-
while (EP0CS & bmEPBUSY);
40-
avail = EP0BCL; // max size fits in one byte (64 bytes)
33+
avail = ep0_recv();
4134
for (c=0;c<avail;++c)
4235
dst[read+c] = EP0BUF[c];
4336
read += avail;
@@ -49,12 +42,46 @@ void writeep0( BYTE* src, WORD len) {
4942
WORD written = 0;
5043
BYTE c;
5144
while ( written < len ) {
52-
while ( EP0CS & bmEPBUSY ); // wait
45+
ep0_busywait();
5346
for (c=0;c<64 && written<len;++c ) {
5447
EP0BUF[c] = src[written++];
5548
}
56-
EP0BCH = 0;
57-
EP0BCL= c;
58-
printf ( "Write %d bytes\n", c );
49+
ep0_load_length(c);
50+
printf("Write %d bytes\n", c);
5951
}
6052
}
53+
54+
void ep0_send_descriptor(__xdata BYTE* src) {
55+
// The ep0_load_length will be read out of the descriptor.
56+
ep0_mode(EP0_DATA_AUTO, EP0_LENGTH_AUTO);
57+
ep0_load_sudptr(src);
58+
}
59+
60+
void ep0_send_auto(__xdata BYTE* src, WORD len) {
61+
ep0_mode(EP0_DATA_AUTO, EP0_LENGTH_MANUAL);
62+
ep0_load_length(len);
63+
ep0_load_sudptr(src);
64+
}
65+
66+
void ep0_send_byte(BYTE data) {
67+
ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
68+
EP0BUF[0] = data;
69+
ep0_load_length(sizeof(data));
70+
}
71+
72+
void ep0_send_word(WORD data) {
73+
ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
74+
EP0BUF[0] = MSB(data);
75+
EP0BUF[1] = LSB(data);
76+
ep0_load_length(sizeof(data));
77+
}
78+
79+
BYTE ep0_recv() {
80+
BYTE len = 0;
81+
ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
82+
ep0_arm(); //ep0_load_length(len);
83+
ep0_busywait();
84+
len = ep0_get_length();
85+
// EP0BUF now has the requested data
86+
return len;
87+
}

0 commit comments

Comments
 (0)