Teensy 3.6 VGA driver

Maybe try reconfiguring the crossbar switch bus master priority levels? The default priority levels are shown on page 417. USB1 has priority level 6, the highest of all.

The RAM is slave port #1. So you should be able to change it by writing to AXBS_PRS1. Maybe try writing 0x05432610, so the DMA controller gets highest priority for slave #1.

Maybe also be worthwhile to write to AXBS_CRS1, to configure the arbitration for slave #1 to park on master #2....

Hi Paul,
unfortunately, that's the case already and does not help.
https://github.com/qix67/uVGA/blob/master/uVGA.cpp#L986
But please read the comment:
Code:
    // let's also give the highest priority from DMA to RAM and GPIO in crossbar switch
    // master 2 = DMA
    // slave 1 = sram backdoor
    // slave 3 = GPIO
    // when only the CPU requests access, this has nearly no effects
    // Kinetis Reference manual says 6 is the highest priority but AXBS_PRSn register description says 0 is the highest
    // I assumed 6 is correct but wathever I chose, I see no difference during my test
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    AXBS_PRS1 = 0x05432610;    //0x06543021;
    AXBS_PRS3 = 0x05432610;    //0x06543021;
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
    AXBS_PRS1 = 0x00002310;    //0x00003021;
    AXBS_PRS3 = 0x00002310;    //0x00003021;
#endif

    // to gain 1 more cycle, when RAM and GPIO port is not used, attach them to DMA and for a fixed priority
    // with this tip, DMA gains a lot of time... really a lot due to fact the frame buffer must be copied byte by byte.
    // This type of copy waste a lot of bandwidth/time, so much it is not possible to trigger copy using a timer to obtain a more accurate pixel
    AXBS_CRS1 = AXBS_CRS_ARB_FIXED | AXBS_CRS_PARK_FIXED | AXBS_CRS_PARK(2);
    AXBS_CRS3 = AXBS_CRS_ARB_FIXED | AXBS_CRS_PARK_FIXED | AXBS_CRS_PARK(2);

    // when DMA uses RAM, it cannot be stopped... but it should already be the default settings.
    AXBS_MGPCR2 = 0x00000000;

    // all other masters must wait, even during undefined length burst
    AXBS_MGPCR0 = 0x00000001;
    AXBS_MGPCR1 = 0x00000001;
    AXBS_MGPCR3 = 0x00000001;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    AXBS_MGPCR4 = 0x00000001;
    AXBS_MGPCR5 = 0x00000001;
    AXBS_MGPCR6 = 0x00000001;
#endif

    // give absolute priority to DMA on SRAM_L and favor DMA on SRAM_U
    // this final settings greatly improve pixel sharpness and line stability under heavy graphic load
    MCM_CR = (MCM_CR & ~(MCM_CR_SRAMLAP(3) | MCM_CR_SRAMUAP(3)))
                    | MCM_CR_SRAMLAP(3) | MCM_CR_SRAMUAP(1);

Is it possible that there's a bug somewhere ?
 
Last edited:
Maybe try reconfiguring the crossbar switch bus master priority levels? The default priority levels are shown on page 417. USB1 has priority level 6, the highest of all.

The RAM is slave port #1. So you should be able to change it by writing to AXBS_PRS1. Maybe try writing 0x05432610, so the DMA controller gets highest priority for slave #1.

Maybe also be worthwhile to write to AXBS_CRS1, to configure the arbitration for slave #1 to park on master #2....

Funny, that's exactly the value I use :) I also modified PGPCR registers to force bus arbitration at each cycle. Unfortunately, this does not fix the problem. PRS values change nothing. CRS values improve stability a lot during line rendering (I parked both SRAM port and GPIO port to DMA) but does not prevent a late start.

The weirder thing is when USB is transfering, lines seems to wave regularly.
 
Question: Does the Added RAM replace the MCU RAM for buffer? That would mean a T_3.5 could then use this VGA hardware for display.

Yes, that's what I want to do.

I will try to add RAM this weekend. I already soldered all components on breakout boards, just need to add a lot of cables to glue everything together. If the RAM works has expected, in the worst case scenario, only one line of framebuffer will be kept in MCU SRAM. If everything goes well, only 16 bytes will be required.
 
buffer public: ->This requires additional function to retrieve row stride. yes please ;-)

#defines would help (?!)
They just need to be defined before #include your library.

I will try to make the function this weekend. I will also move row stride and buffer size computation in define to allow external usage. This weekend starts to be very busy ;)

16Bit Chips: How about ignoring the upper 8 bit ? It's a bit wasteful - but who cares..as long it makes things easier...or cheaper..

As soon as I search 3.3v components, 16 bit version seems to be cheaper than their 8 bit one. 8 bit is like a synonym to 5v.
 
