]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/z80-if.c
new command: memsize. new function z80_memsize_detect().
[z180-stamp.git] / avr / z80-if.c
CommitLineData
35edb766
L
1/*
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
3 *
a1595a8e 4 * SPDX-License-Identifier: GPL-2.0
35edb766
L
5 */
6
0c5890bb
L
7/**
8 *
9 * Pin assignments
10 *
a1595a8e
L
11 * | Z180-Sig | AVR-Port | Dir |
12 * +------------+---------------+-------+
13 * | A0 | PA 0 | O |
14 * | A1 | PA 1 | O |
15 * | A2 | PA 2 | O |
16 * | A3 | PA 3 | O |
17 * | A4 | PA 4 | O |
18 * | A5 | PA 5 | O |
19 * | A6 | PA 6 | O |
20 * | A7 | PA 7 | O |
21 * | A8 | PC 0 | O |
22 * | A9 | PC 1 | O |
23 * | A10 | PC 2 | O |
24 * | A11 | PC 3 | O |
25 * | A12 | PC 4 | O |
26 * | A13 | PC 5 | O |
27 * | A14 | PC 6 | O |
28 * | A15 | PC 7 | O |
29 * | A16 | PE 2 | O |
30 * | A17 | PE 3 | O |
31 * | A18 | PE 4 | O |
32 * | D0 | PF 0 | I/O |
33 * | D1 | PF 1 | I/O |
34 * | D2 | PF 2 | I/O |
35 * | D3 | PF 3 | I/O |
36 * | D4 | PF 4 | I/O |
37 * | D5 | PF 5 | I/O |
38 * | D6 | PF 6 | I/O |
39 * | D7 | PF 7 | I/O |
40 * | RD | PD 3 | O |
41 * | WR | PD 2 | O |
42 * | MREQ | PD 4 | O |
43 * | RST | PD 5 | O |
44 * | BUSREQ | PD 7 | O |
45 * | BUSACK | PD 6 | I |
46 * |
47 * | Optional
48 * +------------------------------------+
49 * | STEP | PG 0 | O |
50 * | RUN | PG 1 | O |
51 * | WAIT | PG 2 | I |
0c5890bb 52
0c5890bb
L
53 */
54
ea6971b8 55
a1595a8e 56#include "z80-if.h"
f338df2a 57#include <util/atomic.h>
0c5890bb 58#include "debug.h"
a1595a8e
L
59#include "config.h"
60#include "env.h"
0c5890bb 61
0c5890bb 62
41d36f28
L
63//#define P_ZCLK PORTB
64//#define ZCLK 5
65//#define DDR_ZCLK DDRB
0c5890bb
L
66#define P_MREQ PORTD
67#define MREQ 4
68#define DDR_MREQ DDRD
69#define P_RD PORTD
70#define RD 3
71#define P_WR PORTD
72#define WR 2
73#define P_BUSREQ PORTD
74#define BUSREQ 7
75#define DDR_BUSREQ DDRD
76#define P_BUSACK PORTD
9b6b4b31 77#define PIN_BUSACK PIND
0c5890bb
L
78#define BUSACK 6
79#define DDR_BUSACK DDRD
0c5890bb 80#define P_RST PORTD
61bd408c 81#define PIN_RST PIND
0c5890bb
L
82#define DDR_RST DDRD
83#define RST 5
84
85
86#define P_DB PORTF
87#define PIN_DB PINF
88#define DDR_DB DDRF
89
90#define P_ADL PORTA
91#define P_ADH PORTC
92#define P_ADB PORTE
93#define PIN_ADB PINE
9b6b4b31
L
94#define DDR_ADL DDRA
95#define DDR_ADH DDRC
0c5890bb
L
96#define DDR_ADB DDRE
97
98#define ADB_WIDTH 3
99#define ADB_SHIFT 2
100//#define ADB_PORT PORTE
101
102
41d36f28 103//#define Z80_O_ZCLK SBIT(P_ZCLK, 5)
0c5890bb
L
104#define Z80_O_MREQ SBIT(P_MREQ, 4)
105#define Z80_O_RD SBIT(P_RD, 3)
106#define Z80_O_WR SBIT(P_WR, 2)
107#define Z80_O_BUSREQ SBIT(P_BUSREQ, 7)
108//#define Z80_O_NMI SBIT(P_NMI, )
109#define Z80_O_RST SBIT(P_RST, 5)
61bd408c 110#define Z80_I_RST SBIT(PIN_RST, 5)
9b6b4b31 111#define Z80_I_BUSACK SBIT(PIN_BUSACK, 6)
0c5890bb
L
112//#define Z80_I_HALT SBIT(P_HALT, )
113
a1595a8e
L
114/* Optional */
115#define P_RUN PORTG
116#define RUN 1
117#define DDR_RUN DDRG
118#define P_STEP PORTG
119#define STEP 0
120#define DDR_STEP DDRG
121#define P_WAIT PORTG
122#define WAIT 2
123#define DDR_WAIT DDRG
124/* All three signals are on the same Port (PortG) */
125#define PORT_SS PORTG
126#define DDR_SS DDRG
127#define PIN_SS PING
128#define Z80_O_RUN SBIT(PORT_SS, RUN)
129#define Z80_O_STEP SBIT(PORT_SS, STEP)
130#define Z80_I_WAIT SBIT(PORT_SS, WAIT)
131
9b6b4b31 132
ea6971b8
L
133#define BUS_TO 20
134
135
0c5890bb
L
136#define MASK(n) ((1<<(n))-1)
137#define SMASK(w,s) (MASK(w) << (s))
138
b35fcb2f
L
139void z80_bus_request_or_exit(void)
140{
141 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED))
142 cmd_error(CMD_RET_FAILURE, EBUSTO, NULL);
143}
0c5890bb 144
f338df2a 145static zstate_t zstate;
ea6971b8 146static volatile uint8_t timer; /* used for bus timeout */
61bd408c 147static bool reset_polarity;
ea6971b8
L
148
149/*---------------------------------------------------------*/
150/* 10Hz timer interrupt generated by OC4A */
151/*---------------------------------------------------------*/
152
a1595a8e 153ISR(TIMER5_COMPA_vect)
ea6971b8
L
154{
155
156 uint8_t i = timer;
157
158 if (i)
159 timer = i - 1;
160}
eded7ec4 161
0c5890bb
L
162/*--------------------------------------------------------------------------*/
163
6035a17b 164
a1595a8e 165static void z80_addrbus_set_in(void)
0c5890bb 166{
9b6b4b31
L
167 /* /MREQ, /RD, /WR: Input, no pullup */
168 DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
169 Z80_O_MREQ = 0;
170 Z80_O_RD = 0;
171 Z80_O_WR = 0;
172
0c5890bb
L
173 P_ADL = 0;
174 DDR_ADL = 0;
175 P_ADH = 0;
176 DDR_ADH = 0;
6353e862 177 PIN_ADB = P_ADB & (MASK(ADB_WIDTH) << ADB_SHIFT);
0c5890bb
L
178 DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
179}
180
54678798 181
a1595a8e 182static void z80_addrbus_set_out(void)
0c5890bb 183{
9b6b4b31
L
184 /* /MREQ, /RD, /WR: Output and high */
185 Z80_O_MREQ = 1;
186 Z80_O_RD = 1;
187 Z80_O_WR = 1;
188 DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
189
0c5890bb
L
190 DDR_ADL = 0xff;
191 DDR_ADH = 0xff;
192 DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
193}
194
195
6035a17b 196static void z80_dbus_set_in(void)
0c5890bb
L
197{
198 DDR_DB = 0;
199 P_DB = 0;
200}
201
62f624d3 202
6035a17b 203static void z80_dbus_set_out(void)
0c5890bb
L
204{
205 DDR_DB = 0xff;
206}
207
61bd408c
L
208static void z80_reset_active(void)
209{
210 if (reset_polarity)
211 Z80_O_RST = 1;
212 else
213 Z80_O_RST = 0;
214}
215
216static void z80_reset_inactive(void)
217{
218 if (reset_polarity)
219 Z80_O_RST = 0;
220 else
221 Z80_O_RST = 1;
222}
62f624d3
L
223
224static void z80_reset_pulse(void)
225{
61bd408c 226 z80_reset_active();
62f624d3 227 _delay_us(10);
61bd408c 228 z80_reset_inactive();
62f624d3
L
229}
230
231
0c5890bb
L
232void z80_setup_bus(void)
233{
a1595a8e
L
234 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
235
61bd408c
L
236 /* /ZRESET: Input, no pullup */
237 DDR_RST &= ~_BV(RST);
a1595a8e 238 Z80_O_RST = 0;
0c5890bb 239
a1595a8e
L
240 /* /BUSREQ: Output and high */
241 Z80_O_BUSREQ = 1;
242 DDR_BUSREQ |= _BV(BUSREQ);
0c5890bb 243
a1595a8e
L
244 /* /BUSACK: Input, no pullup */
245 DDR_BUSACK &= ~_BV(BUSACK);
246 P_BUSACK &= ~_BV(BUSACK);
0c5890bb 247
a1595a8e
L
248 z80_addrbus_set_in();
249 z80_dbus_set_in();
0c5890bb 250
a1595a8e
L
251 if (getenv_yesno(PSTR(ENV_SINGLESTEP))) {
252 /* /RUN & /STEP: output, /WAIT: input */
72f58822 253
a1595a8e
L
254 PORT_SS = (PORT_SS & ~_BV(RUN)) | _BV(STEP);
255 DDR_SS = (DDR_SS & ~_BV(WAIT)) | _BV(RUN) | _BV(STEP);
256 }
257
61bd408c
L
258 reset_polarity = Z80_I_RST;
259 z80_reset_active();
260 DDR_RST |= _BV(RST);
261
a1595a8e
L
262 zstate = RESET;
263 }
ea6971b8 264
a1595a8e
L
265 /* Timer 5 */
266 PRR1 &= ~_BV(PRTIM5);
267 OCR5A = F_CPU / 1024 / 10 - 1; /* Timer: 10Hz interval (OC4A) */
268 TCCR5B = (0b01<<WGM52)|(0b101<<CS40); /* CTC Mode, Prescaler 1024 */
269 TIMSK5 = _BV(OCIE5A); /* Enable oca interrupt */
ea6971b8 270
0c5890bb
L
271}
272
f338df2a 273
62f624d3 274zstate_t z80_bus_state(void)
f338df2a
L
275{
276 return zstate;
277}
278
62f624d3
L
279
280static void z80_busreq_hpulse(void)
0c5890bb 281{
6035a17b 282 z80_dbus_set_in();
a1595a8e 283 z80_addrbus_set_in();
72f58822 284
a1595a8e 285#if 0
8a7decea 286 ATOMIC_BLOCK(ATOMIC_FORCEON) {
62f624d3
L
287 Z80_O_BUSREQ = 1;
288 Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
289 Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
f338df2a 290 }
a1595a8e
L
291#endif
292
4b0604a4 293#if 1
a1595a8e
L
294 ATOMIC_BLOCK(ATOMIC_FORCEON) {
295 Z80_O_BUSREQ = 1;
296
297 do {
298 if (Z80_I_BUSACK == 1) {
299 Z80_O_BUSREQ = 0;
300 break;
301 }
302 } while (1);
303 }
4b0604a4 304#endif
72f58822 305
62f624d3 306 if (zstate & ZST_ACQUIRED) {
ea6971b8
L
307 timer = BUS_TO;
308 while (Z80_I_BUSACK == 1 && timer)
f338df2a 309 ;
ea6971b8 310 if (Z80_I_BUSACK == 0)
a1595a8e 311 z80_addrbus_set_out();
f338df2a 312 }
f338df2a
L
313}
314
f338df2a
L
315
316/*
f338df2a 317
ea6971b8 318 + | | | | |
62f624d3 319 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
ea6971b8
L
320 + | | | | |
321 + | 0 | 1 | 2 | 3 |
322Event + | | | | |
62f624d3 323----------------+---------------+---------------+---------------+---------------+
ea6971b8
L
324 | | | | |
325Reset | 0 | 0 | 0 | 0 |
326 | | | | |
327 | | | | |
328Request | 1 | | 3 | |
329 | | | | |
330 | | | | |
331Release | | 0 | | 2 |
332 | | | | |
333 | | | | |
334Run | 2 | 3 | | |
335 | | | | |
336 | | | | |
337Restart | | | 2 | 3 |
338 | | | | |
339 | | | | |
340M_Cycle | | | | 3 |
341 | | | | |
342 | | | | |
62f624d3 343*/
f338df2a 344
62f624d3 345zstate_t z80_bus_cmd(bus_cmd_t cmd)
f338df2a 346{
62f624d3 347 switch (cmd) {
f338df2a 348
62f624d3 349 case Reset:
6035a17b 350 z80_dbus_set_in();
a1595a8e 351 z80_addrbus_set_in();
61bd408c 352 z80_reset_active();
62f624d3
L
353 Z80_O_BUSREQ = 1;
354 zstate = RESET;
f338df2a
L
355 break;
356
62f624d3
L
357 case Request:
358 switch (zstate) {
359 case RESET:
360 Z80_O_BUSREQ = 0;
61bd408c 361 z80_reset_inactive();
ea6971b8
L
362 timer = BUS_TO;
363 while (Z80_I_BUSACK == 1 && timer)
62f624d3 364 ;
ea6971b8 365 if (Z80_I_BUSACK == 0) {
a1595a8e 366 z80_addrbus_set_out();
ea6971b8
L
367 zstate = RESET_AQRD;
368 } else {
61bd408c 369 z80_reset_active();
ea6971b8
L
370 Z80_O_BUSREQ = 1;
371 }
62f624d3
L
372 break;
373
374 case RUNNING:
375 Z80_O_BUSREQ = 0;
ea6971b8
L
376 timer = BUS_TO;
377 while (Z80_I_BUSACK == 1 && timer)
62f624d3 378 ;
ea6971b8 379 if (Z80_I_BUSACK == 0) {
a1595a8e 380 z80_addrbus_set_out();
ea6971b8
L
381 zstate = RUNNING_AQRD;
382 } else {
383 Z80_O_BUSREQ = 1;
384 }
62f624d3
L
385 break;
386
387 default:
388 break;
389 }
f338df2a 390 break;
f338df2a 391
62f624d3
L
392 case Release:
393 switch (zstate) {
394 case RESET_AQRD:
6035a17b 395 z80_dbus_set_in();
a1595a8e 396 z80_addrbus_set_in();
61bd408c 397 z80_reset_active();
62f624d3
L
398 Z80_O_BUSREQ = 1;
399 zstate = RESET;
400 break;
401 case RUNNING_AQRD:
6035a17b 402 z80_dbus_set_in();
a1595a8e 403 z80_addrbus_set_in();
62f624d3
L
404 Z80_O_BUSREQ = 1;
405 zstate = RUNNING;
406 break;
407 default:
408 break;
409 }
410 break;
f338df2a 411
62f624d3
L
412 case Run:
413 switch (zstate) {
414 case RESET:
61bd408c 415 z80_reset_inactive();
62f624d3
L
416 zstate = RUNNING;
417 break;
418
419 case RESET_AQRD:
6035a17b 420 z80_dbus_set_in();
a1595a8e 421 z80_addrbus_set_in();
62f624d3 422 z80_reset_pulse();
a1595a8e 423 z80_addrbus_set_out();
62f624d3
L
424 zstate = RUNNING_AQRD;
425 break;
426 default:
427 break;
428 }
429 break;
f338df2a 430
62f624d3
L
431 case Restart:
432 switch (zstate) {
433 case RUNNING:
434 case RUNNING_AQRD:
435 z80_reset_pulse();
436 break;
437 default:
438 break;
439 }
440 break;
f338df2a 441
62f624d3
L
442 case M_Cycle:
443 switch (zstate) {
444 case RUNNING_AQRD:
ea6971b8 445 z80_busreq_hpulse(); /* TODO: */
62f624d3
L
446 break;
447 default:
448 break;
449 }
f338df2a 450 }
62f624d3 451 return zstate;
9b6b4b31
L
452}
453
62f624d3 454
9b6b4b31
L
455/*--------------------------------------------------------------------------*/
456
54678798 457static
9b6b4b31
L
458//inline __attribute__ ((always_inline))
459void z80_setaddress(uint32_t addr)
460{
a1595a8e
L
461 P_ADL = addr;
462 P_ADH = (addr & 0xff00) >> 8;
463 PIN_ADB = (((addr >> 16) << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT;
0c5890bb
L
464}
465
1e5609bf
L
466int32_t z80_memsize_detect(void)
467{
468 const uint8_t PATTERN_1 = 0x55;
469 const uint8_t PATTERN_2 = ~PATTERN_1;
470 uint32_t addr;
471
472 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED))
473 return -EBUSTO;
474
475 uint8_t ram_0 = z80_read(0);
476 uint8_t ram_1 = z80_read(1);
477
478 z80_write(0, ram_0 ^ 0xff);
479 z80_write(1, ram_1);
480 if ((z80_read(0) ^ ram_0) != 0xff) {
481 addr = 0;
482 } else {
483 z80_write(0, PATTERN_1);
484 for (addr=1; addr < CONFIG_SYS_RAMSIZE_MAX; addr <<= 1) {
485 uint8_t ram_i = z80_read(addr);
486 z80_write(addr, PATTERN_2);
487 if (z80_read(0) != PATTERN_1 || z80_read(addr) != PATTERN_2)
488 break;
489 z80_write(addr, ram_i);
490 }
491 }
492
493 z80_write(0, ram_0);
494 z80_bus_cmd(Release);
495
496 return addr;
497}
498
0c5890bb
L
499void z80_write(uint32_t addr, uint8_t data)
500{
501 z80_setaddress(addr);
502 Z80_O_MREQ = 0;
6035a17b 503 z80_dbus_set_out();
9b6b4b31
L
504 P_DB = data;
505 P_DB = data;
506 Z80_O_WR = 0;
0c5890bb
L
507 Z80_O_WR = 0;
508 Z80_O_WR = 1;
509 Z80_O_MREQ = 1;
510}
511
512uint8_t z80_read(uint32_t addr)
513{
514 uint8_t data;
515
516 z80_setaddress(addr);
517 Z80_O_MREQ = 0;
6035a17b 518 z80_dbus_set_in();
0c5890bb
L
519 Z80_O_RD = 0;
520 Z80_O_RD = 0;
9b6b4b31 521 Z80_O_RD = 0;
0c5890bb
L
522 data = PIN_DB;
523 Z80_O_RD = 1;
524 Z80_O_MREQ = 1;
525
526 return data;
527}
528
529
530void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
531{
6035a17b 532 z80_dbus_set_out();
0c5890bb 533 Z80_O_MREQ = 0;
ea6971b8 534 P_DB = data;
0c5890bb
L
535 while(length--) {
536 z80_setaddress(addr++);
ea6971b8
L
537 Z80_O_WR = 0;
538 Z80_O_WR = 0;
539 Z80_O_WR = 1;
540 }
541 Z80_O_MREQ = 1;
542}
543
544void z80_write_block_P(const FLASH uint8_t *src, uint32_t dest, uint32_t length)
545{
546 uint8_t data;
547
548 z80_dbus_set_out();
549 Z80_O_MREQ = 0;
550 while(length--) {
551 z80_setaddress(dest++);
552 data = *src++;
0c5890bb 553 P_DB = data;
9b6b4b31
L
554 P_DB = data;
555 Z80_O_WR = 0;
0c5890bb
L
556 Z80_O_WR = 0;
557 Z80_O_WR = 1;
558 }
559 Z80_O_MREQ = 1;
560}
561
ea6971b8 562void z80_write_block(const uint8_t *src, uint32_t dest, uint32_t length)
0c5890bb
L
563{
564 uint8_t data;
54678798 565
6035a17b 566 z80_dbus_set_out();
0c5890bb
L
567 Z80_O_MREQ = 0;
568 while(length--) {
569 z80_setaddress(dest++);
570 data = *src++;
571 P_DB = data;
9b6b4b31
L
572 P_DB = data;
573 Z80_O_WR = 0;
0c5890bb
L
574 Z80_O_WR = 0;
575 Z80_O_WR = 1;
576 }
577 Z80_O_MREQ = 1;
578}
579
ea6971b8
L
580void z80_read_block (uint8_t *dest, uint32_t src, size_t length)
581{
582 uint8_t data;
583
584 Z80_O_MREQ = 0;
585 z80_dbus_set_in();
586 while(length--) {
587 z80_setaddress(src++);
588 Z80_O_RD = 0;
589 Z80_O_RD = 0;
590 Z80_O_RD = 0;
591 data = PIN_DB;
592 Z80_O_RD = 1;
593 *dest++ = data;
594 }
595 Z80_O_MREQ = 1;
596}
597
598
0c5890bb
L
599/*
600 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
601 017A' rx.in_idx: ds 1 ;
602 017B' rx.out_idx: ds 1 ;
603 017C' rx.buf: ds rx.buf_len ;
604 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
54678798 605
0c5890bb
L
606 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
607 018D' tx.in_idx: ds 1 ;
608 018E' tx.out_idx: ds 1 ;
609 018F' tx.buf: ds tx.buf_len ;
610 019E' tx.buf_end equ $-1 ; last byte
611*/
612
613
614typedef struct __attribute__((packed)) {
615 uint8_t mask;
616 uint8_t in_idx;
617 uint8_t out_idx;
618 uint8_t buf[];
619} zfifo_t;
620
621
622
623#define FIFO_BUFSIZE_MASK -3
624#define FIFO_INDEX_IN -2
625#define FIFO_INDEX_OUT -1
626
627
628static struct {
629 uint32_t base;
630 uint8_t idx_out,
631 idx_in,
632 mask;
633 } fifo_dsc[NUM_FIFOS];
54678798 634
0c5890bb 635
8a7decea 636void z80_memfifo_init(const fifo_t f, uint32_t addr)
0c5890bb 637{
8a7decea 638 fifo_dsc[f].base = addr;
0c5890bb 639
0c5890bb 640
bbd45c46 641 if (addr != 0) {
8a7decea
L
642 z80_bus_cmd(Request);
643 fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK);
644 fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN);
645 fifo_dsc[f].idx_out = z80_read(addr + FIFO_INDEX_OUT);
646 z80_bus_cmd(Release);
910e7206
L
647
648 if (fifo_dsc[f].idx_in != 0 || fifo_dsc[f].idx_out != 0) {
649 DBG_P(1, "## z80_memfifo_init: %i, %lx, in: %.2x, out: %.2x, mask: %.2x\n",
650 f, addr, fifo_dsc[f].idx_in, fifo_dsc[f].idx_out, fifo_dsc[f].mask);
651 }
8a7decea 652 }
0c5890bb
L
653}
654
655
656int z80_memfifo_is_empty(const fifo_t f)
657{
658 int rc = 1;
659
89adce76 660 if (fifo_dsc[f].base != 0) {
0c5890bb
L
661
662 uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
663 uint8_t idx;
664
62f624d3 665 z80_bus_cmd(Request);
0c5890bb 666 idx = z80_read(adr);
62f624d3 667 z80_bus_cmd(Release);
0c5890bb
L
668 rc = idx == fifo_dsc[f].idx_out;
669 }
670
671 return rc;
672}
673
674int z80_memfifo_is_full(const fifo_t f)
675{
ce47d431 676 int rc = 0;
54678798 677
0c5890bb 678 if (fifo_dsc[f].base != 0) {
62f624d3 679 z80_bus_cmd(Request);
0c5890bb
L
680 rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
681 == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
62f624d3 682 z80_bus_cmd(Release);
0c5890bb
L
683 }
684 return rc;
685}
686
89adce76
L
687
688uint8_t z80_memfifo_getc_wait(const fifo_t f)
0c5890bb
L
689{
690 uint8_t rc, idx;
54678798 691
0c5890bb
L
692 while (z80_memfifo_is_empty(f))
693 ;
694
62f624d3 695 z80_bus_cmd(Request);
0c5890bb
L
696 idx = fifo_dsc[f].idx_out;
697 rc = z80_read(fifo_dsc[f].base+idx);
698 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
699 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
62f624d3 700 z80_bus_cmd(Release);
54678798 701
0c5890bb
L
702 return rc;
703}
704
89adce76
L
705int z80_memfifo_getc(const fifo_t f)
706{
707 int rc = -1;
708
709 if (fifo_dsc[f].base != 0) {
710 uint8_t idx = fifo_dsc[f].idx_out;
711 z80_bus_cmd(Request);
712 if (idx != z80_read(fifo_dsc[f].base + FIFO_INDEX_IN)) {
713 rc = z80_read(fifo_dsc[f].base+idx);
714 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
715 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
716 }
717 z80_bus_cmd(Release);
718 }
719
720 return rc;
721}
722
0c5890bb
L
723
724void z80_memfifo_putc(fifo_t f, uint8_t val)
725{
726 int idx;
54678798 727
0c5890bb
L
728 while (z80_memfifo_is_full(f))
729 ;
730
62f624d3 731 z80_bus_cmd(Request);
0c5890bb
L
732 idx = fifo_dsc[f].idx_in;
733 z80_write(fifo_dsc[f].base+idx, val);
734 fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
735 z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
62f624d3 736 z80_bus_cmd(Release);
0c5890bb 737}