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