manufacturer of I/O-rich SBCs, operator interfaces, handheld instruments, and development tools for embedded control low cost single board computers, embedded controllers, and operator interfaces for scientific instruments & industrial control development tools for embedded control order our low cost I/O-rich embedded control products embedded controller manufacturer profile single board computers & embedded controllers development tools & starter kits for your embedded design operator interfaces with touchscreens and graphical user interface plug-in expansion modules for digital & analog I/O C language & Forth language integrated development tools, IDE single board and embedded computer accessories embedded controller enclosures, bezels, environmental gaskets

QScreen C User Guide

Table of Contents

PART 1 GETTING STARTED

Introduction. How to Use This Manual

Chapter 1: Getting to Know Your QScreen Controller

Chapter 2: Your First Program

Chapter 3: The IDE: Writing, Compiling, Downloading and Debugging Programs

Writing Programs

Accessing the Standard (Kernel) Library Functions

Initializing Variables

Compiling Programs

Using the Interactive Debugger

Overview of the Forth Language and Programming Environment

Displaying the Values of Static Variables

Use Type Keywords To Interactively Call C Functions

Displaying the Values of FORTH_ARRAY Elements

Under the Hood of the QED-Forth Interactive Debugger

Other Useful QED-Forth Functions

Chapter 4: Making Effective Use of Memory

Chapter 5: Real Time Programming

Chapter 6: Failure and Run-Time Error Recovery

PART 3 COMMUNICATIONS, MEASUREMENT, AND CONTROL

Chapter 7: Digital and Timer-Controlled I/O

Chapter 8: Data Acquisition Using Analog to Digital Conversion

Chapter 9: Serial Communications

Chapter 10: The Battery-Backed Real-Time Clock

PART 4: PUTTING IT ALL TOGETHER

Chapter 11: A Turnkeyed Application

PART 5: REFERENCE DATA

Appendix A: QScreen Electrical Specifications

Appendix B: Connector Pinouts

Appendix C: QScreen Schematics

Chapter 3

<< Previous | Next>>

The IDE: Writing, Compiling, Downloading and Debugging Programs

In this Chapter we’ll explore the QScreen Controller’s tools for writing, editing, downloading and debugging your application program.  You’ll learn:

How to efficiently use the editor and compiler to write and compile both short and long programs;

Coding and file-naming conventions;

How to access the QScreen Controller’s onboard functions; and,

How to interactively debug your programs.

Writing Programs

Using the Editor/Compiler

In the prior Chapter we introduced the Mosaic IDE and the tools you can use to edit, compile, and download your program. Briefly, the text pad toolbar provides the following buttons:

The Compile Tool, designated by the “Debug” icon, invokes the Control-C compiler – Forth programmers do not need to use it because Forth programs are compiled as they are downloaded onto the QCard Controller.  The Compile Tool invokes the compiler and assembler only – it does not produce downloadable code.  Use it to quickly check the syntax of a program and find compile errors.

The Make Tool, designated by the “Make” icon is also for C programmers.  It controls how C programs are linked and stored in memory.  Forth programmers do not need to use it.  The Make Tool performs a standard, single-page memory model build of your program for programs that do not exceed 32 Kbytes of memory.  If you see the following warning printed in the compiler output, then you must switch to the multi-page memory model build (Multi-Page Make icon):

WARNING:  Input section “.doubleword” from ‘progname.o11’ is not used !

Forth programmers will also not need the Multi-Page Make Tool, designated by the “Multi-Page Make” icon, which assists in compiling long C programs.  The Multi-Page Make Tool invokes the C compiler’s multi-page build mode for long programs.  Still, each source code file should be less than 32 Kbytes worth of compiled source code or the above warning will be issued and the program will not run.

The Terminal icon launches the communications program, Mosaic Terminal, which is used to download your compiled program to the QScreen Controller.

Sylistic Conventions

Code Comments

At the top of the GETSTART.4TH source code file are some comments that tell what the program does.  The \ character means that the remainder of the line is a comment.  Note that the editor colors all comments differently to make it easy to distinguish comments from source code.  Forth keywords are also colored differently than user-defined routines.  You can change the default colors if you like.At the top of the GETSTART.C source code file are some comments that tell what the program does.  Single- or multi-line comments can be enclosed in the standard

 

/*    */

delimiters.  The double-slash

 

//

token means that the remainder of the line is a comment.  Note that the editor colors all comments differently to make it easy to distinguish comments from source code.  C keywords are also colored differently than user-defined routines.  You can change the default colors if you like.

Style Conventions

