STM32F103C8 BluePill VGA Project

What are you developing?
feluga
Posts: 34
Joined: Wed Mar 18, 2020 2:50 am

Re: STM32F103C8 BluePill VGA Project

Post by feluga »

Hello!

Some News:
- I have released version 1.1 with support for Arduino Print Class on BlueVGA.
- It's possible to print to the screen in the same way as Serial.print() and Serial.println()
- Thus the VGA Monitor can work as an output monitor for Arduino Sketches!
- It scrolls the screen automatically when printing on the last line or when wrapping text in the last line as well.
- It understands '\n' (new line) '\r' (carriage return) and '\t' (tab) - number of columns used for TAB can be configured by code
- Print Class and all variations of print() and println() work on both official STM32 Core and Roger's Core as well.


Example of usage:

Code: Select all

#include "bluevga.h"
#include "font.h"

BlueVGA vga(ASCII_FONT);   // starts VGA driver using bitmap array ASCII_FONT

// There is also a 'printTest.ino' file that can be found in the library examples 
void setup() {
  vga.setTextCursor(0, 1);                 // position cursor at x = 0 and y = 1 (second line) in the screen
  vga.print("Hello World\t\t");            // it supports all Arduino ways for println() and understands '\t' as tab, default 4 columns
  vga.print("tab space\n");                // it also understands '\n' as new line and '\r' as carriage return in the same line
  vga.setTextWrap(false);                  // it allows to wrap  or not text when printing beyond right margin of the screen
  vga.setTextTab(3);                       // it allows to set number of columns for TAB ('\t')
  vga.setTextColor(RGB_GREEN, RGB_BLACK);  // it allows to define foreground (green) and background (black) colors for further printing
  vga.print(3.1415, 3);                    // it works as Arduino does, printing floats witn any number of decimal digits 
  uint8_t color = vga.getTextColor();      // gets current printing colors in format 8 bits rgb0rgb0 BGColor 4 bits followed by FGColor 4 bits
  uint8_t x = vga.getTextCursorX();        // gets current X cursor position
  uint8_t y = vga.getTextCursorY();        // gets current Y cursor position
  vga.scrollText(3);                       // it scrolls the screen up 3 lines. No change on current cursor position. Just scrolls text and its colors!
  for(uint32_t i=0;;i++) {                 // prints numbers for ever and scrolls the screen when reaching last line
    vga.print("value of i is ");
    vga.println(i);
    vga.waitVSync();                       // waits to end of VGA frame drawing routine to end -- makes the image to stay solid
  }
}
I hope it is useful for you all!

ag123
Posts: 467
Joined: Thu Dec 19, 2019 5:30 am
Answers: 1

Re: STM32F103C8 BluePill VGA Project

Post by ag123 »

+1 :)

feluga
Posts: 34
Joined: Wed Mar 18, 2020 2:50 am

Re: STM32F103C8 BluePill VGA Project

Post by feluga »

More news on the development of BlueVGA Arduino Library!

Working on adding pixel drawing functions to the library, always with a low footprint.
The examples below use just about 4.5K RAM and about 22K Flash using STM32 Official Core.

Example of a sketch that animates drawing a sine curve. It may inspire someone to create a data analyser or even a low frequency oscilloscope in the future... :D
Sine.gif
Sine.gif (10.69 KiB) Viewed 409 times
I also experimented with an old known game! This is a nice way to test and "to stress" the CPU of the Bluepill with pixels ;)
SpaceInvaders.gif
SpaceInvaders.gif (8.96 KiB) Viewed 409 times

User avatar
fpiSTM
Posts: 677
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 25
Location: Le Mans
Contact:

Re: STM32F103C8 BluePill VGA Project

Post by fpiSTM »

+1 :!:

ag123
Posts: 467
Joined: Thu Dec 19, 2019 5:30 am
Answers: 1

Re: STM32F103C8 BluePill VGA Project

Post by ag123 »

+1 :!:

User avatar
Bakisha
Posts: 56
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 3
Contact:

