floppy_f1.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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_sel gpiob
  27. #define pin_sel 10 /* PB10 */
  28. #define gpio_mot gpiob
  29. #define pin_mot 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 irq_index 23
  50. void IRQ_23(void) __attribute__((alias("IRQ_INDEX_changed"))); /* EXTI9_5 */
  51. /* We sometimes cast u_buf to uint32_t[], hence the alignment constraint. */
  52. #define U_BUF_SZ 8192
  53. static uint8_t u_buf[U_BUF_SZ] aligned(4);
  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. /* Configure SELECT/MOTOR lines. */
  69. configure_pin(sel, GPO_bus);
  70. configure_pin(mot, GPO_bus);
  71. }
  72. static void rdata_prep(void)
  73. {
  74. /* RDATA Timer setup:
  75. * The counter runs from 0x0000-0xFFFF inclusive at SAMPLE rate.
  76. *
  77. * Ch.2 (RDATA) is in Input Capture mode, sampling on every clock and with
  78. * no input prescaling or filtering. Samples are captured on the falling
  79. * edge of the input (CCxP=1). DMA is used to copy the sample into a ring
  80. * buffer for batch processing in the DMA-completion ISR. */
  81. tim_rdata->psc = TIM_PSC-1;
  82. tim_rdata->arr = 0xffff;
  83. tim_rdata->ccmr1 = TIM_CCMR1_CC2S(TIM_CCS_INPUT_TI1);
  84. tim_rdata->dier = TIM_DIER_CC2DE;
  85. tim_rdata->cr2 = 0;
  86. tim_rdata->egr = TIM_EGR_UG; /* update CNT, PSC, ARR */
  87. tim_rdata->sr = 0; /* dummy write */
  88. /* RDATA DMA setup: From the RDATA Timer's CCRx into a circular buffer. */
  89. dma_rdata.par = (uint32_t)(unsigned long)&tim_rdata->ccr2;
  90. dma_rdata.cr = (DMA_CR_PL_HIGH |
  91. DMA_CR_MSIZE_16BIT |
  92. DMA_CR_PSIZE_16BIT |
  93. DMA_CR_MINC |
  94. DMA_CR_CIRC |
  95. DMA_CR_DIR_P2M |
  96. DMA_CR_EN);
  97. tim_rdata->ccer = TIM_CCER_CC2E | TIM_CCER_CC2P;
  98. }
  99. static void wdata_prep(void)
  100. {
  101. /* WDATA Timer setup:
  102. * The counter is incremented at SAMPLE rate.
  103. *
  104. * Ch.1 (WDATA) is in PWM mode 1. It outputs O_TRUE for 400ns and then
  105. * O_FALSE until the counter reloads. By changing the ARR via DMA we alter
  106. * the time between (fixed-width) O_TRUE pulses, mimicking floppy drive
  107. * timings. */
  108. tim_wdata->psc = TIM_PSC-1;
  109. tim_wdata->ccmr1 = (TIM_CCMR1_CC1S(TIM_CCS_OUTPUT) |
  110. TIM_CCMR1_OC1M(TIM_OCM_PWM1));
  111. tim_wdata->ccer = TIM_CCER_CC1E | ((O_TRUE==0) ? TIM_CCER_CC1P : 0);
  112. tim_wdata->ccr1 = sample_ns(400);
  113. tim_wdata->dier = TIM_DIER_UDE;
  114. tim_wdata->cr2 = 0;
  115. }
  116. static void dma_wdata_start(void)
  117. {
  118. dma_wdata.cr = (DMA_CR_PL_HIGH |
  119. DMA_CR_MSIZE_16BIT |
  120. DMA_CR_PSIZE_16BIT |
  121. DMA_CR_MINC |
  122. DMA_CR_CIRC |
  123. DMA_CR_DIR_M2P |
  124. DMA_CR_EN);
  125. }
  126. static void drive_deselect(void)
  127. {
  128. write_pin(sel, FALSE);
  129. unit_nr = -1;
  130. }
  131. static uint8_t drive_select(uint8_t nr)
  132. {
  133. write_pin(sel, TRUE);
  134. unit_nr = 0;
  135. delay_us(delay_params.select_delay);
  136. return ACK_OKAY;
  137. }
  138. static uint8_t drive_motor(uint8_t nr, bool_t on)
  139. {
  140. if (unit[0].motor == on)
  141. return ACK_OKAY;
  142. write_pin(mot, on);
  143. unit[0].motor = on;
  144. if (on)
  145. delay_ms(delay_params.motor_delay);
  146. return ACK_OKAY;
  147. }
  148. static void reset_bus(void)
  149. {
  150. write_pin(sel, FALSE);
  151. write_pin(mot, FALSE);
  152. }
  153. /*
  154. * Local variables:
  155. * mode: C
  156. * c-file-style: "Linux"
  157. * c-basic-offset: 4
  158. * tab-width: 4
  159. * indent-tabs-mode: nil
  160. * End:
  161. */