From c7d87fd98c99e74f3bfdbd2be58b04099fd2fa96 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 30 May 2012 10:55:53 +1000 Subject: [PATCH] Complete the RunningFigure example --- doc/dmd-running-figure.dox | 84 ++++++ doc/mainpage.dox | 7 + .../examples/RunningFigure/RunningFigure.pde | 136 ++++++++- .../RunningFigureISR/RunningFigureISR.pde | 263 ++++++++++++++++++ 4 files changed, 485 insertions(+), 5 deletions(-) create mode 100644 doc/dmd-running-figure.dox create mode 100644 libraries/DMD/examples/RunningFigureISR/RunningFigureISR.pde diff --git a/doc/dmd-running-figure.dox b/doc/dmd-running-figure.dox new file mode 100644 index 00000000..b4da2d78 --- /dev/null +++ b/doc/dmd-running-figure.dox @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** +\file dmd-running-figure.dox +\page dmd_running_figure Running figure example + +This example demonstrates how to draw animated bitmaps to +Freetronics Large Dot +Matrix Displays. These displays have 512 LED's arranged in a +32x16 matrix and controlled by an SPI interface. The displays are +available in red, blue, green, yellow, and white variations. + +The first step is to initialize the display: + +\dontinclude DMD/examples/RunningFigure/RunningFigure.pde +\skip #include +\until DMD display; + +We will also need some bitmaps to animate the running figure. We will use +static bitmaps stored in program memory. The first frame of the 10-frame +animation is: + +\dontinclude DMD/examples/RunningFigure/RunningFigure.pde +\skip run1 +\until }; + +As can be seen, the bitmap is made up of 0's and 1's; a 1 bit indicates that +the corresponding LED will be lit when it is drawn to the dot matrix display. +The first two bytes are the width and height of the bitmap in pixels. +In this case, the first frame is 16x16 pixels. Other frames in the animation +are 18x16 and 13x16. + +We store pointers to all of the frames in a common array: + +\dontinclude DMD/examples/RunningFigure/RunningFigure.pde +\skip frames[] +\until frame = 0 + +All that remains is to run the animation loop: + +\dontinclude DMD/examples/RunningFigure/RunningFigure.pde +\skip ADVANCE_MS +\until display.loop() +\until } + +Each time \c ADVANCE_MS milliseconds expires, we clear the display and +draw a bitmap centered on the screen. To help with the centering, we read +the width value from the bitmap for the current frame (the height is +always 16). We must also call DMD::loop() repeatedly from the application's +main loop() function to ensure that the display is kept refreshed. + +Sometimes it can be inconvenient to arrange for DMD::loop() to be called +regularly. An alternative is to use Timer1 and +\ref dmd_interrupts "interrupt-driven display refresh": + +\dontinclude DMD/examples/RunningFigureISR/RunningFigureISR.pde +\skip ADVANCE_MS +\until loop() +\until } + +The full source code for the example follows: + +\include DMD/examples/RunningFigure/RunningFigure.pde +*/ diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 982106d4..01d91ae5 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -42,6 +42,13 @@ LCD shield. \li \ref lcd_hello_world "Hello World" example for the Freetronics LCD shield. \li \ref lcd_form "Form" example for LCD displays. +\section main_DMD Freetronics Large Dot Matrix Display (DMD) + +\li DMD class to manage the initialize of the display. +\li Bitmap class to manage drawing to in-memory bitmaps and the DMD display. +\li \ref dmd_running_figure "RunningFigure" example that demonstrates how +to draw and animate bitmaps. + \section main_BlinkLED BlinkLED Utility Library \li BlinkLED class that simplifies the process of blinking a LED connected diff --git a/libraries/DMD/examples/RunningFigure/RunningFigure.pde b/libraries/DMD/examples/RunningFigure/RunningFigure.pde index 76e4f796..e45e56fe 100644 --- a/libraries/DMD/examples/RunningFigure/RunningFigure.pde +++ b/libraries/DMD/examples/RunningFigure/RunningFigure.pde @@ -107,29 +107,155 @@ byte const run4[] PROGMEM = { B00000100, B00000000 }; +byte const run5[] PROGMEM = { + 13, 16, + B00000000, B00000000, + B00000000, B00110000, + B00000111, B11111000, + B00000111, B11111000, + B00000111, B11110000, + B00001111, B11100000, + B00000111, B00000000, + B00001111, B00000000, + B00001111, B00000000, + B00001111, B10000000, + B00011100, B00000000, + B00111000, B00000000, + B01110000, B00000000, + B11100000, B00000000, + B11000000, B00000000, + B10000000, B00000000 +}; + +byte const run6[] PROGMEM = { + 16, 16, + B00000000, B00000000, + B00000000, B00011100, + B00000000, B00111110, + B00000001, B11111110, + B00000000, B11100000, + B00000001, B11100000, + B00000001, B11111000, + B00000011, B00011100, + B00000110, B00111000, + B00000110, B01110000, + B00001100, B00100000, + B00111000, B00000000, + B01100000, B00000000, + B11000000, B00000000, + B10000000, B00000000, + B10000000, B00000000 +}; + +byte const run7[] PROGMEM = { + 18, 16, + B00000000, B00000011, B10000000, + B00000000, B01111011, B10000000, + B00000000, B01111111, B10000000, + B00000000, B00001111, B00100000, + B00000000, B00011001, B11000000, + B00000000, B00110000, B11000000, + B00000000, B01110000, B00000000, + B00000001, B11110000, B00000000, + B11111111, B10111000, B00000000, + B11111111, B00011100, B00000000, + B00000000, B00001110, B00000000, + B00000000, B00000111, B00000000, + B00000000, B00000011, B10000000, + B00000000, B00000001, B11000000, + B00000000, B00000000, B01000000, + B00000000, B00000000, B00000000 +}; + +byte const run8[] PROGMEM = { + 18, 16, + B00000000, B00000110, B00000000, + B00000001, B11101111, B00000000, + B00000001, B11111111, B00000000, + B00000000, B00111110, B00000000, + B00000000, B01111111, B11000000, + B00000000, B11100011, B10000000, + B00000001, B11000000, B00000000, + B00000011, B11100000, B00000000, + B11111111, B01110000, B00000000, + B11111110, B00111000, B00000000, + B00000000, B00011100, B00000000, + B00000000, B00000110, B00000000, + B00000000, B00000110, B00000000, + B00000000, B00000111, B00000000, + B00000000, B00000011, B00000000, + B00000000, B00000001, B00000000 +}; + +byte const run9[] PROGMEM = { + 16, 16, + B00000000, B00000000, + B00000000, B01001110, + B00000001, B11101110, + B00000011, B11111110, + B00000011, B11111110, + B00000001, B10111100, + B00000011, B00000000, + B00000111, B00000000, + B11111111, B10000000, + B11111100, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000 +}; + +byte const run10[] PROGMEM = { + 13, 16, + B00000000, B00000000, + B00000000, B00110000, + B00000000, B01111000, + B00000111, B11111000, + B00001111, B11111000, + B00000111, B11000000, + B00001110, B00000000, + B00001100, B00000000, + B00001100, B00000000, + B01111100, B00000000, + B11111100, B00000000, + B00011000, B00000000, + B00110000, B00000000, + B01110000, B00000000, + B01100000, B00000000, + B01000000, B00000000 +}; + const prog_uint8_t *frames[] = { run1, run2, run3, - run4 + run4, + run5, + run6, + run7, + run8, + run9, + run10 }; #define NUM_FRAMES (sizeof(frames) / sizeof(frames[0])) -#define ADVANCE_MS (1000 / NUM_FRAMES) unsigned int frame = 0; + +#define ADVANCE_MS (1000 / NUM_FRAMES) unsigned long lastFrame; void setup() { - display.drawBitmap(8, 0, run1); - lastFrame = millis(); + lastFrame = millis() - ADVANCE_MS; } void loop() { if ((millis() - lastFrame) >= ADVANCE_MS) { - frame = (frame + 1) % NUM_FRAMES; display.clear(); int x = (32 - pgm_read_byte(frames[frame])) / 2; display.drawBitmap(x, 0, frames[frame]); lastFrame += ADVANCE_MS; + frame = (frame + 1) % NUM_FRAMES; } display.loop(); } diff --git a/libraries/DMD/examples/RunningFigureISR/RunningFigureISR.pde b/libraries/DMD/examples/RunningFigureISR/RunningFigureISR.pde new file mode 100644 index 00000000..e60b20bd --- /dev/null +++ b/libraries/DMD/examples/RunningFigureISR/RunningFigureISR.pde @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +DMD display; + +// Running stick figure pictures are loosely based on those from this tutorial: +// http://www.fluidanims.com/FAelite/phpBB3/viewtopic.php?f=10&t=102 + +byte const run1[] PROGMEM = { + 16, 16, + B00000000, B00001100, + B00000000, B00011110, + B00000111, B11111110, + B00001111, B11111110, + B00011100, B11111100, + B00000001, B11111100, + B00000001, B11110000, + B00000011, B11111000, + B00000111, B00011000, + B00001110, B01110000, + B00011100, B01100000, + B00111000, B00000000, + B01110000, B00000000, + B01100000, B00000000, + B01000000, B00000000, + B00000000, B00000000 +}; + +byte const run2[] PROGMEM = { + 18, 16, + B00000000, B01110011, B10000000, + B00000000, B11111111, B10000000, + B00000000, B00011111, B10000000, + B00000000, B00111111, B11000000, + B00000000, B01111011, B11000000, + B00000000, B11110011, B10000000, + B00000001, B11100000, B00000000, + B00000011, B11100000, B00000000, + B00000111, B01110000, B00000000, + B01111110, B00111000, B00000000, + B11111100, B00011100, B00000000, + B00000000, B00001110, B00000000, + B00000000, B00000111, B00000000, + B00000000, B00000011, B10000000, + B00000000, B00000001, B00000000, + B00000000, B00000000, B00000000 +}; + +byte const run3[] PROGMEM = { + 18, 16, + B00000000, B00110000, B00000000, + B00000000, B01111000, B00000000, + B00000000, B00011111, B00000000, + B00000000, B00011111, B00000000, + B00000000, B00111111, B10000000, + B00000000, B01111111, B11000000, + B00000000, B11100011, B10000000, + B00000001, B11000000, B00000000, + B00000011, B11100000, B00000000, + B11111111, B01110000, B00000000, + B11111110, B00111000, B00000000, + B00000000, B00011000, B00000000, + B00000000, B00011100, B00000000, + B00000000, B00001110, B00000000, + B00000000, B00000100, B00000000, + B00000000, B00000000, B00000000 +}; + +byte const run4[] PROGMEM = { + 16, 16, + B00000001, B11100000, + B00000011, B11111100, + B00000000, B00111110, + B00000000, B01111110, + B00000000, B11111100, + B00000001, B10011111, + B00000011, B00001110, + B00000011, B00000000, + B00000011, B10000000, + B11111111, B10000000, + B11111000, B11000000, + B00000001, B11000000, + B00000011, B10000000, + B00000111, B00000000, + B00000110, B00000000, + B00000100, B00000000 +}; + +byte const run5[] PROGMEM = { + 13, 16, + B00000000, B00000000, + B00000000, B00110000, + B00000111, B11111000, + B00000111, B11111000, + B00000111, B11110000, + B00001111, B11100000, + B00000111, B00000000, + B00001111, B00000000, + B00001111, B00000000, + B00001111, B10000000, + B00011100, B00000000, + B00111000, B00000000, + B01110000, B00000000, + B11100000, B00000000, + B11000000, B00000000, + B10000000, B00000000 +}; + +byte const run6[] PROGMEM = { + 16, 16, + B00000000, B00000000, + B00000000, B00011100, + B00000000, B00111110, + B00000001, B11111110, + B00000000, B11100000, + B00000001, B11100000, + B00000001, B11111000, + B00000011, B00011100, + B00000110, B00111000, + B00000110, B01110000, + B00001100, B00100000, + B00111000, B00000000, + B01100000, B00000000, + B11000000, B00000000, + B10000000, B00000000, + B10000000, B00000000 +}; + +byte const run7[] PROGMEM = { + 18, 16, + B00000000, B00000011, B10000000, + B00000000, B01111011, B10000000, + B00000000, B01111111, B10000000, + B00000000, B00001111, B00100000, + B00000000, B00011001, B11000000, + B00000000, B00110000, B11000000, + B00000000, B01110000, B00000000, + B00000001, B11110000, B00000000, + B11111111, B10111000, B00000000, + B11111111, B00011100, B00000000, + B00000000, B00001110, B00000000, + B00000000, B00000111, B00000000, + B00000000, B00000011, B10000000, + B00000000, B00000001, B11000000, + B00000000, B00000000, B01000000, + B00000000, B00000000, B00000000 +}; + +byte const run8[] PROGMEM = { + 18, 16, + B00000000, B00000110, B00000000, + B00000001, B11101111, B00000000, + B00000001, B11111111, B00000000, + B00000000, B00111110, B00000000, + B00000000, B01111111, B11000000, + B00000000, B11100011, B10000000, + B00000001, B11000000, B00000000, + B00000011, B11100000, B00000000, + B11111111, B01110000, B00000000, + B11111110, B00111000, B00000000, + B00000000, B00011100, B00000000, + B00000000, B00000110, B00000000, + B00000000, B00000110, B00000000, + B00000000, B00000111, B00000000, + B00000000, B00000011, B00000000, + B00000000, B00000001, B00000000 +}; + +byte const run9[] PROGMEM = { + 16, 16, + B00000000, B00000000, + B00000000, B01001110, + B00000001, B11101110, + B00000011, B11111110, + B00000011, B11111110, + B00000001, B10111100, + B00000011, B00000000, + B00000111, B00000000, + B11111111, B10000000, + B11111100, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000, + B00000000, B11000000 +}; + +byte const run10[] PROGMEM = { + 13, 16, + B00000000, B00000000, + B00000000, B00110000, + B00000000, B01111000, + B00000111, B11111000, + B00001111, B11111000, + B00000111, B11000000, + B00001110, B00000000, + B00001100, B00000000, + B00001100, B00000000, + B01111100, B00000000, + B11111100, B00000000, + B00011000, B00000000, + B00110000, B00000000, + B01110000, B00000000, + B01100000, B00000000, + B01000000, B00000000 +}; + +const prog_uint8_t *frames[] = { + run1, + run2, + run3, + run4, + run5, + run6, + run7, + run8, + run9, + run10 +}; +#define NUM_FRAMES (sizeof(frames) / sizeof(frames[0])) +unsigned int frame = 0; + +#define ADVANCE_MS (1000 / NUM_FRAMES) + +ISR(TIMER1_OVF_vect) +{ + display.refresh(); +} + +void setup() { + display.enableTimer1(); +} + +void loop() { + display.clear(); + int x = (32 - pgm_read_byte(frames[frame])) / 2; + display.drawBitmap(x, 0, frames[frame]); + frame = (frame + 1) % NUM_FRAMES; + + delay(ADVANCE_MS); +}