Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
199 Kevin 1
#include "defines.h"
2
#include "CUBE.h"
3
#include "SPI1.h"
206 Kevin 4
#include "glcdfont.h"
213 Kevin 5
#include "UART1.h"
199 Kevin 6
 
7
static CUBE_DATA *cube_data_ptr;
8
 
9
inline void Cube_Delay() {
10
    // Small delay to ensure that latch speeds are < 30Mhz
11
    Nop();
12
    Nop();
13
    Nop();
14
}
15
 
231 Kevin 16
void Cube_Init(CUBE_DATA *data, uint8_t BC) {
199 Kevin 17
    cube_data_ptr = data;
201 Kevin 18
    cube_data_ptr->current_layer = 0;
205 Kevin 19
    cube_data_ptr->rotation_counter = 0;
212 Kevin 20
    cube_data_ptr->frame_state = IDLE;
21
    cube_data_ptr->frame_escape = 0;
199 Kevin 22
 
23
    SFT_D = 0;
24
    SFT_S = 0;
25
    SFT_K = 0;
26
    SFT_R = 0;
27
    GSLAT = 0;
28
    XBLNK = 0;
29
 
30
    SFT_D_TRIS = 0;
31
    SFT_S_TRIS = 0;
32
    SFT_K_TRIS = 0;
33
    SFT_R_TRIS = 0;
34
    GSLAT_TRIS = 0;
35
    XBLNK_TRIS = 0;
36
 
37
    // Clear the shift register
38
    Cube_Delay();
39
    SFT_K = 1;
40
    Cube_Delay();
41
    SFT_K = 0;
42
    Cube_Delay();
43
    SFT_S = 1;
44
    Cube_Delay();
45
    SFT_S = 0;
46
    Cube_Delay();
47
    SFT_R = 1;
48
 
200 Kevin 49
    Cube_Write_DCS(BC);
199 Kevin 50
    Cube_Clear();
206 Kevin 51
    Cube_Overlay_Clear();
199 Kevin 52
}
53
 
54
void Cube_Timer_Interrupt(void) {
206 Kevin 55
    // OR values in the overlay array with the display array
231 Kevin 56
    uint8_t i;
57
    uint16_t j;
206 Kevin 58
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
59
        for (j = 0; j < GCS_LAYER_SIZE; j++) {
60
            cube_data_ptr->GCS_WRITE[i][j] = cube_data_ptr->GCS[i][j] | cube_data_ptr->GCS_OVERLAY[i][j];
61
        }
62
    }
199 Kevin 63
    // Write to the GCS register
206 Kevin 64
    SPI1_Write(cube_data_ptr->GCS_WRITE[cube_data_ptr->current_layer], GCS_LAYER_SIZE, &Cube_GCS_Write_Callback);
199 Kevin 65
}
66
 
212 Kevin 67
////////////////////////
68
// Callback functions //
69
////////////////////////
70
 
199 Kevin 71
void Cube_DCS_Write_Callback(void) {
72
    // GSLAT must be >7ms after DCS write
73
    Delay_MS(7);
74
    GSLAT = 0;
75
    Cube_Delay();
76
    GSLAT = 1;
77
    Cube_Delay();
78
    GSLAT = 0;
79
}
80
 
81
void Cube_GCS_Write_Callback(void) {
82
    // Disable LED output and latch in written data to GCS
83
    XBLNK = 0;
84
    Cube_Delay();
85
    GSLAT = 1;
86
    // Set the shift register to turn on the current layer
231 Kevin 87
    uint8_t i;
199 Kevin 88
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
89
        Cube_Delay();
201 Kevin 90
        SFT_D = (i == CUBE_LAYER_COUNT - cube_data_ptr->current_layer - 1) ? 1 : 0;
199 Kevin 91
        Cube_Delay();
92
        SFT_K = 1;
93
        Cube_Delay();
94
        SFT_K = 0;
95
    }
96
    Cube_Delay();
97
    SFT_S = 1;
98
    Cube_Delay();
99
    SFT_S = 0;
100
    Cube_Delay();
101
    // Enable LED output
102
    XBLNK = 1;
103
    Cube_Delay();
104
    GSLAT = 0;
105
 
201 Kevin 106
    cube_data_ptr->current_layer = (cube_data_ptr->current_layer == CUBE_LAYER_COUNT-1)
107
            ? 0 : cube_data_ptr->current_layer + 1;
199 Kevin 108
}
109
 
212 Kevin 110
////////////////////////////
111
// Cube control functions //
112
////////////////////////////
113
 
231 Kevin 114
void Cube_Write_DCS(uint8_t BC) {
200 Kevin 115
    XBLNK = 0;
231 Kevin 116
    uint8_t i,j;
200 Kevin 117
    // Write configuration data to the DC/BC/FC/UD registers
231 Kevin 118
    uint8_t DCS[GCS_LAYER_SIZE] = {0};
200 Kevin 119
    for (i = 0; i < 8; i++) {
231 Kevin 120
        uint16_t offset = i * GCS_REG_SIZE;
200 Kevin 121
 
122
        for (j = 0; j < 21; j++) {
123
            DCS[offset + j] = 0xFF; // Dot correction
124
        }
125
 
126
        // Warning: do not set BC > 0x6F
127
        DCS[offset + 21] = BC; // Global red brightness
128
        DCS[offset + 22] = BC; // Global green brightness
129
        DCS[offset + 23] = BC; // Global blue brightness
130
 
131
        // DC low range, auto repeat, no timing reset, 8 bit counter mode
132
        DCS[offset + 24] = 0x68; // 0110 1000
133
    }
134
 
135
    GSLAT = 1;
136
    SPI1_Write(DCS, GCS_LAYER_SIZE, &Cube_DCS_Write_Callback);
201 Kevin 137
    Delay_MS(10); // Delay until the entire DCS write is finished
200 Kevin 138
}
139
 
199 Kevin 140
void Cube_Clear(void) {
231 Kevin 141
    uint8_t i;
142
    uint16_t j;
199 Kevin 143
    for (i = 0; i < CUBE_LAYER_COUNT; i++)
144
        for (j = 0; j < GCS_LAYER_SIZE; j++)
145
            cube_data_ptr->GCS[i][j] = 0x00;
146
}
147
 
