-
-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathDMD_RGB_FM6126a.h
211 lines (162 loc) · 6.89 KB
/
DMD_RGB_FM6126a.h
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#pragma once
#ifndef DMD_RGB_FM6126_H
#define DMD_RGB_FM6126_H
/*--------------------------------------------------------------------------------------
This file is a part of the DMD_STM32 library
DMD_STM32.h - STM32 port of DMD.h library
https://github.com/board707/DMD_STM32
Dmitry Dmitriev (c) 2019-2023
/--------------------------------------------------------------------------------------*/
// FM6126a driver class
// (supported for STM32 boards only)
/*--------------------------------------------------------------------------------------*/
#if (defined(__STM32F1__) || defined(__STM32F4__))
#include "DMD_RGB.h"
// Moment of set CLK signal (0 - CLK immediately with DATA, 1 - CLK one step after DATA)
#define CLOCK_SEPARATE 0
#if CLOCK_SEPARATE == 1
#if defined (DIRECT_OUTPUT)
#define pew \
*(this->datasetreg) = this->clk_clrmask; \
*(this->datasetreg) = *ptr++; \
*(this->datasetreg) = this->clkmask;
#else
#define pew \
*(this->datasetreg) = this->clk_clrmask; \
*(this->datasetreg) = this->expand[*ptr++]; \
*(this->datasetreg) = this->clkmask;
#endif
#elif CLOCK_SEPARATE == 0
#if defined (DIRECT_OUTPUT)
#define pew \
*(this->datasetreg) = this->clk_clrmask; \
*(this->datasetreg) = *ptr++;
#else
#define pew \
*(this->datasetreg) = this->clk_clrmask; \
*(this->datasetreg) = this->expand[*ptr++];
#endif
#endif
template <int MUX_CNT, int P_Width, int P_Height, int SCAN, int SCAN_TYPE, int COL_DEPTH>
class DMD_RGB_FM6126_BASE : public DMD_RGB<MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COL_DEPTH>
{
public:
DMD_RGB_FM6126_BASE(uint8_t* mux_list, byte _pin_nOE, byte _pin_SCLK, uint8_t* pinlist,
byte panelsWide, byte panelsHigh, bool d_buf = false) :
DMD_RGB<MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COL_DEPTH>
(mux_list, _pin_nOE, _pin_SCLK, pinlist,
panelsWide, panelsHigh, d_buf)
{}
#if CLOCK_SEPARATE == 1
void generate_rgbtable() override { DMD_RGB_BASE::generate_rgbtable_default(CLK_AFTER_DATA); }
#elif CLOCK_SEPARATE == 0
void generate_rgbtable() override { DMD_RGB_BASE::generate_rgbtable_default(CLK_WITH_DATA); }
#endif
virtual void chip_init() override {
uint16_t b12a;
//b12a = 0b0111111111111111; // from rpi lib
//b12a = 0b0111100011111111;
//b12a = 0b0000011111100000; // from ESP32-HUB75-MatrixPanel-I2S-DMA
b12a = 0b1111111111000000; // from loganalyzer
uint16_t b13a = 0b0000000001000000;
*(this->oesetreg) = this->oemask; // Disable LED output during row/plane switchover
this->set_mux(1); // A -> High
*(this->latsetreg) = this->latmask << 16; // LAT - LOW
*(this->datasetreg) = this->clk_clrmask; // off all rgb channels
this->send_to_allRGB(b13a, 12); // write 2nd config register
delayMicroseconds(2);
this->send_to_allRGB(b12a, 11); // write 1st config register
delayMicroseconds(2);
this->send_to_allRGB(0, 3); // send all 0's to all rgb
//*muxclrreg = mux_clrmask;
this->set_mux(0); // Clear all mux channels
*(this->oesetreg) = this->oemask << 16;
}
#if (defined(__STM32F1__) || defined(__STM32F4__))
virtual void scan_dmd_p2() override {
timer_set_count(this->MAIN_TIMER, 0);
timer_set_count(this->OE_TIMER, 0);
timer_oc_set_mode(this->OE_TIMER, this->oe_channel, (timer_oc_mode)this->OE_polarity, 0);
timer_generate_update(this->MAIN_TIMER);
timer_generate_update(this->OE_TIMER);
timer_resume(this->OE_TIMER);
timer_resume(this->MAIN_TIMER);
}
#endif
};
template <int MUX_CNT, int P_Width, int P_Height, int SCAN, int SCAN_TYPE, int COL_DEPTH>
class DMD_RGB_FM6126 : public DMD_RGB_FM6126_BASE<MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COL_DEPTH>
{
public:
DMD_RGB_FM6126(uint8_t* mux_list, byte _pin_nOE, byte _pin_SCLK, uint8_t* pinlist,
byte panelsWide, byte panelsHigh, bool d_buf = false) :
DMD_RGB_FM6126_BASE <MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COL_DEPTH>
(mux_list, _pin_nOE, _pin_SCLK, pinlist, panelsWide, panelsHigh, d_buf)
{}
virtual void scan_dmd_p3() override {
// buffptr, being 'volatile' type, doesn't take well to optimization.
// A local register copy can speed some things up:
volatile uint8_t* ptr = this->buffptr;
for (uint16_t uu = 0; uu < this->x_len - 8; uu += 8)
{
// Loop is unrolled for speed:
pew pew pew pew pew pew pew pew
}
pew pew pew pew pew
* (this->datasetreg) = this->clkmask << 16; // Set clock low
*(this->latsetreg) = this->latmask; // Latch data loaded during *prior* interrupt
pew pew pew
* (this->datasetreg) = this->clkmask << 16; // Set clock low
*(this->latsetreg) = this->latmask << 16;// Latch down
*(this->datasetreg) = this->clk_clrmask;
this->buffptr += this->displ_len;
}
};
//--------------------------------------------------------------------------------------
template <int MUX_CNT, int P_Width, int P_Height, int SCAN, int SCAN_TYPE>
class DMD_RGB_FM6126 <MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COLOR_4BITS_Packed>
: public DMD_RGB_FM6126_BASE<MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COLOR_4BITS_Packed>
{
public:
DMD_RGB_FM6126(uint8_t* mux_list, byte _pin_nOE, byte _pin_SCLK, uint8_t* pinlist,
byte panelsWide, byte panelsHigh, bool d_buf = false) :
DMD_RGB_FM6126_BASE <MUX_CNT, P_Width, P_Height, SCAN, SCAN_TYPE, COLOR_4BITS_Packed>
(mux_list, _pin_nOE, _pin_SCLK, pinlist, panelsWide, panelsHigh, d_buf)
{}
virtual void scan_dmd_p3() override {
// buffptr, being 'volatile' type, doesn't take well to optimization.
// A local register copy can speed some things up:
volatile uint8_t* ptr = this->buffptr;
if (this->plane > 0) {
for (uint16_t uu = 0; uu < this->x_len - 8; uu += 8)
{
// Loop is unrolled for speed:
pew pew pew pew pew pew pew pew
}
pew pew pew pew pew
* (this->datasetreg) = this->clkmask << 16; // Set clock low
*(this->latsetreg) = this->latmask; // Latch data loaded during *prior* interrupt
pew pew pew
* (this->datasetreg) = this->clkmask << 16; // Set clock low
*(this->latsetreg) = this->latmask << 16;// Latch down
this->buffptr += this->displ_len;
}
else { // 920 ticks from TCNT1=0 (above) to end of function
for (int i = 0; i < this->x_len; i++) {
byte b =
((ptr[i] >> 2) & 0x30) |
((ptr[i + this->displ_len] >> 4) & 0x0C) |
((ptr[i + this->displ_len * 2] >> 6) & 0x03);
*(this->datasetreg) = this->clk_clrmask; // Clear all data and clock bits together
if (i == (this->x_len - 3)) *(this->latsetreg) = this->latmask;
*(this->datasetreg) = this->expand[b]; // Set new data bits
*(this->datasetreg) = this->clkmask;
}
*(this->datasetreg) = this->clkmask << 16; // Set clock low
*(this->latsetreg) = this->latmask << 16;// Latch down
}
}
};
#undef pew
#endif
#endif