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