Skip to content

Commit

Permalink
Fixed #99 and #89 + #85
Browse files Browse the repository at this point in the history
  • Loading branch information
buu342 committed Mar 26, 2023
1 parent 6c49db9 commit b716f17
Show file tree
Hide file tree
Showing 12 changed files with 346 additions and 60 deletions.
8 changes: 8 additions & 0 deletions Examples/Libdragon/2. USB Read/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ int main(void)
usb_initialize();
usb_write(DATATYPE_TEXT, "Type something into the console!\n", 33+1);

// Because of a bug in the 64Drive firmware, it can sometimes miss out on USB data.
// This happens more often the sooner successive usb_poll calls are made, and since this
// sample doesn't really do anything complex, the time between calls is pretty short.
// As a result, we'll need to increase the poll time to fix this sample for 64Drive users.
// In a proper game, you will likely not need to touch this function.
// It will likely be removed in a future version of a library, once a better USB polling protocl is made.
usb_set_64drive_polltime(50000);

// Run in a loop
while (1)
{
Expand Down
58 changes: 46 additions & 12 deletions Examples/Libultra/1. Hello World/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ using UNFLoader.

// How many cycles for the 64Drive to wait for data.
// Lowering this might improve performance slightly faster at the expense of USB reading accuracy
#define D64_POLLTIME 2000
#define D64_DEFAULTPOLLTIME 2000

// Cartridge Interface definitions. Obtained from 64Drive's Spec Sheet
#define D64_BASE_ADDRESS 0xB0000000
Expand Down Expand Up @@ -285,6 +285,9 @@ int usb_readblock = -1;
#endif
#endif

// Flashcart specific stuff
static u32 d64_polltime = D64_DEFAULTPOLLTIME;


/*********************************
USB functions
Expand Down Expand Up @@ -883,7 +886,7 @@ static u32 usb_64drive_poll()
usb_64drive_arm(DEBUG_ADDRESS, DEBUG_ADDRESS_SIZE);

// Burn some time to see if any USB data comes in
for (i=0; i<D64_POLLTIME; i++)
for (i=0; i<d64_polltime; i++)
;

// If there's data to service
Expand Down Expand Up @@ -947,6 +950,25 @@ static void usb_64drive_read()
}


/*==============================
usb_set_64drive_polltime
Sets the time which the 64Drive should poll
for incoming USB data. Default is 2000.
Lowering this value improves game performance
at the cost of polling accuracy.
This is a hacky workaround for a 64Drive bug,
but it is planned to be removed in the future
when the polling protocol is changed.
@param The time to stall for waiting for USB
data
==============================*/

void usb_set_64drive_polltime(int polltime)
{
d64_polltime = polltime;
}


/*********************************
EverDrive functions
*********************************/
Expand Down Expand Up @@ -1082,16 +1104,24 @@ static void usb_everdrive_writereg(u64 reg, u32 value)
/*==============================
usb_everdrive_usbbusy
Spins until the USB is no longer busy
@return 1 on success, 0 on failure
==============================*/

static void usb_everdrive_usbbusy()
static u8 usb_everdrive_usbbusy()
{
u32 val __attribute__((aligned(8)));
do
u32 timeout = 0;
u32 val __attribute__((aligned(8))) = 0;
while ((val & ED_USBSTAT_ACT) != 0)
{
usb_everdrive_readreg(ED_REG_USBCFG, &val);
timeout++;
if (timeout > 8192)
{
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_RDNOP);
return 0;
}
}
while ((val & ED_USBSTAT_ACT) != 0);
return 1;
}


Expand Down Expand Up @@ -1135,8 +1165,9 @@ static void usb_everdrive_readusb(void* buffer, int size)
// Request to read from the USB
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_RD | addr);

// Wait for the FPGA to transfer the data to its internal buffer
usb_everdrive_usbbusy();
// Wait for the FPGA to transfer the data to its internal buffer, or stop on timeout
if (!usb_everdrive_usbbusy())
return;

