From 081aab987b3abd76925c76a36fba659e10787b63 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 25 May 2012 17:41:27 +1000 Subject: [PATCH] Library for using Freetronics dot matrix displays --- doc/Doxyfile | 4 +- gen/genflip.c | 48 + libraries/DMD/Bitmap.cpp | 956 ++++++++++++++++++ libraries/DMD/Bitmap.h | 138 +++ libraries/DMD/DMD.cpp | 618 +++++++++++ libraries/DMD/DMD.h | 60 ++ libraries/DMD/DejaVuSans9.h | 166 +++ libraries/DMD/DejaVuSansBold9.h | 166 +++ libraries/DMD/DejaVuSansItalic9.h | 166 +++ libraries/DMD/Mono5x7.h | 155 +++ libraries/DMD/dmd-4x1.fig | 36 + libraries/DMD/dmd-4x1.png | Bin 0 -> 2493 bytes libraries/DMD/dmd-4x2.fig | 60 ++ libraries/DMD/dmd-4x2.png | Bin 0 -> 4853 bytes libraries/DMD/dmd-4x3.fig | 84 ++ libraries/DMD/dmd-4x3.png | Bin 0 -> 6997 bytes libraries/DMD/dmd-info.txt | 53 + libraries/DMD/examples/Demo/Demo.pde | 144 +++ .../examples/RunningFigure/RunningFigure.pde | 135 +++ libraries/DMD/keywords.txt | 43 + 20 files changed, 3030 insertions(+), 2 deletions(-) create mode 100644 gen/genflip.c create mode 100644 libraries/DMD/Bitmap.cpp create mode 100644 libraries/DMD/Bitmap.h create mode 100644 libraries/DMD/DMD.cpp create mode 100644 libraries/DMD/DMD.h create mode 100644 libraries/DMD/DejaVuSans9.h create mode 100644 libraries/DMD/DejaVuSansBold9.h create mode 100644 libraries/DMD/DejaVuSansItalic9.h create mode 100644 libraries/DMD/Mono5x7.h create mode 100644 libraries/DMD/dmd-4x1.fig create mode 100644 libraries/DMD/dmd-4x1.png create mode 100644 libraries/DMD/dmd-4x2.fig create mode 100644 libraries/DMD/dmd-4x2.png create mode 100644 libraries/DMD/dmd-4x3.fig create mode 100644 libraries/DMD/dmd-4x3.png create mode 100644 libraries/DMD/dmd-info.txt create mode 100644 libraries/DMD/examples/Demo/Demo.pde create mode 100644 libraries/DMD/examples/RunningFigure/RunningFigure.pde create mode 100644 libraries/DMD/keywords.txt diff --git a/doc/Doxyfile b/doc/Doxyfile index 0855d498..b987d7fa 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -610,7 +610,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../libraries/LCD ../libraries/BlinkLED ../libraries/I2C ../libraries/RTC ../libraries/Melody ../libraries/PowerSave . +INPUT = ../libraries/LCD ../libraries/BlinkLED ../libraries/I2C ../libraries/RTC ../libraries/Melody ../libraries/PowerSave ../libraries/DMD . # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -688,7 +688,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = ../libraries/BlinkLED/examples/Cylon ../libraries/BlinkLED/examples/Cylon4 ../libraries/BlinkLED/examples/StarTrek ../libraries/LCD/examples/HelloWorld ../libraries/LCD/examples/Form ../libraries/RTC/examples/AlarmClock +IMAGE_PATH = ../libraries/BlinkLED/examples/Cylon ../libraries/BlinkLED/examples/Cylon4 ../libraries/BlinkLED/examples/StarTrek ../libraries/LCD/examples/HelloWorld ../libraries/LCD/examples/Form ../libraries/RTC/examples/AlarmClock ../libraries/DMD # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/gen/genflip.c b/gen/genflip.c new file mode 100644 index 00000000..67f0f50b --- /dev/null +++ b/gen/genflip.c @@ -0,0 +1,48 @@ +/* + * 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 + +int main(int argc, char *argv[]) +{ + int value; + printf("static const uint8_t flipBits[256] PROGMEM = {\n"); + for (value = 0; value < 256; ++value) { + int flipped = + ((value & 0x01) << 7) | ((value & 0x02) << 5) | + ((value & 0x04) << 3) | ((value & 0x08) << 1) | + ((value & 0x10) >> 1) | ((value & 0x20) >> 3) | + ((value & 0x40) >> 5) | ((value & 0x80) >> 7); + if ((value % 12) == 0) + printf(" "); + else + printf(" "); + if (value != 255) + printf("0x%02X,", flipped); + else + printf("0x%02X", flipped); + if ((value % 12) == 11) + printf("\n"); + } + printf("\n};\n"); + return 0; +} diff --git a/libraries/DMD/Bitmap.cpp b/libraries/DMD/Bitmap.cpp new file mode 100644 index 00000000..00fccb7e --- /dev/null +++ b/libraries/DMD/Bitmap.cpp @@ -0,0 +1,956 @@ +/* + * 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 "Bitmap.h" +#include +#include +#include + +/** + * \class Bitmap Bitmap.h + * \brief Represents a monochrome bitmap within main memory. + * + * Bitmaps are a rectangular arrangement of width() x height() pixels, + * with each pixel set to either \ref Black or \ref White. The co-ordinate + * system has origin (0, 0) at the top-left of the bitmap. + * + * Functions within this class can be used to draw various shapes into + * the bitmap's data() buffer; e.g. drawLine(), drawRect(), drawBitmap(), + * drawText(), clear(), fill(), etc. + * + * \sa DMD + */ + +/** + * \typedef Bitmap::Color + * \brief Type that represents the color of a pixel in a bitmap. + * + * \sa Black, White + */ + +/** + * \var Bitmap::Black + * \brief Color value corresponding to "black". + */ + +/** + * \var Bitmap::White + * \brief Color value corresponding to "white". If the bitmap is + * displayed on a LED array, then it may have a different physical color. + * + * Note: while the value of this constant is 1, the bitmap itself stores + * white pixels as 0 and black as 1 because the DMD display uses 1 to + * indicate a pixel being off. + */ + +/** + * \var Bitmap::NoFill + * \brief Special color value that is used with drawRect() and drawCircle() + * to indicate that the interior of the shape should not be filled. + * For all other uses, \ref NoFill is equivalent to \ref White. + */ + +/** + * \brief Constructs a new in-memory bitmap that is \a width x \a height + * pixels in size. + * + * \sa width(), height(), isValid() + */ +Bitmap::Bitmap(int width, int height) + : _width(width) + , _height(height) + , _stride((width + 7) / 8) + , fb(0) + , _font(0) + , _textColor(White) +{ + // Allocate memory for the framebuffer and clear it (1 = pixel off). + unsigned int size = _stride * _height; + fb = (uint8_t *)malloc(size); + if (fb) + memset(fb, 0xFF, size); +} + +/** + * \brief Destroys this bitmap. + */ +Bitmap::~Bitmap() +{ + if (fb) + free(fb); +} + +/** + * \fn bool Bitmap::isValid() const + * \brief Returns true if the memory for this bitmap is valid; false otherwise. + * + * This function can be called just after the constructor to determine if + * the memory for the bitmap was allocated successfully. + */ + +/** + * \fn int Bitmap::width() const + * \brief Returns the width of the bitmap in pixels. + * + * \sa height(), stride(), bitsPerPixel() + */ + +/** + * \fn int Bitmap::height() const + * \brief Returns the height of the bitmap in pixels. + * + * \sa width(), bitsPerPixel() + */ + +/** + * \fn int Bitmap::stride() const + * \brief Returns the number of bytes in each line of the bitmap's data() buffer. + * + * \sa width(), bitsPerPixel(), data() + */ + +/** + * \fn int Bitmap::bitsPerPixel() const + * \brief Returns the number of bits per pixel for the bitmap; always 1. + * + * \sa width(), height() + */ + +/** + * \fn uint8_t *Bitmap::data() + * \brief Returns a pointer to the start of the bitmap's data buffer. + * + * The data is organized as height() lines of stride() bytes, laid out + * horizontally across the extent of width() pixels. The most significant + * bit in each byte has the lowest x value. + * + * Note: bits within the data are 1 for \ref Black and 0 for \ref White, + * which is the reverse of the constant values. This differs from pixel() + * which returns the correct constant. + * + * \sa pixel(), stride() + */ + +/** + * \fn const uint8_t *Bitmap::data() const + * \brief Returns a constant pointer to the start of the bitmap's data buffer. + * \overload + */ + +/** + * \brief Clears the entire bitmap to the specified \a color. + * + * \sa fill() + */ +void Bitmap::clear(Color color) +{ + unsigned int size = _stride * _height; + if (color == Black) + memset(fb, 0xFF, size); + else + memset(fb, 0x00, size); +} + +/** + * \brief Returns the color of the pixel at (\a x, \a y); either \ref Black + * or \ref White. + * + * Returns \a Black if \a x or \a y is out of range. + * + * \sa setPixel(), data() + */ +Bitmap::Color Bitmap::pixel(int x, int y) const +{ + if (((unsigned int)x) >= ((unsigned int)_width) || + ((unsigned int)y) >= ((unsigned int)_height)) + return Black; + uint8_t *ptr = fb + y * _stride + (x >> 3); + if (*ptr & ((uint8_t)0x80) >> (x & 0x07)) + return Black; + else + return White; +} + +/** + * \brief Sets the pixel at (\a x, \a y) to \a color. + * + * \sa pixel() + */ +void Bitmap::setPixel(int x, int y, Color color) +{ + if (((unsigned int)x) >= ((unsigned int)_width) || + ((unsigned int)y) >= ((unsigned int)_height)) + return; // Pixel is off-screen. + uint8_t *ptr = fb + y * _stride + (x >> 3); + if (color) + *ptr &= ~(((uint8_t)0x80) >> (x & 0x07)); + else + *ptr |= (((uint8_t)0x80) >> (x & 0x07)); +} + +/** + * \brief Draws a line from (\a x1, \a y1) to (\a x2, \a y2) in \a color. + * + * \sa drawRect(), drawCircle() + */ +void Bitmap::drawLine(int x1, int y1, int x2, int y2, Color color) +{ + // Midpoint line scan-conversion algorithm from "Computer Graphics: + // Principles and Practice", Second Edition, Foley, van Dam, et al. + int dx = x2 - x1; + int dy = y2 - y1; + int xstep, ystep; + int d, incrE, incrNE; + if (dx < 0) { + xstep = -1; + dx = -dx; + } else { + xstep = 1; + } + if (dy < 0) { + ystep = -1; + dy = -dy; + } else { + ystep = 1; + } + if (dx >= dy) { + d = 2 * dy - dx; + incrE = 2 * dy; + incrNE = 2 * (dy - dx); + setPixel(x1, y1, color); + while (x1 != x2) { + if (d <= 0) { + d += incrE; + } else { + d += incrNE; + y1 += ystep; + } + x1 += xstep; + setPixel(x1, y1, color); + } + } else { + d = 2 * dx - dy; + incrE = 2 * dx; + incrNE = 2 * (dx - dy); + setPixel(x1, y1, color); + while (y1 != y2) { + if (d <= 0) { + d += incrE; + } else { + d += incrNE; + x1 += xstep; + } + y1 += ystep; + setPixel(x1, y1, color); + } + } +} + +/** + * \brief Draws a rectangle from (\a x1, \a y1) to (\a x2, \a y2), with the + * outline in \a borderColor and the interior filled with \a fillColor. + * + * If \a fillColor is \ref NoFill, then the interior is not filled. + * + * \sa drawFilledRect(), drawLine(), drawCircle(), fill() + */ +void Bitmap::drawRect(int x1, int y1, int x2, int y2, Color borderColor, Color fillColor) +{ + int temp; + if (x1 > x2) { + temp = x1; + x1 = x2; + x2 = temp; + } + if (y1 > y2) { + temp = y1; + y1 = y2; + y2 = temp; + } + if (fillColor == borderColor) { + fill(x1, y1, x2 - x1 + 1, y2 - y1 + 1, fillColor); + } else { + drawLine(x1, y1, x2, y1, borderColor); + if (y1 < y2) + drawLine(x2, y1 + 1, x2, y2, borderColor); + if (x1 < x2) + drawLine(x2 - 1, y2, x1, y2, borderColor); + if (y1 < (y2 - 1)) + drawLine(x1, y2 - 1, x1, y1 + 1, borderColor); + if (fillColor != NoFill) + fill(x1 + 1, y1 + 1, x2 - x1 - 1, y2 - y1 - 1, fillColor); + } +} + +/** + * \fn void Bitmap::drawFilledRect(int x1, int y1, int x2, int y2, Color color) + * \brief Draws a filled rectangle from (\a x1, \a y1) to (\a x2, \a y2) + * in \a color. + * + * This is a convenience function that is equivalent to + * drawRect(\a x1, \a y1, \a x2, \a y2, \a color, \a color). + * + * \sa drawRect(), drawFilledCircle() + */ + +/** + * \brief Draws a circle with a specific center (\a centerX, \a centerY) + * and \a radius, with the outline in \a borderColor and the interior + * filled with \a fillColor. + * + * If \a fillColor is \ref NoFill, then the interior is not filled. + * + * \sa drawFilledCircle(), drawLine(), drawRect() + */ +void Bitmap::drawCircle(int centerX, int centerY, int radius, Color borderColor, Color fillColor) +{ + // Midpoint circle scan-conversion algorithm using second-order + // differences from "Computer Graphics: Principles and Practice", + // Second Edition, Foley, van Dam, et al. + if (radius < 0) + radius = -radius; + int x = 0; + int y = radius; + int d = 1 - radius; + int deltaE = 3; + int deltaSE = 5 - 2 * radius; + drawCirclePoints(centerX, centerY, radius, x, y, borderColor, fillColor); + while (y > x) { + if (d < 0) { + d += deltaE; + deltaE += 2; + deltaSE += 2; + } else { + d += deltaSE; + deltaE += 2; + deltaSE += 4; + --y; + } + ++x; + drawCirclePoints(centerX, centerY, radius, x, y, borderColor, fillColor); + } +} + +/** + * \fn void Bitmap::drawFilledCircle(int centerX, int centerY, int radius, Color color) + * \brief Draws a filled circle with a specific center (\a centerX, \a centerY) + * and \a radius in \a color. + * + * This is a convenience function that is equivalent to + * drawCircle(\a centerX, \a centerY, \a radius, \a color, \a color). + * + * \sa drawCircle(), drawFilledRect() + */ + +/** + * \brief Draws \a bitmap at (\a x, \a y) in \a color. + * + * Bits that are set to \ref White in the \a bitmap are drawn with \a color. + * Bits that are set to \ref Black in the \a bitmap are drawn with the + * inverse of \a color. The pixel at (\a x, \a y) will be the top-left + * corner of the drawn image. + * + * Note: \a bitmap must not be the same as this object or the behaviour will + * be undefined. To copy a region of a bitmap to elsewhere within the + * same bitmap, use copy() instead. + * + * \sa drawInvertedBitmap(), copy() + */ +void Bitmap::drawBitmap(int x, int y, const Bitmap &bitmap, Color color) +{ + int w = bitmap.width(); + int s = bitmap.stride(); + int h = bitmap.height(); + Color invColor = !color; + for (uint8_t by = 0; by < h; ++by) { + const uint8_t *line = bitmap.data() + by * s; + uint8_t mask = 0x80; + uint8_t value = *line++; + for (uint8_t bx = 0; bx < w; ++bx) { + if (value & mask) + setPixel(x + bx, y + by, invColor); + else + setPixel(x + bx, y + by, color); + mask >>= 1; + if (!mask) { + mask = 0x80; + value = *line++; + } + } + } +} + +/** + * \brief Draws \a bitmap at (\a x, \a y) in \a color. + * + * The \a bitmap must point to program memory. The first two bytes are the + * width and height of the bitmap in pixels. The rest of the data contains + * the pixels for the bitmap, with lines byte-aligned. + * + * Bits that are 1 in the \a bitmap are drawn with \a color. Bits that are + * 0 in the \a bitmap are drawn with the inverse of \a color. The pixel at + * (\a x, \a y) will be the top-left corner of the drawn image. + * + * \sa drawInvertedBitmap(), fill() + */ +void Bitmap::drawBitmap(int x, int y, const prog_uint8_t *bitmap, Color color) +{ + uint8_t w = pgm_read_byte(bitmap); + uint8_t s = (w + 7) >> 3; + uint8_t h = pgm_read_byte(bitmap + 1); + Color invColor = !color; + for (uint8_t by = 0; by < h; ++by) { + const prog_uint8_t *line = bitmap + 2 + by * s; + uint8_t mask = 0x80; + uint8_t value = pgm_read_byte(line); + for (uint8_t bx = 0; bx < w; ++bx) { + if (value & mask) + setPixel(x + bx, y + by, color); + else + setPixel(x + bx, y + by, invColor); + mask >>= 1; + if (!mask) { + mask = 0x80; + ++line; + value = pgm_read_byte(line); + } + } + } +} + +/** + * \fn void Bitmap::drawInvertedBitmap(int x, int y, const Bitmap &bitmap) + * \brief Draws \a bitmap at (\a x, \a y) in inverted colors. + * + * This is a convenience function that is equivalent to + * drawBitmap(\a x, \a y, \a bitmap, \ref Black). + * + * \sa drawBitmap() + */ + +/** + * \fn void Bitmap::drawInvertedBitmap(int x, int y, const prog_uint8_t *bitmap) + * \brief Draws \a bitmap at (\a x, \a y) in inverted colors. + * + * This is a convenience function that is equivalent to + * drawBitmap(\a x, \a y, \a bitmap, \ref Black). + * + * \sa drawBitmap() + */ + +/** + * \fn const prog_uint8_t *Bitmap::font() const + * \brief Returns the currently selected font, or null if none selected. + * + * \sa setFont(), drawText(), drawChar(), charWidth() + */ + +/** + * \fn void Bitmap::setFont(const prog_uint8_t *font) + * \brief Sets the \a font for use with drawText() and drawChar(). + * + * \code + * #include + * + * display.setFont(DejaVuSans9); + * display.drawText(0, 0, "Hello"); + * \endcode + * + * New fonts can be generated with GLCDFontCreator2. + * + * \sa font(), drawText(), drawChar() + */ + +/** + * \fn Color Bitmap::textColor() const + * \brief Returns the color that will be used for drawing text with + * drawText() and drawChar(). The default is \ref White. + * + * \sa setTextColor(), drawText(), drawChar() + */ + +/** + * \fn void Bitmap::setTextColor(Color textColor) + * \brief Sets the \a color that will be used for drawing text with + * drawText() and drawChar(). + * + * \sa textColor(), drawText(), drawChar() + */ + +#define fontIsFixed(font) (pgm_read_byte((font)) == 0 && \ + pgm_read_byte((font) + 1) == 0) +#define fontWidth(font) (pgm_read_byte((font) + 2)) +#define fontHeight(font) (pgm_read_byte((font) + 3)) +#define fontFirstChar(font) (pgm_read_byte((font) + 4)) +#define fontCharCount(font) (pgm_read_byte((font) + 5)) + +/** + * \brief Draws the \a len characters of \a str at (\a x, \a y). + * + * If \a len is less than zero, then the actual length of \a str will be used. + * + * The position (\a x, \a y) will be the upper-left pixel of the first + * character that is drawn. + * + * \sa drawChar(), textColor(), font() + */ +void Bitmap::drawText(int x, int y, const char *str, int len) +{ + if (!_font) + return; + uint8_t height = fontHeight(_font); + if (len < 0) + len = strlen(str); + while (len-- > 0) { + x += drawChar(x, y, *str++); + if (len > 0) { + fill(x, y, 1, height, !_textColor); + ++x; + } + if (x >= _width) + break; + } +} + +/** + * \brief Draws \a len characters starting at \a start from \a str to the + * screen at (\a x, \a y). + * + * If \a len is less than zero, then the actual length of \a str will be used. + * + * The position (\a x, \a y) will be the upper-left pixel of the first + * character that is drawn. + * + * \sa drawChar(), textColor(), font() + */ +void Bitmap::drawText(int x, int y, const String &str, int start, int len) +{ + if (!_font) + return; + uint8_t height = fontHeight(_font); + if (len < 0) + len = str.length() - start; + while (len-- > 0) { + x += drawChar(x, y, str[start++]); + if (len > 0) { + fill(x, y, 1, height, !_textColor); + ++x; + } + if (x >= _width) + break; + } +} + +/** + * \brief Draws a single character \a ch at (\a x, \a y). + * + * Returns the width of the character in pixels so that higher-order functions + * like drawText() can advance \a x to the location of the next character + * to be drawn. The width does not include inter-character spacing. + * + * The position (\a x, \a y) will be the upper-left pixel of the drawn + * character. + * + * \sa drawText(), textColor(), font(), charWidth() + */ +int Bitmap::drawChar(int x, int y, char ch) +{ + uint8_t height = fontHeight(_font); + if (ch == ' ') { + // Font may not have space, or it is zero-width. Calculate + // the real size and fill the space. + int spaceWidth = charWidth('n'); + fill(x, y, spaceWidth, height, !_textColor); + return spaceWidth; + } + uint8_t first = fontFirstChar(_font); + uint8_t count = fontCharCount(_font); + uint8_t index = (uint8_t)ch; + if (index < first || index >= (first + count)) + return 0; + index -= first; + uint8_t heightBytes = (height + 7) >> 3;; + uint8_t width; + const prog_uint8_t *image; + if (fontIsFixed(_font)) { + // Fixed-width font. + width = fontWidth(_font); + image = _font + 6 + index * heightBytes * width; + } else { + // Variable-width font. + width = pgm_read_byte(_font + 6 + index); + image = _font + 6 + count; + for (uint8_t temp = 0; temp < index; ++temp) { + // Scan through all previous characters to find the starting + // location for this one. + image += pgm_read_byte(_font + 6 + temp) * heightBytes; + } + } + if ((x + width) <= 0 || (y + height) <= 0) + return width; // Character is off the top or left of the screen. + Color invColor = !_textColor; + for (uint8_t cx = 0; cx < width; ++cx) { + for (uint8_t cy = 0; cy < heightBytes; ++cy) { + uint8_t value = pgm_read_byte(image + cy * width + cx); + int posn; + if (heightBytes > 1 && cy == (heightBytes - 1)) + posn = height - 8; + else + posn = cy * 8; + for (uint8_t bit = 0; bit < 8; ++bit) { + if ((posn + bit) >= (cy * 8) && (posn + bit) <= height) { + if (value & 0x01) + setPixel(x + cx, y + posn + bit, _textColor); + else + setPixel(x + cx, y + posn + bit, invColor); + } + value >>= 1; + } + } + } + return width; +} + +/** + * \brief Returns the width in pixels of \a ch in the current font(). + * + * Returns zero if font() is not set, or \a ch is not present in font(). + * + * \sa drawChar(), font(), textWidth(), textHeight() + */ +int Bitmap::charWidth(char ch) const +{ + uint8_t index = (uint8_t)ch; + if (!_font) + return 0; + uint8_t first = fontFirstChar(_font); + uint8_t count = fontCharCount(_font); + if (index == ' ') + index = 'n'; // In case the font does not contain space. + if (index < first || index >= (first + count)) + return 0; + if (fontIsFixed(_font)) + return fontWidth(_font); + else + return pgm_read_byte(_font + 6 + (index - first)); +} + +/** + * \brief Returns the width in pixels of the \a len characters of \a str + * in the current font(), including inter-character spacing. + * + * If \a len is less than zero, then the actual length of \a str will be used. + * + * \sa drawText(), charWidth(), textHeight() + */ +int Bitmap::textWidth(const char *str, int len) const +{ + int width = 0; + if (len < 0) + len = strlen(str); + while (len-- > 0) { + width += charWidth(*str++); + if (len > 0) + ++width; + } + return width; +} + +/** + * \brief Returns the width in pixels of the \a len characters of \a str + * in the current font(), starting at \a start, including inter-character + * spacing. + * + * If \a len is less than zero, then the actual length of \a str will be used. + * + * \sa drawText(), charWidth(), textHeight() + */ +int Bitmap::textWidth(const String &str, int start, int len) const +{ + int width = 0; + if (len < 0) + len = str.length() - start; + while (len-- > 0) { + width += charWidth(str[start++]); + if (len > 0) + ++width; + } + return width; +} + +/** + * \brief Returns the height in pixels of the current text drawing font(); + * or zero if font() is not set. + * + * \sa font(), charWidth(), textWidth() + */ +int Bitmap::textHeight() const +{ + if (_font) + return fontHeight(_font); + else + return 0; +} + +/** + * \brief Copies the \a width x \a height pixels starting at top-left + * corner (\a x, \a y) to (\a destX, \a destY) in the bitmap \a dest. + * + * The \a dest bitmap can be the same as this object, in which case the copy + * will be performed in a manner that correctly handles overlapping regions. + * + * If some part of the source region is outside the bounds of this object, + * then the value \ref Black will be copied to \a dest for those pixels. + * This can be used to produce a behaviour similar to scroll() when + * \a bitmap is the same as this object. + * + * \sa drawBitmap(), fill(), scroll() + */ +void Bitmap::copy(int x, int y, int width, int height, Bitmap *dest, int destX, int destY) +{ + if (dest == this) { + // Copying to within the same bitmap, so copy in a direction + // that will prevent problems with overlap. + blit(x, y, x + width - 1, y + height - 1, destX, destY); + } else { + // Copying to a different bitmap. + while (height > 0) { + for (int tempx = 0; tempx < width; ++tempx) + dest->setPixel(destX + tempx, destY, pixel(x + tempx, y)); + ++y; + ++destY; + --height; + } + } +} + +/** + * \brief Fills the \a width x \a height pixels starting at top-left + * corner (\a x, \a y) with \a color. + * + * \sa copy(), clear(), invert(), drawRect() + */ +void Bitmap::fill(int x, int y, int width, int height, Color color) +{ + while (height > 0) { + for (int temp = 0; temp < width; ++temp) + setPixel(x + temp, y, color); + ++y; + --height; + } +} + +/** + * \brief Fills the \a width x \a height pixels starting at top-left + * corner (\a x, \a y) with the contents of \a pattern. + * + * The \a pattern must point to program memory. The first two bytes are the + * width and height of the pattern in pixels. The rest of the data contains + * the pixels for the pattern, with lines byte-aligned. + * + * Bits that are 1 in the \a pattern are drawn with \a color. Bits that are + * 0 in the \a pattern are drawn with the inverse of \a color. + * + * \sa drawBitmap(), clear(), invert() + */ +void Bitmap::fill(int x, int y, int width, int height, const prog_uint8_t *pattern, Color color) +{ + uint8_t w = pgm_read_byte(pattern); + uint8_t s = (w + 7) >> 3; + uint8_t h = pgm_read_byte(pattern + 1); + if (!w || !h) + return; + Color invColor = !color; + for (int tempy = 0; tempy < height; ++tempy) { + const prog_uint8_t *startLine = pattern + 2 + (tempy % h) * s; + const prog_uint8_t *line = startLine; + uint8_t mask = 0x80; + uint8_t value = pgm_read_byte(line++); + int bit = 0; + for (int tempx = 0; tempx < width; ++tempx) { + if (value & mask) + setPixel(x + tempx, y + tempy, color); + else + setPixel(x + tempx, y + tempy, invColor); + if (++bit >= w) { + mask = 0x80; + line = startLine; + value = pgm_read_byte(line++); + bit = 0; + } else { + mask >>= 1; + if (!mask) { + mask = 0x80; + value = pgm_read_byte(line++); + } + } + } + } +} + +/** + * \fn void Bitmap::scroll(int dx, int dy, Color fillColor) + * \brief Scrolls the entire contents of the bitmap by \a dx and \a dy. + * + * If \a dx is 2 and \a dy is -1, then the region will be scrolled two + * pixels to the right and one pixel up. Pixels that are uncovered + * by the scroll are filled with \a fillColor. + * + * \sa copy(), fill() + */ + +/** + * \brief Scrolls the \a width x \a height pixels starting at top-left + * corner (\a x, \a y) by \a dx and \a dy. + * + * If \a dx is 2 and \a dy is -1, then the region will be scrolled two + * pixels to the right and one pixel up. Pixels that are uncovered + * by the scroll are filled with \a fillColor. + * + * \sa copy(), fill() + */ +void Bitmap::scroll(int x, int y, int width, int height, int dx, int dy, Color fillColor) +{ + // Bail out if no scrolling at all. + if (!dx && !dy) + return; + + // Clamp the scroll region to the extents of the bitmap. + if (x < 0) { + width += x; + x = 0; + } + if (y < 0) { + height += y; + y = 0; + } + if ((x + width) > _width) + width = _width - x; + if ((y + height) > _height) + height = _height - y; + if (width <= 0 || height <= 0) + return; + + // Scroll the region in the specified direction. + if (dy < 0) { + if (dx < 0) + blit(x - dx, y - dy, x + width - 1 + dx, y + height - 1 + dy, x, y); + else + blit(x, y - dy, x + width - 1 - dx, y + height - 1 + dy, x + dx, y); + } else { + if (dx < 0) + blit(x - dx, y, x + width - 1 + dx, y + height - 1 - dy, x, y + dy); + else + blit(x, y, x + width - 1 - dx, y + height - 1 - dy, x + dx, y + dy); + } + + // Fill the pixels that were uncovered by the scroll. + if (dy < 0) { + fill(x, y + height + dy, width, -dy, fillColor); + if (dx < 0) + fill(x + width + dx, y, -dx, height + dy, fillColor); + else if (dx > 0) + fill(x, y, dx, height + dy, fillColor); + } else if (dy > 0) { + fill(x, y, width, -dy, fillColor); + if (dx < 0) + fill(x + width + dx, y + dy, -dx, height - dy, fillColor); + else if (dx > 0) + fill(x, y + dy, dx, height - dy, fillColor); + } else if (dx < 0) { + fill(x + width + dx, y, -dx, height, fillColor); + } else if (dx > 0) { + fill(x, y, dx, height, fillColor); + } +} + +/** + * \brief Inverts the \a width x \a height pixels starting at top-left + * corner (\a x, \a y). + * + * \sa fill() + */ +void Bitmap::invert(int x, int y, int width, int height) +{ + while (height > 0) { + for (int tempx = x + width - 1; tempx >= x; --tempx) + setPixel(tempx, y, !pixel(tempx, y)); + --height; + ++y; + } +} + +void Bitmap::blit(int x1, int y1, int x2, int y2, int x3, int y3) +{ + if (y3 < y1 || (y1 == y3 && x3 <= x1)) { + for (int tempy = y1; tempy <= y2; ++tempy) { + int y = y1 - tempy + y3; + int x = x3 - x1; + for (int tempx = x1; tempx <= x2; ++tempx) + setPixel(x + tempx, y, pixel(tempx, tempy)); + } + } else { + for (int tempy = y2; tempy >= y1; --tempy) { + int y = y1 - tempy + y3; + int x = x3 - x1; + for (int tempx = x2; tempx >= x1; --tempx) + setPixel(x + tempx, y, pixel(tempx, tempy)); + } + } +} + +void Bitmap::drawCirclePoints(int centerX, int centerY, int radius, int x, int y, Color borderColor, Color fillColor) +{ + if (x != y) { + setPixel(centerX + x, centerY + y, borderColor); + setPixel(centerX + y, centerY + x, borderColor); + setPixel(centerX + y, centerY - x, borderColor); + setPixel(centerX + x, centerY - y, borderColor); + setPixel(centerX - x, centerY - y, borderColor); + setPixel(centerX - y, centerY - x, borderColor); + setPixel(centerX - y, centerY + x, borderColor); + setPixel(centerX - x, centerY + y, borderColor); + if (fillColor != NoFill) { + if (radius > 1) { + drawLine(centerX - x + 1, centerY + y, centerX + x - 1, centerY + y, fillColor); + drawLine(centerX - y + 1, centerY + x, centerX + y - 1, centerY + x, fillColor); + drawLine(centerX - x + 1, centerY - y, centerX + x - 1, centerY - y, fillColor); + drawLine(centerX - y + 1, centerY - x, centerX + y - 1, centerY - x, fillColor); + } else if (radius == 1) { + setPixel(centerX, centerY, fillColor); + } + } + } else { + setPixel(centerX + x, centerY + y, borderColor); + setPixel(centerX + y, centerY - x, borderColor); + setPixel(centerX - x, centerY - y, borderColor); + setPixel(centerX - y, centerY + x, borderColor); + if (fillColor != NoFill) { + if (radius > 1) { + drawLine(centerX - x + 1, centerY + y, centerX + x - 1, centerY + y, fillColor); + drawLine(centerX - x + 1, centerY - y, centerX + x - 1, centerY - y, fillColor); + } else if (radius == 1) { + setPixel(centerX, centerY, fillColor); + } + } + } +} diff --git a/libraries/DMD/Bitmap.h b/libraries/DMD/Bitmap.h new file mode 100644 index 00000000..f2be2f0f --- /dev/null +++ b/libraries/DMD/Bitmap.h @@ -0,0 +1,138 @@ +/* + * 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. + */ + +#ifndef Bitmap_h +#define Bitmap_h + +#include +#include + +class DMD; +class String; + +class Bitmap +{ +public: + Bitmap(int width, int height); + ~Bitmap(); + + bool isValid() const { return fb != 0; } + + typedef uint8_t Color; + + static const Color Black = 0; + static const Color White = 1; + static const Color NoFill = 2; + + int width() const { return _width; } + int height() const { return _height; } + int stride() const { return _stride; } + int bitsPerPixel() const { return 1; } + + uint8_t *data() { return fb; } + const uint8_t *data() const { return fb; } + + void clear(Color color = Black); + + Color pixel(int x, int y) const; + void setPixel(int x, int y, Color color); + + void drawLine(int x1, int y1, int x2, int y2, Color color = White); + void drawRect(int x1, int y1, int x2, int y2, Color borderColor = White, Color fillColor = NoFill); + void drawFilledRect(int x1, int y1, int x2, int y2, Color color = White); + void drawCircle(int centerX, int centerY, int radius, Color borderColor = White, Color fillColor = NoFill); + void drawFilledCircle(int centerX, int centerY, int radius, Color color = White); + + void drawBitmap(int x, int y, const Bitmap &bitmap, Color color = White); + void drawBitmap(int x, int y, const prog_uint8_t *bitmap, Color color = White); + void drawInvertedBitmap(int x, int y, const Bitmap &bitmap); + void drawInvertedBitmap(int x, int y, const prog_uint8_t *bitmap); + + const prog_uint8_t *font() const { return _font; } + void setFont(const prog_uint8_t *font) { _font = font; } + + Color textColor() const { return _textColor; } + void setTextColor(Color color) { _textColor = color; } + + void drawText(int x, int y, const char *str, int len = -1); + void drawText(int x, int y, const String &str, int start = 0, int len = -1); + + int drawChar(int x, int y, char ch); + + int charWidth(char ch) const; + int textWidth(const char *str, int len = -1) const; + int textWidth(const String &str, int start = 0, int len = -1) const; + int textHeight() const; + + void copy(int x, int y, int width, int height, Bitmap *dest, int destX, int destY); + void fill(int x, int y, int width, int height, Color color); + void fill(int x, int y, int width, int height, const prog_uint8_t *pattern, Color color = White); + + void scroll(int dx, int dy, Color fillColor = Black); + void scroll(int x, int y, int width, int height, int dx, int dy, Color fillColor = Black); + + void invert(int x, int y, int width, int height); + +private: + // Disable copy constructor and operator=(). + Bitmap(const Bitmap &) {} + Bitmap &operator=(const Bitmap &) { return *this; } + + int _width; + int _height; + int _stride; + uint8_t *fb; + const prog_uint8_t *_font; + Color _textColor; + + friend class DMD; + + void blit(int x1, int y1, int x2, int y2, int x3, int y3); + void drawCirclePoints(int centerX, int centerY, int radius, int x, int y, Color borderColor, Color fillColor); +}; + +inline void Bitmap::drawFilledRect(int x1, int y1, int x2, int y2, Color color) +{ + drawRect(x1, y1, x2, y2, color, color); +} + +inline void Bitmap::drawFilledCircle(int centerX, int centerY, int radius, Color color) +{ + drawCircle(centerX, centerY, radius, color, color); +} + +inline void Bitmap::drawInvertedBitmap(int x, int y, const Bitmap &bitmap) +{ + drawBitmap(x, y, bitmap, Black); +} + +inline void Bitmap::drawInvertedBitmap(int x, int y, const prog_uint8_t *bitmap) +{ + drawBitmap(x, y, bitmap, Black); +} + +inline void Bitmap::scroll(int dx, int dy, Color fillColor) +{ + scroll(0, 0, _width, _height, dx, dy, fillColor); +} + +#endif diff --git a/libraries/DMD/DMD.cpp b/libraries/DMD/DMD.cpp new file mode 100644 index 00000000..bd493b52 --- /dev/null +++ b/libraries/DMD/DMD.cpp @@ -0,0 +1,618 @@ +/* + * 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.h" +#if defined(ARDUINO) && ARDUINO >= 100 +#include +#else +#include +#endif +#include +#include +#include +#include +#include + +/** + * \class DMD DMD.h + * \brief Handle large dot matrix displays composed of LED's. + * + * This class is designed for use with + * 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 (for which this class + * always uses the constant \ref White regardless of the physical color). + * + * \section dmd_drawing Drawing + * + * DMD inherits from Bitmap so that any of the drawing functions in that + * class can be used to draw directly to dot matrix displays. The following + * example initializes a single display panel and draws a rectangle and a + * circle into it at setup time: + * + * \code + * #include + * + * DMD display; + * + * void setup() { + * display.drawRect(5, 2, 27, 13); + * display.drawCircle(16, 8, 4); + * } + * \endcode + * + * The display must be updated frequently from the application's main loop: + * + * \code + * void loop() { + * display.loop(); + * } + * \endcode + * + * \section dmd_interrupts Interrupt-driven display refresh + * + * The loop() method simplifies updating the display from the application's + * main loop but it can sometimes be inconvenient to arrange for it to be + * called regularly, especially if the application wishes to use + * delay() or delayMicroseconds(). + * + * DMD provides an asynchronous display update mechanism using Timer1 + * interrupts. The application turns on interrupts using enableTimer1() + * and then calls refresh() from the interrupt service routine: + * + * \code + * #include + * + * DMD display; + * + * ISR(TIMER1_OVF_vect) + * { + * display.refresh(); + * } + * + * void setup() { + * display.enableTimer1(); + * } + * \endcode + * + * DMD can also be used with third-party timer libraries such as + * TimerOne: + * + * \code + * #include + * #include + * + * DMD display; + * + * void refreshDisplay() + * { + * display.refresh(); + * } + * + * void setup() { + * Timer1.initialize(5000); + * Timer1.attachInterrupt(refreshDisplay); + * } + * \endcode + * + * \section dmd_double_buffer Double buffering + * + * When using interrupts, the system can sometimes exhibit "tearing" artifacts + * where half-finished images are displayed because an interrupt fired in + * the middle of a screen update. + * + * This problem can be alleviated using double buffering: all rendering is done + * to an off-screen buffer that is swapped onto the screen once it is ready + * for display. Rendering then switches to the other buffer that is now + * off-screen. The following example demonstrates this: + * + * \code + * #include + * + * DMD display; + * + * ISR(TIMER1_OVF_vect) + * { + * display.refresh(); + * } + * + * void setup() { + * display.setDoubleBuffer(true); + * display.enableTimer1(); + * } + * + * void loop() { + * updateDisplay(); + * display.swapBuffers(); + * delay(50); // Delay between frames. + * } + * + * void updateDisplay() { + * // Draw the new display contents into the off-screen buffer. + * display.clear(); + * ... + * } + * \endcode + * + * The downside of double buffering is that it uses twice as much main memory + * to manage the contents of the screen. + * + * \section dmd_multi Multiple panels + * + * Multiple panels can be daisy-chained together using ribbon cables. + * If there is a single row of panels, then they must be connected + * to the Arduino board as follows: + * + * \image html dmd-4x1.png + * + * If there are multiple rows of panels, then alternating rows are + * flipped upside-down so that the short ribbon cables provided by + * Freetronics reach (this technique is thanks to Chris Debenham; see + * http://www.adebenham.com/category/arduino/dmd/ for more details): + * + * \image html dmd-4x2.png + * + * This technique can be repeated for as many rows as required, with the + * bottom row always right-way-up: + * + * \image html dmd-4x3.png + * + * DMD automatically takes care of flipping the data for panels in the + * alternating rows. No special action is required by the user except + * to physically connect the panels as shown and to initialize the DMD + * class appropriately: + * + * \code + * #include + * + * DMD display(4, 2); // 4 panels wide, 2 panels high + * \endcode + */ + +// Pins on the DMD connector board. +#define DMD_PIN_PHASE_LSB 6 // A +#define DMD_PIN_PHASE_MSB 7 // B +#define DMD_PIN_LATCH 8 // SCLK +#define DMD_PIN_OUTPUT_ENABLE 9 // nOE +#define DMD_PIN_SPI_SS SS // SPI Slave Select +#define DMD_PIN_SPI_MOSI MOSI // SPI Master Out, Slave In (R) +#define DMD_PIN_SPI_MISO MISO // SPI Master In, Slave Out +#define DMD_PIN_SPI_SCK SCK // SPI Serial Clock (CLK) + +// Dimension information for the display. +#define DMD_NUM_COLUMNS 32 // Number of columns in a panel. +#define DMD_NUM_ROWS 16 // Number of rows in a panel. + +// Refresh times. +#define DMD_REFRESH_MS 5 +#define DMD_REFRESH_US 5000 + +/** + * \brief Constructs a new dot matrix display handler for a display that + * is \a widthPanels x \a heightPanels in size. + * + * Note: the parameters to this constructor are specified in panels, + * whereas width() and height() are specified in pixels. + * + * \sa width(), height() + */ +DMD::DMD(int widthPanels, int heightPanels) + : Bitmap(widthPanels * DMD_NUM_COLUMNS, heightPanels * DMD_NUM_ROWS) + , _doubleBuffer(false) + , phase(0) + , fb0(0) + , fb1(0) + , displayfb(0) + , lastRefresh(millis()) +{ + // Both rendering and display are to fb0 initially. + fb0 = displayfb = fb; + + // Initialize SPI to MSB-first, mode 0, clock divider = 2. + pinMode(DMD_PIN_SPI_SCK, OUTPUT); + pinMode(DMD_PIN_SPI_MOSI, OUTPUT); + pinMode(DMD_PIN_SPI_SS, OUTPUT); + digitalWrite(DMD_PIN_SPI_SCK, LOW); + digitalWrite(DMD_PIN_SPI_MOSI, LOW); + digitalWrite(DMD_PIN_SPI_SS, HIGH); + SPCR |= _BV(MSTR); + SPCR |= _BV(SPE); + SPCR &= ~(_BV(DORD)); // MSB-first + SPCR &= ~0x0C; // Mode 0 + SPCR &= ~0x03; // Clock divider rate 2 + SPSR |= 0x01; // MSB of clock divider rate + + // Initialize the DMD-specific pins. + pinMode(DMD_PIN_PHASE_LSB, OUTPUT); + pinMode(DMD_PIN_PHASE_MSB, OUTPUT); + pinMode(DMD_PIN_LATCH, OUTPUT); + pinMode(DMD_PIN_OUTPUT_ENABLE, OUTPUT); + digitalWrite(DMD_PIN_PHASE_LSB, LOW); + digitalWrite(DMD_PIN_PHASE_MSB, LOW); + digitalWrite(DMD_PIN_LATCH, LOW); + digitalWrite(DMD_PIN_OUTPUT_ENABLE, LOW); + digitalWrite(DMD_PIN_SPI_MOSI, HIGH); +} + +/** + * \brief Destroys this dot matrix display handler. + */ +DMD::~DMD() +{ + if (fb0) + free(fb0); + if (fb1) + free(fb1); + fb = 0; // Don't free the buffer again in the base class. +} + +/** + * \fn bool DMD::doubleBuffer() const + * \brief Returns true if the display is double-buffered; false if + * single-buffered. The default is false. + * + * \sa setDoubleBuffer(), swapBuffers(), refresh() + */ + +/** + * \brief Enables or disables double-buffering according to \a doubleBuffer. + * + * When double-buffering is enabled, rendering operations are sent to a + * memory buffer that isn't currently displayed on-screen. Once the + * application has completed the screen update, it calls swapBuffers() + * to display the current buffer and switch rendering to the other + * now invisible buffer. + * + * Double-buffering is recommended if refresh() is being called from an + * interrupt service routine, to prevent "tearing" artifacts that result + * from simultaneous update of a single shared buffer. + * + * This function will allocate memory for the extra buffer when + * \a doubleBuffer is true. If there is insufficient memory for the + * second screen buffer, then this class will revert to single-buffered mode. + * + * \sa doubleBuffer(), swapBuffers(), refresh() + */ +void DMD::setDoubleBuffer(bool doubleBuffer) +{ + if (doubleBuffer != _doubleBuffer) { + _doubleBuffer = doubleBuffer; + if (doubleBuffer) { + // Allocate a new back buffer. + unsigned int size = _stride * _height; + fb1 = (uint8_t *)malloc(size); + + // Clear the new back buffer and then switch to it, leaving + // the current contents of fb0 on the screen. + if (fb1) { + memset(fb1, 0xFF, size); + cli(); + fb = fb1; + displayfb = fb0; + sei(); + } else { + // Failed to allocate the memory, so revert to single-buffered. + _doubleBuffer = false; + } + } else if (fb1) { + // Disabling double-buffering, so forcibly switch to fb0. + cli(); + fb = fb0; + displayfb = fb0; + sei(); + + // Free the unnecessary buffer. + free(fb1); + fb1 = 0; + } + } +} + +/** + * \brief Swaps the buffers that are used for rendering to the display. + * + * When doubleBuffer() is false, this function does nothing. + * Otherwise the front and back rendering buffers are swapped. + * See the description of setDoubleBuffer() for more information. + * + * The new rendering back buffer will have undefined contents and will + * probably need to be re-inialized with clear() or fill() before + * drawing to it. The swapBuffersAndCopy() function can be used instead + * to preserve the screen contents from one frame to the next. + * + * \sa swapBuffersAndCopy(), setDoubleBuffer() + */ +void DMD::swapBuffers() +{ + if (_doubleBuffer) { + // Turn off interrupts while swapping buffers so that we don't + // accidentally try to refresh() in the middle of this code. + cli(); + if (fb == fb0) { + fb = fb1; + displayfb = fb0; + } else { + fb = fb0; + displayfb = fb1; + } + sei(); + } +} + +/** + * \brief Swaps the buffers that are used for rendering to the display + * and copies the former back buffer contents to the new back buffer. + * + * Normally when swapBuffers() is called, the new rendering back buffer + * will have undefined contents from two frames prior and must be cleared + * with clear() or fill() before writing new contents to it. + * This function instead copies the previous frame into the new + * rendering buffer so that it can be updated in-place. + * + * This function is useful if the screen does not change much from one + * frame to the next. If the screen changes a lot between frames, then it + * is usually better to explicitly clear() or fill() the new back buffer. + * + * \sa swapBuffers(), setDoubleBuffer() + */ +void DMD::swapBuffersAndCopy() +{ + swapBuffers(); + if (_doubleBuffer) + memcpy(fb, displayfb, _stride * _height); +} + +/** + * \brief Performs regular display refresh activities from the + * application's main loop. + * + * \code + * DMD display; + * + * void loop() { + * display.loop(); + * } + * \endcode + * + * If you are using a timer interrupt service routine, then call + * refresh() in response to the interrupt instead of calling loop(). + * + * \sa refresh() + */ +void DMD::loop() +{ + unsigned long currentTime = millis(); + if ((currentTime - lastRefresh) >= DMD_REFRESH_MS) { + lastRefresh = currentTime; + refresh(); + } +} + +// Send a single byte via SPI. +static inline void spiSend(byte value) +{ + SPDR = value; + while (!(SPSR & _BV(SPIF))) + ; // Wait for the transfer to complete. +} + +// Flip the bits in a byte. Table generated by genflip.c +static const uint8_t flipBits[256] PROGMEM = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, + 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, + 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, + 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, + 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, + 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, + 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, + 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, + 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, + 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, + 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, + 0x3F, 0xBF, 0x7F, 0xFF +}; + +/** + * \brief Refresh the display. + * + * This function must be called at least once every 5 milliseconds + * for smooth non-flickering update of the display. It is usually + * called by loop(), but can also be called in response to a + * timer interrupt. + * + * If this function is called from an interrupt service routine, + * then it is recommended that double-buffering be enabled with + * setDoubleBuffer() to prevent "tearing" artifacts that result + * from simultaneous update of a single shared buffer. + * + * \sa loop(), setDoubleBuffer(), enableTimer1() + */ +void DMD::refresh() +{ + // Bail out if there is a conflict on the SPI bus. + if (!digitalRead(DMD_PIN_SPI_SS)) + return; + + // Transfer the data for the next group of interleaved rows. + int stride4 = _stride * 4; + uint8_t *data0; + uint8_t *data1; + uint8_t *data2; + uint8_t *data3; + bool flipRow = ((_height & 0x10) == 0); + for (int y = 0; y < _height; y += 16) { + if (!flipRow) { + // The panels in this row are the right way up. + data0 = displayfb + _stride * (y + phase); + data1 = data0 + stride4; + data2 = data1 + stride4; + data3 = data2 + stride4; + for (int x = _stride; x > 0; --x) { + spiSend(*data3++); + spiSend(*data2++); + spiSend(*data1++); + spiSend(*data0++); + } + flipRow = true; + } else { + // The panels in this row are upside-down and reversed. + data0 = displayfb + _stride * (y + 16 - phase) - 1; + data1 = data0 - stride4; + data2 = data1 - stride4; + data3 = data2 - stride4; + for (int x = _stride; x > 0; --x) { + spiSend(pgm_read_byte(&(flipBits[*data3--]))); + spiSend(pgm_read_byte(&(flipBits[*data2--]))); + spiSend(pgm_read_byte(&(flipBits[*data1--]))); + spiSend(pgm_read_byte(&(flipBits[*data0--]))); + } + flipRow = false; + } + } + + // Latch the data from the shift registers onto the actual display. + digitalWrite(DMD_PIN_OUTPUT_ENABLE, LOW); + digitalWrite(DMD_PIN_LATCH, HIGH); + digitalWrite(DMD_PIN_LATCH, LOW); + if (phase & 0x02) + digitalWrite(DMD_PIN_PHASE_MSB, HIGH); + else + digitalWrite(DMD_PIN_PHASE_MSB, LOW); + if (phase & 0x01) + digitalWrite(DMD_PIN_PHASE_LSB, HIGH); + else + digitalWrite(DMD_PIN_PHASE_LSB, LOW); + digitalWrite(DMD_PIN_OUTPUT_ENABLE, HIGH); + phase = (phase + 1) & 0x03; +} + +/** + * \brief Enables Timer1 overflow interrupts for updating this display. + * + * The application must also provide an interrupt service routine for + * Timer1 that calls refresh(): + * + * \code + * #include + * + * DMD display; + * + * ISR(TIMER1_OVF_vect) + * { + * display.refresh(); + * } + * + * void setup() { + * display.enableTimer1(); + * } + * \endcode + * + * If timer interrupts are being used to update the display, then it is + * unnecessary to call loop(). + * + * \sa refresh(), disableTimer1(), setDoubleBuffer() + */ +void DMD::enableTimer1() +{ + // Number of CPU cycles in the display's refresh period. + unsigned long numCycles = (F_CPU / 2000000) * DMD_REFRESH_US; + + // Determine the prescaler to be used. + #define TIMER1_RESOLUTION 65536UL + uint8_t prescaler; + if (numCycles < TIMER1_RESOLUTION) { + // No prescaling required. + prescaler = _BV(CS10); + } else if (numCycles < TIMER1_RESOLUTION * 8) { + // Prescaler = 8. + prescaler = _BV(CS11); + numCycles >>= 3; + } else if (numCycles < TIMER1_RESOLUTION * 64) { + // Prescaler = 64. + prescaler = _BV(CS11) | _BV(CS10); + numCycles >>= 6; + } else if (numCycles < TIMER1_RESOLUTION * 256) { + // Prescaler = 256. + prescaler = _BV(CS12); + numCycles >>= 8; + } else if (numCycles < TIMER1_RESOLUTION * 1024) { + // Prescaler = 1024. + prescaler = _BV(CS12) | _BV(CS10); + numCycles >>= 10; + } else { + // Too long, so set the maximum timeout. + prescaler = _BV(CS12) | _BV(CS10); + numCycles = TIMER1_RESOLUTION - 1; + } + + // Configure Timer1 for the period we want. + TCCR1A = 0; + TCCR1B = _BV(WGM13); + uint8_t saveSREG = SREG; + cli(); + ICR1 = numCycles; + SREG = saveSREG; // Implicit sei() if interrupts were on previously. + TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11) | _BV(CS10))) | prescaler; + + // Turn on the Timer1 overflow interrupt. + TIMSK1 |= _BV(TOIE1); +} + +/** + * \brief Disables Timer1 overflow interrupts. + * + * \sa enableTimer1() + */ +void DMD::disableTimer1() +{ + // Turn off the Timer1 overflow interrupt. + TIMSK1 &= ~_BV(TOIE1); +} + +/** + * \brief Converts an RGB value into a pixel color value. + * + * Returns \ref White if any of \a r, \a g, or \a b are non-zero; + * otherwise returns \ref Black. + * + * This function is provided for upwards compatibility with future + * displays that support full color. Monochrome applications should + * use the \ref Black and \ref White constants directly. + */ +DMD::Color DMD::fromRGB(uint8_t r, uint8_t g, uint8_t b) +{ + if (r || g || b) + return White; + else + return Black; +} diff --git a/libraries/DMD/DMD.h b/libraries/DMD/DMD.h new file mode 100644 index 00000000..1bc46570 --- /dev/null +++ b/libraries/DMD/DMD.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef DMD_h +#define DMD_h + +#include "Bitmap.h" + +class DMD : public Bitmap +{ +public: + explicit DMD(int widthPanels = 1, int heightPanels = 1); + ~DMD(); + + bool doubleBuffer() const { return _doubleBuffer; } + void setDoubleBuffer(bool doubleBuffer); + void swapBuffers(); + void swapBuffersAndCopy(); + + void loop(); + void refresh(); + + void enableTimer1(); + void disableTimer1(); + + static Color fromRGB(uint8_t r, uint8_t g, uint8_t b); + +private: + // Disable copy constructor and operator=(). + DMD(const DMD &other) : Bitmap(other) {} + DMD &operator=(const DMD &) { return *this; } + + bool _doubleBuffer; + uint8_t phase; + uint8_t *fb0; + uint8_t *fb1; + uint8_t *displayfb; + unsigned long lastRefresh; +}; + +#endif diff --git a/libraries/DMD/DejaVuSans9.h b/libraries/DMD/DejaVuSans9.h new file mode 100644 index 00000000..f1356dca --- /dev/null +++ b/libraries/DMD/DejaVuSans9.h @@ -0,0 +1,166 @@ + + +/* + * + * DejaVuSans9 + * + * created with FontCreator + * written by F. Maximilian Thiele + * + * http://www.apetech.de/fontCreator + * me@apetech.de + * + * File Name : DejaVuSans9.h + * Date : 28.05.2012 + * Font size in bytes : 3962 + * Font width : 10 + * Font height : 10 + * Font first char : 32 + * Font last char : 128 + * Font used chars : 96 + * + * The font data are defined as + * + * struct _FONT_ { + * uint16_t font_Size_in_Bytes_over_all_included_Size_it_self; + * uint8_t font_Width_in_Pixel_for_fixed_drawing; + * uint8_t font_Height_in_Pixel_for_all_characters; + * unit8_t font_First_Char; + * uint8_t font_Char_Count; + * + * uint8_t font_Char_Widths[font_Last_Char - font_First_Char +1]; + * // for each character the separate width in pixels, + * // characters < 128 have an implicit virtual right empty row + * + * uint8_t font_data[]; + * // bit field of all characters + */ + +#include +#include + +#ifndef DEJAVUSANS9_H +#define DEJAVUSANS9_H + +#define DEJAVUSANS9_WIDTH 10 +#define DEJAVUSANS9_HEIGHT 10 + +static uint8_t DejaVuSans9[] PROGMEM = { + 0x0F, 0x7A, // size + 0x0A, // width + 0x0A, // height + 0x20, // first char + 0x60, // char count + + // char widths + 0x00, 0x01, 0x03, 0x06, 0x05, 0x08, 0x06, 0x01, 0x02, 0x02, + 0x05, 0x05, 0x01, 0x02, 0x01, 0x03, 0x04, 0x03, 0x04, 0x04, + 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x06, 0x06, + 0x06, 0x04, 0x08, 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x05, + 0x05, 0x01, 0x02, 0x05, 0x04, 0x06, 0x05, 0x05, 0x04, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x06, 0x07, 0x06, 0x05, 0x05, 0x02, + 0x03, 0x02, 0x04, 0x05, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x03, 0x04, 0x04, 0x01, 0x02, 0x04, 0x01, 0x07, 0x04, 0x04, + 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x05, 0x07, 0x05, 0x05, + 0x04, 0x03, 0x01, 0x03, 0x06, 0x05, + + // font data + 0xBE, 0x00, // 33 + 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, // 34 + 0x28, 0xE8, 0x3E, 0xE8, 0x3E, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 35 + 0x98, 0x94, 0xFE, 0xA4, 0x64, 0x00, 0x00, 0x40, 0x00, 0x00, // 36 + 0x1E, 0x12, 0xDE, 0x30, 0x18, 0xF6, 0x90, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 37 + 0x60, 0x9C, 0x92, 0x62, 0xC4, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 38 + 0x06, 0x00, // 39 + 0x7E, 0x81, 0x00, 0x00, // 40 + 0xC3, 0x3C, 0x00, 0x00, // 41 + 0x12, 0x0C, 0x1E, 0x0C, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, // 42 + 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // 43 + 0x80, 0x40, // 44 + 0x20, 0x20, 0x00, 0x00, // 45 + 0x80, 0x00, // 46 + 0xC0, 0x38, 0x06, 0x00, 0x00, 0x00, // 47 + 0x7C, 0x82, 0x82, 0x7C, 0x00, 0x00, 0x00, 0x00, // 48 + 0x82, 0xFE, 0x80, 0x00, 0x00, 0x00, // 49 + 0xC4, 0xA2, 0x92, 0x8C, 0x00, 0x00, 0x00, 0x00, // 50 + 0x84, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00, // 51 + 0x60, 0x58, 0x44, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // 52 + 0x9E, 0x92, 0x92, 0x62, 0x00, 0x00, 0x00, 0x00, // 53 + 0x7C, 0x96, 0x92, 0x62, 0x00, 0x00, 0x00, 0x00, // 54 + 0x02, 0xC2, 0x3A, 0x06, 0x00, 0x00, 0x00, 0x00, // 55 + 0x6C, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00, // 56 + 0x9C, 0x92, 0xD2, 0x7C, 0x00, 0x00, 0x00, 0x00, // 57 + 0x88, 0x00, // 58 + 0x88, 0x40, // 59 + 0x20, 0x20, 0x50, 0x50, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 60 + 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 61 + 0x88, 0x50, 0x50, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 62 + 0x02, 0xB2, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, // 63 + 0x78, 0x84, 0x32, 0x4A, 0x4A, 0xFA, 0x44, 0x38, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, // 64 + 0xC0, 0x38, 0x26, 0x26, 0x38, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 65 + 0xFE, 0x92, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, // 66 + 0x7C, 0xC6, 0x82, 0x82, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, // 67 + 0xFE, 0x82, 0x82, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, // 68 + 0xFE, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, // 69 + 0xFE, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, // 70 + 0x7C, 0xC6, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, // 71 + 0xFE, 0x10, 0x10, 0x10, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, // 72 + 0xFE, 0x00, // 73 + 0x00, 0xFE, 0x80, 0x40, // 74 + 0xFE, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, // 75 + 0xFE, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, // 76 + 0xFE, 0x0C, 0x30, 0x30, 0x0C, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 77 + 0xFE, 0x0C, 0x10, 0x60, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, // 78 + 0x7C, 0xC6, 0x82, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, // 79 + 0xFE, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, // 80 + 0x7C, 0xC6, 0x82, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x40, 0x00, // 81 + 0xFE, 0x12, 0x32, 0x4E, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, // 82 + 0x4C, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, // 83 + 0x02, 0x02, 0xFE, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 84 + 0x7E, 0x80, 0x80, 0x80, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, // 85 + 0x06, 0x38, 0xC0, 0xC0, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 86 + 0x06, 0x38, 0xE0, 0x1E, 0xE0, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 87 + 0x82, 0x46, 0x38, 0x38, 0xC6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 88 + 0x02, 0x0C, 0xF0, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 89 + 0xC2, 0xA2, 0x92, 0x8A, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, // 90 + 0xFE, 0x02, 0x40, 0x40, // 91 + 0x06, 0x38, 0xC0, 0x00, 0x00, 0x00, // 92 + 0x02, 0xFE, 0x40, 0x40, // 93 + 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, // 94 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, // 95 + 0x01, 0x02, 0x00, 0x00, // 96 + 0xE0, 0xA8, 0xA8, 0xF8, 0x00, 0x00, 0x00, 0x00, // 97 + 0xFF, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, // 98 + 0x70, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, // 99 + 0x70, 0x88, 0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, // 100 + 0x70, 0xA8, 0xA8, 0xB0, 0x00, 0x00, 0x00, 0x00, // 101 + 0x08, 0xFF, 0x09, 0x00, 0x00, 0x00, // 102 + 0x70, 0x88, 0x88, 0xF8, 0x00, 0x80, 0x80, 0x40, // 103 + 0xFF, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, // 104 + 0xFA, 0x00, // 105 + 0x00, 0xFA, 0x80, 0xC0, // 106 + 0xFF, 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, // 107 + 0xFF, 0x00, // 108 + 0xF8, 0x08, 0x08, 0xF8, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 109 + 0xF8, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, // 110 + 0x70, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, // 111 + 0xF8, 0x88, 0x88, 0x70, 0xC0, 0x00, 0x00, 0x00, // 112 + 0x70, 0x88, 0x88, 0xF8, 0x00, 0x00, 0x00, 0xC0, // 113 + 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, // 114 + 0x98, 0xA8, 0xE8, 0x00, 0x00, 0x00, // 115 + 0x08, 0xFC, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, // 116 + 0xF8, 0x80, 0x80, 0xF8, 0x00, 0x00, 0x00, 0x00, // 117 + 0x18, 0x60, 0x80, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // 118 + 0x38, 0xC0, 0x30, 0x08, 0x30, 0xC0, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 119 + 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 + 0x18, 0x60, 0x80, 0x60, 0x18, 0x80, 0x80, 0x40, 0x00, 0x00, // 121 + 0x88, 0xC8, 0xA8, 0x98, 0x00, 0x00, 0x00, 0x00, // 122 + 0x10, 0xEE, 0x02, 0x00, 0x40, 0x40, // 123 + 0xFE, 0xC0, // 124 + 0x02, 0xEE, 0x10, 0x40, 0x40, 0x00, // 125 + 0x20, 0x10, 0x10, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 126 + 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xC0, 0x80, 0x80, 0x80, 0xC0 // 127 + +}; + +#endif diff --git a/libraries/DMD/DejaVuSansBold9.h b/libraries/DMD/DejaVuSansBold9.h new file mode 100644 index 00000000..3c139bdd --- /dev/null +++ b/libraries/DMD/DejaVuSansBold9.h @@ -0,0 +1,166 @@ + + +/* + * + * DejaVuSansBold9 + * + * created with FontCreator + * written by F. Maximilian Thiele + * + * http://www.apetech.de/fontCreator + * me@apetech.de + * + * File Name : DejaVuSansBold9.h + * Date : 28.05.2012 + * Font size in bytes : 4662 + * Font width : 10 + * Font height : 10 + * Font first char : 32 + * Font last char : 128 + * Font used chars : 96 + * + * The font data are defined as + * + * struct _FONT_ { + * uint16_t font_Size_in_Bytes_over_all_included_Size_it_self; + * uint8_t font_Width_in_Pixel_for_fixed_drawing; + * uint8_t font_Height_in_Pixel_for_all_characters; + * unit8_t font_First_Char; + * uint8_t font_Char_Count; + * + * uint8_t font_Char_Widths[font_Last_Char - font_First_Char +1]; + * // for each character the separate width in pixels, + * // characters < 128 have an implicit virtual right empty row + * + * uint8_t font_data[]; + * // bit field of all characters + */ + +#include +#include + +#ifndef DEJAVUSANSBOLD9_H +#define DEJAVUSANSBOLD9_H + +#define DEJAVUSANSBOLD9_WIDTH 10 +#define DEJAVUSANSBOLD9_HEIGHT 10 + +static uint8_t DejaVuSansBold9[] PROGMEM = { + 0x12, 0x36, // size + 0x0A, // width + 0x0A, // height + 0x20, // first char + 0x60, // char count + + // char widths + 0x00, 0x02, 0x03, 0x06, 0x05, 0x08, 0x07, 0x01, 0x03, 0x03, + 0x05, 0x05, 0x02, 0x03, 0x02, 0x03, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02, 0x02, 0x06, 0x06, + 0x06, 0x04, 0x08, 0x07, 0x05, 0x06, 0x06, 0x05, 0x05, 0x06, + 0x07, 0x02, 0x03, 0x06, 0x05, 0x07, 0x06, 0x06, 0x05, 0x06, + 0x06, 0x05, 0x06, 0x06, 0x07, 0x09, 0x07, 0x06, 0x06, 0x03, + 0x03, 0x03, 0x04, 0x05, 0x02, 0x05, 0x05, 0x04, 0x05, 0x05, + 0x04, 0x05, 0x05, 0x02, 0x03, 0x05, 0x02, 0x08, 0x05, 0x05, + 0x05, 0x05, 0x03, 0x04, 0x03, 0x05, 0x06, 0x08, 0x06, 0x06, + 0x04, 0x04, 0x01, 0x04, 0x06, 0x05, + + // font data + 0xDE, 0xDE, 0x00, 0x00, // 33 + 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, // 34 + 0x28, 0xF8, 0x2E, 0xF8, 0x2E, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 35 + 0x98, 0xB4, 0xFE, 0xB4, 0x64, 0x00, 0x00, 0x40, 0x00, 0x00, // 36 + 0x0C, 0x12, 0xD2, 0x7C, 0x78, 0x96, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 37 + 0x60, 0xFC, 0x9E, 0xB2, 0x62, 0xE0, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 38 + 0x06, 0x00, // 39 + 0x3C, 0xFF, 0x81, 0x00, 0x00, 0x00, // 40 + 0x81, 0xFF, 0x3C, 0x00, 0x00, 0x00, // 41 + 0x14, 0x18, 0x3E, 0x18, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, // 42 + 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // 43 + 0xC0, 0xC0, 0x40, 0x00, // 44 + 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, // 45 + 0xC0, 0xC0, 0x00, 0x00, // 46 + 0xC0, 0x38, 0x06, 0x00, 0x00, 0x00, // 47 + 0x7C, 0xFE, 0x82, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, // 48 + 0x82, 0x82, 0xFE, 0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, // 49 + 0xC2, 0xE2, 0xB2, 0x9E, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, // 50 + 0x82, 0x92, 0x92, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, // 51 + 0x60, 0x58, 0x44, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, // 52 + 0x9E, 0x9E, 0x92, 0xF2, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // 53 + 0x7C, 0xFE, 0x96, 0xF2, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, // 54 + 0x82, 0xE2, 0x7A, 0x1E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, // 55 + 0x6C, 0xEE, 0x92, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, // 56 + 0x8C, 0x9E, 0xD2, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, // 57 + 0xD8, 0xD8, 0x00, 0x00, // 58 + 0xD8, 0xD8, 0x40, 0x00, // 59 + 0x20, 0x50, 0x50, 0x50, 0xD8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 60 + 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 61 + 0x88, 0xD8, 0x50, 0x50, 0x50, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 62 + 0x02, 0xDA, 0xDE, 0x0E, 0x00, 0x00, 0x00, 0x00, // 63 + 0x78, 0x84, 0x32, 0x4A, 0x4A, 0xFA, 0x44, 0x38, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, // 64 + 0x80, 0xF0, 0x7E, 0x4E, 0x7E, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 65 + 0xFE, 0xFE, 0x92, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, // 66 + 0x38, 0x7C, 0xC6, 0x82, 0x82, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 67 + 0xFE, 0xFE, 0x82, 0x82, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 68 + 0xFE, 0xFE, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, // 69 + 0xFE, 0xFE, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, // 70 + 0x78, 0xFC, 0x86, 0x92, 0xF2, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 71 + 0xFE, 0xFE, 0x10, 0x10, 0x10, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 72 + 0xFE, 0xFE, 0x00, 0x00, // 73 + 0x00, 0xFE, 0xFE, 0x80, 0xC0, 0x40, // 74 + 0xFE, 0xFE, 0x38, 0x6C, 0xC6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 75 + 0xFE, 0xFE, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, // 76 + 0xFE, 0xFE, 0x0C, 0x30, 0x0C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 77 + 0xFE, 0xFE, 0x0C, 0x30, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 78 + 0x7C, 0xFE, 0x82, 0x82, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 79 + 0xFE, 0xFE, 0x12, 0x1E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, // 80 + 0x7C, 0xFE, 0x82, 0x82, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, // 81 + 0xFE, 0xFE, 0x12, 0x7E, 0xEC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 82 + 0xCC, 0x9E, 0x92, 0xF2, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, // 83 + 0x02, 0x02, 0xFE, 0xFE, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 84 + 0x7E, 0xFE, 0x80, 0x80, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 85 + 0x02, 0x1E, 0xF8, 0xC0, 0xF8, 0x1E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 86 + 0x0E, 0xFE, 0xE0, 0x3C, 0x06, 0x3C, 0xE0, 0xFE, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 87 + 0x82, 0xC6, 0x7C, 0x10, 0x7C, 0xC6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 88 + 0x06, 0x0E, 0xF8, 0xF8, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89 + 0xC2, 0xE2, 0xB2, 0x9A, 0x8E, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 90 + 0xFF, 0xFF, 0x81, 0x00, 0x00, 0x00, // 91 + 0x06, 0x38, 0xC0, 0x00, 0x00, 0x00, // 92 + 0x81, 0xFF, 0xFF, 0x00, 0x00, 0x00, // 93 + 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, // 94 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, // 95 + 0x01, 0x02, 0x00, 0x00, // 96 + 0xE8, 0xE8, 0xA8, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, // 97 + 0xFF, 0xFF, 0x88, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, // 98 + 0x70, 0xF8, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, // 99 + 0x70, 0xF8, 0x88, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, // 100 + 0x70, 0xF8, 0xA8, 0xB8, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, // 101 + 0x08, 0xFE, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, // 102 + 0x70, 0xF8, 0x88, 0xF8, 0xF8, 0x00, 0x80, 0x80, 0xC0, 0x40, // 103 + 0xFF, 0xFF, 0x08, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, // 104 + 0xFB, 0xFB, 0x00, 0x00, // 105 + 0x00, 0xFB, 0xFB, 0x80, 0xC0, 0x40, // 106 + 0xFF, 0xFF, 0x70, 0xD8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, // 107 + 0xFF, 0xFF, 0x00, 0x00, // 108 + 0xF8, 0xF8, 0x08, 0xF8, 0xF8, 0x08, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 109 + 0xF8, 0xF8, 0x08, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, // 110 + 0x70, 0xF8, 0x88, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, // 111 + 0xF8, 0xF8, 0x88, 0xF8, 0x70, 0xC0, 0xC0, 0x00, 0x00, 0x00, // 112 + 0x70, 0xF8, 0x88, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xC0, 0xC0, // 113 + 0xF8, 0xF8, 0x08, 0x00, 0x00, 0x00, // 114 + 0xB0, 0xB8, 0xE8, 0x68, 0x00, 0x00, 0x00, 0x00, // 115 + 0xFC, 0xFC, 0x88, 0x00, 0x00, 0x00, // 116 + 0xF8, 0xF8, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, // 117 + 0x18, 0x78, 0xC0, 0xC0, 0x78, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 118 + 0x18, 0xF8, 0xE0, 0x38, 0x38, 0xE0, 0xF8, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 119 + 0x88, 0xD8, 0x70, 0x70, 0xD8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 + 0x08, 0x38, 0xE0, 0xE0, 0x38, 0x08, 0x00, 0x80, 0xC0, 0x00, 0x00, 0x00, // 121 + 0xC8, 0xE8, 0xB8, 0x98, 0x00, 0x00, 0x00, 0x00, // 122 + 0x08, 0xFF, 0xF7, 0x81, 0x00, 0x00, 0x00, 0x00, // 123 + 0xFE, 0xC0, // 124 + 0x81, 0xF7, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, // 125 + 0x20, 0x10, 0x10, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 126 + 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xC0, 0x80, 0x80, 0x80, 0xC0 // 127 + +}; + +#endif diff --git a/libraries/DMD/DejaVuSansItalic9.h b/libraries/DMD/DejaVuSansItalic9.h new file mode 100644 index 00000000..97c42008 --- /dev/null +++ b/libraries/DMD/DejaVuSansItalic9.h @@ -0,0 +1,166 @@ + + +/* + * + * DejaVuSansItalic9 + * + * created with FontCreator + * written by F. Maximilian Thiele + * + * http://www.apetech.de/fontCreator + * me@apetech.de + * + * File Name : DejaVuSansItalic9.h + * Date : 28.05.2012 + * Font size in bytes : 4572 + * Font width : 10 + * Font height : 10 + * Font first char : 32 + * Font last char : 128 + * Font used chars : 96 + * + * The font data are defined as + * + * struct _FONT_ { + * uint16_t font_Size_in_Bytes_over_all_included_Size_it_self; + * uint8_t font_Width_in_Pixel_for_fixed_drawing; + * uint8_t font_Height_in_Pixel_for_all_characters; + * unit8_t font_First_Char; + * uint8_t font_Char_Count; + * + * uint8_t font_Char_Widths[font_Last_Char - font_First_Char +1]; + * // for each character the separate width in pixels, + * // characters < 128 have an implicit virtual right empty row + * + * uint8_t font_data[]; + * // bit field of all characters + */ + +#include +#include + +#ifndef DEJAVUSANSITALIC9_H +#define DEJAVUSANSITALIC9_H + +#define DEJAVUSANSITALIC9_WIDTH 10 +#define DEJAVUSANSITALIC9_HEIGHT 10 + +static uint8_t DejaVuSansItalic9[] PROGMEM = { + 0x11, 0xDC, // size + 0x0A, // width + 0x0A, // height + 0x20, // first char + 0x60, // char count + + // char widths + 0x00, 0x03, 0x03, 0x06, 0x04, 0x07, 0x06, 0x01, 0x03, 0x03, + 0x05, 0x05, 0x01, 0x03, 0x01, 0x03, 0x05, 0x04, 0x05, 0x05, + 0x05, 0x05, 0x04, 0x05, 0x05, 0x05, 0x02, 0x02, 0x06, 0x06, + 0x06, 0x04, 0x08, 0x06, 0x05, 0x06, 0x06, 0x05, 0x05, 0x06, + 0x07, 0x03, 0x03, 0x06, 0x04, 0x08, 0x07, 0x06, 0x05, 0x06, + 0x05, 0x06, 0x05, 0x06, 0x05, 0x08, 0x06, 0x05, 0x06, 0x04, + 0x02, 0x04, 0x04, 0x05, 0x02, 0x05, 0x05, 0x04, 0x06, 0x05, + 0x03, 0x05, 0x05, 0x03, 0x03, 0x05, 0x03, 0x08, 0x05, 0x05, + 0x05, 0x05, 0x04, 0x04, 0x03, 0x05, 0x05, 0x07, 0x05, 0x05, + 0x05, 0x04, 0x01, 0x05, 0x06, 0x05, + + // font data + 0x80, 0x38, 0x06, 0x00, 0x00, 0x00, // 33 + 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, // 34 + 0x20, 0xF8, 0x2E, 0xF8, 0x2E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 35 + 0x98, 0xDC, 0xA6, 0x64, 0x00, 0x40, 0x00, 0x00, // 36 + 0x1C, 0xD2, 0x2E, 0x10, 0xEC, 0x92, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 37 + 0x60, 0x9C, 0x92, 0xA2, 0x64, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 38 + 0x06, 0x00, // 39 + 0xF8, 0x06, 0x01, 0x00, 0x00, 0x00, // 40 + 0x80, 0x61, 0x1E, 0x00, 0x00, 0x00, // 41 + 0x12, 0x0C, 0x1E, 0x0C, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, // 42 + 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // 43 + 0x80, 0x00, // 44 + 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, // 45 + 0x80, 0x00, // 46 + 0x60, 0x30, 0x0C, 0x00, 0x00, 0x00, // 47 + 0x78, 0x84, 0x82, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, // 48 + 0x80, 0x82, 0xF2, 0x8E, 0x00, 0x00, 0x00, 0x00, // 49 + 0x80, 0xC4, 0xA2, 0x92, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, // 50 + 0x40, 0x84, 0x92, 0x92, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, // 51 + 0x40, 0x70, 0xC8, 0x7C, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, // 52 + 0x80, 0x9C, 0x92, 0x92, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, // 53 + 0x78, 0x94, 0x92, 0x72, 0x00, 0x00, 0x00, 0x00, // 54 + 0x82, 0x42, 0x32, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 55 + 0x60, 0xAC, 0x92, 0x92, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, // 56 + 0x80, 0x9C, 0x92, 0x72, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, // 57 + 0x80, 0x08, 0x00, 0x00, // 58 + 0x80, 0x08, 0x00, 0x00, // 59 + 0x20, 0x20, 0x50, 0x50, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 60 + 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 61 + 0x88, 0x50, 0x50, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 62 + 0x82, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, // 63 + 0xE0, 0x18, 0xE8, 0x94, 0x94, 0xF4, 0xCC, 0x78, 0x40, 0xC0, 0x80, 0x80, 0x80, 0x40, 0x00, 0x00, // 64 + 0x80, 0x60, 0x38, 0x24, 0x3E, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 65 + 0xC0, 0xB8, 0x96, 0x92, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, // 66 + 0x78, 0x84, 0x82, 0x82, 0x82, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 67 + 0xC0, 0xB8, 0x86, 0x82, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 68 + 0xC0, 0xB8, 0x96, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 69 + 0xC0, 0x38, 0x16, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 70 + 0x78, 0x84, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 71 + 0xC0, 0x38, 0x16, 0x10, 0xD0, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 72 + 0xC0, 0x38, 0x06, 0x00, 0x00, 0x00, // 73 + 0x00, 0xF0, 0x0E, 0xC0, 0x00, 0x00, // 74 + 0xC0, 0x38, 0x16, 0x68, 0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 75 + 0xC0, 0xB8, 0x86, 0x80, 0x00, 0x00, 0x00, 0x00, // 76 + 0xC0, 0x38, 0x06, 0x38, 0x10, 0xC8, 0x3C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 77 + 0xC0, 0x38, 0x06, 0x38, 0xC0, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 78 + 0x78, 0x84, 0x82, 0x82, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 79 + 0xC0, 0x38, 0x16, 0x12, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, // 80 + 0x78, 0x84, 0x82, 0x82, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, // 81 + 0xC0, 0x38, 0x16, 0x72, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, // 82 + 0x40, 0x8C, 0x92, 0x92, 0x62, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 83 + 0x02, 0xC2, 0x3A, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 84 + 0x78, 0x86, 0x80, 0x80, 0x78, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 85 + 0x0E, 0xF0, 0x40, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, // 86 + 0xFE, 0x60, 0x1C, 0x02, 0xFE, 0x60, 0x1C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 87 + 0x80, 0x42, 0x2C, 0x10, 0x6C, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 88 + 0x02, 0xCC, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // 89 + 0x80, 0xC2, 0xA2, 0x92, 0x8A, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 90 + 0xC0, 0xBC, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, // 91 + 0x1E, 0xE0, 0x00, 0x00, // 92 + 0x80, 0xC0, 0x3D, 0x03, 0x00, 0x00, 0x00, 0x00, // 93 + 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, // 94 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, // 95 + 0x01, 0x02, 0x00, 0x00, // 96 + 0xC0, 0xA8, 0xA8, 0xE8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, // 97 + 0xC0, 0x7C, 0x93, 0x88, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, // 98 + 0xF0, 0x98, 0x88, 0x08, 0x00, 0x00, 0x00, 0x00, // 99 + 0xF0, 0x98, 0x88, 0xC8, 0x3C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 100 + 0x70, 0xB8, 0xA8, 0xA8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // 101 + 0xC8, 0x3E, 0x09, 0x00, 0x00, 0x00, // 102 + 0xF0, 0x98, 0x88, 0xC8, 0x38, 0x80, 0x80, 0x80, 0x40, 0x00, // 103 + 0xC0, 0x3C, 0x13, 0xC8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, // 104 + 0xE0, 0x38, 0x01, 0x00, 0x00, 0x00, // 105 + 0xC0, 0x38, 0x01, 0xC0, 0x00, 0x00, // 106 + 0xC0, 0x3C, 0x23, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // 107 + 0xC0, 0x3C, 0x03, 0x00, 0x00, 0x00, // 108 + 0xE0, 0x18, 0x08, 0xC8, 0x78, 0x10, 0xC8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 109 + 0xE0, 0x38, 0x08, 0xC8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, // 110 + 0x70, 0x98, 0x88, 0xC8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, // 111 + 0xE0, 0x98, 0x88, 0xC8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, // 112 + 0xF0, 0x88, 0x88, 0xF0, 0x18, 0x00, 0x00, 0xC0, 0x00, 0x00, // 113 + 0xE0, 0x38, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, // 114 + 0x80, 0xB8, 0xA8, 0xE8, 0x00, 0x00, 0x00, 0x00, // 115 + 0xF8, 0x8C, 0x08, 0x00, 0x00, 0x00, // 116 + 0xE0, 0x98, 0x80, 0xE0, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, // 117 + 0x38, 0xC0, 0x60, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // 118 + 0xF8, 0x60, 0x10, 0xF8, 0x40, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 119 + 0x80, 0x48, 0x30, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 + 0x00, 0xF8, 0x60, 0x10, 0x08, 0x80, 0x40, 0x00, 0x00, 0x00, // 121 + 0x80, 0xC8, 0xA8, 0x98, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // 122 + 0x08, 0xF8, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, // 123 + 0xFE, 0xC0, // 124 + 0x80, 0x80, 0x71, 0x0F, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, // 125 + 0x20, 0x10, 0x10, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 126 + 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xC0, 0x80, 0x80, 0x80, 0xC0 // 127 + +}; + +#endif diff --git a/libraries/DMD/Mono5x7.h b/libraries/DMD/Mono5x7.h new file mode 100644 index 00000000..f3c82c07 --- /dev/null +++ b/libraries/DMD/Mono5x7.h @@ -0,0 +1,155 @@ + + +/* + * + * Mono5x7 + * + * created with FontCreator + * written by F. Maximilian Thiele + * + * http://www.apetech.de/fontCreator + * me@apetech.de + * + * File Name : Mono5x7.h + * Date : 29.05.2012 + * Font size in bytes : 3462 + * Font width : 5 + * Font height : 7 + * Font first char : 32 + * Font last char : 128 + * Font used chars : 96 + * + * The font data are defined as + * + * struct _FONT_ { + * uint16_t font_Size_in_Bytes_over_all_included_Size_it_self; + * uint8_t font_Width_in_Pixel_for_fixed_drawing; + * uint8_t font_Height_in_Pixel_for_all_characters; + * unit8_t font_First_Char; + * uint8_t font_Char_Count; + * + * uint8_t font_Char_Widths[font_Last_Char - font_First_Char +1]; + * // for each character the separate width in pixels, + * // characters < 128 have an implicit virtual right empty row + * + * uint8_t font_data[]; + * // bit field of all characters + */ + +#include +#include + +#ifndef MONO5X7_H +#define MONO5X7_H + +#define MONO5X7_WIDTH 5 +#define MONO5X7_HEIGHT 7 + +static uint8_t Mono5x7[] PROGMEM = { + 0x00, 0x00, // size + 0x05, // width + 0x07, // height + 0x20, // first char + 0x60, // char count + + // font data + 0x00, 0x00, 0x00, 0x00, 0x00, // 32 + 0x00, 0x00, 0x5F, 0x00, 0x00, // 33 + 0x00, 0x07, 0x00, 0x07, 0x00, // 34 + 0x14, 0x7F, 0x14, 0x7F, 0x14, // 35 + 0x24, 0x2A, 0x7F, 0x2A, 0x12, // 36 + 0x23, 0x13, 0x08, 0x64, 0x62, // 37 + 0x36, 0x49, 0x55, 0x22, 0x50, // 38 + 0x00, 0x05, 0x03, 0x00, 0x00, // 39 + 0x00, 0x1C, 0x22, 0x41, 0x00, // 40 + 0x00, 0x41, 0x22, 0x1C, 0x00, // 41 + 0x14, 0x08, 0x3E, 0x08, 0x14, // 42 + 0x08, 0x08, 0x3E, 0x08, 0x08, // 43 + 0x00, 0x50, 0x30, 0x00, 0x00, // 44 + 0x08, 0x08, 0x08, 0x08, 0x08, // 45 + 0x00, 0x60, 0x60, 0x00, 0x00, // 46 + 0x20, 0x10, 0x08, 0x04, 0x02, // 47 + 0x3E, 0x51, 0x49, 0x45, 0x3E, // 48 + 0x00, 0x42, 0x7F, 0x40, 0x00, // 49 + 0x42, 0x61, 0x51, 0x49, 0x46, // 50 + 0x21, 0x41, 0x45, 0x4B, 0x31, // 51 + 0x18, 0x14, 0x12, 0x7F, 0x10, // 52 + 0x27, 0x45, 0x45, 0x45, 0x39, // 53 + 0x3C, 0x4A, 0x49, 0x49, 0x30, // 54 + 0x01, 0x71, 0x09, 0x05, 0x03, // 55 + 0x36, 0x49, 0x49, 0x49, 0x36, // 56 + 0x06, 0x49, 0x49, 0x29, 0x1E, // 57 + 0x00, 0x36, 0x36, 0x00, 0x00, // 58 + 0x00, 0x56, 0x36, 0x00, 0x00, // 59 + 0x08, 0x14, 0x22, 0x41, 0x00, // 60 + 0x14, 0x14, 0x14, 0x14, 0x14, // 61 + 0x00, 0x41, 0x22, 0x14, 0x08, // 62 + 0x02, 0x01, 0x51, 0x09, 0x06, // 63 + 0x32, 0x49, 0x79, 0x41, 0x3E, // 64 + 0x7E, 0x11, 0x11, 0x11, 0x7E, // 65 + 0x7F, 0x49, 0x49, 0x49, 0x36, // 66 + 0x3E, 0x41, 0x41, 0x41, 0x22, // 67 + 0x7F, 0x41, 0x41, 0x22, 0x1C, // 68 + 0x7F, 0x49, 0x49, 0x49, 0x41, // 69 + 0x7F, 0x09, 0x09, 0x09, 0x01, // 70 + 0x3E, 0x41, 0x49, 0x49, 0x78, // 71 + 0x7F, 0x08, 0x08, 0x08, 0x7F, // 72 + 0x00, 0x41, 0x7F, 0x41, 0x00, // 73 + 0x20, 0x40, 0x41, 0x3F, 0x01, // 74 + 0x7F, 0x08, 0x14, 0x22, 0x41, // 75 + 0x7F, 0x40, 0x40, 0x40, 0x40, // 76 + 0x7F, 0x02, 0x0C, 0x02, 0x7F, // 77 + 0x7F, 0x04, 0x08, 0x10, 0x7F, // 78 + 0x3E, 0x41, 0x41, 0x41, 0x3E, // 79 + 0x7F, 0x09, 0x09, 0x09, 0x06, // 80 + 0x3E, 0x41, 0x51, 0x21, 0x5E, // 81 + 0x7F, 0x09, 0x19, 0x29, 0x46, // 82 + 0x46, 0x49, 0x49, 0x49, 0x31, // 83 + 0x01, 0x01, 0x7F, 0x01, 0x01, // 84 + 0x3F, 0x40, 0x40, 0x40, 0x3F, // 85 + 0x1F, 0x20, 0x40, 0x20, 0x1F, // 86 + 0x3F, 0x40, 0x38, 0x40, 0x3F, // 87 + 0x63, 0x14, 0x08, 0x14, 0x63, // 88 + 0x07, 0x08, 0x70, 0x08, 0x07, // 89 + 0x61, 0x51, 0x49, 0x45, 0x43, // 90 + 0x00, 0x7F, 0x41, 0x41, 0x00, // 91 + 0x02, 0x04, 0x08, 0x10, 0x20, // 92 + 0x00, 0x41, 0x41, 0x7F, 0x00, // 93 + 0x04, 0x02, 0x01, 0x02, 0x04, // 94 + 0x40, 0x40, 0x40, 0x40, 0x40, // 95 + 0x00, 0x02, 0x04, 0x08, 0x00, // 96 + 0x20, 0x54, 0x54, 0x54, 0x78, // 97 + 0x7F, 0x48, 0x44, 0x44, 0x38, // 98 + 0x38, 0x44, 0x44, 0x44, 0x20, // 99 + 0x38, 0x44, 0x44, 0x48, 0x7F, // 100 + 0x38, 0x54, 0x54, 0x54, 0x18, // 101 + 0x08, 0x7E, 0x09, 0x01, 0x02, // 102 + 0x0C, 0x52, 0x52, 0x52, 0x3E, // 103 + 0x7F, 0x08, 0x04, 0x04, 0x78, // 104 + 0x00, 0x44, 0x7D, 0x40, 0x00, // 105 + 0x20, 0x40, 0x44, 0x3D, 0x00, // 106 + 0x7F, 0x10, 0x28, 0x44, 0x00, // 107 + 0x00, 0x41, 0x7F, 0x40, 0x00, // 108 + 0x7C, 0x04, 0x18, 0x04, 0x78, // 109 + 0x7C, 0x08, 0x04, 0x04, 0x78, // 110 + 0x38, 0x44, 0x44, 0x44, 0x38, // 111 + 0x7C, 0x14, 0x14, 0x14, 0x08, // 112 + 0x08, 0x14, 0x14, 0x18, 0x7C, // 113 + 0x7C, 0x08, 0x04, 0x04, 0x08, // 114 + 0x48, 0x54, 0x54, 0x54, 0x20, // 115 + 0x04, 0x3F, 0x44, 0x40, 0x00, // 116 + 0x3C, 0x40, 0x40, 0x20, 0x7C, // 117 + 0x1C, 0x20, 0x40, 0x20, 0x1C, // 118 + 0x3C, 0x40, 0x30, 0x40, 0x3C, // 119 + 0x44, 0x28, 0x10, 0x28, 0x44, // 120 + 0x0C, 0x50, 0x50, 0x50, 0x3C, // 121 + 0x44, 0x64, 0x54, 0x4C, 0x44, // 122 + 0x00, 0x08, 0x36, 0x41, 0x00, // 123 + 0x00, 0x00, 0x7F, 0x00, 0x00, // 124 + 0x00, 0x41, 0x36, 0x08, 0x00, // 125 + 0x08, 0x04, 0x08, 0x10, 0x08, // 126 + 0x00, 0x00, 0x00, 0x00, 0x00 // 127 + +}; + +#endif diff --git a/libraries/DMD/dmd-4x1.fig b/libraries/DMD/dmd-4x1.fig new file mode 100644 index 00000000..d0949c23 --- /dev/null +++ b/libraries/DMD/dmd-4x1.fig @@ -0,0 +1,36 @@ +#FIG 3.2 Produced by xfig version 3.2.5b +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 3375 2700 4500 2700 4500 3375 3375 3375 3375 2700 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 4950 2700 6075 2700 6075 3375 4950 3375 4950 2700 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 6525 2700 7650 2700 7650 3375 6525 3375 6525 2700 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 8100 2700 9225 2700 9225 3375 8100 3375 8100 2700 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 4950 3060 4500 3060 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 6525 3060 6075 3060 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 8100 3060 7650 3060 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 9900 3060 9225 3060 +2 2 0 1 0 26 50 -1 -1 0.000 1 0 -1 0 0 5 + 9900 2835 10800 2835 10800 3285 9900 3285 9900 2835 +4 0 0 50 -1 0 12 0.0000 4 135 675 10035 3105 Arduino\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 8370 3105 Panel 4\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 6795 3105 Panel 3\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 5220 3105 Panel 2\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 3645 3105 Panel 1\001 diff --git a/libraries/DMD/dmd-4x1.png b/libraries/DMD/dmd-4x1.png new file mode 100644 index 0000000000000000000000000000000000000000..f796bbd28daa86468c985d40c3010e3fc79d1ec5 GIT binary patch literal 2493 zcmd6pdpy(s9>>4ZiTnsrogdOfb4g2L@v|(suepu%)5DUVsL{-rTbNRbFlufSBe~yJ zu4PF}%%v>%UmKCzrZr1`LTrBPJkEJM&f`4JIscu<@$o>j0j1cA*iU}cr%ppc5w<@qd1Awfeqm7kERK8$>g&XhMBlCsp5OI)+ zF;zE-*siMd6q4~uPwD#Udyf>y<3T`jQ9Q7&n-TvC68jbZo~}3#SGpMe*u`|4GUWWr z6@TWoZCVKBnC6VDwU_9ejxe6UVOl(uL9c&NNPb+L=z?>!?3a(^qS`0ZXL2Ds`s!mR zX%%?=xy~LP~ zS$Bz7)+lxEURh;keJdMO`W!^jDb~9S>E8M4&GfzdCEqvPKfD6~-aUi@!1Y~CQUE}x zPym1;YwV9`0;K_f=c*0>r&?Nh62bD6m6EL1-u<2VnW!JO`JGz*LfyefdarVK|HFBQ zEiwM`pC3h6vNQZC+-NG-)=hQ0Rr!z`A`4SH5?Ijs`=z|HTF+{mlD;}B66`p56{?=r zCG%V@3`@D%biR8QSz8bup>hvZHE`w4#9H*e?F^G=StvUlHaF|Ulu^~#>xAX0L3+)q+G z5G&VCmU=Y2C!kkrtXI9Oxt{~vRI~J9+&q+l<9&>!%}Ko5(goV(kdJt>AL51ZvRAf0 zg#k_OuCK{swY6EZEo#EF)em&$i!Bxx|0;(QR8$4d?JBn-DGQIubK7b&Opv_?+L zu&;`15tfKsSooV<-0&c2+N^GU`=ogh17BcaxSRPzxM8=rise9~O!77@59yaGy=um? zmc7TEhKB2FjO2$*6cS#BqZg$JbTkv6lw@I#LiE+|6?baK+-YoZiJ@KLUQfjF9`Ff% zSYL+6J;x9C^-HTP)Mc2B4O@`Ho7(KnR4DCiV|CA0fI#0@2$mXCr?{&a#D&@xcM7_#^$vIp^9=`BzctP(Z;HD(B}vuG??BxYn^5! zivkkA6|Zr}SMQc9Vy9NU;Yg=*PmqfBoZOlCX|s7>1PKLM8Fsn{i&S=T?Bw<7#Fi(ONl zr}Cn(U*h1h+c?b|B5}tZMd1WJa!VX{u$R8^TuRw1yK_vm4uI=opPTTPbYF3H$uD0Xu;z7m6Xr{ z<+Fu7&gFh3Ii9YP61Yj4B3RhWp&)5>Rtc7)LN<2?FT1Tdmy-)|%h55Im4&G{*NlQm z$O~do;ruScb8g^gjhTu#Z>y7kT`l?kK8@=>yyL}_nb5w5su@wt3ugQuyn)ypd%rrzE!$qOl=19W5qi5Ci!Xlr@;Fb8N&` zU1Mk}cZa?0ZC|%W({_JdL-ihP&_JSjasrg3jL}@r5ibuR|#x7bff$~sQMF|w+YjJBM zzr-~;|1o!~e**^xADao8P2sZ6+0mSCBlcV}cDx_^8@$h$iYTyn{x(RcyIU@JbkuX< z`{&~)TrQ~bZlpZ`Q^GXJurd$h=4#xx_VwurR;P&lmK6}Zxj;r2!!uJu@)^kaIAx+k z+ZaD9RnUIaCswphFHG5JI#D;Md-%{QlmS2L^80nV)4F+gR_NxQuAW&hncBY)wacC% zl$6uq%U#|$gM3_feJZnkE!ZTzXlNmd%CsOACn^3!wf)H5D#?5yEXS~~Lb05A{ITF8 z=@ye`K7`K|2L>J#llK@@sKk4hbA0+oFMj{LG|m{#=+SXp(>#KEzFC=jxI$%Yj7Oh; zqhJ>=y20a^A2c^5o1l$_OxdEum7fMTgL}G8b^Z~$M`GP+6Fq65i@{mWhDHiubTbMpC_L(>V7Wf&0PMokCxdA33}k}W;Yi^JG(mpl z2{y*h?@@7=(~(PYknz^=>cJ+~=qRN3;AM4n^=9n3)h#)##13EEw4>@b`8^$5fR~D# zT$OwkSb{si(bn0f?)1fkL%dB=LOzPp7n;ruu^dECI94 l7HJ@gbOLbw0Gx`J2Idri%>Sc9lavKR+UKNao%cV-_9w5-g6aSO literal 0 HcmV?d00001 diff --git a/libraries/DMD/dmd-4x2.fig b/libraries/DMD/dmd-4x2.fig new file mode 100644 index 00000000..233d939c --- /dev/null +++ b/libraries/DMD/dmd-4x2.fig @@ -0,0 +1,60 @@ +#FIG 3.2 Produced by xfig version 3.2.5b +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 9900 3060 9225 3060 +2 2 0 1 0 26 50 -1 -1 0.000 1 0 -1 0 0 5 + 9900 2835 10800 2835 10800 3285 9900 3285 9900 2835 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 3375 1575 4500 1575 4500 2250 3375 2250 3375 1575 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 4950 1575 6075 1575 6075 2250 4950 2250 4950 1575 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 8100 1575 9225 1575 9225 2250 8100 2250 8100 1575 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 7650 1935 8100 1935 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 6525 1575 7650 1575 7650 2250 6525 2250 6525 1575 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 6075 1935 6525 1935 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 4500 1935 4950 1935 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 4 + 1 1 3.00 60.00 120.00 + 3375 3015 2925 3015 2925 1890 3375 1890 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 3375 2700 4500 2700 4500 3375 3375 3375 3375 2700 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 4950 2700 6075 2700 6075 3375 4950 3375 4950 2700 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 6525 2700 7650 2700 7650 3375 6525 3375 6525 2700 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 8100 2700 9225 2700 9225 3375 8100 3375 8100 2700 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 4950 3060 4500 3060 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 6525 3060 6075 3060 +2 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 3.00 60.00 120.00 + 8100 3060 7650 3060 +4 0 0 50 -1 0 12 0.0000 4 135 675 10035 3105 Arduino\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 8370 3105 Panel 8\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 6795 3105 Panel 7\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 5220 3105 Panel 6\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 3645 3105 Panel 5\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 4230 1845 Panel 4\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 5805 1845 Panel 3\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 7380 1845 Panel 2\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 8955 1845 Panel 1\001 diff --git a/libraries/DMD/dmd-4x2.png b/libraries/DMD/dmd-4x2.png new file mode 100644 index 0000000000000000000000000000000000000000..ac0f3144a1dd857db96ae87cfcb27489750cdd5a GIT binary patch literal 4853 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 +#include +#include +#include +#include + +DMD display; + +ISR(TIMER1_OVF_vect) +{ + display.refresh(); +} + +void setup() { + display.enableTimer1(); +} + +void loop() { + drawShapes(); + delay(1000); + + drawBricks(); + delay(1000); + + drawStickFigures(); + delay(1000); + + drawText(); + delay(1000); + + drawBoldText(); + delay(1000); + + drawItalicText(); + delay(1000); + + drawMonoText(); + delay(1000); + + drawMarquee(); + delay(500); +} + +void drawShapes() +{ + display.clear(); + display.drawCircle(6, 8, 3); + display.drawFilledCircle(16, 8, 3); + display.drawLine(22, 5, 28, 11); + display.drawLine(28, 5, 22, 11); + display.drawRect(0, 0, display.width() - 1, display.height() - 1); +} + +void drawBricks() +{ + static const uint8_t bricks[] PROGMEM = { + 16, 6, + B11111111, B11111111, + B10000000, B10000000, + B10000000, B10000000, + B11111111, B11111111, + B00001000, B00001000, + B00001000, B00001000 + }; + display.fill(0, 0, display.width(), display.height(), bricks); +} + +void drawStickFigures() +{ + static const uint8_t stickFigure[] PROGMEM = { + 9, 13, + B00111110, B00000000, + B01000001, B00000000, + B01000001, B00000000, + B00111110, B00000000, + B00001000, B00000000, + B00001000, B00000000, + B11111111, B10000000, + B00001000, B00000000, + B00001000, B00000000, + B00010100, B00000000, + B00100010, B00000000, + B01000001, B00000000, + B10000000, B10000000 + }; + display.clear(); + display.drawBitmap(2, 1, stickFigure); + display.drawInvertedBitmap(12, 1, stickFigure); + display.drawBitmap(22, 1, stickFigure); +} + +void drawText() +{ + display.clear(); + display.setFont(DejaVuSans9); + display.drawText(0, 0, "Hello"); + display.drawText(9, 8, "World"); +} + +void drawBoldText() +{ + display.clear(); + display.setFont(DejaVuSansBold9); + display.drawText(0, 0, "Hello"); + display.drawText(4, 8, "World"); +} + +void drawItalicText() +{ + display.clear(); + display.setFont(DejaVuSansItalic9); + display.drawText(0, 0, "Hello"); + display.drawText(2, 8, "World"); +} + +void drawMonoText() +{ + display.clear(); + display.setFont(Mono5x7); + display.drawText(0, 0, "Hello"); + display.drawText(3, 8, "World"); +} + +static const char message[] = "Eat at Joes!"; + +void drawMarquee() +{ + int width = display.width(); + display.setFont(DejaVuSans9); + int msgWidth = display.textWidth(message); + int fullScroll = msgWidth + width + 1; + for (int x = 0; x < fullScroll; ++x) { + display.clear(); + display.drawText(width - x, 3, message); + delay(50); + } +} diff --git a/libraries/DMD/examples/RunningFigure/RunningFigure.pde b/libraries/DMD/examples/RunningFigure/RunningFigure.pde new file mode 100644 index 00000000..76e4f796 --- /dev/null +++ b/libraries/DMD/examples/RunningFigure/RunningFigure.pde @@ -0,0 +1,135 @@ +/* + * 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 +}; + +const prog_uint8_t *frames[] = { + run1, + run2, + run3, + run4 +}; +#define NUM_FRAMES (sizeof(frames) / sizeof(frames[0])) +#define ADVANCE_MS (1000 / NUM_FRAMES) +unsigned int frame = 0; +unsigned long lastFrame; + +void setup() { + display.drawBitmap(8, 0, run1); + lastFrame = millis(); +} + +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; + } + display.loop(); +} diff --git a/libraries/DMD/keywords.txt b/libraries/DMD/keywords.txt new file mode 100644 index 00000000..ce3266e9 --- /dev/null +++ b/libraries/DMD/keywords.txt @@ -0,0 +1,43 @@ +DMD KEYWORD1 +Bitmap KEYWORD1 + +doubleBuffer KEYWORD2 +setDoubleBuffer KEYWORD2 +swapBuffers KEYWORD2 +swapBuffersAndCopy KEYWORD2 +refresh KEYWORD2 +enableTimer1 KEYWORD2 +disableTimer1 KEYWORD2 + +isValid KEYWORD2 +width KEYWORD2 +height KEYWORD2 +stride KEYWORD2 +bitsPerPixel KEYWORD2 +clear KEYWORD2 +pixel KEYWORD2 +setPixel KEYWORD2 +drawLine KEYWORD2 +drawRect KEYWORD2 +drawFilledRect KEYWORD2 +drawCircle KEYWORD2 +drawFilledCircle KEYWORD2 +drawBitmap KEYWORD2 +drawInvertedBitmap KEYWORD2 +font KEYWORD2 +setFont KEYWORD2 +textColor KEYWORD2 +setTextColor KEYWORD2 +drawText KEYWORD2 +drawChar KEYWORD2 +charWidth KEYWORD2 +textWidth KEYWORD2 +textHeight KEYWORD2 +copy KEYWORD2 +fill KEYWORD2 +scroll KEYWORD2 +invert KEYWORD2 + +Black LITERAL1 +White LITERAL1 +NoFill LITERAL1