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 BT817 Graphics Engine and Review of Evaluation board. Following list contains links to all parts of my review:


  • Introduction and Overview of Table of Contents (coming soon)
  • Review of BT817 Graphics Engine (coming soon)
  • Review of ME817EV Evaluation Board (coming soon)
  • Project description + Tutorial: Pacman
  • Tutorial: How BT817 Coprocessor works (this article)
  • Project description: ZUSI 3 display (coming soon)


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()


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 BT817 graphics engine (coming soon) and Review of evaluation board (coming soon).