DMA: Implemented all dma transfer modes

This commit is contained in:
Sour 2019-02-16 00:47:02 -05:00
parent 6d22b920b8
commit 85c84146bf
2 changed files with 38 additions and 26 deletions

View file

@ -7,34 +7,39 @@ DmaController::DmaController(shared_ptr<MemoryManager> memoryManager)
_memoryManager = memoryManager; _memoryManager = memoryManager;
} }
void DmaController::RunSingleTransfer(DmaChannelConfig &channel, uint32_t &bytesLeft)
{
const uint8_t *transferOffsets = _transferOffset[channel.TransferMode];
uint8_t transferByteCount = _transferByteCount[channel.TransferMode];
uint8_t i = 0;
while(bytesLeft > 0 && transferByteCount > 0) {
if(channel.InvertDirection) {
uint8_t valToWrite = _memoryManager->Read(0x2100 | channel.DestAddress + transferOffsets[i], MemoryOperationType::DmaRead);
_memoryManager->Write(channel.SrcAddress, valToWrite, MemoryOperationType::DmaWrite);
} else {
uint8_t valToWrite = _memoryManager->Read(channel.SrcAddress, MemoryOperationType::DmaRead);
_memoryManager->Write(0x2100 | channel.DestAddress + transferOffsets[i], valToWrite, MemoryOperationType::DmaWrite);
}
if(!channel.FixedTransfer) {
channel.SrcAddress = (channel.SrcAddress + (channel.Decrement ? -1 : 1)) & 0xFFFFFF;
}
transferByteCount--;
bytesLeft--;
i++;
}
}
void DmaController::RunDma(DmaChannelConfig &channel) void DmaController::RunDma(DmaChannelConfig &channel)
{ {
//"Note, however, that writing $0000 to this register actually results in a transfer of $10000 bytes, not 0." //"Note, however, that writing $0000 to this register actually results in a transfer of $10000 bytes, not 0."
uint32_t transferSize = channel.TransferSize ? channel.TransferSize : 0x10000; uint32_t bytesLeft = channel.TransferSize ? channel.TransferSize : 0x10000;
uint8_t offset = 0; while(bytesLeft > 0) {
if(channel.InvertDirection) { //Manual DMA transfers run to the end of the transfer when started
for(uint32_t i = 0; i < transferSize; i++) { RunSingleTransfer(channel, bytesLeft);
uint8_t valToWrite = _memoryManager->Read(0x2100 | channel.DestAddress + offset, MemoryOperationType::DmaRead);
_memoryManager->Write(channel.SrcAddress, valToWrite, MemoryOperationType::DmaWrite);
if(!channel.FixedTransfer) {
channel.SrcAddress += channel.Decrement ? -1 : 1;
}
}
} else {
for(uint32_t i = 0; i < transferSize; i++) {
uint8_t valToWrite = _memoryManager->Read(channel.SrcAddress, MemoryOperationType::DmaRead);
_memoryManager->Write(0x2100 | channel.DestAddress + offset, valToWrite, MemoryOperationType::DmaWrite);
if(channel.TransferMode == 1) {
offset = (offset + 1) & 0x01;
}
if(!channel.FixedTransfer) {
channel.SrcAddress += channel.Decrement ? -1 : 1;
}
}
} }
} }

View file

@ -20,13 +20,20 @@ struct DmaChannelConfig
class DmaController class DmaController
{ {
private: private:
static constexpr uint8_t _transferByteCount[8] = { 1, 2, 2, 4, 4, 2, 4 };
static constexpr uint8_t _transferOffset[8][4] = {
{ 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 1, 1 },
{ 0, 1, 2, 3 }, { 0, 1, 0, 1 }, { 0, 0, 0, 0 }, { 0, 0, 1, 1 }
};
DmaChannelConfig _channel[8] = {}; DmaChannelConfig _channel[8] = {};
shared_ptr<MemoryManager> _memoryManager; shared_ptr<MemoryManager> _memoryManager;
void RunSingleTransfer(DmaChannelConfig &channel, uint32_t &bytesLeft);
void RunDma(DmaChannelConfig &channel);
public: public:
DmaController(shared_ptr<MemoryManager> memoryManager); DmaController(shared_ptr<MemoryManager> memoryManager);
void RunDma(DmaChannelConfig & channel);
void Write(uint16_t addr, uint8_t value); void Write(uint16_t addr, uint8_t value);
}; };