Based on the trivial resistor connection to VGA adapter I did - and half re-did so far - that sounds like a few 'glue' cables to solder with banks of 8 to deal with. Good luck! I got my VGA connector replaced - hopefully with correct reference points - just need to redo the 6 wires from the Teensy GND and resistors to the VGA pins so I can see it flicker with USB interruptions. Having it work on both T_3.5 and T_3.6 with the board will make the effort more worthwhile to build the board. For the pin functions needed do the under pins offer any opportunities to move from the edge pins?
 
For the pin functions needed do the under pins offer any opportunities to move from the edge pins?

Unfortunately no. It has to be pin 0-7 of port D because it is GPIO, not alternate pin function. Technically, it is possible to use a different port but ports A, B and C carry a lot more functions than port D and you will lose a lot of pins/functions. Port A is not usable because only pin A5 is available (pin 25) and you will loose pin 3,4,26,27,28,39. Port B is not possible because only pins B0-B3 are available (pin 16-19) and you will loose pins 0,1,29,30,31,32. Port C is possible (pin 15,22,23,9,10,13,11,12) but LED on pin 13 may change voltage and you will loose pins 35,36,37,38 because they share the same port. The last port (E) is not possible, only pin E24,25,26 are available.

If I can make flexbus work, it will use different pins (see here) but in the same manner, it will not be possible to choose the pin you want.
 
There is a missing line (UVGA_240M_452X300) :
2017-09-22 20.20.43.jpg
As you see on the photo, the top line of "RUN" is missing
 
There is a missing line (UVGA_240M_452X300) :
View attachment 11587
As you see on the photo, the top line of "RUN" is missing

Can you enable library debug mode and check the line starting with "y SRAM_U: ", it should be in the first line of the debug output. The missing line can be either the first or 2nd line in SRAM_U.
 
Can you enable library debug mode and check the line starting with "y SRAM_U: ", it should be in the first line of the debug output. The missing line can be either the first or 2nd line in SRAM_U.
No need to check. I check on my side and it is not there but somewhere in SRAM_L, it's weird ???

Stupid me, this video mode repeats line, I forget to divide video line number by 2 to obtain frame buffer line. It is really when the DMA switch from SRAM_L TCD to SRAM_U TCD. I think one line is not repeated
 
Last edited:
There is a missing line (UVGA_240M_452X300) :
View attachment 11587
As you see on the photo, the top line of "RUN" is missing

Problem fixed and fix commited on github. The last 2 lines of SRAM_L were not duplicated.

I still wonder how monitor can keep sync because vsync starts 2 lines earlier and the whole screen height was reduced by 2 lines, wonderful analog world :)
 
2 quick questions:

Should I include this library with Teensyduino 1.40?

Can someone post a video, showing the hardware used and results running on a monitor? Looking for something showing how it works, not just a close-up of the screen only.

I finally took time to make a video.


The video shows the hardware and all demos. I packed nearly all of them in a single program. Teensy runs @240MHz and frame buffer resolution is 703x300. The sphere demo runs separately because its resolution is 452x300 and everything is in realtime, no flipbook trick because there is not enough memory to do it. Near the end of the video, you can see some spheres are missing at the top of the screen because teensy cannot draw them fast enough before the DMA sends bytes to TV.

The black connector near the teensy is not used here. I used it when I tested my code on teensy 3.2.
 
Last edited:
Hi Paul,
unfortunately, that's the case already and does not help.
https://github.com/qix67/uVGA/blob/master/uVGA.cpp#L986

Is it possible that there's a bug somewhere ?

Another explanation is a shielding problem. USB signals may generate electromagnetic noise disturbing the VGA signals.

How wonderful is my cable shielding :rolleyes: but I used small cat6 network cable conductors ;)
DSC01176.jpg

800x600@60 VGA uses ~24MHz signal. USB 2.0 seems to use 24/48Mhz signal and USB 1.1 uses 1.5/12MHz signal, they all seems to be harmonic, no :confused:
 
Another explanation is a shielding problem. USB signals may generate electromagnetic noise disturbing the VGA signals.

How wonderful is my cable shielding :rolleyes: but I used small cat6 network cable conductors ;)
View attachment 11592

800x600@60 VGA uses ~24MHz signal. USB 2.0 seems to use 24/48Mhz signal and USB 1.1 uses 1.5/12MHz signal, they all seems to be harmonic, no :confused:

No. noise can not move the pixels or slow down DMA. The pixels move to the right border. Just make a static picture with long vertical stripes, and you'll see what it looks like. With USB-HOST even *much* more than with USB-Device. I'd say it's much more than 100ns sometimes ? I have no idea how to measure it with my equipment.
I can take a picture, if really needed.
 
qix67 - Good Work! The DEMO video looks impressive. And your off PCB connector looks much easier to wire more cleanly than the PCB style Frank and I are using.
 
buffer public: ->This requires additional function to retrieve row stride. yes please ;-)

#defines would help (?!)
They just need to be defined before #include your library.

I just committed a new version allowing static frame buffer usage. I tried to make it as simple as possible to use.

I add various macros at the end of uVGA.h and I add an example in README.txt (2b). I could not make it in less than ... 2 lines :)
 
No. noise can not move the pixels or slow down DMA. The pixels move to the right border. Just make a static picture with long vertical stripes, and you'll see what it looks like. With USB-HOST even *much* more than with USB-Device. I'd say it's much more than 100ns sometimes ? I have no idea how to measure it with my equipment.
I can take a picture, if really needed.

I think there is at least one problem coming from either noise or grounding problem. I don't think DMA slows down, I think the pixel displacements are a side effect produced by the monitor due to malformed/not sharp enough signals

The problem is instable end of line like on the following photo but it globally affects whole screen.

IMG_20170924_112929.jpg

In my case, it occurs when I let arduino IDE console opened, without doing anything with it. This looks like end of line appears too early but DMA cannot do this. Start of line is ok. I wrapped all my VGA conductors in an aluminium foil and nearly all ends of line are displayed correctly.


I tried to add a lot of Serial.print in my test code and even with foil I keep to have flickering line and at the same time, I have a lot of usb traffic (linux reports more than 1000 usb interrupt per second). I will try to prepare a little PCB removing all need of wires, perhaps it will solve the problem.
 
The line displacements are very weird. It seems to affect more some color than other.

On the following photo, blue lines seem to be more disturbed than green lines. The strangest one are the 3rd and 4th blue lines. The right side of 3rd blue line is partially moved to the right but it does not affect the following green line and the right side of the next blue line is ok. There is 9 pixels between each vertical line (168MHz,640x480@60Hz). On the photo, we can see 2 monitor pixels per image pixel and most of displacements are 1 monitor pixel wide this makes 1/2 image pixel. If it were a DMA problem, once a pixel is delayed, all the following ones will be delayed but not here, 9 pixels later, everything is ok. The problem may come from monitor sampling rate. Because I don't send pixels at the correct pixel clock rate, the monitor will put the color on one pixel or the next depending on clock skew.

IMG_20170924_121024.jpg

I am curious to see the output produced by a CRT, I think. I should have one during october.
 
Last edited:
I'll see what I can on my display(s) [LCD & CRT] - my direct wired on PCB - similar to Frank's just needs two more lines run and then time to test. I wired a PS2 connector for C64 reference.
 
The line displacements are very weird. It seems to affect more some color than other.

On the following photo, blue lines seem to be more disturbed than green lines. The strangest one are the 3rd and 4th blue lines. The right side of 3rd blue line is partially moved to the right but it does not affect the following green line and the right side of the next blue line is ok. There is 9 pixels between each vertical line (168MHz,640x480@60Hz). On the photo, we can see 2 monitor pixels per image pixel and most of displacements are 1 monitor pixel wide this makes 1/2 image pixel. If it were a DMA problem, once a pixel is delayed, all the following ones will be delayed but not here, 9 pixels later, everything is ok. The problem may come from monitor sampling rate. Because I don't send pixels at the correct pixel clock rate, the monitor will put the color on one pixel or the next depending on clock skew.

View attachment 11599

I am curious to see the output produced by a CRT, I think. I should have one during october.

Oh, I've not noticed that there is difference depending on the colors. Good catch.
The displacement is *much* more with USB-HOST. Several pixels.
 
I just committed a new version allowing static frame buffer usage. I tried to make it as simple as possible to use.

I add various macros at the end of uVGA.h and I add an example in README.txt (2b). I could not make it in less than ... 2 lines :)

Great. I'll try it tomorrow.
 
My board is working with current GitHub code. My meter says VGA pin 2 color channel has 1K swapped with 2K so my shading will be off - I am using the 100 Ohm resistors for H&V/Sync so I may not have the cleanest edges?
<edit>: weak edges seems to be from USB Serial Monitor - noted below.

Here is my board back - PS2 wired with 3.3V but not tested yet.
Board1_Built.jpg

DrawingTest runs smoothly - no obvious problems - but too fast to see any errors

