Forked LEDMatrix and added horizontal scrolling
Fork of LEDMatrix by
LEDMatrix.cpp@5:334fc002e200, 2016-01-15 (annotated)
- Committer:
- Bobty
- Date:
- Fri Jan 15 12:18:34 2016 +0000
- Revision:
- 5:334fc002e200
- Parent:
- 4:40d4afefcd74
Cleared inversion on clear(); Changed setAlert to setHighlight
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 | 5:334fc002e200 | 56 | _lineHighlight[i] = false; |
Bobty | 3:1e06e89bc0c9 | 57 | _lineInvert[i] = false; |
Bobty | 2:cd2da920cf98 | 58 | } |
Bobty | 2:cd2da920cf98 | 59 | _isBusy = false; |
Bobty | 2:cd2da920cf98 | 60 | _charSeparation = 1; |
Bobty | 3:1e06e89bc0c9 | 61 | _flashCounter = 0; |
Bobty | 4:40d4afefcd74 | 62 | _flashRate = 50; |
Bobty | 3:1e06e89bc0c9 | 63 | _flashState = false; |
Bobty | 4:40d4afefcd74 | 64 | _scrollCounter = 0; |
Bobty | 4:40d4afefcd74 | 65 | _scrollRate = 7; |
yihui | 0:13728deac7a7 | 66 | } |
yihui | 0:13728deac7a7 | 67 | |
Bobty | 3:1e06e89bc0c9 | 68 | void LEDMatrix::begin(uint8_t *_pDisplayBuf, uint16_t width, uint16_t height, uint16_t dispBufWidth, |
Bobty | 4:40d4afefcd74 | 69 | uint16_t numLines, int charSeparation, int flashRate, int scrollRate) |
yihui | 0:13728deac7a7 | 70 | { |
Bobty | 2:cd2da920cf98 | 71 | ASSERT(0 == (width % LED_MATRIX_LEDS_HORIZONTALLY)); |
Bobty | 2:cd2da920cf98 | 72 | ASSERT(0 == (scroll_width % LED_MATRIX_LEDS_HORIZONTALLY)); |
Bobty | 2:cd2da920cf98 | 73 | ASSERT(0 == (height % LED_MATRIX_LEDS_VERTICALLY)); |
yihui | 0:13728deac7a7 | 74 | |
Bobty | 2:cd2da920cf98 | 75 | this->_pDisplayBuf = _pDisplayBuf; |
yihui | 0:13728deac7a7 | 76 | this->width = width; |
yihui | 0:13728deac7a7 | 77 | this->height = height; |
Bobty | 2:cd2da920cf98 | 78 | this->dispBufWidth = dispBufWidth; |
Bobty | 2:cd2da920cf98 | 79 | this->numLines = numLines; |
Bobty | 2:cd2da920cf98 | 80 | this->_charSeparation = charSeparation; |
Bobty | 4:40d4afefcd74 | 81 | if (flashRate > 0) |
Bobty | 4:40d4afefcd74 | 82 | this->_flashRate = flashRate; |
Bobty | 4:40d4afefcd74 | 83 | if (scrollRate > 0) |
Bobty | 4:40d4afefcd74 | 84 | this->_scrollRate = scrollRate; |
Bobty | 2:cd2da920cf98 | 85 | if (numLines > LED_MATRIX_MAX_LINES) |
Bobty | 2:cd2da920cf98 | 86 | this->numLines = LED_MATRIX_MAX_LINES; |
Bobty | 2:cd2da920cf98 | 87 | for (int i = 0; i < LED_MATRIX_LEDS_VERTICALLY; i++) |
Bobty | 2:cd2da920cf98 | 88 | { |
Bobty | 2:cd2da920cf98 | 89 | this->_hScrollWidth[i] = dispBufWidth; |
Bobty | 2:cd2da920cf98 | 90 | } |
yihui | 0:13728deac7a7 | 91 | |
Bobty | 2:cd2da920cf98 | 92 | _isEnabled = true; |
yihui | 0:13728deac7a7 | 93 | } |
yihui | 0:13728deac7a7 | 94 | |
yihui | 0:13728deac7a7 | 95 | void LEDMatrix::drawPoint(uint16_t x, uint16_t y, uint8_t pixel) |
yihui | 0:13728deac7a7 | 96 | { |
Bobty | 2:cd2da920cf98 | 97 | ASSERT(dispBufWidth > x); |
yihui | 0:13728deac7a7 | 98 | ASSERT(height > y); |
yihui | 0:13728deac7a7 | 99 | |
Bobty | 2:cd2da920cf98 | 100 | uint8_t *byte = _pDisplayBuf + (height - 1 - y) * dispBufWidth / 8 + x / 8; |
Bobty | 2:cd2da920cf98 | 101 | uint8_t bit = x % 8; |
yihui | 0:13728deac7a7 | 102 | |
Bobty | 2:cd2da920cf98 | 103 | if (pixel) |
Bobty | 2:cd2da920cf98 | 104 | { |
yihui | 0:13728deac7a7 | 105 | *byte |= 0x80 >> bit; |
Bobty | 2:cd2da920cf98 | 106 | } |
Bobty | 2:cd2da920cf98 | 107 | else |
Bobty | 2:cd2da920cf98 | 108 | { |
yihui | 0:13728deac7a7 | 109 | *byte &= ~(0x80 >> bit); |
yihui | 0:13728deac7a7 | 110 | } |
yihui | 0:13728deac7a7 | 111 | } |
yihui | 0:13728deac7a7 | 112 | |
yihui | 0:13728deac7a7 | 113 | void LEDMatrix::drawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t pixel) |
yihui | 0:13728deac7a7 | 114 | { |
Bobty | 2:cd2da920cf98 | 115 | for (uint16_t x = x1; x < x2; x++) |
Bobty | 2:cd2da920cf98 | 116 | { |
Bobty | 2:cd2da920cf98 | 117 | for (uint16_t y = y1; y < y2; y++) |
Bobty | 2:cd2da920cf98 | 118 | { |
yihui | 0:13728deac7a7 | 119 | drawPoint(x, y, pixel); |
yihui | 0:13728deac7a7 | 120 | } |
yihui | 0:13728deac7a7 | 121 | } |
yihui | 0:13728deac7a7 | 122 | } |
yihui | 0:13728deac7a7 | 123 | |
yihui | 0:13728deac7a7 | 124 | void LEDMatrix::drawImage(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t *image) |
yihui | 0:13728deac7a7 | 125 | { |
yihui | 0:13728deac7a7 | 126 | ASSERT(0 == ((x2 - x1) % 8)); |
yihui | 0:13728deac7a7 | 127 | |
Bobty | 2:cd2da920cf98 | 128 | for (uint16_t x = x1; x < x2; x++) |
Bobty | 2:cd2da920cf98 | 129 | { |
Bobty | 2:cd2da920cf98 | 130 | for (uint16_t y = y1; y < y2; y++) |
Bobty | 2:cd2da920cf98 | 131 | { |
yihui | 0:13728deac7a7 | 132 | uint8_t *byte = image + x * 8 + y / 8; |
yihui | 0:13728deac7a7 | 133 | uint8_t bit = 7 - (y % 8); |
yihui | 0:13728deac7a7 | 134 | uint8_t pixel = (*byte >> bit) & 1; |
yihui | 0:13728deac7a7 | 135 | drawPoint(x, y, pixel); |
yihui | 0:13728deac7a7 | 136 | } |
yihui | 0:13728deac7a7 | 137 | } |
yihui | 0:13728deac7a7 | 138 | } |
yihui | 0:13728deac7a7 | 139 | |
Bobty | 2:cd2da920cf98 | 140 | //void LEDMatrix::clear() |
Bobty | 2:cd2da920cf98 | 141 | //{ |
Bobty | 2:cd2da920cf98 | 142 | // uint8_t *ptr = _pDisplayBuf; |
Bobty | 2:cd2da920cf98 | 143 | // for (uint16_t i = 0; i < (dispBufWidth * height / 8); i++) |
Bobty | 2:cd2da920cf98 | 144 | // { |
Bobty | 2:cd2da920cf98 | 145 | // *ptr = 0x00; |
Bobty | 2:cd2da920cf98 | 146 | // ptr++; |
Bobty | 2:cd2da920cf98 | 147 | // } |
Bobty | 2:cd2da920cf98 | 148 | //} |
yihui | 0:13728deac7a7 | 149 | |
Bobty | 2:cd2da920cf98 | 150 | void LEDMatrix::invertColour() |
yihui | 0:13728deac7a7 | 151 | { |
yihui | 0:13728deac7a7 | 152 | mask = ~mask; |
yihui | 0:13728deac7a7 | 153 | } |
yihui | 0:13728deac7a7 | 154 | |
Bobty | 2:cd2da920cf98 | 155 | uint8_t LEDMatrix::isInvertedColour() |
yihui | 0:13728deac7a7 | 156 | { |
yihui | 0:13728deac7a7 | 157 | return mask; |
yihui | 0:13728deac7a7 | 158 | } |
yihui | 0:13728deac7a7 | 159 | |
yihui | 0:13728deac7a7 | 160 | void LEDMatrix::scan() |
yihui | 0:13728deac7a7 | 161 | { |
Bobty | 2:cd2da920cf98 | 162 | // On each call this function handles one row of the display |
Bobty | 2:cd2da920cf98 | 163 | static uint8_t scanRowIdx = 0; |
yihui | 0:13728deac7a7 | 164 | |
Bobty | 2:cd2da920cf98 | 165 | // Check if being updated |
Bobty | 2:cd2da920cf98 | 166 | if (_isBusy) |
yihui | 0:13728deac7a7 | 167 | return; |
Bobty | 2:cd2da920cf98 | 168 | |
Bobty | 2:cd2da920cf98 | 169 | // Check if display enabled |
Bobty | 2:cd2da920cf98 | 170 | if (!_isEnabled) |
Bobty | 2:cd2da920cf98 | 171 | return; |
yihui | 0:13728deac7a7 | 172 | |
Bobty | 2:cd2da920cf98 | 173 | // Base of this scan row in buffer to display |
Bobty | 2:cd2da920cf98 | 174 | uint8_t *pBufBase = _pDisplayBuf + scanRowIdx * (dispBufWidth / 8); |
Bobty | 2:cd2da920cf98 | 175 | |
Bobty | 2:cd2da920cf98 | 176 | // Handle multiple units vertically |
Bobty | 2:cd2da920cf98 | 177 | for (int rowIdx = 0; rowIdx < (height / LED_MATRIX_LEDS_VERTICALLY); rowIdx++) |
Bobty | 1:79cf2e115449 | 178 | { |
Bobty | 2:cd2da920cf98 | 179 | // Calculate buffer position within this unit |
Bobty | 2:cd2da920cf98 | 180 | uint8_t *pBuf = pBufBase + rowIdx * (dispBufWidth / 8) * LED_MATRIX_LEDS_VERTICALLY; |
yihui | 0:13728deac7a7 | 181 | |
Bobty | 3:1e06e89bc0c9 | 182 | // Work out which display line we're in |
Bobty | 3:1e06e89bc0c9 | 183 | uint8_t dispMask = mask; |
Bobty | 3:1e06e89bc0c9 | 184 | int rowsInLine = (height/numLines); |
Bobty | 3:1e06e89bc0c9 | 185 | int dispLine = scanRowIdx / rowsInLine; |
Bobty | 3:1e06e89bc0c9 | 186 | if (dispLine < numLines) |
Bobty | 3:1e06e89bc0c9 | 187 | { |
Bobty | 3:1e06e89bc0c9 | 188 | if (_lineInvert[dispLine]) |
Bobty | 3:1e06e89bc0c9 | 189 | dispMask = ~dispMask; |
Bobty | 3:1e06e89bc0c9 | 190 | } |
Bobty | 3:1e06e89bc0c9 | 191 | |
Bobty | 2:cd2da920cf98 | 192 | // Work along the display row sending out data as we go |
Bobty | 2:cd2da920cf98 | 193 | // Noting that the first data we send out will be shunted to the end of the row |
Bobty | 2:cd2da920cf98 | 194 | int hScrollPos = _hScrollPos[scanRowIdx]; |
Bobty | 2:cd2da920cf98 | 195 | int hScrollWidth = _hScrollWidth[scanRowIdx]; |
Bobty | 2:cd2da920cf98 | 196 | if (hScrollWidth > dispBufWidth) |
Bobty | 2:cd2da920cf98 | 197 | hScrollWidth = dispBufWidth; |
Bobty | 2:cd2da920cf98 | 198 | int bitOffset = hScrollPos % 8; |
Bobty | 2:cd2da920cf98 | 199 | for (int byteIdx = (width / 8) - 1; byteIdx >= 0; byteIdx--) |
Bobty | 1:79cf2e115449 | 200 | { |
Bobty | 2:cd2da920cf98 | 201 | // When a row is scrolled a single byte on the display can be a combination of two buffer bytes |
Bobty | 2:cd2da920cf98 | 202 | uint8_t* pByte1 = pBuf + ((byteIdx*8 + hScrollPos) % hScrollWidth) / 8; |
Bobty | 2:cd2da920cf98 | 203 | uint8_t* pByte2 = pBuf + (((byteIdx+1)*8 + hScrollPos) % hScrollWidth) / 8; |
Bobty | 2:cd2da920cf98 | 204 | uint8_t pixels = ((*pByte1) << bitOffset) + (((*pByte2) >> (8 - bitOffset)) % 256); |
Bobty | 2:cd2da920cf98 | 205 | |
Bobty | 2:cd2da920cf98 | 206 | // Reverse the bits so they come out in the right order |
Bobty | 3:1e06e89bc0c9 | 207 | pixels = reverseBits(pixels) ^ dispMask; // reverse: mask = 0xff, normal: mask =0x00 |
Bobty | 1:79cf2e115449 | 208 | for (uint8_t bit = 0; bit < 8; bit++) |
Bobty | 1:79cf2e115449 | 209 | { |
yihui | 0:13728deac7a7 | 210 | clk = 0; |
yihui | 0:13728deac7a7 | 211 | r1 = pixels & (0x80 >> bit); |
yihui | 0:13728deac7a7 | 212 | clk = 1; |
yihui | 0:13728deac7a7 | 213 | } |
yihui | 0:13728deac7a7 | 214 | } |
yihui | 0:13728deac7a7 | 215 | } |
yihui | 0:13728deac7a7 | 216 | |
Bobty | 2:cd2da920cf98 | 217 | // Disable display |
Bobty | 2:cd2da920cf98 | 218 | oe = 1; |
yihui | 0:13728deac7a7 | 219 | |
Bobty | 2:cd2da920cf98 | 220 | // Select row (rows are muxed) |
Bobty | 2:cd2da920cf98 | 221 | int rowSel = LED_MATRIX_LEDS_VERTICALLY - 1 - scanRowIdx; |
Bobty | 2:cd2da920cf98 | 222 | a = (rowSel & 0x01); |
Bobty | 2:cd2da920cf98 | 223 | b = (rowSel & 0x02); |
Bobty | 2:cd2da920cf98 | 224 | c = (rowSel & 0x04); |
Bobty | 2:cd2da920cf98 | 225 | d = (rowSel & 0x08); |
yihui | 0:13728deac7a7 | 226 | |
Bobty | 2:cd2da920cf98 | 227 | // Latch data |
yihui | 0:13728deac7a7 | 228 | stb = 0; |
yihui | 0:13728deac7a7 | 229 | stb = 1; |
yihui | 0:13728deac7a7 | 230 | |
Bobty | 2:cd2da920cf98 | 231 | // Reenable display |
Bobty | 2:cd2da920cf98 | 232 | oe = 0; |
yihui | 0:13728deac7a7 | 233 | |
Bobty | 2:cd2da920cf98 | 234 | // Move the scan row on for next time |
Bobty | 2:cd2da920cf98 | 235 | scanRowIdx = (scanRowIdx + 1) & 0x0F; |
yihui | 0:13728deac7a7 | 236 | } |
yihui | 0:13728deac7a7 | 237 | |
yihui | 0:13728deac7a7 | 238 | void LEDMatrix::on() |
yihui | 0:13728deac7a7 | 239 | { |
Bobty | 2:cd2da920cf98 | 240 | _isEnabled = true; |
yihui | 0:13728deac7a7 | 241 | } |
yihui | 0:13728deac7a7 | 242 | |
yihui | 0:13728deac7a7 | 243 | void LEDMatrix::off() |
yihui | 0:13728deac7a7 | 244 | { |
Bobty | 2:cd2da920cf98 | 245 | _isEnabled = false; |
yihui | 0:13728deac7a7 | 246 | oe = 1; |
yihui | 0:13728deac7a7 | 247 | } |
yihui | 0:13728deac7a7 | 248 | |
Bobty | 2:cd2da920cf98 | 249 | bool LEDMatrix::getRowsToWorkOn(int lineIdx, int &startRow, int &numRows) |
Bobty | 2:cd2da920cf98 | 250 | { |
Bobty | 2:cd2da920cf98 | 251 | // lineIdx == -1 means all lines |
Bobty | 2:cd2da920cf98 | 252 | startRow = 0; |
Bobty | 2:cd2da920cf98 | 253 | numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 254 | if (lineIdx != -1) |
Bobty | 2:cd2da920cf98 | 255 | { |
Bobty | 2:cd2da920cf98 | 256 | if ((lineIdx < 0) || (lineIdx >= numLines)) |
Bobty | 2:cd2da920cf98 | 257 | return false; |
Bobty | 2:cd2da920cf98 | 258 | numRows = height / numLines; |
Bobty | 2:cd2da920cf98 | 259 | startRow = lineIdx * numRows; |
Bobty | 2:cd2da920cf98 | 260 | } |
Bobty | 2:cd2da920cf98 | 261 | return true; |
Bobty | 2:cd2da920cf98 | 262 | } |
Bobty | 2:cd2da920cf98 | 263 | |
Bobty | 2:cd2da920cf98 | 264 | void LEDMatrix::scrollReset(int lineIdx) |
Bobty | 2:cd2da920cf98 | 265 | { |
Bobty | 2:cd2da920cf98 | 266 | // Interpret param |
Bobty | 2:cd2da920cf98 | 267 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 268 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 269 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 270 | return; |
Bobty | 2:cd2da920cf98 | 271 | // Reset scroll position all rows |
Bobty | 2:cd2da920cf98 | 272 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 273 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 274 | } |
Bobty | 2:cd2da920cf98 | 275 | |
Bobty | 2:cd2da920cf98 | 276 | void LEDMatrix::scroll(int lineIdx, bool scrollLeft) |
Bobty | 2:cd2da920cf98 | 277 | { |
Bobty | 2:cd2da920cf98 | 278 | // Interpret param |
Bobty | 2:cd2da920cf98 | 279 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 280 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 281 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 282 | return; |
Bobty | 2:cd2da920cf98 | 283 | // Reset scroll position all rows |
Bobty | 2:cd2da920cf98 | 284 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 285 | { |
Bobty | 2:cd2da920cf98 | 286 | if (scrollLeft) |
Bobty | 2:cd2da920cf98 | 287 | { |
Bobty | 2:cd2da920cf98 | 288 | _hScrollPos[i]++; |
Bobty | 2:cd2da920cf98 | 289 | if (_hScrollPos[i] >= _hScrollWidth[i]) |
Bobty | 2:cd2da920cf98 | 290 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 291 | } |
Bobty | 2:cd2da920cf98 | 292 | else |
Bobty | 2:cd2da920cf98 | 293 | { |
Bobty | 2:cd2da920cf98 | 294 | _hScrollPos[i]--; |
Bobty | 2:cd2da920cf98 | 295 | if (_hScrollPos[i] < 0) |
Bobty | 2:cd2da920cf98 | 296 | _hScrollPos[i] = _hScrollWidth[i]-1; |
Bobty | 2:cd2da920cf98 | 297 | } |
Bobty | 2:cd2da920cf98 | 298 | } |
Bobty | 2:cd2da920cf98 | 299 | } |
Bobty | 2:cd2da920cf98 | 300 | |
Bobty | 2:cd2da920cf98 | 301 | void LEDMatrix::scrollToPos(int lineIdx, int pos) |
Bobty | 1:79cf2e115449 | 302 | { |
Bobty | 2:cd2da920cf98 | 303 | // Interpret param |
Bobty | 2:cd2da920cf98 | 304 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 305 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 306 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 307 | return; |
Bobty | 2:cd2da920cf98 | 308 | // Check pos |
Bobty | 2:cd2da920cf98 | 309 | if ((pos < 0) || (pos >= dispBufWidth)) |
Bobty | 2:cd2da920cf98 | 310 | return; |
Bobty | 2:cd2da920cf98 | 311 | // Reset scroll position all rows |
Bobty | 2:cd2da920cf98 | 312 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 313 | _hScrollPos[i] = pos; |
Bobty | 2:cd2da920cf98 | 314 | } |
Bobty | 2:cd2da920cf98 | 315 | |
Bobty | 2:cd2da920cf98 | 316 | void LEDMatrix::clear(int lineIdx) |
Bobty | 2:cd2da920cf98 | 317 | { |
Bobty | 2:cd2da920cf98 | 318 | // Interpret param |
Bobty | 2:cd2da920cf98 | 319 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 320 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 321 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 322 | return; |
Bobty | 2:cd2da920cf98 | 323 | // Clear section |
Bobty | 2:cd2da920cf98 | 324 | uint8_t *ptr = _pDisplayBuf + startRow * (dispBufWidth / 8); |
Bobty | 2:cd2da920cf98 | 325 | int bytesToZero = numRows * (dispBufWidth / 8); |
Bobty | 2:cd2da920cf98 | 326 | for (int i = 0; i < bytesToZero; i++) |
Bobty | 2:cd2da920cf98 | 327 | *ptr++ = 0x00; |
Bobty | 5:334fc002e200 | 328 | // Stop invert |
Bobty | 5:334fc002e200 | 329 | for (int i = 0; i < LED_MATRIX_MAX_LINES; i++) |
Bobty | 5:334fc002e200 | 330 | _lineInvert[i] = false; |
Bobty | 2:cd2da920cf98 | 331 | } |
Bobty | 2:cd2da920cf98 | 332 | |
Bobty | 4:40d4afefcd74 | 333 | void LEDMatrix::setScrollRate(int rate) |
Bobty | 4:40d4afefcd74 | 334 | { |
Bobty | 4:40d4afefcd74 | 335 | _scrollRate = rate; |
Bobty | 4:40d4afefcd74 | 336 | } |
Bobty | 4:40d4afefcd74 | 337 | |
Bobty | 4:40d4afefcd74 | 338 | void LEDMatrix::setFlashRate(int rate) |
Bobty | 4:40d4afefcd74 | 339 | { |
Bobty | 4:40d4afefcd74 | 340 | _flashRate = rate; |
Bobty | 4:40d4afefcd74 | 341 | } |
Bobty | 4:40d4afefcd74 | 342 | |
Bobty | 2:cd2da920cf98 | 343 | void LEDMatrix::setupScroll(int lineIdx, int scrollWidth, int scrollInc) |
Bobty | 2:cd2da920cf98 | 344 | { |
Bobty | 2:cd2da920cf98 | 345 | // Interpret param |
Bobty | 2:cd2da920cf98 | 346 | int startRow = 0; |
Bobty | 2:cd2da920cf98 | 347 | int numRows = LED_MATRIX_LEDS_VERTICALLY; |
Bobty | 2:cd2da920cf98 | 348 | if (!getRowsToWorkOn(lineIdx, startRow, numRows)) |
Bobty | 2:cd2da920cf98 | 349 | return; |
Bobty | 2:cd2da920cf98 | 350 | scrollWidth = (((scrollWidth / 8) + 1) * 8); |
Bobty | 2:cd2da920cf98 | 351 | if (scrollWidth <= 0) |
Bobty | 2:cd2da920cf98 | 352 | return; |
Bobty | 2:cd2da920cf98 | 353 | for (int i = startRow; i < startRow+numRows; i++) |
Bobty | 2:cd2da920cf98 | 354 | { |
Bobty | 2:cd2da920cf98 | 355 | _hScrollPos[i] = 0; |
Bobty | 2:cd2da920cf98 | 356 | _hScrollWidth[i] = scrollWidth; |
Bobty | 2:cd2da920cf98 | 357 | } |
Bobty | 3:1e06e89bc0c9 | 358 | // Store the scroll increment |
Bobty | 3:1e06e89bc0c9 | 359 | int startLine = 0; |
Bobty | 3:1e06e89bc0c9 | 360 | int linesToProcess = numLines; |
Bobty | 3:1e06e89bc0c9 | 361 | if (lineIdx != -1) |
Bobty | 3:1e06e89bc0c9 | 362 | { |
Bobty | 3:1e06e89bc0c9 | 363 | if ((lineIdx < 0) || (lineIdx >= numLines)) |
Bobty | 3:1e06e89bc0c9 | 364 | return; |
Bobty | 3:1e06e89bc0c9 | 365 | startLine = lineIdx; |
Bobty | 3:1e06e89bc0c9 | 366 | linesToProcess = 1; |
Bobty | 3:1e06e89bc0c9 | 367 | } |
Bobty | 3:1e06e89bc0c9 | 368 | for (int i = 0; i < linesToProcess; i++) |
Bobty | 3:1e06e89bc0c9 | 369 | _lineScrollInc[i+startLine] = scrollInc; |
Bobty | 2:cd2da920cf98 | 370 | } |
Bobty | 2:cd2da920cf98 | 371 | |
Bobty | 5:334fc002e200 | 372 | void LEDMatrix::setHighlight(int lineIdx, bool highlightOn) |
Bobty | 3:1e06e89bc0c9 | 373 | { |
Bobty | 5:334fc002e200 | 374 | // Store the highlight status |
Bobty | 3:1e06e89bc0c9 | 375 | int startLine = 0; |
Bobty | 3:1e06e89bc0c9 | 376 | int linesToProcess = numLines; |
Bobty | 3:1e06e89bc0c9 | 377 | if (lineIdx != -1) |
Bobty | 3:1e06e89bc0c9 | 378 | { |
Bobty | 3:1e06e89bc0c9 | 379 | if ((lineIdx < 0) || (lineIdx >= numLines)) |
Bobty | 3:1e06e89bc0c9 | 380 | return; |
Bobty | 3:1e06e89bc0c9 | 381 | startLine = lineIdx; |
Bobty | 3:1e06e89bc0c9 | 382 | linesToProcess = 1; |
Bobty | 3:1e06e89bc0c9 | 383 | } |
Bobty | 3:1e06e89bc0c9 | 384 | for (int i = 0; i < linesToProcess; i++) |
Bobty | 5:334fc002e200 | 385 | _lineHighlight[i+startLine] = highlightOn; |
Bobty | 3:1e06e89bc0c9 | 386 | } |
Bobty | 3:1e06e89bc0c9 | 387 | |
Bobty | 2:cd2da920cf98 | 388 | void LEDMatrix::serviceEffects() |
Bobty | 2:cd2da920cf98 | 389 | { |
Bobty | 4:40d4afefcd74 | 390 | // Scroll logic |
Bobty | 4:40d4afefcd74 | 391 | _scrollCounter++; |
Bobty | 4:40d4afefcd74 | 392 | if (_scrollCounter >= _scrollRate) |
Bobty | 2:cd2da920cf98 | 393 | { |
Bobty | 4:40d4afefcd74 | 394 | _scrollCounter = 0; |
Bobty | 4:40d4afefcd74 | 395 | int rowsInLine = (height / numLines); |
Bobty | 4:40d4afefcd74 | 396 | for (int i = 0; i < numLines; i++) |
Bobty | 4:40d4afefcd74 | 397 | { |
Bobty | 4:40d4afefcd74 | 398 | for (int j = 0; j < rowsInLine; j++) |
Bobty | 4:40d4afefcd74 | 399 | _hScrollPos[i*rowsInLine+j] += _lineScrollInc[i]; |
Bobty | 4:40d4afefcd74 | 400 | } |
Bobty | 3:1e06e89bc0c9 | 401 | } |
Bobty | 3:1e06e89bc0c9 | 402 | |
Bobty | 3:1e06e89bc0c9 | 403 | // Update flash state |
Bobty | 3:1e06e89bc0c9 | 404 | _flashCounter++; |
Bobty | 3:1e06e89bc0c9 | 405 | if (_flashCounter >= _flashRate) |
Bobty | 3:1e06e89bc0c9 | 406 | { |
Bobty | 3:1e06e89bc0c9 | 407 | _flashCounter = 0; |
Bobty | 3:1e06e89bc0c9 | 408 | _flashState = !_flashState; |
Bobty | 4:40d4afefcd74 | 409 | for (int i = 0; i < numLines; i++) |
Bobty | 5:334fc002e200 | 410 | _lineInvert[i] = _lineHighlight[i] ? _flashState : false; |
Bobty | 2:cd2da920cf98 | 411 | } |
Bobty | 2:cd2da920cf98 | 412 | } |
Bobty | 2:cd2da920cf98 | 413 | |
Bobty | 2:cd2da920cf98 | 414 | // Reverse bits in byte |
Bobty | 2:cd2da920cf98 | 415 | uint8_t LEDMatrix::reverseBits(uint8_t b) |
Bobty | 2:cd2da920cf98 | 416 | { |
Bobty | 2:cd2da920cf98 | 417 | b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; |
Bobty | 2:cd2da920cf98 | 418 | b = (b & 0xCC) >> 2 | (b & 0x33) << 2; |
Bobty | 2:cd2da920cf98 | 419 | b = (b & 0xAA) >> 1 | (b & 0x55) << 1; |
Bobty | 2:cd2da920cf98 | 420 | return b; |
Bobty | 1:79cf2e115449 | 421 | } |
Bobty | 1:79cf2e115449 | 422 | |
Bobty | 2:cd2da920cf98 | 423 | // Display ASCII char |
Bobty | 2:cd2da920cf98 | 424 | int LEDMatrix::displayChar(int xPos, int yPos, char ch) |
Bobty | 1:79cf2e115449 | 425 | { |
Bobty | 2:cd2da920cf98 | 426 | const int FONT_HEIGHT = 7; |
Bobty | 2:cd2da920cf98 | 427 | const int FONT_WIDTH = 5; |
Bobty | 2:cd2da920cf98 | 428 | |
Bobty | 2:cd2da920cf98 | 429 | // Find the width of the character |
Bobty | 2:cd2da920cf98 | 430 | uint8_t chTotalBits = 0; |
Bobty | 2:cd2da920cf98 | 431 | int chIdxInFont = (ch % 128) - 0x20; |
Bobty | 2:cd2da920cf98 | 432 | // Special case for £, euro and yen signs |
Bobty | 2:cd2da920cf98 | 433 | if ((ch >= 0xa3) && (ch <= 0xa5)) |
Bobty | 2:cd2da920cf98 | 434 | chIdxInFont = ch - 0xa3 + 128 - ' '; |
Bobty | 2:cd2da920cf98 | 435 | for (int i = 0; i < FONT_HEIGHT; i++) |
Bobty | 2:cd2da920cf98 | 436 | { |
Bobty | 2:cd2da920cf98 | 437 | uint8_t chBits = font5x7[chIdxInFont][i]; |
Bobty | 2:cd2da920cf98 | 438 | chTotalBits |= chBits; |
Bobty | 2:cd2da920cf98 | 439 | } |
Bobty | 2:cd2da920cf98 | 440 | uint8_t rightShift = 0; |
Bobty | 2:cd2da920cf98 | 441 | for (int j = 0; j < FONT_WIDTH; j++) |
Bobty | 2:cd2da920cf98 | 442 | { |
Bobty | 2:cd2da920cf98 | 443 | if (chTotalBits & 0x01) |
Bobty | 2:cd2da920cf98 | 444 | break; |
Bobty | 2:cd2da920cf98 | 445 | chTotalBits = chTotalBits >> 1; |
Bobty | 2:cd2da920cf98 | 446 | rightShift++; |
Bobty | 2:cd2da920cf98 | 447 | } |
Bobty | 2:cd2da920cf98 | 448 | uint8_t charWidth = 8; |
Bobty | 2:cd2da920cf98 | 449 | for (int j = 0; j < FONT_WIDTH+1; j++) |
Bobty | 2:cd2da920cf98 | 450 | { |
Bobty | 2:cd2da920cf98 | 451 | if (chTotalBits & 0x80) |
Bobty | 2:cd2da920cf98 | 452 | break; |
Bobty | 2:cd2da920cf98 | 453 | chTotalBits = chTotalBits << 1; |
Bobty | 2:cd2da920cf98 | 454 | charWidth--; |
Bobty | 2:cd2da920cf98 | 455 | } |
Bobty | 2:cd2da920cf98 | 456 | |
Bobty | 2:cd2da920cf98 | 457 | // display character |
Bobty | 2:cd2da920cf98 | 458 | int xOffset = xPos / 8; |
Bobty | 2:cd2da920cf98 | 459 | int bitOffset = xPos % 8; |
Bobty | 2:cd2da920cf98 | 460 | // printf("%c %d %d %d %d\n", ch, charPos, charWidth, xOffset, bitOffset); |
Bobty | 2:cd2da920cf98 | 461 | if (xOffset >= (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 462 | return 0; |
Bobty | 2:cd2da920cf98 | 463 | |
Bobty | 2:cd2da920cf98 | 464 | // Copy the bits of the character into the buffer |
Bobty | 2:cd2da920cf98 | 465 | for (int i = 0; i < FONT_HEIGHT; i++) |
Bobty | 2:cd2da920cf98 | 466 | { |
Bobty | 2:cd2da920cf98 | 467 | // Check we don't go off the display buffer |
Bobty | 2:cd2da920cf98 | 468 | int rowIdx = i + yPos; |
Bobty | 2:cd2da920cf98 | 469 | if (rowIdx > height) |
Bobty | 2:cd2da920cf98 | 470 | break; |
Bobty | 2:cd2da920cf98 | 471 | |
Bobty | 2:cd2da920cf98 | 472 | // |
Bobty | 2:cd2da920cf98 | 473 | uint8_t chBits = font5x7[chIdxInFont][i] >> rightShift; |
Bobty | 2:cd2da920cf98 | 474 | int dispBufPos = (rowIdx * (dispBufWidth/8) + xOffset); |
Bobty | 2:cd2da920cf98 | 475 | _pDisplayBuf[dispBufPos] |= ((chBits << (8 - charWidth)) >> bitOffset); |
Bobty | 2:cd2da920cf98 | 476 | if (xOffset + 1 < (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 477 | _pDisplayBuf[dispBufPos + 1] |= ((chBits << (8-bitOffset)) << (8 - charWidth)); |
Bobty | 2:cd2da920cf98 | 478 | } |
Bobty | 2:cd2da920cf98 | 479 | |
Bobty | 2:cd2da920cf98 | 480 | return charWidth; |
Bobty | 1:79cf2e115449 | 481 | } |
Bobty | 1:79cf2e115449 | 482 | |
Bobty | 2:cd2da920cf98 | 483 | // Display a large digit |
Bobty | 2:cd2da920cf98 | 484 | int LEDMatrix::displayLargeDigit(int curX, int curY, char ch) |
Bobty | 1:79cf2e115449 | 485 | { |
Bobty | 2:cd2da920cf98 | 486 | // Bounds check |
Bobty | 2:cd2da920cf98 | 487 | if ((ch < '0') || (ch > '9')) |
Bobty | 2:cd2da920cf98 | 488 | return 0; |
Bobty | 2:cd2da920cf98 | 489 | |
Bobty | 2:cd2da920cf98 | 490 | // Get character data |
Bobty | 2:cd2da920cf98 | 491 | const uint8_t* charData = bigFont[ch-'0']; |
Bobty | 2:cd2da920cf98 | 492 | int numLines = sizeof(bigFont[0])/sizeof(bigFont[0][0]); |
Bobty | 2:cd2da920cf98 | 493 | |
Bobty | 2:cd2da920cf98 | 494 | // Find the position and width of the character |
Bobty | 2:cd2da920cf98 | 495 | uint16_t chTotalBits = 0; |
Bobty | 2:cd2da920cf98 | 496 | for (int i = 0; i < numLines; i++) |
Bobty | 2:cd2da920cf98 | 497 | chTotalBits |= charData[i]; |
Bobty | 2:cd2da920cf98 | 498 | uint16_t rightShift = 0; |
Bobty | 2:cd2da920cf98 | 499 | for (; rightShift < 16; rightShift++) |
Bobty | 2:cd2da920cf98 | 500 | { |
Bobty | 2:cd2da920cf98 | 501 | if (chTotalBits & 0x01) |
Bobty | 2:cd2da920cf98 | 502 | break; |
Bobty | 2:cd2da920cf98 | 503 | chTotalBits = chTotalBits >> 1; |
Bobty | 2:cd2da920cf98 | 504 | } |
Bobty | 2:cd2da920cf98 | 505 | uint16_t charWidth = 16; |
Bobty | 2:cd2da920cf98 | 506 | for (; charWidth > 0; charWidth--) |
Bobty | 2:cd2da920cf98 | 507 | { |
Bobty | 2:cd2da920cf98 | 508 | if (chTotalBits & 0x8000) |
Bobty | 2:cd2da920cf98 | 509 | break; |
Bobty | 2:cd2da920cf98 | 510 | chTotalBits = chTotalBits << 1; |
Bobty | 2:cd2da920cf98 | 511 | } |
Bobty | 2:cd2da920cf98 | 512 | |
Bobty | 2:cd2da920cf98 | 513 | // display character |
Bobty | 2:cd2da920cf98 | 514 | int xOffset = curX / 8; |
Bobty | 2:cd2da920cf98 | 515 | int bitOffset = curX % 8; |
Bobty | 2:cd2da920cf98 | 516 | // printf("%c %d %d %d %d %d\n", ch, curX, charWidth, rightShift, xOffset, bitOffset); |
Bobty | 2:cd2da920cf98 | 517 | if (xOffset >= (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 518 | return 0; |
Bobty | 2:cd2da920cf98 | 519 | for (int i = 0; i < numLines; i++) |
Bobty | 2:cd2da920cf98 | 520 | { |
Bobty | 2:cd2da920cf98 | 521 | uint32_t chBits = charData[i] >> rightShift; |
Bobty | 2:cd2da920cf98 | 522 | chBits = (chBits << (24-charWidth)) >> bitOffset; |
Bobty | 2:cd2da920cf98 | 523 | for (int j = 0; j < 3; j++) |
Bobty | 2:cd2da920cf98 | 524 | { |
Bobty | 2:cd2da920cf98 | 525 | if (xOffset + j >= (dispBufWidth/8)) |
Bobty | 2:cd2da920cf98 | 526 | break; |
Bobty | 2:cd2da920cf98 | 527 | _pDisplayBuf[(i + curY) * (dispBufWidth/8) + xOffset + j] |= ((chBits >> (16-j*8)) & 0xff); |
Bobty | 2:cd2da920cf98 | 528 | } |
Bobty | 2:cd2da920cf98 | 529 | } |
Bobty | 2:cd2da920cf98 | 530 | |
Bobty | 2:cd2da920cf98 | 531 | return charWidth; |
Bobty | 1:79cf2e115449 | 532 | } |
Bobty | 2:cd2da920cf98 | 533 | |
Bobty | 2:cd2da920cf98 | 534 | // Display line of characters |
Bobty | 2:cd2da920cf98 | 535 | int LEDMatrix::displayLine(int lineIdx, const char* line) |
Bobty | 2:cd2da920cf98 | 536 | { |
Bobty | 2:cd2da920cf98 | 537 | if (lineIdx >= numLines) |
Bobty | 2:cd2da920cf98 | 538 | lineIdx = 0; |
Bobty | 2:cd2da920cf98 | 539 | _isBusy = true; |
Bobty | 2:cd2da920cf98 | 540 | int curX = 0; |
Bobty | 2:cd2da920cf98 | 541 | int curY = lineIdx * height/numLines; |
Bobty | 2:cd2da920cf98 | 542 | for (int chIdx = 0; chIdx < strlen(line); chIdx++) |
Bobty | 2:cd2da920cf98 | 543 | { |
Bobty | 2:cd2da920cf98 | 544 | curX += displayChar(curX, curY, line[chIdx]) + _charSeparation; |
Bobty | 2:cd2da920cf98 | 545 | } |
Bobty | 2:cd2da920cf98 | 546 | _isBusy = false; |
Bobty | 2:cd2da920cf98 | 547 | return curX; |
Bobty | 2:cd2da920cf98 | 548 | } |
Bobty | 2:cd2da920cf98 | 549 |