]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/z80-if.c
User Timer1 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
9e689a83
L
219 /* Timer1: CTC: Toggle OC1C on compare match */
220 PRR0 &= ~_BV(PRTIM1);
221 OCR1A = 0;
222 OCR1C = 0;
223 TCCR1A = (0b01 << COM1C0) | (0b00 << WGM10);
224 TCCR1B = (0b01 << WGM12) | (0b001 << CS10);
54678798 225}
62f624d3 226
0c5890bb
L
227void z80_setup_bus(void)
228{
54678798
L
229 z80_setup_clock();
230
9b6b4b31 231 /* /ZRESET: Output and low */
0c5890bb
L
232 Z80_O_RST = 0;
233 DDR_RST |= _BV(RST);
234
9b6b4b31 235 /* /BUSREQ: Output and high */
0c5890bb
L
236 Z80_O_BUSREQ = 1;
237 DDR_BUSREQ |= _BV(BUSREQ);
238
9b6b4b31 239 /* /BUSACK: Input, no pullup */
0c5890bb
L
240 DDR_BUSACK &= ~_BV(BUSACK);
241 P_BUSACK &= ~_BV(BUSACK);
242
9b6b4b31 243 /* /IOCS1: Input, no pullup */
0c5890bb
L
244 DDR_IOCS1 &= ~_BV(IOCS1);
245 P_IOCS1 &= ~_BV(IOCS1);
246
9b6b4b31 247 z80_setup_addrbus_tristate();
0c5890bb 248 z80_setup_dbus_in();
72f58822 249
f338df2a 250 zstate = RESET;
0c5890bb
L
251}
252
f338df2a 253
62f624d3 254zstate_t z80_bus_state(void)
f338df2a
L
255{
256 return zstate;
257}
258
62f624d3
L
259
260static void z80_busreq_hpulse(void)
0c5890bb
L
261{
262 z80_setup_dbus_in();
9b6b4b31 263 z80_setup_addrbus_tristate();
72f58822 264
62f624d3
L
265 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
266 Z80_O_BUSREQ = 1;
267 Z80_O_BUSREQ = 1; /* 2 AVR clock cycles */
268 Z80_O_BUSREQ = 0; /* 2 AVR clock cycles */
f338df2a 269 }
72f58822 270
62f624d3 271 if (zstate & ZST_ACQUIRED) {
f338df2a
L
272 while(Z80_I_BUSACK == 1)
273 ;
274 z80_setup_addrbus_active();
f338df2a 275 }
f338df2a
L
276}
277
f338df2a
L
278
279/*
f338df2a 280
62f624d3
L
281 + | | | | |
282 + State | RESET | RESET_AQRD | RUNNING | RUNNING_AQRD |
283 + | | | | |
284 + | 0 | 1 | 2 | 3 |
285Event + | | | | |
286----------------+---------------+---------------+---------------+---------------+
287 | | | | |
288Reset | 0 | 0 | 0 | 0 |
289 | | | | |
290 | | | | |
291Request | 1 | | 3 | |
292 | | | | |
293 | | | | |
294Release | | 0 | | 2 |
295 | | | | |
296 | | | | |
297Run | 2 | 3 | | |
298 | | | | |
299 | | | | |
300Restart | | | 2 | 3 |
301 | | | | |
302 | | | | |
303M_Cycle | | | | 3 |
304 | | | | |
305 | | | | |
306*/
f338df2a 307
62f624d3 308zstate_t z80_bus_cmd(bus_cmd_t cmd)
f338df2a 309{
62f624d3 310 switch (cmd) {
f338df2a 311
62f624d3 312 case Reset:
f338df2a
L
313 z80_setup_dbus_in();
314 z80_setup_addrbus_tristate();
315 Z80_O_RST = 0;
62f624d3
L
316 Z80_O_BUSREQ = 1;
317 zstate = RESET;
f338df2a
L
318 break;
319
62f624d3
L
320 case Request:
321 switch (zstate) {
322 case RESET:
323 Z80_O_BUSREQ = 0;
324 Z80_O_RST = 1;
325 while(Z80_I_BUSACK == 1)
326 ;
327 z80_setup_addrbus_active();
328 zstate = RESET_AQRD;
329 break;
330
331 case RUNNING:
332 Z80_O_BUSREQ = 0;
333 while(Z80_I_BUSACK == 1)
334 ;
335 z80_setup_addrbus_active();
336 zstate = RUNNING_AQRD;
337 break;
338
339 default:
340 break;
341 }
f338df2a 342 break;
f338df2a 343
62f624d3
L
344 case Release:
345 switch (zstate) {
346 case RESET_AQRD:
347 z80_setup_dbus_in();
348 z80_setup_addrbus_tristate();
349 Z80_O_RST = 0;
350 Z80_O_BUSREQ = 1;
351 zstate = RESET;
352 break;
353 case RUNNING_AQRD:
354 z80_setup_dbus_in();
355 z80_setup_addrbus_tristate();
356 Z80_O_BUSREQ = 1;
357 zstate = RUNNING;
358 break;
359 default:
360 break;
361 }
362 break;
f338df2a 363
62f624d3
L
364 case Run:
365 switch (zstate) {
366 case RESET:
367 Z80_O_RST = 1;
368 zstate = RUNNING;
369 break;
370
371 case RESET_AQRD:
372 z80_setup_dbus_in();
373 z80_setup_addrbus_tristate();
374 z80_reset_pulse();
375 z80_setup_addrbus_active();
376 zstate = RUNNING_AQRD;
377 break;
378 default:
379 break;
380 }
381 break;
f338df2a 382
62f624d3
L
383 case Restart:
384 switch (zstate) {
385 case RUNNING:
386 case RUNNING_AQRD:
387 z80_reset_pulse();
388 break;
389 default:
390 break;
391 }
392 break;
f338df2a 393
62f624d3
L
394 case M_Cycle:
395 switch (zstate) {
396 case RUNNING_AQRD:
397 z80_busreq_hpulse();
398 break;
399 default:
400 break;
401 }
f338df2a 402 }
62f624d3 403 return zstate;
9b6b4b31
L
404}
405
62f624d3 406
9b6b4b31
L
407/*--------------------------------------------------------------------------*/
408
54678798 409static
9b6b4b31
L
410//inline __attribute__ ((always_inline))
411void z80_setaddress(uint32_t addr)
412{
413 addr_t x; x.l = addr;
414
415 P_ADL = x.b[0];
416 P_ADH = x.b[1];
417 PIN_ADB = ((x.b[2] << ADB_SHIFT) ^ P_ADB) & MASK(ADB_WIDTH) << ADB_SHIFT ;
0c5890bb
L
418}
419
420void z80_write(uint32_t addr, uint8_t data)
421{
422 z80_setaddress(addr);
423 Z80_O_MREQ = 0;
0c5890bb 424 z80_setup_dbus_out();
9b6b4b31
L
425 P_DB = data;
426 P_DB = data;
427 Z80_O_WR = 0;
0c5890bb
L
428 Z80_O_WR = 0;
429 Z80_O_WR = 1;
430 Z80_O_MREQ = 1;
431}
432
433uint8_t z80_read(uint32_t addr)
434{
435 uint8_t data;
436
437 z80_setaddress(addr);
438 Z80_O_MREQ = 0;
439 z80_setup_dbus_in();
440 Z80_O_RD = 0;
441 Z80_O_RD = 0;
9b6b4b31 442 Z80_O_RD = 0;
0c5890bb
L
443 data = PIN_DB;
444 Z80_O_RD = 1;
445 Z80_O_MREQ = 1;
446
447 return data;
448}
449
450
451void z80_memset(uint32_t addr, uint8_t data, uint32_t length)
452{
453 z80_setup_dbus_out();
454 Z80_O_MREQ = 0;
455 while(length--) {
456 z80_setaddress(addr++);
457 P_DB = data;
9b6b4b31
L
458 P_DB = data;
459 Z80_O_WR = 0;
0c5890bb
L
460 Z80_O_WR = 0;
461 Z80_O_WR = 1;
462 }
463 Z80_O_MREQ = 1;
464}
465
9b6b4b31 466void z80_write_block(const __flash uint8_t *src, uint32_t dest, uint32_t length)
0c5890bb
L
467{
468 uint8_t data;
54678798 469
0c5890bb
L
470 z80_setup_dbus_out();
471 Z80_O_MREQ = 0;
472 while(length--) {
473 z80_setaddress(dest++);
474 data = *src++;
475 P_DB = data;
9b6b4b31
L
476 P_DB = data;
477 Z80_O_WR = 0;
0c5890bb
L
478 Z80_O_WR = 0;
479 Z80_O_WR = 1;
480 }
481 Z80_O_MREQ = 1;
482}
483
484/*
485 0179' rx.bs_mask: ds 1 ; (buf_len - 1)
486 017A' rx.in_idx: ds 1 ;
487 017B' rx.out_idx: ds 1 ;
488 017C' rx.buf: ds rx.buf_len ;
489 018B' rx.buf_end equ $-1 ; last byte (start+len-1)
54678798 490
0c5890bb
L
491 018C' tx.bs_mask: ds 1 ; (buf_len - 1)
492 018D' tx.in_idx: ds 1 ;
493 018E' tx.out_idx: ds 1 ;
494 018F' tx.buf: ds tx.buf_len ;
495 019E' tx.buf_end equ $-1 ; last byte
496*/
497
498
499typedef struct __attribute__((packed)) {
500 uint8_t mask;
501 uint8_t in_idx;
502 uint8_t out_idx;
503 uint8_t buf[];
504} zfifo_t;
505
506
507
508#define FIFO_BUFSIZE_MASK -3
509#define FIFO_INDEX_IN -2
510#define FIFO_INDEX_OUT -1
511
512
513static struct {
514 uint32_t base;
515 uint8_t idx_out,
516 idx_in,
517 mask;
518 } fifo_dsc[NUM_FIFOS];
54678798 519
0c5890bb
L
520
521void z80_memfifo_init(const fifo_t f, uint32_t adr)
522{
523
524DBG_P(2, "z80_memfifo_init: %i, %lx\n", f, adr);
525
526 fifo_dsc[f].base = adr;
527
62f624d3 528 z80_bus_cmd(Request);
0c5890bb
L
529
530 fifo_dsc[f].mask = z80_read(adr + FIFO_BUFSIZE_MASK);
531 fifo_dsc[f].idx_in = z80_read(adr + FIFO_INDEX_IN);
532 fifo_dsc[f].idx_out = z80_read(adr + FIFO_INDEX_OUT);
533
62f624d3 534 z80_bus_cmd(Release);
0c5890bb
L
535}
536
537
538int z80_memfifo_is_empty(const fifo_t f)
539{
540 int rc = 1;
541
542 if (fifo_dsc[f].base != 0) {
543
544 uint32_t adr = fifo_dsc[f].base + FIFO_INDEX_IN;
545 uint8_t idx;
546
62f624d3 547 z80_bus_cmd(Request);
0c5890bb 548 idx = z80_read(adr);
62f624d3 549 z80_bus_cmd(Release);
0c5890bb
L
550 rc = idx == fifo_dsc[f].idx_out;
551 }
552
553 return rc;
554}
555
556int z80_memfifo_is_full(const fifo_t f)
557{
558 int rc = 1;
54678798 559
0c5890bb 560 if (fifo_dsc[f].base != 0) {
62f624d3 561 z80_bus_cmd(Request);
0c5890bb
L
562 rc = ((fifo_dsc[f].idx_in + 1) & fifo_dsc[f].mask)
563 == z80_read(fifo_dsc[f].base+FIFO_INDEX_OUT);
62f624d3 564 z80_bus_cmd(Release);
0c5890bb
L
565 }
566 return rc;
567}
568
569uint8_t z80_memfifo_getc(const fifo_t f)
570{
571 uint8_t rc, idx;
54678798 572
0c5890bb
L
573 while (z80_memfifo_is_empty(f))
574 ;
575
62f624d3 576 z80_bus_cmd(Request);
0c5890bb
L
577 idx = fifo_dsc[f].idx_out;
578 rc = z80_read(fifo_dsc[f].base+idx);
579 fifo_dsc[f].idx_out = ++idx & fifo_dsc[f].mask;
580 z80_write(fifo_dsc[f].base+FIFO_INDEX_OUT, fifo_dsc[f].idx_out);
62f624d3 581 z80_bus_cmd(Release);
54678798 582
0c5890bb
L
583 return rc;
584}
585
586
587void z80_memfifo_putc(fifo_t f, uint8_t val)
588{
589 int idx;
54678798 590
0c5890bb
L
591 while (z80_memfifo_is_full(f))
592 ;
593
62f624d3 594 z80_bus_cmd(Request);
0c5890bb
L
595 idx = fifo_dsc[f].idx_in;
596 z80_write(fifo_dsc[f].base+idx, val);
597 fifo_dsc[f].idx_in = ++idx & fifo_dsc[f].mask;
598 z80_write(fifo_dsc[f].base+FIFO_INDEX_IN, fifo_dsc[f].idx_in);
62f624d3 599 z80_bus_cmd(Release);
0c5890bb
L
600}
601
602/*--------------------------------------------------------------------------*/
72f58822
L
603/*
604 TODO: Rewrite msg_fifo routines for AVR
605*/
0c5890bb
L
606
607static struct {
608 uint32_t base;
609 //uint8_t idx_out, idx_in;
610 uint16_t count;
611 uint8_t buf[256];
612 } msg_fifo;
613
614/*--------------------------------------------------------------------------*/
615
616#if 0
617
618static void tim1_setup(void)
619{
620 RCC_APB2RSTR |= RCC_APB2RSTR_TIM1RST;
621 RCC_APB2RSTR &= ~RCC_APB2RSTR_TIM1RST;
622
623 TIM1_CR1 = 0;
624
625 TIM1_SMCR = 0
626 /* | TIM_SMCR_ETP */
627 /* | TIM_SMCR_ETF_CK_INT_N_2 */
628 | TIM_SMCR_TS_ETRF
629 | TIM_SMCR_SMS_OFF
630 ;
631
632 TIM1_DIER = TIM_DIER_TDE;
633
634
635 TIM1_CCMR1 = 0
636 | TIM_CCMR1_OC1M_FORCE_LOW
637 | TIM_CCMR1_CC1S_OUT;
638
639 TIM1_SMCR |= TIM_SMCR_SMS_TM;
640}
641
642#endif
643
644/*--------------------------------------------------------------------------*/
645
646void z80_setup_msg_fifo(void)
647{
648// gpio_set_mode(P_BUSACK, GPIO_MODE_INPUT,
649// GPIO_CNF_INPUT_FLOAT, GPIO_BUSACK | GPIO_IOCS1);
650
651//...
652
653// msg_fifo.count = NELEMS(msg_fifo.buf);
654 msg_fifo.count = 0;
655 msg_fifo.base = 0;
656
657}
658
659
660void z80_init_msg_fifo(uint32_t addr)
661{
662
663DBG_P(1, "z80_init_msg_fifo: %lx\n", addr);
664
62f624d3 665 z80_bus_cmd(Request);
0c5890bb 666 z80_write(addr+FIFO_INDEX_OUT, z80_read(addr+FIFO_INDEX_IN));
62f624d3 667 z80_bus_cmd(Release);
0c5890bb
L
668 msg_fifo.base = addr;
669}
670
671
672int z80_msg_fifo_getc(void)
673{
674 int c = -1;
54678798 675
9b6b4b31 676#if 0
0c5890bb
L
677 if (msg_fifo.count != (NELEMS(msg_fifo.buf) /*- DMA1_CNDTR4 */ )) {
678 c = msg_fifo.buf[msg_fifo.count];
679 if (++msg_fifo.count == NELEMS(msg_fifo.buf))
680 msg_fifo.count = 0;
681
682 if (msg_fifo.base != 0) {
62f624d3 683 z80_bus_cmd(Request);
0c5890bb 684 z80_write(msg_fifo.base+FIFO_INDEX_OUT, msg_fifo.count);
62f624d3 685 z80_bus_cmd(Release);
0c5890bb
L
686 }
687 }
9b6b4b31 688#endif
0c5890bb
L
689
690 return c;
691}