The example programs on your CD-ROM follow several stylistic conventions.  Here is a brief summary:

  Macros and constants are spelled with CAPITAL_LETTERS.

  Variable names are spelled with small_letters.

  Function names use both capital and small letters, with underscores indicating the start of a new subword within the function namewith capital letters indicating the start of a new subword within the function name.  For example:

 

void SaveCircleParameters(void)

To minimize the need to skip from one file to another, we have decided not to group all #define statements in a header file that is separate from the program being compiled.  Rather, the #define statements are defined close to where they are used in the program file that is being compiled.

File Naming Conventions

For backward compatibility with DOS and Windows 3.1, all filenames have 8 or fewer characters.  C source code files have the .C extension, and header files have the .H extension.  When you use the Make Tool utility to compile a source code file with the filename,

NAME.C

several files with the extensions shown in Table 3‑1 are created:

Table 3‑1      Files Created by the C Compiler.

FILENAME.ext

Description

NAME.C

Source code text file created by you, the programmer

NAME.A11

Assembled output text file created by C11 compiler

NAME.O11

Object code binary file created by ASM11 assembler

NAME.LCF

Linker command text file created by CC or CCM batch file

NAME.S

S-record (raw download ascii file) created by linker

NAME.DLF

Final download file created by CC or CCM batch file; includes S records and definitions for QED-Forth

NAME.MAP

Map file listing created by linker

NAME.MEM

Symbols map file

NAME.USE

Memory usage summary

NAME.BAK

Backup file sometimes created by the editor

While this list may seem overwhelming, you won’t have to worry about most of these files.  You’ll create your NAME.C and .H source code and header files in a directory of your choice, run the automated Make Tool by clicking on the Make icon, and send the resulting NAME.DLF download file to the QScreen Controller using the Terminal program.  In fact, unless you tell it otherwise, the editor’s “File” menu will typically show you only files with the .C and .H extensions (“Source Files”); you won’t have to wade through the files with the other extensions.  Similarly, the Mosaic Terminal typically lists only files with the .DLF extension, so it will be easy to select the download file to send to the QScreen Controller.

Using Function Prototypes

This stylistic convention deserves its own section.  We strongly urge that you define or prototype each function before it is called.  If the compiler generates a warning that a function has been called without a prototype, we recommend that you check your source code and insert the required function prototype, or move the definition of the function so that it is defined before it is called. 

A prototype is a declaration that specifies the function name and the types of its return value and input parameters.  For example, the following is a valid function prototype:

 

_Q float CalcArea( unsigned int radius);

This declaration specifies that CalcArea() is a function that expects one unsigned integer input and returns a floating point value.  As discussed below, the _Q tags the function as one that is interactively callable during debugging. The CalcArea() function can then be defined later in the source code file.  If a function is prototyped in one file and defined in another, add the extern specifer before the prototype.

You can preface any function prototype with the _Q tag if you want to interactively call the function from the terminal.  The QScreen Controller’s onboard operating system maintains a list, called the dictionary, of the names of functions tagged with the _Q so that it can recognize them when you send a command line from your terminal.

Prototype and Declare the Parameter Types of Every Function

Defining or prototyping a function before it is called allows the compiler to help find parameter passing errors, and it also prevents unnecessary promotion of parameters that can render the code slower and defeat the QScreen Controller’s interactive function-calling capability.  To avoid unwanted promotion and runtime errors, each and every parameter in the function prototype or function definition must be preceded with a type specifier.  For example, leaving out the unsigned int keywords in the prototype for CalcArea() above would lead to promotion of the input parameter, possibly resulting in a runtime error message from the compiler or linker. 

Using function prototypes and definitions that explicitly specify the type of each and every input and output parameter results in more readable and reliable code.

Accessing the Standard (Kernel) Library Functions

The command

 

#include < \mosaic\allqed.h >

near the top of the GETSTART.C file is a preprocessor directive that includes all of the relevant header files for the QScreen Controller, and all of the standard C header files (such as stdio.h, math.h, float.h, string.h, etc.)  We strongly recommend that this statement be placed at the top of each C program file that you write.  It gives you access to all of the pre-coded library routines that reside on the QScreen Controller.  These routines let you control the A/D converters, digital I/O, serial ports, real-time clock, and many other useful functions.  The ALLQED.H file also gives you access to the QScreen Controller’s multitasking and paged memory capabilities, as well as the standard ANSI C library functions including printing and string conversion routines such as printf() and sprintf(). Including these files is very efficient; it generates almost no additional runtime code while giving you access to very powerful capabilities.

You can call any of these functions from within your C code.  There is one limitation however:

Do not nest functions of the type _forth.

