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 00000000..f796bbd2 Binary files /dev/null and b/libraries/DMD/dmd-4x1.png differ 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 00000000..ac0f3144 Binary files /dev/null and b/libraries/DMD/dmd-4x2.png differ diff --git a/libraries/DMD/dmd-4x3.fig b/libraries/DMD/dmd-4x3.fig new file mode 100644 index 00000000..78c111ae --- /dev/null +++ b/libraries/DMD/dmd-4x3.fig @@ -0,0 +1,84 @@ +#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 1 0 4 11 7 50 -1 -1 0.000 0 0 -1 1 0 4 + 1 1 3.00 60.00 120.00 + 9225 1890 9675 1890 9675 765 9225 765 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 3375 450 4500 450 4500 1125 3375 1125 3375 450 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 4950 450 6075 450 6075 1125 4950 1125 4950 450 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 6525 450 7650 450 7650 1125 6525 1125 6525 450 +2 2 0 1 0 7 50 -1 -1 0.000 1 0 -1 0 0 5 + 8100 450 9225 450 9225 1125 8100 1125 8100 450 +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 810 4500 810 +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 810 6075 810 +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 810 7650 810 +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 3645 3105 Panel 9\001 +4 0 0 50 -1 0 12 0.0000 4 135 705 5175 3105 Panel 10\001 +4 0 0 50 -1 0 12 0.0000 4 135 705 6750 3105 Panel 11\001 +4 0 0 50 -1 0 12 0.0000 4 135 705 8325 3105 Panel 12\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 8955 1845 Panel 5\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 7380 1845 Panel 6\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 5805 1845 Panel 7\001 +4 0 0 50 -1 0 12 3.1416 4 135 600 4230 1845 Panel 8\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 3645 855 Panel 1\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 5220 855 Panel 2\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 6795 855 Panel 3\001 +4 0 0 50 -1 0 12 0.0000 4 135 600 8370 855 Panel 4\001 diff --git a/libraries/DMD/dmd-4x3.png b/libraries/DMD/dmd-4x3.png new file mode 100644 index 00000000..7291057c Binary files /dev/null and b/libraries/DMD/dmd-4x3.png differ diff --git a/libraries/DMD/dmd-info.txt b/libraries/DMD/dmd-info.txt new file mode 100644 index 00000000..c1cca739 --- /dev/null +++ b/libraries/DMD/dmd-info.txt @@ -0,0 +1,53 @@ +Description of the interface to the Freetronics Dot Matrix Display (DMD) +======================================================================== + +Pins: + D6: A - interleave phase select LSB + D7: B - interleave phase select MSB (set the MSB first) + D8: SCLK - this is the "latch" pin that copies all previously transferred + data from the shift register to the actual display. Normally low, + then flip to high and then low again to latch the data. + D9: nOE - Output enable (when low). + D10: Conflict detect (if it goes low, something else is using SPI) + This is the standard SPI SS - Slave select - pin. + D11: R - this is the standard SPI MOSI - Master out, slave in - pin. + D12: MISO - master in, slave out - unused + D13: CLK - standard Serial Clock pin for SPI + +Initialisation: + SPI: bit order = MSB-first, data mode = 0, clock divider = 128 + (use a smaller clock divider, such as 2, for better performance + when driving multiple displays) + + Set A, B, CLK, SCLK, and nOE to LOW outputs + Set R to HIGH output + + phase = 0 + +Every 5ms, do the following to refresh the display: + Send the bytes for 4 interleaved rows based on phase, via SPI: + phase == 0: 0, 4, 8, 12 (actually sent in the order 12, 8, 4, 0) + phase == 1: 1, 5, 9, 13 + phase == 2: 2, 6, 10, 14 + phase == 3: 3, 7, 11, 15 + Then latch the data for the rows as follows: + Set nOE to LOW + Set SCLK to HIGH and then back to LOW + Set A and B to indicate the current phase + Set nOE to HIGH + Finally, increment the phase, wrapping around from 3 to 0 + The above code assumes the following memory organisation: + The display is W panels wide and H panels high. + Each panel is 32 pixels wide (4 bytes) and 16 pixels high. + Memory is organised as W * H * 4 bytes for each row, and 16 rows. + That is, the 2D arrangement of panels is flattened into 1D for + clocking the data out. + In addition, a 1 bit in memory is a LED that is *off*. + +Other things: + Multiple panels need to be daisy-chained in the order N, ..., 1 with N + plugged into the connector board on the Arduino and 1 at the end of + the daisy-chain. Because the shipped cables are short, multiple rows + can be oriented in alternating order with odd-numbered rows + (counting from 1) upside-down and reversed. More details here: + http://www.adebenham.com/category/arduino/dmd/ diff --git a/libraries/DMD/examples/Demo/Demo.pde b/libraries/DMD/examples/Demo/Demo.pde new file mode 100644 index 00000000..e3b83655 --- /dev/null +++ b/libraries/DMD/examples/Demo/Demo.pde @@ -0,0 +1,144 @@ +/* +This example demonstrates how to use the DMD and related classes to +draw things on a Freetronics Large Dot Matrix Display. + +This example is placed into the public domain. +*/ + +#include +#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