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

                                                    
                                                                                     
 


                                                                                 
 
                                                                                    
 
                                                
 
                     
 

                                                                                      
 



                                                                                           
 
                


                     
 
                                                                                      
 
                                                                                                             


                                                       
                  
 
 
 
                                                   




                                                   

                                          


                                    








                                                   
                     
 

 
 



                                                                            
                                       












                                                                            


                                                                            
                                                              
                                          




                                       
                                 


                    
                                 







                                                  

                                              

                                          
                                   

         
                                                                          


 
                                                   
                     
                                                    
 
                               
 
                                           
         
                                  

                                                    


                                                
                 


                         

                                  




                                                   
                        

                                                   
                               
 
                                           
         
                              


                         

                                  




                                                   
             

                                                   
                                  
 
                       
 
                                     
         
                                               
 
                                  
                 

                                                  




                              
                    




                                                   
                 

                                                   
                                   
 
                                                                               

                                                              

                            


                                                     
                                            
 
                                                                         













                                                                                               
                                                  




                                     

 
                                                   


                                                   
                                                























                                                          

                                              

                                               

                                                   
                                    
 
                         
                                                                                  
                         
 






                                      
                                               











                                                                  
                                                                                                           

                                                                              






                                                      
                                          







                                                        
 
// license:BSD-3-Clause
// copyright-holders:Tim Lindner, R. Belmont
/*****************************************************************************************

    ds1315.cpp

    Dallas Semiconductor's Phantom Time Chip DS1315.
    NOTE: writes are decoded, but the host's time will always be returned when asked.

    November 2017: R. Belmont added capability to emulate DS1216 and other DS121x
    parts where the clock sits in the same place as a ROM.  The backing callback
    returns the ROM contents when the RTC is locked.

    April 2015: chip enable / chip reset / phantom writes by Karl-Ludwig Deisenhofer

    November 2001: implementation by Tim Lindner

    HOW DOES IT WORK?

    READS: pattern recognition (64 bits in correct order). When RTC finally enables
    64 bits of data can be read. Chance of accidential pattern recognition is minimal.

    WRITES: two different locations (bits 0 and 1) are used to transfer data to the
    DS1315.   64 bit with time/date info are transmitted directly after recognition
    of the magic 64 bit pattern (see read above).
    **************************************************************************************/

#include "emu.h"
#include "ds1315.h"
#include "coreutil.h"


DEFINE_DEVICE_TYPE(DS1315, ds1315_device, "ds1315", "Dallas DS1315 Phantom Time Chip")

ds1315_device::ds1315_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, DS1315, tag, owner, clock),
	m_backing_read(*this),
	m_mode(),
	m_count(0)
{
}

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

void ds1315_device::device_start()
{
	m_backing_read.resolve_safe(0xff);

	save_item(NAME(m_count));
	save_item(NAME(m_mode));
	save_item(NAME(m_raw_data));
}


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

void ds1315_device::device_reset()
{
	chip_reset();
}



/***************************************************************************
    LOCAL VARIABLES
***************************************************************************/

static const uint8_t ds1315_pattern[] =
{
	1, 0, 1, 0, 0, 0, 1, 1,
	0, 1, 0, 1, 1, 1, 0, 0,
	1, 1, 0, 0, 0, 1, 0, 1,
	0, 0, 1, 1, 1, 0, 1, 0,
	1, 0, 1, 0, 0, 0, 1, 1,
	0, 1, 0, 1, 1, 1, 0, 0,
	1, 1, 0, 0, 0, 1, 0, 1,
	0, 0, 1, 1, 1, 0, 1, 0
};


/***************************************************************************
    IMPLEMENTATION
***************************************************************************/

// automated read, does all the work the real Dallas chip does
uint8_t ds1315_device::read(offs_t offset)
{
	if (m_mode == DS_SEEK_MATCHING)
	{
		if (offset & 1)
		{
			read_1();
		}
		else
		{
			read_0();
		}

		if (offset & 4)
		{
			m_count = 0;
			m_mode = DS_SEEK_MATCHING;
		}

		return m_backing_read(offset);
	}
	else if (m_mode == DS_CALENDAR_IO)
	{
		return read_data();
	}

	return 0xff;    // shouldn't happen, but compilers don't know that
}


/*-------------------------------------------------
 read_0 (actual data)
 -------------------------------------------------*/

uint8_t ds1315_device::read_0()
{
	if (ds1315_pattern[m_count++] == 0)
	{
		if (m_count == 64)
		{
			/* entire pattern matched */
			m_count = 0;
			m_mode = DS_CALENDAR_IO;
			fill_raw_data();
		}
		return 0;
	}

	m_count = 0;
	m_mode = DS_SEEK_MATCHING;
	return 0;
}


/*-------------------------------------------------
    read_1 (actual data)
-------------------------------------------------*/

uint8_t ds1315_device::read_1()
{
	if (ds1315_pattern[m_count++] == 1)
	{
		m_count %= 64;
		return 0;
	}

	m_count = 0;
	m_mode = DS_SEEK_MATCHING;
	return 0;
}


/*-------------------------------------------------
    read_data
-------------------------------------------------*/

uint8_t ds1315_device::read_data()
{
	uint8_t result;

	if (m_mode == DS_CALENDAR_IO)
	{
		result = m_raw_data[m_count++];

		if (m_count == 64)
		{
			m_mode = DS_SEEK_MATCHING;
			m_count = 0;
		}

		return result;
	}

	m_count = 0;
	return 0;
}


/*-------------------------------------------------
    fill_raw_data
-------------------------------------------------*/

void ds1315_device::fill_raw_data()
{
	/* This routine calls a standard 'C' library routine to get the current
	   date and time and then fill in the raw data struct.
	*/

	system_time systime;
	int raw[8], i, j;

	/* get the current date/time from the core */
	machine().current_datetime(systime);

	raw[0] = 0; /* tenths and hundreths of seconds are always zero */
	raw[1] = dec_2_bcd(systime.local_time.second);
	raw[2] = dec_2_bcd(systime.local_time.minute);
	raw[3] = dec_2_bcd(systime.local_time.hour);

	raw[4] = dec_2_bcd((systime.local_time.weekday != 0) ? systime.local_time.weekday : 7);
	raw[5] = dec_2_bcd(systime.local_time.mday);
	raw[6] = dec_2_bcd(systime.local_time.month + 1);
	raw[7] = dec_2_bcd(systime.local_time.year - 1900); /* Epoch is 1900 */

	/* Ok now we have the raw bcd bytes. Now we need to push them into our bit array */

	for (i = 0; i < 64; i++)
	{
		j = i / 8;
		m_raw_data[i] = (raw[j] & 0x0001);
		raw[j] = raw[j] >> 1;
	}
}




/*-------------------------------------------------
write_data
-------------------------------------------------*/

uint8_t ds1315_device::write_data(offs_t offset)
{
	static int write_count;
	if (write_count >= 64)
		write_count = 0;

	if (m_mode == DS_CALENDAR_IO)
	{
		m_raw_data[write_count++] = offset & 0x01;

		if (write_count == 64)
		{
			write_count = 0;

			m_mode = DS_SEEK_MATCHING;
			m_count = 0;
			input_raw_data();
		}
	}
	return 0; // ignore
}

/*-------------------------------------------------
  ds1315_input_raw_data

  Routine is called when new date and time has
  been written to the clock chip. Currently we
  ignore setting the date and time in the clock
  chip.
-------------------------------------------------*/

void ds1315_device::input_raw_data()
{
	int raw[8], i, j;
	raw[0] = raw[1] = raw[2] = raw[3] = raw[4] = raw[5] = raw[6] = raw[7] = 0;
	uint8_t flag = 1;

	for (i = 0; i < 64; i++)
	{
		j = i / 8;
		if ((i % 8) == 0)
			flag = 1;

		if (m_raw_data[i] & 1)
				raw[j] |= flag;
		flag <<= 1;
	}
	raw[0] = bcd_2_dec(raw[0]); // hundreds of seconds
	raw[1] = bcd_2_dec(raw[1]); // seconds (often set to zero)
	raw[2] = bcd_2_dec(raw[2]); // minute
	raw[3] = bcd_2_dec(raw[3]); // hour

	raw[4] = bcd_2_dec(raw[4]); // weekday (10 for Friday ?!)
	raw[5] = bcd_2_dec(raw[5]); // mday
	raw[6] = bcd_2_dec(raw[6]); // month
	raw[7] = bcd_2_dec(raw[7]); // year (two digits)

	logerror("\nDS1315 RTC INPUT (WILL BE IGNORED) mm/dd/yy  hh:mm:ss - %02d/%02d/%02d %02d/%02d/%02d",
				raw[6], raw[5], raw[7], raw[3], raw[2], raw[1]
			);
}

/*-------------------------------------------------
   query and reset chip status
   -------------------------------------------------*/
bool ds1315_device::chip_enable()
{
	return (m_mode == DS_CALENDAR_IO);
}

// Set a defined state (important for pattern detection)
void ds1315_device::chip_reset()
{
	memset(m_raw_data, 0, sizeof(m_raw_data));
	m_count = 0;
	m_mode = DS_SEEK_MATCHING;
}