-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RP2 PIO background read #9659
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this, I'm excited!
I did have some review comments & requested changes. I also didn't actually test the code. Any suggestion on something that would be useful to try/test if I don't have a TAC5xxx codec?
static void fill_buf_info_read(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_bytes) { | ||
if (obj != mp_const_none) { | ||
info->obj = obj; | ||
mp_get_buffer_raise(obj, &info->info, MP_BUFFER_WRITE); | ||
size_t stride = mp_binary_get_size('@', info->info.typecode, NULL); | ||
if (stride > 4) { | ||
mp_raise_ValueError(MP_ERROR_TEXT("Buffer elements must be 4 bytes long or less")); | ||
} | ||
if (*stride_in_bytes && stride != *stride_in_bytes) { | ||
mp_raise_ValueError(MP_ERROR_TEXT("Mismatched data size")); | ||
} | ||
*stride_in_bytes = stride; | ||
} else { | ||
memset(info, 0, sizeof(*info)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please combine the fill_buf_info_{read,write} routines? I notice you've added detection of mismatched stride between the "once" and "loop" variants, which should probably apply to write as well. I think you'd just have to add the access type parameter and pass MP_BUFFER_{READ,WRITE} in.
Or is there a reason the new checking you added should not also have been done for the background write case?
//| pending: int | ||
//| pending_write: int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document that the pending
property is a deprecated alias for pending_write
and will be removed in a future version of CircuitPython.
} | ||
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_pending_write_obj, rp2pio_statemachine_obj_get_pending_write); | ||
|
||
const mp_obj_property_t rp2pio_statemachine_pending_write_obj = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the MP_PROPERTY_GETTER macro here, even though it wasn't used in the code whose style you were emultaing elsewhere in this file. We should tidy away the direct uses of const mp_obj_property_t
that have not previously been done, like the other ones in this file.
@@ -1023,121 +1047,241 @@ uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) { | |||
return _current_program_offset[pio_index][sm]; | |||
} | |||
|
|||
bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once, const sm_buf_info *loop, uint8_t stride_in_bytes, bool swap) { | |||
bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once_write, const sm_buf_info *loop_write, uint8_t stride_in_bytes, bool swap) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't personally have changed the parameter and local variables names but this is OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to make it clearer that the parameters are buffers not flags, as loop
is used for instance in https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/audio_dma.c
int background_stride_in_bytes; | ||
bool dma_completed, byteswap; | ||
bool dma_completed_write, byteswap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm are two byteswap values (one for read, one for write) needed?
For testing with no codec, I'm getting together a loopback example similar to https://github.com/adafruit/Adafruit_CircuitPython_PIOASM/blob/main/examples/pioasm_i2s_codec.py that will send a |
I've added a loopback example at https://github.com/timchinowsky/tac5 which you should be able to run as is on a Feather RP2040 if you connect DOUT (D9) to DIN (D10). |
The last two commits add double buffering and a with open(filename, 'w') as f:
while True:
f.write(self.pcm.pio.last_read) With the double-buffering and The four-line sections starting with |
add double-buffering for background read and write
b5019a4
to
10dfea4
Compare
Background playback of 8-channel audio from SD card to a 4-codec TAC5212 setup now working! Details at https://github.com/timchinowsky/tac5. |
Hey @timchinowsky ! I've been loving this new feature and have recently implemented in a simple general purpose I2S library: https://github.com/relic-se/CircuitPython_I2SInOut. So far so good, but if you need any assistance with reviewing these updates further, let me know how I can help. |
@relic-se that's great, thanks for letting me know! |
I'm not certain exactly what your goals in the recent updates are, but rather than building bespoke audio DSP processes for the rp2pio module, it would likely be better to find a way to integrate it into the existing audio systems of CircuitPython using the audiosample API. That way the existing processing modules could be used with custom PIO systems (ie: Alternatively, a separate |
It's also possible to feed data from rp2pio into an |
Yes, totally. I was thinking when I started this that I would be leaning more on That said, I also like the idea of enabling I'm also planning to continue filling out the API for the TAC5212 codec. For instance, the part has built in biquad filters on both ADCs and DACs (up to 3 per channel) and optional loopback between ADC and DAC, so the part can be used to implement 6-stage biquad analog-in/analog out filtering without any microcontroller involvement at all. |
Okay, I see where you're coming from here. Multi-channel output is fairly niche, so I don't think it's at the forefront of development in those areas. Yet, I don't see why one could operate with multiple mono/stereo outputs simultaneously as you've described for the time being. As I've been playing around more with the API, I do think it's possible to connect an object like
Currently, the new I'd really like to see the new |
SGTM 🚀 |
This PR adds a
background_read
method torp2pio.StateMachine
to complement the existingbackground_write
.