// license:BSD-3-Clause
// copyright-holders:Tim Schuerewegen, Ryan Holtz
/*********************************************************************
Philips PCF8583 Clock and Calendar with 240 x 8-bit RAM
**********************************************************************
The PCF8583 comes in three package configurations:
PCF8583P - 8-pin dual-inline package (DIP8)
PCF8583T - 8-pin small-outline package (SO8)
PCF8583BS - 20-pin thin quad-flat package (HVQFN20)
**********************************************************************
DIP8 pinning: ____ ____
| \/ |
OSCI 1 | | 8 Vdd
OSCI 2 | | 7 /INT
A0 3 | PCF8583P | 6 SCL
Vss 4 | | 5 SDA
|__________|
**********************************************************************
SO8 pinning: _____ _____
| | \/ |
OSCI 1 | | | 8 Vdd
OSCI 2 | | | 7 /INT
A0 3 | | PCF8583P | 6 SCL
Vss 4 | | | 5 SDA
|_|__________|
**********************************************************************
HVQFN20 pinning:
NC NC NC NC NC
20 19 18 17 16
__________________
| |
| __________ |
| | | |
NC 1 | | | | 15 Vdd
OSCI 2 | | | | 14 /INT
OSCO 3 | | PCF8583BS| | 13 SCL
A0 4 | | | | 12 SDA
Vss 5 | | | | 11 NC
| |__________| |
| |
|__________________|
6 7 8 9 10
NC NC NC NC NC
*********************************************************************/
#ifndef MAME_MACHINE_PCF8583_H
#define MAME_MACHINE_PCF8583_H
#pragma once
#include "dirtc.h"
class pcf8583_device : public device_t,
public device_rtc_interface,
public device_nvram_interface
{
public:
pcf8583_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 32'768);
auto irq() { return m_irq_callback.bind(); }
void set_a0(uint8_t a0);
DECLARE_WRITE_LINE_MEMBER(scl_w);
DECLARE_WRITE_LINE_MEMBER(sda_w);
DECLARE_READ_LINE_MEMBER(sda_r);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// device_rtc_interface overrides
virtual bool rtc_feature_y2k() const override { return true; }
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override;
// device_nvram_interface overrides
virtual void nvram_default() override;
virtual void nvram_read(emu_file &file) override;
virtual void nvram_write(emu_file &file) override;
private:
enum
{
REG_CONTROL = 0x00,
REG_HUNDREDTHS = 0x01,
REG_SECONDS = 0x02,
REG_MINUTES = 0x03,
REG_HOURS = 0x04,
REG_YEAR_DATE = 0x05,
REG_MONTH_DAY = 0x06,
REG_TIMER = 0x07,
REG_ALARM_CONTROL = 0x08,
REG_ALARM_HUNDREDTHS = 0x09,
REG_ALARM_SECONDS = 0x0a,
REG_ALARM_MINUTES = 0x0b,
REG_ALARM_HOURS = 0x0c,
REG_ALARM_DATE = 0x0d,
REG_ALARM_MONTH = 0x0e,
REG_ALARM_TIMER = 0x0f
};
enum
{
CONTROL_STOP_BIT = 0x80
};
static const device_timer_id TIMER_TICK = 0;
// get/set date
uint8_t get_date_year() { return (m_data[REG_YEAR_DATE] >> 6) & 3; }
void set_date_year(uint8_t year) { m_data[REG_YEAR_DATE] = (m_data[REG_YEAR_DATE] & 0x3f) | ((year % 4) << 6); }
uint8_t get_date_month() { return bcd_to_integer(m_data[6] & 0x1f); }
void set_date_month(uint8_t month) { m_data[REG_MONTH_DAY] = (m_data[REG_MONTH_DAY] & 0xe0) | (convert_to_bcd(month) & 0x1f); }
uint8_t get_date_day() { return bcd_to_integer(m_data[REG_YEAR_DATE] & 0x3f); }
void set_date_day(uint8_t day) { m_data[REG_YEAR_DATE] = (m_data[REG_YEAR_DATE] & 0xc0) | (convert_to_bcd(day) & 0x3f); }
// get/set time
uint8_t get_time_hour() { return bcd_to_integer(m_data[REG_HOURS]); }
void set_time_hour(uint8_t hour) { m_data[REG_HOURS] = convert_to_bcd(hour); }
uint8_t get_time_minute() { return bcd_to_integer(m_data[REG_MINUTES]); }
void set_time_minute(uint8_t minute){ m_data[REG_MINUTES] = convert_to_bcd(minute); }
uint8_t get_time_second() { return bcd_to_integer(m_data[REG_SECONDS]); }
void set_time_second(uint8_t second){ m_data[REG_SECONDS] = convert_to_bcd(second); }
void write_register(uint8_t offset, uint8_t data);
void advance_hundredths();
void clear_rx_buffer();
devcb_write_line m_irq_callback;
// internal state
uint8_t m_data[256];
int m_scl;
int m_sda;
int m_inp;
bool m_transfer_active;
int m_bit_index;
bool m_irq;
uint8_t m_data_recv_index;
uint8_t m_data_recv;
uint8_t m_mode;
uint8_t m_pos;
uint8_t m_write_address;
uint8_t m_read_address;
emu_timer * m_timer;
enum { RTC_MODE_NONE, RTC_MODE_SEND, RTC_MODE_RECV };
static constexpr uint8_t WRITE_ADDRESS_BASE = 0xa0;
static constexpr uint8_t READ_ADDRESS_BASE = 0xa1;
};
// device type definition
DECLARE_DEVICE_TYPE(PCF8583, pcf8583_device)
#endif // MAME_MACHINE_PCF8583_H