]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/z80-if.c
User Timer0 as Z180 Clock
[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
56#include <avr/io.h>
57#include <util/delay.h>
f338df2a 58#include <util/atomic.h>
0c5890bb
L
59#include <stdio.h>
60#include "debug.h"
61#include "z80-if.h"
62
63
64/* Number of array elements */
65#define NELEMS(x) (sizeof x/sizeof *x)
66
67
68#define CONCAT(x,y) x ## y
69#define EVALUATOR(x,y) CONCAT(x,y)
70
71#define GPIO_(X) CONCAT(GPIO, X)
72
73struct bits {
74 uint8_t b0:1;
75 uint8_t b1:1;
76 uint8_t b2:1;
77 uint8_t b3:1;
78 uint8_t b4:1;
79 uint8_t b5:1;
80 uint8_t b6:1;
81 uint8_t b7:1;
82} __attribute__((__packed__));
83
84#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
85
86
54678798
L
87#define P_ZCLK PORTB
88#define ZCLK 7
89#define DDR_ZCLK DDRB
0c5890bb
L
90#define P_MREQ PORTD
91#define MREQ 4
92#define DDR_MREQ DDRD
93#define P_RD PORTD
94#define RD 3
95#define P_WR PORTD
96#define WR 2
97#define P_BUSREQ PORTD
98#define BUSREQ 7
99#define DDR_BUSREQ DDRD
100#define P_BUSACK PORTD
9b6b4b31 101#define PIN_BUSACK PIND
0c5890bb
L
102#define BUSACK 6
103#define DDR_BUSACK DDRD
104//#define P_HALT PORTA
105//#define HALT 12
106#define P_IOCS1 PORTE
107#define IOCS1 5
108#define DDR_IOCS1 DDRE
109//#define P_NMI PORTB
110//#define NMI 7
111#define P_RST PORTD
112#define DDR_RST DDRD
113#define RST 5
114
115
116#define P_DB PORTF
117#define PIN_DB PINF
118#define DDR_DB DDRF
119
120#define P_ADL PORTA
121#define P_ADH PORTC
122#define P_ADB PORTE
123#define PIN_ADB PINE
9b6b4b31
L
124#define DDR_ADL DDRA
125#define DDR_ADH DDRC
0c5890bb
L
126#define DDR_ADB DDRE
127
128#define ADB_WIDTH 3
129#define ADB_SHIFT 2
130//#define ADB_PORT PORTE
131
132
54678798 133#define Z80_O_ZCLK SBIT(P_ZCLK, 7)
0c5890bb
L
134#define Z80_O_MREQ SBIT(P_MREQ, 4)
135#define Z80_O_RD SBIT(P_RD, 3)
136#define Z80_O_WR SBIT(P_WR, 2)
137#define Z80_O_BUSREQ SBIT(P_BUSREQ, 7)
138//#define Z80_O_NMI SBIT(P_NMI, )
139#define Z80_O_RST SBIT(P_RST, 5)
9b6b4b31 140#define Z80_I_BUSACK SBIT(PIN_BUSACK, 6)
0c5890bb
L
141//#define Z80_I_HALT SBIT(P_HALT, )
142
9b6b4b31 143
0c5890bb
L
144#define MASK(n) ((1<<(n))-1)
145#define SMASK(w,s) (MASK(w) << (s))
146
147
148
eded7ec4
L
149typedef union {
150 uint32_t l;
151 uint16_t w[2];
152 uint8_t b[4];
153} addr_t;
f338df2a
L
154
155
156static zstate_t zstate;
eded7ec4 157
0c5890bb
L
158/*--------------------------------------------------------------------------*/
159
160
9b6b4b31 161static void z80_setup_addrbus_tristate(void)
0c5890bb 162{
9b6b4b31
L
163 /* /MREQ, /RD, /WR: Input, no pullup */
164 DDR_MREQ &= ~(_BV(MREQ) | _BV(RD) | _BV(WR));
165 Z80_O_MREQ = 0;
166 Z80_O_RD = 0;
167 Z80_O_WR = 0;
168
0c5890bb
L
169 P_ADL = 0;
170 DDR_ADL = 0;
171 P_ADH = 0;
172 DDR_ADH = 0;
9b6b4b31 173 PIN_ADB = P_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
0c5890bb
L
174 DDR_ADB = DDR_ADB & ~(MASK(ADB_WIDTH) << ADB_SHIFT);
175}
176
54678798 177
9b6b4b31 178static void z80_setup_addrbus_active(void)
0c5890bb 179{
9b6b4b31
L
180 /* /MREQ, /RD, /WR: Output and high */
181 Z80_O_MREQ = 1;
182 Z80_O_RD = 1;
183 Z80_O_WR = 1;
184 DDR_MREQ |= _BV(MREQ) | _BV(RD) | _BV(WR);
185
0c5890bb
L
186 DDR_ADL = 0xff;
187 DDR_ADH = 0xff;
188 DDR_ADB = DDR_ADB | (MASK(ADB_WIDTH) << ADB_SHIFT);
189}
190
191
0c5890bb
L
192static void z80_setup_dbus_in(void)
193{
194 DDR_DB = 0;
195 P_DB = 0;
196}
197
62f624d3 198
0c5890bb
L
199static void z80_setup_dbus_out(void)
200{
201 DDR_DB = 0xff;
202}
203
62f624d3
L
204
205static void z80_reset_pulse(void)
206{
207 Z80_O_RST = 0;
208 _delay_us(10);
209 Z80_O_RST = 1;
210}
211
54678798
L
212static
213void z80_setup_clock(void)
214{
215 /* ZCLK: Output and low */
216 DDR_ZCLK |= _BV(ZCLK);
217 Z80_O_ZCLK = 0;
218
219 /* Timer0: CTC: Toggle OC0A on compare match */
220 PRR0 &= ~_BV(PRTIM0);
221 TCCR0A = _BV(COM0A0) | _BV(WGM01);
222 OCR0A = 0;
223 TCCR0B = (0x01 << CS00);
224}
62f624d3 225
0c5890bb
L
226void z80_setup_bus(void)
227{
54678798
L
228 z80_setup_clock();
229
9b6b4b31 230 /* /ZRESET: Output and low */
0c5890bb
L
231 Z80_O_RST = 0;
232 DDR_RST |= _BV(RST);
233
9b6b4b31 234 /* /BUSREQ: Output and high */
0c5890bb
L
235 Z80_O_BUSREQ = 1;
236 DDR_BUSREQ |= _BV(BUSREQ);
237
9b6b4b31 238 /* /BUSACK: Input, no pullup */
0c5890bb
L
239 DDR_BUSACK &= ~_BV(BUSACK);
240 P_BUSACK &= ~_BV(BUSACK);
241
9b6b4b31 242 /* /IOCS1: Input, no pullup */
0c5890bb
L
243 DDR_IOCS1 &= ~_BV(IOCS1);
244 P_IOCS1 &= ~_BV(IOCS1);
245
9b6b4b31 246 z80_setup_addrbus_tristate();
0c5890bb 247 z80_setup_dbus_in();
72f58822 248
f338df2a 249 zstate = RESET;
0c5890bb
L
250}
251
f338df2a 252
62f624d3 253zstate_t z80_bus_state(void)
f338df2a
L
254{
255 return zstate;
256}
257
62f624d3
L
258
259static void z80_busreq_hpulse(void)
0c5890bb
L
260{
261 z80_setup_dbus_in();
9b6b4b31 262 z80_setup_addrbus_tristate();
72f58822 263
62f624d3
L
264 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
265 Z80_O_BUSREQ = 1;
266 Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
267 Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
f338df2a 268 }
72f58822 269
62f624d3 270 if (zstate & ZST_ACQUIRED) {
f338df2a
L
271 while(Z80_I_BUSACK == 1)
272 ;
273 z80_setup_addrbus_active();
f338df2a 274 }
f338df2a
L
275}
276
f338df2a
L
277
278/*
f338df2a 279
62f624d3
L
280 + | | | | |
281 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
282 + | | | | |
283 + | 0 | 1 | 2 | 3 |
284Event + | | | | |
285----------------+---------------+---------------+---------------+---------------+
286 | | | | |
287Reset | 0 | 0 | 0 | 0 |
288 | | | | |
289 | | | | |
290Request | 1 | | 3 | |
291 | | | | |
292 | | | | |
293Release | | 0 | | 2 |
294 | | | | |
295 | | | | |
296Run | 2 | 3 | | |
297 | | | | |
298 | | | | |
299Restart | | | 2 | 3 |
300 | | | | |
301 | | | | |
302M_Cycle | | | | 3 |
303 | | | | |
304 | | | | |
305*/
f338df2a 306
62f624d3 307zstate_t z80_bus_cmd(bus_cmd_t cmd)
f338df2a 308{
62f624d3 309 switch (cmd) {
f338df2a 310
62f624d3 311 case Reset:
f338df2a
L
312 z80_setup_dbus_in();
313 z80_setup_addrbus_tristate();
314 Z80_O_RST = 0;
62f624d3
L
315 Z80_O_BUSREQ = 1;
316 zstate = RESET;
f338df2a
L
317 break;
318
62f624d3
L
319 case Request:
320 switch (zstate) {
321 case RESET:
322 Z80_O_BUSREQ = 0;
323 Z80_O_RST = 1;
324 while(Z80_I_BUSACK == 1)
325 ;
326 z80_setup_addrbus_active();
327 zstate = RESET_AQRD;
328 break;
329
330 case RUNNING:
331 Z80_O_BUSREQ = 0;
332 while(Z80_I_BUSACK == 1)
333 ;
334 z80_setup_addrbus_active();
335 zstate = RUNNING_AQRD;
336 break;
337
338 default:
339 break;
340 }
f338df2a 341 break;
f338df2a 342
62f624d3
L
343 case Release:
344 switch (zstate) {
345 case RESET_AQRD:
346 z80_setup_dbus_in();
347 z80_setup_addrbus_tristate();
348 Z80_O_RST = 0;
349 Z80_O_BUSREQ = 1;
350 zstate = RESET;
351 break;
352 case RUNNING_AQRD:
353 z80_setup_dbus_in();
354 z80_setup_addrbus_tristate();
355 Z80_O_BUSREQ = 1;
356 zstate = RUNNING;
357 break;
358 default:
359 break;
360 }
361 break;
f338df2a 362
62f624d3
L
363 case Run:
364 switch (zstate) {
365 case RESET:
366 Z80_O_RST = 1;
367 zstate = RUNNING;
368 break;
369
370 case RESET_AQRD:
371 z80_setup_dbus_in();
372 z80_setup_addrbus_tristate();
373 z80_reset_pulse();
374 z80_setup_addrbus_active();
375 zstate = RUNNING_AQRD;
376 break;
377 default:
378 break;
379 }
380 break;
f338df2a 381
62f624d3
L
382 case Restart:
383 switch (zstate) {
384 case RUNNING:
385 case RUNNING_AQRD:
386 z80_reset_pulse();
387 break;
388 default:
389 break;
390 }
391 break;
f338df2a 392
62f624d3
L
393 case M_Cycle:
394 switch (zstate) {
395 case RUNNING_AQRD:
396 z80_busreq_hpulse();
397 break;
398 default:
399 break;
400 }
f338df2a 401 }
62f624d3 402 return zstate;
9b6b4b31
L
403}
404
62f624d3 405
9b6b4b31
L
406/*--------------------------------------------------------------------------*/
407
54678798 408static
9b6b4b31
L
409//inline __attribute__ ((always_inline))
410void z80_setaddress(uint32_t addr)
411{
412 addr_t x; x.l = addr;
413
414 P_ADL = x.b[0];
415 P_ADH = x.b[1];
416 PIN_ADB = ((x.b[2] << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT ;
0c5890bb
L
417}
418
419void z80_write(uint32_t addr, uint8_t data)
420{
421 z80_setaddress(addr);
422 Z80_O_MREQ = 0;
0c5890bb 423 z80_setup_dbus_out();
9b6b4b31
L
424 P_DB = data;
425 P_DB = data;
426 Z80_O_WR = 0;
0c5890bb
L
427 Z80_O_WR = 0;
428 Z80_O_WR = 1;
429 Z80_O_MREQ = 1;
430}
431
432uint8_t z80_read(uint32_t addr)
433{
434 uint8_t data;
435
436 z80_setaddress(addr);
437 Z80_O_MREQ = 0;
438 z80_setup_dbus_in();
439 Z80_O_RD = 0;
440 Z80_O_RD = 0;
9b6b4b31 441 Z80_O_RD = 0;
0c5890bb
L
442 data = PIN_DB;
443 Z80_O_RD = 1;
444 Z80_O_MREQ = 1;
445
446 return data;
447}
448
449
450void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
451{
452 z80_setup_dbus_out();
453 Z80_O_MREQ = 0;
454 while(length--) {
455 z80_setaddress(addr++);
456 P_DB = data;
9b6b4b31
L
457 P_DB = data;
458 Z80_O_WR = 0;
0c5890bb
L
459 Z80_O_WR = 0;
460 Z80_O_WR = 1;
461 }
462 Z80_O_MREQ = 1;
463}
464
9b6b4b31 465void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
0c5890bb
L
466{
467 uint8_t data;
54678798 468
0c5890bb
L
469 z80_setup_dbus_out();
470 Z80_O_MREQ = 0;
471 while(length--) {
472 z80_setaddress(dest++);
473 data = *src++;
474 P_DB = data;
9b6b4b31
L
475 P_DB = data;
476 Z80_O_WR = 0;
0c5890bb
L
477 Z80_O_WR = 0;
478 Z80_O_WR = 1;
479 }
480 Z80_O_MREQ = 1;
481}
482
483/*
484 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
485 017A' rx.in_idx: ds 1 ;
486 017B' rx.out_idx: ds 1 ;
487 017C' rx.buf: ds rx.buf_len ;
488 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
54678798 489
0c5890bb
L
490 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
491 018D' tx.in_idx: ds 1 ;
492 018E' tx.out_idx: ds 1 ;
493 018F' tx.buf: ds tx.buf_len ;
494 019E' tx.buf_end equ $-1 ; last byte
495*/
496
497
498typedef struct __attribute__((packed)) {
499 uint8_t mask;
500 uint8_t in_idx;
501 uint8_t out_idx;
502 uint8_t buf[];
503} zfifo_t;
504
505
506
507#define FIFO_BUFSIZE_MASK -3
508#define FIFO_INDEX_IN -2
509#define FIFO_INDEX_OUT -1
510
511
512static struct {
513 uint32_t base;
514 uint8_t idx_out,
515 idx_in,
516 mask;
517 } fifo_dsc[NUM_FIFOS];
54678798 518
0c5890bb
L
519
520void z80_memfifo_init(const fifo_t f, uint32_t adr)
521{
522
523DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
524
525 fifo_dsc[f].base = adr;
526
62f624d3 527 z80_bus_cmd(Request);
0c5890bb
L
528
529 fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
530 fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
531 fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
532
62f624d3 533 z80_bus_cmd(Release);
0c5890bb
L
534}
535
536
537int z80_memfifo_is_empty(const fifo_t f)
538{
539 int rc = 1;
540
541 if (fifo_dsc[f].base != 0) {
542
543 uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
544 uint8_t idx;
545
62f624d3 546 z80_bus_cmd(Request);
0c5890bb 547 idx = z80_read(adr);
62f624d3 548 z80_bus_cmd(Release);
0c5890bb
L
549 rc = idx == fifo_dsc[f].idx_out;
550 }
551
552 return rc;
553}
554
555int z80_memfifo_is_full(const fifo_t f)
556{
557 int rc = 1;
54678798 558
0c5890bb 559 if (fifo_dsc[f].base != 0) {
62f624d3 560 z80_bus_cmd(Request);
0c5890bb
L
561 rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
562 == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
62f624d3 563 z80_bus_cmd(Release);
0c5890bb
L
564 }
565 return rc;
566}
567
568uint8_t z80_memfifo_getc(const fifo_t f)
569{
570 uint8_t rc, idx;
54678798 571
0c5890bb
L
572 while (z80_memfifo_is_empty(f))
573 ;
574
62f624d3 575 z80_bus_cmd(Request);
0c5890bb
L
576 idx = fifo_dsc[f].idx_out;
577 rc = z80_read(fifo_dsc[f].base+idx);
578 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
579 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
62f624d3 580 z80_bus_cmd(Release);
54678798 581
0c5890bb
L
582 return rc;
583}
584
585
586void z80_memfifo_putc(fifo_t f, uint8_t val)
587{
588 int idx;
54678798 589
0c5890bb
L
590 while (z80_memfifo_is_full(f))
591 ;
592
62f624d3 593 z80_bus_cmd(Request);
0c5890bb
L
594 idx = fifo_dsc[f].idx_in;
595 z80_write(fifo_dsc[f].base+idx, val);
596 fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
597 z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
62f624d3 598 z80_bus_cmd(Release);
0c5890bb
L
599}
600
601/*--------------------------------------------------------------------------*/
72f58822
L
602/*
603 TODO: Rewrite msg_fifo routines for AVR
604*/
0c5890bb
L
605
606static struct {
607 uint32_t base;
608 //uint8_t idx_out, idx_in;
609 uint16_t count;
610 uint8_t buf[256];
611 } msg_fifo;
612
613/*--------------------------------------------------------------------------*/
614
615#if 0
616
617static void tim1_setup(void)
618{
619 RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
620 RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
621
622 TIM1_CR1 = 0;
623
624 TIM1_SMCR = 0
625 /* | TIM_SMCR_ETP */
626 /* | TIM_SMCR_ETF_CK_INT_N_2 */
627 | TIM_SMCR_TS_ETRF
628 | TIM_SMCR_SMS_OFF
629 ;
630
631 TIM1_DIER = TIM_DIER_TDE;
632
633
634 TIM1_CCMR1 = 0
635 | TIM_CCMR1_OC1M_FORCE_LOW
636 | TIM_CCMR1_CC1S_OUT;
637
638 TIM1_SMCR |= TIM_SMCR_SMS_TM;
639}
640
641#endif
642
643/*--------------------------------------------------------------------------*/
644
645void z80_setup_msg_fifo(void)
646{
647// gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
648// GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
649
650//...
651
652// msg_fifo.count = NELEMS(msg_fifo.buf);
653 msg_fifo.count = 0;
654 msg_fifo.base = 0;
655
656}
657
658
659void z80_init_msg_fifo(uint32_t addr)
660{
661
662DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
663
62f624d3 664 z80_bus_cmd(Request);
0c5890bb 665 z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
62f624d3 666 z80_bus_cmd(Release);
0c5890bb
L
667 msg_fifo.base = addr;
668}
669
670
671int z80_msg_fifo_getc(void)
672{
673 int c = -1;
54678798 674
9b6b4b31 675#if 0
0c5890bb
L
676 if (msg_fifo.count != (NELEMS(msg_fifo.buf) /*- DMA1_CNDTR4 */ )) {
677 c = msg_fifo.buf[msg_fifo.count];
678 if (++msg_fifo.count == NELEMS(msg_fifo.buf))
679 msg_fifo.count = 0;
680
681 if (msg_fifo.base != 0) {
62f624d3 682 z80_bus_cmd(Request);
0c5890bb 683 z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
62f624d3 684 z80_bus_cmd(Release);
0c5890bb
L
685 }
686 }
9b6b4b31 687#endif
0c5890bb
L
688
689 return c;
690}