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"
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
 
200 Kevin 17
void Cube_Init(CUBE_DATA *data, char 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;
199 Kevin 21
 
22
    SFT_D = 0;
23
    SFT_S = 0;
24
    SFT_K = 0;
25
    SFT_R = 0;
26
    GSLAT = 0;
27
    XBLNK = 0;
28
 
29
    SFT_D_TRIS = 0;
30
    SFT_S_TRIS = 0;
31
    SFT_K_TRIS = 0;
32
    SFT_R_TRIS = 0;
33
    GSLAT_TRIS = 0;
34
    XBLNK_TRIS = 0;
35
 
36
    // Clear the shift register
37
    Cube_Delay();
38
    SFT_K = 1;
39
    Cube_Delay();
40
    SFT_K = 0;
41
    Cube_Delay();
42
    SFT_S = 1;
43
    Cube_Delay();
44
    SFT_S = 0;
45
    Cube_Delay();
46
    SFT_R = 1;
47
 
200 Kevin 48
    Cube_Write_DCS(BC);
199 Kevin 49
    Cube_Clear();
206 Kevin 50
    Cube_Overlay_Clear();
199 Kevin 51
}
52
 
53
void Cube_Timer_Interrupt(void) {
206 Kevin 54
    // OR values in the overlay array with the display array
55
    int i,j;
56
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
57
        for (j = 0; j < GCS_LAYER_SIZE; j++) {
58
            cube_data_ptr->GCS_WRITE[i][j] = cube_data_ptr->GCS[i][j] | cube_data_ptr->GCS_OVERLAY[i][j];
59
        }
60
    }
199 Kevin 61
    // Write to the GCS register
206 Kevin 62
    SPI1_Write(cube_data_ptr->GCS_WRITE[cube_data_ptr->current_layer], GCS_LAYER_SIZE, &Cube_GCS_Write_Callback);
199 Kevin 63
}
64
 
65
void Cube_DCS_Write_Callback(void) {
66
    // GSLAT must be >7ms after DCS write
67
    Delay_MS(7);
68
    GSLAT = 0;
69
    Cube_Delay();
70
    GSLAT = 1;
71
    Cube_Delay();
72
    GSLAT = 0;
73
}
74
 
75
void Cube_GCS_Write_Callback(void) {
76
    // Disable LED output and latch in written data to GCS
77
    XBLNK = 0;
78
    Cube_Delay();
79
    GSLAT = 1;
80
    // Set the shift register to turn on the current layer
81
    int i;
82
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
83
        Cube_Delay();
201 Kevin 84
        SFT_D = (i == CUBE_LAYER_COUNT - cube_data_ptr->current_layer - 1) ? 1 : 0;
199 Kevin 85
        Cube_Delay();
86
        SFT_K = 1;
87
        Cube_Delay();
88
        SFT_K = 0;
89
    }
90
    Cube_Delay();
91
    SFT_S = 1;
92
    Cube_Delay();
93
    SFT_S = 0;
94
    Cube_Delay();
95
    // Enable LED output
96
    XBLNK = 1;
97
    Cube_Delay();
98
    GSLAT = 0;
99
 
201 Kevin 100
    cube_data_ptr->current_layer = (cube_data_ptr->current_layer == CUBE_LAYER_COUNT-1)
101
            ? 0 : cube_data_ptr->current_layer + 1;
199 Kevin 102
}
103
 
200 Kevin 104
void Cube_Write_DCS(char BC) {
105
    XBLNK = 0;
106
    int i,j;
107
    // Write configuration data to the DC/BC/FC/UD registers
108
    unsigned char DCS[GCS_LAYER_SIZE] = {0};
109
    for (i = 0; i < 8; i++) {
110
        int offset = i * GCS_REG_SIZE;
111
 
112
        for (j = 0; j < 21; j++) {
113
            DCS[offset + j] = 0xFF; // Dot correction
114
        }
115
 
116
        // Warning: do not set BC > 0x6F
117
        DCS[offset + 21] = BC; // Global red brightness
118
        DCS[offset + 22] = BC; // Global green brightness
119
        DCS[offset + 23] = BC; // Global blue brightness
120
 
121
        // DC low range, auto repeat, no timing reset, 8 bit counter mode
122
        DCS[offset + 24] = 0x68; // 0110 1000
123
    }
124
 
125
    GSLAT = 1;
126
    SPI1_Write(DCS, GCS_LAYER_SIZE, &Cube_DCS_Write_Callback);
201 Kevin 127
    Delay_MS(10); // Delay until the entire DCS write is finished
200 Kevin 128
}
129
 
199 Kevin 130
void Cube_Clear(void) {
131
    int i,j;
132
    for (i = 0; i < CUBE_LAYER_COUNT; i++)
133
        for (j = 0; j < GCS_LAYER_SIZE; j++)
134
            cube_data_ptr->GCS[i][j] = 0x00;
135
}
136
 
137
void Cube_Set_All(int R, int G, int B) {
201 Kevin 138
    // Set all pixels in the cube to the given color
199 Kevin 139
    R &= 0x0FFF;
140
    G &= 0x0FFF;
141
    B &= 0x0FFF;
142
    int i,j,k;
143
    for (i = 0; i < CUBE_LAYER_COUNT; i++) {
144
        for (j = 0; j < CUBE_ROW_COUNT; j++) {
145
            int j_var = j * GCS_REG_SIZE;
146
            for (k = 0; k < 4; k++) {
147
                int k_var = j_var + (k * 9);
148
                cube_data_ptr->GCS[i][k_var+0] = R & 0xFF;;
149
                cube_data_ptr->GCS[i][k_var+1] = (G << 4) | (R >> 8);
150
                cube_data_ptr->GCS[i][k_var+2] = G >> 4;
151
                cube_data_ptr->GCS[i][k_var+3] = B & 0xFF;
152
                cube_data_ptr->GCS[i][k_var+4] = (R << 4) | (B >> 8);
153
                cube_data_ptr->GCS[i][k_var+5] = R >> 4;
154
                cube_data_ptr->GCS[i][k_var+6] = G & 0xFF;
155
                cube_data_ptr->GCS[i][k_var+7] = (B << 4) | (G >> 8);
156
                cube_data_ptr->GCS[i][k_var+8] = B >> 4;
157
            }
158
        }
159
    }
160
}
161
 
162
void Cube_Set_Layer(int layer, int R, int G, int B) {
201 Kevin 163
    // Set all pixels in the specified layer to the given color
199 Kevin 164
    R &= 0x0FFF;
165
    G &= 0x0FFF;
166
    B &= 0x0FFF;
167
    int i,j;
168
    for (i = 0; i < CUBE_ROW_COUNT; i++) {
169
        int i_var = i * GCS_REG_SIZE;
170
        for (j = 0; j < 4; j++) {
171
            int j_var = i_var + (j * 9);
172
            cube_data_ptr->GCS[layer][j_var+0] = R & 0xFF;;
173
            cube_data_ptr->GCS[layer][j_var+1] = (G << 4) | (R >> 8);
174
            cube_data_ptr->GCS[layer][j_var+2] = G >> 4;
175
            cube_data_ptr->GCS[layer][j_var+3] = B & 0xFF;
176
            cube_data_ptr->GCS[layer][j_var+4] = (R << 4) | (B >> 8);
177
            cube_data_ptr->GCS[layer][j_var+5] = R >> 4;
178
            cube_data_ptr->GCS[layer][j_var+6] = G & 0xFF;
179
            cube_data_ptr->GCS[layer][j_var+7] = (B << 4) | (G >> 8);
180
            cube_data_ptr->GCS[layer][j_var+8] = B >> 4;
181
        }
182
    }
183
}
184
 
185
void Cube_Set_Pixel(int layer, int row, int column, int R, int G, int B) {
201 Kevin 186
    // Set the specified pixel to the given color
199 Kevin 187
    R &= 0x0FFF;
188
    G &= 0x0FFF;
189
    B &= 0x0FFF;
190
    int var = row * GCS_REG_SIZE + (column / 2 * 9);
191
    switch (column % 2) {
192
        case 0:
193
            cube_data_ptr->GCS[layer][var+0] = R & 0xFF;
194
            cube_data_ptr->GCS[layer][var+1] = (G << 4) | (R >> 8);
195
            cube_data_ptr->GCS[layer][var+2] = G >> 4;
196
            cube_data_ptr->GCS[layer][var+3] = B & 0xFF;
197
            cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0xF0) | (B >> 8);
198
            break;
199
        case 1:
200
            cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0x0F) | (R << 4);
201
            cube_data_ptr->GCS[layer][var+5] = R >> 4;
202
            cube_data_ptr->GCS[layer][var+6] = G & 0xFF;
203
            cube_data_ptr->GCS[layer][var+7] = (B << 4) | (G >> 8);
204
            cube_data_ptr->GCS[layer][var+8] = B >> 4;
205
            break;
206
    }
205 Kevin 207
}
208
 
209
void Cube_Get_Pixel(int layer, int row, int column, int* R, int* G, int* B) {
210
    int var = row * GCS_REG_SIZE + (column / 2 * 9);
211
    switch (column % 2) {
212
        // Concatenate lower byte and upper byte of each color channel
213
        case 0:
214
            *R = cube_data_ptr->GCS[layer][var+0] | ((cube_data_ptr->GCS[layer][var+1] & 0x0F) << 8);
215
            *G = (cube_data_ptr->GCS[layer][var+1] >> 4) | (cube_data_ptr->GCS[layer][var+2] << 4);
216
            *B = cube_data_ptr->GCS[layer][var+3] | ((cube_data_ptr->GCS[layer][var+4] & 0x0F) << 8);
217
            break;
218
        case 1:
219
            *R = (cube_data_ptr->GCS[layer][var+4] >> 4) | (cube_data_ptr->GCS[layer][var+5] << 4);
220
            *G = cube_data_ptr->GCS[layer][var+6] | ((cube_data_ptr->GCS[layer][var+7] & 0x0F) << 8);
221
            *B = (cube_data_ptr->GCS[layer][var+7] >> 4) | (cube_data_ptr->GCS[layer][var+8] << 4);
222
            break;
223
    }
224
}
225
 
226
void Cube_Move_Pixel(int layer1, int row1, int column1, int layer2, int row2, int column2) {
206 Kevin 227
    // Copies data from pixel 1 to pixel 2
205 Kevin 228
    // Note: destination pixel value is overwritten
229
    int prev_R, prev_G, prev_B;
230
    Cube_Get_Pixel(layer1, row1, column1, &prev_R, &prev_G, &prev_B);
231
    Cube_Set_Pixel(layer2, row2, column2, prev_R, prev_G, prev_B);
232
}
233
 
