8000 Fix playing audio from SD card · sparkfun/circuitpython@e724bc1 · GitHub
[go: up one dir, main page]

Skip to content
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e724bc1

Browse files
committed
Fix playing audio from SD card
1 parent 618943d commit e724bc1

File tree

9 files changed

+142
-45
lines changed

9 files changed

+142
-45
lines changed

extmod/vfs_fat_diskio.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,17 @@ DRESULT disk_read (
131131
} else {
132132
vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
133133
vfs->readblocks[3] = mp_obj_new_bytearray_by_ref(count * SECSIZE(&vfs->fatfs), buff);
134-
mp_call_method_n_kw(2, 0, vfs->readblocks);
135-
// TODO handle error return
134+
nlr_buf_t nlr;
135+
if (nlr_push(&nlr) == 0) {
136+
mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->readblocks);
137+
nlr_pop();
138+
if (mp_obj_get_int(ret) != 0) {
139+
return RES_ERROR;
140+
}
141+
} else {
142+
// Exception thrown by readblocks or something it calls.
143+
return RES_ERROR;
144+
}
136145
}
137146

138147
return RES_OK;
@@ -167,8 +176,17 @@ DRESULT disk_write (
167176
} else {
168177
vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
169178
vfs->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * SECSIZE(&vfs->fatfs), (void*)buff);
170-
mp_call_method_n_kw(2, 0, vfs->writeblocks);
171-
// TODO handle error return
179+
nlr_buf_t nlr;
180+
if (nlr_push(&nlr) == 0) {
181+
mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->writeblocks);
182+
nlr_pop();
183+
if (mp_obj_get_int(ret) != 0) {
184+
return RES_ERROR;
185+
}
186+
} else {
187+
// Exception thrown by writeblocks or something it calls.
188+
return RES_ERROR;
189+
}
172190
}
173191

174192
return RES_OK;

main.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ bool start_mp(safe_mode_t safe_mode) {
233233
}
234234
}
235235

236-
void run_boot_py(safe_mode_t safe_mode) {
236+
void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
237237
// If not in safe mode, run boot before initing USB and capture output in a
238238
// file.
239239
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
@@ -258,10 +258,12 @@ void run_boot_py(safe_mode_t safe_mode) {
258258
// This saves wear and tear on the flash and also prevents filesystem damage if power is lost
259259
// during the write, which may happen due to bobbling the power connector or weak power.
260260

261+
static const size_t NUM_CHARS_TO_COMPARE = 160;
261262
if (!have_boot_py && f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
262-
char file_contents[512];
263+
264+
char file_contents[NUM_CHARS_TO_COMPARE];
263265
UINT chars_read = 0;
264-
f_read(boot_output_file, file_contents, 512, &chars_read);
266+
f_read(boot_output_file, file_contents, NUM_CHARS_TO_COMPARE, &chars_read);
265267
f_close(boot_output_file);
266268
skip_boot_output =
267269
// + 2 accounts for \r\n.

ports/atmel-samd/Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ endif
102102
ifeq ($(DEBUG), 1)
103103
# Turn on Python modules useful for debugging (e.g. uheap, ustack).
104104
CFLAGS += -ggdb
105-
## CFLAGS += -flto
106-
CFLAGS += -fno-inline -fno-ipa-sra
105+
# You may want to disable -flto if it interferes with debugging.
106+
CFLAGS += -flto
107+
# You may want to enable these flags to make setting breakpoints easier.
108+
## CFLAGS += -fno-inline -fno-ipa-sra
107109
ifeq ($(CHIP_FAMILY), samd21)
108110
CFLAGS += -DENABLE_MICRO_TRACE_BUFFER
109111
endif

ports/atmel-samd/audio_dma.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434

3535
#include "py/mpstate.h"
3636

37+
static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];
38+
39+
// This cannot be in audio_dma_state because it's volatile.
40+
static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT];
41+
3742
uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
3843
if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
3944
audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
@@ -70,7 +75,7 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
7075
return 1;
7176
}
7277

73-
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
78+
static void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
7479
if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
7580
audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
7681
audioio_rawsample_reset_buffer(sample, single_channel, audio_channel);
@@ -81,7 +86,10 @@ void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t
8186
}
8287
}
8388

84-
bool audiosample_get_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t channel, uint8_t** buffer, uint32_t* buffer_length) {
89+
static audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
90+
bool single_channel,
91+
uint8_t channel,
92+
uint8_t** buffer, uint32_t* buffer_length) {
8593
if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) {
8694
audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj);
8795
return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length);
@@ -90,7 +98,7 @@ bool audiosample_get_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t ch
9098
audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj);
9199
return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length);
92100
}
93-
return true;
101+
return GET_BUFFER_DONE;
94102
}
95103

96104
static void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel,
@@ -117,7 +125,6 @@ uint8_t find_free_audio_dma_channel(void) {
117125
return channel;
118126
}
119127

