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