206 Kevin 234
void Cube_Rotate_Shell(char shell, char direction) {
205 Kevin 235
    // Shell is the layer to rotate, with the outermost being 0
236
    int layer, origin_R, origin_G, origin_B;;
237
    for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {
206 Kevin 238
        if (direction) {
239
            switch(shell) {
240
                case 0:
241
                    // Rotate outermost layer
242
                    Cube_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
243
                    Cube_Move_Pixel(layer, 0, 1, layer, 0, 0);
244
                    Cube_Move_Pixel(layer, 0, 2, layer, 0, 1);
245
                    Cube_Move_Pixel(layer, 0, 3, layer, 0, 2);
246
                    Cube_Move_Pixel(layer, 0, 4, layer, 0, 3);
247
                    Cube_Move_Pixel(layer, 0, 5, layer, 0, 4);
248
                    Cube_Move_Pixel(layer, 0, 6, layer, 0, 5);
249
                    Cube_Move_Pixel(layer, 0, 7, layer, 0, 6);
250
                    Cube_Move_Pixel(layer, 1, 7, layer, 0, 7);
251
                    Cube_Move_Pixel(layer, 2, 7, layer, 1, 7);
252
                    Cube_Move_Pixel(layer, 3, 7, layer, 2, 7);
253
                    Cube_Move_Pixel(layer, 4, 7, layer, 3, 7);
254
                    Cube_Move_Pixel(layer, 5, 7, layer, 4, 7);
255
                    Cube_Move_Pixel(layer, 6, 7, layer, 5, 7);
256
                    Cube_Move_Pixel(layer, 7, 7, layer, 6, 7);
257
                    Cube_Move_Pixel(layer, 7, 6, layer, 7, 7);
258
                    Cube_Move_Pixel(layer, 7, 5, layer, 7, 6);
259
                    Cube_Move_Pixel(layer, 7, 4, layer, 7, 5);
260
                    Cube_Move_Pixel(layer, 7, 3, layer, 7, 4);
261
                    Cube_Move_Pixel(layer, 7, 2, layer, 7, 3);
262
                    Cube_Move_Pixel(layer, 7, 1, layer, 7, 2);
263
                    Cube_Move_Pixel(layer, 7, 0, layer, 7, 1);
264
                    Cube_Move_Pixel(layer, 6, 0, layer, 7, 0);
265
                    Cube_Move_Pixel(layer, 5, 0, layer, 6, 0);
266
                    Cube_Move_Pixel(layer, 4, 0, layer, 5, 0);
267
                    Cube_Move_Pixel(layer, 3, 0, layer, 4, 0);
268
                    Cube_Move_Pixel(layer, 2, 0, layer, 3, 0);
269
                    Cube_Move_Pixel(layer, 1, 0, layer, 2, 0);
270
                    Cube_Set_Pixel(layer, 1, 0, origin_R, origin_G, origin_B);
271
                    break;
272
                case 1:
273
                    // Rotate second to outermost layer
274
                    Cube_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
275
                    Cube_Move_Pixel(layer, 1, 2, layer, 1, 1);
276
                    Cube_Move_Pixel(layer, 1, 3, layer, 1, 2);
277
                    Cube_Move_Pixel(layer, 1, 4, layer, 1, 3);
278
                    Cube_Move_Pixel(layer, 1, 5, layer, 1, 4);
279
                    Cube_Move_Pixel(layer, 1, 6, layer, 1, 5);
280
                    Cube_Move_Pixel(layer, 2, 6, layer, 1, 6);
281
                    Cube_Move_Pixel(layer, 3, 6, layer, 2, 6);
282
                    Cube_Move_Pixel(layer, 4, 6, layer, 3, 6);
283
                    Cube_Move_Pixel(layer, 5, 6, layer, 4, 6);
284
                    Cube_Move_Pixel(layer, 6, 6, layer, 5, 6);
285
                    Cube_Move_Pixel(layer, 6, 5, layer, 6, 6);
286
                    Cube_Move_Pixel(layer, 6, 4, layer, 6, 5);
287
                    Cube_Move_Pixel(layer, 6, 3, layer, 6, 4);
288
                    Cube_Move_Pixel(layer, 6, 2, layer, 6, 3);
289
                    Cube_Move_Pixel(layer, 6, 1, layer, 6, 2);
290
                    Cube_Move_Pixel(layer, 5, 1, layer, 6, 1);
291
                    Cube_Move_Pixel(layer, 4, 1, layer, 5, 1);
292
                    Cube_Move_Pixel(layer, 3, 1, layer, 4, 1);
293
                    Cube_Move_Pixel(layer, 2, 1, layer, 3, 1);
294
                    Cube_Set_Pixel(layer, 2, 1, origin_R, origin_G, origin_B);
295
                    break;
296
                case 2:
297
                    // Rotate second to innermost layer
298
                    Cube_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
299
                    Cube_Move_Pixel(layer, 2, 3, layer, 2, 2);
300
                    Cube_Move_Pixel(layer, 2, 4, layer, 2, 3);
301
                    Cube_Move_Pixel(layer, 2, 5, layer, 2, 4);
302
                    Cube_Move_Pixel(layer, 3, 5, layer, 2, 5);
303
                    Cube_Move_Pixel(layer, 4, 5, layer, 3, 5);
304
                    Cube_Move_Pixel(layer, 5, 5, layer, 4, 5);
305
                    Cube_Move_Pixel(layer, 5, 4, layer, 5, 5);
306
                    Cube_Move_Pixel(layer, 5, 3, layer, 5, 4);
307
                    Cube_Move_Pixel(layer, 5, 2, layer, 5, 3);
308
                    Cube_Move_Pixel(layer, 4, 2, layer, 5, 2);
309
                    Cube_Move_Pixel(layer, 3, 2, layer, 4, 2);
310
                    Cube_Set_Pixel(layer, 3, 2, origin_R, origin_G, origin_B);
311
                    break;
312
                case 3:
313
                    // Rotate innermost layer
314
                    Cube_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
315
                    Cube_Move_Pixel(layer, 3, 4, layer, 3, 3);
316
                    Cube_Move_Pixel(layer, 4, 4, layer, 3, 4);
317
                    Cube_Move_Pixel(layer, 4, 3, layer, 4, 4);
318
                    Cube_Set_Pixel(layer, 4, 3, origin_R, origin_G, origin_B);
319
                    break;
320
            }
321
        } else {
322
            switch(shell) {
323
                case 0:
324
                    // Rotate outermost layer
325
                    Cube_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
326
                    Cube_Move_Pixel(layer, 1, 0, layer, 0, 0);
327
                    Cube_Move_Pixel(layer, 2, 0, layer, 1, 0);
328
                    Cube_Move_Pixel(layer, 3, 0, layer, 2, 0);
329
                    Cube_Move_Pixel(layer, 4, 0, layer, 3, 0);
330
                    Cube_Move_Pixel(layer, 5, 0, layer, 4, 0);
331
                    Cube_Move_Pixel(layer, 6, 0, layer, 5, 0);
332
                    Cube_Move_Pixel(layer, 7, 0, layer, 6, 0);
333
                    Cube_Move_Pixel(layer, 7, 1, layer, 7, 0);
334
                    Cube_Move_Pixel(layer, 7, 2, layer, 7, 1);
335
                    Cube_Move_Pixel(layer, 7, 3, layer, 7, 2);
336
                    Cube_Move_Pixel(layer, 7, 4, layer, 7, 3);
337
                    Cube_Move_Pixel(layer, 7, 5, layer, 7, 4);
338
                    Cube_Move_Pixel(layer, 7, 6, layer, 7, 5);
339
                    Cube_Move_Pixel(layer, 7, 7, layer, 7, 6);
340
                    Cube_Move_Pixel(layer, 6, 7, layer, 7, 7);
341
                    Cube_Move_Pixel(layer, 5, 7, layer, 6, 7);
342
                    Cube_Move_Pixel(layer, 4, 7, layer, 5, 7);
343
                    Cube_Move_Pixel(layer, 3, 7, layer, 4, 7);
344
                    Cube_Move_Pixel(layer, 2, 7, layer, 3, 7);
345
                    Cube_Move_Pixel(layer, 1, 7, layer, 2, 7);
346
                    Cube_Move_Pixel(layer, 0, 7, layer, 1, 7);
347
                    Cube_Move_Pixel(layer, 0, 6, layer, 0, 7);
348
                    Cube_Move_Pixel(layer, 0, 5, layer, 0, 6);
349
                    Cube_Move_Pixel(layer, 0, 4, layer, 0, 5);
350
                    Cube_Move_Pixel(layer, 0, 3, layer, 0, 4);
351
                    Cube_Move_Pixel(layer, 0, 2, layer, 0, 3);
352
                    Cube_Move_Pixel(layer, 0, 1, layer, 0, 2);
353
                    Cube_Set_Pixel(layer, 0, 1, origin_R, origin_G, origin_B);
354
                    break;
355
                case 1:
356
                    // Rotate second to outermost layer
357
                    Cube_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
358
                    Cube_Move_Pixel(layer, 2, 1, layer, 1, 1);
359
                    Cube_Move_Pixel(layer, 3, 1, layer, 2, 1);
360
                    Cube_Move_Pixel(layer, 4, 1, layer, 3, 1);
361
                    Cube_Move_Pixel(layer, 5, 1, layer, 4, 1);
362
                    Cube_Move_Pixel(layer, 6, 1, layer, 5, 1);
363
                    Cube_Move_Pixel(layer, 6, 2, layer, 6, 1);
364
                    Cube_Move_Pixel(layer, 6, 3, layer, 6, 2);
365
                    Cube_Move_Pixel(layer, 6, 4, layer, 6, 3);
366
                    Cube_Move_Pixel(layer, 6, 5, layer, 6, 4);
367
                    Cube_Move_Pixel(layer, 6, 6, layer, 6, 5);
368
                    Cube_Move_Pixel(layer, 5, 6, layer, 6, 6);
369
                    Cube_Move_Pixel(layer, 4, 6, layer, 5, 6);
370
                    Cube_Move_Pixel(layer, 3, 6, layer, 4, 6);
371
                    Cube_Move_Pixel(layer, 2, 6, layer, 3, 6);
372
                    Cube_Move_Pixel(layer, 1, 6, layer, 2, 6);
373
                    Cube_Move_Pixel(layer, 1, 5, layer, 1, 6);
374
                    Cube_Move_Pixel(layer, 1, 4, layer, 1, 5);
375
                    Cube_Move_Pixel(layer, 1, 3, layer, 1, 4);
376
                    Cube_Move_Pixel(layer, 1, 2, layer, 1, 3);
377
                    Cube_Set_Pixel(layer, 1, 2, origin_R, origin_G, origin_B);
378
                    break;
379
                case 2:
380
                    // Rotate second to innermost layer
381
                    Cube_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
382
                    Cube_Move_Pixel(layer, 3, 2, layer, 2, 2);
383
                    Cube_Move_Pixel(layer, 4, 2, layer, 3, 2);
384
                    Cube_Move_Pixel(layer, 5, 2, layer, 4, 2);
385
                    Cube_Move_Pixel(layer, 5, 3, layer, 5, 2);
386
                    Cube_Move_Pixel(layer, 5, 4, layer, 5, 3);
387
                    Cube_Move_Pixel(layer, 5, 5, layer, 5, 4);
388
                    Cube_Move_Pixel(layer, 4, 5, layer, 5, 5);
389
                    Cube_Move_Pixel(layer, 3, 5, layer, 4, 5);
390
                    Cube_Move_Pixel(layer, 2, 5, layer, 3, 5);
391
                    Cube_Move_Pixel(layer, 2, 4, layer, 2, 5);
392
                    Cube_Move_Pixel(layer, 2, 3, layer, 2, 4);
393
                    Cube_Set_Pixel(layer, 2, 3, origin_R, origin_G, origin_B);
394
                    break;
395
                case 3:
396
                    // Rotate innermost layer
397
                    Cube_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
398
                    Cube_Move_Pixel(layer, 4, 3, layer, 3, 3);
399
                    Cube_Move_Pixel(layer, 4, 4, layer, 4, 3);
400
                    Cube_Move_Pixel(layer, 3, 4, layer, 4, 4);
401
                    Cube_Set_Pixel(layer, 3, 4, origin_R, origin_G, origin_B);
402
                    break;
403
            }
205 Kevin 404
        }
405
    }
406
}
407
 