Re: STM32F103C8 BluePill VGA Project

Post by Bakisha »

+1
I'm just curious, did you implement full 224x240 bitmap mode? Or it still use rest of 256 tiles that are not used by font letters, to be placed in 28x30 array?

feluga
Posts: 34
Joined: Wed Mar 18, 2020 2:50 am

Re: STM32F103C8 BluePill VGA Project

Post by feluga »

Good question! I'm glad you asked it!
The way I implemented is sort of a mix of what you just wrote. :D
Bakisha wrote:
Thu Sep 03, 2020 10:51 am
I'm just curious, did you implement full 224x240 bitmap mode?
No, I draw pixel by pixel for the Sine curve in a 250ms interval in order to make a nice plotting animation.
A 224x240 bitmap mode in flash is almost impossible for such animation.
A RAM bitmap pixel matrix for that would use at least about 8K RAM just for the pixels, but I had a target to make it work in the lowest memory footprint possible.
Bakisha wrote:
Thu Sep 03, 2020 10:51 am
Or it still use rest of 256 tiles that are not used by font letters, to be placed in 28x30 array?
Yes, but I use a RAM bitmap for the tiles, thus I can do several alternatives.
1) To copy a flash tile letters bitmap to RAM and use, as you said, the remaining free tiles to set pixel wherever I need.
2) To use all 256 RAM tiles and just allocate them in the 28x30 array wherever I need and set the pixels I need.
3) To split the 256 RAM tiles in 2 groups: Fixed bitmap RAM tiles and Dynamic bitmap RAM Tiles.

You can imagine the 28x30 tiles as a sparse matrix, where most of those are tile Zero which has a blank character of 8x8, such as " ".
In the case of the Sine Curve drawing animation, I just use alternative 2, and draw the letters on top allocating a RAM tile for each.
For each pixel I need to set in the screen, I first check if it's Zero or already allocated from the 255 RAM tile pool.
I set the tile if necessary and then I set the pixel in this tile. Otherwise, I just set the pixel on a non-Zero tile that is already in the 28x30 screen.

For the Space Invader, I had to use alternative 3 because it uses many tiles in a dynamic frame to frame screen drawing.
Thus in my first trial I run out of tiles...
In this game I use about 75 fixed RAM tiles and the other 180 are dynamically allocated in the screen as the game bitmaps are drawn.
All of it is done frame by frame in 60Hz, thus I redraw the screen 60 times per second in VBLANK time space.
The challenge here is to do it fast enough to fit in VBLANK which is about 2 ms per frame!

Other better performance solutions can be created, of course.
By using this Sparse Matrix approach I save a lot more RAM than what would be needed to create a giant 224x240 bitmap!

Everything for the fun and joy of the challenge!

In case anyone wants to test it, below you will find the bin files for both examples
arduino_build_for_both_exemples.zip
(22.89 KiB) Downloaded 21 times
In the Space Invaders example, it runs with no user interation, like playing by itself, and also displays the Score as the number of allocated tiles for each frame and it displays the Hi-Score as the maximum number of tiles allocated along its execution. This helped me to watch how the code was running.

Connections to VGA plug are detailed at https://github.com/rocorbera/BlueVga/

User avatar
Bakisha
Posts: 56
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 3
Contact:

Re: STM32F103C8 BluePill VGA Project

Post by Bakisha »

feluga wrote:
Thu Sep 03, 2020 2:59 pm

1) To copy a flash tile letters bitmap to RAM and use, as you said, the remaining free tiles to set pixel wherever I need.
2) To use all 256 RAM tiles and just allocate them in the 28x30 array wherever I need and set the pixels I need.
3) To split the 256 RAM tiles in 2 groups: Fixed bitmap RAM tiles and Dynamic bitmap RAM Tiles.
Thanks for explanation. That was the thing i was curious about.

I have idea for full bitmap mode, i don't know is it possible to implement (you are using assembler, and only thing i can think of is timer triggering DMA transfer from memory to GPIO's BSSR register).