Many functions that are callable from C are actually of the _forth type.  This includes functions that are in the kernel on the QScreen Controller, or are part of software distributions such as the Graphical User Interface (GUI) Toolkit.  A call to one of these _forth functions may not be made from within the parameter list of a call to another _forth function.

There is always a straightforward way of avoiding such nesting of function calls: simply use a variable to hold the required intermediate return value/parameter.  For example, if you need to use the _forth function FetchChar() to fetch the first character from the extended address returned by the _forth function DisplayBuffer() in paged memory, you could execute the following statements:

 

static xaddr buffer_xaddress = DisplayBuffer( );

FetchChar( buffer_xaddress);

This code is correct, while nesting the call to DisplayBuffer() inside the parameter list of FetchChar() would be incorrect.

Initializing Variables

Caution:
RAM-Resident Variables & Arrays Must Be Initialized Within Functions

A common mistake made when creating application programs for embedded systems is the use of compile-time initialization for RAM-based quantities such as variables and arrays.  While this approach of initializing quantities outside of function definitions may work during program development, it fails when the device goes into production because the variables and arrays are not properly initialized when power is cycled. 

Only run-time initialization, i.e., initializations that are performed within functions (which are in turn called by the autostart program), will occur reliably in an embedded application.

Even users with battery-backed RAM in their systems should always perform initializations within functions.  This approach will avoid hard-to-diagnose field failures that result from corrupted data in a battery-backed RAM that is never re-initialized to valid values.

Feel free to call Mosaic Industries for help with this or other programming issues.

Compiling Programs

Compiling Multiple Source Code Files

When writing large programs it is often useful to break up the program into multiple source code files.  The Make Tool allows you to accomplish this in one of two ways.

    1. First, you can designate one of your source code files as the primary file, and insert into this file statements of the form,

 

#include “\path\filename”

to include the other source code functions, where \path is the standard DOS path specification that allows the file to be located.  The primary file must have a .C extension.

    2. Second, you can split your source code into several files that start with the same sequence of characters, such as:

 

CODE.C    // this is the primary file that you compile

CODE1.C   // CODE1.C and CODE2.C are subsidiary files that are automatically

CODE2.C   // compiled and linked when CODE.C is compiled

All of these files must have the .C extension.  Then, when you compile CODE.C using the Make Tool (by clicking on the Hammer icon), all of the files with a .C extension whose name starts with CODE (namely, CODE.C, CODE1.C and CODE2.C) will be compiled and linked together.  Note that the Make Tool cannot handle filenames that start with a numeral or filenames that contain the dash character; thus a source code file named 1CODE.C or MY-CODE.C cannot be compiled.

Finally, note that one and only one of the program files must include a function named main().

Controlling the Memory Map

Compilation Errors

Compilation Errors (from QED Software Manual)

Downloading and Installing a Program

Using Terminals other than TextPad

Editors and Terminals for the PC

This interactive style of programming and debugging is especially easy if you can switch rapidly between the editor and terminal programs on your PC.  If you have an IBM-compatible or clone PC, we recommend that you use the editor (either Write or Notepad) and terminal (named Terminal) that come with the Microsoft Windows™ software.  This inexpensive package gives your PC a simple yet very powerful menu-based operating environment.  You control the computer by pointing at menu entries and clicking a button on a movable mouse to select the desired options.  The operating system software lets you switch from editing mode to terminal communications mode by simply clicking on the appropriate program window.

A step-by-step guide to configuring the Windows terminal and editor for use with the QVGA Controller is presented below.

Of course, any text editor and terminal programs will allow you to program in QED-Forth as long as the terminal is properly configured.  We provide a simple public domain terminal called Kermit with each QED Product Design Kit and QED Developer Package; while it is fairly primitive compared to the Windows Terminal, it can be used.  The last section of this appendix provides some hints about the operation of Kermit.

Editors and Terminals for the Apple Macintosh (Forth only)

Editors and Terminals for the Apple Macintosh

Apple Macintosh users can use any of the popular available terminal programs such as Smartcom™ or Microphone™.  The editor can be the simple MockWrite desk accessory which operates in conjunction with any application.  Macintosh owners can also use the System 7 multitasking operating system to switch between editor and terminal programs.

Terminal Configuration for Smooth Downloads  -- Configuring other Windows Terminals (from QED Software Manual)

Appendix A Terminal Configurations for QED Communications A-1 (Getting Started C v31)

Terminal Configuration for Smooth Downloads A-1 (Getting Started C v31)

How to Configure the Microsoft Windows Terminal A-2 (Getting Started C v31)

Setting the autostart

[3u-d4-a] ???

An Additional Feature in the RECEIVE.HEX Function

The function named:

    RECEIVE.HEX    ( xaddr1 <text> --  )

