Forum Rule: Always post complete source code & details to reproduce any issue!
Page 9 of 9 FirstFirst ... 7 8 9
Results 201 to 205 of 205

Thread: Teensy 3.6 VGA driver

  1. #201
    Junior Member
    Join Date
    Jun 2017
    Posts
    7
    Hi, Sorry to dig up this older thread, but I was searching for VGA on the Teensy. After watching the Ben Eater makes a video card I tried to write a routine to display something to VGA and after a lot of tweaking I managed to display 162x600 mono using this code
    Code:
    #define NOP __asm__ __volatile__ ("nop\n\t")
    bool screenbuf[200][628];
    
    const int vsync=16;
    const int hsync=15;
    const int redpix=19;
    int ledState = 0x00;
    const int ledPin = 13;
    int bar=0;
    
    void setup() {
      // put your setup code here, to run once:
      pinMode(vsync, OUTPUT);
      pinMode(hsync, OUTPUT);
      pinMode(redpix, OUTPUT);  
      for (int y=0;y<601;y++){
        for (int x=0;x<162;x++){
          if (bar<10){
             screenbuf[x][y]=  true;        
          } else {
             screenbuf[x][y]=  false;          
          }
    
         }
          bar++;
          if (bar>20){
            bar=0;
          }
         
      }  
    }
    
    void loop() {
      for (int y=0;y<628;y++){
        if (y>600 && y<605){
          ledState=0x00;
        } else {
          ledState=0x01;
        }
      GPIOC_PDOR = ledState;    
      for (int x=0;x<231;x++){
        if (x<=162){// pixels
          if (screenbuf[x][y]){
            ledState = 0x05;
          } else {
            ledState = 0x01;
          }          
        }
        if (x>162 && x<176){// front porch
          ledState=0x01;
        }
        if (x>171 && x<209){// vsync
          ledState=0x00;
        }
        if (x>208 && x<231){//back porc
          ledState=0x01;
        }
        GPIOB_PDOR = ledState;
      }
      }
    
    }
    I then moved this over to a interrupt running at 60hz and that also worked, but my cpu was maxed and I couldnt do anything else apart from display what was in the initial array.

    Although it will not let me do anything else I am quite pleases that I managed to display anything at all !

    So I am going to look at your lib and make up a interface and see what it can do.

  2. #202
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,018
    Would be nice to see the VGA get attention - especially if possible for pending Teensy 4. Not looked at that here for some time since I wired up the needed adapter and used it some on the Teensy64 VGA board FrankB built.

    Is the 60 Hz _isr() code not shown? It gets 16.7 ms to run and leave any time to run loop() at 60 Hz.

  3. #203
    Junior Member
    Join Date
    Jun 2017
    Posts
    7
    Quote Originally Posted by defragster View Post
    Would be nice to see the VGA get attention - especially if possible for pending Teensy 4. Not looked at that here for some time since I wired up the needed adapter and used it some on the Teensy64 VGA board FrankB built.

    Is the 60 Hz _isr() code not shown? It gets 16.7 ms to run and leave any time to run loop() at 60 Hz.
    I will have a look for that, but I did find this that looks easy enough for me to tinker with.

    http://orchardelica.com/wp/?page_id=529
    Code:
    //
    /*
    * this code is a basic 'get you up and running' code
    * and is rough and ready. It is availble to help you 
    * figure things out. Hopefully you can improve on it.
    * mortonkopf
    */
    //based on timings from Lukas Hartmann
    //also added the drawing functions from Lukas.
    //https://www.youtube.com/watch?v=FfxH6zlsDGo
    // using 72MHz Teensy 3.1
    // using resistors on outputs to derive c0.7v signals
    //based on wiring from Nick Gammon VGA page
     
    #define Width  200 //sreen pixels
    #define Height  200  //screen pixels
     
    /////for spiral pattern///////
    unsigned long runTime = 0;
    float sx = 0, sy = 0;
    uint16_t xx = 0, xx1 = 0, yy = 0, yy1 = 0;
    /////////////
    #include <SdFat.h>
    SdFat sd;
    SdFile myFile;
    const int chipSelect = 10;
    unsigned long bitmapOffset = 54;//0x36;
     
    uint8_t lcdBuffer[Height*Width]; 
    // PortB[0:3, 16:19] = {16, 17, 19, 18, 0, 1, 32, 25}
    /* Teensy external pin number / GPIO port / bit of port
    0 B 16
    1 B 17
    16 B 0
    17 B 1
    18 B 3
    19 B 2
    25 B 19
    32 B 18
    */
    //* bit colour values from bitmap will be?
    //Bit    7  6  5  4  3  2  1  0
    //Data   R  R  R  G  G  G  B  B
     
    // VGA PINS
    #define RGB_OUT GPIOB_PDOR
    #define PIN_VR1 18//16 
    #define PIN_VR2 19//17
    #define PIN_VG1 16//19
    #define PIN_VG2 17//18
    #define PIN_VB1 0
    #define PIN_VB2 1
    #define PIN_VBLANK 8
    #define PIN_HBLANK 7
     
    //#define RED B00110000
    //#define BLUE B00000011
    //#define GREEN B00001100
     
    //byte colours[6] = {0x01,0x02,0x04,0x08,0x10,0x20};//option for calling all single bit/pin values r,r,b,b,g,g
     
    static volatile int VSYNC = 0;
     
    #define NOP asm volatile("nop\n\t");
     
    volatile uint32_t currentLine = 0;
    volatile uint32_t currentFrame = 0;
     
    IntervalTimer timer0;
     
    #define UPPER_BORDER 40
     
    void timerLine() {
      cli();
     
      if (currentLine>1) {
        digitalWrite(PIN_VBLANK, 1);
      } else {
        digitalWrite(PIN_VBLANK, 0);
      }
     
      digitalWrite(PIN_HBLANK, 0);
      RGB_OUT = 0x00;
      RGB_OUT = 0x00;
      RGB_OUT = 0x00;
      RGB_OUT = 0x00;
      
      digitalWrite(PIN_HBLANK, 1);
     
      currentLine++;
      currentLine = currentLine%525;
     
      NOP;
     
      uint32_t y = (currentLine - UPPER_BORDER)>>1;//>>2;//how many rows to duplicate (to square up the image)
     
    //display output section is within the timer >>
      if (y>=0 && y<Height){  //for each row do
      
        for (int i=0; i<40; i++) {//left edge buffer
          RGB_OUT = 0;
        }
        
        uint8_t* displayPointer = lcdBuffer + Width*y;
        
       for (int x=0; x<Width; x++) {
        
        uint32_t color = *(displayPointer++);
     
          color = color | (color<<12); //shift bits
          RGB_OUT = color;
       //   RGB_OUT = color;
      //    RGB_OUT = color;
      //    RGB_OUT = color; //four calls wide to square up each pixel
        }//end of one row of pixels
      }//end of display output section
     
      VSYNC = 0;
       if (y==Height) {  
        VSYNC = 1;
      }
      RGB_OUT = 0;
      sei();
    }
     
     
    void setup()   {
      delay(500);
        // Initialize SdFat or print a detailed error message and halt
      if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
     
    //////-------------------------////////////  
      delay(500);
      pinMode(PIN_VR1, OUTPUT);
      pinMode(PIN_VG1, OUTPUT);
      pinMode(PIN_VB1, OUTPUT);
      pinMode(PIN_VR2, OUTPUT);
      pinMode(PIN_VG2, OUTPUT);
      pinMode(PIN_VB2, OUTPUT);
      pinMode(PIN_VBLANK, OUTPUT);
      pinMode(PIN_HBLANK, OUTPUT);
      
       pinMode(23, INPUT);//for input for patterns controlled by abalogue input?
      
      timer0.begin(timerLine, 31.468);
     
    }
     
    unsigned int tick = 0;
    int t=0;
    int y =0;
     
    void loop()          
    {
        if (VSYNC==1) {
          tick++;   
          VSYNC=0;
    //---------------in this section we can fill the buffer with our colours------//
         
    //display a bmp from sd card
    //displayBMP("holly21.bmp"); //bmp needs to be 8bit bmp
     
    spiral();
    //drawCircle(100,100,50,0x1);    // DRAW the circle
    maths1();
     
    //fill the screen with a colour
    //fillScreen(0x0);
      
    //then draw a diagonal series of dots
     // drawLine(10,10,100,100,0x1); 
     
    //then draw a line 
    //  for(int x=0;x<100;x++){
    //   putPixel(x,10,0x1);
    //   }
       
        }
    }
     
     
     
    //------------drawing functions-------------------------//
    void drawPixel(int x0,int y0,uint8_t color) {
      lcdBuffer[y0*Width+x0] = color;
    }
    void drawLine(int x0, int y0, int x1, int y1, uint8_t color) {
      int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
      int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; 
      int err = (dx>dy ? dx : -dy)/2, e2;
     
      for(;;){
        drawPixel(x0,y0,color);
        if (x0==x1 && y0==y1) break;
        e2 = err;
        if (e2 >-dx) { err -= dy; x0 += sx; }
        if (e2 < dy) { err += dx; y0 += sy; }
      }
    }
    void fillScreen(uint8_t c) {
      for (int y=0; y<Height; y++) {
        for (int x=0; x<Width; x++) {
          lcdBuffer[y*Width+x] = c;
        }
      }
    }
    //----------------------------//
     
    void drawCircle(int xm, int ym, int r, int col){  //centre values
     
       int x = -r, y = 0, err = 2-2*r;                /* bottom left to top right */
       do {                           
     
          drawPixel(xm-x, ym+y,col);                        /*   I. Quadrant +x +y */
          drawPixel(xm-y, ym-x,col);                        /*  II. Quadrant -x +y */
          drawPixel(xm+x, ym-y,col);                        /* III. Quadrant -x -y */
          drawPixel(xm+y, ym+x,col);                        /*  IV. Quadrant +x -y */
          r = err;                                   
          if (r <= y) err += ++y*2+1;                             /* e_xy+e_y < 0 */
          if (r > x || err > y)                  /* e_xy+e_x > 0 or no 2nd y-step */
             err += ++x*2+1;                                     /* -> x-step now */
       } while (x < 0); 
    }
     
    //------------use a bmp to load values into buffer---------------//
     
    void displayBMP(char* filename){ //this is really flakey on the numbers for pad1 to make it work
      //----------------------------------------------------//
          //open the file for reading:
      if (!myFile.open(filename/*"holly.bmp"*/, O_READ)) {
        sd.errorHalt("opening file for read failed");
      }
      int pad1 = Width*6; //for the colour table ref for 8bit bmp? //these pad values are trial and error for me
       byte data;
       byte dataG, dataB, dataR, pix;
       int row,col;
     
     // loop through each pixel in the file
    for(int j=pad1; j<(Height*Width)+(pad1-Width);j++){
       //set position in file to read
       int x = bitmapOffset+j;    
          myFile.seekSet(x);
          data = myFile.read();
          //attempt to move 8bit colour to 6pins of output using bit mask- might not be right
          dataR = data & B00000011; //should this be &= ?
          dataB = data & B00011000;
          dataG = data & B11000000;
          pix = (dataG>>2) + (dataB) + dataR;
     
    //put the data into the buffer - but is upside down?
       lcdBuffer[j-pad1+109] = pix;
      }
      // close the file:
      myFile.close();  
    }
    //---------------end of displaybmp------------------------------------//
     
     
    //---------------patternFrac-------------------------//
     /*  https://github.com/pixelmatix/aurora
     * based on Copyright (c) 2014 Jason Coon
    */
    int time = 0;
    int cycles = 0;
    int16_t v;
    int z;
     void patternFrac() {
        for (int x = 0; x < Width; x++) {
            for (int y = 0; y < Height; y++) {
               v = 0;
                uint8_t wibble = (time);
                v += (x * wibble * 2 + time);
                v += (y * (128 - wibble) * 2 + time);
                v += (y * x * (-time) / 2);
            
        //    if(((v>>8)+127)>20) {
              lcdBuffer[y*Width+x] = (v >> 8) + 127;
        //    }
        //        else { lcdBuffer[y*Width+x] = 0;}
            }
        }
        time += 1;
        cycles++;
        if (cycles >= 750) {
            time = 0;
            cycles = 0;
        }
    }
    //-------------------------------end of pattern--------------//
     
    //--------------------------maths1 pattern------------------//
    int deep =65;
    void maths1(){
     
      for(int number=0;number<150;number++){
        for (int x = 0; x < Width; x++) {
            for (int y = 0; y < Height; y++) {
               v = 0;
                uint8_t wibble = (time);
                v += (x * wibble * 2 + time);
                v += (y * (128 - wibble) * 2 + time);
                v += (y * x * (-time) / 2);
            
            if(((v>>8)+127)>deep) {
              lcdBuffer[y*Width+x] = (v >> 8) + 127;}
                else { lcdBuffer[y*Width+x] = 0;}
            }
        }
        deep +=1;
        time += 1;
        cycles++;
        if (cycles >= 180) { //keep cycles and deep max lengths different for more interesting pattern variation
          deep =65;
            time = 0;
            cycles = 0;
        }
    }
    //second part
    deep = 245;
    cycles = 170;
    time=0;
      for(int number=0;number<170;number++){
        for (int x = 0; x < Width; x++) {
            for (int y = 0; y < Height; y++) {
               v = 0;
                uint8_t wibble = (time);
                v += (x * wibble * 2 + time);
                v += (y * (128 - wibble) * 2 + time);
                v += (y * x * (-time) / 2);
            
            if(((v>>8)+127)>deep) {
              lcdBuffer[y*Width+x] = (v >> 8) + 127;}
                else { lcdBuffer[y*Width+x] = 0;}
            }
        }
        deep -=1;
        time -= 1;
        cycles--;
        }
    }
     
    //------------------------------------------------//
     
    //--------spiral pattern----------------//
    void spiral(){
      fillScreen(0x0);
    byte c = random(0x01,0x40);
    int n = random(12, 30), r = random(25, 55);
     // Rainbow patern generator
    // Alan Senior 22/2/15 
      for (long i = 0; i < (360 * n); i++) {
        sx = cos((i / n - 90) * 0.0174532925);
        sy = sin((i / n - 90) * 0.0174532925);
        xx = sx * (20 - r) + 100;
        yy = sy * (20 - r) + 100;
     
        sy = cos(((i % 360) - 90) * 0.0174532925);
        sx = sin(((i % 360) - 90) * 0.0174532925);
        xx1 = sx * r + xx;
        yy1 = sy * r + yy;
        drawPixel(xx1, yy1, c);
    }
    byte cc =random(0x01,0x40);
      n = random(2, 20),
      r = random(30, 55);
      for (long i = 0; i < (360 * n); i++) {
        sx = cos((i / n - 90) * 0.0174532925);
        sy = sin((i / n - 90) * 0.0174532925);
        xx = sx * (20 - r) + 100;
        yy = sy * (20 - r) + 100;
     
        sy = cos(((i % 360) - 90) * 0.0174532925);
        sx = sin(((i % 360) - 90) * 0.0174532925);
        xx1 = sx * r + xx;
        yy1 = sy * r + yy;
        drawPixel(xx1, yy1, cc);//i
      }fillScreen(0x00);
    }
    //---------end of sprial pattern--------------------//

  4. #204
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,018
    Oh - and congrats on getting something to show as noted.

    The interval timer "myTimer.begin(function, microseconds);" with : timer0.begin(timerLine, 31.468);
    is asking to be called 31778.31 times per second ?

    reformatted the _isr to read it - timer calls:
    Code:
    void timerLine() {
      cli();
    
      if (currentLine > 1) {
        digitalWrite(PIN_VBLANK, 1);
      } else {
        digitalWrite(PIN_VBLANK, 0);
      }
    
      digitalWrite(PIN_HBLANK, 0);
      RGB_OUT = 0x00;
      RGB_OUT = 0x00;
      RGB_OUT = 0x00;
      RGB_OUT = 0x00;
    
      digitalWrite(PIN_HBLANK, 1);
      currentLine++;
      currentLine = currentLine % 525;
      NOP;
    
      uint32_t y = (currentLine - UPPER_BORDER) >> 1; //>>2;//how many rows to duplicate (to square up the image)
      //display output section is within the timer >>
      if (y >= 0 && y < Height) { //for each row do
    
        for (int i = 0; i < 40; i++) { //left edge buffer
          RGB_OUT = 0;
        }
    
        uint8_t* displayPointer = lcdBuffer + Width * y;
        for (int x = 0; x < Width; x++) {
          uint32_t color = *(displayPointer++);
          color = color | (color << 12); //shift bits
          RGB_OUT = color;
        }//end of one row of pixels
      }//end of display output section
    
      VSYNC = 0;
      if (y == Height) {
        VSYNC = 1;
      }
      RGB_OUT = 0;
      sei();
    }

Posting Permissions

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