[posted] VGA out for Teensy 4.0/4.1

Are the resistor values for 12 Bit the same for the R2R?

Yes Frank , the resistor value are the same when you add more stage ( 1 x 536 and 1 x 270 ohm ).
Just bad that i cant help for the VGA code on Teensy :) , i was more involved in STM32 in the past , and the registers / DMA etc used on teensy are actually black magic up i can learn more on this MCU :D
 
Does this look OK?
T4VGA.jpg
 
Are you aware of the VLSI23S010D ?
This is a 1MBIT SPI memory with integrated DACS for video. It can do PAL, NTSC (and I think VGA) - LQFP48 (would have to practice soldering...)

There is also a successor, with 4MBIt and higher resolutions. Unfortunately it is a BGA.

But with a chip it's not so much fun...
 
for the emulators you need the PSRAM soldered on the T4.1 and of course the analog joystick + the 3 buttons. See IOPIN.h, should be also on the schematic of the MCUME project.
This is the min config (some emus don't need the PSRAM)

USB can also be added for the computers (not all, mostly ST and Amiga). I2C keyboard for computer keyboard is optional.
 
for the emulators you need the PSRAM soldered on the T4.1 and of course the analog joystick + the 3 buttons. See IOPIN.h, should be also on the schematic of the MCUME project.
This is the min config (some emus don't need the PSRAM)

USB can also be added for the computers (not all, mostly ST and Amiga). I2C keyboard for computer keyboard is optional.

Thanks :)
What do you think?
5b6fae2649a4ab87d8fb6c90f9cd5734.jpg

- The analog joystick + Fire is on a extra connector.
- 3 Buttons "on board"
- C64 Joystick connector,
- Big connector is for all signals but VGA + I2S

Schmatic attached
 

Attachments

  • vga.pdf
    436.8 KB · Views: 120
Ok, corrected the name to MCUME ;) added an I2C connector, and ordered 5pcs ...
Thanks. I'll stop polluting this thread now ;)
 
Looking great!
You went for the full ladder of resistors which is not a bad thing.
So you directly used the I2S audio chip directly on the PCB, I never went that far (I used the module from amazon)... ;-)
Most important is VGA and audio. Buttons can be remapped in SW

I will just miss a fixed USB connector on the PCB but for the rest it looks ok. I never found a proper way to connect USB host to the teensy with a floating wires...

Having the full header on the side is a great idea.
I was looking for a way to support both ILI display or VGA with the same PCB but the issue will be the resistors on the SPI. But not if we use the SPI bus on 39,26,27 + another pin for CS via the full header connector.

Thanks a lot for the contribution.
You know that I am not a HW guy, my PCB will never be that nice!
 
I'm not a hardware-guy, too. And I have not enough practice with creating PCBs.. maybe I do 3 different in a year.. and.. 70% of the first run have a mistake somewhere!
But from china, that's not a big problem.. paid around 7.50€ now (PCBs in nice blue - not the color above)
If it turns out to work (I hope so..well..30% chance ;) , I want to send you one (with parts). Another goes to BriComp, and I'll use the remaining three.
USB: PJRC sells a cable for that. And I once made a "daughter board" - very small - that can be soldered on top of the Teensy. It was made for the 3.6, so it's above the ethernet, unfortunately.

Edit: Turns out that my prefered shop does not sell 536Ohm in small quantities .. grrr..§$%&/ I don't need 5000pcs..
 
You are also from Germany I think, I am from Brussels.
I typically order from Mouser but I was lucky to have a small electronic shop nearby selling parts.
He just retired 2 months ago unfortunately...

I have not been very active the past months on the Teensy.
I wanted to upgrade some of my old computers...
After 35 years, I decided to upgrade my own Atari520ST with a Terriblefire534 and extra memory.
Those boards are made to replace 68000 on Amiga but I ended up on the Atari forum with a guy using them on Atari.
I am still struggling with some compatibility issue but it basically runs with the IDE CF. It is amazing to see an ST with a 68030 at 50MHz.

I was thinking about using the Teensy 4.1 on real C64. There was that Backbit project using T3.5. May be we could add VGA output to a real C64 and simulate the VIC chip?
 
You are also from Germany I think, I am from Brussels.
I typically order from Mouser but I was lucky to have a small electronic shop nearby selling parts.
He just retired 2 months ago unfortunately...

I have not been very active the past months on the Teensy.
I wanted to upgrade some of my old computers...
After 35 years, I decided to upgrade my own Atari520ST with a Terriblefire534 and extra memory.
Those boards are made to replace 68000 on Amiga but I ended up on the Atari forum with a guy using them on Atari.
I am still struggling with some compatibility issue but it basically runs with the IDE CF. It is amazing to see an ST with a 68030 at 50MHz.

I was thinking about using the Teensy 4.1 on real C64. There was that Backbit project using T3.5. May be we could add VGA output to a real C64 and simulate the VIC chip?