accepts an Intel or Motorola hex dump and initializes memory locations on the QVGA Controller starting at the specified 32-bit address xaddr1.  In V3.1, if xaddr1 equals FFFFFFFFH (that is, a 32-bit -1), the memory storage addresses are as specified in the hex dump itself.  This may be convenient for some applications.

Using the Interactive Debugger

In the prior chapter, you gained experience using the debugging environment that lets you interactively execute any designated function with input arguments of your own choosing.  Now we’ll look more closely at the operation of the debugging environment, and explain how to use it to examine and manipulate the values of static variables, Forth Array elements, and memory locations.

The interactive debugging environment conveys several advantages.  First, you can test each function of a program individually without changing the main() function and recompiling.  This saves compilation and download time. Second, the environment makes it easy to test each function with a wide range of input parameters, allowing you to isolate bugs that might otherwise be missed until later in the program development cycle.  Such thorough function-by-function testing of a program facilitates more rapid development of reliable programs.

We’ll start by learning how to use the interactive environment to examine the values of static variables.  The explanation of how this works involves taking a brief high-level look at the interactive QED-Forth language that is built into the QScreen Controller. Understanding how QED-Forth operates will empower you to take full advantage of the debugging capabilities of the QScreen Controller.

Overview of the Forth Language and Programming Environment

The QED-Forth interactive environment makes it easy to examine the contents of static variables.  A brief overview of how the Forth language works will help clarify the procedure.

The Forth Data Stack

Forth is a stack-oriented high level language that combines the interactive benefits of an interpreter with the speed of a compiler.  Unlike C, FORTH is implemented as a two-stack language.  In addition to the return stack that most languages use to keep track of function calls and returns, FORTH has a data stack that is used to pass parameters.  All arithmetic, logical, I/O, and decision operations remove any required arguments from the data stack and leave the results on the data stack.  This leads to postfix notation: the operation is stated after the data or operands are placed on the stack.  This is the same notation used by Hewlitt Packard’s RPN (reverse polish notation) calculators.

Unlike C, Forth uses spaces as delimiters to distinguish different keywords and tokens.  For example, a C compiler can easily parse the addition expression:

 

5+4

as three distinct tokens: 5, +, and 4.  But because the above expression was typed without any spaces, Forth would interpret the expression as a single token, assume it’s the name of a function, and would try to find it in its dictionary.  In Forth the expression must be entered as:

 

5  4  +

which includes the required spaces and uses postfix notation to add the numbers and leave the result on the data stack.

To see how this works, we’ll talk to the interactive QED-Forth interpreter on the QScreen Controller.  To start, enter the terminal now: if the terminal program is already active, click on its window or hold down the “Alt” key and press “Tab” until the terminal announcement appears on your screen.  If you haven’t started the terminal program yet during this session, double-click on the Mosaic Terminal icon to start it up.  Connect and power up your QScreen Controller; pressing the Return key should cause QED-Forth’s ok prompt to appear in the terminal window.

To start, we’ll ensure that the current number base is decimal by typing the command,

DECIMAL

from the terminal.  With each character you type QED-Forth echoes the character in you terminal window.  The back arrow in the line above indicates that you pressed the Enter key which sends a carriage return character; but you won’t see it as an echoed character on your screen.  QED-Forth executes this command when the terminating carriage return is received.  Also recall that QED-Forth case-insensitive, so you can freely mix upper and lower case letters.  Now we can put some numbers on the QED-Forth data stack by typing :

5  7

followed by a carriage return. QED-Forth responds:

ok   ( 2 ) \ 5 \ 7

We have underlined QED-Forth’s response for clarity.  QED-Forth is showing a picture of its data stack.  The ( 2 ) means that there are two items on the stack.  Each of the items is listed, and items are separated by a \ character, which can be read as under.  So we could describe the stack right now as 5 under 7; the 7 is on top of the stack, and the 5 is under it. If there are more than 5 items on the stack, the stack print displays the number of stack items and the values of the top 5 items.

The stack print that shows what’s on the data stack is a feature of the debugging environment.  To disable the stack print, you could execute (that is, type at your terminal) the DEBUG OFF command.  It is not recommended that you do this, though; it’s very helpful to keep track of the items on the data stack while developing your program.

To multiply the numbers that are now on the stack, type the multiply operator which is a * character:

*

and QED-Forth responds:

ok  ( 1 ) \ 35

The QED-Forth * operator removes the two operands 5 and 7 from the stack, multiplies them, and puts the result of the multiplication on the stack.  To subtract 5 from the number on the stack, type:

5  -

which produces the response:

ok  ( 1 ) \ 30

