A demo for Adafruit 64x32 demo with PWM
Dependencies: mbed-rtos BufferedSerial Adafruit_GFX_MBED LedMatrix-PWM FastIO mbed-dev
main.cpp@0:9f43f6e0d6ad, 2017-10-08 (annotated)
- Committer:
- davidr99
- Date:
- Sun Oct 08 00:32:58 2017 +0000
- Revision:
- 0:9f43f6e0d6ad
- Child:
- 1:442e873e4f52
First Checkin of PWM LED Matrix
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
davidr99 | 0:9f43f6e0d6ad | 1 | /* |
davidr99 | 0:9f43f6e0d6ad | 2 | The goal of this program is to show the basic connections and workings of Adafruits 32x16 RGB LED matrix board (http://www.adafruit.com/products/420), |
davidr99 | 0:9f43f6e0d6ad | 3 | also sold on other places, for instance http://www.ebay.com/itm/PH6-RGB-Full-Color-LED-16-32-Dot-Matrix-Display-Module-/310303408628?pt=LH_DefaultDomain_0&hash=item483f8641f4 (no |
davidr99 | 0:9f43f6e0d6ad | 4 | affiliation with either of them). |
davidr99 | 0:9f43f6e0d6ad | 5 | This program is not intended to be highly optimized or a guideline in C programming in any way (more of the opposite actually). |
davidr99 | 0:9f43f6e0d6ad | 6 | To have more than 7 colors on this thing, you need to implement software PWM of some sort. I have obviously not done that, but if YOU do, please let me know! |
davidr99 | 0:9f43f6e0d6ad | 7 | Adafruit have a wicked demo program for an arduino - www.youtube.com/watch?v=lY-flFEfsHo |
davidr99 | 0:9f43f6e0d6ad | 8 | There are probably lots of ways to make this perform better, perhaps by using Neal Hormans port of the Adafruit_GFX library (http://mbed.org/users/nkhorman/code/Adafruit_GFX/). |
davidr99 | 0:9f43f6e0d6ad | 9 | No error checking or out-of-bounds checking is done. Use at your own peril. |
davidr99 | 0:9f43f6e0d6ad | 10 | For more detailed information on the driver chip, see http://www.bjtopspace.com/ziliao/CYT62726.pdf |
davidr99 | 0:9f43f6e0d6ad | 11 | Although the chips on my board says jx15020, I've been informed that they are equvivalent to the CYT62726, and so far it's a match. |
davidr99 | 0:9f43f6e0d6ad | 12 | Feel free to use all or parts of this work. |
davidr99 | 0:9f43f6e0d6ad | 13 | If you choose to do so, I would appreciate a small mentioning in the scrolling opening credits ;) |
davidr99 | 0:9f43f6e0d6ad | 14 | |
davidr99 | 0:9f43f6e0d6ad | 15 | Best regards, |
davidr99 | 0:9f43f6e0d6ad | 16 | Hugo Harming |
davidr99 | 0:9f43f6e0d6ad | 17 | upgraded@hotmail.com |
davidr99 | 0:9f43f6e0d6ad | 18 | */ |
davidr99 | 0:9f43f6e0d6ad | 19 | |
davidr99 | 0:9f43f6e0d6ad | 20 | #include "mbed.h" |
davidr99 | 0:9f43f6e0d6ad | 21 | #include "rtos.h" |
davidr99 | 0:9f43f6e0d6ad | 22 | #define LOW 0 |
davidr99 | 0:9f43f6e0d6ad | 23 | #define HIGH 1 |
davidr99 | 0:9f43f6e0d6ad | 24 | |
davidr99 | 0:9f43f6e0d6ad | 25 | BusOut ABCD(D5,D6,D7,D8); // Row address. |
davidr99 | 0:9f43f6e0d6ad | 26 | DigitalOut CLK(D9); // Data clock - rising edge |
davidr99 | 0:9f43f6e0d6ad | 27 | DigitalOut LAT(D3); // Data latch - active low (pulse up after data load) |
davidr99 | 0:9f43f6e0d6ad | 28 | DigitalOut OE(D4); // Output enable - active low (hold high during data load, bring low after LAT pulse) |
davidr99 | 0:9f43f6e0d6ad | 29 | DigitalOut R1(D10); // RED Serial in for upper half |
davidr99 | 0:9f43f6e0d6ad | 30 | DigitalOut R2(D13); // RED Serial in for lower half |
davidr99 | 0:9f43f6e0d6ad | 31 | DigitalOut G1(D11); // GREEN Serial in for upper half |
davidr99 | 0:9f43f6e0d6ad | 32 | DigitalOut G2(A0); // GREEN Serial in for lower half |
davidr99 | 0:9f43f6e0d6ad | 33 | DigitalOut B1(D12); // BLUE Serial in for upper half |
davidr99 | 0:9f43f6e0d6ad | 34 | DigitalOut B2(A1); // BLUE Serial in for lower half |
davidr99 | 0:9f43f6e0d6ad | 35 | |
davidr99 | 0:9f43f6e0d6ad | 36 | const int nPlanes = 5; |
davidr99 | 0:9f43f6e0d6ad | 37 | |
davidr99 | 0:9f43f6e0d6ad | 38 | unsigned char gm[64][16][nPlanes]; // Buffer with 32x6 bytes. Graphics memory if you like. |
davidr99 | 0:9f43f6e0d6ad | 39 | unsigned int plane; // Counter for demo code |
davidr99 | 0:9f43f6e0d6ad | 40 | |
davidr99 | 0:9f43f6e0d6ad | 41 | void Init() |
davidr99 | 0:9f43f6e0d6ad | 42 | { |
davidr99 | 0:9f43f6e0d6ad | 43 | // Set up things to a known state |
davidr99 | 0:9f43f6e0d6ad | 44 | CLK = LOW; |
davidr99 | 0:9f43f6e0d6ad | 45 | LAT = LOW; |
davidr99 | 0:9f43f6e0d6ad | 46 | OE = HIGH; //display off |
davidr99 | 0:9f43f6e0d6ad | 47 | ABCD = 0; |
davidr99 | 0:9f43f6e0d6ad | 48 | plane=0; |
davidr99 | 0:9f43f6e0d6ad | 49 | } |
davidr99 | 0:9f43f6e0d6ad | 50 | |
davidr99 | 0:9f43f6e0d6ad | 51 | void WrRow(unsigned char Row) |
davidr99 | 0:9f43f6e0d6ad | 52 | { |
davidr99 | 0:9f43f6e0d6ad | 53 | // Write specified row (and row+8) to display. Valid input: 0 to 7. |
davidr99 | 0:9f43f6e0d6ad | 54 | ABCD=15-Row; // Set row address |
davidr99 | 0:9f43f6e0d6ad | 55 | for(int col=63; col >= 0; col--) { // To daisychain more displays, I guess you would have to increase this counter to n*32 columns. Might mirror though. |
davidr99 | 0:9f43f6e0d6ad | 56 | char val = gm[col][Row][plane]; |
davidr99 | 0:9f43f6e0d6ad | 57 | |
davidr99 | 0:9f43f6e0d6ad | 58 | R1 = (val & 1); // Red bit, upper half |
davidr99 | 0:9f43f6e0d6ad | 59 | G1 = (val & 2); // Green bit, upper half |
davidr99 | 0:9f43f6e0d6ad | 60 | B1 = (val & 4); // Blue bit, upper half |
davidr99 | 0:9f43f6e0d6ad | 61 | |
davidr99 | 0:9f43f6e0d6ad | 62 | R2 = (val & 8); // Red bit, lower half |
davidr99 | 0:9f43f6e0d6ad | 63 | G2 = (val & 16); // Green bit, lower half |
davidr99 | 0:9f43f6e0d6ad | 64 | B2 = (val & 32); // Blue bit, lower half |
davidr99 | 0:9f43f6e0d6ad | 65 | CLK = HIGH; // tick (clock bit in) |
davidr99 | 0:9f43f6e0d6ad | 66 | CLK = LOW; // tock |
davidr99 | 0:9f43f6e0d6ad | 67 | } |
davidr99 | 0:9f43f6e0d6ad | 68 | LAT = HIGH; // Latch entire row |
davidr99 | 0:9f43f6e0d6ad | 69 | LAT = LOW; |
davidr99 | 0:9f43f6e0d6ad | 70 | } |
davidr99 | 0:9f43f6e0d6ad | 71 | |
davidr99 | 0:9f43f6e0d6ad | 72 | void Pset(unsigned char x,unsigned char y, unsigned long c) |
davidr99 | 0:9f43f6e0d6ad | 73 | { |
davidr99 | 0:9f43f6e0d6ad | 74 | int r, g, b; |
davidr99 | 0:9f43f6e0d6ad | 75 | |
davidr99 | 0:9f43f6e0d6ad | 76 | r = (c & 0xFF); // Extract red bit from color |
davidr99 | 0:9f43f6e0d6ad | 77 | g = (c & 0xFF00) >> 8; // Extract green bit from color |
davidr99 | 0:9f43f6e0d6ad | 78 | b = (c & 0xFF0000) >> 16; // Extract blue bit from color |
davidr99 | 0:9f43f6e0d6ad | 79 | |
davidr99 | 0:9f43f6e0d6ad | 80 | for(int p=0;p<nPlanes;p++) |
davidr99 | 0:9f43f6e0d6ad | 81 | { |
davidr99 | 0:9f43f6e0d6ad | 82 | if (y >= 16) |
davidr99 | 0:9f43f6e0d6ad | 83 | { |
davidr99 | 0:9f43f6e0d6ad | 84 | // Keep last 3 bits |
davidr99 | 0:9f43f6e0d6ad | 85 | gm[x][y - 16][p] = (gm[x][y - 16][p] & 0b111000) + ((r >> p) & 1) + (((g << 1) >> p) & 2) + (((b << 2) >> p) & 4); |
davidr99 | 0:9f43f6e0d6ad | 86 | } |
davidr99 | 0:9f43f6e0d6ad | 87 | else |
davidr99 | 0:9f43f6e0d6ad | 88 | { |
davidr99 | 0:9f43f6e0d6ad | 89 | // keep first 3 bits |
davidr99 | 0:9f43f6e0d6ad | 90 | gm[x][y][p] = (gm[x][y][p] & 0b000111) + ((((r >> p) & 1) + (((g << 1) >> p) & 2) + (((b << 2) >> p) & 4)) << 3); |
davidr99 | 0:9f43f6e0d6ad | 91 | } |
davidr99 | 0:9f43f6e0d6ad | 92 | } |
davidr99 | 0:9f43f6e0d6ad | 93 | } |
davidr99 | 0:9f43f6e0d6ad | 94 | |
davidr99 | 0:9f43f6e0d6ad | 95 | void Paint() |
davidr99 | 0:9f43f6e0d6ad | 96 | { |
davidr99 | 0:9f43f6e0d6ad | 97 | if (plane >= (nPlanes - 1)) |
davidr99 | 0:9f43f6e0d6ad | 98 | { |
davidr99 | 0:9f43f6e0d6ad | 99 | plane = 0; |
davidr99 | 0:9f43f6e0d6ad | 100 | } |
davidr99 | 0:9f43f6e0d6ad | 101 | else |
davidr99 | 0:9f43f6e0d6ad | 102 | { |
davidr99 | 0:9f43f6e0d6ad | 103 | plane++; |
davidr99 | 0:9f43f6e0d6ad | 104 | } |
davidr99 | 0:9f43f6e0d6ad | 105 | |
davidr99 | 0:9f43f6e0d6ad | 106 | // Write graphics memory to display |
davidr99 | 0:9f43f6e0d6ad | 107 | for(int Row=0; Row<16; Row++) { |
davidr99 | 0:9f43f6e0d6ad | 108 | OE = HIGH; // Disable output |
davidr99 | 0:9f43f6e0d6ad | 109 | WrRow(Row); |
davidr99 | 0:9f43f6e0d6ad | 110 | OE = LOW; // Enable output |
davidr99 | 0:9f43f6e0d6ad | 111 | wait_us(2 * (1 << plane)); // Wasting some time. Use for whatever else. Probably better with a ticker for the display refresh. |
davidr99 | 0:9f43f6e0d6ad | 112 | } |
davidr99 | 0:9f43f6e0d6ad | 113 | OE = HIGH; // Disable output |
davidr99 | 0:9f43f6e0d6ad | 114 | } |
davidr99 | 0:9f43f6e0d6ad | 115 | |
davidr99 | 0:9f43f6e0d6ad | 116 | void PaintThread() |
davidr99 | 0:9f43f6e0d6ad | 117 | { |
davidr99 | 0:9f43f6e0d6ad | 118 | Paint(); |
davidr99 | 0:9f43f6e0d6ad | 119 | } |
davidr99 | 0:9f43f6e0d6ad | 120 | |
davidr99 | 0:9f43f6e0d6ad | 121 | int main() |
davidr99 | 0:9f43f6e0d6ad | 122 | { |
davidr99 | 0:9f43f6e0d6ad | 123 | Init(); // Set things up |
davidr99 | 0:9f43f6e0d6ad | 124 | Ticker ticker; |
davidr99 | 0:9f43f6e0d6ad | 125 | ticker.attach(PaintThread, 0.003); |
davidr99 | 0:9f43f6e0d6ad | 126 | |
davidr99 | 0:9f43f6e0d6ad | 127 | while(1) { |
davidr99 | 0:9f43f6e0d6ad | 128 | |
davidr99 | 0:9f43f6e0d6ad | 129 | for(int x=0;x<64;x++) |
davidr99 | 0:9f43f6e0d6ad | 130 | { |
davidr99 | 0:9f43f6e0d6ad | 131 | for(int y=0;y<32;y++) |
davidr99 | 0:9f43f6e0d6ad | 132 | { |
davidr99 | 0:9f43f6e0d6ad | 133 | Pset(x, y, 0xFF0101); |
davidr99 | 0:9f43f6e0d6ad | 134 | } |
davidr99 | 0:9f43f6e0d6ad | 135 | //Paint(); // Display refresh time sets loop duration. |
davidr99 | 0:9f43f6e0d6ad | 136 | } |
davidr99 | 0:9f43f6e0d6ad | 137 | |
davidr99 | 0:9f43f6e0d6ad | 138 | Thread::wait(1000); |
davidr99 | 0:9f43f6e0d6ad | 139 | |
davidr99 | 0:9f43f6e0d6ad | 140 | for(int c=0; c<16; c++) { |
davidr99 | 0:9f43f6e0d6ad | 141 | for(int x=c; x<(63-c); x++) {// Top side |
davidr99 | 0:9f43f6e0d6ad | 142 | Pset(x,c,c); |
davidr99 | 0:9f43f6e0d6ad | 143 | Thread::wait(10); |
davidr99 | 0:9f43f6e0d6ad | 144 | //Paint(); // Display refresh time sets loop duration. |
davidr99 | 0:9f43f6e0d6ad | 145 | } |
davidr99 | 0:9f43f6e0d6ad | 146 | for(int y=c; y<(31-c); y++) {// Right side |
davidr99 | 0:9f43f6e0d6ad | 147 | Pset(63-c,y,c << 8); |
davidr99 | 0:9f43f6e0d6ad | 148 | Thread::wait(10); |
davidr99 | 0:9f43f6e0d6ad | 149 | //Paint(); |
davidr99 | 0:9f43f6e0d6ad | 150 | } |
davidr99 | 0:9f43f6e0d6ad | 151 | for(int x=(63-c); x>=c; x--) {// Bottom side |
davidr99 | 0:9f43f6e0d6ad | 152 | Pset(x,(31-c),c << 16); |
davidr99 | 0:9f43f6e0d6ad | 153 | Thread::wait(10); |
davidr99 | 0:9f43f6e0d6ad | 154 | //Paint(); |
davidr99 | 0:9f43f6e0d6ad | 155 | } |
davidr99 | 0:9f43f6e0d6ad | 156 | for(int y=(31-c); y>=c; y--) { // Left side |
davidr99 | 0:9f43f6e0d6ad | 157 | Pset(c,y,c << 8); |
davidr99 | 0:9f43f6e0d6ad | 158 | Thread::wait(10); |
davidr99 | 0:9f43f6e0d6ad | 159 | //Paint(); |
davidr99 | 0:9f43f6e0d6ad | 160 | } |
davidr99 | 0:9f43f6e0d6ad | 161 | } |
davidr99 | 0:9f43f6e0d6ad | 162 | |
davidr99 | 0:9f43f6e0d6ad | 163 | Thread::wait(1000); |
davidr99 | 0:9f43f6e0d6ad | 164 | |
davidr99 | 0:9f43f6e0d6ad | 165 | /* |
davidr99 | 0:9f43f6e0d6ad | 166 | for(long w=0;w<1000;w++) |
davidr99 | 0:9f43f6e0d6ad | 167 | { |
davidr99 | 0:9f43f6e0d6ad | 168 | Paint(); // Display refresh time sets loop duration. |
davidr99 | 0:9f43f6e0d6ad | 169 | }*/ |
davidr99 | 0:9f43f6e0d6ad | 170 | } |
davidr99 | 0:9f43f6e0d6ad | 171 | } |