Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages | Examples

Getting Started, Hello World!

Hello World!

This section tells you how to write applications for turbo.

We start with a simple hello-world example.

/*
 * Copyright (C) 2003-2006 BLADOX, s.r.o.  All rights reserved.
 * 
 * This file is part of an example program for Turbo. This example
 * program may be used, distributed and modified without limitation.
 *
 */

#include <config.h>
#include <turbo/turbo.h>

u8 PROGMEM t_Foo_en[] = "Hello World!";

void action_menu (void *data)
{
  display_text_raw (t_Foo_en, Q_DISPLAY_TEXT_USER_CLEAR);
}

void turbo_handler (u8 action, void *data)
{
  switch (action)
  {
    case ACTION_INSERT_MENU:
      insert_menu (t_Foo_en);
      break;
    case ACTION_MENU_SELECTION:
      stk_thread (action_menu, data);
      break;
    default:
      break;
  }
}

You can see there are 2 functions in this example:

Let us start with the turbo_handler(). This function is required for each application and has to be called turbo_handler().

Attention:
Your application code must include the turbo_handler() function.
The turbo_handler() function is a handler - it receives actions and somehow handles them.
Note:
We could call the "action" also "event" or "signal" as well, but we decided to use the term action (ACTION_SOMETHING) because events are used in Ref. 11.14 SIM Toolkit specification and because SIGNAL keyword is used in avr-libc.
app_struct.png

Application structure


So handler receives actions and somehow reacts. There are actions related to:

As a speciality hardware interrupts are also handled by actions. For more see Actions.

In our hello-world example we handle the following two actions:

Usage of config.h

The purpose of config.h is to control macros in the standard headers included. It must be included as the first item.

The most important is the define DEBUG. Turbo provides the possibility to send debugging printouts to SPI and via Turbo programmer display them as the program is running. You can use several functions in your code: dpsp("text"), dpih(intvalueashex), dbch(char_as_hex) or dbc(char). If there is the #define DEBUG then these debugging commands are compiled in. In case the #define DEBUG is commented out (not present) then these commands are unused and there is no memory wasted.

Same for languages. You can have all the internationalization strings in your code but compile in only some languages just by commenting out the CONFIG_LANG_XX defines.

So you can have one code and with the help of config.h control what should be in the compiled result.

#ifndef _CONFIG_TURBO_
#define _CONFIG_TURBO_

#define DEBUG

#define CONFIG_LANG_EN
#define CONFIG_LANG_DE
#define CONFIG_LANG_IT
#define CONFIG_LANG_FR
#define CONFIG_LANG_ES
#define CONFIG_LANG_NL
#define CONFIG_LANG_SE
#define CONFIG_LANG_DK
#define CONFIG_LANG_PT
#define CONFIG_LANG_FI
#define CONFIG_LANG_NO
#define CONFIG_LANG_EL
#define CONFIG_LANG_TR
#define CONFIG_LANG_HU
#define CONFIG_LANG_PL
#define CONFIG_LANG_UN
#define CONFIG_LANG_CZ
#define CONFIG_LANG_HE
#define CONFIG_LANG_AR
#define CONFIG_LANG_RU
#define CONFIG_LANG_IS

#endif

Application Persistent Data

Application can store data in the EEPROM. The question is how to store the pointer on such data - it cannot be in RAM because its value would be lost after reset. So it has to be in EEPROM - pointer stored in EEPROM on data stored in EEPROM. The solution are the reg_app_data() and app_data() calls.

Typical example of persistent data usage

typedef struct _My_Persistent_Data
{
u8      x;
u16     y;
u8 *    p1;
} My_Persistent_Data;

u8 x;
u16 y;
u8 *p1;

void turbo_handler (u8 action, void *data)
{
  switch (action)
  {
    case ACTION_APP_REGISTER:
      {
        My_Persistent_Data *p = emalloc (sizeof (My_Persistent_Data));
        
        wb (&p->x, 0);
        ww (&p->y, 0x1234);
        ww (&p->p1, NULL);

        reg_app_data (p);
        break;
      }
    case ACTION_APP_UNREGISTER:
      {
        My_Persistent_Data *p = app_data ();
        
        efree (rw (&p->p1));
        efree (p);
        break;
      }
    case ACTION_APP_INIT:
      {
        My_Persistent_Data *p = app_data ();

        x = rb (&p->x);
        y = rw (&p->y);
        p1 = rw (&p->p1);
        break;
      }
...
  }
}

Shared Memory

It is possible to share memory between application, i.e. one application may have access to some data of another application.

Shared memory is implemented by key to pointer association, where key is for simplicity one byte number. First application prepares memory and uses u8 shmem_reg_key(u8 key, void *pointer) to associate key<->pointer. Another application makes lookup on given key and pointer is returned by void * shmem_key(u8 key).


Copyright © 2004-2006 BLADOX
Turbo version 1.2