Some have expressed the interest for simple modes for the Bitbox. An recent commit is providing such mode , on top of the standard kernel.
The so-called simple modes are called like this because they provide a frame buffer interface, so the application programmer will only have to write bits and bytes to the video memory - much like it's done on PC. So the interface is a vram buch of memory and a color palette (because the tradeoff is a reduced palette or resolution)
There are two examples in the bitbox SDK (one of them below), but generally you'll need to define a simple makefile variable VGA_SIMPLE_MODE=X with the given mode and include the bitbox.mk standard makefile.
(Yes it's currently defined at compile time - if your program needs to switch between two modes at runtime, it might be time to switch to a standard kernel / engine - it's not difficult !)
Showing posts with label kernel. Show all posts
Showing posts with label kernel. Show all posts
Tuesday, November 11, 2014
Monday, October 6, 2014
New kernel modes (including 800x600@56Hz !)
Since a recent commit, developers now have a better way to set modes.
The kconf.h kernel configuration file allows now several modes, selectable through your project Makefile config options.
Current defined timings include :
- 640x480, 60Hz @ 168MHz clock (default one), 7 clocks per pixel
- 320x480, 60Hz @ 168MHz clock (repeat each line twice to use as 320x240 display)
- 640x480, 60Hz, overclocked at 192 MHZ, 7 clocks per pixel (longer vsync time)
- 800x600, 56Hz ! overclocked a bit at 180MHz. Yes the bitbox can do 800x600, 56fps.
You only have 5 clocks per pixels here however, so you'd better optimize that blit loop.
other modes can be created by adding config lines to the kconf.h file, all timing computation is based on number of pixels for Porch begin/end/sync and display sizes in pixels ; however be sure to get the right clock ratios to run USB/SDIO clocks at 48MHz !
The kconf.h kernel configuration file allows now several modes, selectable through your project Makefile config options.
Current defined timings include :
- 640x480, 60Hz @ 168MHz clock (default one), 7 clocks per pixel
- 320x480, 60Hz @ 168MHz clock (repeat each line twice to use as 320x240 display)
- 640x480, 60Hz, overclocked at 192 MHZ, 7 clocks per pixel (longer vsync time)
- 800x600, 56Hz ! overclocked a bit at 180MHz. Yes the bitbox can do 800x600, 56fps.
You only have 5 clocks per pixels here however, so you'd better optimize that blit loop.
other modes can be created by adding config lines to the kconf.h file, all timing computation is based on number of pixels for Porch begin/end/sync and display sizes in pixels ; however be sure to get the right clock ratios to run USB/SDIO clocks at 48MHz !
![]() |
| yes, testkernel can work at 800x600 (sorry bad pic) |
Saturday, September 13, 2014
"I love playing. The keyboard is my journal."
Well, now we can join Pharrell Williams and play the Bitbox with an USB Keyboard since commit 3a983ff
The USB code can now read USB keyboard and produce events, and a small function has been added to emulate the gamepad with a keyboard, so to get basic keyboard support you need to add one line in games. Or just check for the events yourself.
Keyboard can be read from an application by using the event_get() function , which returns a (possibly empty) event, check for e.type = evt_keyboard_press or evt_keyboard_release events, and then get the modifiers (Control, Shift...) state in e.kbd.mod and the keyboard code e.kbd.key bytes.
The code themselves are position-dependent, not letter-dependant (by example on a QWERTY keyboard the Q letter has the same code than the AZERTY 'A' letter, thanks to the USB norm for that), so if you want to type some text, use the appropriate translating tables. (there are two key maps available on the kernel for now, QWERTY and AZERTY).
All key codes ("Usages") can be found on the HID Usage Tables, Usage Page 7.
All of it is defined in the bitbox.h file.
The bootloader 2 has been upgraded with it, by additionally displaying the last key pressed or released on screen. Also, the examples now include keyboard usage.
The USB code can now read USB keyboard and produce events, and a small function has been added to emulate the gamepad with a keyboard, so to get basic keyboard support you need to add one line in games. Or just check for the events yourself.
Keyboard can be read from an application by using the event_get() function , which returns a (possibly empty) event, check for e.type = evt_keyboard_press or evt_keyboard_release events, and then get the modifiers (Control, Shift...) state in e.kbd.mod and the keyboard code e.kbd.key bytes.
The code themselves are position-dependent, not letter-dependant (by example on a QWERTY keyboard the Q letter has the same code than the AZERTY 'A' letter, thanks to the USB norm for that), so if you want to type some text, use the appropriate translating tables. (there are two key maps available on the kernel for now, QWERTY and AZERTY).
All key codes ("Usages") can be found on the HID Usage Tables, Usage Page 7.
All of it is defined in the bitbox.h file.
The bootloader 2 has been upgraded with it, by additionally displaying the last key pressed or released on screen. Also, the examples now include keyboard usage.
Friday, February 14, 2014
Devices API design
Revision 1 API
the preceding API for gamepads on rev1 was very simple : in fact it was only a halfword (!), representing the bits of each button on the SNES gamepad. This was simple, convenient and closest to the hardware.Now with the different class of devices that can be used and the fact the USB HID is used, I think we will need to have a different API.
Monday, October 21, 2013
An efficient scanline blitting algorithm
For the bitbox kernel, we need to have a fast graphical objects blitting library, since we will often have the same needs. Blitting from low Z to high Z of a fixed tiled background + overdrawing small sprites (to keep the 5k cycles budget) only goes so far, because as we are overdrawing pixels, we will be hitting the 5k cycles / lines pretty soon.
We will sum up the needs of such a library and propose an algorithm.
We will sum up the needs of such a library and propose an algorithm.
Friday, September 20, 2013
Tutorial : developing for Bitbox (the basics)
We're going over the course of this tutorial to program and build a simple program for the bitbox console on ubuntu. I'm trying it on a 13.04 Ubuntu, so adapt accordingly.
For windows, there is a small guide on the blog, you can use is in parallel with this page.
Monday, January 14, 2013
storing pixels
As with horizontal resolution, different choices can lead to different modes, but I’ll show some generic principles, you can adapt and create your own mode. Or reuse one.
There are several general ways to store pixels in order to output them.
The first, direct approach is a frame buffer.
A frame buffer is a chunk of memory storing pixels exactly as they will be output, so that you output to the screen what you’ve got in memory. Sometimes, things can be a little messier with color planes (i.e. one framebuffer per Rn G and B) and banks.
What resolution can we use if we want to use it with the current memory size ?
We can, of course use Flash for static images. But then, only using static images is quite restrictive for a game console.
Let’s pretend use 2 bytes per pixel. We have 192kb of memory on the stm32f4, but we can only use 128 as the other 64k is core coupled memory and won’t be seen by the DMA. So we can store 64k pixels (half that for 16 bits).
For a 4/3 aspect ratio, that’s sqrt(3/4*64*1024) = 221 lines.
We thus could store one screen of 294x221 pixels, or two screens of (only!) 221x147 if we want double buffering !
Which begins to enter the domain of lame for a 32bits game console.
For a better resolution of 640x480 @ 12bpp, we would need 640x480x2 = 614 400 bytes , which is about 5 times the RAM and more than half the Flash size.
For this, we need to compress the image we want in RAM and decompress it at 25 MHz pixel clock.
So we will need some translation functions that prepares a line of pixels for the current line from the frame buffer while the DMA outputs a line buffer. and then exchange those front and back buffers, exactly timed at 31 000 times per second.
Needless to say we won’t use jpeg.
Note that we need this compressed data to be manipulated by our game, so PNG and the like (really LZ77/LZW in memory pixel storage) will be too CPU intensive also, as well as impractical to manipulate for non static images.
The display function will translate the pixel color ids to a table of pixel colors and store it in the buffer. Generally it’s done by hardware by means of a RAMDAC (in : pixel ids, out : VGA signal, inside : some RAM for the palette / a DAC, hence, a ramdac. See wikipedia article.) but those chips are becoming hard to find/expensive and that’s an additional chip and that would force us using indexed color, so no).
Is it feasible by software ?
Let’s calculate how much time lines per seconds we could output.
Let’s consider a naive pixel / byte algorithm, not using 32bit word-aware method.
- Excluding loops housekeeping, that’s around 6 clocks per pixel IIUC the ARM reference latency roughly
- 1 read per pixel for the pixelID,
- 1 read to read the palette color from memory
- 1 store per pixel to the buffer.
(taking 70% of the CPU power - not counting V blank periods where we’re not outputting video, compared to None when we’re using a framebuffer. That’s a serious memory/cpu tradeoff, but if we can do better, having 50% of a 168MHz CPU isn’t so bad after all).
Note that if we can use 16 colors palette, that’s half the RAM also (4bits pp) or in 4 colors that’s 2bpp (with 1/4 less pixel reads and keeping the whole palette in registers so no palette reads … that with combined word writes can make it much faster).
Note also that with a palette you can manipulate the palette individually from the pixel data, so you can do fadeouts quite easily by switching palettes (not for free but because you’re already doing the translation work).
But that is quite expensive, and another method will be used first.
Tiled backgrounds
Another technique, often used for backgrounds and very similar to text mode goes further : instead of having a palette of pixels, lets have a palette of sub-images, composed to make a bigger image : one for a tree top, one for a bottom tree, one for grass : repeat many times and you have a big forest with 3 small images + a map.
It’s similar to text modes in that instead of doing it with letters (buffer of characters on screen + small bitmaps representing letters), you do it with color images (which can be letters).
Nice editors exist for tiled data, and we will use one to compose our images.
Storing such an image need storing tiles + a tilemap referencing your elements. The bigger the tile, the less bits you need to store the tilemap, the more you need to store the tiles. Note that tiles can be stored with a palette also.
Many other choices can be made, and combining them is possible, but we have few cycles to spare for now, so let's consider only tiles for now.
Subscribe to:
Posts (Atom)
