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

Add fractional divider support for RMT hal #2127

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

Conversation

Tnze
Copy link

@Tnze Tnze commented Sep 9, 2024

Thank you for your contribution!

We appreciate the time and effort you've put into this pull request.
To help us review it efficiently, please ensure you've gone through the following checklist:

Submission Checklist 📝

  • I have updated existing examples or added new ones (if applicable).
  • I have used cargo xtask fmt-packages command to ensure that all changed code is formatted correctly.
  • My changes were added to the CHANGELOG.md in the proper section.
  • I have added necessary changes to user code to the Migration Guide.
  • My changes are in accordance to the esp-rs API guidelines

Extra:

Pull Request Details 📖

Description

The hardware support fractional divider, but the HAL doesn't use it. We can use it to achieve higher accuracy.

Testing

Describe how you tested your changes.

Didn't test yet

esp-hal/src/rmt.rs Outdated Show resolved Hide resolved
@Tnze
Copy link
Author

Tnze commented Sep 10, 2024

The solver from lcd_cam use Farey Sequence to find the closest fractional number.

Using Stern-Brocot Tree might be a better solution with O(log²V) complexity which V is the maximum limit of denominator.

@Tnze
Copy link
Author

Tnze commented Sep 10, 2024

Current implementation is tested on ESP32-H2 which successfully dividing 32MHz resulted in 152kHz.

@Tnze Tnze marked this pull request as ready for review September 11, 2024 15:42
@bugadani bugadani linked an issue Sep 11, 2024 that may be closed by this pull request
esp-hal/src/rmt.rs Outdated Show resolved Hide resolved
esp-hal/CHANGELOG.md Outdated Show resolved Hide resolved
esp-hal/src/rmt.rs Outdated Show resolved Hide resolved
esp-hal/src/rmt.rs Outdated Show resolved Hide resolved
esp-hal/src/rmt.rs Outdated Show resolved Hide resolved
esp-hal/src/rmt.rs Outdated Show resolved Hide resolved
@Tnze
Copy link
Author

Tnze commented Sep 23, 2024

Is there anything else that needs to be modified?🤔

@bjoernQ
Copy link
Contributor

bjoernQ commented Sep 24, 2024

Sorry, this takes so long - I think code looks good but personally I wasn't able to reproduce reasonable frequencies which might be a me issue (or my logic-analyzer's issue). Someone else will look into it

@Tnze
Copy link
Author

Tnze commented Sep 24, 2024

The code is tested on my ESP32-H2 board. Can you share your testing code?

@bjoernQ
Copy link
Contributor

bjoernQ commented Sep 24, 2024

IIRC I just modified https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/rmt_tx.rs to use a given frequency, use 1 for all lengths and use carrier-modulation. It showed frequency/2 for frequencies which don't require a fractional divider but for fractional-dividers the frequency was off in my case

@Tnze
Copy link
Author

Tnze commented Sep 24, 2024

Is that mean you are setting 1 tick for high and 1 tick for low, which causes the period to be 2 ticks?

@Tnze
Copy link
Author

Tnze commented Sep 24, 2024

You can left the code and tell me what output do you expect. I can test it tomorrow.

@bjoernQ
Copy link
Contributor

bjoernQ commented Sep 24, 2024

Is that mean you are setting 1 tick for high and 1 tick for low, which causes the period to be 2 ticks?

IIRC yes

@bjoernQ
Copy link
Contributor

bjoernQ commented Sep 24, 2024

With this code

#[entry]
fn main() -> ! {
    let peripherals = esp_hal::init(esp_hal::Config::default());

    let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

    let freq = 16.MHz();

    let rmt = Rmt::new(peripherals.RMT, freq).unwrap();

    let tx_config = TxChannelConfig {
        clk_divider: 1,
        ..TxChannelConfig::default()
    };

    let mut channel = rmt.channel0.configure(io.pins.gpio4, tx_config).unwrap();

    let delay = Delay::new();

    let mut data = [PulseCode {
        level1: true,
        length1: 10,
        level2: false,
        length2: 10,
    }; 20];

    data[data.len() - 1] = PulseCode::default();

    loop {
        let transaction = channel.transmit(&data);
        channel = transaction.wait().unwrap();
        delay.delay_millis(500);
    }
}

On H2 I get

image

With 8MHz

image

But with 10MHz

image

@Tnze
Copy link
Author

Tnze commented Sep 25, 2024

Based on the phenomenon you have tested, it is indeed true that fractional division is not working. Perhaps my previous testing was not thorough enough.

Diode on my H2 board is short circuited and smoking. I can't test it today.

I checked the output parameters of the solver, seems good. So maybe it's a register setting problem? I see there are unused #[cfg(pcr)] in the implementation. Maybe we should remove it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RMT] Feature request: fractional divider support
4 participants