summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/upd7002.cpp
blob: 69b9bb262ee2bd56876d7afe8bf2c7ae69a60003 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
                       
                                     













                                                                               
                      
 
                                                                     
 
                                                                                                               
                                                                                                                                        

 
 
                                                   



                                                   
 


                                                     





                                              

 
















                                                                              
 

                                     
 


                                  
 


                                                                                             
         







                                                                      
 

                                                                                                   
 

                                                                     
                                                            




                                               
                                                                                   



         
                                    
 


                           
                                        

                       
                                       

                               
                                       





                 
                                      
 





                                                                       




                                                                                                
 

                                                             
 

                                                                        

                                                                 
                                              

                                                             
                                                       
                                                    

                                                                                                  
                                                                                          

                                                              
                                                                    
 
                                       

                                                       
                                    

                                                       
                                                                                                            

                                                     
                                                                                                           








                                                                                                             


                                                                                                    


                      
// license:BSD-3-Clause
// copyright-holders:Gordon Jefferyes
/******************************************************************************
    uPD7002 Analogue to Digital Converter

    MESS Driver By:

    Gordon Jefferyes
    mess_bbc@gjeffery.dircon.co.uk

******************************************************************************/

#include "emu.h"
#include "upd7002.h"


/* Device Interface */

DEFINE_DEVICE_TYPE(UPD7002, upd7002_device, "upd7002", "uPD7002 ADC")

upd7002_device::upd7002_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, UPD7002, tag, owner, clock), m_status(0), m_data1(0), m_data0(0), m_digitalvalue(0), m_conversion_counter(0)
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void upd7002_device::device_start()
{
	m_get_analogue_cb.bind_relative_to(*owner());
	m_eoc_cb.bind_relative_to(*owner());

	// register for state saving
	save_item(NAME(m_status));
	save_item(NAME(m_data1));
	save_item(NAME(m_data0));
	save_item(NAME(m_digitalvalue));
	save_item(NAME(m_conversion_counter));
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void upd7002_device::device_reset()
{
	m_status = 0;
	m_data1 = 0;
	m_data0 = 0;
	m_digitalvalue = 0;
	m_conversion_counter = 0;
}


/*****************************************************************************
 Implementation
*****************************************************************************/


READ8_MEMBER( upd7002_device::eoc_r )
{
	return (m_status>>7)&0x01;
}


void upd7002_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch (id)
	{
	case TIMER_CONVERSION_COMPLETE:
		{
		int counter_value = param;
		if (counter_value==m_conversion_counter)
		{
			// this really always does a 12 bit conversion
			m_data1 = m_digitalvalue>>8;
			m_data0 = m_digitalvalue&0xf0;

			// set the status register with top 2 MSB, not busy and conversion complete
			m_status = (m_status & 0x0f)|((m_data1 & 0xc0)>>2)|0x40;

			// call the EOC function with EOC from status
			// eoc_r(0) this has just been set to 0
			if (!m_eoc_cb.isnull()) m_eoc_cb(0);
			m_conversion_counter=0;
		}
		break;
		}
	default:
		assert_always(false, "Unknown id in upd7002_device::device_timer");
	}
}


READ8_MEMBER( upd7002_device::read )
{
	switch(offset&0x03)
	{
		case 0:
			return m_status;

		case 1:
			return m_data1;

		case 2: case 3:
			return m_data0;
	}
	return 0;
}



WRITE8_MEMBER( upd7002_device::write )
{
	/* logerror("write to uPD7002 $%02X = $%02X\n",offset,data); */

	switch(offset&0x03)
	{
		case 0:
		/*
		Data Latch/AD start
		    D0 and D1 together define which one of the four input channels is selected
		    D2 flag input, normally set to 0????
		    D3 defines whether an 8 (0) or 12 (1) bit resolution conversion should occur
		    D4 to D7 not used.

		    an 8  bit conversion typically takes 4ms
		    an 12 bit conversion typically takes 10ms

		    writing to this register will initiate a conversion.
		*/

		/* set D6=0 busy ,D7=1 conversion not complete */
		m_status=(data & 0x0f) | 0x80;

		// call the EOC function with EOC from status
		// eoc_r(0) this has just been set to 1
		if (!m_eoc_cb.isnull()) m_eoc_cb(1);

		/* the uPD7002 works by sampling the analogue value at the start of the conversion
		   so it is read hear and stored until the end of the A to D conversion */

		// this function should return a 16 bit value.
		m_digitalvalue = m_get_analogue_cb(m_status & 0x03);

		m_conversion_counter++;

		// call a timer to start the conversion
		if (m_status & 0x08)
		{
			// 12 bit conversion takes 10ms
			timer_set(attotime::from_msec(10), TIMER_CONVERSION_COMPLETE, m_conversion_counter);
		} else {
			// 8 bit conversion takes 4ms
			timer_set(attotime::from_msec(4), TIMER_CONVERSION_COMPLETE, m_conversion_counter);
		}
		break;

		case 1: case 2:
		/* Nothing */
		break;

		case 3:
		/* Test Mode: Used for inspecting the device, The data input-output terminals assume an input
		      state and are connected to the A/D counter. Therefore, the A/D conversion data
		      read out after this is meaningless.
		*/
		break;
	}
}