Skip to content

Commit d04bde6

Browse files
Framerate setting after screen init and restore old voice timer code for now
1 parent 989d731 commit d04bde6

File tree

2 files changed

+54
-19
lines changed

2 files changed

+54
-19
lines changed

M4_Eyes/M4_Eyes.ino

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,13 @@ void setup() {
172172
}
173173

174174
yield();
175-
uint8_t e;
175+
uint8_t e, rtna = 0x01; // Screen refresh rate control (datasheet 9.2.18, FRCTRL2)
176176
// Initialize displays
177177
eye[0].display = arcada._display;
178+
eye[0].display->sendCommand(0xC6, &rtna, 1);
178179
if (NUM_EYES > 1) {
179180
eye[1].display = arcada.display2;
181+
eye[1].display->sendCommand(0xC6, &rtna, 1);
180182
}
181183

182184
yield();

M4_Eyes/pdmvoice.cpp

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@
33

44
#if defined(ADAFRUIT_MONSTER_M4SK_EXPRESS)
55

6-
#include "globals.h"
76
#include <SPI.h>
87

98
#define MIN_PITCH_HZ 65
109
#define MAX_PITCH_HZ 1600
1110
#define TYP_PITCH_HZ 175
1211

12+
// Playback timer stuff - use TC3 on MONSTER M4SK (no TC4 on this board)
13+
#define TIMER TC3
14+
#define TIMER_IRQN TC3_IRQn
15+
#define TIMER_IRQ_HANDLER TC3_Handler
16+
#define TIMER_GCLK_ID TC3_GCLK_ID
17+
#define TIMER_GCM_ID GCM_TC2_TC3
18+
1319
// PDM mic allows 1.0 to 3.25 MHz max clock (2.4 typical).
1420
// SPI native max is is 24 MHz, so available speeds are 12, 6, 3 MHz.
1521
#define SPI_BITRATE 3000000
@@ -97,7 +103,6 @@ static int16_t playbackIndexJumped;
97103
static uint16_t nextOut = 2048;
98104

99105
float voicePitch(float p);
100-
static void playCallback(void);
101106

102107
// START PITCH SHIFT (no arguments) ----------------------------------------
103108

