]>
Commit | Line | Data |
---|---|---|
acd9bdaf L |
1 | /** |
2 | * | |
3 | * Pin assignments | |
4 | * | |
5 | * | Z180-Sig | STM32-Port | Buffer | Dir |Special Function | | |
6 | * | -------- | ---------- | ------ | --- | --------------- | | |
7 | * | A0 |A 1 |P |O | | | |
8 | * | A1 |A 2 |P |O | | | |
9 | * | A2 |A 3 |P |O | | | |
10 | * | A3 |A 4 |P |O | | | |
11 | * | A4 |A 5 |P |O | | | |
12 | * | A5 |A 6 |P |O | | | |
13 | * | A6 |A 7 |P |O | | | |
14 | * | A7 |A 8 | |O | | | |
15 | * | A8 |C 0 |P |O | | | |
16 | * | A9 |C 1 |P |O | | | |
17 | * | A10 |C 2 |P |O | | | |
18 | * | A11 |C 3 |P |O | | | |
19 | * | A12 |C 4 |P |O | | | |
20 | * | A13 |C 5 |P |O | | | |
21 | * | A14 |C 6 | |O | | | |
22 | * | A15 |C 7 | |O | | | |
23 | * | A16 |C 10 | |O | | | |
24 | * | A17 |C 11 | |O | | | |
25 | * | A18 |C 12 | |O | | | |
26 | * | D0 |B 8 | |I/O | | | |
27 | * | D1 |B 9 | |I/O | | | |
28 | * | D2 |B 10 | |I/O | | | |
29 | * | D3 |B 11 | |I/O | | | |
30 | * | D4 |B 12 | |I/O | | | |
31 | * | D5 |B 13 | |I/O | | | |
32 | * | D6 |B 14 | |I/O | | | |
33 | * | D7 |B 15 | |I/O | | | |
34 | * | ME |C 13 |P |O | | | |
35 | * | RD |B 0 |P |O | | | |
36 | * | WR |B 1 |P |O | | | |
37 | * | BUSREQ |D 2 | |O | | | |
38 | * | IOCS1 |A 11 | |I |TIM1_CH4 | | |
39 | * | BUSACK |A 12 | |I | | | |
40 | * | HALT |A 12 | |I | | | |
41 | * | NMI |B 7 | |O | | | |
42 | * | RST |B 6 | |O |TIM16_CH1N | | |
43 | * | | | | | | | |
44 | * | |A 9 | | |af1 USART1_TX | | |
45 | * | |A 10 | | |af1 USART1_RX | | |
46 | * | |A 15 | |JTDI | remap SPI1_NSS' | | |
47 | * | |B 3 | |JTDO |remap SPI1_SCK' | | |
48 | * | |B 4 | |NJTRST |remap SPI1_MISO' | | |
49 | * | |B 5 | | |remap SPI1_MOSI' | | |
50 | * | |C 14 | | |af1 OSC32 | | |
51 | * | |C 15 | | |af1 OSC32 | | |
e64eba00 | 52 | |
e64eba00 L |
53 | |
54 | AFIO_MAPR2 = | |
55 | AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON (frees | |
56 | AFIO_MAPR_SPI1_REMAP | |
57 | ||
acd9bdaf L |
58 | */ |
59 | ||
e64eba00 L |
60 | |
61 | #include <libopencm3/stm32/gpio.h> | |
62 | #include <libopencm3/stm32/rcc.h> | |
63 | #include <libopencm3/stm32/timer.h> | |
64 | #include <libopencm3/stm32/dma.h> | |
65 | #include "z80-if.h" | |
66 | ||
67 | /* Number of array elements */ | |
68 | #define NELEMS(x) (sizeof x/sizeof *x) | |
69 | ||
70 | #define ODR 0x0c | |
71 | #define IDR 0x08 | |
72 | ||
73 | #define CONCAT(x,y) x ## y | |
74 | #define EVALUATOR(x,y) CONCAT(x,y) | |
75 | ||
76 | #define GPIO_(X) CONCAT(GPIO, X) | |
77 | ||
e64eba00 | 78 | |
e64eba00 | 79 | |
e64eba00 L |
80 | |
81 | #define P_ME GPIOC | |
82 | #define ME 13 | |
83 | #define P_RD GPIOB | |
84 | #define RD 0 | |
85 | #define P_WR GPIOB | |
86 | #define WR 1 | |
87 | #define P_BUSREQ GPIOD | |
88 | #define BUSREQ 2 | |
89 | #define P_BUSACK GPIOA | |
acd9bdaf | 90 | #define BUSACK 12 |
e64eba00 L |
91 | //#define P_HALT GPIOA |
92 | //#define HALT 12 | |
acd9bdaf L |
93 | #define P_IOCS1 GPIOA |
94 | #define IOCS1 11 | |
e64eba00 L |
95 | #define P_NMI GPIOB |
96 | #define NMI 7 | |
97 | #define P_RST GPIOB | |
98 | #define RST 6 | |
99 | ||
100 | #define ADp1_OFS 0 | |
101 | #define ADp1_WIDTH 8 | |
102 | #define ADp1_SHIFT 1 | |
103 | #define ADp1_PORT GPIOA | |
104 | ||
105 | #define ADp2_OFS ADp1_WIDTH | |
106 | #define ADp2_WIDTH 8 | |
107 | #define ADp2_SHIFT 0 | |
108 | #define ADp2_PORT GPIOC | |
109 | ||
110 | #define ADp3_OFS (ADp2_OFS+ADp2_WIDTH) | |
111 | #define ADp3_WIDTH 3 | |
112 | #define ADp3_SHIFT 10 | |
113 | #define ADp3_PORT GPIOC | |
114 | ||
115 | #define ADunbuff1_WIDTH 1 | |
116 | #define ADunbuff1_SHIFT 8 | |
117 | #define ADunbuff1_PORT GPIOA | |
118 | ||
119 | #define ADunbuff2_WIDTH 2 | |
120 | #define ADunbuff2_SHIFT 6 | |
121 | #define ADunbuff2_PORT GPIOC | |
122 | ||
123 | #define ADunbuff3_WIDTH 3 | |
124 | #define ADunbuff3_SHIFT 10 | |
125 | #define ADunbuff3_PORT GPIOC | |
126 | ||
127 | #define DB_OFS 0 | |
128 | #define DB_WIDTH 8 | |
129 | #define DB_SHIFT 8 | |
130 | #define DB_PORT GPIOB | |
131 | ||
132 | #define GPIO_ME GPIO_(ME) | |
133 | #define GPIO_RD GPIO_(RD) | |
134 | #define GPIO_WR GPIO_(WR) | |
135 | #define GPIO_BUSREQ GPIO_(BUSREQ) | |
136 | #define GPIO_BUSACK GPIO_(BUSACK) | |
137 | //#define GPIO_HALT GPIO_(HALT) | |
acd9bdaf | 138 | #define GPIO_IOCS1 GPIO_(IOCS1) |
e64eba00 L |
139 | #define GPIO_NMI GPIO_(NMI) |
140 | #define GPIO_RST GPIO_(RST) | |
141 | ||
142 | #define Z80_O_ME BBIO_PERIPH(P_ME+ODR, ME) | |
143 | #define Z80_O_RD BBIO_PERIPH(P_RD+ODR, RD) | |
144 | #define Z80_O_WR BBIO_PERIPH(P_WR+ODR, WR) | |
145 | #define Z80_O_BUSREQ BBIO_PERIPH(P_BUSREQ+ODR, BUSREQ) | |
146 | #define Z80_O_NMI BBIO_PERIPH(P_NMI+ODR, NMI) | |
147 | #define Z80_O_RST BBIO_PERIPH(P_RST+ODR, RST) | |
148 | ||
149 | #define Z80_I_BUSACK BBIO_PERIPH(P_BUSACK+IDR, BUSACK) | |
150 | //#define Z80_I_HALT BBIO_PERIPH(P_HALT+IDR, HALT) | |
151 | ||
152 | ||
153 | #define MASK(n) ((1<<n)-1) | |
154 | ||
155 | #define IOFIELD_SET(src, ofs, width, shift) \ | |
156 | ((((src>>ofs) & MASK(width)) << shift) | ((((~src>>ofs) & MASK(width)) << shift) << 16)) | |
157 | ||
158 | #define IOFIELD_GET(src, width, shift) \ | |
159 | ((src>>shift) & MASK(width)) | |
160 | ||
161 | #define CNF_MODE_I_F (GPIO_CNF_INPUT_FLOAT<<2 |GPIO_MODE_INPUT) | |
162 | #define CNF_MODE_O_PP (GPIO_CNF_OUTPUT_PUSHPULL<<2 | GPIO_MODE_OUTPUT_10_MHZ) | |
163 | ||
164 | #define DB_MODE_INPUT ( (CNF_MODE_I_F << (4 * 0)) \ | |
165 | | (CNF_MODE_I_F << (4 * 1)) \ | |
166 | | (CNF_MODE_I_F << (4 * 2)) \ | |
167 | | (CNF_MODE_I_F << (4 * 3)) \ | |
168 | | (CNF_MODE_I_F << (4 * 4)) \ | |
169 | | (CNF_MODE_I_F << (4 * 5)) \ | |
170 | | (CNF_MODE_I_F << (4 * 6)) \ | |
171 | | (CNF_MODE_I_F << (4 * 7))) | |
172 | ||
173 | #define DB_MODE_OUTPUT ( (CNF_MODE_O_PP << (4 * 0)) \ | |
174 | | (CNF_MODE_O_PP << (4 * 1)) \ | |
175 | | (CNF_MODE_O_PP << (4 * 2)) \ | |
176 | | (CNF_MODE_O_PP << (4 * 3)) \ | |
177 | | (CNF_MODE_O_PP << (4 * 4)) \ | |
178 | | (CNF_MODE_O_PP << (4 * 5)) \ | |
179 | | (CNF_MODE_O_PP << (4 * 6)) \ | |
180 | | (CNF_MODE_O_PP << (4 * 7))) | |
181 | ||
182 | ||
183 | /*--------------------------------------------------------------------------*/ | |
184 | ||
e64eba00 L |
185 | static void tim16_setup(void) |
186 | { | |
acd9bdaf L |
187 | RCC_APB2RSTR |= RCC_APB2RSTR_TIM16RST; |
188 | RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM16RST; | |
e64eba00 L |
189 | |
190 | TIM16_BDTR = TIM_BDTR_MOE; | |
191 | ||
192 | TIM16_CCMR1 = 0 | |
193 | | TIM_CCMR1_OC1M_FORCE_LOW | |
e64eba00 L |
194 | | TIM_CCMR1_CC1S_OUT; |
195 | ||
196 | TIM16_CCER = TIM_CCER_CC1NE | |
197 | | TIM_CCER_CC1NP; | |
198 | ||
199 | TIM16_ARR = 48; /* default */ | |
200 | TIM16_CCR1 = 1; /* */ | |
201 | } | |
202 | ||
203 | /*--------------------------------------------------------------------------*/ | |
204 | ||
acd9bdaf | 205 | static void tim16_set(int mode) |
e64eba00 L |
206 | { |
207 | uint16_t cc_mode; | |
208 | ||
209 | cc_mode = TIM_CCMR1_CC1S_OUT; | |
210 | ||
211 | TIM16_CR1 = TIM_CR1_OPM; | |
212 | ||
213 | if (mode < 0) | |
214 | cc_mode |= TIM_CCMR1_OC1M_FORCE_LOW; | |
215 | else if (mode == 0) | |
216 | cc_mode |= TIM_CCMR1_OC1M_FORCE_HIGH; | |
217 | else { | |
218 | TIM16_ARR = mode; | |
219 | cc_mode |= TIM_CCMR1_OC1M_PWM2; | |
220 | } | |
221 | ||
222 | TIM16_CCMR1 = cc_mode; | |
223 | ||
224 | if (mode > 0) | |
225 | TIM16_CR1 |= TIM_CR1_CEN; | |
226 | } | |
227 | ||
228 | /*--------------------------------------------------------------------------*/ | |
229 | ||
230 | ||
231 | ||
232 | /* | |
233 | * A0..A6, A8..A13 are buffered. No need to disable. | |
234 | * A7, A14..A18: set to input. | |
235 | */ | |
236 | ||
237 | static void z80_setup_adrbus_tristate(void) | |
238 | { | |
239 | #if 0 | |
240 | gpio_set_mode(ADunbuff1_PORT, GPIO_MODE_INPUT, | |
241 | GPIO_CNF_INPUT_FLOAT, MASK(ADunbuff1_WIDTH) << ADunbuff1_SHIFT); | |
242 | gpio_set_mode(ADunbuff2_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, | |
243 | (MASK(ADunbuff2_WIDTH) << ADunbuff2_SHIFT) | (MASK(ADunbuff3_WIDTH) << ADunbuff3_SHIFT)); | |
244 | #else | |
245 | GPIO_CRH(GPIOA) = (GPIO_CRH(GPIOA) & ~(0x0f << (4 * 0))) | |
246 | | (CNF_MODE_I_F << (4 * 0)); | |
247 | GPIO_CRL(GPIOC) = (GPIO_CRL(GPIOC) & ~((0x0f << (4 * 6)) | (0x0f << (4 * 7)))) | |
248 | | ((CNF_MODE_I_F << (4 * 6)) | (CNF_MODE_I_F << (4 * 7))); | |
249 | GPIO_CRH(GPIOC) = (GPIO_CRH(GPIOC) & ~((0x0f << (4*2)) | (0x0f << (4*3)) | (0x0f << (4*4)))) | |
250 | | ((CNF_MODE_I_F << (4*2)) | (CNF_MODE_I_F << (4*3)) | (CNF_MODE_I_F << (4*4))); | |
251 | #endif | |
252 | } | |
253 | ||
254 | ||
255 | static void z80_setup_adrbus_active(void) | |
256 | { | |
257 | #if 0 | |
258 | gpio_set_mode(ADunbuff1_PORT, GPIO_MODE_OUTPUT_10_MHZ, | |
259 | GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADunbuff1_WIDTH) << ADunbuff1_SHIFT); | |
260 | gpio_set_mode(ADunbuff2_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, | |
261 | (MASK(ADunbuff2_WIDTH) << ADunbuff2_SHIFT) | (MASK(ADunbuff3_WIDTH) << ADunbuff3_SHIFT)); | |
262 | #else | |
263 | GPIO_CRH(GPIOA) = (GPIO_CRH(GPIOA) & ~(0x0f << (4 * 0))) | |
264 | | (CNF_MODE_O_PP << (4 * 0)); | |
265 | GPIO_CRL(GPIOC) = (GPIO_CRL(GPIOC) & ~((0x0f << (4 * 6)) | (0x0f << (4 * 7)))) | |
266 | | ((CNF_MODE_O_PP << (4 * 6)) | (CNF_MODE_O_PP << (4 * 7))); | |
267 | GPIO_CRH(GPIOC) = (GPIO_CRH(GPIOC) & ~((0x0f << (4*2)) | (0x0f << (4*3)) | (0x0f << (4*4)))) | |
268 | | ((CNF_MODE_O_PP << (4*2)) | (CNF_MODE_O_PP << (4*3)) | (CNF_MODE_O_PP << (4*4))); | |
269 | #endif | |
270 | } | |
271 | ||
272 | ||
273 | static void z80_setup_dbus_in(void) | |
274 | { | |
275 | GPIO_CRH(DB_PORT) = DB_MODE_INPUT; | |
276 | } | |
277 | ||
278 | static void z80_setup_dbus_out(void) | |
279 | { | |
280 | GPIO_CRH(DB_PORT) = DB_MODE_OUTPUT; | |
281 | } | |
282 | ||
283 | ||
284 | static void z80_setaddress(uint32_t addr) | |
285 | { | |
286 | GPIO_BSRR(ADp1_PORT) = IOFIELD_SET(addr, ADp1_OFS, ADp1_WIDTH, ADp1_SHIFT); | |
287 | GPIO_BSRR(ADp2_PORT) = IOFIELD_SET(addr, ADp2_OFS, ADp2_WIDTH, ADp2_SHIFT); | |
288 | GPIO_BSRR(ADp3_PORT) = IOFIELD_SET(addr, ADp3_OFS, ADp3_WIDTH, ADp3_SHIFT); | |
289 | } | |
290 | ||
291 | void z80_setup_bus(void) | |
292 | { | |
293 | tim16_setup(); | |
acd9bdaf | 294 | |
e64eba00 L |
295 | gpio_set_mode(P_RST, GPIO_MODE_OUTPUT_10_MHZ, |
296 | GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_RST); | |
297 | Z80_O_BUSREQ = 1; | |
298 | gpio_set_mode(P_BUSREQ, GPIO_MODE_OUTPUT_10_MHZ, | |
299 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO_BUSREQ); | |
300 | Z80_O_NMI = 1; | |
301 | gpio_set_mode(P_NMI, GPIO_MODE_OUTPUT_10_MHZ, | |
302 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO_NMI); | |
303 | Z80_O_ME = 1; | |
304 | Z80_O_RD = 1; | |
305 | Z80_O_WR = 1; | |
306 | gpio_set_mode(P_ME, GPIO_MODE_OUTPUT_2_MHZ, | |
307 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO_ME); | |
308 | gpio_set_mode(P_RD, GPIO_MODE_OUTPUT_10_MHZ, | |
309 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO_RD | GPIO_WR); | |
310 | ||
e64eba00 L |
311 | //Z80_O_BUSREQ = 0; |
312 | //while(Z80_I_BUSACK == 1); | |
313 | ||
314 | gpio_set_mode(ADp1_PORT, GPIO_MODE_OUTPUT_10_MHZ, | |
315 | GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp1_WIDTH) << ADp1_SHIFT); | |
316 | gpio_set_mode(ADp2_PORT, GPIO_MODE_OUTPUT_10_MHZ, | |
317 | GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp2_WIDTH) << ADp2_SHIFT); | |
318 | gpio_set_mode(ADp3_PORT, GPIO_MODE_OUTPUT_10_MHZ, | |
319 | GPIO_CNF_OUTPUT_PUSHPULL, MASK(ADp3_WIDTH) << ADp3_SHIFT); | |
320 | ||
321 | z80_setup_dbus_in(); | |
322 | } | |
323 | ||
acd9bdaf | 324 | void z80_request_bus(void) |
e64eba00 L |
325 | { |
326 | Z80_O_BUSREQ = 0; | |
327 | while(Z80_I_BUSACK == 1); | |
328 | z80_setup_adrbus_active(); | |
329 | } | |
330 | ||
331 | void z80_release_bus(void) | |
332 | { | |
333 | z80_setup_dbus_in(); | |
334 | z80_setup_adrbus_tristate(); | |
335 | Z80_O_BUSREQ = 1; | |
336 | while(Z80_I_BUSACK == 0); | |
337 | } | |
338 | ||
339 | void z80_reset(level_t level) | |
340 | { | |
341 | int x = level ? -1 : 0; | |
342 | ||
343 | tim16_set(x); | |
344 | ||
345 | // Z80_O_RST = level; | |
346 | } | |
347 | ||
348 | void z80_reset_pulse(void) | |
349 | { | |
350 | tim16_set(48); | |
351 | } | |
352 | ||
353 | void z80_busreq(level_t level) | |
354 | { | |
355 | Z80_O_BUSREQ = level; | |
356 | } | |
357 | ||
358 | #if 0 | |
359 | int z80_stat_halt(void) | |
360 | { | |
361 | return Z80_I_HALT; | |
362 | } | |
363 | #endif | |
364 | ||
365 | void z80_write(uint32_t addr, uint8_t data) | |
366 | { | |
367 | z80_setaddress(addr); | |
368 | Z80_O_ME = 0; | |
369 | GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT); | |
370 | z80_setup_dbus_out(); | |
371 | Z80_O_WR = 0; | |
372 | Z80_O_WR = 1; | |
373 | Z80_O_ME = 1; | |
374 | } | |
375 | ||
376 | uint8_t z80_read(uint32_t addr) | |
377 | { | |
378 | uint8_t data; | |
379 | ||
380 | z80_setaddress(addr); | |
381 | Z80_O_ME = 0; | |
382 | z80_setup_dbus_in(); | |
383 | Z80_O_RD = 0; | |
384 | Z80_O_RD = 0; | |
385 | data = IOFIELD_GET(GPIO_IDR(DB_PORT),DB_WIDTH, DB_SHIFT); | |
386 | Z80_O_RD = 1; | |
387 | Z80_O_ME = 1; | |
388 | ||
389 | return data; | |
390 | } | |
391 | ||
392 | ||
393 | void z80_memset(uint32_t addr, uint8_t data, int length) | |
394 | { | |
395 | z80_setup_dbus_out(); | |
396 | Z80_O_ME = 0; | |
397 | while(length--) { | |
398 | z80_setaddress(addr++); | |
399 | GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT); | |
400 | Z80_O_WR = 0; | |
401 | Z80_O_WR = 1; | |
402 | } | |
403 | Z80_O_ME = 1; | |
404 | } | |
405 | ||
406 | void z80_write_block(uint8_t *src, uint32_t dest, uint32_t length) | |
407 | { | |
408 | uint8_t data; | |
409 | ||
410 | z80_setup_dbus_out(); | |
411 | Z80_O_ME = 0; | |
412 | while(length--) { | |
413 | z80_setaddress(dest++); | |
414 | data = *src++; | |
415 | GPIO_BSRR(DB_PORT) = IOFIELD_SET(data, DB_OFS, DB_WIDTH, DB_SHIFT); | |
416 | Z80_O_WR = 0; | |
417 | Z80_O_WR = 1; | |
418 | } | |
419 | Z80_O_ME = 1; | |
420 | } | |
421 | ||
422 | /* | |
423 | 0179' rx.bs_mask: ds 1 ; (buf_len - 1) | |
424 | 017A' rx.in_idx: ds 1 ; | |
425 | 017B' rx.out_idx: ds 1 ; | |
426 | 017C' rx.buf: ds rx.buf_len ; | |
427 | 018B' rx.buf_end equ $-1 ; last byte (start+len-1) | |
428 | ||
429 | 018C' tx.bs_mask: ds 1 ; (buf_len - 1) | |
430 | 018D' tx.in_idx: ds 1 ; | |
431 | 018E' tx.out_idx: ds 1 ; | |
432 | 018F' tx.buf: ds tx.buf_len ; | |
433 | 019E' tx.buf_end equ $-1 ; last byte | |
434 | */ | |
435 | ||
436 | #define fifo_bufsize_mask -3 | |
437 | #define fifo_index_in -2 | |
438 | #define fifo_index_out -1 | |
439 | ||
440 | #if 1 | |
441 | ||
442 | static struct { | |
443 | uint32_t base; | |
444 | uint8_t idx_out, | |
445 | idx_in, | |
446 | mask; | |
acd9bdaf | 447 | } fifo_dsc[2]; |
e64eba00 | 448 | |
acd9bdaf | 449 | void z80_memfifo_init(void) |
e64eba00 | 450 | { |
acd9bdaf L |
451 | z80_request_bus(); |
452 | fifo_dsc[fifo_in].base = tx_fifo; | |
453 | fifo_dsc[fifo_in].idx_out = z80_read(tx_fifo+fifo_index_out); | |
454 | fifo_dsc[fifo_in].idx_in = z80_read(tx_fifo+fifo_index_in); | |
455 | fifo_dsc[fifo_in].mask = z80_read(tx_fifo+fifo_bufsize_mask); | |
456 | ||
457 | fifo_dsc[fifo_out].base = rx_fifo; | |
458 | fifo_dsc[fifo_out].idx_out = z80_read(rx_fifo+fifo_index_out); | |
459 | fifo_dsc[fifo_out].idx_in = z80_read(rx_fifo+fifo_index_in); | |
460 | fifo_dsc[fifo_out].mask = z80_read(rx_fifo+fifo_bufsize_mask); | |
e64eba00 L |
461 | z80_release_bus(); |
462 | } | |
463 | #endif | |
464 | ||
acd9bdaf | 465 | int z80_memfifo_is_empty(fifo_t f) |
e64eba00 | 466 | { |
acd9bdaf | 467 | uint32_t adr = fifo_dsc[f].base+fifo_index_in; |
e64eba00 L |
468 | uint8_t idx; |
469 | ||
acd9bdaf | 470 | z80_request_bus(); |
e64eba00 L |
471 | idx = z80_read(adr); |
472 | z80_release_bus(); | |
473 | ||
acd9bdaf | 474 | return idx == fifo_dsc[f].idx_out; |
e64eba00 L |
475 | } |
476 | ||
acd9bdaf | 477 | int z80_memfifo_is_full(fifo_t f) |
e64eba00 L |
478 | { |
479 | int rc; | |
480 | ||
acd9bdaf L |
481 | z80_request_bus(); |
482 | rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask) | |
483 | == z80_read(fifo_dsc[f].base+fifo_index_out); | |
e64eba00 L |
484 | z80_release_bus(); |
485 | ||
486 | return rc; | |
487 | } | |
488 | ||
acd9bdaf | 489 | uint8_t z80_memfifo_getc(fifo_t f) |
e64eba00 L |
490 | { |
491 | uint8_t rc, idx; | |
492 | ||
acd9bdaf | 493 | while (z80_memfifo_is_empty(f)) |
e64eba00 L |
494 | ; |
495 | ||
acd9bdaf L |
496 | z80_request_bus(); |
497 | idx = fifo_dsc[f].idx_out; | |
498 | rc = z80_read(fifo_dsc[f].base+idx); | |
499 | fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask; | |
500 | z80_write(fifo_dsc[f].base+fifo_index_out, fifo_dsc[f].idx_out); | |
e64eba00 L |
501 | z80_release_bus(); |
502 | ||
503 | return rc; | |
504 | } | |
505 | ||
506 | ||
acd9bdaf | 507 | void z80_memfifo_putc(fifo_t f, uint8_t val) |
e64eba00 L |
508 | { |
509 | int idx; | |
510 | ||
acd9bdaf | 511 | while (z80_memfifo_is_full(f)) |
e64eba00 L |
512 | ; |
513 | ||
acd9bdaf L |
514 | z80_request_bus(); |
515 | idx = fifo_dsc[f].idx_in; | |
516 | z80_write(fifo_dsc[f].base+idx, val); | |
517 | fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask; | |
518 | z80_write(fifo_dsc[f].base+fifo_index_in, fifo_dsc[f].idx_in); | |
e64eba00 L |
519 | z80_release_bus(); |
520 | } | |
521 | ||
acd9bdaf L |
522 | /*--------------------------------------------------------------------------*/ |
523 | ||
524 | //volatile uint8_t io_infifo[256]; | |
525 | ||
526 | static struct { | |
527 | uint8_t idx_out, | |
528 | idx_in; | |
529 | uint16_t count; | |
530 | uint8_t buf[256]; | |
531 | } io_infifo; | |
532 | ||
533 | /*--------------------------------------------------------------------------*/ | |
534 | ||
535 | static void tim1_setup(void) | |
536 | { | |
537 | RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST; | |
538 | RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST; | |
539 | ||
540 | TIM1_CR1 = 0; | |
541 | ||
542 | TIM1_SMCR = 0 | |
543 | /* | TIM_SMCR_ETP */ | |
544 | /* | TIM_SMCR_ETF_CK_INT_N_2 */ | |
545 | | TIM_SMCR_TS_ETRF | |
546 | | TIM_SMCR_SMS_OFF | |
547 | ; | |
548 | ||
549 | TIM1_DIER = TIM_DIER_TDE; | |
550 | ||
551 | ||
552 | TIM1_CCMR1 = 0 | |
553 | | TIM_CCMR1_OC1M_FORCE_LOW | |
554 | | TIM_CCMR1_CC1S_OUT; | |
555 | ||
556 | TIM1_SMCR |= TIM_SMCR_SMS_TM; | |
557 | } | |
558 | ||
559 | /*--------------------------------------------------------------------------*/ | |
560 | ||
561 | static void tim1_ch4_setup(void) | |
562 | { | |
563 | /* Reset Timer 1 */ | |
564 | RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST; | |
565 | RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST; | |
566 | ||
567 | TIM1_CCMR2 = 0 | |
568 | | TIM_CCMR2_CC4S_IN_TI2 | |
569 | | TIM_CCMR2_IC4F_OFF | |
570 | | TIM_CCMR2_IC4PSC_OFF; | |
571 | ||
572 | TIM1_CCER = 0 | |
573 | /* | TIM_CCER_CC4P */ | |
574 | | TIM_CCER_CC4E; | |
575 | ||
576 | /* Enable DMA for channel 4 */ | |
577 | TIM1_DIER = TIM_DIER_CC4DE; | |
578 | } | |
579 | ||
580 | /*--------------------------------------------------------------------------*/ | |
581 | ||
582 | static void dma1_ch4_setup(void) | |
583 | { | |
584 | DMA1_CCR4 = | |
585 | DMA_CCR_PL_VERY_HIGH | |
586 | | DMA_CCR_MSIZE_8BIT | |
587 | | DMA_CCR_PSIZE_8BIT | |
588 | | DMA_CCR_MINC | |
589 | | DMA_CCR_CIRC; | |
590 | ||
591 | DMA1_CMAR4 = (uint32_t) io_infifo.buf; | |
592 | ||
593 | #if (DB_SHIFT == 0) || (DB_SHIFT == 8) | |
594 | DMA1_CPAR4 = DB_PORT + IDR + DB_SHIFT/8; | |
595 | #else | |
596 | #error "Databus not byte aligned!" | |
597 | #endif | |
598 | ||
599 | DMA1_CNDTR4 = io_infifo.count = NELEMS(io_infifo.buf); | |
600 | ||
601 | DMA1_CCR4 |= DMA_CCR_EN; | |
602 | } | |
603 | ||
604 | /*--------------------------------------------------------------------------*/ | |
605 | ||
606 | void z80_setup_io_infifo(void) | |
607 | { | |
608 | gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT, | |
609 | GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1); | |
610 | ||
611 | tim1_ch4_setup(); | |
612 | dma1_ch4_setup(); | |
613 | } | |
614 | ||
615 | ||
616 | int z80_io_infifo_getc(void) | |
e64eba00 L |
617 | { |
618 | int c = -1; | |
619 | ||
acd9bdaf L |
620 | if (io_infifo.count != DMA1_CNDTR4) { |
621 | c = io_infifo.buf[NELEMS(io_infifo.buf) - io_infifo.count--]; | |
622 | if (io_infifo.count == 0) | |
623 | io_infifo.count = NELEMS(io_infifo.buf); | |
e64eba00 L |
624 | } |
625 | ||
626 | return c; | |
627 | } | |
628 |