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