b3edb56608fd14c5552c993687fd356dec78b0d3
[Arduino] / Hub08_LedMatrix / LEDMatrix.cpp
1 /**
2  * LED Matrix library for http://www.seeedstudio.com/depot/ultrathin-16x32-red-led-matrix-panel-p-1582.html
3  * The LED Matrix panel has 32x16 pixels. Several panel can be combined together as a large screen.
4  *
5  * Coordinate & Connection (Arduino -> panel 0 -> panel 1 -> ...)
6  *   (0, 0)                                     (0, 0)
7  *     +--------+--------+--------+               +--------+--------+
8  *     |   5    |    4   |    3   |               |    1   |    0   |
9  *     |        |        |        |               |        |        |<----- Arduino
10  *     +--------+--------+--------+               +--------+--------+
11  *     |   2    |    1   |    0   |                              (64, 16)
12  *     |        |        |        |<----- Arduino
13  *     +--------+--------+--------+
14  *                             (96, 32)
15  *  Copyright (c) 2013 Seeed Technology Inc.
16  *  @auther     Yihui Xiong
17  *  @date       Nov 8, 2013
18  *  @license    MIT
19  */
20
21 #include "LEDMatrix.h"
22 #include "Arduino.h"
23
24 #if 0
25 #define ASSERT(e)   if (!(e)) { Serial.println(#e); while (1); }
26 #else
27 #define ASSERT(e)
28 #endif
29
30 LEDMatrix::LEDMatrix(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t oe, uint8_t r1, uint8_t stb, uint8_t clk)
31 {
32     this->clk = clk;
33     this->r1 = r1;
34     this->stb = stb;
35     this->oe = oe;
36     this->a = a;
37     this->b = b;
38     this->c = c;
39     this->d = d;
40
41     mask = 0xff;
42     state = 0;
43 }
44
45 void LEDMatrix::begin(uint8_t *displaybuf, uint16_t width, uint16_t height)
46 {
47     ASSERT(0 == (width % 32));
48     ASSERT(0 == (height % 16));
49
50     this->displaybuf = displaybuf;
51     this->width = width;
52     this->height = height;
53
54     pinMode(a, OUTPUT);
55     pinMode(b, OUTPUT);
56     pinMode(c, OUTPUT);
57     pinMode(d, OUTPUT);
58     pinMode(oe, OUTPUT);
59     pinMode(r1, OUTPUT);
60     pinMode(clk, OUTPUT);
61     pinMode(stb, OUTPUT);
62
63     state = 1;
64 }
65
66 void LEDMatrix::drawPoint(uint16_t x, uint16_t y, uint8_t pixel)
67 {
68     ASSERT(width > x);
69     ASSERT(height > y);
70
71     uint8_t *byte = displaybuf + x / 8 + y * width / 8;
72     uint8_t  bit = x % 8;
73
74     if (pixel) {
75         *byte |= 0x80 >> bit;
76     } else {
77         *byte &= ~(0x80 >> bit);
78     }
79 }
80
81 void LEDMatrix::drawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t pixel)
82 {
83     for (uint16_t x = x1; x < x2; x++) {
84         for (uint16_t y = y1; y < y2; y++) {
85             drawPoint(x, y, pixel);
86         }
87     }
88 }
89
90 void LEDMatrix::drawImage(uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height, const uint8_t *image)
91 {
92     for (uint16_t y = 0; y < height; y++) {
93         for (uint16_t x = 0; x < width; x++) {
94             const uint8_t *byte = image + (x + y * width) / 8;
95             uint8_t  bit = 7 - x % 8;
96             uint8_t  pixel = (*byte >> bit) & 1;
97
98             drawPoint(x + xoffset, y + yoffset, pixel);
99         }
100     }
101 }
102
103 void LEDMatrix::clear()
104 {
105     uint8_t *ptr = displaybuf;
106     for (uint16_t i = 0; i < (width * height / 8); i++) {
107         *ptr = 0x00;
108         ptr++;
109     }
110 }
111
112 void LEDMatrix::reverse()
113 {
114     mask = ~mask;
115 }
116
117 uint8_t LEDMatrix::isReversed()
118 {
119     return mask;
120 }
121
122 void LEDMatrix::scan()
123 {
124     static uint8_t row = 0;  // from 0 to 15
125
126     if (!state) {
127         return;
128     }
129
130     uint8_t *head = displaybuf + row * (width / 8);
131     for (uint8_t line = 0; line < (height / 16); line++) {
132         uint8_t *ptr = head;
133         head += width * 2;              // width * 16 / 8
134
135         for (uint8_t byte = 0; byte < (width / 8); byte++) {
136             uint8_t pixels = *ptr;
137             ptr++;
138             pixels = pixels ^ mask;     // reverse: mask = 0xff, normal: mask =0x00
139             for (uint8_t bit = 0; bit < 8; bit++) {
140                 digitalWrite(clk, LOW);
141                 digitalWrite(r1, pixels & (0x80 >> bit));
142                 digitalWrite(clk, HIGH);
143             }
144         }
145     }
146
147     digitalWrite(oe, HIGH);              // disable display
148
149     // select row
150     digitalWrite(a, (row & 0x01));
151     digitalWrite(b, (row & 0x02));
152     digitalWrite(c, (row & 0x04));
153     digitalWrite(d, (row & 0x08));
154
155     // latch data
156     digitalWrite(stb, LOW);
157     digitalWrite(stb, HIGH);
158     digitalWrite(stb, LOW);
159
160     digitalWrite(oe, LOW);              // enable display
161
162     row = (row + 1) & 0x0F;
163 }
164
165 void LEDMatrix::on()
166 {
167     state = 1;
168 }
169
170 void LEDMatrix::off()
171 {
172     state = 0;
173     digitalWrite(oe, HIGH);
174 }