void tone(uint8_t pin, uint16_t frequency, uint32_t duration) { uint32_t count, load; volatile uint32_t *config; if (pin >= CORE_NUM_DIGITAL) return; if (duration) { count = (frequency * duration / 1000) * 2; } else { count = 0xFFFFFFFF; } load = (F_BUS / 2) / frequency; config = portConfigRegister(pin); __disable_irq(); if (pin != tone_pin) { if (tone_pin < CORE_NUM_DIGITAL) { tone_reg[0] = 1; // clear pin } tone_pin = pin; tone_reg = portClearRegister(pin); tone_reg[0] = 1; // clear pin tone_reg[384] = 1; // output mode; *config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); } tone_toggle_count = count; if (PIT_LDVAL3 != load) { PIT_TCTRL3 = 0; PIT_LDVAL3 = load; PIT_TCTRL3 = 3; } __enable_irq(); }
void tone(uint8_t pin, uint16_t frequency, uint32_t duration) { uint32_t count; volatile uint32_t *config; float usec; if (pin >= CORE_NUM_DIGITAL) return; if (duration) { count = (frequency * duration / 1000) * 2; } else { count = 0xFFFFFFFF; } usec = (float)500000.0 / (float)frequency; config = portConfigRegister(pin); // TODO: IntervalTimer really needs an API to disable and enable // the interrupt on a single timer. __disable_irq(); if (pin == tone_pin) { if (frequency == tone_frequency) { // same pin, same frequency, so just update the // duration. Users will call repetitively call // tone() with the same setting, expecting a // continuous output with no glitches or phase // changes or jitter at each call. tone_toggle_count = count; } else { // same pin, but a new frequency. TONE_CLEAR_PIN; // clear pin tone_timer.begin(tone_interrupt, usec); } } else { if (tone_pin < CORE_NUM_DIGITAL) { TONE_CLEAR_PIN; // clear pin } tone_pin = pin; tone_reg = portClearRegister(pin); #if defined(KINETISL) tone_mask = digitalPinToBitMask(pin); #endif TONE_CLEAR_PIN; // clear pin TONE_OUTPUT_PIN; // output mode; *config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); tone_toggle_count = count; tone_timer.begin(tone_interrupt, usec); } __enable_irq(); }
#define CYCLES_800_T1H (F_CPU / 1250000) // 0.7us on, .6us off ?? #define CYCLES_800 (F_CPU / 800000) #define CYCLES_400_T0H (F_CPU / 2000000) #define CYCLES_400_T1H (F_CPU / 833333) #define CYCLES_400 (F_CPU / 400000) // TODO: test dithering?? CRGB scale = CRGB(m_brightness, m_brightness, m_brightness); // corbin, fix m_brightness to not mess w/stuff // corbin...figure out how to do the template based on the type PixelController<GRB> pixelController(m_pixels, numLEDs, scale, DISABLE_DITHER); pixelController.preStepFirstByteDithering(); volatile uint8_t *set = portSetRegister(pin); volatile uint8_t *clr = portClearRegister(pin); // Get access to the clock ARM_DEMCR |= ARM_DEMCR_TRCENA; // what is this set for?? ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; ARM_DWT_CYCCNT = 0; #ifdef NEO_KHZ400 if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream #endif uint32_t cyc = ARM_DWT_CYCCNT + CYCLES_800; register uint8_t b = pixelController.loadAndScale0(); while (pixelController.has(1)) { pixelController.stepDithering();