-
Notifications
You must be signed in to change notification settings - Fork 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
[RFC] periph/pdm: propose API and add nrf52 implementation #16125
base: master
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.
What is PDM? Is it similar to PWM?
If it's intended for sound, it could also implement the DAC DDS API.
/* Configure sampling rate */ | ||
switch (rate) { | ||
case PDM_SAMPLE_RATE_16KHZ: | ||
#ifdef CPU_MODEL_NRF52840XXAA |
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.
#ifdef CPU_MODEL_NRF52840XXAA | |
#ifdef PDM_PDMCLKCTRL_FREQ_1280K |
PDM is not so much comparable to PWM but more to PCM. Think of it as PCM with a very high sampling rate but a sampling resolution of 1 bit. As a result, it can represent much higher frequencies (up to half the bit rate) at a low dynamic range (down to 1 bit), and can represent lower frequencies with a much higher dynamic range. There's two things where it is used:
The DSS API doesn't realy work with it, as it assumes a sampling resolution which is not there. (It's similar in general, though, but has different parameters. There's a sampling rate, but no sampling depth). |
Good to know that there's a microphone on the thingy:52, at least someone can test this PR (and eventually find bugs) |
Like on the thingy52 board, the microbit-v2 also has such a microphone built in. As for PDM and PCM, this API looks a bit mixed to me: The pin is addressed as a PDM pin, but the hardware peripheral eventually provides PCM data, if I understand correctly. Is this a kind of peripheral that's present on anything else except the nrf5x? |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
Needs rebase. @chrysn are still interested by this one ? (and do you have the hardware to test it ?) |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
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.
Also adding some information about stereo mode would be good. For example letting the user know that the first sample in each buffer is always the Left Channel.
I'm currently working on fully supporting the feather-nrf52-sense board and for this I would like this api to be merged, so i could help with the completion of the code, maybe writing a stereo example and testing it etc.
Please let me know what you think about this.
(PDM_INTEN_STOPPED_Enabled << PDM_INTEN_STOPPED_Pos)); | ||
|
||
/* Configure internal RAM buffer size, divide by 2 for stereo mode */ | ||
NRF_PDM->SAMPLE.MAXCNT = (PDM_BUF_SIZE >> mode); |
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.
NRF_PDM->SAMPLE.MAXCNT = (PDM_BUF_SIZE >> mode); | |
NRF_PDM->SAMPLE.MAXCNT = (PDM_BUF_SIZE); |
According to the datasheet and also logically the SAMPLE.MAXCNT shouldn't change if we run the pdm in stereo mode, because we still want to fill the double buffer _pdm_buff and not only half of it.
The only thing that changes is that in stereo mode "the buffer in RAM can contain half the stereo sampling time as compared to the mono sampling time".
if (NRF_PDM->EVENTS_STARTED == 1) { | ||
NRF_PDM->EVENTS_STARTED = 0; | ||
uint8_t next_buf_pos = (_pdm_current_buf + 1) & 0x1; | ||
NRF_PDM->SAMPLE.PTR = (uint32_t)&_pdm_buf[next_buf_pos * (PDM_BUF_SIZE >> 1)]; |
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.
NRF_PDM->SAMPLE.PTR = (uint32_t)&_pdm_buf[next_buf_pos * (PDM_BUF_SIZE >> 1)]; | |
NRF_PDM->SAMPLE.PTR = (uint32_t)&_pdm_buf[next_buf_pos * (PDM_BUF_SIZE)]; |
Here the buffer shouldn't be divided by 2 because the _pdm_buf is PDM_BUF_SIZE * 2. So dividing PDM_BUF_SIZE here would result in us only looping one quarter of the whole buffer.
NRF_PDM->EVENTS_END = 0; | ||
|
||
/* Process received samples frame */ | ||
isr_ctx.cb(isr_ctx.arg, &_pdm_buf[_pdm_current_buf * (PDM_BUF_SIZE >> 1)]); |
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.
isr_ctx.cb(isr_ctx.arg, &_pdm_buf[_pdm_current_buf * (PDM_BUF_SIZE >> 1)]); | |
isr_ctx.cb(isr_ctx.arg, &_pdm_buf[_pdm_current_buf * (PDM_BUF_SIZE)]); |
Similarly to the change on line 148 dividing the PDM_BUF_SIZE here would only return one quarter of the double buffer _pdm_buff
Contribution description
This PR proposes an API for the PDM peripheral available at least in nRF52 CPUs. An implementation is proposed for nRF and there's a configuration for the adafruit-clue board.
I could never really convert the "sound" to a hearable signal so I'm wondering if it works correctly. The values printed seems correct though (higher when make noise, lower otherwise) but I have no ground truth.
I'm also wondering if this could fit in the I2S API proposed by @bergzand in #15131, and thus there's no need for PDM API of this PR.
Testing procedure
Run
tests/periph_pdm
on adafruit-clue.Issues/PRs references
None