Skip to content

Commit 33d6d55

Browse files
committed
the basics work
the sequence has to be a minimum length, 8 entries, but this problem is not detected. I don't THINK this is an insurmountable problem.
1 parent 33f5598 commit 33d6d55

File tree

6 files changed

+139
-8
lines changed

6 files changed

+139
-8
lines changed

ports/raspberrypi/audio_dma.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "shared-bindings/audiocore/RawSample.h"
3030
#include "shared-bindings/audiocore/WaveFile.h"
3131
#include "shared-bindings/microcontroller/__init__.h"
32+
#include "bindings/rp2pio/StateMachine.h"
3233
#include "supervisor/background_callback.h"
3334

3435
#include "py/mpstate.h"
@@ -324,7 +325,9 @@ void audio_dma_stop(audio_dma_t *dma) {
324325
channel_mask |= 1 << dma->channel[1];
325326
}
326327
dma_hw->inte0 &= ~channel_mask;
327-
irq_set_mask_enabled(1 << DMA_IRQ_0, false);
328+
if (!dma_hw->inte0) {
329+
irq_set_mask_enabled(1 << DMA_IRQ_0, false);
330+
}
328331

329332
// Run any remaining audio tasks because we remove ourselves from
330333
// playing_audio.
@@ -442,13 +445,20 @@ STATIC void dma_callback_fun(void *arg) {
442445
void isr_dma_0(void) {
443446
for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) {
444447
uint32_t mask = 1 << i;
445-
if ((dma_hw->intr & mask) != 0 && MP_STATE_PORT(playing_audio)[i] != NULL) {
448+
if ((dma_hw->intr & mask) == 0) {
449+
continue;
450+
}
451+
if (MP_STATE_PORT(playing_audio)[i] != NULL) {
446452
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i];
447453
// Record all channels whose DMA has completed; they need loading.
448454
dma->channels_to_load_mask |= mask;
449455
background_callback_add(&dma->callback, dma_callback_fun, (void *)dma);
450-
dma_hw->ints0 = mask;
451456
}
457+
if (MP_STATE_PORT(continuous_pio)[i] != NULL) {
458+
rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(continuous_pio)[i];
459+
rp2pio_statemachine_dma_complete(pio, i);
460+
}
461+
dma_hw->ints0 = mask;
452462
}
453463
}
454464

ports/raspberrypi/bindings/rp2pio/StateMachine.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ STATIC mp_obj_t rp2pio_statemachine_start_continuous_write(size_t n_args, const
480480
mp_raise_ValueError(translate("Buffer elements must be 4 bytes long or less"));
481481
}
482482

