Skip to content

Commit db1119a

Browse files
committed
pbio/drv/sound/sound_ev3: Implement minimum-viable audio playback
1 parent 0747186 commit db1119a

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

lib/pbio/drv/sound/sound_ev3.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,32 @@ static const pbdrv_gpio_t pin_audio = PBDRV_GPIO_EV3_PIN(3, 7, 4, 0, 0);
3030
// and we do not want the usable bit depth to vary as the sample rate changes.
3131
static const unsigned N_BITS_PER_SAMPLE = 12;
3232

33+
static uint64_t sample_timing_accum_numerator;
34+
static uint32_t sample_idx;
35+
36+
static const uint16_t *playing_data;
37+
static uint32_t playing_data_len;
38+
static uint32_t playing_sample_rate;
39+
3340
static void sound_isr() {
3441
EHRPWMETIntClear(SOC_EHRPWM_0_REGS);
3542
IntSystemStatusClear(SYS_INT_EHRPWM0);
3643

37-
// TODO: Load samples
44+
// Convert the hardware sample index to a desired data sample index
45+
// (using a naive ratio, rearranged to be computable using integers)
46+
// TODO: Use a real DSP resampling algorithm
47+
sample_timing_accum_numerator += (uint64_t)playing_sample_rate * (1ull << N_BITS_PER_SAMPLE);
48+
if (sample_timing_accum_numerator >= SOC_EHRPWM_0_MODULE_FREQ) {
49+
sample_timing_accum_numerator -= SOC_EHRPWM_0_MODULE_FREQ;
50+
sample_idx++;
51+
}
52+
if (sample_idx == playing_data_len) {
53+
sample_idx = 0;
54+
}
55+
56+
uint16_t sample = playing_data[sample_idx];
57+
// TODO: Dither the quantization error
58+
HWREGH(SOC_EHRPWM_0_REGS + EHRPWM_CMPB) = sample >> (16 - N_BITS_PER_SAMPLE);
3859
}
3960

4061
void pbdrv_sound_stop() {
@@ -52,7 +73,28 @@ void pbdrv_sound_stop() {
5273
}
5374

5475
void pbdrv_sound_start(const uint16_t *data, uint32_t length, uint32_t sample_rate) {
76+
// Stop any currently-playing sounds
77+
pbdrv_sound_stop();
5578

79+
if (length == 0) {
80+
return;
81+
}
82+
83+
__asm__ volatile ("" ::: "memory");
84+
playing_data = data;
85+
playing_data_len = length;
86+
playing_sample_rate = sample_rate;
87+
sample_idx = 0;
88+
sample_timing_accum_numerator = 0;
89+
__asm__ volatile ("" ::: "memory");
90+
91+
// Set the first sample
92+
HWREGH(SOC_EHRPWM_0_REGS + EHRPWM_CMPB) = data[0] >> (16 - N_BITS_PER_SAMPLE);
93+
94+
// Enable all the sound generation
95+
pbdrv_gpio_out_high(&pin_sound_en);
96+
EHRPWMETIntEnable(SOC_EHRPWM_0_REGS);
97+
HWREGH(SOC_EHRPWM_0_REGS + EHRPWM_TBCTL) = (HWREGH(SOC_EHRPWM_0_REGS + EHRPWM_TBCTL) & ~EHRPWM_TBCTL_CTRMODE) | EHRPWM_TBCTL_CTRMODE_UP;
5698
}
5799

58100
void pbdrv_sound_init() {

0 commit comments

Comments
 (0)