133cfb2b05b4fbeec867f3498856204263a142f0
[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 USE_SPI
25 #include <SPI.h>
26 #endif
27
28 #if 0
29 #define ASSERT(e)   if (!(e)) { Serial.println(#e); while (1); }
30 #else
31 #define ASSERT(e)
32 #endif
33
34 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)
35 {
36     this->clk = clk;
37     this->r1 = r1;
38     this->stb = stb;
39     this->oe = oe;
40     this->a = a;
41     this->b = b;
42     this->c = c;
43     this->d = d;
44
45     mask = 0xff;
46     state = 0;
47 #if USE_SPI
48         SPI.begin();
49 #endif
50 }
51
52 void LEDMatrix::begin(uint8_t *displaybuf, uint16_t width, uint16_t height)
53 {
54     ASSERT(0 == (width % 32));
55     ASSERT(0 == (height % 16));
56
57     this->displaybuf = displaybuf;
58     this->width = width;
59     this->height = height;
60
61     pinMode(a, OUTPUT);
62     pinMode(b, OUTPUT);
63     pinMode(c, OUTPUT);
64     pinMode(d, OUTPUT);
65     pinMode(oe, OUTPUT);
66     pinMode(r1, OUTPUT);
67     pinMode(clk, OUTPUT);
68     pinMode(stb, OUTPUT);
69
70     state = 1;
71 }
72
73 void LEDMatrix::drawPoint(uint16_t x, uint16_t y, uint8_t pixel)
74 {
75     ASSERT(width > x);
76     ASSERT(height > y);
77
78     uint8_t *byte = displaybuf + x / 8 + y * width / 8;
79     uint8_t  bit = x % 8;
80
81     if (pixel) {
82         *byte |= 0x80 >> bit;
83     } else {
84         *byte &= ~(0x80 >> bit);
85     }
86 }
87
88 void LEDMatrix::drawRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t pixel)
89 {
90     for (uint16_t x = x1; x < x2; x++) {
91         for (uint16_t y = y1; y < y2; y++) {
92             drawPoint(x, y, pixel);
93         }
94     }
95 }
96
97 void LEDMatrix::drawImage(uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height, const uint8_t *image)
98 {
99     for (uint16_t y = 0; y < height; y++) {
100         for (uint16_t x = 0; x < width; x++) {
101             const uint8_t *byte = image + (x + y * width) / 8;
102             uint8_t  bit = 7 - x % 8;
103             uint8_t  pixel = (*byte >> bit) & 1;
104
105             drawPoint(x + xoffset, y + yoffset, pixel);
106         }
107     }
108 }
109
110 void LEDMatrix::clear()
111 {
112     uint8_t *ptr = displaybuf;
113     for (uint16_t i = 0; i < (width * height / 8); i++) {
114         *ptr = 0x00;
115         ptr++;
116     }
117 }
118
119 void LEDMatrix::reverse()
120 {
121     mask = ~mask;
122 }
123
124 uint8_t LEDMatrix::isReversed()
125 {
126     return mask;
127 }
128
129 void LEDMatrix::scan()
130 {
131     static uint8_t row = 0;  // from 0 to 15
132
133     if (!state) {
134         return;
135     }
136
137     uint8_t *head = displaybuf + row * (width / 8);
138     for (uint8_t line = 0; line < (height / 16); line++) {
139         uint8_t *ptr = head;
140         head += width * 2;              // width * 16 / 8
141
142         for (uint8_t byte = 0; byte < (width / 8); byte++) {
143             uint8_t pixels = *ptr;
144             ptr++;
145             pixels = pixels ^ mask;     // reverse: mask = 0xff, normal: mask =0x00
146 #if USE_SPI
147                 SPI.transfer(pixels);
148 #else
149             for (uint8_t bit = 0; bit < 8; bit++) {
150                 digitalWrite(clk, LOW);
151                 digitalWrite(r1, pixels & (0x80 >> bit));
152                 digitalWrite(clk, HIGH);
153             }
154 #endif
155         }
156     }
157
158     // select row
159     digitalWrite(a, (row & 0x01));
160     digitalWrite(b, (row & 0x02));
161     digitalWrite(c, (row & 0x04));
162     digitalWrite(d, (row & 0x08));
163
164     digitalWrite(oe, HIGH);              // disable display
165
166     // latch data
167     digitalWrite(stb, LOW);
168     digitalWrite(stb, HIGH);
169     digitalWrite(stb, LOW);
170
171     digitalWrite(oe, LOW);              // enable display
172
173     row = (row + 1) & 0x0F;
174 }
175
176 void LEDMatrix::on()
177 {
178     state = 1;
179 }
180
181 void LEDMatrix::off()
182 {
183     state = 0;
184     digitalWrite(oe, HIGH);
185 }