]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/z80-if.c
Detect ZRESET polarity
[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
0c5890bb 139
f338df2a 140static zstate_t zstate;
ea6971b8 141static volatile uint8_t timer; /* used for bus timeout */
61bd408c 142static bool reset_polarity;
ea6971b8
L
143
144/*---------------------------------------------------------*/
145/* 10Hz timer interrupt generated by OC4A */
146/*---------------------------------------------------------*/
147
a1595a8e 148ISR(TIMER5_COMPA_vect)
ea6971b8
L
149{
150
151 uint8_t i = timer;
152
153 if (i)
154 timer = i - 1;
155}
eded7ec4 156
0c5890bb
L
157/*--------------------------------------------------------------------------*/
158
6035a17b 159
a1595a8e 160static void z80_addrbus_set_in(void)
0c5890bb 161{
9b6b4b31
L
162 /* /MREQ, /RD, /WR: Input, no pullup */
163 DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
164 Z80_O_MREQ = 0;
165 Z80_O_RD = 0;
166 Z80_O_WR = 0;
167
0c5890bb
L
168 P_ADL = 0;
169 DDR_ADL = 0;
170 P_ADH = 0;
171 DDR_ADH = 0;
6353e862 172 PIN_ADB = P_ADB & (MASK(ADB_WIDTH) << ADB_SHIFT);
0c5890bb
L
173 DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
174}
175
54678798 176
a1595a8e 177static void z80_addrbus_set_out(void)
0c5890bb 178{
9b6b4b31
L
179 /* /MREQ, /RD, /WR: Output and high */
180 Z80_O_MREQ = 1;
181 Z80_O_RD = 1;
182 Z80_O_WR = 1;
183 DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
184
0c5890bb
L
185 DDR_ADL = 0xff;
186 DDR_ADH = 0xff;
187 DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
188}
189
190
6035a17b 191static void z80_dbus_set_in(void)
0c5890bb
L
192{
193 DDR_DB = 0;
194 P_DB = 0;
195}
196
62f624d3 197
6035a17b 198static void z80_dbus_set_out(void)
0c5890bb
L
199{
200 DDR_DB = 0xff;
201}
202
61bd408c
L
203static void z80_reset_active(void)
204{
205 if (reset_polarity)
206 Z80_O_RST = 1;
207 else
208 Z80_O_RST = 0;
209}
210
211static void z80_reset_inactive(void)
212{
213 if (reset_polarity)
214 Z80_O_RST = 0;
215 else
216 Z80_O_RST = 1;
217}
62f624d3
L
218
219static void z80_reset_pulse(void)
220{
61bd408c 221 z80_reset_active();
62f624d3 222 _delay_us(10);
61bd408c 223 z80_reset_inactive();
62f624d3
L
224}
225
226
0c5890bb
L
227void z80_setup_bus(void)
228{
a1595a8e
L
229 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
230
61bd408c
L
231 /* /ZRESET: Input, no pullup */
232 DDR_RST &= ~_BV(RST);
a1595a8e 233 Z80_O_RST = 0;
0c5890bb 234
a1595a8e
L
235 /* /BUSREQ: Output and high */
236 Z80_O_BUSREQ = 1;
237 DDR_BUSREQ |= _BV(BUSREQ);
0c5890bb 238
a1595a8e
L
239 /* /BUSACK: Input, no pullup */
240 DDR_BUSACK &= ~_BV(BUSACK);
241 P_BUSACK &= ~_BV(BUSACK);
0c5890bb 242
a1595a8e
L
243 z80_addrbus_set_in();
244 z80_dbus_set_in();
0c5890bb 245
a1595a8e
L
246 if (getenv_yesno(PSTR(ENV_SINGLESTEP))) {
247 /* /RUN & /STEP: output, /WAIT: input */
72f58822 248
a1595a8e
L
249 PORT_SS = (PORT_SS & ~_BV(RUN)) | _BV(STEP);
250 DDR_SS = (DDR_SS & ~_BV(WAIT)) | _BV(RUN) | _BV(STEP);
251 }
252
61bd408c
L
253 reset_polarity = Z80_I_RST;
254 z80_reset_active();
255 DDR_RST |= _BV(RST);
256
a1595a8e
L
257 zstate = RESET;
258 }
ea6971b8 259
a1595a8e
L
260 /* Timer 5 */
261 PRR1 &= ~_BV(PRTIM5);
262 OCR5A = F_CPU / 1024 / 10 - 1; /* Timer: 10Hz interval (OC4A) */
263 TCCR5B = (0b01<<WGM52)|(0b101<<CS40); /* CTC Mode, Prescaler 1024 */
264 TIMSK5 = _BV(OCIE5A); /* Enable oca interrupt */
ea6971b8 265
0c5890bb
L
266}
267
f338df2a 268
62f624d3 269zstate_t z80_bus_state(void)
f338df2a
L
270{
271 return zstate;
272}
273
62f624d3
L
274
275static void z80_busreq_hpulse(void)
0c5890bb 276{
6035a17b 277 z80_dbus_set_in();
a1595a8e 278 z80_addrbus_set_in();
72f58822 279
a1595a8e 280#if 0
8a7decea 281 ATOMIC_BLOCK(ATOMIC_FORCEON) {
62f624d3
L
282 Z80_O_BUSREQ = 1;
283 Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
284 Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
f338df2a 285 }
a1595a8e
L
286#endif
287
4b0604a4 288#if 1
a1595a8e
L
289 ATOMIC_BLOCK(ATOMIC_FORCEON) {
290 Z80_O_BUSREQ = 1;
291
292 do {
293 if (Z80_I_BUSACK == 1) {
294 Z80_O_BUSREQ = 0;
295 break;
296 }
297 } while (1);
298 }
4b0604a4 299#endif
72f58822 300
62f624d3 301 if (zstate & ZST_ACQUIRED) {
ea6971b8
L
302 timer = BUS_TO;
303 while (Z80_I_BUSACK == 1 && timer)
f338df2a 304 ;
ea6971b8 305 if (Z80_I_BUSACK == 0)
a1595a8e 306 z80_addrbus_set_out();
f338df2a 307 }
f338df2a
L
308}
309
f338df2a
L
310
311/*
f338df2a 312
ea6971b8 313 + | | | | |
62f624d3 314 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
ea6971b8
L
315 + | | | | |
316 + | 0 | 1 | 2 | 3 |
317Event + | | | | |
62f624d3 318----------------+---------------+---------------+---------------+---------------+
ea6971b8
L
319 | | | | |
320Reset | 0 | 0 | 0 | 0 |
321 | | | | |
322 | | | | |
323Request | 1 | | 3 | |
324 | | | | |
325 | | | | |
326Release | | 0 | | 2 |
327 | | | | |
328 | | | | |
329Run | 2 | 3 | | |
330 | | | | |
331 | | | | |
332Restart | | | 2 | 3 |
333 | | | | |
334 | | | | |
335M_Cycle | | | | 3 |
336 | | | | |
337 | | | | |
62f624d3 338*/
f338df2a 339
62f624d3 340zstate_t z80_bus_cmd(bus_cmd_t cmd)
f338df2a 341{
62f624d3 342 switch (cmd) {
f338df2a 343
62f624d3 344 case Reset:
6035a17b 345 z80_dbus_set_in();
a1595a8e 346 z80_addrbus_set_in();
61bd408c 347 z80_reset_active();
62f624d3
L
348 Z80_O_BUSREQ = 1;
349 zstate = RESET;
f338df2a
L
350 break;
351
62f624d3
L
352 case Request:
353 switch (zstate) {
354 case RESET:
355 Z80_O_BUSREQ = 0;
61bd408c 356 z80_reset_inactive();
ea6971b8
L
357 timer = BUS_TO;
358 while (Z80_I_BUSACK == 1 && timer)
62f624d3 359 ;
ea6971b8 360 if (Z80_I_BUSACK == 0) {
a1595a8e 361 z80_addrbus_set_out();
ea6971b8
L
362 zstate = RESET_AQRD;
363 } else {
61bd408c 364 z80_reset_active();
ea6971b8
L
365 Z80_O_BUSREQ = 1;
366 }
62f624d3
L
367 break;
368
369 case RUNNING:
370 Z80_O_BUSREQ = 0;
ea6971b8
L
371 timer = BUS_TO;
372 while (Z80_I_BUSACK == 1 && timer)
62f624d3 373 ;
ea6971b8 374 if (Z80_I_BUSACK == 0) {
a1595a8e 375 z80_addrbus_set_out();
ea6971b8
L
376 zstate = RUNNING_AQRD;
377 } else {
378 Z80_O_BUSREQ = 1;
379 }
62f624d3
L
380 break;
381
382 default:
383 break;
384 }
f338df2a 385 break;
f338df2a 386
62f624d3
L
387 case Release:
388 switch (zstate) {
389 case RESET_AQRD:
6035a17b 390 z80_dbus_set_in();
a1595a8e 391 z80_addrbus_set_in();
61bd408c 392 z80_reset_active();
62f624d3
L
393 Z80_O_BUSREQ = 1;
394 zstate = RESET;
395 break;
396 case RUNNING_AQRD:
6035a17b 397 z80_dbus_set_in();
a1595a8e 398 z80_addrbus_set_in();
62f624d3
L
399 Z80_O_BUSREQ = 1;
400 zstate = RUNNING;
401 break;
402 default:
403 break;
404 }
405 break;
f338df2a 406
62f624d3
L
407 case Run:
408 switch (zstate) {
409 case RESET:
61bd408c 410 z80_reset_inactive();
62f624d3
L
411 zstate = RUNNING;
412 break;
413
414 case RESET_AQRD:
6035a17b 415 z80_dbus_set_in();
a1595a8e 416 z80_addrbus_set_in();
62f624d3 417 z80_reset_pulse();
a1595a8e 418 z80_addrbus_set_out();
62f624d3
L
419 zstate = RUNNING_AQRD;
420 break;
421 default:
422 break;
423 }
424 break;
f338df2a 425
62f624d3
L
426 case Restart:
427 switch (zstate) {
428 case RUNNING:
429 case RUNNING_AQRD:
430 z80_reset_pulse();
431 break;
432 default:
433 break;
434 }
435 break;
f338df2a 436
62f624d3
L
437 case M_Cycle:
438 switch (zstate) {
439 case RUNNING_AQRD:
ea6971b8 440 z80_busreq_hpulse(); /* TODO: */
62f624d3
L
441 break;
442 default:
443 break;
444 }
f338df2a 445 }
62f624d3 446 return zstate;
9b6b4b31
L
447}
448
62f624d3 449
9b6b4b31
L
450/*--------------------------------------------------------------------------*/
451
54678798 452static
9b6b4b31
L
453//inline __attribute__ ((always_inline))
454void z80_setaddress(uint32_t addr)
455{
a1595a8e
L
456 P_ADL = addr;
457 P_ADH = (addr & 0xff00) >> 8;
458 PIN_ADB = (((addr >> 16) << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT;
0c5890bb
L
459}
460
461void z80_write(uint32_t addr, uint8_t data)
462{
463 z80_setaddress(addr);
464 Z80_O_MREQ = 0;
6035a17b 465 z80_dbus_set_out();
9b6b4b31
L
466 P_DB = data;
467 P_DB = data;
468 Z80_O_WR = 0;
0c5890bb
L
469 Z80_O_WR = 0;
470 Z80_O_WR = 1;
471 Z80_O_MREQ = 1;
472}
473
474uint8_t z80_read(uint32_t addr)
475{
476 uint8_t data;
477
478 z80_setaddress(addr);
479 Z80_O_MREQ = 0;
6035a17b 480 z80_dbus_set_in();
0c5890bb
L
481 Z80_O_RD = 0;
482 Z80_O_RD = 0;
9b6b4b31 483 Z80_O_RD = 0;
0c5890bb
L
484 data = PIN_DB;
485 Z80_O_RD = 1;
486 Z80_O_MREQ = 1;
487
488 return data;
489}
490
491
492void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
493{
6035a17b 494 z80_dbus_set_out();
0c5890bb 495 Z80_O_MREQ = 0;
ea6971b8 496 P_DB = data;
0c5890bb
L
497 while(length--) {
498 z80_setaddress(addr++);
ea6971b8
L
499 Z80_O_WR = 0;
500 Z80_O_WR = 0;
501 Z80_O_WR = 1;
502 }
503 Z80_O_MREQ = 1;
504}
505
506void z80_write_block_P(const FLASH uint8_t *src, uint32_t dest, uint32_t length)
507{
508 uint8_t data;
509
510 z80_dbus_set_out();
511 Z80_O_MREQ = 0;
512 while(length--) {
513 z80_setaddress(dest++);
514 data = *src++;
0c5890bb 515 P_DB = data;
9b6b4b31
L
516 P_DB = data;
517 Z80_O_WR = 0;
0c5890bb
L
518 Z80_O_WR = 0;
519 Z80_O_WR = 1;
520 }
521 Z80_O_MREQ = 1;
522}
523
ea6971b8 524void z80_write_block(const uint8_t *src, uint32_t dest, uint32_t length)
0c5890bb
L
525{
526 uint8_t data;
54678798 527
6035a17b 528 z80_dbus_set_out();
0c5890bb
L
529 Z80_O_MREQ = 0;
530 while(length--) {
531 z80_setaddress(dest++);
532 data = *src++;
533 P_DB = data;
9b6b4b31
L
534 P_DB = data;
535 Z80_O_WR = 0;
0c5890bb
L
536 Z80_O_WR = 0;
537 Z80_O_WR = 1;
538 }
539 Z80_O_MREQ = 1;
540}
541
ea6971b8
L
542void z80_read_block (uint8_t *dest, uint32_t src, size_t length)
543{
544 uint8_t data;
545
546 Z80_O_MREQ = 0;
547 z80_dbus_set_in();
548 while(length--) {
549 z80_setaddress(src++);
550 Z80_O_RD = 0;
551 Z80_O_RD = 0;
552 Z80_O_RD = 0;
553 data = PIN_DB;
554 Z80_O_RD = 1;
555 *dest++ = data;
556 }
557 Z80_O_MREQ = 1;
558}
559
560
0c5890bb
L
561/*
562 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
563 017A' rx.in_idx: ds 1 ;
564 017B' rx.out_idx: ds 1 ;
565 017C' rx.buf: ds rx.buf_len ;
566 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
54678798 567
0c5890bb
L
568 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
569 018D' tx.in_idx: ds 1 ;
570 018E' tx.out_idx: ds 1 ;
571 018F' tx.buf: ds tx.buf_len ;
572 019E' tx.buf_end equ $-1 ; last byte
573*/
574
575
576typedef struct __attribute__((packed)) {
577 uint8_t mask;
578 uint8_t in_idx;
579 uint8_t out_idx;
580 uint8_t buf[];
581} zfifo_t;
582
583
584
585#define FIFO_BUFSIZE_MASK -3
586#define FIFO_INDEX_IN -2
587#define FIFO_INDEX_OUT -1
588
589
590static struct {
591 uint32_t base;
592 uint8_t idx_out,
593 idx_in,
594 mask;
595 } fifo_dsc[NUM_FIFOS];
54678798 596
0c5890bb 597
8a7decea 598void z80_memfifo_init(const fifo_t f, uint32_t addr)
0c5890bb 599{
8a7decea 600 fifo_dsc[f].base = addr;
0c5890bb 601
0c5890bb 602
bbd45c46 603 if (addr != 0) {
8a7decea
L
604 z80_bus_cmd(Request);
605 fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK);
606 fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN);
607 fifo_dsc[f].idx_out = z80_read(addr + FIFO_INDEX_OUT);
608 z80_bus_cmd(Release);
910e7206
L
609
610 if (fifo_dsc[f].idx_in != 0 || fifo_dsc[f].idx_out != 0) {
611 DBG_P(1, "## z80_memfifo_init: %i, %lx, in: %.2x, out: %.2x, mask: %.2x\n",
612 f, addr, fifo_dsc[f].idx_in, fifo_dsc[f].idx_out, fifo_dsc[f].mask);
613 }
8a7decea 614 }
0c5890bb
L
615}
616
617
618int z80_memfifo_is_empty(const fifo_t f)
619{
620 int rc = 1;
621
89adce76 622 if (fifo_dsc[f].base != 0) {
0c5890bb
L
623
624 uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
625 uint8_t idx;
626
62f624d3 627 z80_bus_cmd(Request);
0c5890bb 628 idx = z80_read(adr);
62f624d3 629 z80_bus_cmd(Release);
0c5890bb
L
630 rc = idx == fifo_dsc[f].idx_out;
631 }
632
633 return rc;
634}
635
636int z80_memfifo_is_full(const fifo_t f)
637{
ce47d431 638 int rc = 0;
54678798 639
0c5890bb 640 if (fifo_dsc[f].base != 0) {
62f624d3 641 z80_bus_cmd(Request);
0c5890bb
L
642 rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
643 == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
62f624d3 644 z80_bus_cmd(Release);
0c5890bb
L
645 }
646 return rc;
647}
648
89adce76
L
649
650uint8_t z80_memfifo_getc_wait(const fifo_t f)
0c5890bb
L
651{
652 uint8_t rc, idx;
54678798 653
0c5890bb
L
654 while (z80_memfifo_is_empty(f))
655 ;
656
62f624d3 657 z80_bus_cmd(Request);
0c5890bb
L
658 idx = fifo_dsc[f].idx_out;
659 rc = z80_read(fifo_dsc[f].base+idx);
660 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
661 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
62f624d3 662 z80_bus_cmd(Release);
54678798 663
0c5890bb
L
664 return rc;
665}
666
89adce76
L
667int z80_memfifo_getc(const fifo_t f)
668{
669 int rc = -1;
670
671 if (fifo_dsc[f].base != 0) {
672 uint8_t idx = fifo_dsc[f].idx_out;
673 z80_bus_cmd(Request);
674 if (idx != z80_read(fifo_dsc[f].base + FIFO_INDEX_IN)) {
675 rc = z80_read(fifo_dsc[f].base+idx);
676 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
677 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
678 }
679 z80_bus_cmd(Release);
680 }
681
682 return rc;
683}
684
0c5890bb
L
685
686void z80_memfifo_putc(fifo_t f, uint8_t val)
687{
688 int idx;
54678798 689
0c5890bb
L
690 while (z80_memfifo_is_full(f))
691 ;
692
62f624d3 693 z80_bus_cmd(Request);
0c5890bb
L
694 idx = fifo_dsc[f].idx_in;
695 z80_write(fifo_dsc[f].base+idx, val);
696 fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
697 z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
62f624d3 698 z80_bus_cmd(Release);
0c5890bb 699}