Hi Sunspot,
I just wrote a nice long technical repsonse but I hit a wrong keystroke and it was all gone in a flash :-(
Anyway, here goes again, but expurgated.
Here is some code I use to generate a high frequency square wave
void setup() {
// put your setup code here, to run once:
setupCameraClock(PA8);
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
}
void setupCameraClock(int pin)
{
#define CLOCK_COUNT 3
timer_dev *timerDevice = PIN_MAP[pin].timer_device;
uint8 timerChannel = PIN_MAP[pin].timer_channel;
pinMode(pin,PWM);
timer_pause(timerDevice);
timer_set_reload(timerDevice,CLOCK_COUNT);
timer_set_prescaler(timerDevice,timerChannel);
timer_set_compare(timerDevice, timerChannel, CLOCK_COUNT);
timer_resume(timerDevice);
}
I forget the precise frequiency, but its at least 8Mhz
So if you adapt that code, you can get the PWM on your audio output in running at a nice value e.g. 100Khz
Then if you look at PWM write it does this
void pwmWrite(uint8 pin, uint16 duty_cycle) {
if (pin >= BOARD_NR_GPIO_PINS) {
return;
}
timer_dev *dev = PIN_MAP[pin].timer_device;
uint8 cc_channel = PIN_MAP[pin].timer_channel;
ASSERT(dev && cc_channel);
timer_set_compare(dev, cc_channel, duty_cycle);
}
And looking at what set_timer_compare does
static inline void timer_set_compare(timer_dev *dev,
uint8 channel,
uint16 value) {
__io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1);
*ccr = value;
}
So if you cache *ccr in to a global variable in setup, and just write new values you can adjust the PWM very quickly
So to play from SD, once Victor gets the SD DMA working, you should be able to double buffer DMA into ram, then use another timer interrupt to take the data from the double buffer and play it.
You also need a low pass audio filter, perhaps with the 3dB point at around 5kHz would probably do
However, this isn't the simplest of projects.