Yes.. things like these are fun.
But for me, it's not that interesting. In addition, the VIC is very tricky. It has to be cycle-excact to be 100% compatible - I have it working in the emulaton, but for 3.6 I had to do a few tradeoffs. Some Demos are not working. The VIC code would have to be rewritten...
It is very tricky, too... the Commodore engeneers did a totally amazing, unbelievable job. Decades later users still found new ways to use it for new effects. With 1MHZ system clock...

I like more to just use the grey "bread" housing, with the keyboard... :)
 
Arrived :)
20210311_180035.jpg
The colors are quite good, sound too. As you see I added USB:
20210311_183047.jpg
Well.. the USB connection is very near to the VGA :-(
A few vias are too near to pads. Needs a bit attention when soldering.
As said.. most of my boards have issues :) If I ever do a second version i'll fix that (and I need to create a "checklist" with these isues listed, to make my next boards better). Perhaps a 2nd USB to power the VGA->HDMI converter would be useful, too.


So far, only VGA and Sound is tested. There's a simple lowpass after the chip. As I bought some PT8211 clones "TM8211" several years ago, and have never tested them, I tried it here. For my ears, it's pretty equal.
As I'm not an "audiophile" I have no plans to test the soundquality further.

20210311_183253.jpg
 
Looking great!
Can you still fit a VGA cable with a USB mouse/keyboard like dongle next to it ?
I typically have a small passive HUB attached so should be ok (just like the USB connector width)
Have you tested Audio using the interrupt based Audio driver of the VGA library?

if you use a VGA2HDMI adapter may be not a bad idea to power it via an extra USB port but will the power be enough if you for e.g. connect other stuff via the header pins.

Not bad for a first design.
I like the fact you have all connectors (but the joystick) at the back.

I also like the SMD pinch on the picture, you had fun soldering the resistors ;-)
 
My eyes are not the best. Farnell did not want to send to me (only to companies), but I found TME.eu sells 536R - but as 0603 only. Soldering them was a bit tricky for me - even more as there are two vias very close to a pad :-(
Most other parts are 0805 - way better.
When I take a photo with my smartphone and look at the solder joints enlarged, they look terrible - they are almost created in the blind.
I think I need to get some kind of aid to make soldering small parts work better. Maybe a microscope. $$$ :-(

USB: A small dongle should fit. Cables with slim connectors, too.
You have a PM.
 
Last edited:
Hi there! Big thanks to jean marc and others for this contribution.
I have to drive a tft lcd with no frame buffer. Timings are not as strict as vga.

Resolution is 480x 480. 8bpp is fine as I will copy the lsb to the least significant bits to make it 16 bits.

Do you see an issue in adapting a bit the timings and the pclk??? Ant trap needs to be avoided??
 
Should be doable. I could go up to 640x480. So your TFT interface is 16 bits digital correct? You can indeed make lowest bits being zero for each component
 
For a TFT display you need to add 'data enable' and 'pixel clock' signals , 'data enable can be tied to vcc but pixel clock have to be generated , it's not needed on VGA screen , so then set the colors , then data enable , then pixel clock :)
Now i don't remember if you need to connect the TFT 'RST' signal to vcc or if it's controlled from the MCU, check your datasheet for this ...

Cheers.
 
Hi !
Thanks for the replies!

Indeed pixclk needs to be generated. Looking at the code I need to route pll5 to an output pin. I think that is it.
Timings are probably not as critical with my small 480x480 tft.

Jean marc, all the videos instabilities you had were due to the vga monitor loosing sync or unlocking ??

Should not really happen with the tft contrôler . It is an st7701s.

Will give a try in august. Cheers
 
Issue I had was because of having to use 2 dmas to control the 2 flexio registers. There is no way to have 8 bits output with a single flexio on the teensy4.x. 8 consecutive IO is only possible with flexio3 but that one has no DMA.
 
Hi Jean-Marc,

I have a question about video out on tensy:

Using a Lepton module IR camera, with MISO to teensy I need to have a PAL signal out on a pin.
So do you think it's possible to convert a matrice image 120x160 to PAL signal ?
How can I do it ? Is this alway realize by somebody ?

regards.

Laurent.
 
adding thisinfo prev post
sample code arduino :
goal is to write on pin in PAL format otherwise of png...
from https://github.com/NachtRaveVL/Lepton-FLiR-Arduino/blob/master/examples/ImageCaptureExample/ImageCaptureExample.ino
Code:
// Lepton-FLiR-Arduino Image Capture Example
// In this example, we will copy out thermal image frames to individual BMP files located
// on a MicroSD card using the SD library. Note that you will need a MicroSD card reader
// module for this example to work. Both the FLiR module and MicroSD card reader module
// will be on the same SPI lines, just using different chip enable pins/wires.

#include "LeptonFLiR.h"
#include <SD.h>

const byte flirCSPin = 22;
LeptonFLiR flirController(Wire, flirCSPin); // Library using Wire and chip select pin D22

const byte cardCSPin = 24;

void setup() {
    Serial.begin(115200);

    Wire.begin();                       // Wire must be started first
    Wire.setClock(400000);              // Supported baud rates are 100kHz, 400kHz, and 1000kHz
    SPI.begin();                        // SPI must be started first as well

    SD.begin(cardCSPin);                // SD library using chip select pin D24

    // Using memory allocation mode 80x60 8bpp and fahrenheit temperature mode
    flirController.init(LeptonFLiR_ImageStorageMode_80x60_8bpp, LeptonFLiR_TemperatureMode_Fahrenheit);

    // Setting use of AGC for histogram equalization (since we only have 8-bit per pixel data anyways)
    flirController.agc_setAGCEnabled(ENABLED);

    flirController.sys_setTelemetryEnabled(ENABLED); // Ensure telemetry is enabled

    SD.rmdir("FLIR");                   // Starting fresh with new frame captures
}

uint32_t lastFrameNumber = -1;          // Tracks for when a new frame is available

void loop() {
    if (flirController.readNextFrame()) { // Read next frame and store result into internal imageData
        uint32_t frameNumber = flirController.getTelemetryFrameCounter();

        if (frameNumber > lastFrameNumber) { // Frame counter increments every 3rd frame due to export restrictions
            lastFrameNumber = frameNumber;

            char fileName[] = "FLIR/IMG0000.BMP";
            uint16_t fileNumber = (uint16_t)(frameNumber / 3);
            wordsToHexString((uint16_t *)&fileNumber, 1, &fileName[8], 4);

            File bmpFile = SD.open(fileName, FILE_WRITE);

            if (bmpFile) {
                writeBMPFile(bmpFile,
                             flirController.getImageData(),
                             flirController.getImageWidth(),
                             flirController.getImageHeight(),
                             flirController.getImagePitch());

                bmpFile.close();

                Serial.print(fileName);
                Serial.println(" written...");
            }
        }

        // Occasionally flat field correction normalization needs ran
        if (flirController.getShouldRunFFCNormalization())
            flirController.sys_runFFCNormalization();
    }
}

// Writes a BMP file out, code from: http://stackoverflow.com/questions/2654480/writing-bmp-image-in-pure-c-c-without-other-libraries
void writeBMPFile(File &bmpFile, byte *imageData, int width, int height, int pitch) {
    byte file[14] = {
        'B','M', // magic
        0,0,0,0, // size in bytes
        0,0, // app data
        0,0, // app data
        40+14,0,0,0 // start of data offset
    };
    byte info[40] = {
        40,0,0,0, // info hd size
        0,0,0,0, // width
        0,0,0,0, // heigth
        1,0, // number color planes
        24,0, // bits per pixel
        0,0,0,0, // compression is none
        0,0,0,0, // image bits size
        0x13,0x0B,0,0, // horz resoluition in pixel / m
        0x13,0x0B,0,0, // vert resolutions (0x03C3 = 96 dpi, 0x0B13 = 72 dpi)
        0,0,0,0, // #colors in pallete
        0,0,0,0, // #important colors
    };

    uint32_t padSize  = (4-(width*3)%4)%4;
    uint32_t sizeData = width*height*3 + height*padSize;
    uint32_t sizeAll  = sizeData + sizeof(file) + sizeof(info);

    file[ 2] = (byte)((sizeAll      ) & 0xFF);
    file[ 3] = (byte)((sizeAll >>  8) & 0xFF);
    file[ 4] = (byte)((sizeAll >> 16) & 0xFF);
    file[ 5] = (byte)((sizeAll >> 24) & 0xFF);
    info[ 4] = (byte)((width      ) & 0xFF);
    info[ 5] = (byte)((width >>  8) & 0xFF);
    info[ 6] = (byte)((width >> 16) & 0xFF);
    info[ 7] = (byte)((width >> 24) & 0xFF);
    info[ 8] = (byte)((height      ) & 0xFF);
    info[ 9] = (byte)((height >>  8) & 0xFF);
    info[10] = (byte)((height >> 16) & 0xFF);
    info[11] = (byte)((height >> 24) & 0xFF);
    info[20] = (byte)((sizeData      ) & 0xFF);
    info[21] = (byte)((sizeData >>  8) & 0xFF);
    info[22] = (byte)((sizeData >> 16) & 0xFF);
    info[23] = (byte)((sizeData >> 24) & 0xFF);

    bmpFile.write((byte *)file, sizeof(file));
    bmpFile.write((byte *)info, sizeof(info));

    byte pad[3] = {0,0,0};
    imageData += (height - 1) * pitch;

    for (int y = height - 1; y >= 0; --y) {
        for (int x = 0; x < width; ++x) {
            byte pixel[3]; // blue green red
            pixel[0] = pixel[1] = pixel[2] = imageData[x];

            bmpFile.write((byte *)pixel, 3);
        }

        bmpFile.write((byte *)pad, padSize);
        imageData -= pitch;
    }
}
 
Back
Top