diff --git a/src/animations/Makefile b/src/animations/Makefile index 3b4a409..585edb9 100644 --- a/src/animations/Makefile +++ b/src/animations/Makefile @@ -30,6 +30,10 @@ ifeq ($(ANIMATION_MHERWEG),y) SRC += mherweg.c endif +ifeq ($(ANIMATION_MOIRE),y) + SRC += moire.c +endif + ifeq ($(ANIMATION_BREAKOUT),y) SRC += breakout_demo.c endif diff --git a/src/animations/config.in b/src/animations/config.in index 2a17321..2d21fdd 100644 --- a/src/animations/config.in +++ b/src/animations/config.in @@ -42,6 +42,7 @@ comment "Animations" dep_bool "Breakout Demo" ANIMATION_BREAKOUT $GAME_BREAKOUT dep_bool "Martin Herweg" ANIMATION_MHERWEG $RANDOM_SUPPORT + dep_bool "Moire" ANIMATION_MOIRE $RANDOM_SUPPORT dep_bool "Langton Ant" ANIMATION_LTN_ANT $RANDOM_SUPPORT dep_bool_menu "Time Display" ANIMATION_TIME $SCROLLTEXT_SUPPORT $LAP_TIME_EXTENSION diff --git a/src/animations/mherweg.c b/src/animations/mherweg.c index 94a9c33..6f56575 100644 --- a/src/animations/mherweg.c +++ b/src/animations/mherweg.c @@ -27,51 +27,6 @@ #define PGM(x) pgm_read_byte(&(x)) -#if NUM_ROWS < 64 && NUM_COLS < 64 - /** use 8 bit operands where feasible */ - typedef signed char operand_t; -#else - /** use 16 bit operands if either width or height are >= 64 */ - typedef int operand_t; -#endif - - -/** - * An implementation of Bresenham's line drawing algorithm. - * @param p1 first coordinate of the line - * @param p2 second coordinate of the line - * @param color brightness level of the line - */ -static void line(pixel p1, - pixel const p2, - unsigned char const color) -{ - operand_t const dx = p1.x < p2.x ? p2.x - p1.x : p1.x - p2.x; - operand_t const sx = p1.x < p2.x ? 1 : -1; - operand_t const dy = p1.y < p2.y ? p2.y - p1.y : p1.y - p2.y; - operand_t const sy = p1.y < p2.y ? 1 : -1; - operand_t error = dx - dy; - - while(1) - { - setpixel(p1, color); - if ((p1.x == p2.x) && (p1.y == p2.y)) - break; - operand_t const error2 = 2 * error; - if (error2 > -dy) - { - error -= dy; - p1.x += sx; - } - if (error2 < dx) - { - error += dx; - p1.y += sy; - } - } -} - - /** * Draws a rectangle at the given coordinates. * @param p coordinate of the rectangle's upper right corner diff --git a/src/animations/moire.c b/src/animations/moire.c new file mode 100644 index 0000000..ce35b30 --- /dev/null +++ b/src/animations/moire.c @@ -0,0 +1,88 @@ +/** + * \defgroup moire A moire like pattern. + * @{ + */ + +/** + * @file moire.c + * @brief Implementation of a simple moire like pattern. + * @author Christian Kroll + */ + +#include "../config.h" +#include "../pixel.h" +#include "../util.h" + +/** + * Number of pixels of the complete border. + */ +#define NUMBER_OF_BORDER_PIXELS (2u * UNUM_COLS + 2u * (UNUM_ROWS - 2u)) + +/** + * Draws a moire like pattern. Works best if the number of border pixels is a + * multiple of the size of the gradient color map. + */ +void moire(void) +{ + // add rotating color map +#if NUMPLANE == 3 + static unsigned char const gradient[] = {0, 1, 2, 3, 2, 1}; +#else + static unsigned char gradient[NUMPLANE * 2u] = {0}; + for (unsigned char i = 1; i <= NUMPLANE; ++i) + { + gradient[i] = i; + gradient[(NUMPLANE * 2) - i] = i; + } +#endif + + unsigned int cycles = 30000; + unsigned char pos = 0, color_index = 0; + pixel p1 = (pixel){0 ,0}; + + while(cycles--) + { + // walk around the border; do that by mapping a linear increasing value + // to appropriate screen coordinates + + // first pixel is between top right and top left corner + if (pos < NUM_COLS) + { + p1.x = pos; + } + // first pixel is between top left and bottom left corner + else if (pos < (NUM_COLS + NUM_ROWS - 1)) + { + p1.y = pos - (NUM_COLS - 1); + } + // first pixel is between bottom left and bottom right corner + else if (pos < (2 * NUM_COLS + NUM_ROWS - 2)) + { + p1.x = 2 * NUM_COLS + NUM_ROWS - 3 - pos; + } + // first pixel is between bottom right and top left corner + else + { + p1.y = 3 * NUM_COLS + NUM_ROWS - 4 - pos; + } + + // second pixel in opposite direction + pixel const p2 = (pixel){NUM_COLS - 1 - p1.x, NUM_ROWS - 1 - p1.y}; + + // draw line right accross the display and switch to next color + line(p1, p2, gradient[color_index++]); + + // if we have reached the origin, reset position, rotate color index and + // wait for 40 ms (25 fps) to make the frame visible for human viewers + if (++pos == NUMBER_OF_BORDER_PIXELS) + { + pos = 0; + ++color_index; + wait(40); + } + // ensure the color index keeps within bounds + color_index %= (2u * NUMPLANE); + } +} + +/*@}*/ diff --git a/src/animations/moire.h b/src/animations/moire.h new file mode 100644 index 0000000..9749025 --- /dev/null +++ b/src/animations/moire.h @@ -0,0 +1,19 @@ +/** + * \defgroup moire A moire like pattern. + * @{ + */ + +/** + * @file moire.h + * @brief Interface file for a moire pattern implementation. + * @author Christian Kroll + */ + +#ifndef MOIRE_H_ +#define MOIRE_H_ + +void moire(void); + +#endif /* MOIRE_H_ */ + +/*@}*/ diff --git a/src/display_loop.c b/src/display_loop.c index faf47a0..42929e2 100644 --- a/src/display_loop.c +++ b/src/display_loop.c @@ -18,6 +18,7 @@ #include "animations/bitmapscroller/fairydust.h" #include "animations/fpmath_patterns.h" #include "animations/mherweg.h" +#include "animations/moire.h" #include "animations/blackhole.h" #include "animations/squares.h" #ifdef ANIMATION_TIME @@ -183,62 +184,68 @@ void display_loop(){ break; #endif -#ifdef ANIMATION_TIME +#ifdef ANIMATION_MOIRE case 15: + moire(); + break; +#endif + +#ifdef ANIMATION_TIME + case 16: time_anim(); break; #endif #ifdef ANIMATION_LTN_ANT - case 16: + case 17: ltn_ant(); break; #endif #ifdef ANIMATION_LABORLOGO - case 17: + case 18: laborlogo(); break; #endif #ifdef ANIMATION_AMPHIBIAN - case 18: + case 19: amphibian(); break; #endif #ifdef ANIMATION_LOGO_OOS - case 19: + case 20: logo_OutOfSpec(); break; #endif #ifdef ANIMATION_FAIRYDUST - case 20: + case 21: fairydust(); break; #endif #ifdef ANIMATION_PLASMA - case 21: + case 22: plasma(); break; #endif #ifdef ANIMATION_PSYCHEDELIC - case 22: + case 23: psychedelic(); break; #endif #ifdef ANIMATION_BLACKHOLE - case 23: + case 24: blackhole(); break; #endif #ifdef ANIMATION_SQUARES - case 24: + case 25: squares(); break; #endif diff --git a/src/pixel.c b/src/pixel.c index af03015..ba46700 100644 --- a/src/pixel.c +++ b/src/pixel.c @@ -58,3 +58,38 @@ unsigned char get_pixel(pixel p){ return 0!= (pixmap[0][p.y][p.x/8] & shl_table[p.x%8]); } } + +/** + * An implementation of Bresenham's line drawing algorithm. + * @param p1 first coordinate of the line + * @param p2 second coordinate of the line + * @param color brightness level of the line + */ +void line(pixel p1, + pixel const p2, + unsigned char const color) +{ + operand_t const dx = p1.x < p2.x ? p2.x - p1.x : p1.x - p2.x; + operand_t const sx = p1.x < p2.x ? 1 : -1; + operand_t const dy = p1.y < p2.y ? p2.y - p1.y : p1.y - p2.y; + operand_t const sy = p1.y < p2.y ? 1 : -1; + operand_t error = dx - dy; + + while(1) + { + setpixel(p1, color); + if ((p1.x == p2.x) && (p1.y == p2.y)) + break; + operand_t const error2 = 2 * error; + if (error2 > -dy) + { + error -= dy; + p1.x += sx; + } + if (error2 < dx) + { + error += dx; + p1.y += sy; + } + } +} diff --git a/src/pixel.h b/src/pixel.h index a9204f4..252e4b5 100644 --- a/src/pixel.h +++ b/src/pixel.h @@ -42,6 +42,15 @@ typedef struct cursor{ pixelmode_t mode; } cursor_t; + +#if NUM_ROWS < 64 && NUM_COLS < 64 + /** use 8 bit operands where feasible */ + typedef signed char operand_t; +#else + /** use 16 bit operands if either width or height are >= 64 */ + typedef int operand_t; +#endif + /**************************************************************************** * Pixel routines */ @@ -79,4 +88,8 @@ static inline void set_cursor(cursor_t* cur, pixel p){ setpixel(p, cur->mode ? 3 : 0); } +void line(pixel p1, + pixel const p2, + unsigned char const color); + #endif // PIXEL_H