Forked LEDMatrix and added horizontal scrolling

Fork of LEDMatrix by Yihui Xiong

LEDMatrix.cpp

Committer:
Bobty
Date:
2016-01-11
Revision:
1:79cf2e115449
Parent:
0:13728deac7a7
Child:
2:cd2da920cf98

File content as of revision 1:79cf2e115449:

/**
 * LED Matrix library for http://www.seeedstudio.com/depot/ultrathin-16x32-red-led-matrix-panel-p-1582.html
 * The LED Matrix panel has 32x16 pixels. Several panel can be combined together as a large screen.
 * 
 * Coordinate & Connection (mbed -> panel 0 -> panel 1 -> ...)
 *   (0, 0)                                     (0, 0)
 *     +--------+--------+--------+               +--------+--------+
 *     |   5    |    3   |    1   |               |    1   |    0   |
 *     |        |        |        |               |        |        |<----- mbed
 *     +--------+--------+--------+               +--------+--------+
 *     |   4    |    2   |    0   |                              (64, 16)
 *     |        |        |        |<----- mbed
 *     +--------+--------+--------+
 *                             (96, 32)
 *  Copyright (c) 2013 Seeed Technology Inc.
 *  @auther     Yihui Xiong
 *  @date       Nov 8, 2013
 *  @license    Apache
 */

#include "LEDMatrix.h"
#include "mbed.h"

#if 0
#define ASSERT(e)   if (!(e)) { Serial.println(#e); while (1); }
#else
#define ASSERT(e)
#endif

LEDMatrix::LEDMatrix(PinName pinA, PinName pinB, PinName pinC, PinName pinD, PinName pinOE, PinName pinR1, PinName pinSTB, PinName pinCLK) :
        a(pinA), b(pinB), c(pinC), d(pinD), oe(pinOE), r1(pinR1), stb(pinSTB), clk(pinCLK)
{
    this->clk = clk;
    this->r1 = r1;
    this->stb = stb;
    this->oe = oe;
    this->a = a;
    this->b = b;
    this->c = c;
    this->d = d;

    mask = 0xff;
    state = 0;
    _horizontalScrollPos = 0;
}

void LEDMatrix::begin(uint8_t *displaybuf, uint16_t width, uint16_t height)
{
    ASSERT(0 == (width % 32));
    ASSERT(0 == (height % 16));

    this->displaybuf = displaybuf;
    this->width = width;
    this->height = height;
    
    state = 1;
}

void LEDMatrix::drawPoint(uint16_t x, uint16_t y, uint8_t pixel)
{
    ASSERT(width > x);
    ASSERT(height > y);

    uint8_t *byte = displaybuf + (height - 1 - y) * width / 8 + (width - 1 - x) / 8;
    uint8_t  bit = (width - 1 - x) % 8;

    if (pixel) {
        *byte |= 0x80 >> bit;
    } else {
        *byte &= ~(0x80 >> bit);
    }
}

void LEDMatrix::drawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t pixel)
{
    for (uint16_t x = x1; x < x2; x++) {
        for (uint16_t y = y1; y < y2; y++) {
            drawPoint(x, y, pixel);
        }
    }
}

void LEDMatrix::drawImage(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t *image)
{
    ASSERT(0 == ((x2 - x1) % 8));

    for (uint16_t x = x1; x < x2; x++) {
        for (uint16_t y = y1; y < y2; y++) {
            uint8_t *byte = image + x * 8 + y / 8;
            uint8_t  bit = 7 - (y % 8);
            uint8_t  pixel = (*byte >> bit) & 1;

            drawPoint(x, y, pixel);
        }
    }
}

void LEDMatrix::clear()
{
    uint8_t *ptr = displaybuf;
    for (uint16_t i = 0; i < (width * height / 8); i++) {
        *ptr = 0x00;
        ptr++;
    }
}

void LEDMatrix::reverse()
{
    mask = ~mask;
}

uint8_t LEDMatrix::isReversed()
{
    return mask;
}

void LEDMatrix::scan()
{
    static uint8_t row = 0;

    if (!state) 
    {
        return;
    }

    uint8_t *head = displaybuf + row * (width / 8);
    for (uint8_t line = 0; line < (height / 16); line++) 
    {
        uint8_t *ptr = head;
        head += line * width * 2;

        for (uint8_t byteIdx = 0; byteIdx < (width / 8); byteIdx++)
        {
            uint8_t* pByte1 = ptr + (((byteIdx*8 + width - _horizontalScrollPos + 7) % width) / 8);
            uint8_t* pByte2 = ptr + (((byteIdx*8 + width - _horizontalScrollPos - 1) % width) / 8);
            int bitOffset = _horizontalScrollPos % 8;
            uint8_t pixels = ((*pByte1) >> bitOffset) + (((*pByte2) << (8 - bitOffset)) % 256);
            
//            uint8_t pixels = *ptr;
//            ptr++;
            pixels = pixels ^ mask;   // reverse: mask = 0xff, normal: mask =0x00 
            for (uint8_t bit = 0; bit < 8; bit++) 
            {
                clk = 0;
                r1 = pixels & (0x80 >> bit);
//                wait_us(1);
                clk = 1;
            }
        }
    }

    oe = 1;              // disable display

    // select row
    a = (row & 0x01);
    b = (row & 0x02);
    c = (row & 0x04);
    d = (row & 0x08);

    // latch data
    stb = 0;
//    wait_us(1);
    stb = 1;

    oe = 0;              // enable display

    row = (row + 1) & 0x0F;
}

void LEDMatrix::on()
{
    state = 1;
}

void LEDMatrix::off()
{
    state = 0;
    oe = 1;
}

void LEDMatrix::scrollReset()
{
    _horizontalScrollPos = 0;
}

void LEDMatrix::scrollLeft()
{
    _horizontalScrollPos++;
    if (_horizontalScrollPos >= width)
        _horizontalScrollPos = 0;
}

void LEDMatrix::scrollToPos(int pos)
{
    if ((pos <= 0) || (pos >= width))
        return;
    _horizontalScrollPos = pos;
}