Skip to content

Commit 2901d0f

Browse files
committed
raspberrypi: neopixel_write works on pin A0 (GPIO41) now
1 parent 17d8828 commit 2901d0f

File tree

1 file changed

+90
-70
lines changed

1 file changed

+90
-70
lines changed

ports/raspberrypi/common-hal/rp2pio/StateMachine.c

Lines changed: 90 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -203,22 +203,6 @@ static pio_pinmask_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pi
203203
return pins_we_use;
204204
}
205205

206-
static bool can_add_program(PIO pio, const pio_program_t *program, int offset) {
207-
if (offset == -1) {
208-
return pio_can_add_program(pio, program);
209-
}
210-
return pio_can_add_program_at_offset(pio, program, offset);
211-
}
212-
213-
static uint add_program(PIO pio, const pio_program_t *program, int offset) {
214-
if (offset == -1) {
215-
return pio_add_program(pio, program);
216-
} else {
217-
pio_add_program_at_offset(pio, program, offset);
218-
return offset;
219-
}
220-
}
221-
222206
static enum pio_fifo_join compute_fifo_type(int fifo_type_in, bool rx_fifo, bool tx_fifo) {
223207
if (fifo_type_in != PIO_FIFO_JOIN_AUTO) {
224208
return fifo_type_in;
@@ -246,6 +230,50 @@ static int compute_fifo_depth(enum pio_fifo_join join) {
246230
return 4;
247231
}
248232

233+
234+
// from pico-sdk/src/rp2_common/hardware_pio/pio.c
235+
static bool is_gpio_compatible(PIO pio, uint32_t used_gpio_ranges) {
236+
#if PICO_PIO_VERSION > 0
237+
bool gpio_base = pio_get_gpio_base(pio);
238+
return !((gpio_base && (used_gpio_ranges & 1)) ||
239+
(!gpio_base && (used_gpio_ranges & 4)));
240+
#else
241+
((void)pio);
242+
((void)used_gpio_ranges);
243+
return true;
244+
#endif
245+
}
246+
247+
static bool use_existing_program(PIO *pio_out, uint *sm_out, int *offset_inout, uint32_t program_id, size_t program_len, uint gpio_base, uint gpio_count) {
248+
uint32_t required_gpio_ranges;
249+
if (gpio_count) {
250+
required_gpio_ranges = (1u << (gpio_base >> 4)) |
251+
(1u << ((gpio_base + gpio_count - 1) >> 4));
252+
} else {
253+
required_gpio_ranges = 0;
254+
}
255+
256+
for (size_t i = 0; i < NUM_PIOS; i++) {
257+
PIO pio = pio_instances[i];
258+
if (!is_gpio_compatible(pio, required_gpio_ranges)) {
259+
continue;
260+
}
261+
for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) {
262+
if (_current_program_id[i][j] == program_id &&
263+
_current_program_len[i][j] == program_len &&
264+
(*offset_inout == -1 || *offset_inout == _current_program_offset[i][j])) {
265+
*pio_out = pio;
266+
*sm_out = j;
267+
*offset_inout = _current_program_offset[i][j];
268+
mp_printf(&mp_plat_print, "use existing program pio=%i offset=%u\n",
269+
i, _current_program_offset[i][j]);
270+
return true;
271+
}
272+
}
273+
}
274+
return false;
275+
}
276+
249277
bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
250278
const uint16_t *program, size_t program_len,
251279
size_t frequency,
@@ -272,88 +300,80 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
272300
// Create a program id that isn't the pointer so we can store it without storing the original object.
273301
uint32_t program_id = ~((uint32_t)program);
274302

275-
int pio_gpio_offset = 0;
303+
mp_printf(&mp_plat_print, "construct\n");
276304

305+
uint gpio_base = 0, gpio_count = 0;
277306
#if NUM_BANK0_GPIOS > 32
278307
PIO_PINMASK_PRINT(pins_we_use);
279308
if (PIO_PINMASK_VALUE(pins_we_use) >> 32) {
280-
pio_gpio_offset = 16;
281309
if (PIO_PINMASK_VALUE(pins_we_use) & 0xffff) {
282310
mp_printf(&mp_plat_print, "Uses pins from 0-15 and 32-47. not possible\n");
283311
return false;
284312
}
285313
}
314+
315+
pio_pinmask_value_t v = PIO_PINMASK_VALUE(pins_we_use);
316+
if (v) {
317+
while (!(v & 1)) {
318+
gpio_base++;
319+
v >>= 1;
320+
}
321+
while (v) {
322+
gpio_count++;
323+
v >>= 1;
324+
}
325+
}
286326
#endif
287327

288328
// Next, find a PIO and state machine to use.
289-
size_t pio_index = NUM_PIOS;
290-
uint8_t program_offset = 32;
291329
pio_program_t program_struct = {
292330
.instructions = (uint16_t *)program,
293331
.length = program_len,
294332
.origin = -1
295333
};
296-
for (size_t i = 0; i < NUM_PIOS; i++) {
297-
PIO pio = pio_instances[i];
298-
uint8_t free_count = 0;
299-
for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) {
300-
if (_current_program_id[i][j] == program_id &&
301-
_current_program_len[i][j] == program_len &&
302-
(offset == -1 || offset == _current_program_offset[i][j])) {
303-
program_offset = _current_program_offset[i][j];
304-
}
305-
if (!pio_sm_is_claimed(pio, j)) {
306-
free_count++;
307-
}
308-
}
309-
if (free_count > 0 && (program_offset < 32 || can_add_program(pio, &program_struct, offset))) {
310-
pio_index = i;
311-
if (program_offset < 32) {
312-
break;
313-
}
334+
PIO pio;
335+
uint state_machine;
336+
bool added = false;
337+
338+
if (!use_existing_program(&pio, &state_machine, &offset, program_id, program_len, gpio_base, gpio_count)) {
339+
uint program_offset;
340+
mp_printf(&mp_plat_print, "gpio_base = %d gpio_count = %d\n", gpio_base, gpio_count);
341+
bool r = pio_claim_free_sm_and_add_program_for_gpio_range(&program_struct, &pio, &state_machine, &program_offset, gpio_base, gpio_count, true);
342+
if (!r) {
343+
return false;
314344
}
315-
// Reset program offset if we weren't able to find a free state machine
316-
// on that PIO. (We would have broken the loop otherwise.)
317-
program_offset = 32;
345+
offset = program_offset;
346+
added = true;
318347
}
319348

320-
size_t state_machine = NUM_PIO_STATE_MACHINES;
321-
if (pio_index < NUM_PIOS) {
322-
PIO pio = pio_instances[pio_index];
323-
for (size_t i = 0; i < NUM_PIOS; i++) {
324-
if (i == pio_index) {
325-
continue;
326-
}
327-
pio_pinmask_t intersection = PIO_PINMASK_AND(_current_pins[i], pins_we_use);
328-
if (PIO_PINMASK_VALUE(intersection) != 0) {
329-
// Pin in use by another PIO already.
330-
return false;
349+
size_t pio_index = pio_get_index(pio);
350+
for (size_t i = 0; i < NUM_PIOS; i++) {
351+
if (i == pio_index) {
352+
continue;
353+
}
354+
pio_pinmask_t intersection = PIO_PINMASK_AND(_current_pins[i], pins_we_use);
355+
if (PIO_PINMASK_VALUE(intersection) != 0) {
356+
if (added) {
357+
pio_remove_program(pio, &program_struct, offset);
331358
}
359+
pio_sm_unclaim(pio, state_machine);
360+
// Pin in use by another PIO already.
361+
return false;
332362
}
333-
state_machine = pio_claim_unused_sm(pio, false);
334-
}
335-
if (pio_index == NUM_PIOS || state_machine < 0 || state_machine >= NUM_PIO_STATE_MACHINES) {
336-
return false;
337363
}
338364

339-
self->pio = pio_instances[pio_index];
365+
self->pio = pio;
340366
self->state_machine = state_machine;
341-
if (program_offset == 32) {
342-
program_offset = add_program(self->pio, &program_struct, offset);
343-
}
344-
self->offset = program_offset;
367+
self->offset = offset;
345368
_current_program_id[pio_index][state_machine] = program_id;
346369
_current_program_len[pio_index][state_machine] = program_len;
347-
_current_program_offset[pio_index][state_machine] = program_offset;
370+
_current_program_offset[pio_index][state_machine] = offset;
348371
_current_sm_pins[pio_index][state_machine] = pins_we_use;
349372
PIO_PINMASK_MERGE(_current_pins[pio_index], pins_we_use);
350373

351-
pio_sm_set_pins_with_mask(self->pio, state_machine, PIO_PINMASK_VALUE(initial_pin_state) >> pio_gpio_offset, PIO_PINMASK_VALUE(pins_we_use) >> pio_gpio_offset);
352-
pio_sm_set_pindirs_with_mask(self->pio, state_machine, PIO_PINMASK_VALUE(initial_pin_direction) >> pio_gpio_offset, PIO_PINMASK_VALUE(pins_we_use) >> pio_gpio_offset);
374+
pio_sm_set_pins_with_mask64(self->pio, state_machine, PIO_PINMASK_VALUE(initial_pin_state), PIO_PINMASK_VALUE(pins_we_use));
375+
pio_sm_set_pindirs_with_mask64(self->pio, state_machine, PIO_PINMASK_VALUE(initial_pin_direction), PIO_PINMASK_VALUE(pins_we_use));
353376
rp2pio_statemachine_set_pull(pull_pin_up, pull_pin_down, pins_we_use);
354-
#if NUM_BANK0_GPIOS > 32
355-
self->pio_gpio_offset = pio_gpio_offset;
356-
#endif
357377
self->initial_pin_state = initial_pin_state;
358378
self->initial_pin_direction = initial_pin_direction;
359379
self->pull_pin_up = pull_pin_up;
@@ -423,8 +443,8 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
423443

424444
mp_arg_validate_int_range(wrap_target, 0, program_len - 1, MP_QSTR_wrap_target);
425445

426-
wrap += program_offset;
427-
wrap_target += program_offset;
446+
wrap += offset;
447+
wrap_target += offset;
428448

429449
sm_config_set_wrap(&c, wrap_target, wrap);
430450
sm_config_set_in_shift(&c, in_shift_right, auto_push, push_threshold);
@@ -478,7 +498,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
478498
SM_DMA_CLEAR_CHANNEL_READ(pio_index, state_machine);
479499
SM_DMA_CLEAR_CHANNEL_WRITE(pio_index, state_machine);
480500

481-
pio_sm_init(self->pio, self->state_machine, program_offset, &c);
501+
pio_sm_init(self->pio, self->state_machine, offset, &c);
482502
common_hal_rp2pio_statemachine_run(self, init, init_len);
483503

484504
common_hal_rp2pio_statemachine_set_frequency(self, frequency);

0 commit comments

Comments
 (0)