231 Kevin 148
void Cube_Set_All(uint16_t R, uint16_t G, uint16_t B) {
201 Kevin 149
    // Set all pixels in the cube to the given color
199 Kevin 150
    R &= 0x0FFF;
151
    G &= 0x0FFF;
152
    B &= 0x0FFF;
231 Kevin 153
    uint8_t i,j,k;
199 Kevin 154
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
155
        for (j = 0; j < CUBE_ROW_COUNT; j++) {
231 Kevin 156
            uint16_t j_var = j * GCS_REG_SIZE;
199 Kevin 157
            for (k = 0; k < 4; k++) {
231 Kevin 158
                uint16_t k_var = j_var + (k * 9);
199 Kevin 159
                cube_data_ptr->GCS[i][k_var+0] = R & 0xFF;;
160
                cube_data_ptr->GCS[i][k_var+1] = (G << 4) | (R >> 8);
161
                cube_data_ptr->GCS[i][k_var+2] = G >> 4;
162
                cube_data_ptr->GCS[i][k_var+3] = B & 0xFF;
163
                cube_data_ptr->GCS[i][k_var+4] = (R << 4) | (B >> 8);
164
                cube_data_ptr->GCS[i][k_var+5] = R >> 4;
165
                cube_data_ptr->GCS[i][k_var+6] = G & 0xFF;
166
                cube_data_ptr->GCS[i][k_var+7] = (B << 4) | (G >> 8);
167
                cube_data_ptr->GCS[i][k_var+8] = B >> 4;
168
            }
169
        }
170
    }
171
}
172
 
231 Kevin 173
void Cube_Set_Layer(uint8_t layer, uint16_t R, uint16_t G, uint16_t B) {
201 Kevin 174
    // Set all pixels in the specified layer to the given color
199 Kevin 175
    R &= 0x0FFF;
176
    G &= 0x0FFF;
177
    B &= 0x0FFF;
231 Kevin 178
    uint8_t i,j;
199 Kevin 179
    for (i = 0; i < CUBE_ROW_COUNT; i++) {
231 Kevin 180
        uint16_t i_var = i * GCS_REG_SIZE;
199 Kevin 181
        for (j = 0; j < 4; j++) {
231 Kevin 182
            uint16_t j_var = i_var + (j * 9);
199 Kevin 183
            cube_data_ptr->GCS[layer][j_var+0] = R & 0xFF;;
184
            cube_data_ptr->GCS[layer][j_var+1] = (G << 4) | (R >> 8);
185
            cube_data_ptr->GCS[layer][j_var+2] = G >> 4;
186
            cube_data_ptr->GCS[layer][j_var+3] = B & 0xFF;
187
            cube_data_ptr->GCS[layer][j_var+4] = (R << 4) | (B >> 8);
188
            cube_data_ptr->GCS[layer][j_var+5] = R >> 4;
189
            cube_data_ptr->GCS[layer][j_var+6] = G & 0xFF;
190
            cube_data_ptr->GCS[layer][j_var+7] = (B << 4) | (G >> 8);
191
            cube_data_ptr->GCS[layer][j_var+8] = B >> 4;
192
        }
193
    }
194
}
195
 
231 Kevin 196
void Cube_Set_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t R, uint16_t G, uint16_t B) {
201 Kevin 197
    // Set the specified pixel to the given color
199 Kevin 198
    R &= 0x0FFF;
199
    G &= 0x0FFF;
200
    B &= 0x0FFF;
231 Kevin 201
    uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);
199 Kevin 202
    switch (column % 2) {
203
        case 0:
204
            cube_data_ptr->GCS[layer][var+0] = R & 0xFF;
205
            cube_data_ptr->GCS[layer][var+1] = (G << 4) | (R >> 8);
206
            cube_data_ptr->GCS[layer][var+2] = G >> 4;
207
            cube_data_ptr->GCS[layer][var+3] = B & 0xFF;
208
            cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0xF0) | (B >> 8);
209
            break;
210
        case 1:
211
            cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0x0F) | (R << 4);
212
            cube_data_ptr->GCS[layer][var+5] = R >> 4;
213
            cube_data_ptr->GCS[layer][var+6] = G & 0xFF;
214
            cube_data_ptr->GCS[layer][var+7] = (B << 4) | (G >> 8);
215
            cube_data_ptr->GCS[layer][var+8] = B >> 4;
216
            break;
217
    }
205 Kevin 218
}
219
 
231 Kevin 220
void Cube_Get_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t* R, uint16_t* G, uint16_t* B) {
221
    uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);
205 Kevin 222
    switch (column % 2) {
223
        // Concatenate lower byte and upper byte of each color channel
224
        case 0:
225
            *R = cube_data_ptr->GCS[layer][var+0] | ((cube_data_ptr->GCS[layer][var+1] & 0x0F) << 8);
226
            *G = (cube_data_ptr->GCS[layer][var+1] >> 4) | (cube_data_ptr->GCS[layer][var+2] << 4);
227
            *B = cube_data_ptr->GCS[layer][var+3] | ((cube_data_ptr->GCS[layer][var+4] & 0x0F) << 8);
228
            break;
229
        case 1:
230
            *R = (cube_data_ptr->GCS[layer][var+4] >> 4) | (cube_data_ptr->GCS[layer][var+5] << 4);
231
            *G = cube_data_ptr->GCS[layer][var+6] | ((cube_data_ptr->GCS[layer][var+7] & 0x0F) << 8);
232
            *B = (cube_data_ptr->GCS[layer][var+7] >> 4) | (cube_data_ptr->GCS[layer][var+8] << 4);
233
            break;
234
    }
235
}
236
 
231 Kevin 237
void Cube_Move_Pixel(uint8_t layer1, uint8_t row1, uint8_t column1, uint8_t layer2, uint8_t row2, uint8_t column2) {
206 Kevin 238
    // Copies data from pixel 1 to pixel 2
205 Kevin 239
    // Note: destination pixel value is overwritten
231 Kevin 240
    uint16_t prev_R, prev_G, prev_B;
205 Kevin 241
    Cube_Get_Pixel(layer1, row1, column1, &prev_R, &prev_G, &prev_B);
242
    Cube_Set_Pixel(layer2, row2, column2, prev_R, prev_G, prev_B);
243
}
244
 
231 Kevin 245
void Cube_Rotate_Shell(uint8_t shell, uint8_t direction) {
205 Kevin 246
    // Shell is the layer to rotate, with the outermost being 0
231 Kevin 247
    uint8_t layer;
248
    uint16_t origin_R, origin_G, origin_B;
205 Kevin 249
    for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {
206 Kevin 250
        if (direction) {
251
            switch(shell) {
252
                case 0:
253
                    // Rotate outermost layer
254
                    Cube_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
255
                    Cube_Move_Pixel(layer, 0, 1, layer, 0, 0);
256
                    Cube_Move_Pixel(layer, 0, 2, layer, 0, 1);
257
                    Cube_Move_Pixel(layer, 0, 3, layer, 0, 2);
258
                    Cube_Move_Pixel(layer, 0, 4, layer, 0, 3);
259
                    Cube_Move_Pixel(layer, 0, 5, layer, 0, 4);
260
                    Cube_Move_Pixel(layer, 0, 6, layer, 0, 5);
261
                    Cube_Move_Pixel(layer, 0, 7, layer, 0, 6);
262
                    Cube_Move_Pixel(layer, 1, 7, layer, 0, 7);
263
                    Cube_Move_Pixel(layer, 2, 7, layer, 1, 7);
264
                    Cube_Move_Pixel(layer, 3, 7, layer, 2, 7);
265
                    Cube_Move_Pixel(layer, 4, 7, layer, 3, 7);
266
                    Cube_Move_Pixel(layer, 5, 7, layer, 4, 7);
267
                    Cube_Move_Pixel(layer, 6, 7, layer, 5, 7);
268
                    Cube_Move_Pixel(layer, 7, 7, layer, 6, 7);
269
                    Cube_Move_Pixel(layer, 7, 6, layer, 7, 7);
270
                    Cube_Move_Pixel(layer, 7, 5, layer, 7, 6);
271
                    Cube_Move_Pixel(layer, 7, 4, layer, 7, 5);
272
                    Cube_Move_Pixel(layer, 7, 3, layer, 7, 4);
273
                    Cube_Move_Pixel(layer, 7, 2, layer, 7, 3);
274
                    Cube_Move_Pixel(layer, 7, 1, layer, 7, 2);
275
                    Cube_Move_Pixel(layer, 7, 0, layer, 7, 1);
276
                    Cube_Move_Pixel(layer, 6, 0, layer, 7, 0);
277
                    Cube_Move_Pixel(layer, 5, 0, layer, 6, 0);
278
                    Cube_Move_Pixel(layer, 4, 0, layer, 5, 0);
279
                    Cube_Move_Pixel(layer, 3, 0, layer, 4, 0);
280
                    Cube_Move_Pixel(layer, 2, 0, layer, 3, 0);
281
                    Cube_Move_Pixel(layer, 1, 0, layer, 2, 0);
282
                    Cube_Set_Pixel(layer, 1, 0, origin_R, origin_G, origin_B);
283
                    break;
284
                case 1:
285
                    // Rotate second to outermost layer
286
                    Cube_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
287
                    Cube_Move_Pixel(layer, 1, 2, layer, 1, 1);
288
                    Cube_Move_Pixel(layer, 1, 3, layer, 1, 2);
289
                    Cube_Move_Pixel(layer, 1, 4, layer, 1, 3);
290
                    Cube_Move_Pixel(layer, 1, 5, layer, 1, 4);
291
                    Cube_Move_Pixel(layer, 1, 6, layer, 1, 5);
292
                    Cube_Move_Pixel(layer, 2, 6, layer, 1, 6);
293
                    Cube_Move_Pixel(layer, 3, 6, layer, 2, 6);
294
                    Cube_Move_Pixel(layer, 4, 6, layer, 3, 6);
295
                    Cube_Move_Pixel(layer, 5, 6, layer, 4, 6);
296
                    Cube_Move_Pixel(layer, 6, 6, layer, 5, 6);
297
                    Cube_Move_Pixel(layer, 6, 5, layer, 6, 6);
298
                    Cube_Move_Pixel(layer, 6, 4, layer, 6, 5);
299
                    Cube_Move_Pixel(layer, 6, 3, layer, 6, 4);
300
                    Cube_Move_Pixel(layer, 6, 2, layer, 6, 3);
301
                    Cube_Move_Pixel(layer, 6, 1, layer, 6, 2);
302
                    Cube_Move_Pixel(layer, 5, 1, layer, 6, 1);
303
                    Cube_Move_Pixel(layer, 4, 1, layer, 5, 1);
304
                    Cube_Move_Pixel(layer, 3, 1, layer, 4, 1);
305
                    Cube_Move_Pixel(layer, 2, 1, layer, 3, 1);
306
                    Cube_Set_Pixel(layer, 2, 1, origin_R, origin_G, origin_B);
307
                    break;
308
                case 2:
309
                    // Rotate second to innermost layer
310
                    Cube_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
311
                    Cube_Move_Pixel(layer, 2, 3, layer, 2, 2);
312
                    Cube_Move_Pixel(layer, 2, 4, layer, 2, 3);
313
                    Cube_Move_Pixel(layer, 2, 5, layer, 2, 4);
314
                    Cube_Move_Pixel(layer, 3, 5, layer, 2, 5);
315
                    Cube_Move_Pixel(layer, 4, 5, layer, 3, 5);
316
                    Cube_Move_Pixel(layer, 5, 5, layer, 4, 5);
317
                    Cube_Move_Pixel(layer, 5, 4, layer, 5, 5);
318
                    Cube_Move_Pixel(layer, 5, 3, layer, 5, 4);
319
                    Cube_Move_Pixel(layer, 5, 2, layer, 5, 3);
320
                    Cube_Move_Pixel(layer, 4, 2, layer, 5, 2);
321
                    Cube_Move_Pixel(layer, 3, 2, layer, 4, 2);
322
                    Cube_Set_Pixel(layer, 3, 2, origin_R, origin_G, origin_B);
323
                    break;
324
                case 3:
325
                    // Rotate innermost layer
326
                    Cube_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
327
                    Cube_Move_Pixel(layer, 3, 4, layer, 3, 3);
328
                    Cube_Move_Pixel(layer, 4, 4, layer, 3, 4);
329
                    Cube_Move_Pixel(layer, 4, 3, layer, 4, 4);
330
                    Cube_Set_Pixel(layer, 4, 3, origin_R, origin_G, origin_B);
331
                    break;
332
            }
333
        } else {
334
            switch(shell) {
335
                case 0:
336
                    // Rotate outermost layer
337
                    Cube_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
338
                    Cube_Move_Pixel(layer, 1, 0, layer, 0, 0);
339
                    Cube_Move_Pixel(layer, 2, 0, layer, 1, 0);
340
                    Cube_Move_Pixel(layer, 3, 0, layer, 2, 0);
341
                    Cube_Move_Pixel(layer, 4, 0, layer, 3, 0);
342
                    Cube_Move_Pixel(layer, 5, 0, layer, 4, 0);
343
                    Cube_Move_Pixel(layer, 6, 0, layer, 5, 0);
344
                    Cube_Move_Pixel(layer, 7, 0, layer, 6, 0);
345
                    Cube_Move_Pixel(layer, 7, 1, layer, 7, 0);
346
                    Cube_Move_Pixel(layer, 7, 2, layer, 7, 1);
347
                    Cube_Move_Pixel(layer, 7, 3, layer, 7, 2);
348
                    Cube_Move_Pixel(layer, 7, 4, layer, 7, 3);
349
                    Cube_Move_Pixel(layer, 7, 5, layer, 7, 4);
350
                    Cube_Move_Pixel(layer, 7, 6, layer, 7, 5);
351
                    Cube_Move_Pixel(layer, 7, 7, layer, 7, 6);
352
                    Cube_Move_Pixel(layer, 6, 7, layer, 7, 7);
353
                    Cube_Move_Pixel(layer, 5, 7, layer, 6, 7);
354
                    Cube_Move_Pixel(layer, 4, 7, layer, 5, 7);
355
                    Cube_Move_Pixel(layer, 3, 7, layer, 4, 7);
356
                    Cube_Move_Pixel(layer, 2, 7, layer, 3, 7);
357
                    Cube_Move_Pixel(layer, 1, 7, layer, 2, 7);
358
                    Cube_Move_Pixel(layer, 0, 7, layer, 1, 7);
359
                    Cube_Move_Pixel(layer, 0, 6, layer, 0, 7);
360
                    Cube_Move_Pixel(layer, 0, 5, layer, 0, 6);
361
                    Cube_Move_Pixel(layer, 0, 4, layer, 0, 5);
362
                    Cube_Move_Pixel(layer, 0, 3, layer, 0, 4);
363
                    Cube_Move_Pixel(layer, 0, 2, layer, 0, 3);
364
                    Cube_Move_Pixel(layer, 0, 1, layer, 0, 2);
365
                    Cube_Set_Pixel(layer, 0, 1, origin_R, origin_G, origin_B);
366
                    break;
367
                case 1:
368
                    // Rotate second to outermost layer
369
                    Cube_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
370
                    Cube_Move_Pixel(layer, 2, 1, layer, 1, 1);
371
                    Cube_Move_Pixel(layer, 3, 1, layer, 2, 1);
372
                    Cube_Move_Pixel(layer, 4, 1, layer, 3, 1);
373
                    Cube_Move_Pixel(layer, 5, 1, layer, 4, 1);
374
                    Cube_Move_Pixel(layer, 6, 1, layer, 5, 1);
375
                    Cube_Move_Pixel(layer, 6, 2, layer, 6, 1);
376
                    Cube_Move_Pixel(layer, 6, 3, layer, 6, 2);
377
                    Cube_Move_Pixel(layer, 6, 4, layer, 6, 3);
378
                    Cube_Move_Pixel(layer, 6, 5, layer, 6, 4);
379
                    Cube_Move_Pixel(layer, 6, 6, layer, 6, 5);
380
                    Cube_Move_Pixel(layer, 5, 6, layer, 6, 6);
381
                    Cube_Move_Pixel(layer, 4, 6, layer, 5, 6);
382
                    Cube_Move_Pixel(layer, 3, 6, layer, 4, 6);
383
                    Cube_Move_Pixel(layer, 2, 6, layer, 3, 6);
384
                    Cube_Move_Pixel(layer, 1, 6, layer, 2, 6);
385
                    Cube_Move_Pixel(layer, 1, 5, layer, 1, 6);
386
                    Cube_Move_Pixel(layer, 1, 4, layer, 1, 5);
387
                    Cube_Move_Pixel(layer, 1, 3, layer, 1, 4);
388
                    Cube_Move_Pixel(layer, 1, 2, layer, 1, 3);
389
                    Cube_Set_Pixel(layer, 1, 2, origin_R, origin_G, origin_B);
390
                    break;
391
                case 2:
392
                    // Rotate second to innermost layer
393
                    Cube_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
394
                    Cube_Move_Pixel(layer, 3, 2, layer, 2, 2);
395
                    Cube_Move_Pixel(layer, 4, 2, layer, 3, 2);
396
                    Cube_Move_Pixel(layer, 5, 2, layer, 4, 2);
397
                    Cube_Move_Pixel(layer, 5, 3, layer, 5, 2);
398
                    Cube_Move_Pixel(layer, 5, 4, layer, 5, 3);
399
                    Cube_Move_Pixel(layer, 5, 5, layer, 5, 4);
400
                    Cube_Move_Pixel(layer, 4, 5, layer, 5, 5);
401
                    Cube_Move_Pixel(layer, 3, 5, layer, 4, 5);
402
                    Cube_Move_Pixel(layer, 2, 5, layer, 3, 5);
403
                    Cube_Move_Pixel(layer, 2, 4, layer, 2, 5);
404
                    Cube_Move_Pixel(layer, 2, 3, layer, 2, 4);
405
                    Cube_Set_Pixel(layer, 2, 3, origin_R, origin_G, origin_B);
406
                    break;
407
                case 3:
408
                    // Rotate innermost layer
409
                    Cube_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
410
                    Cube_Move_Pixel(layer, 4, 3, layer, 3, 3);
411
                    Cube_Move_Pixel(layer, 4, 4, layer, 4, 3);
412
                    Cube_Move_Pixel(layer, 3, 4, layer, 4, 4);
413
                    Cube_Set_Pixel(layer, 3, 4, origin_R, origin_G, origin_B);
414
                    break;
415
            }
205 Kevin 416
        }
417
    }
418
}
419
 
231 Kevin 420
void Cube_Rotate(uint8_t direction) {
205 Kevin 421
    // Rotate outermost layer
206 Kevin 422
    Cube_Rotate_Shell(0, direction);
205 Kevin 423
    // Rotate second to outermost layer
424
    if ((cube_data_ptr->rotation_counter != 1) && (cube_data_ptr->rotation_counter != 5)) {
206 Kevin 425
        Cube_Rotate_Shell(1, direction);
205 Kevin 426
    }
427
    // Rotate second to innermost layer
428
    if ((cube_data_ptr->rotation_counter != 0) && (cube_data_ptr->rotation_counter != 2) &&
429
        (cube_data_ptr->rotation_counter != 4) && (cube_data_ptr->rotation_counter != 6)) {
206 Kevin 430
        Cube_Rotate_Shell(2, direction);
205 Kevin 431
    }
432
    // Rotate innermost layer
433
    if ((cube_data_ptr->rotation_counter == 3) || (cube_data_ptr->rotation_counter == 7)) {
206 Kevin 434
        Cube_Rotate_Shell(3, direction);
205 Kevin 435
    }
436
 
209 Kevin 437
    if (direction == 0) {
438
        cube_data_ptr->rotation_counter = (cube_data_ptr->rotation_counter == CUBE_ROTATIONS - 1)
439
                ? 0 : cube_data_ptr->rotation_counter + 1;
440
    } else {
441
        cube_data_ptr->rotation_counter = (cube_data_ptr->rotation_counter == 0)
442
                ? CUBE_ROTATIONS - 1 : cube_data_ptr->rotation_counter - 1;
443
    }
206 Kevin 444
}
445
 
