Skip to content

Commit ff1942c

Browse files
committed
Enable protomatter on RP2040 builds
Also found a race condition between timer_disable and redraw, which would happen if I debugger-paused inside common_hal_rgbmatrix_timer_disable or put a delay or print inside it. That's what pausing inside reconstruct fixes. So that the "right timer" can be chosen, `timer_allocate` now gets the `self` pointer. It's guaranteed at this point that the pin information is accurate, so you can e.g., find a PWM unit related to the pins themselves. This required touching each port to add the parameter even though it's unused everywhere but raspberrypi.
1 parent aae10fb commit ff1942c

File tree

16 files changed

+182
-37
lines changed

16 files changed

+182
-37
lines changed

ports/atmel-samd/common-hal/rgbmatrix/RGBMatrix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include "samd/timers.h"
3232
#include "timer_handler.h"
3333

34-
void *common_hal_rgbmatrix_timer_allocate() {
34+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self) {
3535
uint8_t timer_index = find_free_timer();
3636
if (timer_index == 0xff) {
3737
return NULL;

ports/atmel-samd/common-hal/rgbmatrix/RGBMatrix.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
2828
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
2929

30-
void *common_hal_rgbmatrix_timer_allocate(void);
30+
#include "shared-module/rgbmatrix/RGBMatrix.h"
31+
32+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self);
3133
void common_hal_rgbmatrix_timer_enable(void*);
3234
void common_hal_rgbmatrix_timer_disable(void*);
3335
void common_hal_rgbmatrix_timer_free(void*);

ports/nrf/common-hal/rgbmatrix/RGBMatrix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
extern void _PM_IRQ_HANDLER(void);
3434

35-
void *common_hal_rgbmatrix_timer_allocate() {
35+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self) {
3636
nrfx_timer_t *timer = nrf_peripherals_allocate_timer_or_throw();
3737
nrf_peripherals_timer_never_reset(timer);
3838
return timer->p_reg;

ports/nrf/common-hal/rgbmatrix/RGBMatrix.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
2828
#define MICROPY_INCLUDED_NRF_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
2929

30-
void *common_hal_rgbmatrix_timer_allocate(void);
30+
#include "shared-module/rgbmatrix/RGBMatrix.h"
31+
32+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self);
3133
void common_hal_rgbmatrix_timer_enable(void*);
3234
void common_hal_rgbmatrix_timer_disable(void*);
3335
void common_hal_rgbmatrix_timer_free(void*);

ports/raspberrypi/common-hal/pwmio/PWMOut.c

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,22 @@ static uint32_t _mask(uint8_t slice, uint8_t channel) {
4949
return 1 << (slice * CHANNELS_PER_SLICE + channel);
5050
}
5151

52+
void pwmout_never_reset(uint8_t slice, uint8_t channel) {
53+
never_reset_channel |= _mask(slice, channel);
54+
}
55+
56+
void pwmout_reset_ok(uint8_t slice, uint8_t channel) {
57+
never_reset_channel &= ~_mask(slice, channel);
58+
}
59+
5260
void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) {
53-
never_reset_channel |= _mask(self->slice, self->channel);
61+
pwmout_never_reset(self->slice, self->channel);
5462

5563
never_reset_pin_number(self->pin->number);
5664
}
5765

5866
void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) {
59-
never_reset_channel &= ~_mask(self->slice, self->channel);
67+
pwmout_reset_ok(self->slice, self->channel);
6068
}
6169

6270
void pwmout_reset(void) {
@@ -80,21 +88,7 @@ void pwmout_reset(void) {
8088
}
8189
}
8290

83-
pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
84-
const mcu_pin_obj_t* pin,
85-
uint16_t duty,
86-
uint32_t frequency,
87-
bool variable_frequency) {
88-
self->pin = pin;
89-
self->variable_frequency = variable_frequency;
90-
self->duty_cycle = duty;
91-
92-
if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) {
93-
return PWMOUT_INVALID_FREQUENCY;
94-
}
95-
96-
uint8_t slice = pwm_gpio_to_slice_num(pin->number);
97-
uint8_t channel = pwm_gpio_to_channel(pin->number);
91+
pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t channel, bool variable_frequency, uint32_t frequency) {
9892
uint32_t channel_use_mask = _mask(slice, channel);
9993

10094
// Check the channel first.
@@ -116,14 +110,39 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
116110
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
117111
}
118112
}
119-
self->slice = slice;
120-
self->channel = channel;
121113