483-
ok = common_hal_rp2pio_statemachine_start_continuous_write(self, ((uint8_t *)bufinfo.buf) + start, length, stride_in_bytes);
483+
ok = common_hal_rp2pio_statemachine_start_continuous_write(self, args[ARG_buffer].u_obj, ((uint8_t *)bufinfo.buf) + start, length, stride_in_bytes);
484484
}
485485
if (!ok) {
486486
mp_raise_OSError(MP_EIO);

ports/raspberrypi/bindings/rp2pio/StateMachine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void common_hal_rp2pio_statemachine_run(rp2pio_statemachine_obj_t *self, const u
6565

6666
// Writes out the given data.
6767
bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes);
68-
bool common_hal_rp2pio_statemachine_start_continuous_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes);
68+
bool common_hal_rp2pio_statemachine_start_continuous_write(rp2pio_statemachine_obj_t *self, mp_obj_t buf_obj, const uint8_t *data, size_t len, uint8_t stride_in_bytes);
6969
bool common_hal_rp2pio_statemachine_end_continuous_write(rp2pio_statemachine_obj_t *self);
7070
bool common_hal_rp2pio_statemachine_readinto(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t stride_in_bytes);
7171
bool common_hal_rp2pio_statemachine_write_readinto(rp2pio_statemachine_obj_t *self,

ports/raspberrypi/common-hal/rp2pio/StateMachine.c

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#include "py/objproperty.h"
4343
#include "py/runtime.h"
4444

45+
#define NO_DMA_CHANNEL (-1)
46+
4547
// Count how many state machines are using each pin.
4648
STATIC uint8_t _pin_reference_count[TOTAL_GPIO_COUNT];
4749
STATIC uint32_t _current_program_id[NUM_PIOS][NUM_PIO_STATE_MACHINES];
@@ -330,6 +332,9 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
330332
sm_config_set_fifo_join(&c, join);
331333
self->sm_config = c;
332334

335+
// no DMA allocated
336+
self->dma_channel[0] = self->dma_channel[1] = NO_DMA_CHANNEL;
337+
333338
pio_sm_init(self->pio, self->state_machine, program_offset, &c);
334339
common_hal_rp2pio_statemachine_run(self, init, init_len);
335340

@@ -581,6 +586,7 @@ void common_hal_rp2pio_statemachine_set_frequency(rp2pio_statemachine_obj_t *sel
581586

582587
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins) {
583588
common_hal_rp2pio_statemachine_stop(self);
589+
(void)common_hal_rp2pio_statemachine_end_continuous_write(self);
584590

585591
uint8_t sm = self->state_machine;
586592
uint8_t pio_index = pio_get_index(self->pio);
@@ -849,10 +855,114 @@ uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) {
849855
return _current_program_offset[pio_index][sm];
850856
}
851857

852-
bool common_hal_rp2pio_statemachine_start_continuous_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes) {
853-
return false;
858+
#define HERE(fmt, ...) (mp_printf(&mp_plat_print, "%s: %d: " fmt "\n", __FILE__, __LINE__,##__VA_ARGS__))
859+
860+
bool common_hal_rp2pio_statemachine_start_continuous_write(rp2pio_statemachine_obj_t *self, mp_obj_t buf_obj, const uint8_t *data, size_t len, uint8_t stride_in_bytes) {
861+
if (self->dma_channel[0] != NO_DMA_CHANNEL && stride_in_bytes == self->continuous_stride_in_bytes) {
862+
HERE("updating channel pending=%d\n", self->pending_set_data);
863+
while (self->pending_set_data) {
864+
RUN_BACKGROUND_TASKS;
865+
if (self->user_interruptible && mp_hal_is_interrupted()) {
866+
(void)common_hal_rp2pio_statemachine_end_continuous_write(self);
867+
return false;
868+
}
869+
}
870+
871+
common_hal_mcu_disable_interrupts();
872+
self->next_buffer = data;
873+
self->next_size = len / stride_in_bytes;
874+
self->pending_set_data = true;
875+
common_hal_mcu_enable_interrupts();
876+
877+
// need to keep a reference alive to the buffer, lest the GC collect it while its lone remaining pointer is in the DMA peripheral register
878+
self->buf_objs[++self->buf_obj_idx % 2] = buf_obj;
879+
return true;
880+
}
881+
882+
common_hal_rp2pio_statemachine_end_continuous_write(self);
883+
884+
for (int i = 0; i < 2; i++) {
885+
HERE("allocating channel %d", i);
886+
if (self->dma_channel[i] == -1) {
887+
self->dma_channel[i] = dma_claim_unused_channel(false);
888+
HERE("got channel %d", self->dma_channel[i]);
889+
MP_STATE_PORT(continuous_pio)[self->dma_channel[i]] = self;
890+
}
891+
if (self->dma_channel[i] == -1) {
892+
HERE("allocating channel %d failed", i);
893+
(void)common_hal_rp2pio_statemachine_end_continuous_write(self);
894+
return false;
895+
}
896+
}
897+
898+
volatile uint8_t *tx_destination = (volatile uint8_t *)&self->pio->txf[self->state_machine];
899+
900+
self->tx_dreq = pio_get_dreq(self->pio, self->state_machine, true);
901+
902+
dma_channel_config c;
903+
904+
self->pending_set_data = false;
905+
self->continuous_stride_in_bytes = stride_in_bytes;
906+
self->buf_objs[0] = buf_obj;
907+
self->buf_objs[1] = NULL;
908+
909+
self->next_buffer = data;
910+
self->next_size = len / stride_in_bytes;
911+
912+
c = dma_channel_get_default_config(self->dma_channel[0]);
913+
channel_config_set_transfer_data_size(&c, _stride_to_dma_size(stride_in_bytes));
914+
channel_config_set_dreq(&c, self->tx_dreq);
915+
channel_config_set_read_increment(&c, true);
916+
channel_config_set_write_increment(&c, false);
917+
// channel_config_set_chain_to(&c, self->dma_channel[1]);
918+
dma_channel_configure(self->dma_channel[0], &c,
919+
tx_destination,
920+
data,
921+
len / stride_in_bytes,
922+
false);
923+
924+
#if 0
925+
channel_config_set_chain_to(&c, self->dma_channel[0]);
926+
dma_channel_configure(self->dma_channel[1], &c,
927+
tx_destination,
928+
data,
929+
len / stride_in_bytes,
930+
false);
931+
#endif
932+
933+
dma_hw->inte0 |= (1 << self->dma_channel[0]) | (1 << self->dma_channel[1]);
934+
irq_set_mask_enabled(1 << DMA_IRQ_0, true);
935+
936+
HERE("OK let's go");
937+
dma_start_channel_mask(1u << self->dma_channel[0]);
938+
return true;
939+
}
940+
941+
void rp2pio_statemachine_dma_complete(rp2pio_statemachine_obj_t *self, int channel) {
942+
HERE("dma complete[%d] pending set data=%d busy=%d,%d %d@%p", channel, self->pending_set_data, dma_channel_is_busy(self->dma_channel[0]), dma_channel_is_busy(self->dma_channel[1]),
943+
self->next_size, self->next_buffer);
944+
945+
dma_channel_set_read_addr(channel, self->next_buffer, false);
946+
dma_channel_set_trans_count(channel, self->next_size, true);
947+
948+
self->pending_set_data = false;
854949
}
855950

856951
bool common_hal_rp2pio_statemachine_end_continuous_write(rp2pio_statemachine_obj_t *self) {
857-
return false;
952+
for (int i = 0; i < 2; i++) {
953+
if (self->dma_channel[i] == NO_DMA_CHANNEL) {
954+
continue;
955+
}
956+
int channel = self->dma_channel[i];
957+
uint32_t channel_mask = 1u << channel;
958+
dma_hw->inte0 &= ~channel_mask;
959+
if (!dma_hw->inte0) {
960+
irq_set_mask_enabled(1 << DMA_IRQ_0, false);
961+
}
962+
MP_STATE_PORT(continuous_pio)[channel] = NULL;
963+
dma_channel_abort(channel);
964+
dma_channel_unclaim(channel);
965+
self->dma_channel[i] = NO_DMA_CHANNEL;
966+
}
967+
return true;
858968
}

ports/raspberrypi/common-hal/rp2pio/StateMachine.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ typedef struct {
5454
bool in_shift_right;
5555
bool user_interruptible;
5656
uint8_t offset;
57+
58+
// dma-related items
59+
uint8_t buf_obj_idx;
60+
const uint8_t *next_buffer;
61+
size_t next_size;
62+
int dma_channel[2];
63+
mp_obj_t buf_objs[2];
64+
int continuous_stride_in_bytes;
65+
volatile int pending_set_data;
5766
} rp2pio_statemachine_obj_t;
5867

5968
void reset_rp2pio_statemachine(void);
@@ -82,6 +91,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
8291
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self);
8392

8493
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins);
94+
void rp2pio_statemachine_dma_complete(rp2pio_statemachine_obj_t *self, int channel);
8595

8696
extern const mp_obj_type_t rp2pio_statemachine_type;
8797

ports/raspberrypi/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define MICROPY_PORT_ROOT_POINTERS \
4747
mp_obj_t counting[NUM_PWM_SLICES]; \
4848
mp_obj_t playing_audio[NUM_DMA_CHANNELS]; \
49+
mp_obj_t continuous_pio[NUM_DMA_CHANNELS]; \
4950
CIRCUITPY_COMMON_ROOT_POINTERS;
5051

5152
#endif // __INCLUDED_MPCONFIGPORT_H

0 commit comments

Comments
 (0)