206 Kevin 408
void Cube_Rotate(char direction) {
205 Kevin 409
    // Rotate outermost layer
206 Kevin 410
    Cube_Rotate_Shell(0, direction);
205 Kevin 411
    // Rotate second to outermost layer
412
    if ((cube_data_ptr->rotation_counter != 1) && (cube_data_ptr->rotation_counter != 5)) {
206 Kevin 413
        Cube_Rotate_Shell(1, direction);
205 Kevin 414
    }
415
    // Rotate second to innermost layer
416
    if ((cube_data_ptr->rotation_counter != 0) && (cube_data_ptr->rotation_counter != 2) &&
417
        (cube_data_ptr->rotation_counter != 4) && (cube_data_ptr->rotation_counter != 6)) {
206 Kevin 418
        Cube_Rotate_Shell(2, direction);
205 Kevin 419
    }
420
    // Rotate innermost layer
421
    if ((cube_data_ptr->rotation_counter == 3) || (cube_data_ptr->rotation_counter == 7)) {
206 Kevin 422
        Cube_Rotate_Shell(3, direction);
205 Kevin 423
    }
424
 
425
    cube_data_ptr->rotation_counter = (cube_data_ptr->rotation_counter == CUBE_ROTATIONS-1)
426
            ? 0 : cube_data_ptr->rotation_counter + 1;
206 Kevin 427
}
428
 
