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