]> cloudbase.mooo.com Git - z180-stamp.git/blob - stm32/z180-stamp-stm32.c
Merge tag 'fatfs-0.10b'
[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_fast8_t tick_10ms = 0;
323 static int_fast16_t count_ms = 0;
324
325 int_fast8_t 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, uint32_t length, uint8_t wval, int inc)
393 {
394 uint8_t rval;
395 int_fast8_t 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) | ((uint32_t)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, /* fct nr. */
547 0, 0, /* sub fct nr. from, to */
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_fast8_t 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_fast8_t 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 unsigned sec = 0;
649 uint32_t sec_base = hdrom_start;
650
651 DBG_P(1, "Loading z80 memory... \n");
652
653 while (sec < hdrom_sections) {
654 DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n",
655 hdrom_address[sec],
656 hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
657 hdrom_length_of_sections[sec]);
658
659 z80_write_block((unsigned char *) &hdrom[sec_base], /* src */
660 hdrom_address[sec], /* dest */
661 hdrom_length_of_sections[sec]); /* len */
662 sec_base+=hdrom_length_of_sections[sec];
663 sec++;
664 }
665 }
666 /*--------------------------------------------------------------------------*/
667
668 int main(void)
669 {
670 int_fast8_t state = 0;
671 int ch;
672
673 clock_setup();
674 gpio_setup();
675 tim3_setup();
676 setvbuf(stdout, NULL, _IONBF, 0);
677 serial_setup();
678 printf("\n(STM32F100+HD64180)_stamp Tester\n");
679
680 DBG_P(1, "z80_setup_bus... ");
681 z80_setup_msg_fifo();
682 z80_setup_bus();
683 DBG_P(1, "done.\n");
684
685 /*
686 * If the RTC is pre-configured just allow access, don't reconfigure.
687 * Otherwise enable it with the LSE as clock source and 0x7fff as
688 * prescale value.
689 */
690 rtc_auto_awake(LSE, 0x7fff);
691
692 systick_setup();
693
694 DBG_P(1, "Get bus... ");
695 z80_busreq(LOW);
696 z80_reset(HIGH);
697 z80_request_bus();
698 DBG_P(1, "got it!\n");
699
700 z80_memset(0, 0x76, 0x80000);
701 //z80_sram_fill(0, 512 * 1024, 0x76, 0);
702 z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
703
704 z80_load_mem();
705 z80_reset(LOW);
706 DBG_P(1, "Bus released!\n");
707 z80_release_bus();
708 z80_reset(HIGH);
709 DBG_P(1, "Reset released!\n");
710
711
712 ledset(0, BLINK1, 50);
713
714 while (1) {
715
716 if (Stat & S_10MS_TO) {
717 Stat &= ~S_10MS_TO;
718 do_10ms();
719 }
720
721 if (get_key_short(KEY0)) {
722 z80_reset_pulse();
723 }
724
725 if ((ch = serial_getc()) >= 0) {
726 switch (state) {
727 case 0:
728 if (ch == ESCCHAR) {
729 state = 1;
730 /* TODO: Timer starten */
731 } else
732 z80_memfifo_putc(fifo_out, ch);
733 break;
734 case 1:
735 switch (ch) {
736
737 case 'h': /* test: green led on */
738 tim3_set(-1);
739 break;
740 case 'l': /* test: green led off */
741 tim3_set(0);
742 break;
743 case 'p': /* test: pulse on led pin */
744 tim3_set(24000000 / 1000000 * 5); /* 5 us */
745 break;
746 case 'r':
747 z80_reset_pulse();
748 break;
749
750 case ESCCHAR:
751 default:
752 z80_memfifo_putc(fifo_out, ch);
753 }
754 state = 0;
755 break;
756 }
757 }
758
759 check_msg_fifo();
760 }
761
762 return 0;
763 }