Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 11:01 01 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : VGA on the VGAMite: how it works

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10310
Posted: 10:34am 29 Nov 2021
Copy link to clipboard 
Print this post

Not invented by me I'm afraid but really clever

Timer 1 is set to run at the system speed (100.7MHz). This then generates the horizontal synch pulse using PWM. The clever bit is that timer 1 is also set to do an output compare at the end of the horizontal blanking period. This compare generates an interrupt. Finally timer 1 rollover is used as the clock source for timer 2.

Timer 2 is now running at the horizontal synch rate. This then generates a vertical synch pulse using PWM. Timer 2 also uses output compare to generate an interrupt at the end of the vertical blanking period.

The interrupt at the end of the vertical blanking period just sets the line counter to 0.

The interrupt at the end of the horizontal blanking period just triggers a DMA transfer from the memory holding the next line to SPI3. SPI3 is set to run at one quarter of the system speed (25.175MHz)

DMA completion triggers an interrupt. This interrupt updates the DMA memory location to point to the next line of data ready for the DMA to be triggered by the timer 1 interrupt

So simple, but so clever because the code in the interrupt routines is trivial and therefore the CPU load is minimal and because timer 2 is driven by timer 1 rollover the synch pulses are perfectly timed and locked together.

Not doable on things like the Picomite as it doesn't have the sophisticated timers needed so generating VGA becomes very processor intensive and/or uses multiple PIO processes


void TIM1_CC_IRQHandler(void)
{
   if(valid) DMA1_Stream5->CR |= DMA_SxCR_EN;   // start the DMA
   TIM1->SR &= ~TIM_IT_CC2;                     // clear the timer interrupt bit
}

void TIM2_IRQHandler(void)
   valid=1; // enable output after the first vertical blanking period after reboot
   vline=0; // reset the line counter
   TIM2->SR &= ~TIM_IT_CC2; // clear the timer interrupt bit
}
void DMA1_Stream5_IRQHandler(void)
{
   DMA1->HIFCR DMA_HIFCR_CHTIF5|DMA_HIFCR_CFEIF5|DMA_HIFCR_CTEIF5|DMA_HIFCR_CDMEIF5; //clear any DMA interrupt flags except end of transfer
   if(DMA1->HISR & DMA_HISR_TCIF5) {// If the interrupt is end of transfer
       DMA1->HIFCR = DMA_HIFCR_CTCIF5; //clear the end of transfer interrupt flag
       DMA1_Stream5->CR &= ~DMA_SxCR_EN; // disable the stream
       DMA1_Stream5->M0AR=(uint32_t)&fb[vline][0]; //point DMA to the next line
       vline++; //increment the line counter
       if(vline>=480) vline=480; //if in frame blanking just replay a blank line
   }
}


Edited 2021-11-29 20:53 by matherp
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2442
Posted: 11:43am 29 Nov 2021
Copy link to clipboard 
Print this post

out of curiosity, would it be possible to generate video using a set of character bitmaps and just an 80x24 array of bytes holding character codes for each character position? this would use minimal quantities of RAM (80x24 = 1920 bytes), even if the character bitmaps were also held in RAM (24 lines -> 20*256 = 5120 bytes).

one approach could be to build each scan line on-the-fly, although doing it this way would be quite CPU intensive, and play havoc with the workings of everything else in mmbasic!


not saying this should be done, just curious if it is technically possible.


cheers,
rob   :-)
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10310
Posted: 11:54am 29 Nov 2021
Copy link to clipboard 
Print this post

  Quote  out of curiosity, would it be possible to generate video using a set of character bitmaps and just an 80x24 array of bytes holding character codes for each character position?


Doubt it, you would only have 6.3uS to build each line during line blanking
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7937
Posted: 12:29pm 29 Nov 2021
Copy link to clipboard 
Print this post

If I understand you correctly, that's basically how the old method of character generation worked. Video ram stored character codes, not pixels. A character generator ROM stored the pixel patterns for the characters. Each scan looked at successive lines of the characters (read from the ROM), so top row of a 40x16 screen would have 320 pixels. The next 7 scans would complete the first row of characters. First the top line of each character then the second line then the third etc. Then you start on the next row of characters.

It works well, but you can only use block graphics. Machines like the Nascom, TRS-80 etc. use this method.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5089
Posted: 12:40pm 29 Nov 2021
Copy link to clipboard 
Print this post

What Peter explains is method to map memory (RAM) on a VGA screen. Almost without involvement of the CPU.

If you would like to map characters to VGA (in stead of bitmapped RAM) you need the character (ROM) in between. That is what a "video chip" does. It maps a character ROM in between RAM and VGA output.

Since we don't have a dedicated video chip inside the STM, you would have to do this using the ARM. Basicaly real-time translating to characters.

Although this might be possible, you would end up in a system where the ARM is more or less generating the video signal on it's own, busy during the whole active part of the video (everything outside the HSYNC and VSYNC).

Something like a ZX81 in slow mode.

No good idea....

Volhout
PicomiteVGA PETSCII ROBOTS
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7937
Posted: 12:55pm 29 Nov 2021
Copy link to clipboard 
Print this post

True. :)
It's a very early way to get characters onto a screen. I think I first saw it in The Cheap Video Cookbook (the circuit is almost directly copied for the Nascom-1 video). It had the advantage at that time that it used only TTL logic & counters to copy the video RAM onto the screen. It was switching the character generator RAM access between CPU and row counter access that caused the famous screen flash on some early machines.

This early technique still works nicely on a FPGA.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025