// Danijel Ptičar
#define OP_DECODEMODE 9
#define OP_INTENSITY 10
#define OP_SCANLIMIT 11
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
#define leftButton A2
#define rightButton A4
#define rotateButton A3
#define downButton A1
int DIN = 11; //
int CLK = 13; //
int LOAD = 10; //
byte matrix[8];
byte piece[2];
int8_t pieceX, pieceY;
uint16_t pieceCount = 0;
uint8_t refreshDisplay = true;
void sendData( byte address, byte data)
{
uint16_t bitmask;
uint16_t pck;
pck = address;
pck <<= 8;
pck |= data;
for ( bitmask = 0x8000; bitmask; bitmask >>= 1)
{
/*
if (bitmask & pck) PORTB |= 0b00001000; //digitalWrite(DIN, 1);
else PORTB &= ~0b00001000; //digitalWrite(DIN, 0);
PORTB |= 0b00100000; //digitalWrite(CLK, HIGH);
PORTB &= ~0b00100000; //digitalWrite(CLK, LOW);
*/
if (bitmask & pck) digitalWrite(DIN, 1);
else digitalWrite(DIN, 0);
digitalWrite(CLK, HIGH);
digitalWrite(CLK, LOW);
}
digitalWrite(LOAD, HIGH);
digitalWrite(LOAD, LOW);
}
void clearMatrix() // brise matricu i lik
{
piece[0] = 0b00000000;
piece[1] = 0b00000000;
for (int x = 0; x < 8; x++) matrix[x] = 0;
}
#define np 6
unsigned long Randomtime;
byte rotatable;
void createPiece()
{
unsigned long time;
time = Randomtime + millis();
rotatable = 0;
if (time % np == 0)
{
piece[0] = 0b00000011;
piece[1] = 0b00000011;
}
if (time % np == 1)
{
piece[0] = 0b00000001; // left
piece[1] = 0b00000011; // right
rotatable = 1;
}
if (time % np == 2)
{
piece[0] = 0b00000001; // left
piece[1] = 0b00000000; // right
}
if (time % np == 3)
{
piece[0] = 0b00000001; // left
piece[1] = 0b00000001; // right
}
if (time % np == 4)
{
piece[0] = 0b00000011; // left
piece[1] = 0b00000000; // right
}
if (time % np == 5)
{
piece[0] = 0b00000001; // left
piece[1] = 0b00000010; // right
rotatable = 1;
}
pieceX = 3;
pieceY = 0;
}
byte checkCollision()
{
if (matrix[pieceX] & (piece[0] << pieceY)) return 1;
if (matrix[pieceX + 1] & (piece[1] << pieceY)) return 1;
return 0;
}
void rotate() // rotira lik
{
byte bit1, bit2, bit3, bit4;
if (!rotatable) return;
bit1 = piece[0] & 0b00000010;
bit2 = piece[0] & 0b00000001;
bit3 = piece[1] & 0b00000010;
bit4 = piece[1] & 0b00000001;
piece[0] = piece[1] = 0x00;
if (bit1) piece[0] |= 0b00000001;
if (bit2) piece[1] |= 0b00000001;
if (bit3) piece[0] |= 0b00000010;
if (bit4) piece[1] |= 0b00000010;
}
byte checkBottomBorder()
{
int8_t numberOfPixels = 0; // prebrojavam koliko ima pixela u liku
for (byte bitmask = 0x80; bitmask; bitmask >>= 1) if (bitmask & piece[0]) numberOfPixels++;
for (byte bitmask = 0x80; bitmask; bitmask >>= 1) if (bitmask & piece[1]) numberOfPixels++;
// prebrojavam koliko ima pixela nakon shiftanja, ako je broj isti sve OK, inace je lik ispao van
for (byte bitmask = 0x80; bitmask; bitmask >>= 1) if (bitmask & (piece[0] << pieceY)) numberOfPixels--;
for (byte bitmask = 0x80; bitmask; bitmask >>= 1) if (bitmask & (piece[1] << pieceY)) numberOfPixels--;
if (numberOfPixels != 0) return 1;
return 0;
}
byte checkBordersLR()
{
if (piece[0] && pieceX < 0) return 1;
if (piece[1] && pieceX < -1) return 1;
if (piece[0] && pieceX > 7) return 1;
if (piece[1] && pieceX > 6) return 1;
return 0;
}
void mergeMatrixPiece()
{
matrix[pieceX] |= (piece[0] << pieceY);
matrix[pieceX + 1] |= (piece[1] << pieceY);
piece[0] = 0;
piece[1] = 0;
}
byte clearFullRow()
{
byte bitmask = 0x80;
byte bm1 = 0x00;
for (bitmask = 0x80; bitmask; bitmask >>= 1)
{
byte pixelCount = 0;
for (byte x = 0; x < 8; x++)
{
if (bitmask & matrix[x]) pixelCount++;
}
if (pixelCount == 8)
{
for (byte k = 0; k < 5; k++)
{
for (byte x = 0; x < 8; x++)
{
matrix[x] = matrix[x] & ~bitmask;
}
drawMatrix();
delay(50);
for (byte x = 0; x < 8; x++)
{
matrix[x] = matrix[x] | bitmask;
}
drawMatrix();
delay(50);
}
// ovo brise pixele u punom redu
for (byte x = 0; x < 8; x++) {
matrix[x] = (matrix[x] & bm1) | ( (matrix[x] << 1) & (bm1 ^ 0xFF) );
}
return 1;
} else bm1 = bm1 | bitmask;
}
return 0;
}
void drawMatrix()
{
for (int x = 0; x < 8; x++)
{
if (x == pieceX) sendData(x + 1, matrix[x] | piece[0] << pieceY);
else if (x == pieceX + 1) sendData(x + 1, matrix[x] | piece[1] << pieceY);
else sendData(x + 1, matrix[x]);
}
refreshDisplay = false;
}
unsigned long time1;
byte intensity = 0;
void setup() {
// put your setup code here, to run once:
pinMode(DIN, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(LOAD, OUTPUT);
digitalWrite(LOAD, LOW);
pinMode(leftButton, INPUT_PULLUP);
pinMode(rightButton, INPUT_PULLUP);
pinMode(rotateButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
sendData(OP_DISPLAYTEST, 0);
sendData(OP_SCANLIMIT, 7);
sendData(OP_DECODEMODE, 0);
sendData(OP_SHUTDOWN, 1);
for (int i = 0; i < 8; i++) sendData(i + 1, 0b00000000);
sendData(OP_INTENSITY, 0);
Serial.begin(57600);
time1 = millis();
clearMatrix();
createPiece();
}
uint32_t buttonMillis = 0;
uint8_t buttonState[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
uint8_t checkButton(int bp)
{
if (millis() - buttonMillis > 50)
if (digitalRead(bp) == 0 && buttonState[bp] == 1)
{
buttonState[bp] = 0;
buttonMillis = millis();
return 1;
}
if (millis() - buttonMillis > 50)
if (digitalRead(bp) == 1 && buttonState[bp] == 0)
{
buttonState[bp] = 1;
buttonMillis = millis();
return 0;
}
return 0;
}
#define startSpeed 900
unsigned long defSpeed = startSpeed;
byte pixelX = 0, pixelY = 0;
int16_t score = 0;
byte gameEND = 0;
unsigned long currentSpeed = startSpeed;
void loop() {
// put your main code here, to run repeatedly:
Randomtime = time1 = millis();
score = 0;
defSpeed = startSpeed;
currentSpeed = startSpeed;
clearMatrix();
createPiece();
gameEND = 0;
pieceCount = 0;
while (!gameEND)
{
if (refreshDisplay) drawMatrix();
byte newCode = 0;
if (checkButton(leftButton)) newCode = 3;
if (checkButton(rightButton)) newCode = 4;
if (checkButton(rotateButton)) newCode = 1;
if (checkButton(downButton)) newCode = 2;
Randomtime = millis();
if ( newCode )
{
if (newCode == 1) {
rotate();
if (checkBordersLR() | checkCollision()) rotate(), rotate(), rotate();
}
if (newCode == 2) {
currentSpeed = 100;
}
if (newCode == 3) { // left
pieceX--;
if (checkBordersLR() | checkCollision()) pieceX++;
}
if (newCode == 4) {// right
pieceX++;
if (checkBordersLR() | checkCollision()) pieceX--;
}
if (newCode == 5) sendData(OP_INTENSITY, intensity++);
refreshDisplay = true;
}
if (millis() - time1 > currentSpeed)
{
pieceY++;
if (checkBottomBorder()) {
pieceY--;
mergeMatrixPiece();
for (int i = 0; i < 2; i++) score += clearFullRow(); // dovoljno 2 puta
if (defSpeed > 300) defSpeed -= 25;
else defSpeed -= 5;
//Serial.print(currentSpeed); Serial.print(" "); Serial.print(pieceCount); Serial.print(" "); Serial.println(score);
createPiece();
pieceCount++;
currentSpeed = defSpeed;
}
if (checkCollision()) {
pieceY--;
mergeMatrixPiece();
for (int i = 0; i < 2; i++) score += clearFullRow();
if (defSpeed > 300) defSpeed -= 25;
else defSpeed -= 5;
//Serial.print(defSpeed); Serial.print(" "); Serial.print(pieceCount); Serial.print(" "); Serial.println(score);
createPiece(); // mora biti zajedno, cim kreiram lik da vidim dali lezi na necemu !
pieceCount++;
if (checkCollision()) gameEND = 1;
currentSpeed = defSpeed;
}
time1 = millis();
refreshDisplay = true;
}
}// gameEND
clearMatrix();
drawMatrix();
if (score) {
for (int x = 0; score; x++)
{
byte bitmask = 0x80;
while (score && bitmask)
{
matrix[x] |= bitmask;
bitmask >>= 1;
score--;
drawMatrix();
delay(200);
}
}
delay(4000);
}
delay(1000);
}