// Read from the internal buffer and store it in our buffer
usb_everdrive_readdata(buffer, ED_GET_REGADD(ED_REG_USBDAT + addr), block);
Expand Down Expand Up @@ -1204,9 +1235,10 @@ static void usb_everdrive_write(int datatype, const void* data, int size)
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_WRNOP);
usb_everdrive_writedata(usb_buffer, ED_GET_REGADD(ED_REG_USBDAT + baddr), blocksend);

// Set USB to write mode with the new address and wait for USB to end
// Set USB to write mode with the new address and wait for USB to end (or stop if it times out)
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_WR | baddr);
usb_everdrive_usbbusy();
if (!usb_everdrive_usbbusy())
return;

// Keep track of what we've read so far
left -= block;
Expand All @@ -1230,7 +1262,8 @@ static u32 usb_everdrive_poll()
int offset = 0;

// Wait for the USB to be ready
usb_everdrive_usbbusy();
if (!usb_everdrive_usbbusy())
return;

// Check if the USB is ready to be read
if (!usb_everdrive_canread())
Expand Down Expand Up @@ -1267,7 +1300,8 @@ static u32 usb_everdrive_poll()
}

// Read the CMP Signal
usb_everdrive_usbbusy();
if (!usb_everdrive_usbbusy())
return;
usb_everdrive_readusb(buff, 16);
if (buff[0] != 'C' || buff[1] != 'M' || buff[2] != 'P' || buff[3] != 'H')
{
Expand Down
20 changes: 20 additions & 0 deletions Examples/Libultra/1. Hello World/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,24 @@

extern void usb_purge();


/*********************************
Flashcart Specific Functions
*********************************/

/*==============================
usb_set_64drive_polltime
Sets the time which the 64Drive should poll
for incoming USB data. Default is 2000.
Lowering this value improves game performance
at the cost of polling accuracy.
This is a hacky workaround for a 64Drive bug,
but it is planned to be removed in the future
when the polling protocol is changed.
@param The time to stall for waiting for USB
data
==============================*/

void usb_set_64drive_polltime(int polltime);

#endif
58 changes: 46 additions & 12 deletions Examples/Libultra/2. Thread Faults/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ using UNFLoader.

// How many cycles for the 64Drive to wait for data.
// Lowering this might improve performance slightly faster at the expense of USB reading accuracy
#define D64_POLLTIME 2000
#define D64_DEFAULTPOLLTIME 2000

// Cartridge Interface definitions. Obtained from 64Drive's Spec Sheet
#define D64_BASE_ADDRESS 0xB0000000
Expand Down Expand Up @@ -285,6 +285,9 @@ int usb_readblock = -1;
#endif
#endif

// Flashcart specific stuff
static u32 d64_polltime = D64_DEFAULTPOLLTIME;


/*********************************
USB functions
Expand Down Expand Up @@ -883,7 +886,7 @@ static u32 usb_64drive_poll()
usb_64drive_arm(DEBUG_ADDRESS, DEBUG_ADDRESS_SIZE);

// Burn some time to see if any USB data comes in
for (i=0; i<D64_POLLTIME; i++)
for (i=0; i<d64_polltime; i++)
;

// If there's data to service
Expand Down Expand Up @@ -947,6 +950,25 @@ static void usb_64drive_read()
}


/*==============================
usb_set_64drive_polltime
Sets the time which the 64Drive should poll
for incoming USB data. Default is 2000.
Lowering this value improves game performance
at the cost of polling accuracy.
This is a hacky workaround for a 64Drive bug,
but it is planned to be removed in the future
when the polling protocol is changed.
@param The time to stall for waiting for USB
data
==============================*/

void usb_set_64drive_polltime(int polltime)
{
d64_polltime = polltime;
}


/*********************************
EverDrive functions
*********************************/
Expand Down Expand Up @@ -1082,16 +1104,24 @@ static void usb_everdrive_writereg(u64 reg, u32 value)
/*==============================
usb_everdrive_usbbusy
Spins until the USB is no longer busy
@return 1 on success, 0 on failure
==============================*/

static void usb_everdrive_usbbusy()
static u8 usb_everdrive_usbbusy()
{
u32 val __attribute__((aligned(8)));
do
u32 timeout = 0;
u32 val __attribute__((aligned(8))) = 0;
while ((val & ED_USBSTAT_ACT) != 0)
{
usb_everdrive_readreg(ED_REG_USBCFG, &val);
timeout++;
if (timeout > 8192)
{
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_RDNOP);
return 0;
}
}
while ((val & ED_USBSTAT_ACT) != 0);
return 1;
}


