File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / rp5c15.h
Revision 1.1.1.17 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:00 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

//
// RTC (RP5C15)
//

#pragma once

#include "rtc.h"

class MFPDevice;
class X68030PowerDevice;

struct RP5C15
{
	// レジスタ 13, 14, 15 は Bank0/Bank1 どちらも同じものが見える。
	// これらのレジスタは Bank1 だったら Bank0 を見せる。
	//
	// RTC の未使用ビットは、RTC への書き込み時に未使用ビットを
	// mask[] で '0' にマスクしてから変数に書き込むこと。
	union {
		uint8 r[16 + 13];
		struct {
			uint8 sec1;
			uint8 sec10;
			uint8 min1;
			uint8 min10;
			uint8 hour1;
			uint8 hour10;
			uint8 wday;
			uint8 day1;
			uint8 day10;
			uint8 mon1;
			uint8 mon10;
			uint8 year1;
			uint8 year10;
			uint8 mode;
			uint8 test;
			uint8 reset;

			uint8 clksel;
			uint8 adjust;
			uint8 alarm_min1;
			uint8 alarm_min10;
			uint8 alarm_hour1;
			uint8 alarm_hour10;
			uint8 alarm_wday;
			uint8 alarm_day1;
			uint8 alarm_day10;
			uint8 padding1;
			uint8 sel24;
			uint8 leap;
			uint8 padding2;
		} __packed;
	};

	// レジスタマスク (有効ビットを '1' としたもの)
	static const uint8 mask[16 + 13];

	// バンク0
	static const uint SEC1			= 0x00;	// $E8A001
	static const uint SEC10			= 0x01;	// $E8A003
	static const uint MIN1			= 0x02;	// $E8A005
	static const uint MIN10			= 0x03;	// $E8A007
	static const uint HOUR1			= 0x04;	// $E8A009
	static const uint HOUR10		= 0x05;	// $E8A00B
	static const uint WDAY			= 0x06;	// $E8A00D
	static const uint DAY1			= 0x07;	// $E8A00F
	static const uint DAY10			= 0x08;	// $E8A011
	static const uint MON1			= 0x09;	// $E8A013
	static const uint MON10			= 0x0a;	// $E8A015
	static const uint YEAR1			= 0x0b;	// $E8A017
	static const uint YEAR10		= 0x0c;	// $E8A019
	static const uint MODE			= 0x0d;	// $E8A01B
	static const uint TEST			= 0x0e;	// $E8A01D
	static const uint RESET			= 0x0f;	// $E8A01F
	// バンク1
	static const uint CLKSEL		= 0x10;	// $E8A001
	static const uint ADJUST		= 0x11;	// $E8A003
	static const uint ALARM_MIN1	= 0x12;	// $E8A005
	static const uint ALARM_MIN10	= 0x13;	// $E8A007
	static const uint ALARM_HOUR1	= 0x14;	// $E8A009
	static const uint ALARM_HOUR10	= 0x15;	// $E8A00B
	static const uint ALARM_WDAY	= 0x16;	// $E8A00D
	static const uint ALARM_DAY1	= 0x17;	// $E8A00F
	static const uint ALARM_DAY10	= 0x18;	// $E8A011
	static const uint notused1		= 0x19;	// $E8A013
	static const uint SEL24			= 0x1a;	// $E8A015
	static const uint LEAP			= 0x1b;	// $E8A017
	static const uint notused2		= 0x1c;	// $E8A019
	// バンク1 の 13, 14, 15 はバンク0 と共通
	static const uint MODE_BANK1	= 0x1d;	// $E8A01B
	static const uint TEST_BANK1	= 0x1e;	// $E8A01D
	static const uint RESET_BANK1	= 0x1f;	// $E8A01F

	static const uint MODE_TIMER_EN	= 0x08;
	static const uint MODE_ALARM_EN	= 0x04;
	static const uint MODE_BANK		= 0x01;

	static const uint RESET_1Hz		= 0x08;
	static const uint RESET_16Hz	= 0x04;
	static const uint RESET_TIMER	= 0x02;
	static const uint RESET_ALARM	= 0x01;
};

class RP5C15Device : public RTCDevice
{
	using inherited = RTCDevice;
 public:
	RP5C15Device();
	~RP5C15Device() override;

	bool Init() override;

	uint GetSec() const override;	// 秒(0-59)
	uint GetMin() const override;	// 分(0-59)
	uint GetHour() const override;	// 時(0-23)
	uint GetWday() const override;	// 曜日(0が日曜)
	uint GetMday() const override;	// 日(1-31)
	uint GetMon() const override;	// 月(1-12)
	uint GetYear() const override;	// 年(西暦)
	uint GetLeap() const override;	// うるう年カウンタ(0..3)

 protected:
	// BusIO インタフェース
	static const uint32 NPORT = 16;
	busdata ReadPort(uint32 offset);
	busdata WritePort(uint32 offset, uint32 data);
	busdata PeekPort(uint32 offset);
	bool PokePort(uint32 offset, uint32 data);

	// 仮想 RTC からのクロック
	void Tick32Hz() override;
	void Tick2Hz() override;
	void Tick1Hz() override;

	void SetSec(uint v) override;
	void SetMin(uint v) override;
	void SetHour(uint v) override;
	void SetWday(uint v) override;
	void SetMday(uint v) override;
	void SetMon(uint v) override;
	void SetYear(uint v) override;
	void SetLeap(uint v) override;

 private:
	void ChangeAlarmOut();

	DECLARE_MONITOR_SCREEN(MonitorScreen);

	// レジスタ
	RP5C15 reg {};

	// CLKOUT 端子の状態 (true なら 'H')
	bool clkout {};

	// 分周段から秒カウンタへのカウントアップホールド内部信号。
	bool clock_hold {};

	// CLKOUT 1/60Hz 用の 60秒カウンタ。カレンダとは独立。
	uint32 cnt_60sec {};

	// アラーム端子出力。
	// ALARM 端子は負論理(Low active) だが、ここでは
	// アサート(L) のとき true とする。
	bool alarm_out {};

	// 内部アラーム 16Hz 信号。CLKOUT、alarm_1Hz とは独立。
	bool alarm_16Hz {};
	// 内部アラーム 1Hz 信号。CLKOUT、alarm_16Hz とは独立。
	bool alarm_1Hz {};
	// アラーム時刻一致信号。
	// XXX アラーム機能自体は未実装。
	bool alarm_on {};

	MFPDevice *mfp {};
	X68030PowerDevice *power {};

	Monitor *monitor {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.