summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/mb87078.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/machine/mb87078.c')
-rw-r--r--src/emu/machine/mb87078.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/emu/machine/mb87078.c b/src/emu/machine/mb87078.c
new file mode 100644
index 00000000000..c98eccceccb
--- /dev/null
+++ b/src/emu/machine/mb87078.c
@@ -0,0 +1,169 @@
+/*****************************************************************************
+
+ MB87078 6-bit,4-channel electronic volume controller emulator
+
+ (for more detailed chip description see the mb87078.h file)
+
+ *****************************************************************************/
+
+#include "driver.h"
+#include "machine/mb87078.h"
+
+struct MB87078 {
+ const struct MB87078interface *intf;
+ int gain[4]; /* gain index 0-63,64,65 */
+ int channel_latch; /* current channel */
+ UINT8 latch[4*2]; /* 6bit+3bit 4 data latches */
+ UINT8 reset_comp;
+};
+
+static struct MB87078 chip[MAX_MB87078];
+
+static float MB87078_gain_decibel[66]={
+ 0.0, -0.5, -1.0, -1.5, -2.0, -2.5, -3.0, -3.5,
+ -4.0, -4.5, -5.0, -5.5, -6.0, -6.5, -7.0, -7.5,
+ -8.0, -8.5, -9.0, -9.5,-10.0,-10.5,-11.0,-11.5,
+ -12.0,-12.5,-13.0,-13.5,-14.0,-14.5,-15.0,-15.5,
+ -16.0,-16.5,-17.0,-17.5,-18.0,-18.5,-19.0,-19.5,
+ -20.0,-20.5,-21.0,-21.5,-22.0,-22.5,-23.0,-23.5,
+ -24.0,-24.5,-25.0,-25.5,-26.0,-26.5,-27.0,-27.5,
+ -28.0,-28.5,-29.0,-29.5,-30.0,-30.5,-31.0,-31.5,
+ -32.0, -256.0
+ };
+
+static int MB87078_gain_percent[66]={
+ 100,94,89,84,79,74,70,66,
+ 63,59,56,53,50,47,44,42,
+ 39,37,35,33,31,29,28,26,
+ 25,23,22,21,19,18,17,16,
+ 15,14,14,13,12,11,11,10,
+ 10, 9, 8, 8, 7, 7, 7, 6,
+ 6, 5, 5, 5, 5, 4, 4, 4,
+ 3, 3, 3, 3, 3, 2, 2, 2,
+ 2, 0
+};
+
+#define GAIN_MAX_INDEX 64
+#define GAIN_INFINITY_INDEX 65
+
+
+
+static int calc_gain_index(int data0, int data1)
+{
+//data 0: GD0-GD5
+//data 1: 1 2 4 8 16
+// c1 c2 EN C0 C32
+
+ if (!(data1&4))
+ {
+ return GAIN_INFINITY_INDEX;
+ }
+ else
+ {
+ if ((data1&16))
+ {
+ return GAIN_MAX_INDEX;
+ }
+ else
+ {
+ if ((data1&8))
+ {
+ return 0;
+ }
+ else
+ {
+ return (data0^0x3f);
+ }
+ }
+ }
+}
+
+
+static void gain_recalc(int which)
+{
+ struct MB87078 *c = chip + which;
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ int old_index = c->gain[i];
+ c->gain[i] = calc_gain_index(c->latch[i], c->latch[4+i]);
+ if (old_index != c->gain[i])
+ {
+ (*c->intf->gain_changed_cb)(i, MB87078_gain_percent[c->gain[i]] );
+ }
+ }
+}
+
+
+void MB87078_start(int which, const struct MB87078interface *intf)
+{
+ if (which >= MAX_MB87078) return;
+
+ chip[which].intf = intf;
+
+ /* reset chip */
+ MB87078_reset_comp_w(which,0);
+ MB87078_reset_comp_w(which,1);
+}
+
+
+void MB87078_stop(void)
+{
+ //int i;
+ //for (i = 0; i < MAX_MB87078; i++){ };
+}
+
+
+void MB87078_reset_comp_w(int which, int level)
+{
+ struct MB87078 *c = chip + which;
+
+ c->reset_comp = level;
+
+ /*this seems to be true, according to the datasheets*/
+ if (level==0)
+ {
+ c->latch[0] = 0x3f;
+ c->latch[1] = 0x3f;
+ c->latch[2] = 0x3f;
+ c->latch[3] = 0x3f;
+ c->latch[4] = 0x0 | 0x4;
+ c->latch[5] = 0x1 | 0x4;
+ c->latch[6] = 0x2 | 0x4;
+ c->latch[7] = 0x3 | 0x4;
+ }
+ gain_recalc(which);
+}
+
+
+void MB87078_data_w(int which, int data, int dsel)
+{
+ struct MB87078 *c = chip + which;
+
+ if (c->reset_comp==0) return;
+
+ if (dsel==0)
+ {/*gd0-gd5*/
+ c->latch[0+c->channel_latch] = data & 0x3f;
+ }
+ else
+ {/*dcs1,dsc2,en,c0,c32,X*/
+ c->channel_latch = data & 3;
+ c->latch[4+c->channel_latch] = data & 0x1f; //always zero bit 5
+ }
+ gain_recalc(which);
+}
+
+
+float MB87078_gain_decibel_r(int which, int channel)
+{
+ return MB87078_gain_decibel[ chip[which].gain[channel] ];
+}
+
+
+int MB87078_gain_percent_r(int which, int channel)
+{
+ return MB87078_gain_percent[ chip[which].gain[channel] ];
+}
+