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