Spheres fails to build without edit below - then runs well. They move smoothly and quickly they look like a blur of about 8 unless you fixate and follow as they move across the screen - seems to lose it nearing 600 spheres - though still running at 1,000+ they just don't fill to the top of the screen right near 600 - though at 1,050 they are edge to edge - and slowing down so only about 4 blurred impressions at 1209 spheres the screen is brighter on the bottom. At 1600 plus spheres the text counter in the lower left got pushed off - then came back about 1650 and still running with whole screen flash:
Spheres - NEEDS THIS EDIT TO INO:
//#define UVGA_240M_452X200
#define UVGA_DEFAULT_REZ

spheres:85: error: 'modeline' was not declared in this scope ret = uvga.begin(&modeline);
^
Using library uVGA at version 1.0 in folder: i:\tcode\libraries\uVGA 'modeline' was not declared in this scope

The ASCIITableVGA shows some character edge jitter.
<EDIT> running without USB SERIAL stops the Jitter! Text is smooth and clean! {TyCommander with Serial Off, or USB battery pack }
 
Last edited:
Tried above on my desktop 23" LCD at 240 MHz. Dropped to 168 MHz with drawingTest and that worked , and on second 19" LCD.

That then worked fine on my old iiyama Vision Master CRT, but did not come up with a working resolution on the KDS CRT. The sketch might debug print the working resolution?

Really Funny having the T_3.6 on the above PCB - with a battery pack about the same size but heavier than Teensy - plugged into an 80 (?) pound CRT.

Frank sent me his PS2 VGA code - I'll test with PS2 keyboard and see if the KDS gets a sync on alternate resolutions too. And I should swap those two resistors :(
Teensy pin 8 (port D, bit 3) -> 1k resistor -> VGA pin 2 (green)
Teensy pin 7 (port D, bit 2) -> 2k2 resistor -> VGA pin 2(green)

<edit>: Adding vertical line pics that seem okay edge to edge - except green line color fade on black screen in pic is similar to on screen - except dimmer not yellow (evident on white background where alternate green lines are thinner?). This is at 240 Mhz - NO USB connect ( adding USB shows harsh flickering zipper edges )- on 3rd LCD ( a DELL with a HUB to be like Frank ) :

20170925_004809.jpg20170925_004816.jpg
Code:
void loop()
{
  int fb_width, fb_height;
  int row, col;

  uvga.get_frame_buffer_size(&fb_width, &fb_height);
  uvga.clear(0b11111111);
  for (col = 0; col < fb_width; col += 18) {
    uvga.drawLine(col, 0, col, fb_height, 0b00011100);
    uvga.drawLine(col + 9, 0, col + 9, fb_height, 0b00000011);
  }
  delay( 3000 );
  uvga.clear(0);
  for (col = 0; col < fb_width; col += 18) {
    uvga.drawLine(col, 0, col, fb_height, 0b00011100);
    uvga.drawLine(col + 9, 0, col + 9, fb_height, 0b00000011);
  }
  delay( 3000 );
}
 
Last edited:
Spheres fails to build without edit below - then runs well. They move smoothly and quickly they look like a blur of about 8 unless you fixate and follow as they move across the screen - seems to lose it nearing 600 spheres - though still running at 1,000+ they just don't fill to the top of the screen right near 600 - though at 1,050 they are edge to edge - and slowing down so only about 4 blurred impressions at 1209 spheres the screen is brighter on the bottom. At 1600 plus spheres the text counter in the lower left got pushed off - then came back about 1650 and still running with whole screen flash:

Well, I forgot to say spheres demo runs only @240MHz. The code works in all resolutions with your change but in 703x300, it takes too much time to clear the frame buffer. When there is too many spheres (~1209 here), the beam reaches the bottom of the screen before the text is printed. Later, displaying everything takes so much time that a black frame is inserted between each image.

Technically, it is not a bug, it is just a hardware limit.

The ASCIITableVGA shows some character edge jitter.
<EDIT> running without USB SERIAL stops the Jitter! Text is smooth and clean! {TyCommander with Serial Off, or USB battery pack }

Then, this means we all have the same problem as soon as usb is connected.
 
Again - Very impressive and useful work qix67!

I should have done a pic of the jitter USB connect causes - it was significant! With TyCommander serial Off stops it - when on with no messages it is ugly. Now I see why Frank jumped to PS2 support with USB Host being as bad or worse. Hoping there is some bandwidth to tweak a solution?

Workaround for debug would be to dump to Serial1 and use a second Teensy (with TyCommander) to echo/proxy through the text to another serial window. Though PS2 pins using Serial1 as built so will need to see if another is open. New Teensy64_VGA PCB does present Serial1 pins as ready to use.

In Spheres - 240Mhz - got it - I tried that before I pushed the speed up from default - it does compile there.
Spheres and Hardware limit makes sense - I was surprised when it kept running so well that long. Nobody needs to watch spheres that long anyhow - it could just count down or restart once it hits 1200 - or even 500 before the first anomaly I caught.
 
Back
Top