212 Kevin 446
///////////////////////////////
447
// Overlay control functions //
448
///////////////////////////////
206 Kevin 449
 
450
void Cube_Overlay_Clear(void) {
231 Kevin 451
    uint16_t i,j;
452
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
453
        for (j = 0; j < GCS_LAYER_SIZE; j++) {
206 Kevin 454
            cube_data_ptr->GCS_OVERLAY[i][j] = 0x00;
231 Kevin 455
        }
456
    }
206 Kevin 457
}
458
 
231 Kevin 459
void Cube_Overlay_Set_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t R, uint16_t G, uint16_t B) {
206 Kevin 460
    // Set the specified pixel to the given color
461
    R &= 0x0FFF;
462
    G &= 0x0FFF;
463
    B &= 0x0FFF;
231 Kevin 464
    uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);
206 Kevin 465
    switch (column % 2) {
466
        case 0:
467
            cube_data_ptr->GCS_OVERLAY[layer][var+0] = R & 0xFF;
468
            cube_data_ptr->GCS_OVERLAY[layer][var+1] = (G << 4) | (R >> 8);
469
            cube_data_ptr->GCS_OVERLAY[layer][var+2] = G >> 4;
470
            cube_data_ptr->GCS_OVERLAY[layer][var+3] = B & 0xFF;
471
            cube_data_ptr->GCS_OVERLAY[layer][var+4] = (cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0xF0) | (B >> 8);
472
            break;
473
        case 1:
474
            cube_data_ptr->GCS_OVERLAY[layer][var+4] = (cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0x0F) | (R << 4);
475
            cube_data_ptr->GCS_OVERLAY[layer][var+5] = R >> 4;
476
            cube_data_ptr->GCS_OVERLAY[layer][var+6] = G & 0xFF;
477
            cube_data_ptr->GCS_OVERLAY[layer][var+7] = (B << 4) | (G >> 8);
478
            cube_data_ptr->GCS_OVERLAY[layer][var+8] = B >> 4;
479
            break;
480
    }
481
}
482
 
231 Kevin 483
void Cube_Overlay_Get_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t* R, uint16_t* G, uint16_t* B) {
484
    uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);
206 Kevin 485
    switch (column % 2) {
486
        // Concatenate lower byte and upper byte of each color channel
487
        case 0:
488
            *R = cube_data_ptr->GCS_OVERLAY[layer][var+0] | ((cube_data_ptr->GCS_OVERLAY[layer][var+1] & 0x0F) << 8);
489
            *G = (cube_data_ptr->GCS_OVERLAY[layer][var+1] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+2] << 4);
490
            *B = cube_data_ptr->GCS_OVERLAY[layer][var+3] | ((cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0x0F) << 8);
491
            break;
492
        case 1:
493
            *R = (cube_data_ptr->GCS_OVERLAY[layer][var+4] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+5] << 4);
494
            *G = cube_data_ptr->GCS_OVERLAY[layer][var+6] | ((cube_data_ptr->GCS_OVERLAY[layer][var+7] & 0x0F) << 8);
495
            *B = (cube_data_ptr->GCS_OVERLAY[layer][var+7] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+8] << 4);
496
            break;
497
    }
498
}
499
 
231 Kevin 500
void Cube_Overlay_Move_Pixel(uint8_t layer1, uint8_t row1, uint8_t column1, uint8_t layer2, uint8_t row2, uint8_t column2) {
206 Kevin 501
    // Copies data from pixel 1 to pixel 2
502
    // Note: destination pixel value is overwritten
231 Kevin 503
    uint16_t prev_R, prev_G, prev_B;
206 Kevin 504
    Cube_Overlay_Get_Pixel(layer1, row1, column1, &prev_R, &prev_G, &prev_B);
505
    Cube_Overlay_Set_Pixel(layer2, row2, column2, prev_R, prev_G, prev_B);
506
}
507
 
