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
0 commit comments