Merge branch 'master' into audio
This commit is contained in:
@@ -9,9 +9,11 @@
|
||||
#include <86box/dma.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/filters.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/snd_opl.h>
|
||||
#include <86box/snd_ym7128.h>
|
||||
|
||||
@@ -38,6 +40,10 @@ typedef struct adgold_t
|
||||
int adgold_mma_intpos[2];
|
||||
|
||||
pc_timer_t adgold_mma_timer_count;
|
||||
|
||||
uint8_t adgold_midi_ctrl, midi_queue[16];
|
||||
int midi_r, midi_w;
|
||||
int uart_in, uart_out, sysex;
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -54,6 +60,7 @@ typedef struct adgold_t
|
||||
|
||||
int fm_vol_l, fm_vol_r;
|
||||
int samp_vol_l, samp_vol_r;
|
||||
int aux_vol_l, aux_vol_r;
|
||||
int vol_l, vol_r;
|
||||
int treble, bass;
|
||||
|
||||
@@ -61,7 +68,9 @@ typedef struct adgold_t
|
||||
int16_t mma_buffer[2][SOUNDBUFLEN];
|
||||
|
||||
int pos;
|
||||
|
||||
|
||||
int gameport_enabled;
|
||||
|
||||
int surround_enabled;
|
||||
} adgold_t;
|
||||
|
||||
@@ -134,12 +143,17 @@ void adgold_update_irq_status(adgold_t *adgold)
|
||||
uint8_t temp = 0xf;
|
||||
|
||||
if (!(adgold->adgold_mma_regs[0][8] & 0x10) && (adgold->adgold_mma_status & 0x10)) /*Timer 0*/
|
||||
temp &= ~2;
|
||||
temp &= ~2;
|
||||
if (!(adgold->adgold_mma_regs[0][8] & 0x20) && (adgold->adgold_mma_status & 0x20)) /*Timer 1*/
|
||||
temp &= ~2;
|
||||
temp &= ~2;
|
||||
if (!(adgold->adgold_mma_regs[0][8] & 0x40) && (adgold->adgold_mma_status & 0x40)) /*Timer 2*/
|
||||
temp &= ~2;
|
||||
|
||||
temp &= ~2;
|
||||
if (!(adgold->adgold_mma_regs[0][0xd] & 0x01) && (adgold->adgold_mma_status & 0x04))
|
||||
temp &= ~2;
|
||||
if (!(adgold->adgold_mma_regs[0][0xd] & 0x04) && (adgold->adgold_mma_status & 0x08))
|
||||
temp &= ~2;
|
||||
if (!(adgold->adgold_mma_regs[0][0xd] & 0x10) && (adgold->adgold_mma_status & 0x80))
|
||||
temp &= ~2;
|
||||
if ((adgold->adgold_mma_status & 0x01) && !(adgold->adgold_mma_regs[0][0xc] & 2))
|
||||
temp &= ~2;
|
||||
if ((adgold->adgold_mma_status & 0x02) && !(adgold->adgold_mma_regs[1][0xc] & 2))
|
||||
@@ -249,11 +263,19 @@ void adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
adgold->adgold_38x_regs[0x0c] = val;
|
||||
adgold->samp_vol_r = (int)(int8_t)(val - 128);
|
||||
break;
|
||||
case 0x0d: /*Aux volume left*/
|
||||
adgold->adgold_38x_regs[0x0d] = val;
|
||||
adgold->aux_vol_l = (int)(int8_t)(val - 128);
|
||||
break;
|
||||
case 0x0e: /*Aux volume right*/
|
||||
adgold->adgold_38x_regs[0x0e] = val;
|
||||
adgold->aux_vol_r = (int)(int8_t)(val - 128);
|
||||
break;
|
||||
|
||||
case 0x18: /*Surround*/
|
||||
adgold->adgold_38x_regs[0x18] = val;
|
||||
ym7128_write(&adgold->ym7128, val);
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
adgold->adgold_38x_regs[adgold->adgold_38x_addr] = val;
|
||||
@@ -380,6 +402,45 @@ void adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
case 0xc:
|
||||
adgold->adgold_mma_intpos[0] = (7 - ((val >> 2) & 7)) * 8;
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
adgold->adgold_midi_ctrl = val & 0x3f;
|
||||
|
||||
if ((adgold->adgold_midi_ctrl & 0x0f) != 0x0f) {
|
||||
if ((adgold->adgold_midi_ctrl & 0x0f) == 0x00) {
|
||||
adgold->uart_out = 0;
|
||||
adgold->uart_in = 0;
|
||||
adgold->midi_w = 0;
|
||||
adgold->midi_r = 0;
|
||||
adgold->adgold_mma_status &= ~0x8c;
|
||||
} else {
|
||||
if (adgold->adgold_midi_ctrl & 0x01)
|
||||
adgold->uart_in = 1;
|
||||
if (adgold->adgold_midi_ctrl & 0x04)
|
||||
adgold->uart_out = 1;
|
||||
if (adgold->adgold_midi_ctrl & 0x02) {
|
||||
adgold->uart_in = 0;
|
||||
adgold->midi_w = 0;
|
||||
adgold->midi_r = 0;
|
||||
}
|
||||
if (adgold->adgold_midi_ctrl & 0x08)
|
||||
adgold->uart_out = 0;
|
||||
adgold->adgold_mma_status &= ~0x80;
|
||||
}
|
||||
} else
|
||||
adgold->adgold_mma_status &= ~0x8c;
|
||||
|
||||
adgold_update_irq_status(adgold);
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
if (adgold->uart_out) {
|
||||
midi_raw_out_byte(val);
|
||||
|
||||
adgold->adgold_mma_status &= ~0x08;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
break;
|
||||
}
|
||||
adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val;
|
||||
break;
|
||||
@@ -467,9 +528,9 @@ uint8_t adgold_read(uint16_t addr, void *p)
|
||||
{
|
||||
case 0x00: /*Control/ID*/
|
||||
if (adgold->surround_enabled)
|
||||
temp = 0x50; /*16-bit ISA, surround module, no telephone/CDROM*/
|
||||
temp = 0x51; /*8-bit ISA, surround module, no telephone/CD-ROM*/
|
||||
else
|
||||
temp = 0x70; /*16-bit ISA, no telephone/surround/CD-ROM*/
|
||||
temp = 0x71; /*8-bit ISA, no telephone/surround/CD-ROM*/
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -482,7 +543,7 @@ uint8_t adgold_read(uint16_t addr, void *p)
|
||||
|
||||
case 4: case 6:
|
||||
temp = adgold->adgold_mma_status;
|
||||
adgold->adgold_mma_status = 0; /*JUKEGOLD expects timer status flags to auto-clear*/
|
||||
adgold->adgold_mma_status &= ~0xf3; /*JUKEGOLD expects timer status flags to auto-clear*/
|
||||
adgold_update_irq_status(adgold);
|
||||
break;
|
||||
case 5:
|
||||
@@ -491,12 +552,26 @@ uint8_t adgold_read(uint16_t addr, void *p)
|
||||
{
|
||||
case 6: /*Timer 2 low*/
|
||||
adgold->adgold_mma.timer2_read = adgold->adgold_mma.timer2_count;
|
||||
adgold->adgold_mma_status |= 0x40;
|
||||
temp = adgold->adgold_mma.timer2_read & 0xff;
|
||||
break;
|
||||
case 7: /*Timer 2 high*/
|
||||
temp = adgold->adgold_mma.timer2_read >> 8;
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
temp = 0;
|
||||
if (adgold->uart_in) {
|
||||
temp = adgold->midi_queue[adgold->midi_r];
|
||||
if (adgold->midi_r != adgold->midi_w) {
|
||||
adgold->midi_r++;
|
||||
adgold->midi_r &= 0x0f;
|
||||
}
|
||||
adgold->adgold_mma_status &= ~0x04;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = adgold->adgold_mma_regs[0][adgold->adgold_mma_addr];
|
||||
break;
|
||||
@@ -579,6 +654,17 @@ void adgold_timer_poll(void *p)
|
||||
adgold_t *adgold = (adgold_t *)p;
|
||||
|
||||
timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t)((double)TIMER_USEC * 1.88964));
|
||||
|
||||
if (adgold->adgold_midi_ctrl & 0x3f) {
|
||||
if ((adgold->adgold_midi_ctrl & 0x3f) != 0x3f) {
|
||||
if (adgold->uart_out)
|
||||
adgold->adgold_mma_status |= 0x08;
|
||||
if (adgold->adgold_midi_ctrl & 0x10)
|
||||
adgold->adgold_mma_status |= 0x80;
|
||||
}
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/
|
||||
{
|
||||
adgold->adgold_mma.timer0_count--;
|
||||
@@ -752,6 +838,59 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p)
|
||||
free(adgold_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
adgold_filter_cd_audio(int channel, double *buffer, void *p)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *)p;
|
||||
double c;
|
||||
int aux = channel ? adgold->aux_vol_r : adgold->aux_vol_l;
|
||||
int vol = channel ? adgold->vol_r : adgold->vol_l;
|
||||
|
||||
c = ((((*buffer) * aux) / 4096.0) * vol) / 4096.0;
|
||||
*buffer = c;
|
||||
}
|
||||
|
||||
|
||||
static void adgold_input_msg(void *p, uint8_t *msg, uint32_t len)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *)p;
|
||||
uint8_t i;
|
||||
|
||||
if (adgold->sysex)
|
||||
return;
|
||||
|
||||
if (adgold->uart_in) {
|
||||
adgold->adgold_mma_status |= 0x04;
|
||||
|
||||
for (i=0; i < len; i++) {
|
||||
adgold->midi_queue[adgold->midi_w++] = msg[i];
|
||||
adgold->midi_w &= 0x0f;
|
||||
}
|
||||
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
|
||||
static int adgold_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *)p;
|
||||
uint32_t i;
|
||||
|
||||
if (abort) {
|
||||
adgold->sysex = 0;
|
||||
return 0;
|
||||
}
|
||||
adgold->sysex = 1;
|
||||
for (i=0;i<len;i++) {
|
||||
if (adgold->midi_r == adgold->midi_w)
|
||||
return (len-i);
|
||||
adgold->midi_queue[adgold->midi_w++] = buffer[i];
|
||||
adgold->midi_w &= 0x0f;
|
||||
}
|
||||
adgold->sysex = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *adgold_init(const device_t *info)
|
||||
{
|
||||
@@ -762,6 +901,8 @@ void *adgold_init(const device_t *info)
|
||||
memset(adgold, 0, sizeof(adgold_t));
|
||||
|
||||
adgold->surround_enabled = device_get_config_int("surround");
|
||||
|
||||
adgold->gameport_enabled = device_get_config_int("gameport");
|
||||
|
||||
opl3_init(&adgold->opl);
|
||||
if (adgold->surround_enabled)
|
||||
@@ -798,6 +939,8 @@ void *adgold_init(const device_t *info)
|
||||
adgold->fm_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0a] - 128);
|
||||
adgold->samp_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x0b] - 128);
|
||||
adgold->samp_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0c] - 128);
|
||||
adgold->aux_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x0d] - 128);
|
||||
adgold->aux_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0e] - 128);
|
||||
|
||||
adgold->adgold_mma_enable[0] = 0;
|
||||
adgold->adgold_mma_fifo_start[0] = adgold->adgold_mma_fifo_end[0] = 0;
|
||||
@@ -805,10 +948,17 @@ void *adgold_init(const device_t *info)
|
||||
/*388/389 are handled by adlib_init*/
|
||||
io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold);
|
||||
|
||||
if (adgold->gameport_enabled)
|
||||
gameport_remap(gameport_add(&gameport_201_device), 0x201);
|
||||
|
||||
timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1);
|
||||
|
||||
sound_add_handler(adgold_get_buffer, adgold);
|
||||
sound_set_cd_audio_filter(adgold_filter_cd_audio, adgold);
|
||||
|
||||
if (device_get_config_int("receive_input"))
|
||||
midi_in_handler(1, adgold_input_msg, adgold_input_sysex, adgold);
|
||||
|
||||
return adgold;
|
||||
}
|
||||
|
||||
@@ -829,9 +979,15 @@ void adgold_close(void *p)
|
||||
|
||||
static const device_config_t adgold_config[] =
|
||||
{
|
||||
{
|
||||
"gameport", "Enable Game port", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"surround", "Surround module", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
|
||||
@@ -67,9 +67,10 @@ typedef struct {
|
||||
uint32_t sr_cir;
|
||||
uint16_t sr_ram[128];
|
||||
|
||||
uint8_t uart_ctrl, uart_status,
|
||||
uart_res;
|
||||
uint32_t uart_fifo;
|
||||
uint8_t uart_data, uart_ctrl,
|
||||
uart_status, uart_res;
|
||||
uint32_t uart_fifo[8];
|
||||
uint8_t read_fifo_pos, write_fifo_pos;
|
||||
|
||||
ac97_codec_t * codec;
|
||||
uint32_t codec_ctrl;
|
||||
@@ -165,6 +166,8 @@ typedef struct {
|
||||
#define UART_STATUS_TXRDY (1<<1)
|
||||
#define UART_STATUS_RXRDY (1<<0)
|
||||
|
||||
#define UART_FIFO_BYTE_VALID 0x00000100
|
||||
|
||||
#define FORMAT_MONO_8 0
|
||||
#define FORMAT_STEREO_8 1
|
||||
#define FORMAT_MONO_16 2
|
||||
@@ -174,7 +177,6 @@ typedef struct {
|
||||
static void es1371_fetch(es1371_t *dev, int dac_nr);
|
||||
static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl);
|
||||
|
||||
|
||||
#ifdef ENABLE_AUDIOPCI_LOG
|
||||
int audiopci_do_log = ENABLE_AUDIOPCI_LOG;
|
||||
|
||||
@@ -205,10 +207,12 @@ es1371_update_irqs(es1371_t *dev)
|
||||
if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN))
|
||||
irq = 1;
|
||||
|
||||
/* MIDI input is unsupported for now */
|
||||
if ((dev->int_status & INT_STATUS_UART) && (dev->uart_status & UART_STATUS_TXINT) &&
|
||||
((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20))
|
||||
dev->int_status &= ~INT_STATUS_UART;
|
||||
|
||||
if ((dev->uart_status & UART_STATUS_TXINT) || (dev->uart_status & UART_STATUS_RXINT)) {
|
||||
dev->int_status |= INT_STATUS_UART;
|
||||
irq = 1;
|
||||
}
|
||||
|
||||
if (irq)
|
||||
dev->int_status |= INT_STATUS_INTR;
|
||||
@@ -225,10 +229,96 @@ es1371_update_irqs(es1371_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_update_tx_irq(es1371_t *dev)
|
||||
{
|
||||
dev->uart_status &= ~UART_STATUS_TXINT;
|
||||
|
||||
if (((dev->uart_ctrl & UART_CTRL_TXINTEN) == 0x20) && (dev->uart_status & UART_STATUS_TXRDY))
|
||||
dev->uart_status |= UART_STATUS_TXINT;
|
||||
|
||||
es1371_update_irqs(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_set_tx_irq(es1371_t *dev, int set)
|
||||
{
|
||||
dev->uart_status &= ~UART_STATUS_TXRDY;
|
||||
|
||||
if (set)
|
||||
dev->uart_status |= UART_STATUS_TXRDY;
|
||||
|
||||
es1371_update_tx_irq(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_update_rx_irq(es1371_t *dev)
|
||||
{
|
||||
dev->uart_status &= ~UART_STATUS_RXINT;
|
||||
|
||||
if ((dev->uart_ctrl & UART_CTRL_RXINTEN) && (dev->uart_status & UART_STATUS_RXRDY))
|
||||
dev->uart_status |= UART_STATUS_RXINT;
|
||||
|
||||
es1371_update_irqs(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_set_rx_irq(es1371_t *dev, int set)
|
||||
{
|
||||
dev->uart_status &= ~UART_STATUS_RXRDY;
|
||||
|
||||
if (set)
|
||||
dev->uart_status |= UART_STATUS_RXRDY;
|
||||
|
||||
es1371_update_rx_irq(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_scan_fifo(es1371_t *dev)
|
||||
{
|
||||
if (dev->read_fifo_pos != dev->write_fifo_pos) {
|
||||
dev->uart_data = dev->uart_fifo[dev->read_fifo_pos];
|
||||
dev->read_fifo_pos = (dev->read_fifo_pos + 1) & 7;
|
||||
|
||||
es1371_set_rx_irq(dev, 1);
|
||||
} else
|
||||
es1371_set_rx_irq(dev, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_write_fifo(es1371_t *dev, uint8_t val)
|
||||
{
|
||||
if (dev->write_fifo_pos < 8) {
|
||||
dev->uart_fifo[dev->write_fifo_pos] = val | UART_FIFO_BYTE_VALID;
|
||||
dev->write_fifo_pos = (dev->write_fifo_pos + 1) & 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_reset_fifo(es1371_t *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
dev->uart_fifo[i] = 0x00000000;
|
||||
|
||||
dev->read_fifo_pos = dev->write_fifo_pos = 0;
|
||||
|
||||
es1371_set_rx_irq(dev, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_reset(void *p)
|
||||
{
|
||||
es1371_t *dev = (es1371_t *) p;
|
||||
int i;
|
||||
|
||||
nmi = 0;
|
||||
|
||||
@@ -316,7 +406,14 @@ es1371_reset(void *p)
|
||||
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
dev->uart_fifo = 0xfffffe00;
|
||||
for (i = 0; i < 8; i++)
|
||||
dev->uart_fifo[i] = 0xffff0000;
|
||||
|
||||
/* Reset the UART TX. */
|
||||
es1371_set_tx_irq(dev, 0);
|
||||
|
||||
/* Reset the UART (RX) FIFO. */
|
||||
es1371_reset_fifo(dev);
|
||||
|
||||
/* Update interrupts to ensure they're all correctly cleared. */
|
||||
es1371_update_irqs(dev);
|
||||
@@ -344,7 +441,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
ret = dev->uart_fifo;
|
||||
audiopci_log("[30:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
|
||||
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -363,7 +463,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
ret = dev->uart_fifo;
|
||||
audiopci_log("[34:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
|
||||
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -377,7 +480,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
ret = dev->uart_fifo;
|
||||
audiopci_log("[38:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
|
||||
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -391,12 +497,19 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
ret = dev->uart_fifo;
|
||||
audiopci_log("[3C:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
|
||||
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (page == 0x0e || page == 0x0f) {
|
||||
audiopci_log("Read frame = %02x, page = %02x, uart fifo valid = %02x, temp = %03x\n", frame, page, dev->valid, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -420,7 +533,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
|
||||
audiopci_log("[30:%02X] dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -441,7 +556,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
|
||||
audiopci_log("[34:%02X] dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -455,7 +572,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
|
||||
audiopci_log("[38:%02X] dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -470,11 +589,17 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
|
||||
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
|
||||
Addressable as longword only */
|
||||
case 0xe: case 0xf:
|
||||
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
|
||||
audiopci_log("[3C:%02X] dev->uart_fifo[%02X] = %08X\n", page,
|
||||
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
|
||||
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (page == 0x0e || page == 0x0f) {
|
||||
audiopci_log("Write frame = %02x, page = %02x, uart fifo = %08x, val = %02x\n", frame, page, dev->uart_fifo, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -505,21 +630,27 @@ es1371_inb(uint16_t port, void *p)
|
||||
must be for a reason */
|
||||
case 0x04:
|
||||
ret = dev->int_status & 0xff;
|
||||
audiopci_log("[R] STATUS 0- 7 = %02X\n", ret);
|
||||
break;
|
||||
case 0x05:
|
||||
ret = (dev->int_status >> 8) & 0xff;
|
||||
audiopci_log("[R] STATUS 8-15 = %02X\n", ret);
|
||||
break;
|
||||
case 0x06:
|
||||
ret = (dev->int_status >> 16) & 0x0f;
|
||||
audiopci_log("[R] STATUS 16-23 = %02X\n", ret);
|
||||
break;
|
||||
case 0x07:
|
||||
ret = ((dev->int_status >> 24) & 0x03) | 0xfc;
|
||||
audiopci_log("[R] STATUS 24-31 = %02X\n", ret);
|
||||
break;
|
||||
|
||||
/* UART Data Register, Address 08H
|
||||
Addressable as byte only */
|
||||
case 0x08:
|
||||
ret = 0x00;
|
||||
ret = dev->uart_data;
|
||||
es1371_set_rx_irq(dev, 0);
|
||||
audiopci_log("[R] UART DATA = %02X\n", ret);
|
||||
break;
|
||||
|
||||
/* UART Status Register, Address 09H
|
||||
@@ -533,6 +664,7 @@ es1371_inb(uint16_t port, void *p)
|
||||
Addressable as byte only */
|
||||
case 0x0a:
|
||||
ret = dev->uart_res & 0x01;
|
||||
audiopci_log("[R] UART RES = %02X\n", ret);
|
||||
break;
|
||||
|
||||
/* Memory Page Register, Address 0CH
|
||||
@@ -661,6 +793,8 @@ es1371_inw(uint16_t port, void *p)
|
||||
break;
|
||||
}
|
||||
|
||||
audiopci_log("es1371_inw: port=%04x ret=%04x\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -682,6 +816,7 @@ es1371_inl(uint16_t port, void *p)
|
||||
Addressable as longword only */
|
||||
case 0x04:
|
||||
ret = dev->int_status;
|
||||
audiopci_log("[R] STATUS = %08X\n", ret);
|
||||
break;
|
||||
|
||||
/* Memory Page Register, Address 0CH
|
||||
@@ -783,22 +918,36 @@ es1371_outb(uint16_t port, uint8_t val, void *p)
|
||||
/* UART Data Register, Address 08H
|
||||
Addressable as byte only */
|
||||
case 0x08:
|
||||
audiopci_log("MIDI data = %02x\n", val);
|
||||
/* TX does not use FIFO. */
|
||||
midi_raw_out_byte(val);
|
||||
es1371_set_tx_irq(dev, 1);
|
||||
break;
|
||||
|
||||
/* UART Control Register, Address 09H
|
||||
Addressable as byte only */
|
||||
case 0x09:
|
||||
audiopci_log("[W] UART CTRL = %02X\n", val);
|
||||
dev->uart_ctrl = val & 0xe3;
|
||||
if ((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20)
|
||||
dev->int_status &= ~INT_STATUS_UART;
|
||||
es1371_update_irqs(dev);
|
||||
audiopci_log("ES1371 UART Cntrl = %02x\n", dev->uart_ctrl);
|
||||
|
||||
if ((val & 0x03) == 0x03) {
|
||||
/* Reset TX */
|
||||
es1371_set_tx_irq(dev, 1);
|
||||
|
||||
/* Software reset */
|
||||
es1371_reset_fifo(dev);
|
||||
} else {
|
||||
es1371_set_tx_irq(dev, 1);
|
||||
|
||||
es1371_update_tx_irq(dev);
|
||||
es1371_update_rx_irq(dev);
|
||||
}
|
||||
break;
|
||||
|
||||
/* UART Reserved Register, Address 0AH
|
||||
Addressable as byte only */
|
||||
case 0x0a:
|
||||
audiopci_log("[W] UART RES = %02X\n", val);
|
||||
dev->uart_res = val & 0x01;
|
||||
break;
|
||||
|
||||
@@ -965,6 +1114,7 @@ es1371_outl(uint16_t port, uint32_t val, void *p)
|
||||
/* Interrupt/Chip Select Status Register, Address 04H
|
||||
Addressable as longword only */
|
||||
case 0x04:
|
||||
audiopci_log("[W] STATUS = %08X\n", val);
|
||||
break;
|
||||
|
||||
/* Memory Page Register, Address 0CH
|
||||
@@ -1704,29 +1854,10 @@ es1371_poll(void *p)
|
||||
|
||||
timer_advance_u64(&dev->dac[1].timer, dev->dac[1].latch);
|
||||
|
||||
es1371_scan_fifo(dev);
|
||||
|
||||
es1371_update(dev);
|
||||
|
||||
if (dev->int_ctrl & INT_UART_EN) {
|
||||
//audiopci_log("UART INT Enabled\n");
|
||||
if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
|
||||
/* We currently don't implement MIDI Input.
|
||||
But if anything sets MIDI Input and Output together we'd have to take account
|
||||
of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is
|
||||
enabled as well but not in the MIDI Output portion */
|
||||
dev->int_status &= ~INT_STATUS_UART;
|
||||
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
|
||||
} else if (!(dev->uart_ctrl & UART_CTRL_RXINTEN) && ((dev->uart_ctrl & UART_CTRL_TXINTEN))) {
|
||||
/* Or enable the UART IRQ and the respective TX bits only when the MIDI Output is
|
||||
enabled */
|
||||
dev->int_status |= INT_STATUS_UART;
|
||||
} else {
|
||||
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
|
||||
}
|
||||
|
||||
//audiopci_log("UART control = %02x\n", dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN));
|
||||
es1371_update_irqs(dev);
|
||||
}
|
||||
|
||||
if (dev->int_ctrl & INT_DAC1_EN) {
|
||||
frac = dev->dac[0].ac & 0x7fff;
|
||||
idx = dev->dac[0].ac >> 15;
|
||||
@@ -1846,12 +1977,51 @@ generate_es1371_filter(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
es1371_input_msg(void *p, uint8_t *msg, uint32_t len)
|
||||
{
|
||||
es1371_t *dev = (es1371_t *)p;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
es1371_write_fifo(dev, msg[i]);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
es1371_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
|
||||
{
|
||||
es1371_t *dev = (es1371_t *)p;
|
||||
uint32_t i = -1;
|
||||
|
||||
audiopci_log("Abort = %i\n", abort);
|
||||
|
||||
if (dev->uart_status & UART_STATUS_RXRDY)
|
||||
abort = 1;
|
||||
|
||||
if (!abort) {
|
||||
for (i = 0; i < len; i++) {
|
||||
es1371_write_fifo(dev, buffer[i]);
|
||||
if (dev->uart_status & UART_STATUS_RXRDY)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The last sent position is in i. Return 7 - i. */
|
||||
|
||||
return 7 - i;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
es1371_init(const device_t *info)
|
||||
{
|
||||
es1371_t *dev = malloc(sizeof(es1371_t));
|
||||
memset(dev, 0x00, sizeof(es1371_t));
|
||||
|
||||
if (device_get_config_int("receive_input"))
|
||||
midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev);
|
||||
|
||||
sound_add_handler(es1371_get_buffer, dev);
|
||||
sound_set_cd_audio_filter(es1371_filter_cd_audio, dev);
|
||||
|
||||
@@ -1920,7 +2090,11 @@ static const device_config_t es1371_config[] =
|
||||
}
|
||||
},
|
||||
.default_int = AC97_CODEC_CS4297A
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <86box/filters.h>
|
||||
#include <86box/snd_mpu401.h>
|
||||
#include <86box/snd_opl.h>
|
||||
#include <86box/snd_sb.h>
|
||||
#include <86box/snd_sb_dsp.h>
|
||||
|
||||
|
||||
@@ -413,7 +414,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
if (!(val & 0x20))
|
||||
{
|
||||
if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pit.timer[0]) / PITCONST;;
|
||||
if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pas16->pit.timer[0]) / PITCONST;;
|
||||
if (val & 4) pas16->pit.rl[1] = pas16->pit.c[1];
|
||||
if (val & 8) pas16->pit.rl[2] = pas16->pit.c[2];
|
||||
}
|
||||
@@ -429,7 +430,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
if (!(pas16->pit.ctrl & 0x30))
|
||||
{
|
||||
if (!t)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
|
||||
else
|
||||
{
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
@@ -450,7 +451,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
pas16->pit.rm[t] = 3;
|
||||
if (!t)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
|
||||
else
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
}
|
||||
@@ -519,8 +520,8 @@ static uint8_t pas16_pit_in(uint16_t port, void *p)
|
||||
pas16->pit.rereadlatch[t] = 0;
|
||||
if (!t)
|
||||
{
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
|
||||
if ((timer_get_remaining_u64(&pit.timer[t]) / PITCONST) > 65536)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
|
||||
if ((timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST) > 65536)
|
||||
pas16->pit.rl[t] = 0xFFFF;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user