#include "common.h" #include "libtwl/dma/dmaNitro.h" #include "tusb.h" #include "device/dcd.h" #include "DSPicoUsb.h" #include "DSPicoUsbInEndpoint.h" void DSPicoUsbInEndpoint::BeginTransfer(const u8* buffer, u32 length) { rtos_lockMutex(&_mutex); { _buffer = buffer; _bufferLength = length; _remaining = length; _bufferOffset = 0; _currentDSPicoBuffer = 0; _transferActive = true; SendUsbBlock(true); SendUsbBlock(false); } rtos_unlockMutex(&_mutex); } void DSPicoUsbInEndpoint::ProcessTransferCompleteEvent(u32 transferredBytes) { rtos_lockMutex(&_mutex); { if (_transferActive) { _remaining -= transferredBytes; if (_remaining == 0) { dcd_event_xfer_complete(0, _endpointAddress, _bufferLength, XFER_RESULT_SUCCESS, true); _transferActive = false; } else { u32 length = _remaining; if (length > 512) { length = 512; } rtos_lockMutex(&gCardMutex); { card_romSetCmd(DSPICO_CMD_USB_COMMAND_BEGIN_TRANSFER(_endpointAddress, 1 - _currentDSPicoBuffer, length)); card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false); card_romWaitBusy(); } rtos_unlockMutex(&gCardMutex); SendUsbBlock(false); } } else { // This seems to happen only once on the control endpoint. Idk why. dcd_event_xfer_complete(0, _endpointAddress, transferredBytes, XFER_RESULT_SUCCESS, true); } } rtos_unlockMutex(&_mutex); } void DSPicoUsbInEndpoint::SendUsbBlock(bool startTransfer) { u32 length = _bufferLength - _bufferOffset; if (length > 0) { if (length > 512) { length = 512; } rtos_lockMutex(&gCardMutex); { REG_DMA3SAD = (u32)(_buffer + _bufferOffset); REG_DMA3DAD = (u32)®_MCD1; REG_DMA3CNT = 0xA6400001; card_romSetCmd(DSPICO_CMD_USB_WRITE_DATA(_currentDSPicoBuffer, _endpointAddress, startTransfer, length)); card_romStartXfer(MCCNT1_DIR_WRITE | MCCNT1_RESET_OFF | MCCNT1_CLK_6_7_MHZ | MCCNT1_LEN_512 | MCCNT1_CMD_SCRAMBLE | MCCNT1_LATENCY2(8) | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_LATENCY1(0), false); card_romWaitBusy(); REG_DMA3CNT = 0; } rtos_unlockMutex(&gCardMutex); _bufferOffset += length; _currentDSPicoBuffer = 1 - _currentDSPicoBuffer; } else if (startTransfer) { // zero length transfer rtos_lockMutex(&gCardMutex); { card_romSetCmd(DSPICO_CMD_USB_WRITE_DATA(_currentDSPicoBuffer, _endpointAddress, true, 0)); card_romStartXfer(DSPICO_USB_DEFAULT_COMMAND_SETTINGS, false); card_romWaitBusy(); } rtos_unlockMutex(&gCardMutex); } }