Fri, 18 Apr 2014 01:34:20 -0600
added RTC emulation (attempts to set the date are ignored, and the year is currently hardcoded to 1987 because UNIX PC SysV has a few Y2K bugs)
Makefile | file | annotate | diff | revisions | |
src/memory.c | file | annotate | diff | revisions | |
src/state.h | file | annotate | diff | revisions | |
src/tc8250.c | file | annotate | diff | revisions | |
src/tc8250.h | file | annotate | diff | revisions |
1.1 diff -r c19afa2c81db -r b63a3999e2e7 Makefile 1.2 --- a/Makefile Fri Apr 18 01:26:01 2014 -0600 1.3 +++ b/Makefile Fri Apr 18 01:34:20 2014 -0600 1.4 @@ -118,7 +118,7 @@ 1.5 TARGET = freebee 1.6 1.7 # source files that produce object files 1.8 -SRC = main.c state.c memory.c wd279x.c wd2010.c keyboard.c 1.9 +SRC = main.c state.c memory.c wd279x.c wd2010.c keyboard.c tc8250.c 1.10 SRC += musashi/m68kcpu.c musashi/m68kdasm.c musashi/m68kops.c musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c 1.11 1.12 # source type - either "c" or "cpp" (C or C++)
2.1 diff -r c19afa2c81db -r b63a3999e2e7 src/memory.c 2.2 --- a/src/memory.c Fri Apr 18 01:26:01 2014 -0600 2.3 +++ b/src/memory.c Fri Apr 18 01:34:20 2014 -0600 2.4 @@ -377,6 +377,13 @@ 2.5 case 0x070000: // Line Printer Status Register 2.6 break; 2.7 case 0x080000: // Real Time Clock 2.8 + ENFORCE_SIZE_W(bits, address, 16, "RTCWRITE"); 2.9 + /*printf("IoWrite RTCWRITE %x\n", data);*/ 2.10 + tc8250_set_chip_enable(&state.rtc_ctx, data & 0x8000); 2.11 + tc8250_set_address_latch_enable(&state.rtc_ctx, data & 0x4000); 2.12 + tc8250_set_write_enable(&state.rtc_ctx, data & 0x2000); 2.13 + tc8250_write_reg(&state.rtc_ctx, (data & 0x0F00) >> 8); 2.14 + handled = true; 2.15 break; 2.16 case 0x090000: // Phone registers 2.17 switch (address & 0x0FF000) { 2.18 @@ -693,7 +700,7 @@ 2.19 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 2.20 break; 2.21 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 2.22 - break; 2.23 + return (tc8250_read_reg(&state.rtc_ctx)); 2.24 case 0x040000: // [ef][4c]xxxx ==> General Control Register 2.25 switch (address & 0x077000) { 2.26 case 0x040000: // [ef][4c][08]xxx ==> EE
3.1 diff -r c19afa2c81db -r b63a3999e2e7 src/state.h 3.2 --- a/src/state.h Fri Apr 18 01:26:01 2014 -0600 3.3 +++ b/src/state.h Fri Apr 18 01:34:20 2014 -0600 3.4 @@ -7,6 +7,8 @@ 3.5 #include "wd279x.h" 3.6 #include "wd2010.h" 3.7 #include "keyboard.h" 3.8 +#include "tc8250.h" 3.9 + 3.10 3.11 // Maximum size of the Boot PROMs. Must be a binary power of two. 3.12 #define ROM_SIZE 32768 3.13 @@ -90,6 +92,9 @@ 3.14 3.15 /// Keyboard controller context 3.16 KEYBOARD_STATE kbd; 3.17 + 3.18 + /// Real time clock context 3.19 + TC8250_CTX rtc_ctx; 3.20 } S_state; 3.21 3.22 // Global emulator state. Yes, I know global variables are evil, please don't
4.1 diff -r c19afa2c81db -r b63a3999e2e7 src/tc8250.c 4.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 +++ b/src/tc8250.c Fri Apr 18 01:34:20 2014 -0600 4.4 @@ -0,0 +1,247 @@ 4.5 +#include <stdint.h> 4.6 +#include <stdbool.h> 4.7 +#include <malloc.h> 4.8 +#include <time.h> 4.9 +#include "tc8250.h" 4.10 + 4.11 +#ifndef TC8250_DEBUG 4.12 +#define NDEBUG 4.13 +#endif 4.14 +#include "utils.h" 4.15 + 4.16 +void tc8250_init(TC8250_CTX *ctx) 4.17 +{ 4.18 + ctx->chip_enable = false; 4.19 + ctx->address_latch_enable = false; 4.20 + ctx->write_enable = false; 4.21 + ctx->address = 0; 4.22 +} 4.23 + 4.24 +void tc8250_set_chip_enable(TC8250_CTX *ctx, bool enabled) 4.25 +{ 4.26 + LOG("tc8250_set_chip_enable %d\n", enabled); 4.27 + ctx->chip_enable = enabled; 4.28 +} 4.29 + 4.30 +void tc8250_set_address_latch_enable(TC8250_CTX *ctx, bool enabled) 4.31 +{ 4.32 + LOG("tc8250_set_address_latch_enable %d\n", enabled); 4.33 + ctx->address_latch_enable = enabled; 4.34 +} 4.35 + 4.36 +void tc8250_set_write_enable(TC8250_CTX *ctx, bool enabled) 4.37 +{ 4.38 + LOG("tc8250_set_write_enable %d\n", enabled); 4.39 + ctx->write_enable = enabled; 4.40 +} 4.41 + 4.42 +uint8_t get_second(TC8250_CTX *ctx) 4.43 +{ 4.44 + time_t t; 4.45 + struct tm g; 4.46 + uint8_t ret; 4.47 + t = time(NULL); 4.48 + gmtime_r(&t, &g); 4.49 + ret = g.tm_sec; 4.50 + return (ret); 4.51 +} 4.52 + 4.53 +uint8_t get_minute(TC8250_CTX *ctx) 4.54 +{ 4.55 + time_t t; 4.56 + struct tm g; 4.57 + uint8_t ret; 4.58 + t = time(NULL); 4.59 + gmtime_r(&t, &g); 4.60 + ret = g.tm_min; 4.61 + return (ret); 4.62 +} 4.63 + 4.64 +uint8_t get_hour(TC8250_CTX *ctx) 4.65 +{ 4.66 + time_t t; 4.67 + struct tm g; 4.68 + uint8_t ret; 4.69 + t = time(NULL); 4.70 + gmtime_r(&t, &g); 4.71 + ret = g.tm_hour; 4.72 + return (ret); 4.73 +} 4.74 + 4.75 +uint8_t get_day(TC8250_CTX *ctx) 4.76 +{ 4.77 + time_t t; 4.78 + struct tm g; 4.79 + uint8_t ret; 4.80 + t = time(NULL); 4.81 + gmtime_r(&t, &g); 4.82 + ret = g.tm_mday; 4.83 + return (ret); 4.84 +} 4.85 + 4.86 +uint8_t get_month(TC8250_CTX *ctx) 4.87 +{ 4.88 + time_t t; 4.89 + struct tm g; 4.90 + uint8_t ret; 4.91 + t = time(NULL); 4.92 + gmtime_r(&t, &g); 4.93 + ret = g.tm_mon; 4.94 + return (ret); 4.95 +} 4.96 + 4.97 +uint8_t get_year(TC8250_CTX *ctx) 4.98 +{ 4.99 + /*time_t t; 4.100 + struct tm g; 4.101 + uint8_t ret; 4.102 + t = time(NULL); 4.103 + gmtime_r(&t, &g); 4.104 + ret = g.tm_year; 4.105 + return (ret);*/ 4.106 + return (87); 4.107 +} 4.108 + 4.109 +uint8_t get_weekday(TC8250_CTX *ctx) 4.110 +{ 4.111 + time_t t; 4.112 + struct tm g; 4.113 + uint8_t ret; 4.114 + t = time(NULL); 4.115 + gmtime_r(&t, &g); 4.116 + ret = g.tm_wday; 4.117 + return (ret); 4.118 +} 4.119 + 4.120 +uint8_t tc8250_read_reg(TC8250_CTX *ctx) 4.121 +{ 4.122 + LOG("tc8250_read_reg %x\n", ctx->address); 4.123 + switch (ctx->address){ 4.124 + case ONE_SEC_DIGT: 4.125 + return (get_second(ctx) % 10); 4.126 + case TEN_SEC_DIGT: 4.127 + return (get_second(ctx) / 10); 4.128 + case ONE_MIN_DIGT: 4.129 + return (get_minute(ctx) % 10); 4.130 + case TEN_MIN_DIGT: 4.131 + return (get_minute(ctx) / 10); 4.132 + case ONE_HR_DIGT: 4.133 + return (get_hour(ctx) % 10); 4.134 + case TEN_HR_DIGT: 4.135 + return (get_hour(ctx) / 10); 4.136 + case ONE_DAY_DIGT: 4.137 + return (get_day(ctx) % 10); 4.138 + case TEN_DAY_DIGT: 4.139 + return (get_day(ctx) / 10); 4.140 + case ONE_MNTH_DIGT: 4.141 + return (get_month(ctx) % 10); 4.142 + case TEN_MNTH_DIGT: 4.143 + return (get_month(ctx) / 10); 4.144 + case ONE_YR_DIGT: 4.145 + return (get_year(ctx) % 10); 4.146 + case TEN_YR_DIGT: 4.147 + return (get_year(ctx) / 10); 4.148 + case WEEK_DAY: 4.149 + return (get_weekday(ctx) / 10); 4.150 + case TOUT_CONTROL: 4.151 + return (0); 4.152 + case PROTECT_KEY: 4.153 + return (0); 4.154 + case RTC_STATUS: 4.155 + return (0); 4.156 + default: 4.157 + return (0); 4.158 + } 4.159 +} 4.160 + 4.161 +void set_seconds(TC8250_CTX *ctx, uint8_t val) 4.162 +{ 4.163 +} 4.164 + 4.165 +void set_minutes(TC8250_CTX *ctx, uint8_t val) 4.166 +{ 4.167 +} 4.168 + 4.169 +void set_hours(TC8250_CTX *ctx, uint8_t val) 4.170 +{ 4.171 +} 4.172 + 4.173 +void set_days(TC8250_CTX *ctx, uint8_t val) 4.174 +{ 4.175 +} 4.176 + 4.177 +void set_months(TC8250_CTX *ctx, uint8_t val) 4.178 +{ 4.179 +} 4.180 + 4.181 +void set_years(TC8250_CTX *ctx, uint8_t val) 4.182 +{ 4.183 +} 4.184 + 4.185 +void set_weekday(TC8250_CTX *ctx, uint8_t val) 4.186 +{ 4.187 +} 4.188 + 4.189 +void tc8250_write_reg(TC8250_CTX *ctx, uint8_t val) 4.190 +{ 4.191 + LOG("tc8250_write_reg %x", val); 4.192 + if (ctx->address_latch_enable){ 4.193 + LOG(" address\n"); 4.194 + ctx->address = val; 4.195 + return; 4.196 + } 4.197 + if (ctx->chip_enable){ 4.198 + LOG(" %x\n", ctx->address); 4.199 + switch (ctx->address){ 4.200 + case ONE_SEC_DIGT: 4.201 + set_seconds(ctx, val % 10); 4.202 + break; 4.203 + case TEN_SEC_DIGT: 4.204 + set_seconds(ctx, val % 10 * 10); 4.205 + break; 4.206 + case ONE_MIN_DIGT: 4.207 + set_minutes(ctx, val % 10); 4.208 + break; 4.209 + case TEN_MIN_DIGT: 4.210 + set_minutes(ctx, val % 10 * 10); 4.211 + break; 4.212 + case ONE_HR_DIGT: 4.213 + set_hours(ctx, val % 10); 4.214 + break; 4.215 + case TEN_HR_DIGT: 4.216 + set_hours(ctx, val % 10 * 10); 4.217 + break; 4.218 + case ONE_DAY_DIGT: 4.219 + set_days(ctx, val % 10); 4.220 + break; 4.221 + case TEN_DAY_DIGT: 4.222 + set_days(ctx, val % 10 * 10); 4.223 + break; 4.224 + case ONE_MNTH_DIGT: 4.225 + set_months(ctx, val % 10); 4.226 + break; 4.227 + case TEN_MNTH_DIGT: 4.228 + set_months(ctx, val % 10 * 10); 4.229 + break; 4.230 + case ONE_YR_DIGT: 4.231 + set_years(ctx, val % 10); 4.232 + break; 4.233 + case TEN_YR_DIGT: 4.234 + set_years(ctx, val % 10 * 10); 4.235 + break; 4.236 + case WEEK_DAY: 4.237 + set_weekday(ctx, val % 10); 4.238 + break; 4.239 + case TOUT_CONTROL: 4.240 + break; 4.241 + case PROTECT_KEY: 4.242 + break; 4.243 + case RTC_STATUS: 4.244 + break; 4.245 + default: 4.246 + break; 4.247 + } 4.248 + }else{ 4.249 + LOG("\n"); 4.250 + } 4.251 +}
5.1 diff -r c19afa2c81db -r b63a3999e2e7 src/tc8250.h 5.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 +++ b/src/tc8250.h Fri Apr 18 01:34:20 2014 -0600 5.4 @@ -0,0 +1,48 @@ 5.5 +#ifndef _TC8250_H 5.6 +#define _TC8250_H 5.7 + 5.8 +#include <stdbool.h> 5.9 +#include <stddef.h> 5.10 +#include <stdint.h> 5.11 +#include <stdio.h> 5.12 + 5.13 +typedef struct { 5.14 + bool chip_enable; 5.15 + bool address_latch_enable; 5.16 + bool write_enable; 5.17 + uint8_t address; 5.18 + uint8_t seconds_offset; 5.19 + uint8_t minutes_offset; 5.20 + uint8_t hours_offset; 5.21 + uint8_t days_offset; 5.22 + uint8_t months_offset; 5.23 + uint8_t years_offset; 5.24 + uint8_t weekday_offset; 5.25 +} TC8250_CTX; 5.26 + 5.27 +void tc8250_init(TC8250_CTX *ctx); 5.28 +void tc8250_set_chip_enable(TC8250_CTX *ctx, bool enabled); 5.29 +void tc8250_set_address_latch_enable(TC8250_CTX *ctx, bool enabled); 5.30 +void tc8250_set_write_enable(TC8250_CTX *ctx, bool enabled); 5.31 +uint8_t tc8250_read_reg(TC8250_CTX *ctx); 5.32 +void tc8250_write_reg(TC8250_CTX *ctx, uint8_t val); 5.33 + 5.34 +enum { 5.35 + ONE_SEC_DIGT = 0x0, /* 1 sec digit */ 5.36 + TEN_SEC_DIGT = 0x1, /* 10 sec digit */ 5.37 + ONE_MIN_DIGT = 0x2, /* 1 minute digit */ 5.38 + TEN_MIN_DIGT = 0x3, /* 10 minutes digit */ 5.39 + ONE_HR_DIGT = 0x4, /* 1 hour digit */ 5.40 + TEN_HR_DIGT = 0x5, /* 10 hours digit */ 5.41 + ONE_DAY_DIGT = 0x6, /* 1 day digit */ 5.42 + TEN_DAY_DIGT = 0x7, /* 10 days digit */ 5.43 + ONE_MNTH_DIGT = 0x8, /* 1 month digit */ 5.44 + TEN_MNTH_DIGT = 0x9, /* 10 month digit */ 5.45 + ONE_YR_DIGT = 0xa, /* 1 year digit */ 5.46 + TEN_YR_DIGT = 0xb, /* 10 year digit */ 5.47 + WEEK_DAY = 0xc, /* day of the week */ 5.48 + TOUT_CONTROL = 0xd, /* Tout control */ 5.49 + PROTECT_KEY = 0xe, /* protection key */ 5.50 + RTC_STATUS = 0xf /* real time clock status */ 5.51 +}; 5.52 +#endif