MeshX 0.4
This repository provides an implementation for Bluetooth Low Energy (BLE) Mesh network nodes. The project allows you to create BLE mesh nodes that can communicate with each other, enabling the development of smart home solutions or other IoT-based applications.
Loading...
Searching...
No Matches
meshx_pwm.c File Reference

MeshX PWM Runtime Implementation (Updated to reduce log verbosity). More...

#include <string.h>
#include <stdbool.h>
#include "interface/gpio/meshx_pwm.h"
#include "interface/gpio/meshx_gpio_platform.h"
#include "../../inc/meshx_err.h"
#include "../../interface/logging/meshx_log.h"
#include "../../inc/module_id.h"

Data Structures

struct  meshx_pwm_config_t
 PWM configuration structure. More...
struct  meshx_pwm_state_t
 PWM runtime state structure. More...
struct  meshx_pwm_runtime_t
 PWM runtime state structure. More...

Functions

meshx_err_t meshx_pwm_init (void)
 Initialize PWM subsystem.
meshx_err_t meshx_pwm_deinit (void)
 Deinitialize PWM subsystem.
static meshx_err_t validate_pwm_logical_pin (uint8_t logical_pin)
 Validate logical pin number for PWM.
static meshx_err_t validate_pwm_frequency (uint32_t frequency)
 Validate PWM frequency.
static meshx_err_t validate_pwm_duty_cycle (uint8_t duty_cycle)
 Validate PWM duty cycle.
static meshx_err_t validate_pwm_resolution (uint8_t resolution)
 Validate PWM resolution.
static meshx_err_t allocate_pwm_channel (uint8_t logical_pin, uint8_t *channel)
 Allocate PWM channel.
meshx_err_t meshx_pwm_start (uint8_t logical_pin)
 Start PWM output on pin.
meshx_err_t meshx_pwm_stop (uint8_t logical_pin)
 Stop PWM output on pin.
meshx_err_t meshx_pwm_set_duty_cycle (uint8_t logical_pin, uint8_t duty_cycle)
 Set PWM duty cycle.
meshx_err_t meshx_pwm_get_duty_cycle (uint8_t logical_pin, uint8_t *duty_cycle)
 Get PWM duty cycle.
meshx_err_t meshx_pwm_set_frequency (uint8_t logical_pin, uint32_t frequency)
 Set PWM frequency.
meshx_err_t meshx_pwm_get_frequency (uint8_t logical_pin, uint32_t *frequency)
 Get PWM frequency.
meshx_err_t meshx_pwm_set_resolution (uint8_t logical_pin, uint8_t resolution)
 Set PWM resolution.
meshx_err_t meshx_pwm_get_resolution (uint8_t logical_pin, uint8_t *resolution)
 Get PWM resolution.
bool meshx_pwm_is_initialized (void)
 Check if PWM subsystem is initialized.
uint8_t meshx_pwm_get_pin_count (void)
 Get number of configured PWM pins.
uint8_t meshx_pwm_get_allocated_channels (void)
 Get number of allocated PWM channels.
bool meshx_pwm_is_started (uint8_t logical_pin)
 Check if PWM is started on pin.
void meshx_pwm_test_set_pin_count (uint8_t count)

Variables

static meshx_pwm_runtime_t pwm_runtime
static meshx_pwm_config_t test_pwm_configs [128]
static meshx_pwm_state_t test_pwm_states [128]

Detailed Description

MeshX PWM Runtime Implementation (Updated to reduce log verbosity).

This file implements the PWM runtime subsystem for MeshX. It provides the runtime API for PWM operations with parameter validation, hardware channel allocation, and PWM state management.

Author
MeshX Team
Date
2024

Function Documentation

◆ allocate_pwm_channel()

meshx_err_t allocate_pwm_channel ( uint8_t logical_pin,
uint8_t * channel )
static

Allocate PWM channel.

Parameters
logical_pinLogical pin number
[out]channelAllocated channel number
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
239{
240 if (channel == NULL) {
241 return MESHX_INVALID_ARG;
242 }
243
244 // Check if channel is already allocated for this pin
245 if (pwm_runtime.pwm_configs != NULL) {
246 uint8_t configured_channel = pwm_runtime.pwm_configs[logical_pin].channel;
247 if (configured_channel != 0xFF) { // 0xFF means not configured
248 // Check if channel is already in use
249 for (uint8_t i = 0; i < pwm_runtime.allocated_channels; i++) {
250 if (pwm_runtime.channel_allocation[i] == configured_channel) {
251 // Channel already allocated to another pin
253 }
254 }
255
256 *channel = configured_channel;
257 pwm_runtime.channel_allocation[pwm_runtime.allocated_channels++] = configured_channel;
258 return MESHX_SUCCESS;
259 }
260 }
261
262 // Find free channel (simple linear search)
263 // TODO: Implement better channel allocation strategy
264 for (uint8_t ch = 0; ch < sizeof(pwm_runtime.channel_allocation); ch++) {
265 bool channel_in_use = false;
266 for (uint8_t i = 0; i < pwm_runtime.allocated_channels; i++) {
267 if (pwm_runtime.channel_allocation[i] == ch) {
268 channel_in_use = true;
269 break;
270 }
271 }
272
273 if (!channel_in_use) {
274 *channel = ch;
275 pwm_runtime.channel_allocation[pwm_runtime.allocated_channels++] = ch;
276
277 // Update configuration if available
278 if (pwm_runtime.pwm_configs != NULL) {
279 pwm_runtime.pwm_configs[logical_pin].channel = ch;
280 }
281
282 return MESHX_SUCCESS;
283 }
284 }
285
286 return MESHX_ERR_GPIO_PWM_NOT_SUPPORTED; // No channels available
287}
@ MESHX_INVALID_ARG
Definition meshx_err.h:46
@ MESHX_ERR_GPIO_PWM_NOT_SUPPORTED
Definition meshx_err.h:68
**This function is called by the parent element when a state change request *is received It validates the request and returns a result to the element not the model layer **return * MESHX_SUCCESS
Definition meshx_model_level.cpp:385
static meshx_pwm_runtime_t pwm_runtime
Definition meshx_pwm.c:54

◆ meshx_pwm_deinit()

meshx_err_t meshx_pwm_deinit ( void )

Deinitialize PWM subsystem.

This function deinitializes the PWM subsystem and releases all resources. It stops all PWM outputs, deconfigures channels, and cleans up platform resources.

Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
120{
121 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Deinitializing PWM subsystem");
122
123 if (!pwm_runtime.initialized) {
124 MESHX_LOGW(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM not initialized");
125 return MESHX_SUCCESS;
126 }
127
128 // Stop all active PWM outputs
129 for (uint8_t i = 0; i < pwm_runtime.pwm_pin_count; i++) {
130 if (pwm_runtime.pwm_states != NULL && pwm_runtime.pwm_states[i].started) {
132 }
133 }
134
135 // Deinitialize platform-specific PWM
137 if (err != MESHX_SUCCESS) {
138 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Platform PWM deinit failed: %d", err);
139 return err;
140 }
141
142 // Free allocated resources
143 // Note: In actual implementation, these would be freed if dynamically allocated
144 // For now, just reset pointers since they're statically allocated or NULL
145 pwm_runtime.pwm_configs = NULL;
146 pwm_runtime.pwm_states = NULL;
147 memset(pwm_runtime.channel_allocation, 0xFF, sizeof(pwm_runtime.channel_allocation));
148 pwm_runtime.allocated_channels = 0;
149
150 pwm_runtime.initialized = false;
151 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM subsystem deinitialized");
152 return MESHX_SUCCESS;
153}
meshx_err_t
MeshX Error Codes.
Definition meshx_err.h:43
meshx_err_t meshx_pwm_platform_deinit(void)
Platform-specific PWM deinitialization.
#define MESHX_LOGW(module_id, format,...)
Definition meshx_log.h:120
#define MESHX_LOGE(module_id, format,...)
Definition meshx_log.h:114
#define MESHX_LOGD(module_id, format,...)
Definition meshx_log.h:132
meshx_err_t meshx_pwm_stop(uint8_t logical_pin)
Stop PWM output on pin.
Definition meshx_pwm.c:373
@ MODULE_ID_COMPONENT_MESHX_GPIO
Definition module_id.h:44

◆ meshx_pwm_get_allocated_channels()

uint8_t meshx_pwm_get_allocated_channels ( void )

Get number of allocated PWM channels.

Returns
uint8_t Number of allocated channels
689{
690 return pwm_runtime.allocated_channels;
691}

◆ meshx_pwm_get_duty_cycle()

meshx_err_t meshx_pwm_get_duty_cycle ( uint8_t logical_pin,
uint8_t * duty_cycle )

Get PWM duty cycle.

Parameters
logical_pinLogical pin number (0-255)
[out]duty_cyclePointer to store duty cycle
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
481{
482 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Getting PWM duty cycle from pin %u", logical_pin);
483
484 if (duty_cycle == NULL) {
485 return MESHX_INVALID_ARG;
486 }
487
488 // Validate pin
489 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
490 if (err != MESHX_SUCCESS) {
491 return err;
492 }
493
494 // Check if PWM is started
495 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
497 }
498
499 // TODO: Get from platform-specific implementation
500 // For now, return from runtime state
501 *duty_cycle = pwm_runtime.pwm_states[logical_pin].duty_cycle;
502
504 "PWM duty cycle on pin %u is %u%%", logical_pin, *duty_cycle);
505 return MESHX_SUCCESS;
506}
static meshx_err_t validate_pwm_logical_pin(uint8_t logical_pin)
Validate logical pin number for PWM.
Definition meshx_pwm.c:161

◆ meshx_pwm_get_frequency()

meshx_err_t meshx_pwm_get_frequency ( uint8_t logical_pin,
uint32_t * frequency )

Get PWM frequency.

Parameters
logical_pinLogical pin number (0-255)
[out]frequencyPointer to store frequency
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
563{
564 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Getting PWM frequency from pin %u", logical_pin);
565
566 if (frequency == NULL) {
567 return MESHX_INVALID_ARG;
568 }
569
570 // Validate pin
571 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
572 if (err != MESHX_SUCCESS) {
573 return err;
574 }
575
576 // Check if PWM is started
577 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
579 }
580
581 // TODO: Get from platform-specific implementation
582 // For now, return from runtime state
583 *frequency = pwm_runtime.pwm_states[logical_pin].frequency;
584
586 "PWM frequency on pin %u is %u Hz", logical_pin, *frequency);
587 return MESHX_SUCCESS;
588}

◆ meshx_pwm_get_pin_count()

uint8_t meshx_pwm_get_pin_count ( void )

Get number of configured PWM pins.

Returns
uint8_t Number of configured PWM pins
679{
680 return pwm_runtime.pwm_pin_count;
681}

◆ meshx_pwm_get_resolution()

meshx_err_t meshx_pwm_get_resolution ( uint8_t logical_pin,
uint8_t * resolution )

Get PWM resolution.

Parameters
logical_pinLogical pin number (0-255)
[out]resolutionPointer to store resolution
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
635{
636 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Getting PWM resolution from pin %u", logical_pin);
637
638 if (resolution == NULL) {
639 return MESHX_INVALID_ARG;
640 }
641
642 // Validate pin
643 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
644 if (err != MESHX_SUCCESS) {
645 return err;
646 }
647
648 // Check if PWM is started
649 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
651 }
652
653 // TODO: Get from platform-specific implementation
654 // For now, return from runtime state
655 *resolution = pwm_runtime.pwm_states[logical_pin].resolution;
656
658 "PWM resolution on pin %u is %u bits", logical_pin, *resolution);
659 return MESHX_SUCCESS;
660}

◆ meshx_pwm_init()

meshx_err_t meshx_pwm_init ( void )

Initialize PWM subsystem.

This function initializes the PWM subsystem based on compiled configuration. It sets up hardware PWM channels and configures all PWM pins according to their YAML configuration.

Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
70{
71 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Initializing PWM subsystem");
72
73 if (pwm_runtime.initialized) {
74 MESHX_LOGW(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM already initialized");
75 return MESHX_SUCCESS;
76 }
77
78 // Initialize platform-specific PWM
80 if (err != MESHX_SUCCESS) {
81 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Platform PWM init failed: %d", err);
82 return err;
83 }
84
85 // TODO: Load configuration from generated headers
86 // For now, initialize with empty configuration
87 pwm_runtime.pwm_pin_count = 0;
88 pwm_runtime.pwm_configs = NULL;
89 pwm_runtime.pwm_states = NULL;
90 memset(pwm_runtime.channel_allocation, 0xFF, sizeof(pwm_runtime.channel_allocation));
91 pwm_runtime.allocated_channels = 0;
92
93 pwm_runtime.initialized = true;
94#if CONFIG_ENABLE_UNIT_TEST
95 pwm_runtime.pwm_pin_count = 128;
96 pwm_runtime.pwm_configs = test_pwm_configs;
97 pwm_runtime.pwm_states = test_pwm_states;
98 memset(test_pwm_configs, 0, sizeof(test_pwm_configs));
99 memset(test_pwm_states, 0, sizeof(test_pwm_states));
100 for (int i = 0; i < 128; i++) {
101 test_pwm_configs[i].logical_pin = i;
102 test_pwm_configs[i].channel = 0xFF;
103 test_pwm_configs[i].frequency = 1000;
104 test_pwm_configs[i].resolution = 10;
105 }
106#endif
107 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM subsystem initialized");
108 return MESHX_SUCCESS;
109}
meshx_err_t meshx_pwm_platform_init(void)
Platform-specific PWM initialization.
static meshx_pwm_config_t test_pwm_configs[128]
Definition meshx_pwm.c:56
static meshx_pwm_state_t test_pwm_states[128]
Definition meshx_pwm.c:57

◆ meshx_pwm_is_initialized()

bool meshx_pwm_is_initialized ( void )

Check if PWM subsystem is initialized.

Returns
true if initialized
false if not initialized
669{
670 return pwm_runtime.initialized;
671}

◆ meshx_pwm_is_started()

bool meshx_pwm_is_started ( uint8_t logical_pin)

Check if PWM is started on pin.

Parameters
logical_pinLogical pin number
Returns
true if PWM is started
false if PWM is not started
701{
702 if (!pwm_runtime.initialized || logical_pin >= pwm_runtime.pwm_pin_count) {
703 return false;
704 }
705
706 if (pwm_runtime.pwm_states == NULL) {
707 return false;
708 }
709
710 return pwm_runtime.pwm_states[logical_pin].started;
711}

◆ meshx_pwm_set_duty_cycle()

meshx_err_t meshx_pwm_set_duty_cycle ( uint8_t logical_pin,
uint8_t duty_cycle )

Set PWM duty cycle.

Parameters
logical_pinLogical pin number (0-255)
duty_cycleDuty cycle (0-100%)
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
434{
436 "Setting PWM duty cycle on pin %u to %u%%", logical_pin, duty_cycle);
437
438 // Validate pin
439 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
440 if (err != MESHX_SUCCESS) {
441 return err;
442 }
443
444 // Validate duty cycle
445 err = validate_pwm_duty_cycle(duty_cycle);
446 if (err != MESHX_SUCCESS) {
447 return err;
448 }
449
450 // Check if PWM is started
451 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
453 }
454
455 // TODO: Get physical pin from logical pin mapping
456 // For now, use logical pin as physical pin (simplified)
457 uint8_t physical_pin = logical_pin;
458
459 // Set platform-specific PWM duty cycle
460 err = meshx_pwm_platform_set_duty_cycle(physical_pin, duty_cycle);
461 if (err != MESHX_SUCCESS) {
462 return err;
463 }
464
465 // Update runtime state
466 pwm_runtime.pwm_states[logical_pin].duty_cycle = duty_cycle;
467
469 "PWM duty cycle set on pin %u to %u%%", logical_pin, duty_cycle);
470 return MESHX_SUCCESS;
471}
meshx_err_t meshx_pwm_platform_set_duty_cycle(uint8_t physical_pin, uint8_t duty_cycle)
Platform-specific PWM duty cycle set.
static meshx_err_t validate_pwm_duty_cycle(uint8_t duty_cycle)
Validate PWM duty cycle.
Definition meshx_pwm.c:207

◆ meshx_pwm_set_frequency()

meshx_err_t meshx_pwm_set_frequency ( uint8_t logical_pin,
uint32_t frequency )

Set PWM frequency.

Parameters
logical_pinLogical pin number (0-255)
frequencyFrequency in Hz
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
516{
518 "Setting PWM frequency on pin %u to %u Hz", logical_pin, frequency);
519
520 // Validate pin
521 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
522 if (err != MESHX_SUCCESS) {
523 return err;
524 }
525
526 // Validate frequency
527 err = validate_pwm_frequency(frequency);
528 if (err != MESHX_SUCCESS) {
529 return err;
530 }
531
532 // Check if PWM is started
533 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
535 }
536
537 // TODO: Get physical pin from logical pin mapping
538 // For now, use logical pin as physical pin (simplified)
539 uint8_t physical_pin = logical_pin;
540
541 // Set platform-specific PWM frequency
542 err = meshx_pwm_platform_set_frequency(physical_pin, frequency);
543 if (err != MESHX_SUCCESS) {
544 return err;
545 }
546
547 // Update runtime state
548 pwm_runtime.pwm_states[logical_pin].frequency = frequency;
549
551 "PWM frequency set on pin %u to %u Hz", logical_pin, frequency);
552 return MESHX_SUCCESS;
553}
meshx_err_t meshx_pwm_platform_set_frequency(uint8_t physical_pin, uint32_t frequency)
Platform-specific PWM frequency set.
static meshx_err_t validate_pwm_frequency(uint32_t frequency)
Validate PWM frequency.
Definition meshx_pwm.c:186

◆ meshx_pwm_set_resolution()

meshx_err_t meshx_pwm_set_resolution ( uint8_t logical_pin,
uint8_t resolution )

Set PWM resolution.

Parameters
logical_pinLogical pin number (0-255)
resolutionResolution in bits (typically 8-16)
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
598{
600 "Setting PWM resolution on pin %u to %u bits", logical_pin, resolution);
601
602 // Validate pin
603 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
604 if (err != MESHX_SUCCESS) {
605 return err;
606 }
607
608 // Validate resolution
609 err = validate_pwm_resolution(resolution);
610 if (err != MESHX_SUCCESS) {
611 return err;
612 }
613
614 // Check if PWM is started
615 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
617 }
618
619 // Update runtime state
620 pwm_runtime.pwm_states[logical_pin].resolution = resolution;
621
623 "PWM resolution set on pin %u to %u bits", logical_pin, resolution);
624 return MESHX_SUCCESS;
625}
static meshx_err_t validate_pwm_resolution(uint8_t resolution)
Validate PWM resolution.
Definition meshx_pwm.c:222

◆ meshx_pwm_start()

meshx_err_t meshx_pwm_start ( uint8_t logical_pin)

Start PWM output on pin.

Parameters
logical_pinLogical pin number (0-255)
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
296{
297 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Starting PWM on pin %u", logical_pin);
298
299 // Validate pin
300 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
301 if (err != MESHX_SUCCESS) {
302 return err;
303 }
304
305 // Check if already started
306 if (pwm_runtime.pwm_states != NULL && pwm_runtime.pwm_states[logical_pin].started) {
307 MESHX_LOGW(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM already started on pin %u", logical_pin);
308 return MESHX_SUCCESS;
309 }
310
311 // Get configuration
312 uint32_t frequency = 1000; // Default 1kHz
313 uint8_t duty_cycle = 50; // Default 50%
314 uint8_t resolution = 10; // Default 10-bit
315
316 if (pwm_runtime.pwm_configs != NULL) {
317 frequency = pwm_runtime.pwm_configs[logical_pin].frequency;
318 duty_cycle = pwm_runtime.pwm_configs[logical_pin].duty_cycle;
319 resolution = pwm_runtime.pwm_configs[logical_pin].resolution;
320 }
321
322 // Validate parameters
323 err = validate_pwm_frequency(frequency);
324 if (err != MESHX_SUCCESS) return err;
325
326 err = validate_pwm_duty_cycle(duty_cycle);
327 if (err != MESHX_SUCCESS) return err;
328
329 err = validate_pwm_resolution(resolution);
330 if (err != MESHX_SUCCESS) return err;
331
332 // Allocate PWM channel
333 uint8_t channel;
334 err = allocate_pwm_channel(logical_pin, &channel);
335 if (err != MESHX_SUCCESS) {
337 "Failed to allocate PWM channel for pin %u: %d", logical_pin, err);
338 return err;
339 }
340
341 // TODO: Get physical pin from logical pin mapping
342 // For now, use logical pin as physical pin (simplified)
343 uint8_t physical_pin = logical_pin;
344
345 // Start platform-specific PWM
346 err = meshx_pwm_platform_start(physical_pin, frequency, duty_cycle, resolution);
347 if (err != MESHX_SUCCESS) {
349 "Platform PWM start failed for pin %u: %d", logical_pin, err);
350 return err;
351 }
352
353 // Update runtime state
354 if (pwm_runtime.pwm_states != NULL) {
355 pwm_runtime.pwm_states[logical_pin].started = true;
356 pwm_runtime.pwm_states[logical_pin].frequency = frequency;
357 pwm_runtime.pwm_states[logical_pin].duty_cycle = duty_cycle;
358 pwm_runtime.pwm_states[logical_pin].resolution = resolution;
359 }
360
362 "PWM started on pin %u: %u Hz, %u%%, %u-bit",
363 logical_pin, frequency, duty_cycle, resolution);
364 return MESHX_SUCCESS;
365}
meshx_err_t meshx_pwm_platform_start(uint8_t physical_pin, uint32_t frequency, uint8_t duty_cycle, uint8_t resolution)
Platform-specific PWM start.
static meshx_err_t allocate_pwm_channel(uint8_t logical_pin, uint8_t *channel)
Allocate PWM channel.
Definition meshx_pwm.c:238

◆ meshx_pwm_stop()

meshx_err_t meshx_pwm_stop ( uint8_t logical_pin)

Stop PWM output on pin.

Parameters
logical_pinLogical pin number (0-255)
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
374{
375 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Stopping PWM on pin %u", logical_pin);
376
377 // Validate pin
378 meshx_err_t err = validate_pwm_logical_pin(logical_pin);
379 if (err != MESHX_SUCCESS) {
380 return err;
381 }
382
383 // Check if already stopped
384 if (pwm_runtime.pwm_states == NULL || !pwm_runtime.pwm_states[logical_pin].started) {
385 MESHX_LOGW(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM already stopped on pin %u", logical_pin);
386 return MESHX_SUCCESS;
387 }
388
389 // TODO: Get physical pin from logical pin mapping
390 // For now, use logical pin as physical pin (simplified)
391 uint8_t physical_pin = logical_pin;
392
393 // Stop platform-specific PWM
394 err = meshx_pwm_platform_stop(physical_pin);
395 if (err != MESHX_SUCCESS) {
397 "Platform PWM stop failed for pin %u: %d", logical_pin, err);
398 return err;
399 }
400
401 // Free allocated channel
402 if (pwm_runtime.pwm_configs != NULL) {
403 uint8_t channel = pwm_runtime.pwm_configs[logical_pin].channel;
404 if (channel != 0xFF) {
405 // Remove from allocation tracking
406 for (uint8_t i = 0; i < pwm_runtime.allocated_channels; i++) {
407 if (pwm_runtime.channel_allocation[i] == channel) {
408 // Shift remaining channels
409 for (uint8_t j = i; j < pwm_runtime.allocated_channels - 1; j++) {
410 pwm_runtime.channel_allocation[j] = pwm_runtime.channel_allocation[j + 1];
411 }
412 pwm_runtime.allocated_channels--;
413 break;
414 }
415 }
416 }
417 }
418
419 // Update runtime state
420 pwm_runtime.pwm_states[logical_pin].started = false;
421
422 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "PWM stopped on pin %u", logical_pin);
423 return MESHX_SUCCESS;
424}
meshx_err_t meshx_pwm_platform_stop(uint8_t physical_pin)
Platform-specific PWM stop.

◆ meshx_pwm_test_set_pin_count()

void meshx_pwm_test_set_pin_count ( uint8_t count)
715{
716 if (count > 128) count = 128;
717 pwm_runtime.pwm_pin_count = count;
718}

◆ validate_pwm_duty_cycle()

meshx_err_t validate_pwm_duty_cycle ( uint8_t duty_cycle)
static

Validate PWM duty cycle.

Parameters
duty_cycleDuty cycle (0-100%)
Returns
meshx_err_t MESHX_SUCCESS if valid, error code if invalid
208{
209 if (duty_cycle > 100) {
211 }
212
213 return MESHX_SUCCESS;
214}
@ MESHX_ERR_GPIO_PWM_INVALID_PARAM
Definition meshx_err.h:69

◆ validate_pwm_frequency()

meshx_err_t validate_pwm_frequency ( uint32_t frequency)
static

Validate PWM frequency.

Parameters
frequencyFrequency in Hz
Returns
meshx_err_t MESHX_SUCCESS if valid, error code if invalid
187{
188 if (frequency == 0) {
190 }
191
192 // TODO: Check against hardware limits from BSP constraints
193 // For now, just check basic validity
194 if (frequency > 40000000) { // 40MHz theoretical max
196 }
197
198 return MESHX_SUCCESS;
199}

◆ validate_pwm_logical_pin()

meshx_err_t validate_pwm_logical_pin ( uint8_t logical_pin)
static

Validate logical pin number for PWM.

Parameters
logical_pinLogical pin number to validate
Returns
meshx_err_t MESHX_SUCCESS if valid, error code if invalid
162{
163 if (!pwm_runtime.initialized) {
165 }
166
167 if (logical_pin >= pwm_runtime.pwm_pin_count) {
169 }
170
171 // Check if pin is configured for PWM
172 if (pwm_runtime.pwm_configs != NULL &&
173 pwm_runtime.pwm_configs[logical_pin].logical_pin != logical_pin) {
175 }
176
177 return MESHX_SUCCESS;
178}
@ MESHX_ERR_GPIO_INVALID_PIN
Definition meshx_err.h:63
@ MESHX_ERR_GPIO_NOT_INITIALIZED
Definition meshx_err.h:70

◆ validate_pwm_resolution()

meshx_err_t validate_pwm_resolution ( uint8_t resolution)
static

Validate PWM resolution.

Parameters
resolutionResolution in bits
Returns
meshx_err_t MESHX_SUCCESS if valid, error code if invalid
223{
224 if (resolution == 0 || resolution > 20) { // ESP32 supports up to 20-bit
226 }
227
228 return MESHX_SUCCESS;
229}

Variable Documentation

◆ pwm_runtime

meshx_pwm_runtime_t pwm_runtime
static

◆ test_pwm_configs

meshx_pwm_config_t test_pwm_configs[128]
static

◆ test_pwm_states

meshx_pwm_state_t test_pwm_states[128]
static