Skip to content

Commit 4406aed

Browse files
authored
Fix issue with rp2xxxx pwm (#542)
Co-authored-by: curuvar <[email protected]>
1 parent 0796a23 commit 4406aed

File tree

1 file changed

+82
-4
lines changed
  • port/raspberrypi/rp2xxx/src/hal

1 file changed

+82
-4
lines changed

port/raspberrypi/rp2xxx/src/hal/pwm.zig

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
const std = @import("std");
22
const microzig = @import("microzig");
33
const PWM = microzig.chip.peripherals.PWM;
4+
const pins = microzig.hal.pins;
5+
6+
const compatibility = @import("compatibility.zig");
7+
const has_rp2350b = compatibility.has_rp2350b;
48

59
const log = std.log.scoped(.pwm);
610

711
pub const Config = struct {};
812

913
fn get_regs(slice: u32) *volatile Regs {
10-
@import("std").debug.assert(slice < 8);
14+
@import("std").debug.assert(slice < if (has_rp2350b) 12 else 8);
1115
const PwmType = microzig.chip.types.peripherals.PWM;
1216
const reg_diff = comptime @offsetOf(PwmType, "CH1_CSR") - @offsetOf(PwmType, "CH0_CSR");
1317
return @as(*volatile Regs, @ptrFromInt(@intFromPtr(PWM) + reg_diff * slice));
@@ -18,37 +22,73 @@ pub const Channel = enum(u1) { a, b };
1822
pub const Slice = enum(u32) {
1923
_,
2024

25+
/// Set the wrap value for the slice. This is the number of pwm clock
26+
/// cycles that the slice will count to before wrapping.
27+
///
28+
/// Parameters:
29+
/// wrap - the wrap value
2130
pub fn set_wrap(self: Slice, wrap: u16) void {
2231
set_slice_wrap(@intFromEnum(self), wrap);
2332
}
2433

34+
/// Enable the slice.
2535
pub fn enable(self: Slice) void {
2636
get_regs(@intFromEnum(self)).csr.modify(.{ .EN = 1 });
2737
}
2838

39+
/// Disable the slice
2940
pub fn disable(self: Slice) void {
3041
get_regs(@intFromEnum(self)).csr.modify(.{ .EN = 0 });
3142
}
3243

44+
/// Set the slice to phase correct mode.
45+
///
46+
/// Parameters:
47+
/// phase_correct - true to enable phase correct mode, false to disable it
3348
pub fn set_phase_correct(self: Slice, phase_correct: bool) void {
3449
set_slice_phase_correct(@intFromEnum(self), phase_correct);
3550
}
3651

52+
/// Set the slice to a clock divider mode.
53+
///
54+
/// Parameters:
55+
/// integer - the integer part of the clock divider
56+
/// fraction - the fractional part of the clock divider
3757
pub fn set_clk_div(self: Slice, integer: u8, fraction: u4) void {
3858
set_slice_clk_div(@intFromEnum(self), integer, fraction);
3959
}
4060
};
4161

42-
// An instance of Pwm corresponds to one of the 16 total channels
43-
// (There are eight slices and each has two channels)
62+
// An instance of Pwm corresponds to one of the channels
63+
//
64+
// There are eight pwm instances on RP2040 and RP2350A and
65+
// twelve on RP2350B. Each pwm instance has two channels
66+
// (a and b).
4467
pub const Pwm = struct {
4568
slice_number: u32,
4669
channel: Channel,
4770

71+
/// Set the level of the channel. This is the number of pwm clock
72+
/// cycles that the channel will be high.
73+
///
74+
/// The duty cycle of the channel is the ratio of this `level`
75+
/// to the the channel's `wrap` value.
76+
///
77+
/// Parameters:
78+
/// level - the level to set
4879
pub fn set_level(self: Pwm, level: u16) void {
4980
set_channel_level(self.slice_number, self.channel, level);
5081
}
5182

83+
/// Set the channel to be inverted
84+
///
85+
/// Parameters:
86+
/// inverted - true to invert the channel, false to disable inversion
87+
pub fn set_inverted(self: Pwm, inverted: bool) void {
88+
set_channel_inversion(self.slice_number, self.channel, inverted);
89+
}
90+
91+
/// Get the slice that this pwm instance is on.
5292
pub fn slice(self: Pwm) Slice {
5393
return @enumFromInt(self.slice_number);
5494
}
@@ -69,13 +109,24 @@ const Regs = extern struct {
69109
top: @TypeOf(PWM.CH0_TOP),
70110
};
71111

112+
/// Set the slice to phase correct mode.
113+
///
114+
/// Parameters:
115+
/// slice - the slice to set
116+
/// phase_correct - true to enable phase correct mode, false to disable it
72117
pub fn set_slice_phase_correct(slice: u32, phase_correct: bool) void {
73118
log.debug("PWM{} set phase correct: {}", .{ slice, phase_correct });
74119
get_regs(slice).csr.modify(.{
75120
.PH_CORRECT = @intFromBool(phase_correct),
76121
});
77122
}
78123

124+
/// Set the slice to a clock divider mode.
125+
///
126+
/// Parameters:
127+
/// slice - the slice to set
128+
/// integer - the integer part of the clock divider
129+
/// fraction - the fractional part of the clock divider
79130
pub fn set_slice_clk_div(slice: u32, integer: u8, fraction: u4) void {
80131
log.debug("PWM{} set clk div: {}.{}", .{ slice, integer, fraction });
81132
get_regs(slice).div.modify(.{
@@ -84,13 +135,24 @@ pub fn set_slice_clk_div(slice: u32, integer: u8, fraction: u4) void {
84135
});
85136
}
86137

138+
/// Set the slice to a clock divider mode.
139+
///
140+
/// Parameters:
141+
/// slice - the slice to set
142+
/// mode - the clock divider mode
87143
pub fn set_slice_clk_div_mode(slice: u32, mode: ClkDivMode) void {
88144
log.debug("PWM{} set clk div mode: {}", .{ slice, mode });
89145
get_regs(slice).csr.modify(.{
90146
.DIVMODE = @intFromEnum(mode),
91147
});
92148
}
93149

150+
/// Set the channel to invert its output.
151+
///
152+
/// Parameters:
153+
/// slice - the slice to set
154+
/// channel - the channel to set
155+
/// invert - true to invert the channel's output, false to disable inversion
94156
pub fn set_channel_inversion(
95157
slice: u32,
96158
channel: Channel,
@@ -100,17 +162,33 @@ pub fn set_channel_inversion(
100162
.a => get_regs(slice).csr.modify(.{
101163
.A_INV = @intFromBool(invert),
102164
}),
103-
.b => get_regs(slice).csr.modifi(.{
165+
.b => get_regs(slice).csr.modify(.{
104166
.B_INV = @intFromBool(invert),
105167
}),
106168
}
107169
}
108170

171+
/// Set the wrap value for the slice. This is the number of pwm clock
172+
/// cycles that the slice will count to before wrapping.
173+
///
174+
/// Parameters:
175+
/// slice - the slice to set
176+
/// wrap - the wrap value
109177
pub fn set_slice_wrap(slice: u32, wrap: u16) void {
110178
log.debug("PWM{} set wrap: {}", .{ slice, wrap });
111179
get_regs(slice).top.raw = wrap;
112180
}
113181

182+
/// Set the level of the channel. This is the number of pwm clock
183+
/// cycles that the channel will be high.
184+
///
185+
/// The duty cycle of the channel is the ratio of this `level`
186+
/// to the the channel's `wrap` value.
187+
///
188+
/// Parameters:
189+
/// slice - the slice to set
190+
/// channel - the channel to set
191+
/// level - the level to set
114192
pub fn set_channel_level(
115193
slice: u32,
116194
channel: Channel,

0 commit comments

Comments
 (0)