]> cloudbase.mooo.com Git - z180-stamp.git/blob - stm32/z180-stamp-stm32.c
888494d16a3e588db6b3d736a72a8f077ce072f0
[z180-stamp.git] / stm32 / z180-stamp-stm32.c
1 /*
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <stdio.h>
8
9 #include <libopencmsis/core_cm3.h>
10 #include <libopencm3/cm3/nvic.h>
11 #include <libopencm3/cm3/systick.h>
12 #include <libopencm3/stm32/rtc.h>
13 #include <libopencm3/stm32/rcc.h>
14 #include <libopencm3/stm32/gpio.h>
15 #include <libopencm3/stm32/timer.h>
16
17 #define ODR 0x0c
18 #define IDR 0x08
19
20
21 #include "debug.h"
22 #include "serial.h"
23 #include "z80-if.h"
24 #include "../z180/hdrom.h"
25
26 #define ESCCHAR ('^'-0x40)
27
28 #define S_10MS_TO (1<<0)
29
30 /*
31 * LED Connections
32 */
33
34 #define LED_PORT GPIOC
35 #define LED_BLUE_PIN GPIO8
36 #define BLUE 8
37 #define LED_GREEN_PIN GPIO9
38 #define GREEN 9
39
40
41 #define LED_BLUE_ON() BBIO_PERIPH(LED_PORT+ODR, BLUE) = 1
42 #define LED_BLUE_OFF() BBIO_PERIPH(LED_PORT+ODR, BLUE) = 0
43 #define LED_BLUE_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, BLUE) = !BBIO_PERIPH(LED_PORT+ODR, BLUE)
44
45 #define LED_GREEN_ON() BBIO_PERIPH(LED_PORT+ODR, GREEN) = 1
46 #define LED_GREEN_OFF() BBIO_PERIPH(LED_PORT+ODR, GREEN) = 0
47 #define LED_GREEN_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, GREEN) = !BBIO_PERIPH(LED_PORT+ODR, GREEN)
48
49
50 /*
51 * Button connections
52 */
53
54 //BBIO_PERIPH(GPIOA+IDR, 0);
55
56 #define KEY_PORT GPIOA_IDR
57 #define KEY0 GPIO0
58 //#define KEY1 GPIO1
59 //#define KEY2 GPIO2
60
61 #define REPEAT_MASK KEY0 // repeat: key0
62 #define REPEAT_START 100 // after 1s
63 #define REPEAT_NEXT 20 // every 200ms
64
65
66 typedef enum {
67 NOTHING, PULSE, BLINK1, BLINK2
68 } LED_MODE;
69
70 typedef struct {
71 uint8_t mode;
72 uint8_t ontime, offtime;
73 } led_stat_t;
74
75 volatile uint8_t led_timer[2];
76 led_stat_t led_stat[2];
77
78 volatile int timeout_1s;
79 volatile uint32_t Stat;
80
81
82 /*--------------------------------------------------------------------------*/
83
84
85 static void clock_setup(void)
86 {
87 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
88 rcc_clock_setup_in_hsi_out_24mhz();
89
90 /* Enable clocks for:
91 GPIO port A (for GPIO_USART1_TX and Button)
92 GPIO port C (LEDs)
93 USART1
94 TIM16 (RST-Pin)
95 TIM1 (IOCS1)
96 */
97 rcc_peripheral_enable_clock(&RCC_APB2ENR,
98 RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
99 | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
100 | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN
101 | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN);
102 /* Enable clocks for:
103 TIM3
104 */
105 rcc_peripheral_enable_clock(&RCC_APB1ENR,
106 RCC_APB1ENR_TIM3EN);
107
108 /* Enable clocks for:
109 DMA1
110 */
111 rcc_peripheral_enable_clock(&RCC_AHBENR,
112 RCC_AHBENR_DMA1EN);
113 }
114
115 static void systick_setup(void)
116 {
117 /* SysTick interrupt every N clock pulses: set reload to N-1 */
118 STK_RVR = 24000000/1000 - 1;
119
120 /* Set source to core clock, enable int and start counting. */
121 STK_CSR = STK_CSR_CLKSOURCE_AHB | STK_CSR_TICKINT | STK_CSR_ENABLE;
122 }
123
124 #if 0
125 static void nvic_setup(void)
126 {
127 // nvic_enable_irq(NVIC_RTC_IRQ);
128 // nvic_set_priority(NVIC_RTC_IRQ, 1);
129 }
130 #endif
131
132 static void tim3_setup(void)
133 {
134 TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;
135
136 TIM3_CCMR2 = 0
137 | TIM_CCMR2_OC4M_FORCE_LOW
138 /* | TIM_CCMR2_OC4M_FORCE_HIGH */
139 /* | TIM_CCMR2_OC4M_PWM2 */
140
141 /* | TIM_CCMR2_OC4PE */
142 /* | TIM_CCMR2_OC4FE */
143 | TIM_CCMR2_CC4S_OUT;
144
145 TIM3_CCER = TIM_CCER_CC4E
146 | TIM_CCER_CC4P;
147
148 TIM3_ARR = 48; /* default */
149 TIM3_CCR4 = 1; /* */
150 }
151
152 static void gpio_setup(void)
153 {
154
155 /* Disable JTAG-DP, but leave SW-DP Enabled. (free PA15, PB3, PB4)
156 Remap SPI1 to PB3, PB4, PB5 and PA15.
157 Remap TIM3 (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9)
158 Port D0/Port D1 mapping on OSC_IN/OSC_OUT
159 */
160 gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON,
161 AFIO_MAPR_SPI1_REMAP
162 | AFIO_MAPR_TIM3_REMAP_FULL_REMAP
163 | AFIO_MAPR_PD01_REMAP);
164
165 /* LEDs and User Button. */
166 gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
167 GPIO_CNF_OUTPUT_PUSHPULL, LED_BLUE_PIN);
168 gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_10_MHZ,
169 GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, LED_GREEN_PIN);
170 gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
171 GPIO_CNF_INPUT_FLOAT, GPIO0);
172 }
173
174
175 /*--------------------------------------------------------------------------*/
176
177 void delay_systicks(int ticks)
178 {
179 int start, stop, now;
180
181 start = STK_CVR;
182 stop = start - ticks;
183 if (stop < 0) {
184 stop += STK_RVR;
185 do {
186 now = STK_CVR;
187 } while ((now > stop) || (now <= start));
188 } else {
189 do {
190 now = STK_CVR;
191 } while ((now > stop) && (now <= start));
192 }
193 }
194
195
196 /*--------------------------------------------------------------------------*/
197
198 static void led_toggle(uint8_t lednr) {
199 if (lednr == 0)
200 LED_BLUE_TOGGLE();
201 else if (lednr == 1)
202 LED_GREEN_TOGGLE();
203 }
204
205 static void led_on(uint8_t lednr) {
206 if (lednr == 0)
207 LED_BLUE_ON();
208 else if (lednr == 1)
209 LED_GREEN_ON();
210 }
211
212 static void led_off(uint8_t lednr) {
213 if (lednr == 0)
214 LED_BLUE_OFF();
215 else if (lednr == 1)
216 LED_GREEN_OFF();
217 }
218
219 static uint8_t led_is_on(uint8_t lednr) {
220 if (lednr == 0)
221 return BBIO_PERIPH(LED_PORT+ODR, BLUE);
222 else if (lednr == 1)
223 return BBIO_PERIPH(LED_PORT+ODR, GREEN);
224 else
225 return 0;
226 }
227
228 static void ledset(uint8_t lednr, uint8_t what, uint8_t len) {
229
230 led_stat[lednr].mode = what;
231 switch (what) {
232 case PULSE:
233 led_stat[lednr].ontime = len;
234 led_stat[lednr].offtime = 0;
235 led_timer[lednr] = len;
236 led_on(lednr);
237 break;
238 case BLINK1:
239 case BLINK2:
240 if (what == BLINK1)
241 led_stat[lednr].offtime = 100 - len;
242 else
243 led_stat[lednr].offtime = 200 - len;
244 led_stat[lednr].ontime = len;
245 led_timer[lednr] = len;
246 led_on(lednr);
247 break;
248 default:
249 break;
250 }
251 }
252
253 /*--------------------------------------------------------------------------*/
254
255 static volatile uint16_t key_state,
256 key_press, // key press detect
257 key_rpt; // key long press and repeat
258
259
260 static uint16_t get_key_press(uint16_t key_mask) {
261 __disable_irq();
262 // read and clear atomic !
263 key_mask &= key_press; // read key(s)
264 key_press ^= key_mask; // clear key(s)
265 __enable_irq();
266 return key_mask;
267 }
268
269 /*
270 static uint16_t get_key_rpt(uint16_t key_mask) {
271 __disable_irq();
272 // read and clear atomic !
273 key_mask &= key_rpt; // read key(s)
274 key_rpt ^= key_mask; // clear key(s)
275 __enable_irq();
276 return key_mask;
277 }
278 */
279
280 static uint16_t get_key_short(uint16_t key_mask) {
281 __disable_irq();
282 // read key state and key press atomic !
283 return get_key_press(key_state & key_mask);
284 }
285
286 /*
287 static uint16_t get_key_long(uint16_t key_mask) {
288 return get_key_press(get_key_rpt(key_mask));
289 }
290 */
291
292 static void key_timerproc() {
293 static uint16_t key_in_last, rpt;
294 uint16_t key_in, c;
295
296 key_in = KEY_PORT;
297
298 c = key_in_last & key_in & ~key_state;
299
300 // key_state = key_state & key_in_last | (key_state | key_in_last) & key_in;
301 // key_state = key_state & key_in | (key_state | key_in) & key_in_last;
302
303 key_state = c | ((key_in_last | key_in) & key_state);
304
305 // key_state = (key_state&key_in_last) | (key_state&key_in) | (key_in_last&key_in);
306
307 key_press |= c;
308
309 key_in_last = key_in;
310
311
312 if ((key_state & REPEAT_MASK) == 0) // check repeat function
313 rpt = REPEAT_START;
314 if (--rpt == 0) {
315 rpt = REPEAT_NEXT; // repeat delay
316 key_rpt |= key_state & REPEAT_MASK;
317 }
318
319 }
320
321 /*--------------------------------------------------------------------------*/
322
323 void sys_tick_handler(void)
324 {
325 static int_fast8_t tick_10ms = 0;
326 static int_fast16_t count_ms = 0;
327
328 int_fast8_t i;
329
330 ++tick_10ms;
331 if (tick_10ms == 10)
332 {
333 Stat |= S_10MS_TO;
334
335 tick_10ms = 0;
336
337 i = led_timer[0];
338 if (i)
339 led_timer[0] = i - 1;
340 i = led_timer[1];
341 if (i)
342 led_timer[1] = i - 1;
343
344 key_timerproc();
345
346 /* Drive timer procedure of low level disk I/O module */
347 //disk_timerproc();
348 }
349
350 count_ms++;
351 if (count_ms == 1000) {
352 count_ms = 0;
353
354 i = timeout_1s;
355 if (i)
356 timeout_1s = i - 1;
357 }
358 }
359
360 void rtc_isr(void)
361 {
362 /* The interrupt flag isn't cleared by hardware, we have to do it. */
363 rtc_clear_flag(RTC_SEC);
364
365 }
366
367 /*--------------------------------------------------------------------------*/
368
369 void tim3_set(int mode)
370 {
371 uint16_t cc_mode;
372
373 cc_mode = TIM_CCMR2_CC4S_OUT;
374
375 TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP /*| TIM_CR1_OPM */ ;
376
377 if (mode < 0)
378 cc_mode |= TIM_CCMR2_OC4M_FORCE_LOW;
379 else if (mode == 0)
380 cc_mode |= TIM_CCMR2_OC4M_FORCE_HIGH;
381 else {
382 TIM3_ARR = mode;
383 TIM3_CCR4 = mode/2;
384 cc_mode |= TIM_CCMR2_OC4M_PWM2;
385 }
386
387 TIM3_CCMR2 = cc_mode;
388
389 if (mode > 0)
390 TIM3_CR1 |= TIM_CR1_CEN;
391 }
392
393 /*--------------------------------------------------------------------------*/
394
395 static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
396 {
397 uint8_t rval;
398 int_fast8_t errors = 0;
399
400 DBG_P(1, "SRAM: Check %#.5x byte... ", length);
401 while (length--) {
402 if ((rval = z80_read(addr)) != wval) {
403 if (errors == 0) {
404 printf("\nSRAM: Address W R\n" \
405 " -------------\n");
406 // 12345 00 11
407 }
408 printf(" %.5lx %.2x %.2x\n", addr, wval, rval);
409
410 if (++errors > 16 )
411 break;
412 }
413 addr++;
414 wval += inc;
415 }
416 DBG_P(1, "Done.\n");
417
418 return addr;
419 }
420
421 #if 0
422 static void z80_sram_fill(uint32_t addr, int length, uint8_t startval, int inc)
423 {
424 printf("SRAM: Write %#.5x byte... ", length); //fflush(stdout);
425 while (length--) {
426 z80_write(addr, startval);
427 ++addr;
428 startval += inc;
429 }
430 printf("Done.\n");
431 }
432
433
434 void z80_sram_fill_string(uint32_t addr, int length, const char *text)
435 {
436 char c;
437 const char *p = text;
438
439 while (length--) {
440 z80_write(addr++, c = *p++);
441 if (c == 0)
442 p = text;
443 }
444 }
445
446
447 uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
448 {
449 char c;
450 const char *p = text;
451
452 while (length--) {
453 c = *p++;
454 if (z80_read(addr) != c)
455 break;
456 ++addr;
457 if (c == 0)
458 p = text;
459 }
460 return addr;
461 }
462
463 const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
464 const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
465
466 #endif
467
468 uint8_t z80_get_byte(uint32_t adr)
469 {
470 uint8_t data;
471
472 z80_request_bus();
473 data = z80_read(adr),
474 z80_release_bus();
475
476 return data;
477 }
478
479
480 /*--------------------------------------------------------------------------*/
481
482 static void do_10ms(void)
483 {
484 for (uint_fast8_t i = 0; i < 2; i++) {
485 switch (led_stat[i].mode) {
486 case PULSE:
487 if (led_timer[i] == 0) {
488 led_off(i);
489 led_stat[i].mode = NOTHING;
490 }
491 break;
492 case BLINK1:
493 case BLINK2:
494 if (led_timer[i] == 0) {
495 if (led_is_on(i))
496 led_timer[i] = led_stat[i].offtime;
497 else
498 led_timer[i] = led_stat[i].ontime;
499 led_toggle(i);
500 }
501 break;
502 default:
503 break;
504 }
505 }
506 }
507
508 struct msg_item {
509 uint8_t fct;
510 uint8_t sub_min, sub_max;
511 void (*func)(uint8_t, int, uint8_t *);
512 };
513
514 uint32_t msg_to_addr(uint8_t *msg)
515 {
516 uint32_t addr = msg[0] | (msg[1] << 8) | ((uint32_t)msg[2] << 16);
517
518 return addr;
519
520 }
521
522 void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
523 {
524 (void)subf; (void)len;
525
526 z80_init_msg_fifo(msg_to_addr(msg));
527 }
528
529
530 void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
531 {
532 (void)len;
533
534 z80_memfifo_init(subf - 1, msg_to_addr(msg));
535 }
536
537
538 void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
539 {
540 (void)subf;
541
542 while (len--)
543 putchar(*msg++);
544 }
545
546
547 const struct msg_item z80_messages[] =
548 {
549 { 0, /* fct nr. */
550 0, 0, /* sub fct nr. from, to */
551 &do_msg_ini_msgfifo},
552 { 0,
553 1, 2,
554 &do_msg_ini_memfifo},
555 { 1,
556 1, 1,
557 &do_msg_char_out},
558 { 0xff, /* end mark */
559 0, 0,
560 0},
561
562 };
563
564
565
566
567 void do_message(int len, uint8_t *msg)
568 {
569 uint8_t fct, sub_fct;
570 int_fast8_t i = 0;
571
572 if (len >= 2) {
573 fct = *msg++;
574 sub_fct = *msg++;
575 len -= 2;
576
577 while (fct != z80_messages[i].fct)
578 ++i;
579
580 if (z80_messages[i].fct == 0xff) {
581 DBG_P(1, "do_message: Unknown function: %i, %i\n",
582 fct, sub_fct);
583 return; /* TODO: unknown message # */
584 }
585
586 while (fct == z80_messages[i].fct) {
587 if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
588 break;
589 ++i;
590 }
591
592 if (z80_messages[i].fct != fct) {
593 DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
594 fct, sub_fct);
595 return; /* TODO: unknown message sub# */
596 }
597
598 (z80_messages[i].func)(sub_fct, len, msg);
599
600
601 } else {
602 /* TODO: error */
603 DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
604 }
605 }
606
607
608
609 #define CTRBUF_LEN 256
610
611 void check_msg_fifo(void)
612 {
613 int ch;
614 static int_fast8_t state;
615 static int msglen,idx;
616 static uint8_t buffer[CTRBUF_LEN];
617
618 while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
619 switch (state) {
620 case 0: /* wait for start of message */
621 if (ch == 0x81) {
622 msglen = 0;
623 idx = 0;
624 state = 1;
625 }
626 break;
627 case 1: /* get msg len */
628 if (ch > 0 && ch <= CTRBUF_LEN) {
629 msglen = ch;
630 state = 2;
631 } else
632 state = 0;
633 break;
634 case 2: /* get message */
635 buffer[idx++] = ch;
636 if (idx == msglen)
637 state = 3;
638 break;
639 }
640 }
641
642 if (state == 3) {
643 do_message(msglen, buffer);
644 state = 0;
645 }
646 }
647
648
649 void z80_load_mem(void)
650 {
651 unsigned sec = 0;
652 uint32_t sec_base = hdrom_start;
653
654 DBG_P(1, "Loading z80 memory... \n");
655
656 while (sec < hdrom_sections) {
657 DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n",
658 hdrom_address[sec],
659 hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
660 hdrom_length_of_sections[sec]);
661
662 z80_write_block((unsigned char *) &hdrom[sec_base], /* src */
663 hdrom_address[sec], /* dest */
664 hdrom_length_of_sections[sec]); /* len */
665 sec_base+=hdrom_length_of_sections[sec];
666 sec++;
667 }
668 }
669 /*--------------------------------------------------------------------------*/
670
671 int main(void)
672 {
673 int_fast8_t state = 0;
674 int ch;
675
676 clock_setup();
677 gpio_setup();
678 tim3_setup();
679 setvbuf(stdout, NULL, _IONBF, 0);
680 serial_setup();
681 printf("\n(STM32F100+HD64180)_stamp Tester\n");
682
683 DBG_P(1, "z80_setup_bus... ");
684 z80_setup_msg_fifo();
685 z80_setup_bus();
686 DBG_P(1, "done.\n");
687
688 /*
689 * If the RTC is pre-configured just allow access, don't reconfigure.
690 * Otherwise enable it with the LSE as clock source and 0x7fff as
691 * prescale value.
692 */
693 rtc_auto_awake(RCC_LSE, 0x7fff);
694
695 systick_setup();
696
697 DBG_P(1, "Get bus... ");
698 z80_busreq(LOW);
699 z80_reset(HIGH);
700 z80_request_bus();
701 DBG_P(1, "got it!\n");
702
703 z80_memset(0, 0x76, 0x80000);
704 //z80_sram_fill(0, 512 * 1024, 0x76, 0);
705 z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
706
707 z80_load_mem();
708 z80_reset(LOW);
709 DBG_P(1, "Bus released!\n");
710 z80_release_bus();
711 z80_reset(HIGH);
712 DBG_P(1, "Reset released!\n");
713
714
715 ledset(0, BLINK1, 50);
716
717 while (1) {
718
719 if (Stat & S_10MS_TO) {
720 Stat &= ~S_10MS_TO;
721 do_10ms();
722 }
723
724 if (get_key_short(KEY0)) {
725 z80_reset_pulse();
726 }
727
728 if ((ch = serial_getc()) >= 0) {
729 switch (state) {
730 case 0:
731 if (ch == ESCCHAR) {
732 state = 1;
733 /* TODO: Timer starten */
734 } else
735 z80_memfifo_putc(fifo_out, ch);
736 break;
737 case 1:
738 switch (ch) {
739
740 case 'h': /* test: green led on */
741 tim3_set(-1);
742 break;
743 case 'l': /* test: green led off */
744 tim3_set(0);
745 break;
746 case 'p': /* test: pulse on led pin */
747 tim3_set(24000000 / 1000000 * 5); /* 5 us */
748 break;
749 case 'r':
750 z80_reset_pulse();
751 break;
752
753 case ESCCHAR:
754 default:
755 z80_memfifo_putc(fifo_out, ch);
756 }
757 state = 0;
758 break;
759 }
760 }
761
762 check_msg_fifo();
763 }
764
765 return 0;
766 }