added double buffering to prevent tearning
[Arduino] / Hub08_LedMatrix / Hub08_LedMatrix.ino
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  *
16  */
17
18 #define FONT8x8 0
19
20 #include <avr/pgmspace.h>
21 #include "LEDMatrix.h"
22 #include "font.h"
23
24 #define WIDTH   64*1 // 2 panels * 64
25 #define HEIGHT  16
26
27 #if USE_SPI
28 #include <SPI.h> // Arduino IDE compilation won't work without this
29 #endif
30
31 // hub08 pinout: la lb lc ld en  r1  lat  clk            
32 //     LEDMatrix(a, b, c, d, oe, r1, stb, clk);
33 LEDMatrix matrix(4, 5, 6, 7, 9,  11, 10,  13);
34
35 // Display Buffer 128 = 64 * 16 / 8
36 uint8_t displaybuf[(WIDTH/8) * HEIGHT*2];
37
38 uint8_t displaybuf_w[((WIDTH/8)+1) * HEIGHT];
39
40 byte cell[16];
41
42 void MatrixWriteCharacter(int x,int y, char character)
43 {
44   //Serial.print(x);
45   //Serial.print("  ");
46   //Serial.println(character);
47 #if FONT8x8
48   for(int i=0; i<8; i++) {
49      uint8_t *pDst = displaybuf_w + (i+y) * ((WIDTH / 8) + 1) + x  ;
50      *pDst = (font_8x8[character - 0x20][i]);
51   }
52 #else
53   for(int i=0; i<16; i++) {
54      cell[i] = pgm_read_byte_near(&font_8x16[(character - 0x20)][i]);
55   }
56
57   //uint8_t *pDst = displaybuf_w + (y) * ((WIDTH / 8) + 1) + x  ;
58   uint8_t *pDst = displaybuf_w + x  + y * ((WIDTH/8)+1);
59
60   byte mask = 1;
61   for(int j=0; j<8; j++) {
62
63     byte out  = 0;
64     for(int i=0; i<8; i++) {
65         out <<= 1;
66         if ( cell[i] & mask ) {
67                 out |= 1;
68         }
69      }
70      *pDst = out;
71      pDst += (WIDTH/8)+1;
72
73      mask <<= 1;
74   }
75
76   mask = 1;
77   for(int j=0; j<8; j++) {
78     byte out  = 0;
79     for(int i=8; i<16; i++) {
80         out <<= 1;
81         if ( cell[i] & mask ) {
82                 out |= 1;
83         }
84      }
85      *pDst = out;
86      pDst += (WIDTH/8)+1;
87
88      mask <<= 1;
89   }
90 #endif
91 }
92
93
94
95 void matrixPrint(String c) {
96   //c="33";
97   //Serial.println(c);
98   //Serial.println(c.length());
99   for (int i=0 ; i<c.length() ; i++) {
100       MatrixWriteCharacter(i,3,c[i]);
101       matrix.scan();
102       //Serial.print(i);
103       //Serial.print(" -> ");
104       //Serial.println(c[i]);
105   }
106 }
107
108
109 void setup()
110 {
111     matrix.begin(displaybuf, WIDTH, HEIGHT);
112     Serial.begin(115200);
113     matrix.clear();
114     //matrixPrint("12345678");
115     // uint8_t *pDst = displaybuf + y * (WIDTH / 8) + x / 8;
116         memset(displaybuf_w, 0, sizeof(displaybuf_w));
117 }
118
119 void matrixDelay(int x) {
120   for (int y=0; y<x; y++) { matrix.scan(); }
121   
122 }
123
124 //String poruka="X       XX      XOX     XOOX    XOoOX   XOooOX  XOoIoOX XOoiioOX        ";
125 //String poruka="        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras blandit libero id ex dapibus suscipit. Proin vitae cursus eros. Ut porttitor congue metus at viverra. In consectetur ex massa.";
126 String poruka="!\"#$%&'()*+,-./0123456789:;<=>?@AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqReSsTtUuVvWwXxYyZz[\\]^_`{|}~";
127 //String poruka="~";
128
129 int pos = 0; // position in circular display
130
131 void loop()
132 {
133     for (int p=0; p<poruka.length() ; p++) {
134         pos = ( pos + 1 ) % (( WIDTH / 8 )+1);
135 //      int pos_ch = ( pos + (WIDTH/8) ) % (( WIDTH / 8 )+1);
136         int pos_ch = ( pos + (WIDTH/8) ) % (( WIDTH / 8 )+1);
137         MatrixWriteCharacter(pos_ch,0,poruka.charAt(p));
138
139         int step_up = ((WIDTH/8)+1)-pos; // move up one line when falling off the end of circular buffer
140
141         Serial.print(pos);
142         Serial.print(" step_up=");
143         Serial.print(step_up);
144         Serial.print(" char=");
145         Serial.println(poruka.charAt(p));
146
147         for (int o=0; o<8; o++) {
148                 uint8_t *src  = displaybuf_w + pos;
149                 uint8_t *dest = matrix.offscreen_buffer();
150
151                 int i = 0;
152
153                 for (int y = 0; y < HEIGHT; y++ ) {
154                         for (int x = 0; x < (WIDTH/8); x++) {
155
156                                 int j  = ( x   < step_up ? y : y-1 ) * ((WIDTH/8)+1) + x;
157                                 int j1 = ( x+1 < step_up ? y : y-1 ) * ((WIDTH/8)+1) + x+1;
158
159                                 *(dest + i) = ( *(src + j) << o ) | (( *(src + j1) & ( 0xff << 8 - o ) ) >> 8 - o );
160 //                              *(dest + i) = *(src + j);
161 #if USE_SPI
162                                 matrix.scan();
163                                 delayMicroseconds(100 / (WIDTH / 64));
164 #else
165                                 matrix.scan();
166                                 delayMicroseconds(100 / (WIDTH / 64));
167 #endif
168                                 i++;
169                         }
170                 }
171                 matrix.swap();
172           }
173     }
174
175 }