1 /*
2 * KCemu -- The emulator for the KC85 homecomputer series and much more.
3 * Copyright (C) 1997-2010 Torsten Paul
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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <iostream>
21 #include <iomanip>
22
23 #include "kc/system.h"
24
25 #include "kc/kc.h"
26 #include "kc/pio2.h"
27 #include "kc/tape.h"
28 #include "kc/memory2.h"
29
30 #include "libdbg/dbg.h"
31
32 #define memory ((Memory2 *)memory)
33
PIO2(void)34 PIO2::PIO2(void)
35 {
36 _irq[A] = _irq[B] = 0;
37 _value[A] = _value[B] = 0;
38 _irq_vector[A] = _irq_vector[B] = 0;
39 _ready[A] = _ready[B] = 1;
40 _strobe[A] = _strobe[B] = 0;
41
42 _irq_enable[A] = _irq_enable[B] = 0;
43 _irq_active[A] = _irq_active[B] = 0;
44 }
45
~PIO2(void)46 PIO2::~PIO2(void)
47 {
48 }
49
50 byte_t
in(word_t addr)51 PIO2::in(word_t addr)
52 {
53 DBG(2, form("KCemu/PIO/2/in",
54 "PIO2::in(): addr = %04x\n",
55 addr));
56
57 switch (addr & 3)
58 {
59 case 0:
60 return in_A_DATA();
61 case 1:
62 return in_B_DATA();
63 case 2:
64 return in_A_CTRL();
65 case 3:
66 return in_B_CTRL();
67 }
68
69 return 0; // shouldn't be reached
70 }
71
72 void
out(word_t addr,byte_t val)73 PIO2::out(word_t addr, byte_t val)
74 {
75 DBG(2, form("KCemu/PIO/2/out",
76 "PIO2::out(): addr = %04x, val = %02x\n",
77 addr, val));
78
79 switch (addr & 3)
80 {
81 case 0:
82 out_A_DATA(val);
83 break;
84 case 1:
85 out_B_DATA(val);
86 break;
87 case 2:
88 out_A_CTRL(val);
89 break;
90 case 3:
91 out_B_CTRL(val);
92 break;
93 }
94 }
95
96 void
change_A(byte_t changed,byte_t val)97 PIO2::change_A(byte_t changed, byte_t val)
98 {
99 if (changed & 0x01)
100 {
101 DBG(2, form("KCemu/PIO/2/change/A",
102 "PIO A: CAOS ROM E [%d]\n",
103 (val & 1)));
104 memory->enableCAOS(val & 0x01);
105 }
106 if (changed & 0x02)
107 {
108 DBG(2, form("KCemu/PIO/2/change/A",
109 "PIO A: RAM 0 [%d]\n",
110 ((val >> 1) & 1)));
111 memory->enableRAM(val & 0x02);
112 }
113 if (changed & 0x04)
114 {
115 DBG(2, form("KCemu/PIO/2/change/A",
116 "PIO A: IRM [%d]\n",
117 ((val >> 2) & 1)));
118 memory->enableIRM(val & 0x04);
119 }
120 if (changed & 0x08)
121 {
122 DBG(2, form("KCemu/PIO/2/change/A",
123 "PIO A: write protect RAM 0 [%d]\n",
124 ((val >> 3) & 1)));
125 memory->protectRAM(val & 0x08);
126 }
127 if (changed & 0x10)
128 {
129 DBG(2, form("KCemu/PIO/2/change/A",
130 "PIO A: K OUT (unused) [%d]\n",
131 ((val >> 4) & 1)));
132 }
133 if (changed & 0x20)
134 {
135 DBG(2, form("KCemu/PIO/2/change/A",
136 "PIO A: LED [%d]\n",
137 ((val >> 5) & 1)));
138 }
139 if (changed & 0x40)
140 {
141 DBG(2, form("KCemu/PIO/2/change/A",
142 "PIO A: TAPE Power [%d]\n",
143 ((val >> 6) & 1)));
144 tape->power((val >> 6) & 1);
145 }
146 }
147
change_B(byte_t changed,byte_t val)148 void PIO2::change_B(byte_t changed, byte_t val)
149 {
150 if (changed & 0x01)
151 {
152 DBG(2, form("KCemu/PIO/2/change/B",
153 "PIO B: flip-flop [%d]\n",
154 (val & 1)));
155 }
156 if (changed & 0x0e)
157 {
158 DBG(2, form("KCemu/PIO/2/change/B",
159 "PIO B: volume [%d]\n",
160 ((val >> 1) & 7)));
161 }
162 if (changed & 0x10)
163 {
164 DBG(2, form("KCemu/PIO/2/change/B",
165 "PIO B: unused 0x10 [%d]\n",
166 ((val >> 4) & 1)));
167 }
168 if (changed & 0x20)
169 {
170 DBG(2, form("KCemu/PIO/2/change/B",
171 "PIO B: RAM 8 [%d]\n",
172 ((val >> 5) & 1)));
173 }
174 if (changed & 0x40)
175 {
176 DBG(2, form("KCemu/PIO/2/change/B",
177 "PIO B: RAM 8 write protect [%d]\n",
178 ((val >> 6) & 1)));
179 }
180 if (changed & 0x80)
181 {
182 DBG(2, form("KCemu/PIO/2/change/B",
183 "PIO B: foreground blink [%d]\n",
184 ((val >> 6) & 1)));
185 }
186 }
187
188 void
tape_callback(byte_t val)189 PIO2::tape_callback(byte_t val)
190 {
191 strobe_A();
192 }
193