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)

Fri, 18 Apr 2014 01:34:20 -0600

author
andrew@localhost
date
Fri, 18 Apr 2014 01:34:20 -0600
changeset 151
b63a3999e2e7
parent 150
c19afa2c81db
child 152
d61e13d6e2a5

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