WIP
This commit is contained in:
parent
e2d1e1e281
commit
190e7d629e
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)µcontroller_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);
|
||||
|
|
|
@ -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 \
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue