#include "STM32F0x1.h" #include "CortexM0.h" #include "gpio.h" #include "pcmdma.h" typedef __SIZE_TYPE__ size_t; /* TIMER: * fs = 8000Hz, ft = 3 * fs = 24000Hz * reload = SystemCoreClock / ft = 48000000Hz / 24000Hz = 2000 * PINY : +PA9[AF2], -PB0[AF2] => TIM1:CH2 * DMA : TIM1_UP = 5 */ static void Dma1Ch5Init (void * addr) { // Configure the peripheral data register address etc DMA1. CPAR5.R = reinterpret_cast (& (TIM1.CCR2)); DMA1. CMAR5.R = reinterpret_cast (addr); DMA1.CNDTR5.R = FULL_LEN; // Configure increment, size, interrupts and circular mode DMA1.CCR5.modify([](auto & ccr) -> auto { ccr.B.MINC = SET; ccr.B.MSIZE = 1u; ccr.B.PSIZE = 1u; ccr.B.DIR = SET; ccr.B.HTIE = SET; // Po půlce přerušit. ccr.B.TCIE = SET; // Po dokončení přerušit. ccr.B.CIRC = SET; ccr.B.EN = RESET; return ccr.R; }); } static PcmDma * PcmDmaInstance = nullptr; PcmDma::PcmDma() noexcept : pL(buffer), pH(buffer + HALF_LEN) { PcmDmaInstance = this; const GpioClass de (GpioPortA, 12); de << true; // použitý hardware používá jako budič sluchátek 75176 (RS485), nutno vybavit for (unsigned n=0; n> 1; GpioClass pin1p (GpioPortA, 9, GPIO_Mode_AF); GpioClass pin1n (GpioPortB, 0, GPIO_Mode_AF); pin1p.setAF (2); pin1n.setAF (2); // 1. Enable clock peripheral RCC.APB2ENR.B.TIM1EN = SET; RCC.AHBENR. B.DMA1EN = SET; // 2. Timer TIM1.PSC.R = 0u; TIM1.ARR.R = MAXPWM - 1; TIM1.RCR.R = 0u; // OC preload, CC output, Mode 6 = PWM1 TIM1.CCMR1_Output.modify([](TIM1_Type::CCMR1_Output_DEF & r) -> auto { r.B.OC2PE = SET; r.B.OC2M = 6u; return r.R; }); // povol pin + negaci TIM1.CCER.modify([](TIM1_Type::CCER_DEF & r) -> auto { r.B.CC2E = SET; r.B.CC2NE = SET; return r.R; }); // Set Output, dead time TIM1.BDTR.modify([](TIM1_Type::BDTR_DEF & r) -> auto { //r.B.DTG = 48u; // dead: 1 us r.B.MOE = SET; // Main output enable //r.B.OSSR = 1u; // Off-state selection for Run mode - TODO return r.R; }); // Preload TIM1.CR1.modify([](TIM1_Type::CR1_DEF & r) -> auto { r.B.ARPE = SET; // TIM1_ARR register is buffered r.B.URS = SET; // Only counter overflow/underflow generates an update DMA request return r.R; }); /* Update DMA request enable * Spustíme DMA - sice budou dlouhé buffery, ale přerušení jen po 20ms */ TIM1.EGR.B.UG = SET; // Reinitialize the counter and generates an update of the registers TIM1.DIER.B.UDE = SET; // Update DMA request enabled Dma1Ch5Init (buffer); // 3. NVIC NVIC_EnableIRQ (DMA1_CH4_5_6_7_DMA2_CH3_4_5_IRQn); TIM1.CR1.R |= 1u; // enable TIM1 (překladač bohužel bere poslední bit jako half, registr to neunese) DMA1.CCR5.R |= 1u; // enable DMA (dtto) } // Přerušení od DMA extern "C" void DMA1_CH4_5_6_7_DMA2_CH3_4_5_IRQHandler (void) { DMA1_Type::ISR_DEF status (DMA1.ISR); DMA1.IFCR.R = status.R; // clear flags if (!PcmDmaInstance) return; if (status.B.HTIF5 != RESET) PcmDmaInstance->send(false); else if (status.B.TCIF5 != RESET) PcmDmaInstance->send(true); }