Blame | Last modification | View Log | RSS feed
#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;
}
}