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