Aid VSU performance

This commit is contained in:
Guy Perfect 2024-11-17 14:57:56 -06:00
parent e97b52e944
commit bc864644f7
2 changed files with 98 additions and 89 deletions

View File

@ -64,7 +64,9 @@ typedef struct {
} wave; } wave;
/* Other state */ /* Other state */
uint32_t clocks; /* Clocks until next sample */ uint32_t clocks; /* Clocks until next wave or noise sample */
uint8_t freqmod; /* Frequency modifications are active */
uint32_t until; /* Clocks until channel component update */
} Channel; } Channel;
/* Simulation state */ /* Simulation state */

View File

@ -74,49 +74,8 @@ static void vsuNextFreqMod(VB *sim, Channel *chan) {
} }
/* Process one channel */ /* Process one channel */
static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) { static void vsuEmulateChannel(VB *sim, Channel *chan, uint32_t clocks) {
uint32_t bit; /* Pseudorandom bit */ uint32_t bit; /* Pseudorandom bit */
Channel *chan; /* Channel handle */
int freqmod; /* Frequency modifications enabled */
uint32_t until; /* Clocks to process sub-channel components */
/* Select channel */
chan = &sim->vsu.channels[index];
/* Channel is disabled */
if (!chan->int_.enb)
return;
/* Frequency modifications are active */
freqmod =
index == 4 && /* Channel 5 */
sim->vsu.freqmod.enb && /* Modifications enabled */
sim->vsu.freqmod.interval != 0 /* Modifications valid */
;
/* Process all clocks */
do {
/* Clocks until next state change */
until = clocks;
if (chan->clocks < until)
until = chan->clocks;
if (chan->env.enb && chan->env.clocks < until)
until = chan->env.clocks;
if (chan->int_.auto_ && chan->int_.clocks < until)
until = chan->int_.clocks;
if (freqmod && sim->vsu.freqmod.clocks < until)
until = sim->vsu.freqmod.clocks;
/* Manage clocks */
clocks -= until;
chan->clocks -= until;
if (chan->env.enb)
chan->env.clocks -= until;
if (chan->int_.auto_)
chan->int_.clocks -= until;
if (freqmod)
sim->vsu.freqmod.clocks -= until;
/* Automatic shutoff */ /* Automatic shutoff */
if (chan->int_.auto_ && chan->int_.clocks == 0) { if (chan->int_.auto_ && chan->int_.clocks == 0) {
@ -124,11 +83,11 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
return; return;
} }
/* Next sample */ /* Next input sample */
if (chan->clocks == 0) { if (chan->clocks == 0) {
/* Wave */ /* Wave */
if (index != 5) { if (chan != &sim->vsu.channels[5]) {
chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current); chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current);
chan->wave.sample = (chan->wave.sample + 1) & 31; chan->wave.sample = (chan->wave.sample + 1) & 31;
} }
@ -158,7 +117,7 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
} }
/* Frequency modification */ /* Frequency modification */
if (freqmod && sim->vsu.freqmod.clocks == 0) { if (chan->freqmod && sim->vsu.freqmod.clocks == 0) {
chan->freq.current = sim->vsu.freqmod.next; chan->freq.current = sim->vsu.freqmod.next;
vsuNextFreqMod(sim, chan); vsuNextFreqMod(sim, chan);
if (!chan->int_.enb) if (!chan->int_.enb)
@ -167,8 +126,6 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
(sim->vsu.freqmod.clk == 0 ? 19200 : 153600); (sim->vsu.freqmod.clk == 0 ? 19200 : 153600);
} }
} while (clocks != 0);
} }
/* Produce output for a channel */ /* Produce output for a channel */
@ -230,6 +187,8 @@ static void vsuWriteEV1(VB *sim, int index, uint8_t value) {
sim->vsu.freqmod.func = value >> 4 & 1; sim->vsu.freqmod.func = value >> 4 & 1;
sim->vsu.freqmod.rep = value >> 5 & 1; sim->vsu.freqmod.rep = value >> 5 & 1;
vsuNextFreqMod(sim, chan); vsuNextFreqMod(sim, chan);
chan->freqmod =
sim->vsu.freqmod.enb && sim->vsu.freqmod.interval != 0;
break; break;
case 5: /* Channel 6 */ case 5: /* Channel 6 */
@ -313,6 +272,8 @@ static void vsuWriteSWP(VB *sim, uint8_t value) {
(sim->vsu.freqmod.clk == 0 ? 19200 : 153600); (sim->vsu.freqmod.clk == 0 ? 19200 : 153600);
if (clocks < sim->vsu.freqmod.clocks) if (clocks < sim->vsu.freqmod.clocks)
sim->vsu.freqmod.clocks = clocks; sim->vsu.freqmod.clocks = clocks;
sim->vsu.channels[4].freqmod =
sim->vsu.freqmod.enb && sim->vsu.freqmod.interval != 0;
} }
@ -321,6 +282,8 @@ static void vsuWriteSWP(VB *sim, uint8_t value) {
/* Process component */ /* Process component */
static void vsuEmulate(VB *sim, uint32_t clocks) { static void vsuEmulate(VB *sim, uint32_t clocks) {
Channel *chan; /* Input channel */
uint32_t chantil; /* Clocks until next channel state update */
float i0; /* Current analog input sample */ float i0; /* Current analog input sample */
float o0; /* Current analog output sample */ float o0; /* Current analog output sample */
uint16_t output[2]; /* Digital output samples */ uint16_t output[2]; /* Digital output samples */
@ -340,8 +303,50 @@ static void vsuEmulate(VB *sim, uint32_t clocks) {
sim->vsu.clocks -= until; sim->vsu.clocks -= until;
/* Process all channels */ /* Process all channels */
for (x = 0; x < 6; x++) for (x = 0; x < 6; x++) {
vsuEmulateChannel(sim, x, until); chan = &sim->vsu.channels[x];
chantil = until;
/* Process all clocks */
while (chan->int_.enb && chantil != 0) {
/* Determine when the next state change will occur */
if (chan->until == 0) {
/* Clocks until next state change */
chan->until = chan->clocks;
if (chan->env.enb && chan->env.clocks < chan->until)
chan->until = chan->env.clocks;
if (chan->int_.auto_ && chan->int_.clocks < chan->until)
chan->until = chan->int_.clocks;
if (chan->freqmod && sim->vsu.freqmod.clocks < chan->until)
chan->until = sim->vsu.freqmod.clocks;
/* Manage clocks */
chan->clocks -= chan->until;
if (chan->env.enb)
chan->env.clocks -= chan->until;
if (chan->int_.auto_)
chan->int_.clocks -= chan->until;
if (chan->freqmod)
sim->vsu.freqmod.clocks -= chan->until;
}
/* Manage clocks */
if (chan->until > chantil) {
chan->until -= chantil;
chantil = 0;
} else {
chantil -= chan->until;
chan->until = 0;
}
/* Update channel state */
if (chan->until == 0)
vsuEmulateChannel(sim, chan, chan->until);
}
}
/* Wait for the current sample to finish */ /* Wait for the current sample to finish */
if (sim->vsu.clocks != 0) if (sim->vsu.clocks != 0)
@ -416,6 +421,8 @@ static void vsuReset(VB *sim) {
for (x = 0; x < 6; x++) { for (x = 0; x < 6; x++) {
chan = &sim->vsu.channels[x]; chan = &sim->vsu.channels[x];
chan->clocks = 0; chan->clocks = 0;
chan->freqmod = 0;
chan->until = 0;
chan->env.clocks = 0; chan->env.clocks = 0;
chan->env.enb = 0; chan->env.enb = 0;
chan->env.dir = 0; chan->env.dir = 0;