summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/pcf8593.cpp
blob: 77527bf462174193edaa50e7b368fc1868e36686 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                       
                                     







                                                                      
                









                                                                               
               





                                                                                   

               





                                                              

 


                                                                            
 
                                                            

 


                                                   
 
                                                                                                               
                                                                                            



                                                      

 


                                                   
 
                                   
 



                                                                                 

 


                                                   
 




                                           
                          






                                                                                                                                                
 
 




                                                                                             
 









                                                                                
 












                                                                                                                       


 



                                                   
 








                                                   
 
                                               
 

                                          
 








                                                   







                                                   
                                        
 
                   
                                                  
         
                               




                                            

                                                                                                                                  
                                              
                                               
                                 
                                                                                                                      
                                                                                  
                                                                                                 
                                         
                                                                       

                                                                               
                                                                                                 
                                         
                                                                       

                                                                    
                                                                                                 
                                         
                                                                         

                                                                                                   
                                                                                                                      

                                                                                                                                                                                         

                                                    

                                                            






                                            

                                                                            
                                              
                                               
                                 
                                                                                                    
                                                
                                                      

                                                                                 

                                                                       

                                                    

                                                   





                                 
                          







                                                   
                                        
 
                        
                      

                               
                                                                 
                                                                   
                                            

                                                                     
                                                 



                                              

                                                                  
                                            

                                                                    
                                         


                   
                          







                                                   
                                       
 
                     







                                                   
                                      
 

                                                         
 
// license:BSD-3-Clause
// copyright-holders:Tim Schuerewegen
/*********************************************************************

    Philips PCF8593 CMOS clock/calendar circuit

    (c) 2001-2007 Tim Schuerewegen

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

#include "emu.h"
#include "pcf8593.h"


/***************************************************************************
    PARAMETERS/CONSTANTS/MACROS
***************************************************************************/

#define LOG_LEVEL  1
#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)

// get/set date
#define RTC_GET_DATE_YEAR       ((m_data[5] >> 6) & 3)
#define RTC_SET_DATE_YEAR(x)    m_data[5] = (m_data[5] & 0x3F) | (((x) % 4) << 6)
#define RTC_GET_DATE_MONTH      bcd_to_integer( m_data[6])
#define RTC_SET_DATE_MONTH(x)   m_data[6] = convert_to_bcd( x)
#define RTC_GET_DATE_DAY        (bcd_to_integer( m_data[5] & 0x3F))
#define RTC_SET_DATE_DAY(x)     m_data[5] = (m_data[5] & 0xC0) | convert_to_bcd( x)

// get/set time
#define RTC_GET_TIME_HOUR       bcd_to_integer( m_data[4])
#define RTC_SET_TIME_HOUR(x)    m_data[4] = convert_to_bcd( x)
#define RTC_GET_TIME_MINUTE     bcd_to_integer( m_data[3])
#define RTC_SET_TIME_MINUTE(x)  m_data[3] = convert_to_bcd( x)
#define RTC_GET_TIME_SECOND     bcd_to_integer( m_data[2])
#define RTC_SET_TIME_SECOND(x)  m_data[2] = convert_to_bcd( x)


//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

const device_type PCF8593 = &device_creator<pcf8593_device>;


//-------------------------------------------------
//  pcf8593_device - constructor
//-------------------------------------------------

pcf8593_device::pcf8593_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, PCF8593, "PCF8593 RTC", tag, owner, clock, "pcf8593", __FILE__),
		device_rtc_interface(mconfig, *this),
		device_nvram_interface(mconfig, *this)
{
}


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

void pcf8593_device::device_start()
{
	_logerror( 0, ("pcf8593_init\n"));
	memset(m_register, 0, sizeof(m_register));
	m_timer = timer_alloc(TIMER_UPDATE_COUNTER);
	m_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
}

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

void pcf8593_device::device_reset()
{
	_logerror( 0, ("pcf8593_reset\n"));
	m_pin_scl = 1;
	m_pin_sda = 1;
	m_active  = false;
	m_inp     = 0;
	m_mode    = RTC_MODE_RECV;
	m_bits    = 0;
	m_pos     = 0;
	clear_buffer_rx();
	set_time(true, RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH, RTC_GET_DATE_DAY, 0, RTC_GET_TIME_HOUR, RTC_GET_TIME_MINUTE, RTC_GET_TIME_SECOND);
}


//-------------------------------------------------
//  device_timer - handler timer events
//-------------------------------------------------

void pcf8593_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch(id)
	{
		case TIMER_UPDATE_COUNTER:
			_logerror( 2, ("pcf8593_timer_callback (%d)\n", param));
			// check if counting is enabled
			if (!(m_data[0] & 0x80))
				advance_seconds();
			break;
	}
}


//-------------------------------------------------
//  rtc_clock_updated -
//-------------------------------------------------

