// license:BSD-3-Clause // copyright-holders:Curt Coder /********************************************************************* mc146818.h Implementation of the MC146818 chip Real time clock chip with CMOS battery backed ram Used in IBM PC/AT, several PC clones, Amstrad NC200, Apollo workstations *********************************************************************/ #ifndef MAME_MACHINE_MC146818_H #define MAME_MACHINE_MC146818_H #pragma once //************************************************************************** // INTERFACE CONFIGURATION MACROS //************************************************************************** #define MCFG_MC146818_IRQ_HANDLER(_irq) \ devcb = &downcast(*device).set_irq_callback(DEVCB_##_irq); // The MC146818 doesn't have century support, but when syncing the date & time at startup we can optionally store the century. #define MCFG_MC146818_CENTURY_INDEX(_century_index) \ downcast(device)->set_century_index(_century_index); // The MC146818 doesn't have UTC support, but when syncing the data & time at startup we can use UTC instead of local time. #define MCFG_MC146818_UTC(_utc) \ downcast(device)->set_use_utc(_utc); #define MCFG_MC146818_BINARY(_bin) \ downcast(device)->set_binary(_bin); #define MCFG_MC146818_24_12(_hour) \ downcast(device)->set_hour(_hour); #define MCFG_MC146818_EPOCH(_epoch) \ downcast(device)->set_epoch(_epoch); #define MCFG_MC146818_BINARY_YEAR(_bin) \ downcast(device)->set_binary_year(_bin); //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // ======================> mc146818_device class mc146818_device : public device_t, public device_nvram_interface { public: // construction/destruction mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // callbacks template devcb_base &set_irq_callback(Object &&cb) { return m_write_irq.set_callback(std::forward(cb)); } void set_century_index(int century_index) { m_century_index = century_index; } void set_use_utc(bool use_utc) { m_use_utc = use_utc; } void set_binary(bool binary) { m_binary = binary; } void set_hour(bool hour) { m_hour = hour; } void set_epoch(int epoch) { m_epoch = epoch; } void set_binary_year(int bin) { m_binyear = bin; } // read/write access DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); protected: mc146818_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // 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_nvram_interface overrides virtual void nvram_default() override; virtual void nvram_read(emu_file &file) override; virtual void nvram_write(emu_file &file) override; static constexpr unsigned char ALARM_DONTCARE = 0xc0; static constexpr unsigned char HOURS_PM = 0x80; virtual int data_size() { return 64; } enum { REG_SECONDS = 0, REG_ALARM_SECONDS = 1, REG_MINUTES = 2, REG_ALARM_MINUTES = 3, REG_HOURS = 4, REG_ALARM_HOURS = 5, REG_DAYOFWEEK = 6, REG_DAYOFMONTH = 7, REG_MONTH = 8, REG_YEAR = 9, REG_A = 0xa, REG_B = 0xb, REG_C = 0xc, REG_D = 0xd }; enum { REG_A_RS0 = 1, REG_A_RS1 = 2, REG_A_RS2 = 4, REG_A_RS3 = 8, REG_A_DV0 = 16, REG_A_DV1 = 32, REG_A_DV2 = 64, REG_A_UIP = 128 }; enum { REG_B_DSE = 1, // TODO: When set the chip will adjust the clock by an hour at start and end of DST REG_B_24_12 = 2, REG_B_DM = 4, REG_B_SQWE = 8, // TODO: When set the chip will output a square wave on SQW pin REG_B_UIE = 16, REG_B_AIE = 32, REG_B_PIE = 64, REG_B_SET = 128 }; enum { REG_C_UF = 16, REG_C_AF = 32, REG_C_PF = 64, REG_C_IRQF = 128 }; enum { REG_D_VRT = 128 }; // internal helpers int to_ram(int a); int from_ram(int a); void set_base_datetime(); void update_irq(); void update_timer(); virtual int get_timer_bypass(); int get_seconds(); void set_seconds(int seconds); int get_minutes(); void set_minutes(int minutes); int get_hours(); void set_hours(int hours); int get_dayofweek(); void set_dayofweek(int dayofweek); int get_dayofmonth(); void set_dayofmonth(int dayofmonth); int get_month(); void set_month(int month); int get_year(); void set_year(int year); optional_memory_region m_region; // internal state uint8_t m_index; std::vector m_data; attotime m_last_refresh; static const device_timer_id TIMER_CLOCK = 0; static const device_timer_id TIMER_PERIODIC = 1; emu_timer *m_clock_timer; emu_timer *m_periodic_timer; devcb_write_line m_write_irq; int m_century_index, m_epoch; bool m_use_utc, m_binary, m_hour, m_binyear; }; // device type definition DECLARE_DEVICE_TYPE(MC146818, mc146818_device) #endif // MAME_MACHINE_MC146818_H