PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 line
2.4KB

  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) || defined(ESP32)
  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. void ICACHE_RAM_ATTR espShow(
  17. uint8_t pin, uint8_t *pixels, uint32_t numBytes, 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 / 2500000) // 0.4us
  23. #define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
  24. #define CYCLES_800 (F_CPU / 800000) // 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, pinMask;
  30. pinMask = _BV(pin);
  31. p = pixels;
  32. end = p + numBytes;
  33. pix = *p++;
  34. mask = 0x80;
  35. startTime = 0;
  36. #ifdef NEO_KHZ400
  37. if(is800KHz) {
  38. #endif
  39. time0 = CYCLES_800_T0H;
  40. time1 = CYCLES_800_T1H;
  41. period = CYCLES_800;
  42. #ifdef NEO_KHZ400
  43. } else { // 400 KHz bitstream
  44. time0 = CYCLES_400_T0H;
  45. time1 = CYCLES_400_T1H;
  46. period = CYCLES_400;
  47. }
  48. #endif
  49. for(t = time0;; t = time0) {
  50. if(pix & mask) t = time1; // Bit high duration
  51. while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
  52. #ifdef ESP8266
  53. GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
  54. #else
  55. gpio_set_level(pin, HIGH);
  56. #endif
  57. startTime = c; // Save start time
  58. while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
  59. #ifdef ESP8266
  60. GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
  61. #else
  62. gpio_set_level(pin, LOW);
  63. #endif
  64. if(!(mask >>= 1)) { // Next bit/byte
  65. if(p >= end) break;
  66. pix = *p++;
  67. mask = 0x80;
  68. }
  69. }
  70. while((_getCycleCount() - startTime) < period); // Wait for last bit
  71. }
  72. #endif // ESP8266