floppy_f1.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * floppy_f1.c
  3. *
  4. * Floppy interface control: STM32F103C8.
  5. *
  6. * Written & released by Keir Fraser <keir.xen@gmail.com>
  7. *
  8. * This is free and unencumbered software released into the public domain.
  9. * See the file COPYING for more details, or visit <http://unlicense.org>.
  10. */
  11. #define O_FALSE 1
  12. #define O_TRUE 0
  13. #define GPO_bus GPO_opendrain(_2MHz,O_FALSE)
  14. #define AFO_bus AFO_opendrain(_2MHz)
  15. static unsigned int GPI_bus;
  16. /* Input pins */
  17. #define gpio_index gpiob
  18. #define pin_index 6 /* PB6 */
  19. #define gpio_trk0 gpiob
  20. #define pin_trk0 7 /* PB7 */
  21. #define gpio_wrprot gpiob
  22. #define pin_wrprot 8 /* PB8 */
  23. /* Output pins. */
  24. #define gpio_densel gpiob
  25. #define pin_densel 9 /* PB9 */
  26. #define gpio_sel0 gpiob
  27. #define pin_sel0 10 /* PB10 */
  28. #define gpio_mot0 gpiob
  29. #define pin_mot0 11 /* PB11 */
  30. #define gpio_dir gpiob
  31. #define pin_dir 12 /* PB12 */
  32. #define gpio_step gpiob
  33. #define pin_step 13 /* PB13 */
  34. #define gpio_wgate gpiob
  35. #define pin_wgate 14 /* PB14 */
  36. #define gpio_side gpiob
  37. #define pin_side 15 /* PB15 */
  38. /* RDATA: Pin B3, Timer 2 Channel 2, DMA1 Channel 7. */
  39. #define gpio_rdata gpiob
  40. #define pin_rdata 3
  41. #define tim_rdata (tim2)
  42. #define dma_rdata (dma1->ch7)
  43. /* WDATA: Pin B4, Timer 3 Channel 1, DMA1 Channel 3. */
  44. #define gpio_wdata gpiob
  45. #define pin_wdata 4
  46. #define tim_wdata (tim3)
  47. #define dma_wdata (dma1->ch3)
  48. typedef uint16_t timcnt_t;
  49. #define TIM_PSC 0
  50. #define irq_index 23
  51. void IRQ_23(void) __attribute__((alias("IRQ_INDEX_changed"))); /* EXTI9_5 */
  52. #define irq_index_delay 31
  53. void IRQ_31(void) __attribute__((alias("IRQ_INDEX_delay")));
  54. static void floppy_mcu_init(void)
  55. {
  56. /* Determine whether input pins must be internally pulled down. */
  57. configure_pin(index, GPI_pull_down);
  58. delay_us(10);
  59. GPI_bus = (get_index() == LOW) ? GPI_pull_up : GPI_floating;
  60. printk("Floppy Inputs: %sternal Pullup\n",
  61. (GPI_bus == GPI_pull_up) ? "In" : "Ex");
  62. /* Remap timers to RDATA/WDATA pins. */
  63. afio->mapr |= (AFIO_MAPR_TIM2_REMAP_PARTIAL_1
  64. | AFIO_MAPR_TIM3_REMAP_PARTIAL);
  65. /* Set up EXTI mapping for INDEX: PB[15:0] -> EXT[15:0] */
  66. afio->exticr1 = afio->exticr2 = afio->exticr3 = afio->exticr4 = 0x1111;
  67. configure_pin(rdata, GPI_bus);
  68. }
  69. static void rdata_prep(void)
  70. {
  71. /* RDATA Timer setup:
  72. * The counter runs from 0x0000-0xFFFF inclusive at full SYSCLK rate.
  73. *
  74. * Ch.2 (RDATA) is in Input Capture mode, sampling on every clock and with
  75. * no input prescaling or filtering. Samples are captured on the falling
  76. * edge of the input (CCxP=1). DMA is used to copy the sample into a ring
  77. * buffer for batch processing in the DMA-completion ISR. */
  78. tim_rdata->psc = 0;
  79. tim_rdata->arr = 0xffff;
  80. tim_rdata->ccmr1 = TIM_CCMR1_CC2S(TIM_CCS_INPUT_TI1);
  81. tim_rdata->dier = TIM_DIER_CC2DE;
  82. tim_rdata->cr2 = 0;
  83. tim_rdata->egr = TIM_EGR_UG; /* update CNT, PSC, ARR */
  84. tim_rdata->sr = 0; /* dummy write */
  85. /* RDATA DMA setup: From the RDATA Timer's CCRx into a circular buffer. */
  86. dma_rdata.par = (uint32_t)(unsigned long)&tim_rdata->ccr2;
  87. dma_rdata.cr = (DMA_CR_PL_HIGH |
  88. DMA_CR_MSIZE_16BIT |
  89. DMA_CR_PSIZE_16BIT |
  90. DMA_CR_MINC |
  91. DMA_CR_CIRC |
  92. DMA_CR_DIR_P2M |
  93. DMA_CR_EN);
  94. tim_rdata->ccer = TIM_CCER_CC2E | TIM_CCER_CC2P;
  95. }
  96. static void wdata_prep(void)
  97. {
  98. /* WDATA Timer setup:
  99. * The counter is incremented at full SYSCLK rate.
  100. *
  101. * Ch.1 (WDATA) is in PWM mode 1. It outputs O_TRUE for 400ns and then
  102. * O_FALSE until the counter reloads. By changing the ARR via DMA we alter
  103. * the time between (fixed-width) O_TRUE pulses, mimicking floppy drive
  104. * timings. */
  105. tim_wdata->psc = 0;
  106. tim_wdata->ccmr1 = (TIM_CCMR1_CC1S(TIM_CCS_OUTPUT) |
  107. TIM_CCMR1_OC1M(TIM_OCM_PWM1));
  108. tim_wdata->ccer = TIM_CCER_CC1E | ((O_TRUE==0) ? TIM_CCER_CC1P : 0);
  109. tim_wdata->ccr1 = sysclk_ns(400);
  110. tim_wdata->dier = TIM_DIER_UDE;
  111. tim_wdata->cr2 = 0;
  112. }
  113. static void dma_wdata_start(void)
  114. {
  115. dma_wdata.cr = (DMA_CR_PL_HIGH |
  116. DMA_CR_MSIZE_16BIT |
  117. DMA_CR_PSIZE_16BIT |
  118. DMA_CR_MINC |
  119. DMA_CR_CIRC |
  120. DMA_CR_DIR_M2P |
  121. DMA_CR_EN);
  122. }
  123. /*
  124. * Local variables:
  125. * mode: C
  126. * c-file-style: "Linux"
  127. * c-basic-offset: 4
  128. * tab-width: 4
  129. * indent-tabs-mode: nil
  130. * End:
  131. */