122114
channel_use |= channel_use_mask;
123115
if (variable_frequency) {
124116
slice_variable_frequency |= 1 << slice;
125117
}
126118

119+
return PWMOUT_OK;
120+
}
121+
122+
pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
123+
const mcu_pin_obj_t* pin,
124+
uint16_t duty,
125+
uint32_t frequency,
126+
bool variable_frequency) {
127+
self->pin = pin;
128+
self->variable_frequency = variable_frequency;
129+
self->duty_cycle = duty;
130+
131+
if (frequency == 0 || frequency > (common_hal_mcu_processor_get_frequency() / 2)) {
132+
return PWMOUT_INVALID_FREQUENCY;
133+
}
134+
135+
uint8_t slice = pwm_gpio_to_slice_num(pin->number);
136+
uint8_t channel = pwm_gpio_to_channel(pin->number);
137+
138+
int r = pwmout_allocate(slice, channel, variable_frequency, frequency);
139+
if (r != PWMOUT_OK) {
140+
return r;
141+
}
142+
143+
self->slice = slice;
144+
self->channel = channel;
145+
127146
if (target_slice_frequencies[slice] != frequency) {
128147
// Reset the counter and compare values.
129148
pwm_hw->slice[slice].ctr = PWM_CH0_CTR_RESET;
@@ -144,20 +163,23 @@ bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t* self) {
144163
return self->pin == NULL;
145164
}
146165

147-
void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
148-
if (common_hal_pwmio_pwmout_deinited(self)) {
149-
return;
150-
}
151-
uint32_t channel_mask = _mask(self->slice, self->channel);
166+
void pwmout_free(uint8_t slice, uint8_t channel) {
167+
uint32_t channel_mask = _mask(slice, channel);
152168
channel_use &= ~channel_mask;
153169
never_reset_channel &= ~channel_mask;
154-
uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (self->slice * CHANNELS_PER_SLICE + self->channel);
170+
uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (slice * CHANNELS_PER_SLICE + channel);
155171
if ((channel_use & slice_mask) == 0) {
156-
target_slice_frequencies[self->slice] = 0;
157-
slice_variable_frequency &= ~(1 << self->slice);
158-
pwm_set_enabled(self->slice, false);
172+
target_slice_frequencies[slice] = 0;
173+
slice_variable_frequency &= ~(1 << slice);
174+
pwm_set_enabled(slice, false);
159175
}
176+
}
160177

178+
void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
179+
if (common_hal_pwmio_pwmout_deinited(self)) {
180+
return;
181+
}
182+
pwmout_free(self->slice, self->channel);
161183
reset_pin_number(self->pin->number);
162184
self->pin = NULL;
163185
}

ports/raspberrypi/common-hal/pwmio/PWMOut.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,10 @@ typedef struct {
4545
void pwmout_reset(void);
4646
// Private API for AudioPWMOut.
4747
void pwmio_pwmout_set_top(pwmio_pwmout_obj_t* self, uint32_t top);
48+
// Private APIs for RGBMatrix
49+
enum pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t channel, bool variable_frequency, uint32_t frequency);
50+
void pwmout_free(uint8_t slice, uint8_t channel);
51+
void pwmout_never_reset(uint8_t slice, uint8_t channel);
52+
void pwmout_reset_ok(uint8_t slice, uint8_t channel);
4853

