I am trying to understand how to use DMA to vary PWM duty cycle so that I could put it through a low-pass filter to create a sine wave. I am using the rogerclarkmelbourne core. I tried doing it with dma_setup_transfer (commented out) and with dma_tube_config (which is evidently the preferred way of doing DMA now), but I'm not understanding how they're supposed to work. In either case I get a compiler error on the DMA_CCR_CIRC | DMA_CCR_MINC portion:
Compilation error: invalid conversion from 'const void*' to 'volatile void*' [-fpermissive]
Can anyone tell me what I'm doing wrong?
Code: Select all
#include "libmaple/dma.h"
#define filteredPWMpin PB0
// sinewave = round(512/2*(sin(dt:dt:2*pi)+1))
#define SINSIZE 64
const uint16_t Sinewave[SINSIZE] =
{ 281, 306, 330, 354, 377, 398, 418, 437, 454, 469, 482, 493, 501, 507, 511, 512,
511, 507, 501, 493, 482, 469, 454, 437, 418, 398, 377, 354, 330, 306, 281, 256,
231, 206, 182, 158, 135, 114, 94, 75, 58, 43, 30, 19, 11, 5, 1, 0,
1, 5, 11, 19, 30, 43, 58, 75, 94, 114, 135, 158, 182, 206, 231, 256 };
#include <libmaple/timer.h>
timer_dev *timerdev;
uint8 cc_channel;
void pwmSetup (uint8 pin, uint16 duty_cycle) {
if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
timerdev = PIN_MAP[pin].timer_device;
cc_channel = PIN_MAP[pin].timer_channel;
ASSERT(timerdev && cc_channel);
timer_set_reload(timerdev, 512);
timer_set_compare(timerdev, cc_channel, duty_cycle);
dma_init(DMA1);
__IO uint32 *ccr = &(timerdev->regs).gen->CCR1 + (cc_channel - 1);
// dma_setup_transfer is deprecated in favor of dma_tube_config
/*
dma_setup_transfer( DMA1, DMA_CH1, Sinewave, DMA_SIZE_16BITS,
ccr,
DMA_SIZE_16BITS,
DMA_CCR_CIRC | DMA_CCR_MINC );
dma_set_num_transfers(DMA1, DMA_CH1, SINSIZE);
dma_enable(DMA1, DMA_CH1);
*/
struct dma_tube_config myconfig;
myconfig.tube_dst = ccr;
myconfig.tube_dst_size = DMA_SIZE_16BITS;
myconfig.tube_src = Sinewave;
myconfig.tube_src_size = DMA_SIZE_16BITS;
myconfig.tube_nr_xfers = SINSIZE;
myconfig.tube_flags = DMA_CCR_CIRC | DMA_CCR_MINC;
myconfig.tube_req_src = DMA_REQ_SRC_TIM4_CH2; //?
}
void setup() {
// put your setup code here, to run once:
pinMode(filteredPWMpin, PWM);
pwmSetup(filteredPWMpin, 1);
}
void loop() {
// put your main code here, to run repeatedly:
}