Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
via65c22.c
Go to the documentation of this file.
1 /* Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
2  Copyright (C)2016,2020 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 
18 /* Commodore LCD emulator, C version.
19  * (C)2013,2014 LGB Gabor Lenart
20  * Visit my site (the better, JavaScript version of the emu is here too): http://commodore-lcd.lgb.hu/
21  * Can be distributed/used/modified under the terms of GNU/GPL 3 (or later), please see file COPYING
22  * or visit this page: http://www.gnu.org/licenses/gpl-3.0.html
23  */
24 
26 #include "xemu/via65c22.h"
27 
28 #define INA(via) (via->ina)(0xFF)
29 #define INB(via) ((via->ORB & via->DDRB) | ((via->inb)(255 - via->DDRB) & (255 - via->DDRB)))
30 #define OUTA(via, data) (via->outa)(via->DDRA, data)
31 #define OUTB(via, data) (via->outb)(via->DDRB, data)
32 #define INT(via, level) (via->setint)(via->irqLevel = level)
33 #define alert(via, msg) DEBUG("%s: ALERT: %s" NL, via->name, msg)
34 #define INSR(via) (via->insr)()
35 #define OUTSR(via, data) (via->outsr)(data)
36 
37 static inline void ifr_check(struct Via65c22 *via)
38 {
39  if (via->IFR & via->IER & 127) {
40  via->IFR |= 128;
41  if (!via->irqLevel) INT(via, 1);
42  } else {
43  via->IFR &= 127;
44  if ( via->irqLevel) INT(via, 0);
45  }
46 }
47 
48 static inline void ifr_clear (struct Via65c22 *via, Uint8 mask) { via->IFR &= 255 - mask; ifr_check(via); }
49 static inline void ifr_set (struct Via65c22 *via, Uint8 mask) { via->IFR |= mask; ifr_check(via); }
50 static inline void ifr_on_pa (struct Via65c22 *via) { ifr_clear(via, ((via->PCR & 0x0E) == 0x02 || (via->PCR & 0x0E) == 0x06) ? 2 : 3); }
51 static inline void ifr_on_pb (struct Via65c22 *via) { ifr_clear(via, ((via->PCR & 0xE0) == 0x20 || (via->PCR & 0xE0) == 0x60) ? 0x10 : 0x18); }
52 
53 
54 
55 
56 void via_reset(struct Via65c22 *via)
57 {
58  //via->ACR = via->PCR = via->DDRA = via->DDRB = via->ORA = via->ORB = 0;
59  via->ORA = via->ORB = via->DDRA = via->DDRB = 0;
60  via->SR = via->SRcount = via->SRmode = via->IER = via->IFR = via->ACR = via->PCR = 0;
61  via->T1C = via->T2C = via->T1LL = via->T1LH = via->T2LL = via->T2LH = 0;
62  via->T1run = via->T2run = 0; // false
63  INT(via, 0);
64  DEBUG("%s: RESET" NL, via->name);
65 }
66 
67 
68 static void def_outa (Uint8 mask, Uint8 data) {}
69 static void def_outb (Uint8 mask, Uint8 data) {}
70 static void def_outsr (Uint8 data) {}
71 static Uint8 def_ina (Uint8 mask) { return 0xFF; }
72 static Uint8 def_inb (Uint8 mask) { return 0xFF; }
73 static Uint8 def_insr (void) { return 0xFF; }
74 static void def_setint(int level) {}
75 
76 
77 void via_init(
78  struct Via65c22 *via, const char *name,
79  void (*outa)(Uint8 mask, Uint8 data),
80  void (*outb)(Uint8 mask, Uint8 data),
81  void (*outsr)(Uint8 data),
82  Uint8 (*ina)(Uint8 mask),
83  Uint8 (*inb)(Uint8 mask),
84  Uint8 (*insr)(void),
85  void (*setint)(int level)
86 ) {
87  via->name = name;
88  via->outa = outa ? outa : def_outa;
89  via->outb = outb ? outb : def_outb;
90  via->outsr = outsr ? outsr : def_outsr;
91  via->ina = ina ? ina : def_ina;
92  via->inb = inb ? inb : def_inb;
93  via->insr = insr ? insr : def_insr;
94  via->setint = setint ? setint : def_setint;
95  via_reset(via);
96 }
97 
98 
99 void via_write(struct Via65c22 *via, int addr, Uint8 data)
100 {
101  //DEBUG("%s: write reg %02X with data %02X" NL, via->name, addr, data);
102  switch (addr) {
103  case 0x0: // port B data
104  via->ORB = data; // FIXED BUG
105  OUTB(via, data);
106  ifr_on_pb(via);
107  break;
108  case 0x1: // port A data
109  via->ORA = data; // FIXED BUG
110  OUTA(via, data);
111  ifr_on_pa(via);
112  break;
113  case 0x2: // port B DDR
114  if (data != via->DDRB) {
115  via->DDRB = data;
116  OUTB(via, via->ORB);
117  }
118  break;
119  case 0x3: // port A DDR
120  if (data != via->DDRA) {
121  via->DDRA = data;
122  OUTA(via, via->ORA);
123  }
124  break;
125  case 0x4: //
126  via->T1LL = data;
127  break;
128  case 0x5:
129  via->T1LH = data;
130  ifr_clear(via, 64);
131  via->T1run = 1;
132  via->T1C = via->T1LL | (via->T1LH << 8);
133  break;
134  case 0x6:
135  via->T1LL = data;
136  break;
137  case 0x7:
138  via->T1LH = data;
139  ifr_clear(via, 64);
140  break;
141  case 0x8:
142  via->T2LL = data;
143  break;
144  case 0x9:
145  via->T2LH = data;
146  ifr_clear(via, 32);
147  via->T2run = 1;
148  via->T2C = via->T2LL | (via->T2LH << 8);
149  break;
150  case 0xA: // SR
151  ifr_clear(via, 4);
152  via->SR = data;
153  if (via->SRmode) via->SRcount = 8;
154  break;
155  case 0xB: // ACR
156  via->SRmode = (data >> 2) & 7;
157  via->ACR = data;
158  if (data & 32) alert(via, "pulse counting T2 mode is not supported!");
159  break;
160  case 0xC: // PCR
161  via->PCR = data;
162  break;
163  case 0xD: // IFR
164  ifr_clear(via, data);
165  break;
166  case 0xE: // IER
167  if (data & 128) via->IER |= data; else via->IER &= (255 - data);
168  ifr_check(via);
169  break;
170  case 0xF: // port A data (no handshake)
171  OUTA(via, data);
172  ifr_on_pa(via);
173  break;
174  }
175 }
176 
177 Uint8 via_read(struct Via65c22 *via, int addr)
178 {
179  //DEBUG("%s: read reg %02X" NL, via->name, addr);
180  switch (addr) {
181  case 0x0: // port B data
182  ifr_on_pb(via);
183  return INB(via);
184  case 0x1: // port A data
185  ifr_on_pa(via);
186  return INA(via);
187  case 0x2: // port B DDR
188  return via->DDRB;
189  case 0x3: // port A DDR
190  return via->DDRA;
191  case 0x4: //
192  ifr_clear(via, 64);
193  return via->T1C & 0xFF;
194  case 0x5:
195  return via->T1C >> 8;
196  case 0x6:
197  return via->T1LL;
198  case 0x7:
199  return via->T1C >> 8;
200  case 0x8:
201  ifr_clear(via, 32);
202  return via->T2C & 0xFF;
203  case 0x9:
204  return via->T2C >> 8;
205  case 0xA: // SR
206  ifr_clear(via, 4);
207  if (via->SRmode) via->SRcount = 8;
208  return via->SR;
209  case 0xB: // ACR
210  return via->ACR;
211  case 0xC: // PCR
212  return via->PCR;
213  case 0xD: // IFR
214  return via->IFR;
215  case 0xE: // IER
216  return via->IER | 128;
217  case 0xF: // port A data (no handshake)
218  ifr_on_pa(via);
219  return INA(via);
220  }
221  return 0; // make gcc happy :)
222 }
223 
224 void via_tick(struct Via65c22 *via, int ticks)
225 {
226  /* T1 */
227  if (via->T1run) {
228  via->T1C -= ticks;
229  if (via->T1C <= 0) {
230  //console.log("Expired T1");
231  ifr_set(via, 64);
232  if (via->ACR & 64) via->T1C = via->T1LL | (via->T1LH << 8); else via->T1run = 0;
233  }
234  }
235  /* T2 */
236  via->T2C -= ticks;
237  if (via->T2run) {
238  if (via->T2C <= 0) {
239  ifr_set(via, 32);
240  via->T2run = 0;
241  }
242  }
243  via->T2C &= 0xFFFF;
244  /* shift register */
245  if (via->SRcount) {
246  via->SRcount -= ticks;
247  if (via->SRcount <= 0) {
248  switch(via->SRmode) {
249  case 0: via->SRcount = 0; ifr_clear(via, 4); break; // disabled
250  case 2: via->SR = INSR(via); via->SRcount = 0; ifr_set(via, 4); break; // PHI2-in
251  case 4: OUTSR(via, via->SR); via->SRcount = via->T2LL + 2; ifr_clear(via, 4); break; // free-T2-out, VIA2 seems to use this mode!
252  default: via->SRcount = 0 ; ifr_clear(via, 4); alert(via, "SRmode is not supported!"); break;
253  }
254  }
255  }
256 }
via_tick
void via_tick(struct Via65c22 *via, int ticks)
Definition: via65c22.c:224
Via65c22::DDRA
Uint8 DDRA
Definition: via65c22.h:30
Via65c22::ORB
Uint8 ORB
Definition: via65c22.h:30
Via65c22::T2C
int T2C
Definition: via65c22.h:31
Via65c22::T1run
int T1run
Definition: via65c22.h:32
OUTB
#define OUTB(via, data)
Definition: via65c22.c:31
Via65c22::name
const char * name
Definition: via65c22.h:29
Via65c22::PCR
Uint8 PCR
Definition: via65c22.h:30
Via65c22::ina
Uint8(* ina)(Uint8 mask)
Definition: via65c22.h:25
via65c22.h
Via65c22::ACR
Uint8 ACR
Definition: via65c22.h:30
Via65c22::T2LL
Uint8 T2LL
Definition: via65c22.h:30
Via65c22::T1LH
Uint8 T1LH
Definition: via65c22.h:30
addr
int addr
Definition: dma65.c:81
Via65c22::T1LL
Uint8 T1LL
Definition: via65c22.h:30
Via65c22::ORA
Uint8 ORA
Definition: via65c22.h:30
OUTSR
#define OUTSR(via, data)
Definition: via65c22.c:35
m65-memcontent-generator.data
data
Definition: m65-memcontent-generator.py:119
alert
#define alert(via, msg)
Definition: via65c22.c:33
INSR
#define INSR(via)
Definition: via65c22.c:34
Via65c22
Definition: via65c22.h:21
Uint8
uint8_t Uint8
Definition: fat32.c:51
Via65c22::outa
void(* outa)(Uint8 mask, Uint8 data)
Definition: via65c22.h:22
Via65c22::IFR
Uint8 IFR
Definition: via65c22.h:30
emutools_basicdefs.h
Via65c22::irqLevel
int irqLevel
Definition: via65c22.h:32
via_init
void via_init(struct Via65c22 *via, const char *name, void(*outa)(Uint8 mask, Uint8 data), void(*outb)(Uint8 mask, Uint8 data), void(*outsr)(Uint8 data), Uint8(*ina)(Uint8 mask), Uint8(*inb)(Uint8 mask), Uint8(*insr)(void), void(*setint)(int level))
Definition: via65c22.c:77
Via65c22::IER
Uint8 IER
Definition: via65c22.h:30
OUTA
#define OUTA(via, data)
Definition: via65c22.c:30
Via65c22::DDRB
Uint8 DDRB
Definition: via65c22.h:30
NL
#define NL
Definition: fat32.c:37
Via65c22::outsr
void(* outsr)(Uint8 data)
Definition: via65c22.h:24
Via65c22::inb
Uint8(* inb)(Uint8 mask)
Definition: via65c22.h:26
Via65c22::setint
void(* setint)(int level)
Definition: via65c22.h:28
via_read
Uint8 via_read(struct Via65c22 *via, int addr)
Definition: via65c22.c:177
via_reset
void via_reset(struct Via65c22 *via)
Definition: via65c22.c:56
Via65c22::SRmode
int SRmode
Definition: via65c22.h:32
INT
#define INT(via, level)
Definition: via65c22.c:32
Via65c22::outb
void(* outb)(Uint8 mask, Uint8 data)
Definition: via65c22.h:23
INB
#define INB(via)
Definition: via65c22.c:29
Via65c22::SR
Uint8 SR
Definition: via65c22.h:30
mask
int mask
Definition: dma65.c:83
via_write
void via_write(struct Via65c22 *via, int addr, Uint8 data)
Definition: via65c22.c:99
name
const char * name
Definition: joystick.c:46
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
Via65c22::T1C
int T1C
Definition: via65c22.h:31
Via65c22::T2LH
Uint8 T2LH
Definition: via65c22.h:30
Via65c22::insr
Uint8(* insr)(void)
Definition: via65c22.h:27
Via65c22::SRcount
int SRcount
Definition: via65c22.h:32
INA
#define INA(via)
Definition: via65c22.c:28
Via65c22::T2run
int T2run
Definition: via65c22.h:32