@@ -110,8 +115,8 @@ bool voiceSetup(bool modEnable) {
110115

111116
// Allocate buffer for voice modulation, if enabled
112117
if(modEnable) {
113-
// Second 16.0 comes from min period in voicePitch()
114-
modBuf = (uint8_t *)malloc((int)(48000000.0 /16.0 / 16.0 / MOD_MIN + 0.5));
118+
// 250 comes from min period in voicePitch()
119+
modBuf = (uint8_t *)malloc((int)(48000000.0 / 250.0 / MOD_MIN + 0.5));
115120
// If malloc fails, program will continue without modulation
116121
}
117122

@@ -145,7 +150,37 @@ bool voiceSetup(bool modEnable) {
145150

146151
analogWriteResolution(12);
147152

148-
voicePitch(1.0); // Set timer interval & callback
153+
// Feed TIMER off GCLK1 (already set to 48 MHz by Arduino core)
154+
GCLK->PCHCTRL[TIMER_GCLK_ID].bit.CHEN = 0; // Disable channel
155+
while(GCLK->PCHCTRL[TIMER_GCLK_ID].bit.CHEN); // Wait for disable
156+
GCLK_PCHCTRL_Type pchctrl;
157+
pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK1_Val;
158+
pchctrl.bit.CHEN = 1;
159+
GCLK->PCHCTRL[TIMER_GCLK_ID].reg = pchctrl.reg;
160+
while(!GCLK->PCHCTRL[TIMER_GCLK_ID].bit.CHEN); // Wait for enable
161+
162+
// Disable timer before configuring it
163+
TIMER->COUNT16.CTRLA.bit.ENABLE = 0;
164+
while(TIMER->COUNT16.SYNCBUSY.bit.ENABLE);
165+
166+
// 16-bit counter mode, 1:1 prescale, match-frequency generation mode
167+
TIMER->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16;
168+
TIMER->COUNT16.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV1_Val;
169+
TIMER->COUNT16.WAVE.bit.WAVEGEN = TC_WAVE_WAVEGEN_MFRQ_Val;
170+
171+
TIMER->COUNT16.CTRLBCLR.reg = TC_CTRLBCLR_DIR; // Count up
172+
while(TIMER->COUNT16.SYNCBUSY.bit.CTRLB);
173+
174+
voicePitch(1.0); // Set timer interval
175+
176+
TIMER->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Overflow interrupt
177+
NVIC_DisableIRQ(TIMER_IRQN);
178+
NVIC_ClearPendingIRQ(TIMER_IRQN);
179+
NVIC_SetPriority(TIMER_IRQN, 0); // Top priority
180+
NVIC_EnableIRQ(TIMER_IRQN);
181+
182+
TIMER->COUNT16.CTRLA.bit.ENABLE = 1; // Enable timer
183+
while(TIMER->COUNT16.SYNCBUSY.bit.ENABLE); // Wait for it
149184

150185
return true; // Success
151186
}
@@ -161,15 +196,14 @@ bool voiceSetup(bool modEnable) {
161196
// adjustment (after appying constraints) will be returned.
162197
float voicePitch(float p) {
163198
float desiredPlaybackRate = sampleRate * p;
164-
int32_t period = (int32_t)(48000000.0 / 16.0 / desiredPlaybackRate);
165-
if(period > 160) period = 160; // Hard limit is 65536, 160 is a practical limit
166-
else if(period < 16) period = 16; // Leave some cycles for IRQ handler
167-
float actualPlaybackRate = 48000000.0 / 16.0 / (float)period;
199+
int32_t period = (int32_t)(48000000.0 / desiredPlaybackRate + 0.5);
200+
if(period > 2500) period = 2500; // Hard limit is 65536, 2.5K is a practical limit
201+
else if(period < 250) period = 250; // Leave some cycles for IRQ handler
202+
TIMER->COUNT16.CC[0].reg = period - 1;
203+
while(TIMER->COUNT16.SYNCBUSY.bit.CC0);
204+
float actualPlaybackRate = 48000000.0 / (float)period;
168205
p = (actualPlaybackRate / sampleRate); // New pitch
169206
jumpThreshold = (int)(jump * p + 0.5);
170-
171-
arcada.timerCallback((int)actualPlaybackRate, playCallback);
172-
173207
return p;
174208
}
175209

@@ -189,12 +223,9 @@ void voiceGain(float g) {
189223
void voiceMod(uint32_t freq, uint8_t waveform) {
190224
if(modBuf) { // Ignore if no modulation buffer allocated
191225
if(freq < MOD_MIN) freq = MOD_MIN;
192-
/*
193-
TO DO: FIX THIS NOW THAT USING ARCADA ZEROTIMER:
194226
uint16_t period = TIMER->COUNT16.CC[0].reg + 1; // Audio out timer ticks
195-
float playbackRate = 48000000.0 / 16.0 / (float)period; // Audio out samples/sec
227+
float playbackRate = 48000000.0 / (float)period; // Audio out samples/sec
196228
modLen = (int)(playbackRate / freq + 0.5);
197-
*/
198229
if(modLen < 2) modLen = 2;
199230
if(waveform > 4) waveform = 4;
200231
modWave = waveform;
@@ -366,8 +397,10 @@ void PDM_SERCOM_HANDLER(void) {
366397
evenWord ^= 1;
367398
}
368399

369-
// Playback timer callback
370-
static void playCallback(void) {
400+
// Playback timer interrupt
401+
void TIMER_IRQ_HANDLER(void) {
402+
TIMER->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF;
403+
371404
// Modulation is done on the output (rather than the input) because
372405
// pitch-shifting modulated input would cause weird waveform
373406
// discontinuities. This does require recalculating the modulation table

0 commit comments

Comments
 (0)