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.
This commit is contained in:
parent
5fbe6d4805
commit
412eb87080
@ -1877,21 +1877,6 @@ msgstr ""
|
|||||||
msgid "Polygon needs at least 3 points"
|
msgid "Polygon needs at least 3 points"
|
||||||
msgstr ""
|
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
|
#: shared-bindings/_bleio/Adapter.c
|
||||||
msgid "Prefix buffer must be on the heap"
|
msgid "Prefix buffer must be on the heap"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -103,13 +103,15 @@ void pulseout_reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
||||||
const pwmio_pwmout_obj_t *carrier,
|
|
||||||
const mcu_pin_obj_t *pin,
|
const mcu_pin_obj_t *pin,
|
||||||
uint32_t frequency,
|
uint32_t frequency,
|
||||||
uint16_t duty_cycle) {
|
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) {
|
if (refcount == 0) {
|
||||||
// Find a spare timer.
|
// Find a spare timer.
|
||||||
@ -155,7 +157,7 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
|||||||
}
|
}
|
||||||
refcount++;
|
refcount++;
|
||||||
|
|
||||||
self->pin = carrier->pin->number;
|
self->pin = pin->number;
|
||||||
|
|
||||||
PortGroup *const port_base = &PORT->Group[GPIO_PORT(self->pin)];
|
PortGroup *const port_base = &PORT->Group[GPIO_PORT(self->pin)];
|
||||||
self->pincfg = &port_base->PINCFG[self->pin % 32];
|
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) {
|
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) {
|
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;
|
pulseout_tc_index = 0xff;
|
||||||
}
|
}
|
||||||
self->pin = NO_PIN;
|
self->pin = NO_PIN;
|
||||||
|
common_hal_pwmio_pwmout_deinit(&self->pwmout);
|
||||||
#ifdef SAMD21
|
#ifdef SAMD21
|
||||||
rtc_end_pulse();
|
rtc_end_pulse();
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,10 +30,12 @@
|
|||||||
#include "common-hal/microcontroller/Pin.h"
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
#include "shared-bindings/pwmio/PWMOut.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
__IO PORT_PINCFG_Type *pincfg;
|
__IO PORT_PINCFG_Type *pincfg;
|
||||||
|
pwmio_pwmout_obj_t pwmout;
|
||||||
uint8_t pin;
|
uint8_t pin;
|
||||||
} pulseio_pulseout_obj_t;
|
} pulseio_pulseout_obj_t;
|
||||||
|
|
||||||
|
@ -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) {
|
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
|
||||||
return self->variable_frequency;
|
return self->variable_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
|
||||||
|
return self->pin;
|
||||||
|
}
|
||||||
|
@ -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,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
||||||
const pwmio_pwmout_obj_t *carrier,
|
|
||||||
const mcu_pin_obj_t *pin,
|
const mcu_pin_obj_t *pin,
|
||||||
uint32_t frequency,
|
uint32_t frequency,
|
||||||
uint16_t duty_cycle) {
|
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) {
|
if (pulse_fd < 0) {
|
||||||
pulse_fd = open("/dev/timer0", O_RDONLY);
|
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"));
|
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) {
|
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);
|
close(pulse_fd);
|
||||||
pulse_fd = -1;
|
pulse_fd = -1;
|
||||||
|
|
||||||
|
common_hal_pwmio_pwmout_deinit(&self->pwmout);
|
||||||
|
|
||||||
pulse_buffer = NULL;
|
pulse_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +29,12 @@
|
|||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/pwmio/PWMOut.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
uint8_t pwm_num;
|
uint8_t pwm_num;
|
||||||
|
pwmio_pwmout_obj_t pwmout;
|
||||||
} pulseio_pulseout_obj_t;
|
} pulseio_pulseout_obj_t;
|
||||||
|
|
||||||
void pulseout_reset(void);
|
void pulseout_reset(void);
|
||||||
|
@ -157,3 +157,7 @@ void pwmout_start(uint8_t pwm_num) {
|
|||||||
void pwmout_stop(uint8_t pwm_num) {
|
void pwmout_stop(uint8_t pwm_num) {
|
||||||
ioctl(pwmout_dev[pwm_num].fd, PWMIOC_STOP, 0);
|
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;
|
||||||
|
}
|
||||||
|
@ -32,13 +32,9 @@
|
|||||||
// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
|
// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
||||||
const pwmio_pwmout_obj_t *carrier,
|
|
||||||
const mcu_pin_obj_t *pin,
|
const mcu_pin_obj_t *pin,
|
||||||
uint32_t frequency,
|
uint32_t frequency,
|
||||||
uint16_t duty_cycle) {
|
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();
|
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
|
||||||
if (channel == RMT_CHANNEL_MAX) {
|
if (channel == RMT_CHANNEL_MAX) {
|
||||||
|
@ -152,7 +152,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
|
|||||||
varfreq_timers[timer_index] = true;
|
varfreq_timers[timer_index] = true;
|
||||||
}
|
}
|
||||||
self->variable_frequency = variable_frequency;
|
self->variable_frequency = variable_frequency;
|
||||||
self->pin_number = pin->number;
|
self->pin = pin;
|
||||||
self->deinited = false;
|
self->deinited = false;
|
||||||
self->duty_resolution = duty_bits;
|
self->duty_resolution = duty_bits;
|
||||||
claim_pin(pin);
|
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_tim[self->tim_handle.timer_num] = true;
|
||||||
never_reset_chan[self->chan_handle.channel] = 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) {
|
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
|
// if timer isn't varfreq this will be off aleady
|
||||||
varfreq_timers[self->tim_handle.timer_num] = false;
|
varfreq_timers[self->tim_handle.timer_num] = false;
|
||||||
}
|
}
|
||||||
reset_pin_number(self->pin_number);
|
common_hal_reset_pin(self->pin);
|
||||||
self->deinited = true;
|
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) {
|
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
|
||||||
return self->variable_frequency;
|
return self->variable_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
|
||||||
|
return self->pin;
|
||||||
|
}
|
||||||
|
@ -34,7 +34,7 @@ typedef struct {
|
|||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
ledc_timer_config_t tim_handle;
|
ledc_timer_config_t tim_handle;
|
||||||
ledc_channel_config_t chan_handle;
|
ledc_channel_config_t chan_handle;
|
||||||
uint16_t pin_number;
|
const mcu_pin_obj_t *pin;
|
||||||
uint8_t duty_resolution;
|
uint8_t duty_resolution;
|
||||||
bool variable_frequency : 1;
|
bool variable_frequency : 1;
|
||||||
bool deinited : 1;
|
bool deinited : 1;
|
||||||
|
@ -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 <stdint.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -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
|
|
@ -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 <stdint.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||||||
// No pulseio module functions.
|
|
@ -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_DSE(6)
|
||||||
| IOMUXC_SW_PAD_CTL_PAD_SRE(0));
|
| 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) {
|
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) {
|
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) {
|
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)
|
#define PWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_IpgClk)
|
||||||
|
|
||||||
static int calculate_pulse_count(uint32_t frequency, uint8_t *prescaler) {
|
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) {
|
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
|
||||||
return self->variable_frequency;
|
return self->variable_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
|
||||||
|
return self->pin;
|
||||||
|
}
|
||||||
|
@ -24,10 +24,11 @@ INTERNAL_FLASH_FILESYSTEM = 1
|
|||||||
CIRCUITPY_AUDIOIO = 0
|
CIRCUITPY_AUDIOIO = 0
|
||||||
CIRCUITPY_AUDIOBUSIO = 0
|
CIRCUITPY_AUDIOBUSIO = 0
|
||||||
CIRCUITPY_BUSDEVICE = 1
|
CIRCUITPY_BUSDEVICE = 1
|
||||||
|
CIRCUITPY_COUNTIO = 0
|
||||||
CIRCUITPY_FREQUENCYIO = 0
|
CIRCUITPY_FREQUENCYIO = 0
|
||||||
CIRCUITPY_I2CPERIPHERAL = 0
|
CIRCUITPY_I2CPERIPHERAL = 0
|
||||||
CIRCUITPY_NVM = 0
|
CIRCUITPY_NVM = 0
|
||||||
|
CIRCUITPY_PULSEIO = 0
|
||||||
CIRCUITPY_ROTARYIO = 0
|
CIRCUITPY_ROTARYIO = 0
|
||||||
CIRCUITPY_COUNTIO = 0
|
|
||||||
CIRCUITPY_USB_MIDI = 1
|
CIRCUITPY_USB_MIDI = 1
|
||||||
LONGINT_IMPL = MPZ
|
LONGINT_IMPL = MPZ
|
||||||
|
@ -37,8 +37,6 @@
|
|||||||
#include "fsl_device_registers.h"
|
#include "fsl_device_registers.h"
|
||||||
|
|
||||||
#include "common-hal/microcontroller/Pin.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/pwmio/PWMOut.h"
|
||||||
#include "common-hal/rtc/RTC.h"
|
#include "common-hal/rtc/RTC.h"
|
||||||
#include "common-hal/busio/SPI.h"
|
#include "common-hal/busio/SPI.h"
|
||||||
@ -289,9 +287,6 @@ void reset_port(void) {
|
|||||||
|
|
||||||
// eic_reset();
|
// eic_reset();
|
||||||
|
|
||||||
#if CIRCUITPY_PULSEIO
|
|
||||||
pulseout_reset();
|
|
||||||
#endif
|
|
||||||
#if CIRCUITPY_PWMIO
|
#if CIRCUITPY_PWMIO
|
||||||
pwmout_reset();
|
pwmout_reset();
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,14 +48,14 @@ static volatile uint16_t pulse_array_index = 0;
|
|||||||
static uint16_t pulse_array_length;
|
static uint16_t pulse_array_length;
|
||||||
|
|
||||||
static void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
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) {
|
static void turn_off(pulseio_pulseout_obj_t *pulseout) {
|
||||||
// Disconnect pin from PWM.
|
// Disconnect pin from PWM.
|
||||||
pulseout->pwmout->pwm->PSEL.OUT[0] = 0xffffffff;
|
pulseout->pwmout.pwm->PSEL.OUT[0] = 0xffffffff;
|
||||||
// Make sure pin is low.
|
// 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) {
|
static void start_timer(void) {
|
||||||
@ -100,13 +100,15 @@ void pulseout_reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
||||||
const pwmio_pwmout_obj_t *carrier,
|
|
||||||
const mcu_pin_obj_t *pin,
|
const mcu_pin_obj_t *pin,
|
||||||
uint32_t frequency,
|
uint32_t frequency,
|
||||||
uint16_t duty_cycle) {
|
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) {
|
if (refcount == 0) {
|
||||||
timer = nrf_peripherals_allocate_timer_or_throw();
|
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,
|
.p_context = self,
|
||||||
};
|
};
|
||||||
|
|
||||||
self->pwmout = carrier;
|
|
||||||
|
|
||||||
nrfx_timer_init(timer, &timer_config, &pulseout_event_handler);
|
nrfx_timer_init(timer, &timer_config, &pulseout_event_handler);
|
||||||
turn_off(self);
|
turn_off(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
turn_on(self);
|
turn_on(self);
|
||||||
self->pwmout = NULL;
|
common_hal_pwmio_pwmout_deinit(&self->pwmout);
|
||||||
|
|
||||||
refcount--;
|
refcount--;
|
||||||
if (refcount == 0) {
|
if (refcount == 0) {
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
const pwmio_pwmout_obj_t *pwmout;
|
pwmio_pwmout_obj_t pwmout;
|
||||||
} pulseio_pulseout_obj_t;
|
} pulseio_pulseout_obj_t;
|
||||||
|
|
||||||
void pulseout_reset(void);
|
void pulseout_reset(void);
|
||||||
|
@ -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) {
|
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->channel = channel;
|
||||||
self->pin_number = pin->number;
|
self->pin = pin;
|
||||||
claim_pin(pin);
|
claim_pin(pin);
|
||||||
|
|
||||||
self->frequency = frequency;
|
self->frequency = frequency;
|
||||||
self->variable_frequency = variable_frequency;
|
self->variable_frequency = variable_frequency;
|
||||||
|
|
||||||
// Note this is standard, not strong drive.
|
// 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
|
// disable before mapping pin channel
|
||||||
nrf_pwm_disable(self->pwm);
|
nrf_pwm_disable(self->pwm);
|
||||||
@ -267,15 +267,15 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nrf_gpio_cfg_default(self->pin_number);
|
nrf_gpio_cfg_default(self->pin->number);
|
||||||
|
|
||||||
NRF_PWM_Type *pwm = self->pwm;
|
NRF_PWM_Type *pwm = self->pwm;
|
||||||
self->pwm = NULL;
|
self->pwm = NULL;
|
||||||
|
|
||||||
pwmout_free_channel(pwm, self->channel);
|
pwmout_free_channel(pwm, self->channel);
|
||||||
|
|
||||||
reset_pin_number(self->pin_number);
|
common_hal_reset_pin(self->pin);
|
||||||
self->pin_number = NO_PIN;
|
self->pin = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uint16_t duty_cycle) {
|
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) {
|
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
|
||||||
return self->variable_frequency;
|
return self->variable_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
|
||||||
|
return self->pin;
|
||||||
|
}
|
||||||
|
@ -29,13 +29,14 @@
|
|||||||
|
|
||||||
#include "nrfx_pwm.h"
|
#include "nrfx_pwm.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
#include "shared-bindings/microcontroller/Pin.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
NRF_PWM_Type *pwm;
|
NRF_PWM_Type *pwm;
|
||||||
uint8_t pin_number;
|
|
||||||
uint8_t channel : 7;
|
uint8_t channel : 7;
|
||||||
bool variable_frequency : 1;
|
bool variable_frequency : 1;
|
||||||
|
const mcu_pin_obj_t *pin;
|
||||||
uint16_t duty_cycle;
|
uint16_t duty_cycle;
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
} pwmio_pwmout_obj_t;
|
} pwmio_pwmout_obj_t;
|
||||||
|
@ -42,23 +42,28 @@ static uint8_t refcount = 0;
|
|||||||
volatile alarm_id_t cur_alarm = 0;
|
volatile alarm_id_t cur_alarm = 0;
|
||||||
|
|
||||||
void turn_off(uint8_t slice) {
|
void turn_off(uint8_t slice) {
|
||||||
pwm_hw->slice[slice].ctr = 0;
|
// Set the current counter value near the top so that the output is low. The
|
||||||
pwm_hw->slice[slice].cc = 0;
|
// - 2 gives us a little wiggle room for enabling and disabling the slice.
|
||||||
pwm_hw->slice[slice].top = 0;
|
// The top + 1 ensure we don't end up lower than the cc (and therefore high.)
|
||||||
pwm_hw->slice[slice].div = 1u << PWM_CH0_DIV_INT_LSB;
|
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 = PWM_CH0_CSR_EN_BITS;
|
||||||
pwm_hw->slice[slice].csr = 0;
|
pwm_hw->slice[slice].csr = 0;
|
||||||
|
common_hal_mcu_enable_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pulse_finish(pulseio_pulseout_obj_t *self) {
|
void pulse_finish(pulseio_pulseout_obj_t *self) {
|
||||||
self->pulse_index++;
|
self->pulse_index++;
|
||||||
// Turn pwm pin off by setting duty cyle to 1.
|
// 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) {
|
if (self->pulse_index >= self->pulse_length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (self->pulse_index % 2 == 0) {
|
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];
|
uint64_t delay = self->pulse_buffer[self->pulse_index];
|
||||||
if (delay < self->min_pulse) {
|
if (delay < self->min_pulse) {
|
||||||
@ -78,24 +83,26 @@ int64_t pulseout_interrupt_handler(alarm_id_t id, void *user_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pulseout_reset() {
|
void pulseout_reset() {
|
||||||
refcount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
||||||
const pwmio_pwmout_obj_t *carrier,
|
|
||||||
const mcu_pin_obj_t *pin,
|
const mcu_pin_obj_t *pin,
|
||||||
uint32_t frequency,
|
uint32_t frequency,
|
||||||
uint16_t duty_cycle) {
|
uint16_t duty_cycle) {
|
||||||
|
|
||||||
refcount++;
|
pwmout_result_t result = common_hal_pwmio_pwmout_construct(
|
||||||
self->carrier = (pwmio_pwmout_obj_t *)carrier;
|
&self->carrier, pin, duty_cycle, frequency, false);
|
||||||
self->current_duty_cycle = common_hal_pwmio_pwmout_get_duty_cycle(self->carrier);
|
|
||||||
pwm_set_enabled(self->carrier->slice,false);
|
// This will raise an exception and not return if needed.
|
||||||
turn_off(self->carrier->slice);
|
common_hal_pwmio_pwmout_raise_error(result);
|
||||||
common_hal_pwmio_pwmout_set_duty_cycle(self->carrier,1);
|
|
||||||
self->pin = self->carrier->pin->number;
|
self->current_duty_cycle = duty_cycle;
|
||||||
self->slice = self->carrier->slice;
|
pwm_set_enabled(self->carrier.slice, false);
|
||||||
self->min_pulse = (1000000 / self->carrier->actual_frequency);
|
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) {
|
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)) {
|
if (common_hal_pulseio_pulseout_deinited(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
refcount--;
|
common_hal_pwmio_pwmout_deinit(&self->carrier);
|
||||||
self->pin = NO_PIN;
|
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_index = 0;
|
||||||
self->pulse_length = length;
|
self->pulse_length = length;
|
||||||
|
|
||||||
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);
|
||||||
pwm_set_enabled(self->slice,true);
|
pwm_set_enabled(self->slice, true);
|
||||||
uint64_t delay = self->pulse_buffer[0];
|
uint64_t delay = self->pulse_buffer[0];
|
||||||
if (delay < self->min_pulse) {
|
if (delay < self->min_pulse) {
|
||||||
delay = self->min_pulse;
|
delay = self->min_pulse;
|
||||||
|
@ -39,7 +39,7 @@ typedef struct {
|
|||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
uint8_t pin;
|
uint8_t pin;
|
||||||
uint8_t slice;
|
uint8_t slice;
|
||||||
pwmio_pwmout_obj_t *carrier;
|
pwmio_pwmout_obj_t carrier;
|
||||||
uint16_t *pulse_buffer;
|
uint16_t *pulse_buffer;
|
||||||
uint16_t pulse_length;
|
uint16_t pulse_length;
|
||||||
uint16_t current_duty_cycle;
|
uint16_t current_duty_cycle;
|
||||||
|
@ -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) {
|
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
|
||||||
return self->variable_frequency;
|
return self->variable_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
|
||||||
|
return self->pin;
|
||||||
|
}
|
||||||
|
@ -52,15 +52,15 @@ STATIC pulseio_pulseout_obj_t *curr_pulseout = NULL;
|
|||||||
|
|
||||||
STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
||||||
// Turn on PWM
|
// 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) {
|
STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) {
|
||||||
// Turn off PWM
|
// 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.
|
// Make sure pin is low.
|
||||||
HAL_GPIO_WritePin(pin_port(pulseout->pwmout->tim->pin->port),
|
HAL_GPIO_WritePin(pin_port(pulseout->pwmout.tim->pin->port),
|
||||||
pin_mask(pulseout->pwmout->tim->pin->number), 0);
|
pin_mask(pulseout->pwmout.tim->pin->number), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void start_timer(void) {
|
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_FLAG(&tim_handle, TIM_FLAG_UPDATE) != RESET) {
|
||||||
if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET) {
|
if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET) {
|
||||||
__HAL_TIM_CLEAR_IT(&tim_handle, TIM_IT_UPDATE);
|
__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
|
return; // invalid interrupt
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,13 +111,12 @@ void pulseout_reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
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) {
|
||||||
const mcu_pin_obj_t *pin,
|
pwmout_result_t result = common_hal_pwmio_pwmout_construct(
|
||||||
uint32_t frequency,
|
&self->pwmout, pin, duty_cycle, frequency, false);
|
||||||
uint16_t duty_cycle) {
|
|
||||||
if (!carrier || pin || frequency) {
|
// This will raise an exception and not return if needed.
|
||||||
mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. Construct and pass a PWMOut Carrier instead"));
|
common_hal_pwmio_pwmout_raise_error(result);
|
||||||
}
|
|
||||||
|
|
||||||
// Add to active PulseOuts
|
// Add to active PulseOuts
|
||||||
refcount++;
|
refcount++;
|
||||||
@ -139,13 +138,12 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
|||||||
HAL_TIM_Base_Init(&tim_handle);
|
HAL_TIM_Base_Init(&tim_handle);
|
||||||
tim_handle.Instance->SR = 0;
|
tim_handle.Instance->SR = 0;
|
||||||
|
|
||||||
// The HAL can't work with const, recast required.
|
|
||||||
self->pwmout = (pwmio_pwmout_obj_t *)carrier;
|
|
||||||
turn_off(self);
|
turn_off(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
turn_on(self);
|
turn_on(self);
|
||||||
self->pwmout = NULL;
|
common_hal_pwmio_pwmout_deinit(&self->pwmout);
|
||||||
|
|
||||||
refcount--;
|
refcount--;
|
||||||
if (refcount == 0) {
|
if (refcount == 0) {
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
pwmio_pwmout_obj_t *pwmout;
|
pwmio_pwmout_obj_t pwmout;
|
||||||
} pulseio_pulseout_obj_t;
|
} pulseio_pulseout_obj_t;
|
||||||
|
|
||||||
void pulseout_reset(void);
|
void pulseout_reset(void);
|
||||||
|
@ -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++) {
|
for (uint i = 0; i < tim_num; i++) {
|
||||||
const mcu_tim_pin_obj_t *l_tim = &mcu_tim_pin_list[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_index = l_tim->tim_index;
|
||||||
uint8_t l_tim_channel = l_tim->channel_index - 1;
|
uint8_t l_tim_channel = l_tim->channel_index;
|
||||||
|
|
||||||
// if pin is same
|
// if pin is same
|
||||||
if (l_tim->pin == pin) {
|
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
|
// handle valid/invalid timer instance
|
||||||
if (self->tim != NULL) {
|
if (self->tim != NULL) {
|
||||||
// create instance
|
// create instance
|
||||||
TIMx = mcu_tim_banks[self->tim->tim_index - 1];
|
TIMx = mcu_tim_banks[self->tim->tim_index];
|
||||||
// reserve timer/channel
|
// reserve timer/channel
|
||||||
if (variable_frequency) {
|
if (variable_frequency) {
|
||||||
reserved_tim[self->tim->tim_index - 1] = 0x0F;
|
reserved_tim[self->tim->tim_index] = 0x0F;
|
||||||
} else {
|
} 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);
|
stm_peripherals_timer_reserve(TIMx);
|
||||||
} else { // no match found
|
} else { // no match found
|
||||||
if (tim_chan_taken || tim_taken_internal) {
|
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_InitTypeDef GPIO_InitStruct = {0};
|
||||||
GPIO_InitStruct.Pin = pin_mask(pin->number);
|
GPIO_InitStruct.Pin = pin_mask(pin->number);
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
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.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||||
GPIO_InitStruct.Alternate = self->tim->altfn_index;
|
GPIO_InitStruct.Alternate = self->tim->altfn_index;
|
||||||
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
|
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
|
// translate channel into handle value
|
||||||
self->channel = 4 * (self->tim->channel_index - 1);
|
self->channel = 4 * self->tim->channel_index;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timer init
|
// Timer init
|
||||||
self->handle.Instance = TIMx;
|
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++) {
|
for (size_t i = 0; i < TIM_BANK_ARRAY_LEN; i++) {
|
||||||
if (mcu_tim_banks[i] == self->handle.Instance) {
|
if (mcu_tim_banks[i] == self->handle.Instance) {
|
||||||
never_reset_tim[i] = true;
|
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;
|
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
|
// var freq shuts down entire timer, others just their channel
|
||||||
if (self->variable_frequency) {
|
if (self->variable_frequency) {
|
||||||
reserved_tim[self->tim->tim_index - 1] = 0x00;
|
reserved_tim[self->tim->tim_index] = 0x00;
|
||||||
} else {
|
} 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);
|
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 timer has no active channels, we can disable it
|
||||||
if (!reserved_tim[self->tim->tim_index - 1]) {
|
if (reserved_tim[self->tim->tim_index] == 0) {
|
||||||
tim_frequencies[self->tim->tim_index - 1] = 0x00;
|
tim_frequencies[self->tim->tim_index] = 0x00;
|
||||||
stm_peripherals_timer_free(self->handle.Instance);
|
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"));
|
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->frequency = frequency;
|
||||||
self->period = period;
|
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) {
|
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
|
||||||
return self->variable_frequency;
|
return self->variable_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
|
||||||
|
return self->pin;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,7 @@ typedef struct {
|
|||||||
uint16_t duty_cycle;
|
uint16_t duty_cycle;
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
uint32_t period;
|
uint32_t period;
|
||||||
|
const mcu_pin_obj_t *pin;
|
||||||
} pwmio_pwmout_obj_t;
|
} pwmio_pwmout_obj_t;
|
||||||
|
|
||||||
void pwmout_reset(void);
|
void pwmout_reset(void);
|
||||||
|
@ -59,9 +59,9 @@ typedef struct {
|
|||||||
|
|
||||||
#define TIM(index, alt, channel, tim_pin) \
|
#define TIM(index, alt, channel, tim_pin) \
|
||||||
{ \
|
{ \
|
||||||
.tim_index = index, \
|
.tim_index = index - 1, \
|
||||||
.altfn_index = alt, \
|
.altfn_index = alt, \
|
||||||
.channel_index = channel, \
|
.channel_index = channel - 1, \
|
||||||
.pin = tim_pin, \
|
.pin = tim_pin, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,12 @@
|
|||||||
|
|
||||||
static bool stm_timer_reserved[MP_ARRAY_SIZE(mcu_tim_banks)];
|
static bool stm_timer_reserved[MP_ARRAY_SIZE(mcu_tim_banks)];
|
||||||
static bool stm_timer_never_reset[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
|
#ifdef TIM1
|
||||||
TIM1_CC_IRQn,
|
TIM1_CC_IRQn,
|
||||||
#else
|
#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
|
// 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
|
// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its
|
||||||
// respective APB clock. See DM00031020 Rev 4, page 115.
|
// 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);
|
size_t tim_id = stm_peripherals_timer_get_index(timer);
|
||||||
uint32_t source, clk_div;
|
uint32_t source, clk_div;
|
||||||
if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
|
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;
|
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);
|
size_t tim_id = stm_peripherals_timer_get_index(instance);
|
||||||
return irq_map[tim_id];
|
return irq_map[tim_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
void timers_reset(void) {
|
void timers_reset(void) {
|
||||||
uint16_t never_reset_mask = 0x00;
|
uint16_t never_reset_mask = 0x00;
|
||||||
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
|
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
|
||||||
if (!stm_timer_never_reset[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_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
|
// Check for timers on pins outside the package size
|
||||||
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
|
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
|
||||||
bool timer_in_package = false;
|
bool timer_in_package = false;
|
||||||
// Find each timer instance on the given bank
|
// Find each timer instance on the given bank
|
||||||
for (size_t j = 0; j < MP_ARRAY_SIZE(mcu_tim_pin_list); j++) {
|
for (size_t j = 0; j < MP_ARRAY_SIZE(mcu_tim_pin_list); j++) {
|
||||||
// If a pin is claimed, we skip it
|
// 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)) {
|
&& (common_hal_mcu_pin_is_free(mcu_tim_pin_list[j].pin) == true)) {
|
||||||
// Search whether any pins in the package array match it
|
// Search whether any pins in the package array match it
|
||||||
for (size_t k = 0; k < mcu_pin_globals.map.alloc; k++) {
|
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;
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
stm_timer_callback[tim_idx] = callback;
|
stm_timer_callback[tim_idx] = callback;
|
||||||
tim_clock_enable(1 << tim_idx);
|
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]);
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
stm_timer_reserved[tim_idx] = true;
|
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;
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
HAL_NVIC_DisableIRQ(irq_map[tim_idx]);
|
HAL_NVIC_DisableIRQ(irq_map[tim_idx]);
|
||||||
stm_timer_callback[tim_idx] = NULL;
|
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;
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
stm_timer_never_reset[tim_idx] = true;
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
stm_timer_never_reset[tim_idx] = false;
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
return stm_timer_never_reset[tim_idx];
|
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);
|
size_t tim_idx = stm_peripherals_timer_get_index(instance);
|
||||||
return stm_timer_reserved[tim_idx];
|
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++) {
|
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
|
||||||
if (instance == mcu_tim_banks[i]) {
|
if (instance == mcu_tim_banks[i]) {
|
||||||
return i;
|
return i;
|
||||||
@ -262,7 +269,7 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void);
|
|||||||
return ~(size_t)0;
|
return ~(size_t)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tim_clock_enable(uint16_t mask) {
|
void tim_clock_enable(uint16_t mask) {
|
||||||
#ifdef TIM1
|
#ifdef TIM1
|
||||||
if (mask & (1 << 0)) {
|
if (mask & (1 << 0)) {
|
||||||
__HAL_RCC_TIM1_CLK_ENABLE();
|
__HAL_RCC_TIM1_CLK_ENABLE();
|
||||||
@ -326,7 +333,7 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void);
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tim_clock_disable(uint16_t mask) {
|
void tim_clock_disable(uint16_t mask) {
|
||||||
#ifdef TIM1
|
#ifdef TIM1
|
||||||
if (mask & (1 << 0)) {
|
if (mask & (1 << 0)) {
|
||||||
__HAL_RCC_TIM1_CLK_DISABLE();
|
__HAL_RCC_TIM1_CLK_DISABLE();
|
||||||
@ -390,65 +397,79 @@ static void (*stm_timer_callback[MP_ARRAY_SIZE (mcu_tim_banks)])(void);
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void callback_router(size_t index) {
|
STATIC void callback_router(size_t index) {
|
||||||
if (stm_timer_callback[index - 1]) {
|
if (stm_timer_callback[index - 1]) {
|
||||||
(*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);
|
callback_router(1);
|
||||||
}
|
}
|
||||||
void TIM2_IRQHandler(void) {
|
|
||||||
|
void TIM2_IRQHandler(void) {
|
||||||
callback_router(2);
|
callback_router(2);
|
||||||
}
|
}
|
||||||
void TIM3_IRQHandler(void) {
|
|
||||||
|
void TIM3_IRQHandler(void) {
|
||||||
callback_router(3);
|
callback_router(3);
|
||||||
}
|
}
|
||||||
void TIM4_IRQHandler(void) {
|
|
||||||
|
void TIM4_IRQHandler(void) {
|
||||||
callback_router(4);
|
callback_router(4);
|
||||||
}
|
}
|
||||||
void TIM5_IRQHandler(void) {
|
|
||||||
|
void TIM5_IRQHandler(void) {
|
||||||
callback_router(5);
|
callback_router(5);
|
||||||
}
|
}
|
||||||
void TIM6_DAC_IRQHandler(void) { // Basic timer (DAC)
|
|
||||||
|
void TIM6_DAC_IRQHandler(void) { // Basic timer (DAC)
|
||||||
callback_router(6);
|
callback_router(6);
|
||||||
}
|
}
|
||||||
void TIM7_IRQHandler(void) { // Basic timer
|
|
||||||
|
void TIM7_IRQHandler(void) { // Basic timer
|
||||||
callback_router(7);
|
callback_router(7);
|
||||||
}
|
}
|
||||||
void TIM8_CC_IRQHandler(void) { // Advanced timer
|
|
||||||
|
void TIM8_CC_IRQHandler(void) { // Advanced timer
|
||||||
callback_router(8);
|
callback_router(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advanced timer interrupts are currently unused.
|
// Advanced timer interrupts are currently unused.
|
||||||
void TIM1_BRK_TIM9_IRQHandler(void) {
|
void TIM1_BRK_TIM9_IRQHandler(void) {
|
||||||
callback_router(9);
|
callback_router(9);
|
||||||
}
|
}
|
||||||
void TIM1_UP_TIM10_IRQHandler(void) {
|
|
||||||
|
void TIM1_UP_TIM10_IRQHandler(void) {
|
||||||
callback_router(10);
|
callback_router(10);
|
||||||
}
|
}
|
||||||
void TIM1_TRG_COM_TIM11_IRQHandler(void) {
|
|
||||||
|
void TIM1_TRG_COM_TIM11_IRQHandler(void) {
|
||||||
callback_router(11);
|
callback_router(11);
|
||||||
}
|
}
|
||||||
void TIM8_BRK_TIM12_IRQHandler(void) {
|
|
||||||
|
void TIM8_BRK_TIM12_IRQHandler(void) {
|
||||||
callback_router(12);
|
callback_router(12);
|
||||||
}
|
}
|
||||||
void TIM8_UP_TIM13_IRQHandler(void) {
|
|
||||||
|
void TIM8_UP_TIM13_IRQHandler(void) {
|
||||||
callback_router(13);
|
callback_router(13);
|
||||||
}
|
}
|
||||||
void TIM8_TRG_COM_TIM14_IRQHandler(void) {
|
|
||||||
|
void TIM8_TRG_COM_TIM14_IRQHandler(void) {
|
||||||
callback_router(14);
|
callback_router(14);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (CPY_STM32H7)
|
#if (CPY_STM32H7)
|
||||||
void TIM15_IRQHandler(void) {
|
void TIM15_IRQHandler(void) {
|
||||||
callback_router(15);
|
callback_router(15);
|
||||||
}
|
}
|
||||||
void TIM16_IRQHandler(void) {
|
|
||||||
|
void TIM16_IRQHandler(void) {
|
||||||
callback_router(16);
|
callback_router(16);
|
||||||
}
|
}
|
||||||
void TIM17_IRQHandler(void) {
|
|
||||||
|
void TIM17_IRQHandler(void) {
|
||||||
callback_router(17);
|
callback_router(17);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,10 +41,15 @@
|
|||||||
//| pulsed signal consists of timed on and off periods. Unlike PWM, there is no set duration
|
//| pulsed signal consists of timed on and off periods. Unlike PWM, there is no set duration
|
||||||
//| for on and off pairs."""
|
//| 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.
|
//| """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::
|
//| Send a short series of pulses::
|
||||||
//|
|
//|
|
||||||
@ -54,8 +59,7 @@
|
|||||||
//| import board
|
//| import board
|
||||||
//|
|
//|
|
||||||
//| # 50% duty cycle at 38kHz.
|
//| # 50% duty cycle at 38kHz.
|
||||||
//| pwm = pwmio.PWMOut(board.D13, frequency=38000, duty_cycle=32768)
|
//| pwm = pulseio.PulseOut(board.D13, frequency=38000, duty_cycle=32768)
|
||||||
//| pulse = pulseio.PulseOut(pwm)
|
|
||||||
//| # on off on off on
|
//| # on off on off on
|
||||||
//| pulses = array.array('H', [65000, 1000, 65000, 65000, 1000])
|
//| pulses = array.array('H', [65000, 1000, 65000, 65000, 1000])
|
||||||
//| pulse.send(pulses)
|
//| 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) {
|
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);
|
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
|
||||||
self->base.type = &pulseio_pulseout_type;
|
self->base.type = &pulseio_pulseout_type;
|
||||||
|
common_hal_pulseio_pulseout_construct(self, pin, frequency, duty_cycle);
|
||||||
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);
|
|
||||||
}
|
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
extern const mp_obj_type_t pulseio_pulseout_type;
|
extern const mp_obj_type_t pulseio_pulseout_type;
|
||||||
|
|
||||||
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
|
||||||
const pwmio_pwmout_obj_t *carrier,
|
|
||||||
const mcu_pin_obj_t *pin,
|
const mcu_pin_obj_t *pin,
|
||||||
uint32_t frequency,
|
uint32_t frequency,
|
||||||
uint16_t duty_cycle);
|
uint16_t duty_cycle);
|
||||||
|
@ -35,6 +35,39 @@
|
|||||||
#include "shared-bindings/util.h"
|
#include "shared-bindings/util.h"
|
||||||
#include "supervisor/shared/translate.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:
|
//| class PWMOut:
|
||||||
//| """Output a Pulse Width Modulated signal on a given pin."""
|
//| """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);
|
pwmio_pwmout_obj_t *self = m_new_obj(pwmio_pwmout_obj_t);
|
||||||
self->base.type = &pwmio_pwmout_type;
|
self->base.type = &pwmio_pwmout_type;
|
||||||
pwmout_result_t result = common_hal_pwmio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency);
|
pwmout_result_t result = common_hal_pwmio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency);
|
||||||
switch (result) {
|
common_hal_pwmio_pwmout_raise_error(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
@ -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 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);
|
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.
|
// 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_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_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
|
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PWMIO_PWMOUT_H
|
||||||
|
Loading…
Reference in New Issue
Block a user