Add fractional divider support for RMT hal
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-packagescommand to ensure that all changed code is formatted correctly. - [x] My changes were added to the
CHANGELOG.mdin 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:
- [ ] I have read the CONTRIBUTING.md guide and followed its instructions.
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
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.
Current implementation is tested on ESP32-H2 which successfully dividing 32MHz resulted in 152kHz.
Is there anything else that needs to be modified?🤔
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
The code is tested on my ESP32-H2 board. Can you share your testing code?
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
Is that mean you are setting 1 tick for high and 1 tick for low, which causes the period to be 2 ticks?
You can left the code and tell me what output do you expect. I can test it tomorrow.
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
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
With 8MHz
But with 10MHz
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?
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.
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.
Hi @Tnze are you planning on revisiting this anytime soon?
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.
Also noticed the ESP-IDF also doesn't implement fractional dividers. So no reference implementation here.
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.