32
32
#include "machine_pin_phy.h"
33
33
#include "mplogger.h"
34
34
35
+ #define pwm_assert_raise_val (msg , ret ) if (ret != CY_RSLT_SUCCESS) { \
36
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT(msg), ret); \
37
+ }
38
+
35
39
typedef struct _machine_pwm_obj_t {
36
40
mp_obj_base_t base ;
37
41
cyhal_pwm_t pwm_obj ;
@@ -69,14 +73,35 @@ enum {
69
73
DUTY_NS
70
74
};
71
75
72
- static void mp_machine_pwm_freq_set (machine_pwm_obj_t * self , mp_int_t freq );
76
+ /* Unit conversion macros */
77
+ #define pwm_duty_cycle_ns_to_u16 (duty_ns , fz ) ((int)(((float)(duty_ns * fz) / (float)1000000000) * (float)65536) - 1)
78
+ #define pwm_duty_cycle_u16_to_ns (duty_u16 , fz ) ((int)(((float)(duty_u16 + 1) / (float)65536) * ((float)1000000000 / (float)fz)))
79
+ #define pwm_duty_cycle_u16_to_percent (duty_u16 ) ((float)((duty_u16) * 100) / (float)65535)
80
+ #define pwm_freq_to_period_us (fz ) ((uint32_t)(1000000 / fz))
81
+ #define pwm_period_ns_to_us (period_ns ) ((uint32_t)(period_ns / 1000))
82
+
83
+ static void pwm_duty_ns_assert (mp_int_t duty_ns , uint32_t fz ) {
84
+ if (duty_ns > (int )(1000000000 / fz )) {
85
+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("PWM duty in ns is larger than the period %d ns" ), (int )(1000000000 / fz ));
86
+ }
87
+ }
88
+
89
+ static inline void pwm_freq_duty_set (cyhal_pwm_t * pwm_obj , uint32_t fz , mp_int_t duty_cycle ) {
90
+ cy_rslt_t ret = cyhal_pwm_set_duty_cycle (pwm_obj , pwm_duty_cycle_u16_to_percent (duty_cycle ), fz );
91
+ pwm_assert_raise_val ("PWM frequency and duty cycle set failed with return code %lx !" , ret );
92
+ }
73
93
74
- static cy_rslt_t pwm_freq_duty_set (cyhal_pwm_t * pwm_obj , uint32_t fz , float duty_cycle ) {
75
- return cyhal_pwm_set_duty_cycle (pwm_obj , duty_cycle * 100 , fz ); // duty_cycle in percentage
94
+ static void pwm_duty_set_ns (cyhal_pwm_t * pwm_obj , uint32_t fz , uint32_t pulse_width ) {
95
+ cy_rslt_t ret = cyhal_pwm_set_period (pwm_obj , pwm_freq_to_period_us (fz ), pwm_period_ns_to_us (pulse_width ));
96
+ pwm_assert_raise_val ("PWM period set failed with return code %lx !" , ret );
76
97
}
77
98
78
- static inline cy_rslt_t pwm_duty_set_ns (cyhal_pwm_t * pwm_obj , uint32_t fz , uint32_t pulse_width ) {
79
- return cyhal_pwm_set_period (pwm_obj , 1000000 / fz , pulse_width / 1000 );
99
+ static void pwm_config (machine_pwm_obj_t * self ) {
100
+ if (self -> duty_type == DUTY_U16 ) {
101
+ pwm_freq_duty_set (& self -> pwm_obj , self -> fz , self -> duty );
102
+ } else {
103
+ pwm_duty_set_ns (& self -> pwm_obj , self -> fz , self -> duty );
104
+ }
80
105
}
81
106
82
107
static void mp_machine_pwm_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
@@ -111,19 +136,20 @@ static void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
111
136
}
112
137
113
138
if ((args [ARG_duty_u16 ].u_int != VALUE_NOT_SET )) {
114
- float val = (float )(args [ARG_duty_u16 ].u_int ) / (float )65535 ;
115
- pwm_freq_duty_set (& self -> pwm_obj , self -> fz , val );
116
- self -> duty = args [ARG_duty_u16 ].u_int ;
139
+ self -> duty = args [ARG_duty_u16 ].u_int > 65535 ? 65535 : args [ARG_duty_u16 ].u_int ;
117
140
self -> duty_type = DUTY_U16 ;
118
141
} else if (args [ARG_duty_ns ].u_int != VALUE_NOT_SET ) {
119
- pwm_duty_set_ns ( & self -> pwm_obj , self -> fz , args [ARG_duty_ns ].u_int );
142
+ pwm_duty_ns_assert ( args [ARG_duty_ns ].u_int , self -> fz );
120
143
self -> duty = args [ARG_duty_ns ].u_int ;
121
144
self -> duty_type = DUTY_NS ;
122
145
} else {
123
146
mp_raise_ValueError (MP_ERROR_TEXT ("PWM duty should be specified in either ns or u16" ));
124
147
}
125
148
126
- cyhal_pwm_start (& self -> pwm_obj );
149
+ pwm_config (self );
150
+
151
+ cy_rslt_t result = cyhal_pwm_start (& self -> pwm_obj );
152
+ pwm_assert_raise_val ("PWM start failed with return code %lx !" , result );
127
153
}
128
154
129
155
static mp_obj_t mp_machine_pwm_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
@@ -136,14 +162,9 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
136
162
self -> duty_type = DUTY_NOT_SET ;
137
163
self -> fz = -1 ;
138
164
139
- // Initialize PWM
140
165
cy_rslt_t result = cyhal_pwm_init (& self -> pwm_obj , self -> pin , NULL );
141
-
142
- // To check whether PWM init is successful
143
- if (result != CY_RSLT_SUCCESS ) {
144
- assert_pin_phy_used (result );
145
- mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("PWM initialisation failed with return code %lx !" ), result );
146
- }
166
+ assert_pin_phy_used (result );
167
+ pwm_assert_raise_val ("PWM initialisation failed with return code %lx !" , result );
147
168
148
169
// Process the remaining parameters.
149
170
mp_map_t kw_args ;
@@ -154,16 +175,17 @@ static mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
154
175
}
155
176
156
177
static void mp_machine_pwm_deinit (machine_pwm_obj_t * self ) {
157
- cyhal_pwm_stop (& self -> pwm_obj );
178
+ cy_rslt_t result = cyhal_pwm_stop (& self -> pwm_obj );
179
+ pwm_assert_raise_val ("PWM stop failed with return code %lx !" , result );
158
180
cyhal_pwm_free (& self -> pwm_obj );
159
181
pwm_obj_free (self );
160
182
}
341A
161
183
162
184
static mp_obj_t mp_machine_pwm_duty_get_u16 (machine_pwm_obj_t * self ) {
163
185
if (self -> duty_type == DUTY_NS ) {
164
- return mp_obj_new_float ((( self -> duty ) * ( self -> fz ) * 65535 ) / 1000000000 - 1 );
186
+ return mp_obj_new_int ( pwm_duty_cycle_ns_to_u16 ( self -> duty , self -> fz ));
165
187
} else {
166
- return mp_obj_new_float (self -> duty );
188
+ return mp_obj_new_int (self -> duty );
167
189
}
168
190
}
169
191
@@ -172,36 +194,35 @@ static void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u
172
194
// Check the value is more than the max value
173
195
self -> duty = duty_u16 > 65535 ? 65535 : duty_u16 ;
174
196
self -> duty_type = DUTY_U16 ;
175
- pwm_freq_duty_set ( & self -> pwm_obj , self -> fz , ( float )( self -> duty ) / ( float ) 65535 ); // s conversion of duty_u16 into dutyu16/65535
197
+ pwm_config ( self );
176
198
}
177
199
178
200
static mp_obj_t mp_machine_pwm_duty_get_ns (machine_pwm_obj_t * self ) {
179
201
if (self -> duty_type == DUTY_U16 ) {
180
- return mp_obj_new_float ((( self -> duty ) * 1000000000 ) / (( self -> fz ) * 65535 )); // pw (ns) = duty_cycle*10^9/fz
202
+ return mp_obj_new_int ( pwm_duty_cycle_u16_to_ns ( self -> duty , self -> fz ));
181
203
} else {
182
- return mp_obj_new_float (self -> duty );
204
+ return mp_obj_new_int (self -> duty );
183
205
}
184
206
}
185
207
186
208
// sets the pulse width in nanoseconds
187
209
static void mp_machine_pwm_duty_set_ns (machine_pwm_obj_t * self , mp_int_t duty_ns ) {
210
+ pwm_duty_ns_assert (duty_ns , self -> fz );
188
211
self -> duty = duty_ns ;
189
212
self -> duty_type = DUTY_NS ;
190
- pwm_duty_set_ns ( & self -> pwm_obj , self -> fz , duty_ns );
213
+ pwm_config ( self );
191
214
}
192
215
193
216
static mp_obj_t mp_machine_pwm_freq_get (machine_pwm_obj_t * self ) {
194
217
return MP_OBJ_NEW_SMALL_INT (self -> fz );
195
-
196
218
}
197
219
198
220
static void mp_machine_pwm_freq_set (machine_pwm_obj_t * self , mp_int_t freq ) {
199
- self -> fz = freq ;
200
- pwm_freq_duty_set (& self -> pwm_obj , freq , self -> duty );
201
221
if (self -> duty_type == DUTY_NS ) {
202
- self -> duty = ((self -> duty ) * (self -> fz ) * 65535 ) / 1000000000 ;
203
- mp_machine_pwm_duty_set_ns (self , self -> duty );
222
+ pwm_duty_ns_assert (self -> duty , freq );
204
223
}
224
+ self -> fz = freq ;
225
+ pwm_config (self );
205
226
}
206
227
207
228
void machine_pwm_deinit_all () {
0 commit comments