// ============================ //
// Do not edit this part!!!! //
// ============================ //
// 0x300001 - CONFIG1H
#pragma config OSC = HSPLL // Oscillator Selection bits (HS oscillator,
// PLL enabled (Clock Frequency = 4 x FOSC1))
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit
// (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit
// (Oscillator Switchover mode disabled)
// 0x300002 - CONFIG2L
#pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out
// Reset disabled in hardware and software)
// 0x300003 - CONFIG1H
#pragma config WDT = OFF // Watchdog Timer Enable bit
// (WDT disabled (control is placed on the SWDTEN bit))
// 0x300004 - CONFIG3L
// 0x300005 - CONFIG3H
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit
// (Timer1 configured for higher power operation)
#pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled;
// RE3 input pin disabled)
// 0x300006 - CONFIG4L
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply
// ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit
// (Instruction set extension and Indexed
// Addressing mode disabled (Legacy mode))
#pragma config DEBUG = OFF // Disable In-Circuit Debugger
#define KHZ 1000UL
#define MHZ (KHZ * KHZ)
#define _XTAL_FREQ (40UL * MHZ)
// ============================ //
// End //
// ============================ //
#include <xc.h>
#include <stdint.h>
#define T_PRELOAD_LOW 0xC1
#define T_PRELOAD_HIGH 0x34
// Hold the board as an array of 8x4:
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
// 0 0 0 0
uint8_t board[8][4];
// Initialize the board
void init_board()
{
for (uint8_t i = 0; i < 8; i++)
{
for (uint8_t j = 0; j < 4; j++)
{
board[i][j] = 0;
}
}
}
// Submit a piece to board.
void submit_piece(struct piece)
{
// Before submitting the piece, check if the piece can be submitted.
// If the piece cannot be submitted, return.
if (piece->type == dot)
{
if (board[piece->x][piece->y] == 1)
{
return;
}
}
else if (piece->type == l_piece)
{
if (piece->empty_x == piece->x && piece->empty_y == piece->y)
{
// Empty space is on the top-left.
// OX
// XX
if (board[piece->x + 1][piece->y] == 1 || board[piece->x][piece->y + 1] == 1 || board[piece->x + 1][piece->y + 1] == 1)
{
return;
}
}
else if (piece->empty_x < piece->x && piece->empty_y == piece->y)
{
// Empty space is on the top-right.
// XO
// XX
if (board[piece->x][piece->y] == 1 || board[piece->x][piece->y + 1] == 1 || board[piece->x + 1][piece->y + 1] == 1)
{
return;
}
}
else if (piece->x < piece->empty_x && piece->x < piece->empty_y)
{
// Empty space is on the bottom-right.
// XX
// XO
if (board[piece->x][piece->y] == 1 || board[piece->x + 1][piece->y] == 1 || board[piece->x][piece->y + 1] == 1)
{
return;
}
}
else if (piece->empty_x == piece->x + 1)
{
// Empty space is on the bottom-left.
// XX
// OX
if (board[piece->x][piece->y] == 1 || board[piece->x + 1][piece->y] == 1 || board[piece->x + 1][piece->y + 1] == 1)
{
return;
}
}
}
else if (piece->type == square)
{
if (board[piece->x][piece->y] == 1 || board[piece->x][piece->y + 1] == 1 || board[piece->x + 1][piece->y] == 1 || board[piece->x + 1][piece->y + 1] == 1)
{
return;
}
}
// Set correct values to the board as 1:
if (piece->type == "dot")
{
board[piece->x][piece->y] = 1;
}
else if (piece->type == "l_piece")
{
if (piece->empty_x == piece->x && piece->empty_y == piece->y)
{
// Empty space is on the top-left.
// OX
// XX
board[piece->x + 1][piece->y] = 1;
board[piece->x][piece->y + 1] = 1;
board[piece->x + 1][piece->y + 1] = 1;
}
else if (piece->empty_x < piece->x && piece->empty_y == piece->y)
{
// Empty space is on the top-right.
// XO
// XX
board[piece->x][piece->y] = 1;
board[piece->x][piece->y + 1] = 1;
board[piece->x + 1][piece->y + 1] = 1;
}
else if (piece->x < piece->empty_x && piece->x < piece->empty_y)
{
// Empty space is on the bottom-right.
// XX
// XO
board[piece->x][piece->y] = 1;
board[piece->x + 1][piece->y] = 1;
board[piece->x][piece->y + 1] = 1;
}
else if (piece->empty_x == piece->x + 1)
{
// Empty space is on the bottom-left.
// XX
// OX
board[piece->x][piece->y] = 1;
board[piece->x + 1][piece->y] = 1;
board[piece->x + 1][piece->y + 1] = 1;
}
}
else if (piece->type == "square")
{
board[piece->x][piece->y] = 1;
board[piece->x][piece->y + 1] = 1;
board[piece->x + 1][piece->y] = 1;
board[piece->x + 1][piece->y + 1] = 1;
}
}
// Add a structure for pieces
struct piece
{
uint8_t x;
uint8_t y;
uint8_t empty_x;
uint8_t empty_y;
// Type of the piece: "dot", "l_piece", "square"
char *type;
};
// Square
struct square
{
uint8_t x;
uint8_t y;
};
// Add a helper function to rotate the L-Piece
void rotate_l_piece(struct piece *piece)
{
// Pieces always rotate clockwise.
// Within given square space, determine the next position of empty space.
// Depending on the current position of the piece, move the empty space to the next position.
if (piece->empty_x == piece->x && piece->empty_y == piece->y)
{
// Empty space is on the top-left.
// OX -> XO
// XX -> XX
piece->empty_x = piece->x + 1;
}
else if (piece->empty_x < piece->x && piece->empty_y == piece->y)
{
// Empty space is on the top-right.
// XO -> XX
// XX -> XO
piece->empty_y = piece->y + 1;
}
else if (piece->empty_y == piece->y)
{
// Empty space is on the bottom-right.
// XX -> XX
// XO -> OX
piece->empty_x = piece->x - 1;
}
else if (piece->empty_x == piece->x + 1)
{
// Empty space is on the bottom-left.
// XX -> OX
// OX -> XX
piece->empty_y = piece->y - 1;
}
}
// Add helper functions to move pieces.
void move_piece_left(struct piece *piece)
{
if (piece->x == 0)
{
return;
}
piece->x--;
piece->empty_x--;
}
void move_piece_right(struct piece *piece)
{
if (piece->x == 6)
{
return;
}
piece->x++;
piece->empty_x++;
}
void move_piece_down(struct piece *piece)
{
if (piece->y == 6)
{
return;
}
piece->y++;
piece->empty_y++;
}
void move_piece_up(struct piece *piece)
{
if (piece->y == 0)
{
return;
}
piece->y--;
piece->empty_y--;
}
uint8_t prevB;
void Init()
{
// B
LATB = 0x00;
PORTB = 0x00;
TRISB = 0x10;
// C
LATC = 0x00;
PORTC = 0x00;
TRISC = 0x00;
// D
LATD = 0x00;
PORTD = 0x00;
TRISD = 0x00;
}
void InitializeTimerAndInterrupts()
{
// Enable pre-scalar
// Full pre-scale
// we also need to do in-code scaling
T0CON = 0x00;
T0CONbits.TMR0ON = 1;
T0CONbits.T0PS2 = 1;
T0CONbits.T0PS1 = 0;
T0CONbits.T0PS0 = 1;
// Pre-load the value
TMR0H = T_PRELOAD_HIGH;
TMR0L = T_PRELOAD_LOW;
RCONbits.IPEN = 0;
INTCON = 0x00;
INTCONbits.TMR0IE = 1;
INTCONbits.RBIE = 1;
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
}
// ============================ //
// INTERRUPT SERVICE ROUTINE //
// ============================ //
__interrupt(high_priority) void HandleInterrupt()
{
// Timer overflowed (333 ms)
if (INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;
// Pre-load the value
TMR0H = T_PRELOAD_HIGH;
TMR0L = T_PRELOAD_LOW;
// Fully lit LATC
LATD = ~PORTD;
}
if (INTCONbits.RBIF)
{
// Read the value to satisfy the interrupt
prevB = PORTB;
LATC = ~PORTC;
// Then clear the bit
INTCONbits.RBIF = 0;
}
}
__interrupt(low_priority) void HandleInterrupt2()
{
}
// ============================ //
// MAIN //
// ============================ //
void main()
{
Init();
InitializeTimerAndInterrupts();
prevB = PORTB;
__delay_ms(100);
// Main Loop
while (1)
{
//...
}
}