| 199 |
Kevin |
1 |
#include <xc.h>
|
|
|
2 |
#include <plib.h>
|
|
|
3 |
#include "defines.h"
|
|
|
4 |
#include "CUBE.h"
|
|
|
5 |
#include "SPI1.h"
|
|
|
6 |
|
|
|
7 |
static CUBE_DATA *cube_data_ptr;
|
|
|
8 |
static unsigned char current_layer;
|
|
|
9 |
|
|
|
10 |
inline void Cube_Delay() {
|
|
|
11 |
// Small delay to ensure that latch speeds are < 30Mhz
|
|
|
12 |
Nop();
|
|
|
13 |
Nop();
|
|
|
14 |
Nop();
|
|
|
15 |
}
|
|
|
16 |
|
| 200 |
Kevin |
17 |
void Cube_Init(CUBE_DATA *data, char BC) {
|
| 199 |
Kevin |
18 |
cube_data_ptr = data;
|
|
|
19 |
current_layer = 0;
|
|
|
20 |
|
|
|
21 |
SFT_D = 0;
|
|
|
22 |
SFT_S = 0;
|
|
|
23 |
SFT_K = 0;
|
|
|
24 |
SFT_R = 0;
|
|
|
25 |
GSLAT = 0;
|
|
|
26 |
XBLNK = 0;
|
|
|
27 |
|
|
|
28 |
SFT_D_TRIS = 0;
|
|
|
29 |
SFT_S_TRIS = 0;
|
|
|
30 |
SFT_K_TRIS = 0;
|
|
|
31 |
SFT_R_TRIS = 0;
|
|
|
32 |
GSLAT_TRIS = 0;
|
|
|
33 |
XBLNK_TRIS = 0;
|
|
|
34 |
|
|
|
35 |
// Clear the shift register
|
|
|
36 |
Cube_Delay();
|
|
|
37 |
SFT_K = 1;
|
|
|
38 |
Cube_Delay();
|
|
|
39 |
SFT_K = 0;
|
|
|
40 |
Cube_Delay();
|
|
|
41 |
SFT_S = 1;
|
|
|
42 |
Cube_Delay();
|
|
|
43 |
SFT_S = 0;
|
|
|
44 |
Cube_Delay();
|
|
|
45 |
SFT_R = 1;
|
|
|
46 |
|
| 200 |
Kevin |
47 |
Cube_Write_DCS(BC);
|
| 199 |
Kevin |
48 |
Cube_Clear();
|
|
|
49 |
}
|
|
|
50 |
|
|
|
51 |
void Cube_Timer_Interrupt(void) {
|
|
|
52 |
// Write to the GCS register
|
|
|
53 |
SPI1_Write(cube_data_ptr->GCS[current_layer], GCS_LAYER_SIZE, &Cube_GCS_Write_Callback);
|
|
|
54 |
}
|
|
|
55 |
|
|
|
56 |
void Cube_DCS_Write_Callback(void) {
|
|
|
57 |
// GSLAT must be >7ms after DCS write
|
|
|
58 |
Delay_MS(7);
|
|
|
59 |
GSLAT = 0;
|
|
|
60 |
Cube_Delay();
|
|
|
61 |
GSLAT = 1;
|
|
|
62 |
Cube_Delay();
|
|
|
63 |
GSLAT = 0;
|
|
|
64 |
}
|
|
|
65 |
|
|
|
66 |
void Cube_GCS_Write_Callback(void) {
|
|
|
67 |
// Disable LED output and latch in written data to GCS
|
|
|
68 |
XBLNK = 0;
|
|
|
69 |
Cube_Delay();
|
|
|
70 |
GSLAT = 1;
|
|
|
71 |
// Set the shift register to turn on the current layer
|
|
|
72 |
int i;
|
|
|
73 |
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
|
|
|
74 |
Cube_Delay();
|
|
|
75 |
SFT_D = (i == CUBE_LAYER_COUNT - current_layer - 1) ? 1 : 0;
|
|
|
76 |
Cube_Delay();
|
|
|
77 |
SFT_K = 1;
|
|
|
78 |
Cube_Delay();
|
|
|
79 |
SFT_K = 0;
|
|
|
80 |
}
|
|
|
81 |
Cube_Delay();
|
|
|
82 |
SFT_S = 1;
|
|
|
83 |
Cube_Delay();
|
|
|
84 |
SFT_S = 0;
|
|
|
85 |
Cube_Delay();
|
|
|
86 |
// Enable LED output
|
|
|
87 |
XBLNK = 1;
|
|
|
88 |
Cube_Delay();
|
|
|
89 |
GSLAT = 0;
|
|
|
90 |
|
|
|
91 |
current_layer = (current_layer == CUBE_LAYER_COUNT-1) ? 0 : current_layer + 1;
|
|
|
92 |
}
|
|
|
93 |
|
| 200 |
Kevin |
94 |
void Cube_Write_DCS(char BC) {
|
|
|
95 |
if (BC > CUBE_MAX_BRIGHTNESS)
|
|
|
96 |
BC = CUBE_MAX_BRIGHTNESS;
|
|
|
97 |
|
|
|
98 |
XBLNK = 0;
|
|
|
99 |
int i,j;
|
|
|
100 |
// Write configuration data to the DC/BC/FC/UD registers
|
|
|
101 |
unsigned char DCS[GCS_LAYER_SIZE] = {0};
|
|
|
102 |
for (i = 0; i < 8; i++) {
|
|
|
103 |
int offset = i * GCS_REG_SIZE;
|
|
|
104 |
|
|
|
105 |
for (j = 0; j < 21; j++) {
|
|
|
106 |
DCS[offset + j] = 0xFF; // Dot correction
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
// Warning: do not set BC > 0x6F
|
|
|
110 |
DCS[offset + 21] = BC; // Global red brightness
|
|
|
111 |
DCS[offset + 22] = BC; // Global green brightness
|
|
|
112 |
DCS[offset + 23] = BC; // Global blue brightness
|
|
|
113 |
|
|
|
114 |
// DC low range, auto repeat, no timing reset, 8 bit counter mode
|
|
|
115 |
DCS[offset + 24] = 0x68; // 0110 1000
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
GSLAT = 1;
|
|
|
119 |
SPI1_Write(DCS, GCS_LAYER_SIZE, &Cube_DCS_Write_Callback);
|
|
|
120 |
Delay_MS(8); // Delay until the entire DCS write is finished
|
|
|
121 |
}
|
|
|
122 |
|
| 199 |
Kevin |
123 |
void Cube_Clear(void) {
|
|
|
124 |
int i,j;
|
|
|
125 |
for (i = 0; i < CUBE_LAYER_COUNT; i++)
|
|
|
126 |
for (j = 0; j < GCS_LAYER_SIZE; j++)
|
|
|
127 |
cube_data_ptr->GCS[i][j] = 0x00;
|
|
|
128 |
}
|
|
|
129 |
|
|
|
130 |
void Cube_Set_All(int R, int G, int B) {
|
|
|
131 |
R &= 0x0FFF;
|
|
|
132 |
G &= 0x0FFF;
|
|
|
133 |
B &= 0x0FFF;
|
|
|
134 |
int i,j,k;
|
|
|
135 |
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
|
|
|
136 |
for (j = 0; j < CUBE_ROW_COUNT; j++) {
|
|
|
137 |
int j_var = j * GCS_REG_SIZE;
|
|
|
138 |
for (k = 0; k < 4; k++) {
|
|
|
139 |
int k_var = j_var + (k * 9);
|
|
|
140 |
cube_data_ptr->GCS[i][k_var+0] = R & 0xFF;;
|
|
|
141 |
cube_data_ptr->GCS[i][k_var+1] = (G << 4) | (R >> 8);
|
|
|
142 |
cube_data_ptr->GCS[i][k_var+2] = G >> 4;
|
|
|
143 |
cube_data_ptr->GCS[i][k_var+3] = B & 0xFF;
|
|
|
144 |
cube_data_ptr->GCS[i][k_var+4] = (R << 4) | (B >> 8);
|
|
|
145 |
cube_data_ptr->GCS[i][k_var+5] = R >> 4;
|
|
|
146 |
cube_data_ptr->GCS[i][k_var+6] = G & 0xFF;
|
|
|
147 |
cube_data_ptr->GCS[i][k_var+7] = (B << 4) | (G >> 8);
|
|
|
148 |
cube_data_ptr->GCS[i][k_var+8] = B >> 4;
|
|
|
149 |
}
|
|
|
150 |
}
|
|
|
151 |
}
|
|
|
152 |
}
|
|
|
153 |
|
|
|
154 |
void Cube_Set_Layer(int layer, int R, int G, int B) {
|
|
|
155 |
R &= 0x0FFF;
|
|
|
156 |
G &= 0x0FFF;
|
|
|
157 |
B &= 0x0FFF;
|
|
|
158 |
int i,j;
|
|
|
159 |
for (i = 0; i < CUBE_ROW_COUNT; i++) {
|
|
|
160 |
int i_var = i * GCS_REG_SIZE;
|
|
|
161 |
for (j = 0; j < 4; j++) {
|
|
|
162 |
int j_var = i_var + (j * 9);
|
|
|
163 |
cube_data_ptr->GCS[layer][j_var+0] = R & 0xFF;;
|
|
|
164 |
cube_data_ptr->GCS[layer][j_var+1] = (G << 4) | (R >> 8);
|
|
|
165 |
cube_data_ptr->GCS[layer][j_var+2] = G >> 4;
|
|
|
166 |
cube_data_ptr->GCS[layer][j_var+3] = B & 0xFF;
|
|
|
167 |
cube_data_ptr->GCS[layer][j_var+4] = (R << 4) | (B >> 8);
|
|
|
168 |
cube_data_ptr->GCS[layer][j_var+5] = R >> 4;
|
|
|
169 |
cube_data_ptr->GCS[layer][j_var+6] = G & 0xFF;
|
|
|
170 |
cube_data_ptr->GCS[layer][j_var+7] = (B << 4) | (G >> 8);
|
|
|
171 |
cube_data_ptr->GCS[layer][j_var+8] = B >> 4;
|
|
|
172 |
}
|
|
|
173 |
}
|
|
|
174 |
}
|
|
|
175 |
|
|
|
176 |
void Cube_Set_Pixel(int layer, int row, int column, int R, int G, int B) {
|
|
|
177 |
R &= 0x0FFF;
|
|
|
178 |
G &= 0x0FFF;
|
|
|
179 |
B &= 0x0FFF;
|
|
|
180 |
int var = row * GCS_REG_SIZE + (column / 2 * 9);
|
|
|
181 |
switch (column % 2) {
|
|
|
182 |
case 0:
|
|
|
183 |
cube_data_ptr->GCS[layer][var+0] = R & 0xFF;
|
|
|
184 |
cube_data_ptr->GCS[layer][var+1] = (G << 4) | (R >> 8);
|
|
|
185 |
cube_data_ptr->GCS[layer][var+2] = G >> 4;
|
|
|
186 |
cube_data_ptr->GCS[layer][var+3] = B & 0xFF;
|
|
|
187 |
cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0xF0) | (B >> 8);
|
|
|
188 |
break;
|
|
|
189 |
case 1:
|
|
|
190 |
cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0x0F) | (R << 4);
|
|
|
191 |
cube_data_ptr->GCS[layer][var+5] = R >> 4;
|
|
|
192 |
cube_data_ptr->GCS[layer][var+6] = G & 0xFF;
|
|
|
193 |
cube_data_ptr->GCS[layer][var+7] = (B << 4) | (G >> 8);
|
|
|
194 |
cube_data_ptr->GCS[layer][var+8] = B >> 4;
|
|
|
195 |
break;
|
|
|
196 |
}
|
|
|
197 |
}
|