diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d489cf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +obj/ +*.hex +*.bin +*.elf +*.lss +*.o diff --git a/Makefile b/Makefile index de1b976..81957ed 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ TARGET = main OBJDIR = obj # List C source files here (C dependencies are automatically generated) -SRC = $(TARGET).c tetris.c display.c +SRC = $(TARGET).c tetris.c display.c conway.c # List C++ source files here (C dependencies are automatically generated) CPPSRC = @@ -248,7 +248,7 @@ AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex # Uncomment the following if you do /not/ wish a verification to be # performed after programming the device. -#AVRDUDE_NO_VERIFY = -V +AVRDUDE_NO_VERIFY = -V # Increase verbosity level #AVRDUDE_VERBOSE = -v -v diff --git a/conway.c b/conway.c index dac35e0..2dfa5a1 100644 --- a/conway.c +++ b/conway.c @@ -1,4 +1,9 @@ +#include +#include +#include + #include "main.h" +#include "display.h" #include "conway.h" volatile extern uint8_t *volatile display_buffer; /* Buffer für Display */ @@ -62,14 +67,8 @@ void conway_start() { uint8_t i = 0; - /* populate world */ - /* with pattern - worlds[i][1] |= 0b00001100; - worlds[i][2] |= 0b00011000; - worlds[i][3] |= 0b00001000;*/ - /* by random */ - for (uint8_t q = 0; q < 8; q++) { + for (uint8_t q = 0; q < 32; q++) { uint8_t row = rand() % 16; uint8_t col = rand() % 8; display_set(col, row, 1); @@ -83,8 +82,17 @@ void conway_start() { i = 1 - i; // switch world if (~PINB & KEY_Y) { - _delay_ms(10); return; // exit } + if (~PINB & KEY_A) { + worlds[i][7] |= 0b00001100; + worlds[i][8] |= 0b00011000; + worlds[i][9] |= 0b00001000; + } + if (~PINB & KEY_B) { + worlds[i][7] |= 0b00010000; + worlds[i][8] |= 0b00001000; + worlds[i][9] |= 0b00111000; + } } } diff --git a/conway.h b/conway.h index f5b15b4..0c7aa31 100644 --- a/conway.h +++ b/conway.h @@ -1,4 +1,6 @@ +#include + uint8_t conway_cell_neighbours(uint8_t x, uint8_t y, uint8_t *world); uint8_t conway_next_cell_gen(uint8_t x, uint8_t y, uint8_t *world); void conway_next_gen(uint8_t *world, uint8_t *next_gen); -void conway_start(); +void conway_start( void ); diff --git a/display.c b/display.c index 9d95a69..8d7164b 100644 --- a/display.c +++ b/display.c @@ -1,14 +1,30 @@ #include #include +#include +#include +#include #include "display.h" +#include "font.h" #include "tetris.h" volatile uint8_t *volatile display_buffer; /* Buffer für Display */ -extern volatile board_t brd; extern volatile stone_t stn; +void display_set(uint8_t col, uint8_t row, uint8_t val) { + if (val) { + display_buffer[row] |= (1 << col); + } + else { + display_buffer[row] &= ~(1 << col); + } +} + +void display_toggle(uint8_t col, uint8_t row) { + display_buffer[row] ^= (1 << col); +} + /** * Initialisiere Display im Multiplexing Modus */ @@ -35,32 +51,44 @@ uint8_t * display_print(char *text, uint8_t *buffer) { strupr(text); /* Nur Großbuchstaben sind verfügbar */ - for (uint16_t c = 0; c < len; c++) { - char chr = text[len-c-1]; - uint8_t pattern; - - if (chr >= ' ' && chr <= '_') - pattern = chr - ' '; - else - pattern = 0; /* space */ + for (uint16_t c = len-1; c >= 0; c--) { + char p = text[c]; + char q = (p >= ' ' && p <= '_') ? p - ' ' : 0; - for (uint8_t p = 0; p < 3; p++) { - buffer[p+c*4+16] = font[pattern][p]; - } - //buffer[c*4+16] = 0; /* padding */ + mempcpy(buffer[c*4], font[q], 3); } return buffer; } -void display_laufschrift(uint8_t *buffer, uint16_t bytes, uint8_t speed, uint8_t rounds) { - display_buffer = buffer; - while(1) { - if (display_buffer == buffer) { - display_buffer = buffer+bytes-16; - if (rounds-- == 0) { - return; - } +void display_laufschrift(char *text, uint8_t speed, uint8_t rounds) { + uint16_t len = 4 * strlen(text) + 16; // 4 Bytes pro Character + 2 * 16 Bytes Padding + uint8_t *orig_buffer = display_buffer; + + volatile uint8_t *buffer = malloc(len); + + memset(buffer, 0, len); + display_buffer = display_print("test", buffer); + + while ( TRUE ) { + buffer[15]++; + _delay_ms(500); + } + + //display_roll(buffer, len, speed, rounds); + + display_buffer = orig_buffer; /* reset to old buffer */ + free(buffer); +} + +void display_roll(uint16_t bytes, uint8_t speed, uint8_t rounds) { + uint8_t *end_buffer = display_buffer; + display_buffer += bytes - 16; + + while (rounds) { + if (display_buffer == end_buffer) { + display_buffer = end_buffer + bytes - 16; + rounds--; } display_buffer--; @@ -73,32 +101,27 @@ void display_laufschrift(uint8_t *buffer, uint16_t bytes, uint8_t speed, uint8_t */ ISR(TIMER0_COMP_vect) { static uint8_t column; - static uint8_t counter; uint8_t row_mask = (1 << column); uint16_t column_mask = 0; - for (uint8_t i = 4; i < NUM_LINES; i++) { - if (row_mask & brd[i]) { /* fixed pixels, dimmed */ - column_mask |= (1 << (i-4)); + for (uint8_t i = 0; i < 16; i++) { + if (row_mask & display_buffer[i]) { /* fixed pixels, dimmed */ + column_mask |= (1 << i); } - if (tetris) { /* in tetris mode ? */ - if (i >= tetris->stn.pos_y && i < tetris->stn.pos_y+4) { /* in clipping of falling stone ? */ - if (row_mask & tetris->stn.clipping[i-stn.pos_y]) { - column_mask |= (1 << (i-4)); - } + if (i+4 >= stn.pos_y && i < stn.pos_y) { /* in clipping of falling stone ? */ + if (row_mask & stn.clipping[i+4-stn.pos_y]) { + column_mask |= (1 << i); } } } + PORTD = 0; PORTC = (uint8_t) column_mask; PORTA = (uint8_t) (column_mask >> 8); PORTD = row_mask; column++; - if (column == 8) { - column = 0; - counter++; - } + column %= 8; } diff --git a/display.h b/display.h index 6e3cd0e..5bd9b58 100644 --- a/display.h +++ b/display.h @@ -1,8 +1,12 @@ #ifndef _DISPLAY_H_ #define _DISPLAY_H_ +void display_set(uint8_t col, uint8_t row, uint8_t val); +void display_toggle(uint8_t col, uint8_t row); + void display_init( void ); -void display_laufschrift(uint8_t *buffer, uint16_t bytes, uint8_t speed, uint8_t rounds); +void display_laufschrift(char * text, uint8_t speed, uint8_t rounds); +void display_roll(uint16_t bytes, uint8_t speed, uint8_t rounds); uint8_t * display_print(char *text, uint8_t *buffer); #endif /* _DISPLAY_H_ */ diff --git a/font.h b/font.h index b760e6c..6f51253 100644 --- a/font.h +++ b/font.h @@ -301,7 +301,7 @@ const uint8_t font[][3] = { 0b01111111, 0b00000000 }, - { // \ + { 0b00000011, 0b00011100, 0b01100000 diff --git a/main.c b/main.c index ff3169b..b6db037 100644 --- a/main.c +++ b/main.c @@ -1,11 +1,16 @@ #include +#include #include #include "main.h" #include "display.h" #include "tetris.h" +#include "conway.h" -static uint8_t rwth_logo[] = {0x7c, 0x50, 0x2c, 0x00, 0x78, 0x04, 0x18, 0x04, 0x78, 0x40, 0x7c, 0x40, 0x7c, 0x10, 0x7c, 0x00}; +volatile extern uint8_t *volatile display_buffer; /* Buffer für Display */ + +static uint8_t rwth_logo[] = {0x00, 0x7c, 0x10, 0x7c, 0x40, 0x7c, 0x40, 0x78, 0x04, 0x18, 0x04, 0x78, 0x00, 0x2c, 0x50, 0x7c}; +static char bill_txt[] = "'Nobody will ever need more than 640k RAM!' - Bill Gates, 1981 ;-)"; uint8_t get_seed() { uint8_t seed = 0; @@ -18,6 +23,22 @@ uint8_t get_seed() { return seed; } +void random_start() { + volatile uint8_t random_buffer[16]; + display_buffer = memset(random_buffer, 0, 16); + + while ( TRUE ) { + uint8_t row = rand() % 16; + uint8_t col = rand() % 8; + display_toggle(col, row); + + if (~PINB & KEY_Y) { + break; + } + _delay_ms(20); + } +} + int main( void ) { display_init(); srand(get_seed()); @@ -33,28 +54,17 @@ int main( void ) { /* Demo 1: Tetris */ tetris_start(); + _delay_ms(300); /* Demo 4: Conways Game of Life */ conway_start(); + _delay_ms(300); /* Demo 2: Laufschrift */ - /*char text[] = "'Nobody will ever need more than 640k RAM!' - Bill Gates, 1981 ;-)"; - uint16_t len = 4*strlen(text)+32; // 4 Bytes pro Character + 2 * 16 Bytes Padding - volatile uint8_t text_buffer[len]; - display_print(text, text_buffer); - - // Starte Laufschrift - display_laufschrift(text_buffer, len, 120, 1);*/ +/// display_laufschrift("test", 120, 1); /* Demo 3: Zufall */ - /*volatile uint8_t random_buffer[16]; - display_buffer = memset(random_buffer, 0, 16); - srand(get_seed()); - - for (uint16_t i = 0; i < 450; i++) { - display_toggle(rand()%8, rand()%16); - display_buffer[0] = i; - _delay_ms(20); - }*/ + random_start(); + _delay_ms(300); } } diff --git a/tetris b/tetris deleted file mode 100755 index cae565c..0000000 Binary files a/tetris and /dev/null differ diff --git a/tetris.c b/tetris.c index a64c54d..074b61a 100644 --- a/tetris.c +++ b/tetris.c @@ -4,9 +4,12 @@ #include "tetris.h" -volatile tetris_t *volatile tetris = NULL; +extern volatile uint8_t *volatile display_buffer; /* Buffer für Display */ -//static int16_t scoring[] = {0, 40, 100, 300, 1200}; /* scoring multiplicator for 0-4 flushed lines */ +volatile uint8_t *volatile brd = NULL; /* NULL if not in tetris mode */ +volatile stone_t stn; + +static int16_t scoring[] = {0, 40, 100, 300, 1200}; /* scoring multiplicator for 0-4 flushed lines */ static clipping_t shapes[][4] = { /* including 4 ccw rotations */ { // SHAPE_I @@ -101,7 +104,7 @@ bool_t tetris_turn_stone() { } } - copy_clipping(tmp, stn.clipping); + tetris_copy_clipping(tmp, stn.clipping); return TRUE; } @@ -168,24 +171,19 @@ bool_t tetris_detect_collision(direction_t dir) { } void tetris_start() { - tetris_t state; - + uint8_t debounce = 0; + uint8_t lines = 0; uint8_t frames = 48; + uint8_t score = 0; uint8_t level = 0; - //uint16_t score = 0; - //uint16_t stones = 0; - uint16_t lines = 0; - uint8_t debounce; - tetris = &state; - display_buffer = state.brd+4; /* skipping "virtual" lines */ + brd = malloc(sizeof(board_t)); + display_buffer = brd+4; /* skipping first 4 "virtual" lines */ /* starting with empty board */ - for (uint8_t i = 0; i < NUM_LINES; i++) { - brd[i] = 0; - } + memset(brd, 0, NUM_LINES); - while (TRUE) { /* main loop */ + while ( TRUE ) { /* main loop */ /* add new stone on the top of our board */ uint8_t shape = rand() % NUM_SHAPES; uint8_t orientation = rand() % 4; @@ -195,7 +193,7 @@ void tetris_start() { stn.pos_x = 0; stn.pos_y = 0; - copy_clipping(shapes[shape][orientation], stn.clipping); + tetris_copy_clipping(shapes[shape][orientation], stn.clipping); if (lines > (level + 1) * 10) { level++; /* next level */ @@ -233,16 +231,17 @@ void tetris_start() { } } if (keys & KEY_Y) { - _delay_ms(10); + free(brd); + memset(stn.clipping, 0, 4); return; // exit tetris } if (keys) { - debounce = 6 + debounce = 9; } } - _delay_ms(900 / FRAMES); // sleep for 1 frame (10% for calculations) + _delay_ms(900 / FRAMES); // sleep for 1 frame (100ms approx for calculations) } } while (tetris_detect_collision(DIR_DOWN) == FALSE); @@ -251,17 +250,18 @@ void tetris_start() { } /* check for completed lines and calculate score */ - uint8_t flushed = flush_lines(); - //score += (level + 1) * scoring[flushed]; - //stones++; + uint8_t flushed = tetris_flush_lines(); + score += (level + 1) * scoring[flushed]; lines += flushed; if (brd[3] > 0) { - //return; /* game over */ - for (uint8_t i = 0; i < NUM_LINES; i++) { /* restart with empty board */ - brd[i] = 0; /* starting with empty board */ - } - _delay_ms(1000); + free(brd); + memset(stn.clipping, 0, 4); + return; /* game over */ } } + + free(brd); + brd = NULL; + return; } diff --git a/tetris.h b/tetris.h index 6fc215d..aaa7a2d 100644 --- a/tetris.h +++ b/tetris.h @@ -12,11 +12,6 @@ typedef uint8_t board_t[NUM_LINES]; typedef uint8_t clipping_t[4]; -typedef struct { - stone_t stn; - board_t brd; -} tetris_t; - /* Named according to: http://de.wikipedia.org/wiki/Tetris */ typedef enum { SHAPE_I, /* line of four dots */