Last active
December 27, 2015 17:00
-
-
Save osvein/0236f7b37fdd03de603e to your computer and use it in GitHub Desktop.
Pong on Arduino attempt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "GraphicsDisplay.h" | |
| #define DELAY 1 | |
| #define DELAY_RESET 2 | |
| GraphicsDisplay::GraphicsDisplay(int rs, int rw, int e, volatile byte *db_port, volatile byte *db_pin, volatile byte *db_ddr, int cs0, int cs1, int rst) : Rectangle(NULL, 128, 64), rs(rs), rw(rw), e(e), db_port(db_port), db_pin(db_pin), db_ddr(db_ddr), cs0(cs0), cs1(cs1), rst(rst) { | |
| pinMode(rs, OUTPUT); | |
| pinMode(rw, OUTPUT); | |
| pinMode(e, OUTPUT); | |
| *(db_ddr) = 0xFF; | |
| pinMode(cs0, OUTPUT); | |
| pinMode(cs1, OUTPUT); | |
| pinMode(rst, OUTPUT); | |
| this->reset(); | |
| } | |
| void GraphicsDisplay::reset() { | |
| digitalWrite(this->rst, LOW); | |
| delay(DELAY_RESET); | |
| digitalWrite(this->rst, HIGH); | |
| } | |
| void GraphicsDisplay::enable() { | |
| digitalWrite(this->e, LOW); | |
| delayMicroseconds(DELAY); | |
| digitalWrite(this->e, HIGH); | |
| delayMicroseconds(DELAY); | |
| } | |
| void GraphicsDisplay::selectChip(int chip) { | |
| digitalWrite(this->cs0, chip ? HIGH : LOW); | |
| digitalWrite(this->cs1, chip ? LOW : HIGH); | |
| } | |
| void GraphicsDisplay::send(byte data) { | |
| *(this->db_port) = data; | |
| this->enable(); | |
| } | |
| void GraphicsDisplay::instruct(byte instruction) { | |
| digitalWrite(this->rs, LOW); | |
| this->send(instruction); | |
| digitalWrite(this->rs, HIGH); | |
| } | |
| void GraphicsDisplay::flush(void) { | |
| digitalWrite(this->rs, LOW); | |
| digitalWrite(this->rw, HIGH); | |
| *(this->db_ddr) = 0x00; | |
| do { | |
| this->enable(); | |
| } while (*(this->db_pin) & (GD_BUSY_MASK | GD_RESET_MASK)); | |
| digitalWrite(this->rs, HIGH); | |
| digitalWrite(this->rw, LOW); | |
| *(this->db_ddr) = 0xFF; | |
| } | |
| size_t GraphicsDisplay::write(uint8_t data) { | |
| word raw = data; | |
| raw <<= this->getCursorX() % 8; | |
| this->flush(); | |
| this->send(lowByte(raw)); | |
| byte high = highByte(raw); | |
| if (high) { | |
| this->flush(); | |
| this->send(high); | |
| } | |
| return 1; | |
| } | |
| boolean GraphicsDisplay::seek(unsigned int x, unsigned int y) { | |
| if (!Rectangle::seek(x, y)) { | |
| return false; | |
| } | |
| this->selectChip(x > 63); | |
| this->flush(); | |
| this->instruct((y & GD_Y_MASK) | GD_Y); | |
| int page = x / 8; | |
| this->flush(); | |
| this->instruct((page & GD_X_MASK) | GD_X); | |
| } | |
| Rectangle::Rectangle(Rectangle *parent, unsigned int width, unsigned int height) : parent(parent), width(width), height(height) { | |
| } | |
| Rectangle *Rectangle::getParent() const { | |
| return this->parent; | |
| } | |
| unsigned int Rectangle::getWidth() const { | |
| return this->width; | |
| } | |
| unsigned int Rectangle::getHeight() const { | |
| return this->height; | |
| } | |
| unsigned int Rectangle::getX() const { | |
| return this->x; | |
| } | |
| unsigned int Rectangle::getY() const { | |
| return this->y; | |
| } | |
| boolean Rectangle::move(unsigned int x, unsigned int y) { | |
| Rectangle *parent = this->getParent(); | |
| if (parent == NULL) { | |
| return false; | |
| } | |
| int bytes = (this->getWidth() / 8); | |
| if (this->getWidth() % 8) { | |
| bytes++; | |
| } | |
| // clear | |
| for (int iy = 0; iy < this->getHeight(); iy++) { | |
| parent->seek(this->getX(), this->getY() + iy); | |
| for (int ix = 0; ix <= bytes; ix++) { | |
| parent->write(0x00); | |
| } | |
| } | |
| this->x = x; | |
| this->y = y; | |
| // draw | |
| for (int iy = 0; iy < this->getHeight(); iy++) { | |
| parent->seek(this->getX(), this->getY() + iy); | |
| for (int ix = 0; ix <= bytes; ix++) { | |
| byte data = 0xFF; | |
| if (ix == 0) { | |
| data <<= this->getWidth() % 8; | |
| } | |
| else if (ix == bytes) { | |
| data >>= 8 - (this->getWidth() % 8); | |
| } | |
| parent->write(data); | |
| } | |
| } | |
| } | |
| const Rectangle *Rectangle::detectCollision(int siblingc, const Rectangle *const siblings[]) const { | |
| for (int i = 0; i < siblingc; i++) { | |
| const Rectangle *sibling = siblings[i]; | |
| int collidesX = 0; | |
| collidesX |= this->getX() < sibling->getX() + sibling->getWidth(); | |
| collidesX |= this->getX() + this->getWidth() < sibling->getX(); | |
| int collidesY = 0; | |
| collidesY |= this->getY() < sibling->getY() + sibling->getHeight(); | |
| collidesY |= this->getY() + this->getHeight() < sibling->getY(); | |
| if (collidesX && collidesY) { | |
| return sibling; | |
| } | |
| } | |
| return NULL; | |
| } | |
| unsigned int Rectangle::getCursorX() const { | |
| Rectangle *parent = this->getParent(); | |
| if (parent == NULL) { | |
| return this->getX(); | |
| } | |
| return parent->getCursorX() - this->getX(); | |
| } | |
| unsigned int Rectangle::getCursorY() const { | |
| Rectangle *parent = this->getParent(); | |
| if (parent == NULL) { | |
| return this->getY(); | |
| } | |
| return parent->getCursorY() - this->getY(); | |
| } | |
| size_t Rectangle::write(uint8_t data) { | |
| Rectangle *parent = this->getParent(); | |
| if (parent == NULL) { | |
| return 0; | |
| } | |
| return parent->write(data); | |
| } | |
| boolean Rectangle::seek(unsigned int x, unsigned int y) { | |
| if (x >= this->getWidth() || y >= this->getHeight()) { | |
| return false; | |
| } | |
| Rectangle *parent = this->getParent(); | |
| if (parent == NULL) { | |
| this->x = x; | |
| this->y = y; | |
| return true; | |
| } | |
| return parent->seek(x + this->getX(), y + this->getY()); | |
| } | |
| boolean Rectangle::seek(unsigned int address) { | |
| address *= 8; | |
| unsigned int y = address / this->getHeight(); | |
| unsigned int x = (address % this->getHeight()) * 8; | |
| return this->seek(x, y); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef GraphicsDisplay_h | |
| #define GraphicsDisplay_h 1 | |
| #include <Arduino.h> | |
| #define GD_OFF 0x3E // 00111110 | |
| #define GD_OFF_MASK 0x01 // 00000001 | |
| #define GD_Y 0x40 // 01000000 | |
| #define GD_Y_MASK 0x3F // 00111111 | |
| #define GD_X 0xB8 // 10111000 | |
| #define GD_X_MASK 0x07 // 00000111 | |
| #define GD_Z 0xC0 // 11000000 | |
| #define GD_Z_MASK 0x3F // 00111111 | |
| #define GD_BUSY_MASK 0x01 // 00000001 | |
| #define GD_OFF_MASK 0x04 // 00000100 | |
| #define GD_RESET_MASK 0x08 // 00001000 | |
| class Rectangle : public Print { | |
| public: | |
| Rectangle(Rectangle *parent, unsigned int width, unsigned int height); | |
| Rectangle *getParent() const; | |
| unsigned int getWidth() const; | |
| unsigned int getHeight() const; | |
| unsigned int getX() const; | |
| unsigned int getY() const; | |
| boolean move(unsigned int x, unsigned int y); | |
| const Rectangle *detectCollision(int siblinc, const Rectangle *const siblings[]) const; | |
| virtual unsigned int getCursorX() const; | |
| virtual unsigned int getCursorY() const; | |
| virtual size_t write(uint8_t data); | |
| virtual boolean seek(unsigned int x, unsigned int y); | |
| virtual boolean seek(unsigned int address); | |
| private: | |
| Rectangle *const parent; | |
| const unsigned int width, height; | |
| unsigned int x, y; | |
| }; | |
| class GraphicsDisplay : public Rectangle { | |
| public: | |
| GraphicsDisplay(int rs, int rw, int e, volatile byte *db_port, volatile byte *db_pin, volatile byte *db_ddr, int cs0, int cs1, int rst); | |
| void reset(); | |
| void enable(); | |
| void selectChip(int chip); | |
| void send(byte data); | |
| void instruct(byte instruction); | |
| void flush(void); | |
| size_t write(byte data); | |
| boolean seek(unsigned int x, unsigned int y); | |
| private: | |
| const int rs, rw, e, cs0, cs1, rst; | |
| volatile byte *const db_port, *const db_pin, *const db_ddr; | |
| }; | |
| #endif // GraphicsDisplay_h |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "GraphicsDisplay.h" | |
| #define BALL_WIDTH 2 | |
| #define BALL_HEIGHT 2 | |
| #define PADDLE_WIDTH 2 | |
| #define PADDLE_HEIGHT 16 | |
| #define PADDLE_OFFSET 8 | |
| #define PADDLE1_X PADDLE_OFFSET | |
| #define PADDLE2_X (WIDTH - PADDLE_OFFSET - 1) | |
| #define UPDATE_RATE 100 | |
| #define BUTTON_PCIE PCIE1 | |
| #define BUTTON_PCMSK PCMSK1 | |
| #define BUTTON_PCINT_VECT PCINT1_vect | |
| #define BUTTON1_PCINT PCINT9 | |
| #define BUTTON2_PCINT PCINT10 | |
| #define BUTTON1_PIN A1 | |
| #define BUTTON2_PIN A2 | |
| #define RECT_COUNT 3 | |
| #define WIDTH 128 | |
| #define HEIGHT 64 | |
| int paddle1YDir = -1; | |
| int paddle2YDir = -1; | |
| int paddle1YPos = 40; | |
| int paddle2YPos = 40; | |
| int ballXPos = 64; | |
| int ballYPos = 32; | |
| int ballYDir = -1; | |
| int ballXDir = 1; | |
| GraphicsDisplay disp(8, 9, 10, &PORTD, &PIND, &DDRD, 11, 12, 13); | |
| Rectangle ball(&disp, BALL_WIDTH, BALL_HEIGHT); | |
| Rectangle paddle1(&disp, PADDLE_WIDTH, PADDLE_HEIGHT); | |
| Rectangle paddle2(&disp, PADDLE_WIDTH, PADDLE_HEIGHT); | |
| const Rectangle *const rects[] = { &ball, &paddle1, &paddle2 }; | |
| void setup() { | |
| //Buttonpins | |
| pinMode(BUTTON1_PIN, INPUT_PULLUP); | |
| pinMode(BUTTON2_PIN, INPUT_PULLUP); | |
| // Attach pin change interrupts | |
| PCICR |= _BV(BUTTON_PCIE); | |
| BUTTON_PCMSK |= _BV(BUTTON1_PCINT) | _BV(BUTTON2_PCINT); | |
| } | |
| void loop() { | |
| //Moving the ball, checking for colission, adjusting the direction in x and y axis, | |
| //and resetting the game when someone wins | |
| if (!ball.move(ballXPos, ballYPos)) { | |
| ballYDir=ballYDir*(-1); | |
| } | |
| const Rectangle *collision = ball.detectCollision(RECT_COUNT, rects); | |
| if (collision == &paddle1 || collision == &paddle2) { | |
| ballXDir=ballXDir*(-1); | |
| } | |
| if (ballXPos>PADDLE2_X||ballXPos<PADDLE1_X) { | |
| int paddle1YDir = -1; | |
| int paddle2YDir = -1; | |
| int paddle1YPos = 40; | |
| int paddle2YPos = 40; | |
| int ballXPos = 64; | |
| int ballYPos = 32; | |
| int ballYDir = -1; | |
| int ballXDir = 1; | |
| ball.move(ballXPos, ballYPos); | |
| paddle1.move(PADDLE1_X, paddle1YPos); | |
| paddle2.move(PADDLE2_X, paddle2YPos); | |
| delay(500); | |
| } | |
| //---------------------------------------- | |
| //Colission detection for paddles, disallowing them to move further | |
| if (!paddle1.move(PADDLE1_X, paddle1YPos)) { | |
| paddle1YDir=0; | |
| } | |
| if (!paddle2.move(PADDLE2_X, paddle2YPos)) { | |
| paddle2YDir=0; | |
| } | |
| //------------------------------------------------------------------ | |
| //Increment the positions | |
| ballXPos+=ballXDir; | |
| ballYPos+=ballYDir; | |
| paddle1YPos+=paddle1YDir; | |
| paddle2YPos+=paddle2YDir; | |
| //----------------------- | |
| //Setting the updaterate of the game | |
| delay(UPDATE_RATE); | |
| } | |
| //Functions from the interrupt | |
| ISR(BUTTON_PCINT_VECT) { | |
| paddle1YDir = digitalRead(BUTTON1_PIN) == HIGH ? 1 : -1; | |
| paddle2YDir = digitalRead(BUTTON2_PIN) == HIGH ? 1 : -1; | |
| } | |
| //------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment