Skip to content

Commit 8596504

Browse files
committed
Believed fix for red pixel
Move code into RAM
1 parent cc19379 commit 8596504

File tree

4 files changed

+150
-110
lines changed

4 files changed

+150
-110
lines changed

NeoPixelBus.cpp

+8-105
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ License along with NeoPixel. If not, see
3131

3232
#include "NeoPixelBus.h"
3333

34+
#if defined(ESP8266)
35+
// due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are
36+
// moved into a C file so the attribute will be applied correctly
37+
extern "C" void ICACHE_RAM_ATTR send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin);
38+
extern "C" void ICACHE_RAM_ATTR send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin);
39+
#endif
40+
3441
NeoPixelBus::NeoPixelBus(uint16_t n, uint8_t p, uint8_t t) :
3542
_countPixels(n),
3643
_sizePixels(n * 3),
@@ -62,111 +69,7 @@ void NeoPixelBus::Begin(void)
6269
Dirty();
6370
}
6471

65-
#if defined(ESP8266)
66-
67-
68-
#define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us
69-
#define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
70-
#define CYCLES_800 (F_CPU / 800000) // 1.25us per bit
71-
#define CYCLES_400_T0H (F_CPU / 2000000)
72-
#define CYCLES_400_T1H (F_CPU / 833333)
73-
#define CYCLES_400 (F_CPU / 400000)
74-
75-
static inline void send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin)
76-
{
77-
const uint32_t pinRegister = _BV(pin);
78-
uint8_t mask;
79-
uint8_t subpix;
80-
uint32_t cyclesStart;
81-
82-
// trigger emediately
83-
cyclesStart = ESP.getCycleCount() - CYCLES_800;
84-
do
85-
{
86-
subpix = *pixels++;
87-
for (mask = 0x80; mask != 0; mask >>= 1)
88-
{
89-
// do the checks here while we are waiting on time to pass
90-
uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_800_T1H : CYCLES_800_T0H;
91-
uint32_t cyclesNext = cyclesStart;
92-
93-
// after we have done as much work as needed for this next bit
94-
// now wait for the HIGH
95-
do
96-
{
97-
// cache and use this count so we don't incur another
98-
// instruction before we turn the bit high
99-
cyclesStart = ESP.getCycleCount();
100-
} while ((cyclesStart - cyclesNext) < CYCLES_800);
101-
102-
// set high
103-
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
104-
105-
// wait for the LOW
106-
do
107-
{
108-
cyclesNext = ESP.getCycleCount();
109-
} while ((cyclesNext - cyclesStart) < cyclesBit);
110-
111-
// set low
112-
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
113-
}
114-
} while (pixels < end);
115-
116-
// while accurate, this isn't needed due to the delays at the
117-
// top of Show() to enforce between update timing
118-
// while ((ESP.getCycleCount() - cyclesStart) < CYCLES_800);
119-
}
120-
121-
static inline void send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin)
122-
{
123-
const uint32_t pinRegister = _BV(pin);
124-
uint8_t mask;
125-
uint8_t subpix;
126-
uint32_t cyclesStart;
127-
128-
// trigger emediately
129-
cyclesStart = ESP.getCycleCount() - CYCLES_400;
130-
while (pixels < end)
131-
{
132-
subpix = *pixels++;
133-
for (mask = 0x80; mask; mask >>= 1)
134-
{
135-
uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_400_T1H : CYCLES_400_T0H;
136-
uint32_t cyclesNext = cyclesStart;
137-
138-
// after we have done as much work as needed for this next bit
139-
// now wait for the HIGH
140-
do
141-
{
142-
// cache and use this count so we don't incur another
143-
// instruction before we turn the bit high
144-
cyclesStart = ESP.getCycleCount();
145-
} while ((cyclesStart - cyclesNext) < CYCLES_400);
146-
147-
// set high
148-
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
149-
150-
// wait for the LOW
151-
do
152-
{
153-
cyclesNext = ESP.getCycleCount();
154-
} while ((cyclesNext - cyclesStart) < cyclesBit);
155-
156-
// set low
157-
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
158-
}
159-
}
160-
161-
// while accurate, this isn't needed due to the delays at the
162-
// top of Show() to enforce between update timing
163-
// while ((ESP.getCycleCount() - cyclesStart) < CYCLES_400);
164-
}
165-
166-
#endif
167-
168-
169-
void NeoPixelBus::Show(void)
72+
void NEOPIXEL_RAM_DECL NeoPixelBus::Show(void)
17073
{
17174
if (!_pixels)
17275
return;

NeoPixelBus.h

+10-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ enum ColorType
2525
ColorType_Hsl
2626
};
2727

28+
#if defined(ESP8266)
29+
#define NEOPIXEL_RAM_DECL ICACHE_RAM_ATTR
30+
#else
31+
// All other supported platforms use the default memory location
32+
#define NEOPIXEL_RAM_DECL
33+
#endif
34+
2835
#include "RgbColor.h"
2936
#include "HslColor.h"
3037
#include "NeoPixelAnimator.h"
@@ -57,7 +64,7 @@ class NeoPixelBus
5764
}
5865

5966
void Begin();
60-
void Show();
67+
void NEOPIXEL_RAM_DECL Show();
6168
inline bool CanShow(void) const
6269
{
6370
return (micros() - _endTime) >= 50L;
@@ -81,11 +88,11 @@ class NeoPixelBus
8188
_flagsPixels &= ~NEO_DIRTY;
8289
}
8390

84-
uint8_t* Pixels() const
91+
uint8_t* Pixels() const
8592
{
8693
return _pixels;
8794
};
88-
uint16_t PixelCount() const
95+
uint16_t PixelCount() const
8996
{
9097
return _countPixels;
9198
};
@@ -98,8 +105,6 @@ class NeoPixelBus
98105

99106
RgbColor GetPixelColor(uint16_t n) const;
100107

101-
102-
103108
private:
104109
friend NeoPixelAnimator;
105110

NeoPixelesp8266.c

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
NeoPixelEsp8266.h - NeoPixel library helper functions for Esp8266 using cycle count
3+
Copyright (c) 2015 Michael C. Miller. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include <Arduino.h>
21+
#include <eagle_soc.h>
22+
23+
#if defined(ESP8266)
24+
25+
inline uint32_t _getCycleCount()
26+
{
27+
uint32_t ccount;
28+
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
29+
return ccount;
30+
}
31+
32+
#define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us
33+
#define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
34+
#define CYCLES_800 (F_CPU / 800000) // 1.25us per bit
35+
#define CYCLES_400_T0H (F_CPU / 2000000)
36+
#define CYCLES_400_T1H (F_CPU / 833333)
37+
#define CYCLES_400 (F_CPU / 400000)
38+
39+
void ICACHE_RAM_ATTR send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin)
40+
{
41+
const uint32_t pinRegister = _BV(pin);
42+
uint8_t mask;
43+
uint8_t subpix;
44+
uint32_t cyclesStart;
45+
46+
// trigger emediately
47+
cyclesStart = _getCycleCount() - CYCLES_800;
48+
do
49+
{
50+
subpix = *pixels++;
51+
for (mask = 0x80; mask != 0; mask >>= 1)
52+
{
53+
// do the checks here while we are waiting on time to pass
54+
uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_800_T1H : CYCLES_800_T0H;
55+
uint32_t cyclesNext = cyclesStart;
56+
uint32_t delta;
57+
58+
// after we have done as much work as needed for this next bit
59+
// now wait for the HIGH
60+
do
61+
{
62+
// cache and use this count so we don't incur another
63+
// instruction before we turn the bit high
64+
cyclesStart = _getCycleCount();
65+
} while ((cyclesStart - cyclesNext) < CYCLES_800);
66+
67+
// set high
68+
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
69+
70+
// wait for the LOW
71+
do
72+
{
73+
cyclesNext = _getCycleCount();
74+
} while ((cyclesNext - cyclesStart) < cyclesBit);
75+
76+
// set low
77+
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
78+
}
79+
} while (pixels < end);
80+
81+
// while accurate, this isn't needed due to the delays at the
82+
// top of Show() to enforce between update timing
83+
// while ((_getCycleCount() - cyclesStart) < CYCLES_800);
84+
}
85+
86+
void ICACHE_RAM_ATTR send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin)
87+
{
88+
const uint32_t pinRegister = _BV(pin);
89+
uint8_t mask;
90+
uint8_t subpix;
91+
uint32_t cyclesStart;
92+
93+
// trigger emediately
94+
cyclesStart = _getCycleCount() - CYCLES_400;
95+
while (pixels < end)
96+
{
97+
subpix = *pixels++;
98+
for (mask = 0x80; mask; mask >>= 1)
99+
{
100+
uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_400_T1H : CYCLES_400_T0H;
101+
uint32_t cyclesNext = cyclesStart;
102+
103+
// after we have done as much work as needed for this next bit
104+
// now wait for the HIGH
105+
do
106+
{
107+
// cache and use this count so we don't incur another
108+
// instruction before we turn the bit high
109+
cyclesStart = _getCycleCount();
110+
} while ((cyclesStart - cyclesNext) < CYCLES_400);
111+
112+
// set high
113+
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
114+
115+
// wait for the LOW
116+
do
117+
{
118+
cyclesNext = _getCycleCount();
119+
} while ((cyclesNext - cyclesStart) < cyclesBit);
120+
121+
// set low
122+
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
123+
}
124+
}
125+
126+
// while accurate, this isn't needed due to the delays at the
127+
// top of Show() to enforce between update timing
128+
// while ((_getCycleCount() - cyclesStart) < CYCLES_400);
129+
}
130+
131+
#endif

ReadMe.md

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ This represents a single NeoPixel Bus that is connected by a single pin. Please
8686

8787
#### NeoPixelBus(uint16_t n, uint8_t p = 6, uint8_t t = NEO_GRB | NEO_KHZ800);
8888
instantiates a NewoPixelBus object, with n number of pixels on the bus, over the p pin, using the defined NeoPixel type.
89+
For the exp8266, only pins 0-15 are supported.
8990
There are some NeoPixels that address the color values differently, so if you set the green color but it displays as red, use the NEO_RGB type flag.
9091

9192
```

0 commit comments

Comments
 (0)