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