120-
audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT];
121128
void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer_length,
122129
uint8_t** output_buffer, uint32_t* output_buffer_length,
123130
uint8_t* output_spacing) {
@@ -163,15 +170,21 @@ void audio_dma_convert_signed(audio_dma_t* dma, uint8_t* buffer, uint32_t buffer
163170
void audio_dma_load_next_block(audio_dma_t* dma) {
164171
uint8_t* buffer;
165172
uint32_t buffer_length;
166-
bool last_buffer = audiosample_get_buffer(dma->sample, dma->single_channel, dma->audio_channel,
167-
&buffer, &buffer_length);
173+
audioio_get_buffer_result_t get_buffer_result =
174+
audiosample_get_buffer(dma->sample, dma->single_channel, dma->audio_channel,
175+
&buffer, &buffer_length);
168176

169177
DmacDescriptor* descriptor = dma->second_descriptor;
170178
if (dma->first_descriptor_free) {
171179
descriptor = dma_descriptor(dma->dma_channel);
172180
}
173181
dma->first_descriptor_free = !dma->first_descriptor_free;
174182

183+
if (get_buffer_result == GET_BUFFER_ERROR) {
184+
audio_dma_stop(dma);
185+
return;
186+
}
187+
175188
uint8_t* output_buffer;
176189
uint32_t output_buffer_length;
177190
uint8_t output_spacing;
@@ -180,7 +193,7 @@ void audio_dma_load_next_block(audio_dma_t* dma) {
180193

181194
descriptor->BTCNT.reg = output_buffer_length / dma->beat_size / output_spacing;
182195
descriptor->SRCADDR.reg = ((uint32_t) output_buffer) + output_buffer_length;
183-
if (last_buffer) {
196+
if (get_buffer_result == GET_BUFFER_DONE) {
184197
if (dma->loop) {
185198
audiosample_reset_buffer(dma->sample, dma->single_channel, dma->audio_channel);
186199
} else {
@@ -347,6 +360,7 @@ void audio_dma_init(audio_dma_t* dma) {
347360
void audio_dma_reset(void) {
348361
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
349362
audio_dma_state[i] = NULL;
363+
audio_dma_pending[i] = false;
350364
dma_disable_channel(i);
351365
dma_descriptor(i)->BTCTRL.bit.VALID = false;
352366
MP_STATE_PORT(playing_audio)[i] = NULL;
@@ -367,8 +381,12 @@ bool audio_dma_get_playing(audio_dma_t* dma) {
367381

368382
// WARN(tannewt): DO NOT print from here. Printing calls background tasks such as this and causes a
369383
// stack overflow.
384+
370385
void audio_dma_background(void) {
371386
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
387+
if (audio_dma_pending[i]) {
388+
continue;
389+
}
372390
audio_dma_t* dma = audio_dma_state[i];
373391
if (dma == NULL) {
374392
continue;
@@ -379,6 +397,10 @@ void audio_dma_background(void) {
379397
continue;
380398
}
381399

400+
// audio_dma_load_next_block() can call Python code, which can call audio_dma_background()
401+
// recursively at the next background processing time. So disallow recursive calls to here.
402+
audio_dma_pending[i] = true;
382403
audio_dma_load_next_block(dma);
404+
audio_dma_pending[i] = false;
383405
}
384406
}

shared-module/audioio/RawSample.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,18 @@ void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t* self,
6666
uint8_t channel) {
6767
}
6868

69-
bool audioio_rawsample_get_buffer(audioio_rawsample_obj_t* self,
70-
bool single_channel,
71-
uint8_t channel,
72-
uint8_t** buffer,
73-
uint32_t* buffer_length) {
69+
audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t* self,
70+
bool single_channel,
71+
uint8_t channel,
72+
uint8_t** buffer,
73+
uint32_t* buffer_length) {
7474
*buffer_length = self->len;
7575
if (single_channel) {
7676
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8);
7777
} else {
7878
*buffer = self->buffer;
7979
}
80-
return true;
80+
return GET_BUFFER_DONE;
8181
}
8282

8383
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t* self, bool single_channel,

shared-module/audioio/RawSample.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#include "py/obj.h"
3131

32+
#include "shared-module/audioio/__init__.h"
33+
3234
typedef struct {
3335
mp_obj_base_t base;
3436
uint8_t* buffer;
@@ -45,11 +47,11 @@ typedef struct {
4547
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t* self,
4648
bool single_channel,
4749
uint8_t channel);
48-
bool audioio_rawsample_get_buffer(audioio_rawsample_obj_t* self,
49-
bool single_channel,
50-
uint8_t channel,
51-
uint8_t** buffer,
52-
uint32_t* buffer_length); // length in bytes
50+
audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t* self,
51+
bool single_channel,
52+
uint8_t channel,
53+
uint8_t** buffer,
54+
uint32_t* buffer_length); // length in bytes
5355
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t* self, bool single_channel,
5456
bool* single_buffer, bool* samples_signed,
5557
uint32_t* max_buffer_length, uint8_t* spacing);

shared-module/audioio/WaveFile.c

Lines changed: 26 additions & 13 deletions
10000
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <stdint.h>
3030
#include <string.h>
3131

32+
#include "py/mperrno.h"
3233
#include "py/runtime.h"
3334

3435
#include "shared-module/audioio/WaveFile.h"
@@ -50,20 +51,26 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
5051
uint8_t chunk_header[16];
5152
f_rewind(&self->file->fp);
5253
UINT bytes_read;
53-
f_read(&self->file->fp, chunk_header, 16, &bytes_read);
54+
if (f_read(&self->file->fp, chunk_header, 16, &bytes_read) != FR_OK) {
55+
mp_raise_OSError(MP_EIO);
56+
}
5457
if (bytes_read != 16 ||
5558
memcmp(chunk_header, "RIFF", 4) != 0 ||
5659
memcmp(chunk_header + 8, "WAVEfmt ", 8) != 0) {
5760
mp_raise_ValueError("Invalid wave file");
5861
}
5962
uint32_t format_size;
60-
f_read(&self->file->fp, &format_size, 4, &bytes_read);
63+
if (f_read(&self->file->fp, &format_size, 4, &bytes_read) != FR_OK) {
64+
mp_raise_OSError(MP_EIO);
65+
}
6166
if (bytes_read != 4 ||
6267
format_size > sizeof(struct wave_format_chunk)) {
6368
mp_raise_ValueError("Invalid format chunk size");
6469
}
6570
struct wave_format_chunk format;
66-
f_read(&self->file->fp, &format, format_size, &bytes_read);
71+
if (f_read(&self->file->fp, &format, format_size, &bytes_read) != FR_OK) {
72+
mp_raise_OSError(MP_EIO);
73+
}
6774
if (bytes_read != format_size) {
6875
}
6976

@@ -83,14 +90,18 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
8390
// TODO(tannewt): Skip any extra chunks that occur before the data section.
8491

8592
uint8_t data_tag[4];
86-
f_read(&self->file->fp, &data_tag, 4, &bytes_read);
93+
if (f_read(&self->file->fp, &data_tag, 4, &bytes_read) != FR_OK) {
94+
mp_raise_OSError(MP_EIO);
95+
}
8796
if (bytes_read != 4 ||
8897
memcmp((uint8_t *) data_tag, "data", 4) != 0) {
8998
mp_raise_ValueError("Data chunk must follow fmt chunk");
9099
}
91100

92101
uint32_t data_length;
93-
f_read(&self->file->fp, &data_length, 4, &bytes_read);
102+
if (f_read(&self->file->fp, &data_length, 4, &bytes_read) != FR_OK) {
103+
mp_raise_OSError(MP_EIO);
104+
}
94105
if (bytes_read != 4) {
95106
mp_raise_ValueError("Invalid file");
96107
}
@@ -152,11 +163,11 @@ void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t* self,
152163
self->right_read_count = 0;
153164
}
154165

155-
bool audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
156-
bool single_channel,
157-
uint8_t channel,
158-
uint8_t** buffer,
159-
uint32_t* buffer_length) {
166+
audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
167+
bool single_channel,
168+
uint8_t channel,
169+
uint8_t** buffer,
170+
uint32_t* buffer_length) {
160171
if (!single_channel) {
161172
channel = 0;
162173
}
@@ -171,7 +182,7 @@ bool audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
171182
if (self->bytes_remaining == 0 && need_more_data) {
172183
*buffer = NULL;
173184
*buffer_length = 0;
174-
return true;
185+
return GET_BUFFER_DONE;
175186
}
176187

177188
if (need_more_data) {
@@ -185,7 +196,9 @@ bool audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
185196
} else {
186197
*buffer = self->buffer;
187198
}
188-
f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read);
199+
if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK) {
200+
return GET_BUFFER_ERROR;
201+
}
189202
*buffer_length = length_read;
190203
if (self->buffer_index % 2 == 1) {
191204
self->second_buffer_length = length_read;
@@ -213,7 +226,7 @@ bool audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
213226
*buffer = *buffer + self->bits_per_sample / 8;
214227
}
215228

216-
return self->bytes_remaining == 0;
229+
return self->bytes_remaining == 0 ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA;
217230
}
218231

219232
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t* self, bool single_channel,

shared-module/audioio/WaveFile.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#include "py/obj.h"
3131

32+
#include "shared-module/audioio/__init__.h"
33+
3234
typedef struct {
3335
mp_obj_base_t base;
3436
uint8_t* buffer;
@@ -56,11 +58,11 @@ typedef struct {
5658
void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t* self,
5759
bool single_channel,
5860
uint8_t channel);
59-
bool audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
60-
bool single_channel,
61-
uint8_t channel,
62-
uint8_t** buffer,
63-
uint32_t* buffer_length); // length in bytes
61+
audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t* self,
62+
bool single_channel,
63+
uint8_t channel,
64+
uint8_t** buffer,
65+
uint32_t* buffer_length); // length in bytes
6466
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t* self, bool single_channel,
6567
bool* single_buffer, bool* samples_signed,
6668
uint32_t* max_buffer_length, uint8_t* spacing);

0 commit comments

Comments
 (0)
0