1
1
const std = @import ("std" );
2
2
const microzig = @import ("microzig" );
3
3
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 ;
4
8
5
9
const log = std .log .scoped (.pwm );
6
10
7
11
pub const Config = struct {};
8
12
9
13
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 );
11
15
const PwmType = microzig .chip .types .peripherals .PWM ;
12
16
const reg_diff = comptime @offsetOf (PwmType , "CH1_CSR" ) - @offsetOf (PwmType , "CH0_CSR" );
13
17
return @as (* volatile Regs , @ptrFromInt (@intFromPtr (PWM ) + reg_diff * slice ));
@@ -18,37 +22,73 @@ pub const Channel = enum(u1) { a, b };
18
22
pub const Slice = enum (u32 ) {
19
23
_ ,
20
24
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
21
30
pub fn set_wrap (self : Slice , wrap : u16 ) void {
22
31
set_slice_wrap (@intFromEnum (self ), wrap );
23
32
}
24
33
34
+ /// Enable the slice.
25
35
pub fn enable (self : Slice ) void {
26
36
get_regs (@intFromEnum (self )).csr .modify (.{ .EN = 1 });
27
37
}
28
38
39
+ /// Disable the slice
29
40
pub fn disable (self : Slice ) void {
30
41
get_regs (@intFromEnum (self )).csr .modify (.{ .EN = 0 });
31
42
}
32
43
44
+ /// Set the slice to phase correct mode.
45
+ ///
46
+ /// Parameters:
47
+ /// phase_correct - true to enable phase correct mode, false to disable it
33
48
pub fn set_phase_correct (self : Slice , phase_correct : bool ) void {
34
49
set_slice_phase_correct (@intFromEnum (self ), phase_correct );
35
50
}
36
51
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
37
57
pub fn set_clk_div (self : Slice , integer : u8 , fraction : u4 ) void {
38
58
set_slice_clk_div (@intFromEnum (self ), integer , fraction );
39
59
}
40
60
};
41
61
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).
44
67
pub const Pwm = struct {
45
68
slice_number : u32 ,
46
69
channel : Channel ,
47
70
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
48
79
pub fn set_level (self : Pwm , level : u16 ) void {
49
80
set_channel_level (self .slice_number , self .channel , level );
50
81
}
51
82
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.
52
92
pub fn slice (self : Pwm ) Slice {
53
93
return @enumFromInt (self .slice_number );
54
94
}
@@ -69,13 +109,24 @@ const Regs = extern struct {
69
109
top : @TypeOf (PWM .CH0_TOP ),
70
110
};
71
111
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
72
117
pub fn set_slice_phase_correct (slice : u32 , phase_correct : bool ) void {
73
118
log .debug ("PWM{} set phase correct: {}" , .{ slice , phase_correct });
74
119
get_regs (slice ).csr .modify (.{
75
120
.PH_CORRECT = @intFromBool (phase_correct ),
76
121
});
77
122
}
78
123
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
79
130
pub fn set_slice_clk_div (slice : u32 , integer : u8 , fraction : u4 ) void {
80
131
log .debug ("PWM{} set clk div: {}.{}" , .{ slice , integer , fraction });
81
132
get_regs (slice ).div .modify (.{
@@ -84,13 +135,24 @@ pub fn set_slice_clk_div(slice: u32, integer: u8, fraction: u4) void {
84
135
});
85
136
}
86
137
138
+ /// Set the slice to a clock divider mode.
139
+ ///
140
+ /// Parameters:
141
+ /// slice - the slice to set
142
+ /// mode - the clock divider mode
87
143
pub fn set_slice_clk_div_mode (slice : u32 , mode : ClkDivMode ) void {
88
144
log .debug ("PWM{} set clk div mode: {}" , .{ slice , mode });
89
145
get_regs (slice ).csr .modify (.{
90
146
.DIVMODE = @intFromEnum (mode ),
91
147
});
92
148
}
93
149
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
94
156
pub fn set_channel_inversion (
95
157
slice : u32 ,
96
158
channel : Channel ,
@@ -100,17 +162,33 @@ pub fn set_channel_inversion(
100
162
.a = > get_regs (slice ).csr .modify (.{
101
163
.A_INV = @intFromBool (invert ),
102
164
}),
103
- .b = > get_regs (slice ).csr .modifi (.{
165
+ .b = > get_regs (slice ).csr .modify (.{
104
166
.B_INV = @intFromBool (invert ),
105
167
}),
106
168
}
107
169
}
108
170
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
109
177
pub fn set_slice_wrap (slice : u32 , wrap : u16 ) void {
110
178
log .debug ("PWM{} set wrap: {}" , .{ slice , wrap });
111
179
get_regs (slice ).top .raw = wrap ;
112
180
}
113
181
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
114
192
pub fn set_channel_level (
115
193
slice : u32 ,
116
194
channel : Channel ,
0 commit comments