]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/z80-if.c
Enable pullups on all gpio pins. cleanup
[z180-stamp.git] / avr / z80-if.c
CommitLineData
0c5890bb
L
1/**
2 *
3 * Pin assignments
4 *
72f58822 5 * | Z180-Sig | AVR-Port | Dir | Special Function |
0c5890bb
L
6 * +------------+---------------+-------+-----------------------+
7 * | A0 | PA 0 | O | |
8 * | A1 | PA 1 | O | |
9 * | A2 | PA 2 | O | |
10 * | A3 | PA 3 | O | |
11 * | A4 | PA 4 | O | |
12 * | A5 | PA 5 | O | |
13 * | A6 | PA 6 | O | |
14 * | A7 | PA 7 | O | |
15 * | A8 | PC 0 | O | |
16 * | A9 | PC 1 | O | |
17 * | A10 | PC 2 | O | |
18 * | A11 | PC 3 | O | |
19 * | A12 | PC 4 | O | |
20 * | A13 | PC 5 | O | |
21 * | A14 | PC 6 | O | |
22 * | A15 | PC 7 | O | |
23 * | A16 | PE 2 | O | |
24 * | A17 | PE 3 | O | |
25 * | A18 | PE 4 | O | |
26 * | D0 | PF 0 | I/O | |
27 * | D1 | PF 1 | I/O | |
28 * | D2 | PF 2 | I/O | |
29 * | D3 | PF 3 | I/O | |
30 * | D4 | PF 4 | I/O | |
31 * | D5 | PF 5 | I/O | |
32 * | D6 | PF 6 | I/O | |
33 * | D7 | PF 7 | I/O | |
34 * | RD | PD 3 | O | |
35 * | WR | PD 2 | O | |
36 * | MREQ | PD 4 | O | |
37 * | RST | PD 5 | O | |
38 * | BUSREQ | PD 7 | O | |
39 * | BUSACK | PD 6 | I | |
40 * | IOCS1 | PE 5 | I | |
41 * |* HALT | P | | |
42 * |* NMI | P | | |
43 * | | P | | |
44 * | | P | | af1 USART1_TX |
45 * | | P | | af1 USART1_RX |
46 * | | P |JTDI | remap SPI1_NSS' |
47 * | | P |JTDO | remap SPI1_SCK' |
48 * | | P |JTRST | remap SPI1_MISO' |
49 * | | P | | remap SPI1_MOSI' |
50 * | | P | | af1 OSC32 |
51 * | | P | | af1 OSC32 |
52
53
54 */
55
26331e24 56#include "common.h"
f338df2a 57#include <util/atomic.h>
0c5890bb
L
58#include "debug.h"
59#include "z80-if.h"
60
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
80//#define P_HALT PORTA
81//#define HALT 12
82#define P_IOCS1 PORTE
83#define IOCS1 5
84#define DDR_IOCS1 DDRE
85//#define P_NMI PORTB
86//#define NMI 7
87#define P_RST PORTD
88#define DDR_RST DDRD
89#define RST 5
90
91
92#define P_DB PORTF
93#define PIN_DB PINF
94#define DDR_DB DDRF
95
96#define P_ADL PORTA
97#define P_ADH PORTC
98#define P_ADB PORTE
99#define PIN_ADB PINE
9b6b4b31
L
100#define DDR_ADL DDRA
101#define DDR_ADH DDRC
0c5890bb
L
102#define DDR_ADB DDRE
103
104#define ADB_WIDTH 3
105#define ADB_SHIFT 2
106//#define ADB_PORT PORTE
107
108
41d36f28 109//#define Z80_O_ZCLK SBIT(P_ZCLK, 5)
0c5890bb
L
110#define Z80_O_MREQ SBIT(P_MREQ, 4)
111#define Z80_O_RD SBIT(P_RD, 3)
112#define Z80_O_WR SBIT(P_WR, 2)
113#define Z80_O_BUSREQ SBIT(P_BUSREQ, 7)
114//#define Z80_O_NMI SBIT(P_NMI, )
115#define Z80_O_RST SBIT(P_RST, 5)
9b6b4b31 116#define Z80_I_BUSACK SBIT(PIN_BUSACK, 6)
0c5890bb
L
117//#define Z80_I_HALT SBIT(P_HALT, )
118
9b6b4b31 119
0c5890bb
L
120#define MASK(n) ((1<<(n))-1)
121#define SMASK(w,s) (MASK(w) << (s))
122
0c5890bb 123
eded7ec4
L
124typedef union {
125 uint32_t l;
126 uint16_t w[2];
127 uint8_t b[4];
128} addr_t;
f338df2a
L
129
130
131static zstate_t zstate;
eded7ec4 132
0c5890bb
L
133/*--------------------------------------------------------------------------*/
134
6035a17b
L
135
136static void z80_addrbus_set_tristate(void)
0c5890bb 137{
9b6b4b31
L
138 /* /MREQ, /RD, /WR: Input, no pullup */
139 DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
140 Z80_O_MREQ = 0;
141 Z80_O_RD = 0;
142 Z80_O_WR = 0;
143
0c5890bb
L
144 P_ADL = 0;
145 DDR_ADL = 0;
146 P_ADH = 0;
147 DDR_ADH = 0;
9b6b4b31 148 PIN_ADB = P_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
0c5890bb
L
149 DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
150}
151
54678798 152
6035a17b 153static void z80_addrbus_set_active(void)
0c5890bb 154{
9b6b4b31
L
155 /* /MREQ, /RD, /WR: Output and high */
156 Z80_O_MREQ = 1;
157 Z80_O_RD = 1;
158 Z80_O_WR = 1;
159 DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
160
0c5890bb
L
161 DDR_ADL = 0xff;
162 DDR_ADH = 0xff;
163 DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
164}
165
166
6035a17b 167static void z80_dbus_set_in(void)
0c5890bb
L
168{
169 DDR_DB = 0;
170 P_DB = 0;
171}
172
62f624d3 173
6035a17b 174static void z80_dbus_set_out(void)
0c5890bb
L
175{
176 DDR_DB = 0xff;
177}
178
62f624d3
L
179
180static void z80_reset_pulse(void)
181{
182 Z80_O_RST = 0;
183 _delay_us(10);
184 Z80_O_RST = 1;
185}
186
187
0c5890bb
L
188void z80_setup_bus(void)
189{
9b6b4b31 190 /* /ZRESET: Output and low */
0c5890bb
L
191 Z80_O_RST = 0;
192 DDR_RST |= _BV(RST);
193
9b6b4b31 194 /* /BUSREQ: Output and high */
0c5890bb
L
195 Z80_O_BUSREQ = 1;
196 DDR_BUSREQ |= _BV(BUSREQ);
197
9b6b4b31 198 /* /BUSACK: Input, no pullup */
0c5890bb
L
199 DDR_BUSACK &= ~_BV(BUSACK);
200 P_BUSACK &= ~_BV(BUSACK);
201
9b6b4b31 202 /* /IOCS1: Input, no pullup */
0c5890bb
L
203 DDR_IOCS1 &= ~_BV(IOCS1);
204 P_IOCS1 &= ~_BV(IOCS1);
205
6035a17b
L
206 z80_addrbus_set_tristate();
207 z80_dbus_set_in();
72f58822 208
f338df2a 209 zstate = RESET;
0c5890bb
L
210}
211
f338df2a 212
62f624d3 213zstate_t z80_bus_state(void)
f338df2a
L
214{
215 return zstate;
216}
217
62f624d3
L
218
219static void z80_busreq_hpulse(void)
0c5890bb 220{
6035a17b
L
221 z80_dbus_set_in();
222 z80_addrbus_set_tristate();
72f58822 223
8a7decea 224 ATOMIC_BLOCK(ATOMIC_FORCEON) {
62f624d3
L
225 Z80_O_BUSREQ = 1;
226 Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
227 Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
f338df2a 228 }
72f58822 229
62f624d3 230 if (zstate & ZST_ACQUIRED) {
f338df2a
L
231 while(Z80_I_BUSACK == 1)
232 ;
6035a17b 233 z80_addrbus_set_active();
f338df2a 234 }
f338df2a
L
235}
236
f338df2a
L
237
238/*
f338df2a 239
62f624d3
L
240 + | | | | |
241 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
242 + | | | | |
243 + | 0 | 1 | 2 | 3 |
244Event + | | | | |
245----------------+---------------+---------------+---------------+---------------+
246 | | | | |
247Reset | 0 | 0 | 0 | 0 |
248 | | | | |
249 | | | | |
250Request | 1 | | 3 | |
251 | | | | |
252 | | | | |
253Release | | 0 | | 2 |
254 | | | | |
255 | | | | |
256Run | 2 | 3 | | |
257 | | | | |
258 | | | | |
259Restart | | | 2 | 3 |
260 | | | | |
261 | | | | |
262M_Cycle | | | | 3 |
263 | | | | |
264 | | | | |
265*/
f338df2a 266
62f624d3 267zstate_t z80_bus_cmd(bus_cmd_t cmd)
f338df2a 268{
62f624d3 269 switch (cmd) {
f338df2a 270
62f624d3 271 case Reset:
6035a17b
L
272 z80_dbus_set_in();
273 z80_addrbus_set_tristate();
f338df2a 274 Z80_O_RST = 0;
62f624d3
L
275 Z80_O_BUSREQ = 1;
276 zstate = RESET;
f338df2a
L
277 break;
278
62f624d3
L
279 case Request:
280 switch (zstate) {
281 case RESET:
282 Z80_O_BUSREQ = 0;
283 Z80_O_RST = 1;
284 while(Z80_I_BUSACK == 1)
285 ;
6035a17b 286 z80_addrbus_set_active();
62f624d3
L
287 zstate = RESET_AQRD;
288 break;
289
290 case RUNNING:
291 Z80_O_BUSREQ = 0;
292 while(Z80_I_BUSACK == 1)
293 ;
6035a17b 294 z80_addrbus_set_active();
62f624d3
L
295 zstate = RUNNING_AQRD;
296 break;
297
298 default:
299 break;
300 }
f338df2a 301 break;
f338df2a 302
62f624d3
L
303 case Release:
304 switch (zstate) {
305 case RESET_AQRD:
6035a17b
L
306 z80_dbus_set_in();
307 z80_addrbus_set_tristate();
62f624d3
L
308 Z80_O_RST = 0;
309 Z80_O_BUSREQ = 1;
310 zstate = RESET;
311 break;
312 case RUNNING_AQRD:
6035a17b
L
313 z80_dbus_set_in();
314 z80_addrbus_set_tristate();
62f624d3
L
315 Z80_O_BUSREQ = 1;
316 zstate = RUNNING;
317 break;
318 default:
319 break;
320 }
321 break;
f338df2a 322
62f624d3
L
323 case Run:
324 switch (zstate) {
325 case RESET:
326 Z80_O_RST = 1;
327 zstate = RUNNING;
328 break;
329
330 case RESET_AQRD:
6035a17b
L
331 z80_dbus_set_in();
332 z80_addrbus_set_tristate();
62f624d3 333 z80_reset_pulse();
6035a17b 334 z80_addrbus_set_active();
62f624d3
L
335 zstate = RUNNING_AQRD;
336 break;
337 default:
338 break;
339 }
340 break;
f338df2a 341
62f624d3
L
342 case Restart:
343 switch (zstate) {
344 case RUNNING:
345 case RUNNING_AQRD:
346 z80_reset_pulse();
347 break;
348 default:
349 break;
350 }
351 break;
f338df2a 352
62f624d3
L
353 case M_Cycle:
354 switch (zstate) {
355 case RUNNING_AQRD:
356 z80_busreq_hpulse();
357 break;
358 default:
359 break;
360 }
f338df2a 361 }
62f624d3 362 return zstate;
9b6b4b31
L
363}
364
62f624d3 365
9b6b4b31
L
366/*--------------------------------------------------------------------------*/
367
54678798 368static
9b6b4b31
L
369//inline __attribute__ ((always_inline))
370void z80_setaddress(uint32_t addr)
371{
372 addr_t x; x.l = addr;
373
374 P_ADL = x.b[0];
375 P_ADH = x.b[1];
376 PIN_ADB = ((x.b[2] << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT ;
0c5890bb
L
377}
378
379void z80_write(uint32_t addr, uint8_t data)
380{
381 z80_setaddress(addr);
382 Z80_O_MREQ = 0;
6035a17b 383 z80_dbus_set_out();
9b6b4b31
L
384 P_DB = data;
385 P_DB = data;
386 Z80_O_WR = 0;
0c5890bb
L
387 Z80_O_WR = 0;
388 Z80_O_WR = 1;
389 Z80_O_MREQ = 1;
390}
391
392uint8_t z80_read(uint32_t addr)
393{
394 uint8_t data;
395
396 z80_setaddress(addr);
397 Z80_O_MREQ = 0;
6035a17b 398 z80_dbus_set_in();
0c5890bb
L
399 Z80_O_RD = 0;
400 Z80_O_RD = 0;
9b6b4b31 401 Z80_O_RD = 0;
0c5890bb
L
402 data = PIN_DB;
403 Z80_O_RD = 1;
404 Z80_O_MREQ = 1;
405
406 return data;
407}
408
409
410void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
411{
6035a17b 412 z80_dbus_set_out();
0c5890bb
L
413 Z80_O_MREQ = 0;
414 while(length--) {
415 z80_setaddress(addr++);
416 P_DB = data;
9b6b4b31
L
417 P_DB = data;
418 Z80_O_WR = 0;
0c5890bb
L
419 Z80_O_WR = 0;
420 Z80_O_WR = 1;
421 }
422 Z80_O_MREQ = 1;
423}
424
9b6b4b31 425void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
0c5890bb
L
426{
427 uint8_t data;
54678798 428
6035a17b 429 z80_dbus_set_out();
0c5890bb
L
430 Z80_O_MREQ = 0;
431 while(length--) {
432 z80_setaddress(dest++);
433 data = *src++;
434 P_DB = data;
9b6b4b31
L
435 P_DB = data;
436 Z80_O_WR = 0;
0c5890bb
L
437 Z80_O_WR = 0;
438 Z80_O_WR = 1;
439 }
440 Z80_O_MREQ = 1;
441}
442
443/*
444 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
445 017A' rx.in_idx: ds 1 ;
446 017B' rx.out_idx: ds 1 ;
447 017C' rx.buf: ds rx.buf_len ;
448 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
54678798 449
0c5890bb
L
450 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
451 018D' tx.in_idx: ds 1 ;
452 018E' tx.out_idx: ds 1 ;
453 018F' tx.buf: ds tx.buf_len ;
454 019E' tx.buf_end equ $-1 ; last byte
455*/
456
457
458typedef struct __attribute__((packed)) {
459 uint8_t mask;
460 uint8_t in_idx;
461 uint8_t out_idx;
462 uint8_t buf[];
463} zfifo_t;
464
465
466
467#define FIFO_BUFSIZE_MASK -3
468#define FIFO_INDEX_IN -2
469#define FIFO_INDEX_OUT -1
470
471
472static struct {
473 uint32_t base;
474 uint8_t idx_out,
475 idx_in,
476 mask;
477 } fifo_dsc[NUM_FIFOS];
54678798 478
0c5890bb 479
8a7decea 480void z80_memfifo_init(const fifo_t f, uint32_t addr)
0c5890bb 481{
8a7decea 482 fifo_dsc[f].base = addr;
0c5890bb 483
8a7decea 484 if (addr != 0) {
0c5890bb 485
8a7decea 486DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, addr);
0c5890bb 487
8a7decea
L
488 z80_bus_cmd(Request);
489 fifo_dsc[f].mask = z80_read(addr + FIFO_BUFSIZE_MASK);
490 fifo_dsc[f].idx_in = z80_read(addr + FIFO_INDEX_IN);
491 fifo_dsc[f].idx_out = z80_read(addr + FIFO_INDEX_OUT);
492 z80_bus_cmd(Release);
493 }
0c5890bb
L
494}
495
496
497int z80_memfifo_is_empty(const fifo_t f)
498{
499 int rc = 1;
500
89adce76 501 if (fifo_dsc[f].base != 0) {
0c5890bb
L
502
503 uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
504 uint8_t idx;
505
62f624d3 506 z80_bus_cmd(Request);
0c5890bb 507 idx = z80_read(adr);
62f624d3 508 z80_bus_cmd(Release);
0c5890bb
L
509 rc = idx == fifo_dsc[f].idx_out;
510 }
511
512 return rc;
513}
514
515int z80_memfifo_is_full(const fifo_t f)
516{
517 int rc = 1;
54678798 518
0c5890bb 519 if (fifo_dsc[f].base != 0) {
62f624d3 520 z80_bus_cmd(Request);
0c5890bb
L
521 rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
522 == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
62f624d3 523 z80_bus_cmd(Release);
0c5890bb
L
524 }
525 return rc;
526}
527
89adce76
L
528
529uint8_t z80_memfifo_getc_wait(const fifo_t f)
0c5890bb
L
530{
531 uint8_t rc, idx;
54678798 532
0c5890bb
L
533 while (z80_memfifo_is_empty(f))
534 ;
535
62f624d3 536 z80_bus_cmd(Request);
0c5890bb
L
537 idx = fifo_dsc[f].idx_out;
538 rc = z80_read(fifo_dsc[f].base+idx);
539 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
540 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
62f624d3 541 z80_bus_cmd(Release);
54678798 542
0c5890bb
L
543 return rc;
544}
545
89adce76
L
546int z80_memfifo_getc(const fifo_t f)
547{
548 int rc = -1;
549
550 if (fifo_dsc[f].base != 0) {
551 uint8_t idx = fifo_dsc[f].idx_out;
552 z80_bus_cmd(Request);
553 if (idx != z80_read(fifo_dsc[f].base + FIFO_INDEX_IN)) {
554 rc = z80_read(fifo_dsc[f].base+idx);
555 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
556 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
557 }
558 z80_bus_cmd(Release);
559 }
560
561 return rc;
562}
563
0c5890bb
L
564
565void z80_memfifo_putc(fifo_t f, uint8_t val)
566{
567 int idx;
54678798 568
0c5890bb
L
569 while (z80_memfifo_is_full(f))
570 ;
571
62f624d3 572 z80_bus_cmd(Request);
0c5890bb
L
573 idx = fifo_dsc[f].idx_in;
574 z80_write(fifo_dsc[f].base+idx, val);
575 fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
576 z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
62f624d3 577 z80_bus_cmd(Release);
0c5890bb 578}