esp8266.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // This is a mash-up of the Due show() code + insights from Michael Miller's
  2. // ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
  3. // Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
  4. #if defined(ESP8266)
  5. #include <Arduino.h>
  6. #ifdef ESP8266
  7. #include <eagle_soc.h>
  8. #endif
  9. static uint32_t _getCycleCount(void) __attribute__((always_inline));
  10. static inline uint32_t _getCycleCount(void) {
  11. uint32_t ccount;
  12. __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
  13. return ccount;
  14. }
  15. #ifdef ESP8266
  16. IRAM_ATTR void espShow(
  17. uint8_t pin, uint8_t *pixels, uint32_t numBytes, __attribute__((unused)) boolean is800KHz) {
  18. #else
  19. void espShow(
  20. uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
  21. #endif
  22. #define CYCLES_800_T0H (F_CPU / 2500001) // 0.4us
  23. #define CYCLES_800_T1H (F_CPU / 1250001) // 0.8us
  24. #define CYCLES_800 (F_CPU / 800001) // 1.25us per bit
  25. #define CYCLES_400_T0H (F_CPU / 2000000) // 0.5uS
  26. #define CYCLES_400_T1H (F_CPU / 833333) // 1.2us
  27. #define CYCLES_400 (F_CPU / 400000) // 2.5us per bit
  28. uint8_t *p, *end, pix, mask;
  29. uint32_t t, time0, time1, period, c, startTime;
  30. #ifdef ESP8266
  31. uint32_t pinMask;
  32. pinMask = _BV(pin);
  33. #endif
  34. p = pixels;
  35. end = p + numBytes;
  36. pix = *p++;
  37. mask = 0x80;
  38. startTime = 0;
  39. #ifdef NEO_KHZ400
  40. if(is800KHz) {
  41. #endif
  42. time0 = CYCLES_800_T0H;
  43. time1 = CYCLES_800_T1H;
  44. period = CYCLES_800;
  45. #ifdef NEO_KHZ400
  46. } else { // 400 KHz bitstream
  47. time0 = CYCLES_400_T0H;
  48. time1 = CYCLES_400_T1H;
  49. period = CYCLES_400;
  50. }
  51. #endif
  52. for(t = time0;; t = time0) {
  53. if(pix & mask) t = time1; // Bit high duration
  54. while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
  55. #ifdef ESP8266
  56. GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
  57. #else
  58. gpio_set_level(pin, HIGH);
  59. #endif
  60. startTime = c; // Save start time
  61. while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
  62. #ifdef ESP8266
  63. GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
  64. #else
  65. gpio_set_level(pin, LOW);
  66. #endif
  67. if(!(mask >>= 1)) { // Next bit/byte
  68. if(p >= end) break;
  69. pix = *p++;
  70. mask = 0x80;
  71. }
  72. }
  73. while((_getCycleCount() - startTime) < period); // Wait for last bit
  74. }
  75. #endif // ESP8266