diff options
-rw-r--r-- | Jetris.ino | 335 | ||||
-rw-r--r-- | drawing.h | 24 | ||||
-rw-r--r-- | drawing.ino | 97 | ||||
-rw-r--r-- | maxCommands.h (renamed from MaxCommands.h) | 1 | ||||
-rw-r--r-- | sprites.h | 1 | ||||
-rw-r--r-- | sprites.ino | 1 |
6 files changed, 161 insertions, 298 deletions
@@ -1,35 +1,14 @@ -// THings that miss -// Functions that return something -// Make more safety - +#include "drawing.h" #include "sprites.h" -#include "MaxCommands.h" - -#define clk 5 -#define cs 6 -#define dataIn 3 -#define setDisplay(d) (curDisplay = d) -#define leftPin 2 -#define rightPin 4 -#define dropPin 11 -#define rotatePin 10 -#define clickTime 200 - -//Use the drawDot function to draw -uint8_t buttonLayer[16]; -uint8_t topLayer[16]; - -int curDisplay = 0; void setup() { - //Init Serial - Serial.begin(9600); + Serial.begin(115200); + Serial.println("Starting \n\n"); - Serial.println("Starting up \n\n\n"); + /* Prepare the random generator */ + randomSeed( analogRead(0) ); - randomSeed(analogRead(0)); - - //Init pins + /* Init pins */ pinMode(cs, OUTPUT); pinMode(clk, OUTPUT); pinMode(dataIn, OUTPUT); @@ -38,306 +17,66 @@ void setup() { pinMode(dropPin, INPUT_PULLUP); pinMode(rotatePin, INPUT_PULLUP); - //ButtonInterrupt - //attachInterrupt(digitalPinToInterrupt(left), buttonHandle, FALLING); - - //Setup displays - setDisplay(0); - initDisplay(); - - setDisplay(1); - initDisplay(); + initDisplays(0); + initDisplays(1); initSprites(); - - initGame(); + initGame(); } -///////////////////////////// -// GAME LOGIC // -///////////////////////////// +void loop() { + gameLoop(); +} -Sprite *block; -int xPos; -int yPos; +/* + * GAME LOGIC + */ +struct Sprite *cur_block; -long loopTime; +int x_pos, y_pos; void initGame() { initBlock(); } -void loop() { - +void gameLoop() { + + static long loop_time; + handleButtons(); - if(millis() - loopTime < 500) + if( millis() - loop_time < 500) return; - //Move - if(checkCollision(0, 1)) { - drawSprite(buttonLayer, xPos, yPos, block); + /* Move the block */ + if( checkCollision(0, 1) ){ + drawSprite(buttonLayer, xPos, yPos, cur_block); + + /* Handle the rows, from the top */ handleFullRows(0); renderAll(); - initBlock(); - }else{ + }else { + /* Free to move (one down)*/ moveBlock(0, 1); } - loopTime = millis(); - + loop_time = millis(); } -void initBlock(){ - xPos = 0; - yPos = 0; +void initBlock() { + xPos = yPos = 0; - block = blocks[random(7)]; + block = blocks[ random(7) ]; } -void moveBlock(int xMove, int yMove) { - xPos += xMove; - yPos += yMove; - - //Clear screen - drawRegion(topLayer, 0xFF, 0xFFFF, false); +void moveBlock(int x_move, int y_move) { + x_pos += x_move; + y_pos += y_move; - //Draw ball - drawSprite(topLayer, xPos, yPos, block); - - //Render - renderAll(); - -} - -//Checks if input and button layer have bits in common, or if a block hits button. Returns true if collision -int checkCollision(int xMove, int yMove) { - //Newolute position on map - int yNew = yPos + yMove; - int xNew = xPos + xMove; - - for(int i = 0; i < block->height; i++) { - if(( block->buff[i] >> xNew) & buttonLayer[i + yNew]) - return 1; - } - - //Check if out of bounds - if(xNew + block->width > 8 || xNew < 0 || yNew + block->height > 16) - return 1; - - return 0; -} + /* Redraw ball */ -void rotateBlock() { - Serial.println("Rotate"); - - //If next block exist, switch to that - if( block->rotateNext ) { - Serial.println((uint16_t)block); - Serial.println((uint16_t)block->rotateNext); - - block = block->rotateNext; - Serial.println((uint16_t)block); - } - - //And render - moveBlock(0, 0); -} - -void dropBlock() { - //Move down until it hits something - int count = 0; - while( !checkCollision(0, 1) ) { - moveBlock(0, 1); - delay(10); - } - - drawSprite(buttonLayer, xPos, yPos, block); -} - -void renderAll(){ - setDisplay(0); - render(0); - setDisplay(1); - render(8); -} - -void handleFullRows(int start) { - for(int i = start; i < 16; i++ ) { - if(buttonLayer[15 - i] == 0xFF) { - for(int j = i; j < 16; j++) { - buttonLayer[15 - j] = buttonLayer[14 - j]; - } - handleFullRows(i); - return; - } - } -} - -void renderToSerial() { - Serial.write(0x33); Serial.println("[2J"); - for(int i = 0; i < 16; i++) { - for(int b = 0; b < 8; b++) { - Serial.print( ( buttonLayer[i] & ( 1 << 7 - b ) ) > 0 ); - } - Serial.println(); - } -} - -///////////////////////////// -// Control Handling // -///////////////////////////// - -unsigned long leftLast, rightLast, dropLast, rotateLast; - -void handleButtons() { - //Read from switch - int leftState = !digitalRead(leftPin); - int rightState = !digitalRead(rightPin); - int dropState = !digitalRead(dropPin); - int rotateState = !digitalRead(rotatePin); - //Check if last click was over 100 ms ago - if(millis() - leftLast > clickTime && leftState) { - leftLast = millis(); - - //Move - if( !checkCollision(1, 0) ) { - moveBlock(1, 0); - } - } - - if(millis() - rightLast > clickTime && rightState) { - rightLast = millis(); - //Move - if( !checkCollision(-1, 0) ) { - moveBlock(-1, 0); - } - } - - if(millis() - dropLast > clickTime && dropState) { - dropLast = millis(); - - dropBlock(); - } - - if(millis() - rotateLast > clickTime+100 && rotateState) { - rotateLast = millis(); - - rotateBlock(); - } -} - -///////////////////////////// -// Screendrawing routines // -///////////////////////////// - -void initDisplay() { - - //clear all registers - for ( int i = 0; i < 0x0F; i++) { - writeCommand(i, 0); - } - - //Turn it on - writeCommand(maxSHUTDOWN_INV, 1); - - //Darker please - writeCommand(maxINTENSITY, 0x00); - - //Activate all lines - writeCommand(maxSCAN_LIMIT, 0x07); - -} - -//Draw a region, where mask specifies where to draw. -// xMask = 0b00111100, yMask = 0b01111110 will draw a small 4x6 box -void drawSprite(uint8_t layer[], uint8_t x, uint8_t y, Sprite* sprite) { - //Check if in range - if (x + sprite->width - 1 > 7 || y + sprite->height - 1> 15 ) - return; - - for ( int i = y; i < sprite->height + y; i++) { - //Calculate bits - uint8_t row = layer[i]; - row |= sprite->buff[i - y] >> x; - - layer[i] = row; - - } - -} - -void drawRegion(uint8_t layer[], uint8_t xMask, uint16_t yMask, bool state) { - for (int i = 0; i < 16; i++ ) { - //If y index not in mask, go to next - if (! ( yMask & 1 << i ) ) - continue; - - //Flip the bits - uint8_t row = layer[i]; - if ( state ) { - //Write 1 where on the 1's places in xMask - row |= xMask; - } else { - //Write 0. ~ means bitwise NOT - row &= ~( xMask ); - } - layer[i] = row; - } -} - -unsigned long reRenderLast; - -void render(int where) { - - static uint8_t onScreen[16]; - - bool reRender = (millis() - reRenderLast ) > 1000; - - for(int i = where; i < (where + 8); i++ ) { - uint8_t toWrite = buttonLayer[i] | topLayer[i]; - if(onScreen[i] == toWrite && !reRender) - continue; - - writeCommand(maxDIGIT_0 + i - where, buttonLayer[i] | topLayer[i]); - - onScreen[i] = toWrite; - } - - if(reRender) { - reRenderLast = millis(); - } - -} - -void writeCommand(uint8_t addr, uint8_t data) { - uint16_t uint8_tToWrite = addr << 8 | data; - - //Set Chip select low - digitalWrite(cs, LOW); - - //MSBFIRST is a arduino standard, which says that data goes from left to right - - shiftOut(dataIn, clk, MSBFIRST, addr); - shiftOut(dataIn, clk, MSBFIRST, data); - - //To get to other displays padding is added to step through them - serialPad(curDisplay * 2); - - digitalWrite(cs, HIGH); - - //To Clear out other displays more padding is added - serialPad(2 * 2); -} - -void serialPad(int count) { - - for(int i = 0; i < count; i++) { - //Pad with no-ops - shiftOut(dataIn, clk, MSBFIRST, 0); - } } diff --git a/drawing.h b/drawing.h new file mode 100644 index 0000000..9089d9b --- /dev/null +++ b/drawing.h @@ -0,0 +1,24 @@ +/* Ensure only one definition */ +#ifndef drawing +#define drawing + +#define BUFF_HEIGHT 16 +#define REDRAW_TIME 1000 +#define NUM_DISPLAY 2 +#define CLK 5 +#define CS 6 +#define DATA_IN 3 + +/* Layers */ +uint8_t buttonLayer[16]; +uint8_t topLayer[16]; + +/* Drawing to buffer */ +void drawSprite(uint8_t layer[], uint8_t x, uint8_t y, struct Sprite* sprite); +void clearBuffer(uint8_t layer[] ); + +/* Screen interface commands */ +void render(uint8_t screenBuffer[], unsigned int where); +void initDisplays(int display); + +#endif diff --git a/drawing.ino b/drawing.ino new file mode 100644 index 0000000..b326c7f --- /dev/null +++ b/drawing.ino @@ -0,0 +1,97 @@ +#include "drawing.h" +#include "sprites.h" +#include "maxCommands.h" + +/* Draw sprite to screen + * + * layer: 16x8 bit buffer + * x, y: Position on screen + * sprite: Sprite to draw + */ +void drawSprite(uint8_t layer[], uint8_t x, uint8_t y, struct Sprite* sprite) { + /* Check if in range */ + if( x + sprite->width > 8 || y + sprite->height > 16) + return; + + /* Or buffer with sprite */ + for (int i = y; i < sprite->height + y; i++) { + layer[i] |= sprite->buff[i - y] >> x; + } +} + +/* Clear specified buffer */ +void clearBuffer(uint8_t layer[] ) { + for( int i = 0; i < BUFF_HEIGHT; i++ ) { + layer[i] = 0; + } +} + +/* Render specfied screenbuffer + * + * device: Which screen + * where: It render the next 8 bytes from this index + */ +void render(int device, uint8_t screenBuffer[], unsigned int where) { + + static uint8_t onScreen[BUFF_HEIGHT]; + static unsigned long reRenderLast; + + int i; + uint8_t toWrite; + + /* Completely rerender every one second */ + bool reRender = (millis() - reRenderLast ) > REDRAW_TIME; + + /* Will draw 8 lines from /where/. */ + for(i = where; i < (where + 8); i++) { + toWrite = screenbuffer[i]; + + /* Check if whats on screen is the same */ + if(onScreen[i] == toWrite && !reRender) + continue; + + writeCommand(device, maxDIGIT_0 + i - where, toWrite); + + /* Keep track of whats on screen */ + onScreen[i] = toWrite; + } + + if(reRender) + reRenderLast = millis(); + +} + +/* Write a register to specified display */ +static void writeCommand(int display, uint8_t addr, uint8_t data) { + /* Chip select low */ + digitalWrite(CS, LOW); + + /* Shift out the data, to the max shift registers + * MSBFIRST makes the MSB go first out */ + shiftOut(DATA_IN, CLK, MSBFIRST, addr); + shiftOut(DATA_IN, CLK, MSBFIRST, data); + + /* If the device is number two, the commands should be shiftet through + * Each MAX, holds 16 bits(2 bytes) */ + serialPad(curDisplay * 2); + + digitalWrite(CS, HIGH); + + /* Before writing new commands, all the buffers should be cleaned */ + serialPad(NUM_DISPLAY * 2); + +} + +/* Init specified display */ +void initDisplays(int display) { + +} + +/* Send x amount of empty bytes, recursively(for fun)*/ +static void serialPad(int count) { + shiftOut(DATA_IN, CLK, MSBFIRST, 0); + + if ( count ) + serialPad(count-1); +} + diff --git a/MaxCommands.h b/maxCommands.h index 2baff64..8fed0ac 100644 --- a/MaxCommands.h +++ b/maxCommands.h @@ -16,3 +16,4 @@ #define maxSCAN_LIMIT 0x0B #endif + @@ -190,3 +190,4 @@ struct Sprite lBlockL = { struct Sprite *blocks[] = { &iBlock, &oBlock, &tBlock, &sBlock, &zBlock, &jBlock, &lBlock }; #endif + diff --git a/sprites.ino b/sprites.ino index d519095..54f8aa5 100644 --- a/sprites.ino +++ b/sprites.ino @@ -27,3 +27,4 @@ void initSprites() { lBlockD.rotateNext = &lBlockL; lBlockL.rotateNext = &lBlock; } + |