1 #define CTC_LOWEST_PORT (0xcc&~3)
2
3 #include <stdio.h>
4 #include "../z80-cpu.h"
5 #include "daisy_chain.h"
6
7 enum ctc_triggers { trg0, trg1, trg2, trg3, clk };
8 enum ctc_control_pins { cs0, cs1, ctc_ce, ctc_rd, ctc_m1, ctc_iorq, ctc_iei, ctc_reset};
9
10 static bit pin[8];
11
12 #define cs (pin[1]<<1|pin[0])
13
14 static _uchar cbyte[4], tbyte[4], ibyte[4];
15 static unsigned short counter[4];
16 static FILE *fp;
17 static unsigned long ticks_copy;
18
19
is_ctc_port(unsigned char port)20 bool is_ctc_port(unsigned char port)
21 {
22 return port>>2 == CTC_LOWEST_PORT>>2 ; /* 4 successive ports */
23 }
24
25
reset_ctc(void)26 void reset_ctc(void)
27 {
28 int i;
29 for (i=0;i<4;i++)
30 cbyte[i]=0;
31 for (i=0;i<8;i++)
32 pin[i]=0;
33 }
34
35
init_ctc(void)36 int init_ctc(void)
37 {
38 reset_ctc();
39 return !(fp=fopen(Z80_PORTS,"rb"));
40 }
41
42
ctc_supplies_byte(unsigned char channel)43 unsigned char ctc_supplies_byte(unsigned char channel)
44 { return ibyte[channel&3];
45 }
46
47
48 /* function returns a pointer to a function which is */
49 /* taking an unsigned char and returns an unsigned char */
50 /* WOULD BE SIMPLER: typedef unsigned char(*ptr_Func)(unsigned char); */
51 /* ptr_Func acknowledge_inter(void){...} */
52 unsigned char (*
acknowledge_inter(void)53 acknowledge_inter(void)
54 )(unsigned char)
55 {
56 set_cpu_pin(inter,0);
57 return ctc_supplies_byte;
58 }
59
60
action(unsigned channel)61 void action(unsigned channel)
62 {
63 counter[channel]= tbyte[channel] << (cbyte[channel]&32?8:4);
64 if (cbyte[channel]&128)
65 set_my_priority(channel,acknowledge_inter);
66 if (channel==trg2)
67 { void send_pulse_to_ctc(unsigned channel);
68 send_pulse_to_ctc(trg3); /* hardwired cascade */
69 }
70 }
71
72
read_word(unsigned char port)73 unsigned char read_word(unsigned char port)
74 {
75 unsigned char byte;
76 #ifndef INDIRECT_CTC
77 byte= DATA;
78 #else
79 if (!fp)
80 return 0xff;
81 fflush(fp);
82 if (fseek(fp,(long)port,SEEK_SET))
83 return 0xff; /* hardware malfunction */
84 fread(&byte,1,1,fp);
85 #endif
86 return byte;
87 }
88
89
react(unsigned char byte)90 void react(unsigned char byte)
91 {
92 if (cbyte[cs]&4)
93 {
94 tbyte[cs]=byte;
95 cbyte[cs]&= ~4;
96 if (cbyte[cs]&8)
97 cbyte[cs]|=1;
98 return;
99 }
100 if (byte&1) /* control word */
101 {
102 cbyte[cs]= byte&~3;
103 if (byte&2)
104 cbyte[cs] &= ~1;
105 /*************
106 if (byte&4)
107 4 ticks later: in_byte(port,&tbyte[cs]);
108 **************/
109 }
110 else /* interrupt vector supplied */
111 ibyte[cs1] = (byte&~7) | cs<<1 ;
112 }
113
114
send_pulse_to_ctc(unsigned channel)115 void send_pulse_to_ctc(unsigned channel)
116 {
117 if (channel >= 4)
118 { int i;
119 ticks_copy++;
120 for (i=0;i<4;i++)
121 if ((cbyte[i]&1) && !(cbyte[i]&64))
122 if (--counter[i] == 0)
123 action(i);
124
125 }
126 else if ((cbyte[channel]&1) && (cbyte[channel]&64))
127 {
128 if (--counter[channel] == 0)
129 action(channel);
130 }
131 if ((ADDRESS&255) == CTC_LOWEST_PORT+cs && cpu_pin[iorq] && !pin[ctc_rd])
132 react(read_word(CTC_LOWEST_PORT+cs));
133 }
134
135
set_ctc_pin(unsigned c_pin,bit level)136 void set_ctc_pin(unsigned c_pin, bit level)
137 {
138 pin[c_pin&7] = level;
139 if (level)
140 switch (c_pin)
141 {
142 case cs0: break;
143 case cs1: break;
144 case ctc_iei: break;
145 }
146 else
147 switch (c_pin)
148 {
149 case ctc_rd: break;
150 case ctc_m1: break;
151 case ctc_ce: break;
152 case ctc_iorq: break;
153 case ctc_reset: reset_ctc(); break;
154 }
155 }
156