void pcf8593_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
{
	RTC_SET_TIME_SECOND(second);
	RTC_SET_TIME_MINUTE(minute);
	RTC_SET_TIME_HOUR(hour);
	RTC_SET_DATE_DAY(day);
	RTC_SET_DATE_MONTH(month);
	RTC_SET_DATE_YEAR(year);
}


//-------------------------------------------------
//  nvram_default - called to initialize NVRAM to
//  its default state
//-------------------------------------------------

void pcf8593_device::nvram_default()
{
	memset(m_data, 0, sizeof(m_data));
}

//-------------------------------------------------
//  nvram_read - called to read NVRAM from the
//  .nv file
//-------------------------------------------------

void pcf8593_device::nvram_read(emu_file &file)
{
	file.read(m_data, sizeof(m_data));
}


//-------------------------------------------------
//  nvram_write - called to write NVRAM to the
//  .nv file
//-------------------------------------------------

void pcf8593_device::nvram_write(emu_file &file)
{
	file.write(m_data, sizeof(m_data));
}



/*-------------------------------------------------
    pcf8593_pin_scl
-------------------------------------------------*/

WRITE_LINE_MEMBER(pcf8593_device::scl_w)
{
	// send bit
	if ((m_active) && (!m_pin_scl) && (state))
	{
		switch (m_mode)
		{
			// HOST -> RTC
			case RTC_MODE_RECV :
			{
				// get bit
				if (m_pin_sda) m_data_recv[m_data_recv_index] = m_data_recv[m_data_recv_index] | (0x80 >> m_bits);
				m_bits++;
				// bit 9 = end
				if (m_bits > 8)
				{
					_logerror( 2, ("pcf8593_write_byte(%02X)\n", m_data_recv[m_data_recv_index]));
					// enter receive mode when 1st byte = 0xA3
					if ((m_data_recv[0] == 0xA3) && (m_data_recv_index == 0))
					{
						m_mode = RTC_MODE_SEND;
					}
					// A2 + xx = "read from pos xx" command
					if ((m_data_recv[0] == 0xA2) && (m_data_recv_index == 1))
					{
						m_pos = m_data_recv[1];
					}
					// A2 + xx + .. = write byte
					if ((m_data_recv[0] == 0xA2) && (m_data_recv_index >= 2))
					{
						uint8_t rtc_pos, rtc_val;
						rtc_pos = m_data_recv[1] + (m_data_recv_index - 2);
						rtc_val = m_data_recv[m_data_recv_index];
						//if (rtc_pos == 0) rtc_val = rtc_val & 3; // what is this doing here?
						m_data[rtc_pos] = rtc_val;
						set_time(false, RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH, RTC_GET_DATE_DAY, 0, RTC_GET_TIME_HOUR, RTC_GET_TIME_MINUTE, RTC_GET_TIME_SECOND);
					}
					// next byte
					m_bits = 0;
					m_data_recv_index++;
				}
			}
			break;
			// RTC -> HOST
			case RTC_MODE_SEND :
			{
				// set bit
				m_inp = (m_data[m_pos] >> (7 - m_bits)) & 1;
				m_bits++;
				// bit 9 = end
				if (m_bits > 8)
				{
					_logerror( 2, ("pcf8593_read_byte(%02X)\n", m_data[m_pos]));
					// end ?
					if (m_pin_sda)
					{
						_logerror( 2, ("pcf8593 end\n"));
						m_mode = RTC_MODE_RECV;
						clear_buffer_rx();
					}
					// next byte
					m_bits = 0;
					m_pos++;
				}
			}
			break;
		}
	}
	// save scl
	m_pin_scl = state;
}



/*-------------------------------------------------
    pcf8593_pin_sda_w
-------------------------------------------------*/

WRITE_LINE_MEMBER(pcf8593_device::sda_w)
{
	// clock is high
	if (m_pin_scl)
	{
		// log init I2C
		if (state) _logerror( 1, ("pcf8593 init i2c\n"));
		// start condition (high to low when clock is high)
		if ((!state) && (m_pin_sda))
		{
			_logerror( 1, ("pcf8593 start condition\n"));
			m_active          = true;
			m_bits            = 0;
			m_data_recv_index = 0;
			clear_buffer_rx();
			//m_pos = 0;
		}
		// stop condition (low to high when clock is high)
		if ((state) && (!m_pin_sda))
		{
			_logerror( 1, ("pcf8593 stop condition\n"));
			m_active = false;
		}
	}
	// save sda
	m_pin_sda = state;
}



/*-------------------------------------------------
    pcf8593_pin_sda_r
-------------------------------------------------*/

READ_LINE_MEMBER(pcf8593_device::sda_r)
{
	return m_inp;
}



/*-------------------------------------------------
    pcf8593_clear_buffer_rx
-------------------------------------------------*/

void pcf8593_device::clear_buffer_rx()
{
	memset(&m_data_recv[0], 0, sizeof( m_data_recv));
	m_data_recv_index = 0;
}