231 Kevin 508
void Cube_Overlay_Rotate_Shell(uint8_t shell, uint8_t direction) {
206 Kevin 509
    // Shell is the layer to rotate, with the outermost being 0
231 Kevin 510
    uint8_t layer;
511
    uint16_t origin_R, origin_G, origin_B;;
206 Kevin 512
    for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {
513
        if (direction) {
514
            switch(shell) {
515
                case 0:
516
                    // Rotate outermost layer
517
                    Cube_Overlay_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
518
                    Cube_Overlay_Move_Pixel(layer, 0, 1, layer, 0, 0);
519
                    Cube_Overlay_Move_Pixel(layer, 0, 2, layer, 0, 1);
520
                    Cube_Overlay_Move_Pixel(layer, 0, 3, layer, 0, 2);
521
                    Cube_Overlay_Move_Pixel(layer, 0, 4, layer, 0, 3);
522
                    Cube_Overlay_Move_Pixel(layer, 0, 5, layer, 0, 4);
523
                    Cube_Overlay_Move_Pixel(layer, 0, 6, layer, 0, 5);
524
                    Cube_Overlay_Move_Pixel(layer, 0, 7, layer, 0, 6);
525
                    Cube_Overlay_Move_Pixel(layer, 1, 7, layer, 0, 7);
526
                    Cube_Overlay_Move_Pixel(layer, 2, 7, layer, 1, 7);
527
                    Cube_Overlay_Move_Pixel(layer, 3, 7, layer, 2, 7);
528
                    Cube_Overlay_Move_Pixel(layer, 4, 7, layer, 3, 7);
529
                    Cube_Overlay_Move_Pixel(layer, 5, 7, layer, 4, 7);
530
                    Cube_Overlay_Move_Pixel(layer, 6, 7, layer, 5, 7);
531
                    Cube_Overlay_Move_Pixel(layer, 7, 7, layer, 6, 7);
532
                    Cube_Overlay_Move_Pixel(layer, 7, 6, layer, 7, 7);
533
                    Cube_Overlay_Move_Pixel(layer, 7, 5, layer, 7, 6);
534
                    Cube_Overlay_Move_Pixel(layer, 7, 4, layer, 7, 5);
535
                    Cube_Overlay_Move_Pixel(layer, 7, 3, layer, 7, 4);
536
                    Cube_Overlay_Move_Pixel(layer, 7, 2, layer, 7, 3);
537
                    Cube_Overlay_Move_Pixel(layer, 7, 1, layer, 7, 2);
538
                    Cube_Overlay_Move_Pixel(layer, 7, 0, layer, 7, 1);
539
                    Cube_Overlay_Move_Pixel(layer, 6, 0, layer, 7, 0);
540
                    Cube_Overlay_Move_Pixel(layer, 5, 0, layer, 6, 0);
541
                    Cube_Overlay_Move_Pixel(layer, 4, 0, layer, 5, 0);
542
                    Cube_Overlay_Move_Pixel(layer, 3, 0, layer, 4, 0);
543
                    Cube_Overlay_Move_Pixel(layer, 2, 0, layer, 3, 0);
544
                    Cube_Overlay_Move_Pixel(layer, 1, 0, layer, 2, 0);
545
                    Cube_Overlay_Set_Pixel(layer, 1, 0, origin_R, origin_G, origin_B);
546
                    break;
547
                case 1:
548
                    // Rotate second to outermost layer
549
                    Cube_Overlay_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
550
                    Cube_Overlay_Move_Pixel(layer, 1, 2, layer, 1, 1);
551
                    Cube_Overlay_Move_Pixel(layer, 1, 3, layer, 1, 2);
552
                    Cube_Overlay_Move_Pixel(layer, 1, 4, layer, 1, 3);
553
                    Cube_Overlay_Move_Pixel(layer, 1, 5, layer, 1, 4);
554
                    Cube_Overlay_Move_Pixel(layer, 1, 6, layer, 1, 5);
555
                    Cube_Overlay_Move_Pixel(layer, 2, 6, layer, 1, 6);
556
                    Cube_Overlay_Move_Pixel(layer, 3, 6, layer, 2, 6);
557
                    Cube_Overlay_Move_Pixel(layer, 4, 6, layer, 3, 6);
558
                    Cube_Overlay_Move_Pixel(layer, 5, 6, layer, 4, 6);
559
                    Cube_Overlay_Move_Pixel(layer, 6, 6, layer, 5, 6);
560
                    Cube_Overlay_Move_Pixel(layer, 6, 5, layer, 6, 6);
561
                    Cube_Overlay_Move_Pixel(layer, 6, 4, layer, 6, 5);
562
                    Cube_Overlay_Move_Pixel(layer, 6, 3, layer, 6, 4);
563
                    Cube_Overlay_Move_Pixel(layer, 6, 2, layer, 6, 3);
564
                    Cube_Overlay_Move_Pixel(layer, 6, 1, layer, 6, 2);
565
                    Cube_Overlay_Move_Pixel(layer, 5, 1, layer, 6, 1);
566
                    Cube_Overlay_Move_Pixel(layer, 4, 1, layer, 5, 1);
567
                    Cube_Overlay_Move_Pixel(layer, 3, 1, layer, 4, 1);
568
                    Cube_Overlay_Move_Pixel(layer, 2, 1, layer, 3, 1);
569
                    Cube_Overlay_Set_Pixel(layer, 2, 1, origin_R, origin_G, origin_B);
570
                    break;
571
                case 2:
572
                    // Rotate second to innermost layer
573
                    Cube_Overlay_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
574
                    Cube_Overlay_Move_Pixel(layer, 2, 3, layer, 2, 2);
575
                    Cube_Overlay_Move_Pixel(layer, 2, 4, layer, 2, 3);
576
                    Cube_Overlay_Move_Pixel(layer, 2, 5, layer, 2, 4);
577
                    Cube_Overlay_Move_Pixel(layer, 3, 5, layer, 2, 5);
578
                    Cube_Overlay_Move_Pixel(layer, 4, 5, layer, 3, 5);
579
                    Cube_Overlay_Move_Pixel(layer, 5, 5, layer, 4, 5);
580
                    Cube_Overlay_Move_Pixel(layer, 5, 4, layer, 5, 5);
581
                    Cube_Overlay_Move_Pixel(layer, 5, 3, layer, 5, 4);
582
                    Cube_Overlay_Move_Pixel(layer, 5, 2, layer, 5, 3);
583
                    Cube_Overlay_Move_Pixel(layer, 4, 2, layer, 5, 2);
584
                    Cube_Overlay_Move_Pixel(layer, 3, 2, layer, 4, 2);
585
                    Cube_Overlay_Set_Pixel(layer, 3, 2, origin_R, origin_G, origin_B);
586
                    break;
587
                case 3:
588
                    // Rotate innermost layer
589
                    Cube_Overlay_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
590
                    Cube_Overlay_Move_Pixel(layer, 3, 4, layer, 3, 3);
591
                    Cube_Overlay_Move_Pixel(layer, 4, 4, layer, 3, 4);
592
                    Cube_Overlay_Move_Pixel(layer, 4, 3, layer, 4, 4);
593
                    Cube_Overlay_Set_Pixel(layer, 4, 3, origin_R, origin_G, origin_B);
594
                    break;
595
            }
596
        } else {
597
            switch(shell) {
598
                case 0:
599
                    // Rotate outermost layer
600
                    Cube_Overlay_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
601
                    Cube_Overlay_Move_Pixel(layer, 1, 0, layer, 0, 0);
602
                    Cube_Overlay_Move_Pixel(layer, 2, 0, layer, 1, 0);
603
                    Cube_Overlay_Move_Pixel(layer, 3, 0, layer, 2, 0);
604
                    Cube_Overlay_Move_Pixel(layer, 4, 0, layer, 3, 0);
605
                    Cube_Overlay_Move_Pixel(layer, 5, 0, layer, 4, 0);
606
                    Cube_Overlay_Move_Pixel(layer, 6, 0, layer, 5, 0);
607
                    Cube_Overlay_Move_Pixel(layer, 7, 0, layer, 6, 0);
608
                    Cube_Overlay_Move_Pixel(layer, 7, 1, layer, 7, 0);
609
                    Cube_Overlay_Move_Pixel(layer, 7, 2, layer, 7, 1);
610
                    Cube_Overlay_Move_Pixel(layer, 7, 3, layer, 7, 2);
611
                    Cube_Overlay_Move_Pixel(layer, 7, 4, layer, 7, 3);
612
                    Cube_Overlay_Move_Pixel(layer, 7, 5, layer, 7, 4);
613
                    Cube_Overlay_Move_Pixel(layer, 7, 6, layer, 7, 5);
614
                    Cube_Overlay_Move_Pixel(layer, 7, 7, layer, 7, 6);
615
                    Cube_Overlay_Move_Pixel(layer, 6, 7, layer, 7, 7);
616
                    Cube_Overlay_Move_Pixel(layer, 5, 7, layer, 6, 7);
617
                    Cube_Overlay_Move_Pixel(layer, 4, 7, layer, 5, 7);
618
                    Cube_Overlay_Move_Pixel(layer, 3, 7, layer, 4, 7);
619
                    Cube_Overlay_Move_Pixel(layer, 2, 7, layer, 3, 7);
620
                    Cube_Overlay_Move_Pixel(layer, 1, 7, layer, 2, 7);
621
                    Cube_Overlay_Move_Pixel(layer, 0, 7, layer, 1, 7);
622
                    Cube_Overlay_Move_Pixel(layer, 0, 6, layer, 0, 7);
623
                    Cube_Overlay_Move_Pixel(layer, 0, 5, layer, 0, 6);
624
                    Cube_Overlay_Move_Pixel(layer, 0, 4, layer, 0, 5);
625
                    Cube_Overlay_Move_Pixel(layer, 0, 3, layer, 0, 4);
626
                    Cube_Overlay_Move_Pixel(layer, 0, 2, layer, 0, 3);
627
                    Cube_Overlay_Move_Pixel(layer, 0, 1, layer, 0, 2);
628
                    Cube_Overlay_Set_Pixel(layer, 0, 1, origin_R, origin_G, origin_B);
629
                    break;
630
                case 1:
631
                    // Rotate second to outermost layer
632
                    Cube_Overlay_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
633
                    Cube_Overlay_Move_Pixel(layer, 2, 1, layer, 1, 1);
634
                    Cube_Overlay_Move_Pixel(layer, 3, 1, layer, 2, 1);
635
                    Cube_Overlay_Move_Pixel(layer, 4, 1, layer, 3, 1);
636
                    Cube_Overlay_Move_Pixel(layer, 5, 1, layer, 4, 1);
637
                    Cube_Overlay_Move_Pixel(layer, 6, 1, layer, 5, 1);
638
                    Cube_Overlay_Move_Pixel(layer, 6, 2, layer, 6, 1);
639
                    Cube_Overlay_Move_Pixel(layer, 6, 3, layer, 6, 2);
640
                    Cube_Overlay_Move_Pixel(layer, 6, 4, layer, 6, 3);
641
                    Cube_Overlay_Move_Pixel(layer, 6, 5, layer, 6, 4);
642
                    Cube_Overlay_Move_Pixel(layer, 6, 6, layer, 6, 5);
643
                    Cube_Overlay_Move_Pixel(layer, 5, 6, layer, 6, 6);
644
                    Cube_Overlay_Move_Pixel(layer, 4, 6, layer, 5, 6);
645
                    Cube_Overlay_Move_Pixel(layer, 3, 6, layer, 4, 6);
646
                    Cube_Overlay_Move_Pixel(layer, 2, 6, layer, 3, 6);
647
                    Cube_Overlay_Move_Pixel(layer, 1, 6, layer, 2, 6);
648
                    Cube_Overlay_Move_Pixel(layer, 1, 5, layer, 1, 6);
649
                    Cube_Overlay_Move_Pixel(layer, 1, 4, layer, 1, 5);
650
                    Cube_Overlay_Move_Pixel(layer, 1, 3, layer, 1, 4);
651
                    Cube_Overlay_Move_Pixel(layer, 1, 2, layer, 1, 3);
652
                    Cube_Overlay_Set_Pixel(layer, 1, 2, origin_R, origin_G, origin_B);
653
                    break;
654
                case 2:
655
                    // Rotate second to innermost layer
656
                    Cube_Overlay_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
657
                    Cube_Overlay_Move_Pixel(layer, 3, 2, layer, 2, 2);
658
                    Cube_Overlay_Move_Pixel(layer, 4, 2, layer, 3, 2);
659
                    Cube_Overlay_Move_Pixel(layer, 5, 2, layer, 4, 2);
660
                    Cube_Overlay_Move_Pixel(layer, 5, 3, layer, 5, 2);
661
                    Cube_Overlay_Move_Pixel(layer, 5, 4, layer, 5, 3);
662
                    Cube_Overlay_Move_Pixel(layer, 5, 5, layer, 5, 4);
663
                    Cube_Overlay_Move_Pixel(layer, 4, 5, layer, 5, 5);
664
                    Cube_Overlay_Move_Pixel(layer, 3, 5, layer, 4, 5);
665
                    Cube_Overlay_Move_Pixel(layer, 2, 5, layer, 3, 5);
666
                    Cube_Overlay_Move_Pixel(layer, 2, 4, layer, 2, 5);
667
                    Cube_Overlay_Move_Pixel(layer, 2, 3, layer, 2, 4);
668
                    Cube_Overlay_Set_Pixel(layer, 2, 3, origin_R, origin_G, origin_B);
669
                    break;
670
                case 3:
671
                    // Rotate innermost layer
672
                    Cube_Overlay_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
673
                    Cube_Overlay_Move_Pixel(layer, 4, 3, layer, 3, 3);
674
                    Cube_Overlay_Move_Pixel(layer, 4, 4, layer, 4, 3);
675
                    Cube_Overlay_Move_Pixel(layer, 3, 4, layer, 4, 4);
676
                    Cube_Overlay_Set_Pixel(layer, 3, 4, origin_R, origin_G, origin_B);
677
                    break;
678
            }
679
        }
680
    }
681
}
682
 
