Skip to content
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

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

aabadie
Copy link
Contributor

@aabadie aabadie commented Mar 2, 2021

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

@aabadie aabadie added Type: new feature The issue requests / The PR implemements a new feature for RIOT Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports labels Mar 2, 2021
@benpicco benpicco requested a review from chrysn March 2, 2021 13:40
Copy link
Contributor

@benpicco benpicco left a 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#ifdef CPU_MODEL_NRF52840XXAA
#ifdef PDM_PDMCLKCTRL_FREQ_1280K

@chrysn
Copy link
Member

chrysn commented Mar 2, 2021

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:

  • Sony used it in its SACDs. They claim superior quality, but I haven't found anyone who could hear the difference (and their SACDs contain more data than a regular CD).
  • It's super cheap to get from a digital microphone, as is on the thingy:52.

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).

@aabadie
Copy link
Contributor Author

aabadie commented Mar 2, 2021

It's super cheap to get from a digital microphone, as is on the thingy:52.

Good to know that there's a microphone on the thingy:52, at least someone can test this PR (and eventually find bugs)

@chrysn
Copy link
Member

chrysn commented Mar 23, 2021

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?

@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 22, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@stale
Copy link

stale bot commented Mar 2, 2022

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.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Mar 2, 2022
@aabadie
Copy link
Contributor Author

aabadie commented Mar 23, 2022

Needs rebase. @chrysn are still interested by this one ? (and do you have the hardware to test it ?)

@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Mar 23, 2022
@stale
Copy link

stale bot commented Nov 2, 2022

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.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Nov 2, 2022
Copy link

@Kcebnelloh Kcebnelloh left a 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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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)];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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)]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

@stale stale bot removed State: stale State: The issue / PR has no activity for >185 days labels Dec 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants