rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
out_pwm_map.h File Reference

Which PWM (pulse-width modulation) register drives which pin on the RP2350. More...

#include <stdbool.h>
#include <stdint.h>

Go to the source code of this file.

Macros

#define OUT_PWM_SLICES   12u
 Slices in the block, and channels in a slice.
#define OUT_PWM_CHANNELS   2u
#define OUT_PWM_GPIOS   48u
 The GPIO numbers the fold is defined over: 0 to 47.
#define OUT_PWM_NONE   0xFFu
 Returned for a pin outside OUT_PWM_GPIOS, as a slice and as a channel.
#define OUT_PWM_TICK_HZ   1000000u
 The counter's tick: one count per microsecond, so a pulse width in microseconds is a compare value and a frame of rate R Hz is 1,000,000 / R counts, rounded down.

Functions

uint8_t out_pwm_slice_of (uint8_t pin)
 The slice pin is wired to, or OUT_PWM_NONE.
uint8_t out_pwm_channel_of (uint8_t pin)
 Which of that slice's channels: 0 is A, 1 is B.
bool out_pwm_same_slice (uint8_t a, uint8_t b)
 Whether two GPIOs count against one wrap register.
bool out_pwm_same_compare (uint8_t a, uint8_t b)
 Whether two GPIOs are driven from one compare register.
uint16_t out_pwm_pulse_max (uint16_t rate_hz)
 The longest pulse a frame of rate_hz carries, in microseconds: the frame's last count, one less than its period.

Detailed Description

Which PWM (pulse-width modulation) register drives which pin on the RP2350.

The part has 12 slices of two channels, A and B. A slice counts against one wrap register, so its two channels share a frame rate; each channel holds its own compare register, and that compare register is the pulse width.

GPIO (general-purpose input/output) numbers are folded onto 12 slices. GP0 to GP31 take slice (pin / 2) modulo 8; GP32 to GP47 take slice 8 + (pin / 2) modulo 4. The channel is the low bit of the pin number in both ranges.

The fold is what this header exists for. Two pins 16 apart below GP32 – GP0 and GP16, GP5 and GP21 – are one slice and one channel, which is one compare register muxed to two pads. Above GP32 the distance is 8: GP32 and GP40. Driving both pins of such a pair puts one pulse width on two leads, and only the pin written last says what it is.

This is the pico-sdk's PWM_GPIO_SLICE_NUM restated in pure C, so the host suite can hold it. firmware/iomcu/src/out_pwm.c compares the two on every bind rather than assuming they agree.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ OUT_PWM_GPIOS

#define OUT_PWM_GPIOS   48u

The GPIO numbers the fold is defined over: 0 to 47.

The widest RP2350 bank, the RP2350B's. The RP2350A brings out GP0 to GP29 and the rest of the fold is unreachable there, but which pins a package has is the firmware's fact, not this arithmetic's.

Function Documentation

◆ out_pwm_channel_of()

uint8_t out_pwm_channel_of ( uint8_t pin)

Which of that slice's channels: 0 is A, 1 is B.

OUT_PWM_NONE for a pin outside OUT_PWM_GPIOS.

Parameters
pinGPIO number, 0 to OUT_PWM_GPIOS - 1 (47).
Returns
Channel index, 0 or 1. OUT_PWM_NONE for a pin of 48 or more.

◆ out_pwm_pulse_max()

uint16_t out_pwm_pulse_max ( uint16_t rate_hz)

The longest pulse a frame of rate_hz carries, in microseconds: the frame's last count, one less than its period.

0 for a rate of 0 and for a period the sixteen-bit counter cannot hold (below 16Hz).

A pin is high while the counter is below the compare value, so a pulse of this length leaves one count of low at the end of each frame. One count more never goes low: the pin sits high, which is no pulse at all. This is the rule the output pages refuse an endpoint by, and the wrap firmware/iomcu/src/out_pwm.c programs, so the two cannot disagree.

1784us at 560Hz, 1999us at 500Hz, 2499us at 400Hz and 19999us at 50Hz.

Parameters
rate_hzFrame rate in Hz. The counter tick is OUT_PWM_TICK_HZ.
Returns
Longest pulse in microseconds. 0 for a rate of 0 and for a period above 65536 counts.

◆ out_pwm_same_compare()

bool out_pwm_same_compare ( uint8_t a,
uint8_t b )

Whether two GPIOs are driven from one compare register.

True for a pin against itself, and for the folded pairs – GP0 and GP16, GP32 and GP40. Two such pins cannot carry different pulse widths at all, so a driver that has one of them must refuse the other rather than bind both. False when either pin is outside OUT_PWM_GPIOS.

Parameters
aFirst GPIO number.
bSecond GPIO number.
Returns
true when both pins are in range and fold to one slice and one channel, false otherwise.

◆ out_pwm_same_slice()

bool out_pwm_same_slice ( uint8_t a,
uint8_t b )

Whether two GPIOs count against one wrap register.

True for the two channels of a slice, which can carry different pulse widths but not different frame rates. False when either pin is outside OUT_PWM_GPIOS: a pin the fold does not reach shares nothing.

Parameters
aFirst GPIO number.
bSecond GPIO number.
Returns
true when both pins are in range and fold to one slice, false otherwise.

◆ out_pwm_slice_of()

uint8_t out_pwm_slice_of ( uint8_t pin)

The slice pin is wired to, or OUT_PWM_NONE.

Parameters
pinGPIO number, 0 to OUT_PWM_GPIOS - 1 (47).
Returns
Slice index, 0 to 11. OUT_PWM_NONE for a pin of 48 or more.