RISC-V/V203F6P6/gsm/pwmclass.cpp

108 lines
3.3 KiB
C++
Raw Permalink Normal View History

2025-01-30 19:27:19 +01:00
#include "pwmclass.h"
#include "gpio.h"
typedef __SIZE_TYPE__ size_t;
extern "C" {
[[gnu::interrupt]] extern void DMA1_Channel2_IRQHandler( void );
};
static PwmClass * pPwmInstance = nullptr;
void DMA1_Channel2_IRQHandler( void ) {
DMA1_Type::INTFR_DEF state (DMA1.INTFR);
if (state.B.GIF2 != RESET) {
DMA1.INTFCR.B.CGIF2 = SET;
} else return;
if (state.B.HTIF2 != RESET) {
DMA1.INTFCR.B.CHTIF2 = SET;
if (pPwmInstance) pPwmInstance->send(false);
}
if (state.B.TCIF2 != RESET) {
DMA1.INTFCR.B.CTCIF2 = SET;
if (pPwmInstance) pPwmInstance->send(true);
}
}
/*
* initialize TIM2 for PWM
*/
inline void PwmClass::TimInit() noexcept {
// Enable GPIOA and TIM1
RCC.APB2PCENR.modify([] (RCC_Type::APB2PCENR_DEF & r) -> auto {
r.B.IOPAEN = SET;
r.B.IOPBEN = SET;
//r.B.AFIOEN = SET;
return r.R;
});
RCC.APB1PCENR.B.TIM2EN = SET;
// PA2 is TIM2_CH3, 10MHz Output alt func, push-pull
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
r.B.CNF2 = 2u;
r.B.MODE2 = 1u;
return r.R;
});
// PB1 is DEN, active H Output 10 MHz, push-pull
GPIOB.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
r.B.CNF1 = 0u;
r.B.MODE1 = 1u;
return r.R;
});
GPIOB.BSHR.B.BS1 = SET; // set to H
// Reset TIM2 to init all regs
RCC.APB1PRSTR.B.TIM2RST = SET;
RCC.APB1PRSTR.B.TIM2RST = RESET;
// CTLR1: default is up, events generated, edge align
// SMCFGR: default clk input is CK_INT
// Prescaler
TIM2.PSC.R = 0u; // 144 MHz
// Auto Reload - sets period
TIM2.ATRLR.R = MAXPWM - 1; // 24 kHz
// CH3 Mode is output, PWM1 (CC3S = 00, OC3M = 110)
TIM2.CHCTLR2_Output.modify([](TIM2_Type::CHCTLR2_Output_DEF & r) -> auto {
r.B.OC3M = 0x6u;
return r.R;
});
// Enable TIM1 outputs
TIM2.CCER.modify([](TIM2_Type::CCER_DEF & r) -> auto {
// Enable CH3, CH3 output, positive pol
r.B.CC3E = SET;
//r.B.CC3P = SET; // negative
return r.R;
});
// Reload immediately + Trigger DMA
TIM2.SWEVGR.B.UG = SET;
TIM2.DMAINTENR.B.UDE = SET;
}
inline void PwmClass::DmaInit() noexcept {
// Enable DMA
RCC.AHBPCENR.modify([](RCC_Type::AHBPCENR_DEF & r) -> auto {
r.B.SRAMEN = SET;
r.B.DMA1EN = SET;
return r.R;
});
// DMA can be configured to attach to T2UP
// The system can only DMA out at ~2.2MSPS. 2MHz is stable.
DMA1.CNTR2 .R = FULL_LEN;
DMA1.MADDR2.R = reinterpret_cast<size_t>(buffer);
DMA1.PADDR2.R = reinterpret_cast<size_t>(& TIM2.CH3CVR);
NVIC.EnableIRQ (DMA1_Channel2_IRQn);
DMA1.CFGR2.modify([](DMA1_Type::CFGR2_DEF & r) -> auto {
r.B.DIR = SET; // MEM2PERIPHERAL
r.B.PL = 2u; // High priority.
r.B.PSIZE = 1u; // 16-bit peripheral
r.B.MSIZE = 1u; // 16-bit memory
r.B.MINC = SET; // Increase memory.
r.B.CIRC = SET; // Circular mode.
r.B.HTIE = SET; // Half-trigger
r.B.TCIE = SET; // Whole-trigger
// Enable DMA1 CH2
r.B.EN = SET;
return r.R;
});
}
PwmClass::PwmClass() noexcept : count(0u), pL(buffer), pH(buffer + HALF_LEN), src(nullptr) {
pPwmInstance = this;
TimInit ();
DmaInit ();
// Enable TIM2
TIM2.CTLR1.B.CEN = SET;
}