The QED-Forth - (minus) operator takes the 35 and the 5 from the stack, subtracts, and puts the result on the data stack.

To print the result to the terminal, we could simply type the printing word:

.

(that’s right, the command is simply a dot, the period on your keyboard) which prints the response:

30   ok

The printing word . removes the 30 from the stack and prints it.  The stack is now empty, so QED-Forth does not print a stack picture after the ok.

Notice that throughout this exercise QED-Forth has been interpreting and executing commands immediately. This is because the Forth language is interactive.  The results of executing commands can be immediately determined.  If they are incorrect, the command can be changed to correct the problem.  This leads to a rapid iterative debugging process that speeds program development.  This interactive function execution has been harnessed to speed development of C programs for the QScreen Controller.

QED-Forth Numeric Printing Functions

There are a variety of QED-Forth printing functions, and some related functions that set the current number base and clean up the data stack.  Here is a short list of useful functions that can be executed interactively:

 

Function

Description

.

Prints a 16 bit signed integer in the current number base

U.

Prints a 16 bit unsigned integer in the current number base

D.

Prints a 32-bit signed long in the current number base

PrintFP

Prints an ANSI-C floating point number

HEX

Sets the number base to hexadecimal

DECIMAL

Sets the number base to decimal

SP!

Clears all items off the stack without printing anything

Each of the printing routines removes a number from the data stack and prints it to the terminal.  Because characters are promoted to unsigned int in Forth, the . (dot) function is also used to print 8-bit character data.  The PrintFP function was specifically written to display floating point numeric output from C programs, as internally QED-Forth uses a non-ANSI floating point representation for its own floating point numbers.

The default QED-Forth number base after a COLD restart is DECIMAL.  The number base can be changed to hexadecimal by executing HEX.  All non-floating-point numbers typed at the terminal or printed by QED-Forth are converted using the current number base (corresponding to the most recent execution of DECIMAL or HEX).  Floating point numbers are always converted using the decimal number base.

Displaying the Values of Static Variables

Now that we understand how the Forth data stack works, the procedure for examining variables will make sense.  The examples presented here use code from the GETSTART.C program that we’ve already discussed in detail.  If you have already downloaded the program, you are ready to go.  If your board is presently running a multitasking application and you want to download a new file, type

WARM

to stop the program so that a new download file can be accepted.

If you have not yet compiled the GETSTART.C program and you want to do the exercises here, first compile it by opening \MOSAIC\DEMOS_AND_DRIVERS\MISC\C EXAMPLES\GETSTART.C in the TextPad editor, click on the Make Tool, and after the compilation, enter the Mosaic Terminal and use the “Send Text File” menu item to send GETSTART.DLF to the QScreen Controller.  To run the program, type

main

at your terminal – this initializes all the pointers and variables.  After typing main, let’s type

Nap( )

