Skip to content

Commit

Permalink
Merge branch 'ep0utils'
Browse files Browse the repository at this point in the history
  • Loading branch information
mithro committed Nov 21, 2015
2 parents 3590a1d + c665d75 commit 73ff37e
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 14 deletions.
55 changes: 53 additions & 2 deletions include/eputils.h
Expand Up @@ -21,7 +21,10 @@
#ifndef EPUTILS_H
#define EPUTILS_H

#include <assert.h>

#include "fx2types.h"
#include "fx2macros.h"

/**
* NOTE you can't use these unless you define SYNCDELAY
Expand Down Expand Up @@ -80,13 +83,61 @@
**/
void readep0( BYTE* dst, WORD len );


/**
* Write bytes from src to ep0, allowing host to transfer data
* between 64 byte blocks.
**/
void writeep0 ( BYTE* src, WORD len );
void writeep0( BYTE* src, WORD len );

// The Setup Data Pointer can access data in either of two RAM spaces:
// - On-chip Main RAM (8 KB at 0x0000-0x1FFF)
// - On-chip Scratch RAM (512 bytes at 0xE000-0xE1FF)
// The base address of SUDPTRH:L must be word-aligned.
#define ep0_load_sudptr(src) \
assert( \
(((WORD)src) <= 0x3FFF) || \
(((WORD)src) >= 0xE000 && ((WORD)src) <= 0xE1FF)); \
assert(!(LSB(src) & bmBIT0)); \
LOADWORD(SUDPTR, src);

// For manual mode, SUDPTRCTL must be in "auto read length mode".
//
// | Data Read | Data Length | SUDPTRCTL |
// |-------------|-------------|-----------|
// | Auto (0) | Manual (0) | 0|0 = 0 | SUDPTR->EP0BC
// | Manual (1) | Manual (0) | 1|0 = 1 | EP0BUF->EP0BC
// | Auto (0) | Auto (1) | 0|1 = 1 | SUDPTR
// | Manual (1) | Auto (1) | Invalid | NA
enum ep0_mode_data {
EP0_DATA_AUTO = 0,
EP0_DATA_MANUAL = 1,
};
enum ep0_mode_length {
EP0_LENGTH_AUTO = 1,
EP0_LENGTH_MANUAL = 0,
};

#define ep0_mode(mode_data, mode_length) \
assert(!(mode_data & mode_length)); \
SUDPTRCTL = mode_data | mode_length;

#define ep0_busywait() \
while (EP0CS & bmEPBUSY) printf("w\n");

#define ep0_load_length(len) \
LOADWORD(EP0BC, len);

#define ep0_arm() \
ep0_load_length(0);

// ep0 can only receive 64 bytes
#define ep0_get_length() \
EP0BCL

void ep0_send_auto(__xdata BYTE* src, WORD len);
void ep0_send_byte(BYTE data);
void ep0_send_word(WORD data);

BYTE ep0_recv();

#endif
7 changes: 7 additions & 0 deletions include/fx2macros.h
Expand Up @@ -32,6 +32,13 @@
#define LSW(dword) (WORD)(dword & 0xffff)
#define MAKEDWORD(msw,lsw) (((DWORD)msw << 16) | lsw)

/**
* Load a word register (such as the data pointers), high byte then low byte.
*/
#define LOADWORD(reg, value) \
reg ## H = MSB(value); \
reg ## L = LSB(value);

// clock stuff

/**
Expand Down
51 changes: 39 additions & 12 deletions lib/eputils.c
Expand Up @@ -16,9 +16,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**/




#include <eputils.h>

#include <fx2regs.h>
Expand All @@ -33,11 +30,7 @@ void readep0( BYTE* dst, WORD len) {
WORD read = 0; // n bytes read
BYTE c,avail;
while (read < len) {
EP0BCH = 0;
// NOTE need syncdelay?
EP0BCL = 0; // re-arm ep so host can send more
while (EP0CS & bmEPBUSY);
avail = EP0BCL; // max size fits in one byte (64 bytes)
avail = ep0_recv();
for (c=0;c<avail;++c)
dst[read+c] = EP0BUF[c];
read += avail;
Expand All @@ -49,12 +42,46 @@ void writeep0( BYTE* src, WORD len) {
WORD written = 0;
BYTE c;
while ( written < len ) {
while ( EP0CS & bmEPBUSY ); // wait
ep0_busywait();
for (c=0;c<64 && written<len;++c ) {
EP0BUF[c] = src[written++];
}
EP0BCH = 0;
EP0BCL= c;
printf ( "Write %d bytes\n", c );
ep0_load_length(c);
printf("Write %d bytes\n", c);
}
}

void ep0_send_descriptor(__xdata BYTE* src) {
// The ep0_load_length will be read out of the descriptor.
ep0_mode(EP0_DATA_AUTO, EP0_LENGTH_AUTO);
ep0_load_sudptr(src);
}

void ep0_send_auto(__xdata BYTE* src, WORD len) {
ep0_mode(EP0_DATA_AUTO, EP0_LENGTH_MANUAL);
ep0_load_length(len);
ep0_load_sudptr(src);
}

void ep0_send_byte(BYTE data) {
ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
EP0BUF[0] = data;
ep0_load_length(sizeof(data));
}

void ep0_send_word(WORD data) {
ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
EP0BUF[0] = MSB(data);
EP0BUF[1] = LSB(data);
ep0_load_length(sizeof(data));
}

BYTE ep0_recv() {
BYTE len = 0;
ep0_mode(EP0_DATA_MANUAL, EP0_LENGTH_MANUAL);
ep0_arm(); //ep0_load_length(len);
ep0_busywait();
len = ep0_get_length();
// EP0BUF now has the requested data
return len;
}

0 comments on commit 73ff37e

Please sign in to comment.