Skip to content

Commit

Permalink
PCEmulator: added Speaker sound support
Browse files Browse the repository at this point in the history
  • Loading branch information
fdivitto committed Apr 6, 2021
1 parent 5d9b006 commit a82c051
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
59 changes: 57 additions & 2 deletions examples/VGA/PCEmulator/machine.cpp
Expand Up @@ -115,6 +115,11 @@ void Machine::init()
m_HGCSwitchReg = 0;
m_HGCVSyncQuery = 0;

m_speakerDataEnable = false;

m_soundGen.play(true);
m_soundGen.attach(&m_sinWaveGen);

m_i8042.init(&m_PIC8259A, &m_PIC8259B);

m_PIC8259A.reset();
Expand All @@ -123,6 +128,8 @@ void Machine::init()
m_PIT8253.setCallbacks(this, PITChangeOut, PITTick);
m_PIT8253.reset();
m_PIT8253.runAutoTick(PIT_TICK_FREQ, PIT_UPDATES_PER_SEC);
m_PIT8253.setGate(0, true);
m_PIT8253.setGate(1, true);

memset(m_CGA6845, 0, sizeof(m_CGA6845));
memset(m_HGC6845, 0, sizeof(m_HGC6845));
Expand Down Expand Up @@ -352,14 +359,27 @@ void Machine::writePort(void * context, int address, uint8_t value)
case 0x0041:
case 0x0042:
case 0x0043:
//printf("OUT %04x=%02x\n", address, value);
m->m_PIT8253.write(address & 3, value);
if ((address == 0x43 && (value >> 6) == 2) || address == 0x42)
m->speakerSetFreq();
break;

// 8042 keyboard controller input
case 0x0060:
m->m_i8042.write(0, value);
break;

// PortB
// bit 1 : speaker data enable
// bit 0 : timer 2 gate
case 0x0061:
//printf("OUT %04x=%02x\n", address, value);
m->m_speakerDataEnable = value & 0x02;
m->m_PIT8253.setGate(2, value & 0x01);
m->speakerEnableDisable();
break;

// 8042 keyboard controller input
case 0x0064:
m->m_i8042.write(1, value);
Expand Down Expand Up @@ -445,9 +465,20 @@ uint8_t Machine::readPort(void * context, int address)
case 0x0060:
return m->m_i8042.read(0);

// Port B
// bit 5 : timer 2 out
// bit 4 : toggles every 15.085us (DMA refresh)
// bit 1 : speaker data enable
// bit 0 : timer 2 gate
case 0x0061:
return ((int)m->m_PIT8253.getOut(2) << 5) | // bit 5
(esp_timer_get_time() & 0x10) | // bit 4 (toggles every 16us)
((int)m->m_speakerDataEnable << 1) | // bit 1
((int)m->m_PIT8253.getGate(2)); // bit 0

// I/O port
case 0x0062:
return 0x20 * m->m_PIT8253.readOut(2); // bit 5 = timer 2 output
return 0x20 * m->m_PIT8253.getOut(2); // bit 5 = timer 2 output

// 8042 keyboard controller status register
case 0x0064:
Expand Down Expand Up @@ -495,7 +526,7 @@ void Machine::PITChangeOut(void * context, int timerIndex)
auto m = (Machine*)context;

// timer 0 trigged?
if (timerIndex == 0 && m->m_PIT8253.readOut(0) == true) {
if (timerIndex == 0 && m->m_PIT8253.getOut(0) == true) {
// yes, report IR0 (IRQ8)
m->m_PIC8259A.signalInterrupt(0);
}
Expand Down Expand Up @@ -625,3 +656,27 @@ bool Machine::interrupt(void * context, int num)
}


void Machine::speakerSetFreq()
{
//printf("speakerSetFreq: count = %d\n", m_PIT8253.timerInfo(2).resetCount);
int timerCount = m_PIT8253.timerInfo(2).resetCount;
if (timerCount == 0)
timerCount = 65536;
int freq = PIT_TICK_FREQ / timerCount;
//printf(" freq = %dHz\n", freq);
m_sinWaveGen.setFrequency(freq);
}


void Machine::speakerEnableDisable()
{
bool genEnabled = m_PIT8253.getGate(2);
if (genEnabled && m_speakerDataEnable) {
// speaker enabled
m_sinWaveGen.enable(true);
} else {
// speaker disabled
m_sinWaveGen.enable(false);
}
}

8 changes: 8 additions & 0 deletions examples/VGA/PCEmulator/machine.h
Expand Up @@ -75,6 +75,9 @@ class Machine {
static void PITChangeOut(void * context, int timerIndex);
static void PITTick(void * context, int timerIndex);

void speakerSetFreq();
void speakerEnableDisable();


GraphicsAdapter m_graphicsAdapter;

Expand Down Expand Up @@ -122,6 +125,11 @@ class Machine {
uint8_t m_HGCSwitchReg;
uint16_t m_HGCVSyncQuery;

// speaker/audio
bool m_speakerDataEnable;
SoundGenerator m_soundGen;
SineWaveformGenerator m_sinWaveGen;

};


0 comments on commit a82c051

Please sign in to comment.