static void pssj_write(uint16_t port, uint8_t val, void *p) { pssj_t *pssj = (pssj_t *)p; switch (port & 3) { case 0: pssj->ctrl = val; pssj->enable = (val & 4) && (pssj->ctrl & 3); sn74689_set_extra_divide(&pssj->sn76489, val & 0x40); if (!(val & 8)) pssj->irq = 0; pssj_update_irq(pssj); break; case 1: switch (pssj->ctrl & 3) { case 1: /*Sound channel*/ pssj->wave = val; pssj->pulse_width = val & 7; break; case 3: /*Direct DAC*/ pssj->dac_val = val; break; } break; case 2: pssj->freq = (pssj->freq & 0xf00) | val; break; case 3: pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8); pssj->amplitude = val >> 4; break; } }
static void pssj_callback(void *p) { pssj_t *pssj = (pssj_t *)p; int data; pssj_update(pssj); if (pssj->ctrl & 2) { if ((pssj->ctrl & 3) == 3) { data = dma_channel_read(1); if (data != DMA_NODATA) { pssj->dac_val = data & 0xff; // pclog("DAC_val=%02x\n", data); } } else { data = dma_channel_write(1, 0x80); } if ((data & DMA_OVER) && data != DMA_NODATA) { // pclog("Check IRQ %i %02x\n", pssj->irq, pssj->ctrl); if (pssj->ctrl & 0x08) { pssj->irq = 1; pssj_update_irq(pssj); } } } else { switch (pssj->wave & 0xc0) { case 0x00: /*Pulse*/ pssj->dac_val = (pssj->wave_pos > (pssj->pulse_width << 1)) ? 0xff : 0; break; case 0x40: /*Ramp*/ pssj->dac_val = pssj->wave_pos << 3; break; case 0x80: /*Triangle*/ if (pssj->wave_pos & 16) pssj->dac_val = (pssj->wave_pos ^ 31) << 4; else pssj->dac_val = pssj->wave_pos << 4; break; case 0xc0: pssj->dac_val = 0x80; break; } pssj->wave_pos = (pssj->wave_pos + 1) & 31; } pssj->timer_count += (int)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)); }