#include <htc.h> //PIC hardware mapping

#include <delay.c>

#include <I2CMaster.h>

#include <stdlib.h>

//config bits

__CONFIG(HS & PWRTDIS & WDTDIS & LVPDIS);

/////////// Constants ///////////

#define LEDPLADE8PIN 1 // Defines how many light plates with 8pins that's attached (Not ever actually used, was supposed to be able to handle more than one)

/////////// Bit manipulation functions ///////////

void clear_bit(unsigned char *x, char bitNum){

*x &= ~(1 << bitNum);

}

void set_bit(unsigned char *x, char bitNum) {

*x |= (1 << bitNum);

}

unsigned char get_bit(unsigned char x, char bitNum) {

return x & (1 << bitNum);

}

/////////////// Function prototypes for patterns //////////////////

void glider(void);

void lwss(void);

void toad(void);

void kasse(void);

void blinker(void);

void randompat(void);

/////////// Variables ///////////

////////// GAME OF LIFE ///////////

char LifeGameBuf[2][7];

char LiveCount;

char FirstEvol;

char Pattern;

char NewPattern;

///////////////////////////////////

char i; // Indexes

char j;

char I2C_Address; // Defines the i2c address we want to write to

char I2C_i; // Defines what type of byte we want to send (I don't remember what this is, and it is apparently unused)

/////////// Main program ///////////

void main(void){ // Start

srand(70);

/////////// Opsætning ///////////

/////////// Opsætning af SSP modul ///////////

TRISC = 0b00011000; // Sets port C pin 3 and 4 to be inputs

SSPADD = 39; // Defines the baudrate of the i2c communications

SSPCON = 0b00101000; // Configuration and start of SSP module

SSPCON2 = 0b00000000;

SSPSTAT = 0b11000000;

SSPIE = 1; // Enable interrupt on i2c communication start

SSPIF = 0;

/////////// Setup of interrupts ///////////

PEIE = 1;

GIE = 1; // Global interrupt enable

/////////// GAME OF LIFE ///////////

LiveCount = 0;

Pattern = 0;

NewPattern = 0;

glider();

/////////// Runs in a loop from here (Obviously not) ///////////

/////////// Pattern change ///////////

TRISD = 0b00000010; // Set pins on port D as input and output

while(!0){

PORTD = 0b00001000; // Drive current to RD3 pin

if(RD3 == 0){ // I HAVE NO IDEA WHY THIS WORKS (Basically, the code here sets a pin, then checks if it is set. It worked, I still have no idea why)

Pattern = Pattern + 1;

NewPattern = 1;

DelayMs(255);

}

if(NewPattern){

if(Pattern > 5) Pattern = 0;

if(Pattern == 0) glider();

else if(Pattern == 1) lwss();

else if(Pattern == 2) toad();

else if(Pattern == 3) kasse();

else if(Pattern == 4) blinker();

else if(Pattern == 5) randompat();

NewPattern = 0;

}

//////////////// Blink light to indicate when the next generations of game of life is calculated /////////////////

PORTD = 0;

DelayMs(50);

PORTD = 1;

//////////////// Game of Life /////////////////

if(!FirstEvol){

for(i=0; i<7; i++){

for(j=0; j<8; j++){

if(i == 0){

if(j == 0){

if(get_bit(LifeGameBuf[0][i],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],7)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],7)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],7)) LiveCount = LiveCount + 1;

}

else if (j == 7){

if(get_bit(LifeGameBuf[0][i],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j-1)) LiveCount = LiveCount + 1;

}

else{

if(get_bit(LifeGameBuf[0][i],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][6],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j-1)) LiveCount = LiveCount + 1;

}

}

else if(i == 6){

if(j == 0){

if(get_bit(LifeGameBuf[0][i],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],7)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],7)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],7)) LiveCount = LiveCount + 1;

}

else if (j == 7){

if(get_bit(LifeGameBuf[0][i],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j-1)) LiveCount = LiveCount + 1;

}

else{

if(get_bit(LifeGameBuf[0][i],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][0],j-1)) LiveCount = LiveCount + 1;

}

}

else{

if(j == 0){

if(get_bit(LifeGameBuf[0][i],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],7)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],7)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],7)) LiveCount = LiveCount + 1;

}

else if (j == 7){

if(get_bit(LifeGameBuf[0][i],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],0)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j-1)) LiveCount = LiveCount + 1;

}

else{

if(get_bit(LifeGameBuf[0][i],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i-1],j-1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j+1)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j)) LiveCount = LiveCount + 1;

if(get_bit(LifeGameBuf[0][i+1],j-1)) LiveCount = LiveCount + 1;

}

}

if(LiveCount < 2){clear_bit(&LifeGameBuf[1][i],j);}

else if(LiveCount == 2 && get_bit(LifeGameBuf[1][i],j) == 1){set_bit(&LifeGameBuf[1][i],j);}

else if(LiveCount == 2 && get_bit(LifeGameBuf[1][i],j) == 0){clear_bit(&LifeGameBuf[1][i],j);}

else if(LiveCount == 3){set_bit(&LifeGameBuf[1][i],j);}

else if(LiveCount > 3){clear_bit(&LifeGameBuf[1][i],j);}

LiveCount = 0;

}

}

for(i=0; i<7; i++){

LifeGameBuf[0][i] = LifeGameBuf[1][i];

}

}

FirstEvol = 0; // No longer first generation

////////////// SEND TO DISPLAY /////////////////

i2c_Start();

i2c_Address(15,0);

i2c_Write(LifeGameBuf[0][0]);

i2c_Write(LifeGameBuf[0][1]);

i2c_Write(LifeGameBuf[0][2]);

i2c_Write(LifeGameBuf[0][3]);

i2c_Write(LifeGameBuf[0][4]);

i2c_Write(LifeGameBuf[0][5]);

i2c_Write(LifeGameBuf[0][6]);

i2c_Stop();

}

} // End

static void interrupt isr(void)

{

if(SSPIF){ // Was it a i2c interrupt?

SSPIF = 0; // Clear SSP interrupt flag

}

}

/////////// Game of Life pattern funftions ///////////

void glider() {

LifeGameBuf[0][0] = 0b00100000;

LifeGameBuf[0][1] = 0b10100000;

LifeGameBuf[0][2] = 0b01100000;

LifeGameBuf[0][3] = 0b00000000;

LifeGameBuf[0][4] = 0b00000000;

LifeGameBuf[0][5] = 0b00000000;

LifeGameBuf[0][6] = 0b00000000;

LifeGameBuf[1][0] = LifeGameBuf[0][0];

LifeGameBuf[1][1] = LifeGameBuf[0][1];

LifeGameBuf[1][2] = LifeGameBuf[0][2];

LifeGameBuf[1][3] = LifeGameBuf[0][3];

LifeGameBuf[1][4] = LifeGameBuf[0][4];

LifeGameBuf[1][5] = LifeGameBuf[0][5];

LifeGameBuf[1][6] = LifeGameBuf[0][6];

FirstEvol = 1;

}

void lwss() {

LifeGameBuf[0][0] = 0b00000000;

LifeGameBuf[0][1] = 0b00000000;

LifeGameBuf[0][2] = 0b00110000;

LifeGameBuf[0][3] = 0b11011000;

LifeGameBuf[0][4] = 0b11110000;

LifeGameBuf[0][5] = 0b01100000;

LifeGameBuf[0][6] = 0b00000000;

LifeGameBuf[1][0] = LifeGameBuf[0][0];

LifeGameBuf[1][1] = LifeGameBuf[0][1];

LifeGameBuf[1][2] = LifeGameBuf[0][2];

LifeGameBuf[1][3] = LifeGameBuf[0][3];

LifeGameBuf[1][4] = LifeGameBuf[0][4];

LifeGameBuf[1][5] = LifeGameBuf[0][5];

LifeGameBuf[1][6] = LifeGameBuf[0][6];

FirstEvol = 1;

}

void toad() {

LifeGameBuf[0][0] = 0b00000000;

LifeGameBuf[0][1] = 0b00000000;

LifeGameBuf[0][2] = 0b00000000;

LifeGameBuf[0][3] = 0b00111000;

LifeGameBuf[0][4] = 0b00011100;

LifeGameBuf[0][5] = 0b00000000;

LifeGameBuf[0][6] = 0b00000000;

LifeGameBuf[1][0] = LifeGameBuf[0][0];

LifeGameBuf[1][1] = LifeGameBuf[0][1];

LifeGameBuf[1][2] = LifeGameBuf[0][2];

LifeGameBuf[1][3] = LifeGameBuf[0][3];

LifeGameBuf[1][4] = LifeGameBuf[0][4];

LifeGameBuf[1][5] = LifeGameBuf[0][5];

LifeGameBuf[1][6] = LifeGameBuf[0][6];

FirstEvol = 1;

}

void kasse() {

LifeGameBuf[0][0] = 0b00000000;

LifeGameBuf[0][1] = 0b00110000;

LifeGameBuf[0][2] = 0b01001000;

LifeGameBuf[0][3] = 0b01001000;

LifeGameBuf[0][4] = 0b00110000;

LifeGameBuf[0][5] = 0b00000000;

LifeGameBuf[0][6] = 0b00000000;

LifeGameBuf[1][0] = LifeGameBuf[0][0];

LifeGameBuf[1][1] = LifeGameBuf[0][1];

LifeGameBuf[1][2] = LifeGameBuf[0][2];

LifeGameBuf[1][3] = LifeGameBuf[0][3];

LifeGameBuf[1][4] = LifeGameBuf[0][4];

LifeGameBuf[1][5] = LifeGameBuf[0][5];

LifeGameBuf[1][6] = LifeGameBuf[0][6];

FirstEvol = 1;

}

void blinker() {

LifeGameBuf[0][0] = 0b01000000;

LifeGameBuf[0][1] = 0b01000000;

LifeGameBuf[0][2] = 0b01000000;

LifeGameBuf[0][3] = 0b00001000;

LifeGameBuf[0][4] = 0b00001000;

LifeGameBuf[0][5] = 0b00001000;

LifeGameBuf[0][6] = 0b00000000;

LifeGameBuf[1][0] = LifeGameBuf[0][0];

LifeGameBuf[1][1] = LifeGameBuf[0][1];

LifeGameBuf[1][2] = LifeGameBuf[0][2];

LifeGameBuf[1][3] = LifeGameBuf[0][3];

LifeGameBuf[1][4] = LifeGameBuf[0][4];

LifeGameBuf[1][5] = LifeGameBuf[0][5];

LifeGameBuf[1][6] = LifeGameBuf[0][6];

FirstEvol = 1;

}

void randompat() {

LifeGameBuf[0][0] = (char)rand();

LifeGameBuf[0][1] = (char)rand();

LifeGameBuf[0][2] = (char)rand();

LifeGameBuf[0][3] = (char)rand();

LifeGameBuf[0][4] = (char)rand();

LifeGameBuf[0][5] = (char)rand();

LifeGameBuf[0][6] = (char)rand();

LifeGameBuf[1][0] = LifeGameBuf[0][0];

LifeGameBuf[1][1] = LifeGameBuf[0][1];

LifeGameBuf[1][2] = LifeGameBuf[0][2];

LifeGameBuf[1][3] = LifeGameBuf[0][3];

LifeGameBuf[1][4] = LifeGameBuf[0][4];

LifeGameBuf[1][5] = LifeGameBuf[0][5];

LifeGameBuf[1][6] = LifeGameBuf[0][6];

FirstEvol = 1;

}