Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

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