Skip to content
Snippets Groups Projects
Select Git revision
  • 3962766be08f0ccd81bedab1a5d1d8f6468f972e
  • wip-bootstrap default
  • dualcore
  • ch3/leds
  • ch3/time
  • master
6 results

espneopixel.c

Blame
  • espneopixel.c 2.09 KiB
    // Original version from https://github.com/adafruit/Adafruit_NeoPixel
    // Modifications by dpgeorge to support auto-CPU-frequency detection
    
    // This is a mash-up of the Due show() code + insights from Michael Miller's
    // ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
    // Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
    
    #include "c_types.h"
    #include "eagle_soc.h"
    #include "user_interface.h"
    #include "espneopixel.h"
    
    #define NEO_KHZ400 (1)
    
    static uint32_t _getCycleCount(void) __attribute__((always_inline));
    static inline uint32_t _getCycleCount(void) {
      uint32_t ccount;
      __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
      return ccount;
    }
    
    void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
    
      uint8_t *p, *end, pix, mask;
      uint32_t t, time0, time1, period, c, startTime, pinMask;
    
      pinMask   = 1 << pin;
      p         =  pixels;
      end       =  p + numBytes;
      pix       = *p++;
      mask      = 0x80;
      startTime = 0;
    
      uint32_t fcpu = system_get_cpu_freq() * 1000000;
    
    #ifdef NEO_KHZ400
      if(is800KHz) {
    #endif
        time0  = fcpu / 2500000; // 0.4us
        time1  = fcpu / 1250000; // 0.8us
        period = fcpu /  800000; // 1.25us per bit
    #ifdef NEO_KHZ400
      } else { // 400 KHz bitstream
        time0  = fcpu / 2000000; // 0.5uS
        time1  = fcpu /  833333; // 1.2us
        period = fcpu /  400000; // 2.5us per bit
      }
    #endif
    
      for(t = time0;; t = time0) {
        if(pix & mask) t = time1;                             // Bit high duration
        while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
        GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask);       // Set high
        startTime = c;                                        // Save start time
        while(((c = _getCycleCount()) - startTime) < t);      // Wait high duration
        GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask);       // Set low
        if(!(mask >>= 1)) {                                   // Next bit/byte
          if(p >= end) break;
          pix  = *p++;
          mask = 0x80;
        }
      }
      while((_getCycleCount() - startTime) < period); // Wait for last bit
    }