]> git.sesse.net Git - pistorm/blob - platforms/shared/rtc.c
Working AddDosNode/Enqueue for PiSCSI
[pistorm] / platforms / shared / rtc.c
1 // SPDX-License-Identifier: MIT
2
3 #include <time.h>
4 #include <stdio.h>
5 #include <stdint.h>
6 #include "rtc.h"
7
8 static unsigned char rtc_mystery_reg[3];
9 unsigned char ricoh_memory[0x0F];
10 unsigned char ricoh_alarm[0x0F];
11
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);
15
16   address >>= 2;
17
18   //printf("Wrote byte %.2X.\n", address);
19
20   if (rtc_type == RTC_TYPE_MSM) {
21     switch(address) {
22       case 0x0D:
23         rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08);
24         break;
25       case 0x0E:
26       case 0x0F:
27         rtc_mystery_reg[address - 0x0D] = value;
28         break;
29       default:
30         return;
31     }
32   }
33   else {
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);
40       }
41       else {
42         // Low nibble of value -> low nibble in RTC memory
43         ricoh_memory[address] &= 0xF0;
44         ricoh_memory[address] |= (value & 0x0F);
45       }
46       return;
47     }
48     else if ((rtc_bank & 0x01) && address < 0x0D) {
49       // RTC alarm stuff, no idea what this is supposed to be for.
50       switch(address) {
51         case 0x00:
52         case 0x01:
53         case 0x09:
54         case 0x0C:
55           ricoh_alarm[address] = 0;
56           break;
57         case 0x03:
58         case 0x06:
59           ricoh_alarm[address] &= (value & (0x08 ^ 0xFF));
60           break;
61         case 0x05:
62         case 0x08:
63         case 0x0B:
64           ricoh_alarm[address] = (value & (0x0C ^ 0xFF));
65           break;
66         case 0x0A:
67           ricoh_alarm[address] = (value & (0x0E ^ 0xFF));
68           break;
69         default:
70           ricoh_alarm[address] = value;
71           break;
72       }
73       //printf("Write to Ricoh alarm @%.2X: %.2X -> %.2X\n", address, value, ricoh_alarm[address]);
74       return;
75     }
76     else if (address >= 0x0D) {
77       rtc_mystery_reg[address - 0x0D] = value;
78       return;
79     }
80   }
81 }
82
83 uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) {
84   uint32_t address = address_ & 0x3F;
85
86         if ((address & 3) == 2 || (address & 3) == 0) {
87     //printf("Garbage byte read.\n");
88                 return 0;
89         }
90
91   address >>= 2;
92   time_t t;
93   time(&t);
94   struct tm *rtc_time = localtime(&t);
95
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);
101     }
102     else if ((rtc_bank & 0x01) && address < 0x0D) {
103       // Get byte from alarm
104       return ricoh_alarm[address];
105     }
106   }
107
108   //printf("Read byte %.2X.\n", address);
109
110   switch (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);
125         }
126         else
127           return rtc_time->tm_hour / 10;
128       }
129       else {
130         if (ricoh_alarm[10] & 0x01) {
131           return rtc_time->tm_hour / 10;
132         }
133         else {
134           return (((rtc_time->tm_hour % 12) / 10) | (rtc_time->tm_hour >= 12) ? 0x02 : 0x00);
135         }
136         break;
137       }
138     case 0x06: // Day low?
139       if (rtc_type == RTC_TYPE_MSM)
140         return rtc_time->tm_mday % 10;
141       else
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;
146       else
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;
151       else
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;
156       else
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;
161       else
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;
166       else
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;
171       else
172         return rtc_time->tm_year / 10;
173     case 0x0D: // Mystery register D-F?
174     case 0x0E:
175     case 0x0F:
176       if (rtc_type == RTC_TYPE_MSM) {
177         return rtc_mystery_reg[address - 0x0D];
178       }
179       else {
180         if (address == 0x0D) return rtc_mystery_reg[address - 0x0D];
181         return 0;
182       }
183     default:
184       break;
185   }
186
187   return 0x00;
188 }