This
blog post is the first in series (hopefully, there will be more) of
tutorials on the EvoPrimer dev kit from Raisonance. These tutorials
will mainly concentrate on usage of the circle OS. This tutorial
assumes that you already know how to create a simple Circle OS
project. If you are not aware of the procedure to do so, you can
follow this tutorial to learn about it.
For
this tutorial, we will see how we can create and use a tool bar under
Circle OS. Toolbars are the widgets that appear on the top of the
LCD.
For
this tutorial, we will build a simple game of gears, papers and
scissors (I could not find a rock icon in Tango image library :p).
The game logic itself is simple, the CPU makes a random selection of
an object, either a rock(gears), paper or scissor and compares
against the user selection, selected via the tool bar.
First
we will see how the game logic is implemented and then move on to the
implementation details of the game on the Circle OS.
The
game:
The three game
objects (gear, paper and scissor) are represented using numeric
values which are defined using following '#define's:
#define GEAR 0
#define PAPER 1
#define SIC 2
Next up, we have defines which
represent the result of a match.
#define PLAYER_WINS 3
#define CPU_WINS 4
#define DRAW 5
These two are used to setup the rules
table. This is a two dimensional array which when accessed with
column as CPU selection and row as user selection, returns the result
of the match. All other parts of the application is built on this
core logic. The game is “played” by the the function play() which
takes as input the user choice and internally generates a random
number to make a CPU selection and determines the result of the
match. We'll now see how one can create tool bars and use them.
The tool bars:
You can have up to 4 tool bar items displayed at a time.
The main toolbar is represented by the 'tTheToolBar' which is of type
'tToolbar' which we need to populate with our custom tool bar icons
and their associated call back functions. First, we need to have icons. I got
the icons from the Tango library and used “BMPTOLCD” tool to get
the RGB value from the image files and store it in “C” header
files.
static const uint16_t aPaperIcn[] = {
#include "paper.h"
};
static const uint16_t aGearIcn[] = {
#include "gear.h"
};
static const uint16_t aSiccorIcn[] = {
#include "siccor.h"
};
static const uint16_t aExitIcn[] = {
#include "exit.h"
};
If you were to add the above lines and
copy the header files into current working directory you would
encounter following error message
undefined symbol `!!!!!!!!! FLASH IS FULL !!!!!!!!!' referenced in expression
This is due to the fact that each
circle OS application by default is allocated 8K of program memory
and by including all the header files of icons (which also consumes
program memory), we have exceeded the memory allocated to us.
Solution is to modify the linker script, “Circle_App_OP4.ld” (or
“Circle_App.ld” in case of primer 1 or 2) to allow us to use more
program memory. The linker script is located in the same directory as
the project files are located. Open the file “Circle_App_OP4.ld”
in RIDE ( or your favorite editor) and scroll down to line number 198
and change “16K” to “64K” now that the linker knows the
program memory available (flash), we also need to set the higher
address for the flash. According to the linker script our program
memory starts from “0x800C000” and the higher address would be
0x800C000 + 64K – 1. Modify line 206 as well with the similar
changes that you made to line 198 that is, replace 16K with 64K. Save
the modifications and now the application should compile.
Now that we have icons for the tools
bar, we need to create the toolbar items that can be used by the
circle OS.
const tToolbarItem tItem1 = { aGearIcn, ToolBar_Handle_Gear};
const tToolbarItem tItem2 = { aPaperIcn, ToolBar_Handle_Paper};
const tToolbarItem tItem3 = { aSiccorIcn, ToolBar_Handle_Siccor};
const tToolbarItem tItem4 = { aExitIcn, ToolBar_Handle_Exit};
The above structure initializations has
two parts, the first part is the starting address of the image data
(which has to be 60x60 pixels for proper drawing on the LCD). The second
part is the callback function that will be executed when the user
clicks on the corresponding tool bar item.
enum MENU_code
ToolBar_Handle_Gear (void)
{
Play(GEAR);
return MENU_CONTINUE_COMMAND;
}
enum MENU_code
ToolBar_Handle_Siccor (void)
{
Play(SIC);
return MENU_CONTINUE_COMMAND;
}
enum MENU_code
ToolBar_Handle_Paper (void)
{
Play(PAPER);
return MENU_CONTINUE_COMMAND;
}
enum MENU_code
ToolBar_Handle_Exit (void)
{
MENU_RestoreAppliDivider();
return MENU_Quit();
}
All the toolbar handlers (except for
exit) use the Play() function to play the game. Finally, we register
our toolbar items with the circle OS using the following steps in the Application_Ini().
tTheToolBar.NbItems = 4;
tTheToolBar.FirstDispItem = 0;
tTheToolBar.Items[0] = tItem1;
tTheToolBar.Items[1] = tItem2;
tTheToolBar.Items[2] = tItem3;
tTheToolBar.Items[3] = tItem4;
TOOLBAR_Set (&tTheToolBar);
Above, we populate the main toolbar
('tTheToolBar') with the information of our tool bar items. First
statement sets the number of tool bar items, which is 4 in our case.
The next statement sets the first tool bar item to be displayed which
we have set to zero since we want 'gears' toolbar item to be
displayed first. This parameter can be useful if tool bar items are
greater than 4. In that case you can cycle through your multiple tool
bar items to be displayed. The tool bar for our application is set
using the function “TOOLBAR_Set()”. When you start your
application, you should see the toolbar in the top and should be able
to play the game.
You can download the project and related files from here.
You need to have an account at stm32circle.com to download the files.
I've kept out description of other circle OS features used (such as LCD_Draw()). These can be part of future tutorials. You can post any questions you might have in the comments section. I'll try my best to answer. Please do leave your feed back as well. Would help me to better these tutorials.
P.S.: Toolbars events are actually triggered through the LCD touch screen, hence you need to calibrate the touch screen (if you are restarting the EvoPrimer and have not calibrated the touch screen). Bottom line is, Without calibration, the tool bars won't work.
You can download the project and related files from here.
You need to have an account at stm32circle.com to download the files.
I've kept out description of other circle OS features used (such as LCD_Draw()). These can be part of future tutorials. You can post any questions you might have in the comments section. I'll try my best to answer. Please do leave your feed back as well. Would help me to better these tutorials.
P.S.: Toolbars events are actually triggered through the LCD touch screen, hence you need to calibrate the touch screen (if you are restarting the EvoPrimer and have not calibrated the touch screen). Bottom line is, Without calibration, the tool bars won't work.
This is good ! I like the way you have edited the linker script.Earlier I used to think that this feature (extended memory) is available only in the Premium Version of Ride and wasted lot of time in reducing the Application size, but I think I can use this feature now.I will test it and let you know the result.
ReplyDeleteGlad that this post helped you.
DeleteThe limitation you are talking of is on debugging your code on the primer with RIDE. I think the limit is 64 or 128 K. I am not sure how much that limit is.
Bonsoir, j'ai besoin de votre aide, j'aimerai faire un tableau de deux cases verticalement et 5 cases horizontalement dans l'ecran du module evoprimer je suis nouvelle dans ce domaine et je suis coincée .Donc comment je peux programmer ça sachant sue j'utilise le RIDE7 pour configurer l'evoprimer. Merci d'avance
ReplyDeleteI've used google translate to understand what you've written and my understanding of your problem is on that basis.
DeleteWhat I understand is that you want to draw a table using squares (I presume 2x2). You can easily accomplish this using LCD_FillRect() function. To get you started, I've written a small code for you. You can find it here http://pastebin.com/603braGN. Play with TABLE_COLS, TABLE_ROWS to get a feel of it. Hope this helps.