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_ctc_h
21 #define __kc_ctc_h
22 
23 #include <list>
24 
25 #include "kc/system.h"
26 
27 #include "kc/ic.h"
28 #include "kc/cb.h"
29 #include "kc/ports.h"
30 
31 class CTCCallbackInterface
32 {
33  public:
CTCCallbackInterface(void)34   CTCCallbackInterface(void) {}
~CTCCallbackInterface(void)35   virtual ~CTCCallbackInterface(void) {}
36 
37   virtual void ctc_callback_ZC(int channel) = 0;
38   virtual void ctc_callback_TC(int channel, long tc) = 0;
39   virtual void ctc_callback_start(int channel) = 0;
40   virtual void ctc_callback_stop(int channel) = 0;
41 };
42 
43 class CTC : public InterfaceCircuit, public PortInterface, public Callback
44 {
45  protected:
46   typedef std::list<CTCCallbackInterface *>cb_list_t;
47   typedef cb_list_t::iterator iterator;
48 
49   enum {
50     IRQ            = 0x80,
51     IRQ_DISABLED   = 0x00,
52     IRQ_ENABLED    = 0x80,
53 
54     MODE           = 0x40,
55     MODE_TIMER     = 0x00,
56     MODE_COUNTER   = 0x40,
57 
58     PRESCALER      = 0x20,
59     PRESCALER_16   = 0x00,
60     PRESCALER_256  = 0x20,
61 
62     EDGE           = 0x10,
63     EDGE_FALLING   = 0x00,
64     EDGE_RISING    = 0x10,
65 
66     TRIGGER        = 0x08,
67     TRIGGER_AUTO   = 0x00,
68     TRIGGER_CLOCK  = 0x08,
69 
70     CONSTANT       = 0x04,
71     CONSTANT_NONE  = 0x00,
72     CONSTANT_LOAD  = 0x04,
73 
74     RESET          = 0x02,
75     RESET_NONE     = 0x00,
76     RESET_ACTIVE   = 0x02,
77 
78     CONTROL        = 0x01,
79     CONTROL_VECTOR = 0x00,
80     CONTROL_WORD   = 0x01,
81   };
82 
83   byte_t  _irq_vector;
84   byte_t  _control[4];
85   word_t  _value[4];
86   word_t _timer_value[4];
87   byte_t  _restart[4];
88   long long _counter[4];
89 
90   byte_t _irq_pending[4];
91   byte_t _irq_active[4];
92   long   _irq_valid[4];
93 
94   cb_list_t *_cb_list[4];
95 
96  private:
97   void handle_counter_mode(int channel);
98 
99  protected:
100   virtual long long get_counter() = 0;
101   virtual void trigger_irq(int channel) = 0;
102   virtual void add_callback(unsigned long long offset, Callback *cb, void *data) = 0;
103 
104   virtual void try_trigger_irq(int channel);
105 
106  public:
107   CTC(const char *name);
108   virtual ~CTC(void);
109 
110   virtual bool irq_0(void) = 0;
111   virtual bool irq_1(void) = 0;
112   virtual bool irq_2(void) = 0;
113   virtual bool irq_3(void) = 0;
114 
115   virtual long counter_value_0(void) = 0;
116   virtual long counter_value_1(void) = 0;
117   virtual long counter_value_2(void) = 0;
118   virtual long counter_value_3(void) = 0;
119 
120   void info(void);
121 
122   byte_t c_in(byte_t channel);
123   void c_out(byte_t channel, byte_t val);
124 
125   void trigger(byte_t channel);
126   void callback(void *data);
127 
getIRQVector(byte_t channel)128   byte_t getIRQVector(byte_t channel)
129     {
130       return _irq_vector + 2 * channel;
131     }
getIRQ(byte_t channel)132   byte_t getIRQ(byte_t channel)
133     {
134       return (_control[channel] & IRQ) == IRQ_ENABLED;
135     }
getTimerValue(byte_t channel)136   word_t getTimerValue(byte_t channel)
137     {
138       return _timer_value[channel];
139     }
isCounter(byte_t channel)140   bool isCounter(byte_t channel)
141     {
142       return ((_control[channel] & MODE) == MODE_COUNTER);
143     }
isReset(byte_t channel)144   bool isReset(byte_t channel)
145     {
146       return ((_control[channel] & RESET) == RESET_ACTIVE);
147     }
148 
149   /*
150    *  InterfaceCircuit
151    */
152   virtual void reti(void);
153   virtual void irqreq(void);
154   virtual word_t irqack(void);
155   virtual void reset(bool power_on = false);
156 
157   virtual void register_callback(int channel, CTCCallbackInterface *cbi);
158   virtual void run_cb_start(int channel);
159   virtual void run_cb_stop(int channel);
160   virtual void run_cb_tc(int channel, long tc);
161 };
162 
163 #endif /* __kc_ctc_h */
164