4954
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stddef.h>
28+
29+
#include "py/mphal.h"
30+
31+
#include "common-hal/rgbmatrix/RGBMatrix.h"
32+
#include "shared-bindings/pwmio/PWMOut.h"
33+
#include "shared-module/rgbmatrix/RGBMatrix.h"
34+
35+
#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
36+
37+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self) {
38+
// Choose a PWM channel based on the first RGB pin
39+
uint8_t slice = pwm_gpio_to_slice_num(self->rgb_pins[0]);
40+
uint8_t channel = pwm_gpio_to_channel(self->rgb_pins[0]);
41+
int result = pwmout_allocate(slice, channel, true, 125000000/3);
42+
if (result == PWMOUT_OK) {
43+
// return value must be nonzero (but slice and channel can both be
44+
// zero), so set bit 16...
45+
pwmout_never_reset(slice, channel);
46+
return (void*)(intptr_t)(slice | (channel << 8) | 0x10000);
47+
}
48+
return NULL;
49+
}
50+
51+
void common_hal_rgbmatrix_timer_enable(void* ptr) {
52+
int8_t slice = ((intptr_t)ptr) & 0xff;
53+
pwm_set_enabled(slice, false);
54+
pwm_clear_irq(slice);
55+
pwm_set_enabled(slice, true);
56+
}
57+
58+
void common_hal_rgbmatrix_timer_disable(void* ptr) {
59+
int8_t slice = ((intptr_t)ptr) & 0xff;
60+
pwm_set_enabled(slice, false);
61+
}
62+
63+
void common_hal_rgbmatrix_timer_free(void* ptr) {
64+
intptr_t value = (intptr_t)ptr;
65+
uint8_t slice = value & 0xff;
66+
uint8_t channel = value >> 8;
67+
pwm_set_enabled(slice, false);
68+
pwmout_free(slice, channel);
69+
return;
70+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
28+
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
29+
30+
#include "shared-module/rgbmatrix/RGBMatrix.h"
31+
32+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self);
33+
void common_hal_rgbmatrix_timer_enable(void*);
34+
void common_hal_rgbmatrix_timer_disable(void*);
35+
void common_hal_rgbmatrix_timer_free(void*);
36+
37+
#endif

ports/raspberrypi/common-hal/rgbmatrix/__init__.c

Whitespace-only changes.

ports/raspberrypi/mpconfigport.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ else
2323
CIRCUITPY_NEOPIXEL_WRITE = 0
2424
endif
2525

26+
CIRCUITPY_FRAMEBUFFERIO = 1
2627
CIRCUITPY_FULL_BUILD = 1
2728
CIRCUITPY_PWMIO = 1
29+
CIRCUITPY_RGBMATRIX = 1
2830

2931
# Things that need to be implemented.
3032
CIRCUITPY_COUNTIO = 0 # Use PWM interally

ports/stm/common-hal/rgbmatrix/RGBMatrix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
extern void _PM_IRQ_HANDLER(void);
3535

36-
void *common_hal_rgbmatrix_timer_allocate() {
36+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self) {
3737
TIM_TypeDef * timer = stm_peripherals_find_timer();
3838
stm_peripherals_timer_reserve(timer);
3939
stm_peripherals_timer_never_reset(timer);

ports/stm/common-hal/rgbmatrix/RGBMatrix.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#ifndef MICROPY_INCLUDED_STM_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
2828
#define MICROPY_INCLUDED_STM_COMMON_HAL_RGBMATRIX_RGBMATRIX_H
2929

30-
void *common_hal_rgbmatrix_timer_allocate(void);
30+
#include "shared-module/rgbmatrix/RGBMatrix.h"
31+
32+
void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self);
3133
void common_hal_rgbmatrix_timer_enable(void*);
3234
void common_hal_rgbmatrix_timer_disable(void*);
3335
void common_hal_rgbmatrix_timer_free(void*);

shared-bindings/pwmio/PWMOut.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
extern const mp_obj_type_t pwmio_pwmout_type;
3434

35-
typedef enum {
35+
typedef enum pwmout_result_t {
3636
PWMOUT_OK,
3737
PWMOUT_INVALID_PIN,
3838
PWMOUT_INVALID_FREQUENCY,

shared-module/rgbmatrix/RGBMatrix.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t *self, i
5656
self->tile = tile;
5757
self->serpentine = serpentine;
5858

59-
self->timer = timer ? timer : common_hal_rgbmatrix_timer_allocate();
59+
self->timer = timer ? timer : common_hal_rgbmatrix_timer_allocate(self);
6060
if (self->timer == NULL) {
6161
mp_raise_ValueError(translate("No timer available"));
6262
}
@@ -68,6 +68,8 @@ void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t *self, i
6868
}
6969

7070
void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, mp_obj_t framebuffer) {
71+
self->paused = 1;
72+
7173
common_hal_rgbmatrix_timer_disable(self->timer);
7274
if (framebuffer) {
7375
self->framebuffer = framebuffer;

shared-module/rgbmatrix/RGBMatrix.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#pragma once
2828

29+
#include "py/obj.h"
2930
#include "lib/protomatter/src/core.h"
3031

3132
extern const mp_obj_type_t rgbmatrix_RGBMatrix_type;

0 commit comments

Comments
 (0)