1 // SPDX-License-Identifier: MIT
8 static unsigned char rtc_mystery_reg[3];
9 unsigned char ricoh_memory[0x0F];
10 unsigned char ricoh_alarm[0x0F];
12 void put_rtc_byte(uint32_t address_, uint8_t value_, uint8_t rtc_type) {
13 uint32_t address = address_ & 0x3F;
14 uint8_t value = (value_ & 0x0F);
18 //printf("Wrote byte %.2X.\n", address);
20 if (rtc_type == RTC_TYPE_MSM) {
23 rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08);
27 rtc_mystery_reg[address - 0x0D] = value;
34 int rtc_bank = (rtc_mystery_reg[0] & 0x03);
35 if ((rtc_bank & 0x02) && address < 0x0D) {
36 if (rtc_bank & 0x01) {
37 // Low nibble of value -> high nibble in RTC memory
38 ricoh_memory[address] &= 0x0F;
39 ricoh_memory[address] |= ((value & 0x0F) << 4);
42 // Low nibble of value -> low nibble in RTC memory
43 ricoh_memory[address] &= 0xF0;
44 ricoh_memory[address] |= (value & 0x0F);
48 else if ((rtc_bank & 0x01) && address < 0x0D) {
49 // RTC alarm stuff, no idea what this is supposed to be for.
55 ricoh_alarm[address] = 0;
59 ricoh_alarm[address] &= (value & (0x08 ^ 0xFF));
64 ricoh_alarm[address] = (value & (0x0C ^ 0xFF));
67 ricoh_alarm[address] = (value & (0x0E ^ 0xFF));
70 ricoh_alarm[address] = value;
73 //printf("Write to Ricoh alarm @%.2X: %.2X -> %.2X\n", address, value, ricoh_alarm[address]);
76 else if (address >= 0x0D) {
77 rtc_mystery_reg[address - 0x0D] = value;
83 uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) {
84 uint32_t address = address_ & 0x3F;
86 if ((address & 3) == 2 || (address & 3) == 0) {
87 //printf("Garbage byte read.\n");
94 struct tm *rtc_time = localtime(&t);
96 if (rtc_type == RTC_TYPE_RICOH) {
97 int rtc_bank = (rtc_mystery_reg[0] & 0x03);
98 if ((rtc_bank & 0x02) && address < 0x0D) {
99 // Get low/high nibble from memory (bank 2/3)
100 return ((ricoh_memory[address] >> (rtc_bank & 0x01) ? 4 : 0) & 0x0F);
102 else if ((rtc_bank & 0x01) && address < 0x0D) {
103 // Get byte from alarm
104 return ricoh_alarm[address];
108 //printf("Read byte %.2X.\n", address);
111 case 0x00: // Seconds low?
112 return rtc_time->tm_sec % 10;
113 case 0x01: // Seconds high?
114 return rtc_time->tm_sec / 10;
115 case 0x02: // Minutes low?
116 return rtc_time->tm_min % 10;
117 case 0x03: // Minutes high?
118 return rtc_time->tm_min / 10;
119 case 0x04: // Hours low?
120 return rtc_time->tm_hour % 10;
121 case 0x05: // Hours high?
122 if (rtc_type == RTC_TYPE_MSM) {
123 if (rtc_mystery_reg[2] & 4) {
124 return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x04 : 0x00);
127 return rtc_time->tm_hour / 10;
130 if (ricoh_alarm[10] & 0x01) {
131 return rtc_time->tm_hour / 10;
134 return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x02 : 0x00);
138 case 0x06: // Day low?
139 if (rtc_type == RTC_TYPE_MSM)
140 return rtc_time->tm_mday % 10;
142 return rtc_time->tm_wday;
143 case 0x07: // Day high?
144 if (rtc_type == RTC_TYPE_MSM)
145 return rtc_time->tm_mday / 10;
147 return rtc_time->tm_mday % 10;
148 case 0x08: // Month low?
149 if (rtc_type == RTC_TYPE_MSM)
150 return (rtc_time->tm_mon + 1) % 10;
152 return rtc_time->tm_mday / 10;
153 case 0x09: // Month high?
154 if (rtc_type == RTC_TYPE_MSM)
155 return (rtc_time->tm_mon + 1) / 10;
157 return (rtc_time->tm_mon + 1) % 10;
158 case 0x0A: // Year low?
159 if (rtc_type == RTC_TYPE_MSM)
160 return rtc_time->tm_year % 10;
162 return (rtc_time->tm_mon + 1) / 10;
163 case 0x0B: // Year high?
164 if (rtc_type == RTC_TYPE_MSM)
165 return rtc_time->tm_year / 10;
167 return rtc_time->tm_year % 10;
168 case 0x0C: // Day of week?
169 if (rtc_type == RTC_TYPE_MSM)
170 return rtc_time->tm_wday;
172 return rtc_time->tm_year / 10;
173 case 0x0D: // Mystery register D-F?
176 if (rtc_type == RTC_TYPE_MSM) {
177 return rtc_mystery_reg[address - 0x0D];
180 if (address == 0x0D) return rtc_mystery_reg[address - 0x0D];