0,0 → 1,190 |
#include <xc.h> |
#include <plib.h> |
#include "defines.h" |
#include "CUBE.h" |
#include "SPI1.h" |
|
static CUBE_DATA *cube_data_ptr; |
static unsigned char current_layer; |
|
inline void Cube_Delay() { |
// Small delay to ensure that latch speeds are < 30Mhz |
Nop(); |
Nop(); |
Nop(); |
} |
|
void Cube_Init(CUBE_DATA *data) { |
cube_data_ptr = data; |
current_layer = 0; |
|
SFT_D = 0; |
SFT_S = 0; |
SFT_K = 0; |
SFT_R = 0; |
GSLAT = 0; |
XBLNK = 0; |
|
SFT_D_TRIS = 0; |
SFT_S_TRIS = 0; |
SFT_K_TRIS = 0; |
SFT_R_TRIS = 0; |
GSLAT_TRIS = 0; |
XBLNK_TRIS = 0; |
|
// Clear the shift register |
Cube_Delay(); |
SFT_K = 1; |
Cube_Delay(); |
SFT_K = 0; |
Cube_Delay(); |
SFT_S = 1; |
Cube_Delay(); |
SFT_S = 0; |
Cube_Delay(); |
SFT_R = 1; |
|
int i,j; |
// Write configuration data to the DC/BC/FC/UD registers |
unsigned char DCS[GCS_LAYER_SIZE] = {0}; |
for (i = 0; i < 8; i++) { |
int offset = i * GCS_REG_SIZE; |
|
for (j = 0; j < 21; j++) { |
DCS[offset + j] = 0xFF; // Dot correction |
} |
|
// Warning: do not set BC > 0x8F |
DCS[offset + 21] = 0x1F; // Global red brightness |
DCS[offset + 22] = 0x1F; // Global green brightness |
DCS[offset + 23] = 0x1F; // Global blue brightness |
|
// DC low range, auto repeat, no timing reset, 8 bit counter mode |
DCS[offset + 24] = 0x68; // 0110 1000 |
} |
|
Cube_Clear(); |
|
GSLAT = 1; |
SPI1_Write(DCS, GCS_LAYER_SIZE, &Cube_DCS_Write_Callback); |
Delay_MS(8); // Delay until the entire DCS write is finished |
} |
|
void Cube_Timer_Interrupt(void) { |
// Write to the GCS register |
SPI1_Write(cube_data_ptr->GCS[current_layer], GCS_LAYER_SIZE, &Cube_GCS_Write_Callback); |
} |
|
void Cube_DCS_Write_Callback(void) { |
// GSLAT must be >7ms after DCS write |
Delay_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 GCS |
XBLNK = 0; |
Cube_Delay(); |
GSLAT = 1; |
// Set the shift register to turn on the current layer |
int i; |
for (i = 0; i < CUBE_LAYER_COUNT; i++) { |
Cube_Delay(); |
SFT_D = (i == CUBE_LAYER_COUNT - 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 output |
XBLNK = 1; |
Cube_Delay(); |
GSLAT = 0; |
|
current_layer = (current_layer == CUBE_LAYER_COUNT-1) ? 0 : current_layer + 1; |
} |
|
void Cube_Clear(void) { |
int i,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(int R, int G, int B) { |
R &= 0x0FFF; |
G &= 0x0FFF; |
B &= 0x0FFF; |
int i,j,k; |
for (i = 0; i < CUBE_LAYER_COUNT; i++) { |
for (j = 0; j < CUBE_ROW_COUNT; j++) { |
int j_var = j * GCS_REG_SIZE; |
for (k = 0; k < 4; k++) { |
int 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(int layer, int R, int G, int B) { |
R &= 0x0FFF; |
G &= 0x0FFF; |
B &= 0x0FFF; |
int i,j; |
for (i = 0; i < CUBE_ROW_COUNT; i++) { |
int i_var = i * GCS_REG_SIZE; |
for (j = 0; j < 4; j++) { |
int 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_Pixel(int layer, int row, int column, int R, int G, int B) { |
R &= 0x0FFF; |
G &= 0x0FFF; |
B &= 0x0FFF; |
int 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; |
} |
} |