espneopixel.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. // Original version from https://github.com/adafruit/Adafruit_NeoPixel
  2. // Modifications by dpgeorge to support auto-CPU-frequency detection
  3. // This is a mash-up of the Due show() code + insights from Michael Miller's
  4. // ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
  5. // Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
  6. #include "py/mpconfig.h"
  7. #include "py/mphal.h"
  8. #include "modesp.h"
  9. void IRAM_ATTR esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t timing) {
  10. uint8_t *p, *end, pix, mask;
  11. uint32_t t, time0, time1, period, c, startTime, pinMask;
  12. pinMask = 1 << pin;
  13. p = pixels;
  14. end = p + numBytes;
  15. pix = *p++;
  16. mask = 0x80;
  17. startTime = 0;
  18. uint32_t fcpu = ets_get_cpu_frequency() * 1000000;
  19. if (timing == 1) {
  20. // 800 KHz
  21. time0 = (fcpu * 0.35) / 1000000; // 0.35us
  22. time1 = (fcpu * 0.8) / 1000000; // 0.8us
  23. period = (fcpu * 1.25) / 1000000; // 1.25us per bit
  24. } else {
  25. // 400 KHz
  26. time0 = (fcpu * 0.5) / 1000000; // 0.35us
  27. time1 = (fcpu * 1.2) / 1000000; // 0.8us
  28. period = (fcpu * 2.5) / 1000000; // 1.25us per bit
  29. }
  30. uint32_t irq_state = mp_hal_quiet_timing_enter();
  31. for (t = time0;; t = time0) {
  32. if (pix & mask) t = time1; // Bit high duration
  33. while (((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start
  34. GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, pinMask); // Set high
  35. startTime = c; // Save start time
  36. while (((c = mp_hal_ticks_cpu()) - startTime) < t); // Wait high duration
  37. GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, pinMask); // Set low
  38. if (!(mask >>= 1)) { // Next bit/byte
  39. if(p >= end) break;
  40. pix = *p++;
  41. mask = 0x80;
  42. }
  43. }
  44. while ((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit
  45. mp_hal_quiet_timing_exit(irq_state);
  46. }