Projects/tigris
Projects
/
tigris
Archived
5
0
Fork 0
This repository has been archived on 2024-07-04. You can view files and clone it, but cannot push or open issues or pull requests.
tigris/TIKI-100_emul-src/ctc.c

150 lines
4.2 KiB
C
Raw Permalink Normal View History

2008-09-01 12:30:26 +02:00
/* ctc.c V1.1.0
*
* Z80 CTC emulering for TIKI-100_emul
* Copyright (C) Asbj<EFBFBD>rn Djupdal 2000-2001
*/
#include "TIKI-100_emul.h"
#include "protos.h"
/* data for en seriekanal */
struct ctcParams {
boolean interrupt; /* om interrupt skal genereres */
boolean enable; /* om teller av p<> eller av */
int in; /* inngang - ant. sykler mellom hver inn-puls */
int out; /* utgang - ant. sykler mellom hver ut-puls */
boolean use4MHz; /* om klokke skal brukes i stedet for inngang */
int count; /* sykler igjen til neste ut-puls */
boolean writeTk; /* skriv tidskonstant neste gang */
byte timeConst; /* tidskonstant */
int scale; /* skaleringsfaktor */
};
/* protos */
static void writeCtc (byte value, struct ctcParams *params);
static void recalcCtc (void);
/* variabler */
extern Z80 cpu;
static struct ctcParams params0 = {FALSE, FALSE, 2, FALSE, 0, FALSE, 0, 0};
static struct ctcParams params1 = {FALSE, FALSE, 2, FALSE, 0, FALSE, 0, 0};
static struct ctcParams params2 = {FALSE, FALSE, 1, FALSE, 0, FALSE, 0, 0};
static struct ctcParams params3 = {FALSE, FALSE, 1, FALSE, 0, FALSE, 0, 0};
/*****************************************************************************/
/* skriv til ctc0-register */
void writeCtc0 (byte value) {
writeCtc (value, &params0);
}
/* skriv til ctc1-register */
void writeCtc1 (byte value) {
writeCtc (value, &params1);
}
/* skriv til ctc2-register */
void writeCtc2 (byte value) {
writeCtc (value, &params2);
}
/* skriv til ctc3-register */
void writeCtc3 (byte value) {
writeCtc (value, &params3);
}
/* setter data til gitt seriekanal */
static void writeCtc (byte value, struct ctcParams *params) {
if (params->writeTk) {
params->writeTk = FALSE;
params->timeConst = value;
params->enable = TRUE;
} else {
params->interrupt = value & 128;
if (value & 64) {
params->use4MHz = FALSE;
params->scale = 1;
} else {
params->use4MHz = TRUE;
params->scale = value & 32 ? 256 : 16;
}
params->writeTk = value & 4;
params->enable = !(value & 2);
}
recalcCtc();
}
/* rekalkulerer frekvenser for tellerkanalene */
static void recalcCtc (void) {
params2.in = params0.out;
params3.in = params2.out;
params0.out = params0.timeConst * params0.scale * (params0.use4MHz ? 1 : params0.in);
params1.out = params1.timeConst * params1.scale * (params1.use4MHz ? 1 : params1.in);
params2.out = params2.timeConst * params2.scale * (params2.use4MHz ? 1 : params2.in);
params3.out = params3.timeConst * params3.scale * (params3.use4MHz ? 1 : params3.in);
params0.count = params0.out; /* dette er ikke helt riktig, men bra nok */
params1.count = params1.out;
params2.count = params2.out;
params3.count = params3.out;
recalcBaud();
}
/* les ctc0-register */
byte readCtc0 (void) {
return params0.count / params0.in;
}
/* les ctc1-register */
byte readCtc1 (void) {
return params1.count / params1.in;
}
/* les ctc2-register */
byte readCtc2 (void) {
return params2.count / params2.in;
}
/* les ctc3-register */
byte readCtc3 (void) {
return params3.count / params3.in;
}
/* m<> kalles regelmessig for <20> oppdatere tellere og sjekke om interrupt skal genereres */
void updateCTC (int cycles) {
if (params0.enable) params0.count -= cycles;
if (params1.enable) params1.count -= cycles;
if (params2.enable) params2.count -= cycles;
if (params3.enable) params3.count -= cycles;
if (params0.count <= 0) {
params0.count += params0.out;
if (params0.interrupt) {
IntZ80 (&cpu, 0x10);
}
}
if (params1.count <= 0) {
params1.count += params1.out;
if (params1.interrupt) {
IntZ80 (&cpu, 0x12);
}
}
if (params2.count <= 0) {
params2.count += params2.out;
if (params2.interrupt) {
IntZ80 (&cpu, 0x14);
}
}
if (params3.count <= 0) {
params3.count += params3.out;
if (params3.interrupt) {
IntZ80 (&cpu, 0x16);
}
}
}
/* returnerer antall sykler mellom hver ut puls p<> gitt ctc-kanal */
int getCtc (int c) {
switch (c) {
case 0: return params0.out;
case 1: return params1.out;
case 2: return params2.out;
case 3: return params3.out;
}
return 0;
}