Subversion Repositories Code-Repo

Compare Revisions

Problem with comparison.

Ignore whitespace Rev HEAD → Rev 263

/PIC Stuff/Cerebot_32MX7_LED_Cube/CUBE.c
0,0 → 1,886
#include "defines.h"
#include "CUBE.h"
#include "SPI1.h"
#include "glcdfont.h"
#include "UART1.h"
#include "ETHERNET.h"
 
static CUBE_DATA *cube_data_ptr;
 
inline void Cube_Delay() {
// Small delay to ensure that latch speeds are < 30Mhz
Nop();
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;
 
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;
 
Cube_Write_DCS(BC);
Cube_Clear();
Cube_Overlay_Clear();
}
 
void Cube_Timer_Interrupt(void) {
// OR values in the overlay array with the display array
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_WRITE[i][j] = cube_data_ptr->GCS[i][j] | cube_data_ptr->GCS_OVERLAY[i][j];
}
}
// Write to the GCS register
SPI1_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 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
uint8_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 output
XBLNK = 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 registers
uint8_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 brightness
DCS[offset + 22] = BC; // Global green brightness
DCS[offset + 23] = BC; // Global blue brightness
 
// DC low range, auto repeat, no timing reset, 8 bit counter mode
DCS[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 color
R &= 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 color
R &= 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_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 color
R &= 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 channel
case 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 overwritten
uint16_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_Rotate_Shell(uint8_t shell, uint8_t direction) {
// Shell is the layer to rotate, with the outermost being 0
uint8_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_Rotate_Shell(0, direction);
// Rotate second to outermost layer
if ((cube_data_ptr->rotation_counter != 1) && (cube_data_ptr->rotation_counter != 5)) {
Cube_Rotate_Shell(1, direction);
}
// Rotate second to innermost layer
if ((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 layer
if ((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;
}
}
 
///////////////////////////////
// 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 color
R &= 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 channel
case 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 overwritten
uint16_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 0
uint8_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 layer
Cube_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 buffer
if (length > CUBE_STRING_MAX_LENGTH) length = CUBE_STRING_MAX_LENGTH;
 
Cube_Overlay_Clear();
 
// Copy the passed data into the buffer
uint8_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_Interrupt(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 int8_tacter currently being drawn
if (cube_data_ptr->string_line == 5) {
line = 0x0; // Leave a space between int8_tacters
} 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 color
for (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 int8_tacter as needed
if (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;
}
}
 
/////////////////////////////////////////////
// Functions for processing streaming data //
/////////////////////////////////////////////
 
void Cube_Data_In(uint8_t c) {
// Reset upon receiving the start int8_t
if (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 received
if (c == CUBE_ESCAPE_CHAR) {
cube_data_ptr->frame_escape = 1;
return;
}
// XOR the input int8_t if needed
if (cube_data_ptr->frame_escape) {
c ^= CUBE_ESCAPE_XOR;
cube_data_ptr->frame_escape = 0;
}
// Process data
switch (cube_data_ptr->frame_state) {
case IDLE:
// Reflect the int8_tacter back to the transmitter
UART1_Write(&c, 1);
break;
case READ_LENGTH_MSB: // Save MSB of length
cube_data_ptr->frame_length |= (c << 8);
cube_data_ptr->frame_state = READ_LENGTH_LSB;
break;
case READ_LENGTH_LSB: // Save LSB of length
cube_data_ptr->frame_length |= c;
cube_data_ptr->frame_state = READ_COMMAND;
break;
case READ_COMMAND: // Store the command byte
cube_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;
else
cube_data_ptr->frame_state = READ_DATA;
break;
case READ_DATA: // Read the passed data into the buffer
cube_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 valid
cube_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 command
uint8_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 complete
Cube_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;
uint16_t index = 1;
 
// Read and process the ethernet packet
if (!ETH_Read_Packet(buffer, &length)) {
// Check the opcode (first byte) to determine what to do
 
if (buffer[0] == 0x1) { // 0x1 - Reset into Ethernet mode
Reset_Board(BOARD_MODE_ETHERNET);
} else if (buffer[0] == 0x2) { // 0x2 - Reset back to idle mode
Reset_Board(BOARD_MODE_IDLE);
} else if (buffer[0] == 0xA) { // 0xA - Clear the entire cube
Cube_Clear();
} else if (buffer[0] == 0xB) { // 0xB - Set the global brightness value
Cube_Write_DCS(buffer[1]);
} else if (buffer[0] == 0xC) { // 0xC - Set the entire cube
if (length == 0x0601) {
ClearWDT();
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] == 0xD) { // 0xD - Rotate the cube
Cube_Rotate(buffer[1]);
} else if (buffer[0] == 0xE) { // 0xE - Rotate a layer
Cube_Rotate_Shell(buffer[1], buffer[2]);
}
}
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/CUBE.h
0,0 → 1,130
#ifndef CUBE_H
#define CUBE_H
 
// Cube Parameters
#define CUBE_ROW_COUNT 8
#define CUBE_COLUMN_COUNT 8
#define CUBE_LAYER_COUNT 8
#define CUBE_PIXELS 512
#define CUBE_ROTATIONS 7
 
#define GCS_REG_SIZE 36
#define GCS_LAYER_SIZE (GCS_REG_SIZE*CUBE_ROW_COUNT)
 
// Color Definitions
#define RED 0x08F,0x000,0x000
#define ORANGE 0x08F,0x020,0x000
#define YELLOW 0x08F,0x08F,0x000
#define GREEN 0x000,0x08F,0x000
#define TEAL 0x000,0x08F,0x08F
#define BLUE 0x000,0x000,0x08F
#define PURPLE 0x08F,0x000,0x08F
#define WHITE 0x0FF,0x0FF,0x0FF
 
// Control Pin Declarations
#define SFT_D_TRIS TRISBbits.TRISB15
#define SFT_S_TRIS TRISDbits.TRISD5
#define SFT_K_TRIS TRISDbits.TRISD4
#define SFT_R_TRIS TRISBbits.TRISB14
 
#define SFT_D PORTBbits.RB15
#define SFT_S PORTDbits.RD5
#define SFT_K PORTDbits.RD4
#define SFT_R PORTBbits.RB14
 
#define GSLAT_TRIS TRISDbits.TRISD9
#define XBLNK_TRIS TRISDbits.TRISD2
 
#define GSLAT PORTDbits.RD9
#define XBLNK PORTDbits.RD2
 
// String Overlay Buffer Size
#define CUBE_STRING_MAX_LENGTH 32
 
// Data Streaming In Buffer Size
#define CUBE_FRAME_BUFFER_SIZE 3000
#define CUBE_START_CHAR 0x7E
#define CUBE_ESCAPE_CHAR 0x7D
#define CUBE_ESCAPE_XOR 0x20
 
// Data Streaming In Command Set
#define CUBE_COMMAND_SET_BC 0x0A // [Brightness Value]
#define CUBE_COMMAND_CLEAR 0x0B // (no data)
#define CUBE_COMMAND_SET_PIXEL 0x10 // [Layer, Row, Column, R, G, B]
#define CUBE_COMMAND_SET_ALL 0x11 // [R1, G1, B1, R2, ...]
#define CUBE_COMMAND_START_TEXT 0x20 // [R, G, B, Char1, Char2, Char3, ...]
#define CUBE_COMMAND_STOP_TEXT 0x21 // (no data)
 
typedef enum {
IDLE,
READ_LENGTH_MSB,
READ_LENGTH_LSB,
READ_COMMAND,
READ_DATA,
READ_CHECKSUM
} PROCESS_STATE;
 
typedef struct {
// Variables for base cube
uint8_t GCS[CUBE_LAYER_COUNT][GCS_LAYER_SIZE];
uint8_t GCS_OVERLAY[CUBE_LAYER_COUNT][GCS_LAYER_SIZE];
uint8_t GCS_WRITE[CUBE_LAYER_COUNT][GCS_LAYER_SIZE];
uint8_t current_layer;
uint8_t rotation_counter;
 
// Variables for the scrolling text
uint8_t string[CUBE_STRING_MAX_LENGTH];
uint8_t string_length;
uint8_t string_index;
uint8_t string_line;
uint16_t string_R, string_G, string_B;
 
// Variables for input frame data
PROCESS_STATE frame_state;
uint8_t frame_buffer[CUBE_FRAME_BUFFER_SIZE];
uint8_t frame_checksum;
uint32_t frame_length;
uint32_t frame_index;
uint32_t frame_command;
uint32_t frame_escape;
} CUBE_DATA;
 
void Cube_Init(CUBE_DATA *data, uint8_t BC);
void Cube_Timer_Interrupt(void);
 
// Callbacks on completion of DCS/GCS writes
void Cube_DCS_Write_Callback(void);
void Cube_GCS_Write_Callback(void);
 
// Cube control functions
void Cube_Write_DCS(uint8_t BC);
void Cube_Clear(void);
void Cube_Set_All(uint16_t R, uint16_t G, uint16_t B);
void Cube_Set_Layer(uint8_t layer, uint16_t R, uint16_t G, uint16_t B);
void Cube_Set_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t R, uint16_t G, uint16_t B);
void Cube_Get_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t* R, uint16_t* G, uint16_t* B);
void Cube_Move_Pixel(uint8_t layer1, uint8_t row1, uint8_t column1, uint8_t layer2, uint8_t row2, uint8_t column2);
void Cube_Rotate_Shell(uint8_t shell, uint8_t direction);
void Cube_Rotate(uint8_t direction);
 
// Overlay control functions
void Cube_Overlay_Clear(void);
void Cube_Overlay_Set_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t R, uint16_t G, uint16_t B);
void Cube_Overlay_Get_Pixel(uint8_t layer, uint8_t row, uint8_t column, uint16_t* R, uint16_t* G, uint16_t* B);
void Cube_Overlay_Move_Pixel(uint8_t layer1, uint8_t row1, uint8_t column1, uint8_t layer2, uint8_t row2, uint8_t column2);
void Cube_Overlay_Rotate_Shell(uint8_t shell, uint8_t direction);
 
// Text control functions
void Cube_Text_Init(uint8_t *string, uint8_t length, uint16_t R, uint16_t G, uint16_t B);
void Cube_Text_Interrupt(void);
 
// Data stream in control functions
// UART functions
void Cube_Data_In(uint8_t c);
void Cube_Data_In_Process_Frame(void);
void Cube_Data_Direct_Write_All(uint8_t *buffer);
// Ethernet functions
void Cube_Ethernet_Frame_In(void);
 
#endif /* CUBE_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/ETHERNET.c
0,0 → 1,352
#include "defines.h"
#include "ETHERNET.h"
 
static ETH_DATA *eth_data;
 
/* Function to convert from virtual address to physical address
See 3.4.1 in reference manual for explanation */
uint32_t VA_TO_PA(uint32_t ptr) {
uint32_t ret = ptr & 0x1FFFFFFF;
return ret;
}
 
void ETH_Init(ETH_DATA *data, void(*tx_callback)(void), void(*rx_callback)(void)) {
// Save a pointer to the descriptor tables
eth_data = data;
eth_data->tx_callback = tx_callback;
eth_data->rx_callback = rx_callback;
 
// Bring the PHY reset line high to initialize the PHY
PHY_RESET_TRIS = 0;
PHY_RESET_LAT = 0;
Delay_US(100);
PHY_RESET_LAT = 1;
 
INTDisableInterrupts();
 
// Initialize the I/O lines (dont actually need this)
ETH_MDC_TRIS = 0;
ETH_MDIO_TRIS = 1;
ETH_TXEN_TRIS = 0;
ETH_TXD0_TRIS = 0;
ETH_TXD1_TRIS = 0;
ETH_RXCLK_TRIS = 1;
ETH_RXDV_TRIS = 1;
ETH_RXD0_TRIS = 1;
ETH_RXD1_TRIS = 1;
ETH_RXERR_TRIS = 1;
 
eth_data->TX_descriptor_index = 0;
eth_data->RX_descriptor_index = 0;
 
// Initialize values in the descriptor tables
uint8_t i;
for (i = 0; i < ETH_TX_DESCRIPTOR_COUNT; i++) {
// Set the NPV values for each descriptor (linear list)
eth_data->TX_ED_table.descriptor[i].NPV = 0;
// Set the EOWN values for each descriptor
eth_data->TX_ED_table.descriptor[i].EOWN = 0;
 
// Assign a data buffer to each descriptor
eth_data->TX_ED_table.descriptor[i].BUFFER_ADDR = VA_TO_PA((uint32_t)eth_data->TX_ED_buffer[i]);
}
for (i = 0; i < ETH_RX_DESCRIPTOR_COUNT; i++) {
// Set the NPV values for each descriptor (linear list)
eth_data->RX_ED_table.descriptor[i].NPV = 0;
 
// Set the EOWN values for each descriptor
eth_data->RX_ED_table.descriptor[i].EOWN = 1;
 
// Assign a data buffer to each descriptor
eth_data->RX_ED_table.descriptor[i].BUFFER_ADDR = VA_TO_PA((uint32_t)eth_data->RX_ED_buffer[i]);
}
 
// On the last descriptor, save the address to the beginning of the list
eth_data->TX_ED_table.descriptor[ETH_TX_DESCRIPTOR_COUNT-1].NPV = 1;
eth_data->RX_ED_table.descriptor[ETH_RX_DESCRIPTOR_COUNT-1].NPV = 1;
 
// Set the last RX descriptor EOWN to software, thus using list configuration
// eth_data->TX_ED_table.descriptor[ETH_TX_DESCRIPTOR_COUNT-1].EOWN = 0;
// eth_data->RX_ED_table.descriptor[ETH_RX_DESCRIPTOR_COUNT-1].EOWN = 0;
 
// Loop the end of the descriptor table to the beginning (ring configuration)
eth_data->TX_ED_table.next_ED = VA_TO_PA((uint32_t)eth_data->TX_ED_table.descriptor);
eth_data->RX_ED_table.next_ED = VA_TO_PA((uint32_t)eth_data->RX_ED_table.descriptor);
 
// Save the head of the table to the corresponding ETH register
ETHTXST = VA_TO_PA((uint32_t)eth_data->TX_ED_table.descriptor);
ETHRXST = VA_TO_PA((uint32_t)eth_data->RX_ED_table.descriptor);
 
// Ethernet Initialization Sequence: see section 35.4.10 in the PIC32 Family Reference Manual
// Part 1. Ethernet Controller Initialization
IEC1bits.ETHIE = 0; // Disable ethernet interrupts
ETHCON1bits.ON = 0; // Disable the ethernet module
ETHCON1bits.TXRTS = 0; // Stop transmit logic
ETHCON1bits.RXEN = 0; // Stop receive logic
ETHCON1bits.AUTOFC = 0;
ETHCON1bits.MANFC = 0;
while (ETHSTATbits.ETHBUSY);
IFS1bits.ETHIF = 0; // Clear interrupt flags
ETHIENCLR = 0xFFFF; // Clear the ETHIEN register (interrupt enable)
 
// Part 2. MAC Init
EMAC1CFG1bits.SOFTRESET = 1; // Put the MACMII in reset
EMAC1CFG1bits.SOFTRESET = 0;
// Default I/O configuration, RMII operating mode
EMAC1SUPPbits.RESETRMII = 1; // Reset the MAC RMII module
EMAC1MCFGbits.RESETMGMT = 1; // Reset the MII management module
EMAC1MCFGbits.RESETMGMT = 0;
EMAC1MCFGbits.CLKSEL = 0x8; // Set the MIIM PHY clock to SYSCLK/40
while(EMAC1MINDbits.MIIMBUSY);
 
// Part 3. PHY Init
// Contrary to the ref manual, the ETH module needs to be enabled for the MIIM to work
 
ETHCON1bits.ON = 1; // Enable the ethernet module
uint16_t value;
// Reset the PHY chip
ETH_PHY_Write(PHY_ADDRESS, 0x0, 0x8000);
do {
value = ETH_PHY_Read(PHY_ADDRESS, 0x0);
} while (value & 0x8000 != 0);
 
// Delay to wait for the link to be established
// Something needs to be done about this. 5s is WAY too long to wait
Delay_MS(5000);
// Wait for auto-negotiation to finish
do {
value = ETH_PHY_Read(PHY_ADDRESS, 0x1F); // Acquire link status
} while (value & 0x1000 == 0);
 
ETHCON1bits.ON = 0; // Disable the ethernet module before changing other settings
// Part 4. MAC Configuration
EMAC1CFG1bits.RXENABLE = 1; // Enable the MAC receiving of frames
EMAC1CFG1bits.TXPAUSE = 1; // Enable PAUSE flow control frames
EMAC1CFG1bits.RXPAUSE = 1; // Enable processing of PAUSE control frames
EMAC1CFG2bits.AUTOPAD = 0; // No auto-detection for VLAN padding
EMAC1CFG2bits.VLANPAD = 0; // MAC does not perform padding of short frames
EMAC1CFG2bits.PADENABLE = 1; // Pad all short frames
EMAC1CFG2bits.CRCENABLE = 1; // Append a CRC to every frame
EMAC1CFG2bits.HUGEFRM = 1; // Allow frames of any length
EMAC1CFG2bits.LENGTHCK = 0; // Check the frame lengths to the length/type field
if ((value & 0x14) || (value & 0x18)) {
EMAC1CFG2bits.FULLDPLX = 1; // Operate in full-duplex mode
EMAC1IPGT = 0x15; // Back-to-back interpacket gap @ 0.96us/9.6us
// LED1_LAT = 1;
} else {
EMAC1CFG2bits.FULLDPLX = 0; // Operate in half-duplex mode
EMAC1IPGT = 0x12; // Back-to-back interpacket gap @ 0.96us/9.6us
// LED2_LAT = 1;
}
if ((value & 0x08) || (value & 0x18)) {
EMAC1SUPPbits.SPEEDRMII = 1; // 100Mbps mode
// LED3_LAT = 1;
} else {
EMAC1SUPPbits.SPEEDRMII = 0; // 10Mbps mode
// LED4_LAT = 1;
}
EMAC1IPGRbits.NB2BIPKTGP1 = 0xC; // Set some other delay gap values
EMAC1IPGRbits.NB2BIPKTGP2 = 0x12;
EMAC1CLRTbits.CWINDOW = 0x37; // Set collision window to count of frame bytes
EMAC1CLRTbits.RETX = 0xF; // Set number of retransmission attempts
EMAC1MAXF = 0x7F4; // Set the maximum frame length to 2046 bits
// Default MAC address is 00-04-A3-1A-4C-FC
// Set MAC address to 00-18-3E-00-D7-EB
EMAC1SA0 = 0xEBD7;
EMAC1SA1 = 0x003E;
EMAC1SA2 = 0x1800;
 
// Part 5. Ethernet Controller Initialization cont.
// Flow control is off by default!
ETHRXFCbits.HTEN = 0; // Disable hash table filtering
ETHRXFCbits.MPEN = 0; // Disable magic packet filtering
ETHRXFCbits.PMMODE = 0; // Disable pattern matching
ETHRXFCbits.CRCERREN = 0; // Disable CRC error collection filtering
ETHRXFCbits.CRCOKEN = 0; // Disable CRC filtering
ETHRXFCbits.RUNTERREN = 0; // Disable runt error collection filtering
ETHRXFCbits.RUNTEN = 0; // Disable runt filtering
ETHRXFCbits.UCEN = 1; // Enable unicast filtering
ETHRXFCbits.NOTMEEN = 0; // Disable acceptance of packets to other destinations
ETHRXFCbits.MCEN = 0; // Disable multicast filtering
ETHRXFCbits.BCEN = 0; // Disable broadcast filtering
 
ETHCON2bits.RXBUF_SZ = 0x7F; // Set RX data buffer size to 2032 bytes
 
ETHIENbits.TXBUSEIE = 1; // Enable interrupt on transmit BVCI bus error
ETHIENbits.RXBUSEIE = 1; // Enable interrupt on receive BVCI bus error
ETHIENbits.RXDONEIE = 1; // Enable interrupt on packet received
// ETHIENbits.PKTPENDIE = 1; // Enable interrupt on packet pending
// ETHIENbits.RXACTIE = 1;
ETHIENbits.TXDONEIE = 1; // Enable interrupt on packet sent
ETHIENbits.TXABORTIE = 1; // Enable interrupt on packet send aborted
 
IPC12bits.ETHIP = 1; // Set interrupt priority to 2
IPC12bits.ETHIS = 1; // Set intererupt sub-priority to 2
IEC1bits.ETHIE = 1; // Enable ethernet interrupts
 
EMAC1SUPPbits.RESETRMII = 0; // Bring the RMII module out of reset
ETHCON1bits.RXEN = 1; // Start receive logic
ETHCON1bits.ON = 1; // Enable the ethernet module
 
INTEnableInterrupts();
}
 
/* Reads from the specified register on the PHY chip */
uint16_t ETH_PHY_Read(uint8_t address, uint8_t reg) {
EMAC1MADR = reg | (address << 8);
EMAC1MCMDbits.READ = 1;
Nop();Nop();Nop();
while (EMAC1MINDbits.MIIMBUSY);
EMAC1MCMDbits.READ = 0;
return EMAC1MRDD;
}
 
/* Write to the specified register on the PHY chip */
void ETH_PHY_Write(uint8_t address, uint8_t reg, uint16_t value) {
EMAC1MADR = reg | (address << 8);
EMAC1MWTD = value;
Nop();Nop();Nop();
while (EMAC1MINDbits.MIIMBUSY);
}
 
/* Queries the number of pending packets */
uint8_t ETH_Recv_Queue(void) {
return ETHSTATbits.BUFCNT;
}
 
/* Function to read a single packet (<2014 bytes) */
uint8_t ETH_Read_Packet(uint8_t *buffer, uint16_t *length) {
uint16_t i, j;
uint16_t size;
uint8_t descriptor_index = eth_data->RX_descriptor_index;
 
// Look for the first descriptor where EOWN is cleared and SOP/EOP is set
for (i = 0; i < ETH_RX_DESCRIPTOR_COUNT; i++) {
if ((eth_data->RX_ED_table.descriptor[descriptor_index].EOWN == 0) &&
(eth_data->RX_ED_table.descriptor[descriptor_index].SOP == 1) &&
(eth_data->RX_ED_table.descriptor[descriptor_index].EOP == 1)) {
 
// Read the packet data values into the buffer
size = eth_data->RX_ED_table.descriptor[descriptor_index].BYTE_COUNT - 18;
for (j = 0; j < size; j++) {
buffer[j] = eth_data->RX_ED_buffer[descriptor_index][j+14];
}
*length = size;
 
// Reset the descriptors
eth_data->RX_ED_table.descriptor[descriptor_index].SOP = 0;
eth_data->RX_ED_table.descriptor[descriptor_index].EOP = 0;
eth_data->RX_ED_table.descriptor[descriptor_index].EOWN = 1;
 
eth_data->RX_descriptor_index = (descriptor_index == ETH_RX_DESCRIPTOR_COUNT - 1) ? 0 : descriptor_index + 1;
 
ETHCON1bits.BUFCDEC = 1;
return 0;
 
} else {
descriptor_index = (descriptor_index == ETH_RX_DESCRIPTOR_COUNT - 1) ? 0 : descriptor_index + 1;
}
}
 
return 1;
}
 
/* Function to send a single packet (<2018 bytes) */
uint8_t ETH_Write_Packet(ETH_MAC_ADDRESS dest, ETH_MAC_ADDRESS src, uint16_t length, uint8_t *buffer) {
uint16_t i;
uint16_t write_index = 0;
uint16_t read_index = 0;
uint16_t descriptor_index = eth_data->TX_descriptor_index;
 
// Do a quick sanity check to ensure that we have enough memory to send the message
if (length > ETH_TX_ED_BUFFER_SIZE - 14)
return 1;
 
// Fill the descriptor
eth_data->TX_ED_table.descriptor[descriptor_index].TSV.registers[0] = 0;
eth_data->TX_ED_table.descriptor[descriptor_index].TSV.registers[1] = 0;
eth_data->TX_ED_table.descriptor[descriptor_index].EOWN = 1;
eth_data->TX_ED_table.descriptor[descriptor_index].SOP = 1;
eth_data->TX_ED_table.descriptor[descriptor_index].EOP = 1;
 
for (i = 0; i < 6; i++) {
eth_data->TX_ED_buffer[descriptor_index][write_index] = dest.bytes[i];
write_index++;
}
for (i = 0; i < 6; i++) {
eth_data->TX_ED_buffer[descriptor_index][write_index] = src.bytes[i];
write_index++;
}
eth_data->TX_ED_buffer[descriptor_index][write_index] = length >> 8;
eth_data->TX_ED_buffer[descriptor_index][write_index+1] = length;
write_index += 2;
 
 
eth_data->TX_ED_table.descriptor[descriptor_index].BYTE_COUNT = length + 14;
 
for (i = 0; i < length; i++) {
eth_data->TX_ED_buffer[descriptor_index][write_index] = buffer[read_index];
write_index++;
read_index++;
}
 
// Wait for any previous transmits to finish before sending
while (ETHSTATbits.TXBUSY);
ETHCON1bits.TXRTS = 1;
while (ETHSTATbits.TXBUSY);
 
eth_data->TX_descriptor_index = (descriptor_index == ETH_TX_DESCRIPTOR_COUNT - 1) ? 0 : descriptor_index + 1;
return 0;
}
 
void __ISR(_ETH_VECTOR, ipl1) __ETH_Interrupt_Handler(void) {
// uint32_t value = ETHIRQ;
if (ETHIRQbits.TXBUSE) {
// TX bus error, something -should- be done
ETHIRQbits.TXBUSE = 0;
}
if (ETHIRQbits.RXBUSE) {
// RX bus error, something -should- be done
ETHIRQbits.RXBUSE = 0;
}
if (ETHIRQbits.RXDONE) {
// Call the previously saved function
if (eth_data->rx_callback != NULL)
(*eth_data->rx_callback)();
ETHIRQbits.RXDONE = 0;
}
// if (ETHIRQbits.PKTPEND) {
//
// ETHIRQbits.PKTPEND = 0;
// }
if (ETHIRQbits.TXDONE) {
// Call the previously saved function
if (eth_data->tx_callback != NULL)
(*eth_data->tx_callback)();
ETHIRQbits.TXDONE = 0;
}
if (ETHIRQbits.TXABORT) {
// TX aborted, do we care?
ETHIRQbits.TXABORT = 0;
}
if (ETHIRQbits.RXBUFNA) {
// This is a serious error!
// TODO: handle this
ETHIRQbits.RXBUFNA = 0;
}
if (ETHIRQbits.RXOVFLW) {
// This is a serious error!
// TODO: handle this
ETHIRQbits.RXOVFLW = 0;
}
 
IFS1bits.ETHIF = 0;
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/main.c
0,0 → 1,364
// <editor-fold defaultstate="collapsed" desc="Configuration Bits">
/* ------------------------------------------------------------ */
/* PIC32 Configuration Settings */
/* ------------------------------------------------------------ */
/* Oscillator Settings */
#pragma config FNOSC = PRIPLL // Oscillator Selection Bits
#pragma config POSCMOD = EC // Primary Oscillator Configuration
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider
#pragma config FPLLMUL = MUL_20 // PLL Multiplier
#pragma config FPLLODIV = DIV_1 // PLL Output Divider
#pragma config FPBDIV = DIV_1 // Peripheral Clock Divisor (timers/UART/SPI/I2C)
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable
/* Clock Control Settings */
#pragma config IESO = OFF // Internal/External Clock Switch Over
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin
/* USB Settings */
#pragma config UPLLEN = ON // USB PLL Enable
#pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider
#pragma config FVBUSONIO = OFF // USB VBUS ON Selection
#pragma config FUSBIDIO = OFF // USB USID Selection
/* Other Peripheral Device Settings */
#pragma config FWDTEN = OFF // Watchdog Timer Enable
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1048.576s)
#pragma config FSRSSEL = PRIORITY_7 // SRS Interrupt Priority
#pragma config FCANIO = OFF // CAN I/O Pin Select (default/alternate)
#pragma config FETHIO = ON // Ethernet I/O Pin Select (default/alternate)
#pragma config FMIIEN = OFF // Ethernet MII/RMII select (OFF=RMII)
/* Code Protection Settings */
#pragma config CP = OFF // Code Protect
#pragma config BWP = OFF // Boot Flash Write Protect
#pragma config PWP = OFF // Program Flash Write Protect
/* Debug Settings */
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (on-board debugger)
/* ------------------------------------------------------------ */
// </editor-fold>
 
#include "defines.h"
#include "UART1.h"
#include "SPI1.h"
#include "SPI4.h"
#include "I2C1.h"
#include "ETHERNET.h"
#include "TIMER4.h"
#include "TIMER5.h"
#include "CUBE.h"
#include "BTN.h"
#include "ANIMATIONS.h"
#include "CONTROLLERS.h"
#include "SNAKE.h"
#include "TRON.h"
 
void BTN1_Interrupt(void);
void BTN2_Interrupt(void);
void BTN3_Interrupt(void);
 
void Delay_MS(uint32_t delay_ms) {
// Delays the CPU for the given amount of time.
// Note: Watch out for integer overflow! (max delay_ms = 107374) ??
uint32_t delay = delay_ms * MS_TO_CT_TICKS;
uint32_t startTime = ReadCoreTimer();
while ((uint32_t)(ReadCoreTimer() - startTime) < delay) {};
}
 
void Delay_US(uint32_t delay_us) {
// Delays the CPU for the given amount of time.
// Note: Watch out for integer overflow!
uint32_t delay = delay_us * US_TO_CT_TICKS;
uint32_t startTime = ReadCoreTimer();
while ((uint32_t)(ReadCoreTimer() - startTime) < delay) {};
}
 
uint8_t Get_Reset_Condition(void) {
uint8_t ret = 0;
if (RCONbits.POR && RCONbits.BOR)
ret = RESET_POR;
else if (RCONbits.BOR)
ret = RESET_BOR;
else if (RCONbits.EXTR)
ret = RESET_PIN;
else if (RCONbits.SWR)
ret = RESET_SWR;
else if (RCONbits.CMR)
ret = RESET_CFG;
else if (RCONbits.WDTO)
ret = RESET_WDT;
// Clear the RCON register
RCON = 0x0;
return ret;
}
 
// Initialize a persistent operational state machine
volatile static uint8_t op_state __attribute__((persistent));
 
uint8_t Get_Board_State(void) {
return op_state;
}
 
void Reset_Board(uint8_t next_state) {
op_state = next_state;
// Executes a software reset
INTDisableInterrupts();
SYSKEY = 0x00000000; // Write invalid key to force lock
SYSKEY = 0xAA996655; // Write key1 to SYSKEY
SYSKEY = 0x556699AA; // Write key2 to SYSKEY
/* OSCCON is now unlocked */
// Set SWRST bit to arm reset
RSWRSTSET = 1;
// Read RSWRST register to trigger reset
uint32_t dummy;
dummy = RSWRST;
// Prevent any unwanted code execution until reset occurs
while(1);
}
 
void main() {
// WARNING!! THIS BOARD WILL RESET EVERY 1048.576s DUE TO THE WDT!!
 
/* -------------------- BEGIN INITIALIZATION --------------------- */
// Configure the target for maximum performance at 80 MHz.
// Note: This overrides the peripheral clock to 80Mhz regardless of config
SYSTEMConfigPerformance(CPU_CLOCK_HZ);
 
// Configure the interrupts for multiple vectors
INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
 
// Set all analog I/O pins to digital
AD1PCFGSET = 0xFFFF;
 
// Enable the watchdog timer with windowed mode disabled
// WDT prescaler set to 1048576 (1048.576s) (see config bits)
WDTCON = 0x00008000;
 
// Configure onboard LEDs
LED1_TRIS = 0;
LED2_TRIS = 0;
LED3_TRIS = 0;
LED4_TRIS = 0;
LED1_LAT = 0;
LED2_LAT = 0;
LED3_LAT = 0;
LED4_LAT = 0;
 
// Determine what to do at this point. We either choose to idle (on POR)
// or go into a mode specified prior to the software reset event
uint8_t last_reset = Get_Reset_Condition();
if (last_reset == RESET_POR || last_reset == RESET_BOR ||
last_reset == RESET_PIN || last_reset == RESET_WDT ||
last_reset == RESET_CFG) {
op_state = BOARD_MODE_IDLE;
}
 
// Initialize the SPI1 module
SPI1_DATA spi_1_data;
SPI1_Init(&spi_1_data, NULL);
 
// Initialize the SPI4 module
SPI4_DATA spi_4_data;
SPI4_Init(&spi_4_data);
 
// Initialize the I2C1 module
I2C1_DATA i2c_1_data;
I2C1_Init(&i2c_1_data, I2C1_400KHZ, 0x20);
 
// // Initialize the UART1 module
// UART1_DATA uart_data;
// UART1_Init(&uart_data, &Cube_Data_In);
 
// Initializs the PWM2 output to 20MHz
PWM2_Init();
 
// Initialize the cube variables
CUBE_DATA cube_data;
Cube_Init(&cube_data, 0x40);
 
// Start the cube update layer interrupt
// 2083 = 60Hz, 500 = 250Hz, 250 = 500Hz
TIMER5_DATA timer_5_data;
TIMER5_Init(&timer_5_data, &Cube_Timer_Interrupt, 500);
 
// Start the controller polling and overlay rotation interrupt
TIMER4_DATA timer_4_data;
TIMER4_Init(&timer_4_data, &Controller_Update, NULL, 0);
 
// Process button inputs
BTN_DATA btn_data;
BTN_Init(&btn_data, &BTN1_Interrupt, &BTN2_Interrupt, NULL);
 
// Initialize controllers
CONTROLLER_DATA ctrl_data;
Controller_Init(&ctrl_data, NULL);
 
// Initialize the Ethernet module
ETH_DATA eth_data;
ETH_Init(&eth_data, NULL, &Cube_Ethernet_Frame_In);
SNAKE_DATA snake_data;
TRON_DATA tron_data;
 
PWM2_Start();
TIMER5_Start();
TIMER4_Start();
/* -------------------- END OF INITIALIZATION -------------------- */
/* ------------------------ BEGIN DISPLAY ------------------------ */
 
// Figure out what state to go into here
switch (op_state) {
case BOARD_MODE_IDLE:
Idle_Animation_Sequence();
break;
case BOARD_MODE_SNAKE:;
Controller_Init(&ctrl_data, &Snake_Update_Direction);
Snake_Init(&snake_data);
Snake_Main();
break;
case BOARD_MODE_TRON:
Controller_Init(&ctrl_data, &Tron_Update_Direction);
Tron_Init(&tron_data);
Tron_Main();
break;
case BOARD_MODE_ETHERNET:
TIMER4_Stop();
while(1);
break;
}
 
}
 
void Idle_Animation_Sequence(void) {
Delay_MS(250);
 
// Cube_Set_All(RED);
// Delay_MS(2000);
// Cube_Set_All(GREEN);
// Delay_MS(2000);
// Cube_Set_All(BLUE);
// Delay_MS(2000);
// Animation_Pseudo_Random_Colors(200);
// Animation_Pseudo_Random_Colors(200);
// Animation_Pseudo_Random_Colors(200);
// Animation_Pseudo_Random_Colors(200);
// Animation_Pseudo_Random_Colors(200);
// Animation_Pseudo_Random_Colors(200);
 
// Start the scrolling text
TIMER4_Stop();
TIMER4_Init(NULL, &Controller_Update, &Cube_Text_Interrupt, 100);
// TIMER4_Start();
 
// int8_t start_text[] = "Cube Initialized\r\n";
// UART1_Write(start_text, 18);
 
// Set the overlay text
uint8_t text_string[] = "Welcome to the CCM Lab ";
Cube_Text_Init(text_string, 27, 0xFF, 0xFF, 0xFF);
 
// Loop through some preset animations
while(1) {
// Animation_Solid_Colors(300);
// Animation_Layer_Alternate(300);
// Animation_Pixel_Alternate(200);
// Animation_Full_Color_Sweep(1000);
Animation_Row_Column_Sweep(40);
Animation_Row_Column_Sweep(40);
Animation_Row_Column_Sweep(40);
Animation_Cube_In_Cube(300);
Animation_Cube_In_Cube(300);
Animation_Cube_In_Cube(300);
Animation_Double_Rotation(40);
Animation_Double_Rotation(40);
Animation_Double_Rotation(40);
// Animation_Pseudo_Random_Colors(300);
// Animation_Random_Colors(300);
 
// ClearWDT(); // Clear the WDT if we dont want the board to reset
}
}
 
// Function call on button 1 press to change refresh rate
void BTN1_Interrupt(void) {
static uint8_t state;
state = (state == 4) ? 0 : state + 1;
TIMER5_Stop();
switch (state) {
case 0:
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 500); // 250Hz
break;
case 1:
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 2083); // 60Hz
break;
case 2:
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 4166); // 30Hz
break;
case 3:
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 12498); // 10Hz
break;
case 4:
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 24996); // 5Hz
break;
}
TIMER5_Start();
}
 
// Function call on button 2 press to change brightness
void BTN2_Interrupt(void) {
static uint8_t state;
state = (state == 6) ? 0 : state + 1;
TIMER5_Stop();
Delay_MS(1); // Need to wait for all SPI writes to complete
uint8_t BC;
switch (state) {
case 0:
BC = 0x01;
break;
case 1:
BC = 0x08;
break;
case 2:
BC = 0x10;
break;
case 3:
BC = 0x20;
break;
case 4:
BC = 0x40;
break;
case 5:
BC = 0x80;
break;
case 6:
BC = 0xFF;
break;
}
Cube_Write_DCS(BC);
TIMER5_Start();
}
 
//// Function call on button 3 press to change text scroll speed
//void BTN3_Interrupt(void) {
// static uint8_t state;
// state = (state == 4) ? 0 : state + 1;
// TIMER4_Stop();
// switch (state) {
// case 0:
// TIMER4_Init(NULL, &Cube_Text_Interrupt, 209712);
// break;
// case 1:
// TIMER4_Init(NULL, &Cube_Text_Interrupt, 180000);
// break;
// case 2:
// TIMER4_Init(NULL, &Cube_Text_Interrupt, 150000);
// break;
// case 3:
// TIMER4_Init(NULL, &Cube_Text_Interrupt, 120000);
// break;
// case 4:
// TIMER4_Init(NULL, &Cube_Text_Interrupt, 90000);
// break;
// }
// TIMER4_Start();
//}
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/Makefile-genesis.properties
0,0 → 1,8
#
#Wed Jan 29 14:42:18 EST 2014
default.com-microchip-mplab-nbide-toolchainXC32-XC32LanguageToolchain.md5=83f4565fa27ad9b8015f63d69ef74f66
default.languagetoolchain.dir=C\:\\Program Files (x86)\\Microchip\\xc32\\v1.31\\bin
com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=1f98a0eed69cb2a45c12981fa9470927
default.languagetoolchain.version=1.31
host.platform=windows
conf.ids=default
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/configurations.xml
0,0 → 1,207
<?xml version="1.0" encoding="UTF-8"?>
<configurationDescriptor version="62">
<logicalFolder name="root" displayName="root" projectFiles="true">
<logicalFolder name="HeaderFiles"
displayName="Header Files"
projectFiles="true">
<itemPath>defines.h</itemPath>
<itemPath>SPI1.h</itemPath>
<itemPath>TIMER5.h</itemPath>
<itemPath>CUBE.h</itemPath>
<itemPath>BTN.h</itemPath>
<itemPath>PWM2.h</itemPath>
<itemPath>TIMER4.h</itemPath>
<itemPath>glcdfont.h</itemPath>
<itemPath>UART1.h</itemPath>
<itemPath>SPI4.h</itemPath>
<itemPath>ANIMATIONS.h</itemPath>
<itemPath>I2C1.h</itemPath>
<itemPath>CONTROLLERS.h</itemPath>
<itemPath>SNAKE.h</itemPath>
<itemPath>TRON.h</itemPath>
<itemPath>ETHERNET.h</itemPath>
</logicalFolder>
<logicalFolder name="LinkerScript"
displayName="Linker Files"
projectFiles="true">
</logicalFolder>
<logicalFolder name="SourceFiles"
displayName="Source Files"
projectFiles="true">
<itemPath>main.c</itemPath>
<itemPath>SPI1.c</itemPath>
<itemPath>TIMER5.c</itemPath>
<itemPath>CUBE.c</itemPath>
<itemPath>PWM2.c</itemPath>
<itemPath>BTN.c</itemPath>
<itemPath>TIMER4.c</itemPath>
<itemPath>UART1.c</itemPath>
<itemPath>SPI4.c</itemPath>
<itemPath>ANIMATIONS.c</itemPath>
<itemPath>I2C1.c</itemPath>
<itemPath>CONTROLLERS.c</itemPath>
<itemPath>SNAKE.c</itemPath>
<itemPath>TRON.c</itemPath>
<itemPath>ETHERNET.c</itemPath>
</logicalFolder>
<logicalFolder name="ExternalFiles"
displayName="Important Files"
projectFiles="false">
<itemPath>Makefile</itemPath>
<itemPath>README.txt</itemPath>
</logicalFolder>
</logicalFolder>
<projectmakefile>Makefile</projectmakefile>
<confs>
<conf name="default" type="2">
<toolsSet>
<developmentServer>localhost</developmentServer>
<targetDevice>PIC32MX795F512L</targetDevice>
<targetHeader></targetHeader>
<targetPluginBoard></targetPluginBoard>
<platformTool>PK3OBPlatformTool</platformTool>
<languageToolchain>XC32</languageToolchain>
<languageToolchainVersion>1.31</languageToolchainVersion>
<platform>3</platform>
</toolsSet>
<compileType>
<linkerTool>
<linkerLibItems>
</linkerLibItems>
</linkerTool>
<loading>
<useAlternateLoadableFile>false</useAlternateLoadableFile>
<alternateLoadableFile></alternateLoadableFile>
</loading>
</compileType>
<makeCustomizationType>
<makeCustomizationPreStepEnabled>false</makeCustomizationPreStepEnabled>
<makeCustomizationPreStep></makeCustomizationPreStep>
<makeCustomizationPostStepEnabled>false</makeCustomizationPostStepEnabled>
<makeCustomizationPostStep></makeCustomizationPostStep>
<makeCustomizationPutChecksumInUserID>false</makeCustomizationPutChecksumInUserID>
<makeCustomizationEnableLongLines>false</makeCustomizationEnableLongLines>
<makeCustomizationNormalizeHexFile>false</makeCustomizationNormalizeHexFile>
</makeCustomizationType>
<C32>
<property key="additional-warnings" value="false"/>
<property key="enable-app-io" value="false"/>
<property key="enable-omit-frame-pointer" value="false"/>
<property key="enable-symbols" value="true"/>
<property key="enable-unroll-loops" value="true"/>
<property key="exclude-floating-point" value="false"/>
<property key="extra-include-directories" value=""/>
<property key="generate-16-bit-code" value="false"/>
<property key="generate-micro-compressed-code" value="false"/>
<property key="isolate-each-function" value="false"/>
<property key="make-warnings-into-errors" value="false"/>
<property key="optimization-level" value="-O1"/>
<property key="place-data-into-section" value="false"/>
<property key="post-instruction-scheduling" value="default"/>
<property key="pre-instruction-scheduling" value="default"/>
<property key="preprocessor-macros" value=""/>
<property key="strict-ansi" value="false"/>
<property key="support-ansi" value="false"/>
<property key="use-cci" value="false"/>
<property key="use-iar" value="false"/>
<property key="use-indirect-calls" value="false"/>
</C32>
<C32-AS>
<property key="assembler-symbols" value=""/>
<property key="enable-symbols" value="true"/>
<property key="exclude-floating-point-library" value="false"/>
<property key="expand-macros" value="false"/>
<property key="extra-include-directories-for-assembler" value=""/>
<property key="extra-include-directories-for-preprocessor" value=""/>
<property key="false-conditionals" value="false"/>
<property key="keep-locals" value="false"/>
<property key="list-assembly" value="false"/>
<property key="list-source" value="false"/>
<property key="list-symbols" value="false"/>
<property key="oXC32asm-list-to-file" value="false"/>
<property key="omit-debug-dirs" value="false"/>
<property key="omit-forms" value="false"/>
<property key="preprocessor-macros" value=""/>
<property key="warning-level" value=""/>
</C32-AS>
<C32-LD>
<property key="additional-options-use-response-files" value="false"/>
<property key="enable-check-sections" value="false"/>
<property key="exclude-floating-point-library" value="false"/>
<property key="exclude-standard-libraries" value="false"/>
<property key="extra-lib-directories" value=""/>
<property key="generate-16-bit-code" value="false"/>
<property key="generate-cross-reference-file" value="false"/>
<property key="generate-micro-compressed-code" value="false"/>
<property key="heap-size" value=""/>
<property key="input-libraries" value=""/>
<property key="linker-symbols" value=""/>
<property key="map-file" value=""/>
<property key="no-startup-files" value="false"/>
<property key="oXC32ld-extra-opts" value=""/>
<property key="optimization-level" value=""/>
<property key="preprocessor-macros" value=""/>
<property key="remove-unused-sections" value="false"/>
<property key="report-memory-usage" value="true"/>
<property key="stack-size" value=""/>
<property key="symbol-stripping" value=""/>
<property key="trace-symbols" value=""/>
<property key="warn-section-align" value="false"/>
</C32-LD>
<C32CPP>
<property key="additional-warnings" value="false"/>
<property key="check-new" value="false"/>
<property key="eh-specs" value="true"/>
<property key="enable-app-io" value="false"/>
<property key="enable-omit-frame-pointer" value="false"/>
<property key="enable-symbols" value="true"/>
<property key="enable-unroll-loops" value="true"/>
<property key="exceptions" value="true"/>
<property key="exclude-floating-point" value="false"/>
<property key="extra-include-directories" value=""/>
<property key="generate-16-bit-code" value="false"/>
<property key="generate-micro-compressed-code" value="false"/>
<property key="isolate-each-function" value="false"/>
<property key="make-warnings-into-errors" value="false"/>
<property key="optimization-level" value="-O1"/>
<property key="place-data-into-section" value="false"/>
<property key="post-instruction-scheduling" value="default"/>
<property key="pre-instruction-scheduling" value="default"/>
<property key="preprocessor-macros" value=""/>
<property key="rtti" value="true"/>
<property key="strict-ansi" value="false"/>
<property key="use-cci" value="false"/>
<property key="use-iar" value="false"/>
<property key="use-indirect-calls" value="false"/>
</C32CPP>
<C32Global>
<property key="legacy-libc" value="false"/>
<property key="save-temps" value="false"/>
<property key="wpo-lto" value="false"/>
</C32Global>
<PK3OBPlatformTool>
<property key="AutoSelectMemRanges" value="auto"/>
<property key="SecureSegment.SegmentProgramming" value="FullChipProgramming"/>
<property key="ToolFirmwareFilePath"
value="Press to browse for a specific firmware version"/>
<property key="ToolFirmwareOption.UseLatestFirmware" value="true"/>
<property key="memories.bootflash" value="false"/>
<property key="memories.configurationmemory" value="false"/>
<property key="memories.eeprom" value="false"/>
<property key="memories.id" value="false"/>
<property key="memories.programmemory" value="true"/>
<property key="memories.programmemory.end" value="0x1d07ffff"/>
<property key="memories.programmemory.start" value="0x1d000000"/>
<property key="poweroptions.powerenable" value="false"/>
<property key="programoptions.eraseb4program" value="true"/>
<property key="programoptions.preserveeeprom" value="false"/>
<property key="programoptions.preserveprogramrange" value="false"/>
<property key="programoptions.preserveprogramrange.end" value="0x1d0001ff"/>
<property key="programoptions.preserveprogramrange.start" value="0x1d000000"/>
<property key="programoptions.usehighvoltageonmclr" value="false"/>
<property key="programoptions.uselvpprogramming" value="false"/>
<property key="voltagevalue" value="3.25"/>
</PK3OBPlatformTool>
</conf>
</confs>
</configurationDescriptor>
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/private/configurations.xml
0,0 → 1,25
<?xml version="1.0" encoding="UTF-8"?>
<configurationDescriptor version="62">
<projectmakefile>Makefile</projectmakefile>
<defaultConf>0</defaultConf>
<confs>
<conf name="default" type="2">
<platformToolSN>:=MPLABComm-USB-Microchip:=&lt;vid>04D8:=&lt;pid>8108:=&lt;rev>0002:=&lt;man>Digilent:=&lt;prod>Cerebot 32MX7:=&lt;sn>D370400:=&lt;drv>x:=&lt;xpt>h:=end</platformToolSN>
<languageToolchainDir>C:\Program Files (x86)\Microchip\xc32\v1.31\bin</languageToolchainDir>
<mdbdebugger version="1">
<placeholder1>place holder 1</placeholder1>
<placeholder2>place holder 2</placeholder2>
</mdbdebugger>
<runprofile version="6">
<args></args>
<rundir></rundir>
<buildfirst>true</buildfirst>
<console-type>0</console-type>
<terminal-type>0</terminal-type>
<remove-instrumentation>0</remove-instrumentation>
<environment>
</environment>
</runprofile>
</conf>
</confs>
</configurationDescriptor>
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/private/private.xml
0,0 → 1,3
<?xml version="1.0" encoding="UTF-8"?><project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
</project-private>
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/private/private.properties
--- nbproject/Makefile-default.mk (nonexistent)
+++ nbproject/Makefile-default.mk (revision 263)
@@ -0,0 +1,316 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Include project Makefile
+ifeq "${IGNORE_LOCAL}" "TRUE"
+# do not include local makefile. User is passing all local related variables already
+else
+include Makefile
+# Include makefile containing local settings
+ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk"
+include nbproject/Makefile-local-default.mk
+endif
+endif
+
+# Environment
+MKDIR=gnumkdir -p
+RM=rm -f
+MV=mv
+CP=cp
+
+# Macros
+CND_CONF=default
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+IMAGE_TYPE=debug
+OUTPUT_SUFFIX=elf
+DEBUGGABLE_SUFFIX=elf
+FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+else
+IMAGE_TYPE=production
+OUTPUT_SUFFIX=hex
+DEBUGGABLE_SUFFIX=elf
+FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+endif
+
+# Object Directory
+OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE}
+
+# Distribution Directory
+DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE}
+
+# Source Files Quoted if spaced
+SOURCEFILES_QUOTED_IF_SPACED=main.c SPI1.c TIMER5.c CUBE.c PWM2.c BTN.c TIMER4.c UART1.c SPI4.c ANIMATIONS.c I2C1.c CONTROLLERS.c SNAKE.c TRON.c ETHERNET.c
+
+# Object Files Quoted if spaced
+OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/main.o ${OBJECTDIR}/SPI1.o ${OBJECTDIR}/TIMER5.o ${OBJECTDIR}/CUBE.o ${OBJECTDIR}/PWM2.o ${OBJECTDIR}/BTN.o ${OBJECTDIR}/TIMER4.o ${OBJECTDIR}/UART1.o ${OBJECTDIR}/SPI4.o ${OBJECTDIR}/ANIMATIONS.o ${OBJECTDIR}/I2C1.o ${OBJECTDIR}/CONTROLLERS.o ${OBJECTDIR}/SNAKE.o ${OBJECTDIR}/TRON.o ${OBJECTDIR}/ETHERNET.o
+POSSIBLE_DEPFILES=${OBJECTDIR}/main.o.d ${OBJECTDIR}/SPI1.o.d ${OBJECTDIR}/TIMER5.o.d ${OBJECTDIR}/CUBE.o.d ${OBJECTDIR}/PWM2.o.d ${OBJECTDIR}/BTN.o.d ${OBJECTDIR}/TIMER4.o.d ${OBJECTDIR}/UART1.o.d ${OBJECTDIR}/SPI4.o.d ${OBJECTDIR}/ANIMATIONS.o.d ${OBJECTDIR}/I2C1.o.d ${OBJECTDIR}/CONTROLLERS.o.d ${OBJECTDIR}/SNAKE.o.d ${OBJECTDIR}/TRON.o.d ${OBJECTDIR}/ETHERNET.o.d
+
+# Object Files
+OBJECTFILES=${OBJECTDIR}/main.o ${OBJECTDIR}/SPI1.o ${OBJECTDIR}/TIMER5.o ${OBJECTDIR}/CUBE.o ${OBJECTDIR}/PWM2.o ${OBJECTDIR}/BTN.o ${OBJECTDIR}/TIMER4.o ${OBJECTDIR}/UART1.o ${OBJECTDIR}/SPI4.o ${OBJECTDIR}/ANIMATIONS.o ${OBJECTDIR}/I2C1.o ${OBJECTDIR}/CONTROLLERS.o ${OBJECTDIR}/SNAKE.o ${OBJECTDIR}/TRON.o ${OBJECTDIR}/ETHERNET.o
+
+# Source Files
+SOURCEFILES=main.c SPI1.c TIMER5.c CUBE.c PWM2.c BTN.c TIMER4.c UART1.c SPI4.c ANIMATIONS.c I2C1.c CONTROLLERS.c SNAKE.c TRON.c ETHERNET.c
+
+
+CFLAGS=
+ASFLAGS=
+LDLIBSOPTIONS=
+
+############# Tool locations ##########################################
+# If you copy a project from one host to another, the path where the #
+# compiler is installed may be different. #
+# If you open this project with MPLAB X in the new host, this #
+# makefile will be regenerated and the paths will be corrected. #
+#######################################################################
+# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build
+FIXDEPS=fixDeps
+
+.build-conf: ${BUILD_SUBPROJECTS}
+ ${MAKE} ${MAKE_OPTIONS} -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+
+MP_PROCESSOR_OPTION=32MX795F512L
+MP_LINKER_FILE_OPTION=
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: assemble
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+else
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: assembleWithPreprocess
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+else
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: compile
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+${OBJECTDIR}/main.o: main.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/main.o.d
+ @${RM} ${OBJECTDIR}/main.o
+ @${FIXDEPS} "${OBJECTDIR}/main.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/main.o.d" -o ${OBJECTDIR}/main.o main.c
+
+${OBJECTDIR}/SPI1.o: SPI1.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/SPI1.o.d
+ @${RM} ${OBJECTDIR}/SPI1.o
+ @${FIXDEPS} "${OBJECTDIR}/SPI1.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/SPI1.o.d" -o ${OBJECTDIR}/SPI1.o SPI1.c
+
+${OBJECTDIR}/TIMER5.o: TIMER5.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/TIMER5.o.d
+ @${RM} ${OBJECTDIR}/TIMER5.o
+ @${FIXDEPS} "${OBJECTDIR}/TIMER5.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/TIMER5.o.d" -o ${OBJECTDIR}/TIMER5.o TIMER5.c
+
+${OBJECTDIR}/CUBE.o: CUBE.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/CUBE.o.d
+ @${RM} ${OBJECTDIR}/CUBE.o
+ @${FIXDEPS} "${OBJECTDIR}/CUBE.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/CUBE.o.d" -o ${OBJECTDIR}/CUBE.o CUBE.c
+
+${OBJECTDIR}/PWM2.o: PWM2.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/PWM2.o.d
+ @${RM} ${OBJECTDIR}/PWM2.o
+ @${FIXDEPS} "${OBJECTDIR}/PWM2.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/PWM2.o.d" -o ${OBJECTDIR}/PWM2.o PWM2.c
+
+${OBJECTDIR}/BTN.o: BTN.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/BTN.o.d
+ @${RM} ${OBJECTDIR}/BTN.o
+ @${FIXDEPS} "${OBJECTDIR}/BTN.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/BTN.o.d" -o ${OBJECTDIR}/BTN.o BTN.c
+
+${OBJECTDIR}/TIMER4.o: TIMER4.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/TIMER4.o.d
+ @${RM} ${OBJECTDIR}/TIMER4.o
+ @${FIXDEPS} "${OBJECTDIR}/TIMER4.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/TIMER4.o.d" -o ${OBJECTDIR}/TIMER4.o TIMER4.c
+
+${OBJECTDIR}/UART1.o: UART1.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/UART1.o.d
+ @${RM} ${OBJECTDIR}/UART1.o
+ @${FIXDEPS} "${OBJECTDIR}/UART1.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/UART1.o.d" -o ${OBJECTDIR}/UART1.o UART1.c
+
+${OBJECTDIR}/SPI4.o: SPI4.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/SPI4.o.d
+ @${RM} ${OBJECTDIR}/SPI4.o
+ @${FIXDEPS} "${OBJECTDIR}/SPI4.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/SPI4.o.d" -o ${OBJECTDIR}/SPI4.o SPI4.c
+
+${OBJECTDIR}/ANIMATIONS.o: ANIMATIONS.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/ANIMATIONS.o.d
+ @${RM} ${OBJECTDIR}/ANIMATIONS.o
+ @${FIXDEPS} "${OBJECTDIR}/ANIMATIONS.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/ANIMATIONS.o.d" -o ${OBJECTDIR}/ANIMATIONS.o ANIMATIONS.c
+
+${OBJECTDIR}/I2C1.o: I2C1.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/I2C1.o.d
+ @${RM} ${OBJECTDIR}/I2C1.o
+ @${FIXDEPS} "${OBJECTDIR}/I2C1.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/I2C1.o.d" -o ${OBJECTDIR}/I2C1.o I2C1.c
+
+${OBJECTDIR}/CONTROLLERS.o: CONTROLLERS.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/CONTROLLERS.o.d
+ @${RM} ${OBJECTDIR}/CONTROLLERS.o
+ @${FIXDEPS} "${OBJECTDIR}/CONTROLLERS.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/CONTROLLERS.o.d" -o ${OBJECTDIR}/CONTROLLERS.o CONTROLLERS.c
+
+${OBJECTDIR}/SNAKE.o: SNAKE.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/SNAKE.o.d
+ @${RM} ${OBJECTDIR}/SNAKE.o
+ @${FIXDEPS} "${OBJECTDIR}/SNAKE.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/SNAKE.o.d" -o ${OBJECTDIR}/SNAKE.o SNAKE.c
+
+${OBJECTDIR}/TRON.o: TRON.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/TRON.o.d
+ @${RM} ${OBJECTDIR}/TRON.o
+ @${FIXDEPS} "${OBJECTDIR}/TRON.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/TRON.o.d" -o ${OBJECTDIR}/TRON.o TRON.c
+
+${OBJECTDIR}/ETHERNET.o: ETHERNET.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/ETHERNET.o.d
+ @${RM} ${OBJECTDIR}/ETHERNET.o
+ @${FIXDEPS} "${OBJECTDIR}/ETHERNET.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -fframe-base-loclist -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/ETHERNET.o.d" -o ${OBJECTDIR}/ETHERNET.o ETHERNET.c
+
+else
+${OBJECTDIR}/main.o: main.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/main.o.d
+ @${RM} ${OBJECTDIR}/main.o
+ @${FIXDEPS} "${OBJECTDIR}/main.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/main.o.d" -o ${OBJECTDIR}/main.o main.c
+
+${OBJECTDIR}/SPI1.o: SPI1.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/SPI1.o.d
+ @${RM} ${OBJECTDIR}/SPI1.o
+ @${FIXDEPS} "${OBJECTDIR}/SPI1.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/SPI1.o.d" -o ${OBJECTDIR}/SPI1.o SPI1.c
+
+${OBJECTDIR}/TIMER5.o: TIMER5.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/TIMER5.o.d
+ @${RM} ${OBJECTDIR}/TIMER5.o
+ @${FIXDEPS} "${OBJECTDIR}/TIMER5.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/TIMER5.o.d" -o ${OBJECTDIR}/TIMER5.o TIMER5.c
+
+${OBJECTDIR}/CUBE.o: CUBE.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/CUBE.o.d
+ @${RM} ${OBJECTDIR}/CUBE.o
+ @${FIXDEPS} "${OBJECTDIR}/CUBE.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/CUBE.o.d" -o ${OBJECTDIR}/CUBE.o CUBE.c
+
+${OBJECTDIR}/PWM2.o: PWM2.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/PWM2.o.d
+ @${RM} ${OBJECTDIR}/PWM2.o
+ @${FIXDEPS} "${OBJECTDIR}/PWM2.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/PWM2.o.d" -o ${OBJECTDIR}/PWM2.o PWM2.c
+
+${OBJECTDIR}/BTN.o: BTN.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/BTN.o.d
+ @${RM} ${OBJECTDIR}/BTN.o
+ @${FIXDEPS} "${OBJECTDIR}/BTN.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/BTN.o.d" -o ${OBJECTDIR}/BTN.o BTN.c
+
+${OBJECTDIR}/TIMER4.o: TIMER4.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/TIMER4.o.d
+ @${RM} ${OBJECTDIR}/TIMER4.o
+ @${FIXDEPS} "${OBJECTDIR}/TIMER4.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/TIMER4.o.d" -o ${OBJECTDIR}/TIMER4.o TIMER4.c
+
+${OBJECTDIR}/UART1.o: UART1.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/UART1.o.d
+ @${RM} ${OBJECTDIR}/UART1.o
+ @${FIXDEPS} "${OBJECTDIR}/UART1.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/UART1.o.d" -o ${OBJECTDIR}/UART1.o UART1.c
+
+${OBJECTDIR}/SPI4.o: SPI4.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/SPI4.o.d
+ @${RM} ${OBJECTDIR}/SPI4.o
+ @${FIXDEPS} "${OBJECTDIR}/SPI4.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/SPI4.o.d" -o ${OBJECTDIR}/SPI4.o SPI4.c
+
+${OBJECTDIR}/ANIMATIONS.o: ANIMATIONS.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/ANIMATIONS.o.d
+ @${RM} ${OBJECTDIR}/ANIMATIONS.o
+ @${FIXDEPS} "${OBJECTDIR}/ANIMATIONS.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/ANIMATIONS.o.d" -o ${OBJECTDIR}/ANIMATIONS.o ANIMATIONS.c
+
+${OBJECTDIR}/I2C1.o: I2C1.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/I2C1.o.d
+ @${RM} ${OBJECTDIR}/I2C1.o
+ @${FIXDEPS} "${OBJECTDIR}/I2C1.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/I2C1.o.d" -o ${OBJECTDIR}/I2C1.o I2C1.c
+
+${OBJECTDIR}/CONTROLLERS.o: CONTROLLERS.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/CONTROLLERS.o.d
+ @${RM} ${OBJECTDIR}/CONTROLLERS.o
+ @${FIXDEPS} "${OBJECTDIR}/CONTROLLERS.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/CONTROLLERS.o.d" -o ${OBJECTDIR}/CONTROLLERS.o CONTROLLERS.c
+
+${OBJECTDIR}/SNAKE.o: SNAKE.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/SNAKE.o.d
+ @${RM} ${OBJECTDIR}/SNAKE.o
+ @${FIXDEPS} "${OBJECTDIR}/SNAKE.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/SNAKE.o.d" -o ${OBJECTDIR}/SNAKE.o SNAKE.c
+
+${OBJECTDIR}/TRON.o: TRON.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/TRON.o.d
+ @${RM} ${OBJECTDIR}/TRON.o
+ @${FIXDEPS} "${OBJECTDIR}/TRON.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/TRON.o.d" -o ${OBJECTDIR}/TRON.o TRON.c
+
+${OBJECTDIR}/ETHERNET.o: ETHERNET.c nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} ${OBJECTDIR}
+ @${RM} ${OBJECTDIR}/ETHERNET.o.d
+ @${RM} ${OBJECTDIR}/ETHERNET.o
+ @${FIXDEPS} "${OBJECTDIR}/ETHERNET.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ -c ${MP_CC} $(MP_EXTRA_CC_PRE) -g -x c -c -mprocessor=$(MP_PROCESSOR_OPTION) -O1 -funroll-loops -MMD -MF "${OBJECTDIR}/ETHERNET.o.d" -o ${OBJECTDIR}/ETHERNET.o ETHERNET.c
+
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: compileCPP
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+else
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: link
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE}
+ ${MP_CC} $(MP_EXTRA_LD_PRE) -mdebugger -D__MPLAB_DEBUGGER_PK3=1 -mprocessor=$(MP_PROCESSOR_OPTION) -o dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} -mreserve=data@0x0:0x1FC -mreserve=boot@0x1FC02000:0x1FC02FEF -mreserve=boot@0x1FC02000:0x1FC024FF -Wl,--defsym=__MPLAB_BUILD=1$(MP_EXTRA_LD_POST)$(MP_LINKER_FILE_OPTION),--defsym=__MPLAB_DEBUG=1,--defsym=__DEBUG=1,--defsym=__MPLAB_DEBUGGER_PK3=1,--report-mem
+
+else
+dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk
+ @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE}
+ ${MP_CC} $(MP_EXTRA_LD_PRE) -mprocessor=$(MP_PROCESSOR_OPTION) -o dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} -Wl,--defsym=__MPLAB_BUILD=1$(MP_EXTRA_LD_POST)$(MP_LINKER_FILE_OPTION),--report-mem
+ ${MP_CC_DIR}\\xc32-bin2hex dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}
+endif
+
+
+# Subprojects
+.build-subprojects:
+
+
+# Subprojects
+.clean-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+ ${RM} -r build/default
+ ${RM} -r dist/default
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+DEPFILES=$(shell mplabwildcard ${POSSIBLE_DEPFILES})
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/Makefile-local-default.mk
0,0 → 1,37
#
# Generated Makefile - do not edit!
#
#
# This file contains information about the location of compilers and other tools.
# If you commmit this file into your revision control server, you will be able to
# to checkout the project and build it from the command line with make. However,
# if more than one person works on the same project, then this file might show
# conflicts since different users are bound to have compilers in different places.
# In that case you might choose to not commit this file and let MPLAB X recreate this file
# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at
# least once so the file gets created and the project can be built. Finally, you can also
# avoid using this file at all if you are only building from the command line with make.
# You can invoke make with the values of the macros:
# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ...
#
SHELL=cmd.exe
PATH_TO_IDE_BIN=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/
# Adding MPLAB X bin directory to path.
PATH:=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/:$(PATH)
# Path to java used to run MPLAB X when this makefile was created
MP_JAVA_PATH="C:\Program Files (x86)\Microchip\MPLABX\sys\java\jre1.7.0_25-windows-x64\java-windows/bin/"
OS_CURRENT="$(shell uname -s)"
MP_CC="C:\Program Files (x86)\Microchip\xc32\v1.31\bin\xc32-gcc.exe"
MP_CPPC="C:\Program Files (x86)\Microchip\xc32\v1.31\bin\xc32-g++.exe"
# MP_BC is not defined
MP_AS="C:\Program Files (x86)\Microchip\xc32\v1.31\bin\xc32-as.exe"
MP_LD="C:\Program Files (x86)\Microchip\xc32\v1.31\bin\xc32-ld.exe"
MP_AR="C:\Program Files (x86)\Microchip\xc32\v1.31\bin\xc32-ar.exe"
DEP_GEN=${MP_JAVA_PATH}java -jar "C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/extractobjectdependencies.jar"
MP_CC_DIR="C:\Program Files (x86)\Microchip\xc32\v1.31\bin"
MP_CPPC_DIR="C:\Program Files (x86)\Microchip\xc32\v1.31\bin"
# MP_BC_DIR is not defined
MP_AS_DIR="C:\Program Files (x86)\Microchip\xc32\v1.31\bin"
MP_LD_DIR="C:\Program Files (x86)\Microchip\xc32\v1.31\bin"
MP_AR_DIR="C:\Program Files (x86)\Microchip\xc32\v1.31\bin"
# MP_BC_DIR is not defined
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/project.xml
0,0 → 1,16
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://www.netbeans.org/ns/project/1">
<type>com.microchip.mplab.nbide.embedded.makeproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/make-project/1">
<name>Cerebot_32MX7</name>
<creation-uuid>a23479a1-6afc-4362-a20c-e5ddcf3c7815</creation-uuid>
<make-project-type>0</make-project-type>
<c-extensions>c</c-extensions>
<cpp-extensions/>
<header-extensions>h</header-extensions>
<sourceEncoding>ISO-8859-1</sourceEncoding>
<asminc-extensions/>
<make-dep-projects/>
</data>
</configuration>
</project>
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/Makefile-impl.mk
0,0 → 1,69
#
# Generated Makefile - do not edit!
#
# Edit the Makefile in the project folder instead (../Makefile). Each target
# has a pre- and a post- target defined where you can add customization code.
#
# This makefile implements macros and targets common to all configurations.
#
# NOCDDL
 
 
# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
# and .clean-reqprojects-conf unless SUB has the value 'no'
SUB_no=NO
SUBPROJECTS=${SUB_${SUB}}
BUILD_SUBPROJECTS_=.build-subprojects
BUILD_SUBPROJECTS_NO=
BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
CLEAN_SUBPROJECTS_=.clean-subprojects
CLEAN_SUBPROJECTS_NO=
CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
 
 
# Project Name
PROJECTNAME=Cerebot_32MX7_LED_Cube
 
# Active Configuration
DEFAULTCONF=default
CONF=${DEFAULTCONF}
 
# All Configurations
ALLCONFS=default
 
 
# build
.build-impl: .build-pre
${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf
 
 
# clean
.clean-impl: .clean-pre
${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf
 
# clobber
.clobber-impl: .clobber-pre .depcheck-impl
${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean
 
 
 
# all
.all-impl: .all-pre .depcheck-impl
${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build
 
 
 
# dependency checking support
.depcheck-impl:
# @echo "# This code depends on make tool being used" >.dep.inc
# @if [ -n "${MAKE_VERSION}" ]; then \
# echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
# echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
# echo "include \$${DEPFILES}" >>.dep.inc; \
# echo "endif" >>.dep.inc; \
# else \
# echo ".KEEP_STATE:" >>.dep.inc; \
# echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
# fi
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/Makefile-variables.mk
0,0 → 1,13
#
# Generated - do not edit!
#
# NOCDDL
#
CND_BASEDIR=`pwd`
# default configuration
CND_ARTIFACT_DIR_default=dist/default/production
CND_ARTIFACT_NAME_default=Cerebot_32MX7_LED_Cube.production.hex
CND_ARTIFACT_PATH_default=dist/default/production/Cerebot_32MX7_LED_Cube.production.hex
CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package
CND_PACKAGE_NAME_default=cerebot32mx7ledcube.tar
CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/cerebot32mx7ledcube.tar
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/Package-default.bash
0,0 → 1,73
#!/bin/bash -x
 
#
# Generated - do not edit!
#
 
# Macros
TOP=`pwd`
CND_CONF=default
CND_DISTDIR=dist
TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging
TMPDIRNAME=tmp-packaging
OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
OUTPUT_BASENAME=Cerebot_32MX7_LED_Cube.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
PACKAGE_TOP_DIR=cerebot32mx7ledcube/
 
# Functions
function checkReturnCode
{
rc=$?
if [ $rc != 0 ]
then
exit $rc
fi
}
function makeDirectory
# $1 directory path
# $2 permission (optional)
{
mkdir -p "$1"
checkReturnCode
if [ "$2" != "" ]
then
chmod $2 "$1"
checkReturnCode
fi
}
function copyFileToTmpDir
# $1 from-file path
# $2 to-file path
# $3 permission
{
cp "$1" "$2"
checkReturnCode
if [ "$3" != "" ]
then
chmod $3 "$2"
checkReturnCode
fi
}
 
# Setup
cd "${TOP}"
mkdir -p ${CND_DISTDIR}/${CND_CONF}/package
rm -rf ${TMPDIR}
mkdir -p ${TMPDIR}
 
# Copy files and create directories and links
cd "${TOP}"
makeDirectory ${TMPDIR}/cerebot32mx7ledcube/bin
copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
 
 
# Generate tar file
cd "${TOP}"
rm -f ${CND_DISTDIR}/${CND_CONF}/package/cerebot32mx7ledcube.tar
cd ${TMPDIR}
tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/cerebot32mx7ledcube.tar *
checkReturnCode
 
# Cleanup
cd "${TOP}"
rm -rf ${TMPDIR}
/PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/project.properties
--- README.txt (nonexistent)
+++ README.txt (revision 263)
@@ -0,0 +1,206 @@
+Here lies some random pieces of information that may make it easier to understand the code base
+
+KNOWN ISSUES:
+ Cube is occasionally flickering to ~60Hz. Need to figure out why.
+ Interrupts dont seem to be preempting properly. Not sure why.
+
+PERIPHERAL USAGE:
+ SPI1 - Used by the cube code to send data to the ube
+ SPI4 - Unused
+ I2C1 - Used by the controller code
+ TIMER2 - Used by PWM2
+ TIMER4 - Used by the cube code for the overlay rotation interrupt
+ TIMER5 - Used by the cube code for the update layer interrupt
+ UART1 - Used by the cube code for reading in frame data
+ PWM2 - Generates a constant ~20MHz output, uses TIMER2
+ ETHERNET - Used to remote-update the cube
+
+PERIPHERAL INTERRUPT PRIORITY LEVELS:
+ IPL1 = lowest, IPL7 = highest priority
+ SPI1 - Priority 5, Subpriority 1
+ SPI4 - Priority 6, Subpriority 2
+ I2C1 - Priority 5, Subpriority 1
+ TIMER5 - Priority 3, Subpriority 1
+ TIMER4 - Priority 1, Subpriority 1
+ UART1 - Priority 2, Subpriority 1
+ ETHERNET - Priority 1, Subpriority 1
+
+
+PIN I/Os:
+
+JA-01 AN2/C2IN-/CN4/RB2 RB02
+JA-02 AN3/C2IN+/CN5/RB3 RB03
+JA-03 AN4/C1IN-/CN6/RB4 RB04
+JA-04 PGEC2/AN6/OCFA/RB6 RB06
+JA-07 PGED2/AN7/RB7 RB07
+JA-08 AN8/C1OUT/RB8 RB08
+JA-09 AN9/C2OUT/RB9 RB09
+JA-10 CVrefout/PMA13/AN10/RB10 RB10
+ *
+JB-01 PMD0/RE0 RE00
+JB-02 PMD1/RE1 RE01
+JB-03 PMD2/RE2 RE02
+JB-04 PMD3/RE3 RE03
+JB-07 PMD4/RE4 RE04
+JB-08 PMD5/RE5 RE05
+JB-09 PMD6/RE6 RE06
+JB-10 PMD7/RE7 RE07
+ *
+JC-01 T2CK/RC1 RC01
+JC-02 C2RX/PMD8/RG0 RG00
+JC-03 C2TX/ETXERR/PMD9/RG1 RG01
+JC-04 ETXCLK/PMD15/CN16/RD7 RD07
+JC-07 AN15/ERXD3/AETXD2/OCFB/PMALL/PMA0/CN12/RB15 RB15 (SFT_D)
+JC-08 PMRD/CN14/RD5 RD05 (SFT_S)
+JC-09 OC5/PMWR/CN13/RD4 RD04 (SFT_K)
+JC-10 AN14/ERXD2/AETXD3/PMALH/PMA1/RB14 RB14 (SFT_R)
+ *
+JD-01 SS1/IC2/RD9 RD09 (GSLAT)
+JD-02 SDO1/OC1/INT0/RD0 RD00 (GSSIN)
+JD-03 T5CK/SDI1/RC4 RC04 (GSSOUT)
+JD-04 SCK1/IC3/PMCS2/PMA15/RD10 RD10 (GSSCK)
+JD-07 OC2/RD1 RD01 (PWMCK)
+JD-08 OC3/RD2 RD02 (XBLNK)
+JD-09 OC4/RD3 RD03
+JD-10 ETXD2/IC5/PMD12/RD12 RD12
+ *
+JE-01 AETXD0/SS3/U4RX/U1CTS/CN20/RD14 RD14
+JE-02 SCL3/SDO3/U1TX/RF8 RF08
+JE-03 SDA3/SDI3/U1RX/RF2 RF02
+JE-04 AETXD1/SCK3/U4TX/U1RTS/CN21/RD15 RD15
+JE-07 TRCLK/RA6 RA06 on 32MX7 or INT1/RF8 on MX7CK
+JE-08 TRD3/RA7 RA07
+JE-09 Vref-/CVref-/AERXD2/PMA7/RA9 RA09
+JE-10 Vref+/CVref+/AERXD3/PMA6/RA10 RA10
+ *
+JF-01 AC1RX/SS4/U5RX/U2CTS/RF12 RF12 shared with CAN1 Transceiver (JP-1)
+JF-02 SCL5/SDO4/U2TX/PMA8/CN18/RF5 RF05
+JF-03 SDA5/SDI4/U2RX/PMA9/CN17/RF4 RF04
+JF-04 AC1TX/SCK4/U5TX/U2RTS/RF13 RF13 shared with CAN1 Transceiver (JP-2)
+JF-07 TMS/RA0 RA00 on 32MX7 or INT2/RF9 on MX7CK
+JF-08 TCK/RA1 RA01
+JF-09 TDI/RA4 RA04
+JF-10 TDO/RA5 RA05
+
+N/A SCL2/RA2 RA02 I2C bus #2, not shared with Pmod connector
+N/A SDA2/RA3 RA03 I2C bus #2, not shared with Pmod connector
+N/A AETXCLK/SCL1/INT3/RA14 RA14 I2C Bus #1, not shared with Pmod connector
+N/A AETXEN/SDA1/INT4/RA15 RA15 I2C Bus #1, not shared with Pmod connector
+N/A PGED1/AN0/CN2/RB0 RB00 Used by debug circuit, PGC
+N/A PGEC1/AN1/CN3/RB1 RB01 Used by debug circuit, PGD
+N/A AN5/C1IN+/VBUSON/CN7/RB5 RB05 USB VBUSON
+N/A AN11/ERXERR/AETXERR/PMA12/RB11 RB11 Ethernet PHY
+N/A AN12/ERXD0/AECRS/PMA11/RB12 RB12 Ethernet PHY
+N/A AN13/ERXD1/AECOL/PMA10/RB13 RB13 Ethernet PHY
+N/A OSC1/CLKI/RC12 RC12 Primary Oscillator Crystal
+N/A SOSCI/CN1/RC13 RC13 Secondary Oscillator Crystal
+N/A SOSCO/T1CK/CN0/RC14 RC14 Secondary Oscillator Crystal
+N/A OSC2/CLKO/RC15 RC15 Primary Oscillator Crystal
+N/A ETXEN/PMD14/CN15/RD6 RD06 Ethernet PHY
+N/A RTCC/EMDIO/AEMDIO/IC1/RD8 RD08 Ethernet PHY
+N/A EMDC/AEMDC/IC4/PMCS1/PMA14/RD11 RD11 Ethernet PHY
+N/A ETXD3/PMD13/CN19/RD13 RD13 BTN3
+N/A AERXD0/INT1/RE8 RE08 USB Overcurrent detect
+N/A AERXD1/INT2/RE9 RE09 Ethernet PHY Reset
+N/A C1RX/ETXD1/PMD11/RF0 RF00 Ethernet PHY
+N/A C1TX/ETXD0/PMD10/RF1 RF01 Ethernet PHY
+N/A USBID/RF3 RF03 USBID (USB-4)
+N/A D+/RG2 RG02 D+ (USB-3)
+N/A D-/RG3 RG03 D- (USB-2)
+N/A ECOL/SCK2/U6TX/U3RTS/PMA5/CN8/RG6 RG06 BTN1
+N/A ECRS/SDA4/SDI2/U3RX/PMA4/CN9/RG7 RG07 BTN2
+N/A ERXDV/AERXDV/ECRSDV/AECRSDV/SCL4/SDO2/U3TX/PMA3/CN10/RG8 RG08 Ethernet PHY
+N/A ERXCLK/AERXCLK/EREFCLK/AEREFCLK/SS2/U6RX/U3CTS/PMA2/CN11/RG9 RG09 Ethernet PHY
+N/A TRD1/RG12 RG12 LED1
+N/A TRD0/RG13 RG13 LED2
+N/A TRD2/RG14 RG14 LED3
+N/A AERXERR/RG15 RG15 LED4
+
+
+CONNECTORS:
+
+J1 - Serial USB Misc Connections (MX7CK only)
+ * This header contains other FTDI UART function pins (CTS, DSR, DCD, RI)
+J2 - Serial USB Connector (MX7CK only)
+ * This connector is connected to UART1 or PMOD JE
+J7 - I2C port daisy chain connector
+ * On the Cerebot 32MX7, this connector provides access to the I2C signals, power and ground for I2C2.
+ * On the Cerebot MX7CK, this connector provides access to the I2C signals, power and ground for I2C1 + INT3/4.
+J8 - I2C port daisy chain connector
+ * On the Cerebot 32MX7, this connector provides access to the I2C signals, power and ground for I2C1.
+ * On the Cerebot MX7CK, this connector provides access to the I2C signals, power and ground for I2C2.
+ EEPROM is changed to this port on the MX7CK
+J9 - CAN #1 Connector
+ * This connector is used to access the signals for CAN #1.
+J10 - CAN #2 Connector
+ * This connector is used to access the signals for CAN #2.
+J11 - Ethernet Connector
+ * This connector provides access to the 10/100 Ethernet port.
+J12-J14
+ * Do Not Use.
+J15 - Debug USB Connector
+ * This connector is used to connect the on-board programming and
+ debug circuit to the PC for use with the MPLAB IDE.
+J16 - Power supply source select
+ * This jumper is used to select the source of main board power.
+ Place a shorting block in the upper, ?USB? position to have the
+ board powered from the USB device connector, J19.
+ Place a shorting block in the center, ?EXT? position to have the
+ board powered from one of the external power connectors, J17 or J18.
+ Place a shorting block in the lower, ?DBG? position to have the
+ board powered from the debug USB connector, J15.
+J17 - External Power Connector
+ * This is a 2.5mm x 5.5mm, center positive, coax power connector used to
+ provide external power to the board. The optional Digilent 5V Switching
+ Power Supply is connected here.
+J18 - External Power Connector
+ * This is a screw terminal connector used to provide external power to
+ the board. Be sure to observe proper polarity (marked near the connector)
+ when providing power via this connector, or damage to the board and/or
+ connected devices may result.
+J19 - USB Device / OTG Connector
+ * This is a USB micro-AB connector. It is used when using the PIC32MX795
+ microcontroller to implement a USB device or OTG Host/Device.
+J20 - USB Host Connector
+ * This is a standard sized USB type A connector. This connector is used to
+ connect USB devices to the board when using the PIC32MX795 microcontroller
+ to implement an embedded USB host.
+
+
+ JUMPERS:
+
+ JP1 & JP2 - CAN or Pmod Select
+ * These jumpers select microcontroller signals RF12 and RF13 for use with CAN
+ #1 or Pmod connector JF. Place these jumpers in the CAN position to use CAN
+ #1. Place the jumpers in the PMOD position to use then with Pmod connector JF.
+ JP3 & JP4 - Pull-up enable for I2C port #2
+ * These two jumpers are used to enable/disable the pull-up resistors on I2C
+ port #2. Insert shorting blocks on these two jumpers to enable the pull-up
+ resistors. Remove the shorting blocks to disable the pull-up resistors. Only
+ a single device on the I2C bus should have the pull-up resistors enabled.
+ JP5 - CAN #1 Termination
+ * This jumper is used to enable/disable the 120 ohm termination resistor for
+ CAN #1. Insert the shorting block to enable the termination resistor, remove
+ it to disable the termination resistor.
+ JP6 - CAN #1 5V0 Enable
+ * This jumper is used to enable/disable providing 5V to the CAN #1 connector.
+ Insert the shorting block to connect the board 5V0 supply to pins 9 & 10 of
+ CAN #1 connector. Remove the shorting block to disconnect the 5V0 supply.
+ JP7 - CAN #2 Termination
+ * This jumper is used to enable/disable the 120 ohm termination resistor for
+ CAN #2. Insert the shorting block to enable the termination resistor, remove
+ it to disable the termination resistor.
+ JP8 - CAN #1 5V0 Enable
+ * This jumper is used to enable/disable providing 5V to the CAN #1 connector.
+ Insert the shorting block to connect the board 5V0 supply to pins 9 & 10 of
+ CAN #1 connector. Remove the shorting block to disconnect the 5V0 supply.
+ JP9 - Do Not Use
+ JP10 - USB Host Power Select
+ * This jumper is used to select which host connector is powered when host power
+ is enabled. Place the shorting block in the ?MICRO? position to supply power
+ to the USB micro-AB OTG Connector, J19. Place the shorting block in the ?A?
+ position to supply power to the USB type A Host Connector, J20.
+ JP11 - Programmer Serial Select (MX7CK only)
+ * Remove the jumper to disconnect the USB serial converter's connection to the
+ MCLR pin. Disconnecting this when using the built in debugger is recommended.
+ JP17 - Do Not Use
\ No newline at end of file
/PIC Stuff/Cerebot_32MX7_LED_Cube/defines.h
0,0 → 1,57
// PIC32MX795F512L
 
#ifndef DEFINES_H
#define DEFINES_H
 
#include <xc.h>
#include <plib.h>
#include <stdint.h>
 
// Uncomment ONE of the following:
#define CEREBOT_32MX7
// #define CEREBOT_MX7CK
 
// Power supply must be 5V for proper operation of the board!
 
#define CPU_CLOCK_HZ 80000000UL
#define PERIPHERAL_CLOCK_HZ 80000000UL
#define CPU_CT_HZ (CPU_CLOCK_HZ/2UL)
#define MS_TO_CT_TICKS (CPU_CLOCK_HZ/2000UL)
#define US_TO_CT_TICKS (CPU_CLOCK_HZ/2000000UL)
 
#define ADDRESS_EEPROM 0x50
#define ADDRESS_CONTROLLER_1 0x24
#define ADDRESS_CONTROLLER_2 0x25
 
// LED1 = G12, LED2 = G13, LED3 = G14, LED4 = G15 (active high)
#define LED1_TRIS TRISGbits.TRISG12
#define LED1_LAT LATGbits.LATG12
#define LED2_TRIS TRISGbits.TRISG13
#define LED2_LAT LATGbits.LATG13
#define LED3_TRIS TRISGbits.TRISG14
#define LED3_LAT LATGbits.LATG14
#define LED4_TRIS TRISGbits.TRISG15
#define LED4_LAT LATGbits.LATG15
 
// Reset conditions
#define RESET_POR 0x01 // Power on reset
#define RESET_BOR 0x02 // Brown out reset
#define RESET_SWR 0x03 // Software reset
#define RESET_WDT 0x04 // Watchdog timer reset
#define RESET_PIN 0x05 // MCLR pin reset
#define RESET_CFG 0x06 // Config mismatch reset
 
// Board 'modes' (idle/games/etc)
#define BOARD_MODE_IDLE 0x1
#define BOARD_MODE_SNAKE 0x2
#define BOARD_MODE_TRON 0x3
#define BOARD_MODE_ETHERNET 0x4
 
void Delay_MS(uint32_t delay_ms);
void Delay_US(uint32_t delay_us);
uint8_t Get_Reset_Condition(void);
uint8_t Get_Board_State(void);
void Reset_Board(uint8_t next_state);
void Idle_Animation_Sequence(void);
 
#endif /* DEFINES_H */
/PIC Stuff/Cerebot_32MX7_LED_Cube/ETHERNET.h
0,0 → 1,162
#ifndef ETHERNET_H
#define ETHERNET_H
 
#define ETH_TX_DESCRIPTOR_COUNT 2
#define ETH_RX_DESCRIPTOR_COUNT 2
#define ETH_TX_ED_BUFFER_SIZE 2032
#define ETH_RX_ED_BUFFER_SIZE 2032
 
#ifdef CEREBOT_MX7CK
#define PHY_RESET_TRIS TRISAbits.TRISA6
#define PHY_RESET_LAT LATAbits.LATA6
#endif
#ifdef CEREBOT_32MX7
#define PHY_RESET_TRIS TRISEbits.TRISE9
#define PHY_RESET_LAT LATEbits.LATE9
#endif
#define ETH_MDC_TRIS TRISDbits.TRISD11
#define ETH_MDIO_TRIS TRISDbits.TRISD8
#define ETH_TXEN_TRIS TRISDbits.TRISD6
#define ETH_TXD0_TRIS TRISFbits.TRISF1
#define ETH_TXD1_TRIS TRISFbits.TRISF0
#define ETH_RXCLK_TRIS TRISGbits.TRISG9
#define ETH_RXDV_TRIS TRISGbits.TRISG8
#define ETH_RXD0_TRIS TRISBbits.TRISB12
#define ETH_RXD1_TRIS TRISBbits.TRISB13
#define ETH_RXERR_TRIS TRISBbits.TRISB11
 
#define PHY_ADDRESS 0x0
 
typedef union {
struct {
uint8_t BYTE_0;
uint8_t BYTE_1;
uint8_t BYTE_2;
uint8_t BYTE_3;
uint8_t BYTE_4;
uint8_t BYTE_5;
};
uint8_t bytes[6];
} ETH_MAC_ADDRESS;
 
typedef union {
struct {
// Bits 31:0
unsigned BYTE_COUNT : 16; // Total bytes in frame not counting collided bytes
unsigned COLLISION_COUNT : 4; // Number of collisions current packet incurred durrent transmit attempts
unsigned CRC_ERROR : 1; // Attached CRC did not match the internal generated CRC
unsigned LENGTH_CHECK_ERROR : 1; // Frame length field value in packet does not match actual data byte length and is not a Type field
unsigned LENGTH_OUT_OF_RANGE : 1; // Frame type/length field was larger than 1500 bytes
unsigned DONE : 1; // Transmit of packet was completed
unsigned MULTICASE : 1; // Destination address was a multicast address
unsigned BROADCAST : 1; // Destination address was a broadcast address
unsigned PACKET_DEFER : 1; // Packet was deferred for at least one attempt
unsigned EXCESSIVE_DEFER : 1; // Packet was defered in excess of 6071/24287 nibble(100Mbps)/bit(10Mbps) times
unsigned MAXIMUM_COLLISION : 1; // Packet aborted, number of collisions exceeded RETX
unsigned LATE_COLLISION : 1; // Collision occurred beyond the collision window (512 bit times)
unsigned GIANT : 1; // Frame byte count greater than MACMAXF
unsigned UNDERRUN : 1; // Failed to transfer complete packet to the transmit MAC module
// Bits 63:32
unsigned BYTES_TRANSMITTED : 16; // Total bytes transmitted on wire (including collisions)
unsigned CONTROL_FRAME : 1; // Frame transmitted was a control frame
unsigned PAUSE_CONTROL_FRAME : 1; // Frame transmitted was a control frame with a valid PAUSE Op code
unsigned BACKPRESSURE : 1; // Carrier-sense method backpressure was previously applied
unsigned VLAN_TAGGED : 1; // Frame length/type field contained 0x8100 (VLAN protocol identifier)
unsigned : 12;
};
uint32_t registers[2];
} ETH_TRANSMIT_STATUS_VECTOR;
 
typedef union {
struct {
// Bits 31:0
unsigned BYTE_COUNT : 16; // Length of received frame
unsigned LONG_DROP_EVENT : 1; // Packet over 50000 bit times occured or packet since last RSV was dropped
unsigned RXDV_EVENT : 1; // Last receive event seen not long enough to be a valid packet
unsigned CARRIER_EVENT : 1; // Carrier event detected, noted, and reported
unsigned CODE_VIOLATION : 1; // MII data does not represent a valid data code when MRXER asserted
unsigned CRC_ERROR : 1; // Frame CRC does not match the CRC calculated by the receiver MAC
unsigned LENGTH_CHECK_ERROR : 1; // Frame length field value doe snot match the actual data byte length
unsigned LENGTH_OUT_OF_RANGE : 1; // Frame type/length field was larger than 1500 bytes
unsigned RECEIVE_OK : 1; // Packet has a valid CRC and no symbol errors
unsigned MULTICAST : 1; // Packet had a valid multicast address
unsigned BROADCAST : 1; // Packet had a valid broadcast address
unsigned DRIBBLE_NIBBLE : 1; // An additional 1-7 bits received after packet
unsigned CONTROL_FRAME : 1; // Frame recognized as a control frame
unsigned PAUSE_CONTROL_FRAME : 1; // Frame recognized as a control frame with a valid PAUSE Op code
unsigned UNKNOWN_OP_CODE : 1; // Frame recognized as a control frame but with an unknown Op code
unsigned VLAN_TAGGED : 1; // Frame recognized as a VLAN tagged frame
unsigned : 1;
// Bits 63:32;
unsigned PKT_CHECKSUM : 16; // RX packet payload checksum of this descriptor's packet
unsigned : 8;
unsigned RUNT_PACKET : 1; // Runt packet
unsigned BROADCAST_OR_NOT_DEST : 1; // NOT unicast match AND NOT multicast match
unsigned HASH_TABLE_MATCH : 1; // Hash table match
unsigned MAGIC_PACKET_MATCH : 1; // Magic packet match
unsigned PATTERN_MATCH : 1; // Pattern match
unsigned UNICAST_MATCH : 1; // Unicast match
unsigned BROADCAST_MATCH : 1; // Broadcast match
unsigned MULTICAST_MATCH : 1; // Multicast match
};
uint32_t registers[2];
} ETH_RECEIVE_STATUS_VECTOR;
 
typedef struct {
unsigned : 7;
unsigned EOWN : 1; // Ethernet controller own bit (1 = ED owned by controller, do not modify)
unsigned NPV : 1; // Next ED pointer valid enable bit (1 = NEXT_ED field exists)
unsigned : 7;
unsigned BYTE_COUNT : 11; // Number of bytes to be transmited for this descriptor (1-2047)
unsigned : 3;
unsigned EOP : 1; // End of packet enable bit (1 = transmit end of packet delimiter)
unsigned SOP : 1; // Start of packet enable bit (1 = transmit start of packet delimiter)
uint32_t BUFFER_ADDR; // Starting point address of the data buffer
ETH_TRANSMIT_STATUS_VECTOR TSV; // Transmit status vector bits
} ETH_TX_ETHERNET_DESCRIPTOR;
 
typedef struct {
unsigned : 7;
unsigned EOWN : 1; // Ethernet controller own bit (1 = ED owned by controller, do not modify)
unsigned NPV : 1; // Next ED pointer valid enable bit (1 = NEXT_ED field exists)
unsigned : 7;
unsigned BYTE_COUNT : 11; // Number of bytes to be transmited for this descriptor (1-2047)
unsigned : 3;
unsigned EOP : 1; // End of packet enable bit (1 = transmit end of packet delimiter)
unsigned SOP : 1; // Start of packet enable bit (1 = transmit start of packet delimiter)
uint32_t BUFFER_ADDR; // Starting point address of the data buffer
ETH_RECEIVE_STATUS_VECTOR RSV; // Transmit status vector bits
} ETH_RX_ETHERNET_DESCRIPTOR;
 
typedef struct {
ETH_TX_ETHERNET_DESCRIPTOR descriptor[ETH_TX_DESCRIPTOR_COUNT];
uint32_t next_ED;
} ETH_TX_DESCRIPTOR_TABLE;
 
typedef struct {
ETH_RX_ETHERNET_DESCRIPTOR descriptor[ETH_RX_DESCRIPTOR_COUNT];
uint32_t next_ED;
} ETH_RX_DESCRIPTOR_TABLE;
 
typedef struct {
ETH_TX_DESCRIPTOR_TABLE TX_ED_table;
ETH_RX_DESCRIPTOR_TABLE RX_ED_table;
uint8_t TX_ED_buffer[ETH_TX_DESCRIPTOR_COUNT][ETH_TX_ED_BUFFER_SIZE];
uint8_t RX_ED_buffer[ETH_RX_DESCRIPTOR_COUNT][ETH_RX_ED_BUFFER_SIZE];
uint8_t TX_descriptor_index;
uint8_t RX_descriptor_index;
void (*tx_callback)(void);
void (*rx_callback)(void);
} ETH_DATA;
 
void ETH_Init(ETH_DATA *data, void(*tx_callback)(void), void(*rx_callback)(void));
 
uint16_t ETH_PHY_Read(uint8_t address, uint8_t reg);
void ETH_PHY_Write(uint8_t address, uint8_t reg, uint16_t value);
 
uint8_t ETH_Recv_Queue(void);
uint8_t ETH_Read_Packet(uint8_t *buffer, uint16_t *length);
uint8_t ETH_Write_Packet(ETH_MAC_ADDRESS dest, ETH_MAC_ADDRESS src, uint16_t length, uint8_t *buffer);
 
#endif /* ETHERNET_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/TRON.c
0,0 → 1,165
#include "defines.h"
#include "CONTROLLERS.h"
#include "TRON.h"
 
static TRON_DATA *data_p;
 
void Tron_Init(TRON_DATA *data) {
data_p = data;
 
// Set starting point
data_p->p1_body[0] = (TRON_POINT){0,0,7};
data_p->p2_body[0] = (TRON_POINT){7,7,7};
 
data_p->length = 1;
data_p->delay = 800;
 
Cube_Clear();
Cube_Overlay_Clear();
 
// Draw player 1 light trail
uint32_t index;
for (index = 0; index < data_p->length - 1; index++) {
Cube_Set_Pixel(data_p->p1_body[index].z, data_p->p1_body[index].x, data_p->p1_body[index].y, TRON_PLAYER_1_COLOR);
}
Cube_Set_Pixel(data_p->p1_body[data_p->length-1].z, data_p->p1_body[data_p->length-1].x, data_p->p1_body[data_p->length-1].y, TRON_PLAYER_1_HEAD);
 
// Draw player 2 light trail
for (index = 0; index < data_p->length - 1; index++) {
Cube_Set_Pixel(data_p->p2_body[index].z, data_p->p2_body[index].x, data_p->p2_body[index].y, TRON_PLAYER_2_COLOR);
}
Cube_Set_Pixel(data_p->p2_body[data_p->length-1].z, data_p->p2_body[data_p->length-1].x, data_p->p2_body[data_p->length-1].y, TRON_PLAYER_2_HEAD);
}
 
void Tron_Main(void) {
// Main function, loops and delays while updating the frame every x milliseconds
Tron_Update_Direction(0x04,0x04);
Controller_Set_Leds(0x01,0x01);
Delay_MS(2000);
while (1) {
Tron_Update_Frame();
Delay_MS(data_p->delay);
}
}
 
void Tron_Update_Direction(uint8_t p1, uint8_t p2) {
// Determine the next direction for the trails based off the last button press
if (p1) {
TRON_P1_DIRECTION p1_dir;
p1_dir.value = p1;
data_p->p1_last_direction = p1_dir.value;
TRON_POINT p1_point = data_p->p1_body[data_p->length - 1];
if (p1_dir.up) {
p1_point.z = (p1_point.z == CUBE_LAYER_COUNT - 1) ? 0 : p1_point.z + 1;
} else if (p1_dir.down) {
p1_point.z = (p1_point.z == 0) ? CUBE_LAYER_COUNT - 1 : p1_point.z - 1;
} else if (p1_dir.forward) {
p1_point.x = (p1_point.x == CUBE_ROW_COUNT - 1) ? 0 : p1_point.x + 1;
} else if (p1_dir.right) {
p1_point.y = (p1_point.y == CUBE_COLUMN_COUNT - 1) ? 0 : p1_point.y + 1;
} else if (p1_dir.backward) {
p1_point.x = (p1_point.x == 0) ? CUBE_ROW_COUNT - 1 : p1_point.x - 1;
} else if (p1_dir.left) {
p1_point.y = (p1_point.y== 0) ? CUBE_COLUMN_COUNT - 1 : p1_point.y - 1;
}
data_p->p1_direction = p1_point;
}
if (p2) {
TRON_P2_DIRECTION p2_dir;
p2_dir.value = p2;
data_p->p2_last_direction = p2_dir.value;
TRON_POINT p2_point = data_p->p2_body[data_p->length - 1];
if (p2_dir.up) {
p2_point.z = (p2_point.z == CUBE_LAYER_COUNT - 1) ? 0 : p2_point.z + 1;
} else if (p2_dir.down) {
p2_point.z = (p2_point.z == 0) ? CUBE_LAYER_COUNT - 1 : p2_point.z - 1;
} else if (p2_dir.forward) {
p2_point.x = (p2_point.x == CUBE_ROW_COUNT - 1) ? 0 : p2_point.x + 1;
} else if (p2_dir.right) {
p2_point.y = (p2_point.y == CUBE_COLUMN_COUNT - 1) ? 0 : p2_point.y + 1;
} else if (p2_dir.backward) {
p2_point.x = (p2_point.x == 0) ? CUBE_ROW_COUNT - 1 : p2_point.x - 1;
} else if (p2_dir.left) {
p2_point.y = (p2_point.y== 0) ? CUBE_COLUMN_COUNT - 1 : p2_point.y - 1;
}
data_p->p2_direction = p2_point;
}
}
 
void Tron_Update_Frame(void) {
// Check if there is a head-on collision
if (data_p->p1_direction.x == data_p->p2_direction.x &&
data_p->p1_direction.y == data_p->p2_direction.y &&
data_p->p1_direction.z == data_p->p2_direction.z) {
Cube_Set_Pixel(data_p->p1_direction.z, data_p->p1_direction.x, data_p->p1_direction.y, TRON_COLLISION);
Delay_MS(3000);
Animation_Cube_In_Out(200, TRON_COLLISION);
Reset_Board(BOARD_MODE_IDLE);
}
 
// Check if the location that we are moving to is overlapping either trails
uint32_t index, p1_collision = 0, p2_collision = 0;
for (index = 0; index < data_p->length; index++) {
if (data_p->p1_direction.x == data_p->p1_body[index].x &&
data_p->p1_direction.y == data_p->p1_body[index].y &&
data_p->p1_direction.z == data_p->p1_body[index].z) {
p1_collision = 1;
}
if (data_p->p1_direction.x == data_p->p2_body[index].x &&
data_p->p1_direction.y == data_p->p2_body[index].y &&
data_p->p1_direction.z == data_p->p2_body[index].z) {
p1_collision = 1;
}
if (data_p->p2_direction.x == data_p->p2_body[index].x &&
data_p->p2_direction.y == data_p->p2_body[index].y &&
data_p->p2_direction.z == data_p->p2_body[index].z) {
p2_collision = 1;
}
if (data_p->p2_direction.x == data_p->p1_body[index].x &&
data_p->p2_direction.y == data_p->p1_body[index].y &&
data_p->p2_direction.z == data_p->p1_body[index].z) {
p2_collision = 1;
}
}
 
// Save the new head location of each trail
data_p->length++;
data_p->p1_body[data_p->length - 1] = data_p->p1_direction;
data_p->p2_body[data_p->length - 1] = data_p->p2_direction;
 
Cube_Clear();
// Draw player 1 light trail
for (index = 0; index < data_p->length - 1; index++) {
Cube_Set_Pixel(data_p->p1_body[index].z, data_p->p1_body[index].x, data_p->p1_body[index].y, TRON_PLAYER_1_COLOR);
}
Cube_Set_Pixel(data_p->p1_body[data_p->length-1].z, data_p->p1_body[data_p->length-1].x, data_p->p1_body[data_p->length-1].y, TRON_PLAYER_1_HEAD);
 
// Draw player 2 light trail
for (index = 0; index < data_p->length - 1; index++) {
Cube_Set_Pixel(data_p->p2_body[index].z, data_p->p2_body[index].x, data_p->p2_body[index].y, TRON_PLAYER_2_COLOR);
}
Cube_Set_Pixel(data_p->p2_body[data_p->length-1].z, data_p->p2_body[data_p->length-1].x, data_p->p2_body[data_p->length-1].y, TRON_PLAYER_2_HEAD);
 
// Indicate the point of collision and reset to idle mode
if (p1_collision || p2_collision) {
uint32_t ind = data_p->length - 1;
if (p1_collision)
Cube_Set_Pixel(data_p->p1_body[ind].z, data_p->p1_body[ind].x, data_p->p1_body[ind].y, TRON_COLLISION);
if (p2_collision)
Cube_Set_Pixel(data_p->p2_body[ind].z, data_p->p2_body[ind].x, data_p->p2_body[ind].y, TRON_COLLISION);
Delay_MS(3000);
if (p1_collision && p2_collision)
Animation_Cube_In_Out(200, TRON_COLLISION);
else if (p1_collision)
Animation_Cube_In_Out(200, TRON_PLAYER_2_HEAD);
else if (p2_collision)
Animation_Cube_In_Out(200, TRON_PLAYER_1_HEAD);
Reset_Board(BOARD_MODE_IDLE);
}
 
// Determine the next direction to take
Tron_Update_Direction(data_p->p1_last_direction, data_p->p2_last_direction);
 
// Decrease the delay between frame updates by 5ms
data_p->delay -= 5;
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/ANIMATIONS.c
0,0 → 1,382
#include "defines.h"
#include "ANIMATIONS.h"
#include "CUBE.h"
 
void Animation_Solid_Colors(uint16_t delay_ms) {
Cube_Set_All(RED);
Delay_MS(delay_ms);
Cube_Set_All(GREEN);
Delay_MS(delay_ms);
Cube_Set_All(BLUE);
Delay_MS(delay_ms);
}
 
void Animation_Layer_Alternate(uint16_t delay_ms) {
uint8_t i;
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
if (i % 3 == 0)
Cube_Set_Layer(i,RED);
else if (i % 3 == 1)
Cube_Set_Layer(i,GREEN);
else
Cube_Set_Layer(i,BLUE);
}
Delay_MS(delay_ms);
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
if (i % 3 == 0)
Cube_Set_Layer(i,GREEN);
else if (i % 3 == 1)
Cube_Set_Layer(i,BLUE);
else
Cube_Set_Layer(i,RED);
}
Delay_MS(delay_ms);
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
if (i % 3 == 0)
Cube_Set_Layer(i,BLUE);
else if (i % 3 == 1)
Cube_Set_Layer(i,RED);
else
Cube_Set_Layer(i,GREEN);
}
Delay_MS(delay_ms);
}
 
void Animation_Pixel_Alternate(uint16_t delay_ms) {
uint8_t i,j,k;
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
Cube_Clear();
for (j = 0; j < CUBE_ROW_COUNT; j++) {
for (k = 0; k < CUBE_COLUMN_COUNT; k++) {
int32_t var = (j * 8) + k;
if (var % 3 == 0)
Cube_Set_Pixel(i,j,k,RED);
else if (var % 3 == 1)
Cube_Set_Pixel(i,j,k,GREEN);
else
Cube_Set_Pixel(i,j,k,BLUE);
}
}
Delay_MS(delay_ms);
Cube_Clear();
for (j = 0; j < CUBE_ROW_COUNT; j++) {
for (k = 0; k < CUBE_COLUMN_COUNT; k++) {
int32_t var = (j * 8) + k;
if (var % 3 == 0)
Cube_Set_Pixel(i,j,k,GREEN);
else if (var % 3 == 1)
Cube_Set_Pixel(i,j,k,BLUE);
else
Cube_Set_Pixel(i,j,k,RED);
}
}
Delay_MS(delay_ms);
Cube_Clear();
for (j = 0; j < CUBE_ROW_COUNT; j++) {
for (k = 0; k < CUBE_COLUMN_COUNT; k++) {
int32_t var = (j * 8) + k;
if (var % 3 == 0)
Cube_Set_Pixel(i,j,k,BLUE);
else if (var % 3 == 1)
Cube_Set_Pixel(i,j,k,RED);
else
Cube_Set_Pixel(i,j,k,GREEN);
}
}
Delay_MS(delay_ms);
}
}
 
void Animation_Full_Color_Sweep(uint16_t delay_us) {
int16_t i;
for (i = 0; i < 0x0FF; i+=2) {
Cube_Set_All(i,0,0);
Delay_US(delay_us);
}
for (i = 0; i < 0x0FF; i+=2) {
Cube_Set_All(0x0FF,i,0);
Delay_US(delay_us);
}
for (i = 0x0FF; i >= 0; i-=2) {
Cube_Set_All(i,0x0FF,0);
Delay_US(delay_us);
}
for (i = 0; i < 0x0FF; i+=2) {
Cube_Set_All(0,0x0FF,i);
Delay_US(delay_us);
}
for (i = 0; i < 0x0FF; i+=2) {
Cube_Set_All(i,0x0FF,0x0FF);
Delay_US(delay_us);
}
for (i = 0x0FF; i >= 0; i-=2) {
Cube_Set_All(0x0FF,i,0x0FF);
Delay_US(delay_us);
}
for (i = 0x0FF; i >= 0; i-=2) {
Cube_Set_All(i,0,0x0FF);
Delay_US(delay_us);
}
for (i = 0x0FF; i >= 0; i-=2) {
Cube_Set_All(0,0,i);
Delay_US(delay_us);
}
}
 
void Animation_Row_Column_Sweep(uint16_t delay_ms) {
uint8_t i,j,k,a;
for (i = 0; i < 3; i++) {
for (j = 0; j < CUBE_ROW_COUNT; j++) {
Cube_Clear();
for (k = 0; k < CUBE_COLUMN_COUNT; k++)
if (i % 3 == 0)
for (a = 0; a < CUBE_LAYER_COUNT; a++)
Cube_Set_Pixel(a,j,k,RED);
else if (i % 3 == 1)
for (a = 0; a < CUBE_LAYER_COUNT; a++)
Cube_Set_Pixel(a,j,k,GREEN);
else
for (a = 0; a < CUBE_LAYER_COUNT; a++)
Cube_Set_Pixel(a,j,k,BLUE);
Delay_MS(delay_ms);
}
for (j = 0; j < CUBE_ROW_COUNT; j++) {
Cube_Clear();
for (k = 0; k < CUBE_COLUMN_COUNT; k++)
if (i % 3 == 0)
for (a = 0; a < CUBE_LAYER_COUNT; a++)
Cube_Set_Pixel(a,k,j,RED);
else if (i % 3 == 1)
for (a = 0; a < CUBE_LAYER_COUNT; a++)
Cube_Set_Pixel(a,k,j,GREEN);
else
for (a = 0; a < CUBE_LAYER_COUNT; a++)
Cube_Set_Pixel(a,k,j,BLUE);
Delay_MS(delay_ms);
}
for (j = CUBE_LAYER_COUNT; j != 0; j--) {
Cube_Clear();
if (i % 3 == 0) {
for (k = 0; k < CUBE_LAYER_COUNT; k++)
if (k == j)
Cube_Set_Layer(k,RED);
} else if (i % 3 == 1) {
for (k = 0; k < CUBE_LAYER_COUNT; k++)
if (k == j)
Cube_Set_Layer(k,GREEN);
} else {
for (k = 0; k < CUBE_LAYER_COUNT; k++)
if (k == j)
Cube_Set_Layer(k,BLUE);
}
Delay_MS(delay_ms);
}
}
}
 
void Animation_Pixel_Sweep(uint16_t delay_ms) {
uint8_t i,j,k,a;
for (a = 0; a < 3; a++) {
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_Clear();
if (a % 3 == 0) {
Cube_Set_Pixel(i,j,k,RED);
} else if (a % 3 == 1) {
Cube_Set_Pixel(i,j,k,GREEN);
} else {
Cube_Set_Pixel(i,j,k,BLUE);
}
Delay_MS(delay_ms);
}
}
}
}
}
 
void Animation_Pseudo_Random_Colors(uint16_t delay_ms) {
uint8_t i,j,k;
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
for (j = 0; j < CUBE_ROW_COUNT; j++) {
for (k = 0; k < CUBE_COLUMN_COUNT; k++) {
uint32_t a = rand();
if (a % 5 == 0)
Cube_Set_Pixel(i,j,k,RED);
else if (a % 5 == 1)
Cube_Set_Pixel(i,j,k,GREEN);
else if (a % 5 == 2)
Cube_Set_Pixel(i,j,k,BLUE);
else if (a % 5 == 3)
Cube_Set_Pixel(i,j,k,PURPLE);
else if (a % 5 == 4)
Cube_Set_Pixel(i,j,k,YELLOW);
else
Cube_Set_Pixel(i,j,k,ORANGE);
}
}
}
Delay_MS(delay_ms);
}
 
void Animation_Random_Colors(uint16_t delay_ms) {
uint8_t i,j,k;
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_Set_Pixel(i,j,k,rand()&0x0FF,rand()&0x0FF,rand()&0x0FF);
}
}
}
Delay_MS(delay_ms);
}
 
void Animation_Cube_In_Cube(uint16_t delay_ms) {
uint8_t x,i,j,k;
for (x = 0; x < 5; x++) {
Cube_Clear();
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
if ((x == 0 || x == 4)&&(i == 0 || i == 7)) {
Cube_Set_Layer(i,RED);
} else if ((x == 1 || x == 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,YELLOW);
} else if ((x == 2 || x == 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,GREEN);
} else if ((x == 3 || x == 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,BLUE);
}
 
if ((x == 0 || x == 4)&&(i > 0 && i < 8)) {
for (j = 0; j < 8; j++) {
Cube_Set_Pixel(i,j,0,RED);
Cube_Set_Pixel(i,j,7,RED);
Cube_Set_Pixel(i,0,j,RED);
Cube_Set_Pixel(i,7,j,RED);
}
}
if ((x == 1 || x == 4)&&(i > 1 && i < 7)) {
for (j = 1; j < 7; j++) {
Cube_Set_Pixel(i,j,1,YELLOW);
Cube_Set_Pixel(i,j,6,YELLOW);
Cube_Set_Pixel(i,1,j,YELLOW);
Cube_Set_Pixel(i,6,j,YELLOW);
}
}
if ((x == 2 || x == 4)&&(i > 2 && i < 6)) {
for (j = 2; j < 6; j++) {
Cube_Set_Pixel(i,j,2,GREEN);
Cube_Set_Pixel(i,j,5,GREEN);
Cube_Set_Pixel(i,2,j,GREEN);
Cube_Set_Pixel(i,5,j,GREEN);
}
}
}
Delay_MS(delay_ms);
}
}
 
