-
Notifications
You must be signed in to change notification settings - Fork 0
/
led_render.cpp
116 lines (77 loc) · 2.87 KB
/
led_render.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
////////////////////////////////////////////////////////////////////////////////
//INCLUDE FILES
////////////////////////////////////////////////////////////////////////////////
#include <arduino.h>
#include "led_render.h"
////////////////////////////////////////////////////////////////////////////////
//THIS FILE ONLY APPLIES TO THE ESP8266, ESP32, AND NODEMCU CHIPS/BOARDS
////////////////////////////////////////////////////////////////////////////////
#if defined(ESP8266) || defined(ESP32)
#define CYCLES_T0H (F_CPU / 2500000)
#define CYCLES_T1H (F_CPU / 1250000)
//#define CYCLES_T0H (F_CPU / 2350000)
//#define CYCLES_T1H (F_CPU / 1100000)
#define CYCLES (F_CPU / 800000)
////////////////////////////////////////////////////////////////////////////////
// GET THE NUMBER OF CPU CYCLES SINCE POWER ON
////////////////////////////////////////////////////////////////////////////////
static INLINE ICACHE_RAM_ATTR uint32_t esp_cycle() {
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
////////////////////////////////////////////////////////////////////////////////
// RENDER ALL OF THE ARRAYS AND GRIDS WITHIN A SINGLE PASS
////////////////////////////////////////////////////////////////////////////////
void ICACHE_RAM_ATTR led_render::render() {
intr_disable();
uint32_t start = 0;
uint16_t count = 0;
uint32_t value = 0;
uint32_t low = 0;
uint32_t data[LED_RENDER_TOTAL];
//FIND THE MAXIMUM NUMBER OF LEDS TO RENDER
//ALSO, RESET EACH LED ARRAY'S INTERNAL POINTER
for (uint16_t x=0; x<LED_RENDER_TOTAL; x++) {
if (!list[x]) continue;
list[x]->rewind();
count = max(count, list[x]->total());
value |= (1 << list[x]->pin());
pinMode(list[x]->pin(), OUTPUT);
}
for (uint16_t i=0; i<count; i++) {
for (uint16_t x=0; x<LED_RENDER_TOTAL; x++) {
if (!list[x]) continue;
color_t color = list[x]->next();
data[x] = (list[x]->mode() == LED_RGB)
? ((uint32_t)color)
: (color.grb());
}
for (int32_t bit=23; bit>=0; bit--) {
//CALCULATE WHICH CHANNELS SHOULD GO LOW
low = 0;
for (uint16_t x=0; x<LED_RENDER_TOTAL; x++) {
if (!list[x]) continue;
if (!(data[x] & (1 << bit))) {
low |= (1 << list[x]->pin());
}
}
//WRITE HIGH VALUE TO **ALL** CHANNELS
start = esp_cycle();
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, value);
//PAUSE UNTIL TIME TO GO LOW, THEN WRITE THE LOW VALUE
//ONLY WRITE TO CHANNELS WITH A **0** BIT
while ((esp_cycle() - start) < CYCLES_T0H) {}
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, low);
//PAUSE AND WRITE LOW VALUE TO **ALL** CHANNELS
while ((esp_cycle() - start) < CYCLES_T1H) {}
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, value);
//PAUSE DURING LOW CYCLE
while ((esp_cycle() - start) < CYCLES) {}
}
//CLEAR ALL BITS
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, value);
}
intr_enable();
}
#endif //defined(ESP8266) || defined(ESP32)