floppy_f1.c 5.5 KB

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