Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
rtc.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2015,2016 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 
20 #include "xep128.h"
21 #include "rtc.h"
22 
23 #include "main.h"
24 
25 #include <time.h>
26 
27 
28 //#define RESET_RTC_INDEX
29 
30 
31 static int _rtc_register;
32 static Uint8 cmos_ram[0x100];
34 
35 
36 void rtc_set_reg(Uint8 val)
37 {
38  _rtc_register = val;
39  DEBUG("RTC: register number %02X has been selected" NL, val);
40 }
41 
42 
44 {
45  DEBUG("RTC: write reg %02X with data %02X" NL, _rtc_register, val);
46  if (_rtc_register == 0xC || _rtc_register == 0xD) return;
47  if (_rtc_register == 0xA) val &= 127;
48  cmos_ram[_rtc_register] = val;
49 #ifdef RESET_RTC_INDEX
50  _rtc_register = 0xD;
51 #endif
52 }
53 
54 
55 static int _rtc_conv(int bin, int is_hour)
56 {
57  int b7 = 0;
58  if (is_hour && (!(cmos_ram[0xB] & 2))) { // AM/PM
59  if (bin == 0) {
60  bin = 12;
61  } else if (bin == 12) {
62  b7 = 128;
63  } else if (bin > 12) {
64  bin -= 12;
65  b7 = 128;
66  }
67  }
68  if (!(cmos_ram[0xB] & 4)) { // do bin->bcd
69  bin = ((bin / 10) << 4) | (bin % 10);
70  }
71  return bin | b7;
72 }
73 
74 
75 static void _rtc_update(void)
76 {
77  struct tm *t = localtime(&unix_time);
78  cmos_ram[ 0] = _rtc_conv(t->tm_sec, 0);
79  cmos_ram[ 2] = _rtc_conv(t->tm_min, 0);
80  cmos_ram[ 4] = _rtc_conv(t->tm_hour, 1);
81  cmos_ram[ 6] = _rtc_conv(t->tm_wday + 1, 0); // day, 1-7 (week)
82  cmos_ram[ 7] = _rtc_conv(t->tm_mday, 0); // date, 1-31
83  cmos_ram[ 8] = _rtc_conv(t->tm_mon + 1, 0); // month, 1 -12
84  cmos_ram[ 9] = _rtc_conv((t->tm_year % 100) + 20, 0); // year, 0 - 99
85  cmos_ram[0x32] = _rtc_conv(21, 0); // century???
86  DEBUG("RTC: time/date has been updated for \"%d-%02d-%02d %02d:%02d:%02d\" at UNIX epoch %ld" NL,
87  t->tm_year + 1900,
88  t->tm_mon + 1,
89  t->tm_mday,
90  t->tm_hour,
91  t->tm_min,
92  t->tm_sec,
93  (long int)unix_time
94  );
95 }
96 
97 
98 void rtc_reset(void)
99 {
100  memset(cmos_ram, 0, 0x100);
101  _rtc_register = 0xD;
102  rtc_update_trigger = 0;
103  cmos_ram[0xA] = 32;
104  cmos_ram[0xB] = 2; // 2 | 4;
105  cmos_ram[0xC] = 0;
106  cmos_ram[0xD] = 128;
107  DEBUG("RTC: reset" NL);
108  _rtc_update();
109 }
110 
111 
113 {
114  int i = _rtc_register;
115 #ifdef RESET_RTC_INDEX
116  _rtc_register = 0xD;
117 #endif
118  if (i > 63)
119  return 0xFF;
120  if (rtc_update_trigger && (cmos_ram[0xB] & 128) == 0 && i < 10) {
121  _rtc_update();
122  rtc_update_trigger = 0;
123  }
124  DEBUG("RTC: reading register %02X, result will be: %02X" NL, i, cmos_ram[i]);
125  return cmos_ram[i];
126 }
127 
unix_time
time_t unix_time
Definition: enterprise128.c:59
rtc_read_reg
Uint8 rtc_read_reg(void)
Definition: rtc.c:110
rtc_reset
void rtc_reset(void)
Definition: rtc.c:96
Uint8
uint8_t Uint8
Definition: fat32.c:51
rtc.h
NL
#define NL
Definition: fat32.c:37
xep128.h
main.h
rtc_update_trigger
int rtc_update_trigger
Definition: rtc.c:31
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
rtc_set_reg
void rtc_set_reg(Uint8 val)
Definition: rtc.c:34
rtc_write_reg
void rtc_write_reg(Uint8 val)
Definition: rtc.c:41