generalize # of ports; remove atmel neopixel code; remove pin name in mc_pin_obj_t
This commit is contained in:
parent
4382389e6f
commit
b5c03a7085
|
@ -44,11 +44,12 @@ bool speaker_enable_in_use;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Bit mask of claimed pins on each of up to two ports. nrf52832 has one port; nrf52840 has two.
|
// Bit mask of claimed pins on each of up to two ports. nrf52832 has one port; nrf52840 has two.
|
||||||
STATIC uint32_t claimed_pins[2];
|
STATIC uint32_t claimed_pins[GPIO_COUNT];
|
||||||
|
|
||||||
void reset_all_pins(void) {
|
void reset_all_pins(void) {
|
||||||
claimed_pins[0] = 0;
|
for (size_t i = 0; i < GPIO_COUNT; i++) {
|
||||||
claimed_pins[1] = 0;
|
claimed_pins[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t pin = 0; pin < NUMBER_OF_PINS; ++pin) {
|
for (uint32_t pin = 0; pin < NUMBER_OF_PINS; ++pin) {
|
||||||
nrf_gpio_cfg_default(pin);
|
nrf_gpio_cfg_default(pin);
|
||||||
|
|
|
@ -29,133 +29,6 @@
|
||||||
|
|
||||||
#include "tick.h"
|
#include "tick.h"
|
||||||
|
|
||||||
// This magical macro makes sure the delay isn't optimized out and is the
|
|
||||||
// minimal three instructions.
|
|
||||||
#define delay_cycles(cycles) \
|
|
||||||
{ \
|
|
||||||
uint32_t t; \
|
|
||||||
asm volatile ( \
|
|
||||||
"movs %[t], %[c]\n\t" \
|
|
||||||
"loop%=:\n\t" \
|
|
||||||
"subs %[t], #1\n\t" \
|
|
||||||
"bne.n loop%=" : [t] "=r"(t) : [c] "I" (cycles)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t next_start_tick_ms = 0;
|
|
||||||
uint32_t next_start_tick_us = 1000;
|
|
||||||
|
|
||||||
void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
|
void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
|
||||||
// TODO: Figure out timing delays on nRF. Turn off cache using ICACHECNF register.
|
// stub
|
||||||
/*
|
|
||||||
// This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code:
|
|
||||||
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
|
|
||||||
uint8_t *ptr, *end, p, bitMask;
|
|
||||||
uint32_t pinMask;
|
|
||||||
PortGroup* port;
|
|
||||||
|
|
||||||
// This must be called while interrupts are on in case we're waiting for a
|
|
||||||
// future ms tick.
|
|
||||||
wait_until(next_start_tick_ms, next_start_tick_us);
|
|
||||||
|
|
||||||
// Turn off interrupts of any kind during timing-sensitive code.
|
|
||||||
mp_hal_disable_all_interrupts();
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure the NVM cache is consistently timed.
|
|
||||||
|
|
||||||
NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_DETERMINISTIC_Val;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t pin = digitalinout->pin->number;
|
|
||||||
port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register
|
|
||||||
pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code.
|
|
||||||
ptr = pixels;
|
|
||||||
end = ptr + numBytes;
|
|
||||||
p = *ptr++;
|
|
||||||
bitMask = 0x80;
|
|
||||||
|
|
||||||
volatile uint32_t *set = &(port->OUTSET.reg),
|
|
||||||
*clr = &(port->OUTCLR.reg);
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
*set = pinMask;
|
|
||||||
// This is the time where the line is always high regardless of the bit.
|
|
||||||
// For the SK6812 its 0.3us +- 0.15us
|
|
||||||
#ifdef SAMD21
|
|
||||||
asm("nop; nop;");
|
|
||||||
#endif
|
|
||||||
#ifdef SAMD51
|
|
||||||
delay_cycles(3);
|
|
||||||
#endif
|
|
||||||
if(p & bitMask) {
|
|
||||||
// This is the high delay unique to a one bit.
|
|
||||||
// For the SK6812 its 0.3us
|
|
||||||
#ifdef SAMD21
|
|
||||||
asm("nop; nop; nop; nop; nop; nop; nop;");
|
|
||||||
#endif
|
|
||||||
#ifdef SAMD51
|
|
||||||
delay_cycles(11);
|
|
||||||
#endif
|
|
||||||
*clr = pinMask;
|
|
||||||
} else {
|
|
||||||
*clr = pinMask;
|
|
||||||
// This is the low delay unique to a zero bit.
|
|
||||||
// For the SK6812 its 0.3us
|
|
||||||
#ifdef SAMD21
|
|
||||||
asm("nop; nop;");
|
|
||||||
#endif
|
|
||||||
#ifdef SAMD51
|
|
||||||
delay_cycles(3);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if((bitMask >>= 1) != 0) {
|
|
||||||
// This is the delay between bits in a byte and is the 1 code low
|
|
||||||
// level time from the datasheet.
|
|
||||||
// For the SK6812 its 0.6us +- 0.15us
|
|
||||||
#ifdef SAMD21
|
|
||||||
asm("nop; nop; nop; nop; nop;");
|
|
||||||
#endif
|
|
||||||
#ifdef SAMD51
|
|
||||||
delay_cycles(20);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
if(ptr >= end) break;
|
|
||||||
p = *ptr++;
|
|
||||||
bitMask = 0x80;
|
|
||||||
// This is the delay between bytes. It's similar to the other branch
|
|
||||||
// in the if statement except its tuned to account for the time the
|
|
||||||
// above operations take.
|
|
||||||
// For the SK6812 its 0.6us +- 0.15us
|
|
||||||
#ifdef SAMD51
|
|
||||||
delay_cycles(15);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SAMD21
|
|
||||||
// Speed up! (But inconsistent timing.)
|
|
||||||
NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY_Val;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SAMD51
|
|
||||||
// Turn instruction, data, and NVM caches back on.
|
|
||||||
hri_cmcc_clear_CFG_reg(CMCC, CMCC_CFG_DCDIS | CMCC_CFG_ICDIS);
|
|
||||||
hri_nvmctrl_clear_CTRLA_CACHEDIS0_bit(NVMCTRL);
|
|
||||||
hri_nvmctrl_clear_CTRLA_CACHEDIS1_bit(NVMCTRL);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ticks_ms may be out of date at this point because we stopped the
|
|
||||||
// interrupt. We'll risk it anyway.
|
|
||||||
current_tick(&next_start_tick_ms, &next_start_tick_us);
|
|
||||||
if (next_start_tick_us < 100) {
|
|
||||||
next_start_tick_ms += 1;
|
|
||||||
next_start_tick_us = 100 - next_start_tick_us;
|
|
||||||
} else {
|
|
||||||
next_start_tick_us -= 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn on interrupts after timing-sensitive code.
|
|
||||||
mp_hal_enable_all_interrupts();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
qstr name;
|
|
||||||
// These could be squeezed to fewer bits if more fields are needed.
|
// These could be squeezed to fewer bits if more fields are needed.
|
||||||
uint8_t number; // port << 5 | pin number in port (0-31): 6 bits needed
|
uint8_t number; // port << 5 | pin number in port (0-31): 6 bits needed
|
||||||
uint8_t adc_channel; // 0 is no ADC, ADC channel from 1 to 8:
|
uint8_t adc_channel; // 0 is no ADC, ADC channel from 1 to 8:
|
||||||
|
@ -50,7 +49,6 @@ extern const mp_obj_type_t mcu_pin_type;
|
||||||
#define PIN(p_name, p_port, p_pin, p_adc_channel) \
|
#define PIN(p_name, p_port, p_pin, p_adc_channel) \
|
||||||
{ \
|
{ \
|
||||||
{ &mcu_pin_type }, \
|
{ &mcu_pin_type }, \
|
||||||
.name = MP_QSTR_ ## p_name, \
|
|
||||||
.number = NRF_GPIO_PIN_MAP(p_port, p_pin), \
|
.number = NRF_GPIO_PIN_MAP(p_port, p_pin), \
|
||||||
.adc_channel = (p_adc_channel), \
|
.adc_channel = (p_adc_channel), \
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue