Update Apu SignalReady, BeginTransfer sequence
This commit is contained in:
@@ -25,9 +25,6 @@ void APU::Init() {
|
|||||||
|
|
||||||
dsp_.SetSamplePusher(
|
dsp_.SetSamplePusher(
|
||||||
[this](int16_t sample) { this->PushToAudioBuffer(sample); });
|
[this](int16_t sample) { this->PushToAudioBuffer(sample); });
|
||||||
|
|
||||||
// Initialize registers
|
|
||||||
SignalReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void APU::Reset() {
|
void APU::Reset() {
|
||||||
@@ -48,6 +45,7 @@ void APU::Update() {
|
|||||||
// Update the SPC700
|
// Update the SPC700
|
||||||
uint8_t opcode = spc700_.read(spc700_.PC);
|
uint8_t opcode = spc700_.read(spc700_.PC);
|
||||||
spc700_.ExecuteInstructions(opcode);
|
spc700_.ExecuteInstructions(opcode);
|
||||||
|
spc700_.PC++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessSamples();
|
ProcessSamples();
|
||||||
|
|||||||
@@ -60,30 +60,28 @@ class APU : public Observer {
|
|||||||
int16_t GetNextSample();
|
int16_t GetNextSample();
|
||||||
|
|
||||||
void Notify(uint32_t address, uint8_t data) override {
|
void Notify(uint32_t address, uint8_t data) override {
|
||||||
if (address >= 0x2140 && address <= 0x2143) {
|
ports_[address - 0x2140] = data;
|
||||||
spc700_.Notify(address, data);
|
|
||||||
|
switch (address) {
|
||||||
|
case 0x2140:
|
||||||
|
if (data == BEGIN_SIGNAL) {
|
||||||
|
BeginTransfer();
|
||||||
|
} else {
|
||||||
|
AcknowledgeSignal();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x2141:
|
||||||
|
// Handle data byte transfer here, if needed
|
||||||
|
break;
|
||||||
|
case 0x2142:
|
||||||
|
// Handle the setup of destination address, if needed
|
||||||
|
break;
|
||||||
|
case 0x2143:
|
||||||
|
// Handle additional communication or commands
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateClock(int delta_time) { clock_.UpdateClock(delta_time); }
|
|
||||||
|
|
||||||
// Method to fetch a sample from AudioRam
|
|
||||||
uint8_t FetchSampleFromRam(uint16_t address) const {
|
|
||||||
return aram_.read(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to push a processed sample to the audio buffer
|
|
||||||
void PushToAudioBuffer(int16_t sample) { audioSamples_.push_back(sample); }
|
|
||||||
|
|
||||||
// Reads a byte from the specified APU register
|
|
||||||
uint8_t ReadRegister(uint16_t address);
|
|
||||||
|
|
||||||
// Writes a byte to the specified APU register
|
|
||||||
void WriteRegister(uint16_t address, uint8_t value);
|
|
||||||
|
|
||||||
// Returns the audio samples for the current frame
|
|
||||||
const std::vector<int16_t> &GetAudioSamples() const;
|
|
||||||
|
|
||||||
// Called upon a reset
|
// Called upon a reset
|
||||||
void Initialize() {
|
void Initialize() {
|
||||||
spc700_.Reset();
|
spc700_.Reset();
|
||||||
@@ -123,37 +121,67 @@ class APU : public Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BeginTransfer() {
|
void BeginTransfer() {
|
||||||
uint16_t destAddr = ReadAddressFromPorts();
|
const uint16_t startAddress = 0x0200;
|
||||||
uint8_t counter = 0;
|
|
||||||
|
|
||||||
// Port 1 determines whether to execute or transfer
|
// Write the starting address to ports 0x2142 and 0x2143
|
||||||
while (ports_[1] != 0) {
|
WriteToPort(2, static_cast<uint8_t>(startAddress & 0xFF)); // Lower byte
|
||||||
uint8_t data = ports_[1];
|
WriteToPort(3, static_cast<uint8_t>(startAddress >> 8)); // Upper byte
|
||||||
aram_.write(destAddr, data);
|
|
||||||
AcknowledgeSignal();
|
|
||||||
|
|
||||||
destAddr++;
|
// Trigger the actual data transfer process
|
||||||
counter++;
|
TriggerDataTransfer(startAddress);
|
||||||
|
}
|
||||||
|
|
||||||
// Synchronize with the counter from the main CPU
|
void TriggerDataTransfer(uint16_t startAddress) {
|
||||||
while (ports_[0] != counter)
|
const int DATA_SIZE = 0x1000; // Size of the data to be transferred
|
||||||
;
|
uint8_t audioData[DATA_SIZE]; // Buffer containing the audio data
|
||||||
|
|
||||||
|
// Load audioData as needed...
|
||||||
|
|
||||||
|
for (int i = 0; i < DATA_SIZE; ++i) {
|
||||||
|
WriteToPort(1, audioData[i]); // Write data byte
|
||||||
|
WriteToPort(0, i & 0xFF); // Write index and wait for acknowledgment
|
||||||
|
WaitForAcknowledgment(i & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After transferring all data, trigger the execution of the program
|
||||||
|
StartSpcProgram(startAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForAcknowledgment(uint8_t expectedIndex) {
|
||||||
|
while (ports_[0] != expectedIndex) {
|
||||||
|
// Active wait - consider implementing a more efficient mechanism
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteProgram() {
|
void StartSpcProgram(uint16_t startAddress) {
|
||||||
// For now, this is a placeholder. Actual execution would involve running
|
// Send the start address for execution
|
||||||
// the SPC700's instruction at the specified address.
|
WriteToPort(2, static_cast<uint8_t>(startAddress & 0xFF)); // Lower byte
|
||||||
spc700_.ExecuteInstructions(ReadAddressFromPorts());
|
WriteToPort(3, static_cast<uint8_t>(startAddress >> 8)); // Upper byte
|
||||||
|
|
||||||
|
WriteToPort(1, 0x00); // Zero value indicates execution command
|
||||||
|
WriteToPort(0, 0xCE); // Send a unique signal to start execution
|
||||||
|
|
||||||
|
// Wait for acknowledgment
|
||||||
|
WaitForAcknowledgment(0xCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method will be called by the main CPU to write to the APU's ports.
|
void ExecuteProgram() { spc700_.ExecuteInstructions(ReadAddressFromPorts()); }
|
||||||
|
|
||||||
void WriteToPort(uint8_t portNum, uint8_t value) {
|
void WriteToPort(uint8_t portNum, uint8_t value) {
|
||||||
if (portNum < 4) {
|
ports_[portNum] = value;
|
||||||
ports_[portNum] = value;
|
switch (portNum) {
|
||||||
if (portNum == 0 && value == BEGIN_SIGNAL) {
|
case 0:
|
||||||
BeginTransfer();
|
memory_.WriteByte(0x2140, value);
|
||||||
}
|
break;
|
||||||
|
case 1:
|
||||||
|
memory_.WriteByte(0x2141, value);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
memory_.WriteByte(0x2142, value);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
memory_.WriteByte(0x2143, value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +189,25 @@ class APU : public Observer {
|
|||||||
ready_callback_ = callback;
|
ready_callback_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateClock(int delta_time) { clock_.UpdateClock(delta_time); }
|
||||||
|
|
||||||
|
// Method to fetch a sample from AudioRam
|
||||||
|
uint8_t FetchSampleFromRam(uint16_t address) const {
|
||||||
|
return aram_.read(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to push a processed sample to the audio buffer
|
||||||
|
void PushToAudioBuffer(int16_t sample) { audioSamples_.push_back(sample); }
|
||||||
|
|
||||||
|
// Reads a byte from the specified APU register
|
||||||
|
uint8_t ReadRegister(uint16_t address);
|
||||||
|
|
||||||
|
// Writes a byte to the specified APU register
|
||||||
|
void WriteRegister(uint16_t address, uint8_t value);
|
||||||
|
|
||||||
|
// Returns the audio samples for the current frame
|
||||||
|
const std::vector<int16_t> &GetAudioSamples() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constants for communication
|
// Constants for communication
|
||||||
static const uint8_t READY_SIGNAL_0 = 0xAA;
|
static const uint8_t READY_SIGNAL_0 = 0xAA;
|
||||||
@@ -189,7 +236,7 @@ class APU : public Observer {
|
|||||||
MemoryImpl &memory_;
|
MemoryImpl &memory_;
|
||||||
|
|
||||||
DigitalSignalProcessor dsp_;
|
DigitalSignalProcessor dsp_;
|
||||||
SPC700 spc700_{aram_};
|
Spc700 spc700_{aram_};
|
||||||
std::vector<int16_t> audioSamples_;
|
std::vector<int16_t> audioSamples_;
|
||||||
|
|
||||||
std::function<void()> ready_callback_;
|
std::function<void()> ready_callback_;
|
||||||
|
|||||||
Reference in New Issue
Block a user