Expand Down Expand Up @@ -1135,8 +1165,9 @@ static void usb_everdrive_readusb(void* buffer, int size)
// Request to read from the USB
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_RD | addr);

// Wait for the FPGA to transfer the data to its internal buffer
usb_everdrive_usbbusy();
// Wait for the FPGA to transfer the data to its internal buffer, or stop on timeout
if (!usb_everdrive_usbbusy())
return;

// Read from the internal buffer and store it in our buffer
usb_everdrive_readdata(buffer, ED_GET_REGADD(ED_REG_USBDAT + addr), block);
Expand Down Expand Up @@ -1204,9 +1235,10 @@ static void usb_everdrive_write(int datatype, const void* data, int size)
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_WRNOP);
usb_everdrive_writedata(usb_buffer, ED_GET_REGADD(ED_REG_USBDAT + baddr), blocksend);

// Set USB to write mode with the new address and wait for USB to end
// Set USB to write mode with the new address and wait for USB to end (or stop if it times out)
usb_everdrive_writereg(ED_REG_USBCFG, ED_USBMODE_WR | baddr);
usb_everdrive_usbbusy();
if (!usb_everdrive_usbbusy())
return;

// Keep track of what we've read so far
left -= block;
Expand All @@ -1230,7 +1262,8 @@ static u32 usb_everdrive_poll()
int offset = 0;

// Wait for the USB to be ready
usb_everdrive_usbbusy();
if (!usb_everdrive_usbbusy())
return;

// Check if the USB is ready to be read
if (!usb_everdrive_canread())
Expand Down Expand Up @@ -1267,7 +1300,8 @@ static u32 usb_everdrive_poll()
}

// Read the CMP Signal
usb_everdrive_usbbusy();
if (!usb_everdrive_usbbusy())
return;
usb_everdrive_readusb(buff, 16);
if (buff[0] != 'C' || buff[1] != 'M' || buff[2] != 'P' || buff[3] != 'H')
{
Expand Down
20 changes: 20 additions & 0 deletions Examples/Libultra/2. Thread Faults/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,24 @@

extern void usb_purge();


/*********************************
Flashcart Specific Functions
*********************************/

/*==============================
usb_set_64drive_polltime
Sets the time which the 64Drive should poll
for incoming USB data. Default is 2000.
Lowering this value improves game performance
at the cost of polling accuracy.
This is a hacky workaround for a 64Drive bug,
but it is planned to be removed in the future
when the polling protocol is changed.
@param The time to stall for waiting for USB
data
==============================*/

void usb_set_64drive_polltime(int polltime);

#endif
8 changes: 8 additions & 0 deletions Examples/Libultra/3. USB Read/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ static void mainThreadFunction(void *arg)
char incoming_type = 0;
int incoming_size = 0;

// Because of a bug in the 64Drive firmware, it can sometimes miss out on USB data.
// This happens more often the sooner successive usb_poll calls are made, and since this
// sample doesn't really do anything complex, the time between calls is pretty short.
// As a result, we'll need to increase the poll time to fix this sample for 64Drive users.
// In a proper game, you will likely not need to touch this function.
// It will likely be removed in a future version of a library, once a better USB polling protocl is made.
usb_set_64drive_polltime(50000);

// Give the user instructions
usb_write(DATATYPE_TEXT, "Type something into the console!\n", 33+1);

Expand Down
Loading

0 comments on commit b716f17

Please sign in to comment.