From 412eb87080878cffc91b90ddbec3606709a0744f Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 21 Jul 2021 16:27:09 -0700 Subject: [PATCH] Switch to pin, frequency and duty_cycle PulseOut Passing in a PWMOut still works but is deprecated. It will be removed in CircuitPython 8.0.0 This also switches STM32 timer indices and channel indices to 0-based in our pin data rather than `- 1` everywhere. The latter is more bug prone. Most of the way for #3264 Tested on Metro M0, Metro M4, Feather S2, Feather nRF52840, Feather STM32F4 and Arduino RP2040. --- locale/circuitpython.pot | 15 -- .../atmel-samd/common-hal/pulseio/PulseOut.c | 15 +- .../atmel-samd/common-hal/pulseio/PulseOut.h | 2 + ports/atmel-samd/common-hal/pwmio/PWMOut.c | 4 + ports/cxd56/common-hal/pulseio/PulseOut.c | 14 +- ports/cxd56/common-hal/pulseio/PulseOut.h | 3 + ports/cxd56/common-hal/pwmio/PWMOut.c | 4 + ports/esp32s2/common-hal/pulseio/PulseOut.c | 4 - ports/esp32s2/common-hal/pwmio/PWMOut.c | 10 +- ports/esp32s2/common-hal/pwmio/PWMOut.h | 2 +- ports/mimxrt10xx/common-hal/pulseio/PulseIn.c | 246 ------------------ ports/mimxrt10xx/common-hal/pulseio/PulseIn.h | 55 ---- .../mimxrt10xx/common-hal/pulseio/PulseOut.c | 210 --------------- .../mimxrt10xx/common-hal/pulseio/PulseOut.h | 45 ---- .../mimxrt10xx/common-hal/pulseio/__init__.c | 1 - ports/mimxrt10xx/common-hal/pwmio/PWMOut.c | 85 +----- ports/mimxrt10xx/mpconfigport.mk | 3 +- ports/mimxrt10xx/supervisor/port.c | 5 - ports/nrf/common-hal/pulseio/PulseOut.c | 22 +- ports/nrf/common-hal/pulseio/PulseOut.h | 2 +- ports/nrf/common-hal/pwmio/PWMOut.c | 16 +- ports/nrf/common-hal/pwmio/PWMOut.h | 3 +- .../raspberrypi/common-hal/pulseio/PulseOut.c | 47 ++-- .../raspberrypi/common-hal/pulseio/PulseOut.h | 2 +- ports/raspberrypi/common-hal/pwmio/PWMOut.c | 4 + ports/stm/common-hal/pulseio/PulseOut.c | 30 +-- ports/stm/common-hal/pulseio/PulseOut.h | 2 +- ports/stm/common-hal/pwmio/PWMOut.c | 49 ++-- ports/stm/common-hal/pwmio/PWMOut.h | 1 + ports/stm/peripherals/periph.h | 4 +- ports/stm/peripherals/timers.c | 93 ++++--- shared-bindings/pulseio/PulseOut.c | 53 ++-- shared-bindings/pulseio/PulseOut.h | 1 - shared-bindings/pwmio/PWMOut.c | 63 ++--- shared-bindings/pwmio/PWMOut.h | 5 + 35 files changed, 272 insertions(+), 848 deletions(-) delete mode 100644 ports/mimxrt10xx/common-hal/pulseio/PulseIn.c delete mode 100644 ports/mimxrt10xx/common-hal/pulseio/PulseIn.h delete mode 100644 ports/mimxrt10xx/common-hal/pulseio/PulseOut.c delete mode 100644 ports/mimxrt10xx/common-hal/pulseio/PulseOut.h delete mode 100644 ports/mimxrt10xx/common-hal/pulseio/__init__.c diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 9afa77328d..81531c0cbd 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1877,21 +1877,6 @@ msgstr "" msgid "Polygon needs at least 3 points" msgstr "" -#: ports/esp32s2/common-hal/pulseio/PulseOut.c -msgid "" -"Port does not accept PWM carrier. Pass a pin, frequency and duty cycle " -"instead" -msgstr "" - -#: ports/atmel-samd/common-hal/pulseio/PulseOut.c -#: ports/cxd56/common-hal/pulseio/PulseOut.c -#: ports/nrf/common-hal/pulseio/PulseOut.c -#: ports/stm/common-hal/pulseio/PulseOut.c -msgid "" -"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " -"instead" -msgstr "" - #: shared-bindings/_bleio/Adapter.c msgid "Prefix buffer must be on the heap" msgstr "" diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c index 56b5f036ed..b72e0d1f43 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c @@ -103,13 +103,15 @@ void pulseout_reset() { } void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle) { - if (!carrier || pin || frequency) { - mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. Construct and pass a PWMOut Carrier instead")); - } + + pwmout_result_t result = common_hal_pwmio_pwmout_construct( + &self->pwmout, pin, duty_cycle, frequency, false); + + // This will raise an exception and not return if needed. + common_hal_pwmio_pwmout_raise_error(result); if (refcount == 0) { // Find a spare timer. @@ -155,7 +157,7 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, } refcount++; - self->pin = carrier->pin->number; + self->pin = pin->number; PortGroup *const port_base = &PORT->Group[GPIO_PORT(self->pin)]; self->pincfg = &port_base->PINCFG[self->pin % 32]; @@ -173,7 +175,7 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *self) { - return self->pin == NO_PIN; + return common_hal_pwmio_pwmout_deinited(&self->pwmout); } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { @@ -191,6 +193,7 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { pulseout_tc_index = 0xff; } self->pin = NO_PIN; + common_hal_pwmio_pwmout_deinit(&self->pwmout); #ifdef SAMD21 rtc_end_pulse(); #endif diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.h b/ports/atmel-samd/common-hal/pulseio/PulseOut.h index 8f8e504fab..d4a767065e 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseOut.h +++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.h @@ -30,10 +30,12 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" +#include "shared-bindings/pwmio/PWMOut.h" typedef struct { mp_obj_base_t base; __IO PORT_PINCFG_Type *pincfg; + pwmio_pwmout_obj_t pwmout; uint8_t pin; } pulseio_pulseout_obj_t; diff --git a/ports/atmel-samd/common-hal/pwmio/PWMOut.c b/ports/atmel-samd/common-hal/pwmio/PWMOut.c index 815f1a7fe0..4f6661b55d 100644 --- a/ports/atmel-samd/common-hal/pwmio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pwmio/PWMOut.c @@ -493,3 +493,7 @@ uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) { bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) { return self->variable_frequency; } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/cxd56/common-hal/pulseio/PulseOut.c b/ports/cxd56/common-hal/pulseio/PulseOut.c index be0d51f575..5e296a1b1e 100644 --- a/ports/cxd56/common-hal/pulseio/PulseOut.c +++ b/ports/cxd56/common-hal/pulseio/PulseOut.c @@ -58,13 +58,15 @@ static bool pulseout_timer_handler(unsigned int *next_interval_us, void *arg) { } void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle) { - if (!carrier || pin || frequency) { - mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. Construct and pass a PWMOut Carrier instead")); - } + + pwmout_result_t result = common_hal_pwmio_pwmout_construct( + &self->pwmout, pin, duty_cycle, frequency, false); + + // This will raise an exception and not return if needed. + common_hal_pwmio_pwmout_raise_error(result); if (pulse_fd < 0) { pulse_fd = open("/dev/timer0", O_RDONLY); @@ -74,7 +76,7 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, mp_raise_RuntimeError(translate("All timers in use")); } - self->pwm_num = carrier->number; + self->pwm_num = self->pwmout.number; } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { @@ -86,6 +88,8 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { close(pulse_fd); pulse_fd = -1; + common_hal_pwmio_pwmout_deinit(&self->pwmout); + pulse_buffer = NULL; } diff --git a/ports/cxd56/common-hal/pulseio/PulseOut.h b/ports/cxd56/common-hal/pulseio/PulseOut.h index 61bc175276..18106636c1 100644 --- a/ports/cxd56/common-hal/pulseio/PulseOut.h +++ b/ports/cxd56/common-hal/pulseio/PulseOut.h @@ -29,9 +29,12 @@ #include "py/obj.h" +#include "shared-bindings/pwmio/PWMOut.h" + typedef struct { mp_obj_base_t base; uint8_t pwm_num; + pwmio_pwmout_obj_t pwmout; } pulseio_pulseout_obj_t; void pulseout_reset(void); diff --git a/ports/cxd56/common-hal/pwmio/PWMOut.c b/ports/cxd56/common-hal/pwmio/PWMOut.c index 61806540b1..e9bffd21e9 100644 --- a/ports/cxd56/common-hal/pwmio/PWMOut.c +++ b/ports/cxd56/common-hal/pwmio/PWMOut.c @@ -157,3 +157,7 @@ void pwmout_start(uint8_t pwm_num) { void pwmout_stop(uint8_t pwm_num) { ioctl(pwmout_dev[pwm_num].fd, PWMIOC_STOP, 0); } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/esp32s2/common-hal/pulseio/PulseOut.c b/ports/esp32s2/common-hal/pulseio/PulseOut.c index d3490d1810..b762cefb84 100644 --- a/ports/esp32s2/common-hal/pulseio/PulseOut.c +++ b/ports/esp32s2/common-hal/pulseio/PulseOut.c @@ -32,13 +32,9 @@ // Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle) { - if (carrier || !pin || !frequency) { - mp_raise_NotImplementedError(translate("Port does not accept PWM carrier. Pass a pin, frequency and duty cycle instead")); - } rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt(); if (channel == RMT_CHANNEL_MAX) { diff --git a/ports/esp32s2/common-hal/pwmio/PWMOut.c b/ports/esp32s2/common-hal/pwmio/PWMOut.c index 7b3c005ff4..71cf5c19d0 100644 --- a/ports/esp32s2/common-hal/pwmio/PWMOut.c +++ b/ports/esp32s2/common-hal/pwmio/PWMOut.c @@ -152,7 +152,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, varfreq_timers[timer_index] = true; } self->variable_frequency = variable_frequency; - self->pin_number = pin->number; + self->pin = pin; self->deinited = false; self->duty_resolution = duty_bits; claim_pin(pin); @@ -167,7 +167,7 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { never_reset_tim[self->tim_handle.timer_num] = true; never_reset_chan[self->chan_handle.channel] = true; - never_reset_pin_number(self->pin_number); + never_reset_pin_number(self->pin->number); } void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { @@ -202,7 +202,7 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { // if timer isn't varfreq this will be off aleady varfreq_timers[self->tim_handle.timer_num] = false; } - reset_pin_number(self->pin_number); + common_hal_reset_pin(self->pin); self->deinited = true; } @@ -232,3 +232,7 @@ uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) { bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) { return self->variable_frequency; } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/esp32s2/common-hal/pwmio/PWMOut.h b/ports/esp32s2/common-hal/pwmio/PWMOut.h index 9480b8885a..f94325248b 100644 --- a/ports/esp32s2/common-hal/pwmio/PWMOut.h +++ b/ports/esp32s2/common-hal/pwmio/PWMOut.h @@ -34,7 +34,7 @@ typedef struct { mp_obj_base_t base; ledc_timer_config_t tim_handle; ledc_channel_config_t chan_handle; - uint16_t pin_number; + const mcu_pin_obj_t *pin; uint8_t duty_resolution; bool variable_frequency : 1; bool deinited : 1; diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c deleted file mode 100644 index c1f7ce20b6..0000000000 --- a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries - * Copyright (c) 2019 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "common-hal/pulseio/PulseIn.h" - -#include - -#include "background.h" -#include "mpconfigport.h" -#include "py/gc.h" -#include "py/runtime.h" - -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/pulseio/PulseIn.h" -#include "supervisor/shared/translate.h" - -// TODO -// static void pulsein_set_config(pulseio_pulsein_obj_t* self, bool first_edge) { -// uint32_t sense_setting; -// if (!first_edge) { -// sense_setting = EIC_CONFIG_SENSE0_BOTH_Val; -// configure_eic_channel(self->channel, sense_setting); -// return; -// } else if (self->idle_state) { -// sense_setting = EIC_CONFIG_SENSE0_FALL_Val; -// } else { -// sense_setting = EIC_CONFIG_SENSE0_RISE_Val; -// } -// set_eic_handler(self->channel, EIC_HANDLER_PULSEIN); -// turn_on_eic_channel(self->channel, sense_setting); -// } - -// void pulsein_interrupt_handler(uint8_t channel) { -// // Grab the current time first. -// uint32_t current_us; -// uint64_t current_ms; -// current_tick(¤t_ms, ¤t_us); -// -// // current_tick gives us the remaining us until the next tick but we want the number since the -// // last ms. -// current_us = 1000 - current_us; -// pulseio_pulsein_obj_t* self = get_eic_channel_data(channel); -// if (!supervisor_background_tasks_ok() || self->errored_too_fast) { -// self->errored_too_fast = true; -// common_hal_pulseio_pulsein_pause(self); -// return; -// } -// if (self->first_edge) { -// self->first_edge = false; -// pulsein_set_config(self, false); -// } else { -// uint32_t ms_diff = current_ms - self->last_ms; -// uint16_t us_diff = current_us - self->last_us; -// uint32_t total_diff = us_diff; -// if (self->last_us > current_us) { -// total_diff = 1000 + current_us - self->last_us; -// if (ms_diff > 1) { -// total_diff += (ms_diff - 1) * 1000; -// } -// } else { -// total_diff += ms_diff * 1000; -// } -// uint16_t duration = 0xffff; -// if (total_diff < duration) { -// duration = total_diff; -// } -// -// uint16_t i = (self->start + self->len) % self->maxlen; -// self->buffer[i] = duration; -// if (self->len < self->maxlen) { -// self->len++; -// } else { -// self->start++; -// } -// } -// self->last_ms = current_ms; -// self->last_us = current_us; -// } - -void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, - const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { -// if (!pin->has_extint) { -// mp_raise_RuntimeError(translate("No hardware support on pin")); -// } -// if (eic_get_enable() && !eic_channel_free(pin->extint_channel)) { -// mp_raise_RuntimeError(translate("EXTINT channel already in use")); -// } -// -// self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false); -// if (self->buffer == NULL) { -// mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t)); -// } -// self->channel = pin->extint_channel; -// self->pin = pin->number; -// self->maxlen = maxlen; -// self->idle_state = idle_state; -// self->start = 0; -// self->len = 0; -// self->first_edge = true; -// self->last_us = 0; -// self->last_ms = 0; -// self->errored_too_fast = false; -// -// set_eic_channel_data(pin->extint_channel, (void*) self); -// -// // Check to see if the EIC is enabled and start it up if its not.' -// if (eic_get_enable() == 0) { -// turn_on_external_interrupt_controller(); -// } -// -// gpio_set_pin_function(pin->number, GPIO_PIN_FUNCTION_A); -// -// turn_on_cpu_interrupt(self->channel); -// -// claim_pin(pin); -// -// // Set config will enable the EIC. -// pulsein_set_config(self, true); -} - -bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t *self) { -// return self->pin == NO_PIN; - return true; -} - -void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t *self) { -// if (common_hal_pulseio_pulsein_deinited(self)) { -// return; -// } -// set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT); -// turn_off_eic_channel(self->channel); -// reset_pin_number(self->pin); -// self->pin = NO_PIN; -} - -void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t *self) { -// uint32_t mask = 1 << self->channel; -// EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos; -} - -void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t *self, - uint16_t trigger_duration) { -// // Make sure we're paused. -// common_hal_pulseio_pulsein_pause(self); -// -// // Reset erroring -// self->errored_too_fast = false; -// -// // Send the trigger pulse. -// if (trigger_duration > 0) { -// gpio_set_pin_pull_mode(self->pin, GPIO_PULL_OFF); -// gpio_set_pin_direction(self->pin, GPIO_DIRECTION_OUT); -// gpio_set_pin_level(self->pin, !self->idle_state); -// common_hal_mcu_delay_us((uint32_t)trigger_duration); -// gpio_set_pin_level(self->pin, self->idle_state); -// } -// -// // Reconfigure the pin and make sure its set to detect the first edge. -// self->first_edge = true; -// self->last_ms = 0; -// self->last_us = 0; -// gpio_set_pin_function(self->pin, GPIO_PIN_FUNCTION_A); -// uint32_t mask = 1 << self->channel; -// // Clear previous interrupt state and re-enable it. -// EIC->INTFLAG.reg = mask << EIC_INTFLAG_EXTINT_Pos; -// EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos; -// -// pulsein_set_config(self, true); -} - -void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t *self) { -// common_hal_mcu_disable_interrupts(); -// self->start = 0; -// self->len = 0; -// common_hal_mcu_enable_interrupts(); -} - -uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t *self) { -// if (self->len == 0) { -// mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); -// } -// common_hal_mcu_disable_interrupts(); -// uint16_t value = self->buffer[self->start]; -// self->start = (self->start + 1) % self->maxlen; -// self->len--; -// common_hal_mcu_enable_interrupts(); -// -// return value; - return 0; -} - -uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t *self) { -// return self->maxlen; - return 0; -} - -uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t *self) { -// return self->len; - return 0; -} - -bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t *self) { -// uint32_t mask = 1 << self->channel; -// return (EIC->INTENSET.reg & (mask << EIC_INTENSET_EXTINT_Pos)) == 0; - return true; -} - -uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t *self, - int16_t index) { -// common_hal_mcu_disable_interrupts(); -// if (index < 0) { -// index += self->len; -// } -// if (index < 0 || index >= self->len) { -// common_hal_mcu_enable_interrupts(); -// mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); -// } -// uint16_t value = self->buffer[(self->start + index) % self->maxlen]; -// common_hal_mcu_enable_interrupts(); -// return value; - return 0; -} diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.h b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.h deleted file mode 100644 index cce4f58ca7..0000000000 --- a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * Copyright (c) 2019 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PULSEIO_PULSEIN_H -#define MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PULSEIO_PULSEIN_H - -#include "common-hal/microcontroller/Pin.h" - -#include "py/obj.h" - -// TODO -typedef struct { - mp_obj_base_t base; -// uint8_t channel; -// uint8_t pin; -// uint16_t* buffer; -// uint16_t maxlen; -// bool idle_state; -// volatile uint16_t start; -// volatile uint16_t len; -// volatile bool first_edge; -// volatile uint64_t last_ms; -// volatile uint16_t last_us; -// volatile bool errored_too_fast; -} pulseio_pulsein_obj_t; - -// void pulsein_reset(void); -// -// void pulsein_interrupt_handler(uint8_t channel); - -#endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PULSEIO_PULSEIN_H diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c b/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c deleted file mode 100644 index b38f6f093f..0000000000 --- a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George - * Copyright (c) 2019 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "common-hal/pulseio/PulseOut.h" - -#include - -#include "mpconfigport.h" -#include "py/gc.h" -#include "py/runtime.h" -#include "shared-bindings/pulseio/PulseOut.h" -#include "supervisor/shared/translate.h" - -// TODO - -// This timer is shared amongst all PulseOut objects under the assumption that -// the code is single threaded. -// static uint8_t refcount = 0; -// -// static uint8_t pulseout_tc_index = 0xff; -// -// static __IO PORT_PINCFG_Type *active_pincfg = NULL; -// static uint16_t *pulse_buffer = NULL; -// static volatile uint16_t pulse_index = 0; -// static uint16_t pulse_length; -// static volatile uint32_t current_compare = 0; -// -// static void turn_on(__IO PORT_PINCFG_Type * pincfg) { -// pincfg->reg = PORT_PINCFG_PMUXEN; -// } -// -// static void turn_off(__IO PORT_PINCFG_Type * pincfg) { -// pincfg->reg = PORT_PINCFG_RESETVALUE; -// } -// -// void pulse_finish(void) { -// pulse_index++; -// -// if (active_pincfg == NULL) { -// return; -// } -// // Always turn it off. -// turn_off(active_pincfg); -// if (pulse_index >= pulse_length) { -// return; -// } -// current_compare = (current_compare + pulse_buffer[pulse_index] * 3 / 4) & 0xffff; -// Tc* tc = tc_insts[pulseout_tc_index]; -// tc->COUNT16.CC[0].reg = current_compare; -// if (pulse_index % 2 == 0) { -// turn_on(active_pincfg); -// } -// } - -void pulseout_interrupt_handler(uint8_t index) { -// if (index != pulseout_tc_index) return; -// Tc* tc = tc_insts[index]; -// if (!tc->COUNT16.INTFLAG.bit.MC0) return; -// -// pulse_finish(); -// -// // Clear the interrupt bit. -// tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; -} - -void pulseout_reset() { -// refcount = 0; -// pulseout_tc_index = 0xff; -// active_pincfg = NULL; -} - -void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, - const mcu_pin_obj_t *pin, - uint32_t frequency, - uint16_t duty_cycle) { -// if (refcount == 0) { -// // Find a spare timer. -// Tc *tc = NULL; -// int8_t index = TC_INST_NUM - 1; -// for (; index >= 0; index--) { -// if (tc_insts[index]->COUNT16.CTRLA.bit.ENABLE == 0) { -// tc = tc_insts[index]; -// break; -// } -// } -// if (tc == NULL) { -// mp_raise_RuntimeError(translate("All timers in use")); -// } -// -// pulseout_tc_index = index; -// -// set_timer_handler(true, index, TC_HANDLER_PULSEOUT); -// // We use GCLK0 for SAMD21 and GCLK1 for SAMD51 because they both run at 48mhz making our -// // math the same across the boards. -// #ifdef SAMD21 -// turn_on_clocks(true, index, 0); -// #endif -// #ifdef SAMD51 -// turn_on_clocks(true, index, 1); -// #endif -// -// -// #ifdef SAMD21 -// tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | -// TC_CTRLA_PRESCALER_DIV64 | -// TC_CTRLA_WAVEGEN_NFRQ; -// #endif -// #ifdef SAMD51 -// tc_reset(tc); -// tc_set_enable(tc, false); -// tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_PRESCALER_DIV64; -// tc->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_NFRQ; -// #endif -// -// tc_set_enable(tc, true); -// tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP; -// } -// refcount++; -// -// self->pin = carrier->pin->number; -// -// PortGroup *const port_base = &PORT->Group[GPIO_PORT(self->pin)]; -// self->pincfg = &port_base->PINCFG[self->pin % 32]; -// -// // Set the port to output a zero. -// port_base->OUTCLR.reg = 1 << (self->pin % 32); -// port_base->DIRSET.reg = 1 << (self->pin % 32); -// -// // Turn off the pinmux which should connect the port output. -// turn_off(self->pincfg); -} - -bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *self) { -// return self->pin == NO_PIN; - return false; -} - -void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { -// if (common_hal_pulseio_pulseout_deinited(self)) { -// return; -// } -// PortGroup *const port_base = &PORT->Group[GPIO_PORT(self->pin)]; -// port_base->DIRCLR.reg = 1 << (self->pin % 32); -// -// turn_on(self->pincfg); -// -// refcount--; -// if (refcount == 0) { -// tc_reset(tc_insts[pulseout_tc_index]); -// pulseout_tc_index = 0xff; -// } -// self->pin = NO_PIN; -} - -void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t *self, uint16_t *pulses, uint16_t length) { -// if (active_pincfg != NULL) { -// mp_raise_RuntimeError(translate("Another send is already active")); -// } -// active_pincfg = self->pincfg; -// pulse_buffer = pulses; -// pulse_index = 0; -// pulse_length = length; -// -// current_compare = pulses[0] * 3 / 4; -// Tc* tc = tc_insts[pulseout_tc_index]; -// tc->COUNT16.CC[0].reg = current_compare; -// -// // Clear our interrupt in case it was set earlier -// tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; -// tc->COUNT16.INTENSET.reg = TC_INTENSET_MC0; -// tc_enable_interrupts(pulseout_tc_index); -// turn_on(active_pincfg); -// tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER; -// -// while(pulse_index < length) { -// // Do other things while we wait. The interrupts will handle sending the -// // signal. -// RUN_BACKGROUND_TASKS; -// } -// -// tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP; -// tc->COUNT16.INTENCLR.reg = TC_INTENCLR_MC0; -// tc_disable_interrupts(pulseout_tc_index); -// active_pincfg = NULL; -} diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.h b/ports/mimxrt10xx/common-hal/pulseio/PulseOut.h deleted file mode 100644 index da022b738d..0000000000 --- a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * Copyright (c) 2019 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PULSEIO_PULSEOUT_H -#define MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PULSEIO_PULSEOUT_H - -#include "common-hal/microcontroller/Pin.h" - -#include "py/obj.h" - -// TODO -typedef struct { - mp_obj_base_t base; -// __IO PORT_PINCFG_Type *pincfg; -// uint8_t pin; -} pulseio_pulseout_obj_t; - -void pulseout_reset(void); -// void pulseout_interrupt_handler(uint8_t index); - -#endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PULSEIO_PULSEOUT_H diff --git a/ports/mimxrt10xx/common-hal/pulseio/__init__.c b/ports/mimxrt10xx/common-hal/pulseio/__init__.c deleted file mode 100644 index 2bee925bc7..0000000000 --- a/ports/mimxrt10xx/common-hal/pulseio/__init__.c +++ /dev/null @@ -1 +0,0 @@ -// No pulseio module functions. diff --git a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c index d48bda7cd1..8eb3251bf3 100644 --- a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c +++ b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c @@ -56,97 +56,16 @@ static void config_periph_pin(const mcu_pwm_obj_t *periph) { | IOMUXC_SW_PAD_CTL_PAD_DSE(6) | IOMUXC_SW_PAD_CTL_PAD_SRE(0)); } -// TODO -// #include "samd/pins.h" - -// #undef ENABLE -// -// # define _TCC_SIZE(unused, n) TCC ## n ## _SIZE, -// # define TCC_SIZES { REPEAT_MACRO(_TCC_SIZE, 0, TCC_INST_NUM) } -// -// static uint32_t tcc_periods[TCC_INST_NUM]; -// static uint32_t tc_periods[TC_INST_NUM]; -// -// uint32_t target_tcc_frequencies[TCC_INST_NUM]; -// uint8_t tcc_refcount[TCC_INST_NUM]; -// -//// This bitmask keeps track of which channels of a TCC are currently claimed. -// #ifdef SAMD21 -// uint8_t tcc_channels[3]; // Set by pwmout_reset() to {0xf0, 0xfc, 0xfc} initially. -// #endif -// #ifdef SAMD51 -// uint8_t tcc_channels[5]; // Set by pwmout_reset() to {0xc0, 0xf0, 0xf8, 0xfc, 0xfc} initially. -// #endif -// -// static uint8_t never_reset_tc_or_tcc[TC_INST_NUM + TCC_INST_NUM]; void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { -// if (self->timer->is_tc) { -// never_reset_tc_or_tcc[self->timer->index] += 1; -// } else { -// never_reset_tc_or_tcc[TC_INST_NUM + self->timer->index] += 1; -// } -// -// never_reset_pin_number(self->pin->number); } void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { -// if (self->timer->is_tc) { -// never_reset_tc_or_tcc[self->timer->index] -= 1; -// } else { -// never_reset_tc_or_tcc[TC_INST_NUM + self->timer->index] -= 1; -// } } void pwmout_reset(void) { -// // Reset all timers -// for (int i = 0; i < TCC_INST_NUM; i++) { -// target_tcc_frequencies[i] = 0; -// tcc_refcount[i] = 0; -// } -// Tcc *tccs[TCC_INST_NUM] = TCC_INSTS; -// for (int i = 0; i < TCC_INST_NUM; i++) { -// if (never_reset_tc_or_tcc[TC_INST_NUM + i] > 0) { -// continue; -// } -// // Disable the module before resetting it. -// if (tccs[i]->CTRLA.bit.ENABLE == 1) { -// tccs[i]->CTRLA.bit.ENABLE = 0; -// while (tccs[i]->SYNCBUSY.bit.ENABLE == 1) { -// } -// } -// uint8_t mask = 0xff; -// for (uint8_t j = 0; j < tcc_cc_num[i]; j++) { -// mask <<= 1; -// } -// tcc_channels[i] = mask; -// tccs[i]->CTRLA.bit.SWRST = 1; -// while (tccs[i]->CTRLA.bit.SWRST == 1) { -// } -// } -// Tc *tcs[TC_INST_NUM] = TC_INSTS; -// for (int i = 0; i < TC_INST_NUM; i++) { -// if (never_reset_tc_or_tcc[i] > 0) { -// continue; -// } -// tcs[i]->COUNT16.CTRLA.bit.SWRST = 1; -// while (tcs[i]->COUNT16.CTRLA.bit.SWRST == 1) { -// } -// } } -// static uint8_t tcc_channel(const pin_timer_t* t) { -// // For the SAMD51 this hardcodes the use of OTMX == 0x0, the output matrix mapping, which uses -// // SAMD21-style modulo mapping. -// return t->wave_output % tcc_cc_num[t->index]; -// } - -// bool channel_ok(const pin_timer_t* t) { -// uint8_t channel_bit = 1 << tcc_channel(t); -// return (!t->is_tc && ((tcc_channels[t->index] & channel_bit) == 0)) || -// t->is_tc; -// } - #define PWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_IpgClk) static int calculate_pulse_count(uint32_t frequency, uint8_t *prescaler) { @@ -325,3 +244,7 @@ uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) { bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) { return self->variable_frequency; } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/mimxrt10xx/mpconfigport.mk b/ports/mimxrt10xx/mpconfigport.mk index ac5e7fc8ed..3f4d9d4b7f 100644 --- a/ports/mimxrt10xx/mpconfigport.mk +++ b/ports/mimxrt10xx/mpconfigport.mk @@ -24,10 +24,11 @@ INTERNAL_FLASH_FILESYSTEM = 1 CIRCUITPY_AUDIOIO = 0 CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_BUSDEVICE = 1 +CIRCUITPY_COUNTIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 CIRCUITPY_NVM = 0 +CIRCUITPY_PULSEIO = 0 CIRCUITPY_ROTARYIO = 0 -CIRCUITPY_COUNTIO = 0 CIRCUITPY_USB_MIDI = 1 LONGINT_IMPL = MPZ diff --git a/ports/mimxrt10xx/supervisor/port.c b/ports/mimxrt10xx/supervisor/port.c index 2493252d78..08322873bd 100644 --- a/ports/mimxrt10xx/supervisor/port.c +++ b/ports/mimxrt10xx/supervisor/port.c @@ -37,8 +37,6 @@ #include "fsl_device_registers.h" #include "common-hal/microcontroller/Pin.h" -#include "common-hal/pulseio/PulseIn.h" -#include "common-hal/pulseio/PulseOut.h" #include "common-hal/pwmio/PWMOut.h" #include "common-hal/rtc/RTC.h" #include "common-hal/busio/SPI.h" @@ -289,9 +287,6 @@ void reset_port(void) { // eic_reset(); - #if CIRCUITPY_PULSEIO - pulseout_reset(); - #endif #if CIRCUITPY_PWMIO pwmout_reset(); #endif diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c index 17f498ba8e..1c3c317a05 100644 --- a/ports/nrf/common-hal/pulseio/PulseOut.c +++ b/ports/nrf/common-hal/pulseio/PulseOut.c @@ -48,14 +48,14 @@ static volatile uint16_t pulse_array_index = 0; static uint16_t pulse_array_length; static void turn_on(pulseio_pulseout_obj_t *pulseout) { - pulseout->pwmout->pwm->PSEL.OUT[0] = pulseout->pwmout->pin_number; + pulseout->pwmout.pwm->PSEL.OUT[0] = pulseout->pwmout.pin->number; } static void turn_off(pulseio_pulseout_obj_t *pulseout) { // Disconnect pin from PWM. - pulseout->pwmout->pwm->PSEL.OUT[0] = 0xffffffff; + pulseout->pwmout.pwm->PSEL.OUT[0] = 0xffffffff; // Make sure pin is low. - nrf_gpio_pin_clear(pulseout->pwmout->pin_number); + nrf_gpio_pin_clear(pulseout->pwmout.pin->number); } static void start_timer(void) { @@ -100,13 +100,15 @@ void pulseout_reset() { } void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle) { - if (!carrier || pin || frequency) { - mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. Construct and pass a PWMOut Carrier instead")); - } + + pwmout_result_t result = common_hal_pwmio_pwmout_construct( + &self->pwmout, pin, duty_cycle, frequency, false); + + // This will raise an exception and not return if needed. + common_hal_pwmio_pwmout_raise_error(result); if (refcount == 0) { timer = nrf_peripherals_allocate_timer_or_throw(); @@ -122,14 +124,12 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, .p_context = self, }; - self->pwmout = carrier; - nrfx_timer_init(timer, &timer_config, &pulseout_event_handler); turn_off(self); } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *self) { - return self->pwmout == NULL; + return common_hal_pwmio_pwmout_deinited(&self->pwmout); } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { @@ -137,7 +137,7 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { return; } turn_on(self); - self->pwmout = NULL; + common_hal_pwmio_pwmout_deinit(&self->pwmout); refcount--; if (refcount == 0) { diff --git a/ports/nrf/common-hal/pulseio/PulseOut.h b/ports/nrf/common-hal/pulseio/PulseOut.h index 714f740b20..03560bceac 100644 --- a/ports/nrf/common-hal/pulseio/PulseOut.h +++ b/ports/nrf/common-hal/pulseio/PulseOut.h @@ -34,7 +34,7 @@ typedef struct { mp_obj_base_t base; - const pwmio_pwmout_obj_t *pwmout; + pwmio_pwmout_obj_t pwmout; } pulseio_pulseout_obj_t; void pulseout_reset(void); diff --git a/ports/nrf/common-hal/pwmio/PWMOut.c b/ports/nrf/common-hal/pwmio/PWMOut.c index e49214631b..6dd4a153b8 100644 --- a/ports/nrf/common-hal/pwmio/PWMOut.c +++ b/ports/nrf/common-hal/pwmio/PWMOut.c @@ -74,7 +74,7 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { } } - never_reset_pin_number(self->pin_number); + common_hal_never_reset_pin(self->pin); } void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { @@ -232,14 +232,14 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, } self->channel = channel; - self->pin_number = pin->number; + self->pin = pin; claim_pin(pin); self->frequency = frequency; self->variable_frequency = variable_frequency; // Note this is standard, not strong drive. - nrf_gpio_cfg_output(self->pin_number); + nrf_gpio_cfg_output(self->pin->number); // disable before mapping pin channel nrf_pwm_disable(self->pwm); @@ -267,15 +267,15 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { return; } - nrf_gpio_cfg_default(self->pin_number); + nrf_gpio_cfg_default(self->pin->number); NRF_PWM_Type *pwm = self->pwm; self->pwm = NULL; pwmout_free_channel(pwm, self->channel); - reset_pin_number(self->pin_number); - self->pin_number = NO_PIN; + common_hal_reset_pin(self->pin); + self->pin = NULL; } void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uint16_t duty_cycle) { @@ -313,3 +313,7 @@ uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) { bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) { return self->variable_frequency; } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/nrf/common-hal/pwmio/PWMOut.h b/ports/nrf/common-hal/pwmio/PWMOut.h index f96c5e4f81..49e67c3b66 100644 --- a/ports/nrf/common-hal/pwmio/PWMOut.h +++ b/ports/nrf/common-hal/pwmio/PWMOut.h @@ -29,13 +29,14 @@ #include "nrfx_pwm.h" #include "py/obj.h" +#include "shared-bindings/microcontroller/Pin.h" typedef struct { mp_obj_base_t base; NRF_PWM_Type *pwm; - uint8_t pin_number; uint8_t channel : 7; bool variable_frequency : 1; + const mcu_pin_obj_t *pin; uint16_t duty_cycle; uint32_t frequency; } pwmio_pwmout_obj_t; diff --git a/ports/raspberrypi/common-hal/pulseio/PulseOut.c b/ports/raspberrypi/common-hal/pulseio/PulseOut.c index 4e403fa020..38a4859c2b 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseOut.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseOut.c @@ -42,23 +42,28 @@ static uint8_t refcount = 0; volatile alarm_id_t cur_alarm = 0; void turn_off(uint8_t slice) { - pwm_hw->slice[slice].ctr = 0; - pwm_hw->slice[slice].cc = 0; - pwm_hw->slice[slice].top = 0; - pwm_hw->slice[slice].div = 1u << PWM_CH0_DIV_INT_LSB; + // Set the current counter value near the top so that the output is low. The + // - 2 gives us a little wiggle room for enabling and disabling the slice. + // The top + 1 ensure we don't end up lower than the cc (and therefore high.) + uint32_t top = MAX(pwm_hw->slice[slice].cc + 1, pwm_hw->slice[slice].top - 2); + // Disable interrupts so this happens as fast as possible. + common_hal_mcu_disable_interrupts(); + pwm_hw->slice[slice].ctr = top; + // Enable for at least one cycle so that the new counter value takes effect. pwm_hw->slice[slice].csr = PWM_CH0_CSR_EN_BITS; pwm_hw->slice[slice].csr = 0; + common_hal_mcu_enable_interrupts(); } void pulse_finish(pulseio_pulseout_obj_t *self) { self->pulse_index++; // Turn pwm pin off by setting duty cyle to 1. - common_hal_pwmio_pwmout_set_duty_cycle(self->carrier,1); + common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, 1); if (self->pulse_index >= self->pulse_length) { return; } if (self->pulse_index % 2 == 0) { - common_hal_pwmio_pwmout_set_duty_cycle(self->carrier,self->current_duty_cycle); + common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, self->current_duty_cycle); } uint64_t delay = self->pulse_buffer[self->pulse_index]; if (delay < self->min_pulse) { @@ -78,24 +83,26 @@ int64_t pulseout_interrupt_handler(alarm_id_t id, void *user_data) { } void pulseout_reset() { - refcount = 0; } void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle) { - refcount++; - self->carrier = (pwmio_pwmout_obj_t *)carrier; - self->current_duty_cycle = common_hal_pwmio_pwmout_get_duty_cycle(self->carrier); - pwm_set_enabled(self->carrier->slice,false); - turn_off(self->carrier->slice); - common_hal_pwmio_pwmout_set_duty_cycle(self->carrier,1); - self->pin = self->carrier->pin->number; - self->slice = self->carrier->slice; - self->min_pulse = (1000000 / self->carrier->actual_frequency); + pwmout_result_t result = common_hal_pwmio_pwmout_construct( + &self->carrier, pin, duty_cycle, frequency, false); + + // This will raise an exception and not return if needed. + common_hal_pwmio_pwmout_raise_error(result); + + self->current_duty_cycle = duty_cycle; + pwm_set_enabled(self->carrier.slice, false); + turn_off(self->carrier.slice); + common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, 1); + self->pin = self->carrier.pin->number; + self->slice = self->carrier.slice; + self->min_pulse = (1000000 / self->carrier.actual_frequency); } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *self) { @@ -106,7 +113,7 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { if (common_hal_pulseio_pulseout_deinited(self)) { return; } - refcount--; + common_hal_pwmio_pwmout_deinit(&self->carrier); self->pin = NO_PIN; } @@ -115,8 +122,8 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t *self, uint16_t *pu self->pulse_index = 0; self->pulse_length = length; - common_hal_pwmio_pwmout_set_duty_cycle(self->carrier,self->current_duty_cycle); - pwm_set_enabled(self->slice,true); + common_hal_pwmio_pwmout_set_duty_cycle(&self->carrier, self->current_duty_cycle); + pwm_set_enabled(self->slice, true); uint64_t delay = self->pulse_buffer[0]; if (delay < self->min_pulse) { delay = self->min_pulse; diff --git a/ports/raspberrypi/common-hal/pulseio/PulseOut.h b/ports/raspberrypi/common-hal/pulseio/PulseOut.h index 49a14f3a51..cf4645cc1f 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseOut.h +++ b/ports/raspberrypi/common-hal/pulseio/PulseOut.h @@ -39,7 +39,7 @@ typedef struct { mp_obj_base_t base; uint8_t pin; uint8_t slice; - pwmio_pwmout_obj_t *carrier; + pwmio_pwmout_obj_t carrier; uint16_t *pulse_buffer; uint16_t pulse_length; uint16_t current_duty_cycle; diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index 5215f2b8df..f5e93f517e 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -292,3 +292,7 @@ uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) { bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) { return self->variable_frequency; } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/stm/common-hal/pulseio/PulseOut.c b/ports/stm/common-hal/pulseio/PulseOut.c index 9e28002a69..fe3caa08b2 100644 --- a/ports/stm/common-hal/pulseio/PulseOut.c +++ b/ports/stm/common-hal/pulseio/PulseOut.c @@ -52,15 +52,15 @@ STATIC pulseio_pulseout_obj_t *curr_pulseout = NULL; STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) { // Turn on PWM - HAL_TIM_PWM_Start(&(pulseout->pwmout->handle), pulseout->pwmout->channel); + HAL_TIM_PWM_Start(&(pulseout->pwmout.handle), pulseout->pwmout.channel); } STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) { // Turn off PWM - HAL_TIM_PWM_Stop(&(pulseout->pwmout->handle), pulseout->pwmout->channel); + HAL_TIM_PWM_Stop(&(pulseout->pwmout.handle), pulseout->pwmout.channel); // Make sure pin is low. - HAL_GPIO_WritePin(pin_port(pulseout->pwmout->tim->pin->port), - pin_mask(pulseout->pwmout->tim->pin->number), 0); + HAL_GPIO_WritePin(pin_port(pulseout->pwmout.tim->pin->port), + pin_mask(pulseout->pwmout.tim->pin->number), 0); } STATIC void start_timer(void) { @@ -80,7 +80,7 @@ STATIC void pulseout_event_handler(void) { if (__HAL_TIM_GET_FLAG(&tim_handle, TIM_FLAG_UPDATE) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET) { __HAL_TIM_CLEAR_IT(&tim_handle, TIM_IT_UPDATE); - if (curr_pulseout->pwmout == NULL) { + if (common_hal_pulseio_pulseout_deinited(curr_pulseout)) { return; // invalid interrupt } @@ -111,13 +111,12 @@ void pulseout_reset() { } void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, - const mcu_pin_obj_t *pin, - uint32_t frequency, - uint16_t duty_cycle) { - if (!carrier || pin || frequency) { - mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. Construct and pass a PWMOut Carrier instead")); - } + const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle) { + pwmout_result_t result = common_hal_pwmio_pwmout_construct( + &self->pwmout, pin, duty_cycle, frequency, false); + + // This will raise an exception and not return if needed. + common_hal_pwmio_pwmout_raise_error(result); // Add to active PulseOuts refcount++; @@ -139,13 +138,12 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, HAL_TIM_Base_Init(&tim_handle); tim_handle.Instance->SR = 0; - // The HAL can't work with const, recast required. - self->pwmout = (pwmio_pwmout_obj_t *)carrier; + turn_off(self); } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *self) { - return self->pwmout == NULL; + return common_hal_pwmio_pwmout_deinited(&self->pwmout); } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { @@ -153,7 +151,7 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { return; } turn_on(self); - self->pwmout = NULL; + common_hal_pwmio_pwmout_deinit(&self->pwmout); refcount--; if (refcount == 0) { diff --git a/ports/stm/common-hal/pulseio/PulseOut.h b/ports/stm/common-hal/pulseio/PulseOut.h index 29894f27d2..3a0c460ff7 100644 --- a/ports/stm/common-hal/pulseio/PulseOut.h +++ b/ports/stm/common-hal/pulseio/PulseOut.h @@ -34,7 +34,7 @@ typedef struct { mp_obj_base_t base; - pwmio_pwmout_obj_t *pwmout; + pwmio_pwmout_obj_t pwmout; } pulseio_pulseout_obj_t; void pulseout_reset(void); diff --git a/ports/stm/common-hal/pwmio/PWMOut.c b/ports/stm/common-hal/pwmio/PWMOut.c index 17ef82a060..e5dc18cd79 100644 --- a/ports/stm/common-hal/pwmio/PWMOut.c +++ b/ports/stm/common-hal/pwmio/PWMOut.c @@ -89,8 +89,8 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, for (uint i = 0; i < tim_num; i++) { const mcu_tim_pin_obj_t *l_tim = &mcu_tim_pin_list[i]; - uint8_t l_tim_index = l_tim->tim_index - 1; - uint8_t l_tim_channel = l_tim->channel_index - 1; + uint8_t l_tim_index = l_tim->tim_index; + uint8_t l_tim_channel = l_tim->channel_index; // if pin is same if (l_tim->pin == pin) { @@ -127,14 +127,14 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, // handle valid/invalid timer instance if (self->tim != NULL) { // create instance - TIMx = mcu_tim_banks[self->tim->tim_index - 1]; + TIMx = mcu_tim_banks[self->tim->tim_index]; // reserve timer/channel if (variable_frequency) { - reserved_tim[self->tim->tim_index - 1] = 0x0F; + reserved_tim[self->tim->tim_index] = 0x0F; } else { - reserved_tim[self->tim->tim_index - 1] |= 1 << (self->tim->channel_index - 1); + reserved_tim[self->tim->tim_index] |= 1 << self->tim->channel_index; } - tim_frequencies[self->tim->tim_index - 1] = frequency; + tim_frequencies[self->tim->tim_index] = frequency; stm_peripherals_timer_reserve(TIMx); } else { // no match found if (tim_chan_taken || tim_taken_internal) { @@ -148,6 +148,13 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, } } + uint32_t prescaler = 0; // prescaler is 15 bit + uint32_t period = 0; // period is 16 bit + uint32_t source_freq = stm_peripherals_timer_get_source_freq(TIMx); + if (!timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq)) { + return PWMOUT_INVALID_FREQUENCY; + } + GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = pin_mask(pin->number); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; @@ -155,18 +162,12 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = self->tim->altfn_index; HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); + self->pin = pin; - tim_clock_enable(1 << (self->tim->tim_index - 1)); + tim_clock_enable(1 << (self->tim->tim_index)); // translate channel into handle value - self->channel = 4 * (self->tim->channel_index - 1); - - uint32_t prescaler = 0; // prescaler is 15 bit - uint32_t period = 0; // period is 16 bit - uint32_t source_freq = stm_peripherals_timer_get_source_freq(TIMx); - if (!timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq)) { - return PWMOUT_INVALID_FREQUENCY; - } + self->channel = 4 * self->tim->channel_index; // Timer init self->handle.Instance = TIMx; @@ -207,7 +208,7 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { for (size_t i = 0; i < TIM_BANK_ARRAY_LEN; i++) { if (mcu_tim_banks[i] == self->handle.Instance) { never_reset_tim[i] = true; - never_reset_pin_number(self->tim->pin->port, self->tim->pin->number); + common_hal_never_reset_pin(self->pin); break; } } @@ -232,16 +233,16 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { } // var freq shuts down entire timer, others just their channel if (self->variable_frequency) { - reserved_tim[self->tim->tim_index - 1] = 0x00; + reserved_tim[self->tim->tim_index] = 0x00; } else { - reserved_tim[self->tim->tim_index - 1] &= ~(1 << self->tim->channel_index); + reserved_tim[self->tim->tim_index] &= ~(1 << self->tim->channel_index); HAL_TIM_PWM_Stop(&self->handle, self->channel); } - reset_pin_number(self->tim->pin->port,self->tim->pin->number); + common_hal_reset_pin(self->pin); // if reserved timer has no active channels, we can disable it - if (!reserved_tim[self->tim->tim_index - 1]) { - tim_frequencies[self->tim->tim_index - 1] = 0x00; + if (reserved_tim[self->tim->tim_index] == 0) { + tim_frequencies[self->tim->tim_index] = 0x00; stm_peripherals_timer_free(self->handle.Instance); } @@ -290,7 +291,7 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t *self, uint32_t fr mp_raise_ValueError(translate("Could not restart PWM")); } - tim_frequencies[self->tim->tim_index - 1] = frequency; + tim_frequencies[self->tim->tim_index] = frequency; self->frequency = frequency; self->period = period; } @@ -302,3 +303,7 @@ uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) { bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) { return self->variable_frequency; } + +const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) { + return self->pin; +} diff --git a/ports/stm/common-hal/pwmio/PWMOut.h b/ports/stm/common-hal/pwmio/PWMOut.h index 4cf2b1c670..de3a304721 100644 --- a/ports/stm/common-hal/pwmio/PWMOut.h +++ b/ports/stm/common-hal/pwmio/PWMOut.h @@ -44,6 +44,7 @@ typedef struct { uint16_t duty_cycle; uint32_t frequency; uint32_t period; + const mcu_pin_obj_t *pin; } pwmio_pwmout_obj_t; void pwmout_reset(void); diff --git a/ports/stm/peripherals/periph.h b/ports/stm/peripherals/periph.h index 488541d096..d9e65c2172 100644 --- a/ports/stm/peripherals/periph.h +++ b/ports/stm/peripherals/periph.h @@ -59,9 +59,9 @@ typedef struct { #define TIM(index, alt, channel, tim_pin) \ { \ - .tim_index = index, \ + .tim_index = index - 1, \ .altfn_index = alt, \ - .channel_index = channel, \ + .channel_index = channel - 1, \ .pin = tim_pin, \ } diff --git a/ports/stm/peripherals/timers.c b/ports/stm/peripherals/timers.c index 6121deab16..24060678e4 100644 --- a/ports/stm/peripherals/timers.c +++ b/ports/stm/peripherals/timers.c @@ -41,8 +41,12 @@ static bool stm_timer_reserved[MP_ARRAY_SIZE(mcu_tim_banks)]; static bool stm_timer_never_reset[MP_ARRAY_SIZE(mcu_tim_banks)]; -static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); - static size_t irq_map[] = { + +typedef void (*stm_timer_callback_t)(void); +// Array of function pointers. +static stm_timer_callback_t stm_timer_callback[MP_ARRAY_SIZE(mcu_tim_banks)]; + +static size_t irq_map[] = { #ifdef TIM1 TIM1_CC_IRQn, #else @@ -139,7 +143,7 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); // If the APB prescaler is 1, then the timer clock is equal to its respective // APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its // respective APB clock. See DM00031020 Rev 4, page 115. - uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef *timer) { +uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef *timer) { size_t tim_id = stm_peripherals_timer_get_index(timer); uint32_t source, clk_div; if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { @@ -158,12 +162,12 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); return source; } - size_t stm_peripherals_timer_get_irqnum(TIM_TypeDef *instance) { +size_t stm_peripherals_timer_get_irqnum(TIM_TypeDef *instance) { size_t tim_id = stm_peripherals_timer_get_index(instance); return irq_map[tim_id]; } - void timers_reset(void) { +void timers_reset(void) { uint16_t never_reset_mask = 0x00; for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) { if (!stm_timer_never_reset[i]) { @@ -175,14 +179,14 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask)); } - TIM_TypeDef *stm_peripherals_find_timer(void) { +TIM_TypeDef *stm_peripherals_find_timer(void) { // Check for timers on pins outside the package size for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) { bool timer_in_package = false; // Find each timer instance on the given bank for (size_t j = 0; j < MP_ARRAY_SIZE(mcu_tim_pin_list); j++) { // If a pin is claimed, we skip it - if ((mcu_tim_pin_list[j].tim_index == i + 1) + if ((mcu_tim_pin_list[j].tim_index == i) && (common_hal_mcu_pin_is_free(mcu_tim_pin_list[j].pin) == true)) { // Search whether any pins in the package array match it for (size_t k = 0; k < mcu_pin_globals.map.alloc; k++) { @@ -210,7 +214,7 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); return NULL; } - void stm_peripherals_timer_preinit(TIM_TypeDef *instance, uint8_t prio, void (*callback)(void)) { +void stm_peripherals_timer_preinit(TIM_TypeDef *instance, uint8_t prio, void (*callback)(void)) { size_t tim_idx = stm_peripherals_timer_get_index(instance); stm_timer_callback[tim_idx] = callback; tim_clock_enable(1 << tim_idx); @@ -218,16 +222,16 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); HAL_NVIC_EnableIRQ(irq_map[tim_idx]); } - void stm_peripherals_timer_reserve(TIM_TypeDef *instance) { +void stm_peripherals_timer_reserve(TIM_TypeDef *instance) { size_t tim_idx = stm_peripherals_timer_get_index(instance); stm_timer_reserved[tim_idx] = true; } - void stm_peripherals_timer_set_callback(void (*callback)(void), TIM_TypeDef *timer) { +void stm_peripherals_timer_set_callback(void (*callback)(void), TIM_TypeDef *timer) { stm_timer_callback[stm_peripherals_timer_get_index(timer)] = callback; } - void stm_peripherals_timer_free(TIM_TypeDef *instance) { +void stm_peripherals_timer_free(TIM_TypeDef *instance) { size_t tim_idx = stm_peripherals_timer_get_index(instance); HAL_NVIC_DisableIRQ(irq_map[tim_idx]); stm_timer_callback[tim_idx] = NULL; @@ -236,24 +240,27 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); stm_timer_never_reset[tim_idx] = false; } - void stm_peripherals_timer_never_reset(TIM_TypeDef *instance) { +void stm_peripherals_timer_never_reset(TIM_TypeDef *instance) { size_t tim_idx = stm_peripherals_timer_get_index(instance); stm_timer_never_reset[tim_idx] = true; } - void stm_peripherals_timer_reset_ok(TIM_TypeDef *instance) { + +void stm_peripherals_timer_reset_ok(TIM_TypeDef *instance) { size_t tim_idx = stm_peripherals_timer_get_index(instance); stm_timer_never_reset[tim_idx] = false; } - bool stm_peripherals_timer_is_never_reset(TIM_TypeDef *instance) { + +bool stm_peripherals_timer_is_never_reset(TIM_TypeDef *instance) { size_t tim_idx = stm_peripherals_timer_get_index(instance); return stm_timer_never_reset[tim_idx]; } - bool stm_peripherals_timer_is_reserved(TIM_TypeDef *instance) { + +bool stm_peripherals_timer_is_reserved(TIM_TypeDef *instance) { size_t tim_idx = stm_peripherals_timer_get_index(instance); return stm_timer_reserved[tim_idx]; } - size_t stm_peripherals_timer_get_index(TIM_TypeDef *instance) { +size_t stm_peripherals_timer_get_index(TIM_TypeDef *instance) { for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) { if (instance == mcu_tim_banks[i]) { return i; @@ -262,7 +269,7 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); return ~(size_t)0; } - void tim_clock_enable(uint16_t mask) { +void tim_clock_enable(uint16_t mask) { #ifdef TIM1 if (mask & (1 << 0)) { __HAL_RCC_TIM1_CLK_ENABLE(); @@ -326,7 +333,7 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); #endif } - void tim_clock_disable(uint16_t mask) { +void tim_clock_disable(uint16_t mask) { #ifdef TIM1 if (mask & (1 << 0)) { __HAL_RCC_TIM1_CLK_DISABLE(); @@ -390,65 +397,79 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void); #endif } - STATIC void callback_router(size_t index) { +STATIC void callback_router(size_t index) { if (stm_timer_callback[index - 1]) { (*stm_timer_callback[index - 1])(); } } - void TIM1_CC_IRQHandler(void) { // Advanced timer +void TIM1_CC_IRQHandler(void) { // Advanced timer callback_router(1); } - void TIM2_IRQHandler(void) { + +void TIM2_IRQHandler(void) { callback_router(2); } - void TIM3_IRQHandler(void) { + +void TIM3_IRQHandler(void) { callback_router(3); } - void TIM4_IRQHandler(void) { + +void TIM4_IRQHandler(void) { callback_router(4); } - void TIM5_IRQHandler(void) { + +void TIM5_IRQHandler(void) { callback_router(5); } - void TIM6_DAC_IRQHandler(void) { // Basic timer (DAC) + +void TIM6_DAC_IRQHandler(void) { // Basic timer (DAC) callback_router(6); } - void TIM7_IRQHandler(void) { // Basic timer + +void TIM7_IRQHandler(void) { // Basic timer callback_router(7); } - void TIM8_CC_IRQHandler(void) { // Advanced timer + +void TIM8_CC_IRQHandler(void) { // Advanced timer callback_router(8); } // Advanced timer interrupts are currently unused. - void TIM1_BRK_TIM9_IRQHandler(void) { +void TIM1_BRK_TIM9_IRQHandler(void) { callback_router(9); } - void TIM1_UP_TIM10_IRQHandler(void) { + +void TIM1_UP_TIM10_IRQHandler(void) { callback_router(10); } - void TIM1_TRG_COM_TIM11_IRQHandler(void) { + +void TIM1_TRG_COM_TIM11_IRQHandler(void) { callback_router(11); } - void TIM8_BRK_TIM12_IRQHandler(void) { + +void TIM8_BRK_TIM12_IRQHandler(void) { callback_router(12); } - void TIM8_UP_TIM13_IRQHandler(void) { + +void TIM8_UP_TIM13_IRQHandler(void) { callback_router(13); } - void TIM8_TRG_COM_TIM14_IRQHandler(void) { + +void TIM8_TRG_COM_TIM14_IRQHandler(void) { callback_router(14); } #if (CPY_STM32H7) - void TIM15_IRQHandler(void) { +void TIM15_IRQHandler(void) { callback_router(15); } - void TIM16_IRQHandler(void) { + +void TIM16_IRQHandler(void) { callback_router(16); } - void TIM17_IRQHandler(void) { + +void TIM17_IRQHandler(void) { callback_router(17); } #endif diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c index ccea353386..564320ae0d 100644 --- a/shared-bindings/pulseio/PulseOut.c +++ b/shared-bindings/pulseio/PulseOut.c @@ -41,10 +41,15 @@ //| pulsed signal consists of timed on and off periods. Unlike PWM, there is no set duration //| for on and off pairs.""" //| -//| def __init__(self, carrier: pwmio.PWMOut) -> None: +//| def __init__(self, pin: microcontroller.Pin, *, frequency: int = 38000, duty_cycle: int = 1 << 15) -> None: //| """Create a PulseOut object associated with the given PWMout object. //| -//| :param ~pwmio.PWMOut carrier: PWMOut that is set to output on the desired pin. +//| :param ~microcontroller.Pin pin: PWMOut that is set to output on the desired pin. +//| :param int frequency: Carrier signal frequency in Hertz +//| :param int duty_cycle: 16-bit duty cycle of carrier frequency (0 - 65536) +//| +//| For backwards compatibility, ``pin`` may be a PWMOut object used as the carrier. This +//| compatibility will be removed in CircuitPython 8.0.0. //| //| Send a short series of pulses:: //| @@ -54,8 +59,7 @@ //| import board //| //| # 50% duty cycle at 38kHz. -//| pwm = pwmio.PWMOut(board.D13, frequency=38000, duty_cycle=32768) -//| pulse = pulseio.PulseOut(pwm) +//| pwm = pulseio.PulseOut(board.D13, frequency=38000, duty_cycle=32768) //| # on off on off on //| pulses = array.array('H', [65000, 1000, 65000, 65000, 1000]) //| pulse.send(pulses) @@ -66,27 +70,30 @@ //| ... //| STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_pin, ARG_frequency, ARG_duty_cycle}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 38000} }, + { MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1 << 15} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *pin = args[ARG_pin].u_obj; + mp_int_t frequency = args[ARG_frequency].u_int; + mp_int_t duty_cycle = args[ARG_duty_cycle].u_int; + if (mp_obj_is_type(args[ARG_pin].u_obj, &pwmio_pwmout_type)) { + pwmio_pwmout_obj_t *pwmout = args[ARG_pin].u_obj; + duty_cycle = common_hal_pwmio_pwmout_get_duty_cycle(pwmout); + frequency = common_hal_pwmio_pwmout_get_frequency(pwmout); + pin = common_hal_pwmio_pwmout_get_pin(pwmout); + // Deinit the pin so we can use it. + common_hal_pwmio_pwmout_deinit(pwmout); + } + validate_obj_is_free_pin(MP_OBJ_FROM_PTR(pin)); pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t); self->base.type = &pulseio_pulseout_type; - - mp_obj_t carrier_obj = pos_args[0]; - if (mp_obj_is_type(carrier_obj, &pwmio_pwmout_type)) { - // Use a PWMOut Carrier - mp_arg_check_num(n_args, kw_args, 1, 1, false); - common_hal_pulseio_pulseout_construct(self, (pwmio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj), NULL, 0, 0); - } else { - // Use a Pin, frequency, and duty cycle - enum { ARG_pin, ARG_frequency}; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 38000} }, - { MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1 << 15} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); - common_hal_pulseio_pulseout_construct(self, NULL, pin, args[ARG_frequency].u_int, args[ARG_frequency].u_int); - } + common_hal_pulseio_pulseout_construct(self, pin, frequency, duty_cycle); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/pulseio/PulseOut.h b/shared-bindings/pulseio/PulseOut.h index dce58a63e0..0c64c1363a 100644 --- a/shared-bindings/pulseio/PulseOut.h +++ b/shared-bindings/pulseio/PulseOut.h @@ -34,7 +34,6 @@ extern const mp_obj_type_t pulseio_pulseout_type; extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self, - const pwmio_pwmout_obj_t *carrier, const mcu_pin_obj_t *pin, uint32_t frequency, uint16_t duty_cycle); diff --git a/shared-bindings/pwmio/PWMOut.c b/shared-bindings/pwmio/PWMOut.c index 2a1bda2d38..e34b27ad4a 100644 --- a/shared-bindings/pwmio/PWMOut.c +++ b/shared-bindings/pwmio/PWMOut.c @@ -35,6 +35,39 @@ #include "shared-bindings/util.h" #include "supervisor/shared/translate.h" + +void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) { + switch (result) { + case PWMOUT_OK: + break; + case PWMOUT_INVALID_PIN: + mp_raise_ValueError(translate("Invalid pin")); + break; + case PWMOUT_INVALID_FREQUENCY: + mp_raise_ValueError(translate("Invalid PWM frequency")); + break; + case PWMOUT_INVALID_FREQUENCY_ON_PIN: + mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer")); + break; + case PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE: + mp_raise_ValueError(translate("Cannot vary frequency on a timer that is already in use")); + break; + case PWMOUT_ALL_TIMERS_ON_PIN_IN_USE: + mp_raise_ValueError(translate("All timers for this pin are in use")); + break; + case PWMOUT_ALL_TIMERS_IN_USE: + mp_raise_RuntimeError(translate("All timers in use")); + break; + case PWMOUT_ALL_CHANNELS_IN_USE: + mp_raise_RuntimeError(translate("All channels in use")); + break; + default: + case PWMOUT_INITIALIZATION_ERROR: + mp_raise_RuntimeError(translate("Could not start PWM")); + break; + } +} + //| class PWMOut: //| """Output a Pulse Width Modulated signal on a given pin.""" //| @@ -102,35 +135,7 @@ STATIC mp_obj_t pwmio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, pwmio_pwmout_obj_t *self = m_new_obj(pwmio_pwmout_obj_t); self->base.type = &pwmio_pwmout_type; pwmout_result_t result = common_hal_pwmio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency); - switch (result) { - case PWMOUT_OK: - break; - case PWMOUT_INVALID_PIN: - mp_raise_ValueError(translate("Invalid pin")); - break; - case PWMOUT_INVALID_FREQUENCY: - mp_raise_ValueError(translate("Invalid PWM frequency")); - break; - case PWMOUT_INVALID_FREQUENCY_ON_PIN: - mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer")); - break; - case PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE: - mp_raise_ValueError(translate("Cannot vary frequency on a timer that is already in use")); - break; - case PWMOUT_ALL_TIMERS_ON_PIN_IN_USE: - mp_raise_ValueError(translate("All timers for this pin are in use")); - break; - case PWMOUT_ALL_TIMERS_IN_USE: - mp_raise_RuntimeError(translate("All timers in use")); - break; - case PWMOUT_ALL_CHANNELS_IN_USE: - mp_raise_RuntimeError(translate("All channels in use")); - break; - default: - case PWMOUT_INITIALIZATION_ERROR: - mp_raise_RuntimeError(translate("Could not start PWM")); - break; - } + common_hal_pwmio_pwmout_raise_error(result); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/pwmio/PWMOut.h b/shared-bindings/pwmio/PWMOut.h index f4d205b215..e55205e756 100644 --- a/shared-bindings/pwmio/PWMOut.h +++ b/shared-bindings/pwmio/PWMOut.h @@ -55,8 +55,13 @@ extern void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t *self, uint extern uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self); extern bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self); +// Don't use this! It is only used internally for backwards compatibility. +extern const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self); + // This is used by the supervisor to claim PWMOut devices indefinitely. extern void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self); extern void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self); +extern void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO_PWMOUT_H