Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 21 of 21

Thread: cheap 32x32 RGB panel with 24bit color and 30fps live streaming

Threaded View

  1. #1
    Junior Member
    Join Date
    Feb 2014
    Posts
    7

    cheap 32x32 RGB panel with 24bit color and 30fps live streaming

    Teensy is just so awesome!
    Click image for larger version. 

Name:	teensy.jpg 
Views:	1827 
Size:	157.9 KB 
ID:	1503

    In contrast to the intelligent LED-strips, the cheap 32x32 RGB panels natively only support 1bit per color. If you want more, you have to switch the LEDs rapidly. The Adafruit Matrix library for Arduino only supported this for up to 4bits per color, in total 4096 colors.

    Using the incredibly powerfull Teensy I was able to increase this to 8bit per color, 24bit in total, thats 16.7 million colors, with 30fps! I believe this is a first. To achieve this, I prepare the interleaved, gamma-corrected buffer on the PC in a Java app and stream it live. This is possible due to the fast USB of the Teensy. You can stream any part of your screen. I don't use DMA yet, this could reduce CPU even more.

    Especially on dark scenes there are still some artifacts on the bottom side, must either be a bug or timing issue.

    Videos: NEW http://youtu.be/SDrxM1TDR18 http://youtu.be/x0Wcpol7cO4, http://youtu.be/dmCp1OEAtMU

    Here's the Teensy 3.1 sketch:
    Code:
        /* Modified by Markus Lipp adding interleaved buffers, streaming, 32x32 & 24bit support
        * Based on "_16x32_Matrix R3.0" by Creater Alex Medeiros, http://PenguinTech.tk
        * Use code freely and distort its contents as much as you want, just remeber to thank the
        * original creaters of the code by leaving their information in the header. :)
        */
    
        //modified by markus lipp for 32x32 panel
    
    
        //PortC[0:11] = {15, 22, 23, 9, 10, 13, 11, 12, 28, 27, 29, 30}
        //PortD[0:7] = {2, 14, 7, 8, 6, 20, 21, 5}
        //Define pins
        const uint8_t
        //PortC
        APIN      = 15, BPIN      = 22, CPIN      = 23, DPIN = 9,
        CLOCKPIN  = 10, LATCHPIN  = 13, OEPIN     = 11,
        //PortD
        R1PIN     = 2, R2PIN     = 8,
        G1PIN     = 14, G2PIN     = 6,
        B1PIN     = 7, B2PIN     = 20;
    
        uint8_t pinTable[13] = {
          R1PIN,R2PIN,G1PIN,G2PIN,B1PIN,B2PIN,
          APIN,BPIN,CPIN,DPIN,CLOCKPIN,LATCHPIN,OEPIN};
    
        //Addresses 1/8 rows Through a decoder
        uint16_t const A = 1, B = 2,C = 4, D=8;
        //Acts like a 16 bit shift register
        uint16_t const SCLK   = 16;
        uint16_t const LATCH  = 32;
        uint16_t const OE     = 64;
    
        uint16_t const abcVar[16] = { //Decoder counter var
          0,A,B,A+B,C,C+A,C+B,A+B+C,
          0+D,A+D,B+D,A+B+D,C+D,C+A+D,C+B+D,A+B+C+D};
    
        //Data Lines for row 1 red and row 9 red, ect.
        uint16_t const RED1   = 1, RED2   = 8;
        uint16_t const GREEN1 = 2, GREEN2 = 16;
        uint16_t const BLUE1  = 4, BLUE2  = 32;
    
        const uint8_t SIZEX = 32;
        const uint8_t SIZEY = 32;
    
        //Here is where the data is all read
        uint8_t interleavedBuffer[SIZEX*SIZEY*4];
    
        //BAM and interrupt variables
        boolean actDisplay = false;
        uint8_t rowN = 0;
        uint16_t BAM;
        uint8_t BAMMAX = 7; //now 24bit color! (0-7)
    
        void setup() {
          for(uint8_t i = 0; i < 13; i++){
                pinMode(pinTable[i], OUTPUT);
            }
          timerInit();
          Serial.begin(250000);
        }
    
        uint8_t r,g, prevVal,val;
        int dataPos=0;
    
        void loop() {       
           if (Serial.available())
           {     
              prevVal = val;
              val = Serial.read();     
           
              if ( (prevVal==0x21 && val==0x8) || dataPos>=4096)
              {
                 dataPos=0;
              }
              else
              {
                interleavedBuffer[dataPos++] = val;
              }
           } 
        }
    
        IntervalTimer timer1;
        #define BAMDUR 2
        void timerInit() {
            timer1.begin(timerCallBack,BAMDUR);
            BAM = 0;
        }
    
    
        //Where the PIT calls
        void timerCallBack() {
            attackMatrix(); // Updated the display
            if(BAM > BAMMAX) { //Checks the BAM cycle for next time.
                BAM = 0;
                timer1.begin(timerCallBack,BAMDUR);
                actDisplay = false;
            } else {
                BAM ++;
                actDisplay = true;
            }
        }
    
        //The updating matrix stuff happens here
        //each pair of rows is taken through its BAM cycle
        //then the rowNumber is increased and id done again
        void attackMatrix() {
            uint16_t portData;
    
            //sets up which BAM the matrix is on
            if(BAM == 0) { timer1.begin(timerCallBack,BAMDUR); }
            if(BAM == 1) { timer1.begin(timerCallBack,BAMDUR*2); }
            if(BAM == 2) { timer1.begin(timerCallBack,BAMDUR*4); }
            if(BAM == 3) { timer1.begin(timerCallBack,BAMDUR*8); }
            if(BAM == 4) { timer1.begin(timerCallBack,BAMDUR*16); }
            if(BAM == 5) { timer1.begin(timerCallBack,BAMDUR*32); }
            if(BAM == 6) { timer1.begin(timerCallBack,BAMDUR*64); }
            if(BAM == 7) { timer1.begin(timerCallBack,BAMDUR*128); }
    
            portData = 0; // Clear data to enter
            portData |= (abcVar[rowN])|OE; // abc, OE
            portData &=~ LATCH;        //LATCH LOW
            GPIOC_PDOR = portData;  // Write to Port
           
            uint8_t *start = &interleavedBuffer[rowN*SIZEX*8+((7-BAMMAX)+BAM)*32];
           
            for(uint8_t _x = 0; _x < 32; _x++){
    
                  GPIOD_PDOR = start[_x]; // Transfer data
                  GPIOC_PDOR |=  SCLK;// Clock HIGH
                  GPIOC_PDOR &=~ SCLK;// Clock LOW
            }
    
            GPIOC_PDOR |= LATCH;// Latch HIGH
            GPIOC_PDOR &=~ OE;// OE LOW, Displays line   
    
            if(BAM == BAMMAX){
               if(rowN == 15){
                    rowN = 0;
                } else {
                    rowN ++;
                }
            }
        }
    And here is the Java live streaming app for your PC. Just start the jar in the bin directory. Move&Scale the small window to define what to stream. Select Interleaved RGB8 for Teensy as output mode. Click "enable output" to start streaming.
    https://dl.dropboxusercontent.com/u/...reenStream.rar

    Click image for larger version. 

Name:	streamingApp.png 
Views:	503 
Size:	368.7 KB 
ID:	1500

    Here's a link to the Arduino version I posted earlier. It's just 4bit and 12fps. http://forums.adafruit.com/viewtopic.php?f=47&t=50115
    Last edited by MarkusL; 02-23-2014 at 10:32 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •