-/*\r
- Skelton for retropc emulator\r
-\r
- Author : Takeda.Toshiya\r
- Date : 2008.06.10-\r
-\r
- [ uPD4991A ]\r
-*/\r
-\r
-#include "upd4991a.h"\r
-#include "../fileio.h"\r
-\r
-void UPD4991A::initialize()\r
-{\r
- // initialize rtc\r
- memset(regs, 0, sizeof(regs));\r
- ctrl1 = ctrl2 = mode = 0;\r
- \r
- emu->get_host_time(&cur_time);\r
- read_from_cur_time();\r
- \r
- // register event\r
- register_event(this, 0, 1000000.0, true, ®ister_id);\r
-}\r
-\r
-void UPD4991A::write_io8(uint32 addr, uint32 data)\r
-{\r
- addr &= 0x0f;\r
- if(addr <= 12) {\r
- if(mode == 0 || mode == 3) {\r
- if(regs[0][addr] != data) {\r
- regs[0][addr] = data;\r
- write_to_cur_time();\r
- }\r
- } else if(mode == 1) {\r
- regs[1][addr] = data;\r
- } else if(mode == 2) {\r
- uint8 tmp = regs[2][addr] ^ data;\r
- regs[2][addr] = data;\r
- // am/pm is changed ?\r
- if(addr == 12 && (tmp & 8)) {\r
- read_from_cur_time();\r
- }\r
- } else {\r
- }\r
- } else if(addr == 13) {\r
- ctrl1 = data;\r
- } else if(addr == 14) {\r
- ctrl2 = data;\r
- } else if(addr == 15) {\r
- mode = data & 0x0b;\r
- }\r
-}\r
-\r
-uint32 UPD4991A::read_io8(uint32 addr)\r
-{\r
- addr &= 0x0f;\r
- if(addr <= 12) {\r
- if(mode == 0 || mode == 3) {\r
- return regs[0][addr];\r
- } else if(mode == 1 || mode == 2) {\r
- return regs[mode][addr];\r
- }\r
- } else if(addr == 14) {\r
- return ctrl2;\r
- }\r
- return 0x0f;\r
-}\r
-\r
-void UPD4991A::event_callback(int event_id, int err)\r
-{\r
- // update clock\r
- if(cur_time.initialized) {\r
- cur_time.increment();\r
- } else {\r
- emu->get_host_time(&cur_time); // resync\r
- cur_time.initialized = true;\r
- }\r
- \r
- if(!(ctrl1 & 8)) {\r
- read_from_cur_time();\r
- }\r
-}\r
-\r
-#define MODE_12H !(regs[2][12] & 8)\r
-\r
-void UPD4991A::read_from_cur_time()\r
-{\r
- int hour = MODE_12H ? (cur_time.hour % 12) : cur_time.hour;\r
- int ampm = (MODE_12H && cur_time.hour >= 12) ? 4 : 0;\r
- \r
- regs[0][ 0] = TO_BCD_LO(cur_time.second);\r
- regs[0][ 1] = TO_BCD_HI(cur_time.second);\r
- regs[0][ 2] = TO_BCD_LO(cur_time.minute);\r
- regs[0][ 3] = TO_BCD_HI(cur_time.minute);\r
- regs[0][ 4] = TO_BCD_LO(hour);\r
- regs[0][ 5] = TO_BCD_HI(hour) | ampm;\r
- regs[0][ 6] = cur_time.day_of_week;\r
- regs[0][ 7] = TO_BCD_LO(cur_time.day);\r
- regs[0][ 8] = TO_BCD_HI(cur_time.day);\r
- regs[0][ 9] = TO_BCD_LO(cur_time.month);\r
- regs[0][10] = TO_BCD_HI(cur_time.month);\r
- regs[0][11] = TO_BCD_LO(cur_time.year);\r
- regs[0][12] = TO_BCD_HI(cur_time.year);\r
- \r
- // TODO: check alarm\r
-}\r
-\r
-void UPD4991A::write_to_cur_time()\r
-{\r
- cur_time.second = regs[0][0] + (regs[0][1] & 7) * 10;\r
- cur_time.minute = regs[0][2] + (regs[0][3] & 7) * 10;\r
- if(MODE_12H) {\r
- cur_time.hour = regs[0][4] + (regs[0][5] & 1) * 10 + (regs[0][5] & 4 ? 12 : 0);\r
- } else {\r
- cur_time.hour = regs[0][4] + (regs[0][5] & 3) * 10;\r
- }\r
-// cur_time.day_of_week = regs[0][6];\r
- cur_time.day = regs[0][7] + (regs[0][8] & 3) * 10;\r
- cur_time.month = regs[0][9] + (regs[0][10] & 1) * 10;\r
- cur_time.year = regs[0][11] + regs[0][12] * 10;\r
- cur_time.update_year();\r
- cur_time.update_day_of_week();\r
- \r
- // restart event\r
- cancel_event(this, register_id);\r
- register_event(this, 0, 1000000.0, true, ®ister_id);\r
-}\r
-\r
-\r
-#define STATE_VERSION 1\r
-\r
-void UPD4991A::save_state(FILEIO* state_fio)\r
-{\r
- state_fio->FputUint32(STATE_VERSION);\r
- state_fio->FputInt32(this_device_id);\r
- \r
- cur_time.save_state((void *)state_fio);\r
- state_fio->FputInt32(register_id);\r
- state_fio->Fwrite(regs, sizeof(regs), 1);\r
- state_fio->FputUint8(ctrl1);\r
- state_fio->FputUint8(ctrl2);\r
- state_fio->FputUint8(mode);\r
-}\r
-\r
-bool UPD4991A::load_state(FILEIO* state_fio)\r
-{\r
- if(state_fio->FgetUint32() != STATE_VERSION) {\r
- return false;\r
- }\r
- if(state_fio->FgetInt32() != this_device_id) {\r
- return false;\r
- }\r
- if(!cur_time.load_state((void *)state_fio)) {\r
- return false;\r
- }\r
- register_id = state_fio->FgetInt32();\r
- state_fio->Fread(regs, sizeof(regs), 1);\r
- ctrl1 = state_fio->FgetUint8();\r
- ctrl2 = state_fio->FgetUint8();\r
- mode = state_fio->FgetUint8();\r
- return true;\r
-}\r
-\r
+/*
+ Skelton for retropc emulator
+
+ Author : Takeda.Toshiya
+ Date : 2008.06.10-
+
+ [ uPD4991A ]
+*/
+
+#include "upd4991a.h"
+#include "../fileio.h"
+
+void UPD4991A::initialize()
+{
+ // initialize rtc
+ memset(regs, 0, sizeof(regs));
+ ctrl1 = ctrl2 = mode = 0;
+
+ emu->get_host_time(&cur_time);
+ read_from_cur_time();
+
+ // register event
+ register_event(this, 0, 1000000.0, true, ®ister_id);
+}
+
+void UPD4991A::write_io8(uint32 addr, uint32 data)
+{
+ addr &= 0x0f;
+ if(addr <= 12) {
+ if(mode == 0 || mode == 3) {
+ if(regs[0][addr] != data) {
+ regs[0][addr] = data;
+ write_to_cur_time();
+ }
+ } else if(mode == 1) {
+ regs[1][addr] = data;
+ } else if(mode == 2) {
+ uint8 tmp = regs[2][addr] ^ data;
+ regs[2][addr] = data;
+ // am/pm is changed ?
+ if(addr == 12 && (tmp & 8)) {
+ read_from_cur_time();
+ }
+ } else {
+ }
+ } else if(addr == 13) {
+ ctrl1 = data;
+ } else if(addr == 14) {
+ ctrl2 = data;
+ } else if(addr == 15) {
+ mode = data & 0x0b;
+ }
+}
+
+uint32 UPD4991A::read_io8(uint32 addr)
+{
+ addr &= 0x0f;
+ if(addr <= 12) {
+ if(mode == 0 || mode == 3) {
+ return regs[0][addr];
+ } else if(mode == 1 || mode == 2) {
+ return regs[mode][addr];
+ }
+ } else if(addr == 14) {
+ return ctrl2;
+ }
+ return 0x0f;
+}
+
+void UPD4991A::event_callback(int event_id, int err)
+{
+ // update clock
+ if(cur_time.initialized) {
+ cur_time.increment();
+ } else {
+ emu->get_host_time(&cur_time); // resync
+ cur_time.initialized = true;
+ }
+
+ if(!(ctrl1 & 8)) {
+ read_from_cur_time();
+ }
+}
+
+#define MODE_12H !(regs[2][12] & 8)
+
+void UPD4991A::read_from_cur_time()
+{
+ int hour = MODE_12H ? (cur_time.hour % 12) : cur_time.hour;
+ int ampm = (MODE_12H && cur_time.hour >= 12) ? 4 : 0;
+
+ regs[0][ 0] = TO_BCD_LO(cur_time.second);
+ regs[0][ 1] = TO_BCD_HI(cur_time.second);
+ regs[0][ 2] = TO_BCD_LO(cur_time.minute);
+ regs[0][ 3] = TO_BCD_HI(cur_time.minute);
+ regs[0][ 4] = TO_BCD_LO(hour);
+ regs[0][ 5] = TO_BCD_HI(hour) | ampm;
+ regs[0][ 6] = cur_time.day_of_week;
+ regs[0][ 7] = TO_BCD_LO(cur_time.day);
+ regs[0][ 8] = TO_BCD_HI(cur_time.day);
+ regs[0][ 9] = TO_BCD_LO(cur_time.month);
+ regs[0][10] = TO_BCD_HI(cur_time.month);
+ regs[0][11] = TO_BCD_LO(cur_time.year);
+ regs[0][12] = TO_BCD_HI(cur_time.year);
+
+ // TODO: check alarm
+}
+
+void UPD4991A::write_to_cur_time()
+{
+ cur_time.second = regs[0][0] + (regs[0][1] & 7) * 10;
+ cur_time.minute = regs[0][2] + (regs[0][3] & 7) * 10;
+ if(MODE_12H) {
+ cur_time.hour = regs[0][4] + (regs[0][5] & 1) * 10 + (regs[0][5] & 4 ? 12 : 0);
+ } else {
+ cur_time.hour = regs[0][4] + (regs[0][5] & 3) * 10;
+ }
+// cur_time.day_of_week = regs[0][6];
+ cur_time.day = regs[0][7] + (regs[0][8] & 3) * 10;
+ cur_time.month = regs[0][9] + (regs[0][10] & 1) * 10;
+ cur_time.year = regs[0][11] + regs[0][12] * 10;
+ cur_time.update_year();
+ cur_time.update_day_of_week();
+
+ // restart event
+ cancel_event(this, register_id);
+ register_event(this, 0, 1000000.0, true, ®ister_id);
+}
+
+
+#define STATE_VERSION 1
+
+void UPD4991A::save_state(FILEIO* state_fio)
+{
+ state_fio->FputUint32(STATE_VERSION);
+ state_fio->FputInt32(this_device_id);
+
+ cur_time.save_state((void *)state_fio);
+ state_fio->FputInt32(register_id);
+ state_fio->Fwrite(regs, sizeof(regs), 1);
+ state_fio->FputUint8(ctrl1);
+ state_fio->FputUint8(ctrl2);
+ state_fio->FputUint8(mode);
+}
+
+bool UPD4991A::load_state(FILEIO* state_fio)
+{
+ if(state_fio->FgetUint32() != STATE_VERSION) {
+ return false;
+ }
+ if(state_fio->FgetInt32() != this_device_id) {
+ return false;
+ }
+ if(!cur_time.load_state((void *)state_fio)) {
+ return false;
+ }
+ register_id = state_fio->FgetInt32();
+ state_fio->Fread(regs, sizeof(regs), 1);
+ ctrl1 = state_fio->FgetUint8();
+ ctrl2 = state_fio->FgetUint8();
+ mode = state_fio->FgetUint8();
+ return true;
+}
+