esp-hal icon indicating copy to clipboard operation
esp-hal copied to clipboard

Add fractional divider support for RMT hal

Open Tnze opened this issue 1 year ago • 13 comments

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 📝

  • [x] I have updated existing examples or added new ones (if applicable).
  • [x] I have used cargo xtask fmt-packages command to ensure that all changed code is formatted correctly.
  • [x] My changes were added to the CHANGELOG.md in the proper section.
  • [x] I have added necessary changes to user code to the Migration Guide.
  • [x] 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

Tnze avatar Sep 09 '24 16:09 Tnze

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 avatar Sep 10 '24 04:09 Tnze

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

Tnze avatar Sep 10 '24 04:09 Tnze

Is there anything else that needs to be modified?🤔

Tnze avatar Sep 23 '24 08:09 Tnze

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

bjoernQ avatar Sep 24 '24 06:09 bjoernQ

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

Tnze avatar Sep 24 '24 06:09 Tnze

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

bjoernQ avatar Sep 24 '24 07:09 bjoernQ

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

Tnze avatar Sep 24 '24 07:09 Tnze

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

Tnze avatar Sep 24 '24 07:09 Tnze

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 avatar Sep 24 '24 07:09 bjoernQ

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

bjoernQ avatar Sep 24 '24 08:09 bjoernQ

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?

Tnze avatar Sep 25 '24 07:09 Tnze

Converting this to a draft for now, no rush here. If you'd like some help with wrapping this up please let us know and we can find somebody to do any remaining work.

jessebraham avatar Oct 07 '24 11:10 jessebraham

I fixed the burnt out diode. I got the same result as the previous @bjoernQ by oscilloscope. I spent some time, but I couldn't find the cause of the problem.

Tnze avatar Oct 10 '24 03:10 Tnze

Hi @Tnze are you planning on revisiting this anytime soon?

MabezDev avatar Jan 21 '25 17:01 MabezDev

Hi @Tnze are you planning on revisiting this anytime soon?

I can't find out why the registers setting doesn't work. Would be nice if someone can help. The parameters calculation seems right.

Tnze avatar Jan 21 '25 18:01 Tnze

Also noticed the ESP-IDF also doesn't implement fractional dividers. So no reference implementation here.

Tnze avatar Jan 21 '25 18:01 Tnze

Thank you for the PR, @Tnze. I'm going to close this now, I'm not sure why this isn't working, but without a reference implementation in esp-idf this might be hard to solve.

MabezDev avatar May 08 '25 14:05 MabezDev