OSDN Git Service

[VM][STATE] Apply new framework to some VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / msm58321.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2008.05.02-
6
7         [ MSM58321/MSM5832 ]
8 */
9
10 #include "vm.h"
11 #include "../emu.h"
12 #include "msm58321.h"
13
14 #define EVENT_BUSY      0
15 #define EVENT_INC       1
16 #define EVENT_PULSE     2
17
18 #if defined(Q_OS_WIN)
19 DLL_PREFIX_I struct cur_time_s cur_time;
20 #endif
21
22 MSM58321::MSM58321(VM_TEMPLATE* parent_vm, EMU* parent_emu) : MSM58321_BASE(parent_vm, parent_emu)
23 {
24                 initialize_output_signals(&outputs_busy);
25                 set_device_name(_T("MSM58321 RTC"));
26 }
27
28 void MSM58321::initialize()
29 {
30         DEVICE::initialize();
31         // init rtc
32         memset(regs, 0, sizeof(regs));
33         regs[5] = 8; // 24h
34         regs[15] = 0x0f;
35         wreg = regnum = 0;
36         cs = true;
37         rd = wr = addr_wr = busy = hold = false;
38         count_1024hz = count_1s = count_1m = count_1h = 0;
39         
40         get_host_time(&cur_time);
41         read_from_cur_time();
42         
43         // register events
44 #ifdef MSM58321_START_DAY
45         start_day = MSM58321_START_DAY;
46 #endif
47 #ifdef MSM58321_START_YEAR
48         start_year = MSM58321_START_YEAR;
49 #endif
50         register_event(this, EVENT_BUSY, 1000000.0, true, &register_id);
51         register_event(this, EVENT_PULSE, 1000000.0 / 8192.0, true, NULL);      // 122.1 usec
52 }
53
54
55 void MSM58321::read_from_cur_time()
56 {
57         // update clock
58         int hour = (regs[5] & 8) ? cur_time.hour : (cur_time.hour % 12);
59         int ampm = (cur_time.hour > 11) ? 4 : 0;
60         
61         regs[ 0] = TO_BCD_LO(cur_time.second);
62         regs[ 1] = TO_BCD_HI(cur_time.second);
63         regs[ 2] = TO_BCD_LO(cur_time.minute);
64         regs[ 3] = TO_BCD_HI(cur_time.minute);
65         regs[ 4] = TO_BCD_LO(hour);
66         regs[ 5] = TO_BCD_HI(hour) | ampm | (regs[5] & 8);
67         regs[ 6] = cur_time.day_of_week;
68         regs[ 7] = TO_BCD_LO(cur_time.day - start_day);
69         regs[ 8] = TO_BCD_HI(cur_time.day - start_day) | (regs[8] & 0x0c);
70         regs[ 9] = TO_BCD_LO(cur_time.month);
71         regs[10] = TO_BCD_HI(cur_time.month);
72         regs[11] = TO_BCD_LO(cur_time.year - start_year);
73         regs[12] = TO_BCD_HI(cur_time.year - start_year);
74 }
75
76 void MSM58321::write_to_cur_time()
77 {
78         cur_time.second = regs[0] + (regs[1] & 7) * 10;
79         cur_time.minute = regs[2] + (regs[3] & 7) * 10;
80         cur_time.hour = regs[4] + (regs[5] & 3) * 10;
81         if(!(regs[5] & 8)) {
82                 cur_time.hour %= 12;
83                 if(regs[5] & 4) {
84                         cur_time.hour += 12;
85                 }
86         }
87 //      cur_time.day_of_week = regs[6] & 7;
88         cur_time.day = regs[7] + (regs[8] & 3) * 10;
89         cur_time.day += start_day;
90         cur_time.month = regs[9] + (regs[10] & 1) * 10;
91         cur_time.year = regs[11] + regs[12] * 10;
92         cur_time.year += start_year;
93         cur_time.update_year();
94         cur_time.update_day_of_week();
95         
96         // restart event
97         cancel_event(this, register_id);
98         register_event(this, EVENT_BUSY, 1000000.0, true, &register_id);
99 }
100
101 void MSM58321::set_busy(bool val)
102 {
103         if(busy != val) {
104                 write_signals(&outputs_busy, busy ? 0 : 0xffffffff);    // negative
105         }
106         busy = val;
107 }