Conversation
The commutation_intervals array in TimingState was never populated by the firmware ISR, only by the harness's manual copy. This meant e_com_time, e_rpm, and average_interval were always zero in production. Fix: move intervals array into Commutation struct (ISR-owned), add record_interval() called at each step advance (matching C main.c:882), and compute e_com_time in the ISR's sync section. Main loop now reads e_com_time from SharedComm instead of computing it from a local array. Remove the harness's manual intervals copy (no longer needed) and the now-empty commutation_intervals field from TimingState.
There was a problem hiding this comment.
Sorry @kaidokert, you have reached your weekly rate limit of 1500000 diff characters.
Please try again later or upgrade to continue using Sourcery
📝 WalkthroughWalkthroughPer-step commutation interval recording was moved into the ISR/Commutation; ISR now publishes computed Changes
Sequence Diagram(s)sequenceDiagram
participant ISR
participant Commutation
participant SharedState
participant MainLoop
ISR->>Commutation: record_interval(step_interval)
Commutation-->>ISR: store intervals[step-1]
ISR->>Commutation: compute sum/avg -> e_com_time_raw
Commutation-->>ISR: e_com_time_raw
ISR->>SharedState: set_e_com_time((sum + 4) >> 1)
MainLoop->>SharedState: read e_com_time()
SharedState-->>MainLoop: e_com_time
MainLoop->>MainLoop: update timing (average, eRPM, duty)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 2/5 reviews remaining, refill in 28 minutes and 30 seconds. Comment |
❌ 2 Tests Failed:
View the full list of 2 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
rm32/src/commutation.rs (1)
25-30: ⚡ Quick winAdd direct unit tests for
record_interval()index mapping.This is a new correctness-critical helper; add focused tests for forward/reverse and wrap cases to prevent off-by-one regressions.
Proposed tests
#[cfg(test)] mod tests { use super::*; + + #[test] + fn record_interval_writes_current_step_slot() { + let mut c = Commutation::new(); + c.step = 3; + c.record_interval(1234); + assert_eq!(c.intervals[2], 1234); + } + + #[test] + fn record_interval_after_forward_wrap_writes_step1_slot() { + let mut c = Commutation::new(); + c.step = 6; + c.advance(); // -> step 1 + c.record_interval(777); + assert_eq!(c.intervals[0], 777); + } + + #[test] + fn record_interval_after_reverse_wrap_writes_step6_slot() { + let mut c = Commutation::new(); + c.forward = false; + c.step = 1; + c.advance(); // -> step 6 + c.record_interval(888); + assert_eq!(c.intervals[5], 888); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rm32/src/commutation.rs` around lines 25 - 30, Add focused unit tests for record_interval to verify the index mapping uses (step - 1) as usize: create tests in commutation.rs that directly manipulate a Commutation instance's step and intervals, call record_interval(value) and assert intervals[(step - 1) as usize] == value. Include at least: a forward case (e.g., step = 1 updates intervals[0]), a mid-range case (e.g., step = 3 updates intervals[2]), a reverse-like case by setting step to a previous value and verifying the same mapping, and a wrap case where step = 0 should update the last index of intervals (verify the last slot was written). Reference the record_interval method and the Commutation fields step and intervals when locating code to test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@rm32/src/commutation.rs`:
- Around line 25-30: Add focused unit tests for record_interval to verify the
index mapping uses (step - 1) as usize: create tests in commutation.rs that
directly manipulate a Commutation instance's step and intervals, call
record_interval(value) and assert intervals[(step - 1) as usize] == value.
Include at least: a forward case (e.g., step = 1 updates intervals[0]), a
mid-range case (e.g., step = 3 updates intervals[2]), a reverse-like case by
setting step to a previous value and verifying the same mapping, and a wrap case
where step = 0 should update the last index of intervals (verify the last slot
was written). Reference the record_interval method and the Commutation fields
step and intervals when locating code to test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 927a09ad-ee40-435c-8c21-223c3d4d5cbf
📒 Files selected for processing (5)
rm32/src/bin/harness.rsrm32/src/commutation.rsrm32/src/control/isr_logic.rsrm32/src/control/state.rsrm32/src/main_state.rs
💤 Files with no reviewable changes (2)
- rm32/src/control/state.rs
- rm32/src/bin/harness.rs
There was a problem hiding this comment.
Code Review
This pull request refactors the commutation interval tracking by moving the storage logic from the main loop into the Commutation struct and updating it directly within the ISR. The review identified an indexing issue where intervals were being recorded for the incorrect step due to the order of operations in the ISR, and suggested optimizing the e_com_time calculation to avoid redundant processing in the high-frequency control loop.
Verifies e_com_time > 100 after motor commutation steps, catching the bug where the intervals array was never populated by the ISR (would have produced e_com_time=2 from empty array rounding bias).
Computing the 6-interval sum on every 20kHz ISR tick was wasteful — it only changes when a commutation step advances. Move the computation into record_interval() which returns the updated e_com_time, and publish to SharedComm at each of the 3 advance() call sites. record_interval after advance matches C ordering where step is incremented before commutation_intervals[step-1] is written.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
rm32/src/control/isr_logic.rs (1)
60-63: ⚡ Quick winConsider extracting a helper for
record_interval+set_e_com_time.The same 3-line sequence is duplicated in three places; a tiny helper reduces future drift risk when one advance path changes.
♻️ Suggested refactor
+fn publish_e_com_time<S: SharedComm>(commutation: &mut Commutation, shared: &S) { + let e_com = commutation.record_interval(shared.commutation_interval() as u16); + shared.set_e_com_time(e_com); +} ... - let e_com = ctx - .commutation - .record_interval(ctx.shared.commutation_interval() as u16); - ctx.shared.set_e_com_time(e_com); + publish_e_com_time(&mut ctx.commutation, ctx.shared); ... - let e_com = ctx - .commutation - .record_interval(ctx.shared.commutation_interval() as u16); - ctx.shared.set_e_com_time(e_com); + publish_e_com_time(&mut ctx.commutation, ctx.shared); ... - let e_com = commutation.record_interval(shared.commutation_interval() as u16); - shared.set_e_com_time(e_com); + publish_e_com_time(commutation, shared);Also applies to: 203-207, 270-271
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rm32/src/control/isr_logic.rs` around lines 60 - 63, Extract the duplicated three-line sequence into a small helper (e.g., a method named update_e_com_time or set_e_com_from_commutation) that captures the pattern: call commutation.record_interval(ctx.shared.commutation_interval() as u16) and then ctx.shared.set_e_com_time(...) with the result; implement the helper to accept &mut self or &mut ctx as appropriate and replace each duplicated occurrence (the blocks currently calling commutation.record_interval and ctx.shared.set_e_com_time) with a single call to that helper so all paths use the same logic.rm32/src/commutation.rs (1)
25-34: ⚡ Quick winAdd direct unit tests for
record_interval()behavior.This new method is core to telemetry correctness; add focused tests for slot mapping (
step - 1) and expected computed value from a known 6-interval set.✅ Example test additions
#[cfg(test)] mod tests { use super::*; + #[test] + fn record_interval_writes_step_slot() { + let mut c = Commutation::new(); + c.step = 3; + c.record_interval(120); + assert_eq!(c.intervals[2], 120); + } + + #[test] + fn record_interval_recomputes_e_com_time_from_all_slots() { + let mut c = Commutation::new(); + c.intervals = [100, 100, 100, 100, 100, 100]; + c.step = 1; + let e = c.record_interval(100); + assert_eq!(e, ((600u32 + 4) >> 1) as i32); + }Also applies to: 64-165
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rm32/src/commutation.rs` around lines 25 - 34, Add focused unit tests for the record_interval method: create a Commutation instance, set its step to a known value (e.g., 1..6), call record_interval(commutation_interval) and assert that intervals[(step - 1) as usize] was updated with the passed u16 value and that the returned e_com_time equals the expected computation for a known 6‑interval set (compute expected as ((sum_of_intervals + 4) >> 1) cast to i32). Include at least one test that fills multiple slots (e.g., populate all six intervals with known values, call record_interval for one slot, and verify both the slot mapping and the returned aggregated value) and ensure step is set appropriately before each call to record_interval.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@rm32/src/commutation.rs`:
- Around line 25-34: Add focused unit tests for the record_interval method:
create a Commutation instance, set its step to a known value (e.g., 1..6), call
record_interval(commutation_interval) and assert that intervals[(step - 1) as
usize] was updated with the passed u16 value and that the returned e_com_time
equals the expected computation for a known 6‑interval set (compute expected as
((sum_of_intervals + 4) >> 1) cast to i32). Include at least one test that fills
multiple slots (e.g., populate all six intervals with known values, call
record_interval for one slot, and verify both the slot mapping and the returned
aggregated value) and ensure step is set appropriately before each call to
record_interval.
In `@rm32/src/control/isr_logic.rs`:
- Around line 60-63: Extract the duplicated three-line sequence into a small
helper (e.g., a method named update_e_com_time or set_e_com_from_commutation)
that captures the pattern: call
commutation.record_interval(ctx.shared.commutation_interval() as u16) and then
ctx.shared.set_e_com_time(...) with the result; implement the helper to accept
&mut self or &mut ctx as appropriate and replace each duplicated occurrence (the
blocks currently calling commutation.record_interval and
ctx.shared.set_e_com_time) with a single call to that helper so all paths use
the same logic.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e950e7a1-8ffa-4c86-b03c-80c1396eddbe
📒 Files selected for processing (2)
rm32/src/commutation.rsrm32/src/control/isr_logic.rs
Summary
commutation_intervalsarray was never populated by the firmware ISR, causinge_com_time,e_rpm, andaverage_intervalto always be zero in productionCommutationstruct (ISR-owned), addrecord_interval()at each step advance matching Cmain.c:882e_com_timeto SharedComm; main loop reads instead of computing from stale local arraycommutation_intervalsfromTimingState(no longer needed in main loop)Test plan
Summary by CodeRabbit