Forked LEDMatrix and added horizontal scrolling
Fork of LEDMatrix by
LEDMatrix.cpp@2:cd2da920cf98, 2016-01-14 (annotated)
- Committer:
- Bobty
- Date:
- Thu Jan 14 12:57:59 2016 +0000
- Revision:
- 2:cd2da920cf98
- Parent:
- 1:79cf2e115449
- Child:
- 3:1e06e89bc0c9
Improved scrolling; Now handles multiple independent lines of text; Converted the coordinate system to more conventional one
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yihui | 0:13728deac7a7 | 1 | /** |
yihui | 0:13728deac7a7 | 2 | * LED Matrix library for http://www.seeedstudio.com/depot/ultrathin-16x32-red-led-matrix-panel-p-1582.html |
yihui | 0:13728deac7a7 | 3 | * The LED Matrix panel has 32x16 pixels. Several panel can be combined together as a large screen. |
yihui | 0:13728deac7a7 | 4 | * |
yihui | 0:13728deac7a7 | 5 | * Coordinate & Connection (mbed -> panel 0 -> panel 1 -> ...) |
yihui | 0:13728deac7a7 | 6 | * (0, 0) (0, 0) |
yihui | 0:13728deac7a7 | 7 | * +--------+--------+--------+ +--------+--------+ |
yihui | 0:13728deac7a7 | 8 | * | 5 | 3 | 1 | | 1 | 0 | |
yihui | 0:13728deac7a7 | 9 | * | | | | | | |<----- mbed |
yihui | 0:13728deac7a7 | 10 | * +--------+--------+--------+ +--------+--------+ |
yihui | 0:13728deac7a7 | 11 | * | 4 | 2 | 0 | (64, 16) |
yihui | 0:13728deac7a7 | 12 | * | | | |<----- mbed |
yihui | 0:13728deac7a7 | 13 | * +--------+--------+--------+ |
yihui | 0:13728deac7a7 | 14 | * (96, 32) |
yihui | 0:13728deac7a7 | 15 | * Copyright (c) 2013 Seeed Technology Inc. |
yihui | 0:13728deac7a7 | 16 | * @auther Yihui Xiong |
yihui | 0:13728deac7a7 | 17 | * @date Nov 8, 2013 |
yihui | 0:13728deac7a7 | 18 | * @license Apache |
Bobty | 2:cd2da920cf98 | 19 | * |
Bobty | 2:cd2da920cf98 | 20 | * Heavily modified by Rob Dobson, 2016 |
yihui | 0:13728deac7a7 | 21 | */ |
yihui | 0:13728deac7a7 | 22 | |
yihui | 0:13728deac7a7 | 23 | #include "LEDMatrix.h" |
yihui | 0:13728deac7a7 | 24 | #include "mbed.h" |
Bobty | 2:cd2da920cf98 | 25 | #include "fontBig.h" |
Bobty | 2:cd2da920cf98 | 26 | #include "font5x7.h" |
yihui | 0:13728deac7a7 | 27 | |
yihui | 0:13728deac7a7 | 28 | #if 0 |
yihui | 0:13728deac7a7 | 29 | #define ASSERT(e) if (!(e)) { Serial.println(#e); while (1); } |
yihui | 0:13728deac7a7 | 30 | #else |
yihui | 0:13728deac7a7 | 31 | #define ASSERT(e) |
yihui | 0:13728deac7a7 | 32 | #endif |
yihui | 0:13728deac7a7 | 33 | |
yihui | 0:13728deac7a7 | 34 | LEDMatrix::LEDMatrix(PinName pinA, PinName pinB, PinName pinC, PinName pinD, PinName pinOE, PinName pinR1, PinName pinSTB, PinName pinCLK) : |
yihui | 0:13728deac7a7 | 35 | a(pinA), b(pinB), c(pinC), d(pinD), oe(pinOE), r1(pinR1), stb(pinSTB), clk(pinCLK) |
yihui | 0:13728deac7a7 | 36 | { |
yihui | 0:13728deac7a7 | 37 | this->clk = clk; |
yihui | 0:13728deac7a7 | 38 | this->r1 = r1; |
yihui | 0:13728deac7a7 | 39 | this->stb = stb; |
yihui | 0:13728deac7a7 | 40 | this->oe = oe; |
yihui | 0:13728deac7a7 | 41 | this->a = a; |
yihui | 0:13728deac7a7 | 42 | this->b = b; |
yihui | 0:13728deac7a7 | 43 | this->c = c; |
yihui | 0:13728deac7a7 | 44 | this->d = d; |
yihui | 0:13728deac7a7 | 45 | |
yihui | 0:13728deac7a7 | 46 | mask = 0xff; |
Bobty | 2:cd2da920cf98 | 47 | _isEnabled = false; |
Bobty | 2:cd2da920cf98 | 48 | for (int i = 0; i < LED_MATRIX_LEDS_VERTICALLY; i++) |
Bobty | 2:cd2da920cf98 | 49 | { |
Bobty | 2:cd2da920cf98 | 50 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 51 | _hScrollWidth[i] = LED_MATRIX_LEDS_HORIZONTALLY; |
Bobty | 2:cd2da920cf98 | 52 | } |
Bobty | 2:cd2da920cf98 | 53 | for (int i = 0; i < LED_MATRIX_MAX_LINES; i++) |
Bobty | 2:cd2da920cf98 | 54 | { |
Bobty | 2:cd2da920cf98 | 55 | _lineScrollInc[i] = 0; |
Bobty | 2:cd2da920cf98 | 56 | } |
Bobty | 2:cd2da920cf98 | 57 | _isBusy = false; |
Bobty | 2:cd2da920cf98 | 58 | _charSeparation = 1; |
yihui | 0:13728deac7a7 | 59 | } |
yihui | 0:13728deac7a7 | 60 | |
Bobty | 2:cd2da920cf98 | 61 | void LEDMatrix::begin(uint8_t *_pDisplayBuf, uint16_t width, uint16_t height, uint16_t dispBufWidth, uint16_t numLines, int charSeparation) |
yihui | 0:13728deac7a7 | 62 | { |
Bobty | 2:cd2da920cf98 | 63 | ASSERT(0 == (width % LED_MATRIX_LEDS_HORIZONTALLY)); |
Bobty | 2:cd2da920cf98 | 64 | ASSERT(0 == (scroll_width % LED_MATRIX_LEDS_HORIZONTALLY)); |
Bobty | 2:cd2da920cf98 | 65 | ASSERT(0 == (height % LED_MATRIX_LEDS_VERTICALLY)); |
yihui | 0:13728deac7a7 | 66 | |
Bobty | 2:cd2da920cf98 | 67 | this->_pDisplayBuf = _pDisplayBuf; |
yihui | 0:13728deac7a7 | 68 | this->width = width; |
yihui | 0:13728deac7a7 | 69 | this->height = height; |
Bobty | 2:cd2da920cf98 | 70 | this->dispBufWidth = dispBufWidth; |
Bobty | 2:cd2da920cf98 | 71 | this->numLines = numLines; |
Bobty | 2:cd2da920cf98 | 72 | this->_charSeparation = charSeparation; |
Bobty | 2:cd2da920cf98 | 73 | if (numLines > LED_MATRIX_MAX_LINES) |
Bobty | 2:cd2da920cf98 | 74 | this->numLines = LED_MATRIX_MAX_LINES; |
Bobty | 2:cd2da920cf98 | 75 | for (int i = 0; i < LED_MATRIX_LEDS_VERTICALLY; i++) |
Bobty | 2:cd2da920cf98 | 76 | { |
Bobty | 2:cd2da920cf98 | 77 | this->_hScrollWidth[i] = dispBufWidth; |
Bobty | 2:cd2da920cf98 | 78 | } |
yihui | 0:13728deac7a7 | 79 | |
Bobty | 2:cd2da920cf98 | 80 | _isEnabled = true; |
yihui | 0:13728deac7a7 | 81 | } |
yihui | 0:13728deac7a7 | 82 | |
yihui | 0:13728deac7a7 | 83 | void LEDMatrix::drawPoint(uint16_t x, uint16_t y, uint8_t pixel) |
yihui | 0:13728deac7a7 | 84 | { |
Bobty | 2:cd2da920cf98 | 85 | ASSERT(dispBufWidth > x); |
yihui | 0:13728deac7a7 | 86 | ASSERT(height > y); |
yihui | 0:13728deac7a7 | 87 | |
Bobty | 2:cd2da920cf98 | 88 | uint8_t *byte = _pDisplayBuf + (height - 1 - y) * dispBufWidth / 8 + x / 8; |
Bobty | 2:cd2da920cf98 | 89 | uint8_t bit = x % 8; |
yihui | 0:13728deac7a7 | 90 | |
Bobty | 2:cd2da920cf98 | 91 | if (pixel) |
Bobty | 2:cd2da920cf98 | 92 | { |
yihui | 0:13728deac7a7 | 93 | *byte |= 0x80 >> bit; |
Bobty | 2:cd2da920cf98 | 94 | } |
Bobty | 2:cd2da920cf98 | 95 | else |
Bobty | 2:cd2da920cf98 | 96 | { |
yihui | 0:13728deac7a7 | 97 | *byte &= ~(0x80 >> bit); |
yihui | 0:13728deac7a7 | 98 | } |
yihui | 0:13728deac7a7 | 99 | } |
yihui | 0:13728deac7a7 | 100 | |
yihui | 0:13728deac7a7 | 101 | void LEDMatrix::drawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t pixel) |
yihui | 0:13728deac7a7 | 102 | { |
Bobty | 2:cd2da920cf98 | 103 | for (uint16_t x = x1; x < x2; x++) |
Bobty | 2:cd2da920cf98 | 104 | { |
Bobty | 2:cd2da920cf98 | 105 | for (uint16_t y = y1; y < y2; y++) |
Bobty | 2:cd2da920cf98 | 106 | { |
yihui | 0:13728deac7a7 | 107 | drawPoint(x, y, pixel); |
yihui | 0:13728deac7a7 | 108 | } |
yihui | 0:13728deac7a7 | 109 | } |
yihui | 0:13728deac7a7 | 110 | } |
yihui | 0:13728deac7a7 | 111 | |
yihui | 0:13728deac7a7 | 112 | void LEDMatrix::drawImage(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t *image) |
yihui | 0:13728deac7a7 | 113 | { |
yihui | 0:13728deac7a7 | 114 | ASSERT(0 == ((x2 - x1) % 8)); |
yihui | 0:13728deac7a7 | 115 | |
Bobty | 2:cd2da920cf98 | 116 | for (uint16_t x = x1; x < x2; x++) |
Bobty | 2:cd2da920cf98 | 117 | { |
Bobty | 2:cd2da920cf98 | 118 | for (uint16_t y = y1; y < y2; y++) |
Bobty | 2:cd2da920cf98 | 119 | { |
yihui | 0:13728deac7a7 | 120 | uint8_t *byte = image + x * 8 + y / 8; |
yihui | 0:13728deac7a7 | 121 | uint8_t bit = 7 - (y % 8); |
yihui | 0:13728deac7a7 | 122 | uint8_t pixel = (*byte >> bit) & 1; |
yihui | 0:13728deac7a7 | 123 | drawPoint(x, y, pixel); |
yihui | 0:13728deac7a7 | 124 | } |
yihui | 0:13728deac7a7 | 125 | } |
yihui | 0:13728deac7a7 | 126 | } |
yihui | 0:13728deac7a7 | 127 | |
Bobty | 2:cd2da920cf98 | 128 | //void LEDMatrix::clear() |
Bobty | 2:cd2da920cf98 | 129 | //{ |
Bobty | 2:cd2da920cf98 | 130 | // uint8_t *ptr = _pDisplayBuf; |
Bobty | 2:cd2da920cf98 | 131 | // for (uint16_t i = 0; i < (dispBufWidth * height / 8); i++) |
Bobty | 2:cd2da920cf98 | 132 | // { |
Bobty | 2:cd2da920cf98 | 133 | // *ptr = 0x00; |
Bobty | 2:cd2da920cf98 | 134 | // ptr++; |
Bobty | 2:cd2da920cf98 | 135 | // } |
Bobty | 2:cd2da920cf98 | 136 | //} |
yihui | 0:13728deac7a7 | 137 | |
Bobty | 2:cd2da920cf98 | 138 | void LEDMatrix::invertColour() |
yihui | 0:13728deac7a7 | 139 | { |
yihui | 0:13728deac7a7 | 140 | mask = ~mask; |
yihui | 0:13728deac7a7 | 141 | } |
yihui | 0:13728deac7a7 | 142 | |
Bobty | 2:cd2da920cf98 | 143 | uint8_t LEDMatrix::isInvertedColour() |
yihui | 0:13728deac7a7 | 144 | { |
yihui | 0:13728deac7a7 | 145 | return mask; |
yihui | 0:13728deac7a7 | 146 | } |
yihui | 0:13728deac7a7 | 147 | |
yihui | 0:13728deac7a7 | 148 | void LEDMatrix::scan() |
yihui | 0:13728deac7a7 | 149 | { |
Bobty | 2:cd2da920cf98 | 150 | // On each call this function handles one row of the display |
Bobty | 2:cd2da920cf98 | 151 | static uint8_t scanRowIdx = 0; |
yihui | 0:13728deac7a7 | 152 | |
Bobty | 2:cd2da920cf98 | 153 | // Check if being updated |
Bobty | 2:cd2da920cf98 | 154 | if (_isBusy) |
yihui | 0:13728deac7a7 | 155 | return; |
Bobty | 2:cd2da920cf98 | 156 | |
Bobty | 2:cd2da920cf98 | 157 | // Check if display enabled |
Bobty | 2:cd2da920cf98 | 158 | if (!_isEnabled) |
Bobty | 2:cd2da920cf98 | 159 | return; |
yihui | 0:13728deac7a7 | 160 | |
Bobty | 2:cd2da920cf98 | 161 | // Base of this scan row in buffer to display |
Bobty | 2:cd2da920cf98 | 162 | uint8_t *pBufBase = _pDisplayBuf + scanRowIdx * (dispBufWidth / 8); |
Bobty | 2:cd2da920cf98 | 163 | |
Bobty | 2:cd2da920cf98 | 164 | // Handle multiple units vertically |
Bobty | 2:cd2da920cf98 | 165 | for (int rowIdx = 0; rowIdx < (height / LED_MATRIX_LEDS_VERTICALLY); rowIdx++) |
Bobty | 1:79cf2e115449 | 166 | { |
Bobty | 2:cd2da920cf98 | 167 | // Calculate buffer position within this unit |
Bobty | 2:cd2da920cf98 | 168 | uint8_t *pBuf = pBufBase + rowIdx * (dispBufWidth / 8) * LED_MATRIX_LEDS_VERTICALLY; |
yihui | 0:13728deac7a7 | 169 | |
Bobty | 2:cd2da920cf98 | 170 | // Work along the display row sending out data as we go |
Bobty | 2:cd2da920cf98 | 171 | // Noting that the first data we send out will be shunted to the end of the row |
Bobty | 2:cd2da920cf98 | 172 | int hScrollPos = _hScrollPos[scanRowIdx]; |
Bobty | 2:cd2da920cf98 | 173 | int hScrollWidth = _hScrollWidth[scanRowIdx]; |
Bobty | 2:cd2da920cf98 | 174 | if (hScrollWidth > dispBufWidth) |
Bobty | 2:cd2da920cf98 | 175 | hScrollWidth = dispBufWidth; |
Bobty | 2:cd2da920cf98 | 176 | int bitOffset = hScrollPos % 8; |
Bobty | 2:cd2da920cf98 | 177 | for (int byteIdx = (width / 8) - 1; byteIdx >= 0; byteIdx--) |
Bobty | 1:79cf2e115449 | 178 | { |
Bobty | 2:cd2da920cf98 | 179 | // When a row is scrolled a single byte on the display can be a combination of two buffer bytes |
Bobty | 2:cd2da920cf98 | 180 | uint8_t* pByte1 = pBuf + ((byteIdx*8 + hScrollPos) % hScrollWidth) / 8; |
Bobty | 2:cd2da920cf98 | 181 | uint8_t* pByte2 = pBuf + (((byteIdx+1)*8 + hScrollPos) % hScrollWidth) / 8; |
Bobty | 2:cd2da920cf98 | 182 | uint8_t pixels = ((*pByte1) << bitOffset) + (((*pByte2) >> (8 - bitOffset)) % 256); |
Bobty | 2:cd2da920cf98 | 183 | |
Bobty | 2:cd2da920cf98 | 184 | // Reverse the bits so they come out in the right order |
Bobty | 2:cd2da920cf98 | 185 | pixels = reverseBits(pixels) ^ mask; // reverse: mask = 0xff, normal: mask =0x00 |
Bobty | 1:79cf2e115449 | 186 | for (uint8_t bit = 0; bit < 8; bit++) |
Bobty | 1:79cf2e115449 | 187 | { |
yihui | 0:13728deac7a7 | 188 | clk = 0; |
yihui | 0:13728deac7a7 | 189 | r1 = pixels & (0x80 >> bit); |
yihui | 0:13728deac7a7 | 190 | clk = 1; |
yihui | 0:13728deac7a7 | 191 | } |
yihui | 0:13728deac7a7 | 192 | } |
yihui | 0:13728deac7a7 | 193 | } |
yihui | 0:13728deac7a7 | 194 | |
Bobty | 2:cd2da920cf98 | 195 | // Disable display |
Bobty | 2:cd2da920cf98 | 196 | oe = 1; |
yihui | 0:13728deac7a7 | 197 | |
Bobty | 2:cd2da920cf98 | 198 | // Select row (rows are muxed) |
Bobty | 2:cd2da920cf98 | 199 | int rowSel = LED_MATRIX_LEDS_VERTICALLY - 1 - scanRowIdx; |
Bobty | 2:cd2da920cf98 | 200 | a = (rowSel & 0x01); |
Bobty | 2:cd2da920cf98 | 201 | b = (rowSel & 0x02); |
Bobty | 2:cd2da920cf98 | 202 | c = (rowSel & 0x04); |
Bobty | 2:cd2da920cf98 | 203 | d = (rowSel & 0x08); |
yihui | 0:13728deac7a7 | 204 | |
Bobty | 2:cd2da920cf98 | 205 | // Latch data |
yihui | 0:13728deac7a7 | 206 | stb = 0; |
yihui | 0:13728deac7a7 | 207 | stb = 1; |
yihui | 0:13728deac7a7 | 208 | |
Bobty | 2:cd2da920cf98 | 209 | // Reenable display |
Bobty | 2:cd2da920cf98 | 210 | oe = 0; |
yihui | 0:13728deac7a7 | 211 | |
Bobty | 2:cd2da920cf98 | 212 | // Move the scan row on for next time |
Bobty | 2:cd2da920cf98 | 213 | scanRowIdx = (scanRowIdx + 1) & 0x0F; |
yihui | 0:13728deac7a7 | 214 | } |
yihui | 0:13728deac7a7 | 215 | |
yihui | 0:13728deac7a7 | 216 | void LEDMatrix::on() |
yihui | 0:13728deac7a7 | 217 | { |
Bobty | 2:cd2da920cf98 | 218 | _isEnabled = true; |
yihui | 0:13728deac7a7 | 219 | } |
yihui | 0:13728deac7a7 | 220 | |
yihui | 0:13728deac7a7 | 221 | void LEDMatrix::off() |
yihui | 0:13728deac7a7 | 222 | { |
Bobty | 2:cd2da920cf98 | 223 | _isEnabled = false; |
yihui | 0:13728deac7a7 | 224 | oe = 1; |
yihui | 0:13728deac7a7 | 225 | } |
yihui | 0:13728deac7a7 | 226 | |
Bobty | 2:cd2da920cf98 | 227 | bool LEDMatrix::getRowsToWorkOn(int lineIdx, int &startRow, int &numRows) |
Bobty | 2:cd2da920cf98 | 228 | { |
Bobty | 2:cd2da920cf98 | 229 | // lineIdx == -1 means all lines |
Bobty | 2:cd2da920cf98 | 230 | startRow = 0; |
Bobty | 2:cd2da920cf98 | 231 | numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 232 | if (lineIdx != -1) |
Bobty | 2:cd2da920cf98 | 233 | { |
Bobty | 2:cd2da920cf98 | 234 | if ((lineIdx < 0) || (lineIdx >= numLines)) |
Bobty | 2:cd2da920cf98 | 235 | return false; |
Bobty | 2:cd2da920cf98 | 236 | numRows = height / numLines; |
Bobty | 2:cd2da920cf98 | 237 | startRow = lineIdx * numRows; |
Bobty | 2:cd2da920cf98 | 238 | } |
Bobty | 2:cd2da920cf98 | 239 | return true; |
Bobty | 2:cd2da920cf98 | 240 | } |
Bobty | 2:cd2da920cf98 | 241 | |
Bobty | 2:cd2da920cf98 | 242 | void LEDMatrix::scrollReset(int lineIdx) |
Bobty | 2:cd2da920cf98 | 243 | { |
Bobty | 2:cd2da920cf98 | 244 | // Interpret param |
Bobty | 2:cd2da920cf98 | 245 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 246 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 247 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 248 | return; |
Bobty | 2:cd2da920cf98 | 249 | // Reset scroll position all rows |
Bobty | 2:cd2da920cf98 | 250 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 251 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 252 | } |
Bobty | 2:cd2da920cf98 | 253 | |
Bobty | 2:cd2da920cf98 | 254 | void LEDMatrix::scroll(int lineIdx, bool scrollLeft) |
Bobty | 2:cd2da920cf98 | 255 | { |
Bobty | 2:cd2da920cf98 | 256 | // Interpret param |
Bobty | 2:cd2da920cf98 | 257 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 258 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 259 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 260 | return; |
Bobty | 2:cd2da920cf98 | 261 | // Reset scroll position all rows |
Bobty | 2:cd2da920cf98 | 262 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 263 | { |
Bobty | 2:cd2da920cf98 | 264 | if (scrollLeft) |
Bobty | 2:cd2da920cf98 | 265 | { |
Bobty | 2:cd2da920cf98 | 266 | _hScrollPos[i]++; |
Bobty | 2:cd2da920cf98 | 267 | if (_hScrollPos[i] >= _hScrollWidth[i]) |
Bobty | 2:cd2da920cf98 | 268 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 269 | } |
Bobty | 2:cd2da920cf98 | 270 | else |
Bobty | 2:cd2da920cf98 | 271 | { |
Bobty | 2:cd2da920cf98 | 272 | _hScrollPos[i]--; |
Bobty | 2:cd2da920cf98 | 273 | if (_hScrollPos[i] < 0) |
Bobty | 2:cd2da920cf98 | 274 | _hScrollPos[i] = _hScrollWidth[i]-1; |
Bobty | 2:cd2da920cf98 | 275 | } |
Bobty | 2:cd2da920cf98 | 276 | } |
Bobty | 2:cd2da920cf98 | 277 | } |
Bobty | 2:cd2da920cf98 | 278 | |
Bobty | 2:cd2da920cf98 | 279 | void LEDMatrix::scrollToPos(int lineIdx, int pos) |
Bobty | 1:79cf2e115449 | 280 | { |
Bobty | 2:cd2da920cf98 | 281 | // Interpret param |
Bobty | 2:cd2da920cf98 | 282 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 283 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 284 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 285 | return; |
Bobty | 2:cd2da920cf98 | 286 | // Check pos |
Bobty | 2:cd2da920cf98 | 287 | if ((pos < 0) || (pos >= dispBufWidth)) |
Bobty | 2:cd2da920cf98 | 288 | return; |
Bobty | 2:cd2da920cf98 | 289 | // Reset scroll position all rows |
Bobty | 2:cd2da920cf98 | 290 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 291 | _hScrollPos[i] = pos; |
Bobty | 2:cd2da920cf98 | 292 | } |
Bobty | 2:cd2da920cf98 | 293 | |
Bobty | 2:cd2da920cf98 | 294 | void LEDMatrix::clear(int lineIdx) |
Bobty | 2:cd2da920cf98 | 295 | { |
Bobty | 2:cd2da920cf98 | 296 | // Interpret param |
Bobty | 2:cd2da920cf98 | 297 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 298 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 299 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 300 | return; |
Bobty | 2:cd2da920cf98 | 301 | // Clear section |
Bobty | 2:cd2da920cf98 | 302 | uint8_t *ptr = _pDisplayBuf + startRow * (dispBufWidth / 8); |
Bobty | 2:cd2da920cf98 | 303 | int bytesToZero = numRows * (dispBufWidth / 8); |
Bobty | 2:cd2da920cf98 | 304 | for (int i = 0; i < bytesToZero; i++) |
Bobty | 2:cd2da920cf98 | 305 | *ptr++ = 0x00; |
Bobty | 2:cd2da920cf98 | 306 | } |
Bobty | 2:cd2da920cf98 | 307 | |
Bobty | 2:cd2da920cf98 | 308 | void LEDMatrix::setupScroll(int lineIdx, int scrollWidth, int scrollInc) |
Bobty | 2:cd2da920cf98 | 309 | { |
Bobty | 2:cd2da920cf98 | 310 | // Interpret param |
Bobty | 2:cd2da920cf98 | 311 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 312 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 313 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 314 | return; |
Bobty | 2:cd2da920cf98 | 315 | scrollWidth = (((scrollWidth / 8) + 1) * 8); |
Bobty | 2:cd2da920cf98 | 316 | if (scrollWidth <= 0) |
Bobty | 2:cd2da920cf98 | 317 | return; |
Bobty | 2:cd2da920cf98 | 318 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 319 | { |
Bobty | 2:cd2da920cf98 | 320 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 321 | _hScrollWidth[i] = scrollWidth; |
Bobty | 2:cd2da920cf98 | 322 | _lineScrollInc[i] = scrollInc; |
Bobty | 2:cd2da920cf98 | 323 | } |
Bobty | 2:cd2da920cf98 | 324 | // int rowsInALine = height / numLines; |
Bobty | 2:cd2da920cf98 | 325 | // for (int i = 0; i < rowsInALine; i++) |
Bobty | 2:cd2da920cf98 | 326 | // _hScrollWidth[lineIdx*rowsInALine + i] = scrollWidth; |
Bobty | 2:cd2da920cf98 | 327 | } |
Bobty | 2:cd2da920cf98 | 328 | |
Bobty | 2:cd2da920cf98 | 329 | //void LEDMatrix::setLineScrollInc(int lineIdx, int scrollInc) |
Bobty | 2:cd2da920cf98 | 330 | //{ |
Bobty | 2:cd2da920cf98 | 331 | // if ((lineIdx < 0) || (lineIdx >= numLines)) |
Bobty | 2:cd2da920cf98 | 332 | // return; |
Bobty | 2:cd2da920cf98 | 333 | // int rowsInALine = height / numLines; |
Bobty | 2:cd2da920cf98 | 334 | // for (int i = 0; i < rowsInALine; i++) |
Bobty | 2:cd2da920cf98 | 335 | // _lineScrollInc[lineIdx*rowsInALine + i] = scrollInc; |
Bobty | 2:cd2da920cf98 | 336 | //} |
Bobty | 2:cd2da920cf98 | 337 | |
Bobty | 2:cd2da920cf98 | 338 | void LEDMatrix::serviceEffects() |
Bobty | 2:cd2da920cf98 | 339 | { |
Bobty | 2:cd2da920cf98 | 340 | for (int i = 0; i < LED_MATRIX_MAX_LINES; i++) |
Bobty | 2:cd2da920cf98 | 341 | { |
Bobty | 2:cd2da920cf98 | 342 | _hScrollPos[i] += _lineScrollInc[i]; |
Bobty | 2:cd2da920cf98 | 343 | } |
Bobty | 2:cd2da920cf98 | 344 | } |
Bobty | 2:cd2da920cf98 | 345 | |
Bobty | 2:cd2da920cf98 | 346 | // Reverse bits in byte |
Bobty | 2:cd2da920cf98 | 347 | uint8_t LEDMatrix::reverseBits(uint8_t b) |
Bobty | 2:cd2da920cf98 | 348 | { |
Bobty | 2:cd2da920cf98 | 349 | b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; |
Bobty | 2:cd2da920cf98 | 350 | b = (b & 0xCC) >> 2 | (b & 0x33) << 2; |
Bobty | 2:cd2da920cf98 | 351 | b = (b & 0xAA) >> 1 | (b & 0x55) << 1; |
Bobty | 2:cd2da920cf98 | 352 | return b; |
Bobty | 1:79cf2e115449 | 353 | } |
Bobty | 1:79cf2e115449 | 354 | |
Bobty | 2:cd2da920cf98 | 355 | // Display ASCII char |
Bobty | 2:cd2da920cf98 | 356 | int LEDMatrix::displayChar(int xPos, int yPos, char ch) |
Bobty | 1:79cf2e115449 | 357 | { |
Bobty | 2:cd2da920cf98 | 358 | const int FONT_HEIGHT = 7; |
Bobty | 2:cd2da920cf98 | 359 | const int FONT_WIDTH = 5; |
Bobty | 2:cd2da920cf98 | 360 | |
Bobty | 2:cd2da920cf98 | 361 | // Find the width of the character |
Bobty | 2:cd2da920cf98 | 362 | uint8_t chTotalBits = 0; |
Bobty | 2:cd2da920cf98 | 363 | int chIdxInFont = (ch % 128) - 0x20; |
Bobty | 2:cd2da920cf98 | 364 | // Special case for £, euro and yen signs |
Bobty | 2:cd2da920cf98 | 365 | if ((ch >= 0xa3) && (ch <= 0xa5)) |
Bobty | 2:cd2da920cf98 | 366 | chIdxInFont = ch - 0xa3 + 128 - ' '; |
Bobty | 2:cd2da920cf98 | 367 | for (int i = 0; i < FONT_HEIGHT; i++) |
Bobty | 2:cd2da920cf98 | 368 | { |
Bobty | 2:cd2da920cf98 | 369 | uint8_t chBits = font5x7[chIdxInFont][i]; |
Bobty | 2:cd2da920cf98 | 370 | chTotalBits |= chBits; |
Bobty | 2:cd2da920cf98 | 371 | } |
Bobty | 2:cd2da920cf98 | 372 | uint8_t rightShift = 0; |
Bobty | 2:cd2da920cf98 | 373 | for (int j = 0; j < FONT_WIDTH; j++) |
Bobty | 2:cd2da920cf98 | 374 | { |
Bobty | 2:cd2da920cf98 | 375 | if (chTotalBits & 0x01) |
Bobty | 2:cd2da920cf98 | 376 | break; |
Bobty | 2:cd2da920cf98 | 377 | chTotalBits = chTotalBits >> 1; |
Bobty | 2:cd2da920cf98 | 378 | rightShift++; |
Bobty | 2:cd2da920cf98 | 379 | } |
Bobty | 2:cd2da920cf98 | 380 | uint8_t charWidth = 8; |
Bobty | 2:cd2da920cf98 | 381 | for (int j = 0; j < FONT_WIDTH+1; j++) |
Bobty | 2:cd2da920cf98 | 382 | { |
Bobty | 2:cd2da920cf98 | 383 | if (chTotalBits & 0x80) |
Bobty | 2:cd2da920cf98 | 384 | break; |
Bobty | 2:cd2da920cf98 | 385 | chTotalBits = chTotalBits << 1; |
Bobty | 2:cd2da920cf98 | 386 | charWidth--; |
Bobty | 2:cd2da920cf98 | 387 | } |
Bobty | 2:cd2da920cf98 | 388 | |
Bobty | 2:cd2da920cf98 | 389 | // display character |
Bobty | 2:cd2da920cf98 | 390 | int xOffset = xPos / 8; |
Bobty | 2:cd2da920cf98 | 391 | int bitOffset = xPos % 8; |
Bobty | 2:cd2da920cf98 | 392 | // printf("%c %d %d %d %d\n", ch, charPos, charWidth, xOffset, bitOffset); |
Bobty | 2:cd2da920cf98 | 393 | if (xOffset >= (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 394 | return 0; |
Bobty | 2:cd2da920cf98 | 395 | |
Bobty | 2:cd2da920cf98 | 396 | // Copy the bits of the character into the buffer |
Bobty | 2:cd2da920cf98 | 397 | for (int i = 0; i < FONT_HEIGHT; i++) |
Bobty | 2:cd2da920cf98 | 398 | { |
Bobty | 2:cd2da920cf98 | 399 | // Check we don't go off the display buffer |
Bobty | 2:cd2da920cf98 | 400 | int rowIdx = i + yPos; |
Bobty | 2:cd2da920cf98 | 401 | if (rowIdx > height) |
Bobty | 2:cd2da920cf98 | 402 | break; |
Bobty | 2:cd2da920cf98 | 403 | |
Bobty | 2:cd2da920cf98 | 404 | // |
Bobty | 2:cd2da920cf98 | 405 | uint8_t chBits = font5x7[chIdxInFont][i] >> rightShift; |
Bobty | 2:cd2da920cf98 | 406 | int dispBufPos = (rowIdx * (dispBufWidth/8) + xOffset); |
Bobty | 2:cd2da920cf98 | 407 | _pDisplayBuf[dispBufPos] |= ((chBits << (8 - charWidth)) >> bitOffset); |
Bobty | 2:cd2da920cf98 | 408 | if (xOffset + 1 < (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 409 | _pDisplayBuf[dispBufPos + 1] |= ((chBits << (8-bitOffset)) << (8 - charWidth)); |
Bobty | 2:cd2da920cf98 | 410 | } |
Bobty | 2:cd2da920cf98 | 411 | |
Bobty | 2:cd2da920cf98 | 412 | return charWidth; |
Bobty | 1:79cf2e115449 | 413 | } |
Bobty | 1:79cf2e115449 | 414 | |
Bobty | 2:cd2da920cf98 | 415 | // Display a large digit |
Bobty | 2:cd2da920cf98 | 416 | int LEDMatrix::displayLargeDigit(int curX, int curY, char ch) |
Bobty | 1:79cf2e115449 | 417 | { |
Bobty | 2:cd2da920cf98 | 418 | // Bounds check |
Bobty | 2:cd2da920cf98 | 419 | if ((ch < '0') || (ch > '9')) |
Bobty | 2:cd2da920cf98 | 420 | return 0; |
Bobty | 2:cd2da920cf98 | 421 | |
Bobty | 2:cd2da920cf98 | 422 | // Get character data |
Bobty | 2:cd2da920cf98 | 423 | const uint8_t* charData = bigFont[ch-'0']; |
Bobty | 2:cd2da920cf98 | 424 | int numLines = sizeof(bigFont[0])/sizeof(bigFont[0][0]); |
Bobty | 2:cd2da920cf98 | 425 | |
Bobty | 2:cd2da920cf98 | 426 | // Find the position and width of the character |
Bobty | 2:cd2da920cf98 | 427 | uint16_t chTotalBits = 0; |
Bobty | 2:cd2da920cf98 | 428 | for (int i = 0; i < numLines; i++) |
Bobty | 2:cd2da920cf98 | 429 | chTotalBits |= charData[i]; |
Bobty | 2:cd2da920cf98 | 430 | uint16_t rightShift = 0; |
Bobty | 2:cd2da920cf98 | 431 | for (; rightShift < 16; rightShift++) |
Bobty | 2:cd2da920cf98 | 432 | { |
Bobty | 2:cd2da920cf98 | 433 | if (chTotalBits & 0x01) |
Bobty | 2:cd2da920cf98 | 434 | break; |
Bobty | 2:cd2da920cf98 | 435 | chTotalBits = chTotalBits >> 1; |
Bobty | 2:cd2da920cf98 | 436 | } |
Bobty | 2:cd2da920cf98 | 437 | uint16_t charWidth = 16; |
Bobty | 2:cd2da920cf98 | 438 | for (; charWidth > 0; charWidth--) |
Bobty | 2:cd2da920cf98 | 439 | { |
Bobty | 2:cd2da920cf98 | 440 | if (chTotalBits & 0x8000) |
Bobty | 2:cd2da920cf98 | 441 | break; |
Bobty | 2:cd2da920cf98 | 442 | chTotalBits = chTotalBits << 1; |
Bobty | 2:cd2da920cf98 | 443 | } |
Bobty | 2:cd2da920cf98 | 444 | |
Bobty | 2:cd2da920cf98 | 445 | // display character |
Bobty | 2:cd2da920cf98 | 446 | int xOffset = curX / 8; |
Bobty | 2:cd2da920cf98 | 447 | int bitOffset = curX % 8; |
Bobty | 2:cd2da920cf98 | 448 | // printf("%c %d %d %d %d %d\n", ch, curX, charWidth, rightShift, xOffset, bitOffset); |
Bobty | 2:cd2da920cf98 | 449 | if (xOffset >= (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 450 | return 0; |
Bobty | 2:cd2da920cf98 | 451 | for (int i = 0; i < numLines; i++) |
Bobty | 2:cd2da920cf98 | 452 | { |
Bobty | 2:cd2da920cf98 | 453 | uint32_t chBits = charData[i] >> rightShift; |
Bobty | 2:cd2da920cf98 | 454 | chBits = (chBits << (24-charWidth)) >> bitOffset; |
Bobty | 2:cd2da920cf98 | 455 | for (int j = 0; j < 3; j++) |
Bobty | 2:cd2da920cf98 | 456 | { |
Bobty | 2:cd2da920cf98 | 457 | if (xOffset + j >= (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 458 | break; |
Bobty | 2:cd2da920cf98 | 459 | _pDisplayBuf[(i + curY) * (dispBufWidth/8) + xOffset + j] |= ((chBits >> (16-j*8)) & 0xff); |
Bobty | 2:cd2da920cf98 | 460 | } |
Bobty | 2:cd2da920cf98 | 461 | } |
Bobty | 2:cd2da920cf98 | 462 | |
Bobty | 2:cd2da920cf98 | 463 | return charWidth; |
Bobty | 1:79cf2e115449 | 464 | } |
Bobty | 2:cd2da920cf98 | 465 | |
Bobty | 2:cd2da920cf98 | 466 | // Display line of characters |
Bobty | 2:cd2da920cf98 | 467 | int LEDMatrix::displayLine(int lineIdx, const char* line) |
Bobty | 2:cd2da920cf98 | 468 | { |
Bobty | 2:cd2da920cf98 | 469 | if (lineIdx >= numLines) |
Bobty | 2:cd2da920cf98 | 470 | lineIdx = 0; |
Bobty | 2:cd2da920cf98 | 471 | _isBusy = true; |
Bobty | 2:cd2da920cf98 | 472 | int curX = 0; |
Bobty | 2:cd2da920cf98 | 473 | int curY = lineIdx * height/numLines; |
Bobty | 2:cd2da920cf98 | 474 | for (int chIdx = 0; chIdx < strlen(line); chIdx++) |
Bobty | 2:cd2da920cf98 | 475 | { |
Bobty | 2:cd2da920cf98 | 476 | curX += displayChar(curX, curY, line[chIdx]) + _charSeparation; |
Bobty | 2:cd2da920cf98 | 477 | } |
Bobty | 2:cd2da920cf98 | 478 | _isBusy = false; |
Bobty | 2:cd2da920cf98 | 479 | return curX; |
Bobty | 2:cd2da920cf98 | 480 | } |
Bobty | 2:cd2da920cf98 | 481 |