Skip to content

Instantly share code, notes, and snippets.

@spitty
Last active December 18, 2016 21:11
Show Gist options
  • Save spitty/8f62e84276f0f320e53b66a7631dc2a5 to your computer and use it in GitHub Desktop.
Save spitty/8f62e84276f0f320e53b66a7631dc2a5 to your computer and use it in GitHub Desktop.

Revisions

  1. spitty revised this gist Dec 18, 2016. 1 changed file with 0 additions and 327 deletions.
    327 changes: 0 additions & 327 deletions arduino_life_qr_code.cpp
    Original file line number Diff line number Diff line change
    @@ -1,327 +0,0 @@
    /*
    This Arduino sketch shows QR-code with word 'AMAZING' and a heart
    in the right side of GLCD-display.
    Used parts:
    - Library openGLCD https://bitbucket.org/bperrybap/openglcd/wiki/Home
    - example life.pde "John Conway's Game of Life for openGLCD"
    Author: Maxim Logunov [email protected]
    Date: 2016-12-17
    */

    #include <openGLCD.h>

    /********* user configurable defines ************/
    #define CELL_SIZE 4 // the height and width of each cell
    #define DELAY 50 // number of milliseconds delay between the display of each generation

    /******* end of user configurable defines ********/
    #define ROWS (DISPLAY_HEIGHT / CELL_SIZE)
    #define COLUMNS (DISPLAY_WIDTH / 2 / CELL_SIZE)
    // Modification:
    // ^ use only half of display
    //
    #define BYTES_PER_COLUMN ((COLUMNS + 7)/ 8) //this is the number of bytes needed to hold a column

    #define MAX_ITERATIONS 500 // iterations are terminated if this number is exceeded
    #define STABLE_GENERATIONS 4 // must be at least 2, this is the number of back generations checked for stability

    #define MIN_OBJECTS 2 // minmum number of objects to be seeded by the random generater
    #define MAX_OBJECTS 4 // maximum number of objects for random seed generator
    #define MARGIN 4 // minimum distance from screen edge for randomly seeded objects


    #define BITVAL(_pos) (1<< (7-(_pos % 8))) // macro to get a bitfield value

    #define ALIVE true
    #define DEAD false

    /* ======== Life Objects ========
    * these objects can be displayed on the Arduino life screen
    * to add an object, create and initialise a structure following the examples here
    * add a reference to your structure to the object table, name your object by adding to the enum list
    */

    // structure template for life objects
    typedef struct {
    byte height ;
    byte width ;
    byte bitfield[];
    } object_t, *object_ptr_t;

    // definitions and initialisations for all defined objects here
    struct {
    byte height ;
    byte width ;
    byte bitfield[2];
    } static table = {2,4, { 0b10010000 , // * *
    0b11110000 } }; // ****

    struct {
    byte height ;
    byte width ;
    byte bitfield[3];
    } static glider = {3,3, { 0b00100000 , // *
    0b10100000 , // * *
    0b01100000 }}; // **

    #ifdef NOTUSED
    struct {
    byte height ;
    byte width ;
    byte bitfield[3];
    } static glider2 = {3,3, { 0b10100000 , // * *
    0b11000000 , // **
    0b11110000 }}; // ****
    #endif
    struct {
    byte height ;
    byte width ;
    byte bitfield[4];
    } static loaf = {4,4, { 0b01100000 , // **
    0b10010000 , // * *
    0b01010000 , // * *
    0b00100000 }}; // *
    struct {
    byte height ;
    byte width ;
    byte bitfield[3];
    } static ship = {3,3, { 0b11000000 , // **
    0b10100000 , // * *
    0b01100000 }}; // **

    struct {
    byte height ;
    byte width ;
    byte bitfield[4];
    } static behive = {4,3, { 0b01000000 , // *
    0b10100000 , // * *
    0b10100000 , // * *
    0b01000000}}; // *

    struct {
    byte height ;
    byte width ;
    byte bitfield[1];
    } static blinker = {1,3, { 0b11100000 }}; // ***


    struct {
    byte height ;
    byte width ;
    byte bitfield[2];
    } static block = {2,2, { 0b11000000 , // **
    0b11000000}}; // **

    // place all the objects in the object table
    object_ptr_t objectTable[] = {
    (object_ptr_t)&table,
    (object_ptr_t)&glider,
    (object_ptr_t)&loaf,
    (object_ptr_t)&ship,
    (object_ptr_t)&behive,
    (object_ptr_t)&blinker,
    (object_ptr_t)&block
    };

    #define OBJECT_COUNT (sizeof( objectTable/ sizeof(object_ptr_t)))

    // enumerate all the objects, add any new objects to the end of this enum (note case difference )
    // the life program references all objects using the names in this list
    enum {Table,Glider,Loaf,Ship,Behive,Blinker,Block};

    byte generations[STABLE_GENERATIONS][ROWS][BYTES_PER_COLUMN]; // array used to calculate, draw and check if iterations are changing

    // This part descripbes QR-code
    #define RECTSIZE 21
    #define PXSIZE 2

    const int bits[RECTSIZE][RECTSIZE] = {{0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0},
    {0,1,1,1,1,1,0,1,1,0,1,1,0,1,0,1,1,1,1,1,0},
    {0,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,0,0,0,1,0},
    {0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0},
    {0,1,0,0,0,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,0},
    {0,1,1,1,1,1,0,1,1,0,1,0,0,1,0,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,1,0,1,0,0,1,1,0,0,1,0,0,1,1,1,1,0,1,1,0},
    {1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,1,0,1},
    {0,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1,1},
    {1,0,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,1,1},
    {0,0,0,1,0,0,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1},
    {1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,1,0,0,1,1},
    {0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1},
    {0,1,1,1,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0},
    {0,1,0,0,0,1,0,1,0,1,1,1,1,0,1,0,1,0,0,1,0},
    {0,1,0,0,0,1,0,1,1,1,0,0,1,1,0,0,1,0,1,0,1},
    {0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0},
    {0,1,1,1,1,1,0,1,1,0,0,1,1,0,0,0,1,1,1,0,0},
    {0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,0,0,0,1,0}};

    void setup(){
    GLCD.Init(); // initialise the library, non inverted writes pixels onto a clear screen
    GLCD.SelectFont(System5x7);
    GLCD.DrawString("Life", gTextfmt_center, gTextfmt_center);
    delay(1000);
    // ^ delay decreased
    seed(3);
    }

    void loop (void){
    GLCD.ClearScreen();
    // Draw QR-code
    for (int i = 0; i < RECTSIZE; i++) {
    for (int j = 0; j < RECTSIZE; j++) {
    uint8_t color = (bits[i][j] == 0 ? PIXEL_ON : PIXEL_OFF);
    GLCD.FillRect(75 + j * PXSIZE, 11 + i * PXSIZE, 2, 2, color);
    }
    }

    unsigned int i = generate();
    GLCD.CursorTo(0,0);
    GLCD.print(i);
    GLCD.print(" iterations");
    delay(2000);
    seed(1); // use random seed
    }

    unsigned int generate(){
    unsigned int iteration = 0;
    byte thisGeneration,nextGeneration;
    thisGeneration = nextGeneration = 0;
    //display the initial array
    for(int row = 0; row < ROWS; row++)
    {
    for(int column = 0; column < COLUMNS; column++)
    {
    if(isAlive(thisGeneration,row,column))
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, BLACK) ;
    else
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, WHITE) ;
    }
    }

    delay(1500); // show the seeded condition a little longer
    do{
    thisGeneration = iteration % STABLE_GENERATIONS;
    nextGeneration = (thisGeneration+1) % STABLE_GENERATIONS;
    delay(DELAY);
    memset(generations[nextGeneration],0,sizeof(generations[0])); // clear the array for the next generation
    //see who lives and who dies
    for(int row = 0; row < ROWS; row++){
    for(int column = 0; column < COLUMNS; column++){
    boolean cell = isAlive(thisGeneration,row,column);
    byte n = getNeighborCount(thisGeneration,row,column);
    if(cell == DEAD){
    if(n==3) {
    setLife(nextGeneration,row,column,ALIVE); // birth
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, BLACK) ;
    }
    }
    else{
    if(n==2 || n==3) {
    setLife(nextGeneration,row,column,ALIVE); //survival
    // No need to draw cell as it is already there.
    } else {
    setLife(nextGeneration,row,column,DEAD); //death
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, WHITE) ;
    }
    }
    }
    }
    }
    while(isStable(thisGeneration) == false && ++iteration < MAX_ITERATIONS ) ;
    return iteration;
    }

    void seed(int seedValue){
    // a hard coded seed is used if seedvalue is zero, otherwise a random seed is used
    memset(generations,0,sizeof(generations)); // clear all generation arrays
    if(seedValue == 0){
    // load default objects, arguments are offsets from the center of the screen
    loadObject(Table,2,-9); // put a table object 2 down from the center and 9 columns left or center
    loadObject(Glider, -5,-9); // put a glider 5 rows above the center and 9 columns left of center
    }
    else{
    // load some random objects and place at random positions
    byte nbrObjects = random(MIN_OBJECTS,MAX_OBJECTS+1); // make a random number of objects
    for(byte i=0; i < nbrObjects;i++){
    byte obj = random(7); // OBJECT_COUNT);
    int column = random(MARGIN - (COLUMNS/2), (COLUMNS/2) - MARGIN);
    int row = random(MARGIN - (ROWS/2) , (ROWS/2) - MARGIN);
    loadObject(obj,row,column);
    }
    }
    }

    void loadObject(void * object, char y, char x){
    // object_ptr is the object to be loaded
    // y and x are offsets from the center of the display
    object_ptr_t object_ptr = (object_ptr_t)object;
    byte row = (ROWS/2) + y;
    byte column = (COLUMNS/2) + x;
    for(byte ys = 0; ys < object_ptr->height; ys++ ){
    for(byte xs=0; xs < object_ptr->width; xs++ ){
    if( (row +ys < ROWS) && (column +xs < COLUMNS)){
    // this code only works on widths up to 8 bits
    boolean value = object_ptr->bitfield[ys] & BITVAL(xs) ;
    setLife(0, row+ys, column+xs, value) ; // objects always loaded into the first array
    }
    }
    }
    }

    void loadObject(int object, char y, char x){
    loadObject(objectTable[object], y, x );
    }

    boolean isStable(byte thisGeneration){
    // returns true if any two captured generations are the same
    for(byte i=0; i < STABLE_GENERATIONS; i++)
    if(i != thisGeneration)
    if(memcmp(generations[thisGeneration], generations[i], sizeof(generations[0])) == 0)
    return true;
    return false;
    }

    boolean isAlive( byte generation, byte row, byte column){
    byte b = generations[generation][row][column /8];
    return b & BITVAL(column) ;
    }

    void setLife( byte generation, byte row, byte column, boolean state){
    byte elem = column /8;
    byte b = generations[generation][row][elem];
    if(state != DEAD){
    b = b | BITVAL(column);
    }
    else{
    b &= ~(BITVAL(column)) ;
    }
    generations[generation][row][elem] = b;
    }

    byte getNeighborCount( byte generation, byte row, byte column){
    byte count = 0;
    for(byte d = 0;d < 8; d++)
    if(isNeighborAlive(generation,row,column,d) != 0)
    count++;
    return count;
    }

    boolean isNeighborAlive( byte generation , byte row, byte column, byte dir){
    byte nrow=row;
    byte ncol=column;
    if(dir == 7 || dir == 0 || dir == 1)
    nrow--;
    if(dir == 3 || dir == 4 || dir == 5)
    nrow++;
    if(dir == 5 || dir == 6 || dir == 7)
    ncol--;
    if(dir == 1 || dir == 2 || dir == 3)
    ncol++;
    if(ncol==255) ncol = COLUMNS - 1;
    if(ncol==COLUMNS) ncol = 0;
    if(nrow==255) nrow = ROWS - 1;
    if(nrow==ROWS) nrow = 0;
    return isAlive(generation,nrow,ncol);
    }
  2. spitty revised this gist Dec 18, 2016. 1 changed file with 327 additions and 0 deletions.
    327 changes: 327 additions & 0 deletions arduino_life_qr_code.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,327 @@
    /*
    This Arduino sketch shows QR-code with word 'AMAZING' and a heart
    in the right side of GLCD-display.
    Used parts:
    - Library openGLCD https://bitbucket.org/bperrybap/openglcd/wiki/Home
    - example life.pde "John Conway's Game of Life for openGLCD"
    Author: Maxim Logunov [email protected]
    Date: 2016-12-17
    */

    #include <openGLCD.h>

    /********* user configurable defines ************/
    #define CELL_SIZE 4 // the height and width of each cell
    #define DELAY 50 // number of milliseconds delay between the display of each generation

    /******* end of user configurable defines ********/
    #define ROWS (DISPLAY_HEIGHT / CELL_SIZE)
    #define COLUMNS (DISPLAY_WIDTH / 2 / CELL_SIZE)
    // Modification:
    // ^ use only half of display
    //
    #define BYTES_PER_COLUMN ((COLUMNS + 7)/ 8) //this is the number of bytes needed to hold a column

    #define MAX_ITERATIONS 500 // iterations are terminated if this number is exceeded
    #define STABLE_GENERATIONS 4 // must be at least 2, this is the number of back generations checked for stability

    #define MIN_OBJECTS 2 // minmum number of objects to be seeded by the random generater
    #define MAX_OBJECTS 4 // maximum number of objects for random seed generator
    #define MARGIN 4 // minimum distance from screen edge for randomly seeded objects


    #define BITVAL(_pos) (1<< (7-(_pos % 8))) // macro to get a bitfield value

    #define ALIVE true
    #define DEAD false

    /* ======== Life Objects ========
    * these objects can be displayed on the Arduino life screen
    * to add an object, create and initialise a structure following the examples here
    * add a reference to your structure to the object table, name your object by adding to the enum list
    */

    // structure template for life objects
    typedef struct {
    byte height ;
    byte width ;
    byte bitfield[];
    } object_t, *object_ptr_t;

    // definitions and initialisations for all defined objects here
    struct {
    byte height ;
    byte width ;
    byte bitfield[2];
    } static table = {2,4, { 0b10010000 , // * *
    0b11110000 } }; // ****

    struct {
    byte height ;
    byte width ;
    byte bitfield[3];
    } static glider = {3,3, { 0b00100000 , // *
    0b10100000 , // * *
    0b01100000 }}; // **

    #ifdef NOTUSED
    struct {
    byte height ;
    byte width ;
    byte bitfield[3];
    } static glider2 = {3,3, { 0b10100000 , // * *
    0b11000000 , // **
    0b11110000 }}; // ****
    #endif
    struct {
    byte height ;
    byte width ;
    byte bitfield[4];
    } static loaf = {4,4, { 0b01100000 , // **
    0b10010000 , // * *
    0b01010000 , // * *
    0b00100000 }}; // *
    struct {
    byte height ;
    byte width ;
    byte bitfield[3];
    } static ship = {3,3, { 0b11000000 , // **
    0b10100000 , // * *
    0b01100000 }}; // **

    struct {
    byte height ;
    byte width ;
    byte bitfield[4];
    } static behive = {4,3, { 0b01000000 , // *
    0b10100000 , // * *
    0b10100000 , // * *
    0b01000000}}; // *

    struct {
    byte height ;
    byte width ;
    byte bitfield[1];
    } static blinker = {1,3, { 0b11100000 }}; // ***


    struct {
    byte height ;
    byte width ;
    byte bitfield[2];
    } static block = {2,2, { 0b11000000 , // **
    0b11000000}}; // **

    // place all the objects in the object table
    object_ptr_t objectTable[] = {
    (object_ptr_t)&table,
    (object_ptr_t)&glider,
    (object_ptr_t)&loaf,
    (object_ptr_t)&ship,
    (object_ptr_t)&behive,
    (object_ptr_t)&blinker,
    (object_ptr_t)&block
    };

    #define OBJECT_COUNT (sizeof( objectTable/ sizeof(object_ptr_t)))

    // enumerate all the objects, add any new objects to the end of this enum (note case difference )
    // the life program references all objects using the names in this list
    enum {Table,Glider,Loaf,Ship,Behive,Blinker,Block};

    byte generations[STABLE_GENERATIONS][ROWS][BYTES_PER_COLUMN]; // array used to calculate, draw and check if iterations are changing

    // This part descripbes QR-code
    #define RECTSIZE 21
    #define PXSIZE 2

    const int bits[RECTSIZE][RECTSIZE] = {{0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0},
    {0,1,1,1,1,1,0,1,1,0,1,1,0,1,0,1,1,1,1,1,0},
    {0,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,0,0,0,1,0},
    {0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0},
    {0,1,0,0,0,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,0},
    {0,1,1,1,1,1,0,1,1,0,1,0,0,1,0,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,1,0,1,0,0,1,1,0,0,1,0,0,1,1,1,1,0,1,1,0},
    {1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,1,0,1},
    {0,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1,1},
    {1,0,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,1,1},
    {0,0,0,1,0,0,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1},
    {1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,1,0,0,1,1},
    {0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1},
    {0,1,1,1,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0},
    {0,1,0,0,0,1,0,1,0,1,1,1,1,0,1,0,1,0,0,1,0},
    {0,1,0,0,0,1,0,1,1,1,0,0,1,1,0,0,1,0,1,0,1},
    {0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0},
    {0,1,1,1,1,1,0,1,1,0,0,1,1,0,0,0,1,1,1,0,0},
    {0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,0,0,0,1,0}};

    void setup(){
    GLCD.Init(); // initialise the library, non inverted writes pixels onto a clear screen
    GLCD.SelectFont(System5x7);
    GLCD.DrawString("Life", gTextfmt_center, gTextfmt_center);
    delay(1000);
    // ^ delay decreased
    seed(3);
    }

    void loop (void){
    GLCD.ClearScreen();
    // Draw QR-code
    for (int i = 0; i < RECTSIZE; i++) {
    for (int j = 0; j < RECTSIZE; j++) {
    uint8_t color = (bits[i][j] == 0 ? PIXEL_ON : PIXEL_OFF);
    GLCD.FillRect(75 + j * PXSIZE, 11 + i * PXSIZE, 2, 2, color);
    }
    }

    unsigned int i = generate();
    GLCD.CursorTo(0,0);
    GLCD.print(i);
    GLCD.print(" iterations");
    delay(2000);
    seed(1); // use random seed
    }

    unsigned int generate(){
    unsigned int iteration = 0;
    byte thisGeneration,nextGeneration;
    thisGeneration = nextGeneration = 0;
    //display the initial array
    for(int row = 0; row < ROWS; row++)
    {
    for(int column = 0; column < COLUMNS; column++)
    {
    if(isAlive(thisGeneration,row,column))
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, BLACK) ;
    else
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, WHITE) ;
    }
    }

    delay(1500); // show the seeded condition a little longer
    do{
    thisGeneration = iteration % STABLE_GENERATIONS;
    nextGeneration = (thisGeneration+1) % STABLE_GENERATIONS;
    delay(DELAY);
    memset(generations[nextGeneration],0,sizeof(generations[0])); // clear the array for the next generation
    //see who lives and who dies
    for(int row = 0; row < ROWS; row++){
    for(int column = 0; column < COLUMNS; column++){
    boolean cell = isAlive(thisGeneration,row,column);
    byte n = getNeighborCount(thisGeneration,row,column);
    if(cell == DEAD){
    if(n==3) {
    setLife(nextGeneration,row,column,ALIVE); // birth
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, BLACK) ;
    }
    }
    else{
    if(n==2 || n==3) {
    setLife(nextGeneration,row,column,ALIVE); //survival
    // No need to draw cell as it is already there.
    } else {
    setLife(nextGeneration,row,column,DEAD); //death
    GLCD.DrawRoundRect(column * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE, CELL_SIZE/2, WHITE) ;
    }
    }
    }
    }
    }
    while(isStable(thisGeneration) == false && ++iteration < MAX_ITERATIONS ) ;
    return iteration;
    }

    void seed(int seedValue){
    // a hard coded seed is used if seedvalue is zero, otherwise a random seed is used
    memset(generations,0,sizeof(generations)); // clear all generation arrays
    if(seedValue == 0){
    // load default objects, arguments are offsets from the center of the screen
    loadObject(Table,2,-9); // put a table object 2 down from the center and 9 columns left or center
    loadObject(Glider, -5,-9); // put a glider 5 rows above the center and 9 columns left of center
    }
    else{
    // load some random objects and place at random positions
    byte nbrObjects = random(MIN_OBJECTS,MAX_OBJECTS+1); // make a random number of objects
    for(byte i=0; i < nbrObjects;i++){
    byte obj = random(7); // OBJECT_COUNT);
    int column = random(MARGIN - (COLUMNS/2), (COLUMNS/2) - MARGIN);
    int row = random(MARGIN - (ROWS/2) , (ROWS/2) - MARGIN);
    loadObject(obj,row,column);
    }
    }
    }

    void loadObject(void * object, char y, char x){
    // object_ptr is the object to be loaded
    // y and x are offsets from the center of the display
    object_ptr_t object_ptr = (object_ptr_t)object;
    byte row = (ROWS/2) + y;
    byte column = (COLUMNS/2) + x;
    for(byte ys = 0; ys < object_ptr->height; ys++ ){
    for(byte xs=0; xs < object_ptr->width; xs++ ){
    if( (row +ys < ROWS) && (column +xs < COLUMNS)){
    // this code only works on widths up to 8 bits
    boolean value = object_ptr->bitfield[ys] & BITVAL(xs) ;
    setLife(0, row+ys, column+xs, value) ; // objects always loaded into the first array
    }
    }
    }
    }

    void loadObject(int object, char y, char x){
    loadObject(objectTable[object], y, x );
    }

    boolean isStable(byte thisGeneration){
    // returns true if any two captured generations are the same
    for(byte i=0; i < STABLE_GENERATIONS; i++)
    if(i != thisGeneration)
    if(memcmp(generations[thisGeneration], generations[i], sizeof(generations[0])) == 0)
    return true;
    return false;
    }

    boolean isAlive( byte generation, byte row, byte column){
    byte b = generations[generation][row][column /8];
    return b & BITVAL(column) ;
    }

    void setLife( byte generation, byte row, byte column, boolean state){
    byte elem = column /8;
    byte b = generations[generation][row][elem];
    if(state != DEAD){
    b = b | BITVAL(column);
    }
    else{
    b &= ~(BITVAL(column)) ;
    }
    generations[generation][row][elem] = b;
    }

    byte getNeighborCount( byte generation, byte row, byte column){
    byte count = 0;
    for(byte d = 0;d < 8; d++)
    if(isNeighborAlive(generation,row,column,d) != 0)
    count++;
    return count;
    }

    boolean isNeighborAlive( byte generation , byte row, byte column, byte dir){
    byte nrow=row;
    byte ncol=column;
    if(dir == 7 || dir == 0 || dir == 1)
    nrow--;
    if(dir == 3 || dir == 4 || dir == 5)
    nrow++;
    if(dir == 5 || dir == 6 || dir == 7)
    ncol--;
    if(dir == 1 || dir == 2 || dir == 3)
    ncol++;
    if(ncol==255) ncol = COLUMNS - 1;
    if(ncol==COLUMNS) ncol = 0;
    if(nrow==255) nrow = ROWS - 1;
    if(nrow==ROWS) nrow = 0;
    return isAlive(generation,nrow,ncol);
    }
  3. spitty created this gist Dec 18, 2016.
    53 changes: 53 additions & 0 deletions arduino_qr_code.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    /*
    This Arduino sketch shows QR-code with word 'AMAZING' and a heart
    in the right side of GLCD-display.
    Library openGLCD https://bitbucket.org/bperrybap/openglcd/wiki/Home
    is used.
    Author: Maxim Logunov [email protected]
    Date: 2016-12-17
    */

    #include <openGLCD.h>

    #define RECTSIZE 21
    #define PXSIZE 2

    const int bits[RECTSIZE][RECTSIZE] = {{0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0},
    {0,1,1,1,1,1,0,1,1,0,1,1,0,1,0,1,1,1,1,1,0},
    {0,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,0,0,0,1,0},
    {0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0},
    {0,1,0,0,0,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,0},
    {0,1,1,1,1,1,0,1,1,0,1,0,0,1,0,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0},
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    {1,1,0,1,0,0,1,1,0,0,1,0,0,1,1,1,1,0,1,1,0},
    {1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,1,0,1},
    {0,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1,1},
    {1,0,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,1,1},
    {0,0,0,1,0,0,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1},
    {1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,1,0,0,1,1},
    {0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1},
    {0,1,1,1,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0},
    {0,1,0,0,0,1,0,1,0,1,1,1,1,0,1,0,1,0,0,1,0},
    {0,1,0,0,0,1,0,1,1,1,0,0,1,1,0,0,1,0,1,0,1},
    {0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0},
    {0,1,1,1,1,1,0,1,1,0,0,1,1,0,0,0,1,1,1,0,0},
    {0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,0,0,0,1,0}};

    void setup()
    {
    GLCD.Init();
    GLCD.ClearScreen();
    }
    void loop()
    {
    for (int i = 0; i < RECTSIZE; i++) {
    for (int j = 0; j < RECTSIZE; j++) {
    uint8_t color = (bits[i][j] == 0 ? PIXEL_ON : PIXEL_OFF);
    // padding-top : 11 = (64 - RECTSIZE * PXSIZE) / 2
    // padding-left : 75 = WIDTH / 2 + (64 - RECTSIZE * PXSIZE) / 2
    GLCD.FillRect(75 + j * PXSIZE, 11 + i * PXSIZE, 2, 2, color);
    }
    }
    delay(1000);
    }