[WIP] VGA-out (without FPGA)

(serisman) #21

I don’t think they are disabled by hardware automatically because the STM32F103 supports interrupt cascading (i.e. an interrupt can occur during the processing of a previous interrupt). But, I might not really need to disable interrupts for this anyway.

Interesting… I hadn’t thought of that approach, but that might just do it!

It would slightly slow down the transition from data -> command (slightly), so it’s possible it would now get ‘extra’ data (that are really commands)

Maybe. I tried with a naked ISR and it didn’t work at all, probably because it was overwriting a register inappropriately. I haven’t yet dug into converting this to a pure inline assembly ISR.

I was originally polling the pins continuously but that had even worse latency. I am already driving VGA with interrupts, but I can’t poll SPI from within the vga interrupts as they have very strict timing requirements.

I ‘think’ I get what you are saying now. Basically pre-decide whether the next transition would be an enable or disable and change the ISR vector on the fly accordingly? I think this would require running the vector table from memory which I think IS possible with these MCUs but needs to be researched a bit more.


Yes, exactly

If you do go for hardware fix you can simplify it to a single NPN transistor with two resistors:

(serisman) #23

Love it!

Looks like that should work quite well, and is even simpler than what I had in mind.

I might even be able to ditch the resistors and get it down to a single n-channel mosfet (2n7002) by switching on the built in pull-up resistor for the input pin. It’s a little evil to not have a resistor on the mosfet gate, but would probably work just fine in this case.


You’ll be fine in this case. Now the previous engineer at my work not putting any series or gate-source resistors on a 500W push-pull converter’s fets and relying on the gate driver chip’s output impedance for source and sink current, that’s insane …

(serisman) #25

Getting closer, but still not quite there…

Retaining software control of the SPI enable with this in the ISR we are now only off by one bit:

SPI2->CR1 = 0x8641; // Enable SPI
if ((GPIOB->IDR & 0x1200) != 0x0200) { // CS=0, DC=1
  SPI2->CR1 = 0x8701; // Disable SPI

Switching to hardware control of the SPI enable (single n-channel mosfet and pull-up resistors) gives this (an extra byte per page):

I do like having the mosfet to combine the DC/CS signals, but will probably need to find a solution that retains software control.

(serisman) #26

Problem solved!

Apparently the STM32F103’s internal pull-up resistors are too weak (30-50 k) and cause too slow of a transition from low -> high. I turned off the internal pull-ups and instead installed an external 10k resistor (and switched back to hardware SPI enable) which seems to have solved the problem!

So, my last known ‘issue’ is to try and get rid of some ‘jitter’ that is occurring on the video output. I currently start the SPI DMA process inside a timer interrupt, but it is possible that sometimes that interrupt is a bit delayed if the processor is doing other things. I think I can instead have the timer directly start the DMA without going through an interrupt which should provide rock solid output. Will check more into this later.

But for now this is extremely satisfying to see running as well as it does! :smiley:

(Simon) #27

Looks really good … nice work!


In the attempt of getting rid of that mosfet. How about connecting CS to SS input so you can test for DC bit only in the ISR if line:

if ((GPIOB->IDR & 0x0200) != 0x0200)

If the compiler is smart it will leave out the cmp.w instruction (and.w instruction sets zero flag) other wise you can use inline assembly.

That last screenshot looks mesmerizing :slight_smile:

Thinking more clearly now, that wouldn’t speed up the enabling of SPI, only SPI disabling.
I also looked a bit into arm assembly. The push only stacks r3 and lr (linkRegister) and not range r0-r3 as a thought previously. meaning there must be some main IRQ handler calling this handler.

Your current IRQ handler can be optimized using inline assembly:
When r3 is not used (use r0,r2 instead) and EXTI_ClearITPendingBit code is inlined, r3 and lr don’t need to be stacked and the push (r3,lr} can be removed. The pop {r3, pc} which returns from the IRQ must be changed into MOV PC, LR


Looks amazing, keep up the awesome work!