429
 
430
void Cube_Overlay_Clear(void) {
431
    int i,j;
432
    for (i = 0; i < CUBE_LAYER_COUNT; i++)
433
        for (j = 0; j < GCS_LAYER_SIZE; j++)
434
            cube_data_ptr->GCS_OVERLAY[i][j] = 0x00;
435
}
436
 
437
void Cube_Overlay_Set_Pixel(int layer, int row, int column, int R, int G, int B) {
438
    // Set the specified pixel to the given color
439
    R &= 0x0FFF;
440
    G &= 0x0FFF;
441
    B &= 0x0FFF;
442
    int var = row * GCS_REG_SIZE + (column / 2 * 9);
443
    switch (column % 2) {
444
        case 0:
445
            cube_data_ptr->GCS_OVERLAY[layer][var+0] = R & 0xFF;
446
            cube_data_ptr->GCS_OVERLAY[layer][var+1] = (G << 4) | (R >> 8);
447
            cube_data_ptr->GCS_OVERLAY[layer][var+2] = G >> 4;
448
            cube_data_ptr->GCS_OVERLAY[layer][var+3] = B & 0xFF;
449
            cube_data_ptr->GCS_OVERLAY[layer][var+4] = (cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0xF0) | (B >> 8);
450
            break;
451
        case 1:
452
            cube_data_ptr->GCS_OVERLAY[layer][var+4] = (cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0x0F) | (R << 4);
453
            cube_data_ptr->GCS_OVERLAY[layer][var+5] = R >> 4;
454
            cube_data_ptr->GCS_OVERLAY[layer][var+6] = G & 0xFF;
455
            cube_data_ptr->GCS_OVERLAY[layer][var+7] = (B << 4) | (G >> 8);
456
            cube_data_ptr->GCS_OVERLAY[layer][var+8] = B >> 4;
457
            break;
458
    }
459
}
460
 
461
void Cube_Overlay_Get_Pixel(int layer, int row, int column, int* R, int* G, int* B) {
462
    int var = row * GCS_REG_SIZE + (column / 2 * 9);
463
    switch (column % 2) {
464
        // Concatenate lower byte and upper byte of each color channel
465
        case 0:
466
            *R = cube_data_ptr->GCS_OVERLAY[layer][var+0] | ((cube_data_ptr->GCS_OVERLAY[layer][var+1] & 0x0F) << 8);
467
            *G = (cube_data_ptr->GCS_OVERLAY[layer][var+1] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+2] << 4);
468
            *B = cube_data_ptr->GCS_OVERLAY[layer][var+3] | ((cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0x0F) << 8);
469
            break;
470
        case 1:
471
            *R = (cube_data_ptr->GCS_OVERLAY[layer][var+4] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+5] << 4);
472
            *G = cube_data_ptr->GCS_OVERLAY[layer][var+6] | ((cube_data_ptr->GCS_OVERLAY[layer][var+7] & 0x0F) << 8);
473
            *B = (cube_data_ptr->GCS_OVERLAY[layer][var+7] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+8] << 4);
474
            break;
475
    }
476
}
477
 
