-
Fonts ok, adding alpha transparency
10/18/2015 at 18:49 • 0 commentsConverting and adding (mono) true type fonts is done. Text is displayed in 16 grey-scale values. Displaying text on black background is beautiful but displaying the same text on another background colour or over an image is ugly. I decided to work on alpha transparency.
Alpha transparency
If one wants to display text with a specified colour on an image or other background, the system must do a calculation between the pixel text weight colour (16 values) and the background pixel colour (240 colour values, BTW I've fixed the palette colour content to 685-RGB values + 16 grey-scale). This calculation has to take into account a user transparency selection (also 16 values). I've implemented LUT to do this but this is not finished yet.
Other benefit of this alpha transparency is for the blob copy operation that will have a transparency factor. The purpose is to mix the pixels colour values of the blob to copy with the pixels colour values of the screen that receive the blob. That will normally gives a nice effect.
Work on progress ...
-
Still alive
09/21/2015 at 16:24 • 0 commentsJust this log to inform that I'm working on fonts and fonts conversion.
:-)
-
HOMER WP5: FPGA conf via USB
08/15/2015 at 20:50 • 0 commentsI've managed to do a better video thanks to a tripod.
Progress:
- Now, it's possible to upload the FPGA configuration file via USB (VCOM port). It remains to store this file into the FLASH next to the LPC812, then the board will be ready at power on.
- I've made a little python application to do some tests with the board but also -and mainly- to upload image files to the embedded flash.
Here is the source C code for the animation. This code can easily be embedded in a small 8bit uC.
//Init LisaGlyph for (uint32_t i=0; i<LISA_GLYPHS; i++) GlyphLisa[i] = LISA_FL_START_ADDRESS + i * LISA_FL_STEP_ADDRESS; //Init Lisa for (uint32_t i=0; i<N_LISA; i++) { Lisa[i].size = (SIZE_t){ LISA_SIZE_W, LISA_SIZE_H}; Lisa[i].pos.X = rand() % 1000; Lisa[i].pos.Y = rand() % 500; Lisa[i].inc.X = rand() % 10 + 0.5; Lisa[i].inc.Y = i / 10.0 + 0.5; Lisa[i].idxGlyph = 0; } //Init HomerGlyph for (uint32_t i=0; i<HOMER_GLYPHS; i++) GlyphHomer[i] = HOMER_FL_START_ADDRESS + i * HOMER_FL_STEP_ADDRESS; //Init Homer for (uint32_t i=0; i<N_HOMER; i++) { Homer[i].size = (SIZE_t){ HOMER_SIZE_W, HOMER_SIZE_H}; Homer[i].pos.X = rand() % 1000; Homer[i].pos.Y = rand() % 500;; Homer[i].inc.X = rand() % 10; Homer[i].inc.Y = i / 2.0; Homer[i].idxGlyph = 0; } //Init BallGlyph for (uint32_t i=0; i<BALL_GLYPHS; i++) GlyphBall[i] = BALL_FL_START_ADDRESS + i * BALL_FL_STEP_ADDRESS; Ball.size = (SIZE_t){ BALL_SIZE_W, BALL_SIZE_H}; Ball.pos.X = 500; Ball.pos.Y = 100; Ball.vit.X = 7.0; Ball.acc.X = 0; Ball.vit.Y = 0; Ball.acc.Y = 1.5; Ball.idxGlyph = 0; GlyphMur = MUR_FL_START_ADDRESS; Mur.size = (SIZE_t){ MUR_SIZE_W, MUR_SIZE_H}; Mur.pos.X = 500; Mur.pos.Y = 719-512; //Init display GPUstorePalette(0); GPUclipArea((COORD_t){0, 0}, (COORD_t){1279, 719}); while (1) { GPUclearScreen(45); for (uint32_t i=0; i<N_HOMER/2; i++) GPUcopyBlob( GlyphHomer[ Homer[i].idxGlyph ], (COORD_t){ (int16_t)Homer[i].pos.X, (int16_t)Homer[i].pos.Y }, Homer[i].size, 0 ); for (uint32_t i=0; i<N_LISA/2; i++) GPUcopyBlob( GlyphLisa[ Lisa[i].idxGlyph ], (COORD_t){ (int16_t)Lisa[i].pos.X, (int16_t)Lisa[i].pos.Y }, Lisa[i].size, 0 ); GPUcopyBlob( GlyphMur, (COORD_t){ (int16_t)Mur.pos.X, (int16_t)Mur.pos.Y }, Mur.size, 0 ); for (uint32_t i=N_LISA/2; i<N_LISA; i++) GPUcopyBlob( GlyphLisa[ Lisa[i].idxGlyph ], (COORD_t){ (int16_t)Lisa[i].pos.X, (int16_t)Lisa[i].pos.Y }, Lisa[i].size, 0 ); for (uint32_t i=N_HOMER/2; i<N_HOMER; i++) GPUcopyBlob( GlyphHomer[ Homer[i].idxGlyph ], (COORD_t){ (int16_t)Homer[i].pos.X, (int16_t)Homer[i].pos.Y }, Homer[i].size, 0 ); GPUcopyBlob( GlyphBall[ Ball.idxGlyph ], (COORD_t){ (int16_t)Ball.pos.X, (int16_t)Ball.pos.Y }, Ball.size, 0 ); GPUdrawLine((COORD_t){0, 0}, (COORD_t){ 1279, 0}, 15, 0); GPUdrawLine((COORD_t){0, 0}, (COORD_t){ 0, 719}, 15, 0); GPUdrawLine((COORD_t){1279, 0}, (COORD_t){ 1279, 719}, 15, 0); GPUdrawLine((COORD_t){0, 719}, (COORD_t){ 1279, 719}, 15, 0); for (uint32_t i=0; i<N_LISA; i++) { Lisa[i].pos.X += Lisa[i].inc.X; Lisa[i].pos.Y += Lisa[i].inc.Y; if (Lisa[i].pos.X > SCR_W - Lisa[i].size.W || Lisa[i].pos.X < 0 ) { Lisa[i].inc.X = - Lisa[i].inc.X; Lisa[i].pos.X += Lisa[i].inc.X; } if (Lisa[i].pos.Y > SCR_H - Lisa[i].size.H || Lisa[i].pos.Y < 0 ) { Lisa[i].inc.Y = - Lisa[i].inc.Y; Lisa[i].pos.Y += Lisa[i].inc.Y; } Lisa[i].idxGlyph = ((uint16_t)(Lisa[i].pos.X/5)) % LISA_GLYPHS; } for (uint32_t i=0; i<N_HOMER; i++) { Homer[i].pos.X += Homer[i].inc.X; Homer[i].pos.Y += Homer[i].inc.Y; if (Homer[i].pos.X > SCR_W - Homer[i].size.W || Homer[i].pos.X < 0 ) { Homer[i].inc.X = - Homer[i].inc.X; Homer[i].pos.X += Homer[i].inc.X; } if (Homer[i].pos.Y > SCR_H - Homer[i].size.H || Homer[i].pos.Y < 0 ) { Homer[i].inc.Y = - Homer[i].inc.Y; Homer[i].pos.Y += Homer[i].inc.Y; } Homer[i].idxGlyph = ((uint16_t)(Homer[i].pos.X/20)) % HOMER_GLYPHS; } Ball.vit.X += Ball.acc.X; Ball.vit.Y += Ball.acc.Y; Ball.pos.X += Ball.vit.X; Ball.pos.Y += Ball.vit.Y; if (Ball.pos.X > SCR_W - Ball.size.W || Ball.pos.X < 0 ) { Ball.vit.X = - Ball.vit.X; Ball.pos.X += Ball.vit.X; } if (Ball.pos.Y > SCR_H - Ball.size.H || Ball.pos.Y < 0 ) { Ball.vit.Y = - Ball.vit.Y; Ball.pos.Y += Ball.vit.Y; } Ball.idxGlyph = ((uint16_t)(Ball.pos.X/5)) % BALL_GLYPHS; //Display it! GPUswapBuffer(); }
Here is for example the C definition of a GPU function, Tx_Buff is a buffer whose the byte elements are sent to the SPI. Address is the blob address in the 8MBytes Flash connected to the FPGA.
Here I use DMA but simple transfert work also.
void GPUcopyBlob(uint32_t Address, COORD_t P1, SIZE_t Size, uint8_t operation) { Tx_Buf[0] = CMD_COPY_BLOB; Tx_Buf[1] = 12; //DATA LENGTH Tx_Buf[2] = Address >> 16; // FlashAddress MSB Tx_Buf[3] = Address >> 8; // FlashAddress mSB Tx_Buf[4] = Address; // FlashAddress LSB Tx_Buf[5] = P1.X >> 8; Tx_Buf[6] = P1.X; Tx_Buf[7] = P1.Y >> 8; Tx_Buf[8] = P1.Y; Tx_Buf[9] = Size.W >> 8; Tx_Buf[10] = Size.W; Tx_Buf[11] = Size.H >> 8; Tx_Buf[12] = Size.H; Tx_Buf[13] = operation; // Start transmission SSP_DMA_Start(14, Tx_Buf, Rx_Buf); }
I've made a SPI speed test, it's possible to go up to 32Mbits/s. That's well within the need. SPI is not the bottleneck here since the receive only commands, not big blobs of data.
-
HOMER WP4: Sprites
08/05/2015 at 22:37 • 3 commentsAt least I managed to discuss with the QSPI flash. Then here are some blobs (sprites) of Lisa :-)
in front of 200 lines moving and two clip area.
The image on screen is better than this bloody video, I can't figure out how to upload a good quality one.
-
HOMER WP3 bis
07/21/2015 at 22:47 • 0 commentsA small video, clip area, drawline, fillarea.
-
HOMER WP3, colors
07/13/2015 at 21:21 • 0 commentsSmall demo with colors (palette a bit ugly). Drawline (Bresenham algorithm) implemented but not perfect yet. Clipping area for Drawline.
-
First animation
07/08/2015 at 22:46 • 0 commentsThis is a first video result. I spent a lot of time debugging a mistake in the VHDL code. The video shows 50 blobs moving in HD resolution double buffering. I haven't yet implemented the palettes then it's grayscale. At every frame I do a clear screen. When the loading from flash will be available, instead of doing a clear screen, it will be possible to load a background.
I'm very happy with this first result :-) -
First HD output
06/28/2015 at 17:07 • 2 commentsThis is a first HD output. I've manage to configure the TDA19988 chip (a little bit by chance ;-) ).
You can see the beautiful random values of a block SRAM in greyscale.
-
HOMER is alive :-)
06/23/2015 at 22:14 • 0 commentsSee video.
FPGA + SRAM + MAX V OK
HDMI Chip ok in test mode, communication ok but no video for the moment.
Problem with NXP that didn't release the datasheet explaining how to configure the chip registers. Then I've to dig into open source code driver (Linux, Mimix, LPC4350). If I was aware of that before I'd never choose this chip.
Nevertheless things are progressing, I'm very hammy that the hardware is running.
Aside HDMI, It remains to test the overall timing for the HD video generation and of course to adapt the VHDL code to this hardware configuration.
-
Homer is born
06/09/2015 at 20:39 • 0 commentsDead or alive ? I've to check soon