1 #include "driver.h"
2 #include "machine/rp5h01.h"
3
4 /****************************************************************************/
5
6 /* local copy of the interface pointer */
7 static struct RP5H01_interface *intf;
8
9 /* these also work as the address masks */
10 enum {
11 COUNTER_MODE_6_BITS = 0x3f,
12 COUNTER_MODE_7_BITS = 0x7f
13 };
14
15 typedef struct _RP5H01 {
16 int counter;
17 int counter_mode; /* test pin */
18 int enabled; /* chip enable */
19 int old_reset; /* reset pin state (level-triggered) */
20 int old_clock; /* clock pin state (level-triggered) */
21 unsigned char *data;
22 } RP5H01;
23
24 static RP5H01 RP5H01_state[MAX_RP5H01];
25
26 /****************************************************************************/
27
RP5H01_init(struct RP5H01_interface * interface)28 int RP5H01_init( struct RP5H01_interface *interface ) {
29 int i;
30
31 /* setup our local copy of the interface */
32 intf = interface;
33
34 if ( intf->num > MAX_RP5H01 ) {
35 log_cb(RETRO_LOG_DEBUG, LOGPRE "Requested number of RP5H01's is bigger than the supported amount\n" );
36 return -1;
37 }
38
39 /* initialize the state */
40 for( i = 0; i < intf->num; i++ ) {
41 RP5H01_state[i].counter = 0;
42 RP5H01_state[i].counter_mode = COUNTER_MODE_6_BITS;
43 RP5H01_state[i].data = &( memory_region( intf->region[i] )[ intf->offset[i] ] );
44 RP5H01_state[i].enabled = 0;
45 RP5H01_state[i].old_reset = -1;
46 RP5H01_state[i].old_clock = -1;
47 }
48
49 return 0;
50 }
51
52 /****************************************************************************/
53
RP5H01_enable_w(int which,int data)54 void RP5H01_enable_w( int which, int data ) {
55 RP5H01 *chip;
56
57 if ( which >= intf->num ) {
58 log_cb(RETRO_LOG_DEBUG, LOGPRE "RP5H01_enable: trying to access an unmapped chip\n" );
59 return;
60 }
61
62 /* get the chip */
63 chip = &RP5H01_state[which];
64
65 /* process the /CE signal and enable/disable the IC */
66 chip->enabled = ( data == 0 ) ? 1 : 0;
67 }
68
RP5H01_reset_w(int which,int data)69 void RP5H01_reset_w( int which, int data ) {
70 RP5H01 *chip;
71 int newstate = ( data == 0 ) ? 0 : 1;
72
73 if ( which >= intf->num ) {
74 log_cb(RETRO_LOG_DEBUG, LOGPRE "RP5H01_enable: trying to access an unmapped chip\n" );
75 return;
76 }
77
78 /* get the chip */
79 chip = &RP5H01_state[which];
80
81 /* if it's not enabled, ignore */
82 if ( !chip->enabled )
83 return;
84
85 /* now look for a 0->1 transition */
86 if ( chip->old_reset == 0 && newstate == 1 ) {
87 /* reset the counter */
88 chip->counter = 0;
89 }
90
91 /* update the pin */
92 chip->old_reset = newstate;
93 }
94
RP5H01_clock_w(int which,int data)95 void RP5H01_clock_w( int which, int data ) {
96 RP5H01 *chip;
97 int newstate = ( data == 0 ) ? 0 : 1;
98
99 if ( which >= intf->num ) {
100 log_cb(RETRO_LOG_DEBUG, LOGPRE "RP5H01_enable: trying to access an unmapped chip\n" );
101 return;
102 }
103
104 /* get the chip */
105 chip = &RP5H01_state[which];
106
107 /* if it's not enabled, ignore */
108 if ( !chip->enabled )
109 return;
110
111 /* now look for a 1->0 transition */
112 if ( chip->old_clock == 1 && newstate == 0 ) {
113 /* increment the counter, and mask it with the mode */
114 chip->counter++;
115 }
116
117 /* update the pin */
118 chip->old_clock = newstate;
119 }
120
RP5H01_test_w(int which,int data)121 void RP5H01_test_w( int which, int data ) {
122 RP5H01 *chip;
123
124 if ( which >= intf->num ) {
125 log_cb(RETRO_LOG_DEBUG, LOGPRE "RP5H01_enable: trying to access an unmapped chip\n" );
126 return;
127 }
128
129 /* get the chip */
130 chip = &RP5H01_state[which];
131
132 /* if it's not enabled, ignore */
133 if ( !chip->enabled )
134 return;
135
136 /* process the test signal and change the counter mode */
137 chip->counter_mode = ( data == 0 ) ? COUNTER_MODE_6_BITS : COUNTER_MODE_7_BITS;
138 }
139
RP5H01_counter_r(int which)140 int RP5H01_counter_r( int which ) {
141 RP5H01 *chip;
142
143 if ( which >= intf->num ) {
144 log_cb(RETRO_LOG_DEBUG, LOGPRE "RP5H01_enable: trying to access an unmapped chip\n" );
145 return 0;
146 }
147
148 /* get the chip */
149 chip = &RP5H01_state[which];
150
151 /* if it's not enabled, ignore */
152 if ( !chip->enabled )
153 return 0; /* ? (should be high impedance) */
154
155 /* return A5 */
156 return ( chip->counter >> 5 ) & 1;
157 }
158
RP5H01_data_r(int which)159 int RP5H01_data_r( int which ) {
160 RP5H01 *chip;
161 int byte, bit;
162
163 if ( which >= intf->num ) {
164 log_cb(RETRO_LOG_DEBUG, LOGPRE "RP5H01_enable: trying to access an unmapped chip\n" );
165 return 0;
166 }
167
168 /* get the chip */
169 chip = &RP5H01_state[which];
170
171 /* if it's not enabled, ignore */
172 if ( !chip->enabled )
173 return 0; /* ? (should be high impedance) */
174
175 /* get the byte offset and bit offset */
176 byte = ( chip->counter & chip->counter_mode) >> 3;
177 bit = 7 - ( chip->counter & 7 );
178
179 /* return the data */
180 return ( chip->data[byte] >> bit ) & 1;
181 }
182
183 /****************************************************************************/
184
WRITE_HANDLER(RP5H01_0_enable_w)185 WRITE_HANDLER( RP5H01_0_enable_w ) {
186 RP5H01_enable_w( 0, data );
187 }
188
WRITE_HANDLER(RP5H01_0_reset_w)189 WRITE_HANDLER( RP5H01_0_reset_w ) {
190 RP5H01_reset_w( 0, data );
191 }
192
WRITE_HANDLER(RP5H01_0_clock_w)193 WRITE_HANDLER( RP5H01_0_clock_w ) {
194 RP5H01_clock_w( 0, data );
195 }
196
WRITE_HANDLER(RP5H01_0_test_w)197 WRITE_HANDLER( RP5H01_0_test_w ) {
198 RP5H01_test_w( 0, data );
199 }
200
READ_HANDLER(RP5H01_0_counter_r)201 READ_HANDLER( RP5H01_0_counter_r ) {
202 return RP5H01_counter_r( 0 );
203 }
204
READ_HANDLER(RP5H01_0_data_r)205 READ_HANDLER( RP5H01_0_data_r ) {
206 return RP5H01_data_r( 0 );
207 }
208