478
void Cube_Overlay_Move_Pixel(int layer1, int row1, int column1, int layer2, int row2, int column2) {
479
    // Copies data from pixel 1 to pixel 2
480
    // Note: destination pixel value is overwritten
481
    int prev_R, prev_G, prev_B;
482
    Cube_Overlay_Get_Pixel(layer1, row1, column1, &prev_R, &prev_G, &prev_B);
483
    Cube_Overlay_Set_Pixel(layer2, row2, column2, prev_R, prev_G, prev_B);
484
}
485
 
486
void Cube_Overlay_Rotate_Shell(char shell, char direction) {
487
    // Shell is the layer to rotate, with the outermost being 0
488
    int layer, origin_R, origin_G, origin_B;;
489
    for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {
490
        if (direction) {
491
            switch(shell) {
492
                case 0:
493
                    // Rotate outermost layer
494
                    Cube_Overlay_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
495
                    Cube_Overlay_Move_Pixel(layer, 0, 1, layer, 0, 0);
496
                    Cube_Overlay_Move_Pixel(layer, 0, 2, layer, 0, 1);
497
                    Cube_Overlay_Move_Pixel(layer, 0, 3, layer, 0, 2);
498
                    Cube_Overlay_Move_Pixel(layer, 0, 4, layer, 0, 3);
499
                    Cube_Overlay_Move_Pixel(layer, 0, 5, layer, 0, 4);
500
                    Cube_Overlay_Move_Pixel(layer, 0, 6, layer, 0, 5);
501
                    Cube_Overlay_Move_Pixel(layer, 0, 7, layer, 0, 6);
502
                    Cube_Overlay_Move_Pixel(layer, 1, 7, layer, 0, 7);
503
                    Cube_Overlay_Move_Pixel(layer, 2, 7, layer, 1, 7);
504
                    Cube_Overlay_Move_Pixel(layer, 3, 7, layer, 2, 7);
505
                    Cube_Overlay_Move_Pixel(layer, 4, 7, layer, 3, 7);
506
                    Cube_Overlay_Move_Pixel(layer, 5, 7, layer, 4, 7);
507
                    Cube_Overlay_Move_Pixel(layer, 6, 7, layer, 5, 7);
508
                    Cube_Overlay_Move_Pixel(layer, 7, 7, layer, 6, 7);
509
                    Cube_Overlay_Move_Pixel(layer, 7, 6, layer, 7, 7);
510
                    Cube_Overlay_Move_Pixel(layer, 7, 5, layer, 7, 6);
511
                    Cube_Overlay_Move_Pixel(layer, 7, 4, layer, 7, 5);
512
                    Cube_Overlay_Move_Pixel(layer, 7, 3, layer, 7, 4);
513
                    Cube_Overlay_Move_Pixel(layer, 7, 2, layer, 7, 3);
514
                    Cube_Overlay_Move_Pixel(layer, 7, 1, layer, 7, 2);
515
                    Cube_Overlay_Move_Pixel(layer, 7, 0, layer, 7, 1);
516
                    Cube_Overlay_Move_Pixel(layer, 6, 0, layer, 7, 0);
517
                    Cube_Overlay_Move_Pixel(layer, 5, 0, layer, 6, 0);
518
                    Cube_Overlay_Move_Pixel(layer, 4, 0, layer, 5, 0);
519
                    Cube_Overlay_Move_Pixel(layer, 3, 0, layer, 4, 0);
520
                    Cube_Overlay_Move_Pixel(layer, 2, 0, layer, 3, 0);
521
                    Cube_Overlay_Move_Pixel(layer, 1, 0, layer, 2, 0);
522
                    Cube_Overlay_Set_Pixel(layer, 1, 0, origin_R, origin_G, origin_B);
523
                    break;
524
                case 1:
525
                    // Rotate second to outermost layer
526
                    Cube_Overlay_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
527
                    Cube_Overlay_Move_Pixel(layer, 1, 2, layer, 1, 1);
528
                    Cube_Overlay_Move_Pixel(layer, 1, 3, layer, 1, 2);
529
                    Cube_Overlay_Move_Pixel(layer, 1, 4, layer, 1, 3);
530
                    Cube_Overlay_Move_Pixel(layer, 1, 5, layer, 1, 4);
531
                    Cube_Overlay_Move_Pixel(layer, 1, 6, layer, 1, 5);
532
                    Cube_Overlay_Move_Pixel(layer, 2, 6, layer, 1, 6);
533
                    Cube_Overlay_Move_Pixel(layer, 3, 6, layer, 2, 6);
534
                    Cube_Overlay_Move_Pixel(layer, 4, 6, layer, 3, 6);
535
                    Cube_Overlay_Move_Pixel(layer, 5, 6, layer, 4, 6);
536
                    Cube_Overlay_Move_Pixel(layer, 6, 6, layer, 5, 6);
537
                    Cube_Overlay_Move_Pixel(layer, 6, 5, layer, 6, 6);
538
                    Cube_Overlay_Move_Pixel(layer, 6, 4, layer, 6, 5);
539
                    Cube_Overlay_Move_Pixel(layer, 6, 3, layer, 6, 4);
540
                    Cube_Overlay_Move_Pixel(layer, 6, 2, layer, 6, 3);
541
                    Cube_Overlay_Move_Pixel(layer, 6, 1, layer, 6, 2);
542
                    Cube_Overlay_Move_Pixel(layer, 5, 1, layer, 6, 1);
543
                    Cube_Overlay_Move_Pixel(layer, 4, 1, layer, 5, 1);
544
                    Cube_Overlay_Move_Pixel(layer, 3, 1, layer, 4, 1);
545
                    Cube_Overlay_Move_Pixel(layer, 2, 1, layer, 3, 1);
546
                    Cube_Overlay_Set_Pixel(layer, 2, 1, origin_R, origin_G, origin_B);
547
                    break;
548
                case 2:
549
                    // Rotate second to innermost layer
550
                    Cube_Overlay_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
551
                    Cube_Overlay_Move_Pixel(layer, 2, 3, layer, 2, 2);
552
                    Cube_Overlay_Move_Pixel(layer, 2, 4, layer, 2, 3);
553
                    Cube_Overlay_Move_Pixel(layer, 2, 5, layer, 2, 4);
554
                    Cube_Overlay_Move_Pixel(layer, 3, 5, layer, 2, 5);
555
                    Cube_Overlay_Move_Pixel(layer, 4, 5, layer, 3, 5);
556
                    Cube_Overlay_Move_Pixel(layer, 5, 5, layer, 4, 5);
557
                    Cube_Overlay_Move_Pixel(layer, 5, 4, layer, 5, 5);
558
                    Cube_Overlay_Move_Pixel(layer, 5, 3, layer, 5, 4);
559
                    Cube_Overlay_Move_Pixel(layer, 5, 2, layer, 5, 3);
560
                    Cube_Overlay_Move_Pixel(layer, 4, 2, layer, 5, 2);
561
                    Cube_Overlay_Move_Pixel(layer, 3, 2, layer, 4, 2);
562
                    Cube_Overlay_Set_Pixel(layer, 3, 2, origin_R, origin_G, origin_B);
563
                    break;
564
                case 3:
565
                    // Rotate innermost layer
566
                    Cube_Overlay_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
567
                    Cube_Overlay_Move_Pixel(layer, 3, 4, layer, 3, 3);
568
                    Cube_Overlay_Move_Pixel(layer, 4, 4, layer, 3, 4);
569
                    Cube_Overlay_Move_Pixel(layer, 4, 3, layer, 4, 4);
570
                    Cube_Overlay_Set_Pixel(layer, 4, 3, origin_R, origin_G, origin_B);
571
                    break;
572
            }
573
        } else {
574
            switch(shell) {
575
                case 0:
576
                    // Rotate outermost layer
577
                    Cube_Overlay_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);
578
                    Cube_Overlay_Move_Pixel(layer, 1, 0, layer, 0, 0);
579
                    Cube_Overlay_Move_Pixel(layer, 2, 0, layer, 1, 0);
580
                    Cube_Overlay_Move_Pixel(layer, 3, 0, layer, 2, 0);
581
                    Cube_Overlay_Move_Pixel(layer, 4, 0, layer, 3, 0);
582
                    Cube_Overlay_Move_Pixel(layer, 5, 0, layer, 4, 0);
583
                    Cube_Overlay_Move_Pixel(layer, 6, 0, layer, 5, 0);
584
                    Cube_Overlay_Move_Pixel(layer, 7, 0, layer, 6, 0);
585
                    Cube_Overlay_Move_Pixel(layer, 7, 1, layer, 7, 0);
586
                    Cube_Overlay_Move_Pixel(layer, 7, 2, layer, 7, 1);
587
                    Cube_Overlay_Move_Pixel(layer, 7, 3, layer, 7, 2);
588
                    Cube_Overlay_Move_Pixel(layer, 7, 4, layer, 7, 3);
589
                    Cube_Overlay_Move_Pixel(layer, 7, 5, layer, 7, 4);
590
                    Cube_Overlay_Move_Pixel(layer, 7, 6, layer, 7, 5);
591
                    Cube_Overlay_Move_Pixel(layer, 7, 7, layer, 7, 6);
592
                    Cube_Overlay_Move_Pixel(layer, 6, 7, layer, 7, 7);
593
                    Cube_Overlay_Move_Pixel(layer, 5, 7, layer, 6, 7);
594
                    Cube_Overlay_Move_Pixel(layer, 4, 7, layer, 5, 7);
595
                    Cube_Overlay_Move_Pixel(layer, 3, 7, layer, 4, 7);
596
                    Cube_Overlay_Move_Pixel(layer, 2, 7, layer, 3, 7);
597
                    Cube_Overlay_Move_Pixel(layer, 1, 7, layer, 2, 7);
598
                    Cube_Overlay_Move_Pixel(layer, 0, 7, layer, 1, 7);
599
                    Cube_Overlay_Move_Pixel(layer, 0, 6, layer, 0, 7);
600
                    Cube_Overlay_Move_Pixel(layer, 0, 5, layer, 0, 6);
601
                    Cube_Overlay_Move_Pixel(layer, 0, 4, layer, 0, 5);
602
                    Cube_Overlay_Move_Pixel(layer, 0, 3, layer, 0, 4);
603
                    Cube_Overlay_Move_Pixel(layer, 0, 2, layer, 0, 3);
604
                    Cube_Overlay_Move_Pixel(layer, 0, 1, layer, 0, 2);
605
                    Cube_Overlay_Set_Pixel(layer, 0, 1, origin_R, origin_G, origin_B);
606
                    break;
607
                case 1:
608
                    // Rotate second to outermost layer
609
                    Cube_Overlay_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);
610
                    Cube_Overlay_Move_Pixel(layer, 2, 1, layer, 1, 1);
611
                    Cube_Overlay_Move_Pixel(layer, 3, 1, layer, 2, 1);
612
                    Cube_Overlay_Move_Pixel(layer, 4, 1, layer, 3, 1);
613
                    Cube_Overlay_Move_Pixel(layer, 5, 1, layer, 4, 1);
614
                    Cube_Overlay_Move_Pixel(layer, 6, 1, layer, 5, 1);
615
                    Cube_Overlay_Move_Pixel(layer, 6, 2, layer, 6, 1);
616
                    Cube_Overlay_Move_Pixel(layer, 6, 3, layer, 6, 2);
617
                    Cube_Overlay_Move_Pixel(layer, 6, 4, layer, 6, 3);
618
                    Cube_Overlay_Move_Pixel(layer, 6, 5, layer, 6, 4);
619
                    Cube_Overlay_Move_Pixel(layer, 6, 6, layer, 6, 5);
620
                    Cube_Overlay_Move_Pixel(layer, 5, 6, layer, 6, 6);
621
                    Cube_Overlay_Move_Pixel(layer, 4, 6, layer, 5, 6);
622
                    Cube_Overlay_Move_Pixel(layer, 3, 6, layer, 4, 6);
623
                    Cube_Overlay_Move_Pixel(layer, 2, 6, layer, 3, 6);
624
                    Cube_Overlay_Move_Pixel(layer, 1, 6, layer, 2, 6);
625
                    Cube_Overlay_Move_Pixel(layer, 1, 5, layer, 1, 6);
626
                    Cube_Overlay_Move_Pixel(layer, 1, 4, layer, 1, 5);
627
                    Cube_Overlay_Move_Pixel(layer, 1, 3, layer, 1, 4);
628
                    Cube_Overlay_Move_Pixel(layer, 1, 2, layer, 1, 3);
629
                    Cube_Overlay_Set_Pixel(layer, 1, 2, origin_R, origin_G, origin_B);
630
                    break;
631
                case 2:
632
                    // Rotate second to innermost layer
633
                    Cube_Overlay_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);
634
                    Cube_Overlay_Move_Pixel(layer, 3, 2, layer, 2, 2);
635
                    Cube_Overlay_Move_Pixel(layer, 4, 2, layer, 3, 2);
636
                    Cube_Overlay_Move_Pixel(layer, 5, 2, layer, 4, 2);
637
                    Cube_Overlay_Move_Pixel(layer, 5, 3, layer, 5, 2);
638
                    Cube_Overlay_Move_Pixel(layer, 5, 4, layer, 5, 3);
639
                    Cube_Overlay_Move_Pixel(layer, 5, 5, layer, 5, 4);
640
                    Cube_Overlay_Move_Pixel(layer, 4, 5, layer, 5, 5);
641
                    Cube_Overlay_Move_Pixel(layer, 3, 5, layer, 4, 5);
642
                    Cube_Overlay_Move_Pixel(layer, 2, 5, layer, 3, 5);
643
                    Cube_Overlay_Move_Pixel(layer, 2, 4, layer, 2, 5);
644
                    Cube_Overlay_Move_Pixel(layer, 2, 3, layer, 2, 4);
645
                    Cube_Overlay_Set_Pixel(layer, 2, 3, origin_R, origin_G, origin_B);
646
                    break;
647
                case 3:
648
                    // Rotate innermost layer
649
                    Cube_Overlay_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);
