/********************************************************************** National Semiconductor ADC0808/ADC0809 8-Bit A/D Converter emulation Copyright MESS Team. Visit http://mamedev.org for licensing and usage restrictions. **********************************************************************/ #include "emu.h" #include "adc0808.h" //************************************************************************** // LIVE DEVICE //************************************************************************** // device type definition const device_type ADC0808 = &device_creator; //------------------------------------------------- // adc0808_device - constructor //------------------------------------------------- adc0808_device::adc0808_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, ADC0808, "ADC0808", tag, owner, clock), m_address(0), m_start(0), m_eoc(0), m_next_eoc(0), m_cycle(0), m_bit(0) { } //------------------------------------------------- // device_config_complete - perform any // operations now that the configuration is // complete //------------------------------------------------- void adc0808_device::device_config_complete() { // inherit a copy of the static data const adc0808_interface *intf = reinterpret_cast(static_config()); if (intf != NULL) *static_cast(this) = *intf; // or initialize to defaults if none provided else { memset(&m_out_eoc_cb, 0, sizeof(m_out_eoc_cb)); } } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void adc0808_device::device_start() { // resolve callbacks m_out_eoc_func.resolve(m_out_eoc_cb, *this); // allocate timers m_cycle_timer = timer_alloc(); m_cycle_timer->adjust(attotime::zero, 0, attotime::from_hz(clock())); // register for state saving save_item(NAME(m_address)); save_item(NAME(m_start)); save_item(NAME(m_eoc)); save_item(NAME(m_next_eoc)); save_item(NAME(m_sar)); save_item(NAME(m_cycle)); save_item(NAME(m_bit)); } //------------------------------------------------- // device_timer - handler timer events //------------------------------------------------- void adc0808_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { if (!m_start) { if (m_cycle == 7) { m_bit++; if (m_bit == 8) { /* sample input */ double vref_pos = m_in_vref_pos_func(this); double vref_neg = m_in_vref_neg_func(this); double input = m_in_in_func[m_address](this); m_sar = (255 * (input - vref_neg)) / (vref_pos - vref_neg); /* trigger end of conversion */ m_next_eoc = 1; } } } if (m_cycle == 0) { /* set end of conversion pin */ if (m_next_eoc != m_eoc) { m_out_eoc_func(m_next_eoc); m_eoc = m_next_eoc; } } m_cycle++; if (m_cycle == 8) { m_cycle = 0; } } //------------------------------------------------- // data_r - data read //------------------------------------------------- READ8_MEMBER( adc0808_device::data_r ) { return m_sar; } //------------------------------------------------- // ale_w - address write //------------------------------------------------- WRITE8_MEMBER( adc0808_device::ale_w ) { m_address = data; } //------------------------------------------------- // start_w - start conversion //------------------------------------------------- WRITE_LINE_MEMBER( adc0808_device::start_w ) { if (!m_start && state) // rising edge { // reset registers m_sar = 0; m_bit = 0; } else if (m_start && !state) // falling edge { // start conversion m_next_eoc = 0; } m_start = state; }