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 #ifndef __kc_pio_h
21 #define __kc_pio_h
22 
23 #include "kc/system.h"
24 
25 #include "kc/ic.h"
26 #include "kc/ports.h"
27 
28 class PIOCallbackInterface
29 {
30  public:
PIOCallbackInterface(void)31   PIOCallbackInterface(void) {}
~PIOCallbackInterface(void)32   virtual ~PIOCallbackInterface(void) {}
33 
34   virtual int callback_A_in(void) = 0;
35   virtual int callback_B_in(void) = 0;
36   virtual void callback_A_out(byte_t val) = 0;
37   virtual void callback_B_out(byte_t val) = 0;
38 };
39 
40 class PIO : public InterfaceCircuit, public PortInterface
41 {
42   protected:
43   enum {
44     A = 0,
45     B = 1,
46   };
47 
48   enum {
49     MODE_OUTPUT        = 0,
50     MODE_INPUT         = 1,
51     MODE_BIDIRECTIONAL = 2,
52     MODE_CONTROL       = 3,
53   };
54 
55   /*
56    *  track first out instruction to allow complete
57    *  initialisation
58    */
59   bool _first_out[2];
60 
61     /*
62      *  external value
63      */
64     byte_t _ext[2];
65 
66     /*
67      *  value of the logical function that triggers the irq in bit-mode
68      *
69      */
70     byte_t _ext_fn[2];
71 
72     /*
73      *  pio mode: 0 - byte output
74      *            1 - byte input
75      *            2 - byte input/output
76      *            3 - bit  input/output
77      */
78     byte_t _mode[2];
79     byte_t _bit_mode[2];
80     bool   _bit_mode_follows[2];
81 
82     /*
83      *  interrupt vector:
84      */
85     byte_t _irq_vector[2];
86 
87     /*
88      *  interrupt control: 0 - irq disabled
89      *                     1 - irq enabled
90      */
91     byte_t _irq[2];
92 
93     /*
94      *  interrupt logic:
95      */
96     byte_t _irq_mask[2];
97     byte_t _irq_h_l[2];
98     byte_t _irq_and_or[2];
99     bool   _irq_mask_follows[2];
100 
101     /*
102      *  interrupt enable input/ output
103      */
104     byte_t _irq_enable[2];
105     byte_t _irq_active[2];
106 
107     byte_t _strobe[2];
108     byte_t _ready[2];
109 
110     byte_t _value[2];
111 
112     /*
113      *  interrupt mask for daisy chain handling
114      */
115     dword_t _z80_irq_mask;
116 
117     /*
118      *  callbacks
119      */
120     PIOCallbackInterface *_cb_a_in;
121     PIOCallbackInterface *_cb_a_out;
122     PIOCallbackInterface *_cb_b_in;
123     PIOCallbackInterface *_cb_b_out;
124 
125     void out_CTRL(int port, byte_t val);
126     void set_EXT(int port, byte_t mask, byte_t val);
127     void trigger_irq(int port);
128 
129     virtual void change_A(byte_t changed, byte_t val) = 0;
130     virtual void change_B(byte_t changed, byte_t val) = 0;
131 
132   public:
133     PIO(void);
134     virtual ~PIO(void);
135 
136     virtual void info(void);
137     virtual byte_t in_A_DATA(void);
138     virtual byte_t in_B_DATA(void);
139     virtual byte_t in_A_CTRL(void);
140     virtual byte_t in_B_CTRL(void);
141     virtual void out_A_DATA(byte_t val);
142     virtual void out_B_DATA(byte_t val);
143     virtual void out_A_CTRL(byte_t val);
144     virtual void out_B_CTRL(byte_t val);
145     virtual void set_A_EXT(byte_t mask, byte_t val);
146     virtual void set_B_EXT(byte_t mask, byte_t val);
147     virtual void strobe_A(void);
148     virtual void strobe_B(void);
149     virtual int  ready_A(void);
150     virtual int  ready_B(void);
151 
getModeA(void)152     virtual byte_t getModeA(void) { return _mode[A]; }
getModeB(void)153     virtual byte_t getModeB(void) { return _mode[B]; }
getIRQA(void)154     virtual byte_t getIRQA(void) { return _irq[A]; }
getIRQB(void)155     virtual byte_t getIRQB(void) { return _irq[B]; }
getIRQVectorA(void)156     virtual byte_t getIRQVectorA(void) { return _irq_vector[A]; }
getIRQVectorB(void)157     virtual byte_t getIRQVectorB(void) { return _irq_vector[B]; }
158 
159     /*
160      *  InterfaceCircuit
161      */
162     virtual void reti(void);
163     virtual void irqreq(void);
164     virtual word_t irqack(void);
165     virtual void reset(bool power_on = false);
166 
167     /*
168      *  callback registering functions
169      */
170     virtual void register_callback_A_in(PIOCallbackInterface *cbi);
171     virtual void register_callback_A_out(PIOCallbackInterface *cbi);
172     virtual void register_callback_B_in(PIOCallbackInterface *cbi);
173     virtual void register_callback_B_out(PIOCallbackInterface *cbi);
174 };
175 
176 #endif /* __kc_pio_h */
177 
178