212 Kevin 683
////////////////////////////
684
// Text control functions //
685
////////////////////////////
206 Kevin 686
 
231 Kevin 687
void Cube_Text_Init(uint8_t *string, uint8_t length, uint16_t R, uint16_t G, uint16_t B) {
206 Kevin 688
    // Ensure that the length of the string does not exceed the storage buffer
689
    if (length > CUBE_STRING_MAX_LENGTH) length = CUBE_STRING_MAX_LENGTH;
690
 
215 Kevin 691
    Cube_Overlay_Clear();
692
 
206 Kevin 693
    // Copy the passed data into the buffer
231 Kevin 694
    uint8_t i;
206 Kevin 695
    for (i = 0; i < length; i++)
696
        cube_data_ptr->string[i] = string[i];
697
    cube_data_ptr->string_length = length;
698
    cube_data_ptr->string_index = 0;
699
    cube_data_ptr->string_line = 0;
700
    cube_data_ptr->string_R = R;
701
    cube_data_ptr->string_G = G;
702
    cube_data_ptr->string_B = B;
703
}
704
 
705
void Cube_Text_Interrupt(void) {
231 Kevin 706
    uint8_t layer;
707
    uint16_t line;
206 Kevin 708
 
709
    // Rotate before drawing the new line at (0,0)
710
    Cube_Overlay_Rotate_Shell(0, 0);
711
 
231 Kevin 712
    // Get the next vertical line of the int8_tacter currently being drawn
206 Kevin 713
    if (cube_data_ptr->string_line == 5) {
231 Kevin 714
        line = 0x0; // Leave a space between int8_tacters
206 Kevin 715
    } else {
716
        line = font[(cube_data_ptr->string[cube_data_ptr->string_index] * 5)
717
                + cube_data_ptr->string_line];
718
    }
719
 
720
    // Draw the line onto (0,0) using the specified color
231 Kevin 721
    for (layer = 8; layer != 0; layer--) {
206 Kevin 722
        if (line & 0x1) {
231 Kevin 723
            Cube_Overlay_Set_Pixel(layer-1, 0, 0, cube_data_ptr->string_R,
206 Kevin 724
                    cube_data_ptr->string_G, cube_data_ptr->string_B);
725
        } else {
231 Kevin 726
            Cube_Overlay_Set_Pixel(layer-1, 0, 0, 0x00, 0x00, 0x00);
206 Kevin 727
        }
728
        line >>= 1;
729
    }
730
 
231 Kevin 731
    // Increment the vertical line and the int8_tacter as needed
206 Kevin 732
    if (cube_data_ptr->string_line == 5) {
733
        cube_data_ptr->string_line = 0;
734
        if (cube_data_ptr->string_index == cube_data_ptr->string_length-1) {
735
            cube_data_ptr->string_index = 0;
736
        } else {
737
            cube_data_ptr->string_index += 1;
738
        }
739
    } else {
740
        cube_data_ptr->string_line += 1;
741
    }
212 Kevin 742
}
743
 