- 224x240 pixels is 28*240=6720 bytes of video RAM. Every bit is addressable pixel, 0 representing background color, 1 is foreground color, but 8x8 pixels (1 tile ) have common foreground/background color.
- 28x30 = 840 bytes for foreground/background color (for each 8x8 pixel group).
- 8*256 = 2048 bytes for tiles (or 8x8 font). In RAM, can be copied from internal flash on startup. Or be in flash and don't use RAM.

So, in total, 9608 bytes of RAM used, plus around 4KB for core usage, should leave 6KB of free RAM.
Basicly, 840 tiles that have fixed position.

I'll test files that you attach as soon as i can. Thanks again.

feluga
Posts: 34
Joined: Wed Mar 18, 2020 2:50 am

Re: STM32F103C8 BluePill VGA Project

Post by feluga »

Bakisha wrote:
Thu Sep 03, 2020 4:25 pm
I have idea for full bitmap mode, i don't know is it possible to implement (you are using assembler, and only thing i can think of is timer triggering DMA transfer from memory to GPIO's BSSR register).
One point is that BSSR is 32 bits register. Thus, it'll need something running to map bits into the BSSR before triggering DMA, for every scanline.
Or to make a big BSSR register bitmap for pixels, but that means a lot of RAM, because for sending 1 pixel it would need 32 bits... plus other issues.... not possible, I think.

I use Port C ODR register, but bluepill only exposes PC13 to PC15 (3 bits = 8 colors). ASM routine translates bit 0 or 1 (pixels) into 3 bits colors and bitbangs a single byte to ODR + 1 (bits 15 to 8 of PC ODR). DMA can't do that translation. Bg/fg colors are 4 bits each in the 28x30 bytes color matrix.
Bakisha wrote:
Thu Sep 03, 2020 4:25 pm
- 224x240 pixels is 28*240=6720 bytes of video RAM. Every bit is addressable pixel, 0 representing background color, 1 is foreground color, but 8x8 pixels (1 tile ) have common foreground/background color.
- 28x30 = 840 bytes for foreground/background color (for each 8x8 pixel group).
- 8*256 = 2048 bytes for tiles (or 8x8 font). In RAM, can be copied from internal flash on startup. Or be in flash and don't use RAM.

So, in total, 9608 bytes of RAM used, plus around 4KB for core usage, should leave 6KB of free RAM.
Basicly, 840 tiles that have fixed position.
Yes, that's 100% possible.
All needed for that is to set inital pointer to that 6720 bytes buffer and to increment that pointer every scanline with 28 bytes.
Using this same pointer as the origin for the pixels it shall use to bitbang VGA in ASM routine.
It can use a slightly modified ASM routine to send pixels to VGA.

Certainly the easiest way to make it run!

User avatar
Bakisha
Posts: 56
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 3
Contact:

Re: STM32F103C8 BluePill VGA Project

Post by Bakisha »

feluga wrote:
Thu Sep 03, 2020 5:04 pm

One point is that BSSR is 32 bits register. Thus, it'll need something running to map bits into the BSSR before triggering DMA, for every scanline.
Or to make a big BSSR register bitmap for pixels, but that means a lot of RAM, because for sending 1 pixel it would need 32 bits... plus other issues.... not possible, I think.
I was thinking BSRR was good choice because it would be possible to use other ports. Yes, it's 32bit register, what i had in mind to use two buffers of 4*pixels bytes per line, and in interrupt use something like:
-Set DMA to send 1st/2nd buffer (with few flags as "if" statement, and always same execution time +/- few cycles)
-Calculate 2nd/1st buffer as stream of 4bytes (32bits) for BSRR (this is not time critical, since DMA is already sending 1st/2nd buffer in background)
-exit interrupt

Only thing to find out is how much cycles is DMA transfer delayed when triggered every 8 cpu ticks (for 224 pixels resolution).

Time for me to dive into RM0008 Reference manual again and find a way to drive DMA with timer :geek:

Post Reply

Return to “Projects”