void Animation_Cube_In_Out(uint16_t delay_ms, uint16_t r, uint16_t g, uint16_t b) {
uint8_t x,i,j,k;
for (x = 0; x < 7; x++) {
Cube_Clear();
for (i = 0; i < CUBE_LAYER_COUNT; i++) {
if ((x == 0 || x == 6)&&(i == 0 || i == 7)) {
Cube_Set_Layer(i,r,g,b);
} else if ((x == 1 || x == 5)&&(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 ((x == 2 || x == 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 ((x == 3)&&(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 ((x == 0 || x == 6)&&(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 ((x == 1 || x == 5)&&(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 ((x == 2 || x == 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);
}
}
}
Delay_MS(delay_ms);
}
}
 
void Animation_Double_Rotation(uint16_t delay_ms) {
Cube_Clear();
uint8_t x,y,z;
for (z = 0; z < 3; z++) {
switch (z % 3) {
case 0:
for (y = 0; y < CUBE_LAYER_COUNT; y++) {
Cube_Set_Pixel(y,0,0,RED);
Cube_Set_Pixel(y,1,1,RED);
Cube_Set_Pixel(y,2,2,RED);
Cube_Set_Pixel(y,3,3,RED);
Cube_Set_Pixel(y,4,4,RED);
Cube_Set_Pixel(y,5,5,RED);
Cube_Set_Pixel(y,6,6,RED);
Cube_Set_Pixel(y,7,7,RED);
}
break;
case 1:
for (y = 0; y < CUBE_LAYER_COUNT; y++) {
Cube_Set_Pixel(y,0,0,GREEN);
Cube_Set_Pixel(y,1,1,GREEN);
Cube_Set_Pixel(y,2,2,GREEN);
Cube_Set_Pixel(y,3,3,GREEN);
Cube_Set_Pixel(y,4,4,GREEN);
Cube_Set_Pixel(y,5,5,GREEN);
Cube_Set_Pixel(y,6,6,GREEN);
Cube_Set_Pixel(y,7,7,GREEN);
}
break;
case 2:
for (y = 0; y < CUBE_LAYER_COUNT; y++) {
Cube_Set_Pixel(y,0,0,BLUE);
Cube_Set_Pixel(y,1,1,BLUE);
Cube_Set_Pixel(y,2,2,BLUE);
Cube_Set_Pixel(y,3,3,BLUE);
Cube_Set_Pixel(y,4,4,BLUE);
Cube_Set_Pixel(y,5,5,BLUE);
Cube_Set_Pixel(y,6,6,BLUE);
Cube_Set_Pixel(y,7,7,BLUE);
}
break;
}
 
for (x = 0; x < 28; x++) {
Delay_MS(delay_ms);
Cube_Rotate(0);
}
}
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/ANIMATIONS.h
0,0 → 1,18
#ifndef ANIMATIONS_H
#define ANIMATIONS_H
 
void Animation_Solid_Colors(uint16_t delay_ms);
void Animation_Layer_Alternate(uint16_t delay_ms);
void Animation_Pixel_Alternate(uint16_t delay_ms);
void Animation_Full_Color_Sweep(uint16_t delay_us);
void Animation_Row_Column_Sweep(uint16_t delay_ms);
void Animation_Pixel_Sweep(uint16_t delay_ms);
void Animation_Pseudo_Random_Colors(uint16_t delay_ms);
void Animation_Random_Colors(uint16_t delay_ms);
void Animation_Cube_In_Cube(uint16_t delay_ms);
void Animation_Double_Rotation(uint16_t delay_ms);
 
void Animation_Cube_In_Out(uint16_t delay_ms, uint16_t r, uint16_t g, uint16_t b);
 
#endif /* ANIMATIONS_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/SNAKE.c
0,0 → 1,186
#include "defines.h"
#include "CONTROLLERS.h"
#include "SNAKE.h"
 
static SNAKE_DATA *data_p;
static uint32_t rand_value __attribute__((persistent));
 
void Snake_Init(SNAKE_DATA *data) {
data_p = data;
 
// Set starting point
data_p->body[0] = (SNAKE_POINT){0,0,7};
 
data_p->pos_head = 0;
data_p->pos_tail = 0;
data_p->length = 1;
data_p->level = 1;
data_p->delay = 800;
 
srand(rand_value);
 
// Generate a starting location for the candy
data_p->candy_loc = Snake_Generate_Candy();
 
// Draw the snake (head)
Cube_Clear();
uint32_t index = data_p->pos_head;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
while (index != data_p->pos_tail) {
if (data_p->length > 1) {
index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
}
}
}
 
void Snake_Main(void) {
// Main function, loops and delays while updating the frame every x milliseconds
Delay_MS(2000);
while (1) {
// Regenerate the seed upon each update so that the candy starts somewhere new every time
rand_value = rand();
Snake_Update_Frame();
Delay_MS(data_p->delay);
}
}
 
void Snake_Update_Direction(uint8_t p1, uint8_t p2) {
// Determine the next direction for the snake based off the last button press
SNAKE_DIRECTION dir;
dir.value = p1 | p2;
data_p->last_direction = dir.value;
 
SNAKE_POINT point = data_p->body[data_p->pos_head];
if (dir.up) {
point.z = (point.z == CUBE_LAYER_COUNT - 1) ? 0 : point.z + 1;
} else if (dir.down) {
point.z = (point.z == 0) ? CUBE_LAYER_COUNT - 1 : point.z - 1;
} else if (dir.forward) {
point.x = (point.x == CUBE_ROW_COUNT - 1) ? 0 : point.x + 1;
} else if (dir.right) {
point.y = (point.y == CUBE_COLUMN_COUNT - 1) ? 0 : point.y + 1;
} else if (dir.backward) {
point.x = (point.x == 0) ? CUBE_ROW_COUNT - 1 : point.x - 1;
} else if (dir.left) {
point.y = (point.y== 0) ? CUBE_COLUMN_COUNT - 1 : point.y - 1;
}
 
data_p->direction = point;
 
// Update the overlay with the candy location
Cube_Overlay_Clear();
Cube_Overlay_Set_Pixel(data_p->candy_loc.z, data_p->candy_loc.x, data_p->candy_loc.y, SNAKE_CANDY_COLOR);
}
 
void Snake_Update_Frame(void) {
uint8_t om_nom_nom = 0;
 
// Check if we are moving onto a candy, if so extend body
if (data_p->direction.x == data_p->candy_loc.x &&
data_p->direction.y == data_p->candy_loc.y &&
data_p->direction.z == data_p->candy_loc.z) {
data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
data_p->body[data_p->pos_head] = data_p->direction;
data_p->length++;
data_p->candy_loc = Snake_Generate_Candy();
om_nom_nom = 1;
}
 
// Check if the location that we are moving to is overlapping the body
uint32_t pos = data_p->pos_tail;
while (pos != data_p->pos_head) {
if (data_p->direction.x == data_p->body[pos].x &&
data_p->direction.y == data_p->body[pos].y &&
data_p->direction.z == data_p->body[pos].z) {
// Indicate the overlapping pixel, delay, then return to idle state
Cube_Set_Pixel(data_p->direction.z, data_p->direction.x, data_p->direction.y, SNAKE_COLLISION_COLOR);
Delay_MS(3000);
Cube_Overlay_Clear();
Animation_Cube_In_Out(200, ORANGE);
Reset_Board(BOARD_MODE_IDLE);
}
pos = (pos == CUBE_PIXELS - 1) ? 0 : pos + 1;
}
 
// If we didnt eat a candy, increment the frame to move the body along
if (!om_nom_nom) {
data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
data_p->pos_tail = (data_p->pos_tail == CUBE_PIXELS - 1) ? 0 : data_p->pos_tail + 1;
data_p->body[data_p->pos_head] = data_p->direction;
}
 
// Draw updated snake location
Cube_Clear();
uint32_t index = data_p->pos_head;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
while (index != data_p->pos_tail) {
if (data_p->length > 1) {
index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
}
}
 
// Determine the next direction to take
Snake_Update_Direction(data_p->last_direction, 0x0);
 
// If we ate a candy, delay for a bit to rest
if (om_nom_nom) {
// Increase the level by one, show on controller if necessary
data_p->level += 1;
if (data_p->level % SNAKE_LEVEL_STEP == 0) {
uint8_t tier = data_p->level / SNAKE_LEVEL_STEP;
Controller_Set_Leds(tier, tier);
}
// Decrease the delay between frame updates by 5ms
data_p->delay -= 5;
// Clear the watchdog timer to prevent resets in a middle of a game
ClearWDT();
}
}
 
SNAKE_POINT Snake_Generate_Candy(void) {
// Generates a random position within the cube that doesnt overlap anything
SNAKE_POINT ret;
uint32_t x, y, z, brk = 0;
while(1) {
x = rand() % 8;
y = rand() % 8;
z = rand() % 8;
 
if (data_p->length != 1) {
uint32_t pos = data_p->pos_tail;
uint32_t overlap = 0;
// Iterate through the frame till we finish or find an overlap
while (pos != data_p->pos_head) {
if (data_p->body[pos].x == x &&
data_p->body[pos].y == y &&
data_p->body[pos].z == z) {
overlap = 1;
break;
} else {
pos = (pos == CUBE_PIXELS - 1) ? 0 : pos + 1;
}
}
if (!overlap)
brk = 1;
} else {
uint32_t pos = data_p->pos_tail;
if (data_p->body[pos].x != x &&
data_p->body[pos].y != y &&
data_p->body[pos].z != z) {
brk = 1;
}
}
 
if (brk)
break;
}
 
ret.x = x;
ret.y = y;
ret.z = z;
return ret;
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/SNAKE.h
0,0 → 1,52
#ifndef SNAKE_H
#define SNAKE_H
 
#include "CUBE.h"
 
#define SNAKE_BODY_COLOR BLUE
#define SNAKE_HEAD_COLOR RED
#define SNAKE_CANDY_COLOR GREEN
#define SNAKE_COLLISION_COLOR ORANGE
 
#define SNAKE_LEVEL_STEP 10
 
typedef struct {
unsigned x :8;
unsigned y :8;
unsigned z :8;
unsigned :8;
} SNAKE_POINT;
 
typedef union {
struct {
unsigned up :1;
unsigned down :1;
unsigned left :1;
unsigned backward :1;
unsigned right :1;
unsigned forward :1;
unsigned :2;
};
uint8_t value;
} SNAKE_DIRECTION;
 
typedef struct {
SNAKE_POINT body[CUBE_PIXELS];
SNAKE_POINT direction;
SNAKE_POINT candy_loc;
uint8_t last_direction;
uint32_t pos_head;
uint32_t pos_tail;
uint32_t length;
uint32_t level;
uint32_t delay;
} SNAKE_DATA;
 
void Snake_Init(SNAKE_DATA *data);
void Snake_Main(void);
void Snake_Update_Direction(uint8_t p1, uint8_t p2);
void Snake_Update_Frame(void);
SNAKE_POINT Snake_Generate_Candy(void);
 
#endif /* SNAKE_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/TRON.h
0,0 → 1,64
#ifndef TRON_H
#define TRON_H
 
#include "CUBE.h"
 
#define TRON_PLAYER_1_COLOR GREEN
#define TRON_PLAYER_2_COLOR PURPLE
#define TRON_PLAYER_1_HEAD BLUE
#define TRON_PLAYER_2_HEAD RED
#define TRON_COLLISION ORANGE
 
typedef struct {
unsigned x :8;
unsigned y :8;
unsigned z :8;
unsigned :8;
} TRON_POINT;
 
typedef union {
struct {
unsigned up :1;
unsigned down :1;
unsigned right :1;
unsigned forward :1;
unsigned left :1;
unsigned backward :1;
unsigned :2;
};
uint8_t value;
} TRON_P1_DIRECTION;
 
typedef union {
struct {
unsigned up :1;
unsigned down :1;
unsigned left :1;
unsigned backward :1;
unsigned right :1;
unsigned forward :1;
unsigned :2;
};
uint8_t value;
} TRON_P2_DIRECTION;
 
typedef struct {
TRON_POINT p1_body[CUBE_PIXELS];
TRON_POINT p1_direction;
uint8_t p1_last_direction;
 
TRON_POINT p2_body[CUBE_PIXELS];
TRON_POINT p2_direction;
uint8_t p2_last_direction;
uint32_t length;
uint32_t delay;
} TRON_DATA;
 
void Tron_Init(TRON_DATA *data);
void Tron_Main(void);
void Tron_Update_Direction(uint8_t p1, uint8_t p2);
void Tron_Update_Frame(void);
 
#endif /* TRON_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/CONTROLLERS.c
0,0 → 1,145
#include "defines.h"
#include "CONTROLLERS.h"
#include "I2C1.h"
 
static CONTROLLER_DATA *ctrl_data_p;
 
void Controller_Init(CONTROLLER_DATA *data,
void (*btn_change_callback)(uint8_t, uint8_t)) {
ctrl_data_p = data;
 
ctrl_data_p->btn_change_callback = btn_change_callback;
ctrl_data_p->ctrl_1_connected = 0;
ctrl_data_p->ctrl_1_buttons_prev = CONTROLLER_BTN_DEFAULT;
ctrl_data_p->ctrl_1_leds = CONTROLLER_LED_DEFAULT;
ctrl_data_p->ctrl_1_active = 0;
 
ctrl_data_p->ctrl_2_connected = 0;
ctrl_data_p->ctrl_2_buttons_prev = CONTROLLER_BTN_DEFAULT;
ctrl_data_p->ctrl_2_leds = CONTROLLER_LED_DEFAULT;
ctrl_data_p->ctrl_2_active = 0;
}
 
void Controller_Update(void) {
uint8_t buffer[2];
uint8_t result, length;
uint8_t ctrl_1_btn = 0, ctrl_2_btn = 0;
 
// Read button values from controllers
I2C1_Master_Restart(CONTROLLER_1_ADDRESS, CONTROLLER_READ, 1);
do {
result = I2C1_Get_Status();
} while (!result);
if (result == I2C1_RECV_OK) {
// Indicate that controller 1 is connected
LED1_LAT = 1;
ctrl_data_p->ctrl_1_connected = 1;
length = I2C1_Read_Buffer(buffer);
buffer[0] = ~buffer[0];
// Button change detected
if (ctrl_data_p->ctrl_1_buttons_prev != buffer[0]) {
// Check if a button has been pressed since startup
if (!ctrl_data_p->ctrl_1_active) {
ctrl_data_p->ctrl_1_active = 1;
}
// Figure out which button has changed
ctrl_1_btn = ctrl_data_p->ctrl_1_buttons_prev ^ buffer[0];
// Save the button if it went from unpressed -> pressed
ctrl_1_btn &= buffer[0];
}
ctrl_data_p->ctrl_1_buttons_prev = buffer[0];
} else {
LED1_LAT = 0;
ctrl_data_p->ctrl_1_connected = 0;
ctrl_data_p->ctrl_1_active = 0;
}
 
I2C1_Master_Restart(CONTROLLER_2_ADDRESS, CONTROLLER_READ, 1);
do {
result = I2C1_Get_Status();
} while (!result);
if (result == I2C1_RECV_OK) {
// Indicate that controller 2 is connected
LED2_LAT = 1;
ctrl_data_p->ctrl_2_connected = 1;
length = I2C1_Read_Buffer(buffer);
buffer[0] = ~buffer[0];
// Button change detected
if (ctrl_data_p->ctrl_2_buttons_prev != buffer[0]) {
// Check if a button has been pressed since startup
if (!ctrl_data_p->ctrl_2_active) {
ctrl_data_p->ctrl_2_active = 1;
}
// Figure out which button has changed
ctrl_2_btn = ctrl_data_p->ctrl_2_buttons_prev ^ buffer[0];
// Save the button if it went from unpressed -> pressed
ctrl_2_btn &= buffer[0];
}
ctrl_data_p->ctrl_2_buttons_prev = buffer[0];
} else {
LED2_LAT = 0;
ctrl_data_p->ctrl_2_connected = 0;
ctrl_data_p->ctrl_2_active = 0;
}
 
// Write LED values to controllers
if (ctrl_data_p->ctrl_1_connected) {
buffer[0] = CONTROLLER_WRITE;
buffer[1] = ctrl_data_p->ctrl_1_leds;
I2C1_Master_Send(CONTROLLER_1_ADDRESS, buffer, 2);
do {
result = I2C1_Get_Status();
} while (!result);
}
 
if (ctrl_data_p->ctrl_2_connected) {
buffer[0] = CONTROLLER_WRITE;
buffer[1] = ctrl_data_p->ctrl_2_leds;
I2C1_Master_Send(CONTROLLER_2_ADDRESS, buffer, 2);
do {
result = I2C1_Get_Status();
} while (!result);
}
 
// If board is in an idle state and a controller is connected, switch modes
if (Get_Board_State() == BOARD_MODE_IDLE) {
// If both controllers are active, go into game TRON mode
if (ctrl_data_p->ctrl_1_active && ctrl_data_p->ctrl_2_active) {
Reset_Board(BOARD_MODE_TRON);
}
// Otherwise if only one controller is active, go into game SNAKE mode
if (ctrl_data_p->ctrl_1_active || ctrl_data_p->ctrl_2_active) {
Reset_Board(BOARD_MODE_SNAKE);
}
}
if (Get_Board_State() == BOARD_MODE_SNAKE) {
// If both controllers are active, go into game TRON mode
if (ctrl_data_p->ctrl_1_active && ctrl_data_p->ctrl_2_active) {
Reset_Board(BOARD_MODE_TRON);
}
}
 
// Call the callback function if any buttons have changed
if (ctrl_data_p->btn_change_callback != NULL) {
if (ctrl_1_btn || ctrl_2_btn) {
(*ctrl_data_p->btn_change_callback)(ctrl_1_btn, ctrl_2_btn);
}
}
}
 
void Controller_Set_Leds(uint8_t ctrl_1, uint8_t ctrl_2) {
ctrl_data_p->ctrl_1_leds = ctrl_1;
ctrl_data_p->ctrl_2_leds = ctrl_2;
}
 
uint8_t Controller_Query(void) {
// Returns the active status of attached controllers
if (ctrl_data_p->ctrl_1_active && ctrl_data_p->ctrl_2_active)
return 0x3;
else if (ctrl_data_p->ctrl_1_active)
return 0x1;
else if (ctrl_data_p->ctrl_2_active)
return 0x2;
return 0;
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/CONTROLLERS.h
0,0 → 1,35
#ifndef CONTROLLERS_H
#define CONTROLLERS_H
 
#define CONTROLLER_READ 0xA
#define CONTROLLER_WRITE 0xB
 
#define CONTROLLER_BTN_DEFAULT 0xC0
#define CONTROLLER_LED_DEFAULT 0x00
 
#define CONTROLLER_1_ADDRESS 0x24
#define CONTROLLER_2_ADDRESS 0x25
 
typedef struct {
void (*btn_change_callback)(uint8_t ctrl_1, uint8_t ctrl_2);
 
uint8_t ctrl_1_connected;
uint8_t ctrl_1_buttons_prev;
uint8_t ctrl_1_leds;
uint8_t ctrl_1_active;
uint8_t ctrl_2_connected;
uint8_t ctrl_2_buttons_prev;
uint8_t ctrl_2_leds;
uint8_t ctrl_2_active;
} CONTROLLER_DATA;
 
void Controller_Init(CONTROLLER_DATA *data,
void (*btn_change_callback)(uint8_t, uint8_t));
void Controller_Update(void);
void Controller_Set_Leds(uint8_t ctrl_1, uint8_t ctrl_2);
void Controller_Btn_Change(void (*callback)(uint8_t, uint8_t));
uint8_t Controller_Query(void);
 
#endif /* CONTROLLERS_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/I2C1.c
0,0 → 1,460
#include "defines.h"
#include "I2C1.h"
 
static I2C1_DATA *i2c_data_p;
 
// Initialize the data structures, should be called once before any I2C routines are called
void I2C1_Init(I2C1_DATA *data, uint8_t speed, uint8_t address) {
i2c_data_p = data;
 
i2c_data_p->buffer_in_len = 0;
i2c_data_p->buffer_in_read_ind = 0;
i2c_data_p->buffer_in_write_ind = 0;
 
i2c_data_p->buffer_out_ind = 0;
i2c_data_p->buffer_out_len = 0;
 
i2c_data_p->operating_state = I2C1_IDLE;
i2c_data_p->return_status = 0;
 
i2c_data_p->slave_in_last_byte = 0;
i2c_data_p->slave_sending_data = 0;
 
i2c_data_p->master_dest_addr = 0;
i2c_data_p->master_status = I2C1_MASTER_IDLE;
 
INTDisableInterrupts();
 
// Enable the I2C module and set the clock stretch enable bit
// Note: Automatically overrides any other pin settings
I2C1CONSET = 0x00008040;
I2C1ADD = address;
if (!speed) I2C1BRG = 0x05A; // Operate at 400kHZ (80MHz)
else I2C1BRG = 0x186; // Operate at 100kHZ (80MHz)
IFS0CLR = 0xE0000000; // Clear any existing events
IPC6CLR = 0x00001F00; // Reset priority levels
IPC6SET = 0x00001500; // Set IPL=5, Subpriority 1
IEC0SET = 0xE0000000; // Enable I2C1 interrupts
 
INTEnableInterrupts();
}
 
// Sends length number of bytes in msg to specified address (no R/W bit)
// Will return status I2C1_SEND_OK or I2C1_SEND_FAIL
void I2C1_Master_Send(uint8_t address, uint8_t *msg, uint32_t length) {
uint32_t i;
if (length == 0)
return;
 
// Copy message to send into buffer and save length/address
for (i = 0; i < length; i++) {
i2c_data_p->buffer_in[i] = msg[i];
}
i2c_data_p->buffer_in_len = length;
i2c_data_p->master_dest_addr = address;
i2c_data_p->buffer_in_read_ind = 0;
i2c_data_p->buffer_in_write_ind = 0;
 
// Change status to 'next' operation
i2c_data_p->operating_state = I2C1_SEND_ADDR;
i2c_data_p->master_status = I2C1_MASTER_SEND;
 
// Generate start condition
I2C1CONbits.SEN = 1;
}
 
// Reads length number of bytes from address (no R/W bit)
// Will return status I2C1_RECV_OK or I2C1_RECV_FAIL
void I2C1_Master_Recv(uint8_t address, uint32_t length) {
if (length == 0)
return;
 
// Save length and address to get data from
i2c_data_p->buffer_in_len = length;
i2c_data_p->master_dest_addr = address;
i2c_data_p->buffer_in_read_ind = 0;
i2c_data_p->buffer_in_write_ind = 0;
 
// Change status to 'next' operation
i2c_data_p->operating_state = I2C1_SEND_ADDR;
i2c_data_p->master_status = I2C1_MASTER_RECV;
 
// Generate start condition
I2C1CONbits.SEN = 1;
}
 
// Writes msg to address then reads length number of bytes from address
// Will return status I2C1_SEND_FAIL or I2C1_RECV_FAIL or I2C1_RECV_OK
void I2C1_Master_Restart(uint8_t address, uint8_t msg, uint32_t length) {
uint8_t c;
if (length == 0) {
c = msg;
I2C1_Master_Send(address, &c, 1);
return;
}
 
// Save length and address to get data from
i2c_data_p->buffer_in[0] = msg;
i2c_data_p->buffer_in_len = length;
i2c_data_p->master_dest_addr = address;
i2c_data_p->buffer_in_read_ind = 0;
i2c_data_p->buffer_in_write_ind = 0;
 
// Change status to 'next' operation
i2c_data_p->operating_state = I2C1_SEND_ADDR;
i2c_data_p->master_status = I2C1_MASTER_RESTART;
 
// Generate start condition
I2C1CONbits.SEN = 1;
}
 
void __ISR(_I2C_1_VECTOR, ipl5) __I2C_1_Interrupt_Handler(void) {
// Bus collision event
if (IFS0bits.I2C1BIF) {
// TODO: Handle bus collision events here
IFS0CLR = 0x20000000;
}
// Slave event
if (IFS0bits.I2C1SIF) {
I2C1_Interrupt_Slave();
IFS0CLR = 0x40000000;
}
// Master event
if (IFS0bits.I2C1MIF) {
I2C1_Interrupt_Master();
IFS0CLR = 0x80000000;
}
}
 
// An internal subroutine used in the master version of the i2c_interrupt_handler
void I2C1_Interrupt_Master() {
 
/* The PIC32 family has different master interrupts than the PIC8 family
* Master mode operations that generate a slave interrupt are:
* 1. Start condition
* 2. Repeated start sequence
* 3. Stop condition
* 4. Data transfer byte received
* 5. During a send ACK or NACK sequence to slave
* 6. Data transfer byte transmitted
* 7. During a slave-detected stop
*/
 
if (I2C1STATbits.IWCOL == 1) {
// TODO: Handle write collisions
I2C1STATbits.IWCOL = 0;
}
 
// If we are in the middle of sending data
if (i2c_data_p->master_status == I2C1_MASTER_SEND) {
switch (i2c_data_p->operating_state) {
case I2C1_IDLE:
break;
case I2C1_SEND_ADDR:
// Send the address with read bit set
i2c_data_p->operating_state = I2C1_CHECK_ACK_SEND;
I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x0;
break;
case I2C1_CHECK_ACK_SEND:
// Check if ACK is received or not
if (!I2C1STATbits.ACKSTAT) {
// If an ACK is received, send next byte of data
if (i2c_data_p->buffer_in_read_ind < i2c_data_p->buffer_in_len) {
I2C1TRN = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
i2c_data_p->buffer_in_read_ind++;
} else {
// If no more data is to be sent, send stop bit
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_SEND_OK;
}
} else {
// If a NACK is received, stop transmission and send error
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_SEND_FAIL;
}
break;
case I2C1_STOPPED:
i2c_data_p->operating_state = I2C1_IDLE;
i2c_data_p->master_status = I2C1_MASTER_IDLE;
break;
}
// If we are in the middle of receiving data
} else if (i2c_data_p->master_status == I2C1_MASTER_RECV) {
switch (i2c_data_p->operating_state) {
case I2C1_IDLE:
break;
case I2C1_SEND_ADDR:
// Send address with write bit set
i2c_data_p->operating_state = I2C1_CHECK_ACK_RECV;
I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x1;
break;
case I2C1_CHECK_ACK_RECV:
// Check if ACK is received
if (!I2C1STATbits.ACKSTAT) {
// If an ACK is received, set module to receive 1 byte of data
i2c_data_p->operating_state = I2C1_RCV_DATA;
I2C1CONbits.RCEN = 1;
} else {
// If a NACK is received, stop transmission and send error
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_RECV_FAIL;
}
break;
case I2C1_RCV_DATA:
// On receive, save byte into buffer
// TODO: Handle possible I2C buffer overflow
i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = I2C1RCV;
i2c_data_p->buffer_in_write_ind++;
if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
// If we still need to read, send an ACK to the slave
i2c_data_p->operating_state = I2C1_REQ_DATA;
I2C1CONbits.ACKDT = 0; // ACK
I2C1CONbits.ACKEN = 1;
} else {
// If we are done reading, send an NACK to the slave
i2c_data_p->operating_state = I2C1_SEND_STOP;
I2C1CONbits.ACKDT = 1; // NACK
I2C1CONbits.ACKEN = 1;
}
break;
case I2C1_REQ_DATA:
// Set module to receive one byte of data
i2c_data_p->operating_state = I2C1_RCV_DATA;
I2C1CONbits.RCEN = 1;
break;
case I2C1_SEND_STOP:
// Send the stop bit
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_RECV_OK;
break;
case I2C1_STOPPED:
i2c_data_p->operating_state = I2C1_IDLE;
i2c_data_p->master_status = I2C1_MASTER_IDLE;
break;
}
} else if (i2c_data_p->master_status == I2C1_MASTER_RESTART) {
switch (i2c_data_p->operating_state) {
case I2C1_IDLE:
break;
case I2C1_SEND_ADDR:
// Send the address with read bit set
i2c_data_p->operating_state = I2C1_CHECK_ACK_SEND;
I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x0;
break;
case I2C1_CHECK_ACK_SEND:
// Check if ACK is received or not
if (!I2C1STATbits.ACKSTAT) {
// If an ACK is received, send first byte of data
I2C1TRN = i2c_data_p->buffer_in[0];
i2c_data_p->operating_state = I2C1_CHECK_ACK_RESTART;
} else {
// If a NACK is received, stop transmission and send error
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_SEND_FAIL;
}
break;
case I2C1_CHECK_ACK_RESTART:
if (!I2C1STATbits.ACKSTAT) {
I2C1CONbits.RSEN = 1;
i2c_data_p->operating_state = I2C1_SEND_ADDR_2;
} else {
// If a NACK is received, stop transmission and send error
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_SEND_FAIL;
}
break;
case I2C1_SEND_ADDR_2:
// Send the address with read bit set
i2c_data_p->operating_state = I2C1_CHECK_ACK_RECV;
I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x1;
break;
case I2C1_CHECK_ACK_RECV:
// Check if ACK is received
if (!I2C1STATbits.ACKSTAT) {
// If an ACK is received, set module to receive 1 byte of data
i2c_data_p->operating_state = I2C1_RCV_DATA;
I2C1CONbits.RCEN = 1;
} else {
// If a NACK is received, stop transmission and send error
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_RECV_FAIL;
}
break;
case I2C1_RCV_DATA:
// On receive, save byte into buffer
// TODO: Handle possible I2C buffer overflow
i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = I2C1RCV;
i2c_data_p->buffer_in_write_ind++;
if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
// If we still need to read, send an ACK to the slave
i2c_data_p->operating_state = I2C1_REQ_DATA;
I2C1CONbits.ACKDT = 0; // ACK
I2C1CONbits.ACKEN = 1;
} else {
// If we are done reading, send an NACK to the slave
i2c_data_p->operating_state = I2C1_SEND_STOP;
I2C1CONbits.ACKDT = 1; // NACK
I2C1CONbits.ACKEN = 1;
}
break;
case I2C1_REQ_DATA:
// Set module to receive one byte of data
i2c_data_p->operating_state = I2C1_RCV_DATA;
I2C1CONbits.RCEN = 1;
break;
case I2C1_SEND_STOP:
// Send the stop bit
i2c_data_p->operating_state = I2C1_STOPPED;
I2C1CONbits.PEN = 1;
i2c_data_p->return_status = I2C1_RECV_OK;
break;
case I2C1_STOPPED:
i2c_data_p->operating_state = I2C1_IDLE;
i2c_data_p->master_status = I2C1_MASTER_IDLE;
break;
}
}
}
 
void I2C1_Interrupt_Slave() {
// !!WARNING!! THIS CODE DOES -NOT- HAVE ANY ERROR HANDLING !!
// TODO: Add error handling to this interrupt function
 
/* The PIC32 family has different slave interrupts than the PIC8 family
* Slave mode operations that generate a slave interrupt are:
* 1. Detection of a valid device address (including general call)
* 2. Reception of data
* 3. Request to transmit data
*/
 
uint8_t received_data;
uint8_t data_read_from_buffer = 0;
uint8_t data_written_to_buffer = 0;
uint8_t overrun_error = 0;
 
// Clear SSPOV (overflow bit)
if (I2C1STATbits.I2COV == 1) {
I2C1STATbits.I2COV = 0;
overrun_error = 1;
i2c_data_p->return_status = I2C1_ERR_OVERRUN;
}
 
// Read SPPxBUF if it is full
if (I2C1STATbits.RBF == 1) {
received_data = I2C1RCV;
data_read_from_buffer = 1;
}
 
if (!overrun_error) {
if (I2C1STATbits.R_W == 0) {
// Slave is receiving data
i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = received_data;
if (i2c_data_p->buffer_in_write_ind == MAXI2C1BUF - 1) {
i2c_data_p->buffer_in_write_ind = 0;
} else {
i2c_data_p->buffer_in_write_ind++;
}
if (i2c_data_p->buffer_in_len < MAXI2C1BUF - 1) {
i2c_data_p->buffer_in_len++;
}
i2c_data_p->slave_in_last_byte = received_data;
i2c_data_p->return_status = I2C1_RECV_OK;
} else {
// Slave is returning data
if (!i2c_data_p->slave_sending_data) {
// If we are not currently sending data, figure out what to reply with
if (I2C1_Process_Request(i2c_data_p->slave_in_last_byte)) {
// Data exists to be returned, send first byte
I2C1TRN = i2c_data_p->buffer_out[0];
data_written_to_buffer = 1;
i2c_data_p->buffer_out_ind = 1;
i2c_data_p->slave_sending_data = 1;
} else {
// Unknown request, fill rest of request with 0s
I2C1TRN = 0x0;
data_written_to_buffer = 1;
i2c_data_p->slave_sending_data = 0;
i2c_data_p->return_status = I2C1_SEND_FAIL;
}
} else {
// Sending remaining data back to master
if (i2c_data_p->buffer_out_ind < i2c_data_p->buffer_out_len) {
I2C1TRN = i2c_data_p->buffer_out[i2c_data_p->buffer_out_ind];
data_written_to_buffer = 1;
i2c_data_p->buffer_out_ind++;
} else {
// Nothing left to send, fill rest of request with 0s
I2C1TRN = 0x0;
data_written_to_buffer = 1;
i2c_data_p->slave_sending_data = 0;
i2c_data_p->return_status = I2C1_SEND_OK;
}
}
}
}
 
// Release the clock stretching bit (if we should)
if (data_read_from_buffer || data_written_to_buffer) {
// Release the clock
if (I2C1CONbits.SCLREL == 0) {
I2C1CONbits.SCLREL = 1;
}
}
}
 
/* Returns 0 if I2C module is currently busy, otherwise returns status code */
uint8_t I2C1_Get_Status() {
if (i2c_data_p->master_status == I2C1_MASTER_IDLE &&
i2c_data_p->operating_state == I2C1_IDLE &&
I2C1STATbits.TBF == 0) {
return i2c_data_p->return_status;
} else {
return 0;
}
}
 
uint8_t I2C1_Buffer_Len() {
return i2c_data_p->buffer_in_len;
}
 
/* Returns 0 if I2C module is currently busy, otherwise returns buffer length */
uint8_t I2C1_Read_Buffer(uint8_t *buffer) {
uint32_t i = 0;
while (i2c_data_p->buffer_in_len != 0) {
buffer[i] = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
i++;
if (i2c_data_p->buffer_in_read_ind == MAXI2C1BUF-1) {
i2c_data_p->buffer_in_read_ind = 0;
} else {
i2c_data_p->buffer_in_read_ind++;
}
i2c_data_p->buffer_in_len--;
}
return i;
}
 
/* Put data to be returned here */
uint8_t I2C1_Process_Request(uint8_t c) {
uint8_t ret = 0;
switch (c) {
case 0x01:
i2c_data_p->buffer_out[0] = 0x12;
i2c_data_p->buffer_out_len = 1;
ret = 1;
break;
case 0x02:
i2c_data_p->buffer_out[0] = 0x34;
i2c_data_p->buffer_out[1] = 0x56;
i2c_data_p->buffer_out_len = 2;
ret = 1;
break;
}
return ret;
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/TIMER4.c
0,0 → 1,59
#include "defines.h"
#include "TIMER4.h"
 
static TIMER4_DATA *timer_data_ptr;
 
void TIMER4_Init(TIMER4_DATA *data, void (*callback_ms)(void),
void (*callback_div)(void), uint32_t time_ms) {
if (data != NULL) // if ptr is null, use existing data
timer_data_ptr = data;
 
// The first callback function will be executed every ms
timer_data_ptr->callback_function_1 = callback_ms;
// The second callback function will be executed at the multiplier specified
timer_data_ptr->callback_function_2 = callback_div;
timer_data_ptr->divider = time_ms;
timer_data_ptr->count = 0;
 
INTDisableInterrupts();
 
T4CON = 0x0;
 
// Set timer to trigger every millisecond
uint16_t time = 5000;
T4CONSET = 0x0040; // Prescaler at 1:16
 
Nop();
TMR4 = 0x0; // Clear timer register
PR4 = time; // Load period register
IPC4SET = 0x00000005; // Set priority level = 1, sub-priority level = 1
IFS0CLR = 0x00010000; // Clear timer interrupt flag
IEC0SET = 0x00010000; // Enable timer interrupt
 
INTEnableInterrupts();
}
 
void TIMER4_Start(void) {
T4CONSET = 0x8000; // Start timer
}
 
void TIMER4_Stop(void) {
T4CONCLR = 0x8000; // Stop timer
}
 
void __ISR(_TIMER_4_VECTOR, ipl4) __TIMER_4_Interrupt_Handler(void) {
// Call the saved callback function
(*timer_data_ptr->callback_function_1)();
 
if (timer_data_ptr->divider != 0 && timer_data_ptr->callback_function_2 != NULL) {
if (timer_data_ptr->count == timer_data_ptr->divider) {
(*timer_data_ptr->callback_function_2)();
timer_data_ptr->count = 0;
} else {
timer_data_ptr->count++;
}
}
 
IFS0CLR = 0x00010000; // Clear the timer interrupt flag
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/TIMER4.h
0,0 → 1,17
#ifndef TIMER4_H
#define TIMER4_H
 
typedef struct {
void (*callback_function_1)(void);
void (*callback_function_2)(void);
uint32_t divider;
uint32_t count;
} TIMER4_DATA;
 
void TIMER4_Init(TIMER4_DATA *data, void (*callback_ms)(void),
void (*callback_div)(void), uint32_t time_ms);
void TIMER4_Start(void);
void TIMER4_Stop(void);
 
#endif /* TIMER4_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/TIMER5.c
0,0 → 1,55
#include "defines.h"
#include "TIMER5.h"
 
static TIMER5_DATA *timer_data_ptr;
 
void TIMER5_Init(TIMER5_DATA *data, void (*callback)(void), uint32_t time_us) {
if (data != NULL) // if ptr is null, use existing data
timer_data_ptr = data;
 
timer_data_ptr->callback_function = callback;
 
INTDisableInterrupts();
 
T5CON = 0x0;
 
// PR5 is 16 bits wide, so we need to determine what pre-scaler to use
uint16_t time;
if (time_us < 13107) {
time = 5 * time_us;
T5CONSET = 0x0040; // Prescaler at 1:16
} else if (time_us < 26214) {
time = 2.5 * time_us;
T5CONSET = 0x0050; // Prescaler at 1:32
} else if (time_us < 52428) {
time = 1.25 * time_us;
T5CONSET = 0x0060; // Prescaler at 1:64
} else { // Maximum time_us of 209712
time = 0.3125 * time_us;
T5CONSET = 0x0070; // Prescaler at 1:256
}
 
Nop();
TMR5 = 0x0; // Clear timer register
PR5 = time; // Load period register
IPC5SET = 0x0000000D; // Set priority level = 3, sub-priority level = 1
IFS0CLR = 0x00100000; // Clear timer interrupt flag
IEC0SET = 0x00100000; // Enable timer interrupt
 
INTEnableInterrupts();
}
 
void TIMER5_Start(void) {
T5CONSET = 0x8000; // Start timer
}
 
void TIMER5_Stop(void) {
T5CONCLR = 0x8000; // Stop timer
}
 
void __ISR(_TIMER_5_VECTOR, ipl4) __TIMER_5_Interrupt_Handler(void) {
// Call the saved callback function
(*timer_data_ptr->callback_function)();
 
IFS0CLR = 0x00100000; // Clear the timer interrupt flag
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/I2C1.h
0,0 → 1,78
#ifndef I2C1_H
#define I2C1_H
 
#define MAXI2C1BUF 32
 
// I2C Operating Speed
#define I2C1_400KHZ 0x0
#define I2C1_100KHZ 0x1
 
// Operating State
#define I2C1_IDLE 0x1
//#define I2C1_STARTED 0x2
#define I2C1_RCV_DATA 0x3
//#define I2C1_SEND_DATA 0x4
#define I2C1_SEND_ADDR 0x5
#define I2C1_SEND_ADDR_2 0x6
#define I2C1_CHECK_ACK_SEND 0x7
#define I2C1_CHECK_ACK_RECV 0x8
#define I2C1_CHECK_ACK_RESTART 0x9
#define I2C1_REQ_DATA 0xA
#define I2C1_SEND_STOP 0xB
//#define I2C1_SEND_START 0xC
#define I2C1_STOPPED 0xD
 
// Operating Mode
#define I2C1_MODE_SLAVE 0x10
#define I2C1_MODE_MASTER 0x11
 
// Master Status
#define I2C1_MASTER_SEND 0x20
#define I2C1_MASTER_RECV 0x21
#define I2C1_MASTER_RESTART 0x22
#define I2C1_MASTER_IDLE 0x23
 
// Return Status
#define I2C1_SEND_OK 0x30
#define I2C1_SEND_FAIL 0x31
#define I2C1_RECV_OK 0x32
#define I2C1_RECV_FAIL 0x33
#define I2C1_DATA_AVAL 0x34
#define I2C1_ERR_NOADDR 0x35
#define I2C1_ERR_OVERRUN 0x36
#define I2C1_ERR_NODATA 0x37
#define I2C1_ERR_BUFFER_OVERRUN 0x38
 
typedef struct {
uint8_t buffer_in[MAXI2C1BUF];
uint32_t buffer_in_len;
uint32_t buffer_in_read_ind;
uint32_t buffer_in_write_ind;
 
uint8_t buffer_out[MAXI2C1BUF];
uint32_t buffer_out_len;
uint32_t buffer_out_ind;
 
uint8_t operating_state;
uint8_t return_status;
 
uint8_t master_dest_addr;
uint8_t master_status;
 
uint8_t slave_in_last_byte;
uint8_t slave_sending_data;
} I2C1_DATA;
 
void I2C1_Init(I2C1_DATA *data, uint8_t speed, uint8_t address);
void I2C1_Master_Send(uint8_t address, uint8_t *msg, uint32_t length);
void I2C1_Master_Recv(uint8_t address, uint32_t length);
void I2C1_Master_Restart(uint8_t address, uint8_t msg, uint32_t length);
void I2C1_Interrupt_Master(void);
void I2C1_Interrupt_Slave(void);
uint8_t I2C1_Get_Status(void);
uint8_t I2C1_Buffer_Len(void);
uint8_t I2C1_Read_Buffer(uint8_t *buffer);
uint8_t I2C1_Process_Request(uint8_t);
 
#endif /* I2C1_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/UART1.c
0,0 → 1,105
#include "defines.h"
#include "UART1.h"
 
static UART1_DATA *uart_data_ptr;
 
/* Note: BRGH values are different from PIC18!
*
* Baud Rate Calculation (BRGH = 0):
* Baud Rate = PerfBusFreq / (16 * (BRG + 1))
* BRG = PerfBusFreq / (16 * Baud Rate) - 1
*
* Baud Rate Calculation (BRGH = 1):
* Baud Rate = PerfBusFreq / (4 * (BRG + 1))
* BRG = PerfBusFreq / (4 * Baud Rate) - 1
*/
 
void UART1_Init(UART1_DATA *data, void (*rx_callback)(uint8_t)) {
uart_data_ptr = data;
uart_data_ptr->rx_callback = rx_callback;
uart_data_ptr->buffer_out_len = 0;
uart_data_ptr->buffer_out_ind = 0;
 
INTDisableInterrupts();
 
IEC0CLR = 0x1C000000; // Disable all UART1 interrupts
IFS0CLR = 0x1C000000; // Clear any existing events
IPC6SET = 0x00000009; // Set Priority = 2, Subpriority = 1
U1MODE = 0x00008008; // UART enabled, BRGH = 1
U1STA = 0x00009400; // TX interrupt on buffer empty, RX interrupt on buffer not empty
 
// U1BRG = 173; // Set baud rate to 115200 @ 80MHz (0.22% error)
U1BRG = 86; // Set baud rate to 230400 @ 80MHz (0.22% error)
// U1BRG = 77; // Set baud rate to 256000 @ 80MHz (0.12% error)
// U1BRG = 42; // Set baud rate to 460800 @ 80MHz (0.94% error)
// U1BRG = 21; // Set baud rate to 921600 @ 80MHz (1.36% error)
IEC0SET = 0x0C000000; // Enable the RX and Error interrupts
 
INTEnableInterrupts();
}
 
uint8_t UART1_Write(uint8_t *string, uint32_t length) {
if (length > UART1_BUFFER_SIZE)
return 0;
if (uart_data_ptr->buffer_out_len != 0)
return 0;
 
// Put the data to send into the outbound buffer
uart_data_ptr->buffer_out_len = length;
uart_data_ptr->buffer_out_ind = 0;
uint8_t i;
for (i = 0; i < length; i++) {
uart_data_ptr->buffer_out[i] = string[i];
}
IEC0SET = 0x10000000; // Enable TX interrupt
return 1;
}
 
void __ISR(_UART_1_VECTOR, ipl2) __UART_1_Interrupt_Handler(void) {
// Process UART1 error flag
if (IFS0bits.U1EIF) {
if (U1STAbits.PERR) { // Process parity error
 
}
if (U1STAbits.FERR) { // Process frame error
 
}
if (U1STAbits.OERR) { // Process receive buffer overrun error
U1STAbits.OERR = 0; // Clear the overrun error if set
}
IFS0CLR = 0x04000000; // Clear the error flag
}
 
// Process UART1 recieve flag
if (IFS0bits.U1RXIF) {
// Read the data received from the last transfer
while (U1STAbits.URXDA) {
uint8_t c = U1RXREG;
// Call the RX callback function on each received data
if (uart_data_ptr->rx_callback != NULL) {
(*uart_data_ptr->rx_callback)(c);
}
}
IFS0CLR = 0x08000000; // Clear the recieve flag
}
 
// Process UART1 transmit flag
if (IFS0bits.U1TXIF && IEC0bits.U1TXIE) {
// Disable the transmit interrupt if all data has been sent
if (uart_data_ptr->buffer_out_ind == uart_data_ptr->buffer_out_len) {
IEC0CLR = 0x10000000;
uart_data_ptr->buffer_out_len = 0;
} else {
// Start filling the transmit buffer
while (!U1STAbits.UTXBF) {
U1TXREG = uart_data_ptr->buffer_out[uart_data_ptr->buffer_out_ind];
uart_data_ptr->buffer_out_ind++;
if (uart_data_ptr->buffer_out_ind == uart_data_ptr->buffer_out_len)
break;
}
}
IFS0CLR = 0x10000000; // Clear the transmit flag
}
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/BTN.c
0,0 → 1,61
#include "defines.h"
#include "BTN.h"
 
static BTN_DATA *btn_data_ptr;
 
void BTN_Init(BTN_DATA *data, void (*callback_1)(void), void (*callback_2)(void), void (*callback_3)(void)) {
btn_data_ptr = data;
btn_data_ptr->callback_function_1 = callback_1;
btn_data_ptr->callback_function_2 = callback_2;
btn_data_ptr->callback_function_3 = callback_3;
 
BTN1_TRIS = 1;
BTN2_TRIS = 1;
BTN3_TRIS = 1;
 
INTDisableInterrupts();
CNCONSET = 0x8000; // Turn on change notice interrupt
#if defined CEREBOT_32MX7
CNENSET = 0x80300; // Set interrupt on CN8/9/19
#elif defined CEREBOT_MX7CK
CNENSET = 0x00300; // Set interrupt on CN8/9
#endif
int32_t tmp = BTN1_PORT;
tmp = BTN2_PORT;
tmp = BTN3_PORT;
IPC6SET = 0xD0000; // Set priority level = 3, sub-priority level = 1
IFS1CLR = 0x1; // Clear interrupt flag
IEC1SET = 0x1; // Enable interrupt
 
INTEnableInterrupts();
}
 
void __ISR(_CHANGE_NOTICE_VECTOR, ipl3) __CN_Interrupt_Handler(void) {
// Upon interrupt, debounce input and call saved function
if (BTN1_PORT == 1) {
Delay_MS(BTN_DEBOUNCE_MS);
if (BTN1_PORT == 1) {
if (btn_data_ptr->callback_function_1 != NULL)
(*btn_data_ptr->callback_function_1)();
}
}
if (BTN2_PORT == 1) {
Delay_MS(BTN_DEBOUNCE_MS);
if (BTN2_PORT == 1) {
if (btn_data_ptr->callback_function_2 != NULL)
(*btn_data_ptr->callback_function_2)();
}
}
#ifdef CEREBOT_32MX7
if (BTN3_PORT == 1) {
Delay_MS(BTN_DEBOUNCE_MS);
if (BTN3_PORT == 1) {
if (btn_data_ptr->callback_function_3 != NULL)
(*btn_data_ptr->callback_function_3)();
}
}
#endif
IFS1CLR = 0x1; // Clear interrupt flag
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/PWM2.c
0,0 → 1,21
#include "defines.h"
#include "PWM2.h"
 
void PWM2_Init(void) {
OC2CON = 0x0000;
OC2R = 0x0001; // PWM initial duty cycle
OC2RS = 0x0001; // PWM duty cycle
OC2CON = 0x0006; // PWM off, 16-bit, timer 2, fault pin disabled
 
IFS0CLR = 0x00000100; // Disable Timer 2 interrupt
T2CONSET = 0x8000; // Turn on Timer 2
PR2 = 0x0003; // PWM period ~ 16-20Mhz
}
 
void PWM2_Start(void) {
OC2CONSET = 0x8000;
}
 
void PWM2_Stop(void) {
OC2CONCLR = 0x8000;
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/SPI1.c
0,0 → 1,118
#include "defines.h"
#include "SPI1.h"
 
static SPI1_DATA *spi_data_ptr;
 
void SPI1_Init(SPI1_DATA *data, void (*rx_callback)(uint8_t)) {
spi_data_ptr = data;
spi_data_ptr->buffer_out_ind = 0;
spi_data_ptr->buffer_out_len = 0;
spi_data_ptr->rx_callback = rx_callback;
INTDisableInterrupts();
 
// Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths
// Alternative Configuration:
// The third value is the SPI bitrate which is 1/2 the frequency of the
// desired clock frequency. Thus 40Mhz / (20Mhz / 2) = 4.
// Note: SPI_OPEN_TBE_NOT_FULL should only be used at >10Mhz speeds
// SpiChnOpen(SPI_CHANNEL1, SPI_OPEN_MSTEN | SPI_OPEN_ENHBUF | SPI_OPEN_TBE_NOT_FULL | SPI_OPEN_RBF_NOT_EMPTY, 4);
// INTSetVectorPriority(INT_SPI_1_VECTOR, INT_PRIORITY_LEVEL_6);
// INTSetVectorSubPriority(INT_SPI_1_VECTOR, INT_SUB_PRIORITY_LEVEL_1);
// INTClearFlag(INT_SPI1E);
// INTClearFlag(INT_SPI1TX);
// INTClearFlag(INT_SPI1RX);
 
// FSCK = FPB / (2 * (SPIxBRG + 1))
IEC0CLR = 0x03800000; // Disable all SPI interrupts
SPI1CON = 0; // Stops and resets the SPI1.
uint32_t tmp = SPI1BUF; // Clears the receive buffer
IFS0CLR = 0x03800000; // Clear any existing event
IPC5CLR = 0x1F000000; // Clear the priority
IPC5SET = 0x19000000; // Set IPL=6, Subpriority 1
SPI1BRG = 0x1; // Use FPB/4 clock frequency
SPI1STATCLR = 0x40; // Clear the Overflow
#ifndef SPI_WRITE_ONLY
IEC0SET = 0x01800000; // Enable RX and Error interrupts
#endif
// Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode
// SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not empty
SPI1CON = 0x18225;
 
INTEnableInterrupts();
}
 
uint8_t SPI1_Write(uint8_t *array, uint32_t length, void (*tx_callback)(void)) {
spi_data_ptr->tx_callback = tx_callback;
 
if (length > SPI1_BUFFER_OUT_SIZE)
return 0;
if (spi_data_ptr->buffer_out_len != 0)
return 0;
 
// Put the data to send into the outbound buffer
spi_data_ptr->buffer_out_len = length;
spi_data_ptr->buffer_out_ind = length-1;
int32_t i;
for (i = 0; i < length; i++) {
spi_data_ptr->buffer_out[i] = array[i];
}
IEC0SET = 0x02000000; // Enable TX interrupt
return 1;
}
 
void __ISR(_SPI_1_VECTOR, ipl6) __SPI_1_Interrupt_Handler(void) {
#ifndef SPI_WRITE_ONLY
// Process SPI1 error flag
if (IFS0bits.SPI1EIF) {
// Clear the receive overflow bit if it is set
if (SPI1STATbits.SPIROV) {
SPI1STATbits.SPIROV = 0;
}
IFS0CLR = 0x00800000; // Clear the error flag
}
 
// Process SPI1 receive flag
if (IFS0bits.SPI1RXIF) {
int32_t i;
// Read the data received from the last transfer
int32_t rxBufferCount = SPI1STATbits.RXBUFELM;
for (i = 0; i < rxBufferCount; i++) {
int8_t c = SPI1BUF;
// Call the RX callback function on the received data
if (spi_data_ptr->rx_callback != NULL)
(*spi_data_ptr->rx_callback)(c);
}
IFS0CLR = 0x01000000; // Clear the RX flag
}
#endif
 
// Process SPI1 transmit flag
if (IFS0bits.SPI1TXIF && IEC0bits.SPI1TXIE) {
int32_t i;
// Disable the transmit interrupt if all data has been sent
if (spi_data_ptr->buffer_out_len == 0) {
IEC0CLR=0x02000000;
if (spi_data_ptr->tx_callback != NULL)
(*spi_data_ptr->tx_callback)();
} else {
// Start transmitting the data in the buffer
int32_t txBufferFree = 16 - SPI1STATbits.TXBUFELM;
if (spi_data_ptr->buffer_out_len > txBufferFree) {
for (i = 0; i < txBufferFree; i++) {
SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
spi_data_ptr->buffer_out_ind--;
}
spi_data_ptr->buffer_out_len -= txBufferFree;
} else {
for (i = 0; i < spi_data_ptr->buffer_out_len; i++) {
SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
spi_data_ptr->buffer_out_ind--;
}
spi_data_ptr->buffer_out_len = 0;
}
}
IFS0CLR = 0x02000000; // Clear the TX flag
}
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/SPI1.h
0,0 → 1,23
#ifndef SPI1_H
#define SPI1_H
 
#define SPI1_BUFFER_OUT_SIZE 300
//#define SPI1_BUFFER_IN_SIZE 10
 
#define SPI_WRITE_ONLY
 
typedef struct {
uint8_t buffer_out[SPI1_BUFFER_OUT_SIZE];
uint32_t buffer_out_ind;
uint32_t buffer_out_len;
 
void (*tx_callback)(void);
void (*rx_callback)(uint8_t);
} SPI1_DATA;
 
void SPI1_Init(SPI1_DATA *data, void (*rx_callback)(uint8_t));
// Note: SPI1_Write() writes MSB -> LSB!
uint8_t SPI1_Write(uint8_t *array, uint32_t length, void (*tx_callback)(void));
 
#endif /* SPI1_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/SPI4.c
0,0 → 1,151
#include "defines.h"
#include "SPI4.h"
 
static SPI4_DATA *spi_data_ptr;
 
void SPI4_Init(SPI4_DATA *data) {
spi_data_ptr = data;
spi_data_ptr->buffer_out_ind = 0;
spi_data_ptr->buffer_out_len = 0;
spi_data_ptr->buffer_in_ind = 0;
spi_data_ptr->buffer_in_len = 0;
spi_data_ptr->write_blank = 0;
 
INTDisableInterrupts();
 
// Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths
 
// FSCK = FPB / (2 * (SPIxBRG + 1))
IEC1CLR = 0x00000700; // Disable all SPI interrupts
SPI4CON = 0; // Stops and resets the SPI4.
uint32_t tmp = SPI4BUF; // Clears the receive buffer
IFS1CLR = 0x00000700; // Clear any existing event
IPC8CLR = 0x0000001F; // Clear the priority
IPC8SET = 0x0000001A; // Set IPL=6, Subpriority 2
SPI4BRG = 0x4; // Use FPB/10 clock frequency
SPI4STATCLR = 0x40; // Clear the Overflow
IEC1SET = 0x00000300; // Enable RX and Error interrupts
 
// Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode
// SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not empty
SPI4CON = 0x18225;
 
INTEnableInterrupts();
}
 
uint8_t SPI4_Read(uint32_t length, void (*rx_callback)(uint8_t, uint8_t *)) {
spi_data_ptr->rx_callback = rx_callback;
 
// Ensure that the receiving buffer is large enough
if (length > SPI4_BUFFER_IN_SIZE)
return 0;
// Ensure that no previous transactions are in progress
if (spi_data_ptr->buffer_in_len != 0)
return 0;
 
spi_data_ptr->write_blank = 1;
spi_data_ptr->buffer_in_len = length;
spi_data_ptr->buffer_in_ind = 0;
SPI4_Write(NULL, length, NULL);
return 1;
}
 
uint8_t SPI4_Write(uint8_t *array, uint32_t length, void (*tx_callback)(void)) {
spi_data_ptr->tx_callback = tx_callback;
 
// We only care about the transmit length if we are sending data
if (length > SPI4_BUFFER_OUT_SIZE && !spi_data_ptr->write_blank)
return 0;
 
// Ensure that no previous transactions are in progress
if (spi_data_ptr->buffer_out_len != 0)
return 0;
 
// Put the data to send into the outbound buffer
spi_data_ptr->buffer_out_len = length;
spi_data_ptr->buffer_out_ind = 0;
 
// Copy only if we are actually going to transmit data
if (!spi_data_ptr->write_blank) {
int32_t i;
for (i = 0; i < length; i++) {
spi_data_ptr->buffer_out[i] = array[i];
}
}
IEC1SET = 0x00000400; // Enable TX interrupt
return 1;
}
 
void __ISR(_SPI_4_VECTOR, ipl6) __SPI_4_Interrupt_Handler(void) {
// Process SPI4 error flag
if (IFS1bits.SPI4EIF) {
// Clear the receive overflow bit if it is set
if (SPI4STATbits.SPIROV) {
SPI4STATbits.SPIROV = 0;
}
IFS1CLR = 0x00000100; // Clear the error flag
}
 
// Process SPI4 receive flag
if (IFS1bits.SPI4RXIF) {
uint32_t i;
// Read the data received from the last transfer
uint32_t rxBufferCount = SPI4STATbits.RXBUFELM;
for (i = 0; i < rxBufferCount; i++) {
int8_t c = SPI4BUF;
// Put the received data into the buffer
if (spi_data_ptr->buffer_in_len != 0) {
spi_data_ptr->buffer_in[spi_data_ptr->buffer_in_ind] = c;
spi_data_ptr->buffer_in_ind++;
// If done acquiring requested length, reset
if (spi_data_ptr->buffer_in_ind == spi_data_ptr->buffer_in_len) {
// Call the RX callback function on the received data
if (spi_data_ptr->rx_callback != NULL)
(*spi_data_ptr->rx_callback)(spi_data_ptr->buffer_in_len, spi_data_ptr->buffer_in);
spi_data_ptr->buffer_in_len = 0;
}
}
}
IFS1CLR = 0x00000200; // Clear the RX flag
}
 
// Process SPI4 transmit flag
if (IFS1bits.SPI4TXIF && IEC1bits.SPI4TXIE) {
int32_t i;
// Disable the transmit interrupt if all data has been sent
if (spi_data_ptr->buffer_out_len == 0) {
IEC1CLR=0x00000400;
spi_data_ptr->write_blank = 0;
// Call the TX callback function at end of transmission
if (spi_data_ptr->tx_callback != NULL)
(*spi_data_ptr->tx_callback)();
} else {
// Start transmitting the data in the buffer
int32_t txBufferFree = 16 - SPI4STATbits.TXBUFELM;
if (spi_data_ptr->buffer_out_len > txBufferFree) {
for (i = 0; i < txBufferFree; i++) {
if (spi_data_ptr->write_blank) {
SPI4BUF = 0x00;
} else {
SPI4BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
spi_data_ptr->buffer_out_ind++;
}
}
spi_data_ptr->buffer_out_len -= txBufferFree;
} else {
for (i = 0; i < spi_data_ptr->buffer_out_len; i++) {
if (spi_data_ptr->write_blank) {
SPI4BUF = 0x00;
} else {
SPI4BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind];
spi_data_ptr->buffer_out_ind++;
}
}
spi_data_ptr->buffer_out_len = 0;
}
}
IFS1CLR = 0x00000400; // Clear the TX flag
}
}
/PIC Stuff/Cerebot_32MX7_LED_Cube/SPI4.h
0,0 → 1,26
#ifndef SPI4_H
#define SPI4_H
 
#define SPI4_BUFFER_OUT_SIZE 10
#define SPI4_BUFFER_IN_SIZE 10
 
typedef struct {
uint8_t buffer_out[SPI4_BUFFER_OUT_SIZE];
uint32_t buffer_out_ind;
uint32_t buffer_out_len;
uint8_t write_blank;
 
uint8_t buffer_in[SPI4_BUFFER_IN_SIZE];
uint32_t buffer_in_ind;
uint32_t buffer_in_len;
 
void (*tx_callback)(void);
void (*rx_callback)(uint8_t, uint8_t *);
} SPI4_DATA;
 
void SPI4_Init(SPI4_DATA *data);
uint8_t SPI4_Read(uint32_t length, void (*rx_callback)(uint8_t, uint8_t *));
uint8_t SPI4_Write(uint8_t *array, uint32_t length, void (*tx_callback)(void));
 
#endif /* SPI4_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/TIMER5.h
0,0 → 1,13
#ifndef TIMER5_H
#define TIMER5_H
 
typedef struct {
void (*callback_function)(void);
} TIMER5_DATA;
 
void TIMER5_Init(TIMER5_DATA *data, void (*callback)(void), uint32_t time_us);
void TIMER5_Start(void);
void TIMER5_Stop(void);
 
#endif /* TIMER5_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/UART1.h
0,0 → 1,17
#ifndef UART1_H
#define UART1_H
 
#define UART1_BUFFER_SIZE 128
 
typedef struct {
void (*rx_callback)(uint8_t c);
 
uint8_t buffer_out[UART1_BUFFER_SIZE];
uint32_t buffer_out_ind;
uint32_t buffer_out_len;
} UART1_DATA;
 
void UART1_Init(UART1_DATA *data, void (*rx_callback)(uint8_t));
uint8_t UART1_Write(uint8_t *string, uint32_t length);
 
#endif /* UART1_H */
/PIC Stuff/Cerebot_32MX7_LED_Cube/glcdfont.h
0,0 → 1,264
#ifndef FONT5X7_H
#define FONT5X7_H
 
// Standard ASCII 5x7 font
// LSB = top of vertical line, 5 lines from left to right
 
const uint8_t font[] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x21, 0x54, 0x54, 0x78, 0x41,
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0xF0, 0x29, 0x24, 0x29, 0xF0,
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x32, 0x48, 0x48, 0x48, 0x32,
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x39, 0x44, 0x44, 0x44, 0x39,
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0xAA, 0x00, 0x55, 0x00, 0xAA,
0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x06, 0x0F, 0x09, 0x0F, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif
/PIC Stuff/Cerebot_32MX7_LED_Cube/CubeInterface.py
0,0 → 1,257
import serial
from CubeRawCommands import *
 
# Constants
CUBE_LAYER_COUNT = 8
CUBE_ROW_COUNT = 8
CUBE_COLUMN_COUNT = 8
CUBE_ROTATIONS = 7
GCS_REG_SIZE = 36
GCS_LAYER_SIZE = GCS_REG_SIZE * CUBE_ROW_COUNT
 
# 3 bytes per LED, 1536 total for the cube
cube_buffer = bytearray(CUBE_LAYER_COUNT*GCS_LAYER_SIZE)
rotation_counter = 0
 
# Specify the serial port to connect to
serial_port = serial.Serial()
 
'''Opens the serial port for sending commands through.'''
def Cube_Init(port, baudrate):
serial_port.port = port
serial_port.baudrate = baudrate
serial_port.open()
 
'''Clears the local buffer for LED values.'''
def Cube_Clear():
for i in range(len(cube_buffer)):
cube_buffer[i] = 0
 
'''Sets a specific pixel in the local buffer.'''
def Cube_Set_Pixel(layer, row, column, R, G, B):
# Set the specified pixel to the given color
R &= 0x0FFF
G &= 0x0FFF
B &= 0x0FFF
var = row * GCS_REG_SIZE + (column // 2 * 9)
offset = (layer * GCS_LAYER_SIZE) + var
if column % 2 == 0:
cube_buffer[offset+0] = R & 0xFF
cube_buffer[offset+1] = ((G << 4) | (R >> 8)) & 0xFF
cube_buffer[offset+2] = G >> 4
cube_buffer[offset+3] = B & 0xFF
cube_buffer[offset+4] = ((cube_buffer[offset+4] & 0xF0) | (B >> 8)) & 0xFF
elif column % 2 == 1:
cube_buffer[offset+4] = ((cube_buffer[offset+4] & 0x0F) | (R << 4)) & 0xFF
cube_buffer[offset+5] = R >> 4
cube_buffer[offset+6] = G & 0xFF
cube_buffer[offset+7] = ((B << 4) | (G >> 8)) & 0xFF
cube_buffer[offset+8] = B >> 4
 
'''Retreives a specific pixel in the local buffer.'''
def Cube_Get_Pixel(layer, row, column):
# Get and return the color for the specified pixel
R = G = B = 0
var = row * GCS_REG_SIZE + (column // 2 * 9)
offset = (layer * GCS_LAYER_SIZE) + var
if column % 2 == 0:
R = cube_buffer[offset+0] | ((cube_buffer[offset+1] & 0x0F) << 8);
G = (cube_buffer[offset+1] >> 4) | (cube_buffer[offset+2] << 4);
B = cube_buffer[offset+3] | ((cube_buffer[offset+4] & 0x0F) << 8);
elif column % 2 == 1:
R = (cube_buffer[offset+4] >> 4) | (cube_buffer[offset+5] << 4);
G = cube_buffer[offset+6] | ((cube_buffer[offset+7] & 0x0F) << 8);
B = (cube_buffer[offset+7] >> 4) | (cube_buffer[offset+8] << 4);
return [R,G,B]
 
'''Moves a value from one pixel to another in the local buffer.'''
def Cube_Move_Pixel(layer_1, row_1, column_1, layer_2, row_2, column_2):
old = Cube_Get_Pixel(layer1, row_1, column_1)
Cube_Set_Pixel(layer_2, row_2, column_2, old[0], old[1], old[2])
 
'''Rotates the specified shell in the local buffer.'''
def Cube_Rotate_Shell(shell, direction):
for layer in range(CUBE_LAYER_COUNT):
if direction == 1:
if shell == 0:
# Rotate outermost layer
old = Cube_Get_Pixel(layer, 0, 0);
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, old[0], old[1], old[2]);
elif shell == 1:
# Rotate second to outermost layer
old = Cube_Get_Pixel(layer, 1, 1);
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, old[0], old[1], old[2]);
elif shell == 2:
# Rotate second to innermost layer
old = Cube_Get_Pixel(layer, 2, 2);
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, old[0], old[1], old[2]);
elif shell == 3:
# Rotate innermost layer
old = Cube_Get_Pixel(layer, 3, 3);
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, old[0], old[1], old[2]);
else:
if shell == 0:
# Rotate outermost layer
old = Cube_Get_Pixel(layer, 0, 0);
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, old[0], old[1], old[2]);
if shell == 1:
# Rotate second to outermost layer
old = Cube_Get_Pixel(layer, 1, 1);
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, old[0], old[1], old[2]);
if shell == 2:
# Rotate second to innermost layer
old = Cube_Get_Pixel(layer, 2, 2);
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, old[0], old[1], old[2]);
if shell == 3:
# Rotate innermost layer
old = Cube_Get_Pixel(layer, 3, 3);
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, old[0], old[1], old[2]);
 
'''Rotates the entire cube in the local buffer.'''
def Cube_Rotate(direction):
# Rotate outermost layer
Cube_Rotate_Shell(0, direction);
# Rotate second to outermost layer
if ((rotation_counter != 1) and (rotation_counter != 5)):
Cube_Rotate_Shell(1, direction);
# Rotate second to innermost layer
if ((rotation_counter != 0) and (rotation_counter != 2) and (rotation_counter != 4) and (rotation_counter != 6)):
Cube_Rotate_Shell(2, direction);
# Rotate innermost layer
if ((rotation_counter == 3) or (rotation_counter == 7)):
Cube_Rotate_Shell(3, direction);
 
if (direction == 0):
if rotation_counter == CUBE_ROTATIONS - 1:
rotation_counter = 0
else:
rotation_counter = rotation_counter + 1
else:
if rotation_counter == 0:
rotation_counter = CUBE_ROTATIONS - 1
else:
rotation_counter = rotation_counter - 1
 
'''Write the local buffer to the cube.'''
def Cube_Update():
serial_port.write(CMD_Set_All(cube_buffer))
/PIC Stuff/Cerebot_32MX7_LED_Cube/CubeMain.py
0,0 → 1,62
import serial,time
from CubeRawCommands import *
from CubeInterface import *
 
def Animation_Row_Column_Sweep(iterations, delay):
for z in range(iterations):
for i in range(3):
for j in range(CUBE_ROW_COUNT):
Cube_Clear();
for k in range(CUBE_COLUMN_COUNT):
if (i % 3 == 0):
for a in range(CUBE_LAYER_COUNT):
Cube_Set_Pixel(a,j,k,0xFF,0x00,0x00)
elif (i % 3 == 1):
for a in range(CUBE_LAYER_COUNT):
Cube_Set_Pixel(a,j,k,0x00,0xFF,0x00)
else:
for a in range(CUBE_LAYER_COUNT):
Cube_Set_Pixel(a,j,k,0x00,0x00,0xFF)
Cube_Update()
time.sleep(delay)
for j in range(CUBE_ROW_COUNT):
Cube_Clear();
for k in range(CUBE_COLUMN_COUNT):
if (i % 3 == 0):
for a in range(CUBE_LAYER_COUNT):
Cube_Set_Pixel(a,k,j,0xFF,0x00,0x00)
elif (i % 3 == 1):
for a in range(CUBE_LAYER_COUNT):
Cube_Set_Pixel(a,k,j,0x00,0xFF,0x00)
else:
for a in range(CUBE_LAYER_COUNT):
Cube_Set_Pixel(a,k,j,0x00,0x00,0xFF)
Cube_Update()
time.sleep(delay)
for j in range(CUBE_LAYER_COUNT-1, -1, -1):
Cube_Clear();
if (i % 3 == 0):
for k in range(CUBE_LAYER_COUNT):
if (k == j):
for x in range(CUBE_ROW_COUNT):
for y in range(CUBE_COLUMN_COUNT):
Cube_Set_Pixel(k,x,y,0xFF,0x00,0x00)
elif (i % 3 == 1):
for k in range(CUBE_LAYER_COUNT):
if (k == j):
for x in range(CUBE_ROW_COUNT):
for y in range(CUBE_COLUMN_COUNT):
Cube_Set_Pixel(k,x,y,0x00,0xFF,0x00)
else:
for k in range(CUBE_LAYER_COUNT):
if (k == j):
for x in range(CUBE_ROW_COUNT):
for y in range(CUBE_COLUMN_COUNT):
Cube_Set_Pixel(k,x,y,0x00,0x00,0xFF)
Cube_Update()
time.sleep(delay)
 
if __name__ == '__main__':
Cube_Init('COM11', 256000)
 
Animation_Row_Column_Sweep(3,0)
/PIC Stuff/Cerebot_32MX7_LED_Cube/CubeRawCommands.py
0,0 → 1,43
'''Generates the byte array for setting the global brightness.'''
def CMD_Set_BC(brightness):
barray = bytearray.fromhex('7E 00 02 0A')
barray.extend([brightness])
barray.extend([Calculate_Checksum(barray)])
return barray
 
'''Generates the byte array for clearing all pixels.'''
def CMD_Clear():
return bytearray.fromhex('7E 00 01 0B F4')
 
'''Generates the command for setting a specific pixel.'''
def CMD_Set_Pixel(layer, row, column, r, g, b):
barray = bytearray.fromhex('7E 00 07 10')
barray.extend([layer,row,column,r,g,b,])
barray.extend([Calculate_Checksum(barray)])
return barray
 
'''Generates the command for setting the entire cube.'''
def CMD_Set_All(leds):
barray = bytearray.fromhex('7E 09 01 11')
barray.extend(leds)
barray.extend([Calculate_Checksum(barray)])
return barray
 
'''Generates the command for setting the rotating overlay text.'''
def CMD_Start_Text(r, g, b, string):
length = len(string) + 4
barray = bytearray.fromhex('7E 00')
barray.extend([length, 0x20, r, g, b])
barray.extend(string.encode())
barray.extend([Calculate_Checksum(barray)])
return barray
 
'''Generates the command for stopping the rotating overlay text.'''
def CMD_Stop_Text():
return bytes.fromhex('7E 00 01 21 DE')
 
def Calculate_Checksum(barray):
s = 0
for entry in range(3,len(barray)):
s += barray[entry]
return 255 - (s & 0xFF)
/PIC Stuff/Cerebot_32MX7_LED_Cube/BTN.h
0,0 → 1,31
#ifndef BTN_H
#define BTN_H
 
// BTN1 = CN8, BTN2 = CN9, BTN3 = CN19 (32MX7 only)
// BTN1 = RG6, BTN2 = RG7, BTN3 = RD13 (32MX7 only)
// Note: Write to PORTx is effectively the same as write to LATx
#define BTN1_TRIS TRISGbits.TRISG6
#define BTN1_PORT PORTGbits.RG6
#define BTN2_TRIS TRISGbits.TRISG7
#define BTN2_PORT PORTGbits.RG7
 
#if defined CEREBOT_32MX7
#define BTN3_TRIS TRISDbits.TRISD13
#define BTN3_PORT PORTDbits.RD13
#elif defined CEREBOT_MX7CK
#define BTN3_TRIS TRISAbits.TRISA0
#define BTN3_PORT PORTAbits.RA0
#endif
 
#define BTN_DEBOUNCE_MS 1
 
typedef struct {
void (*callback_function_1)(void);
void (*callback_function_2)(void);
void (*callback_function_3)(void);
} BTN_DATA;
 
void BTN_Init(BTN_DATA *data, void (*callback_1)(void), void (*callback_2)(void), void (*callback_3)(void));
 
#endif /* BTN_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/PWM2.h
0,0 → 1,9
#ifndef PWM2_H
#define PWM2_H
 
void PWM2_Init(void);
void PWM2_Start(void);
void PWM2_Stop(void);
 
#endif /* PWM2_H */
 
/PIC Stuff/Cerebot_32MX7_LED_Cube/Makefile
0,0 → 1,108
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed directly, and they are:
#
# build build a specific configuration
# clean remove built files from a configuration
# clobber remove all built files
# all build all configurations
# help print help mesage
#
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
# .help-impl are implemented in nbproject/makefile-impl.mk.
#
# Available make variables:
#
# CND_BASEDIR base directory for relative paths
# CND_DISTDIR default top distribution directory (build artifacts)
# CND_BUILDDIR default top build directory (object files, ...)
# CONF name of current configuration
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
#
# NOCDDL
 
 
# Environment
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin
RANLIB=ranlib
 
 
# build
build: .build-post
 
.build-pre:
# Add your pre 'build' code here...
 
.build-post: .build-impl
# Add your post 'build' code here...
 
 
# clean
clean: .clean-post
 
.clean-pre:
# Add your pre 'clean' code here...
 
.clean-post: .clean-impl
# Add your post 'clean' code here...
 
 
# clobber
clobber: .clobber-post
 
.clobber-pre:
# Add your pre 'clobber' code here...
 
.clobber-post: .clobber-impl
# Add your post 'clobber' code here...
 
 
# all
all: .all-post
 
.all-pre:
# Add your pre 'all' code here...
 
.all-post: .all-impl
# Add your post 'all' code here...
 
 
# help
help: .help-post
 
.help-pre:
# Add your pre 'help' code here...
 
.help-post: .help-impl
# Add your post 'help' code here...
 
 
 
# include project implementation makefile
include nbproject/Makefile-impl.mk
 
# include project make variables
include nbproject/Makefile-variables.mk