17#include "gpio_rp2350.h"
25#define OFF32(x) (*(&x + _high_gpio))
28using namespace _IO_BANK0_;
29using namespace _PADS_BANK0_;
31function<void()> gpio_rp2350::_intHandler[48] {
nullptr};
32uint8_t gpio_rp2350::_irqConfig [48] {0};
34gpio_rp2350::gpio_rp2350(gpio_pin_t gpio) : _gpio(gpio) {
38 _mask = 1 << (gpio % 32);
39 _high_gpio = (gpio > 31);
42void gpio_rp2350::setGpio(gpio_pin_t gpio) {
45 _mask = 1 << (gpio % 32);
46 _high_gpio = (gpio > 31);
49gpio_pin_t gpio_rp2350::getGpio()
const {
53void gpio_rp2350::gpioMode (uint16_t mode) {
55 setSEL (GPIO_CTRL_FUNCSEL__sio);
59bool gpio_rp2350::gpioRead ()
const {
63 bool res = OFF32( SIO.GPIO_IN ) & _mask;
68void gpio_rp2350::gpioWrite (
bool value) {
72 OFF32( SIO.GPIO_OE_CLR ) = _mask;
74 OFF32( SIO.GPIO_OE_SET ) = _mask;
77 else if (_open_source) {
79 OFF32( SIO.GPIO_OE_SET ) = _mask;
81 OFF32( SIO.GPIO_OE_CLR ) = _mask;
87 OFF32( SIO.GPIO_OUT_SET ) = _mask;
89 OFF32( SIO.GPIO_OUT_CLR ) = _mask;
94void gpio_rp2350::gpioToggle() {
96 if (_open_drain || _open_source) {
97 OFF32( SIO.GPIO_OE_XOR ) = _mask;
99 OFF32( SIO.GPIO_OUT_XOR ) = _mask;
103void gpio_rp2350::gpioAttachIrq (gpio_mode_t mode,
104 function<
void()> handler) {
105 _irqConfig[_gpio] = 0;
107 if (mode & GPIO::LEVEL_LOW) {
108 _irqConfig[_gpio] |= 0x1;
110 if (mode & GPIO::LEVEL_HIGH) {
111 _irqConfig[_gpio] |= 0x2;
113 if (mode & GPIO::FALLING) {
114 _irqConfig[_gpio] |= 0x4;
116 if (mode & GPIO::RISING) {
117 _irqConfig[_gpio] |= 0x8;
120 _intHandler[_gpio] = handler;
125void gpio_rp2350::gpioDetachIrq () {
129 _intHandler[_gpio] =
nullptr;
132void gpio_rp2350::gpioEnableIrq() {
133 PROC0_INTE0_t *INTE_SET = &IO_BANK0_SET.PROC0_INTE0 + (_gpio >> 3) + (SIO.CPUID*18);
134 PROC0_INTE0_t *INTE_CLR = &IO_BANK0_CLR.PROC0_INTE0 + (_gpio >> 3) + (SIO.CPUID*18);
135 INTR0_t *INTR = &IO_BANK0.INTR0 + (_gpio >> 3);
136 int mask_shift = (_gpio & 0x7) * 4;
139 NVIC_DisableIRQ(IO_IRQ_BANK0_IRQn);
141 *INTE_CLR = (0xf << mask_shift);
142 *INTE_SET = _irqConfig[_gpio] << mask_shift;
144 *INTR = (0xf << mask_shift);
146 NVIC_ClearPendingIRQ(IO_IRQ_BANK0_IRQn);
147 NVIC_EnableIRQ (IO_IRQ_BANK0_IRQn);
150void gpio_rp2350::gpioDisableIrq() {
151 PROC0_INTE0_t *INTE_CLR = &IO_BANK0_CLR.PROC0_INTE0 + (_gpio >> 3) + (SIO.CPUID*18);
152 INTR0_t *INTR = &IO_BANK0.INTR0 + (_gpio >> 3);
153 int mask_shift = (_gpio & 0x7) * 4;
155 *INTR = (0xf << mask_shift);
157 *INTE_CLR = (0xf << mask_shift);
160void gpio_rp2350::setSEL (uint8_t sel)
const {
162 GPIO_CTRL_t *IO_CTRL = &IO_BANK0.GPIO0_CTRL + (_gpio << 1);
164 IO_CTRL->FUNCSEL = sel;
165 IO_CTRL->OUTOVER = 0;
168 IO_CTRL->IRQOVER = 0;
172 GPIO_t *PAD_CTRL = &PADS_BANK0.GPIO[_gpio];
177void gpio_rp2350::setMode (uint16_t mode) {
180 _open_source =
false;
182 OFF32( SIO.GPIO_OUT_CLR ) = _mask;
183 OFF32( SIO.GPIO_OE_CLR ) = _mask;
185 GPIO_t *PAD_CTRL = &PADS_BANK0.GPIO[_gpio];
189 PAD_CTRL->DRIVE = GPIO_DRIVE__2mA;
192 PAD_CTRL->SCHMITT = 1;
193 PAD_CTRL->SLEWFAST = 0;
195 if (mode & GPIO::INPUT) {
199 if (mode & GPIO::INPUT_INVERT) {
202 GPIO_CTRL_t *io_ctrl = &IO_BANK0.GPIO0_CTRL + (_gpio << 1);
203 io_ctrl->INOVER = GPIO_CTRL_INOVER__INVERT;
205 if (mode & GPIO::OUTPUT) {
206 OFF32( SIO.GPIO_OE_SET ) = _mask;
208 if (mode & GPIO::OUTPUT_OPEN_DRAIN) {
209 _open_drain |= _mask;
210 OFF32( SIO.GPIO_OE_SET ) = _mask;
212 if (mode & GPIO::OUTPUT_OPEN_SOURCE) {
213 _open_source |= _mask;
214 OFF32( SIO.GPIO_OUT_SET ) = _mask;
216 if (mode & GPIO::PULLUP) {
219 if (mode & GPIO::PULLDOWN) {
222 if (mode & GPIO::FAST) {
223 PAD_CTRL->SLEWFAST = 1;
225 if ((mode & GPIO::DRIVE_4mA) || (mode & GPIO::DRIVE_8mA)) {
226 PAD_CTRL->DRIVE = (mode >> 10) & 0x3;
228 if (mode & GPIO::INIT_HIGH) {
231 if (mode & GPIO::INIT_LOW) {
240void IO_IRQ_BANK0_Handler(
void) {
241 PROC0_INTS0_t *INTS = &IO_BANK0.PROC0_INTS0 + (SIO.CPUID*18);
242 INTR0_t *INTR = &IO_BANK0.INTR0;
243 for (
int i = 0; i < 6; ++i, INTS++, INTR++) {
244 while (uint8_t pos = __builtin_ffs(*INTS)) {
246 *INTR = (1 << --pos);
248 uint16_t gpio = (pos >> 2) + (i << 3);
249 if (gpio_rp2350::_intHandler[gpio]) {
250 gpio_rp2350::_intHandler[gpio]();