650
                    Cube_Overlay_Move_Pixel(layer, 4, 3, layer, 3, 3);
651
                    Cube_Overlay_Move_Pixel(layer, 4, 4, layer, 4, 3);
652
                    Cube_Overlay_Move_Pixel(layer, 3, 4, layer, 4, 4);
653
                    Cube_Overlay_Set_Pixel(layer, 3, 4, origin_R, origin_G, origin_B);
654
                    break;
655
            }
656
        }
657
    }
658
}
659
 
660
 
661
void Cube_Text_Init(char *string, char length, int R, int G, int B) {
662
    // Ensure that the length of the string does not exceed the storage buffer
663
    if (length > CUBE_STRING_MAX_LENGTH) length = CUBE_STRING_MAX_LENGTH;
664
 
665
    // Copy the passed data into the buffer
666
    int i;
667
    for (i = 0; i < length; i++)
668
        cube_data_ptr->string[i] = string[i];
669
    cube_data_ptr->string_length = length;
670
    cube_data_ptr->string_index = 0;
671
    cube_data_ptr->string_line = 0;
672
    cube_data_ptr->string_R = R;
673
    cube_data_ptr->string_G = G;
674
    cube_data_ptr->string_B = B;
675
}
676
 
677
void Cube_Text_Interrupt(void) {
678
    int layer, line;
679
 
680
    // Rotate before drawing the new line at (0,0)
681
    Cube_Overlay_Rotate_Shell(0, 0);
682
 
683
    // Get the next vertical line of the character currently being drawn
684
    if (cube_data_ptr->string_line == 5) {
685
        line = 0x0; // Leave a space between characters
686
    } else {
687
        line = font[(cube_data_ptr->string[cube_data_ptr->string_index] * 5)
688
                + cube_data_ptr->string_line];
689
    }
690
 
691
    // Draw the line onto (0,0) using the specified color
692
    for (layer = 7; layer >= 0; layer--) {
693
        if (line & 0x1) {
694
            Cube_Overlay_Set_Pixel(layer, 0, 0, cube_data_ptr->string_R,
695
                    cube_data_ptr->string_G, cube_data_ptr->string_B);
696
        } else {
697
            Cube_Overlay_Set_Pixel(layer, 0, 0, 0x00, 0x00, 0x00);
698
        }
699
        line >>= 1;
700
    }
701
 
702
    // Increment the vertical line and the character as needed
703
    if (cube_data_ptr->string_line == 5) {
704
        cube_data_ptr->string_line = 0;
705
        if (cube_data_ptr->string_index == cube_data_ptr->string_length-1) {
706
            cube_data_ptr->string_index = 0;
707
        } else {
708
            cube_data_ptr->string_index += 1;
709
        }
710
    } else {
711
        cube_data_ptr->string_line += 1;
712
    }
199 Kevin 713
}