Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 |
