Call to arms | Teensy + SDRAM = true


LCDIF requires 64-byte aligned buffers, the extmem_malloc interface doesn't have a way to request aligned allocations... should probably fix that.
Note this is sort-of nothing new, in that DMA access really prefers things to be at least 32 byte aligned. Which is for example why many
of our display drivers have something in them like:
Code:
uint8_t ILI9341_t3n::useFrameBuffer(
    boolean b) // use the frame buffer?  First call will allocate
{
#ifdef ENABLE_ILI9341_FRAMEBUFFER

  if (b) {
    // First see if we need to allocate buffer
    if (_pfbtft == NULL) {
      // Hack to start frame buffer on 32 byte boundary
      _we_allocated_buffer = (uint16_t *)malloc(CBALLOC + 32);
      if (_we_allocated_buffer == NULL)
        return 0; // failed
      _pfbtft = (uint16_t *)(((uintptr_t)_we_allocated_buffer + 32) &
                             ~((uintptr_t)(31)));
      memset(_pfbtft, 0, CBALLOC);
    }
...
 
Note this is sort-of nothing new, in that DMA access really prefers things to be at least 32 byte aligned.
My understanding is that making things 32-byte aligned is usually due to the CPU cache since each line is 32 bytes long.
That really doesn't matter for a framebuffer, since the CPU is the only device that writes to it, it is safe to perform unaligned cache operations because you won't accidentally invalidate nearby data in the unaligned regions.

In this case the LCDIF explicitly requires 64-byte aligned buffers because it ignores/repurposes the lower bits of the addresses.
Ordinary malloc has aligned_alloc() to allocate aligned memory, extmem should have an equivalent...
 
In this case the LCDIF explicitly requires 64-byte aligned buffers because it ignores/repurposes the lower bits of the addresses.
Ordinary malloc has aligned_alloc() to allocate aligned memory, extmem should have an equivalent...
Thanks... I know that I have run into some strange issues in past when they were not 32 byte alligned. Not sure if the cache or not.
Or simply becuase we don't have a Safe version of the cache delete, except to do the flush delete to make sure all of it is written out.

Don't know if the malloc on Arduino/Teensy has the aligned alloc or not... I just sort of took Frank's lead on allocating frame buffers.

Now back to playing with Camera... Probably going to hook up my older Logic 16 to get all of the signals.
Side note. Makes me appreciate, working on boards with easy to access IO pins for debugging.
I try to add them to boards I make for myself... Also for boards like this it probably does not cost anything unless you populate them.

Example of other ones. Some of the MicroMod carrier boards by Sparkfun have them... Like the ATP:
1706140997371.png

There is another row of .1" pin holes, that they ship un-populated. (I soldered in male pins on mine...)
Trying to decide now if I am going to now move the connections to breadboard or, try to use test clips:
1706141206567.png

for each of these pins.

But back to playing...
 
Must have made a mistake somewhere yesterday... first thing I tried today was setting the SDRAM speed to 133MHz and running the elcdif sample at 1280x1024x60... and it works perfectly. No glitches/corruption visible on the frames, and no complaining from the ELCDIF about underflows (which isn't included in the sample code but can be monitored).
For some reason yesterday this resolution only worked when the SDRAM speed was bumped up to 200MHz. AFAIK I haven't changed anything else.

Update: I added 1680x1050x60 and 1920x1080x60 modes... both work, although there's occasional glitches if the SDRAM is clocked below 200MHz.
The LCDIF supposedly supports a max clock of 75MHz but 1920x1080 runs it at 148.5MHz... and since the framebuffer is 8bpp that is also the required read speed (148MB/s) which is why I said yesterday, I'm not even sure how LCDIF is managing to achieve this given the SDRAM read speeds that we have measured so far.
 
Last edited:
Can't find any reference to the maximum supported resolution in the documentation but I doubt the clock could go much higher.
 
It's not much to look at currently because I'm using 4 bit output (16 colors) through resistors to run a VGA monitor. I need to dig up an old ISA VGA card with a removable DAC that I can repurpose... or get USB working so I can have file storage/input devices and play Commander Keen (uses EGA colors).

There used to be a common chip on early DVI capable video cards called the SiI140 (that's "S-i-capital i-140") that converted typical video signals (HSYNC/VSYNC/clk/24-bits of color) to DVI / TMDS signals. I would guess they're no longer available / superseded by something else, but a board based around a chip like that would be perfect to slot on top of the current devboard to give DVI/HDMI output.
 
I'd say they were basing that on either the required pixel clock (70.5MHz for 1280x800 vs. 75MHz, the supposed max for eLCDIF) or the required memory bandwidth for 24bpp (184MB/sec) rather than it being a limitation of the signal generation hardware.
 
It's not much to look at currently because I'm using 4 bit output (16 colors) through resistors to run a VGA monitor. I need to dig up an old ISA VGA card with a removable DAC that I can repurpose... or get USB working so I can have file storage/input devices and play Commander Keen (uses EGA colors).

There used to be a common chip on early DVI capable video cards called the SiI140 (that's "S-i-capital i-140") that converted typical video signals (HSYNC/VSYNC/clk/24-bits of color) to DVI / TMDS signals. I would guess they're no longer available / superseded by something else, but a board based around a chip like that would be perfect to slot on top of the current devboard to give DVI/HDMI output.
The plan is to make a gen5, Rezo is compiling a complete list of pins, he knows that USB HOST, SDCARD and a bunch more stuff should be added. Once he gives me that complete list, I will make the gen5 board.

But it would still be nice to see a video of the performance. 1280x1024 is super cool for the Teensy!
 
Now back to playing with Camera... Probably going to hook up my older Logic 16 to get all of the signals.
Side note. Makes me appreciate, working on boards with easy to access IO pins for debugging.
I try to add them to boards I make for myself... Also for boards like this it probably does not cost anything unless you populate them.
Follow on from yesterdays post... Went with the clips...
1706211881675.png


Still debugging
1706212133375.png

The rare time when I need the old 16 channel...
 
@Dogbone06 In the schematics for the board way back at the start of the thread, there's a diode shown going from VUSB to +5V. If I supply external power to +5V the USB port won't be able to power anything connected to it... so I guess using a powered hub would be the only option?
 
If you remove that diode and bridge the pads, power can travel both ways. So after doing that, supply your own 5V voltage, and that power will travel out from the USB port. And thus becoming sort of a “host”.

It will not damage the board. That diode is just there from long time ago.
 
The results are quite dissapointing. I suspect that something isn't right. But I still ran through the entire test to keep this educational and strict in terms of research. Defragster is sleeping now and he will take a look at this when he wakes up again.

For anyone that doesn't know this sketch: 13 and 57 test result are just names that mjs513/defragster wrote. Basically there are two tests inside the sketch, I don't know the exact details but the serial monitor spits out those results. And so I simply logged it with the spreadsheet.

The test sketch used is this one: https://github.com/mjs513/SDRAM_t4/blob/main/examples/CapReadSDRAM/CapReadSDRAM.ino
With the below settings used which are set in the top of the sketch. "noCap" is a little confusing in terms of logic. I have only performed these tests with a capacitor present, the values are listed in the results. noCap = false, means that we have a capacitor present. I think a better logic would be capPresent = true.
1706358849326.png


The test was performed with code provided by Defragster (linking to mjs5123 Git).
I then tested the various capacitors that @PaulStoffregen told me to buy.
Teensy processor speed: 600MHz
SDRAM speed: 221MHz

Below are the results:
Cap Value13 test result in secondsErrors found57 test result in secondsErrors found
1.0 pF10,08084,442214592512
1.5 pF10,08084,442214592512
2.2 pF10,08084,442214592512
2.7 pF10,08084,442214592512
3.3 pF10,08084,442214592512
3.9 pF10,08084,442214592512
4.3 pF10,08084,442214592512
4.7 pF10,08084,442214592512
5.6 pF10,08084,442214592512
6.8 pF10,08084,442214592512
7.5 pF10,08084,442214592512
8.2 pF10,08084,442214592512
9.1 pF10,08084,442214592512
10 pF10,08084,442214592512
11 pF10,08084,442214592512
12 pF10,08084,442214592512
13 pF10,08084,442214592512
15 pF10,08084,442214592512
18 pF10,08084,442214592512
22 pF10,08084,442214592512
CAPS USED IN TEST
1.0 pF 81-GRM1555C1H1R0WA1D
1.5 pF 81-GRM1555C1H1R5WA1D
2.2 pF 81-GJM1555C1H2R2GB1D
2.7 pF 81-GJM1555C1H2R7GB1D
3.3 pF 81-GJM1555C1H3R3WB1D
3.9 pF 81-GJM1555C1H3R9GB1D
4.3 pF 81-GJM1555C1H4R3GB1D
4.7 pF 81-GJM1555C1H4R7GB1D
5.6 pF 81-GJM1555C1H5R6FB1D
6.8 pF 81-GJM1555C1H6R8FB1D
7.5 pF 81-GJM1555C1H7R5WB1D
8.2 pF 81-GJM1555C1H8R2FB1D
9.1 pF 81-GJM1555C1H9R1FB1D
10 pF 81-GRM1555C1H100FA1D
11 pF 81-GCM1555C1H110FA6D
12 pF 81-GRM1555C1H120GA1D
13 pF 81-GRT1555C1H130FA2D
15 pF 81-GRM1555C1H150GA1D
18 pF 81-GRM1555C1H180GA1D
22 pF 81-GRM1555C1E220GA1D
 
Or maybe "UseDQS" might be clearer, as it really is configuring whether the DQS pin is used (regardless of whether it actually has a capacitor connected or is merely pin's self capacitance) versus not using the DQS pin at all.
Yeh something like that. I have restarted the test from high value caps (22pF) and going down. They work, and so I click 1 and send via serMon to perform the long test that takes 45 minutes per cap. So this will take a while. I'll upload the spreadsheet once this is done in a day or two.
 
Indeed the "no cap" name is quite confusing!
I think that noCap set to true, means that the cap is there. Atleast from the tests I'm doing. It works at 221MHz. So I will continue as such.

Cap Value13 test result in secondsErrors found57 test result in secondsErrors found57 test with 100 reReads in secondsErrors found
18 pF10,08084,4402439.020
 
I think that noCap set to true, means that the cap is there.

The reason it's so confusing is no SMT capacitor connected is still the pin's capacitance (~5pF). Even if you don't solder a capacitor, configuring it to use capacitance will just use the pin's own capacitance if you didn't add a SMT capacitor.

Well, also naming something as a negative leads to expressing double negatives, which add even more confusion.

The public API should really express this option as whether the DQS (EMC_39) pin is used.
 
Fully agree, "UseDQS" is a very good name for the boolean. Makes it super clear.

So you see my table above, I write down the error count and the time it takes to run the test. I guess what we want to find is the test that takes the least amount of time. When that is found we know that we've found the best capacitor to work with 221MHz. Is this correct?
 
Back
Top