//PIC Stuff/Cerebot_32MX7_LED_Cube/ANIMATIONS.c |
---|
399,7 → 399,7 |
r = rand(); |
if (r % 3 == 0) { |
// Increase |
data[j] = (data[j] == CUBE_LAYER_COUNT - 1) ? data[j] : data[j] + 1; |
data[j] = (data[j] == CUBE_LAYER_COUNT) ? data[j] : data[j] + 1; |
} else if (r % 3 == 1) { |
// Decrease |
data[j] = (data[j] == 0) ? data[j] : data[j] - 1; |
423,7 → 423,7 |
r = rand(); |
if (r % 3 == 0) { |
// Increase |
data[j] = (data[j] == CUBE_LAYER_COUNT - 1) ? data[j] : data[j] + 1; |
data[j] = (data[j] == CUBE_LAYER_COUNT) ? data[j] : data[j] + 1; |
} else if (r % 3 == 1) { |
// Decrease |
data[j] = (data[j] == 0) ? data[j] : data[j] - 1; |
//PIC Stuff/Cerebot_32MX7_LED_Cube/CONTROLLERS.c |
---|
4,17 → 4,23 |
static CONTROLLER_DATA *ctrl_data_p; |
void Controller_Init(CONTROLLER_DATA *data) { |
ctrl_data_p = data; |
void Controller_Init(CONTROLLER_DATA *data, |
void (*change_callback)(uint8_t controller, CTRL_BTN_STATUS values)) { |
if (data != NULL) |
ctrl_data_p = data; |
ctrl_data_p->change_callback = change_callback; |
// Variable initialization |
int i; |
int i, j; |
for (i = 0; i < CONTROLLER_MAX_COUNT; i++) { |
ctrl_data_p->connected_controllers[i] = 0x0; |
ctrl_data_p->led_status[i][0] = 0x0; |
ctrl_data_p->led_status[i][1] = 0x0; |
ctrl_data_p->btn_prev[i] = 0x0; |
ctrl_data_p->btn_last[i] = 0x0; |
ctrl_data_p->led_status[i].w[i] = 0x0; |
ctrl_data_p->btn_prev[i].w = 0x0; |
ctrl_data_p->btn_curr[i].w = 0x0; |
for (j = 0; j < 16; j++) { |
ctrl_data_p->led_status[i].w[j] = 0x0; |
} |
} |
ctrl_data_p->connected_count = 0x0; |
24,157 → 30,167 |
} |
void Controller_Poll_Connected(void) { |
uint8_t buffer[2] = {CONTROLLER_CMD_RESET}; |
uint8_t result, length, i; |
uint8_t buffer[2]; |
uint8_t result, i; |
uint8_t address = CONTROLLER_PREFIX_ADDRESS + CONTROLLER_START_ADDRESS; |
// Attempt to contact each controller to see if its connected |
for (i = 0; i < CONTROLLER_MAX_COUNT; i++) { |
// I2C1_Master_Send(address + i, buffer, 1); |
// do { |
// result = I2C1_Get_Status(); |
// } while (!result); |
// if (result == I2C1_SEND_OK) { |
// // If a controller is connected, save its address |
// ctrl_data_p->connected_controllers[ctrl_data_p->connected_count] |
// = address + i; |
// ctrl_data_p->connected_count++; |
// } |
I2C1_Master_Restart(address + i, CONTROLLER_CMD_READ, 1); |
do { |
result = I2C1_Get_Status(); |
} while (!result); |
if (result == I2C1_RECV_OK) { |
length = I2C1_Read_Buffer(buffer); |
uint8_t length = I2C1_Read_Buffer(buffer); |
// If a controller is connected, save its address |
ctrl_data_p->connected_controllers[ctrl_data_p->connected_count] |
= address + i; |
ctrl_data_p->connected_controllers[ctrl_data_p->connected_count] = address + i; |
ctrl_data_p->connected_count++; |
} |
// A small delay is needed between polls |
Delay_MS(1); |
} |
// Show the number of controllers connected |
if (ctrl_data_p->connected_count & 0x1) |
LED1_LAT = 1; |
if (ctrl_data_p->connected_count & 0x2) |
LED2_LAT = 1; |
if (ctrl_data_p->connected_count & 0x4) |
LED3_LAT = 1; |
if (ctrl_data_p->connected_count & 0x8) |
LED4_LAT = 1; |
} |
void Controller_Update(void) { |
/* |
uint8_t buffer[2]; |
uint8_t result, length; |
uint8_t ctrl_1_btn = 0, ctrl_2_btn = 0; |
uint8_t result, length, i, j; |
CTRL_BTN_STATUS btn_change; |
for (i = 0; i < ctrl_data_p->connected_count; i++) { |
// Store the last read values |
ctrl_data_p->btn_prev[i] = ctrl_data_p->btn_curr[i]; |
// 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; |
// Read in the button values for each controller |
I2C1_Master_Restart(ctrl_data_p->connected_controllers[i], CONTROLLER_CMD_READ, 1); |
do { |
result = I2C1_Get_Status(); |
} while (!result); |
// Save the read values |
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; |
ctrl_data_p->btn_curr[i].w = buffer[0]; |
// Determine if a change was made between the current and previous values |
if (ctrl_data_p->btn_curr[i].w != ctrl_data_p->btn_prev[i].w) { |
// Determine if a button was pressed (unpressed->pressed) |
btn_change.w = ctrl_data_p->btn_prev[i].w ^ ctrl_data_p->btn_curr[i].w; |
btn_change.w &= ctrl_data_p->btn_curr[i].w; |
// If a button was pressed, call the saved callback |
if (btn_change.w) { |
if (ctrl_data_p->change_callback != NULL) { |
ctrl_data_p->change_callback(i, btn_change); |
} |
} |
// 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); |
void Controller_Set_Left_Leds(uint8_t controller, uint8_t value) { |
uint8_t result, i; |
uint8_t buffer[18]; |
for (i = 0; i < 4; i++) { |
if (value & (0x01 << i)) |
ctrl_data_p->led_status[controller].w[i+12] = CONTROLLER_BRIGHTNESS_HIGH; |
else |
ctrl_data_p->led_status[controller].w[i+12] = 0x00; |
} |
// Write the LED value to the controller |
buffer[0] = CONTROLLER_CMD_WRITE; |
for (i = 0; i < 16; i++) |
buffer[i+1] = ctrl_data_p->led_status[controller].w[i]; |
I2C1_Master_Send(ctrl_data_p->connected_controllers[controller], buffer, 17); |
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); |
} |
Delay_MS(1); |
} |
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); |
void Controller_Set_Middle_Leds(uint8_t controller, uint8_t value) { |
uint8_t result, i; |
uint8_t buffer[18]; |
for (i = 0; i < 8; i++) { |
if (value & (0x01 << i)) |
ctrl_data_p->led_status[controller].w[i] = CONTROLLER_BRIGHTNESS_HIGH; |
else |
ctrl_data_p->led_status[controller].w[i] = 0x00; |
} |
// 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); |
} |
// Write the LED value to the controller |
buffer[0] = CONTROLLER_CMD_WRITE; |
for (i = 0; i < 16; i++) |
buffer[i+1] = ctrl_data_p->led_status[controller].w[i]; |
I2C1_Master_Send(ctrl_data_p->connected_controllers[controller], buffer, 17); |
do { |
result = I2C1_Get_Status(); |
} while (!result); |
Delay_MS(1); |
} |
void Controller_Set_Right_Leds(uint8_t controller, uint8_t value) { |
uint8_t result, i; |
uint8_t buffer[18]; |
for (i = 0; i < 4; i++) { |
if (value & (0x01 << i)) |
ctrl_data_p->led_status[controller].w[i+8] = CONTROLLER_BRIGHTNESS_HIGH; |
else |
ctrl_data_p->led_status[controller].w[i+8] = 0x00; |
} |
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); |
} |
} |
*/ |
// Write the LED value to the controller |
buffer[0] = CONTROLLER_CMD_WRITE; |
for (i = 0; i < 16; i++) |
buffer[i+1] = ctrl_data_p->led_status[controller].w[i]; |
I2C1_Master_Send(ctrl_data_p->connected_controllers[controller], buffer, 17); |
do { |
result = I2C1_Get_Status(); |
} while (!result); |
Delay_MS(1); |
} |
void Controller_Set_Leds(uint8_t controller, uint16_t value) { |
// ctrl_data_p->ctrl_1_leds = ctrl_1; |
// ctrl_data_p->ctrl_2_leds = ctrl_2; |
uint8_t Controller_Get_Connected(void) { |
return ctrl_data_p->connected_count; |
} |
uint8_t Controller_Query(uint8_t controller) { |
// // 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; |
void Controller_Set_Active(uint8_t controller) { |
uint8_t buffer[2]; |
uint8_t result; |
buffer[0] = CONTROLLER_CMD_ACTIVE; |
I2C1_Master_Send(ctrl_data_p->connected_controllers[controller], buffer, 1); |
do { |
result = I2C1_Get_Status(); |
} while (!result); |
Delay_MS(1); |
} |
void Controller_Set_Idle(uint8_t controller) { |
uint8_t buffer[2]; |
uint8_t result; |
buffer[0] = CONTROLLER_CMD_RESET; |
I2C1_Master_Send(ctrl_data_p->connected_controllers[controller], buffer, 1); |
do { |
result = I2C1_Get_Status(); |
} while (!result); |
Delay_MS(1); |
} |
//PIC Stuff/Cerebot_32MX7_LED_Cube/CONTROLLERS.h |
---|
4,30 → 4,74 |
#define CONTROLLER_CMD_READ 0xA |
#define CONTROLLER_CMD_WRITE 0xB |
#define CONTROLLER_CMD_RESET 0xC |
#define CONTROLLER_CMD_ACTIVE 0xD |
#define CONTROLLER_BTN_DEFAULT 0xC0 |
#define CONTROLLER_LED_DEFAULT 0x00 |
#define CONTROLLER_PREFIX_ADDRESS 0xA0 |
#define CONTROLLER_PREFIX_ADDRESS 0x10 |
#define CONTROLLER_START_ADDRESS 0x01 |
#define CONTROLLER_END_ADDRESS 0x08 |
#define CONTROLLER_MAX_COUNT 8 |
#define CONTROLLER_MAX_COUNT 4 |
#define CONTROLLER_BRIGHTNESS_HIGH 0x80 |
typedef union { |
struct { |
unsigned BTN_L_N :1; |
unsigned BTN_L_E :1; |
unsigned BTN_R_E :1; |
unsigned BTN_R_N :1; |
unsigned BTN_R_S :1; |
unsigned BTN_R_W :1; |
unsigned BTN_L_S :1; |
unsigned BTN_L_W :1; |
}; |
uint8_t w; |
} CTRL_BTN_STATUS; |
typedef union { |
struct { |
uint8_t LED_0; |
uint8_t LED_1; |
uint8_t LED_2; |
uint8_t LED_3; |
uint8_t LED_4; |
uint8_t LED_5; |
uint8_t LED_6; |
uint8_t LED_7; |
uint8_t LED_N; |
uint8_t LED_W; |
uint8_t LED_E; |
uint8_t LED_S; |
uint8_t LED_A; |
uint8_t LED_B; |
uint8_t LED_C; |
uint8_t LED_D; |
} single; |
uint8_t w[16]; |
} CTRL_LED_VALUES; |
typedef struct { |
uint8_t connected_controllers[CONTROLLER_MAX_COUNT]; |
uint8_t led_status[CONTROLLER_MAX_COUNT][2]; |
uint8_t btn_prev[CONTROLLER_MAX_COUNT]; |
uint8_t btn_last[CONTROLLER_MAX_COUNT]; |
void (*change_callback)(uint8_t controller, CTRL_BTN_STATUS values); |
uint8_t connected_count; |
uint8_t connected_controllers[CONTROLLER_MAX_COUNT]; |
CTRL_LED_VALUES led_status[CONTROLLER_MAX_COUNT]; |
CTRL_BTN_STATUS btn_prev[CONTROLLER_MAX_COUNT]; |
CTRL_BTN_STATUS btn_curr[CONTROLLER_MAX_COUNT]; |
} CONTROLLER_DATA; |
void Controller_Init(CONTROLLER_DATA *data); |
void Controller_Init(CONTROLLER_DATA *data, |
void (*change_callback)(uint8_t controller, CTRL_BTN_STATUS values)); |
void Controller_Poll_Connected(void); |
void Controller_Update(void); |
void Controller_Set_Leds(uint8_t controller, uint16_t value); |
uint8_t Controller_Query(uint8_t controller); |
void Controller_Set_Left_Leds(uint8_t controller, uint8_t value); |
void Controller_Set_Middle_Leds(uint8_t controller, uint8_t value); |
void Controller_Set_Right_Leds(uint8_t controller, uint8_t value); |
uint8_t Controller_Get_Connected(void); |
void Controller_Set_Active(uint8_t controller); |
void Controller_Set_Idle(uint8_t controller); |
#endif /* CONTROLLERS_H */ |
//PIC Stuff/Cerebot_32MX7_LED_Cube/CUBE.h |
---|
14,8 → 14,8 |
// Color Definitions |
#define CLEAR 0x000,0x000,0x000 |
#define RED 0x0FF,0x000,0x000 |
#define ORANGE 0x0FF,0x040,0x000 |
#define YELLOW 0x0FF,0x0FF,0x000 |
#define ORANGE 0x0FF,0x020,0x000 |
#define YELLOW 0x0FF,0x060,0x000 |
#define GREEN 0x000,0x0FF,0x000 |
#define TEAL 0x000,0x0FF,0x040 |
#define BLUE 0x000,0x000,0x0FF |
//PIC Stuff/Cerebot_32MX7_LED_Cube/I2C1.c |
---|
29,11 → 29,22 |
// 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) |
if (speed == 0x01) { |
I2C1BRG = 0x0BE; // Operate at 200kHZ (80MHz) |
I2C1CONbits.DISSLW = 0; // Slew rate control enabled |
} else if (speed == 0x02) { |
I2C1BRG = 0x05A; // Operate at 400kHZ (80MHz) |
I2C1CONbits.DISSLW = 1; // Slew rate control disabled |
} else if (speed == 0x03) { |
I2C1BRG = 0x020; // Operate at 1MHz (80MHz) |
I2C1CONbits.DISSLW = 1; // Slew rate control disabled |
} else { |
I2C1BRG = 0x186; // Operate at 100kHZ (80MHz) |
I2C1CONbits.DISSLW = 0; // Slew rate control enabled |
} |
IFS0CLR = 0xE0000000; // Clear any existing events |
IPC6CLR = 0x00001F00; // Reset priority levels |
IPC6SET = 0x00001500; // Set IPL=5, Subpriority 1 |
IPC6SET = 0x00001600; // Set IPL=6, Subpriority 2 |
IEC0SET = 0xE0000000; // Enable I2C1 interrupts |
INTEnableInterrupts(); |
249,7 → 260,8 |
// 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]; |
uint8_t to_send = i2c_data_p->buffer_in[0]; |
I2C1TRN = to_send; |
i2c_data_p->operating_state = I2C1_CHECK_ACK_RESTART; |
} else { |
// If a NACK is received, stop transmission and send error |
//PIC Stuff/Cerebot_32MX7_LED_Cube/I2C1.h |
---|
4,8 → 4,10 |
#define MAXI2C1BUF 32 |
// I2C Operating Speed |
#define I2C1_400KHZ 0x0 |
#define I2C1_100KHZ 0x1 |
#define I2C1_100KHZ 0x0 |
#define I2C1_200KHZ 0x1 |
#define I2C1_400KHZ 0x2 |
#define I2C1_1MHZ 0x3 |
// Operating State |
#define I2C1_IDLE 0x1 |
//PIC Stuff/Cerebot_32MX7_LED_Cube/README.txt |
---|
5,14 → 5,14 |
KNOWN ISSUES: |
Cube is occasionally flickering to ~60Hz. Need to figure out why. |
Interrupts dont seem to be preempting properly. Not sure why. |
>= 400MHz I2C1 doesn't seem to work very well the controllers |
PERIPHERAL USAGE: |
SPI1 - Used by the cube code to send data to the ube |
SPI1 - Used by the cube code to send data to the cube |
SPI4 - Unused |
I2C1 - Used by the controller code |
TIMER2 - Used by PWM2 |
TIMER4 - Used by the cube code for the overlay rotation interrupt |
TIMER4 - Used by the cube code for the overlay rotation interrupt / controllers |
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 |
20,10 → 20,10 |
PERIPHERAL INTERRUPT PRIORITY LEVELS: |
IPL1 = lowest, IPL7 = highest priority |
SPI1 - Priority 5, Subpriority 1 |
SPI1 - Priority 6, Subpriority 1 |
SPI4 - Priority 6, Subpriority 2 |
I2C1 - Priority 5, Subpriority 1 |
TIMER5 - Priority 3, Subpriority 1 |
I2C1 - Priority 5, Subpriority 2 |
TIMER5 - Priority 4, Subpriority 1 |
TIMER4 - Priority 1, Subpriority 1 |
UART1 - Priority 2, Subpriority 1 |
ETHERNET - Priority 1, Subpriority 1 |
//PIC Stuff/Cerebot_32MX7_LED_Cube/SNAKE.c |
---|
1,6 → 1,7 |
#include "defines.h" |
#include "CONTROLLERS.h" |
#include "SNAKE.h" |
#include "TIMER4.h" |
static SNAKE_DATA *data_p; |
static uint32_t rand_value __attribute__((persistent)); |
14,8 → 15,10 |
data_p->pos_head = 0; |
data_p->pos_tail = 0; |
data_p->length = 1; |
data_p->level = 1; |
data_p->delay = 800; |
data_p->level = 0; |
data_p->delay = SNAKE_MAXIMUM_DELAY; |
data_p->direction = (SNAKE_POINT){1,0,7}; |
data_p->last_direction = 0x08; |
srand(rand_value); |
36,40 → 39,49 |
void Snake_Main(void) { |
// Main function, loops and delays while updating the frame every x milliseconds |
Delay_MS(2000); |
while(!Controller_Get_Connected()) { |
Delay_MS(100); |
Controller_Poll_Connected(); |
} |
Controller_Set_Active(0); |
Delay_MS(20); |
Controller_Set_Left_Leds(0, 0x1); |
TIMER4_Start(); |
Delay_MS(1000); |
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) { |
void Snake_Update_Direction(uint8_t controller, CTRL_BTN_STATUS value) { |
// 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; |
if (controller == 0) { |
data_p->last_direction = value.w; |
SNAKE_POINT point = data_p->body[data_p->pos_head]; |
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; |
if (value.BTN_L_N || value.BTN_L_E) { // Up |
point.z = (point.z == CUBE_LAYER_COUNT - 1) ? 0 : point.z + 1; |
} else if (value.BTN_L_W || value.BTN_L_S) { // Down |
point.z = (point.z == 0) ? CUBE_LAYER_COUNT - 1 : point.z - 1; |
} else if (value.BTN_R_N) { // Forward |
point.x = (point.x == CUBE_ROW_COUNT - 1) ? 0 : point.x + 1; |
} else if (value.BTN_R_W) { // Right |
point.y = (point.y == CUBE_COLUMN_COUNT - 1) ? 0 : point.y + 1; |
} else if (value.BTN_R_S) { // Backward |
point.x = (point.x == 0) ? CUBE_ROW_COUNT - 1 : point.x - 1; |
} else if (value.BTN_R_E) { // Left |
point.y = (point.y== 0) ? CUBE_COLUMN_COUNT - 1 : point.y - 1; |
} |
data_p->direction = point; |
} |
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); |
124,18 → 136,22 |
} |
// Determine the next direction to take |
Snake_Update_Direction(data_p->last_direction, 0x0); |
Snake_Update_Direction(0, (CTRL_BTN_STATUS)data_p->last_direction); |
// 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 |
// Increase the level by one |
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); |
} |
TIMER4_Stop(); |
Controller_Set_Middle_Leds(0, data_p->level); |
if (data_p->level >= 256) |
Controller_Set_Left_Leds(0, 0x9); |
TIMER4_Start(); |
// Decrease the delay between frame updates by 5ms |
data_p->delay -= 5; |
if (data_p->delay > SNAKE_MINIMUM_DELAY) |
data_p->delay -= 5; |
// Clear the watchdog timer to prevent resets in a middle of a game |
ClearWDT(); |
} |
//PIC Stuff/Cerebot_32MX7_LED_Cube/SNAKE.h |
---|
8,28 → 8,15 |
#define SNAKE_CANDY_COLOR GREEN |
#define SNAKE_COLLISION_COLOR ORANGE |
#define SNAKE_LEVEL_STEP 10 |
#define SNAKE_MAXIMUM_DELAY 800 |
#define SNAKE_MINIMUM_DELAY 300 |
typedef struct { |
unsigned x :8; |
unsigned y :8; |
unsigned z :8; |
unsigned :8; |
uint8_t x; |
uint8_t y; |
uint8_t z; |
} 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; |
44,7 → 31,7 |
void Snake_Init(SNAKE_DATA *data); |
void Snake_Main(void); |
void Snake_Update_Direction(uint8_t p1, uint8_t p2); |
void Snake_Update_Direction(uint8_t controller, CTRL_BTN_STATUS value); |
void Snake_Update_Frame(void); |
SNAKE_POINT Snake_Generate_Candy(void); |
//PIC Stuff/Cerebot_32MX7_LED_Cube/TIMER5.c |
---|
32,7 → 32,8 |
Nop(); |
TMR5 = 0x0; // Clear timer register |
PR5 = time; // Load period register |
IPC5SET = 0x0000000D; // Set priority level = 3, sub-priority level = 1 |
// IPC5SET = 0x0000000D; // Set priority level = 3, sub-priority level = 1 |
IPC5SET = 0x00000011; // Set priority level = 4, sub-priority level = 1 |
IFS0CLR = 0x00100000; // Clear timer interrupt flag |
IEC0SET = 0x00100000; // Enable timer interrupt |
//PIC Stuff/Cerebot_32MX7_LED_Cube/TRON.c |
---|
34,7 → 34,7 |
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); |
// Controller_Set_Leds(0x01,0x01); |
Delay_MS(2000); |
while (1) { |
Tron_Update_Frame(); |
//PIC Stuff/Cerebot_32MX7_LED_Cube/defines.h |
---|
8,8 → 8,8 |
#include <stdint.h> |
// Uncomment ONE of the following: |
#define CEREBOT_32MX7 |
// #define CEREBOT_MX7CK |
//#define CEREBOT_32MX7 |
#define CEREBOT_MX7CK |
#define CPU_CLOCK_HZ 80000000UL |
#define PERIPHERAL_CLOCK_HZ 80000000UL |
//PIC Stuff/Cerebot_32MX7_LED_Cube/main.c |
---|
114,6 → 114,21 |
while(1); |
} |
void Test_Callback(uint8_t controller, CTRL_BTN_STATUS value) { |
LED1_LAT = 0; |
LED2_LAT = 0; |
LED3_LAT = 0; |
LED4_LAT = 0; |
if (value.BTN_R_N) |
LED1_LAT = 1; |
if (value.BTN_R_E) |
LED2_LAT = 1; |
if (value.BTN_R_S) |
LED3_LAT = 1; |
if (value.BTN_R_W) |
LED4_LAT = 1; |
} |
void main() { |
// WARNING!! THIS BOARD WILL RESET EVERY 1048.576s DUE TO THE WDT!! |
131,7 → 146,8 |
// Enable the watchdog timer with windowed mode disabled |
// WDT prescaler set to 1048576 (1048.576s) (see config bits) |
WDTCON = 0x00008000; |
// WDTCON = 0x00008000; |
WDTCON = 0x00000000; |
// Configure onboard LEDs |
LED1_TRIS = 0; |
157,12 → 173,12 |
SPI1_Init(&spi_1_data, NULL); |
// Initialize the SPI4 module |
SPI4_DATA spi_4_data; |
SPI4_Init(&spi_4_data); |
// 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); |
I2C1_Init(&i2c_1_data, I2C1_200KHZ, 0x20); |
// // Initialize the UART1 module |
// UART1_DATA uart_data; |
176,11 → 192,11 |
Cube_Init(&cube_data, 0x40); |
// Start the cube update layer interrupt |
// 2083 = 60Hz, 500 = 250Hz, 250 = 500Hz |
// 2084 = 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 |
// Initialize timer for controller polling and overlay rotation interrupt |
TIMER4_DATA timer_4_data; |
TIMER4_Init(&timer_4_data, NULL, NULL, 0); |
190,7 → 206,7 |
// Initialize controllers |
CONTROLLER_DATA ctrl_data; |
Controller_Init(&ctrl_data); |
Controller_Init(&ctrl_data, NULL); |
// Initialize the Ethernet module |
if (op_state == BOARD_MODE_ETHERNET) { |
203,7 → 219,6 |
TRON_DATA tron_data; |
PWM2_Start(); |
TIMER5_Start(); |
/* -------------------- END OF INITIALIZATION -------------------- */ |
/* ------------------------ BEGIN DISPLAY ------------------------ */ |
211,24 → 226,35 |
// Figure out what to do at this point (depending on current state) |
switch (op_state) { |
case BOARD_MODE_IDLE: |
TIMER5_Start(); // Use the default refresh rate (250Hz) |
Idle_Animation_Sequence(); |
break; |
case BOARD_MODE_SNAKE:; |
Controller_Init(&ctrl_data); |
case BOARD_MODE_SNAKE: |
// Change refresh rate to ~60Hz |
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 2000); |
TIMER5_Start(); |
// Poll the controllers at 1kHz |
Controller_Init(NULL, &Snake_Update_Direction); |
TIMER4_Init(NULL, &Controller_Update, NULL, 0); |
TIMER4_Start(); |
// Initialize and start the game |
Snake_Init(&snake_data); |
Snake_Main(); |
break; |
case BOARD_MODE_TRON: |
Controller_Init(&ctrl_data); |
// Change refresh rate to ~60Hz |
TIMER5_Init(NULL, &Cube_Timer_Interrupt, 2000); |
TIMER5_Start(); |
// Poll the controllers at 1kHz |
Controller_Init(&ctrl_data, NULL); |
TIMER4_Init(NULL, &Controller_Update, NULL, 0); |
// Initialize and start the game |
Tron_Init(&tron_data); |
TIMER4_Start(); |
Tron_Init(&tron_data); |
Tron_Main(); |
break; |
case BOARD_MODE_ETHERNET: |
TIMER4_Stop(); |
TIMER5_Start(); |
LED2_LAT = 1; |
while(1); |
break; |
250,6 → 276,12 |
// Animation_Pseudo_Random_Colors(200); |
// Animation_Pseudo_Random_Colors(200); |
// Animation_Pseudo_Random_Colors(200); |
uint8_t connected, i; |
connected = Controller_Get_Connected(); |
for (i = 0; i < connected; i++) { |
Controller_Set_Idle(i); |
} |
// Start the scrolling text |
TIMER4_Stop(); |
286,8 → 318,8 |
// 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); |
//PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/Makefile-genesis.properties |
---|
1,5 → 1,5 |
# |
#Thu Mar 13 23:02:03 EDT 2014 |
#Mon Mar 17 03:54:28 EDT 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 |
//PIC Stuff/Cerebot_32MX7_LED_Cube/nbproject/configurations.xml |
---|
130,13 → 130,6 |
<property key="exclude-floating-point-library" value="false"/> |
<property key="exclude-standard-libraries" value="false"/> |
<property key="extra-lib-directories" value=""/> |
<property key="fill-flash-options-addr" value=""/> |
<property key="fill-flash-options-const" value=""/> |
<property key="fill-flash-options-how" value="0"/> |
<property key="fill-flash-options-inc-const" value="1"/> |
<property key="fill-flash-options-increment" value=""/> |
<property key="fill-flash-options-seq" value=""/> |
<property key="fill-flash-options-what" value="0"/> |
<property key="generate-16-bit-code" value="false"/> |
<property key="generate-cross-reference-file" value="false"/> |
<property key="generate-micro-compressed-code" value="false"/> |