to put the calculation task asleep; remember to type at least one space after the (.  This stops the variables from being updated in the background.

Let’s start by initializing the contents of the radius variable to 5 by interactively executing (typing) from the terminal:

SetRadiusAndArea( int 5)

Remember to type at least one space after the ( character and after int.  This function is defined in GETSTART.C as:

 

_Q SetRadiusAndArea( uint r)

{  radius = r;

area = CalcArea( r);

}

It assigns the specified input parameter to the unsigned integer radius variable, and assigns the corresponding circular area to the floating point area variable.

Now we can check the value of radius.  The following interactive command places the contents of the integer variable named radius on the Forth data stack:

int  radius

QED-Forth responds with:

ok  ( 1 ) \ 5

Because radius is defined as an unsigned integer, we use the unsigned integer printing routine named U. (U-dot) to remove the value from the Forth data stack and print it.  Type

U.

to print the radius an unsigned integer.  QED-Forth responds with:

5 ok

To speed things up, we can type the entire command sequence on one line so that QED-Forth immediately prints the result.  Type:

int  radius  U.

and QED-Forth responds with:

5 ok

To interactively examine the contents of the floating point area variable, type the command sequence:

float  area  PrintFP

and QED-Forth responds:

78.54 ok

which is indeed the area of a circle whose radius equals 5.

Extracting the Value Referenced by a Pointer

Sometimes C programs add an additional layer of indirection, referencing a value by means of a pointer.  An example of this technique appears in the GETSTART.C program in the form of the static variables radius_ptr and area_ptr; they are defined as:

 

static uint*   radius_ptr;

static float*  area_ptr;

In the InitVars() function near the end of the program, these pointers are initialized as follows:

 

radius_ptr = &radius;

area_ptr = &area;

In other words, radius_ptr holds the address of a variable that represents the radius, and area_ptr holds the address of a variable that represents the area.  Given the radius_ptr and area_ptr, we want to be able to extract the value of radius and area.  The following keywords can be executed interactively to accomplish this:

 

char*      int*      long*      float*

Note that there cannot be any spaces before the * in each keyword, and there must be at least one space after the * and before any subsequent number or variable name. 

For example, to print the radius you can type:

int*  radius_ptr  U.

The int* keyword fetches the 16-bit address from radius_ptr and from that location fetches the integer contents.  U. then prints the answer to the terminal.  Similarly, to print the area you can type:

float*  area_ptr PrintFP

The float* keyword fetches the 16-bit address from area_ptr and from the resulting location fetches the floating point contents. PrintFP then prints the result.

Signed versus Unsigned Numbers

Note that the type specifier used above does not specify signed versus unsigned numbers; rather, the printing function determines whether the number is interpreted as signed or unsigned.  For example, type the following two command lines from the terminal and see how QED-Forth responds:

65535   U.

65535   .

In the first instance, QED-Forth prints 65535, while in the second instance, QED-Forth prints -1 (we’re assuming that you have not changed the number base to HEX). The same binary pattern (in this case, all 16 bits of the number are set) can represent either 65535 or -1 depending on how the number is interpreted and printed.  Thus by choosing the printing function, you can control whether a number is displayed as a signed or unsigned quantity. 

Summary

In summary, to display the contents of a simple static variable, type a command of the form:

 

type  variable_name  print_function_name

where type is one of the following keywords:

 

char      int      long      float

To display the contents of a static variable that is pointed to by a pointer, type a command of the form:

 

type      pointer_name      print_function_name

where type is one of the following keywords:

 

char*    int*     long*     float*

Use Type Keywords To Interactively Call C Functions

The same family of familiar C type-declaration keywords that we used to fetch the contents of variables is also used to facilitate interactive calling of C functions.  Recall that these keywords are:

 

char    int     long    float

char*   int*    long*   float*

We have seen that these keywords are used in two different contexts while debugging.  In the prior chapter we used them to declare the type of an input parameter while interactively calling a function.  For example, we can interactively type from the terminal:

CalcArea( int 5)

where the int keyword is used with the same syntax as an ANSI-C function prototype to declare the input arguments to the called function. 

Second, we used the type keywords in this chapter to extract the value from a variable, as in the interactive QED-Forth command

int  radius  U.

which prints the contents of the radius variable as an unsigned integer. 

These two contexts for the use of the int keyword are related. For example, to calculate the area corresponding to the current value of the radius variable, we can interactively execute:

CalcArea( int radius)

and QED-Forth prints the resulting floating point area in its summary of the return value.  The int keyword serves two complementary purposes here: it tells QED-Forth that the input parameter is a 16-bit integer, and it extracts the value of the radius variable so the variable is passed by value

When interactively calling a function, all parameters that are passed by value should be preceded by the appropriate type keyword.  However, when passing the address of a variable or a structure, simply state the variable or structure name without any type specifiers or & (address-of) operators. 

For example, the function prototype for the DimAndInitFPArray() function in GETSTART.C is:

 

Q void DimAndInitFPArray(float val,int rows,int cols,FORTH_ARRAY* array_ptr)

and the program includes the array declaration:

 

FORTH_ARRAY circle_parameters;

which declares circle_parameters as a FORTH_ARRAY structure in memory.  As we shall see, executing (typing) the name circle_parameters in QED-Forth leaves the address of the array structure on the stack, so there is no need for additional type declarators or & operators.  Thus to interactively dimension the array to have 10 rows, 2 columns and a initialization value of 12.34, we type from the terminal:

DimAndInitFPArray( float 12.34,int 10,int 2,circle_parameters)

To verify that this worked, you can execute:

PrintFPArray( circle_parameters)

which displays the contents of the newly initialized circle_parameters matrix.

Displaying the Values of FORTH_ARRAY Elements

The same type specifier keywords that let you examine static variables can also be used to examine any specified element in a two-dimensional FORTH_ARRAY. The syntax is parallel to what we have already used; the difference is that we now append the row and column indices in square brackets after the array name to specify which element should be fetched. 

For example, recall that circle_parameters is a FORTH_ARRAY that is dimensioned to hold 10 rows and 2 columns of floating point data.  To print the contents of the first element in the array at [row=0, col=0], we type:

float  circle_parameters[ 0, 0]  PrintFP

and QED-Forth prints the result. While this array notation is not exactly like the standard C syntax, it is straightforward.  To print the element whose row index is 5 and whose column index is 1, type:

float  circle_parameters[ 5, 1]  PrintFP

As you might expect, there must not be a space before the [ character, and there must be at least one space after the [ character. This is because

 

circle_parameters[

is defined as a space-delimited QED-Forth function in the GETSTART.DLF file, as explained later in this chapter.

All of the keywords that we learned about above can be used to fetch the contents of appropriately dimensioned arrays.  Arrays that are dimensioned to hold character, integer, long, or float data are accessed using the char, int, long and float keywords, respectively, in front of the array name.  If for some reason you use a FORTH_ARRAY to hold 16-bit pointers , the char*, int*, long* and float* keywords can be used in a manner exactly analogous to the description in the earlier section of this chapter.

Assigning Values to Static Variables and FORTH_ARRAY Elements

You can interactively change the contents of any static variable or FORTH_ARRAY element using the following assignment keywords:

 

=char    =int    =long    =float

Each of these keywords expects to be preceded by the address of a variable or FORTH_ARRAY element, and expects to be followed by a valid number, variable name, or FORTH_ARRAY element specifier.  As expected, the value of the right hand side is assigned to the variable or array element on the left hand side of the assignment expression.

For example, to change the current value of radius to 22, simply type:

radius  =int  22

This syntax was designed to be similar to a C statement that assigns the value 22 to the radius variable.  As you might guess, =int is a single keyword defined in QED-Forth, so there cannot be any spaces between = and int. Similarly, the other tokens in the expression must be separated by spaces; thus there is at least one space after radius and at least one space before 22.

To set the current value of the floating point area variable to 1520. type:

area =float 1520.

To assign the current value of the area variable to element [ 0, 1] in the FORTH_ARRAY circle_parameters, you can execute:

circle_parameters[ 0,1] =float  area

To check that these operations actually worked, we can execute the following commands to examine the contents of the affected variables and array elements:

int radius  U.

float  area  PrintFP

float  circle_parameters[ 0,1]  PrintFP

Under the Hood of the QED-Forth Interactive Debugger

This section is for the curious among you; you need not read or understand this section to use the QED-Forth interactive debugger.  However, it will give you additional insight into the debugging environment.

Variable Declarations

In the example above, radius is defined in the GETSTART.DLF download file as a QED-Forth constant whose value is the address of the radius variable.  To see for yourself, use you editor to open the GETSTART.DLF file.  Select “Open” from the editor’s “file” menu, set the “List Files of Type” option to either “Text Files” or “All Files”, and double click on GETSTART.DLF in the \MOSAIC\DEMOS_AND_DRIVERS\MISC\C_EXAMPLES directory.  The top portion of the file is the hexadecimal dump of the compiled C code in the Motorola S2 record format.  Near the bottom of the file you’ll see some CONSTANT declarations.  Among them is the declaration:

 

008E03 CONSTANT radius

which defines radius as a QED-Forth constant that places the hexadecimal value 8E03 on the stack.  You can verify this by clicking on the Terminal window and typing:

HEX radius  U.

DECIMAL

from the terminal.  This command sequence instructs QED-Forth to print the hexadecimal address of the radius variable, and then return to decimal base.  Note that if you want to pass the address of the radius variable as a parameter to a function (also known as passing a pointer or passing by reference), you leave out the int keyword before radius in the parameter list.

The keyword int is actually a QED-Forth function that examines the next token in the input stream; if it is already a number such as 5 or 3.2, int simply converts it to the nearest integer.  If the next token is a variable address (such as radius), int extracts the 16-bit contents stored at the address.  To see this behavior for yourself, try the following commands at your terminal:

int  5  U.

int  5.45  U.

int  radius  U.

These three statements all yield identical results if the value of radius is still 5. 

Function Declarations

Returning to the GETSTART.DLF file that you opened in the editor, scroll to the area just above the list of CONSTANT definitions and you will see a set of lines starting with the : (colon) character.  In Forth, the : character marks the start of a new definition (function or subroutine), and the ; (semicolon) marks the end of the definition.  These are the function definitions that tell QED-Forth the names and execution addresses of each function in GETSTART.C that was preceded by the _Q declarator. Among these functions you will find some familiar ones including:

 

SetRadiusAndArea(

CalcArea(

DimAndInitFPArray(

PrintFPArray(

The body of each of these Forth definitions defines the compilation address and invokes the routine CALL.CFN (meaning call-C-function). CALL.CFN accepts an optional list of comma-delimited parameters terminated by a closing ) and then sets up the stack frame and calls the function.

So when you type the interactive command

CalcArea( int radius)

with a terminal enter key, here’s what happens:

    1. When QED-Forth accepts the carriage return, it starts interpreting the command line that has been entered.  It looks for the first space-delimited token, and it finds the token:

 

CalcArea(

    2. It looks in its dictionary, and sure enough, it finds that this token has been defined; the definition was compiled when the GETSTART.DLF download file was sent to the QScreen Controller.

    3. When QED-Forth executes the CalcArea( token, it executes the CALL.CFN routine which starts looking for a terminating ) character, and processes any tokens that are present.

    4. The next space-delimited token found is int, which looks for the next token (in this case, radius). Because radius is not a number, int assumes that it is a variable and extracts the 16-bit contents from the address that is left on the Forth data stack by radius.  The contents are left on the Forth data stack.

    5. The terminating ) is found, so the CALL.CFN routine pushes the items on the Forth data stack onto the C stack in the proper order to make a legal C stack frame, and then executes the CalcArea() function as defined in the C program at the specified execution address.

    6. When the CalcArea() function returns, QED-Forth traps its return value from the 68HC11’s registers and prints the value using integer and floating point formats.

FORTH_ARRAY Declarations

Near the bottom of the GETSTART.DLF file you can find the definition of circle_parameters[ that facilitates examining and modifying any element of this array.  The QED-Forth definition is:

 

: circle_parameters[

  circle_parameters  DO[]

;

As described above, the : character marks the start of a new definition, and the ; marks the end of the definition.  The body of the definition is simple: the constant circle_parameters leaves the base address of the FORTH_ARRAY structure on the stack, and DO[] does the rest of the work.  DO[] is defined in the QED-Forth kernel; it searches for a row index followed by a comma, and a column index followed by a terminating ] character.  Then it passes the specified row, column, and array parameter field address to the Forth function named [] (brackets) which places the 32-bit extended address of the array element on the stack.  This extended address can be used as the argument to the familiar keywords that we have discussed such as char, int, long, float, =char, =int, =long, =float, etc.  Thus all of the following are legal debugging commands:

float circle_parameters[ 3,0]  PrintFP

circle_parameters[ 2,1] =float  area

circle_parameters[ 5,0] =float 345.

Some of you may have noticed that CalculationTask[ is also declared to QED-Forth as a potential FORTH_ARRAY in the GETSTART.DLF download file; yet we know that CalculationTask is a task identifier, not a FORTH_ARRAY. The reason for this is that Make Tool always declares the last variable allocated in the common RAM as a potential FORTH_ARRAY; it does this because there it can’t determine the allocated size of the last variable.  The extra definition of CalculationTask[ does no harm (as long as we don’t try to use it improperly).

Summary

The Make Tool calls the QCC.EXE executable program to create the QED-Forth debugging declarations that appear at the bottom of the .DLF download file.  This program has to decide whether each compiler symbol in the .OUT file is a callable function, a variable, or a FORTH_ARRAY.  The Make Tool identifies callable functions by detecting the _pascal? tag that the compiler places there in response to the _Q specifier, and in response prints the functionname( definition into the .DLF file.  The Make Tool identifies variables by detecting whether the corresponding address lies in the common RAM area, and in response prints a QED-Forth CONSTANT declaration into the .DLF file.  Finally, it tentatively identifies FORTH_ARRAYs by checking the size of each variable; if there are exactly 18 bytes allocated to one item in the common RAM, it decides that the associated name should also be declared as a FORTH_ARRAY by printing the name[ definition in the .DLF download file.  To be safe, the Make Tool always declares the last variable as a FORTH_ARRAY because it cannot be sure of its allocated size.

Other Useful QED-Forth Functions

QED-Forth is a complete language that includes over a thousand pre-defined functions, all of which reside in ROM on the QScreen Controller.  Many of these functions are declared in the header files in the \MOSAIC\FABIUS\INCLUDE\MOSAIC directory, and so are callable from C.  The names and descriptions of these functions are detailed in the Control C Glossary in the documentation package.  But there are also additional routines described there that are useful while debugging; these allow you to:

  Modify the contents of EEPROM on the 68HC11 processor.

  Dump the contents of a specified region of memory in hex and ascii format using the DUMP command.

  Specify a new baud rate for the serial port to speed downloads using the BAUD1.AT.STARTUP command.

  Configure the QScreen Controller to execute a specified program each time a reset or restart occurs using the AUTOSTART or PRIORITY.AUTOSTART command.

  Dump out a replica of the board’s program memory space in Intel Hex or Motorola S2 record format to archive your production code.

In sum, the versatile QED-Forth language enhances the power of Control C by providing many operating system functions as well as an interactive debugging environment that speeds program development and testing.

<< Previous | Next>>


Home|Site Map|Products|Manuals|Resources|Order|About Us
Copyright (c) 2006 Mosaic Industries, Inc.
Your source for single board computers, embedded controllers, and operator interfaces for instruments and automation