summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locale/circuitpython.pot12
-rw-r--r--ports/raspberrypi/common-hal/countio/Counter.c103
-rw-r--r--ports/raspberrypi/common-hal/countio/Counter.h19
-rw-r--r--ports/raspberrypi/common-hal/countio/__init__.c1
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.c23
-rw-r--r--ports/raspberrypi/common-hal/pwmio/PWMOut.h4
-rw-r--r--ports/raspberrypi/mpconfigport.h1
-rw-r--r--ports/raspberrypi/mpconfigport.mk1
8 files changed, 163 insertions, 1 deletions
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index de921ec87..2e31d5dfc 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -1722,6 +1722,14 @@ msgid ""
"PWM frequency not writable when variable_frequency is False on construction."
msgstr ""
+#: ports/raspberrypi/common-hal/countio/Counter.c
+msgid "PWM slice already in use"
+msgstr ""
+
+#: ports/raspberrypi/common-hal/countio/Counter.c
+msgid "PWM slice channel A already in use"
+msgstr ""
+
#: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
#: ports/stm/common-hal/displayio/ParallelBus.c
@@ -1759,6 +1767,10 @@ msgstr ""
msgid "Pin is input only"
msgstr ""
+#: ports/raspberrypi/common-hal/countio/Counter.c
+msgid "Pin must be on PWM Channel B"
+msgstr ""
+
#: ports/atmel-samd/common-hal/countio/Counter.c
msgid "Pin must support hardware interrupts"
msgstr ""
diff --git a/ports/raspberrypi/common-hal/countio/Counter.c b/ports/raspberrypi/common-hal/countio/Counter.c
new file mode 100644
index 000000000..69629a084
--- /dev/null
+++ b/ports/raspberrypi/common-hal/countio/Counter.c
@@ -0,0 +1,103 @@
+#include "common-hal/countio/Counter.h"
+
+#include "py/runtime.h"
+#include "py/mpstate.h"
+#include "supervisor/shared/translate.h"
+
+#include "common-hal/pwmio/PWMOut.h"
+
+#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
+#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h"
+#include "src/rp2_common/hardware_irq/include/hardware/irq.h"
+
+
+void common_hal_countio_counter_construct(countio_counter_obj_t* self,
+ const mcu_pin_obj_t* pin_a) {
+
+ if (pwm_gpio_to_channel(pin_a->number) != PWM_CHAN_B) {
+ mp_raise_RuntimeError(translate("Pin must be on PWM Channel B"));
+ }
+
+ self->pin_a = pin_a->number;
+ self->slice_num = pwm_gpio_to_slice_num(self->pin_a);
+
+ if (MP_STATE_PORT(counting)[self->slice_num] != NULL) {
+ mp_raise_RuntimeError(translate("PWM slice already in use"));
+ }
+
+ uint8_t channel = pwm_gpio_to_channel(self->pin_a);
+ if (!pwmio_claim_slice_channels(self->slice_num)) {
+ mp_raise_RuntimeError(translate("PWM slice channel A already in use"));
+ }
+
+ pwm_clear_irq(self->slice_num);
+ pwm_set_irq_enabled(self->slice_num, true);
+ irq_set_exclusive_handler(PWM_IRQ_WRAP, counter_interrupt_handler);
+ irq_set_enabled(PWM_IRQ_WRAP, true);
+
+ pwm_config cfg = pwm_get_default_config();
+ pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_RISING);
+ pwm_init(self->slice_num, &cfg, false);
+ gpio_set_function(self->pin_a, GPIO_FUNC_PWM);
+
+ claim_pin(pin_a);
+
+ MP_STATE_PORT(counting)[self->slice_num] = self;
+
+ self->count = 0;
+ pwm_set_enabled(self->slice_num, true);
+}
+
+bool common_hal_countio_counter_deinited(countio_counter_obj_t* self) {
+ return self->pin_a == 0;
+}
+
+void common_hal_countio_counter_deinit(countio_counter_obj_t* self) {
+ if (common_hal_countio_counter_deinited(self)) {
+ return;
+ }
+
+ pwm_set_enabled(self->slice_num, false);
+ pwm_set_irq_enabled(self->slice_num, false);
+
+ pwmio_release_slice_channels(self->slice_num);
+
+ reset_pin_number(self->pin_a);
+
+ MP_STATE_PORT(counting)[self->slice_num] = NULL;
+ self->pin_a = 0;
+ self->slice_num = 0;
+}
+
+mp_int_t common_hal_countio_counter_get_count(countio_counter_obj_t* self) {
+ self->count += pwm_get_counter(self->slice_num);
+ pwm_set_counter(self->slice_num, 0);
+ return self->count;
+}
+
+void common_hal_countio_counter_set_count(countio_counter_obj_t* self,
+ mp_int_t new_count) {
+ pwm_set_counter(self->slice_num, 0);
+ self->count = new_count;
+}
+
+void common_hal_countio_counter_reset(countio_counter_obj_t* self){
+ pwm_set_counter(self->slice_num, 0);
+ self->count = 0;
+}
+
+void counter_interrupt_handler() {
+ uint32_t mask = pwm_get_irq_status_mask();
+
+ uint8_t i = 1, pos = 1;
+ while (!(i & mask)) {
+ i = i << 1;
+ ++pos;
+ }
+
+ countio_counter_obj_t *self = MP_STATE_PORT(counting)[pos-1];
+ if (self != NULL) {
+ pwm_clear_irq(self->slice_num);
+ self->count += 65536;
+ }
+}
diff --git a/ports/raspberrypi/common-hal/countio/Counter.h b/ports/raspberrypi/common-hal/countio/Counter.h
new file mode 100644
index 000000000..201034cf4
--- /dev/null
+++ b/ports/raspberrypi/common-hal/countio/Counter.h
@@ -0,0 +1,19 @@
+
+#ifndef MICROPY_INCLUDED_RASPBERRRYPI_COMMON_HAL_COUNTIO_COUNTER_H
+#define MICROPY_INCLUDED_RASPBERRRYPI_COMMON_HAL_COUNTIO_COUNTER_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t pin_a;
+ uint8_t slice_num;
+ mp_int_t count;
+} countio_counter_obj_t;
+
+
+void counter_interrupt_handler();
+
+#endif // MICROPY_INCLUDED_RASPBERRRYPI_COMMON_HAL_COUNTIO_COUNTER_H
diff --git a/ports/raspberrypi/common-hal/countio/__init__.c b/ports/raspberrypi/common-hal/countio/__init__.c
new file mode 100644
index 000000000..b95b20d15
--- /dev/null
+++ b/ports/raspberrypi/common-hal/countio/__init__.c
@@ -0,0 +1 @@
+//No countio module functions
diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c
index 9ca31a35e..fd85fbf55 100644
--- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c
+++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c
@@ -61,6 +61,29 @@ static uint32_t _mask(uint8_t slice, uint8_t channel) {
return 1 << (slice * CHANNELS_PER_SLICE + channel);
}
+bool pwmio_claim_slice_channels(uint8_t slice) {
+ uint32_t channel_use_mask_a = _mask(slice, 0);
+ uint32_t channel_use_mask_b = _mask(slice, 1);
+
+ if ((channel_use & channel_use_mask_a) != 0) {
+ return false;
+ }
+ if ((channel_use & channel_use_mask_b) != 0) {
+ return false;
+ }
+
+ channel_use |= channel_use_mask_a;
+ channel_use |= channel_use_mask_b;
+ return true;
+}
+
+void pwmio_release_slice_channels(uint8_t slice) {
+ uint32_t channel_mask = _mask(slice, 0);
+ channel_use &= ~channel_mask;
+ channel_mask = _mask(slice, 1);
+ channel_use &= ~channel_mask;
+}
+
void pwmout_never_reset(uint8_t slice, uint8_t channel) {
never_reset_channel |= _mask(slice, channel);
}
diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.h b/ports/raspberrypi/common-hal/pwmio/PWMOut.h
index 8221bef17..41da81010 100644
--- a/ports/raspberrypi/common-hal/pwmio/PWMOut.h
+++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.h
@@ -51,4 +51,8 @@ void pwmout_free(uint8_t slice, uint8_t channel);
void pwmout_never_reset(uint8_t slice, uint8_t channel);
void pwmout_reset_ok(uint8_t slice, uint8_t channel);
+// Private API for countio to claim both channels on a slice
+bool pwmio_claim_slice_channels(uint8_t slice);
+void pwmio_release_slice_channels(uint8_t slice);
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h
index 4dd3d1268..dba008a94 100644
--- a/ports/raspberrypi/mpconfigport.h
+++ b/ports/raspberrypi/mpconfigport.h
@@ -44,6 +44,7 @@
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
+ mp_obj_t counting[NUM_PWM_SLICES]; \
mp_obj_t playing_audio[NUM_DMA_CHANNELS]; \
CIRCUITPY_COMMON_ROOT_POINTERS;
diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk
index 4e55b0a09..4c149cb2b 100644
--- a/ports/raspberrypi/mpconfigport.mk
+++ b/ports/raspberrypi/mpconfigport.mk
@@ -30,7 +30,6 @@ CIRCUITPY_PWMIO = 1
CIRCUITPY_RGBMATRIX = 1
# Things that need to be implemented.
-CIRCUITPY_COUNTIO = 0 # Use PWM interally
CIRCUITPY_FREQUENCYIO = 0 # Use PWM interally
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_NVM = 1