Rev 268 | Blame | Last modification | View Log | Download | RSS feed
#include "defines.h"#include "CUBE.h"#include "SPI1.h"#include "glcdfont.h"#include "UART1.h"#include "ETHERNET.h"#include "TIMER4.h"static CUBE_DATA *cube_data_ptr;inline void Cube_Delay() {// Small delay to ensure that latch speeds are < 30MhzNop();Nop();Nop();}void Cube_Init(CUBE_DATA *data, uint8_t BC) {cube_data_ptr = data;cube_data_ptr->current_layer = 0;cube_data_ptr->rotation_counter = 0;cube_data_ptr->frame_state = IDLE;cube_data_ptr->frame_escape = 0;DCSIN = 0;DCSCK = 0;SFT_R = 0;SFT_K = 0;SFT_S = 0;SFT_D = 0;GSLAT = 0;XBLNK = 0;DCSIN_TRIS = 0;DCSCK_TRIS = 0;SFT_R_TRIS = 0;SFT_K_TRIS = 0;SFT_S_TRIS = 0;SFT_D_TRIS = 0;GSLAT_TRIS = 0;XBLNK_TRIS = 0;// Clear the shift registerCube_Delay();SFT_K = 1;Cube_Delay();SFT_K = 0;Cube_Delay();SFT_S = 1;Cube_Delay();SFT_S = 0;Cube_Delay();SFT_R = 1;Cube_Write_DCS(BC);Cube_Clear();Cube_Overlay_Clear();}void Cube_Timer_Interrupt(void) {// OR values in the overlay array with the display arrayuint8_t i;uint16_t j;for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < GCS_LAYER_SIZE; j++) {cube_data_ptr->GCS_WRITE[i][j] = cube_data_ptr->GCS[i][j] | cube_data_ptr->GCS_OVERLAY[i][j];}}// Write to the GCS registerSPI1_Write(cube_data_ptr->GCS_WRITE[cube_data_ptr->current_layer], GCS_LAYER_SIZE, &Cube_GCS_Write_Callback);}////////////////////////// Callback functions //////////////////////////void Cube_DCS_Write_Callback(void) {// GSLAT must be >7ms after DCS writeDelay_MS(7);GSLAT = 0;Cube_Delay();GSLAT = 1;Cube_Delay();GSLAT = 0;}void Cube_GCS_Write_Callback(void) {// Disable LED output and latch in written data to GCSXBLNK = 0;Cube_Delay();GSLAT = 1;// Set the shift register to turn on the current layeruint8_t i;for (i = 0; i < CUBE_LAYER_COUNT; i++) {Cube_Delay();SFT_D = (i == CUBE_LAYER_COUNT - cube_data_ptr->current_layer - 1) ? 1 : 0;Cube_Delay();SFT_K = 1;Cube_Delay();SFT_K = 0;}Cube_Delay();SFT_S = 1;Cube_Delay();SFT_S = 0;Cube_Delay();// Enable LED outputXBLNK = 1;Cube_Delay();GSLAT = 0;cube_data_ptr->current_layer = (cube_data_ptr->current_layer == CUBE_LAYER_COUNT-1)? 0 : cube_data_ptr->current_layer + 1;}////////////////////////////// Cube control functions //////////////////////////////void Cube_Write_DCS(uint8_t BC) {XBLNK = 0;uint8_t i,j;// Write configuration data to the DC/BC/FC/UD registersuint8_t DCS[GCS_LAYER_SIZE] = {0};for (i = 0; i < 8; i++) {uint16_t offset = i * GCS_REG_SIZE;for (j = 0; j < 21; j++) {DCS[offset + j] = 0xFF; // Dot correction}// Warning: do not set BC > 0x6F ?? NEED TO VERIFY THIS !!DCS[offset + 21] = BC; // Global red brightnessDCS[offset + 22] = BC; // Global green brightnessDCS[offset + 23] = BC; // Global blue brightness// DC low range, auto repeat, no timing reset, 8 bit counter modeDCS[offset + 24] = 0x68; // 0110 1000}GSLAT = 1;SPI1_Write(DCS, GCS_LAYER_SIZE, &Cube_DCS_Write_Callback);Delay_MS(10); // Delay until the entire DCS write is finished}void Cube_Clear(void) {uint8_t i;uint16_t j;for (i = 0; i < CUBE_LAYER_COUNT; i++)for (j = 0; j < GCS_LAYER_SIZE; j++)cube_data_ptr->GCS[i][j] = 0x00;}void Cube_Set_All(uint16_t R, uint16_t G, uint16_t B) {// Set all pixels in the cube to the given colorR &= 0x0FFF;G &= 0x0FFF;B &= 0x0FFF;uint8_t i,j,k;for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < CUBE_ROW_COUNT; j++) {uint16_t j_var = j * GCS_REG_SIZE;for (k = 0; k < 4; k++) {uint16_t k_var = j_var + (k * 9);cube_data_ptr->GCS[i][k_var+0] = R & 0xFF;;cube_data_ptr->GCS[i][k_var+1] = (G << 4) | (R >> 8);cube_data_ptr->GCS[i][k_var+2] = G >> 4;cube_data_ptr->GCS[i][k_var+3] = B & 0xFF;cube_data_ptr->GCS[i][k_var+4] = (R << 4) | (B >> 8);cube_data_ptr->GCS[i][k_var+5] = R >> 4;cube_data_ptr->GCS[i][k_var+6] = G & 0xFF;cube_data_ptr->GCS[i][k_var+7] = (B << 4) | (G >> 8);cube_data_ptr->GCS[i][k_var+8] = B >> 4;}}}}void Cube_Set_Layer(uint8_t layer, uint16_t R, uint16_t G, uint16_t B) {// Set all pixels in the specified layer to the given colorR &= 0x0FFF;G &= 0x0FFF;B &= 0x0FFF;uint8_t i,j;for (i = 0; i < CUBE_ROW_COUNT; i++) {uint16_t i_var = i * GCS_REG_SIZE;for (j = 0; j < 4; j++) {uint16_t j_var = i_var + (j * 9);cube_data_ptr->GCS[layer][j_var+0] = R & 0xFF;;cube_data_ptr->GCS[layer][j_var+1] = (G << 4) | (R >> 8);cube_data_ptr->GCS[layer][j_var+2] = G >> 4;cube_data_ptr->GCS[layer][j_var+3] = B & 0xFF;cube_data_ptr->GCS[layer][j_var+4] = (R << 4) | (B >> 8);cube_data_ptr->GCS[layer][j_var+5] = R >> 4;cube_data_ptr->GCS[layer][j_var+6] = G & 0xFF;cube_data_ptr->GCS[layer][j_var+7] = (B << 4) | (G >> 8);cube_data_ptr->GCS[layer][j_var+8] = B >> 4;}}}void Cube_Set_Row(uint8_t row, uint16_t R, uint16_t G, uint16_t B) {// Set the specified row to the given colorR &= 0x0FFF;G &= 0x0FFF;B &= 0x0FFF;uint8_t column, layer;for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {for (column = 0; column < CUBE_COLUMN_COUNT; column++) {uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);switch (column % 2) {case 0:cube_data_ptr->GCS[layer][var+0] = R & 0xFF;cube_data_ptr->GCS[layer][var+1] = (G << 4) | (R >> 8);cube_data_ptr->GCS[layer][var+2] = G >> 4;cube_data_ptr->GCS[layer][var+3] = B & 0xFF;cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0xF0) | (B >> 8);break;case 1:cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0x0F) | (R << 4);cube_data_ptr->GCS[layer][var+5] = R >> 4;cube_data_ptr->GCS[layer][var+6] = G & 0xFF;cube_data_ptr->GCS[layer][var+7] = (B << 4) | (G >> 8);cube_data_ptr->GCS[layer][var+8] = B >> 4;break;}}}}void Cube_Set_Column(uint8_t column, uint16_t R, uint16_t G, uint16_t B) {// Set the specified row to the given colorR &= 0x0FFF;G &= 0x0FFF;B &= 0x0FFF;uint8_t row, layer;for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {for (row = 0; row < CUBE_COLUMN_COUNT; row++) {uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);switch (column % 2) {case 0:cube_data_ptr->GCS[layer][var+0] = R & 0xFF;cube_data_ptr->GCS[layer][var+1] = (G << 4) | (R >> 8);cube_data_ptr->GCS[layer][var+2] = G >> 4;cube_data_ptr->GCS[layer][var+3] = B & 0xFF;cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0xF0) | (B >> 8);break;case 1:cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0x0F) | (R << 4);cube_data_ptr->GCS[layer][var+5] = R >> 4;cube_data_ptr->GCS[layer][var+6] = G & 0xFF;cube_data_ptr->GCS[layer][var+7] = (B << 4) | (G >> 8);cube_data_ptr->GCS[layer][var+8] = B >> 4;break;}}}}void Cube_Set_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t R, uint16_t G, uint16_t B) {// Set the specified pixel to the given colorR &= 0x0FFF;G &= 0x0FFF;B &= 0x0FFF;uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);switch (column % 2) {case 0:cube_data_ptr->GCS[layer][var+0] = R & 0xFF;cube_data_ptr->GCS[layer][var+1] = (G << 4) | (R >> 8);cube_data_ptr->GCS[layer][var+2] = G >> 4;cube_data_ptr->GCS[layer][var+3] = B & 0xFF;cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0xF0) | (B >> 8);break;case 1:cube_data_ptr->GCS[layer][var+4] = (cube_data_ptr->GCS[layer][var+4] & 0x0F) | (R << 4);cube_data_ptr->GCS[layer][var+5] = R >> 4;cube_data_ptr->GCS[layer][var+6] = G & 0xFF;cube_data_ptr->GCS[layer][var+7] = (B << 4) | (G >> 8);cube_data_ptr->GCS[layer][var+8] = B >> 4;break;}}void Cube_Get_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t* R, uint16_t* G, uint16_t* B) {uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);switch (column % 2) {// Concatenate lower byte and upper byte of each color channelcase 0:*R = cube_data_ptr->GCS[layer][var+0] | ((cube_data_ptr->GCS[layer][var+1] & 0x0F) << 8);*G = (cube_data_ptr->GCS[layer][var+1] >> 4) | (cube_data_ptr->GCS[layer][var+2] << 4);*B = cube_data_ptr->GCS[layer][var+3] | ((cube_data_ptr->GCS[layer][var+4] & 0x0F) << 8);break;case 1:*R = (cube_data_ptr->GCS[layer][var+4] >> 4) | (cube_data_ptr->GCS[layer][var+5] << 4);*G = cube_data_ptr->GCS[layer][var+6] | ((cube_data_ptr->GCS[layer][var+7] & 0x0F) << 8);*B = (cube_data_ptr->GCS[layer][var+7] >> 4) | (cube_data_ptr->GCS[layer][var+8] << 4);break;}}void Cube_Move_Pixel(uint8_t layer1, uint8_t row1, uint8_t column1, uint8_t layer2, uint8_t row2, uint8_t column2) {// Copies data from pixel 1 to pixel 2// Note: destination pixel value is overwrittenuint16_t prev_R, prev_G, prev_B;Cube_Get_Pixel(layer1, row1, column1, &prev_R, &prev_G, &prev_B);Cube_Set_Pixel(layer2, row2, column2, prev_R, prev_G, prev_B);}void Cube_Set_Sphere(uint8_t layer, uint8_t R, uint8_t G, uint8_t B) {// Super code inefficient (or is it?) lookup tableswitch (layer % 9) {case 0:Cube_Set_Pixel(3, 3, 3, R, G, B);Cube_Set_Pixel(3, 3, 4, R, G, B);Cube_Set_Pixel(3, 4, 3, R, G, B);Cube_Set_Pixel(3, 4, 4, R, G, B);Cube_Set_Pixel(4, 3, 3, R, G, B);Cube_Set_Pixel(4, 3, 4, R, G, B);Cube_Set_Pixel(4, 4, 3, R, G, B);Cube_Set_Pixel(4, 4, 4, R, G, B);break;case 1:Cube_Set_Pixel(2, 3, 3, R, G, B);Cube_Set_Pixel(2, 3, 4, R, G, B);Cube_Set_Pixel(2, 4, 3, R, G, B);Cube_Set_Pixel(2, 4, 4, R, G, B);Cube_Set_Pixel(5, 3, 3, R, G, B);Cube_Set_Pixel(5, 3, 4, R, G, B);Cube_Set_Pixel(5, 4, 3, R, G, B);Cube_Set_Pixel(5, 4, 4, R, G, B);Cube_Set_Pixel(3, 2, 3, R, G, B);Cube_Set_Pixel(3, 2, 4, R, G, B);Cube_Set_Pixel(3, 5, 3, R, G, B);Cube_Set_Pixel(3, 5, 4, R, G, B);Cube_Set_Pixel(3, 3, 2, R, G, B);Cube_Set_Pixel(3, 4, 2, R, G, B);Cube_Set_Pixel(3, 3, 5, R, G, B);Cube_Set_Pixel(3, 4, 5, R, G, B);Cube_Set_Pixel(4, 2, 3, R, G, B);Cube_Set_Pixel(4, 2, 4, R, G, B);Cube_Set_Pixel(4, 5, 3, R, G, B);Cube_Set_Pixel(4, 5, 4, R, G, B);Cube_Set_Pixel(4, 3, 2, R, G, B);Cube_Set_Pixel(4, 4, 2, R, G, B);Cube_Set_Pixel(4, 3, 5, R, G, B);Cube_Set_Pixel(4, 4, 5, R, G, B);break;case 2:Cube_Set_Pixel(1, 3, 3, R, G, B);Cube_Set_Pixel(1, 3, 4, R, G, B);Cube_Set_Pixel(1, 4, 3, R, G, B);Cube_Set_Pixel(1, 4, 4, R, G, B);Cube_Set_Pixel(6, 3, 3, R, G, B);Cube_Set_Pixel(6, 3, 4, R, G, B);Cube_Set_Pixel(6, 4, 3, R, G, B);Cube_Set_Pixel(6, 4, 4, R, G, B);Cube_Set_Pixel(3, 1, 3, R, G, B);Cube_Set_Pixel(3, 1, 4, R, G, B);Cube_Set_Pixel(3, 6, 3, R, G, B);Cube_Set_Pixel(3, 6, 4, R, G, B);Cube_Set_Pixel(3, 3, 1, R, G, B);Cube_Set_Pixel(3, 4, 1, R, G, B);Cube_Set_Pixel(3, 3, 6, R, G, B);Cube_Set_Pixel(3, 4, 6, R, G, B);Cube_Set_Pixel(3, 2, 2, R, G, B);Cube_Set_Pixel(3, 2, 5, R, G, B);Cube_Set_Pixel(3, 5, 5, R, G, B);Cube_Set_Pixel(3, 5, 2, R, G, B);Cube_Set_Pixel(4, 1, 3, R, G, B);Cube_Set_Pixel(4, 1, 4, R, G, B);Cube_Set_Pixel(4, 6, 3, R, G, B);Cube_Set_Pixel(4, 6, 4, R, G, B);Cube_Set_Pixel(4, 3, 1, R, G, B);Cube_Set_Pixel(4, 4, 1, R, G, B);Cube_Set_Pixel(4, 3, 6, R, G, B);Cube_Set_Pixel(4, 4, 6, R, G, B);Cube_Set_Pixel(4, 2, 2, R, G, B);Cube_Set_Pixel(4, 2, 5, R, G, B);Cube_Set_Pixel(4, 5, 5, R, G, B);Cube_Set_Pixel(4, 5, 2, R, G, B);Cube_Set_Pixel(2, 3, 2, R, G, B);Cube_Set_Pixel(2, 4, 2, R, G, B);Cube_Set_Pixel(2, 3, 5, R, G, B);Cube_Set_Pixel(2, 4, 5, R, G, B);Cube_Set_Pixel(2, 2, 3, R, G, B);Cube_Set_Pixel(2, 2, 4, R, G, B);Cube_Set_Pixel(2, 5, 3, R, G, B);Cube_Set_Pixel(2, 5, 4, R, G, B);Cube_Set_Pixel(2, 2, 2, R, G, B);Cube_Set_Pixel(2, 2, 5, R, G, B);Cube_Set_Pixel(2, 5, 2, R, G, B);Cube_Set_Pixel(2, 5, 5, R, G, B);Cube_Set_Pixel(5, 3, 2, R, G, B);Cube_Set_Pixel(5, 4, 2, R, G, B);Cube_Set_Pixel(5, 3, 5, R, G, B);Cube_Set_Pixel(5, 4, 5, R, G, B);Cube_Set_Pixel(5, 2, 3, R, G, B);Cube_Set_Pixel(5, 2, 4, R, G, B);Cube_Set_Pixel(5, 5, 3, R, G, B);Cube_Set_Pixel(5, 5, 4, R, G, B);Cube_Set_Pixel(5, 2, 2, R, G, B);Cube_Set_Pixel(5, 2, 5, R, G, B);Cube_Set_Pixel(5, 5, 2, R, G, B);Cube_Set_Pixel(5, 5, 5, R, G, B);break;case 3:Cube_Set_Pixel(0, 3, 3, R, G, B);Cube_Set_Pixel(0, 3, 4, R, G, B);Cube_Set_Pixel(0, 4, 3, R, G, B);Cube_Set_Pixel(0, 4, 4, R, G, B);Cube_Set_Pixel(7, 3, 3, R, G, B);Cube_Set_Pixel(7, 3, 4, R, G, B);Cube_Set_Pixel(7, 4, 3, R, G, B);Cube_Set_Pixel(7, 4, 4, R, G, B);Cube_Set_Pixel(3, 0, 3, R, G, B);Cube_Set_Pixel(3, 0, 4, R, G, B);Cube_Set_Pixel(3, 7, 3, R, G, B);Cube_Set_Pixel(3, 7, 4, R, G, B);Cube_Set_Pixel(3, 3, 0, R, G, B);Cube_Set_Pixel(3, 4, 0, R, G, B);Cube_Set_Pixel(3, 3, 7, R, G, B);Cube_Set_Pixel(3, 4, 7, R, G, B);Cube_Set_Pixel(3, 2, 6, R, G, B);Cube_Set_Pixel(3, 1, 5, R, G, B);Cube_Set_Pixel(3, 6, 2, R, G, B);Cube_Set_Pixel(3, 5, 1, R, G, B);Cube_Set_Pixel(3, 1, 2, R, G, B);Cube_Set_Pixel(3, 2, 1, R, G, B);Cube_Set_Pixel(3, 6, 5, R, G, B);Cube_Set_Pixel(3, 5, 6, R, G, B);Cube_Set_Pixel(4, 0, 3, R, G, B);Cube_Set_Pixel(4, 0, 4, R, G, B);Cube_Set_Pixel(4, 7, 3, R, G, B);Cube_Set_Pixel(4, 7, 4, R, G, B);Cube_Set_Pixel(4, 3, 0, R, G, B);Cube_Set_Pixel(4, 4, 0, R, G, B);Cube_Set_Pixel(4, 3, 7, R, G, B);Cube_Set_Pixel(4, 4, 7, R, G, B);Cube_Set_Pixel(4, 2, 6, R, G, B);Cube_Set_Pixel(4, 1, 5, R, G, B);Cube_Set_Pixel(4, 6, 2, R, G, B);Cube_Set_Pixel(4, 5, 1, R, G, B);Cube_Set_Pixel(4, 1, 2, R, G, B);Cube_Set_Pixel(4, 2, 1, R, G, B);Cube_Set_Pixel(4, 6, 5, R, G, B);Cube_Set_Pixel(4, 5, 6, R, G, B);Cube_Set_Pixel(1, 2, 5, R, G, B);Cube_Set_Pixel(1, 2, 4, R, G, B);Cube_Set_Pixel(1, 2, 3, R, G, B);Cube_Set_Pixel(1, 2, 2, R, G, B);Cube_Set_Pixel(1, 3, 5, R, G, B);Cube_Set_Pixel(1, 3, 2, R, G, B);Cube_Set_Pixel(1, 4, 5, R, G, B);Cube_Set_Pixel(1, 4, 2, R, G, B);Cube_Set_Pixel(1, 5, 5, R, G, B);Cube_Set_Pixel(1, 5, 4, R, G, B);Cube_Set_Pixel(1, 5, 3, R, G, B);Cube_Set_Pixel(1, 5, 2, R, G, B);Cube_Set_Pixel(2, 1, 5, R, G, B);Cube_Set_Pixel(2, 1, 4, R, G, B);Cube_Set_Pixel(2, 1, 3, R, G, B);Cube_Set_Pixel(2, 1, 2, R, G, B);Cube_Set_Pixel(2, 6, 5, R, G, B);Cube_Set_Pixel(2, 6, 4, R, G, B);Cube_Set_Pixel(2, 6, 3, R, G, B);Cube_Set_Pixel(2, 6, 2, R, G, B);Cube_Set_Pixel(2, 2, 6, R, G, B);Cube_Set_Pixel(2, 3, 6, R, G, B);Cube_Set_Pixel(2, 4, 6, R, G, B);Cube_Set_Pixel(2, 5, 6, R, G, B);Cube_Set_Pixel(2, 2, 1, R, G, B);Cube_Set_Pixel(2, 3, 1, R, G, B);Cube_Set_Pixel(2, 4, 1, R, G, B);Cube_Set_Pixel(2, 5, 1, R, G, B);Cube_Set_Pixel(5, 1, 5, R, G, B);Cube_Set_Pixel(5, 1, 4, R, G, B);Cube_Set_Pixel(5, 1, 3, R, G, B);Cube_Set_Pixel(5, 1, 2, R, G, B);Cube_Set_Pixel(5, 6, 5, R, G, B);Cube_Set_Pixel(5, 6, 4, R, G, B);Cube_Set_Pixel(5, 6, 3, R, G, B);Cube_Set_Pixel(5, 6, 2, R, G, B);Cube_Set_Pixel(5, 2, 6, R, G, B);Cube_Set_Pixel(5, 3, 6, R, G, B);Cube_Set_Pixel(5, 4, 6, R, G, B);Cube_Set_Pixel(5, 5, 6, R, G, B);Cube_Set_Pixel(5, 2, 1, R, G, B);Cube_Set_Pixel(5, 3, 1, R, G, B);Cube_Set_Pixel(5, 4, 1, R, G, B);Cube_Set_Pixel(5, 5, 1, R, G, B);Cube_Set_Pixel(6, 2, 5, R, G, B);Cube_Set_Pixel(6, 2, 4, R, G, B);Cube_Set_Pixel(6, 2, 3, R, G, B);Cube_Set_Pixel(6, 2, 2, R, G, B);Cube_Set_Pixel(6, 3, 5, R, G, B);Cube_Set_Pixel(6, 3, 2, R, G, B);Cube_Set_Pixel(6, 4, 5, R, G, B);Cube_Set_Pixel(6, 4, 2, R, G, B);Cube_Set_Pixel(6, 5, 5, R, G, B);Cube_Set_Pixel(6, 5, 4, R, G, B);Cube_Set_Pixel(6, 5, 3, R, G, B);Cube_Set_Pixel(6, 5, 2, R, G, B);break;case 4:Cube_Set_Pixel(0, 2, 5, R, G, B);Cube_Set_Pixel(0, 2, 4, R, G, B);Cube_Set_Pixel(0, 2, 3, R, G, B);Cube_Set_Pixel(0, 2, 2, R, G, B);Cube_Set_Pixel(0, 3, 5, R, G, B);Cube_Set_Pixel(0, 3, 2, R, G, B);Cube_Set_Pixel(0, 4, 5, R, G, B);Cube_Set_Pixel(0, 4, 2, R, G, B);Cube_Set_Pixel(0, 5, 5, R, G, B);Cube_Set_Pixel(0, 5, 4, R, G, B);Cube_Set_Pixel(0, 5, 3, R, G, B);Cube_Set_Pixel(0, 5, 2, R, G, B);Cube_Set_Pixel(7, 2, 5, R, G, B);Cube_Set_Pixel(7, 2, 4, R, G, B);Cube_Set_Pixel(7, 2, 3, R, G, B);Cube_Set_Pixel(7, 2, 2, R, G, B);Cube_Set_Pixel(7, 3, 5, R, G, B);Cube_Set_Pixel(7, 3, 2, R, G, B);Cube_Set_Pixel(7, 4, 5, R, G, B);Cube_Set_Pixel(7, 4, 2, R, G, B);Cube_Set_Pixel(7, 5, 5, R, G, B);Cube_Set_Pixel(7, 5, 4, R, G, B);Cube_Set_Pixel(7, 5, 3, R, G, B);Cube_Set_Pixel(7, 5, 2, R, G, B);Cube_Set_Pixel(1, 1, 5, R, G, B);Cube_Set_Pixel(1, 1, 4, R, G, B);Cube_Set_Pixel(1, 1, 3, R, G, B);Cube_Set_Pixel(1, 1, 2, R, G, B);Cube_Set_Pixel(1, 6, 5, R, G, B);Cube_Set_Pixel(1, 6, 4, R, G, B);Cube_Set_Pixel(1, 6, 3, R, G, B);Cube_Set_Pixel(1, 6, 2, R, G, B);Cube_Set_Pixel(1, 2, 6, R, G, B);Cube_Set_Pixel(1, 3, 6, R, G, B);Cube_Set_Pixel(1, 4, 6, R, G, B);Cube_Set_Pixel(1, 5, 6, R, G, B);Cube_Set_Pixel(1, 2, 1, R, G, B);Cube_Set_Pixel(1, 3, 1, R, G, B);Cube_Set_Pixel(1, 4, 1, R, G, B);Cube_Set_Pixel(1, 5, 1, R, G, B);Cube_Set_Pixel(6, 1, 5, R, G, B);Cube_Set_Pixel(6, 1, 4, R, G, B);Cube_Set_Pixel(6, 1, 3, R, G, B);Cube_Set_Pixel(6, 1, 2, R, G, B);Cube_Set_Pixel(6, 6, 5, R, G, B);Cube_Set_Pixel(6, 6, 4, R, G, B);Cube_Set_Pixel(6, 6, 3, R, G, B);Cube_Set_Pixel(6, 6, 2, R, G, B);Cube_Set_Pixel(6, 2, 6, R, G, B);Cube_Set_Pixel(6, 3, 6, R, G, B);Cube_Set_Pixel(6, 4, 6, R, G, B);Cube_Set_Pixel(6, 5, 6, R, G, B);Cube_Set_Pixel(6, 2, 1, R, G, B);Cube_Set_Pixel(6, 3, 1, R, G, B);Cube_Set_Pixel(6, 4, 1, R, G, B);Cube_Set_Pixel(6, 5, 1, R, G, B);Cube_Set_Pixel(2, 0, 5, R, G, B);Cube_Set_Pixel(2, 0, 4, R, G, B);Cube_Set_Pixel(2, 0, 3, R, G, B);Cube_Set_Pixel(2, 0, 2, R, G, B);Cube_Set_Pixel(2, 7, 5, R, G, B);Cube_Set_Pixel(2, 7, 4, R, G, B);Cube_Set_Pixel(2, 7, 3, R, G, B);Cube_Set_Pixel(2, 7, 2, R, G, B);Cube_Set_Pixel(2, 5, 0, R, G, B);Cube_Set_Pixel(2, 4, 0, R, G, B);Cube_Set_Pixel(2, 3, 0, R, G, B);Cube_Set_Pixel(2, 2, 0, R, G, B);Cube_Set_Pixel(2, 5, 7, R, G, B);Cube_Set_Pixel(2, 4, 7, R, G, B);Cube_Set_Pixel(2, 3, 7, R, G, B);Cube_Set_Pixel(2, 2, 7, R, G, B);Cube_Set_Pixel(2, 1, 1, R, G, B);Cube_Set_Pixel(2, 1, 6, R, G, B);Cube_Set_Pixel(2, 6, 1, R, G, B);Cube_Set_Pixel(2, 6, 6, R, G, B);Cube_Set_Pixel(5, 0, 5, R, G, B);Cube_Set_Pixel(5, 0, 4, R, G, B);Cube_Set_Pixel(5, 0, 3, R, G, B);Cube_Set_Pixel(5, 0, 2, R, G, B);Cube_Set_Pixel(5, 7, 5, R, G, B);Cube_Set_Pixel(5, 7, 4, R, G, B);Cube_Set_Pixel(5, 7, 3, R, G, B);Cube_Set_Pixel(5, 7, 2, R, G, B);Cube_Set_Pixel(5, 5, 0, R, G, B);Cube_Set_Pixel(5, 4, 0, R, G, B);Cube_Set_Pixel(5, 3, 0, R, G, B);Cube_Set_Pixel(5, 2, 0, R, G, B);Cube_Set_Pixel(5, 5, 7, R, G, B);Cube_Set_Pixel(5, 4, 7, R, G, B);Cube_Set_Pixel(5, 3, 7, R, G, B);Cube_Set_Pixel(5, 2, 7, R, G, B);Cube_Set_Pixel(5, 1, 1, R, G, B);Cube_Set_Pixel(5, 1, 6, R, G, B);Cube_Set_Pixel(5, 6, 1, R, G, B);Cube_Set_Pixel(5, 6, 6, R, G, B);Cube_Set_Pixel(3, 0, 2, R, G, B);Cube_Set_Pixel(3, 0, 5, R, G, B);Cube_Set_Pixel(3, 2, 0, R, G, B);Cube_Set_Pixel(3, 5, 0, R, G, B);Cube_Set_Pixel(3, 7, 2, R, G, B);Cube_Set_Pixel(3, 7, 5, R, G, B);Cube_Set_Pixel(3, 2, 7, R, G, B);Cube_Set_Pixel(3, 5, 7, R, G, B);Cube_Set_Pixel(3, 1, 1, R, G, B);Cube_Set_Pixel(3, 1, 6, R, G, B);Cube_Set_Pixel(3, 6, 1, R, G, B);Cube_Set_Pixel(3, 6, 6, R, G, B);Cube_Set_Pixel(4, 0, 2, R, G, B);Cube_Set_Pixel(4, 0, 5, R, G, B);Cube_Set_Pixel(4, 2, 0, R, G, B);Cube_Set_Pixel(4, 5, 0, R, G, B);Cube_Set_Pixel(4, 7, 2, R, G, B);Cube_Set_Pixel(4, 7, 5, R, G, B);Cube_Set_Pixel(4, 2, 7, R, G, B);Cube_Set_Pixel(4, 5, 7, R, G, B);Cube_Set_Pixel(4, 1, 1, R, G, B);Cube_Set_Pixel(4, 1, 6, R, G, B);Cube_Set_Pixel(4, 6, 1, R, G, B);Cube_Set_Pixel(4, 6, 6, R, G, B);break;case 5:Cube_Set_Pixel(0, 1, 5, R, G, B);Cube_Set_Pixel(0, 1, 4, R, G, B);Cube_Set_Pixel(0, 1, 3, R, G, B);Cube_Set_Pixel(0, 1, 2, R, G, B);Cube_Set_Pixel(0, 6, 5, R, G, B);Cube_Set_Pixel(0, 6, 4, R, G, B);Cube_Set_Pixel(0, 6, 3, R, G, B);Cube_Set_Pixel(0, 6, 2, R, G, B);Cube_Set_Pixel(0, 2, 6, R, G, B);Cube_Set_Pixel(0, 3, 6, R, G, B);Cube_Set_Pixel(0, 4, 6, R, G, B);Cube_Set_Pixel(0, 5, 6, R, G, B);Cube_Set_Pixel(0, 2, 1, R, G, B);Cube_Set_Pixel(0, 3, 1, R, G, B);Cube_Set_Pixel(0, 4, 1, R, G, B);Cube_Set_Pixel(0, 5, 1, R, G, B);Cube_Set_Pixel(1, 0, 2, R, G, B);Cube_Set_Pixel(1, 0, 3, R, G, B);Cube_Set_Pixel(1, 0, 4, R, G, B);Cube_Set_Pixel(1, 0, 5, R, G, B);Cube_Set_Pixel(1, 1, 6, R, G, B);Cube_Set_Pixel(1, 2, 7, R, G, B);Cube_Set_Pixel(1, 3, 7, R, G, B);Cube_Set_Pixel(1, 4, 7, R, G, B);Cube_Set_Pixel(1, 5, 7, R, G, B);Cube_Set_Pixel(1, 6, 6, R, G, B);Cube_Set_Pixel(1, 7, 5, R, G, B);Cube_Set_Pixel(1, 7, 4, R, G, B);Cube_Set_Pixel(1, 7, 3, R, G, B);Cube_Set_Pixel(1, 7, 2, R, G, B);Cube_Set_Pixel(1, 6, 1, R, G, B);Cube_Set_Pixel(1, 5, 0, R, G, B);Cube_Set_Pixel(1, 4, 0, R, G, B);Cube_Set_Pixel(1, 3, 0, R, G, B);Cube_Set_Pixel(1, 2, 0, R, G, B);Cube_Set_Pixel(1, 1, 1, R, G, B);Cube_Set_Pixel(2, 0, 1, R, G, B);Cube_Set_Pixel(2, 1, 0, R, G, B);Cube_Set_Pixel(2, 0, 6, R, G, B);Cube_Set_Pixel(2, 1, 7, R, G, B);Cube_Set_Pixel(2, 6, 7, R, G, B);Cube_Set_Pixel(2, 7, 6, R, G, B);Cube_Set_Pixel(2, 6, 0, R, G, B);Cube_Set_Pixel(2, 7, 1, R, G, B);Cube_Set_Pixel(3, 0, 1, R, G, B);Cube_Set_Pixel(3, 1, 0, R, G, B);Cube_Set_Pixel(3, 0, 6, R, G, B);Cube_Set_Pixel(3, 1, 7, R, G, B);Cube_Set_Pixel(3, 6, 7, R, G, B);Cube_Set_Pixel(3, 7, 6, R, G, B);Cube_Set_Pixel(3, 6, 0, R, G, B);Cube_Set_Pixel(3, 7, 1, R, G, B);Cube_Set_Pixel(4, 0, 1, R, G, B);Cube_Set_Pixel(4, 1, 0, R, G, B);Cube_Set_Pixel(4, 0, 6, R, G, B);Cube_Set_Pixel(4, 1, 7, R, G, B);Cube_Set_Pixel(4, 6, 7, R, G, B);Cube_Set_Pixel(4, 7, 6, R, G, B);Cube_Set_Pixel(4, 6, 0, R, G, B);Cube_Set_Pixel(4, 7, 1, R, G, B);Cube_Set_Pixel(5, 0, 1, R, G, B);Cube_Set_Pixel(5, 1, 0, R, G, B);Cube_Set_Pixel(5, 0, 6, R, G, B);Cube_Set_Pixel(5, 1, 7, R, G, B);Cube_Set_Pixel(5, 6, 7, R, G, B);Cube_Set_Pixel(5, 7, 6, R, G, B);Cube_Set_Pixel(5, 6, 0, R, G, B);Cube_Set_Pixel(5, 7, 1, R, G, B);Cube_Set_Pixel(6, 0, 2, R, G, B);Cube_Set_Pixel(6, 0, 3, R, G, B);Cube_Set_Pixel(6, 0, 4, R, G, B);Cube_Set_Pixel(6, 0, 5, R, G, B);Cube_Set_Pixel(6, 1, 6, R, G, B);Cube_Set_Pixel(6, 2, 7, R, G, B);Cube_Set_Pixel(6, 3, 7, R, G, B);Cube_Set_Pixel(6, 4, 7, R, G, B);Cube_Set_Pixel(6, 5, 7, R, G, B);Cube_Set_Pixel(6, 6, 6, R, G, B);Cube_Set_Pixel(6, 7, 5, R, G, B);Cube_Set_Pixel(6, 7, 4, R, G, B);Cube_Set_Pixel(6, 7, 3, R, G, B);Cube_Set_Pixel(6, 7, 2, R, G, B);Cube_Set_Pixel(6, 6, 1, R, G, B);Cube_Set_Pixel(6, 5, 0, R, G, B);Cube_Set_Pixel(6, 4, 0, R, G, B);Cube_Set_Pixel(6, 3, 0, R, G, B);Cube_Set_Pixel(6, 2, 0, R, G, B);Cube_Set_Pixel(6, 1, 1, R, G, B);Cube_Set_Pixel(7, 1, 5, R, G, B);Cube_Set_Pixel(7, 1, 4, R, G, B);Cube_Set_Pixel(7, 1, 3, R, G, B);Cube_Set_Pixel(7, 1, 2, R, G, B);Cube_Set_Pixel(7, 6, 5, R, G, B);Cube_Set_Pixel(7, 6, 4, R, G, B);Cube_Set_Pixel(7, 6, 3, R, G, B);Cube_Set_Pixel(7, 6, 2, R, G, B);Cube_Set_Pixel(7, 2, 6, R, G, B);Cube_Set_Pixel(7, 3, 6, R, G, B);Cube_Set_Pixel(7, 4, 6, R, G, B);Cube_Set_Pixel(7, 5, 6, R, G, B);Cube_Set_Pixel(7, 2, 1, R, G, B);Cube_Set_Pixel(7, 3, 1, R, G, B);Cube_Set_Pixel(7, 4, 1, R, G, B);Cube_Set_Pixel(7, 5, 1, R, G, B);break;case 6:Cube_Set_Pixel(0, 0, 2, R, G, B);Cube_Set_Pixel(0, 0, 3, R, G, B);Cube_Set_Pixel(0, 0, 4, R, G, B);Cube_Set_Pixel(0, 0, 5, R, G, B);Cube_Set_Pixel(0, 1, 1, R, G, B);Cube_Set_Pixel(0, 1, 6, R, G, B);Cube_Set_Pixel(0, 2, 0, R, G, B);Cube_Set_Pixel(0, 2, 7, R, G, B);Cube_Set_Pixel(0, 3, 0, R, G, B);Cube_Set_Pixel(0, 3, 7, R, G, B);Cube_Set_Pixel(0, 4, 0, R, G, B);Cube_Set_Pixel(0, 4, 7, R, G, B);Cube_Set_Pixel(0, 5, 0, R, G, B);Cube_Set_Pixel(0, 5, 7, R, G, B);Cube_Set_Pixel(0, 6, 6, R, G, B);Cube_Set_Pixel(0, 6, 1, R, G, B);Cube_Set_Pixel(0, 7, 2, R, G, B);Cube_Set_Pixel(0, 7, 3, R, G, B);Cube_Set_Pixel(0, 7, 4, R, G, B);Cube_Set_Pixel(0, 7, 5, R, G, B);Cube_Set_Pixel(1, 0, 1, R, G, B);Cube_Set_Pixel(1, 1, 0, R, G, B);Cube_Set_Pixel(1, 0, 6, R, G, B);Cube_Set_Pixel(1, 1, 7, R, G, B);Cube_Set_Pixel(1, 6, 7, R, G, B);Cube_Set_Pixel(1, 7, 6, R, G, B);Cube_Set_Pixel(1, 6, 0, R, G, B);Cube_Set_Pixel(1, 7, 1, R, G, B);Cube_Set_Pixel(2, 0, 0, R, G, B);Cube_Set_Pixel(2, 0, 7, R, G, B);Cube_Set_Pixel(2, 7, 7, R, G, B);Cube_Set_Pixel(2, 7, 0, R, G, B);Cube_Set_Pixel(3, 0, 0, R, G, B);Cube_Set_Pixel(3, 0, 7, R, G, B);Cube_Set_Pixel(3, 7, 7, R, G, B);Cube_Set_Pixel(3, 7, 0, R, G, B);Cube_Set_Pixel(4, 0, 0, R, G, B);Cube_Set_Pixel(4, 0, 7, R, G, B);Cube_Set_Pixel(4, 7, 7, R, G, B);Cube_Set_Pixel(4, 7, 0, R, G, B);Cube_Set_Pixel(5, 0, 0, R, G, B);Cube_Set_Pixel(5, 0, 7, R, G, B);Cube_Set_Pixel(5, 7, 7, R, G, B);Cube_Set_Pixel(5, 7, 0, R, G, B);Cube_Set_Pixel(6, 0, 1, R, G, B);Cube_Set_Pixel(6, 1, 0, R, G, B);Cube_Set_Pixel(6, 0, 6, R, G, B);Cube_Set_Pixel(6, 1, 7, R, G, B);Cube_Set_Pixel(6, 6, 7, R, G, B);Cube_Set_Pixel(6, 7, 6, R, G, B);Cube_Set_Pixel(6, 6, 0, R, G, B);Cube_Set_Pixel(6, 7, 1, R, G, B);Cube_Set_Pixel(7, 0, 2, R, G, B);Cube_Set_Pixel(7, 0, 3, R, G, B);Cube_Set_Pixel(7, 0, 4, R, G, B);Cube_Set_Pixel(7, 0, 5, R, G, B);Cube_Set_Pixel(7, 1, 1, R, G, B);Cube_Set_Pixel(7, 1, 6, R, G, B);Cube_Set_Pixel(7, 2, 0, R, G, B);Cube_Set_Pixel(7, 2, 7, R, G, B);Cube_Set_Pixel(7, 3, 0, R, G, B);Cube_Set_Pixel(7, 3, 7, R, G, B);Cube_Set_Pixel(7, 4, 0, R, G, B);Cube_Set_Pixel(7, 4, 7, R, G, B);Cube_Set_Pixel(7, 5, 0, R, G, B);Cube_Set_Pixel(7, 5, 7, R, G, B);Cube_Set_Pixel(7, 6, 6, R, G, B);Cube_Set_Pixel(7, 6, 1, R, G, B);Cube_Set_Pixel(7, 7, 2, R, G, B);Cube_Set_Pixel(7, 7, 3, R, G, B);Cube_Set_Pixel(7, 7, 4, R, G, B);Cube_Set_Pixel(7, 7, 5, R, G, B);break;case 7:Cube_Set_Pixel(0, 0, 1, R, G, B);Cube_Set_Pixel(0, 1, 0, R, G, B);Cube_Set_Pixel(0, 0, 6, R, G, B);Cube_Set_Pixel(0, 1, 7, R, G, B);Cube_Set_Pixel(0, 6, 7, R, G, B);Cube_Set_Pixel(0, 7, 6, R, G, B);Cube_Set_Pixel(0, 7, 1, R, G, B);Cube_Set_Pixel(0, 6, 0, R, G, B);Cube_Set_Pixel(1, 0, 0, R, G, B);Cube_Set_Pixel(1, 0, 7, R, G, B);Cube_Set_Pixel(1, 7, 7, R, G, B);Cube_Set_Pixel(1, 7, 0, R, G, B);Cube_Set_Pixel(6, 0, 0, R, G, B);Cube_Set_Pixel(6, 0, 7, R, G, B);Cube_Set_Pixel(6, 7, 7, R, G, B);Cube_Set_Pixel(6, 7, 0, R, G, B);Cube_Set_Pixel(7, 0, 1, R, G, B);Cube_Set_Pixel(7, 1, 0, R, G, B);Cube_Set_Pixel(7, 0, 6, R, G, B);Cube_Set_Pixel(7, 1, 7, R, G, B);Cube_Set_Pixel(7, 6, 7, R, G, B);Cube_Set_Pixel(7, 7, 6, R, G, B);Cube_Set_Pixel(7, 7, 1, R, G, B);Cube_Set_Pixel(7, 6, 0, R, G, B);break;case 8:Cube_Set_Pixel(0, 0, 0, R, G, B);Cube_Set_Pixel(0, 0, 7, R, G, B);Cube_Set_Pixel(0, 7, 7, R, G, B);Cube_Set_Pixel(0, 7, 0, R, G, B);Cube_Set_Pixel(7, 0, 0, R, G, B);Cube_Set_Pixel(7, 0, 7, R, G, B);Cube_Set_Pixel(7, 7, 7, R, G, B);Cube_Set_Pixel(7, 7, 0, R, G, B);break;default:break;}}void Cube_Set_Shell(uint8_t layer, uint8_t R, uint8_t G, uint8_t B) {// Sets the specified shell to the specific color// Shell 0 is the outermost layer, 3 is the innermost cube of pixelsuint8_t i, j, k;for (i = 0; i < CUBE_LAYER_COUNT; i++) {if ((layer == 0 || layer == 4)&&(i == 0 || i == 7)) {Cube_Set_Layer(i,R,G,B);} else if ((layer == 1 || layer == 4)&&(i == 1 || i == 6)) {for (j = 1; j < CUBE_ROW_COUNT-1; j++)for (k = 1; k < CUBE_COLUMN_COUNT-1; k++)Cube_Set_Pixel(i,j,k,R,G,B);} else if ((layer == 2 || layer == 4)&&(i == 2 || i == 5)) {for (j = 2; j < CUBE_ROW_COUNT-2; j++)for (k = 2; k < CUBE_COLUMN_COUNT-2; k++)Cube_Set_Pixel(i,j,k,R,G,B);} else if ((layer == 3 || layer == 4)&&(i == 3 || i == 4)) {for (j = 3; j < CUBE_ROW_COUNT-3; j++)for (k = 3; k < CUBE_COLUMN_COUNT-3; k++)Cube_Set_Pixel(i,j,k,R,G,B);}if ((layer == 0 || layer == 4)&&(i > 0 && i < 8)) {for (j = 0; j < 8; j++) {Cube_Set_Pixel(i,j,0,R,G,B);Cube_Set_Pixel(i,j,7,R,G,B);Cube_Set_Pixel(i,0,j,R,G,B);Cube_Set_Pixel(i,7,j,R,G,B);}}if ((layer == 1 || layer == 4)&&(i > 1 && i < 7)) {for (j = 1; j < 7; j++) {Cube_Set_Pixel(i,j,1,R,G,B);Cube_Set_Pixel(i,j,6,R,G,B);Cube_Set_Pixel(i,1,j,R,G,B);Cube_Set_Pixel(i,6,j,R,G,B);}}if ((layer == 2 || layer == 4)&&(i > 2 && i < 6)) {for (j = 2; j < 6; j++) {Cube_Set_Pixel(i,j,2,R,G,B);Cube_Set_Pixel(i,j,5,R,G,B);Cube_Set_Pixel(i,2,j,R,G,B);Cube_Set_Pixel(i,5,j,R,G,B);}}}}void Cube_Rotate_Shell(uint8_t shell, uint8_t direction) {// Shell is the layer to rotate, with the outermost being 0uint8_t layer;uint16_t origin_R, origin_G, origin_B;for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {if (direction) {switch(shell) {case 0:// Rotate outermost layerCube_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 0, 1, layer, 0, 0);Cube_Move_Pixel(layer, 0, 2, layer, 0, 1);Cube_Move_Pixel(layer, 0, 3, layer, 0, 2);Cube_Move_Pixel(layer, 0, 4, layer, 0, 3);Cube_Move_Pixel(layer, 0, 5, layer, 0, 4);Cube_Move_Pixel(layer, 0, 6, layer, 0, 5);Cube_Move_Pixel(layer, 0, 7, layer, 0, 6);Cube_Move_Pixel(layer, 1, 7, layer, 0, 7);Cube_Move_Pixel(layer, 2, 7, layer, 1, 7);Cube_Move_Pixel(layer, 3, 7, layer, 2, 7);Cube_Move_Pixel(layer, 4, 7, layer, 3, 7);Cube_Move_Pixel(layer, 5, 7, layer, 4, 7);Cube_Move_Pixel(layer, 6, 7, layer, 5, 7);Cube_Move_Pixel(layer, 7, 7, layer, 6, 7);Cube_Move_Pixel(layer, 7, 6, layer, 7, 7);Cube_Move_Pixel(layer, 7, 5, layer, 7, 6);Cube_Move_Pixel(layer, 7, 4, layer, 7, 5);Cube_Move_Pixel(layer, 7, 3, layer, 7, 4);Cube_Move_Pixel(layer, 7, 2, layer, 7, 3);Cube_Move_Pixel(layer, 7, 1, layer, 7, 2);Cube_Move_Pixel(layer, 7, 0, layer, 7, 1);Cube_Move_Pixel(layer, 6, 0, layer, 7, 0);Cube_Move_Pixel(layer, 5, 0, layer, 6, 0);Cube_Move_Pixel(layer, 4, 0, layer, 5, 0);Cube_Move_Pixel(layer, 3, 0, layer, 4, 0);Cube_Move_Pixel(layer, 2, 0, layer, 3, 0);Cube_Move_Pixel(layer, 1, 0, layer, 2, 0);Cube_Set_Pixel(layer, 1, 0, origin_R, origin_G, origin_B);break;case 1:// Rotate second to outermost layerCube_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 1, 2, layer, 1, 1);Cube_Move_Pixel(layer, 1, 3, layer, 1, 2);Cube_Move_Pixel(layer, 1, 4, layer, 1, 3);Cube_Move_Pixel(layer, 1, 5, layer, 1, 4);Cube_Move_Pixel(layer, 1, 6, layer, 1, 5);Cube_Move_Pixel(layer, 2, 6, layer, 1, 6);Cube_Move_Pixel(layer, 3, 6, layer, 2, 6);Cube_Move_Pixel(layer, 4, 6, layer, 3, 6);Cube_Move_Pixel(layer, 5, 6, layer, 4, 6);Cube_Move_Pixel(layer, 6, 6, layer, 5, 6);Cube_Move_Pixel(layer, 6, 5, layer, 6, 6);Cube_Move_Pixel(layer, 6, 4, layer, 6, 5);Cube_Move_Pixel(layer, 6, 3, layer, 6, 4);Cube_Move_Pixel(layer, 6, 2, layer, 6, 3);Cube_Move_Pixel(layer, 6, 1, layer, 6, 2);Cube_Move_Pixel(layer, 5, 1, layer, 6, 1);Cube_Move_Pixel(layer, 4, 1, layer, 5, 1);Cube_Move_Pixel(layer, 3, 1, layer, 4, 1);Cube_Move_Pixel(layer, 2, 1, layer, 3, 1);Cube_Set_Pixel(layer, 2, 1, origin_R, origin_G, origin_B);break;case 2:// Rotate second to innermost layerCube_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 2, 3, layer, 2, 2);Cube_Move_Pixel(layer, 2, 4, layer, 2, 3);Cube_Move_Pixel(layer, 2, 5, layer, 2, 4);Cube_Move_Pixel(layer, 3, 5, layer, 2, 5);Cube_Move_Pixel(layer, 4, 5, layer, 3, 5);Cube_Move_Pixel(layer, 5, 5, layer, 4, 5);Cube_Move_Pixel(layer, 5, 4, layer, 5, 5);Cube_Move_Pixel(layer, 5, 3, layer, 5, 4);Cube_Move_Pixel(layer, 5, 2, layer, 5, 3);Cube_Move_Pixel(layer, 4, 2, layer, 5, 2);Cube_Move_Pixel(layer, 3, 2, layer, 4, 2);Cube_Set_Pixel(layer, 3, 2, origin_R, origin_G, origin_B);break;case 3:// Rotate innermost layerCube_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 3, 4, layer, 3, 3);Cube_Move_Pixel(layer, 4, 4, layer, 3, 4);Cube_Move_Pixel(layer, 4, 3, layer, 4, 4);Cube_Set_Pixel(layer, 4, 3, origin_R, origin_G, origin_B);break;}} else {switch(shell) {case 0:// Rotate outermost layerCube_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 1, 0, layer, 0, 0);Cube_Move_Pixel(layer, 2, 0, layer, 1, 0);Cube_Move_Pixel(layer, 3, 0, layer, 2, 0);Cube_Move_Pixel(layer, 4, 0, layer, 3, 0);Cube_Move_Pixel(layer, 5, 0, layer, 4, 0);Cube_Move_Pixel(layer, 6, 0, layer, 5, 0);Cube_Move_Pixel(layer, 7, 0, layer, 6, 0);Cube_Move_Pixel(layer, 7, 1, layer, 7, 0);Cube_Move_Pixel(layer, 7, 2, layer, 7, 1);Cube_Move_Pixel(layer, 7, 3, layer, 7, 2);Cube_Move_Pixel(layer, 7, 4, layer, 7, 3);Cube_Move_Pixel(layer, 7, 5, layer, 7, 4);Cube_Move_Pixel(layer, 7, 6, layer, 7, 5);Cube_Move_Pixel(layer, 7, 7, layer, 7, 6);Cube_Move_Pixel(layer, 6, 7, layer, 7, 7);Cube_Move_Pixel(layer, 5, 7, layer, 6, 7);Cube_Move_Pixel(layer, 4, 7, layer, 5, 7);Cube_Move_Pixel(layer, 3, 7, layer, 4, 7);Cube_Move_Pixel(layer, 2, 7, layer, 3, 7);Cube_Move_Pixel(layer, 1, 7, layer, 2, 7);Cube_Move_Pixel(layer, 0, 7, layer, 1, 7);Cube_Move_Pixel(layer, 0, 6, layer, 0, 7);Cube_Move_Pixel(layer, 0, 5, layer, 0, 6);Cube_Move_Pixel(layer, 0, 4, layer, 0, 5);Cube_Move_Pixel(layer, 0, 3, layer, 0, 4);Cube_Move_Pixel(layer, 0, 2, layer, 0, 3);Cube_Move_Pixel(layer, 0, 1, layer, 0, 2);Cube_Set_Pixel(layer, 0, 1, origin_R, origin_G, origin_B);break;case 1:// Rotate second to outermost layerCube_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 2, 1, layer, 1, 1);Cube_Move_Pixel(layer, 3, 1, layer, 2, 1);Cube_Move_Pixel(layer, 4, 1, layer, 3, 1);Cube_Move_Pixel(layer, 5, 1, layer, 4, 1);Cube_Move_Pixel(layer, 6, 1, layer, 5, 1);Cube_Move_Pixel(layer, 6, 2, layer, 6, 1);Cube_Move_Pixel(layer, 6, 3, layer, 6, 2);Cube_Move_Pixel(layer, 6, 4, layer, 6, 3);Cube_Move_Pixel(layer, 6, 5, layer, 6, 4);Cube_Move_Pixel(layer, 6, 6, layer, 6, 5);Cube_Move_Pixel(layer, 5, 6, layer, 6, 6);Cube_Move_Pixel(layer, 4, 6, layer, 5, 6);Cube_Move_Pixel(layer, 3, 6, layer, 4, 6);Cube_Move_Pixel(layer, 2, 6, layer, 3, 6);Cube_Move_Pixel(layer, 1, 6, layer, 2, 6);Cube_Move_Pixel(layer, 1, 5, layer, 1, 6);Cube_Move_Pixel(layer, 1, 4, layer, 1, 5);Cube_Move_Pixel(layer, 1, 3, layer, 1, 4);Cube_Move_Pixel(layer, 1, 2, layer, 1, 3);Cube_Set_Pixel(layer, 1, 2, origin_R, origin_G, origin_B);break;case 2:// Rotate second to innermost layerCube_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 3, 2, layer, 2, 2);Cube_Move_Pixel(layer, 4, 2, layer, 3, 2);Cube_Move_Pixel(layer, 5, 2, layer, 4, 2);Cube_Move_Pixel(layer, 5, 3, layer, 5, 2);Cube_Move_Pixel(layer, 5, 4, layer, 5, 3);Cube_Move_Pixel(layer, 5, 5, layer, 5, 4);Cube_Move_Pixel(layer, 4, 5, layer, 5, 5);Cube_Move_Pixel(layer, 3, 5, layer, 4, 5);Cube_Move_Pixel(layer, 2, 5, layer, 3, 5);Cube_Move_Pixel(layer, 2, 4, layer, 2, 5);Cube_Move_Pixel(layer, 2, 3, layer, 2, 4);Cube_Set_Pixel(layer, 2, 3, origin_R, origin_G, origin_B);break;case 3:// Rotate innermost layerCube_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);Cube_Move_Pixel(layer, 4, 3, layer, 3, 3);Cube_Move_Pixel(layer, 4, 4, layer, 4, 3);Cube_Move_Pixel(layer, 3, 4, layer, 4, 4);Cube_Set_Pixel(layer, 3, 4, origin_R, origin_G, origin_B);break;}}}}void Cube_Rotate(uint8_t direction) {// Rotate outermost layerCube_Rotate_Shell(0, direction);// Rotate second to outermost layerif ((cube_data_ptr->rotation_counter != 1) && (cube_data_ptr->rotation_counter != 5)) {Cube_Rotate_Shell(1, direction);}// Rotate second to innermost layerif ((cube_data_ptr->rotation_counter != 0) && (cube_data_ptr->rotation_counter != 2) &&(cube_data_ptr->rotation_counter != 4) && (cube_data_ptr->rotation_counter != 6)) {Cube_Rotate_Shell(2, direction);}// Rotate innermost layerif ((cube_data_ptr->rotation_counter == 3) || (cube_data_ptr->rotation_counter == 7)) {Cube_Rotate_Shell(3, direction);}if (direction == 0) {cube_data_ptr->rotation_counter = (cube_data_ptr->rotation_counter == CUBE_ROTATIONS - 1)? 0 : cube_data_ptr->rotation_counter + 1;} else {cube_data_ptr->rotation_counter = (cube_data_ptr->rotation_counter == 0)? CUBE_ROTATIONS - 1 : cube_data_ptr->rotation_counter - 1;}}void Cube_Shift_Row(uint8_t direction) {// Shifts the display by an entire rowint i, j, k;if (direction) {// Shift values in each row by onefor (i = CUBE_ROW_COUNT - 1; i >= 0; i--) { // Rowfor (j = 0; j < CUBE_COLUMN_COUNT; j++) {for (k = 0; k < CUBE_LAYER_COUNT; k++) {Cube_Move_Pixel(k, i - 1, j, k, i, j);}}}} else {for (i = 0; i < CUBE_ROW_COUNT - 1; i++) {for (j = 0; j < CUBE_COLUMN_COUNT; j++) {for (k = 0; k < CUBE_LAYER_COUNT; k++) {Cube_Move_Pixel(k, i + 1, j, k, i, j);}}}}}void Cube_Shift_Waterfall(uint8_t *values) {// Takes an array of 8 values and sets them to the column height// Each column is set to a manually specified coloruint8_t i, j;uint8_t update_row = CUBE_ROW_COUNT - 1;// First shift the rowsCube_Shift_Row(0);// Then update the empty rowfor (i = 0; i < CUBE_COLUMN_COUNT; i++) {for (j = 0; j < CUBE_LAYER_COUNT; j++) {if (j < values[i] % 9) {// Specify the color for each columnif (i == 0)Cube_Set_Pixel(j, update_row, i, RED);else if (i == 1)Cube_Set_Pixel(j, update_row, i, ORANGE);else if (i == 2)Cube_Set_Pixel(j, update_row, i, YELLOW);else if (i == 3)Cube_Set_Pixel(j, update_row, i, GREEN);else if (i == 4)Cube_Set_Pixel(j, update_row, i, TEAL);else if (i == 5)Cube_Set_Pixel(j, update_row, i, BLUE);else if (i == 6)Cube_Set_Pixel(j, update_row, i, PURPLE);elseCube_Set_Pixel(j, update_row, i, WHITE);} else {Cube_Set_Pixel(j, update_row, i, CLEAR);}}}}void Cube_Shift_Waterfall2(uint8_t *values) {// Takes an array of 8 values and sets them to the column height// Each layer is set to a manually specified coloruint8_t i, j;uint8_t update_row = CUBE_ROW_COUNT - 1;// First shift the rowsCube_Shift_Row(0);// Then update the empty rowfor (i = 0; i < CUBE_COLUMN_COUNT; i++) {for (j = 0; j < CUBE_LAYER_COUNT; j++) {if (j < values[i] % 9) {// Specify the color for each layerif (j == 7)Cube_Set_Pixel(j, update_row, i, RED);else if (j == 6)Cube_Set_Pixel(j, update_row, i, ORANGE);else if (j == 5)Cube_Set_Pixel(j, update_row, i, YELLOW);else if (j == 4)Cube_Set_Pixel(j, update_row, i, GREEN);else if (j == 3)Cube_Set_Pixel(j, update_row, i, TEAL);else if (j == 2)Cube_Set_Pixel(j, update_row, i, BLUE);else if (j == 1)Cube_Set_Pixel(j, update_row, i, PURPLE);elseCube_Set_Pixel(j, update_row, i, WHITE);} else {Cube_Set_Pixel(j, update_row, i, CLEAR);}}}}///////////////////////////////// Overlay control functions /////////////////////////////////void Cube_Overlay_Clear(void) {uint16_t i,j;for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < GCS_LAYER_SIZE; j++) {cube_data_ptr->GCS_OVERLAY[i][j] = 0x00;}}}void Cube_Overlay_Set_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t R, uint16_t G, uint16_t B) {// Set the specified pixel to the given colorR &= 0x0FFF;G &= 0x0FFF;B &= 0x0FFF;uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);switch (column % 2) {case 0:cube_data_ptr->GCS_OVERLAY[layer][var+0] = R & 0xFF;cube_data_ptr->GCS_OVERLAY[layer][var+1] = (G << 4) | (R >> 8);cube_data_ptr->GCS_OVERLAY[layer][var+2] = G >> 4;cube_data_ptr->GCS_OVERLAY[layer][var+3] = B & 0xFF;cube_data_ptr->GCS_OVERLAY[layer][var+4] = (cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0xF0) | (B >> 8);break;case 1:cube_data_ptr->GCS_OVERLAY[layer][var+4] = (cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0x0F) | (R << 4);cube_data_ptr->GCS_OVERLAY[layer][var+5] = R >> 4;cube_data_ptr->GCS_OVERLAY[layer][var+6] = G & 0xFF;cube_data_ptr->GCS_OVERLAY[layer][var+7] = (B << 4) | (G >> 8);cube_data_ptr->GCS_OVERLAY[layer][var+8] = B >> 4;break;}}void Cube_Overlay_Get_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t* R, uint16_t* G, uint16_t* B) {uint16_t var = row * GCS_REG_SIZE + (column / 2 * 9);switch (column % 2) {// Concatenate lower byte and upper byte of each color channelcase 0:*R = cube_data_ptr->GCS_OVERLAY[layer][var+0] | ((cube_data_ptr->GCS_OVERLAY[layer][var+1] & 0x0F) << 8);*G = (cube_data_ptr->GCS_OVERLAY[layer][var+1] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+2] << 4);*B = cube_data_ptr->GCS_OVERLAY[layer][var+3] | ((cube_data_ptr->GCS_OVERLAY[layer][var+4] & 0x0F) << 8);break;case 1:*R = (cube_data_ptr->GCS_OVERLAY[layer][var+4] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+5] << 4);*G = cube_data_ptr->GCS_OVERLAY[layer][var+6] | ((cube_data_ptr->GCS_OVERLAY[layer][var+7] & 0x0F) << 8);*B = (cube_data_ptr->GCS_OVERLAY[layer][var+7] >> 4) | (cube_data_ptr->GCS_OVERLAY[layer][var+8] << 4);break;}}void Cube_Overlay_Move_Pixel(uint8_t layer1, uint8_t row1, uint8_t column1, uint8_t layer2, uint8_t row2, uint8_t column2) {// Copies data from pixel 1 to pixel 2// Note: destination pixel value is overwrittenuint16_t prev_R, prev_G, prev_B;Cube_Overlay_Get_Pixel(layer1, row1, column1, &prev_R, &prev_G, &prev_B);Cube_Overlay_Set_Pixel(layer2, row2, column2, prev_R, prev_G, prev_B);}void Cube_Overlay_Rotate_Shell(uint8_t shell, uint8_t direction) {// Shell is the layer to rotate, with the outermost being 0uint8_t layer;uint16_t origin_R, origin_G, origin_B;;for (layer = 0; layer < CUBE_LAYER_COUNT; layer++) {if (direction) {switch(shell) {case 0:// Rotate outermost layerCube_Overlay_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 0, 1, layer, 0, 0);Cube_Overlay_Move_Pixel(layer, 0, 2, layer, 0, 1);Cube_Overlay_Move_Pixel(layer, 0, 3, layer, 0, 2);Cube_Overlay_Move_Pixel(layer, 0, 4, layer, 0, 3);Cube_Overlay_Move_Pixel(layer, 0, 5, layer, 0, 4);Cube_Overlay_Move_Pixel(layer, 0, 6, layer, 0, 5);Cube_Overlay_Move_Pixel(layer, 0, 7, layer, 0, 6);Cube_Overlay_Move_Pixel(layer, 1, 7, layer, 0, 7);Cube_Overlay_Move_Pixel(layer, 2, 7, layer, 1, 7);Cube_Overlay_Move_Pixel(layer, 3, 7, layer, 2, 7);Cube_Overlay_Move_Pixel(layer, 4, 7, layer, 3, 7);Cube_Overlay_Move_Pixel(layer, 5, 7, layer, 4, 7);Cube_Overlay_Move_Pixel(layer, 6, 7, layer, 5, 7);Cube_Overlay_Move_Pixel(layer, 7, 7, layer, 6, 7);Cube_Overlay_Move_Pixel(layer, 7, 6, layer, 7, 7);Cube_Overlay_Move_Pixel(layer, 7, 5, layer, 7, 6);Cube_Overlay_Move_Pixel(layer, 7, 4, layer, 7, 5);Cube_Overlay_Move_Pixel(layer, 7, 3, layer, 7, 4);Cube_Overlay_Move_Pixel(layer, 7, 2, layer, 7, 3);Cube_Overlay_Move_Pixel(layer, 7, 1, layer, 7, 2);Cube_Overlay_Move_Pixel(layer, 7, 0, layer, 7, 1);Cube_Overlay_Move_Pixel(layer, 6, 0, layer, 7, 0);Cube_Overlay_Move_Pixel(layer, 5, 0, layer, 6, 0);Cube_Overlay_Move_Pixel(layer, 4, 0, layer, 5, 0);Cube_Overlay_Move_Pixel(layer, 3, 0, layer, 4, 0);Cube_Overlay_Move_Pixel(layer, 2, 0, layer, 3, 0);Cube_Overlay_Move_Pixel(layer, 1, 0, layer, 2, 0);Cube_Overlay_Set_Pixel(layer, 1, 0, origin_R, origin_G, origin_B);break;case 1:// Rotate second to outermost layerCube_Overlay_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 1, 2, layer, 1, 1);Cube_Overlay_Move_Pixel(layer, 1, 3, layer, 1, 2);Cube_Overlay_Move_Pixel(layer, 1, 4, layer, 1, 3);Cube_Overlay_Move_Pixel(layer, 1, 5, layer, 1, 4);Cube_Overlay_Move_Pixel(layer, 1, 6, layer, 1, 5);Cube_Overlay_Move_Pixel(layer, 2, 6, layer, 1, 6);Cube_Overlay_Move_Pixel(layer, 3, 6, layer, 2, 6);Cube_Overlay_Move_Pixel(layer, 4, 6, layer, 3, 6);Cube_Overlay_Move_Pixel(layer, 5, 6, layer, 4, 6);Cube_Overlay_Move_Pixel(layer, 6, 6, layer, 5, 6);Cube_Overlay_Move_Pixel(layer, 6, 5, layer, 6, 6);Cube_Overlay_Move_Pixel(layer, 6, 4, layer, 6, 5);Cube_Overlay_Move_Pixel(layer, 6, 3, layer, 6, 4);Cube_Overlay_Move_Pixel(layer, 6, 2, layer, 6, 3);Cube_Overlay_Move_Pixel(layer, 6, 1, layer, 6, 2);Cube_Overlay_Move_Pixel(layer, 5, 1, layer, 6, 1);Cube_Overlay_Move_Pixel(layer, 4, 1, layer, 5, 1);Cube_Overlay_Move_Pixel(layer, 3, 1, layer, 4, 1);Cube_Overlay_Move_Pixel(layer, 2, 1, layer, 3, 1);Cube_Overlay_Set_Pixel(layer, 2, 1, origin_R, origin_G, origin_B);break;case 2:// Rotate second to innermost layerCube_Overlay_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 2, 3, layer, 2, 2);Cube_Overlay_Move_Pixel(layer, 2, 4, layer, 2, 3);Cube_Overlay_Move_Pixel(layer, 2, 5, layer, 2, 4);Cube_Overlay_Move_Pixel(layer, 3, 5, layer, 2, 5);Cube_Overlay_Move_Pixel(layer, 4, 5, layer, 3, 5);Cube_Overlay_Move_Pixel(layer, 5, 5, layer, 4, 5);Cube_Overlay_Move_Pixel(layer, 5, 4, layer, 5, 5);Cube_Overlay_Move_Pixel(layer, 5, 3, layer, 5, 4);Cube_Overlay_Move_Pixel(layer, 5, 2, layer, 5, 3);Cube_Overlay_Move_Pixel(layer, 4, 2, layer, 5, 2);Cube_Overlay_Move_Pixel(layer, 3, 2, layer, 4, 2);Cube_Overlay_Set_Pixel(layer, 3, 2, origin_R, origin_G, origin_B);break;case 3:// Rotate innermost layerCube_Overlay_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 3, 4, layer, 3, 3);Cube_Overlay_Move_Pixel(layer, 4, 4, layer, 3, 4);Cube_Overlay_Move_Pixel(layer, 4, 3, layer, 4, 4);Cube_Overlay_Set_Pixel(layer, 4, 3, origin_R, origin_G, origin_B);break;}} else {switch(shell) {case 0:// Rotate outermost layerCube_Overlay_Get_Pixel(layer, 0, 0, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 1, 0, layer, 0, 0);Cube_Overlay_Move_Pixel(layer, 2, 0, layer, 1, 0);Cube_Overlay_Move_Pixel(layer, 3, 0, layer, 2, 0);Cube_Overlay_Move_Pixel(layer, 4, 0, layer, 3, 0);Cube_Overlay_Move_Pixel(layer, 5, 0, layer, 4, 0);Cube_Overlay_Move_Pixel(layer, 6, 0, layer, 5, 0);Cube_Overlay_Move_Pixel(layer, 7, 0, layer, 6, 0);Cube_Overlay_Move_Pixel(layer, 7, 1, layer, 7, 0);Cube_Overlay_Move_Pixel(layer, 7, 2, layer, 7, 1);Cube_Overlay_Move_Pixel(layer, 7, 3, layer, 7, 2);Cube_Overlay_Move_Pixel(layer, 7, 4, layer, 7, 3);Cube_Overlay_Move_Pixel(layer, 7, 5, layer, 7, 4);Cube_Overlay_Move_Pixel(layer, 7, 6, layer, 7, 5);Cube_Overlay_Move_Pixel(layer, 7, 7, layer, 7, 6);Cube_Overlay_Move_Pixel(layer, 6, 7, layer, 7, 7);Cube_Overlay_Move_Pixel(layer, 5, 7, layer, 6, 7);Cube_Overlay_Move_Pixel(layer, 4, 7, layer, 5, 7);Cube_Overlay_Move_Pixel(layer, 3, 7, layer, 4, 7);Cube_Overlay_Move_Pixel(layer, 2, 7, layer, 3, 7);Cube_Overlay_Move_Pixel(layer, 1, 7, layer, 2, 7);Cube_Overlay_Move_Pixel(layer, 0, 7, layer, 1, 7);Cube_Overlay_Move_Pixel(layer, 0, 6, layer, 0, 7);Cube_Overlay_Move_Pixel(layer, 0, 5, layer, 0, 6);Cube_Overlay_Move_Pixel(layer, 0, 4, layer, 0, 5);Cube_Overlay_Move_Pixel(layer, 0, 3, layer, 0, 4);Cube_Overlay_Move_Pixel(layer, 0, 2, layer, 0, 3);Cube_Overlay_Move_Pixel(layer, 0, 1, layer, 0, 2);Cube_Overlay_Set_Pixel(layer, 0, 1, origin_R, origin_G, origin_B);break;case 1:// Rotate second to outermost layerCube_Overlay_Get_Pixel(layer, 1, 1, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 2, 1, layer, 1, 1);Cube_Overlay_Move_Pixel(layer, 3, 1, layer, 2, 1);Cube_Overlay_Move_Pixel(layer, 4, 1, layer, 3, 1);Cube_Overlay_Move_Pixel(layer, 5, 1, layer, 4, 1);Cube_Overlay_Move_Pixel(layer, 6, 1, layer, 5, 1);Cube_Overlay_Move_Pixel(layer, 6, 2, layer, 6, 1);Cube_Overlay_Move_Pixel(layer, 6, 3, layer, 6, 2);Cube_Overlay_Move_Pixel(layer, 6, 4, layer, 6, 3);Cube_Overlay_Move_Pixel(layer, 6, 5, layer, 6, 4);Cube_Overlay_Move_Pixel(layer, 6, 6, layer, 6, 5);Cube_Overlay_Move_Pixel(layer, 5, 6, layer, 6, 6);Cube_Overlay_Move_Pixel(layer, 4, 6, layer, 5, 6);Cube_Overlay_Move_Pixel(layer, 3, 6, layer, 4, 6);Cube_Overlay_Move_Pixel(layer, 2, 6, layer, 3, 6);Cube_Overlay_Move_Pixel(layer, 1, 6, layer, 2, 6);Cube_Overlay_Move_Pixel(layer, 1, 5, layer, 1, 6);Cube_Overlay_Move_Pixel(layer, 1, 4, layer, 1, 5);Cube_Overlay_Move_Pixel(layer, 1, 3, layer, 1, 4);Cube_Overlay_Move_Pixel(layer, 1, 2, layer, 1, 3);Cube_Overlay_Set_Pixel(layer, 1, 2, origin_R, origin_G, origin_B);break;case 2:// Rotate second to innermost layerCube_Overlay_Get_Pixel(layer, 2, 2, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 3, 2, layer, 2, 2);Cube_Overlay_Move_Pixel(layer, 4, 2, layer, 3, 2);Cube_Overlay_Move_Pixel(layer, 5, 2, layer, 4, 2);Cube_Overlay_Move_Pixel(layer, 5, 3, layer, 5, 2);Cube_Overlay_Move_Pixel(layer, 5, 4, layer, 5, 3);Cube_Overlay_Move_Pixel(layer, 5, 5, layer, 5, 4);Cube_Overlay_Move_Pixel(layer, 4, 5, layer, 5, 5);Cube_Overlay_Move_Pixel(layer, 3, 5, layer, 4, 5);Cube_Overlay_Move_Pixel(layer, 2, 5, layer, 3, 5);Cube_Overlay_Move_Pixel(layer, 2, 4, layer, 2, 5);Cube_Overlay_Move_Pixel(layer, 2, 3, layer, 2, 4);Cube_Overlay_Set_Pixel(layer, 2, 3, origin_R, origin_G, origin_B);break;case 3:// Rotate innermost layerCube_Overlay_Get_Pixel(layer, 3, 3, &origin_R, &origin_G, &origin_B);Cube_Overlay_Move_Pixel(layer, 4, 3, layer, 3, 3);Cube_Overlay_Move_Pixel(layer, 4, 4, layer, 4, 3);Cube_Overlay_Move_Pixel(layer, 3, 4, layer, 4, 4);Cube_Overlay_Set_Pixel(layer, 3, 4, origin_R, origin_G, origin_B);break;}}}}////////////////////////////// Text control functions //////////////////////////////void Cube_Text_Init(uint8_t *string, uint8_t length, uint16_t R, uint16_t G, uint16_t B) {// Ensure that the length of the string does not exceed the storage bufferif (length > CUBE_STRING_MAX_LENGTH) length = CUBE_STRING_MAX_LENGTH;Cube_Overlay_Clear();// Copy the passed data into the bufferuint8_t i;for (i = 0; i < length; i++)cube_data_ptr->string[i] = string[i];cube_data_ptr->string_length = length;cube_data_ptr->string_index = 0;cube_data_ptr->string_line = 0;cube_data_ptr->string_R = R;cube_data_ptr->string_G = G;cube_data_ptr->string_B = B;}void Cube_Text_Update(void) {uint8_t layer;uint16_t line;// Rotate before drawing the new line at (0,0)Cube_Overlay_Rotate_Shell(0, 0);// Get the next vertical line of the character currently being drawnif (cube_data_ptr->string_line == 5) {line = 0x0; // Leave a space between characters} else {line = font[(cube_data_ptr->string[cube_data_ptr->string_index] * 5)+ cube_data_ptr->string_line];}// Draw the line onto (0,0) using the specified colorfor (layer = 8; layer != 0; layer--) {if (line & 0x1) {Cube_Overlay_Set_Pixel(layer-1, 0, 0, cube_data_ptr->string_R,cube_data_ptr->string_G, cube_data_ptr->string_B);} else {Cube_Overlay_Set_Pixel(layer-1, 0, 0, 0x00, 0x00, 0x00);}line >>= 1;}// Increment the vertical line and the character as neededif (cube_data_ptr->string_line == 5) {cube_data_ptr->string_line = 0;if (cube_data_ptr->string_index == cube_data_ptr->string_length-1) {cube_data_ptr->string_index = 0;} else {cube_data_ptr->string_index += 1;}} else {cube_data_ptr->string_line += 1;}}void Cube_Text_Insert(uint8_t c, uint16_t R, uint16_t G, uint16_t B, uint16_t delay) {// Save the character to insertcube_data_ptr->string[0] = c;cube_data_ptr->string_length = 1;cube_data_ptr->string_line = 0;cube_data_ptr->string_R = R;cube_data_ptr->string_G = G;cube_data_ptr->string_B = B;if (delay == 0) {int i;for (i = 0; i < 6; i++) {Cube_Text_Single_Char_Interupt();}} else {// Start a timer to update the overlay with the inserted characterTIMER4_Stop();TIMER4_Init(NULL, NULL, &Cube_Text_Single_Char_Interupt, delay);TIMER4_Start();}}void Cube_Text_Single_Char_Interupt(void) {uint8_t layer;uint8_t line;// Rotate before drawing the new line at (0,0)Cube_Overlay_Rotate_Shell(0, 0);// Get the next vertical line of the character currently being drawnif (cube_data_ptr->string_line == 0) {line = 0x0; // Leave a space between characters} else {line = font[(cube_data_ptr->string[0] * 5) + cube_data_ptr->string_line - 1];}// Draw the line onto (0,0) using the specified colorfor (layer = 8; layer != 0; layer--) {if (line & 0x1) {Cube_Overlay_Set_Pixel(layer-1, 0, 0, cube_data_ptr->string_R,cube_data_ptr->string_G, cube_data_ptr->string_B);} else {Cube_Overlay_Set_Pixel(layer-1, 0, 0, 0x00, 0x00, 0x00);}line >>= 1;}// Increment the vertical line or stop the timer as neededif (cube_data_ptr->string_line == 5) {TIMER4_Stop();} else {cube_data_ptr->string_line += 1;}}void Cube_Text_Interrupt(void) {Cube_Text_Update();}/////////////////////////////////////////////// Functions for processing streaming data ///////////////////////////////////////////////void Cube_Data_In(uint8_t c) {// Reset upon receiving the start int8_tif (c == CUBE_START_CHAR) {cube_data_ptr->frame_length = 0;cube_data_ptr->frame_index = 0;cube_data_ptr->frame_checksum = 0;cube_data_ptr->frame_command = 0;cube_data_ptr->frame_escape = 0;cube_data_ptr->frame_state = READ_LENGTH_MSB;return;}// If the input is the escape int8_t, XOR the next int8_t receivedif (c == CUBE_ESCAPE_CHAR) {cube_data_ptr->frame_escape = 1;return;}// XOR the input int8_t if neededif (cube_data_ptr->frame_escape) {c ^= CUBE_ESCAPE_XOR;cube_data_ptr->frame_escape = 0;}// Process dataswitch (cube_data_ptr->frame_state) {case IDLE:// Reflect the character back to the transmitterUART1_Write(&c, 1);break;case READ_LENGTH_MSB: // Save MSB of lengthcube_data_ptr->frame_length |= (c << 8);cube_data_ptr->frame_state = READ_LENGTH_LSB;break;case READ_LENGTH_LSB: // Save LSB of lengthcube_data_ptr->frame_length |= c;cube_data_ptr->frame_state = READ_COMMAND;break;case READ_COMMAND: // Store the command bytecube_data_ptr->frame_checksum += c;cube_data_ptr->frame_command = c;if (cube_data_ptr->frame_length == 1)cube_data_ptr->frame_state = READ_CHECKSUM;elsecube_data_ptr->frame_state = READ_DATA;break;case READ_DATA: // Read the passed data into the buffercube_data_ptr->frame_checksum += c;cube_data_ptr->frame_buffer[cube_data_ptr->frame_index] = c;cube_data_ptr->frame_index++;if (cube_data_ptr->frame_index == cube_data_ptr->frame_length - 1)cube_data_ptr->frame_state = READ_CHECKSUM;break;case READ_CHECKSUM: // Process frame if checksum is validcube_data_ptr->frame_checksum = 0xFF - cube_data_ptr->frame_checksum;if (cube_data_ptr->frame_checksum == c) {Cube_Data_In_Process_Frame();}cube_data_ptr->frame_state = IDLE;cube_data_ptr->frame_index = 0;cube_data_ptr->frame_length = 0;break;default:break;}}void Cube_Data_In_Process_Frame(void) {// Here we process received frames depending on the commanduint8_t *frame = cube_data_ptr->frame_buffer;switch (cube_data_ptr->frame_command) {case CUBE_COMMAND_SET_BC:TIMER5_Stop();Delay_MS(1); // Need to wait for all SPI writes to completeCube_Write_DCS(frame[0]);TIMER5_Start();break;case CUBE_COMMAND_CLEAR:Cube_Clear();break;case CUBE_COMMAND_SET_PIXEL:Cube_Set_Pixel(frame[0], frame[1], frame[2], frame[3], frame[4], frame[5]);break;case CUBE_COMMAND_SET_ALL:Cube_Data_Direct_Write_All(&frame[0]);break;case CUBE_COMMAND_START_TEXT:Cube_Text_Init(&frame[3], cube_data_ptr->frame_length - 4, frame[0], frame[1], frame[2]);TIMER4_Start();break;case CUBE_COMMAND_STOP_TEXT:TIMER4_Stop();Cube_Overlay_Clear();break;default:break;}}void Cube_Data_Direct_Write_All(uint8_t *buffer) {memcpy(cube_data_ptr->GCS, buffer, CUBE_LAYER_COUNT * GCS_LAYER_SIZE);}void Cube_Ethernet_Frame_In(void) {uint8_t i,j,k;uint8_t buffer[2048] = {0};uint16_t length;// Read and process the ethernet packetif (!ETH_Read_Packet(buffer, &length)) {// Check the opcode (first byte) to determine what to doif (buffer[0] == CUBE_ETH_RESET) { // 0x1 - Reset into Ethernet modeReset_Board(BOARD_MODE_ETHERNET);} else if (Get_Board_State() == BOARD_MODE_ETHERNET) {ClearWDT();if (buffer[0] == CUBE_EHT_IDLE) { // 0x2 - Reset back to idle modeReset_Board(BOARD_MODE_IDLE);} else if (buffer[0] == CUBE_ETH_CLEAR) { // 0xACube_Clear();} else if (buffer[0] == CUBE_ETH_DCS) { // 0xB// Byte 1 = global brightness valueCube_Write_DCS(buffer[1]);} else if (buffer[0] == CUBE_ETH_ROTATE) { // 0xC// Byte 1 = directon to rotateCube_Rotate(buffer[1]);} else if (buffer[0] == CUBE_ETH_ROTATE_LAYER) { // 0xD// Byte 1 = layer to rotate// Byte 2 = direction to rotateCube_Rotate_Shell(buffer[1], buffer[2]);} else if (buffer[0] == CUBE_ETH_WRITE_ALL) { // 0x10// Byte 1+ = pixel color data (R/G/B)if (length == 0x0601) {uint16_t index = 1;for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < CUBE_COLUMN_COUNT; j++) {for (k = 0; k < CUBE_ROW_COUNT; k++) {Cube_Set_Pixel(i, k, j, buffer[index], buffer[index+1], buffer[index+2]);index = index + 3;}}}}} else if (buffer[0] == CUBE_ETH_WRITE_PIXEL) { // 0x11// Byte 1 = row index// Byte 2 = column index// Byte 3 = layer index// Byte 4 = red channel// Byte 5 = green channel// Byte 6 = blue channelCube_Set_Pixel(buffer[3], buffer[1], buffer[2], buffer[4], buffer[5], buffer[6]);} else if (buffer[0] == CUBE_ETH_WRITE_CHANNEL) { // 0x12// Byte 1 = color channel, 0 = red, 1 = green, 2 = blue// Byte 2+ = color datauint16_t r, g, b;uint16_t index = 2;if (buffer[1] % 3 == 0) {for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < CUBE_ROW_COUNT; j++) {for (k = 0; k < CUBE_COLUMN_COUNT; k++) {// Cube_Get_Pixel(i, j, k, &r, &g, &b);Cube_Set_Pixel(i, j, k, buffer[index], 0x00, 0x00);index++;}}}} else if (buffer[1] % 3 == 1) {for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < CUBE_ROW_COUNT; j++) {for (k = 0; k < CUBE_COLUMN_COUNT; k++) {Cube_Get_Pixel(i, j, k, &r, &g, &b);Cube_Set_Pixel(i, j, k, r, buffer[index], b);index++;}}}} else {for (i = 0; i < CUBE_LAYER_COUNT; i++) {for (j = 0; j < CUBE_ROW_COUNT; j++) {for (k = 0; k < CUBE_COLUMN_COUNT; k++) {Cube_Get_Pixel(i, j, k, &r, &g, &b);Cube_Set_Pixel(i, j, k, r, g, buffer[index]);index++;}}}}} else if (buffer[0] == CUBE_ETH_WRITE_TEXT_SCROLL) { // 0x20// Byte 1 = length of string// Byte 2 = red channel// Byte 3 = green channel// Byte 4 = blue channel// Byte 5 = update speed (ms)// Byte 6+ = text stringif (buffer[1] != 0) {TIMER4_Stop();Cube_Text_Init(&buffer[6], buffer[1], buffer[2], buffer[3], buffer[4]);TIMER4_Init(NULL, NULL, &Cube_Text_Interrupt, buffer[5]);TIMER4_Start();} else {TIMER4_Stop();Cube_Overlay_Clear();}} else if (buffer[0] == CUBE_ETH_WRITE_TEXT_STATIC) { // 0x21// Byte 1 = length of string// Byte 2 = red channel// Byte 3 = green channel// Byte 4 = blue channel// Byte 5+ = text stringif (buffer[1] != 0) {TIMER4_Stop();Cube_Text_Init(&buffer[5], buffer[1], buffer[2], buffer[3], buffer[4]);for (i = 0; i < buffer[1] * 5; i++) {Cube_Text_Update();}} else {TIMER4_Stop();Cube_Overlay_Clear();}} else if (buffer[0] == CUBE_EHT_WRITE_TEXT_INSERT) { // 0x22// Byte 1 = red channel// Byte 2 = green channel// Byte 3 = blue channel// Byte 4 = delay x6 between shifts// Byte 5 = characterTIMER4_Stop();Cube_Text_Insert(buffer[5], buffer[1], buffer[2], buffer[3], buffer[4]);} else if (buffer[0] == CUBE_ETH_WATERFALL) { // 0x30// Byte 1 = height of column 0// Byte 2 = height of column 1// Byte 3 = height of column 2// Byte 4 = height of column 3// Byte 5 = height of column 4// Byte 6 = height of column 5// Byte 7 = height of column 6// Byte 8 = height of column 7Cube_Shift_Waterfall(&buffer[1]);} else if (buffer[0] == CUBE_ETH_SPHERE) { // 0x31// Byte 1 = layer (0 = innermost)// Byte 2 = red channel// Byte 3 = green channel// Byte 4 = blue channelCube_Set_Sphere(buffer[1], buffer[2], buffer[3], buffer[4]);}}}}