I welcome you to this part of my Bridgetek BT817 RoadTest review. In previous blog post I described how to draw to the display in the simplest way using display list. In this blog post I will show more advanced way using coprocessor which supports more advanced commands that display list. While these articles are part of my review, they present only few of my opinions about BT817 and evaluation board. If you are interested in my opinions, some notes, description of good and bad thing about chip and evaluation board then you can read them in chapters starting with Review in name. There are two of them: Review of Bridgetek BT817 Embedded Video Engine and Review of Bridgetek ME817EV Evaluation board. Following list contains links to all parts of my review:
- Introduction, contents, summary, and score
- Review of Bridgetek BT817 Embedded Video Engine
- Review of Bridgetek ME817EV Evaluation Board
- Pacman using Bridgetek BT817
- How does the BT817 coprocessor work? (this page)
- ZUSI 3 display (become available in the future)
Using coprocessor
Coprocessor is separate engine, but its controlling in very similar way like display list, but they are differences. Coprocessor commands are more advanced. Their length is variable because often they hold some dynamic parameters like strings. In opposition DL commands which you have seen in previous article are always 4 bytes in length and the only parameters must be encoded inside 3 bytes as part of command (4th byte is opcode). The other difference is that commands are not passed to the BT817 memory directly, but they are passed to FIFO and they are processed by coprocessor. Processing commands may take some time to coprocessor so you should check that there is enough space in FIFO before posting command. Especially when posting command with long parameters (for example commands with long text parameters). Coprocessor maintains some internal states according to commands which you have issued to them. For example, there are command for running display calibration routine. When you execute this routine coprocessor will add commands to DL showing animated points where user should touch, read touches from touch controller and after successful calibration calculate correct coefficients and configure them inside touch engine. As you can see, all things which coprocessor does you can do manually but using coprocessor it is much easier and significantly reduce complexity of your code/firmware on your MCU. Instead of implementing custom calibration routine you can just execute one coprocessor command.
I tried run some coprocessor commands and has been seeing how they affected generated display list.
Example: Coprocessor TEXT command
One of coprocessor command is TEXT command. This command prints text using specified font at specified location. BT817 display list has no support for printing text because this kind of stuff is hardly hardware accelerable. Only way how to draw text using DL is using bitmap command which copy every letter from font bitmap to display. You must manually calculate pixel location for every letter, and you must issue command for printing every letter. Coprocessor very simplifies this because you issue just one TEXT command and coprocessor will generate all the required DL commands for you. I write project which view what happens with DL after issuing commands to coprocessor. Program looks as follows:
BT817_CoprocesorWr32(0x02404000); // CLEAR_COLOR_RGB(64, 64, 64) BT817_CoprocesorWr32(0x26000007); // CLEAR(1, 1, 1) BT817_CoprocesorWr32(0x04FFFFFF); // COLOR_RGB(255, 255, 255) BT817_CoprocesorCmd_Text(100, 50, 25, 0, "abcd"); BT817_CoprocesorWr32(0x00000000); // DISPLAY() BT817_CoprocesorCmd_Swap();
This program makes following scene on display:
After issuing these commands I will wait until coprocessor process all the commands and then I will read whole DL from memory, parse commands which are stored in this list and print them over UART. After executing this commands, I received following output (it is dump of DL memory):
0x00000000 0x02404000 CLEAR_COLOR_RGB 0x00000004 0x26000007 CLEAR 0x00000008 0x04ffffff COLOR_RGB 0x0000000c 0x1f000001 BEGIN 0x00000010 0x8c832ce1 VERTEX2II 0x00000014 0x8ec32ce2 VERTEX2II 0x00000018 0x91032ce3 VERTEX2II 0x0000001c 0x93032ce4 VERTEX2II 0x00000020 0x00000000 DISPLAY
The first column is address inside display list, second column is value inside display list and third column is parsed human-readable name of this command. So, let’s see what happened when we passed commands to coprocessor. The first 3 commands which I have passed to coprocessors are basic DL command.
BT817_CoprocesorWr32(0x02404000); // CLEAR_COLOR_RGB(64, 64, 64) BT817_CoprocesorWr32(0x26000007); // CLEAR(1, 1, 1) BT817_CoprocesorWr32(0x04FFFFFF); // COLOR_RGB(255, 255, 255)
After executing them the same commands appeared inside DL. This is correct. When you pass some basic command, coprocessor do nothing with them, and it just copy them directly to DL. This is useful because you can access DL and coprocessor without need to worry about overwriting some generated commands with your own and backwards. You can just send them to coprocessor and coprocessor will place them to correct location inside DL.
Next command is more interesting. It is command drawing text using font number 22 to the location 100, 50.
BT817_CoprocesorCmd_Text(100, 50, 25, 0, "abcd");
This command is not a standard DL command and it is coprocessor command. After issuing them, coprocessor interpreted it and calculated following 5 commands which it added to the DL.
0x0000000c 0x1f000001 BEGIN 0x00000010 0x8c832ce1 VERTEX2II 0x00000014 0x8ec32ce2 VERTEX2II 0x00000018 0x91032ce3 VERTEX2II 0x0000001c 0x93032ce4 VERTEX2II
The first DL command is BEGIN command with parameter 1 which means BITMAP. This command changes mode of drawing primitive to drawing bitmaps. Following 4 commands were VERTEXII command which is special command that defines source position in font bitmap (you can consider it as a letter index) and coordinates where should be letter pasted. For example, decoding parameters of first VERTEX2II command lead you to following human-readable command:
VERTEX2II(100, 50, 25, 97)
You can see coordinates 100 and 50, font number 25 and finally value 97 which is ascii value of ‘a’. This all make sense because first letter of string which we have print using TEXT command was ‘a’. Now let’s look to following command 0x8ec32ce2. It can be decoded as:
VERTEX2II(118, 50, 25, 98)
As you can see, there are two changes. First chage is that ASCII code changed from 97 to 98 because second letter is ‘b’ instead of ‘a’ and second change is that X coordinate is not 100 but it is 118. Because we are using coprocessor, we do not need to worry about it, but it is good to know that calculation of coordinates of every letter is job of coprocessor.
Following 2 commands prints ‘c’ and ‘d’ in similar way as previous letter was printed. Last command is NULL terminating command which is DISPLAY command which were just copied because it is simple DL command. This command terminates display list and inform graphics engine that there are no more commands.
In previous example I demonstrated how are coprocessor commands translated to DL commands and it was simple but note that coprocessor can draw much complex components, like buttons, sliders and other GUI components. I tried to see what happens in DL when you attempt to draw button using following command:
BT817_CoprocesorCmd_Button(100, 100, 100, 20, 22, 0, "RoadTest");
Result was following:
0x00000020 0x22000000 SAVE_CONTEXT 0x00000024 0x27000002 VERTEX_FORMAT 0x00000028 0x0500000f BITMAP_HANDLE 0x0000002c 0x06000000 CELL 0x00000030 0x0120004c BITMAP_SOURCE 0x00000034 0x28000000 BITMAP_LAYOUT_H 0x00000038 0x07180219 BITMAP_LAYOUT 0x0000003c 0x29000000 BITMAP_SIZE_H 0x00000040 0x0808c814 BITMAP_SIZE 0x00000044 0x20000001 COLOR_MASK 0x00000048 0x0b000000 BLEND_FUNC 0x0000004c 0x1f000001 BEGIN 0x00000050 0x40c80190 VERTEX2F 0x00000054 0x2000000f COLOR_MASK 0x00000058 0x0b000014 BLEND_FUNC 0x0000005c 0x0e00003c LINE_WIDTH 0x00000060 0x1f000009 BEGIN 0x00000064 0x04ffffff COLOR_RGB 0x00000068 0x40ce819d VERTEX2F 0x0000006c 0x418781cf VERTEX2F 0x00000070 0x04000000 COLOR_RGB 0x00000074 0x40d181a3 VERTEX2F 0x00000078 0x418a81d5 VERTEX2F 0x0000007c 0x04003870 COLOR_RGB 0x00000080 0x40cf819f VERTEX2F 0x00000084 0x418881d1 VERTEX2F 0x00000088 0x1f000001 BEGIN 0x0000008c 0x20000001 COLOR_MASK 0x00000090 0x0b000018 BLEND_FUNC 0x00000094 0x40c80190 VERTEX2F 0x00000098 0x2000000e COLOR_MASK 0x0000009c 0x0b00001d BLEND_FUNC 0x000000a0 0x04ffffff COLOR_RGB 0x000000a4 0x40c80190 VERTEX2F 0x000000a8 0x2000000f COLOR_MASK 0x000000ac 0x0b000014 BLEND_FUNC 0x000000b0 0x04000000 COLOR_RGB 0x000000b4 0x05000016 BITMAP_HANDLE 0x000000b8 0x8e463b52 VERTEX2II 0x000000bc 0x8fc63b6f VERTEX2II 0x000000c0 0x90e63b61 VERTEX2II 0x000000c4 0x92063b64 VERTEX2II 0x000000c8 0x93263b54 VERTEX2II 0x000000cc 0x94663b65 VERTEX2II 0x000000d0 0x95863b73 VERTEX2II 0x000000d4 0x96863b74 VERTEX2II 0x000000d8 0x23000000 RESTORE_CONTEXT
As you can see, drawing button which was issued by single coprocessor command resulted into generation of 47 commands inside DL buffer and this is significant offload. Imagine issuing all these commands manually.
The last thing which I want to mention are memories. They are not totally related to the coprocessor, but they are intensively used and required by coprocessor commands. In previous example you can see following BITMAP_SOURCE command:
0x00000030 0x0120004c BITMAP_SOURCE
This command reference address memory at address 0x20004C which is ROM. So this mean that some texture used for drawing button is hardwired into ROM and do not consume any RAM or FLASH memory. In datasheet you can find more comprehensive description of available memory regions but from user perspective there are three important storages which can be used for storing bitmaps and some other things. They are:
- ROM with hardcoded assets like integrated fonts
- RAM which you can use for whatever you want, for example you can copy custom bitmaps or fonts here and then reference them from this memory. Capacity of integrated RAM is 1 MB.
- External FLASH which you also can use for whatever you want similarly to RAM, but it is hard to write and of course you must include some external flash in your design if you want to use it. Evaluation board has onboard 16MB (128 Mb) memory.
On following screenshot from datasheet, you can see all regions. Except regions which I described in previous listing there are RAM for DL commands, area containing special function registers, FIFO for coprocessor commands, some small buffer for human readable description of coprocessor errors and RAM memory for storing firmware of touch controller (you can upload patches here. This is useful if you want to use originally unsupported touch controller. You can find some patches on Bridgetek forum and some of them are also as part of SDK).
This is all from this article. In this article I described how coprocessor works like, how it can simplify some common tasks and how it works internally with examples. In next article I will describe one of my demo projects which I have done for gaining experiences with graphics engine and evaluation board. If you are interested in my opinions about BT817 and evaluation board, some strange pros and cons about it and some other notes, you can find them in article Review of Bridgetek BT817 EMbedded Video Engine and Review of Bridgetek ME817EV Evaluation Board.