summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/video/tlc34076.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/video/tlc34076.c')
-rw-r--r--trunk/src/emu/video/tlc34076.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/trunk/src/emu/video/tlc34076.c b/trunk/src/emu/video/tlc34076.c
new file mode 100644
index 00000000000..8c1af669457
--- /dev/null
+++ b/trunk/src/emu/video/tlc34076.c
@@ -0,0 +1,288 @@
+/***************************************************************************
+
+ tlc34076.c
+
+ Basic implementation of the TLC34076 palette chip and similar
+ compatible chips.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "tlc34076.h"
+
+#define PALETTE_WRITE_ADDR 0x00
+#define PALETTE_DATA 0x01
+#define PIXEL_READ_MASK 0x02
+#define PALETTE_READ_ADDR 0x03
+#define GENERAL_CONTROL 0x08
+#define INPUT_CLOCK_SEL 0x09
+#define OUTPUT_CLOCK_SEL 0x0a
+#define MUX_CONTROL 0x0b
+#define PALETTE_PAGE 0x0c
+#define TEST_REGISTER 0x0e
+#define RESET_STATE 0x0f
+
+typedef struct _tlc34076_state tlc34076_state;
+struct _tlc34076_state
+{
+ UINT8 local_paletteram[0x300];
+ UINT8 regs[0x10];
+ UINT8 palettedata[3];
+ UINT8 writeindex;
+ UINT8 readindex;
+ UINT8 dacbits;
+
+ rgb_t pens[0x100];
+};
+
+
+/*************************************
+ *
+ * Inline functions
+ *
+ *************************************/
+
+INLINE tlc34076_state *get_safe_token( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == TLC34076);
+
+ return (tlc34076_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+/*************************************
+ *
+ * Retrieve Current Palette
+ *
+ *************************************/
+
+const pen_t *tlc34076_get_pens(device_t *device)
+{
+ tlc34076_state *state = get_safe_token(device);
+ offs_t i;
+
+ for (i = 0; i < 0x100; i++)
+ {
+ int r, g, b;
+
+ if ((i & state->regs[PIXEL_READ_MASK]) == i)
+ {
+ r = state->local_paletteram[3 * i + 0];
+ g = state->local_paletteram[3 * i + 1];
+ b = state->local_paletteram[3 * i + 2];
+
+ if (state->dacbits == 6)
+ {
+ r = pal6bit(r);
+ g = pal6bit(g);
+ b = pal6bit(b);
+ }
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0;
+ }
+
+ state->pens[i] = MAKE_RGB(r, g, b);
+ }
+
+ return state->pens;
+}
+
+
+
+/*************************************
+ *
+ * State reset
+ *
+ *************************************/
+
+static DEVICE_RESET( tlc34076 )
+{
+ tlc34076_state *state = get_safe_token(device);
+
+ /* reset the registers */
+ state->regs[PIXEL_READ_MASK] = 0xff;
+ state->regs[GENERAL_CONTROL] = 0x03;
+ state->regs[INPUT_CLOCK_SEL] = 0x00;
+ state->regs[OUTPUT_CLOCK_SEL] = 0x3f;
+ state->regs[MUX_CONTROL] = 0x2d;
+ state->regs[PALETTE_PAGE] = 0x00;
+ state->regs[TEST_REGISTER] = 0x00;
+ state->regs[RESET_STATE] = 0x00;
+}
+
+
+/*************************************
+ *
+ * Read access
+ *
+ *************************************/
+
+READ8_DEVICE_HANDLER( tlc34076_r )
+{
+ tlc34076_state *state = get_safe_token(device);
+ UINT8 result;
+
+ /* keep in range */
+ offset &= 0x0f;
+ result = state->regs[offset];
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case PALETTE_DATA:
+ if (state->readindex == 0)
+ {
+ state->palettedata[0] = state->local_paletteram[3 * state->regs[PALETTE_READ_ADDR] + 0];
+ state->palettedata[1] = state->local_paletteram[3 * state->regs[PALETTE_READ_ADDR] + 1];
+ state->palettedata[2] = state->local_paletteram[3 * state->regs[PALETTE_READ_ADDR] + 2];
+ }
+ result = state->palettedata[state->readindex++];
+ if (state->readindex == 3)
+ {
+ state->readindex = 0;
+ state->regs[PALETTE_READ_ADDR]++;
+ }
+ break;
+ }
+
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * Write access
+ *
+ *************************************/
+
+WRITE8_DEVICE_HANDLER( tlc34076_w )
+{
+ tlc34076_state *state = get_safe_token(device);
+// UINT8 oldval;
+
+ /* keep in range */
+ offset &= 0x0f;
+// oldval = state->regs[offset];
+ state->regs[offset] = data;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case PALETTE_WRITE_ADDR:
+ state->writeindex = 0;
+ break;
+
+ case PALETTE_DATA:
+ state->palettedata[state->writeindex++] = data;
+ if (state->writeindex == 3)
+ {
+ state->local_paletteram[3 * state->regs[PALETTE_WRITE_ADDR] + 0] = state->palettedata[0];
+ state->local_paletteram[3 * state->regs[PALETTE_WRITE_ADDR] + 1] = state->palettedata[1];
+ state->local_paletteram[3 * state->regs[PALETTE_WRITE_ADDR] + 2] = state->palettedata[2];
+ state->writeindex = 0;
+ state->regs[PALETTE_WRITE_ADDR]++;
+ }
+ break;
+
+ case PALETTE_READ_ADDR:
+ state->readindex = 0;
+ break;
+
+ case GENERAL_CONTROL:
+ /*
+ 7 6 5 4 3 2 1 0
+ X X X X X X X 0 HSYNCOUT is active-low
+ X X X X X X X 1 HSYNCOUT is active-high (default)
+ X X X X X X 0 X VSYNCOUT is active-low
+ X X X X X X 1 X VSYNCOUT is active-high (default)
+ X X X X X 0 X X Disable split shift register transfer (default)
+ X X X X 0 1 X X Enable split shift register transfer
+ X X X X 0 X X X Disable special nibble mode (default)
+ X X X X 1 0 X X Enable special nibble mode
+ X X X 0 X X X X 0-IRE pedestal (default)
+ X X X 1 X X X X 7.5-IRE pedestal
+ X X 0 X X X X X Disable sync (default)
+ X X 1 X X X X X Enable sync
+ X 0 X X X X X X Little-endian mode (default)
+ X 1 X X X X X X Big-endian mode
+ 0 X X X X X X X MUXOUT is low (default)
+ 1 X X X X X X X MUXOUT is high
+ */
+ break;
+
+ case INPUT_CLOCK_SEL:
+ /*
+ 3 2 1 0
+ 0 0 0 0 Select CLK0 as clock source?
+ 0 0 0 1 Select CLK1 as clock source
+ 0 0 1 0 Select CLK2 as clock source
+ 0 0 1 1 Select CLK3 as TTL clock source
+ 0 1 0 0 Select CLK3 as TTL clock source
+ 1 0 0 0 Select CLK3 and CLK3 as ECL clock sources
+ */
+ break;
+
+ case OUTPUT_CLOCK_SEL:
+ /*
+ 0 0 0 X X X VCLK frequency = DOTCLK frequency
+ 0 0 1 X X X VCLK frequency = DOTCLK frequency/2
+ 0 1 0 X X X VCLK frequency = DOTCLK frequency/4
+ 0 1 1 X X X VCLK frequency = DOTCLK frequency/8
+ 1 0 0 X X X VCLK frequency = DOTCLK frequency/16
+ 1 0 1 X X X VCLK frequency = DOTCLK frequency/32
+ 1 1 X X X X VCLK output held at logic high level (default condition)
+ X X X 0 0 0 SCLK frequency = DOTCLK frequency
+ X X X 0 0 1 SCLK frequency = DOTCLK frequency/2
+ X X X 0 1 0 SCLK frequency = DOTCLK frequency/4
+ X X X 0 1 1 SCLK frequency = DOTCLK frequency/8
+ X X X 1 0 0 SCLK frequency = DOTCLK frequency/16
+ X X X 1 0 1 SCLK frequency = DOTCLK frequency/32
+ X X X 1 1 X SCLK output held at logic level low (default condition)
+ */
+ break;
+
+ case RESET_STATE:
+ DEVICE_RESET_CALL(tlc34076);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Device interface
+ *
+ *************************************/
+
+static DEVICE_START( tlc34076 )
+{
+ tlc34076_config *config = (tlc34076_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ tlc34076_state *state = get_safe_token(device);
+
+ state->dacbits = config->res_sel ? 8 : 6;
+
+ state_save_register_global_array(device->machine(), state->local_paletteram);
+ state_save_register_global_array(device->machine(), state->regs);
+ state_save_register_global_array(device->machine(), state->pens);
+
+ state_save_register_global(device->machine(), state->writeindex);
+ state_save_register_global(device->machine(), state->readindex);
+ state_save_register_global(device->machine(), state->dacbits);
+}
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID( p, s ) p##tlc34076##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET | DT_HAS_INLINE_CONFIG
+#define DEVTEMPLATE_NAME "TLC34076"
+#define DEVTEMPLATE_FAMILY "RAMDAC"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(TLC34076, tlc34076);