summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/adc1213x.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/adc1213x.c')
-rw-r--r--trunk/src/emu/machine/adc1213x.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/adc1213x.c b/trunk/src/emu/machine/adc1213x.c
new file mode 100644
index 00000000000..38a589c122d
--- /dev/null
+++ b/trunk/src/emu/machine/adc1213x.c
@@ -0,0 +1,377 @@
+/***************************************************************************
+
+ National Semiconductor ADC12130 / ADC12132 / ADC12138
+
+ Self-calibrating 12-bit Plus Sign Serial I/O A/D Converters with MUX
+ and Sample/Hold
+
+ TODO:
+ - Only ADC12138 currently supported
+
+ 2009-06 Converted to be a device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "adc1213x.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _adc12138_state adc12138_state;
+struct _adc12138_state
+{
+ adc1213x_input_convert_func input_callback_r;
+
+ int cycle;
+ int data_out;
+ int data_in;
+ int conv_mode;
+ int auto_cal;
+ int auto_zero;
+ int acq_time;
+ int data_out_sign;
+ int mode;
+ int input_shift_reg;
+ int output_shift_reg;
+ int end_conv;
+};
+
+
+#define ADC1213X_CONV_MODE_12_MSB_FIRST 0
+#define ADC1213X_CONV_MODE_16_MSB_FIRST 1
+#define ADC1213X_CONV_MODE_12_LSB_FIRST 2
+#define ADC1213X_CONV_MODE_16_LSB_FIRST 3
+
+#define ADC1213X_ACQUISITION_TIME_6_CCLK 0
+#define ADC1213X_ACQUISITION_TIME_10_CCLK 1
+#define ADC1213X_ACQUISITION_TIME_18_CCLK 2
+#define ADC1213X_ACQUISITION_TIME_34_CCLK 3
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE adc12138_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == ADC12130) || (device->type() == ADC12132) || (device->type() == ADC12138));
+ return (adc12138_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const adc12138_interface *get_interface(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == ADC12130) || (device->type() == ADC12132) || (device->type() == ADC12138));
+ return (const adc12138_interface *) device->static_config();
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ adc1213x_di_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_di_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ adc1213x->data_in = data & 1;
+}
+
+/*-------------------------------------------------
+ adc1213x_convert
+-------------------------------------------------*/
+
+static void adc1213x_convert(device_t *device, int channel, int bits16, int lsbfirst)
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ int i;
+ int bits;
+ int input_value;
+ double input = 0;
+
+ if (bits16)
+ fatalerror("ADC1213X: 16-bit mode not supported\n");
+
+ if (lsbfirst)
+ fatalerror("ADC1213X: LSB first not supported\n");
+
+ switch (channel)
+ {
+ case 0x8: // H L L L - CH0 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 0);
+ break;
+ }
+ case 0xc: // H H L L - CH1 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 1);
+ break;
+ }
+ case 0x9: // H L L H - CH2 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 2);
+ break;
+ }
+ case 0xd: // H H L H - CH3 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 3);
+ break;
+ }
+ case 0xa: // H L H L - CH4 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 4);
+ break;
+ }
+ case 0xe: // H H H L - CH5 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 5);
+ break;
+ }
+ case 0xb: // H L H H - CH6 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 6);
+ break;
+ }
+ case 0xf: // H H H H - CH7 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 7);
+ break;
+ }
+ default:
+ {
+ fatalerror("ADC1213X: unsupported channel %02X\n", channel);
+ }
+ }
+
+ input_value = (int)(input * 2047.0);
+
+ bits = 12;
+
+ // sign-extend if needed
+ if (adc1213x->data_out_sign)
+ {
+ input_value = input_value | ((input_value & 0x800) << 1);
+ bits++;
+ }
+
+ adc1213x->output_shift_reg = 0;
+
+ for (i=0; i < bits; i++)
+ {
+ if (input_value & (1 << ((bits-1) - i)))
+ {
+ adc1213x->output_shift_reg |= (1 << i);
+ }
+ }
+
+ adc1213x->data_out = adc1213x->output_shift_reg & 1;
+ adc1213x->output_shift_reg >>= 1;
+}
+
+/*-------------------------------------------------
+ adc1213x_cs_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_cs_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ if (data)
+ {
+ //printf("ADC: CS\n");
+
+ if (adc1213x->cycle >= 7)
+ {
+ int mode = adc1213x->input_shift_reg >> (adc1213x->cycle - 8);
+
+ switch (mode & 0xf)
+ {
+ case 0x0: // X X X X L L L L - 12 or 13 Bit MSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 0, 0);
+ break;
+ }
+ case 0x1: // X X X X L L L H - 16 or 17 Bit MSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 1, 0);
+ break;
+ }
+ case 0x4: // X X X X L H L L - 12 or 13 Bit LSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 0, 1);
+ break;
+ }
+ case 0x5: // X X X X L H L H - 16 or 17 Bit LSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 1, 1);
+ break;
+ }
+
+ default:
+ {
+ switch (mode)
+ {
+ case 0x08: // L L L L H L L L - Auto cal
+ {
+ adc1213x->auto_cal = 1;
+ break;
+ }
+
+ case 0x0e: // L L L L H H H L - Acquisition time 6 CCLK cycles
+ {
+ adc1213x->acq_time = ADC1213X_ACQUISITION_TIME_6_CCLK;
+ break;
+ }
+
+ case 0x8d: // H L L L H H L H - Data out with sign
+ {
+ adc1213x->data_out_sign = 1;
+ break;
+ }
+
+ default:
+ {
+ fatalerror("ADC1213X: unknown config mode %02X\n", mode);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ adc1213x->cycle = 0;
+ adc1213x->input_shift_reg = 0;
+
+ adc1213x->end_conv = 0;
+ }
+}
+
+/*-------------------------------------------------
+ adc1213x_sclk_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_sclk_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ if (data)
+ {
+ //printf("ADC: cycle %d, DI = %d\n", adc1213x->cycle, adc1213x->data_in);
+
+ adc1213x->input_shift_reg <<= 1;
+ adc1213x->input_shift_reg |= adc1213x->data_in;
+
+ adc1213x->data_out = adc1213x->output_shift_reg & 1;
+ adc1213x->output_shift_reg >>= 1;
+
+ adc1213x->cycle++;
+ }
+}
+
+/*-------------------------------------------------
+ adc1213x_conv_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_conv_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ adc1213x->end_conv = 1;
+}
+
+/*-------------------------------------------------
+ adc1213x_do_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( adc1213x_do_r )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ //printf("ADC: DO\n");
+ return adc1213x->data_out;
+}
+
+/*-------------------------------------------------
+ adc1213x_eoc_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( adc1213x_eoc_r )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ return adc1213x->end_conv;
+}
+
+/*-------------------------------------------------
+ DEVICE_START( adc1213x )
+-------------------------------------------------*/
+
+static DEVICE_START( adc12138 )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ const adc12138_interface *intf = get_interface(device);
+
+ /* resolve callbacks */
+ adc1213x->input_callback_r = intf->input_callback_r;
+
+ /* register for state saving */
+ device->save_item(NAME(adc1213x->cycle));
+ device->save_item(NAME(adc1213x->data_out));
+ device->save_item(NAME(adc1213x->data_in));
+ device->save_item(NAME(adc1213x->conv_mode));
+ device->save_item(NAME(adc1213x->auto_cal));
+ device->save_item(NAME(adc1213x->auto_zero));
+ device->save_item(NAME(adc1213x->acq_time));
+ device->save_item(NAME(adc1213x->data_out_sign));
+ device->save_item(NAME(adc1213x->mode));
+ device->save_item(NAME(adc1213x->input_shift_reg));
+ device->save_item(NAME(adc1213x->output_shift_reg));
+ device->save_item(NAME(adc1213x->end_conv));
+}
+
+
+/*-------------------------------------------------
+ DEVICE_RESET( adc1213x )
+-------------------------------------------------*/
+
+static DEVICE_RESET( adc12138 )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ adc1213x->conv_mode = ADC1213X_CONV_MODE_12_MSB_FIRST;
+ adc1213x->data_out_sign = 1;
+ adc1213x->auto_cal = 0;
+ adc1213x->auto_zero = 0;
+ adc1213x->acq_time = ADC1213X_ACQUISITION_TIME_10_CCLK;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##adc12138##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "A/D Converter 12138"
+#define DEVTEMPLATE_FAMILY "National Semiconductor A/D Converters 1213x"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##adc12130##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converter 12130"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##adc12132##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converter 12132"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(ADC12130, adc12130);
+DEFINE_LEGACY_DEVICE(ADC12132, adc12132);
+DEFINE_LEGACY_DEVICE(ADC12138, adc12138);