This commit is contained in:
Scott Shawcroft 2018-02-09 00:22:29 -08:00
parent e2d1e1e281
commit 190e7d629e
9 changed files with 189 additions and 197 deletions

View File

@ -272,6 +272,10 @@ SRC_COMMON_HAL = \
analogio/__init__.c \
analogio/AnalogIn.c \
analogio/AnalogOut.c \
pulseio/__init__.c \
pulseio/PulseIn.c \
pulseio/PulseOut.c \
pulseio/PWMOut.c \
# audiobusio/__init__.c \
audiobusio/PDMIn.c \
audioio/__init__.c \
@ -279,10 +283,6 @@ SRC_COMMON_HAL = \
busio/UART.c \
nvm/__init__.c \
nvm/ByteArray.c \
pulseio/__init__.c \
pulseio/PulseIn.c \
pulseio/PulseOut.c \
pulseio/PWMOut.c \
touchio/__init__.c \
touchio/TouchIn.c \
usb_hid/__init__.c \

View File

@ -44,9 +44,7 @@ typedef struct {
Tc *const tc;
Tcc *const tcc;
};
#ifdef SAMD21
bool is_tc:1;
#endif
uint8_t wave_output:4;
} pin_timer_t;

View File

@ -38,24 +38,29 @@
# define _TCC_SIZE(n,unused) TPASTE3(TCC,n,_SIZE),
# define TCC_SIZES { MREPEAT(TCC_INST_NUM, _TCC_SIZE, 0) }
uint32_t target_timer_frequencies[TC_INST_NUM + TCC_INST_NUM];
static uint32_t timer_periods[TC_INST_NUM + TCC_INST_NUM];
uint8_t timer_refcount[TC_INST_NUM + 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];
const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024};
// This bitmask keeps track of which channels of a TCC are currently claimed.
#ifdef SAMD21
uint8_t tcc_channels[3] = {0xf0, 0xfc, 0xfc};
uint8_t tcc_cc_num[3] = {4, 2, 2};
#endif
#ifdef SAMD51
uint8_t tcc_channels[5] = {0xc0, 0xf0, 0xf8, 0xfc, 0xfc};
uint8_t tcc_cc_num[5] = {6, 4, 3, 2, 2};
Tcc* tcc_insts[TCC_INST_NUM] = TCC_INSTS;
#endif
void pwmout_reset(void) {
// Reset all but TC5
for (int i = 0; i < TC_INST_NUM + TCC_INST_NUM; i++) {
if (i == 5) {
target_timer_frequencies[i] = 1000;
timer_refcount[i] = 1;
} else {
target_timer_frequencies[i] = 0;
timer_refcount[i] = 0;
}
// Reset all timers
for (int i = 0; i < TCC_INST_NUM; i++) {
target_timer_frequencies[i] = 0;
timer_refcount[i] = 0;
}
Tcc *tccs[TCC_INST_NUM] = TCC_INSTS;
for (int i = 0; i < TCC_INST_NUM; i++) {
@ -65,32 +70,45 @@ void pwmout_reset(void) {
while (tccs[i]->SYNCBUSY.bit.ENABLE == 1) {
}
}
// TODO(tannewt): Make this depend on the CMSIS.
if (i == 0) {
tcc_channels[i] = 0xf0;
} else {
tcc_channels[i] = 0xfc;
uint8_t mask = 0xff;
for (uint8_t j = 0; j < tcc_cc_num[i]; j++) {
mask <<= 1;
}
tcc_channels[i] = 0xf0;
tccs[i]->CTRLA.bit.SWRST = 1;
}
Tc *tcs[TC_INST_NUM] = TC_INSTS;
for (int i = 0; i < TC_INST_NUM; i++) {
if (tcs[i] == TC5) {
continue;
}
tcs[i]->COUNT16.CTRLA.bit.SWRST = 1;
while (tcs[i]->COUNT16.CTRLA.bit.SWRST == 1) {
}
}
}
static uint8_t tcc_channel(uint8_t timer_index, uint8_t wave_output) {
// 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[index];
}
bool channel_ok(const pin_timer_t* t, uint8_t index) {
return (!t->is_tc && (tcc_channels[index] & (1 << t->channel)) == 0) ||
uint8_t channel_bit = 1 << tcc_channel(index, t->wave_output);
return (!t->is_tc && ((tcc_channels[index] & channel_bit) == 0)) ||
t->is_tc;
}
static uint8_t timer_index(uint32_t base_timer_address) {
static uint8_t timer_index(Tcc* base_timer_address) {
#ifdef SAMD21
return (base_timer_address - ((uint32_t) TCC0)) / 0x400;
#endif
// TCCs are scattered through the memory map of the SAMD51 so use a loop.
#ifdef SAMD51
for (uint8_t i = 0; i < TCC_INST_NUM; i++) {
if (base_timer_address == tcc_insts[i]) {
return i;
}
}
#endif
}
void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
@ -185,32 +203,32 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
}
timer_periods[index] = top;
if (t->is_tc) {
struct tc_config config_tc;
tc_get_config_defaults(&config_tc);
// struct tc_config config_tc;
// tc_get_config_defaults(&config_tc);
//
// config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
// config_tc.clock_prescaler = TC_CTRLA_PRESCALER(divisor);
// config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_PWM;
// config_tc.counter_16_bit.compare_capture_channel[0] = top;
config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
config_tc.clock_prescaler = TC_CTRLA_PRESCALER(divisor);
config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_PWM;
config_tc.counter_16_bit.compare_capture_channel[0] = top;
enum status_code status = tc_init(&self->tc_instance, t->tc, &config_tc);
if (status != STATUS_OK) {
mp_raise_RuntimeError("Failed to init timer");
}
tc_enable(&self->tc_instance);
// enum status_code status = tc_init(&self->tc_instance, t->tc, &config_tc);
// if (status != STATUS_OK) {
// mp_raise_RuntimeError("Failed to init timer");
// }
// tc_enable(&self->tc_instance);
} else {
struct tcc_config config_tcc;
tcc_get_config_defaults(&config_tcc, t->tcc);
config_tcc.counter.clock_prescaler = divisor;
config_tcc.counter.period = top;
config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM;
enum status_code status = tcc_init(&self->tcc_instance, t->tcc, &config_tcc);
if (status != STATUS_OK) {
mp_raise_RuntimeError("Failed to init timer");
}
tcc_enable(&self->tcc_instance);
// struct tcc_config config_tcc;
// tcc_get_config_defaults(&config_tcc, t->tcc);
//
// config_tcc.counter.clock_prescaler = divisor;
// config_tcc.counter.period = top;
// config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM;
//
// enum status_code status = tcc_init(&self->tcc_instance, t->tcc, &config_tcc);
// if (status != STATUS_OK) {
// mp_raise_RuntimeError("Failed to init timer");
// }
// tcc_enable(&self->tcc_instance);
}
target_timer_frequencies[index] = frequency;
@ -222,18 +240,18 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
// We're changing frequency so claim all of the channels.
tcc_channels[index] = 0xff;
} else {
tcc_channels[index] |= (1 << t->channel);
tcc_channels[index] |= (1 << tcc_channel(index, t->channel));
}
}
self->timer = t;
// Connect the wave output to the outside world.
struct system_pinmux_config pin_config;
system_pinmux_get_config_defaults(&pin_config);
pin_config.mux_position = &self->pin->primary_timer == t ? MUX_E : MUX_F;
pin_config.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT;
system_pinmux_pin_set_config(pin->pin, &pin_config);
//struct system_pinmux_config pin_config;
//system_pinmux_get_config_defaults(&pin_config);
//pin_config.mux_position = &self->pin->primary_timer == t ? MUX_E : MUX_F;
//pin_config.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT;
//system_pinmux_pin_set_config(pin->pin, &pin_config);
common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
}
@ -250,20 +268,20 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
uint8_t index = (((uint32_t) t->tcc) - ((uint32_t) TCC0)) / 0x400;
timer_refcount[index]--;
if (!t->is_tc) {
tcc_channels[index] &= ~(1 << t->channel);
tcc_channels[index] &= ~(1 << tcc_channel(index, t->wave_output));
}
if (timer_refcount[index] == 0) {
target_timer_frequencies[index] = 0;
if (t->is_tc) {
tc_disable(&self->tc_instance);
//tc_disable(&self->tc_instance);
} else {
if (t->tcc == TCC0) {
tcc_channels[index] = 0xf0;
} else {
tcc_channels[index] = 0xfc;
}
tcc_disable(&self->tcc_instance);
tcc_reset(&self->tcc_instance);
//tcc_disable(&self->tcc_instance);
//tcc_reset(&self->tcc_instance);
}
}
reset_pin(self->pin->pin);
@ -276,31 +294,32 @@ extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self,
if (t->is_tc) {
index = timer_index((uint32_t) self->timer->tc);
uint16_t adjusted_duty = timer_periods[index] * duty / 0xffff;
tc_set_compare_value(&self->tc_instance, t->channel, adjusted_duty);
//tc_set_compare_value(&self->tc_instance, t->channel, adjusted_duty);
} else {
index = timer_index((uint32_t) self->timer->tcc);
uint32_t adjusted_duty = ((uint64_t) timer_periods[index]) * duty / 0xffff;
tcc_set_compare_value(&self->tcc_instance, t->channel, adjusted_duty);
//tcc_set_compare_value(&self->tcc_instance, t->channel, adjusted_duty);
}
}
uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
const pin_timer_t* t = self->timer;
if (t->is_tc) {
while (tc_is_syncing(&self->tc_instance)) {
/* Wait for sync */
}
uint16_t cv = t->tc->COUNT16.CC[t->channel].reg;
// while (tc_is_syncing(&self->tc_instance)) {
// /* Wait for sync */
// }
uint16_t cv = t->tc->COUNT16.CC[t->wave_output].reg;
return cv * 0xffff / timer_periods[timer_index((uint32_t) self->timer->tc)];
} else {
uint8_t channel = tcc_channel(timer_index(t->tcc), t->wave_output);
uint32_t cv = 0;
if ((t->tcc->STATUS.vec.CCBV & (1 << t->channel)) != 0) {
cv = t->tcc->CCB[t->channel].reg;
if ((t->tcc->STATUS.vec.CCBV & (1 << channel)) != 0) {
cv = t->tcc->CCB[channel].reg;
} else {
cv = t->tcc->CC[t->channel].reg;
cv = t->tcc->CC[channel].reg;
}
uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / timer_periods[timer_index((uint32_t) self->timer->tcc)];
uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / timer_periods[timer_index(t->tcc)];
return duty_cycle;
}
@ -332,31 +351,31 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
uint8_t old_divisor;
uint8_t index;
if (t->is_tc) {
index = timer_index((uint32_t) self->timer->tc);
index = timer_index(t->tc);
old_divisor = t->tc->COUNT16.CTRLA.bit.PRESCALER;
} else {
index = timer_index((uint32_t) self->timer->tcc);
index = timer_index(t->tcc);
old_divisor = t->tcc->CTRLA.bit.PRESCALER;
}
if (new_divisor != old_divisor) {
if (t->is_tc) {
tc_disable(&self->tc_instance);
//tc_disable(&self->tc_instance);
t->tc->COUNT16.CTRLA.bit.PRESCALER = new_divisor;
tc_enable(&self->tc_instance);
//tc_enable(&self->tc_instance);
} else {
tcc_disable(&self->tcc_instance);
//tcc_disable(&self->tcc_instance);
t->tcc->CTRLA.bit.PRESCALER = new_divisor;
tcc_enable(&self->tcc_instance);
//tcc_enable(&self->tcc_instance);
}
}
timer_periods[index] = new_top;
if (t->is_tc) {
while (tc_is_syncing(&self->tc_instance)) {
/* Wait for sync */
}
// while (tc_is_syncing(&self->tc_instance)) {
// /* Wait for sync */
// }
t->tc->COUNT16.CC[0].reg = new_top;
} else {
tcc_set_top_value(&self->tcc_instance, new_top);
//tcc_set_top_value(&self->tcc_instance, new_top);
}
common_hal_pulseio_pwmout_set_duty_cycle(self, old_duty);

View File

@ -36,10 +36,6 @@ typedef struct {
const mcu_pin_obj_t *pin;
const pin_timer_t* timer;
bool variable_frequency;
union {
struct tc_module tc_instance;
struct tcc_module tcc_instance;
};
} pulseio_pwmout_obj_t;
void pwmout_reset(void);

View File

@ -28,10 +28,7 @@
#include <stdint.h>
#include "asf/common2/services/delay/delay.h"
#include "asf/sam0/drivers/extint/extint.h"
#include "asf/sam0/drivers/extint/extint_callback.h"
#include "asf/sam0/drivers/port/port.h"
#include "hal/include/hal_gpio.h"
#include "mpconfigport.h"
#include "py/gc.h"
@ -49,7 +46,7 @@ static uint16_t last_us[EIC_NUMBER_OF_INTERRUPTS];
void pulsein_reset(void) {
for (int i = 0; i < EIC_NUMBER_OF_INTERRUPTS; i++) {
if (active_pulseins[i] != NULL) {
extint_chan_disable_callback(i, EXTINT_CALLBACK_TYPE_DETECT);
//extint_chan_disable_callback(i, EXTINT_CALLBACK_TYPE_DETECT);
}
active_pulseins[i] = NULL;
last_ms[i] = 0;
@ -58,65 +55,65 @@ void pulsein_reset(void) {
}
static void pulsein_set_config(pulseio_pulsein_obj_t* self, bool first_edge) {
struct extint_chan_conf config;
extint_chan_get_config_defaults(&config);
config.gpio_pin = self->pin;
config.gpio_pin_pull = EXTINT_PULL_NONE;
config.filter_input_signal = true;
// struct extint_chan_conf config;
// extint_chan_get_config_defaults(&config);
// config.gpio_pin = self->pin;
// config.gpio_pin_pull = EXTINT_PULL_NONE;
// config.filter_input_signal = true;
if (!first_edge) {
config.detection_criteria = EXTINT_DETECT_BOTH;
//config.detection_criteria = EXTINT_DETECT_BOTH;
} else if (self->idle_state) {
config.detection_criteria = EXTINT_DETECT_FALLING;
//config.detection_criteria = EXTINT_DETECT_FALLING;
} else {
config.detection_criteria = EXTINT_DETECT_RISING;
//config.detection_criteria = EXTINT_DETECT_RISING;
}
extint_chan_disable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
extint_chan_set_config(self->channel, &config);
//extint_chan_disable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
//extint_chan_set_config(self->channel, &config);
// Clear any interrupts that may have triggered without notifying the CPU.
EIC->INTFLAG.reg |= (1UL << self->channel);
extint_chan_enable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
//extint_chan_enable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
}
static void pulsein_callback(void) {
//static void pulsein_callback(void) {
// Grab the current time first.
uint16_t current_us = tc_get_count_value(&ms_timer);
//uint16_t current_us = tc_get_count_value(&ms_timer);
// Add the overflow flag to account for tick interrupts that are blocked by
// this interrupt.
uint64_t current_ms = ticks_ms + TC5->COUNT16.INTFLAG.bit.OVF;
pulseio_pulsein_obj_t* self = active_pulseins[extint_get_current_channel()];
current_us = current_us * 1000 / self->ticks_per_ms;
if (self->first_edge) {
self->first_edge = false;
pulsein_set_config(self, false);
} else {
uint32_t ms_diff = current_ms - last_ms[self->channel];
uint16_t us_diff = current_us - last_us[self->channel];
uint32_t total_diff = us_diff;
if (last_us[self->channel] > current_us) {
total_diff = 1000 + current_us - last_us[self->channel];
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++;
}
}
last_ms[self->channel] = current_ms;
last_us[self->channel] = current_us;
}
//uint64_t current_ms = ticks_ms + TC5->COUNT16.INTFLAG.bit.OVF;
//pulseio_pulsein_obj_t* self = active_pulseins[extint_get_current_channel()];
//current_us = current_us * 1000 / self->ticks_per_ms;
// if (self->first_edge) {
// self->first_edge = false;
// pulsein_set_config(self, false);
// } else {
// uint32_t ms_diff = current_ms - last_ms[self->channel];
// uint16_t us_diff = current_us - last_us[self->channel];
// uint32_t total_diff = us_diff;
// if (last_us[self->channel] > current_us) {
// total_diff = 1000 + current_us - last_us[self->channel];
// 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++;
// }
// }
// last_ms[self->channel] = current_ms;
// last_us[self->channel] = 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) {
@ -129,7 +126,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
mp_raise_RuntimeError("EXTINT channel already in use");
}
self->buffer = (uint16_t *) gc_alloc(maxlen * sizeof(uint16_t), false);
self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false);
if (self->buffer == NULL) {
mp_raise_msg_varg(&mp_type_MemoryError, "Failed to allocate RX buffer of %d bytes", maxlen * sizeof(uint16_t));
}
@ -140,16 +137,15 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
self->start = 0;
self->len = 0;
self->first_edge = true;
self->ticks_per_ms = (system_cpu_clock_get_hz() / 1000 - 1);
active_pulseins[pin->extint_channel] = self;
pulsein_set_config(self, true);
extint_register_callback(
pulsein_callback,
self->channel,
EXTINT_CALLBACK_TYPE_DETECT);
extint_chan_enable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
//extint_register_callback(
// pulsein_callback,
// self->channel,
// EXTINT_CALLBACK_TYPE_DETECT);
//extint_chan_enable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
}
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
@ -160,38 +156,27 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
if (common_hal_pulseio_pulsein_deinited(self)) {
return;
}
extint_chan_disable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
//extint_chan_disable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
active_pulseins[self->channel] = NULL;
reset_pin(self->pin);
self->pin = NO_PIN;
}
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
extint_chan_disable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
//extint_chan_disable_callback(self->channel, EXTINT_CALLBACK_TYPE_DETECT);
}
void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
uint16_t trigger_duration) {
// Send the trigger pulse.
if (trigger_duration > 0) {
struct port_config pin_conf;
port_get_config_defaults(&pin_conf);
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
pin_conf.input_pull = PORT_PIN_PULL_NONE;
port_pin_set_config(self->pin, &pin_conf);
// TODO(tannewt): delay_us isn't exactly correct so we adjust the value
// here before calling it. Find out why its not exact and fix it instead
// of hacking around it here.
uint32_t adjusted_duration = trigger_duration;
adjusted_duration *= 4;
adjusted_duration /= 5;
gpio_set_pin_pull_mode(self->pin, GPIO_PULL_OFF);
gpio_set_pin_direction(self->pin, GPIO_DIRECTION_OUT);
common_hal_mcu_disable_interrupts();
port_pin_set_output_level(self->pin, !self->idle_state);
common_hal_mcu_delay_us(adjusted_duration);
port_pin_set_output_level(self->pin, self->idle_state);
gpio_set_pin_level(self->pin, !self->idle_state);
common_hal_mcu_delay_us(trigger_duration);
gpio_set_pin_level(self->pin, self->idle_state);
common_hal_mcu_enable_interrupts();
}

View File

@ -41,7 +41,6 @@ typedef struct {
volatile uint16_t start;
volatile uint16_t len;
volatile bool first_edge;
uint16_t ticks_per_ms;
} pulseio_pulsein_obj_t;
void pulsein_reset(void);

View File

@ -28,8 +28,7 @@
#include <stdint.h>
#include "asf/sam0/drivers/tc/tc_interrupt.h"
#include "asf/sam0/drivers/port/port.h"
#include "hal/include/hal_gpio.h"
#include "mpconfigport.h"
#include "py/gc.h"
@ -37,13 +36,12 @@
#include "samd21_pins.h"
#include "shared-bindings/pulseio/PulseOut.h"
#undef ENABLE
// This timer is shared amongst all PulseOut objects under the assumption that
// the code is single threaded. Its stored in MICROPY_PORT_ROOT_POINTERS so it
// doesn't get garbage collected.
// the code is single threaded.
static uint8_t refcount = 0;
static Tc* pulseout_tc_instance = NULL;
static __IO PORT_PINCFG_Type *active_pincfg = NULL;
static uint16_t *pulse_buffer = NULL;
static volatile uint16_t pulse_index = 0;
@ -70,7 +68,7 @@ void pulse_finish(struct tc_module *const module) {
return;
}
current_compare = (current_compare + pulse_buffer[pulse_index] * 3 / 4) & 0xffff;
tc_set_compare_value(MP_STATE_VM(pulseout_tc_instance), TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
//tc_set_compare_value(MP_STATE_VM(pulseout_tc_instance), TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
if (pulse_index % 2 == 0) {
turn_on(active_pincfg);
}
@ -78,7 +76,7 @@ void pulse_finish(struct tc_module *const module) {
void pulseout_reset() {
refcount = 0;
MP_STATE_VM(pulseout_tc_instance) = NULL;
pulseout_tc_instance = NULL;
active_pincfg = NULL;
}
@ -97,28 +95,24 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
if (t == NULL) {
mp_raise_RuntimeError("All timers in use");
}
MP_STATE_VM(pulseout_tc_instance) = gc_alloc(sizeof(struct tc_module), false);
if (t == NULL) {
mp_raise_msg(&mp_type_MemoryError, "");
}
struct tc_config config_tc;
tc_get_config_defaults(&config_tc);
// struct tc_config config_tc;
// tc_get_config_defaults(&config_tc);
//
// config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
// config_tc.clock_prescaler = TC_CTRLA_PRESCALER_DIV64;
// config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ;
config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
config_tc.clock_prescaler = TC_CTRLA_PRESCALER_DIV64;
config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ;
tc_init(MP_STATE_VM(pulseout_tc_instance), t, &config_tc);
tc_register_callback(MP_STATE_VM(pulseout_tc_instance), pulse_finish, TC_CALLBACK_CC_CHANNEL0);
tc_enable(MP_STATE_VM(pulseout_tc_instance));
tc_stop_counter(MP_STATE_VM(pulseout_tc_instance));
// tc_init(MP_STATE_VM(pulseout_tc_instance), t, &config_tc);
// tc_register_callback(MP_STATE_VM(pulseout_tc_instance), pulse_finish, TC_CALLBACK_CC_CHANNEL0);
// tc_enable(MP_STATE_VM(pulseout_tc_instance));
// tc_stop_counter(MP_STATE_VM(pulseout_tc_instance));
}
refcount++;
self->pin = carrier->pin->pin;
PortGroup *const port_base = port_get_group_from_gpio_pin(self->pin);
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.
@ -144,8 +138,8 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) {
refcount--;
if (refcount == 0) {
tc_reset(MP_STATE_VM(pulseout_tc_instance));
gc_free(MP_STATE_VM(pulseout_tc_instance));
//tc_reset(MP_STATE_VM(pulseout_tc_instance));
m_free(MP_STATE_VM(pulseout_tc_instance));
MP_STATE_VM(pulseout_tc_instance) = NULL;
}
self->pin = NO_PIN;
@ -161,11 +155,11 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
pulse_length = length;
current_compare = pulses[0] * 3 / 4;
tc_set_compare_value(MP_STATE_VM(pulseout_tc_instance), TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
//tc_set_compare_value(MP_STATE_VM(pulseout_tc_instance), TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
tc_enable_callback(MP_STATE_VM(pulseout_tc_instance), TC_CALLBACK_CC_CHANNEL0);
//tc_enable_callback(MP_STATE_VM(pulseout_tc_instance), TC_CALLBACK_CC_CHANNEL0);
turn_on(active_pincfg);
tc_start_counter(MP_STATE_VM(pulseout_tc_instance));
//tc_start_counter(MP_STATE_VM(pulseout_tc_instance));
while(pulse_index < length) {
// Do other things while we wait. The interrupts will handle sending the
@ -175,7 +169,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
#endif
}
tc_stop_counter(MP_STATE_VM(pulseout_tc_instance));
tc_disable_callback(MP_STATE_VM(pulseout_tc_instance), TC_CALLBACK_CC_CHANNEL0);
//tc_stop_counter(MP_STATE_VM(pulseout_tc_instance));
//tc_disable_callback(MP_STATE_VM(pulseout_tc_instance), TC_CALLBACK_CC_CHANNEL0);
active_pincfg = NULL;
}

View File

@ -197,7 +197,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }
// { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR_audiobusio), (mp_obj_t)&audiobusio_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module },
#define EXPRESS_BOARD
#else
#define MICROPY_PY_BUILTINS_REVERSED (0)
@ -212,7 +212,6 @@ extern const struct _mp_obj_module_t usb_hid_module;
// Disabled for now.
// { MP_OBJ_NEW_QSTR(MP_QSTR_touchio), (mp_obj_t)&touchio_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module },
@ -225,6 +224,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)&microcontroller_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \
@ -260,7 +260,6 @@ extern const struct _mp_obj_module_t usb_hid_module;
struct dac_module* audioout_dac_instance; \
struct events_resource* audioout_sample_event; \
struct events_resource* audioout_dac_event; \
struct tc_module* pulseout_tc_instance; \
FLASH_ROOT_POINTERS \
void run_background_tasks(void);

View File

@ -45,12 +45,14 @@
#define TCC(p_tcc, p_wave_output) \
{ \
.tcc = p_tcc, \
.is_tc = false, \
.wave_output = p_wave_output \
}
#define TC(p_tc, p_wave_output) \
{ \
.tc = p_tc, \
.is_tc = true, \
.wave_output = p_wave_output \
}