example game

This commit is contained in:
ekem 2015-04-30 22:17:25 -07:00
commit 7c4b38cb7d
8 changed files with 1896 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.swp

745
ArduBreakout.ino Normal file
View File

@ -0,0 +1,745 @@
/*
Breakout
Copyright (C) 2011 Sebastian Goscik
All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#include <SPI.h>
#include <Wire.h>
#include "Arduboy.h"
#include <EEPROM.h>
#include "breakout_bitmaps.h"
#define OLED_DC 8
#define OLED_CS 10 // SPI slave-select
#define OLED_CLK 13 // hardware SPI clock
#define OLED_MOSI 11 // hardware SPI MOSI
#define OLED_RESET 7
Arduboy display;
const byte width = 128; //Width of screen
const byte height = 64; //Hight of screen
int dx = -1; //Initial movement of ball
int dy = -1; //Initial movement of ball
int xb; //Balls starting possition
int yb; //Balls starting possition
boolean released; //If the ball has been released by the player
boolean paused = false; //If the game has been paused
byte xPaddle; //X position of paddle
boolean isHit[5][12]; //Array of if bricks are hit or not
boolean bounced=false; //Used to fix double bounce glitch
byte lives = 3; //Amount of lives
byte level = 1; //Current level
unsigned int score=0; //Score for the game
unsigned int brickCount; //Amount of bricks hit
byte pad,pad2,pad3; //Button press buffer used to stop pause repeating
byte oldpad,oldpad2,oldpad3;
char text[16]; //General string buffer
boolean start=false; //If in menu or in game
boolean initialDraw=false;//If the inital draw has happened
char initials[3]; //Initials used in high score
//Ball Bounds used in collision detection
byte leftBall;
byte rightBall;
byte topBall;
byte bottomBall;
//Brick Bounds used in collision detection
byte leftBrick;
byte rightBrick;
byte topBrick;
byte bottomBrick;
int ballclock = 0;
#include "pins_arduino.h" // Arduino pre-1.0 needs this
PROGMEM const unsigned char arduino [] =
{
0x3F, 0xFF, 0xFF, 0xFC, 0x40, 0x00, 0x00, 0x02, 0x89, 0x99,0x54,
0x91, 0x95, 0x55, 0x56, 0xA9, 0x9D, 0x95, 0x55, 0xA9, 0x95, 0x59,
0xD4, 0x91, 0x40, 0x00, 0x00, 0x02, 0x3F, 0xFF, 0xFF, 0xFC
};
void intro()
{
for(int i = -8; i < 28; i = i + 2)
{
display.clearDisplay();
display.setCursor(46, i);
display.print("ARDUBOY");
display.display();
}
tone(A2, 987, 160);
delay(160);
tone(A2, 1318, 400);
delay(2000);
}
void setup()
{
SPI.begin();
display.start();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Hello World!");
display.display();
intro();
}
void movePaddle()
{
//Move right
if(xPaddle < width - 12)
{
if( !digitalRead(5) )
{
xPaddle++;
}
}
//Move left
if(xPaddle > 0)
{
if( !digitalRead(9))
{
xPaddle--;
}
}
}
void moveBall()
{
if(released)
{
//Move ball
xb=xb + dx;
yb=yb + dy;
//Set bounds
leftBall = xb;
rightBall = xb + 2;
topBall = yb;
bottomBall = yb + 2;
//Bounce off top edge
if (yb <= 0)
{
yb = 2;
dy = -dy;
tone(A2, 523, 250);
}
//Lose a life if bottom edge hit
if (yb >= 64)
{
display.drawRect(xPaddle, 63, 11, 1, 0);
xPaddle = 54;
yb=60;
released = false;
lives--;
drawLives();
tone(A2, 175, 250);
if (random(0, 2) == 0)
{
dx = 1;
}
else
{
dx = -1;
}
}
//Bounce off left side
if (xb <= 0)
{
xb = 2;
dx = -dx;
tone(A2, 523, 250);
}
//Bounce off right side
if (xb >= width - 2)
{
xb = width - 4;
dx = -dx;
tone(A2, 523, 250);
}
//Bounce off paddle
if (xb+1>=xPaddle && xb<=xPaddle+12 && yb+2>=63 && yb<=64)
{
dy = -dy;
dx = ((xb-(xPaddle+6))/3); //Applies spin on the ball
tone(A2, 200, 250);
}
//Bounce off Bricks
for (byte row = 0; row < 4; row++)
{
for (byte column = 0; column < 14; column++)
{
if (!isHit[row][column])
{
//Sets Brick bounds
leftBrick = 10 * column;
rightBrick = 10 * column + 10;
topBrick = 6 * row + 1;
bottomBrick = 6 * row + 7;
//If A collison has occured
if (topBall <= bottomBrick && bottomBall >= topBrick &&
leftBall <= rightBrick && rightBall >= leftBrick)
{
Score();
brickCount++;
isHit[row][column] = true;
display.drawRect(10*column, 2+6*row, 8, 4, 0);
//Vertical collision
if (bottomBall > bottomBrick || topBall < topBrick)
{
//Only bounce once each ball move
if(!bounced)
{
dy =- dy;
yb += dy;
bounced = true;
tone(A2, 261, 250);
}
}
//Hoizontal collision
if (leftBall < leftBrick || rightBall > rightBrick)
{
//Only bounce once brick each ball move
if(!bounced)
{
dx =- dx;
xb += dx;
bounced = true;
tone(A2, 261, 250);
}
}
}
}
}
}
//Reset Bounce
bounced = false;
}
else
{
//Ball follows paddle
xb=xPaddle + 5;
//Release ball if FIRE pressed
pad3 = !digitalRead(A0);
if (pad3 == 1 && oldpad3 == 0)
{
released=true;
//Apply random direction to ball on release
if (random(0, 2) == 0)
{
dx = 1;
}
else
{
dx = -1;
}
//Makes sure the ball heads upwards
dy = -1;
}
oldpad3 = pad3;
}
}
void drawBall()
{
display.drawPixel(xb, yb, 0);
display.drawPixel(xb+1, yb, 0);
display.drawPixel(xb, yb+1, 0);
display.drawPixel(xb+1, yb+1, 0);
if(ballclock>4)
{
moveBall();
ballclock=0;
}
ballclock++;
display.drawPixel(xb, yb, 1);
display.drawPixel(xb+1, yb, 1);
display.drawPixel(xb, yb+1, 1);
display.drawPixel(xb+1, yb+1, 1);
}
void drawPaddle()
{
display.drawRect(xPaddle, 63, 11, 1, 0);
movePaddle();
display.drawRect(xPaddle, 63, 11, 1, 1);
}
void drawLives()
{
sprintf(text, "LIVES:%u", lives);
display.setCursor(0, 90);
display.print(text);
}
void drawGameOver()
{
display.drawPixel(xb, yb, 0);
display.drawPixel(xb+1, yb, 0);
display.drawPixel(xb, yb+1, 0);
display.drawPixel(xb+1, yb+1, 0);
display.setCursor(52, 42);
display.print( "Game");
display.setCursor(52, 54);
display.print("Over");
display.display();
delay(4000);
}
void pause()
{
paused = true;
//Draw pause to the screen
display.setCursor(52, 45);
display.print("PAUSE");
display.display();
while (paused)
{
delay(150);
//Unpause if FIRE is pressed
pad2 = !digitalRead(A0);
if (pad2 > 1 && oldpad2 == 0 && released)
{
display.fillRect(52, 45, 30, 11, 0);
paused=false;
}
oldpad2=pad2;
}
}
void Score()
{
score += (level*10);
sprintf(text, "SCORE:%u", score);
display.setCursor(80, 90);
display.print(text);
}
void newLevel(){
//Undraw paddle
display.drawRect(xPaddle, 63, 11, 1, 0);
//Undraw ball
display.drawPixel(xb, yb, 0);
display.drawPixel(xb+1, yb, 0);
display.drawPixel(xb, yb+1, 0);
display.drawPixel(xb+1, yb+1, 0);
//Alter various variables to reset the game
xPaddle = 54;
yb = 60;
brickCount = 0;
released = false;
//Draws new bricks and resets their values
for (byte row = 0; row < 4; row++) {
for (byte column = 0; column < 13; column++)
{
isHit[row][column] = false;
display.drawRect(10*column, 2+6*row, 8, 4, 1);
}
}
//Draws the initial lives
drawLives();
//Draws the initial score
sprintf(text, "SCORE:%u", score);
display.setCursor(80, 90);
display.print(text);
}
//Used to delay images while reading button input
boolean pollFireButton(int n)
{
for(int i = 0; i < n; i++)
{
delay(15);
pad = !digitalRead(A0);
if(pad == 1 && oldpad == 0)
{
oldpad3 = 1; //Forces pad loop 3 to run once
return true;
}
oldpad = pad;
}
return false;
}
//Function by nootropic design to display highscores
boolean displayHighScores(byte file)
{
byte y = 10;
byte x = 24;
// Each block of EEPROM has 10 high scores, and each high score entry
// is 5 bytes long: 3 bytes for initials and two bytes for score.
int address = file*10*5;
byte hi, lo;
display.clearDisplay();
display.setCursor(32, 0);
display.print("HIGH SCORES");
display.display();
for(int i = 0; i < 10; i++)
{
sprintf(text, "%2d", i+1);
display.setCursor(x,y+(i*8));
display.print( text);
display.display();
hi = EEPROM.read(address + (5*i));
lo = EEPROM.read(address + (5*i) + 1);
if ((hi == 0xFF) && (lo == 0xFF))
{
score = 0;
}
else
{
score = (hi << 8) | lo;
}
initials[0] = (char)EEPROM.read(address + (5*i) + 2);
initials[1] = (char)EEPROM.read(address + (5*i) + 3);
initials[2] = (char)EEPROM.read(address + (5*i) + 4);
if (score > 0)
{
sprintf(text, "%c%c%c %u", initials[0], initials[1], initials[2], score);
display.setCursor(x + 24, y + (i*8));
display.print(text);
display.display();
}
}
if (pollFireButton(300))
{
return true;
}
return false;
display.display();
}
boolean titleScreen()
{
//Clears the screen
display.clearDisplay();
display.setCursor(16,22);
display.setTextSize(2);
display.print("ARAKNOID");
display.setTextSize(1);
display.display();
if (pollFireButton(25))
{
return true;
}
//Flash "Press FIRE" 5 times
for(byte i = 0; i < 5; i++)
{
//Draws "Press FIRE"
//display.bitmap(31, 53, fire); display.display();
display.setCursor(31, 53);
display.print("PRESS FIRE!");
display.display();
if (pollFireButton(50))
{
return true;
}
//Removes "Press FIRE"
display.clearDisplay();
display.setCursor(16,22);
display.setTextSize(2);
display.print("ARAKNOID");
display.setTextSize(1);
display.display();
display.display();
if (pollFireButton(25))
{
return true;
}
}
return false;
}
//Function by nootropic design to add high scores
void enterInitials()
{
char index = 0;
display.clearDisplay();
initials[0] = ' ';
initials[1] = ' ';
initials[2] = ' ';
while (true)
{
display.display();
display.clearDisplay();
display.setCursor(16,0);
display.print("HIGH SCORE");
sprintf(text, "%u", score);
display.setCursor(88, 0);
display.print(text);
display.setCursor(56, 20);
display.print(initials[0]);
display.setCursor(64, 20);
display.print(initials[1]);
display.setCursor(72, 20);
display.print(initials[2]);
for(byte i = 0; i < 3; i++)
{
display.drawLine(56 + (i*8), 27, 56 + (i*8) + 6, 27, 1);
}
display.drawLine(56, 28, 88, 28, 0);
display.drawLine(56 + (index*8), 28, 56 + (index*8) + 6, 28, 1);
delay(150);
if (!digitalRead(5))
{
index--;
if (index < 0)
{
index = 0;
} else
{
tone(A2, 1046, 250);
}
}
if (!digitalRead(9))
{
index++;
if (index > 2)
{
index = 2;
} else {
tone(A2, 1046, 250);
}
}
if (!digitalRead(8))
{
initials[index]++;
tone(A2, 523, 250);
// A-Z 0-9 :-? !-/ ' '
if (initials[index] == '0')
{
initials[index] = ' ';
}
if (initials[index] == '!')
{
initials[index] = 'A';
}
if (initials[index] == '[')
{
initials[index] = '0';
}
if (initials[index] == '@')
{
initials[index] = '!';
}
}
if (!digitalRead(10))
{
initials[index]--;
tone(A2, 523, 250);
if (initials[index] == ' ') {
initials[index] = '?';
}
if (initials[index] == '/') {
initials[index] = 'Z';
}
if (initials[index] == 31) {
initials[index] = '/';
}
if (initials[index] == '@') {
initials[index] = ' ';
}
}
if (!digitalRead(A0))
{
if (index < 2)
{
index++;
tone(A2, 1046, 250);
} else {
tone(A2, 1046, 250);
return;
}
}
}
}
void enterHighScore(byte file)
{
// Each block of EEPROM has 10 high scores, and each high score entry
// is 5 bytes long: 3 bytes for initials and two bytes for score.
int address = file * 10 * 5;
byte hi, lo;
char tmpInitials[3];
unsigned int tmpScore = 0;
// High score processing
for(byte i = 0; i < 10; i++)
{
hi = EEPROM.read(address + (5*i));
lo = EEPROM.read(address + (5*i) + 1);
if ((hi == 0xFF) && (lo == 0xFF))
{
// The values are uninitialized, so treat this entry
// as a score of 0.
tmpScore = 0;
} else
{
tmpScore = (hi << 8) | lo;
}
if (score > tmpScore)
{
enterInitials();
for(byte j=i;j<10;j++)
{
hi = EEPROM.read(address + (5*j));
lo = EEPROM.read(address + (5*j) + 1);
if ((hi == 0xFF) && (lo == 0xFF))
{
tmpScore = 0;
}
else
{
tmpScore = (hi << 8) | lo;
}
tmpInitials[0] = (char)EEPROM.read(address + (5*j) + 2);
tmpInitials[1] = (char)EEPROM.read(address + (5*j) + 3);
tmpInitials[2] = (char)EEPROM.read(address + (5*j) + 4);
// write score and initials to current slot
EEPROM.write(address + (5*j), ((score >> 8) & 0xFF));
EEPROM.write(address + (5*j) + 1, (score & 0xFF));
EEPROM.write(address + (5*j) + 2, initials[0]);
EEPROM.write(address + (5*j) + 3, initials[1]);
EEPROM.write(address + (5*j) + 4, initials[2]);
// tmpScore and tmpInitials now hold what we want to
//write in the next slot.
score = tmpScore;
initials[0] = tmpInitials[0];
initials[1] = tmpInitials[1];
initials[2] = tmpInitials[2];
}
score = 0;
initials[0] = ' ';
initials[1] = ' ';
initials[2] = ' ';
return;
}
}
}
void loop()
{
display.display();
//Title screen loop switches from title screen
//and high scores utill FIRE is pressed
while (!start)
{
start = titleScreen();
if (!start)
{
start = displayHighScores(2);
}
}
//Inital level draw
if (!initialDraw)
{
//Clears the screen
display.display();
display.clearDisplay();
//Selects Font
//Draws the new level
newLevel();
initialDraw=true;
}
if (lives>0)
{
drawPaddle();
//Pause game if FIRE pressed
pad = !digitalRead(A0);
if(pad >1 && oldpad==0 && released)
{
oldpad2=0; //Forces pad loop 2 to run once
pause();
}
oldpad=pad;
drawBall();
if(brickCount==60)
{
level++;
newLevel();
}
}
else
{
drawGameOver();
if (score > 0)
{
enterHighScore(2);
}
display.clearDisplay();
initialDraw=false;
start=false;
lives=3;
score=0;
newLevel();
}
}

681
Arduboy.cpp Normal file
View File

@ -0,0 +1,681 @@
#include "Arduboy.h"
#include "glcdfont.c"
Arduboy::Arduboy() { }
void Arduboy::start()
{
pinMode(DC, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
csport = portOutputRegister(digitalPinToPort(CS));
cspinmask = digitalPinToBitMask(CS);
dcport = portOutputRegister(digitalPinToPort(DC));
dcpinmask = digitalPinToBitMask(DC);
/**
* Setup reset pin direction (used by both SPI and I2C)
*/
pinMode(RST, OUTPUT);
digitalWrite(RST, HIGH);
delay(1); // VDD (3.3V) goes high at start, lets just chill for a ms
digitalWrite(RST, LOW); // bring reset low
delay(10); // wait 10ms
digitalWrite(RST, HIGH); // bring out of reset
*csport |= cspinmask;
*dcport &= ~dcpinmask;
*csport &= ~cspinmask;
SPI.transfer(0xAE); // Display Off
SPI.transfer(0XD5); // Set Display Clock Divisor v
SPI.transfer(0xF0); // 0x80 is default
SPI.transfer(0xA8); // Set Multiplex Ratio v
SPI.transfer(0x3F);
SPI.transfer(0xD3); // Set Display Offset v
SPI.transfer(0x0);
SPI.transfer(0x40); // Set Start Line (0)
SPI.transfer(0x8D); // Charge Pump Setting v
SPI.transfer(0x14); // Enable
SPI.transfer(0x20); // Set Memory Mode v
SPI.transfer(0x00); // Horizontal Addressing
SPI.transfer(0xA1); // Set Segment Re-map (A0) | (b0001)
SPI.transfer(0xC8); // Set COM Output Scan Direction
SPI.transfer(0xDA); // Set COM Pins v
SPI.transfer(0x12);
SPI.transfer(0x81); // Set Contrast v
SPI.transfer(0xCF);
SPI.transfer(0xD9); // Set Precharge
SPI.transfer(0xF1);
SPI.transfer(0xDB); // Set VCom Detect
SPI.transfer(0x40);
SPI.transfer(0xA4); // Entire Display ON
SPI.transfer(0xA6); // Set normal/inverse display
SPI.transfer(0xAF); // Display On
*csport |= cspinmask;
*csport |= cspinmask;
*dcport &= ~dcpinmask;
*csport &= ~cspinmask;
SPI.transfer(0x20); // set display mode
SPI.transfer(0x00); // horizontal addressing mode
SPI.transfer(0x21); // set col address
unsigned char start = 0;
unsigned char end = WIDTH - 1;
SPI.transfer(start & 0x7F);
SPI.transfer(end & 0x7F);
SPI.transfer(0x22); // set page address
start = 0;
end = (HEIGHT/8)-1;
SPI.transfer(start & 0x07);
SPI.transfer(end & 0x07);
*dcport |= dcpinmask;
*csport &= ~cspinmask;
}
void Arduboy::blank()
{
for (int a = 0; a < (HEIGHT*WIDTH)/8; a++) SPI.transfer(0x00);
}
void Arduboy::clearDisplay()
{
for (int a = 0; a < (HEIGHT*WIDTH)/8; a++) sBuffer[a] = 0x00;
}
void Arduboy::drawPixel(int x, int y, uint16_t value)
{
if (x < 0 || x > (WIDTH-1) || y < 0 || y > (HEIGHT-1))
{
return;
}
int row = y / 8;
if (value)
{
sBuffer[(row*WIDTH) + x] |= 1 << (y % 8);
}
else
{
sBuffer[(row*WIDTH) + x] &= ~(1 << (y % 8));
}
}
void Arduboy::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
{
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
drawPixel(x0, y0+r, color);
drawPixel(x0, y0-r, color);
drawPixel(x0+r, y0, color);
drawPixel(x0-r, y0, color);
while (x<y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
drawPixel(x0 + x, y0 + y, color);
drawPixel(x0 - x, y0 + y, color);
drawPixel(x0 + x, y0 - y, color);
drawPixel(x0 - x, y0 - y, color);
drawPixel(x0 + y, y0 + x, color);
drawPixel(x0 - y, y0 + x, color);
drawPixel(x0 + y, y0 - x, color);
drawPixel(x0 - y, y0 - x, color);
}
}
void Arduboy::drawCircleHelper
(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)
{
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
while (x<y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x4)
{
drawPixel(x0 + x, y0 + y, color);
drawPixel(x0 + y, y0 + x, color);
}
if (cornername & 0x2)
{
drawPixel(x0 + x, y0 - y, color);
drawPixel(x0 + y, y0 - x, color);
}
if (cornername & 0x8)
{
drawPixel(x0 - y, y0 + x, color);
drawPixel(x0 - x, y0 + y, color);
}
if (cornername & 0x1)
{
drawPixel(x0 - y, y0 - x, color);
drawPixel(x0 - x, y0 - y, color);
}
}
}
void Arduboy::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
{
drawFastVLine(x0, y0-r, 2*r+1, color);
fillCircleHelper(x0, y0, r, 3, 0, color);
}
void Arduboy::fillCircleHelper
(
int16_t x0,
int16_t y0,
int16_t r,
uint8_t cornername,
int16_t delta,
uint16_t color
)
{
// used to do circles and roundrects!
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
while (x < y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x1)
{
drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
}
if (cornername & 0x2)
{
drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
}
}
}
void Arduboy::drawLine
(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
{
// bresenham's algorithm - thx wikpedia
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t err = dx / 2;
int16_t ystep;
if (y0 < y1)
{
ystep = 1;
}
else
{
ystep = -1;
}
for (; x0 <= x1; x0++)
{
if (steep)
{
drawPixel(y0, x0, color);
}
else
{
drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0)
{
y0 += ystep;
err += dx;
}
}
}
void Arduboy::drawRect
(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
drawFastHLine(x, y, w, color);
drawFastHLine(x, y+h-1, w, color);
drawFastVLine(x, y, h, color);
drawFastVLine(x+w-1, y, h, color);
}
void Arduboy::drawFastVLine
(int16_t x, int16_t y, int16_t h, uint16_t color)
{
int end = y+h;
for (int a = max(0,y); a < min(end,HEIGHT); a++)
{
drawPixel(x,a,color);
}
}
void Arduboy::drawFastHLine
(int16_t x, int16_t y, int16_t w, uint16_t color)
{
int end = x+w;
for (int a = max(0,x); a < min(end,WIDTH); a++)
{
drawPixel(a,y,color);
}
}
void Arduboy::fillRect
(int16_t x, int16_t y, int16_t w, int16_t h, int16_t color)
{
// stupidest version - update in subclasses if desired!
for (int16_t i=x; i<x+w; i++)
{
drawFastVLine(i, y, h, color);
}
}
void Arduboy::fillScreen(uint16_t color)
{
fillRect(0, 0, WIDTH, HEIGHT, color);
}
void Arduboy::drawRoundRect
(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
{
// smarter version
drawFastHLine(x+r, y, w-2*r, color); // Top
drawFastHLine(x+r, y+h-1, w-2*r, color); // Bottom
drawFastVLine(x, y+r, h-2*r, color); // Left
drawFastVLine(x+w-1, y+r, h-2*r, color); // Right
// draw four corners
drawCircleHelper(x+r, y+r, r, 1, color);
drawCircleHelper(x+w-r-1, y+r, r, 2, color);
drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
drawCircleHelper(x+r, y+h-r-1, r, 8, color);
}
void Arduboy::fillRoundRect
(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
{
// smarter version
fillRect(x+r, y, w-2*r, h, color);
// draw four corners
fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
fillCircleHelper(x+r, y+r, r, 2, h-2*r-1, color);
}
void Arduboy::drawTriangle
(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
{
drawLine(x0, y0, x1, y1, color);
drawLine(x1, y1, x2, y2, color);
drawLine(x2, y2, x0, y0, color);
}
void Arduboy::fillTriangle
(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
{
int16_t a, b, y, last;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1)
{
swap(y0, y1); swap(x0, x1);
}
if (y1 > y2)
{
swap(y2, y1); swap(x2, x1);
}
if (y0 > y1)
{
swap(y0, y1); swap(x0, x1);
}
if(y0 == y2)
{ // Handle awkward all-on-same-line case as its own thing
a = b = x0;
if(x1 < a)
{
a = x1;
}
else if(x1 > b)
{
b = x1;
}
if(x2 < a)
{
a = x2;
}
else if(x2 > b)
{
b = x2;
}
drawFastHLine(a, y0, b-a+1, color);
return;
}
int16_t dx01 = x1 - x0,
dy01 = y1 - y0,
dx02 = x2 - x0,
dy02 = y2 - y0,
dx12 = x2 - x1,
dy12 = y2 - y1,
sa = 0,
sb = 0;
// For upper part of triangle, find scanline crossings for segments
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
// is included here (and second loop will be skipped, avoiding a /0
// error there), otherwise scanline y1 is skipped here and handled
// in the second loop...which also avoids a /0 error here if y0=y1
// (flat-topped triangle).
if (y1 == y2)
{
last = y1; // Include y1 scanline
}
else
{
last = y1-1; // Skip it
}
for(y = y0; y <= last; y++)
{
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
if(a > b)
{
swap(a,b);
}
drawFastHLine(a, y, b-a+1, color);
}
// For lower part of triangle, find scanline crossings for segments
// 0-2 and 1-2. This loop is skipped if y1=y2.
sa = dx12 * (y - y1);
sb = dx02 * (y - y0);
for(; y <= y2; y++)
{
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
if(a > b)
{
swap(a,b);
}
drawFastHLine(a, y, b-a+1, color);
}
}
void Arduboy::drawBitmap
(int16_t x,
int16_t y,
const uint8_t *bitmap,
int16_t w,
int16_t h,
uint16_t color
)
{
//bitmap is off screen
if (x+w < 0 || x > WIDTH-1 || y+h < 0 || y > HEIGHT-1) return;
int yOffset = abs(y) % 8;
int sRow = y / 8;
if (y < 0)
{
sRow--;
yOffset = 8 - yOffset;
}
for (int a = 0; a < h/8; a++)
{
int bRow = sRow + a;
if (bRow > (HEIGHT/8)-1) break;
if (bRow > -2) {
for (int iCol = 0; iCol<w; iCol++)
{
if (iCol + x > (WIDTH-1))
{
break;
}
if (iCol + x > 0)
{
if (bRow >= 0)
{
if (color)
{
this->sBuffer[ (bRow*WIDTH) + x + iCol ]
|= pgm_read_byte(bitmap+(a*w)+iCol) << yOffset;
}
else
{
this->sBuffer[ (bRow*WIDTH) + x + iCol ]
&= ~(pgm_read_byte(bitmap+(a*w)+iCol) << yOffset);
}
}
if (yOffset && bRow<(HEIGHT/8)-1 && bRow > -2)
{
if (color)
{
this->sBuffer[ ((bRow+1)*WIDTH) + x + iCol ]
|= pgm_read_byte(bitmap+(a*w)+iCol) >> (8-yOffset);
}
else
{
this->sBuffer[ ((bRow+1)*WIDTH) + x + iCol ]
&= ~(pgm_read_byte(bitmap+(a*w)+iCol) >> (8-yOffset));
}
}
}
}
}
}
}
void Arduboy::drawChar
(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
{
if ((x >= WIDTH) || // Clip right
(y >= HEIGHT) || // Clip bottom
((x + 5 * size - 1) < 0) || // Clip left
((y + 8 * size - 1) < 0) // Clip top
)
{
return;
}
for (int8_t i=0; i<6; i++ )
{
uint8_t line;
if (i == 5)
{
line = 0x0;
}
else
{
line = pgm_read_byte(font+(c*5)+i);
}
for (int8_t j = 0; j<8; j++)
{
if (line & 0x1)
{
if (size == 1) // default size
{
drawPixel(x+i, y+j, color);
}
else // big size
{
fillRect(x+(i*size), y+(j*size), size, size, color);
}
}
else if (bg != color)
{
if (size == 1) // default size
{
drawPixel(x+i, y+j, bg);
}
else
{ // big size
fillRect(x+i*size, y+j*size, size, size, bg);
}
}
line >>= 1;
}
}
}
void Arduboy::setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
void Arduboy::setTextSize(uint8_t s)
{
textsize = (s > 0) ? s : 1;
}
void Arduboy::setTextWrap(boolean w)
{
wrap = w;
}
size_t Arduboy::write(uint8_t c)
{
if (c == '\n')
{
cursor_y += textsize*8;
cursor_x = 0;
}
else if (c == '\r')
{
// skip em
}
else
{
drawChar(cursor_x, cursor_y, c, 1, 0, textsize);
cursor_x += textsize*6;
if (wrap && (cursor_x > (WIDTH - textsize*6)))
{
cursor_y += textsize*8;
cursor_x = 0;
}
}
}
void Arduboy::display()
{
this->drawScreen(sBuffer);
}
void Arduboy::drawScreen(const unsigned char *image)
{
for (int a = 0; a < (HEIGHT*WIDTH)/8; a++)
{
SPI.transfer(pgm_read_byte(image + a));
}
}
void Arduboy::drawScreen(unsigned char image[])
{
for (int a = 0; a < (HEIGHT*WIDTH)/8; a++)
{
SPI.transfer(image[a]);
}
}
uint8_t Arduboy::width() { return WIDTH; }
uint8_t Arduboy::height() { return HEIGHT; }
uint8_t Arduboy::getInput()
{
// b00lurdab
uint8_t value = B00000000;
if (digitalRead(9) == 0) { value = value | B00100000; } // left
if (digitalRead(8) == 0) { value = value | B00010000; } // up
if (digitalRead(5) == 0) { value = value | B00001000; } // right
if (digitalRead(10) == 0) { value = value | B00000100; } // down
if (digitalRead(A0) == 0) { value = value | B00000010; } // a?
if (digitalRead(A1) == 0) { value = value | B00000001; } // b?
return value;
}
void Arduboy::swap(int16_t& a, int16_t& b) {
int temp = a;
a = b;
b = temp;
}

64
Arduboy.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef Arduboy_h
#define Arduboy_h
#include <SPI.h>
#include <Print.h>
#define CS 6
#define DC 4
#define RST 12
#define WIDTH 128
#define HEIGHT 64
class Arduboy : public Print
{
public:
Arduboy();
uint8_t getInput();
void start();
void blank();
void clearDisplay();
void display();
void drawScreen(const unsigned char *image);
void drawScreen(unsigned char image[]);
void drawPixel(int x, int y, uint16_t value);
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color);
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color);
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t color);
void fillScreen(uint16_t color);
void drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color);
void fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color);
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void fillTriangle (int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size);
void setCursor(int16_t x, int16_t y);
void setTextSize(uint8_t s);
void setTextWrap(boolean w);
uint8_t width();
uint8_t height();
virtual size_t write(uint8_t);
void swap(int16_t& a, int16_t& b);
private:
unsigned char sBuffer[(HEIGHT*WIDTH)/8];
uint8_t readCapacitivePin(int pinToMeasure);
uint8_t readCapXtal(int pinToMeasure);
volatile uint8_t *mosiport, *clkport, *csport, *dcport;
uint8_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
// Adafruit stuff
protected:
int16_t cursor_x, cursor_y;
uint8_t textsize;
boolean wrap; // If set, 'wrap' text at right edge of display
};
#endif

1
README.md Normal file
View File

@ -0,0 +1 @@
#ArduBreak

124
breakout_bitmaps.cpp Normal file
View File

@ -0,0 +1,124 @@
#include "breakout_bitmaps.h"
PROGMEM const unsigned char title[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x07,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,
0x00,0x08,0x00,0x60,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x03,0xF4,0x10,0x00,
0x00,0x0B,0xFF,0x10,0x00,0x00,0x00,0x20,0x80,0x00,0x00,0x04,0x09,0xD0,0x00,
0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0xB8,0x00,0x00,0x05,0xE1,0xD0,0x00,
0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0x44,0x00,0x00,0x05,0xE1,0xD0,0x00,
0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0x34,0x00,0x00,0x05,0xE1,0xD0,0x00,
0x00,0x0B,0x83,0xCF,0xFF,0xF9,0xFF,0xAE,0x35,0xFF,0x7C,0xF9,0xE1,0xD0,0x00,
0x00,0x0B,0x83,0xC0,0x00,0x06,0x00,0x4E,0x66,0x00,0x83,0x01,0xE1,0xD0,0x00,
0x00,0x0B,0xFF,0x13,0xE7,0xF0,0xFF,0x0F,0xE0,0x7E,0x38,0x73,0xF9,0xD0,0x00,
0x00,0x0B,0xFF,0x13,0xE7,0xF0,0xFF,0x0F,0xC0,0x7E,0x38,0x73,0xF9,0xD0,0x00,
0x00,0x0B,0x83,0xDC,0x0E,0x0C,0x01,0xCF,0x80,0xE1,0x38,0x71,0xE1,0xD0,0x00,
0x00,0x0B,0x83,0xDC,0xCE,0x0C,0x01,0xCF,0xC0,0xE1,0x38,0x71,0xE1,0xD0,0x00,
0x00,0x0B,0x83,0xDD,0x2F,0xF0,0x7F,0xCE,0xE0,0xE1,0x38,0x71,0xE0,0x10,0x00,
0x00,0x0B,0x83,0xDD,0x2F,0xF0,0xFF,0xCE,0x70,0xE1,0x38,0x71,0xE0,0x10,0x00,
0x00,0x0B,0x83,0xDD,0x2E,0x00,0x81,0xCE,0x38,0xE1,0x38,0x71,0xE1,0xD0,0x00,
0x00,0x0B,0xFF,0x1D,0x27,0xFC,0xFE,0xCE,0x1C,0x7E,0x1F,0xC4,0x79,0xD0,0x00,
0x00,0x0B,0xFF,0x1D,0x17,0xFC,0x7E,0xCE,0x0C,0x7E,0x1F,0xCA,0x79,0xD0,0x00,
0x00,0x08,0x00,0x41,0x10,0x01,0x00,0x00,0xE1,0x00,0xC0,0x11,0x00,0x10,0x00,
0x00,0x07,0xFF,0xBE,0x0F,0xFE,0xFF,0xFF,0x1E,0xFF,0x3F,0xE0,0xFF,0xE0,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x04,0x04,0x10,0x03,0x8A,0x10,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x04,0x00,0x00,0x02,0x08,0x80,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xF3,0x35,0x54,0xD7,0x63,0x1A,0xD7,0x60,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x46,0x54,0x95,0x52,0x2A,0x95,0x50,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x35,0x25,0x97,0x53,0x9A,0x57,0x50,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xF0,0x06,0x04,0x00,0x04,0x00,0x38,0x00,0x0A,0x00,0x00,0x00,
0x00,0x00,0x00,0x88,0x09,0x04,0x00,0x20,0x00,0x44,0x00,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0xF2,0x84,0x27,0x31,0xB5,0x98,0x40,0xC6,0x6A,0x80,0x00,0x00,
0x00,0x00,0x00,0x8A,0x82,0x54,0x8A,0x24,0x54,0x4D,0x28,0x8B,0x00,0x00,0x00,
0x00,0x00,0x00,0x8A,0x89,0x44,0xA8,0xA5,0x54,0x45,0x22,0x8A,0x80,0x00,0x00,
0x00,0x00,0x00,0xF1,0x06,0x37,0x1B,0x14,0xD4,0x3C,0xCC,0x6A,0x80,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
PROGMEM const unsigned char fire[] =
{
57,8,
0xF8,0x00,0x00,0x00,0x3D,0xEF,0x8F,0x80,
0xCC,0x00,0x00,0x00,0x60,0xCC,0xD8,0x00,
0xCC,0x00,0x00,0x00,0x60,0xCC,0xD8,0x00,
0xF9,0x67,0x1E,0x78,0x78,0xCF,0x9F,0x00,
0xC1,0x8C,0xA0,0x80,0x60,0xCC,0xD8,0x00,
0xC1,0x8F,0x1C,0x70,0x60,0xCC,0xD8,0x00,
0xC1,0x8C,0x02,0x08,0x60,0xCC,0xDF,0x80,
0xC1,0x87,0xBC,0xF0,0x61,0xEC,0xCF,0x80,
};
PROGMEM const unsigned char arrow[] =
{
5,5,
0x20,
0x10,
0xF8,
0x10,
0x20,
};

13
breakout_bitmaps.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef ASTEROID_BITMAPS_H
#define ASTEROID_BITMAPS_H
#include <avr/pgmspace.h>
extern const unsigned char fire[];
extern const unsigned char title[];
extern const unsigned char arrow[];
#endif

267
glcdfont.c Normal file
View File

@ -0,0 +1,267 @@
#include <avr/io.h>
#include <avr/pgmspace.h>
#ifndef FONT5X7_H
#define FONT5X7_H
// standard ascii 5x7 font
const static unsigned char font[] PROGMEM =
{
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x21, 0x54, 0x54, 0x78, 0x41,
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0xF0, 0x29, 0x24, 0x29, 0xF0,
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x32, 0x48, 0x48, 0x48, 0x32,
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x39, 0x44, 0x44, 0x44, 0x39,
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0xAA, 0x00, 0x55, 0x00, 0xAA,
0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x06, 0x0F, 0x09, 0x0F, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif