Table of ContentsThe Garmin GPS SubsystemConnecting To the Wildcard Bus Selecting the Wildcard Address Mosaic GPS Driver Software
Driver Functions Extract GPS Data from NMEA Sentences
Overview of the Mosaic GPS Software Device Driver Functions
GPS Service Loop Is Best Placed In Its Own Task Demo Program Prints Formatted GPS Data Installing the Mosaic GPS Wildcard Driver Software Using the Mosaic GPS Driver Code with C Using the Mosaic GPS Driver Code with Forth |
The GPS Wildcard User GuideOverview of the Mosaic GPS Software Device Driver FunctionsOn the GPS Wildcard, the NMEA sentence serial data is transmitted by the Garmin GPS subsystem and received by a UART (Universal Asynchronous Receiver Transmitter) chip. The serial data is transmitted at 4800 baud (bits per second). The UART contains a 64-byte receiver FIFO (First In/First Out) buffer that buffers the data until it is read by the processor via the Wildcard bus. Data is continuously streaming out of the GPS subsystem, one multi-sentence frame per second. While some applications may need to continuously extract data to perform navigation functions, other applications may need only infrequent updates of GPS information. The Mosaic GPS driver is written to accommodate this broad range of application needs. For applications with infrequent needs for GPS updates, the data streaming out of the GPS subsystem can be safely ignored until an update is needed. The unused data will overflow the FIFO buffer in the UART, and will effectively be discarded. At any point in time, the GPS_Update function can be called to flush any old characters from the UART FIFO, accept a valid frame of data sentences from the GPS subsystem, and extract the GPS data to a structure where it is accessible to the application program. Applications that need frequent updates from the GPS can run a tight loop in a task that continually calls GPS_Update and uses the resulting data as it becomes available. GPS_Update is the highest level function in the GPS driver. It calls GPS_Next_Frame which waits for 7 sentences from the GPS subsystem and puts them into the GPS_Inbuf, a 600 byte character buffer allocated in common RAM. (To be precise, GPS_Inbuf is a function that returns the 32-bit base xaddress of the gps_default_inbuf character array.) GPS_Update then invokes GPS_Frame_Extract. This workhorse function parses the sentences in the GPS_Inbuf, extracts the relevant data parameters, and stores them into the gps_info structure for use by the application program. Your application program can access the gps_info struct fields in common RAM directly, or invoke a family of additional driver functions to fetch the fields out of the struct and return them. The defining source code for the gps_info struct is presented in Listing 1‑2 on page 19 (for the C language) and Listing 1‑3 on page 33 (for the Forth language). Please take a moment now to examine the listing in your chosen programming language. The field names should be familiar, as they correspond to the data fields from the GPS sentences as described in the prior section. The comments accompanying each field provide additional descriptive information. While the NMEA sentences transmit the numeric data fields as ASCII values, the gps_info data structure stores the numeric data as binary integers (but the directions ‘N’ ‘S’ ‘E’ and ‘W’ are stored as ASCII values in the struct). This maximizes the programmer’s flexibility in performing computations with the numeric data. As an example, let’s take the latitude of Mosaic Industries headquarters, which is approximately 37 degrees, 32.3793 minutes North of the equator. Recall that a minute is one sixtieth (1/60) of a degree. This latitude is reported in the GPRMC sentence as: 3732.3793,N You can see this latitude report in Listing 1‑1 on page 8 in the GPRMC sentence; the latitude is reported in the field after the ‘A’. The first 2 digits are the latitude degrees (37), the next 2 digits are the integer part of the latitude minutes (32), then there is a decimal point, followed by the decimal fractional part of the latitude (.3793), followed by the ‘N’ field for North. After executing GPS_Update (or its component functions GPS_Next_Frame and GPS_Frame_Extract). the latitude is available in the following fields of the gps_info struct:
int sgps_lat_degrees; // 00-89 degrees latitude int sgps_lat_minutes_intpart; // 00-59 integer latitude minutes int sgps_lat_minutes_fraction; // .xxxx lat minutes fractional part (tenthousandths) int sgps_lat_hemisphere; // ascii ‘N’ or ‘S’ Each field name begins with ‘s’ to indicate that it is a struct field, and the field name is descriptive. In this example, the sgps_lat_degrees field contains a binary representation of the latitude degrees (37), and the sgps_lat_minutes_intpart field contains a binary representation of the integer part of the latitude minutes (32). The sgps_lat_minutes_fraction field contains a binary representation of the fractional part of the latitude minutes (3793); its dimensions (units) are ten-thousandths of a minute. The driver provides these fields to preserve all of the latitude information reported by the GPS subsystem in a useable form. To directly fetch the latitude degrees into a variable named latitude_degrees, a C application program could use the statements:
int latitude_degrees; latitude_degrees = gps_info.sgps_lat_degrees; An application program can also use the function GPS_Lat_Degrees that fetches the parameter from the gps_info struct and returns it for use in the program. The following two C statements have the same effect as the statements above:
int latitude_degrees; latitude_degrees = GPS_Lat_Degrees; The function named GPS_Lat_Minutes_Times_10000 scales up the latitude minutes by a factor of 10000 and returns it as a 32-bit integer in the range 0 to 599,999. This function returns the sum of contents of the sgps_lat_minutes_fraction field, plus 10000 times the contents of the sgps_lat_minutes_intpart field. The numeric value of the number returned by this routine is the current latitude minutes times 10000. The dimensions (units) of the returned values are ten-thousandths of a minute. If desired, your application program can convert the latitude minutes into a single floating point number. For example,
float latitude_minutes; latitude_minutes = GPS_Lat_Minutes_Times_10000 / 10000.0 ; Some programmers may want to use fast integer math and avoid converting to the slower floating point math. (Forth programmers using the V4.xx kernels should also be aware of the 5 decimal digit resolution of the legacy floating point package; C programmers and V6.xx Forth programmers have a floating point package with about 7 decimal digits of resolution). The GPS_Lat_Hemisphere function returns the ASCII ‘N’ or ‘S’ latitude character, or your program can fetch it out of the gps_info field using an assignment statement. The longitude is reported in a parallel set of fields in the gps_info struct:
int sgps_long_degrees; // 000-179 degrees longitude int sgps_long_minutes_intpart; // 00-59 integer longitude minutes int sgps_long_minutes_fraction; // .xxxx long minutes fraction part (ten-thousandths) int sgps_long_hemisphere; // ascii ‘E’ or ‘W’ The driver functions GPS_Long_Degrees, GPS_Long_Minutes_Times_10000, and GPS_Long_Hemisphere can be used to return the longitude information to the application program. The GPS reports altitude as a number in the range -9999.9 to 99999.9 meters relative to mean sea level. The GPS driver software multiplies this by ten to convert it to a 32-bit long value in the range -99999 to 999999 in the sgps_altitude_tenth_meters field. The GPS_Altitude_Meters_Times_10 function returns this value for use in the application program. Ground speed is reported by the GPS subsystems in knots, or nautical miles per hour. A nautical mile is 1.152 times longer than a standard (statute) mile, and corresponds to 1 second of latitude arc. A knot is equivalent to 1.152 miles per hour. The GPS reports speed as a number in the range 0.0 to 999.9 knots, and the driver software multiplies this by ten to convert it to an integer in the range 0 to 9999 stored in the sgps_tenth_knots field. The GPS_Knots_Times_10 function returns this value for use in the application program. Course heading (direction) is reported by the GPS as the number of degrees in the range 0.0 to 359.9 relative to true north. The Mosaic GPS driver software multiplies this by ten to convert it to an integer in the range 0 to 3599 stored in the sgps_course_tenth_degrees field. The GPS_Course_Degrees_Times_10 function returns this value for use in the application program. The GPS reports the universal “UTC” time and date at the prime meridian that runs through Greenwich England. These time and date fields are saved as binary quantities in the gps_info struct where they can be accessed directly by the application program. There are no pre-defined driver functions that fetch the time and date quantities. The universal time/date differs from the local time/date by an integer number of hours. For convenience, the GPS_Init function accepts a “local_hour_offset” parameter which is the number of hours that must be added to the universal “UTC” (Greenwich) time to obtain the correct local time. In general, the local_hour_offset for a location with “West” longitude such as the United States has a negative local_hour_offset, while a location with “East” longitude has a positive local_hour_offset. The pre-defined constants GPS_PACIFIC_TIME, GPS_MOUNTAIN_TIME, GPS_CENTRAL_TIME, and GPS_EASTERN_TIME can be passed to the GPS_Init routine to specify the named time zones. To specify daylight savings time, add 1 to the specified time zone constant before passing it to this function (see the glossary entry for GPS_DAYLIGHT_TIME). The GPS_Update function (via its callee, GPS_Frame_Extract) extracts the universal UTC time and date from the GPRMC sentence, and uses the local_hour_offset to calculate the local time and date. These are stored in the following gps_info fields:
int sgps_utc_hour; // 00-23 hour int sgps_utc_date; // 01-31 date of the month int sgps_utc_month; // 01-12 month of the year int sgps_utc_year; // 00-99 2-digit year int sgps_local_second; // 00-59 seconds after minute; utc_second = local_second int sgps_local_minute; // 00-59 minutes after hour; utc_minute = local_minute int sgps_local_hour; // 00-23 hour = (utc_hour + local_time_hour_offset) mod 24 int sgps_local_date; // 01-31 date of the month, result of utclocal conversion int sgps_local_month; // 01-12 month of the year, result of utclocal conversion int sgps_local_year; // 00-99 2-digit year, result of utclocal conversion The GPS_Good_Fix function returns a true (-1) value if the contents of the struct field sgps_fix_quality = 1 and if the contents of the struct field sgps_position_valid is true. In other words, if GPS_Good_Fix returns a nonzero value, the GPS information can be relied upon (according to the GPS receiver itself). The GPS_Numsats_In_Use and GPS_Numsats_In_View functions also report information that is useful for determining the status of the GPS receiver. The GPS_Init function initializes the data structures and the GPS Wildcard hardware. To force a reset and satellite reacquisition, pass a true flag to the GPS_Shutdown function to shut down the GPS, and then pass a false flag to the GPS_Shutdown function to restart the GPS. If the GPS will not be used for significant periods of time, you can save power by shutting it down using GPS_Shutdown. Of course, when the GPS is turned back on there will be a delay while it reacquires the satellite fix. GPS Service Loop Is Best Placed In Its Own TaskA typical GPS application program initializes the GPS by calling GPS_Init, and then repeatedly invokes the high level GPS_Update function to accept a frame of data from the GPS subsystem and populate the fields in the gps_info data structure. GPS_Update calls GPS_Next_Frame which can take over 1 second to obtain a frame of data from the GPS subsystem. If the GPS_Update or GPS_Next_Frame function is invoked in a single-task system, all other instrument tasks could be halted for over a second. To avoid this problem, create a separate task and call GPS_Update from within that task’s infinite loop. Invoke StartTimeslicer (START.TIMESLICER in Forth) to run the multitasker. In this way the GPS will be serviced without blocking time-critical code running in other tasks. As described above, the GPS driver is designed to allow GPS data to be ignored and discarded when it is not needed by the application. Once the application requires data, GPS_Update (or its callee function GPS_Next_Frame) must be able to obtain an unadulterated frame of data from the GPS and store it in the 600 byte GPS_Inbuf buffer. At the serial data rate of 4800 baud, and given that there are 10 bits per character (1 start bit, 8 data bits, and 1 stop bit), each character is transmitted in approximately 2 milliseconds. Thus the 64 byte UART FIFO will not overflow if the processor services the GPS Wildcard at least 8 times per second. This constraint is easily met in a multitasking system with the timeslicer running. Demo Program Prints Formatted GPS DataThe demonstration program presents a simple example of how to use the GPS Wildcard. The GPS_Demo function (or the main function in C) starts and runs the demonstration using the GPS Wildcard. The demonstration program source code is presented at the end of this document in both C and Forth. The demo initializes the GPS by passing the local_hour_offset and module_num (the Wildcard address) to the GPS_Init function. If there is no initialization error, the following descriptive text header is printed to the terminal:
Starting GPS info dump. Type any key to exit this function. This function gets a data frame from the GPS once per second, and prints a statement telling of the fix validity. If the fix is not valid, make sure your antenna is outside, and give the GPS some time (5 minutes worst case) to acquire its satellites. This function periodically calls GPS_Info_Dump to summarize the GPS data. Then the demo enters a loop calling GPS_Update. If GPS_Update returns a true error flag, the demo prints a statement telling us that no GPS fix is available. If the error flag is zero, the demo prints a statement that a fix is available. Every 5 seconds, the demo program calls GPS_Info_Dump to print a formatted summary of the GPS parameters. This simple demo program runs from the default task and uses the default serial port to print data to the Mosaic terminal program running on your PC. In a real application, the GPS_Update function would be called from within a task dedicated to servicing the GPS. Installing the Mosaic GPS Wildcard Driver SoftwareThe GPS Wildcard device driver software is provided as a pre-coded modular runtime library, known as a “kernel extension” because it enhances the on-board kernel's capabilities. The library functions are accessible from C and Forth. Mosaic Industries can provide you with a web site link that will enable you to create a packaged kernel extension that has drivers for all of the hardware that you have on your system. In this way the software drivers are customized to your needs, and you can generate whatever combination of drivers you need. Make sure to specify the GPS Wildcard Drivers in the list of kernel extensions you want to generate, and download the resulting "packages.zip" file to your hard drive. For convenience, a separate pre-generated kernel extension for the GPS Wildcard is available from Mosaic Industries on the Demo and Drivers media (diskette or CD). Look in the Drivers directory, in the subdirectory corresponding to your hardware (the Mosaic Controller of your choice) in the GPS_Wildcard folder. The kernel extension is shipped as a "zipped" file named "packages.zip". Unzipping it (using, for example, winzip or pkzip) extracts the following files: ◙ readme.txt - Provides summary documentation about the library. ◙ install.txt - The installation file, to be loaded to COLD-started Mosaic Controller. ◙ library.4th - Forth name headers and utilities; prepend to Forth programs. ◙ library.c - C callers for all functions in library; #include in C code. ◙ library.h - C prototypes for all functions; #include in extra C files. Library.c and library.h are only needed if you are programming in C. Library.4th is only needed if you are programming in Forth. The uses of all of these files are explained below. We recommend that you move the relevant files to the same directory that contains your application source code. To use the kernel extension, the runtime kernel extension code contained in the install.txt file must first be loaded into the flash memory of the Mosaic Controller. Start the Terminal software with the Mosaic Controller connected to the serial port and turned on. If you have not yet tested your Mosaic Controller and terminal software, please refer to the documentation provided with the Terminal software. Once you can hit enter and see the 'ok' prompt returned in the terminal window, type COLD to ensure that the board is ready to accept the kernel extension install file. Use the "Send File" menu item of the terminal to download the install.txt to the Mosaic Controller. Now, type COLD again and the kernel has been extended! Once install.txt has been loaded, it need not be reloaded each time that you revise your source code. Using the Mosaic GPS Driver Code with CMove the library.c and library.h files into the same directory as your other C source code files. After loading the install.txt file as described above, use the following directive in your source code file: #include “library.c” This file contains calling primitives that implement the functions in the kernel extension package. The library.c file automatically includes the library.h header file. If you have a project with multiple source code files, you should only include library.c once, but use the directive #include “library.h” To load the optional demonstration program described
above, use the “make” icon of the C compiler to compile the file named that is provided on the distribution media. Use the terminal to send the resulting GPSdemo.txt file to the Mosaic Controller, and type main to run the program. See the demo source code listing below for more details.
Note that all of the functions in the kernel extension are of the _forth type. While they are fully callable from C, there are important restrictions. First, the _forth functions may not be called as part of a parameter list of another _forth function. Second, _forth functions may not be called from within an interrupt service routine unless the instructions found in the file named \fabius\qedcode\forthirq.c are followed (this second restriction is lifted for V6.xx kernels as shipped with the PDQ line). Also, in most cases Key and Emit functions should not be called from within interrupt service routines, because these routines call PAUSE, and use of PAUSE within an interrupt routine can halt the multitasker. Using the Mosaic GPS Driver Code with ForthAfter loading the install.txt file and typing COLD, use the terminal to send the “library.4th” file to the Mosaic Controller. Library.4th sets up a reasonable memory map and then defines the constants, structures, and name headers used by the GPS Wildcard kernel extension. Library.4th leaves the memory map in the download map. After library.4th has been loaded, the board is ready to receive your high level source code files. Be sure that your software doesn't initialize the memory management variables DP, VP, or NP, as this could cause memory conflicts. If you wish to change the memory map, edit the memory map commands at the top of the library.4th file itself. The definitions in library.4th share memory with your Forth code, and are therefore vulnerable to corruption due to a crash while testing. If you have problems after reloading your code, try typing COLD, and reload everything starting with library.4th. It is very unlikely that the kernel extension runtime code itself (install.txt) can become corrupted since it is stored in flash on a page that is not typically accessed by code downloads. We recommend that your source code file begin with the sequence:
WHICH.MAP 0= This moves all pre-loaded flash contents to RAM if the Mosaic Controller is in the standard (flash-based) memory map, and then establishes the download (RAM-based) memory map. At the end of this sequence the Mosaic Controller is in the download map, ready to receive additional code. We recommend that your source code file end with the sequence:
4 PAGE.TO.FLASH This copies all loaded code from RAM to flash, and sets up the standard (flash-based) memory map with code located in pages 4, 5 and 6. The SAVE command means that you can often recover from a crash and continue working by typing RESTORE as long as flash pages 4, 5 and 6 haven't been rewritten with any bad data. |
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