744
/////////////////////////////////////////////
745
// Functions for processing streaming data //
746
/////////////////////////////////////////////
747
 
231 Kevin 748
void Cube_Data_In(uint8_t c) {
749
    // Reset upon receiving the start int8_t
212 Kevin 750
    if (c == CUBE_START_CHAR) {
751
        cube_data_ptr->frame_length = 0;
752
        cube_data_ptr->frame_index = 0;
753
        cube_data_ptr->frame_checksum = 0;
754
        cube_data_ptr->frame_command = 0;
215 Kevin 755
        cube_data_ptr->frame_escape = 0;
212 Kevin 756
        cube_data_ptr->frame_state = READ_LENGTH_MSB;
215 Kevin 757
        return;
758
    }
231 Kevin 759
    // If the input is the escape int8_t, XOR the next int8_t received
215 Kevin 760
    if (c == CUBE_ESCAPE_CHAR) {
761
        cube_data_ptr->frame_escape = 1;
762
        return;
763
    }
231 Kevin 764
    // XOR the input int8_t if needed
215 Kevin 765
    if (cube_data_ptr->frame_escape) {
766
        c ^= CUBE_ESCAPE_XOR;
767
        cube_data_ptr->frame_escape = 0;
768
    }
769
    // Process data
770
    switch (cube_data_ptr->frame_state) {
771
        case IDLE:
231 Kevin 772
            // Reflect the int8_tacter back to the transmitter
215 Kevin 773
            UART1_Write(&c, 1);
774
            break;
775
        case READ_LENGTH_MSB: // Save MSB of length
776
            cube_data_ptr->frame_length |= (c << 8);
777
            cube_data_ptr->frame_state = READ_LENGTH_LSB;
778
            break;
779
        case READ_LENGTH_LSB: // Save LSB of length
780
            cube_data_ptr->frame_length |= c;
781
            cube_data_ptr->frame_state = READ_COMMAND;
782
            break;
783
        case READ_COMMAND: // Store the command byte
784
            cube_data_ptr->frame_checksum += c;
785
            cube_data_ptr->frame_command = c;
786
            if (cube_data_ptr->frame_length == 1)
787
                cube_data_ptr->frame_state = READ_CHECKSUM;
788
            else
212 Kevin 789
                cube_data_ptr->frame_state = READ_DATA;
215 Kevin 790
            break;
791
        case READ_DATA: // Read the passed data into the buffer
792
            cube_data_ptr->frame_checksum += c;
793
            cube_data_ptr->frame_buffer[cube_data_ptr->frame_index] = c;
794
            cube_data_ptr->frame_index++;
795
            if (cube_data_ptr->frame_index == cube_data_ptr->frame_length - 1)
796
                cube_data_ptr->frame_state = READ_CHECKSUM;
797
            break;
798
        case READ_CHECKSUM: // Process frame if checksum is valid
799
            cube_data_ptr->frame_checksum = 0xFF - cube_data_ptr->frame_checksum;
800
            if (cube_data_ptr->frame_checksum == c) {
801
                Cube_Data_In_Process_Frame();
802
            }
803
            cube_data_ptr->frame_state = IDLE;
804
            cube_data_ptr->frame_index = 0;
805
            cube_data_ptr->frame_length = 0;
806
            break;
807
        default:
808
            break;
212 Kevin 809
    }
810
}
811
 
812
void Cube_Data_In_Process_Frame(void) {
215 Kevin 813
    // Here we process received frames depending on the command
231 Kevin 814
    uint8_t *frame = cube_data_ptr->frame_buffer;
212 Kevin 815
    switch (cube_data_ptr->frame_command) {
215 Kevin 816
        case CUBE_COMMAND_SET_BC:
817
            TIMER5_Stop();
818
            Delay_MS(1); // Need to wait for all SPI writes to complete
819
            Cube_Write_DCS(frame[0]);
820
            TIMER5_Start();
821
            break;
822
        case CUBE_COMMAND_CLEAR:
823
            Cube_Clear();
824
            break;
212 Kevin 825
        case CUBE_COMMAND_SET_PIXEL:
826
            Cube_Set_Pixel(frame[0], frame[1], frame[2], frame[3], frame[4], frame[5]);
827
            break;
216 Kevin 828
        case CUBE_COMMAND_SET_ALL:
829
            Cube_Data_Direct_Write_All(&frame[0]);
215 Kevin 830
            break;
831
        case CUBE_COMMAND_START_TEXT:
832
            Cube_Text_Init(&frame[3], cube_data_ptr->frame_length - 4, frame[0], frame[1], frame[2]);
833
            TIMER4_Start();
834
            break;
835
        case CUBE_COMMAND_STOP_TEXT:
836
            TIMER4_Stop();
837
            Cube_Overlay_Clear();
838
            break;
212 Kevin 839
        default:
840
            break;
841
    }
215 Kevin 842
}
843
 
231 Kevin 844
void Cube_Data_Direct_Write_All(uint8_t *buffer) {
216 Kevin 845
    memcpy(cube_data_ptr->GCS, buffer, CUBE_LAYER_COUNT * GCS_LAYER_SIZE);
199 Kevin 846
}