Files
dspico-usb-examples/platform/DSPicoUsbInEndpoint.cpp
2025-11-23 14:07:30 +01:00

101 lines
3.1 KiB
C++

#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)&REG_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);
}
}