dac.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * (c) danielinux 2020
  3. * GPLv.2
  4. *
  5. * See LICENSE for details
  6. */
  7. #include <unicore-mx/cm3/nvic.h>
  8. #include <unicore-mx/stm32/dma.h>
  9. #include <unicore-mx/stm32/dac.h>
  10. #include <unicore-mx/stm32/gpio.h>
  11. #include <unicore-mx/stm32/rcc.h>
  12. #include <unicore-mx/stm32/timer.h>
  13. #include "pot.h"
  14. #define DAC_BUFSIZ 512
  15. extern const unsigned char raw_au[];
  16. const unsigned int raw_au_len;
  17. static volatile int dac_written;
  18. static int dac_transfer_size;
  19. static int dac_chunk_size;
  20. static uint8_t dac_outb[DAC_BUFSIZ];
  21. static void dac_xmit(void)
  22. {
  23. uint32_t size = DAC_BUFSIZ;
  24. if ((dac_transfer_size - dac_written ) < size)
  25. size = dac_transfer_size - dac_written;
  26. dac_chunk_size = size;
  27. /* Start DMA transfer of waveform */
  28. dac_trigger_enable(CHANNEL_1);
  29. dac_set_trigger_source(DAC_CR_TSEL1_T2);
  30. dac_dma_enable(CHANNEL_1);
  31. dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t) (dac_outb + dac_written));
  32. dma_set_number_of_data(DMA1, DMA_STREAM5, size);
  33. dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5);
  34. dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7);
  35. dma_enable_stream(DMA1, DMA_STREAM5);
  36. }
  37. int dac_write(const void *buf, unsigned int len)
  38. {
  39. if (dac_written < dac_transfer_size) {
  40. if ((len + dac_transfer_size) > DAC_BUFSIZ)
  41. return 0;
  42. }
  43. if (dac_written >= dac_transfer_size) {
  44. dac_written = 0;
  45. dac_transfer_size = 0;
  46. }
  47. memcpy(dac_outb + dac_transfer_size, buf, len);
  48. dac_transfer_size += len;
  49. dac_xmit();
  50. return dac_written;
  51. }
  52. int dac_space(void)
  53. {
  54. if (dac_written >= dac_transfer_size) {
  55. dac_written = 0;
  56. dac_transfer_size = 0;
  57. }
  58. return DAC_BUFSIZ - dac_transfer_size;
  59. }
  60. /* IRQ Handler */
  61. void dma1_stream5_isr(void)
  62. {
  63. if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_TCIF)) {
  64. if (dac_written < dac_transfer_size)
  65. dac_written += dac_chunk_size;
  66. dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF);
  67. dma_disable_stream(DMA1, DMA_STREAM5);
  68. dac_trigger_disable(CHANNEL_1);
  69. dac_dma_disable(CHANNEL_1);
  70. if (dac_written >= dac_transfer_size) {
  71. return;
  72. } else {
  73. dac_xmit();
  74. }
  75. }
  76. }
  77. /* Initialization functions */
  78. //#define PERIOD (5200)
  79. #define PERIOD 8800
  80. static void timer_setup(void)
  81. {
  82. /* Enable TIM2 clock. */
  83. rcc_periph_clock_enable(RCC_TIM2);
  84. timer_reset(TIM2);
  85. /* Timer global mode: - No divider, Alignment edge, Direction up */
  86. timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT,
  87. TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
  88. timer_continuous_mode(TIM2);
  89. timer_set_period(TIM2, PERIOD);
  90. timer_disable_oc_output(TIM2, TIM_OC2 | TIM_OC3 | TIM_OC4);
  91. timer_enable_oc_output(TIM2, TIM_OC1);
  92. timer_disable_oc_clear(TIM2, TIM_OC1);
  93. timer_disable_oc_preload(TIM2, TIM_OC1);
  94. timer_set_oc_slow_mode(TIM2, TIM_OC1);
  95. timer_set_oc_mode(TIM2, TIM_OC1, TIM_OCM_TOGGLE);
  96. timer_set_oc_value(TIM2, TIM_OC1, 500);
  97. timer_disable_preload(TIM2);
  98. /* Set the timer trigger output (for the DAC) to the channel 1 output
  99. * compare */
  100. timer_set_master_mode(TIM2, TIM_CR2_MMS_COMPARE_OC1REF);
  101. timer_enable_counter(TIM2);
  102. }
  103. static void dac_dma_setup(void)
  104. {
  105. /* DAC channel 1 uses DMA controller 1 Stream 5 Channel 7. */
  106. /* Enable DMA1 clock and IRQ */
  107. rcc_periph_clock_enable(RCC_DMA1);
  108. nvic_set_priority(NVIC_DMA1_STREAM5_IRQ, 1);
  109. nvic_enable_irq(NVIC_DMA1_STREAM5_IRQ);
  110. dma_stream_reset(DMA1, DMA_STREAM5);
  111. dma_set_priority(DMA1, DMA_STREAM5, DMA_SxCR_PL_LOW);
  112. dma_set_memory_size(DMA1, DMA_STREAM5, DMA_SxCR_MSIZE_8BIT);
  113. dma_set_peripheral_size(DMA1, DMA_STREAM5, DMA_SxCR_PSIZE_8BIT);
  114. dma_enable_memory_increment_mode(DMA1, DMA_STREAM5);
  115. dma_enable_circular_mode(DMA1, DMA_STREAM5);
  116. dma_set_transfer_mode(DMA1, DMA_STREAM5,
  117. DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
  118. /* The register to target is the DAC1 8-bit right justified data
  119. register */
  120. dma_set_peripheral_address(DMA1, DMA_STREAM5, (uint32_t) &DAC_DHR8R1);
  121. }
  122. static void dac_hw_init(data_channel c)
  123. {
  124. /* Set DAC GPIO pin to analog mode */
  125. rcc_periph_clock_enable(RCC_GPIOC);
  126. gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4);
  127. timer_setup();
  128. /* Set up DAC */
  129. rcc_periph_clock_enable(RCC_DAC);
  130. dac_enable(c);
  131. }
  132. void dac_play(const uint8_t *buf, int len)
  133. {
  134. int i = 0;
  135. int space;
  136. while(i < len) {
  137. space = dac_space();
  138. if (space > 0) {
  139. if (space > (len - i))
  140. space = len - i;
  141. dac_write(buf + i, space);
  142. i += space;
  143. }
  144. }
  145. }
  146. int dac_init(void)
  147. {
  148. int i;
  149. dac_hw_init(CHANNEL_1);
  150. dac_dma_setup();
  151. pot_set_master(200);
  152. dac_play(raw_au, raw_au_len);
  153. return 0;
  154. }